diff --git a/.htaccess b/.htaccess index e1744eea7fb58e6383b4e05b5d1a8d3bd3f3f92b..01f8f8dd24df5bf518774b24c9843bdd0d61d73a 100644 --- a/.htaccess +++ b/.htaccess @@ -36,7 +36,6 @@ ############################################ ## adjust memory limit -# php_value memory_limit 64M php_value memory_limit 768M php_value max_execution_time 18000 diff --git a/.travis.yml b/.travis.yml index 61087285023605f4dc89cb842c2dabe17104ea0a..661d3a8e8e5cd6d3baf6494c7017abb835b2eee0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,8 @@ php: - 5.6 env: - TEST_SUITE=unit - - TEST_SUITE=integration + - TEST_SUITE=integration_part_1 + - TEST_SUITE=integration_part_2 - TEST_SUITE=integration_integrity - TEST_SUITE=static_phpcs - TEST_SUITE=static_annotation @@ -36,7 +37,7 @@ before_script: - echo '' > ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini # Install MySQL 5.6, create DB for integration tests - > - sh -c "if [ '$TEST_SUITE' = 'integration' ] || [ '$TEST_SUITE' = 'integration_integrity' ]; then + sh -c "if [ '$TEST_SUITE' = 'integration_part_1' ] || [ '$TEST_SUITE' = 'integration_part_2' ] || [ '$TEST_SUITE' = 'integration_integrity' ]; then sudo apt-get remove --purge mysql-common mysql-server-5.5 mysql-server-core-5.5 mysql-client-5.5 mysql-client-core-5.5; sudo apt-get autoremove; sudo apt-get autoclean; @@ -54,10 +55,12 @@ script: # Unit tests - sh -c "if [ '$TEST_SUITE' = 'unit' ]; then ./vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist; fi" # Integration tests - - sh -c "if [ '$TEST_SUITE' = 'integration' ]; then cd dev/tests/integration/; ./../../../vendor/bin/phpunit -c phpunit.xml.dist; fi" + - sh -c "if [ '$TEST_SUITE' = 'integration_part_1' ] || [ '$TEST_SUITE' = 'integration_part_2' ]; then cd dev/tests/integration/; bash IntegationTestsForTravis.sh 2; fi" + - sh -c "if [ '$TEST_SUITE' = 'integration_part_1' ]; then cd dev/tests/integration/; ./../../../vendor/bin/phpunit -c phpunit.xml.travis1; fi" + - sh -c "if [ '$TEST_SUITE' = 'integration_part_2' ]; then cd dev/tests/integration/; ./../../../vendor/bin/phpunit -c phpunit.xml.travis2; fi" # Integration integrity tests - sh -c "if [ '$TEST_SUITE' = 'integration_integrity' ]; then cd dev/tests/integration/; ./../../../vendor/bin/phpunit -c phpunit.xml.dist testsuite/Magento/Test/Integrity; fi" # Static tests [Code Style] - sh -c "if [ '$TEST_SUITE' = 'static_phpcs' ]; then cd dev/tests/static; ./../../../vendor/bin/phpunit -c phpunit.xml.dist --filter 'Magento\\\\Test\\\\Php\\\\LiveCodeTest::testCodeStyle'; fi" # Static tests [Code Style] - - sh -c "if [ '$TEST_SUITE' = 'static_annotation' ]; then cd dev/tests/static; ./../../../vendor/bin/phpunit -c phpunit.xml.dist --filter 'Magento\\\\Test\\\\Php\\\\LiveCodeTest::testAnnotationStandard'; fi" + - sh -c "if [ '$TEST_SUITE' = 'static_annotation' ]; then cd dev/tests/static; ./../../../vendor/bin/phpunit -c phpunit.xml.dist --filter 'Magento\\\\Test\\\\Php\\\\LiveCodeTest::testAnnotationStandard'; fi" \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e56f878e477d8ccacf831da185de27934963b779..c267e405fb2e5d6a9fcd1207f4994cf6e5010d8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,141 @@ +0.74.0-beta13 +============= +* Framework improvements: + * Created Join Directive, Join Process for Tables, XML Config support to define a performance join for search services + * Added support of field weighting for MySQL Search Engine + * Modified indexer declaration to support field declaration + * Model related methods and properties are removed from Magento Object +* Various improvements: + * Added supporting of lost product types for Product Import/Export + * Improved performance of Product Import/Export + * Implemented Payment\Gateway infrastructure as a new design for payment methods + * Fixed messages in Setup CLI + * JS Smart fixed scroll + * Improved sub-menu animation and sub-menu links mouse event effects + * Automated UI Documentation build process with Grunt.js + * Updated composer dependency to newer version + * Implemented direct web link on Magento order transactions records +* Tests: + * Reduced Travis CI integration test time + * Increased test coverage for the Integration module + * Re-structured unit tests for the updater app to follow the convention used by the rest of Magento code +* Fixed Bugs: + * Fixed Help links in Install Wizard + * Fixed an issue where composer install failed since ext-xsl was not available + * Fixed web installer on HHVM + * Fixed broken links to static assets when error occurs + * Fixed failed integration tests on Travis CI builds + * Fixed an issue where menu with one sub-menu item not being displayed + * Fixed an issue where IPN messages did not show relevant info about transaction + * Fixed an issue where Magento\Framework\Data\Form did not accept data-mage-init parameter + * Fixed an issue where not all specified "Multiple Select" Bundle options were added to Shopping Cart + * Fixed ConfigureProductInCustomerWishlistOnBackendTest functional test + * Fixed an issue with all mandatory fields in the Sales data interfaces + * Fixed an issue where billing and shipping sections did not contain address information on order print from Guest + * Fixed an issue where orders placed in different store views had duplicated IDs + * Fixed an issue where Shopping Cart Price Rules were not applying properly for Bundled products + * Fixed an issue where column coupon_rule_name was not filled in the sales_order table when you create the order + * Fixed an issue where customer registration or login on frontend created an empty cart + * Fixed an issue where Product Model sometimes values change in getters methods + * Fixed an issue where deleting option through API service for configurable product did not unlink variations + * Fixed an issue where there was no ability to place order using multishipping if cart contained virtual product + * Fixed an issue where "Terms and Conditions" was absent on order review step + * Fixed an issue where grid actions for "Shopping Cart Items" grid was absent in Customer Account (Backend) + * Fixed XSS vulnerability in Magento "Add to cart" link + * Fixed UI issues on view order info frontend pages for guest customer + * Fixed an issue where "Currency Rates" backend form was displayed broken + * Fixed an issue where padding was missed for Custom Price Checkbox on "Create Order" Backend page + * Fixed an issue where "Choose Variation" buttons lost alignment on "Create Configurable Product" Backend page + * Fixed an issue where "Date & Time" Custom option was displayed broken on "Create Order" Backend page + * Fixed an issue where colon was displayed before every Product Attribute label on Frontend + * Fixed an issue where record from url_rewrite table was not removed when CMS page deleted + * Fixed an issue where widget option "Number of Products to Display" did not work + * Fixed validation message issues for CMS pages + * Fixed an issue where "Click for Price" link was displayed in widgets for product with "Display Actual Price" != "On Gesture" MAP setting + * Fixed an issue where Form_key cookie was not listed in privacy page + * Fixed an issue where merchant wasn’t redirected to correspondent option when trying to enable Dashboard charts + * Fixed an issue where wrong message was displayed after exceeding maximum failed login attempts +* GitHub issues: + * [#1292](https://github.com/magento/magento2/pull/1292) Admin menu with 1 submenu item does not show the subitem + * [#1133](https://github.com/magento/magento2/pull/1133) Getter methods shouldn't change values + * [#1263](https://github.com/magento/magento2/issues/1263) "We don't have as many "product name" as you requested" not showing in mini cart + * [#1284](https://github.com/magento/magento2/issues/1284) Order tracking link redirected to dashboard in admin + +0.74.0-beta12 +============= +* MTF Improvements: + * Functional tests maintenance +* Framework improvements: + * Customer entity table was transformed from EAV into a flat model to minimize DB operations + * Improved admin authentication and removed bypass + * Exposed CMS api's as web API +* Fixed bugs: + * Fixed an issue where "Add Item To Return" button became disabled after required item fields were filled on Frontend + * Fixed an issue with fatal error during place order with non default time zone + * Fixed an issue where it was not possible to filter backups on name + * Fixed an issue where routeIdType did not allow numbers + * Fixed an issue with discounted prices for fixed bundle product + * Fixed an issue with catalog prices not including custom option prices + * Fixed an issue with tier prices being displayed 4 characters + * Fixed an issue with extra FPT labels in mini shopping cart + * Fixed an issue where it was not possible to place orders for products with FPT and catalog prices including tax + * Fixed an issue with FPT attribute being required when creating product + * Fixed an issue where final price was not recalculated after selecting product options + * Fixed an issue where tax labels were not displayed for Bundle options on 'multi-select' and 'dropdown' controls + * Fixed an issue where filters were not shown on product reviews report grid + * Fixed an issue where second customer address was not deleted from customer account + * Fixed an issue where custom options pop-up was still displayed after submit + * Fixed an issue where Second Product was not added to Shopping Cart from Wishlist at first atempt + * Fixed an issue where customer invalid email message was not displayed + * Fixed an issue where All Access Tokens for Customer without Tokens could not be revoked + * Fixed an issue where it was impossible to add Product to Shopping Cart from shared Wishlist + * Magento_Sendfriend module should have upper case 'F' + * Fixed set of issues with Ui module + * Fixed JavaScript error on Invoice creation page +* Various improvements: + * Hide payment credentials in debug log + * Simplification of Payment Configuration + * Introduced new Dialog widget +* Github issues: + * [#1330](https://github.com/magento/magento2/pull/1330) -- Removing unused memory limit in htaccess + * [#1307](https://github.com/magento/magento2/pull/1307) -- Corrected a sentence by removing a word + +0.74.0-beta11 +============= +* Framework improvements: + * Improved component Bookmarks component in scope of Enhanced Data Grids on CMS + * Improved component Advanced Filtering component in scope of Enhanced Data Grids on CMS +* Fixed bugs: + * Fixed an issue where incorrect keys in REST request body allowed the request to go through successfully + * Fixed an issue where interceptors were Generated with Invalid __wakeup() + * Fixed an issue where redirect on the current page was not working in certain conditions + * Fixed an issue where first store could not be selected on frontend + * Fixed an issue with performance toolkit category creation + * Fixed an issue when columns 'Interval', 'Price Rule' had incorrect values in Coupon Usage report + * Fixed an issue where fatal error occured on Abandoned Carts report grid + * Fixed an issue where it was not possible to add product to shopping cart if Use Secure URLs in Frontend = Yes + * Fixed an issue where email was not required during Guest Checkout + * Fixed broken ability to skip reindex in `bin/magento setup:performance:generate-fixtures` command + * Fixed an issue where `bin/magento indexer:reindex` command failed after `bin/magento setup:di:compile` was run + * Fixed bug with broken JS i18n + * Fixed an issue with wrong value at created_at updated_at fields after quote* save + * Fixed an issue where customer could not be created in backend after adding Image type attribute + * Fixed Sales InvoiceItem and Order data interfaces implementation + * Fixed an issue with performance toolkit medium profile + * Fixed an issue where Excel Formula Injection via CSV/XML export + * Fixed an issue where it was not possible to open the Customers page in backend + * Fixed an issue with internal server error after clicking Continue on Billing information + * Fixed an issue where it was not possible to place order with Fedex shipping method +* Various changes: + * Magento Centinel Removal + * Removed ability to have multi-statement queries +* Test coverage: + * Unit tests coverage + * Covered php code by unit tests after new checkout implementation +* Github issues: + * [#424](https://github.com/magento/magento2/issues/424) -- Combine tier pricing messages into block sentences + * [#1300](https://github.com/magento/magento2/issues/1300), [#1311](https://github.com/magento/magento2/issues/1311), [#1313](https://github.com/magento/magento2/issues/1313) -- Creating product error with startdate + 0.74.0-beta10 ============= * Framework improvements: @@ -2514,7 +2652,7 @@ * Canadian provincial sales taxes * Fixed issues with bundle product price inconsistency across the system * Added warnings if invalid tax configuration is created in the Admin panel - * Fixed issues with regards to hidden tax + * Fixed issues with regards to discount tax compensation * Fixed bugs: * Fixed an issue where grouped price was not applied for grouped products * Fixed an issue where a fatal error occurred when opening a grouped product page without assigned products on the frontend diff --git a/Gruntfile.js b/Gruntfile.js index 4718c7cb6dbe4afa7ea14aaeb657ef1d67098dbe..8dcee340ef46cdd59a9631a3d77b2155c0802e6c 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -68,12 +68,17 @@ module.exports = function (grunt) { 'less:luma', 'less:backend' ], + /** * Documentation */ documentation: [ + 'replace:documentation', 'less:documentation', 'styledocco:documentation', + 'usebanner:documentationCss', + 'usebanner:documentationLess', + 'usebanner:documentationHtml', 'clean:var', 'clean:pub' ], @@ -82,12 +87,6 @@ module.exports = function (grunt) { 'mage-minify:legacy' ], - 'documentation-banners': [ - 'usebanner:documentationCss', - 'usebanner:documentationLess', - 'usebanner:documentationHtml' - ], - spec: function (theme) { var runner = require('./dev/tests/js/jasmine/spec_runner'); diff --git a/README.md b/README.md index a1f4a848d6cd7772805466cc1cbc4e117583acb5..286d550ef93cad1b69a526ecebed4ee3e5d17cb3 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ After verifying your prerequisites, perform the following tasks in order to prep <h2>Contributing to the Magento 2 code base</h2> Contributions can take the form of new components or features, changes to existing features, tests, documentation (such as developer guides, user guides, examples, or specifications), bug fixes, optimizations, or just good suggestions. -To make learn about how to make a contribution, click [here][1]. +To learn about how to make a contribution, click [here][1]. To learn about issues, click [here][2]. To open an issue, click [here][3]. diff --git a/app/code/Magento/AdminNotification/Model/Feed.php b/app/code/Magento/AdminNotification/Model/Feed.php index ddbb35a31bb6d7a364f1b234caeb4a675443decb..9fac96e1d230baca5a7ac20cb082575b0997b351 100644 --- a/app/code/Magento/AdminNotification/Model/Feed.php +++ b/app/code/Magento/AdminNotification/Model/Feed.php @@ -73,7 +73,7 @@ class Feed extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\App\ProductMetadataInterface $productMetadata * @param \Magento\Framework\UrlInterface $urlBuilder * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -87,7 +87,7 @@ class Feed extends \Magento\Framework\Model\AbstractModel \Magento\Framework\App\ProductMetadataInterface $productMetadata, \Magento\Framework\UrlInterface $urlBuilder, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/AdminNotification/composer.json b/app/code/Magento/AdminNotification/composer.json index 8ba6ef2ea6411da4d046b0dc825122a5c162dfb6..d26dfd7372721000e9973b16a3ea720e1e09a6e5 100644 --- a/app/code/Magento/AdminNotification/composer.json +++ b/app/code/Magento/AdminNotification/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Authorization/composer.json b/app/code/Magento/Authorization/composer.json index 7b094570b8e66872c98e382896dba25f2f191237..9225d004e7ce2f5753e0f21d8f95ca2fb7cbe9cf 100644 --- a/app/code/Magento/Authorization/composer.json +++ b/app/code/Magento/Authorization/composer.json @@ -3,12 +3,12 @@ "description": "Authorization module provides access to Magento ACL functionality.", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-backend": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-backend": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Backend/Block/Dashboard.php b/app/code/Magento/Backend/Block/Dashboard.php index 6433c0a0514b7e127299077aa81a14f6ca8aa1af..76037de5ac71048f7a97094ea42ac409fa9bbcdc 100644 --- a/app/code/Magento/Backend/Block/Dashboard.php +++ b/app/code/Magento/Backend/Block/Dashboard.php @@ -31,7 +31,11 @@ class Dashboard extends \Magento\Backend\Block\Template $this->addChild('sales', 'Magento\Backend\Block\Dashboard\Sales'); - if ($this->_scopeConfig->getValue(self::XML_PATH_ENABLE_CHARTS, \Magento\Store\Model\ScopeInterface::SCOPE_STORE)) { + $isChartEnabled = $this->_scopeConfig->getValue( + self::XML_PATH_ENABLE_CHARTS, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ); + if ($isChartEnabled) { $block = $this->getLayout()->createBlock('Magento\Backend\Block\Dashboard\Diagrams'); } else { $block = $this->getLayout()->createBlock( @@ -39,7 +43,10 @@ class Dashboard extends \Magento\Backend\Block\Template )->setTemplate( 'dashboard/graph/disabled.phtml' )->setConfigUrl( - $this->getUrl('adminhtml/system_config/edit', ['section' => 'admin']) + $this->getUrl( + 'adminhtml/system_config/edit', + ['section' => 'admin', '_fragment' => 'admin_dashboard-link'] + ) ); } $this->setChild('diagrams', $block); diff --git a/app/code/Magento/Backend/Block/Menu.php b/app/code/Magento/Backend/Block/Menu.php index 087fd1fa351709778cc536f519c4b84206d97134..e913d2a7a38a16d54e48859b18e825d34f313500 100644 --- a/app/code/Magento/Backend/Block/Menu.php +++ b/app/code/Magento/Backend/Block/Menu.php @@ -455,28 +455,14 @@ class Menu extends \Magento\Backend\Block\Template } $id = $this->getJsId($menuItem->getId()); - if (count($menu) > 1 || $level != 1) { - $output .= '<li ' . $this->getUiId( - $menuItem->getId() - ) . ' class="item-' . $itemClass . ' ' . $this->_renderItemCssClass( - $menuItem, - $level - ) . ($level == 0 ? '" id="' . $id . '" aria-haspopup="true' : '') - . '" role="menu-item">' . $this->_renderAnchor( - $menuItem, - $level - ) . $this->_addSubMenu( - $menuItem, - $level, - $limit, - $id - ) . '</li>'; + $subMenu = $this->_addSubMenu($menuItem, $level, $limit, $id); + if (count($menu) > 1 || $level != 1 || $menuItem->getUrl() !== '#') { + $output .= '<li ' . $this->getUiId($menuItem->getId()) + . ' class="item-' . $itemClass . ' ' . $this->_renderItemCssClass($menuItem, $level) + . ($level == 0 ? '" id="' . $id . '" aria-haspopup="true' : '') + . '" role="menu-item">' . $this->_renderAnchor($menuItem, $level) . $subMenu . '</li>'; } else { - $output .= $this->_addSubMenu( - $menuItem, - $level, - $limit, - $id); + $output .= $subMenu; } $itemPosition++; diff --git a/app/code/Magento/Backend/Block/Widget/Button/Item.php b/app/code/Magento/Backend/Block/Widget/Button/Item.php index f48deceef0702776181b5241d1bfee262bf3bb9c..525d75f289cd2413aae01d5232ba0981b7ad547e 100644 --- a/app/code/Magento/Backend/Block/Widget/Button/Item.php +++ b/app/code/Magento/Backend/Block/Widget/Button/Item.php @@ -16,4 +16,25 @@ namespace Magento\Backend\Block\Widget\Button; */ class Item extends \Magento\Framework\Object { + /** + * Object delete flag + * + * @var bool + */ + protected $_isDeleted = false; + + /** + * Set _isDeleted flag value (if $isDeleted parameter is defined) and return current flag value + * + * @param boolean $isDeleted + * @return bool + */ + public function isDeleted($isDeleted = null) + { + $result = $this->_isDeleted; + if ($isDeleted !== null) { + $this->_isDeleted = $isDeleted; + } + return $result; + } } diff --git a/app/code/Magento/Backend/Block/Widget/Form.php b/app/code/Magento/Backend/Block/Widget/Form.php index 7c3154c1ebcc8737ff5dd20b2c5754b9f25b1f31..02ef3b1135009ebace6542173bfbf6a6ce6f701f 100644 --- a/app/code/Magento/Backend/Block/Widget/Form.php +++ b/app/code/Magento/Backend/Block/Widget/Form.php @@ -111,6 +111,13 @@ class Form extends \Magento\Backend\Block\Widget $this->_form = $form; $this->_form->setParent($this); $this->_form->setBaseUrl($this->_urlBuilder->getBaseUrl()); + + $customAttributes = $this->getData('custom_attributes'); + if (is_array($customAttributes)) { + foreach ($customAttributes as $key => $value) { + $this->_form->addCustomAttribute($key, $value); + } + } return $this; } diff --git a/app/code/Magento/Backend/Controller/Adminhtml/Index/GlobalSearch.php b/app/code/Magento/Backend/Controller/Adminhtml/Index/GlobalSearch.php index ba71fa71ec1d8dd23c085509d9f2672cc092824f..afa3019cfd67c03376d34c4a4d38e3f6ec6baf84 100644 --- a/app/code/Magento/Backend/Controller/Adminhtml/Index/GlobalSearch.php +++ b/app/code/Magento/Backend/Controller/Adminhtml/Index/GlobalSearch.php @@ -48,7 +48,7 @@ class GlobalSearch extends \Magento\Backend\Controller\Adminhtml\Index $items[] = [ 'id' => 'error', 'type' => __('Error'), - 'name' => __('Access Denied'), + 'name' => __('Access Denied.'), 'description' => __('You need more permissions to do this.'), ]; } else { diff --git a/app/code/Magento/Backend/Helper/Dashboard/Data.php b/app/code/Magento/Backend/Helper/Dashboard/Data.php index 4fe2b5d5b131cf64868433903959646084f4c08b..efaf955675d592b7444f802db49e19047799387c 100644 --- a/app/code/Magento/Backend/Helper/Dashboard/Data.php +++ b/app/code/Magento/Backend/Helper/Dashboard/Data.php @@ -14,7 +14,7 @@ use Magento\Framework\Config\ConfigOptionsListConstants; class Data extends \Magento\Framework\App\Helper\AbstractHelper { /** - * @var \Magento\Framework\Data\Collection\Db + * @var \MagentoFrameworkDataCollectionAbstractDb */ protected $_stores; @@ -48,7 +48,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper /** * Retrieve stores configured in system. * - * @return \Magento\Framework\Data\Collection\Db + * @return \MagentoFrameworkDataCollectionAbstractDb */ public function getStores() { diff --git a/app/code/Magento/Backend/Model/Auth.php b/app/code/Magento/Backend/Model/Auth.php index 215111aee82e9da0487c7a6c6d1673f7b314d1a4..56dedb777725988006091dac4f75e11acd3c5034 100644 --- a/app/code/Magento/Backend/Model/Auth.php +++ b/app/code/Magento/Backend/Model/Auth.php @@ -145,7 +145,7 @@ class Auth public function login($username, $password) { if (empty($username) || empty($password)) { - self::throwException(__('Please correct the user name or password.')); + self::throwException(__('You did not sign in correctly or your account is temporarily disabled.')); } try { @@ -162,7 +162,7 @@ class Auth } if (!$this->getAuthStorage()->getUser()) { - self::throwException(__('Please correct the user name or password.')); + self::throwException(__('You did not sign in correctly or your account is temporarily disabled.')); } } catch (PluginAuthenticationException $e) { $this->_eventManager->dispatch( @@ -175,7 +175,9 @@ class Auth 'backend_auth_user_login_failed', ['user_name' => $username, 'exception' => $e] ); - self::throwException(__($e->getMessage()? : 'Please correct the user name or password.')); + self::throwException( + __($e->getMessage()? : 'You did not sign in correctly or your account is temporarily disabled.') + ); } } diff --git a/app/code/Magento/Backend/Test/Unit/Block/Widget/FormTest.php b/app/code/Magento/Backend/Test/Unit/Block/Widget/FormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a8ac7638108fa4c1f8e7efc5daedb1ec13c0ebef --- /dev/null +++ b/app/code/Magento/Backend/Test/Unit/Block/Widget/FormTest.php @@ -0,0 +1,104 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Backend\Test\Unit\Block\Widget; + +use Magento\Backend\Block\Template\Context; +use Magento\Backend\Block\Widget\Form; +use Magento\Framework\Data\Form as DataForm; +use Magento\Framework\UrlInterface; + +class FormTest extends \PHPUnit_Framework_TestCase +{ + /** @var Form */ + protected $model; + + /** @var Context |\PHPUnit_Framework_MockObject_MockObject */ + protected $context; + + /** @var DataForm |\PHPUnit_Framework_MockObject_MockObject */ + protected $dataForm; + + /** @var UrlInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $urlBuilder; + + protected function setUp() + { + $this->prepareContext(); + + $this->dataForm = $this->getMockBuilder('Magento\Framework\Data\Form') + ->disableOriginalConstructor() + ->setMethods([ + 'setParent', + 'setBaseUrl', + 'addCustomAttribute', + ]) + ->getMock(); + + $this->model = new Form( + $this->context + ); + } + + protected function prepareContext() + { + $this->urlBuilder = $this->getMockBuilder('Magento\Framework\UrlInterface') + ->getMock(); + + $this->context = $this->getMockBuilder('Magento\Backend\Block\Template\Context') + ->disableOriginalConstructor() + ->getMock(); + $this->context->expects($this->any()) + ->method('getUrlBuilder') + ->willReturn($this->urlBuilder); + } + + public function testSetForm() + { + $baseUrl = 'base_url'; + $attributeKey = 'attribute_key'; + $attributeValue = 'attribute_value'; + + $this->dataForm->expects($this->once()) + ->method('setParent') + ->with($this->model) + ->willReturnSelf(); + $this->dataForm->expects($this->once()) + ->method('setBaseUrl') + ->with($baseUrl) + ->willReturnSelf(); + $this->dataForm->expects($this->once()) + ->method('addCustomAttribute') + ->with($attributeKey, $attributeValue) + ->willReturnSelf(); + + $this->urlBuilder->expects($this->once()) + ->method('getBaseUrl') + ->willReturn($baseUrl); + + $this->model->setData('custom_attributes', [$attributeKey => $attributeValue]); + $this->assertEquals($this->model, $this->model->setForm($this->dataForm)); + } + + public function testSetFormNoCustomAttributes() + { + $baseUrl = 'base_url'; + + $this->dataForm->expects($this->once()) + ->method('setParent') + ->with($this->model) + ->willReturnSelf(); + $this->dataForm->expects($this->once()) + ->method('setBaseUrl') + ->with($baseUrl) + ->willReturnSelf(); + + $this->urlBuilder->expects($this->once()) + ->method('getBaseUrl') + ->willReturn($baseUrl); + + $this->assertEquals($this->model, $this->model->setForm($this->dataForm)); + } +} diff --git a/app/code/Magento/Backend/Test/Unit/Model/AuthTest.php b/app/code/Magento/Backend/Test/Unit/Model/AuthTest.php index 1d713187c130be0cb61cdccf0aa86f5fb55a8ba2..3be5460a6249f050b33e839ed130b2a8c022b5dd 100644 --- a/app/code/Magento/Backend/Test/Unit/Model/AuthTest.php +++ b/app/code/Magento/Backend/Test/Unit/Model/AuthTest.php @@ -50,7 +50,7 @@ class AuthTest extends \PHPUnit_Framework_TestCase /** * @expectedException \Magento\Framework\Exception\AuthenticationException - * @expectedExceptionMessage Please correct the user name or password. + * @expectedExceptionMessage You did not sign in correctly or your account is temporarily disabled. */ public function testLoginFailed() { @@ -59,8 +59,9 @@ class AuthTest extends \PHPUnit_Framework_TestCase ->method('create') ->with('Magento\Backend\Model\Auth\Credential\StorageInterface') ->will($this->returnValue($this->_credentialStorage)); - $exceptionMock = - new \Magento\Framework\Exception\LocalizedException(__('Please correct the user name or password.')); + $exceptionMock = new \Magento\Framework\Exception\LocalizedException( + __('You did not sign in correctly or your account is temporarily disabled.') + ); $this->_credentialStorage ->expects($this->once()) ->method('login') diff --git a/app/code/Magento/Backend/composer.json b/app/code/Magento/Backend/composer.json index 12aea32b4e9ad2d43d7098f725f85e336570cb65..b7e2b7bc15ba6f54e72cc1d6b084c18876592c52 100644 --- a/app/code/Magento/Backend/composer.json +++ b/app/code/Magento/Backend/composer.json @@ -3,27 +3,27 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-developer": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-cron": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/module-reports": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-user": "0.74.0-beta10", - "magento/module-backup": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-translation": "0.74.0-beta10", - "magento/module-require-js": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-developer": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-cron": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/module-reports": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-user": "0.74.0-beta13", + "magento/module-backup": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-translation": "0.74.0-beta13", + "magento/module-require-js": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Backend/i18n/de_DE.csv b/app/code/Magento/Backend/i18n/de_DE.csv index 9e12e495d09b79041066b3d27581470edcc2c62c..fddd1a2eba777c7ab248f5fd11993536cf260914 100644 --- a/app/code/Magento/Backend/i18n/de_DE.csv +++ b/app/code/Magento/Backend/i18n/de_DE.csv @@ -287,7 +287,7 @@ Synchronizing...,Synchronizing... "Current Month","Current Month" YTD,YTD 2YTD,2YTD -"Please correct the user name or password.","Please correct the user name or password." +"You did not sign in correctly or your account is temporarily disabled.","You did not sign in correctly or your account is temporarily disabled." "Authentication error occurred.","Authentication error occurred." "Please specify the admin custom URL.","Please specify the admin custom URL." "Invalid %1. %2","Invalid %1. %2" diff --git a/app/code/Magento/Backend/i18n/en_US.csv b/app/code/Magento/Backend/i18n/en_US.csv index 9e12e495d09b79041066b3d27581470edcc2c62c..fddd1a2eba777c7ab248f5fd11993536cf260914 100644 --- a/app/code/Magento/Backend/i18n/en_US.csv +++ b/app/code/Magento/Backend/i18n/en_US.csv @@ -287,7 +287,7 @@ Synchronizing...,Synchronizing... "Current Month","Current Month" YTD,YTD 2YTD,2YTD -"Please correct the user name or password.","Please correct the user name or password." +"You did not sign in correctly or your account is temporarily disabled.","You did not sign in correctly or your account is temporarily disabled." "Authentication error occurred.","Authentication error occurred." "Please specify the admin custom URL.","Please specify the admin custom URL." "Invalid %1. %2","Invalid %1. %2" diff --git a/app/code/Magento/Backend/i18n/es_ES.csv b/app/code/Magento/Backend/i18n/es_ES.csv index 9e12e495d09b79041066b3d27581470edcc2c62c..fddd1a2eba777c7ab248f5fd11993536cf260914 100644 --- a/app/code/Magento/Backend/i18n/es_ES.csv +++ b/app/code/Magento/Backend/i18n/es_ES.csv @@ -287,7 +287,7 @@ Synchronizing...,Synchronizing... "Current Month","Current Month" YTD,YTD 2YTD,2YTD -"Please correct the user name or password.","Please correct the user name or password." +"You did not sign in correctly or your account is temporarily disabled.","You did not sign in correctly or your account is temporarily disabled." "Authentication error occurred.","Authentication error occurred." "Please specify the admin custom URL.","Please specify the admin custom URL." "Invalid %1. %2","Invalid %1. %2" diff --git a/app/code/Magento/Backend/i18n/fr_FR.csv b/app/code/Magento/Backend/i18n/fr_FR.csv index 9e12e495d09b79041066b3d27581470edcc2c62c..fddd1a2eba777c7ab248f5fd11993536cf260914 100644 --- a/app/code/Magento/Backend/i18n/fr_FR.csv +++ b/app/code/Magento/Backend/i18n/fr_FR.csv @@ -287,7 +287,7 @@ Synchronizing...,Synchronizing... "Current Month","Current Month" YTD,YTD 2YTD,2YTD -"Please correct the user name or password.","Please correct the user name or password." +"You did not sign in correctly or your account is temporarily disabled.","You did not sign in correctly or your account is temporarily disabled." "Authentication error occurred.","Authentication error occurred." "Please specify the admin custom URL.","Please specify the admin custom URL." "Invalid %1. %2","Invalid %1. %2" diff --git a/app/code/Magento/Backend/i18n/nl_NL.csv b/app/code/Magento/Backend/i18n/nl_NL.csv index 9e12e495d09b79041066b3d27581470edcc2c62c..fddd1a2eba777c7ab248f5fd11993536cf260914 100644 --- a/app/code/Magento/Backend/i18n/nl_NL.csv +++ b/app/code/Magento/Backend/i18n/nl_NL.csv @@ -287,7 +287,7 @@ Synchronizing...,Synchronizing... "Current Month","Current Month" YTD,YTD 2YTD,2YTD -"Please correct the user name or password.","Please correct the user name or password." +"You did not sign in correctly or your account is temporarily disabled.","You did not sign in correctly or your account is temporarily disabled." "Authentication error occurred.","Authentication error occurred." "Please specify the admin custom URL.","Please specify the admin custom URL." "Invalid %1. %2","Invalid %1. %2" diff --git a/app/code/Magento/Backend/i18n/pt_BR.csv b/app/code/Magento/Backend/i18n/pt_BR.csv index 9e12e495d09b79041066b3d27581470edcc2c62c..fddd1a2eba777c7ab248f5fd11993536cf260914 100644 --- a/app/code/Magento/Backend/i18n/pt_BR.csv +++ b/app/code/Magento/Backend/i18n/pt_BR.csv @@ -287,7 +287,7 @@ Synchronizing...,Synchronizing... "Current Month","Current Month" YTD,YTD 2YTD,2YTD -"Please correct the user name or password.","Please correct the user name or password." +"You did not sign in correctly or your account is temporarily disabled.","You did not sign in correctly or your account is temporarily disabled." "Authentication error occurred.","Authentication error occurred." "Please specify the admin custom URL.","Please specify the admin custom URL." "Invalid %1. %2","Invalid %1. %2" diff --git a/app/code/Magento/Backend/i18n/zh_CN.csv b/app/code/Magento/Backend/i18n/zh_CN.csv index 9e12e495d09b79041066b3d27581470edcc2c62c..fddd1a2eba777c7ab248f5fd11993536cf260914 100644 --- a/app/code/Magento/Backend/i18n/zh_CN.csv +++ b/app/code/Magento/Backend/i18n/zh_CN.csv @@ -287,7 +287,7 @@ Synchronizing...,Synchronizing... "Current Month","Current Month" YTD,YTD 2YTD,2YTD -"Please correct the user name or password.","Please correct the user name or password." +"You did not sign in correctly or your account is temporarily disabled.","You did not sign in correctly or your account is temporarily disabled." "Authentication error occurred.","Authentication error occurred." "Please specify the admin custom URL.","Please specify the admin custom URL." "Invalid %1. %2","Invalid %1. %2" diff --git a/app/code/Magento/Backend/view/adminhtml/layout/default.xml b/app/code/Magento/Backend/view/adminhtml/layout/default.xml index f52bbb4f8021ff0b5788308689e7ab8f38abdc18..5bcb35156a1c08ba576a4487c28de0ebb4f6b808 100644 --- a/app/code/Magento/Backend/view/adminhtml/layout/default.xml +++ b/app/code/Magento/Backend/view/adminhtml/layout/default.xml @@ -8,6 +8,7 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <head> <title>Magento Admin</title> + <meta name="viewport" content="width=device-width"/> <link src="requirejs/require.js"/> <css src="extjs/resources/css/ext-all.css"/> <css src="extjs/resources/css/ytheme-magento.css"/> 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 cd4550f2e5a03db66fea8e5dd16f9ac38c42f045..4ae9c810ef01a7913961057bb3a3dd680c8f8125 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 @@ -15,9 +15,9 @@ <h1 class="page-heading"><?php echo __('Access denied') ?></h1> <?php if (!$block->hasAvailableResources()): ?> <p> -<?php echo __('Please try to log out and sign in again.') ?><br/> +<?php echo __('Please try to sign out and sign in again.') ?><br/> <?php echo __('If you continue to receive this message, please contact the store owner.') ?> </p> <?php else: ?> -<p><?php echo __('Access denied.') ?></p> +<p><?php echo __('You need more permissions to access this.') ?></p> <?php endif?> 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 501591a40b015dffa463059e781617e0bbc5e8e7..bad6017eb58f2f1334e6433a9f4a242665403d29 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/media/uploader.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/media/uploader.phtml @@ -73,7 +73,7 @@ require([ $('#' + data.fileId) .delay(2000) .hide('highlight'); - alert($.mage.__('File extension not known or unsupported type.')); + alert($.mage.__('We don\'t recognize or support this file extension type.')); } $('#' + data.fileId).remove(); }, diff --git a/app/code/Magento/Backend/view/adminhtml/templates/menu.phtml b/app/code/Magento/Backend/view/adminhtml/templates/menu.phtml index b486dee3d31f052d2b7a027dbdf7b0d8bdfa7c62..68e537bd5556614b4c7fc1cb7c6c92453793de9e 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/menu.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/menu.phtml @@ -8,7 +8,6 @@ ?> - <nav data-mage-init='{"globalNavigation": {}}' class="admin__menu" role="navigation"> <?php echo $block->renderNavigation($block->getMenuModel(), 0, 12); ?> </nav> diff --git a/app/code/Magento/Backend/view/adminhtml/templates/widget/form/container.phtml b/app/code/Magento/Backend/view/adminhtml/templates/widget/form/container.phtml index 90b626aea40edbb68d3c0ede2e4b3e7b58d6d29b..d0c6ee352f93b66e669b2c967170c2b038c3783f 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/widget/form/container.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/widget/form/container.phtml @@ -36,6 +36,7 @@ require([ summaryElement.trigger('click'); } } + $(element).trigger('highlight.validate'); } }); diff --git a/app/code/Magento/Backend/view/adminhtml/templates/widget/grid.phtml b/app/code/Magento/Backend/view/adminhtml/templates/widget/grid.phtml index c750a63e8e1e4f31989620e7f38f0bb6bfa587d7..99ae60d1dc8f9c74a75436f4545a7c0d437a4092 100644 --- a/app/code/Magento/Backend/view/adminhtml/templates/widget/grid.phtml +++ b/app/code/Magento/Backend/view/adminhtml/templates/widget/grid.phtml @@ -31,7 +31,7 @@ $numColumns = sizeof($block->getColumns()); <div class="admin__data-grid-header admin__data-grid-toolbar"> <?php $massActionAvailable = $block->getChildBlock('grid.massaction') && $block->getChildBlock('grid.massaction')->isAvailable() ?> - <?php if ($block->getPagerVisibility() || $block->getExportTypes() || $block->getChildBlock('grid.columnSet')->getFilterVisibility()): ?> + <?php if ($block->getPagerVisibility() || $block->getExportTypes() || $block->getChildBlock('grid.columnSet')->getFilterVisibility() || $massActionAvailable): ?> <div class="admin__data-grid-header-row"> <?php if ($massActionAvailable): ?> <?php echo $block->getMainButtonsHtml() ? '<div class="admin__filter-actions">' . $block->getMainButtonsHtml() . '</div>' : ''; ?> 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 b266fd638eaf6a4d49185a46a40a5383d169f96b..c9ca42066628c32e5246453f02b9a1ff57137ce6 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 @@ -30,8 +30,8 @@ $numColumns = sizeof($block->getColumns()); <?php else: ?> <?php echo $block->getLayout()->getMessagesBlock()->getGroupedHtml() ?> <?php endif; ?> - <?php if ($block->getPagerVisibility() || $block->getExportTypes() || $block->getFilterVisibility()): ?> - <?php $massActionAvailable = $block->getMassactionBlock() && $block->getMassactionBlock()->isAvailable() ?> + <?php $massActionAvailable = $block->getMassactionBlock() && $block->getMassactionBlock()->isAvailable() ?> + <?php if ($block->getPagerVisibility() || $block->getExportTypes() || $block->getFilterVisibility() || $massActionAvailable): ?> <div class="admin__data-grid-header admin__data-grid-toolbar"> <div class="admin__data-grid-header-row"> <?php if ($massActionAvailable): ?> diff --git a/app/code/Magento/Backup/Model/Config/Backend/Cron.php b/app/code/Magento/Backup/Model/Config/Backend/Cron.php index e55b3adb30f206258dc0c7ab7bf0ea2f77cb268a..298b4e60ba4630033904f5022f423175e8f1beec 100644 --- a/app/code/Magento/Backup/Model/Config/Backend/Cron.php +++ b/app/code/Magento/Backup/Model/Config/Backend/Cron.php @@ -34,7 +34,7 @@ class Cron extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\App\Config\ValueFactory $configValueFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param string $runModelPath * @param array $data */ @@ -44,7 +44,7 @@ class Cron extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\App\Config\ValueFactory $configValueFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, $runModelPath = '', array $data = [] ) { diff --git a/app/code/Magento/Backup/Model/Resource/Db.php b/app/code/Magento/Backup/Model/Resource/Db.php index 78c2b95445f3dd47f921d32ef75c8fc5563ba6be..848d03717317c8ebcf830fe8a7cf007a3306cde7 100644 --- a/app/code/Magento/Backup/Model/Resource/Db.php +++ b/app/code/Magento/Backup/Model/Resource/Db.php @@ -124,7 +124,6 @@ class Db if ($row) { $statusObject = new \Magento\Framework\Object(); - $statusObject->setIdFieldName('name'); foreach ($row as $field => $value) { $statusObject->setData(strtolower($field), $value); } diff --git a/app/code/Magento/Backup/composer.json b/app/code/Magento/Backup/composer.json index 54cde5ff34c836e18f89db6182c9c57c50c1ee37..30ca528748ce5de5d93f6cf933d2b5bc8bc24cd1 100644 --- a/app/code/Magento/Backup/composer.json +++ b/app/code/Magento/Backup/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-cron": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-cron": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Bundle/Model/Option.php b/app/code/Magento/Bundle/Model/Option.php index a541f00b80e24c7c6b8d221169b9f2efea55a900..9b7e1029606c65133e418cc9fa3fb415e7a587bc 100644 --- a/app/code/Magento/Bundle/Model/Option.php +++ b/app/code/Magento/Bundle/Model/Option.php @@ -53,7 +53,10 @@ class Option extends \Magento\Framework\Model\AbstractExtensibleModel implements */ public function addSelection(\Magento\Catalog\Model\Product $selection) { - $selections = $this->getDataSetDefault('selections', []); + if (!$this->hasData('selections')) { + $this->setData('selections', []); + } + $selections = $this->getData('selections'); $selections[] = $selection; $this->setSelections($selections); } diff --git a/app/code/Magento/Bundle/Model/Product/Type.php b/app/code/Magento/Bundle/Model/Product/Type.php index 1fdd7bad95292de7c985b119b155091be9659950..f183de707ca487db858664414f7d8b43a221fc86 100644 --- a/app/code/Magento/Bundle/Model/Product/Type.php +++ b/app/code/Magento/Bundle/Model/Product/Type.php @@ -1319,7 +1319,7 @@ class Type extends \Magento\Catalog\Model\Product\Type\AbstractType if (!isset($_result[0])) { throw new \Magento\Framework\Exception\LocalizedException( - __('We cannot add this item to your shopping cart.') + __('We can\'t add this item to your cart right now.') ); } } diff --git a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Creditmemo.php b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Creditmemo.php index 9c912505ae25f325e093d9e5f47544830990ba74..c3242c43e1f5cccc5a2be6905f2d9efdd11a494c 100644 --- a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Creditmemo.php +++ b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Creditmemo.php @@ -25,7 +25,7 @@ class Creditmemo extends AbstractItems * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\String $string * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -36,7 +36,7 @@ class Creditmemo extends AbstractItems \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\String $string, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->string = $string; diff --git a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php index 797529dacf45d44c048db9bf178e9fdfb71d2508..d47ee84b9a2a7b3e0dc0f4c81f12cf43ce5f98cb 100644 --- a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php +++ b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Invoice.php @@ -26,7 +26,7 @@ class Invoice extends AbstractItems * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\String $coreString * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -37,7 +37,7 @@ class Invoice extends AbstractItems \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\String $coreString, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->string = $coreString; diff --git a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Shipment.php b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Shipment.php index 19358878b50889a691df408aab58019f7964fd9a..957bde5254681d3ac16d492d8b9f242a53abb4f4 100644 --- a/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Shipment.php +++ b/app/code/Magento/Bundle/Model/Sales/Order/Pdf/Items/Shipment.php @@ -23,7 +23,7 @@ class Shipment extends AbstractItems * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\String $string * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -34,7 +34,7 @@ class Shipment extends AbstractItems \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\String $string, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->string = $string; diff --git a/app/code/Magento/Bundle/Model/Selection.php b/app/code/Magento/Bundle/Model/Selection.php index 1f68f9795dd2b66e4b9e8866aa1fb8c7de697f8c..ca6031a62e6511c63951bcd3144762eb35f8d8e8 100644 --- a/app/code/Magento/Bundle/Model/Selection.php +++ b/app/code/Magento/Bundle/Model/Selection.php @@ -43,7 +43,7 @@ class Selection extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Catalog\Helper\Data $catalogData * @param \Magento\Bundle\Model\Resource\Selection $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -51,7 +51,7 @@ class Selection extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Catalog\Helper\Data $catalogData, \Magento\Bundle\Model\Resource\Selection $resource, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_catalogData = $catalogData; diff --git a/app/code/Magento/Bundle/Model/Source/Option/Type.php b/app/code/Magento/Bundle/Model/Source/Option/Type.php index 98ecd93865d4cc25ca07963e2a1fe6866f25a04a..2072308cbfd18e7dd1904f7bb0f14ac95a2ce63e 100644 --- a/app/code/Magento/Bundle/Model/Source/Option/Type.php +++ b/app/code/Magento/Bundle/Model/Source/Option/Type.php @@ -38,7 +38,7 @@ class Type extends \Magento\Framework\Model\AbstractExtensibleModel implements * @param AttributeValueFactory $customAttributeFactory * @param array $options * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -48,7 +48,7 @@ class Type extends \Magento\Framework\Model\AbstractExtensibleModel implements AttributeValueFactory $customAttributeFactory, array $options, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->options = $options; diff --git a/app/code/Magento/Bundle/Test/Unit/Model/OptionRepositoryTest.php b/app/code/Magento/Bundle/Test/Unit/Model/OptionRepositoryTest.php index 6c4fc418f0390d2e5262d425da13355a16724a34..72022d497ba0544f89196e0798e162dc9305d1a5 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/OptionRepositoryTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/OptionRepositoryTest.php @@ -286,9 +286,11 @@ class OptionRepositoryTest extends \PHPUnit_Framework_TestCase $optionMock->expects($this->once())->method('setParentId')->with($productId)->willReturnSelf(); $optionIdsMap = [null, $optionId, $optionId]; - $optionMock->expects($this->any())->method('getOptionId')->willReturnCallback(function () use (&$optionIdsMap) { - return array_shift($optionIdsMap); - }); + $optionMock->expects($this->any())->method('getOptionId')->willReturnCallback( + function () use (&$optionIdsMap) { + return array_shift($optionIdsMap); + } + ); $optionMock->expects($this->exactly(2))->method('getProductLinks')->willReturn([$linkedProductMock]); $this->optionResourceMock->expects($this->once())->method('save')->with($optionMock)->willReturnSelf(); @@ -364,21 +366,8 @@ class OptionRepositoryTest extends \PHPUnit_Framework_TestCase $productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); $productMock->expects($this->once())->method('getId')->willReturn($productId); $productMock->expects($this->any())->method('getSku')->willReturn($productSku); - $optionMock = $this->getMock( - '\Magento\Bundle\Model\Option', - [ - 'setStoreId', - 'setParentId', - 'getProductLinks', - 'getOptionId', - 'setOptionId', - 'setDefaultTitle', - 'getTitle' - ], - [], - '', - false - ); + + $optionMock = $this->createOptionMock(); $optionMock->expects($this->once())->method('setStoreId')->with($storeId)->willReturnSelf(); $optionMock->expects($this->once())->method('setParentId')->with($productId)->willReturnSelf(); $optionMock->expects($this->any())->method('getOptionId')->willReturn($optionId); @@ -613,4 +602,57 @@ class OptionRepositoryTest extends \PHPUnit_Framework_TestCase ->willReturn($productMock); $this->assertEquals(['object'], $this->model->getList($productSku)); } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + private function createOptionMock() + { + $contextMock = $this->getMock('Magento\Framework\Model\Context', [], [], '', false); + $registryMock = $this->getMock('Magento\Framework\Registry', [], [], '', false); + $extensionAttributesFactory = $this->getMock( + 'Magento\Framework\Api\ExtensionAttributesFactory', + [], + [], + '', + false + ); + $attributeValueFactoryMock = $this->getMock('Magento\Framework\Api\AttributeValueFactory', [], [], '', false); + $resourceMock = $this->getMock( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + [ + '_construct', + 'getIdFieldName' + ], + [], + '', + false + ); + $resourceCollectionMock = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $optionMock = $this->getMock( + 'Magento\Bundle\Model\Option', + [ + 'setStoreId', + 'setParentId', + 'getProductLinks', + 'getOptionId', + 'setOptionId', + 'setDefaultTitle', + 'getTitle' + ], + [ + $contextMock, + $registryMock, + $extensionAttributesFactory, + $attributeValueFactoryMock, + $resourceMock, + $resourceCollectionMock + ], + '', + true + ); + return $optionMock; + } } diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php index faf53d7d6a78746fb9330adfa434f40a6403aba8..64b4c6789f3cd54959a16be74fac68263b8ff396 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php @@ -695,7 +695,7 @@ class TypeTest extends \PHPUnit_Framework_TestCase ->willReturn(3.14); $result = $this->model->prepareForCartAdvanced($buyRequest, $product); - $this->assertEquals('We cannot add this item to your shopping cart.', $result); + $this->assertEquals('We can\'t add this item to your cart right now.', $result); } /** diff --git a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php index 63d5d857f4d6820e5506d23263103fb69102db6a..44355fae22189ad74f7327552ec9ea74f7214a20 100644 --- a/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Pricing/Adjustment/CalculatorTest.php @@ -209,7 +209,9 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase foreach ($optionData['selections'] as $selectionData) { $selections[] = $this->createSelectionMock($selectionData); } - $option->setData($optionData['data']); + foreach ($optionData['data'] as $key => $value) { + $option->setData($key, $value); + } $option->setData('selections', $selections); return $option; } @@ -230,7 +232,9 @@ class CalculatorTest extends \PHPUnit_Framework_TestCase // All items are saleable $selection->expects($this->any())->method('isSalable')->will($this->returnValue(true)); - $selection->setData($selectionData['data']); + foreach ($selectionData['data'] as $key => $value) { + $selection->setData($key, $value); + } $amountMock = $this->createAmountMock($selectionData['amount']); $selection->expects($this->any())->method('getAmount')->will($this->returnValue($amountMock)); $selection->expects($this->any())->method('getQuantity')->will($this->returnValue(1)); diff --git a/app/code/Magento/Bundle/Test/Unit/Pricing/Price/BundleOptionPriceTest.php b/app/code/Magento/Bundle/Test/Unit/Pricing/Price/BundleOptionPriceTest.php index 2dd5e26749bc16c16aeee5749c232d8ab9c28bde..115c70648490d5f4abeaa1ed27e6e121d2bc8acf 100644 --- a/app/code/Magento/Bundle/Test/Unit/Pricing/Price/BundleOptionPriceTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Pricing/Price/BundleOptionPriceTest.php @@ -242,7 +242,9 @@ class BundleOptionPriceTest extends \PHPUnit_Framework_TestCase foreach ($optionData['selections'] as $selectionData) { $selections[] = $this->createSelectionMock($selectionData); } - $option->setData($optionData['data']); + foreach ($optionData['data'] as $key => $value) { + $option->setData($key, $value); + } $option->setData('selections', $selections); return $option; } @@ -262,7 +264,9 @@ class BundleOptionPriceTest extends \PHPUnit_Framework_TestCase // All items are saleable $selection->expects($this->any())->method('isSalable')->will($this->returnValue(true)); - $selection->setData($selectionData['data']); + foreach ($selectionData['data'] as $key => $value) { + $selection->setData($key, $value); + } $amountMock = $this->createAmountMock($selectionData['amount']); $selection->expects($this->any())->method('getAmount')->will($this->returnValue($amountMock)); $selection->expects($this->any())->method('getQuantity')->will($this->returnValue(1)); diff --git a/app/code/Magento/Bundle/composer.json b/app/code/Magento/Bundle/composer.json index f2ae57503d4c2a4acbb777b362f83bebf14c6c31..ddc09411834f50f6715db4ad8103539915f34a44 100644 --- a/app/code/Magento/Bundle/composer.json +++ b/app/code/Magento/Bundle/composer.json @@ -3,28 +3,28 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-catalog-rule": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/module-gift-message": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-catalog-rule": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/module-gift-message": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-webapi": "0.74.0-beta10" + "magento/module-webapi": "0.74.0-beta13" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Bundle/etc/service_data_attributes.xml b/app/code/Magento/Bundle/etc/extension_attributes.xml similarity index 90% rename from app/code/Magento/Bundle/etc/service_data_attributes.xml rename to app/code/Magento/Bundle/etc/extension_attributes.xml index 8150a2dceeddd7d70d4e16ffa3d1b6996f316d5d..14e924e1a70bc9c9431a5dc062d45bd2f4022769 100644 --- a/app/code/Magento/Bundle/etc/service_data_attributes.xml +++ b/app/code/Magento/Bundle/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> <attribute code="bundle_product_options" type="Magento\Bundle\Api\Data\OptionInterface[]" /> </extension_attributes> diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml index ecc896b655639d943656e4ad96138cd4fabcaa7c..3d0db6d73a2ed8c9fbb3b42732308c429ef9eaac 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/checkbox.phtml @@ -34,7 +34,7 @@ class="change-container-classname admin__control-checkbox checkbox bundle-option-<?php echo $_option->getId() ?> <?php if ($_option->getRequired()) echo 'validate-one-required-by-name' ?>" id="bundle-option-<?php echo $_option->getId() ?>-<?php echo $_selection->getSelectionId() ?>" type="checkbox" - name="bundle_option[<?php echo $_option->getId() ?>]" + name="bundle_option[<?php echo $_option->getId() ?>][<?php echo $_selection->getId() ?>]" <?php if ($block->isSelected($_selection)):?> <?php echo ' checked="checked"'; ?> <?php endif;?> diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml index 9f49261b637733461fc17f0d96db0d8c23731aa0..777aecaf0a49a3721c04f225a2554af413fd259c 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/product/composite/fieldset/options/type/multi.phtml @@ -21,7 +21,7 @@ price="<?php echo $block->getSelectionPrice($_selections[0]) ?>" /> <?php else: ?> <select multiple="multiple" size="5" id="bundle-option-<?php echo $_option->getId() ?>" - name="bundle_option[<?php echo $_option->getId() ?>]" + name="bundle_option[<?php echo $_option->getId() ?>][]" class="admin__control-multiselect bundle-option-<?php echo $_option->getId() ?><?php if ($_option->getRequired()) echo ' required-entry' ?> multiselect change-container-classname" onchange="ProductConfigure.bundleControl.changeSelection(this)"> <?php if(!$_option->getRequired()): ?> diff --git a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml index 5c32f9c42a23c300464df14ee8292b203755b8da..81cb30bc6f7cf4e8a5eb0d624c72035809eb0ab5 100644 --- a/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml +++ b/app/code/Magento/Bundle/view/frontend/templates/catalog/product/view/type/bundle/option/multi.phtml @@ -24,7 +24,7 @@ <select multiple="multiple" size="5" id="bundle-option-<?php echo $_option->getId() ?>" - name="bundle_option[<?php echo $_option->getId() ?>]" + name="bundle_option[<?php echo $_option->getId() ?>][]" class="bundle-option-<?php echo $_option->getId() ?> multiselect product bundle option change-container-classname" <?php if ($_option->getRequired()) echo 'data-validate={required:true}' ?>> <?php if(!$_option->getRequired()): ?> diff --git a/app/code/Magento/Sendfriend/LICENSE.txt b/app/code/Magento/BundleImportExport/LICENSE.txt old mode 100644 new mode 100755 similarity index 100% rename from app/code/Magento/Sendfriend/LICENSE.txt rename to app/code/Magento/BundleImportExport/LICENSE.txt diff --git a/app/code/Magento/Sendfriend/LICENSE_AFL.txt b/app/code/Magento/BundleImportExport/LICENSE_AFL.txt old mode 100644 new mode 100755 similarity index 100% rename from app/code/Magento/Sendfriend/LICENSE_AFL.txt rename to app/code/Magento/BundleImportExport/LICENSE_AFL.txt diff --git a/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php b/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php new file mode 100755 index 0000000000000000000000000000000000000000..9f30386f84f1d857e61ee21e8572af5e5a47ad42 --- /dev/null +++ b/app/code/Magento/BundleImportExport/Model/Import/Product/Type/Bundle.php @@ -0,0 +1,651 @@ +<?php + +/** + * Import entity of bundle product type + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\BundleImportExport\Model\Import\Product\Type; + +use \Magento\Bundle\Model\Product\Price as BundlePrice; + +/** + * Class Bundle + * @package Magento\BundleImportExport\Model\Import\Product\Type + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + */ +class Bundle extends \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType +{ + + /** + * Delimiter before product option value. + */ + const BEFORE_OPTION_VALUE_DELIMITER = ';'; + + /** + * Pair value separator. + */ + const PAIR_VALUE_SEPARATOR = '='; + + /** + * Dynamic value. + */ + const VALUE_DYNAMIC = 'dynamic'; + + /** + * Fixed value. + */ + const VALUE_FIXED = 'fixed'; + + /** + * Not fixed dynamic attribute. + */ + const NOT_FIXED_DYNAMIC_ATTRIBUTE = 'price_view'; + + /** + * Selection price type fixed. + */ + const SELECTION_PRICE_TYPE_FIXED = 0; + + /** + * Selection price type percent. + */ + const SELECTION_PRICE_TYPE_PERCENT = 1; + + /** + * Instance of database adapter. + * + * @var \Magento\Framework\DB\Adapter\AdapterInterface + */ + protected $connection; + + /** + * Instance of application resource. + * + * @var \Magento\Framework\App\Resource + */ + protected $_resource; + + /** + * Array of cached options. + * + * @var array + */ + protected $_cachedOptions = []; + + /** + * Array of cached skus. + * + * @var array + */ + protected $_cachedSkus = []; + + /** + * Mapping array between cached skus and products. + * + * @var array + */ + protected $_cachedSkuToProducts = []; + + /** + * Column names that holds values with particular meaning. + * + * @var string[] + */ + protected $_specialAttributes = [ + 'price_type', + 'weight_type', + 'sku_type', + ]; + + /** + * Custom fields mapping. + * + * @inherited + */ + protected $_customFieldsMapping = [ + 'price_type' => 'bundle_price_type', + 'price_view' => 'bundle_price_view', + 'weight_type' => 'bundle_weight_type', + 'sku_type' => 'bundle_sku_type', + ]; + + /** + * Bundle field mapping. + * + * @var array + */ + protected $_bundleFieldMapping = [ + 'is_default' => 'default', + 'selection_price_value' => 'price', + 'selection_qty' => 'default_qty', + ]; + + /** + * Option type mapping. + * + * @var array + */ + protected $_optionTypeMapping = [ + 'dropdown' => 'select', + 'radiobutton' => 'radio', + 'checkbox' => 'checkbox', + 'multiselect' => 'multi', + ]; + + /** + * @param \Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory $attrSetColFac + * @param \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $prodAttrColFac + * @param array $params + * @param \Magento\Framework\App\Resource $resource + */ + public function __construct( + \Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory $attrSetColFac, + \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $prodAttrColFac, + array $params, + \Magento\Framework\App\Resource $resource + ) { + parent::__construct($attrSetColFac, $prodAttrColFac, $params); + $this->_resource = $resource; + $this->connection = $resource->getConnection('write'); + } + + /** + * Parse selections. + * + * @param array $rowData + * @param int $entityId + * + * @return array + */ + protected function parseSelections($rowData, $entityId) + { + $rowData['bundle_values'] = str_replace( + self::BEFORE_OPTION_VALUE_DELIMITER, + $this->_entityModel->getMultipleValueSeparator(), + $rowData['bundle_values'] + ); + $selections = explode( + \Magento\CatalogImportExport\Model\Import\Product::PSEUDO_MULTI_LINE_SEPARATOR, + $rowData['bundle_values'] + ); + foreach ($selections as $selection) { + $values = explode($this->_entityModel->getMultipleValueSeparator(), $selection); + $option = $this->parseOption($values); + if (isset($option['sku']) && isset($option['name'])) { + if (!isset($this->_cachedOptions[$entityId])) { + $this->_cachedOptions[$entityId] = []; + } + $this->_cachedSkus[] = $option['sku']; + if (!isset($this->_cachedOptions[$entityId][$option['name']])) { + $this->_cachedOptions[$entityId][$option['name']] = []; + $this->_cachedOptions[$entityId][$option['name']] = $option; + $this->_cachedOptions[$entityId][$option['name']]['selections'] = []; + } + $this->_cachedOptions[$entityId][$option['name']]['selections'][] = $option; + $this->_cachedOptionSelectQuery[] = + $this->connection->select() + ->getAdapter() + ->quoteInto('(parent_id = '.(int)$entityId.' AND title = ?)', $option['name']); + } + } + return $selections; + } + + /** + * Parse the option. + * + * @param array $values + * + * @return array + */ + protected function parseOption($values) + { + $option = []; + foreach ($values as $keyValue) { + $keyValue = trim($keyValue); + if ($pos = strpos($keyValue, self::PAIR_VALUE_SEPARATOR)) { + $key = substr($keyValue, 0, $pos); + $value = substr($keyValue, $pos + 1); + if ($key == 'type') { + if (isset($this->_optionTypeMapping[$value])) { + $value = $this->_optionTypeMapping[$value]; + } + } + $option[$key] = $value; + } + } + return $option; + } + + /** + * Populate the option template. + * + * @param array $option + * @param int $entityId + * @param int $index + * @return array + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function populateOptionTemplate($option, $entityId, $index = null) + { + $populatedOption = [ + 'parent_id' => $entityId, + 'required' => isset($option['required']) ? $option['required'] : 1, + 'position' => ($index === null ? 0 : $index), + 'type' => isset($option['type']) ? $option['type'] : 'select', + ]; + if (isset($option['option_id'])) { + $populatedOption['option_id'] = $option['option_id']; + } + return $populatedOption; + } + + /** + * Populate the option value template. + * + * @param array $option + * @param int $optionId + * @param int $storeId + * + * @return array|bool + */ + protected function populateOptionValueTemplate($option, $optionId, $storeId = 0) + { + if (!isset($option['name']) || !$optionId) { + return false; + } + return [ + 'option_id' => $optionId, + 'store_id' => $storeId, + 'title' => $option['name'], + ]; + } + + /** + * Populate the option value template. + * + * @param array $selection + * @param int $optionId + * @param int $parentId + * @param int $index + * @return array + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + protected function populateSelectionTemplate($selection, $optionId, $parentId, $index) + { + if (!isset($selection['parent_product_id'])) { + if (!isset($this->_cachedSkuToProducts[$selection['sku']])) { + return false; + } + $productId = $this->_cachedSkuToProducts[$selection['sku']]; + } else { + $productId = $selection['parent_product_id']; + } + $populatedSelection = [ + 'option_id' => (int)$optionId, + 'parent_product_id' => (int)$parentId, + 'product_id' => (int)$productId, + 'position' => (int)$index, + 'is_default' => (isset($selection['default']) && $selection['default']) ? 1 : 0, + 'selection_price_type' => (isset($selection['price_type']) && $selection['price_type'] == self::VALUE_FIXED) + ? self::SELECTION_PRICE_TYPE_FIXED : self::SELECTION_PRICE_TYPE_PERCENT, + 'selection_price_value' => (isset($selection['price'])) ? (float)$selection['price'] : 0.0, + 'selection_qty' => (isset($selection['default_qty'])) ? (float)$selection['default_qty'] : 1.0, + 'selection_can_change_qty' => 1, + ]; + if (isset($selection['selection_id'])) { + $populatedSelection['selection_id'] = $selection['selection_id']; + } + return $populatedSelection; + } + + /** + * Retrieve mapping between skus and products. + * + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + */ + protected function retrieveProducsByCachedSkus() + { + $this->_cachedSkuToProducts = $this->connection->fetchPairs( + $this->connection->select()->from( + $this->_resource->getTableName('catalog_product_entity'), + ['sku', 'entity_id'] + )->where( + 'sku IN (?)', + $this->_cachedSkus + ) + ); + return $this; + } + + /** + * Save product type specific data. + * + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + */ + public function saveData() + { + if ($this->_entityModel->getBehavior() == \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE) { + $productIds = []; + $newSku = $this->_entityModel->getNewSku(); + while ($bunch = $this->_entityModel->getNextBunch()) { + foreach ($bunch as $rowNum => $rowData) { + $productData = $newSku[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]]; + $productIds[] = $productData['entity_id']; + } + $this->deleteOptionsAndSelections($productIds); + } + } else { + $newSku = $this->_entityModel->getNewSku(); + while ($bunch = $this->_entityModel->getNextBunch()) { + foreach ($bunch as $rowNum => $rowData) { + if (!$this->_entityModel->isRowAllowedToImport($rowData, $rowNum)) { + continue; + } + $productData = $newSku[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]]; + if ($this->_type != $productData['type_id']) { + continue; + } + $this->parseSelections($rowData, $productData['entity_id']); + } + if (!empty($this->_cachedOptions)) { + $this->retrieveProducsByCachedSkus(); + $this->populateExistingOptions(); + $this->insertOptions(); + $this->insertSelections(); + $this->clear(); + } + } + } + return $this; + } + + /** + * Check whether the row is valid. + * + * @param array $rowData + * @param int $rowNum + * @param bool $isNewProduct + * @return bool + */ + public function isRowValid(array $rowData, $rowNum, $isNewProduct = true) + { + $rowData = array_merge($rowData, $this->transformBundleCustomAttributes($rowData)); + return parent::isRowValid($rowData, $rowNum, $isNewProduct); + } + + /** + * Prepare attributes with default value for save. + * + * @param array $rowData + * @param bool $withDefaultValue + * @return array + */ + public function prepareAttributesWithDefaultValueForSave(array $rowData, $withDefaultValue = true) + { + $resultAttrs = parent::prepareAttributesWithDefaultValueForSave($rowData, $withDefaultValue); + $resultAttrs = array_merge($resultAttrs, $this->transformBundleCustomAttributes($rowData)); + return $resultAttrs; + } + + /** + * Transform dynamic/fixed values to integer. + * + * @param array $rowData + * @return array + */ + protected function transformBundleCustomAttributes($rowData) + { + $resultAttrs = []; + foreach (array_keys($this->_customFieldsMapping) as $oldKey) { + if (isset($rowData[$oldKey])) { + if ($oldKey != self::NOT_FIXED_DYNAMIC_ATTRIBUTE) { + $resultAttrs[$oldKey] = (($rowData[$oldKey] == self::VALUE_FIXED) ? + BundlePrice::PRICE_TYPE_FIXED : + BundlePrice::PRICE_TYPE_DYNAMIC); + } + } + } + return $resultAttrs; + } + + /** + * Populates existing options. + * + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + */ + protected function populateExistingOptions() + { + $existingOptions = $this->connection->fetchAssoc( + $this->connection->select()->from( + ['bo' => $this->_resource->getTableName('catalog_product_bundle_option')], + ['option_id', 'parent_id', 'required', 'position', 'type'] + )->joinLeft( + ['bov' => $this->_resource->getTableName('catalog_product_bundle_option_value')], + 'bo.option_id = bov.option_id', + ['value_id', 'title'] + )->where( + implode(' OR ', $this->_cachedOptionSelectQuery) + ) + ); + foreach ($existingOptions as $optionId => $option) { + $this->_cachedOptions[$option['parent_id']][$option['title']]['option_id'] = $optionId; + foreach ($option as $key => $value) { + if (!isset($this->_cachedOptions[$option['parent_id']][$option['title']][$key])) { + $this->_cachedOptions[$option['parent_id']][$option['title']][$key] = $value; + } + } + } + $this->populateExistingSelections($existingOptions); + return $this; + } + + /** + * Populate existing selections. + * + * @param array $existingOptions + * + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + */ + protected function populateExistingSelections($existingOptions) + { + //@codingStandardsIgnoreStart + $existingSelections = $this->connection->fetchAll( + $this->connection->select()->from( + $this->_resource->getTableName('catalog_product_bundle_selection') + )->where( + 'option_id IN (?)', + array_keys($existingOptions) + ) + ); + foreach ($existingSelections as $existingSelection) { + $optionTitle = $existingOptions[$existingSelection['option_id']]['title']; + $cachedOptionsSelections = $this->_cachedOptions[$existingSelection['parent_product_id']][$optionTitle]['selections']; + foreach ($cachedOptionsSelections as $selectIndex => $selection) { + $productId = $this->_cachedSkuToProducts[$selection['sku']]; + if ($productId == $existingSelection['product_id']) { + foreach (array_keys($existingSelection) as $origKey) { + $key = isset($this->_bundleFieldMapping[$origKey]) + ? $this->_bundleFieldMapping[$origKey] + : $origKey; + if ( + !isset($this->_cachedOptions[$existingSelection['parent_product_id']][$optionTitle]['selections'][$selectIndex][$key]) + ) { + $this->_cachedOptions[$existingSelection['parent_product_id']][$optionTitle]['selections'][$selectIndex][$key] = + $existingSelection[$origKey]; + } + } + break; + } + } + } + // @codingStandardsIgnoreEnd + return $this; + } + + /** + * Insert options. + * + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + */ + protected function insertOptions() + { + $optionTable = $this->_resource->getTableName('catalog_product_bundle_option'); + $optionValueTable = $this->_resource->getTableName('catalog_product_bundle_option_value'); + $productIds = []; + $insert = []; + foreach ($this->_cachedOptions as $entityId => $options) { + $index = 0; + $productIds[] = $entityId; + foreach ($options as $key => $option) { + if (isset($option['position'])) { + $index = $option['position']; + } + if ($tmpArray = $this->populateOptionTemplate($option, $entityId, $index)) { + $insert[] = $tmpArray; + $this->_cachedOptions[$entityId][$key]['index'] = $index; + $index++; + } + } + } + $this->connection->insertOnDuplicate($optionTable, $insert, ['required', 'position', 'type']); + $optionIds = $this->connection->fetchAssoc( + $this->connection->select()->from( + $optionTable, + ['option_id', 'position', 'parent_id'] + )->where( + 'parent_id IN (?)', + $productIds + ) + ); + $insertValues = $this->populateInsertOptionValues($optionIds); + if (!empty($insertValues)) { + $this->connection->insertOnDuplicate($optionValueTable, $insertValues, ['title']); + } + return $this; + } + + /** + * Populate array for insert option values + * @param array $optionIds + * @return array + */ + protected function populateInsertOptionValues($optionIds) + { + $insertValues = []; + foreach ($this->_cachedOptions as $entityId => $options) { + foreach ($options as $key => $option) { + foreach ($optionIds as $optionId => $assoc) { + if ($assoc['position'] == $this->_cachedOptions[$entityId][$key]['index'] + && $assoc['parent_id'] == $entityId) { + $insertValues[] = $this->populateOptionValueTemplate($option, $optionId); + $this->_cachedOptions[$entityId][$key]['option_id'] = $optionId; + break; + } + } + } + } + return $insertValues; + } + + /** + * Insert selections. + * + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + */ + protected function insertSelections() + { + $selectionTable = $this->_resource->getTableName('catalog_product_bundle_selection'); + $selections = []; + foreach ($this->_cachedOptions as $productId => $options) { + foreach ($options as $option) { + $index = 0; + foreach ($option['selections'] as $selection) { + if (isset($selection['position'])) { + $index = $selection['position']; + } + if ($tmpArray = $this->populateSelectionTemplate( + $selection, + $option['option_id'], + $productId, + $index + )) { + $selections[] = $tmpArray; + $index++; + } + } + } + } + if (!empty($selections)) { + $this->connection->insertOnDuplicate( + $selectionTable, + $selections, + [ + 'product_id', + 'position', + 'is_default', + 'selection_price_type', + 'selection_price_value', + 'selection_qty', + 'selection_can_change_qty' + ] + ); + } + return $this; + } + + /** + * Delete options and selections. + * + * @param array $productIds + * + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + */ + protected function deleteOptionsAndSelections($productIds) + { + $optionTable = $this->_resource->getTableName('catalog_product_bundle_option'); + $optionValueTable = $this->_resource->getTableName('catalog_product_bundle_option_value'); + $valuesIds = $this->connection->fetchAssoc($this->connection->select()->from( + ['bov' => $optionValueTable], + ['value_id'] + )->joinLeft( + ['bo' => $optionTable], + 'bo.option_id = bov.option_id', + ['option_id'] + )->where( + 'parent_id IN (?)', + $productIds + )); + $this->connection->delete( + $optionTable, + $this->connection->quoteInto('value_id IN (?)', array_keys($valuesIds)) + ); + $productIdsInWhere = $this->connection->quoteInto('parent_id IN (?)', $productIds); + $this->connection->delete( + $optionTable, + $this->connection->quoteInto('parent_id IN (?)', $productIdsInWhere) + ); + $this->connection->delete( + $optionTable, + $this->connection->quoteInto('parent_product_id IN (?)', $productIdsInWhere) + ); + return $this; + } + + /** + * Clear cached values between bunches + * + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + */ + protected function clear() + { + $this->_cachedOptions = []; + $this->_cachedOptionSelectQuery = []; + $this->_cachedSkus = []; + $this->_cachedSkuToProducts = []; + return $this; + } +} diff --git a/app/code/Magento/BundleImportExport/README.md b/app/code/Magento/BundleImportExport/README.md new file mode 100644 index 0000000000000000000000000000000000000000..faabeefc79292982ce4354c10ecd30591e32306a --- /dev/null +++ b/app/code/Magento/BundleImportExport/README.md @@ -0,0 +1,2 @@ +Magento_BundleImportExport module implements Bundle products import/export functionality. +This module is designed to extend existing functionality of Magento_CatalogImportExport module by adding new product type. 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 new file mode 100755 index 0000000000000000000000000000000000000000..a4ecc0261c106ab4c731effca1655f63de612431 --- /dev/null +++ b/app/code/Magento/BundleImportExport/Test/Unit/Model/Import/Product/Type/BundleTest.php @@ -0,0 +1,376 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\BundleImportExport\Test\Unit\Model\Import\Product\Type; + +use \Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +class BundleTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\BundleImportExport\Model\Import\Product\Type\Bundle + */ + protected $bundle; + + /** + * @var ObjectManagerHelper + */ + protected $objectManagerHelper; + + /** + * @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resource; + + /** + * @var \Magento\CatalogImportExport\Model\Import\Product|\PHPUnit_Framework_MockObject_MockObject + */ + protected $entityModel; + + /** + * @var [] + */ + protected $params; + + /** @var + * \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject + */ + protected $connection; + + /** + * @var \Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $attrSetColFac; + + /** + * @var \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $prodAttrColFac; + + /** + * @var \Magento\Eav\Model\Resource\Entity\Attribute\Set\Collection|\PHPUnit_Framework_MockObject_MockObject + */ + protected $setCollection; + + protected function setUp() + { + $this->entityModel = $this->getMock( + 'Magento\CatalogImportExport\Model\Import\Product', + ['getBehavior', 'getNewSku', 'getNextBunch', 'isRowAllowedToImport', 'getRowScope', 'getConnection'], + [], + '', + false + ); + $this->connection = $this->getMock( + 'Magento\Framework\DB\Adapter\Pdo\Mysql', + ['select', 'fetchAll', 'fetchPairs', 'joinLeft', 'insertOnDuplicate', 'delete', 'quoteInto', 'fetchAssoc'], + [], + '', + false + ); + $select = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $select->expects($this->any())->method('from')->will($this->returnSelf()); + $select->expects($this->any())->method('where')->will($this->returnSelf()); + $select->expects($this->any())->method('joinLeft')->will($this->returnSelf()); + $adapter = $this->getMock('Magento\Framework\DB\Adapter\Pdo\Mysql', [], [], '', false); + $adapter->expects($this->any())->method('quoteInto')->will($this->returnValue('query')); + $select->expects($this->any())->method('getAdapter')->willReturn($adapter); + $this->connection->expects($this->any())->method('select')->will($this->returnValue($select)); + $this->connection->expects($this->any())->method('fetchPairs')->will($this->returnValue([ + '1' => '1', '2' => '2' + ])); + $this->connection->expects($this->any())->method('insertOnDuplicate')->willReturnSelf(); + $this->connection->expects($this->any())->method('delete')->willReturnSelf(); + $this->connection->expects($this->any())->method('quoteInto')->willReturn(''); + $this->resource = $this->getMock( + 'Magento\Framework\App\Resource', + ['getConnection', 'getTableName'], + [], + '', + false + ); + $this->resource->expects($this->any())->method('getConnection')->will( + $this->returnValue($this->connection) + ); + $this->resource->expects($this->any())->method('getTableName')->will( + $this->returnValue('tableName') + ); + $this->attrSetColFac = $this->getMock( + 'Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory', + ['create'], + [], + '', + false + ); + $this->setCollection = $this->getMock( + 'Magento\Eav\Model\Resource\Entity\Attribute\Set\Collection', + ['setEntityTypeFilter'], + [], + '', + false + ); + $this->attrSetColFac->expects($this->any())->method('create')->will( + $this->returnValue($this->setCollection) + ); + $this->setCollection->expects($this->any()) + ->method('setEntityTypeFilter') + ->will($this->returnValue([])); + $this->prodAttrColFac = $this->getMock( + 'Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory', + ['create'], + [], + '', + false + ); + $attrCollection = + $this->getMock('\Magento\Catalog\Model\Resource\Product\Attribute\Collection', [], [], '', false); + $attrCollection->expects($this->any())->method('addFieldToFilter')->willReturn([]); + + $this->prodAttrColFac->expects($this->any())->method('create')->will( + $this->returnValue($attrCollection) + ); + $this->params = [ + 0 => $this->entityModel, + 1 => 'bundle' + ]; + $this->objectManagerHelper = new ObjectManagerHelper($this); + + $this->bundle = $this->objectManagerHelper->getObject( + 'Magento\BundleImportExport\Model\Import\Product\Type\Bundle', + [ + 'attrSetColFac' => $this->attrSetColFac, + 'prodAttrColFac' => $this->prodAttrColFac, + 'resource' => $this->resource, + 'params' => $this->params + ] + ); + } + + /** + * Test for method saveData() + * + * @param array $skus + * @param array $bunch + * @param $allowImport + * @dataProvider testSaveDataProvider + */ + public function testSaveData($skus, $bunch, $allowImport) + { + $this->entityModel->expects($this->any())->method('getBehavior')->will($this->returnValue( + \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND + )); + $this->entityModel->expects($this->once())->method('getNewSku')->will($this->returnValue($skus['newSku'])); + $this->entityModel->expects($this->at(2))->method('getNextBunch')->will($this->returnValue([$bunch])); + $this->entityModel->expects($this->any())->method('isRowAllowedToImport')->will($this->returnValue( + $allowImport + )); + + $adapter = $this->getMock('Magento\Framework\DB\Adapter\Pdo\Mysql', [], [], '', false); + $adapter->expects($this->any())->method('quoteInto')->will($this->returnValue('query')); + + $select = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $select->expects($this->any())->method('getAdapter')->willReturn($adapter); + $select->expects($this->any())->method('from')->will($this->returnSelf()); + $select->expects($this->any())->method('where')->will($this->returnSelf()); + $select->expects($this->any())->method('joinLeft')->will($this->returnSelf()); + $this->connection->expects($this->any())->method('select')->will($this->returnValue($select)); + + $this->connection->expects($this->any())->method('fetchAssoc')->with($select)->will($this->returnValue([ + '1' => [ + 'option_id' => '1', + 'parent_id' => '1', + 'required' => '1', + 'position' => '1', + 'type' => 'bundle', + 'value_id' => '1', + 'title' => 'Bundle1', + 'name' => 'bundle1', + 'selections' => [ + ['name' => 'Bundlen1', + 'type' => 'dropdown', + 'required' => '1', + 'sku' => '1', + 'price' => '10', + 'price_type' => 'fixed', + 'default_qty' => '1', + 'is_defaul' => '1', + 'position' => '1', + 'option_id' => '1'] + ] + ], + '2' => [ + 'option_id' => '6', + 'parent_id' => '6', + 'required' => '6', + 'position' => '6', + 'type' => 'bundle', + 'value_id' => '6', + 'title' => 'Bundle6', + 'selections' => [ + ['name' => 'Bundlen6', + 'type' => 'dropdown', + 'required' => '1', + 'sku' => '222', + 'price' => '10', + 'price_type' => 'percent', + 'default_qty' => '2', + 'is_defaul' => '1', + 'position' => '6', + 'option_id' => '6'] + ] + ] + ])); + $this->connection->expects($this->any())->method('fetchAll')->with($select)->will($this->returnValue([[ + 'selection_id' => '1', + 'option_id' => '1', + 'parent_product_id' => '1', + 'product_id' => '1', + 'position' => '1', + 'is_default' => '1' + ]])); + + $this->bundle->saveData(); + } + + + /** + * Data provider for saveData() + * + * @return array + */ + public function testSaveDataProvider() + { + return [ + [ + 'skus' => ['newSku' => ['sku' => ['sku' => 'sku', 'entity_id' => 3, 'type_id' => 'bundle']]], + 'bunch' => ['bundle_values' => 'value1', 'sku' => 'sku', 'name' => 'name'], + 'allowImport' => true + ], + [ + 'skus' => ['newSku' => ['sku' => ['sku' => 'sku', 'entity_id' => 3, 'type_id' => 'simple']]], + 'bunch' => ['bundle_values' => 'value1', 'sku' => 'sku', 'name' => 'name'], + 'allowImport' => true + ], + [ + 'skus' => ['newSku' => ['sku' => ['sku' => 'sku', 'entity_id' => 3, 'type_id' => 'bundle']]], + 'bunch' => ['bundle_values' => 'value1', 'sku' => 'sku', 'name' => 'name'], + 'allowImport' => false + ], + [ + 'skus' => ['newSku' => [ + 'sku' => ['sku' => 'sku', 'entity_id' => 3, 'type_id' => 'bundle'], + 'sku1' => ['sku1' => 'sku1', 'entity_id' => 3, 'type_id' => 'bundle'], + 'sku2' => ['sku2' => 'sku2', 'entity_id' => 3, 'type_id' => 'bundle'] + ]], + 'bunch' => [ + 'sku' => 'sku', + 'name' => 'name', + 'bundle_values' => + 'name=Bundle1,' + . 'type=dropdown,' + . 'required=1,' + . 'sku=1,' + . 'price=10,' + . 'price_type=fixed,' + . 'default_qty=1,' + . 'is_defaul=1,' + . 'position=1,' + . 'option_id=1 | name=Bundle2,' + . 'type=dropdown,' + . 'required=1,' + . 'sku=2,' + . 'price=10,' + . 'price_type=fixed,' + . 'default_qty=1,' + . 'is_defaul=1,' + . 'position=2,' + . 'option_id=2' + ], + 'allowImport' => true + ] + ]; + } + + /** + * Test for method saveData() + */ + public function testSaveDataDelete() + { + $this->entityModel->expects($this->any())->method('getBehavior')->will($this->returnValue( + \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE + )); + $this->entityModel->expects($this->once())->method('getNewSku')->will($this->returnValue([ + 'sku' => ['sku' => 'sku', 'entity_id' => 3, 'attr_set_code' => 'Default', 'type_id' => 'bundle'] + ])); + $this->entityModel->expects($this->at(2))->method('getNextBunch')->will($this->returnValue([ + ['bundle_values' => 'value1', 'sku' => 'sku', 'name' => 'name'] + ])); + $this->entityModel->expects($this->any())->method('isRowAllowedToImport')->will($this->returnValue(true)); + $select = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $this->connection->expects($this->any())->method('select')->will($this->returnValue($select)); + $select->expects($this->any())->method('from')->will($this->returnSelf()); + $select->expects($this->any())->method('where')->will($this->returnSelf()); + $select->expects($this->any())->method('joinLeft')->will($this->returnSelf()); + $this->connection->expects($this->any())->method('fetchAssoc')->with($select)->will($this->returnValue([ + ['id1', 'id2', 'id_3'] + ])); + $this->bundle->saveData(); + } + + public function testPrepareAttributesWithDefaultValueForSaveInsideCall() + { + $bundleMock = $this->getMock( + 'Magento\BundleImportExport\Model\Import\Product\Type\Bundle', + ['transformBundleCustomAttributes'], + [], + '', + false + ); + // Set some attributes to bypass errors due to static call inside method. + $attrVal = 'value'; + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET => $attrVal, + ]; + $this->setPropertyValue($bundleMock, '_attributes', [ + $attrVal => [], + ]); + + $bundleMock + ->expects($this->once()) + ->method('transformBundleCustomAttributes') + ->with($rowData) + ->willReturn([]); + + $bundleMock->prepareAttributesWithDefaultValueForSave($rowData); + } + + /** + * Test for isRowValid() + */ + public function testIsRowValid() + { + $this->entityModel->expects($this->any())->method('getRowScope')->will($this->returnValue(-1)); + $rowData = [ + 'price_type' => 'fixed', + 'price_view' => 'bundle_price_view' + ]; + $this->assertEquals($this->bundle->isRowValid($rowData, 0), true); + } + + /** + * @param $object + * @param $property + * @param $value + */ + protected function setPropertyValue(&$object, $property, $value) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionProperty = $reflection->getProperty($property); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($object, $value); + return $object; + } +} diff --git a/app/code/Magento/BundleImportExport/composer.json b/app/code/Magento/BundleImportExport/composer.json new file mode 100755 index 0000000000000000000000000000000000000000..ddbc85cb67cb1d20f44a4bdb9c64ab3bf44f0127 --- /dev/null +++ b/app/code/Magento/BundleImportExport/composer.json @@ -0,0 +1,28 @@ +{ + "name": "magento/module-bundle-import-export", + "description": "N/A", + "require": { + "php": "~5.5.0|~5.6.0", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-import-export": "0.74.0-beta13", + "magento/module-catalog-import-export": "0.74.0-beta13", + "magento/module-bundle": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/magento-composer-installer": "*" + }, + "type": "magento2-module", + "version": "0.74.0-beta13", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "extra": { + "map": [ + [ + "*", + "Magento/BundleImportExport" + ] + ] + } +} diff --git a/app/code/Magento/BundleImportExport/etc/di.xml b/app/code/Magento/BundleImportExport/etc/di.xml new file mode 100755 index 0000000000000000000000000000000000000000..ba3b3261d78506c988106a21ab837e00053c9719 --- /dev/null +++ b/app/code/Magento/BundleImportExport/etc/di.xml @@ -0,0 +1,9 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> +</config> diff --git a/app/code/Magento/BundleImportExport/etc/import.xml b/app/code/Magento/BundleImportExport/etc/import.xml new file mode 100755 index 0000000000000000000000000000000000000000..551a8bf71c0d0c760f597d9365b0ab261b1b8664 --- /dev/null +++ b/app/code/Magento/BundleImportExport/etc/import.xml @@ -0,0 +1,10 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../ImportExport/etc/import.xsd"> + <entityType entity="catalog_product" name="bundle" model="Magento\BundleImportExport\Model\Import\Product\Type\Bundle" /> +</config> diff --git a/app/code/Magento/BundleImportExport/etc/module.xml b/app/code/Magento/BundleImportExport/etc/module.xml new file mode 100755 index 0000000000000000000000000000000000000000..76f0abbdfe9e0fc9deb584514269d8d7860a2dea --- /dev/null +++ b/app/code/Magento/BundleImportExport/etc/module.xml @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd"> + <module name="Magento_BundleImportExport" setup_version="2.0.0"> + </module> +</config> diff --git a/app/code/Magento/CacheInvalidate/composer.json b/app/code/Magento/CacheInvalidate/composer.json index 14dfe1991c3cc68acb4704227101c474ffc4d9ee..5045f5b065cb0b6b80ecc9810dd84ed828bc7c26 100644 --- a/app/code/Magento/CacheInvalidate/composer.json +++ b/app/code/Magento/CacheInvalidate/composer.json @@ -3,12 +3,12 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-page-cache": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-page-cache": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Captcha/composer.json b/app/code/Magento/Captcha/composer.json index 0d403af211c657d9b84e56406d851f01611932dd..8e61f79ac764e5f722d5de600b515d27f5abc4be 100644 --- a/app/code/Magento/Captcha/composer.json +++ b/app/code/Magento/Captcha/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Captcha/etc/service_data_attributes.xml b/app/code/Magento/Captcha/etc/extension_attributes.xml similarity index 91% rename from app/code/Magento/Captcha/etc/service_data_attributes.xml rename to app/code/Magento/Captcha/etc/extension_attributes.xml index 9fe1969b7130aa69fc31449f53b48016373027ef..e99af65250102d4db36964850c3ee1d602f08b99 100644 --- a/app/code/Magento/Captcha/etc/service_data_attributes.xml +++ b/app/code/Magento/Captcha/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Quote\Api\Data\AddressAdditionalDataInterface"> <attribute code="captcha_string" type="string" /> <attribute code="captcha_form_id" type="string" /> diff --git a/app/code/Magento/Catalog/Api/Data/ProductLinkInterface.php b/app/code/Magento/Catalog/Api/Data/ProductLinkInterface.php index 0c21c9d65562d9179fac25cc17b1a6adc906250f..c05a4514ff37f782d78125c8a250bd0ccf2b2a32 100644 --- a/app/code/Magento/Catalog/Api/Data/ProductLinkInterface.php +++ b/app/code/Magento/Catalog/Api/Data/ProductLinkInterface.php @@ -12,19 +12,19 @@ namespace Magento\Catalog\Api\Data; interface ProductLinkInterface extends \Magento\Framework\Api\ExtensibleDataInterface { /** - * Get product SKU + * Get SKU * * @return string */ - public function getProductSku(); + public function getSku(); /** - * Set product SKU + * Set SKU * * @param string $sku * @return $this */ - public function setProductSku($sku); + public function setSku($sku); /** * Get link type diff --git a/app/code/Magento/Catalog/Api/ProductLinkManagementInterface.php b/app/code/Magento/Catalog/Api/ProductLinkManagementInterface.php index 592c30d139267abf2f8c144fdc500f37aaaec07a..8fecf18233ed1eee00001f26d14bf9bdad7ef4a6 100644 --- a/app/code/Magento/Catalog/Api/ProductLinkManagementInterface.php +++ b/app/code/Magento/Catalog/Api/ProductLinkManagementInterface.php @@ -24,11 +24,10 @@ interface ProductLinkManagementInterface * Assign a product link to another product * * @param string $sku - * @param string $type * @param \Magento\Catalog\Api\Data\ProductLinkInterface[] $items * @throws \Magento\Framework\Exception\NoSuchEntityException * @throws \Magento\Framework\Exception\CouldNotSaveException * @return bool */ - public function setProductLinks($sku, $type, array $items); + public function setProductLinks($sku, array $items); } diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Category/Widget/Chooser.php b/app/code/Magento/Catalog/Block/Adminhtml/Category/Widget/Chooser.php old mode 100644 new mode 100755 index e71abb171e09ffb1043d31fbedc263655f4eff9e..53fb1b7e0419d74a8582d25c3732644bde0bde7b --- a/app/code/Magento/Catalog/Block/Adminhtml/Category/Widget/Chooser.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Category/Widget/Chooser.php @@ -172,6 +172,7 @@ class Chooser extends \Magento\Catalog\Block\Adminhtml\Category\Tree * * @param bool|null $expanded * @return string + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function getLoadTreeUrl($expanded = null) { diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php index 51b88d55268774f48ef71c7ed1b6af9b6cda260e..941e60fb3079cd296ddbf903920563ba34dfbc9e 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Advanced.php @@ -85,7 +85,7 @@ class Advanced extends Generic 'label' => __('Attribute Code'), 'title' => __('Attribute Code'), 'note' => __( - 'For internal use. Must be unique with no spaces. Maximum length of attribute code must be less than %1 symbols', + 'This is used internally. Make sure you don\'t use spaces or more than %1 symbols.', \Magento\Eav\Model\Entity\Attribute::ATTRIBUTE_CODE_MAX_LENGTH ), 'class' => $validateClass diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php index 837e2ac4f8107d8510cc79ac1349d9dcfb0e327d..c974a84d624dd149239a3526b00d914df343b4de 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php @@ -224,9 +224,9 @@ class Front extends Generic ) ); + $this->setForm($form); $form->setValues($attributeObject->getData()); $this->propertyLocker->lock($form); - $this->setForm($form); return parent::_prepareForm(); } } diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Category.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Category.php index b5c69b661f0856d71b5716504ff18d966c6eed6f..54a51a1a55148aee7edeb0d7fb509d7175b408e4 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Category.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Category.php @@ -132,7 +132,7 @@ class Category extends \Magento\Framework\Data\Form\Element\Multiselect 'id' => 'add_category_button', 'label' => $newCategoryCaption, 'title' => $newCategoryCaption, - 'onclick' => 'jQuery("#new-category").dialog("open")', + 'onclick' => 'jQuery("#new-category").trigger("openModal")', 'disabled' => $this->getDisabled(), ] ); diff --git a/app/code/Magento/Catalog/Block/Product/NewProduct.php b/app/code/Magento/Catalog/Block/Product/NewProduct.php index 9787255a0132bcac2407e9c31567da916a17a7bf..d987a78a43f30706306f08d40c5db86117218ef0 100644 --- a/app/code/Magento/Catalog/Block/Product/NewProduct.php +++ b/app/code/Magento/Catalog/Block/Product/NewProduct.php @@ -67,7 +67,6 @@ class NewProduct extends \Magento\Catalog\Block\Product\AbstractProduct implemen $context, $data ); - $this->_isScopePrivate = true; } /** diff --git a/app/code/Magento/Catalog/Block/Product/View/Options/Type/Select.php b/app/code/Magento/Catalog/Block/Product/View/Options/Type/Select.php index 0a8f2c6a6f641cb6717197077a0a5392784783af..7da80121645d24a199e980a2df32a05aa918145c 100644 --- a/app/code/Magento/Catalog/Block/Product/View/Options/Type/Select.php +++ b/app/code/Magento/Catalog/Block/Product/View/Options/Type/Select.php @@ -89,7 +89,8 @@ class Select extends \Magento\Catalog\Block\Product\View\Options\AbstractOptions $type = 'radio'; $class = 'radio admin__control-radio'; if (!$_option->getIsRequire()) { - $selectHtml .= '<div class="field admin__field choice"><input type="radio" id="options_' . + $selectHtml .= '<div class="field choice admin__field admin__field-option">' . + '<input type="radio" id="options_' . $_option->getId() . '" class="' . $class . @@ -97,7 +98,7 @@ class Select extends \Magento\Catalog\Block\Product\View\Options\AbstractOptions $_option->getId() . ']"' . ($this->getSkipJsReloadPrice() ? '' : ' onclick="opConfig.reloadPrice()"') . - ' value="" checked="checked" /><label class="label" for="options_' . + ' value="" checked="checked" /><label class="label admin__field-label" for="options_' . $_option->getId() . '"><span>' . __('None') . '</span></label></div>'; @@ -153,7 +154,7 @@ class Select extends \Magento\Catalog\Block\Product\View\Options\AbstractOptions ' price="' . $this->pricingHelper->currencyByStore($_value->getPrice(true), $store, false) . '" />' . - '<label class="label" for="options_' . + '<label class="label admin__field-label" for="options_' . $_option->getId() . '_' . $count . diff --git a/app/code/Magento/Catalog/Block/Product/Widget/NewWidget.php b/app/code/Magento/Catalog/Block/Product/Widget/NewWidget.php index e1eabc8745699639b3bb351d31c71a00d5df3176..e4f7573a491ba320494d06cc57b26239c0aa95eb 100644 --- a/app/code/Magento/Catalog/Block/Product/Widget/NewWidget.php +++ b/app/code/Magento/Catalog/Block/Product/Widget/NewWidget.php @@ -52,7 +52,7 @@ class NewWidget extends \Magento\Catalog\Block\Product\NewProduct implements \Ma switch ($this->getDisplayType()) { case self::DISPLAY_TYPE_NEW_PRODUCTS: $collection = parent::_getProductCollection() - ->setPageSize($this->getProductsPerPage()) + ->setPageSize($this->getPageSize()) ->setCurPage($this->getCurrentPage()); break; default: @@ -76,7 +76,7 @@ class NewWidget extends \Magento\Catalog\Block\Product\NewProduct implements \Ma $collection = $this->_addProductAttributesAndPrices($collection) ->addStoreFilter() ->addAttributeToSort('created_at', 'desc') - ->setPageSize($this->getProductsPerPage()) + ->setPageSize($this->getPageSize()) ->setCurPage($this->getCurrentPage()); return $collection; } @@ -122,7 +122,7 @@ class NewWidget extends \Magento\Catalog\Block\Product\NewProduct implements \Ma } /** - * Retrieve how much products should be displayed + * Retrieve how many products should be displayed * * @return int */ @@ -135,7 +135,7 @@ class NewWidget extends \Magento\Catalog\Block\Product\NewProduct implements \Ma } /** - * Retrieve how much products should be displayed + * Retrieve how many products should be displayed * * @return int */ @@ -160,6 +160,16 @@ class NewWidget extends \Magento\Catalog\Block\Product\NewProduct implements \Ma return (bool)$this->getData('show_pager'); } + /** + * Retrieve how many products should be displayed on page + * + * @return int + */ + protected function getPageSize() + { + return $this->showPager() ? $this->getProductsPerPage() : $this->getProductsCount(); + } + /** * Render pagination HTML * diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php index 110cb1a5f752db557f1ee4e6d1c843714b6dc741..9585bce699f5faa9b579089f3fbbd8313344b346 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Set/Delete.php @@ -39,7 +39,7 @@ class Delete extends \Magento\Catalog\Controller\Adminhtml\Product\Set $this->messageManager->addSuccess(__('The attribute set has been removed.')); $resultRedirect->setPath('catalog/*/'); } catch (\Exception $e) { - $this->messageManager->addError(__('An error occurred while deleting this set.')); + $this->messageManager->addError(__('We can\'t delete this set right now.')); $resultRedirect->setUrl($this->_redirect->getRedirectUrl($this->getUrl('*'))); } return $resultRedirect; diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/ShowUpdateResult.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/ShowUpdateResult.php index 0f2a86a8b1dc7d8292dd80a60c3b3792549746d4..fafde250a738b7a17bf116bd1a17a5ff5392f852 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/ShowUpdateResult.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/ShowUpdateResult.php @@ -6,26 +6,44 @@ */ namespace Magento\Catalog\Controller\Adminhtml\Product; +use Magento\Catalog\Helper\Product\Composite; +use Magento\Backend\Model\Session; +use Magento\Backend\App\Action\Context; + class ShowUpdateResult extends \Magento\Catalog\Controller\Adminhtml\Product { + /** @var Composite */ + protected $productCompositeHelper; + + /** + * @param Context $context + * @param Builder $productBuilder + * @param Composite $productCompositeHelper + */ + public function __construct( + Context $context, + Builder $productBuilder, + Composite $productCompositeHelper + ) { + $this->productCompositeHelper = $productCompositeHelper; + parent::__construct($context, $productBuilder); + } + /** * Show item update result from updateAction * in Wishlist and Cart controllers. * - * @return bool + * @return \Magento\Framework\View\Result\Layout */ public function execute() { - $session = $this->_objectManager->get('Magento\Backend\Model\Session'); - if ($session->hasCompositeProductResult() - && $session->getCompositeProductResult() instanceof \Magento\Framework\Object + $layout = false; + if ($this->_session->hasCompositeProductResult() + && $this->_session->getCompositeProductResult() instanceof \Magento\Framework\Object ) { - $this->_objectManager->get('Magento\Catalog\Helper\Product\Composite') - ->renderUpdateResult($session->getCompositeProductResult()); - $session->unsCompositeProductResult(); - } else { - $session->unsCompositeProductResult(); - return false; + $layout = $this->productCompositeHelper->renderUpdateResult($this->_session->getCompositeProductResult()); } + $this->_session->unsCompositeProductResult(); + return $layout; } } diff --git a/app/code/Magento/Catalog/Helper/Data.php b/app/code/Magento/Catalog/Helper/Data.php index 1bec07f5db89ee2f4a359ae8da1fa41195ce9acc..67a8a541bb01d521c904a9afc778ff6f0cd0958f 100644 --- a/app/code/Magento/Catalog/Helper/Data.php +++ b/app/code/Magento/Catalog/Helper/Data.php @@ -166,6 +166,21 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper */ protected $categoryRepository; + /** + * @var \Magento\Customer\Api\GroupRepositoryInterface + */ + protected $customerGroupRepository; + + /** + * @var \Magento\Customer\Api\Data\AddressInterfaceFactory + */ + protected $addressFactory; + + /** + * @var \Magento\Customer\Api\Data\RegionInterfaceFactory + */ + protected $regionFactory; + /** * @param \Magento\Framework\App\Helper\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager @@ -185,6 +200,9 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper * @param PriceCurrencyInterface $priceCurrency * @param ProductRepositoryInterface $productRepository * @param CategoryRepositoryInterface $categoryRepository + * @param \Magento\Customer\Api\GroupRepositoryInterface $customerGroupRepository + * @param \Magento\Customer\Api\Data\AddressInterfaceFactory $addressFactory + * @param \Magento\Customer\Api\Data\RegionInterfaceFactory $regionFactory * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -205,7 +223,10 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper CustomerSession $customerSession, PriceCurrencyInterface $priceCurrency, ProductRepositoryInterface $productRepository, - CategoryRepositoryInterface $categoryRepository + CategoryRepositoryInterface $categoryRepository, + \Magento\Customer\Api\GroupRepositoryInterface $customerGroupRepository, + \Magento\Customer\Api\Data\AddressInterfaceFactory $addressFactory, + \Magento\Customer\Api\Data\RegionInterfaceFactory $regionFactory ) { $this->_storeManager = $storeManager; $this->_catalogSession = $catalogSession; @@ -224,6 +245,9 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper $this->priceCurrency = $priceCurrency; $this->productRepository = $productRepository; $this->categoryRepository = $categoryRepository; + $this->customerGroupRepository = $customerGroupRepository; + $this->addressFactory = $addressFactory; + $this->regionFactory = $regionFactory; parent::__construct($context); } @@ -451,6 +475,26 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper ); } + /** + * @param array $taxAddress + * @return \Magento\Customer\Api\Data\AddressInterface|null + */ + private function convertDefaultTaxAddress(array $taxAddress = null) + { + if (empty($taxAddress)) { + return null; + } + /** @var \Magento\Customer\Api\Data\AddressInterface $addressDataObject */ + $addressDataObject = $this->addressFactory->create() + ->setCountryId($taxAddress['country_id']) + ->setPostcode($taxAddress['postcode']); + + if (isset($taxAddress['region_id'])) { + $addressDataObject->setRegion($this->regionFactory->create()->setRegionId($taxAddress['region_id'])); + } + return $addressDataObject; + } + /** * Get product price with all tax settings processing * @@ -466,6 +510,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper * @return float * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function getTaxPrice( $product, @@ -489,12 +534,18 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper } $shippingAddressDataObject = null; - if ($shippingAddress instanceof \Magento\Customer\Model\Address\AbstractAddress) { + if ($shippingAddress === null) { + $shippingAddressDataObject = + $this->convertDefaultTaxAddress($this->_customerSession->getDefaultTaxShippingAddress()); + } elseif ($shippingAddress instanceof \Magento\Customer\Model\Address\AbstractAddress) { $shippingAddressDataObject = $shippingAddress->getDataModel(); } $billingAddressDataObject = null; - if ($billingAddress instanceof \Magento\Customer\Model\Address\AbstractAddress) { + if ($billingAddress === null) { + $billingAddressDataObject = + $this->convertDefaultTaxAddress($this->_customerSession->getDefaultTaxBillingAddress()); + } elseif ($billingAddress instanceof \Magento\Customer\Model\Address\AbstractAddress) { $billingAddressDataObject = $billingAddress->getDataModel(); } @@ -502,6 +553,11 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper $taxClassKey->setType(TaxClassKeyInterface::TYPE_ID) ->setValue($product->getTaxClassId()); + if ($ctc === null && $this->_customerSession->getCustomerGroupId() != null) { + $ctc = $this->customerGroupRepository->getById($this->_customerSession->getCustomerGroupId()) + ->getTaxClassId(); + } + $customerTaxClassKey = $this->_taxClassKeyFactory->create(); $customerTaxClassKey->setType(TaxClassKeyInterface::TYPE_ID) ->setValue($ctc); diff --git a/app/code/Magento/Catalog/Model/AbstractModel.php b/app/code/Magento/Catalog/Model/AbstractModel.php index ba680dc35d5e148f9ed83c6a284df7b2d22e90ce..6ba6241645f3ec82c80989c0d5d969ed7ffbf0ef 100644 --- a/app/code/Magento/Catalog/Model/AbstractModel.php +++ b/app/code/Magento/Catalog/Model/AbstractModel.php @@ -66,7 +66,7 @@ abstract class AbstractModel extends \Magento\Framework\Model\AbstractExtensible * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -76,7 +76,7 @@ abstract class AbstractModel extends \Magento\Framework\Model\AbstractExtensible AttributeValueFactory $customAttributeFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_storeManager = $storeManager; diff --git a/app/code/Magento/Catalog/Model/Attribute/Backend/Startdate.php b/app/code/Magento/Catalog/Model/Attribute/Backend/Startdate.php index b9503e70730c855c2f21c80fafe871ce3f3711ef..459467d268ef7bb0c37f5d9bd7bf52911865cd08 100644 --- a/app/code/Magento/Catalog/Model/Attribute/Backend/Startdate.php +++ b/app/code/Magento/Catalog/Model/Attribute/Backend/Startdate.php @@ -96,7 +96,7 @@ class Startdate extends \Magento\Eav\Model\Entity\Attribute\Backend\Datetime $maxValue = $date->timestamp($maxDate); if ($value > $maxValue) { - $message = __('The From Date value should be less than or equal to the To Date value.'); + $message = __('Make sure the To Date is later than or the same as the From Date.'); $eavExc = new \Magento\Eav\Model\Entity\Attribute\Exception($message); $eavExc->setAttributeCode($attr->getName()); throw $eavExc; diff --git a/app/code/Magento/Catalog/Model/Category.php b/app/code/Magento/Catalog/Model/Category.php index 16bdd17ffd3060776c5b3bcc8de0b17a5879248b..0446ef7afab343c262898bd694513a31347b5dd8 100644 --- a/app/code/Magento/Catalog/Model/Category.php +++ b/app/code/Magento/Catalog/Model/Category.php @@ -234,7 +234,7 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry * @param CategoryRepositoryInterface $categoryRepository * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -258,7 +258,7 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements \Magento\Indexer\Model\IndexerRegistry $indexerRegistry, CategoryRepositoryInterface $categoryRepository, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->metadataService = $metadataService; @@ -451,7 +451,7 @@ class Category extends \Magento\Catalog\Model\AbstractModel implements /** * Get category products collection * - * @return \Magento\Framework\Data\Collection\Db + * @return \Magento\Framework\Data\Collection\AbstractDb */ public function getProductCollection() { diff --git a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php index c8e9119f8c78e9b860c4e4643e0a64ca7d561bac..0c2c324bd8e2c931b57babe59147837b4feb193b 100644 --- a/app/code/Magento/Catalog/Model/CategoryLinkManagement.php +++ b/app/code/Magento/Catalog/Model/CategoryLinkManagement.php @@ -38,7 +38,7 @@ class CategoryLinkManagement implements \Magento\Catalog\Api\CategoryLinkManagem $category = $this->categoryRepository->get($categoryId); $productsPosition = $category->getProductsPosition(); - /** @var \Magento\Framework\Data\Collection\Db $products */ + /** @var \Magento\Framework\Data\Collection\AbstractDb $products */ $products = $category->getProductCollection(); /** @var \Magento\Catalog\Api\Data\CategoryProductLinkInterface[] $links */ diff --git a/app/code/Magento/Catalog/Model/Config/Backend/Category.php b/app/code/Magento/Catalog/Model/Config/Backend/Category.php index 9d5c390d33c89411396f4e7c601dd77f2de866c7..8481a9eda0488e523564a4a104532bc98a37ecb8 100644 --- a/app/code/Magento/Catalog/Model/Config/Backend/Category.php +++ b/app/code/Magento/Catalog/Model/Config/Backend/Category.php @@ -27,7 +27,7 @@ class Category extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Catalog\Model\Category $catalogCategory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -36,7 +36,7 @@ class Category extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Catalog\Model\Category $catalogCategory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_catalogCategory = $catalogCategory; diff --git a/app/code/Magento/Catalog/Model/Config/CatalogClone/Media/Image.php b/app/code/Magento/Catalog/Model/Config/CatalogClone/Media/Image.php index 45559cde81356d796c91fb542361d751e3ca92b6..431539fd0c48810e3f8a5a468deb609bbda19b38 100644 --- a/app/code/Magento/Catalog/Model/Config/CatalogClone/Media/Image.php +++ b/app/code/Magento/Catalog/Model/Config/CatalogClone/Media/Image.php @@ -33,7 +33,7 @@ class Image extends \Magento\Framework\App\Config\Value * @param \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $attributeCollectionFactory * @param \Magento\Eav\Model\Config $eavConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -43,7 +43,7 @@ class Image extends \Magento\Framework\App\Config\Value \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $attributeCollectionFactory, \Magento\Eav\Model\Config $eavConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_attributeCollectionFactory = $attributeCollectionFactory; diff --git a/app/code/Magento/Catalog/Model/Design.php b/app/code/Magento/Catalog/Model/Design.php index 5bbbb3b52d295380b92e2fe30b92644e07575d6c..875295185e26933a640e213cff7ddf00d1e3734e 100644 --- a/app/code/Magento/Catalog/Model/Design.php +++ b/app/code/Magento/Catalog/Model/Design.php @@ -34,7 +34,7 @@ class Design extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\View\DesignInterface $design * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -43,7 +43,7 @@ class Design extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\View\DesignInterface $design, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_localeDate = $localeDate; diff --git a/app/code/Magento/Catalog/Model/Entity/Attribute.php b/app/code/Magento/Catalog/Model/Entity/Attribute.php index ca1e3038e03909c756d7b793669393f78457656e..fa135f47067c0554e3180a963fc4acbe2255fae2 100755 --- a/app/code/Magento/Catalog/Model/Entity/Attribute.php +++ b/app/code/Magento/Catalog/Model/Entity/Attribute.php @@ -87,7 +87,7 @@ class Attribute extends \Magento\Eav\Model\Entity\Attribute * @param \Magento\Framework\Locale\ResolverInterface $localeResolver * @param LockValidatorInterface $lockValidator * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -109,7 +109,7 @@ class Attribute extends \Magento\Eav\Model\Entity\Attribute \Magento\Framework\Locale\ResolverInterface $localeResolver, LockValidatorInterface $lockValidator, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->attrLockValidator = $lockValidator; diff --git a/app/code/Magento/Catalog/Model/Indexer/Category/Flat/System/Config/Mode.php b/app/code/Magento/Catalog/Model/Indexer/Category/Flat/System/Config/Mode.php index cd25a05941afc927a9ab7bb5bb54e1c96cef0394..eac2cb0d79b333c4149fbc6cfc5b7d372c64e13a 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Category/Flat/System/Config/Mode.php +++ b/app/code/Magento/Catalog/Model/Indexer/Category/Flat/System/Config/Mode.php @@ -23,7 +23,7 @@ class Mode extends \Magento\Framework\App\Config\Value * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry * @param \Magento\Indexer\Model\Indexer\State $indexerState * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -33,7 +33,7 @@ class Mode extends \Magento\Framework\App\Config\Value \Magento\Indexer\Model\IndexerRegistry $indexerRegistry, \Magento\Indexer\Model\Indexer\State $indexerState, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $config, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/System/Config/Mode.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/System/Config/Mode.php index 6893e097bf342e1ce74111253c6eb8d64b0f47cb..fddf5015b841c3ca9d7070d8d7ed393c74d2dd97 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/System/Config/Mode.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/System/Config/Mode.php @@ -27,7 +27,7 @@ class Mode extends \Magento\Framework\App\Config\Value * @param \Magento\Catalog\Model\Indexer\Product\Flat\Processor $productFlatIndexerProcessor * @param \Magento\Indexer\Model\Indexer\State $indexerState * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -37,7 +37,7 @@ class Mode extends \Magento\Framework\App\Config\Value \Magento\Catalog\Model\Indexer\Product\Flat\Processor $productFlatIndexerProcessor, \Magento\Indexer\Model\Indexer\State $indexerState, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_productFlatIndexerProcessor = $productFlatIndexerProcessor; diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScope.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScope.php index 508155fef52b3a33115837c0a5fed65f5640fdce..596495c247e91dfb3e729835e2e6e268f702ddad 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScope.php +++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price/System/Config/PriceScope.php @@ -19,7 +19,7 @@ class PriceScope extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -28,7 +28,7 @@ class PriceScope extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Indexer\Model\IndexerRegistry $indexerRegistry, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $config, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index d31a245cf71b04386cd7b251f99dff04c064920d..32ad8cfb390d3bc95efb7b381b03fafaee0c2613 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -244,6 +244,13 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements */ protected $categoryRepository; + /** + * Instance of category collection. + * + * @var \Magento\Catalog\Model\Resource\Category\Collection + */ + protected $categoryCollection; + /** * @var Product\Image\CacheFactory */ @@ -284,6 +291,11 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements */ protected $dataObjectHelper; + /** + * @var int + */ + protected $_productIdCached; + /** * List of attributes in ProductInterface * @var array @@ -586,10 +598,8 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements */ public function getStatus() { - if ($this->_getData(self::STATUS) === null) { - $this->setData(self::STATUS, \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED); - } - return $this->_getData(self::STATUS); + $status = $this->_getData(self::STATUS); + return $status !== null ? $status : \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED; } /** @@ -698,7 +708,24 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements */ public function getCategoryCollection() { - return $this->_getResource()->getCategoryCollection($this); + if ($this->categoryCollection === null || $this->getId() != $this->_productIdCached) { + $categoryCollection = $this->_getResource()->getCategoryCollection($this); + $this->setCategoryCollection($categoryCollection); + $this->_productIdCached = $this->getId(); + } + return $this->categoryCollection; + } + + /** + * Set product categories. + * + * @param \Magento\Framework\Data\Collection $categoryCollection + * @return $this + */ + protected function setCategoryCollection(\Magento\Framework\Data\Collection $categoryCollection) + { + $this->categoryCollection = $categoryCollection; + return $this; } /** @@ -974,6 +1001,9 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements */ protected function _afterLoad() { + if (!$this->hasData(self::STATUS)) { + $this->setData(self::STATUS, \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED); + } parent::_afterLoad(); /** * Load product options @@ -1380,7 +1410,7 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements foreach ($collection as $item) { /** @var \Magento\Catalog\Api\Data\ProductLinkInterface $productLink */ $productLink = $this->productLinkFactory->create(); - $productLink->setProductSku($this->getSku()) + $productLink->setSku($this->getSku()) ->setLinkType($linkTypeName) ->setLinkedProductSku($item['sku']) ->setLinkedProductType($item['type']) @@ -2277,8 +2307,8 @@ class Product extends \Magento\Catalog\Model\AbstractModel implements $identities[] = self::CACHE_PRODUCT_CATEGORY_TAG . '_' . $categoryId; } } - if ($this->getOrigData('status') > $this->getData('status')) { - foreach ($this->getData('category_ids') as $categoryId) { + if ($this->getOrigData('status') != $this->getData('status')) { + foreach ($this->getCategoryIds() as $categoryId) { $identities[] = self::CACHE_PRODUCT_CATEGORY_TAG . '_' . $categoryId; } } diff --git a/app/code/Magento/Catalog/Model/Product/Action.php b/app/code/Magento/Catalog/Model/Product/Action.php index 5f86ef87a78997cb0d928c24782aae85380f5799..3bc9a563dca08ee68941ee0323b83573a102af13 100644 --- a/app/code/Magento/Catalog/Model/Product/Action.php +++ b/app/code/Magento/Catalog/Model/Product/Action.php @@ -43,7 +43,7 @@ class Action extends \Magento\Framework\Model\AbstractModel * @param \Magento\Eav\Model\Config $eavConfig * @param \Magento\Catalog\Model\Indexer\Product\Eav\Processor $productEavIndexerProcessor * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -54,7 +54,7 @@ class Action extends \Magento\Framework\Model\AbstractModel \Magento\Eav\Model\Config $eavConfig, \Magento\Catalog\Model\Indexer\Product\Eav\Processor $productEavIndexerProcessor, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_productWebsiteFactory = $productWebsiteFactory; diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Group.php b/app/code/Magento/Catalog/Model/Product/Attribute/Group.php index 7bbabfc9b3fc8c2b62cfbb7e95a76a0c8f54cc7c..9d6c20684620bda7d7d00dd42eab63c6e63e4aa3 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Group.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Group.php @@ -24,7 +24,7 @@ class Group extends \Magento\Eav\Model\Entity\Attribute\Group * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $attributeCollectionFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -34,7 +34,7 @@ class Group extends \Magento\Eav\Model\Entity\Attribute\Group AttributeValueFactory $customAttributeFactory, \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $attributeCollectionFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_attributeCollectionFactory = $attributeCollectionFactory; diff --git a/app/code/Magento/Catalog/Model/Product/Compare/Item.php b/app/code/Magento/Catalog/Model/Product/Compare/Item.php index b488f1d02e0bdba0c9530c720e48737e1d1c6775..428201a988dd747efcb40452d22e7682c6ec6da4 100644 --- a/app/code/Magento/Catalog/Model/Product/Compare/Item.php +++ b/app/code/Magento/Catalog/Model/Product/Compare/Item.php @@ -77,7 +77,7 @@ class Item extends \Magento\Framework\Model\AbstractModel implements \Magento\Fr * @param \Magento\Customer\Model\Session $customerSession * @param \Magento\Catalog\Helper\Product\Compare $catalogProductCompare * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -88,7 +88,7 @@ class Item extends \Magento\Framework\Model\AbstractModel implements \Magento\Fr \Magento\Customer\Model\Session $customerSession, \Magento\Catalog\Helper\Product\Compare $catalogProductCompare, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_storeManager = $storeManager; diff --git a/app/code/Magento/Catalog/Model/Product/Image.php b/app/code/Magento/Catalog/Model/Product/Image.php index 3a72898c718b769adc15a0d5410f106cb026e467..82d866ada8705ac5aa4eb55b45bbb6b76f140a1c 100644 --- a/app/code/Magento/Catalog/Model/Product/Image.php +++ b/app/code/Magento/Catalog/Model/Product/Image.php @@ -179,7 +179,7 @@ class Image extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\View\FileSystem $viewFileSystem * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) * @SuppressWarnings(PHPMD.UnusedLocalVariable) @@ -196,7 +196,7 @@ class Image extends \Magento\Framework\Model\AbstractModel \Magento\Framework\View\FileSystem $viewFileSystem, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_storeManager = $storeManager; diff --git a/app/code/Magento/Catalog/Model/Product/Link.php b/app/code/Magento/Catalog/Model/Product/Link.php index 26e194bf57f3bf685563d9aa0d1756f9e195136b..7ca13f75821ec5872e76e0292ad92105f18f3cb8 100644 --- a/app/code/Magento/Catalog/Model/Product/Link.php +++ b/app/code/Magento/Catalog/Model/Product/Link.php @@ -55,7 +55,7 @@ class Link extends \Magento\Framework\Model\AbstractModel * @param \Magento\Catalog\Model\Resource\Product\Link\CollectionFactory $linkCollectionFactory * @param \Magento\Catalog\Model\Resource\Product\Link\Product\CollectionFactory $productCollectionFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -64,7 +64,7 @@ class Link extends \Magento\Framework\Model\AbstractModel \Magento\Catalog\Model\Resource\Product\Link\CollectionFactory $linkCollectionFactory, \Magento\Catalog\Model\Resource\Product\Link\Product\CollectionFactory $productCollectionFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_linkCollectionFactory = $linkCollectionFactory; diff --git a/app/code/Magento/Catalog/Model/Product/Option.php b/app/code/Magento/Catalog/Model/Product/Option.php index 5b9211099d6549f308ca1e3edd1f49f68a7380fb..8c5d3d25675d9f0b9b7f05df691d2b61334ade19 100644 --- a/app/code/Magento/Catalog/Model/Product/Option.php +++ b/app/code/Magento/Catalog/Model/Product/Option.php @@ -121,7 +121,7 @@ class Option extends AbstractModel implements \Magento\Catalog\Api\Data\ProductC * @param \Magento\Framework\Stdlib\String $string * @param Option\Validator\Pool $validatorPool * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -133,7 +133,7 @@ class Option extends AbstractModel implements \Magento\Catalog\Api\Data\ProductC \Magento\Framework\Stdlib\String $string, Option\Validator\Pool $validatorPool, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_productOptionValue = $productOptionValue; diff --git a/app/code/Magento/Catalog/Model/Product/Option/Value.php b/app/code/Magento/Catalog/Model/Product/Option/Value.php index 227f070a683e75e67bf464442b8c5c5c35b7381e..e15d16c77a8a6c6ce47f02b5a38abaf857167bb0 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Value.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Value.php @@ -67,7 +67,7 @@ class Value extends AbstractModel implements \Magento\Catalog\Api\Data\ProductCu * @param \Magento\Framework\Registry $registry * @param \Magento\Catalog\Model\Resource\Product\Option\Value\CollectionFactory $valueCollectionFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -75,7 +75,7 @@ class Value extends AbstractModel implements \Magento\Catalog\Api\Data\ProductCu \Magento\Framework\Registry $registry, \Magento\Catalog\Model\Resource\Product\Option\Value\CollectionFactory $valueCollectionFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_valueCollectionFactory = $valueCollectionFactory; diff --git a/app/code/Magento/Catalog/Model/Product/Visibility.php b/app/code/Magento/Catalog/Model/Product/Visibility.php index 1f57690bf22f1220f8f90da426a1306166004f6e..5f98e372655bf518f08c49f04c580f2da9ed7571 100644 --- a/app/code/Magento/Catalog/Model/Product/Visibility.php +++ b/app/code/Magento/Catalog/Model/Product/Visibility.php @@ -49,7 +49,6 @@ class Visibility extends \Magento\Framework\Object ) { $this->_eavEntityAttribute = $eavEntityAttribute; parent::__construct($data); - $this->setIdFieldName('visibility_id'); } /** diff --git a/app/code/Magento/Catalog/Model/ProductLink/Link.php b/app/code/Magento/Catalog/Model/ProductLink/Link.php index 84fdd67df676b354d497de50667e43d0b949ea26..30f641667c35769abd2931e6c58b00b3fd7a576e 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Link.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Link.php @@ -15,7 +15,7 @@ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements /**#@+ * Constants */ - const KEY_PRODUCT_SKU = 'product_sku'; + const KEY_SKU = 'sku'; const KEY_LINK_TYPE = 'link_type'; const KEY_LINKED_PRODUCT_SKU = 'linked_product_sku'; const KEY_LINKED_PRODUCT_TYPE = 'linked_product_type'; @@ -61,14 +61,14 @@ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements } /** - * Get product SKU + * Get SKU * * @identifier * @return string */ - public function getProductSku() + public function getSku() { - return $this->_get(self::KEY_PRODUCT_SKU); + return $this->_get(self::KEY_SKU); } /** @@ -114,14 +114,14 @@ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements } /** - * Set product SKU + * Set SKU * - * @param string $productSku + * @param string $sku * @return $this */ - public function setProductSku($productSku) + public function setSku($sku) { - return $this->setData(self::KEY_PRODUCT_SKU, $productSku); + return $this->setData(self::KEY_SKU, $sku); } /** diff --git a/app/code/Magento/Catalog/Model/ProductLink/Management.php b/app/code/Magento/Catalog/Model/ProductLink/Management.php index e702a6cde0e41f1a8e3316d5a30be821c620fa0b..4264b7a9f1fd2a5564696b6dce070ef4ad87f344 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Management.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Management.php @@ -9,6 +9,7 @@ namespace Magento\Catalog\Model\ProductLink; use Magento\Catalog\Api\Data; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Exception\InputException; class Management implements \Magento\Catalog\Api\ProductLinkManagementInterface { @@ -62,14 +63,23 @@ class Management implements \Magento\Catalog\Api\ProductLinkManagementInterface /** * {@inheritdoc} */ - public function setProductLinks($sku, $type, array $items) + public function setProductLinks($sku, array $items) { $linkTypes = $this->linkTypeProvider->getLinkTypes(); - if (!isset($linkTypes[$type])) { - throw new NoSuchEntityException( - __('Provided link type "%1" does not exist', $type) - ); + // Check if product link type is set and correct + if (!empty($items)) { + foreach ($items as $newLink) { + $type = $newLink->getLinkType(); + if ($type == null) { + throw InputException::requiredField("linkType"); + } + if (!isset($linkTypes[$type])) { + throw new NoSuchEntityException( + __('Provided link type "%1" does not exist', $type) + ); + } + } } $product = $this->productRepository->get($sku); diff --git a/app/code/Magento/Catalog/Model/ProductLink/Repository.php b/app/code/Magento/Catalog/Model/ProductLink/Repository.php index 282d14bb2c243d74792c7ed4e647af56812bcfcf..e455885630a72202efd50b2accda8d7d2f67c2a5 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Repository.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Repository.php @@ -67,7 +67,7 @@ class Repository implements \Magento\Catalog\Api\ProductLinkRepositoryInterface public function save(\Magento\Catalog\Api\Data\ProductLinkInterface $entity) { $linkedProduct = $this->productRepository->get($entity->getLinkedProductSku()); - $product = $this->productRepository->get($entity->getProductSku()); + $product = $this->productRepository->get($entity->getSku()); $links = $this->entityCollectionProvider->getCollection($product, $entity->getLinkType()); $extensions = $this->dataObjectProcessor->buildOutputDataArray( $entity->getExtensionAttributes(), @@ -96,7 +96,7 @@ class Repository implements \Magento\Catalog\Api\ProductLinkRepositoryInterface public function delete(\Magento\Catalog\Api\Data\ProductLinkInterface $entity) { $linkedProduct = $this->productRepository->get($entity->getLinkedProductSku()); - $product = $this->productRepository->get($entity->getProductSku()); + $product = $this->productRepository->get($entity->getSku()); $links = $this->entityCollectionProvider->getCollection($product, $entity->getLinkType()); if (!isset($links[$linkedProduct->getId()])) { @@ -104,7 +104,7 @@ class Repository implements \Magento\Catalog\Api\ProductLinkRepositoryInterface __( 'Product with SKU %1 is not linked to product with SKU %2', $entity->getLinkedProductSku(), - $entity->getProductSku() + $entity->getSku() ) ); } diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index ce62494b11b7385f0519b22bd7c46e553f3ee120..79f26720fff4dd1adf6a8d4b5304e36804920174 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -11,6 +11,7 @@ use Magento\Catalog\Model\Product\Gallery\MimeTypeExtensionMap; use Magento\Catalog\Model\Resource\Product\Collection; use Magento\Framework\Api\Data\ImageContentInterface; use Magento\Framework\Api\Data\ImageContentInterfaceFactory; +use Magento\Framework\Api\ExtensionAttributesFactory; use Magento\Framework\Api\ImageContentValidatorInterface; use Magento\Framework\Api\ImageProcessorInterface; use Magento\Framework\Api\SearchCriteriaInterface; @@ -135,6 +136,11 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa */ protected $imageProcessor; + /** + * @var ExtensionAttributesFactory + */ + protected $extensionAttributesFactory; + /** * @param ProductFactory $productFactory * @param \Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper $initializationHelper @@ -156,6 +162,7 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa * @param ImageContentInterfaceFactory $contentFactory * @param MimeTypeExtensionMap $mimeTypeExtensionMap * @param ImageProcessorInterface $imageProcessor + * @param ExtensionAttributesFactory $extensionAttributesFactory * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -178,7 +185,8 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa ImageContentInterfaceFactory $contentFactory, MimeTypeExtensionMap $mimeTypeExtensionMap, \Magento\Eav\Model\Config $eavConfig, - ImageProcessorInterface $imageProcessor + ImageProcessorInterface $imageProcessor, + ExtensionAttributesFactory $extensionAttributesFactory ) { $this->productFactory = $productFactory; $this->collectionFactory = $collectionFactory; @@ -200,6 +208,7 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa $this->mimeTypeExtensionMap = $mimeTypeExtensionMap; $this->eavConfig = $eavConfig; $this->imageProcessor = $imageProcessor; + $this->extensionAttributesFactory = $extensionAttributesFactory; } /** @@ -672,6 +681,8 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa } $collection->setCurPage($searchCriteria->getCurrentPage()); $collection->setPageSize($searchCriteria->getPageSize()); + $productDataClass = 'Magento\Catalog\Model\Product'; + $this->extensionAttributesFactory->process($collection, $productDataClass); $collection->load(); $searchResult = $this->searchResultsFactory->create(); diff --git a/app/code/Magento/Catalog/Model/Resource/Eav/Attribute.php b/app/code/Magento/Catalog/Model/Resource/Eav/Attribute.php index 63b02e7e2308251a9a66f489806f2f5ef0c783e7..1d0d2c3fab8662855ef8713ba54511b9c973f66e 100644 --- a/app/code/Magento/Catalog/Model/Resource/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Model/Resource/Eav/Attribute.php @@ -107,7 +107,7 @@ class Attribute extends \Magento\Eav\Model\Entity\Attribute implements * @param \Magento\Catalog\Helper\Product\Flat\Indexer $productFlatIndexerHelper * @param LockValidatorInterface $lockValidator * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -132,7 +132,7 @@ class Attribute extends \Magento\Eav\Model\Entity\Attribute implements \Magento\Catalog\Helper\Product\Flat\Indexer $productFlatIndexerHelper, LockValidatorInterface $lockValidator, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_indexerEavProcessor = $indexerEavProcessor; diff --git a/app/code/Magento/Catalog/Model/Resource/Product/Action.php b/app/code/Magento/Catalog/Model/Resource/Product/Action.php index 7ff4afb57d9cdf2fb25f74e6f06a42f6f6006833..2a9d0de92a2e551444f167299e0e834f5b7870de 100644 --- a/app/code/Magento/Catalog/Model/Resource/Product/Action.php +++ b/app/code/Magento/Catalog/Model/Resource/Product/Action.php @@ -40,7 +40,7 @@ class Action extends \Magento\Catalog\Model\Resource\AbstractResource public function updateAttributes($entityIds, $attrData, $storeId) { $object = new \Magento\Framework\Object(); - $object->setIdFieldName('entity_id')->setStoreId($storeId); + $object->setStoreId($storeId); $this->_getWriteAdapter()->beginTransaction(); try { @@ -54,6 +54,7 @@ class Action extends \Magento\Catalog\Model\Resource\AbstractResource foreach ($entityIds as $entityId) { $i++; $object->setId($entityId); + $object->setEntityId($entityId); // collect data for save $this->_saveAttributeValue($object, $attribute, $value); // save collected data every 1000 rows diff --git a/app/code/Magento/Catalog/Model/Resource/Url.php b/app/code/Magento/Catalog/Model/Resource/Url.php index 624964013a896f54e253bcd4c1607ed875d4dfc7..b9a8a3d076b6ff8650a2873107f72fce9cbe3f9c 100644 --- a/app/code/Magento/Catalog/Model/Resource/Url.php +++ b/app/code/Magento/Catalog/Model/Resource/Url.php @@ -432,7 +432,8 @@ class Url extends \Magento\Framework\Model\Resource\Db\AbstractDb } $category = new \Magento\Framework\Object($row); - $category->setIdFieldName('entity_id'); + $category->setId($row['entity_id']); + $category->setEntityId($row['entity_id']); $category->setStoreId($storeId); $this->_prepareCategoryParentId($category); @@ -535,7 +536,8 @@ class Url extends \Magento\Framework\Model\Resource\Db\AbstractDb $rowSet = $adapter->fetchAll($select, $bind); foreach ($rowSet as $row) { $product = new \Magento\Framework\Object($row); - $product->setIdFieldName('entity_id'); + $product->setId($row['entity_id']); + $product->setEntityId($row['entity_id']); $product->setCategoryIds([]); $product->setStoreId($storeId); $products[$product->getId()] = $product; diff --git a/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php b/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php index c9054ef4160d0d8d2f7f0f91af0982ccf6e2fa19..a38152585b3f032c13912188cb3ce1628c99846b 100644 --- a/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php +++ b/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php @@ -40,7 +40,7 @@ class Suffix extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param \Magento\UrlRewrite\Helper\UrlRewrite $urlRewriteHelper * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\Resource $appResource @@ -57,7 +57,7 @@ class Suffix extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Resource $appResource, \Magento\UrlRewrite\Model\UrlFinderInterface $urlFinder, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $config, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/NewProductTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/NewProductTest.php index 24e31b209aff56fff98b257225bc6c8f7de42810..3f671797e793ff8a8984912d155d27ba3101e7e7 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Product/NewProductTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/NewProductTest.php @@ -27,4 +27,9 @@ class NewProductTest extends \PHPUnit_Framework_TestCase { $this->assertEquals([\Magento\Catalog\Model\Product::CACHE_TAG], $this->block->getIdentities()); } + + public function testScope() + { + $this->assertFalse($this->block->isScopePrivate()); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/Widget/NewWidgetTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/Widget/NewWidgetTest.php index 9e4b73cb321c1566080a9146ea2d9786b2e664f0..156971df2a4cf0b5682e517d5de849e430e394b4 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Product/Widget/NewWidgetTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/Widget/NewWidgetTest.php @@ -5,6 +5,12 @@ */ namespace Magento\Catalog\Test\Unit\Block\Product\Widget; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Catalog\Block\Product\Widget\NewWidget; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class NewWidgetTest extends \PHPUnit_Framework_TestCase { /** @@ -22,26 +28,69 @@ class NewWidgetTest extends \PHPUnit_Framework_TestCase */ protected $requestMock; + /** @var \Magento\Backend\Block\Context|\PHPUnit_Framework_MockObject_MockObject */ + protected $context; + + /** @var ObjectManagerHelper */ + protected $objectManager; + + /** @var \Magento\Framework\Event\Manager|\PHPUnit_Framework_MockObject_MockObject */ + protected $eventManager; + + /** @var \Magento\Framework\App\Config|\PHPUnit_Framework_MockObject_MockObject */ + protected $scopeConfig; + + /** @var \Magento\Framework\App\Cache\State|\PHPUnit_Framework_MockObject_MockObject */ + protected $cacheState; + + /** @var \Magento\Catalog\Model\Config|\PHPUnit_Framework_MockObject_MockObject */ + protected $catalogConfig; + + /** @var \Magento\Framework\Stdlib\DateTime\Timezone|\PHPUnit_Framework_MockObject_MockObject */ + protected $localDate; + + /** @var \Magento\Catalog\Model\Resource\Product\Collection|\PHPUnit_Framework_MockObject_MockObject */ + protected $productCollection; + protected function setUp() { - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $contextMock = $this->getMock('Magento\Catalog\Block\Product\Context', [], [], '', false, false); + $this->objectManager = new ObjectManagerHelper($this); + $this->eventManager = $this->getMock('Magento\Framework\Event\Manager', ['dispatch'], [], '', false, false); + $this->scopeConfig = $this->getMock('Magento\Framework\App\Config', ['getValue'], [], '', false, false); + $this->cacheState = $this->getMock('Magento\Framework\App\Cache\State', ['isEnabled'], [], '', false, false); + $this->localDate = $this->getMock('Magento\Framework\Stdlib\DateTime\Timezone', [], [], '', false, false); + $this->catalogConfig = $this->getMockBuilder('Magento\Catalog\Model\Config') + ->setMethods(['getProductAttributes']) + ->disableOriginalConstructor() + ->getMock(); $this->layout = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); $this->requestMock = $this->getMockBuilder('Magento\Framework\App\RequestInterface') ->disableOriginalConstructor() ->getMock(); - $contextMock->expects($this->once()) + $this->context = $this->getMockBuilder('Magento\Catalog\Block\Product\Context') + ->setMethods( + [ + 'getEventManager', 'getScopeConfig', 'getLayout', + 'getRequest', 'getCacheState', 'getCatalogConfig', + 'getLocaleDate' + ] + ) + ->disableOriginalConstructor() + ->disableArgumentCloning() + ->getMock(); + + $this->context->expects($this->any()) ->method('getLayout') - ->will($this->returnValue($this->layout)); - $contextMock->expects($this->once()) + ->willReturn($this->layout); + $this->context->expects($this->any()) ->method('getRequest') ->willReturn($this->requestMock); - $this->block = $objectManager->getObject( + $this->block = $this->objectManager->getObject( 'Magento\Catalog\Block\Product\Widget\NewWidget', [ - 'context' => $contextMock + 'context' => $this->context ] ); } @@ -61,10 +110,10 @@ class NewWidgetTest extends \PHPUnit_Framework_TestCase </span> </div>'; $type = 'widget-new-list'; - $productMock = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false, false); + $productMock = $this->getMock('Magento\Catalog\Model\Product', ['getId'], [], '', false, false); $productMock->expects($this->once()) ->method('getId') - ->will($this->returnValue($id)); + ->willReturn($id); $arguments = [ 'price_id' => 'old-price-' . $id . '-' . $type, 'display_minimal_price' => true, @@ -77,12 +126,12 @@ class NewWidgetTest extends \PHPUnit_Framework_TestCase $this->layout->expects($this->once()) ->method('getBlock') ->with($this->equalTo('product.price.render.default')) - ->will($this->returnValue($priceBoxMock)); + ->willReturn($priceBoxMock); $priceBoxMock->expects($this->once()) ->method('render') ->with($this->equalTo('final_price'), $this->equalTo($productMock), $this->equalTo($arguments)) - ->will($this->returnValue($expectedHtml)); + ->willReturn($expectedHtml); $result = $this->block->getProductPriceHtml($productMock, $type); $this->assertEquals($expectedHtml, $result); @@ -111,4 +160,174 @@ class NewWidgetTest extends \PHPUnit_Framework_TestCase [10, 10] ]; } + + public function testGetProductsCount() + { + $this->assertEquals(10, $this->block->getProductsCount()); + $this->block->setProductsCount(2); + $this->assertEquals(2, $this->block->getProductsCount()); + } + + protected function generalGetProductCollection() + { + $this->eventManager->expects($this->once())->method('dispatch') + ->will($this->returnValue(true)); + $this->scopeConfig->expects($this->once())->method('getValue')->withAnyParameters() + ->willReturn(false); + $this->cacheState->expects($this->atLeastOnce())->method('isEnabled')->withAnyParameters() + ->willReturn(false); + $this->catalogConfig->expects($this->once())->method('getProductAttributes') + ->willReturn([]); + $this->localDate->expects($this->any())->method('date') + ->willReturn(new \DateTime('now', new \DateTimeZone('UTC'))); + + $this->context->expects($this->once())->method('getEventManager')->willReturn($this->eventManager); + $this->context->expects($this->once())->method('getScopeConfig')->willReturn($this->scopeConfig); + $this->context->expects($this->once())->method('getCacheState')->willReturn($this->cacheState); + $this->context->expects($this->once())->method('getCatalogConfig')->willReturn($this->catalogConfig); + $this->context->expects($this->once())->method('getLocaleDate')->willReturn($this->localDate); + + $this->productCollection = $this->getMockBuilder('Magento\Catalog\Model\Resource\Product\Collection') + ->setMethods( + [ + 'setVisibility', 'addMinimalPrice', 'addFinalPrice', + 'addTaxPercents', 'addAttributeToSelect', 'addUrlRewrite', + 'addStoreFilter', 'addAttributeToSort', 'setPageSize', + 'setCurPage', 'addAttributeToFilter' + ] + ) + ->disableOriginalConstructor() + ->getMock(); + $this->productCollection->expects($this->once())->method('setVisibility') + ->willReturnSelf(); + $this->productCollection->expects($this->once())->method('addMinimalPrice') + ->willReturnSelf(); + $this->productCollection->expects($this->once())->method('addFinalPrice') + ->willReturnSelf(); + $this->productCollection->expects($this->once())->method('addTaxPercents') + ->willReturnSelf(); + $this->productCollection->expects($this->once())->method('addAttributeToSelect') + ->willReturnSelf(); + $this->productCollection->expects($this->once())->method('addUrlRewrite') + ->willReturnSelf(); + $this->productCollection->expects($this->once())->method('addStoreFilter') + ->willReturnSelf(); + $this->productCollection->expects($this->once())->method('addAttributeToSort') + ->willReturnSelf(); + $this->productCollection->expects($this->atLeastOnce())->method('setCurPage') + ->willReturnSelf(); + $this->productCollection->expects($this->any())->method('addAttributeToFilter') + ->willReturnSelf(); + } + + /** + * @param string $displayType + * @param bool $pagerEnable + * @param int $productsCount + * @param int $productsPerPage + */ + protected function startTestGetProductCollection($displayType, $pagerEnable, $productsCount, $productsPerPage) + { + $productCollectionFactory = $this->getMock( + 'Magento\Catalog\Model\Resource\Product\CollectionFactory', + ['create'], + [], + '', + false, + false + ); + $productCollectionFactory->expects($this->atLeastOnce())->method('create') + ->willReturn($this->productCollection); + + $this->block = $this->objectManager->getObject( + 'Magento\Catalog\Block\Product\Widget\NewWidget', + [ + 'context' => $this->context, + 'productCollectionFactory' => $productCollectionFactory + ] + ); + + if (null === $productsPerPage) { + $this->block->unsetData('products_per_page'); + } else { + $this->block->setData('products_per_page', $productsPerPage); + } + + $this->block->setData('show_pager', $pagerEnable); + $this->block->setData('display_type', $displayType); + $this->block->setProductsCount($productsCount); + $this->block->toHtml(); + } + + /** + * Test protected `_getProductCollection` and `getPageSize` methods via public `toHtml` method, + * for display_type == DISPLAY_TYPE_NEW_PRODUCTS. + * + * @param bool $pagerEnable + * @param int $productsCount + * @param int $productsPerPage + * @param int $expectedPageSize + * @dataProvider getProductCollectionDataProvider + */ + public function testGetProductNewCollection($pagerEnable, $productsCount, $productsPerPage, $expectedPageSize) + { + $this->generalGetProductCollection(); + + $this->productCollection->expects($this->exactly(2))->method('setPageSize') + ->withConsecutive( + [$productsCount], + [$expectedPageSize] + ) + ->willReturnSelf(); + + $this->startTestGetProductCollection( + NewWidget::DISPLAY_TYPE_NEW_PRODUCTS, + $pagerEnable, + $productsCount, + $productsPerPage + ); + } + + /** + * Test protected `_getProductCollection` and `getPageSize` methods via public `toHtml` method, + * for display_type == DISPLAY_TYPE_ALL_PRODUCTS. + * + * @param bool $pagerEnable + * @param int $productsCount + * @param int $productsPerPage + * @param int $expectedPageSize + * @dataProvider getProductCollectionDataProvider + */ + public function testGetProductAllCollection($pagerEnable, $productsCount, $productsPerPage, $expectedPageSize) + { + $this->generalGetProductCollection(); + + $this->productCollection->expects($this->atLeastOnce())->method('setPageSize')->with($expectedPageSize) + ->willReturnSelf(); + + $this->startTestGetProductCollection( + NewWidget::DISPLAY_TYPE_ALL_PRODUCTS, + $pagerEnable, + $productsCount, + $productsPerPage + ); + } + + public function getProductCollectionDataProvider() + { + return [ + [true, 1, null, 5], + [true, 5, null, 5], + [true, 10, null, 5], + [true, 1, 2, 2], + [true, 5, 3, 3], + [true, 10, 7, 7], + [false, 1, null, 1], + [false, 3, null, 3], + [false, 5, null, 5], + [false, 1, 3, 1], + [false, 3, 5, 3], + [false, 5, 10, 5] + ]; + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/ShowUpdateResultTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/ShowUpdateResultTest.php new file mode 100644 index 0000000000000000000000000000000000000000..67c4c96989db26b6f28360315f48e6946a2c2385 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/ShowUpdateResultTest.php @@ -0,0 +1,151 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product; + +use Magento\Catalog\Controller\Adminhtml\Product\ShowUpdateResult; + +class ShowUpdateResultTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Backend\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject */ + protected $context; + + /** @var \Magento\Framework\View\Layout|\PHPUnit_Framework_MockObject_MockObject */ + protected $layout; + + /** @var \Magento\Backend\Model\Session|\PHPUnit_Framework_MockObject_MockObject */ + protected $session; + + /** @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject */ + protected $request; + + /** + * Init session object + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getSession() + { + $session = $this->getMock( + 'Magento\Backend\Model\Session', + ['hasCompositeProductResult', 'getCompositeProductResult', 'unsCompositeProductResult'], + [], + '', + false + ); + $session->expects($this->once()) + ->method('hasCompositeProductResult') + ->willReturn(true); + $session->expects($this->once()) + ->method('unsCompositeProductResult'); + $session->expects($this->atLeastOnce()) + ->method('getCompositeProductResult') + ->willReturn(new \Magento\Framework\Object()); + + return $session; + } + + /** + * Init context object + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getContext() + { + $productActionMock = $this->getMock('Magento\Catalog\Model\Product\Action', [], [], '', false); + $objectManagerMock = $this->getMockForAbstractClass('Magento\Framework\ObjectManagerInterface'); + $objectManagerMock->expects($this->any()) + ->method('get') + ->willreturn($productActionMock); + + $eventManager = $this->getMockForAbstractClass('Magento\Framework\Event\Manager', ['dispatch'], '', false); + + $eventManager->expects($this->any()) + ->method('dispatch') + ->willReturnSelf(); + + $this->request = $this->getMock( + 'Magento\Framework\App\Request\Http', + ['getParam', 'getPost', 'getFullActionName', 'getPostValue'], + [], + '', + false + ); + + $responseInterfaceMock = $this->getMock( + 'Magento\Framework\App\ResponseInterface', + ['setRedirect', 'sendResponse'], + [], + '', + false + ); + + $managerInterfaceMock = $this->getMock('Magento\Framework\Message\ManagerInterface'); + $this->session = $this->getSession(); + $actionFlagMock = $this->getMock('Magento\Framework\App\ActionFlag', [], [], '', false); + $helperDataMock = $this->getMock('Magento\Backend\Helper\Data', [], [], '', false); + $this->context = $this->getMock( + 'Magento\Backend\App\Action\Context', + [ + 'getRequest', + 'getResponse', + 'getObjectManager', + 'getEventManager', + 'getMessageManager', + 'getSession', + 'getActionFlag', + 'getHelper', + 'getTitle', + 'getView', + 'getResultRedirectFactory' + ], + [], + '', + false + ); + + $this->context->expects($this->any()) + ->method('getEventManager') + ->willReturn($eventManager); + $this->context->expects($this->any()) + ->method('getRequest') + ->willReturn($this->request); + $this->context->expects($this->any()) + ->method('getResponse') + ->willReturn($responseInterfaceMock); + $this->context->expects($this->any()) + ->method('getObjectManager') + ->willReturn($objectManagerMock); + + $this->context->expects($this->any()) + ->method('getMessageManager') + ->willReturn($managerInterfaceMock); + $this->context->expects($this->any()) + ->method('getSession') + ->willReturn($this->session); + $this->context->expects($this->any()) + ->method('getActionFlag') + ->willReturn($actionFlagMock); + $this->context->expects($this->any()) + ->method('getHelper') + ->willReturn($helperDataMock); + + return $this->context; + } + + public function testExecute() + { + $productCompositeHelper = $this->getMock('Magento\Catalog\Helper\Product\Composite', [], [], '', false); + $productCompositeHelper->expects($this->once()) + ->method('renderUpdateResult'); + + $productBuilder = $this->getMock('Magento\Catalog\Controller\Adminhtml\Product\Builder', [], [], '', false); + $context = $this->getContext(); + + /** @var \Magento\Catalog\Controller\Adminhtml\Product\ShowUpdateResult $controller */ + $controller = new ShowUpdateResult($context, $productBuilder, $productCompositeHelper); + $controller->execute(); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkManagementTest.php index fd8b8af6229258c4650220f3d9c3cfb8ae5bf765..9e75726f9dfa284355307d81760d848aa2d7de6e 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryLinkManagementTest.php @@ -57,7 +57,7 @@ class CategoryLinkManagementTest extends \PHPUnit_Framework_TestCase $productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); $productMock->expects($this->once())->method('getSku')->willReturn($productSku); $items = [$productId => $productMock]; - $productsMock = $this->getMock('\Magento\Framework\Data\Collection\Db', [], [], '', false); + $productsMock = $this->getMock('\Magento\Framework\Data\Collection\AbstractDb', [], [], '', false); $this->categoryRepositoryMock->expects($this->once())->method('get')->with($categoryId) ->willReturn($categoryMock); $categoryMock->expects($this->once())->method('getProductsPosition')->willReturn($productsPosition); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php index 92c2026f8961c258516299ba309da2cb811c145c..d8296c8b9edb0ab10a6864332ec2e2121136aa5c 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/ManagementTest.php @@ -135,7 +135,29 @@ class ManagementTest extends \PHPUnit_Framework_TestCase $this->productMock->expects($this->once())->method('getProductLinks')->willReturn([]); $this->productMock->expects($this->once())->method('setProductLinks')->with($links); - $this->assertTrue($this->model->setProductLinks($productSku, $linkType, $links)); + $this->assertTrue($this->model->setProductLinks($productSku, $links)); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage linkType is a required field. + */ + public function testSetProductLinksWithoutLinkTypeInLink() + { + $productSku = 'Simple Product 1'; + + $inputRelatedLink = $this->objectManager->getObject('Magento\Catalog\Model\ProductLink\Link'); + $inputRelatedLink->setProductSku($productSku); + $inputRelatedLink->setData("sku", "Simple Product 1"); + $inputRelatedLink->setPosition(0); + $links = [$inputRelatedLink]; + + $linkTypes = ['related' => 1, 'upsell' => 4, 'crosssell' => 5, 'associated' => 3]; + $this->linkTypeProviderMock->expects($this->once()) + ->method('getLinkTypes') + ->willReturn($linkTypes); + + $this->assertTrue($this->model->setProductLinks($productSku, $links)); } /** @@ -162,7 +184,7 @@ class ManagementTest extends \PHPUnit_Framework_TestCase ->method('getLinkTypes') ->willReturn($linkTypes); - $this->assertTrue($this->model->setProductLinks('', $linkType, $links)); + $this->assertTrue($this->model->setProductLinks('', $links)); } /** @@ -191,7 +213,7 @@ class ManagementTest extends \PHPUnit_Framework_TestCase ->method('get') ->will($this->throwException( new \Magento\Framework\Exception\NoSuchEntityException(__('Requested product doesn\'t exist')))); - $this->model->setProductLinks($productSku, $linkType, $links); + $this->model->setProductLinks($productSku, $links); } /** @@ -221,6 +243,6 @@ class ManagementTest extends \PHPUnit_Framework_TestCase $this->productMock->expects($this->once())->method('getProductLinks')->willReturn([]); $this->productRepositoryMock->expects($this->once())->method('save')->willThrowException(new \Exception()); - $this->model->setProductLinks($productSku, $linkType, $links); + $this->model->setProductLinks($productSku, $links); } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php index 26f70422f0e6075392f7e52c473371af78ded36c..d0922d05816472e3865a0423b4d124a732672246 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php @@ -80,7 +80,7 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase ] )); $entityMock->expects($this->once())->method('getLinkedProductSku')->willReturn('linkedProduct'); - $entityMock->expects($this->once())->method('getProductSku')->willReturn('product'); + $entityMock->expects($this->once())->method('getSku')->willReturn('product'); $entityMock->expects($this->exactly(2))->method('getLinkType')->willReturn('linkType'); $entityMock->expects($this->once())->method('__toArray')->willReturn([]); $linkedProductMock->expects($this->exactly(2))->method('getId')->willReturn(42); @@ -107,7 +107,7 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase ] )); $entityMock->expects($this->once())->method('getLinkedProductSku')->willReturn('linkedProduct'); - $entityMock->expects($this->once())->method('getProductSku')->willReturn('product'); + $entityMock->expects($this->once())->method('getSku')->willReturn('product'); $entityMock->expects($this->exactly(2))->method('getLinkType')->willReturn('linkType'); $entityMock->expects($this->once())->method('__toArray')->willReturn([]); $linkedProductMock->expects($this->exactly(2))->method('getId')->willReturn(42); @@ -134,7 +134,7 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase ] )); $entityMock->expects($this->once())->method('getLinkedProductSku')->willReturn('linkedProduct'); - $entityMock->expects($this->once())->method('getProductSku')->willReturn('product'); + $entityMock->expects($this->once())->method('getSku')->willReturn('product'); $entityMock->expects($this->exactly(2))->method('getLinkType')->willReturn('linkType'); $linkedProductMock->expects($this->exactly(2))->method('getId')->willReturn(42); $this->entityCollectionProviderMock->expects($this->once())->method('getCollection')->willReturn([ @@ -162,7 +162,7 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase ] )); $entityMock->expects($this->once())->method('getLinkedProductSku')->willReturn('linkedProduct'); - $entityMock->expects($this->once())->method('getProductSku')->willReturn('product'); + $entityMock->expects($this->once())->method('getSku')->willReturn('product'); $entityMock->expects($this->exactly(2))->method('getLinkType')->willReturn('linkType'); $linkedProductMock->expects($this->exactly(2))->method('getId')->willReturn(42); $this->entityCollectionProviderMock->expects($this->once())->method('getCollection')->willReturn([ @@ -191,7 +191,7 @@ class RepositoryTest extends \PHPUnit_Framework_TestCase ] )); $entityMock->expects($this->exactly(2))->method('getLinkedProductSku')->willReturn('linkedProduct'); - $entityMock->expects($this->exactly(2))->method('getProductSku')->willReturn('product'); + $entityMock->expects($this->exactly(2))->method('getSku')->willReturn('product'); $entityMock->expects($this->once())->method('getLinkType')->willReturn('linkType'); $this->model->delete($entityMock); } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php old mode 100644 new mode 100755 index 8335225cbbbfc59e25b4c289d113aaf0b17b9424..545c8d990ed9580c42850b9aa45fdd9ee16f8951 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductTest.php @@ -11,12 +11,14 @@ namespace Magento\Catalog\Test\Unit\Model; use Magento\Catalog\Model\Product; use Magento\Framework\Api\Data\ImageContentInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\Catalog\Model\Product\Attribute\Source\Status as Status; /** * Product Test * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.ExcessivePublicCount) * */ class ProductTest extends \PHPUnit_Framework_TestCase @@ -156,6 +158,11 @@ class ProductTest extends \PHPUnit_Framework_TestCase */ protected $entityCollectionProviderMock; + /** + * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $eventManagerMock; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -203,7 +210,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase ->method('getAreaCode') ->will($this->returnValue(\Magento\Backend\App\Area\FrontNameResolver::AREA_CODE)); - $eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface'); + $this->eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface'); $actionValidatorMock = $this->getMock( '\Magento\Framework\Model\ActionValidator\RemoveAction', [], @@ -219,7 +226,9 @@ class ProductTest extends \PHPUnit_Framework_TestCase ['getEventDispatcher', 'getCacheManager', 'getAppState', 'getActionValidator'], [], '', false ); $contextMock->expects($this->any())->method('getAppState')->will($this->returnValue($stateMock)); - $contextMock->expects($this->any())->method('getEventDispatcher')->will($this->returnValue($eventManagerMock)); + $contextMock->expects($this->any()) + ->method('getEventDispatcher') + ->will($this->returnValue($this->eventManagerMock)); $contextMock->expects($this->any()) ->method('getCacheManager') ->will($this->returnValue($cacheInterfaceMock)); @@ -385,6 +394,89 @@ class ProductTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('\Magento\Framework\Data\Collection', $this->model->getCategoryCollection()); } + /** + * @dataProvider getCategoryCollectionCollectionNullDataProvider + */ + public function testGetCategoryCollectionCollectionNull($initCategoryCollection, $getIdResult, $productIdCached) + { + $product = $this->getMock( + '\Magento\Catalog\Model\Product', + [ + '_getResource', + 'setCategoryCollection', + 'getId', + ], + [], + '', + false + ); + + $abstractDbMock = $this->getMockBuilder('\Magento\Framework\Model\Resource\Db\AbstractDb') + ->disableOriginalConstructor() + ->setMethods([ + 'getCategoryCollection', + ]) + ->getMockForAbstractClass(); + $getCategoryCollectionMock = $this->getMock( + '\Magento\Framework\Data\Collection', + [], + [], + '', + false + ); + $product + ->expects($this->once()) + ->method('setCategoryCollection') + ->with($getCategoryCollectionMock); + $product + ->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn($getIdResult); + $abstractDbMock + ->expects($this->once()) + ->method('getCategoryCollection') + ->with($product) + ->willReturn($getCategoryCollectionMock); + $product + ->expects($this->once()) + ->method('_getResource') + ->willReturn($abstractDbMock); + + $this->setPropertyValue($product, 'categoryCollection', $initCategoryCollection); + $this->setPropertyValue($product, '_productIdCached', $productIdCached); + + $result = $product->getCategoryCollection(); + + $productIdCachedActual = $this->getPropertyValue($product, '_productIdCached', $productIdCached); + $this->assertEquals($getIdResult, $productIdCachedActual); + $this->assertEquals($initCategoryCollection, $result); + } + + public function getCategoryCollectionCollectionNullDataProvider() + { + return [ + [ + '$initCategoryCollection' => null, + '$getIdResult' => 'getIdResult value', + '$productIdCached' => 'productIdCached value', + ], + [ + '$initCategoryCollection' => 'value', + '$getIdResult' => 'getIdResult value', + '$productIdCached' => 'not getIdResult value', + ], + ]; + } + + public function testSetCategoryCollection() + { + $collection = $this->getMockBuilder('\Magento\Framework\Data\Collection') + ->disableOriginalConstructor() + ->getMock(); + $this->resource->expects($this->once())->method('getCategoryCollection')->will($this->returnValue($collection)); + $this->assertSame($this->model->getCategoryCollection(), $this->model->getCategoryCollection()); + } + public function testGetCategory() { $this->category->expects($this->any())->method('getId')->will($this->returnValue(10)); @@ -415,16 +507,20 @@ class ProductTest extends \PHPUnit_Framework_TestCase $this->assertEquals([], $this->model->getCategoryIds()); } + public function testGetStatusInitial() + { + $this->assertEquals(Status::STATUS_ENABLED, $this->model->getStatus()); + } + public function testGetStatus() { $this->model->setStatus(null); - $expected = \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED; - $this->assertEquals($expected, $this->model->getStatus()); + $this->assertEquals(Status::STATUS_ENABLED, $this->model->getStatus()); } public function testIsInStock() { - $this->model->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED); + $this->model->setStatus(Status::STATUS_ENABLED); $this->assertTrue($this->model->isInStock()); } @@ -510,7 +606,9 @@ class ProductTest extends \PHPUnit_Framework_TestCase $this->model->setOrigData($key, $value); } } - $this->model->setData($data); + foreach ($data as $key => $value) { + $this->model->setData($key, $value); + } $this->model->isDeleted($isDeleted); $this->assertEquals($expected, $this->model->getIdentities()); } @@ -521,12 +619,12 @@ class ProductTest extends \PHPUnit_Framework_TestCase public function getIdentitiesProvider() { return [ - [ + 'no changes' => [ ['catalog_product_1'], ['id' => 1, 'name' => 'value', 'category_ids' => [1]], ['id' => 1, 'name' => 'value', 'category_ids' => [1]], ], - [ + 'new product' => [ ['catalog_product_1', 'catalog_category_product_1'], null, [ @@ -537,24 +635,57 @@ class ProductTest extends \PHPUnit_Framework_TestCase 'is_changed_categories' => true ] ], - [ - [0 => 'catalog_product_1', 1 => 'catalog_category_product_1'], + 'status and category change' => [ + [0 => 'catalog_product_1', 1 => 'catalog_category_product_1', 2 => 'catalog_category_product_2'], ['id' => 1, 'name' => 'value', 'category_ids' => [1], 'status' => 2], - ['id' => 1, 'name' => 'value', 'category_ids' => [1], 'status' => 1], + [ + 'id' => 1, + 'name' => 'value', + 'category_ids' => [2], + 'status' => 1, + 'affected_category_ids' => [1, 2], + 'is_changed_categories' => true + ], ], - [ - [0 => 'catalog_product_1'], - ['id' => 1, 'name' => 'value', 'category_ids' => [1], 'status' => 1], - ['id' => 1, 'name' => 'value', 'category_ids' => [1], 'status' => 2], + 'status change only' => [ + [0 => 'catalog_product_1', 1 => 'catalog_category_product_7'], + ['id' => 1, 'name' => 'value', 'category_ids' => [7], 'status' => 1], + ['id' => 1, 'name' => 'value', 'category_ids' => [7], 'status' => 2], ], - [ + 'status changed, category unassigned' => [ + [0 => 'catalog_product_1', 1 => 'catalog_category_product_5'], + ['id' => 1, 'name' => 'value', 'category_ids' => [5], 'status' => 2], + [ + 'id' => 1, + 'name' => 'value', + 'category_ids' => [], + 'status' => 1, + 'is_changed_categories' => true, + 'affected_category_ids' => [5] + ], + ], + 'no status changes' => [ [0 => 'catalog_product_1'], - ['id' => 1, 'name' => 'value', 'category_ids' => [1], 'status' => 2], - ['id' => 1, 'name' => 'value', 'category_ids' => [], 'status' => 1], + ['id' => 1, 'name' => 'value', 'category_ids' => [1], 'status' => 1], + ['id' => 1, 'name' => 'value', 'category_ids' => [1], 'status' => 1], ] ]; } + public function testStatusAfterLoad() + { + $this->resource->expects($this->once())->method('load')->with($this->model, 1, null); + $this->eventManagerMock->expects($this->exactly(4))->method('dispatch'); + $this->model->load(1); + $this->assertEquals( + Status::STATUS_ENABLED, + $this->model->getData(\Magento\Catalog\Model\Product::STATUS) + ); + $this->assertFalse($this->model->hasDataChanges()); + $this->model->setStatus(Status::STATUS_DISABLED); + $this->assertTrue($this->model->hasDataChanges()); + } + /** * Test retrieving price Info */ @@ -761,14 +892,14 @@ class ProductTest extends \PHPUnit_Framework_TestCase ->willReturn($linkTypes); $inputRelatedLink = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); - $inputRelatedLink->setProductSku("Simple Product 1"); + $inputRelatedLink->setSku("Simple Product 1"); $inputRelatedLink->setLinkType("related"); $inputRelatedLink->setData("sku", "Simple Product 2"); $inputRelatedLink->setData("type", "simple"); $inputRelatedLink->setPosition(0); $outputRelatedLink = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); - $outputRelatedLink->setProductSku("Simple Product 1"); + $outputRelatedLink->setSku("Simple Product 1"); $outputRelatedLink->setLinkType("related"); $outputRelatedLink->setLinkedProductSku("Simple Product 2"); $outputRelatedLink->setLinkedProductType("simple"); @@ -815,7 +946,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase public function testSetProductLinks() { $link = $this->objectManagerHelper->getObject('Magento\Catalog\Model\ProductLink\Link'); - $link->setProductSku("Simple Product 1"); + $link->setSku("Simple Product 1"); $link->setLinkType("upsell"); $link->setLinkedProductSku("Simple Product 2"); $link->setLinkedProductType("simple"); @@ -1201,4 +1332,31 @@ class ProductTest extends \PHPUnit_Framework_TestCase $productModel->setOptions([]); $this->assertEquals([], $productModel->getOptions()); } + + /** + * @param $object + * @param $property + * @param $value + */ + protected function setPropertyValue(&$object, $property, $value) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionProperty = $reflection->getProperty($property); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($object, $value); + return $object; + } + + /** + * @param $object + * @param $property + */ + protected function getPropertyValue(&$object, $property) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionProperty = $reflection->getProperty($property); + $reflectionProperty->setAccessible(true); + + return $reflectionProperty->getValue($object); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Resource/AbstractTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Resource/AbstractTest.php index 99854ffe12738373d8dff7b3becad6d881bf440d..62460a7b1f667bd43b79cbd8a9921f87cc8ee90f 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Resource/AbstractTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Resource/AbstractTest.php @@ -50,7 +50,8 @@ class AbstractTest extends \PHPUnit_Framework_TestCase $object = $this->getMock('Magento\Catalog\Model\Product', ['__wakeup'], [], '', false); - $object->setData(['test_attr' => 'test_attr', 'attribute_set_id' => $set]); + $object->setData('test_attr', 'test_attr'); + $object->setData('attribute_set_id', $set); $entityType = new \Magento\Framework\Object(); $entityType->setEntityTypeCode('test'); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Resource/Eav/AttributeTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Resource/Eav/AttributeTest.php index 30d400ca8ef2a7317ae56287e729b7e8feb1ec85..bbed8baac68f0545652595c9c8a6f83fbe2828e5 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Resource/Eav/AttributeTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Resource/Eav/AttributeTest.php @@ -121,7 +121,8 @@ class AttributeTest extends \PHPUnit_Framework_TestCase { $this->_processor->expects($this->once())->method('markIndexerAsInvalid'); - $this->_model->setData(['id' => 2, 'used_in_product_listing' => 1]); + $this->_model->setData('id', 2); + $this->_model->setData('used_in_product_listing', 1); $this->_model->afterSave(); } diff --git a/app/code/Magento/Catalog/composer.json b/app/code/Magento/Catalog/composer.json index 723b86045cdfc521d7c84e86c2458d622592f219..2c1ac69b4bbf736b53a62ea9d6387171ece6e7f4 100644 --- a/app/code/Magento/Catalog/composer.json +++ b/app/code/Magento/Catalog/composer.json @@ -3,37 +3,37 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-cms": "0.74.0-beta10", - "magento/module-indexer": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-log": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-widget": "0.74.0-beta10", - "magento/module-wishlist": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-msrp": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-catalog-rule": "0.74.0-beta10", - "magento/module-product-alert": "0.74.0-beta10", - "magento/module-url-rewrite": "0.74.0-beta10", - "magento/module-catalog-url-rewrite": "0.74.0-beta10", - "magento/module-page-cache": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-cms": "0.74.0-beta13", + "magento/module-indexer": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-log": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-widget": "0.74.0-beta13", + "magento/module-wishlist": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-msrp": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-catalog-rule": "0.74.0-beta13", + "magento/module-product-alert": "0.74.0-beta13", + "magento/module-url-rewrite": "0.74.0-beta13", + "magento/module-catalog-url-rewrite": "0.74.0-beta13", + "magento/module-page-cache": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-cookie": "0.74.0-beta10" + "magento/module-cookie": "0.74.0-beta13" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Catalog/etc/webapi.xml b/app/code/Magento/Catalog/etc/webapi.xml index b86beded162cfd7ced4da7d5869e7efccf1d01cf..ec8458cd8c9a7ebeda59b7dfdbde2fbb77b05bf6 100644 --- a/app/code/Magento/Catalog/etc/webapi.xml +++ b/app/code/Magento/Catalog/etc/webapi.xml @@ -361,7 +361,7 @@ <resource ref="anonymous"/> </resources> </route> - <route url="/V1/products/:sku/links/:type" method="POST"> + <route url="/V1/products/:sku/links" method="POST"> <service class="Magento\Catalog\Api\ProductLinkManagementInterface" method="setProductLinks"/> <resources> <resource ref="Magento_Catalog::catalog"/> @@ -373,7 +373,7 @@ <resource ref="Magento_Catalog::catalog"/> </resources> </route> - <route url="/V1/products/:sku/links/:link_type" method="PUT"> + <route url="/V1/products/:sku/links" method="PUT"> <service class="Magento\Catalog\Api\ProductLinkRepositoryInterface" method="save"/> <resources> <resource ref="Magento_Catalog::catalog"/> diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml old mode 100644 new mode 100755 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 05b6e60c4cd48323c522938426a61aa4583d1acd..84ad6a8cd42a7b2e059db7ddeaf44e9c3712fdef 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 @@ -124,7 +124,7 @@ define([ if (!data.result.error) { $galleryContainer.trigger('addItem', data.result); } else { - alert($.mage.__('File extension not known or unsupported type.')); + alert($.mage.__('We don\'t recognize or support this file extension type.')); } }, add: function (event, data) { 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 d2e22b3fb93e7eb99de159ee4f57c7717749785b..648632e2aacbe36150e3c99e4a9d22df2f136e8c 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 @@ -392,14 +392,13 @@ ProductConfigure.prototype = { if (Object.isFunction(this.onLoadIFrameCallback[this.current.listType])) { this.onLoadIFrameCallback[this.current.listType](response); } - document.fire(this.current.listType + ':afterIFrameLoaded'); } - // Hide loader jQuery(this.blockForm).trigger('processStop'); this.clean('current'); + this.initialize(); }, /** 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 46ad78762462021ec363fd33a16025ea2e4a1fee..552e6a3a70ee729d5bcc8367b3f50312d5061adf 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 @@ -7,6 +7,7 @@ define([ 'jquery', 'jquery/ui', + 'Magento_Ui/js/modal/modal', 'mage/translate', 'mage/backend/tree-suggest', 'mage/backend/validation' @@ -51,53 +52,37 @@ define([ options.errorClass, options.validClass || ''); } }); - - this.element.dialog({ + this.element.modal({ + type: 'slide', + modalClass: 'mage-new-category-dialog form-inline', title: $.mage.__('Create Category'), - autoOpen: false, - width: '75%', - dialogClass: 'mage-new-category-dialog form-inline', - modal: true, - multiselect: true, - resizable: false, - position: { - my: 'left top', - at: 'center top', - of: 'body' - }, - open: function () { - // fix for suggest field - overlapping dialog z-index - $('#new_category_parent-suggest').css('z-index', $.ui.dialog.maxZ + 1); + opened: function () { var enteredName = $('#category_ids-suggest').val(); + $('#new_category_name').val(enteredName); if (enteredName === '') { $('#new_category_name').focus(); } $('#new_category_messages').html(''); - $(this).closest('.ui-dialog').addClass('ui-dialog-active'); - - var topMargin = $(this).closest('.ui-dialog').children('.ui-dialog-titlebar').outerHeight() + 15; - $(this).closest('.ui-dialog').css('margin-top', topMargin); }, - close: function () { - $('#new_category_name, #new_category_parent-suggest').val(''); + closed: function () { var validationOptions = newCategoryForm.validation('option'); + + $('#new_category_name, #new_category_parent-suggest').val(''); validationOptions.unhighlight($('#new_category_parent-suggest').get(0), validationOptions.errorClass, validationOptions.validClass || ''); newCategoryForm.validation('clearError'); $('#category_ids-suggest').focus(); - $(this).closest('.ui-dialog').removeClass('ui-dialog-active'); }, buttons: [{ text: $.mage.__('Create Category'), - 'class': 'action-primary', - 'data-action': 'save', - click: function (event) { + class: 'action-primary', + click: function (e) { if (!newCategoryForm.valid()) { return; } + var thisButton = $(e.currentTarget); - var thisButton = $(event.target).closest('[data-action=save]'); thisButton.prop('disabled', true); $.ajax({ type: 'POST', @@ -115,27 +100,25 @@ define([ }, dataType: 'json', context: $('body') - }) - .success( - function (data) { - if (!data.error) { - $('#category_ids-suggest').trigger('selectItem', { - id: data.category.entity_id, - label: data.category.name - }); - $('#new_category_name, #new_category_parent-suggest').val(''); - $('#category_ids-suggest').val(''); - clearParentCategory(); - widget.element.dialog('close'); - } else { - $('#new_category_messages').html(data.messages); - } - } - ) - .complete( - function () { - thisButton.prop('disabled', false); - } + }).success(function (data) { + if (!data.error) { + var $suggest = $('#category_ids-suggest'); + + $suggest.trigger('selectItem', { + id: data.category.entity_id, + label: data.category.name + }); + $('#new_category_name, #new_category_parent-suggest').val(''); + $suggest.val(''); + clearParentCategory(); + widget.element.trigger('closeModal'); + } else { + $('#new_category_messages').html(data.messages); + } + }).complete( + function () { + thisButton.prop('disabled', false); + } ); } }] diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml index 6018b36485e8ac6be25e37475450ad5445fb500c..486d9543f20be46385f57b6804557276f7f47240 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/compare/list.phtml @@ -80,7 +80,7 @@ <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow()) : ?> <div class="secondary-addto-links actions-secondary" data-role="add-to-links"> <a href="#" data-post='<?php echo $block->getAddToWishlistParams($_item); ?>' class="action towishlist" data-action="add-to-wishlist"> - <span><?php echo __('Add to Wishlist') ?></span> + <span><?php echo __('Add to Wish List') ?></span> </a> </div> <?php endif; ?> 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 742b7521914f3184c54be01918804ccab87775bc..154454f16dbfe579d73ac63eab37ae723710f7d5 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/list.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/list.phtml @@ -96,12 +96,12 @@ $imageBlock = $block->getLayout()->createBlock('Magento\Catalog\Block\Product\I <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow()): ?> <a href="#" class="action towishlist" - title="<?php echo $block->escapeHtml(__('Add to Wishlist')); ?>" - aria-label="<?php echo $block->escapeHtml(__('Add to Wishlist')); ?>" + title="<?php echo $block->escapeHtml(__('Add to Wish List')); ?>" + aria-label="<?php echo $block->escapeHtml(__('Add to Wish List')); ?>" data-post='<?php echo $block->getAddToWishlistParams($_product); ?>' data-action="add-to-wishlist" role="button"> - <span><?php echo __('Add to Wishlist') ?></span> + <span><?php echo __('Add to Wish List') ?></span> </a> <?php endif; ?> <?php 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 e4d722b840fb0344f4512745b19712d7ff79444e..a2d391e3eb6955a408b51c5cd8d44f07673fc5d7 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 @@ -251,8 +251,8 @@ switch ($type = $block->getType()) { <?php if ($showWishlist || $showCompare): ?> <div class="secondary-addto-links actions-secondary" data-role="add-to-links"> <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow() && $showWishlist): ?> - <a href="#" data-post='<?php echo $block->getAddToWishlistParams($_item); ?>' class="action towishlist" data-action="add-to-wishlist" title="<?php echo __('Add to Wishlist') ?>"> - <span><?php echo __('Add to Wishlist') ?></span> + <a href="#" data-post='<?php echo $block->getAddToWishlistParams($_item); ?>' class="action towishlist" data-action="add-to-wishlist" title="<?php echo __('Add to Wish List') ?>"> + <span><?php echo __('Add to Wish List') ?></span> </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare): ?> diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/listing.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/listing.phtml index 6431fceac5aa5d958a1038ee05a16ff55f0d8da9..2bb871627594dd90c722a83a264c0ddb0c0e7aa5 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/listing.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/listing.phtml @@ -71,7 +71,7 @@ $imageBlock = $block->getLayout()->createBlock('Magento\Catalog\Block\Product\I $info['links'] = '<div class="product links" data-role="add-to-links">' . '<a href="#" data-post=\'' . $this->helper('Magento\Wishlist\Helper\Data')->getAddParams($_product) . '\' class="action towishlist" data-action="add-to-wishlist">' - . '<span>' . __('Add to Wishlist') . '</span></a>' + . '<span>' . __('Add to Wish List') . '</span></a>' . '<a href="' . $block->getAddToCompareUrl($_product) . '" class="action tocompare">' . '<span>' . __('Add to Compare') . '</span></a></div>'; $info['actions'] = '<div class="product action">' . $info['button'] . $info['links'] . '</div>'; diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/addto.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/addto.phtml index 9cc99cbb34f72f74847087aaa44a0fc36f4d5d4b..547c54ef0a1b7bf23dd0c9f0265941386215b0e9 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/view/addto.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/addto.phtml @@ -18,9 +18,9 @@ $compareHelper = $this->helper('Magento\Catalog\Helper\Product\Compare'); <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow()) : ?> <a href="#" class="action towishlist" - title="<?php echo __('Add to Wishlist') ?>" + title="<?php echo __('Add to Wish List') ?>" data-post='<?php echo $_wishlistSubmitParams; ?>' - data-action="add-to-wishlist"><span><?php echo __('Add to Wishlist') ?></span></a> + data-action="add-to-wishlist"><span><?php echo __('Add to Wish List') ?></span></a> <?php endif; ?> <a href="#" data-post='<?php echo $compareHelper->getPostDataParams($_product);?>' data-role="add-to-links" diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_grid.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_grid.phtml index 2061919c2ff35192eb6ae915e6ba919c926657d5..bf2056e6bf80dd1c25f0bb303aa55c99c87dda68 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_grid.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_grid.phtml @@ -100,8 +100,8 @@ if ($exist = ($block->getProductCollection() && $block->getProductCollection()-> <a href="#" data-post='<?php echo $block->getAddToWishlistParams($_item); ?>' class="action towishlist" data-action="add-to-wishlist" - title="<?php echo __('Add to Wishlist') ?>"> - <span><?php echo __('Add to Wishlist') ?></span> + title="<?php echo __('Add to Wish List') ?>"> + <span><?php echo __('Add to Wish List') ?></span> </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare): ?> diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_list.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_list.phtml index be45c6d5b427100b6c1de76a143cdf542cbf523d..14e3c3a0361ff7e62d22e38f64909eb9b20ddea8 100644 --- a/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_list.phtml +++ b/app/code/Magento/Catalog/view/frontend/templates/product/widget/new/content/new_list.phtml @@ -99,8 +99,8 @@ if ($exist = ($block->getProductCollection() && $block->getProductCollection()-> <a href="#" data-post='<?php echo $block->getAddToWishlistParams($_item); ?>' class="action towishlist" data-action="add-to-wishlist" - title="<?php echo __('Add to Wishlist') ?>"> - <span><?php echo __('Add to Wishlist') ?></span> + title="<?php echo __('Add to Wish List') ?>"> + <span><?php echo __('Add to Wish List') ?></span> </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare): ?> diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index 7b3303731f3457b517b7b7d011e32bc531648313..d009107df13e59af9c7d1e0361a5259f95a50bd3 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -1108,23 +1108,25 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity } $customOptionsDataPre[$productId][$optionId][] = $row; - foreach ($values as $value) { - $row = []; - $valuePriceType = $value['price_type'] == 'percent' ? '%' : ''; - - if (Store::DEFAULT_STORE_ID == $storeId) { - $row['_custom_option_row_title'] = $value['title']; - $row['_custom_option_row_price'] = $value['price'] . $valuePriceType; - $row['_custom_option_row_sku'] = $value['sku']; - $row['_custom_option_row_sort'] = $value['sort_order']; - } else { - $row['_custom_option_row_title'] = $value['title']; - } - if ($row) { - if (Store::DEFAULT_STORE_ID != $storeId) { - $row['_custom_option_store'] = $this->_storeIdToCode[$storeId]; + if ($values) { + foreach ($values as $value) { + $row = []; + $valuePriceType = $value['price_type'] == 'percent' ? '%' : ''; + + if (Store::DEFAULT_STORE_ID == $storeId) { + $row['_custom_option_row_title'] = $value['title']; + $row['_custom_option_row_price'] = $value['price'] . $valuePriceType; + $row['_custom_option_row_sku'] = $value['sku']; + $row['_custom_option_row_sort'] = $value['sort_order']; + } else { + $row['_custom_option_row_title'] = $value['title']; + } + if ($row) { + if (Store::DEFAULT_STORE_ID != $storeId) { + $row['_custom_option_store'] = $this->_storeIdToCode[$storeId]; + } + $customOptionsDataPre[$option['product_id']][$optionId][] = $row; } - $customOptionsDataPre[$option['product_id']][$optionId][] = $row; } } $option = null; diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php old mode 100644 new mode 100755 index 2a2a7bafff8201648fbb8f58a14537119162ceb9..82e2153c4a5295829fdf4e879739d101dfa6b9b7 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -14,6 +14,7 @@ use Magento\Framework\Model\Resource\Db\TransactionManagerInterface; use Magento\Framework\Model\Resource\Db\ObjectRelationProcessor; use Magento\Framework\Stdlib\DateTime; + /** * Import entity product model * @SuppressWarnings(PHPMD.TooManyFields) @@ -29,6 +30,28 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity */ const BUNCH_SIZE = 20; + /** + * Size of bunch to delete attributes of products in one step. + */ + const ATTRIBUTE_DELETE_BUNCH = 1000; + + /** + * default delimiter for several values in one cell + */ + const DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR = ','; + + /** + * Pseudo multi line separator in one cell. + * + * Can be used as custom option value delimiter or in configurable fields cells. + */ + const PSEUDO_MULTI_LINE_SEPARATOR = '|'; + + /** + * Symbol between Name and Value between Pairs. + */ + const PAIR_NAME_VALUE_SEPARATOR = '='; + /** * Value that means all entities (e.g. websites, groups etc.) */ @@ -51,18 +74,79 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity * Names that begins with underscore is not an attribute. This name convention is for * to avoid interference with same attribute name. */ + + /** + * Column product store. + */ const COL_STORE = '_store'; - const COL_ATTR_SET = '_attribute_set'; + /** + * Column product store view code. + */ + const COL_STORE_VIEW_CODE = 'store_view_code'; - const COL_TYPE = '_type'; + /** + * Column website. + */ + const COL_WEBSITE = 'website_code'; + + /** + * Column product attribute set. + */ + const COL_ATTR_SET = '_attribute_set'; - const COL_CATEGORY = '_category'; + /** + * Column product type. + */ + const COL_TYPE = 'product_type'; - const COL_ROOT_CATEGORY = '_root_category'; + /** + * Column product category. + */ + const COL_CATEGORY = 'categories'; + /** + * Column product sku. + */ const COL_SKU = 'sku'; + /** + * Column product name. + */ + const COL_NAME = 'name'; + + /** + * Column product website. + */ + const COL_PRODUCT_WEBSITES = '_product_websites'; + + /** + * Media gallery attribute code. + */ + const MEDIA_GALLERY_ATTRIBUTE_CODE = 'media_gallery'; + + /** + * Column media image. + */ + const COL_MEDIA_IMAGE = '_media_image'; + + /** + * Inventory use config. + */ + const INVENTORY_USE_CONFIG = 'Use Config'; + + /** + * Inventory use config prefix. + */ + const INVENTORY_USE_CONFIG_PREFIX = 'use_config_'; + + /** + * Attribute cache + * + * @var array + */ + protected $_attributeCache = []; + /** * Pairs of attribute set ID-to-name. * @@ -85,9 +169,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity protected $_indexValueAttributes = [ 'status', 'tax_class_id', - 'visibility', 'gift_message_available', - 'custom_design', ]; /** @@ -101,6 +183,13 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity '_upsell_' => \Magento\Catalog\Model\Product\Link::LINK_TYPE_UPSELL, ]; + /** + * Attribute id for product images storage. + * + * @var array + */ + protected $_mediaGalleryAttributeId = null; + /** * Validation failure message template definitions * @@ -133,6 +222,44 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity ValidatorInterface::ERROR_INVALID_WEIGHT => 'Product weight is invalid', ]; + /** + * Map between import file fields and system fields/attributes. + * + * @var array + */ + protected $_fieldsMap = [ + 'image' => 'base_image', + 'image_label' => "base_image_label", + 'image' => 'base_image', + 'image_label' => 'base_image_label', + 'thumbnail' => 'thumbnail_image', + 'thumbnail_label' => 'thumbnail_image_label', + self::COL_MEDIA_IMAGE => 'additional_images', + '_media_image_label' => 'additional_image_labels', + Product::COL_STORE => 'store_view_code', + Product::COL_ATTR_SET => 'attribute_set_code', + Product::COL_TYPE => 'product_type', + Product::COL_PRODUCT_WEBSITES => 'product_websites', + 'status' => 'product_online', + 'news_from_date' => 'new_from_date', + 'news_to_date' => 'new_to_date', + 'options_container' => 'display_product_options_in', + 'minimal_price' => 'map_price', + 'msrp' => 'msrp_price', + 'msrp_enabled' => 'map_enabled', + 'special_from_date' => 'special_price_from_date', + 'special_to_date' => 'special_price_to_date', + 'min_qty' => 'out_of_stock_qty', + 'backorders' => 'allow_backorders', + 'min_sale_qty' => 'min_cart_qty', + 'max_sale_qty' => 'max_cart_qty', + 'notify_stock_qty' => 'notify_on_stock_below', + '_related_sku' => 'related_skus', + '_crosssell_sku' => 'crosssell_skus', + '_upsell_sku' => 'upsell_skus', + 'meta_keyword' => 'meta_keywords', + ]; + /** * Existing products SKU-related information in form of array: * @@ -153,12 +280,12 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity * @var string[] */ protected $_specialAttributes = [ - '_store', - '_attribute_set', - '_type', + self::COL_STORE, + self::COL_ATTR_SET, + self::COL_TYPE, self::COL_CATEGORY, - self::COL_ROOT_CATEGORY, '_product_websites', + self::COL_PRODUCT_WEBSITES, '_tier_price_website', '_tier_price_customer_group', '_tier_price_qty', @@ -188,7 +315,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity '_custom_option_row_sku', '_custom_option_row_sort', '_media_attribute_id', - '_media_image', + self::COL_MEDIA_IMAGE, '_media_label', '_media_position', '_media_is_disabled', @@ -361,11 +488,25 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity */ protected $categoryProcessor; + /** + * Instance of product tax class processor. + * + * @var Product\TaxClassProcessor + */ + protected $taxClassProcessor; + /** * @var Product\Validator */ protected $validator; + /** + * Array of validated rows. + * + * @var array + */ + protected $validatedRows; + /** * @var \Psr\Log\LoggerInterface */ @@ -376,6 +517,13 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity */ protected $masterAttributeCode = 'sku'; + /** + * Instance of catalog product factory. + * + * @var \Magento\Catalog\Model\ProductFactory $catalogProductFactory + */ + protected $catalogProductFactory; + /** * @var ObjectRelationProcessor */ @@ -386,6 +534,13 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity */ protected $transactionManager; + /** + * Flag for replace operation. + * + * @var null + */ + protected $_replaceFlag = null; + /** * @param \Magento\Framework\Json\Helper\Data $jsonHelper * @param \Magento\ImportExport\Helper\Data $importExportData @@ -416,7 +571,9 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity * @param Product\StoreResolver $storeResolver * @param Product\SkuProcessor $skuProcessor * @param Product\CategoryProcessor $categoryProcessor + * @param Product\TaxClassProcessor $taxClassProcessor * @param Product\Validator $validator + * @param \Magento\Catalog\Model\ProductFactory $catalogProductFactory * @param array $data * @throws \Magento\Framework\Exception\LocalizedException * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -452,8 +609,10 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity Product\SkuProcessor $skuProcessor, Product\CategoryProcessor $categoryProcessor, Product\Validator $validator, + \Magento\Catalog\Model\ProductFactory $catalogProductFactory, ObjectRelationProcessor $objectRelationProcessor, TransactionManagerInterface $transactionManager, + Product\TaxClassProcessor $taxClassProcessor, array $data = [] ) { $this->_eventManager = $eventManager; @@ -468,7 +627,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity $this->_linkFactory = $linkFactory; $this->_proxyProdFactory = $proxyProdFactory; $this->_uploaderFactory = $uploaderFactory; - $this->_mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA); + $this->_mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); $this->_stockResItemFac = $stockResItemFac; $this->_localeDate = $localeDate; $this->dateTime = $dateTime; @@ -480,6 +639,8 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity $this->validator = $validator; $this->objectRelationProcessor = $objectRelationProcessor; $this->transactionManager = $transactionManager; + $this->catalogProductFactory = $catalogProductFactory; + $this->taxClassProcessor = $taxClassProcessor; parent::__construct($jsonHelper, $importExportData, $importData, $config, $resource, $resourceHelper, $string); $this->_optionEntity = isset( $data['option_entity'] @@ -493,6 +654,62 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity $this->validator->init(); } + /** + * Check one attribute. Can be overridden in child. + * + * @param string $attrCode Attribute code + * @param array $attrParams Attribute params + * @param array $rowData Row data + * @param int $rowNum + * + * @return boolean + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function isAttributeValid($attrCode, array $attrParams, array $rowData, $rowNum) + { + switch ($attrParams['type']) { + case 'varchar': + $val = $this->string->cleanString($rowData[$attrCode]); + $valid = $this->string->strlen($val) < self::DB_MAX_VARCHAR_LENGTH; + break; + case 'decimal': + $val = trim($rowData[$attrCode]); + $valid = is_numeric($val); + break; + case 'select': + case 'multiselect': + $valid = isset($attrParams['options'][strtolower($rowData[$attrCode])]); + break; + case 'int': + $val = trim($rowData[$attrCode]); + $valid = (string)(int)$val === $val; + break; + case 'datetime': + $val = trim($rowData[$attrCode]); + $valid = strtotime($val) !== false; + break; + case 'text': + $val = $this->string->cleanString($rowData[$attrCode]); + $valid = $this->string->strlen($val) < self::DB_MAX_TEXT_LENGTH; + break; + default: + $valid = true; + break; + } + + if (!$valid) { + $this->addRowError(__("Please correct the value for '%s'."), $rowNum, $attrCode); + } elseif (!empty($attrParams['is_unique'])) { + if (isset($this->_uniqueAttributes[$attrCode][$rowData[$attrCode]]) && ($this->_uniqueAttributes[$attrCode][$rowData[$attrCode]] != $rowData[self::COL_SKU])) { + $this->addRowError(__("Duplicate Unique Attribute for '%s'"), $rowNum, $attrCode); + return false; + } + $this->_uniqueAttributes[$attrCode][$rowData[$attrCode]] = $rowData[self::COL_SKU]; + } + return (bool)$valid; + } + /** * Retrieve instance of product custom options import entity * @@ -503,6 +720,34 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity return $this->_optionEntity; } + /** + * Multiple value separator getter. + * + * @return string + */ + public function getMultipleValueSeparator() + { + if (!empty($this->_parameters[\Magento\ImportExport\Model\Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR])) { + return $this->_parameters[\Magento\ImportExport\Model\Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR]; + } + return self::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR; + } + + /** + * Retrieve id of media gallery attribute. + * + * @return int + */ + public function getMediaGalleryAttributeId() + { + if (!$this->_mediaGalleryAttributeId) { + /** @var $resource \Magento\CatalogImportExport\Model\Import\Proxy\Product\Resource */ + $resource = $this->_resourceFactory->create(); + $this->_mediaGalleryAttributeId = $resource->getAttribute(self::MEDIA_GALLERY_ATTRIBUTE_CODE)->getId(); + } + return $this->_mediaGalleryAttributeId; + } + /** * Set import parameters * @@ -517,6 +762,19 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity return $this; } + /** + * Delete products for replacement. + * + * @return $this + */ + public function deleteProductsForReplacement() + { + $this->setParameters(array('behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE)); + $this->_deleteProducts(); + + return $this; + } + /** * Delete products. * @@ -550,6 +808,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity $this->transactionManager->rollBack(); throw $e; } + $this->_eventManager->dispatch('catalog_product_import_bunch_delete_after', ['adapter' => $this, 'bunch' => $bunch]); } } return $this; @@ -560,24 +819,60 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity * * @throws \Exception * @return bool Result of operation. + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function _importData() { + $this->_validatedRows = null; if (\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE == $this->getBehavior()) { $this->_deleteProducts(); + } elseif (\Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE == $this->getBehavior()) { + $this->_replaceFlag = true; + $this->_replaceProducts(); } else { - $this->_saveProducts(); - foreach ($this->_productTypeModels as $productTypeModel) { - $productTypeModel->saveData(); - } - $this->_saveLinks(); - $this->_saveStockItem(); - $this->getOptionEntity()->importData(); + $this->_saveProductsData(); } $this->_eventManager->dispatch('catalog_product_import_finish_before', ['adapter' => $this]); return true; } + /** + * Replace imported products. + * + * @return $this + */ + protected function _replaceProducts() + { + $this->deleteProductsForReplacement(); + $this->_oldSku = $this->skuProcessor->reloadOldSkus()->getOldSkus(); + $this->_validatedRows = null; + $this->setParameters(array('behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND)); + $this->_saveProductsData(); + + return $this; + } + + /** + * Save products data. + * + * @return $this + */ + protected function _saveProductsData() + { + $this->_saveProducts(); + foreach ($this->_productTypeModels as $productTypeModel) { + $productTypeModel->saveData(); + } + $this->_saveLinks(); + $this->_saveStockItem(); + if ($this->_replaceFlag) { + $this->getOptionEntity()->clearProductsSkuToId(); + } + $this->getOptionEntity()->importData(); + + return $this; + } + /** * Initialize attribute sets code-to-id pairs. * @@ -632,6 +927,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity if ($model->isSuitable()) { $this->_productTypeModels[$productTypeName] = $model; } + $this->_fieldsMap = array_merge($this->_fieldsMap, $model->getCustomFieldsMapping()); $this->_specialAttributes = array_merge($this->_specialAttributes, $model->getParticularAttributes()); } // remove doubles @@ -649,6 +945,8 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity */ protected function _prepareRowForDb(array $rowData) { + $rowData = $this->_customFieldsMapping($rowData); + $rowData = parent::_prepareRowForDb($rowData); static $lastSku = null; @@ -656,9 +954,9 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity if (\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE == $this->getBehavior()) { return $rowData; } - if (self::SCOPE_DEFAULT == $this->getRowScope($rowData)) { - $lastSku = $rowData[self::COL_SKU]; - } + + $lastSku = $rowData[self::COL_SKU]; + if (isset($this->_oldSku[$lastSku])) { $newSku = $this->skuProcessor->getNewSku($lastSku); $rowData[self::COL_ATTR_SET] = $newSku['attr_set_code']; @@ -705,63 +1003,66 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity if (!$this->isRowAllowedToImport($rowData, $rowNum)) { continue; } - if (self::SCOPE_DEFAULT == $this->getRowScope($rowData)) { - $sku = $rowData[self::COL_SKU]; - } + + $sku = $rowData[self::COL_SKU]; + foreach ($this->_linkNameToId as $linkName => $linkId) { $productId = $this->skuProcessor->getNewSku($sku)['entity_id']; $productIds[] = $productId; if (isset($rowData[$linkName . 'sku'])) { - $linkedSku = $rowData[$linkName . 'sku']; - - if ((!is_null( - $this->skuProcessor->getNewSku($linkedSku) - ) || isset( - $this->_oldSku[$linkedSku] - )) && $linkedSku != $sku - ) { - $newSku = $this->skuProcessor->getNewSku($linkedSku); - if (!empty($newSku)) { - $linkedId = $newSku['entity_id']; - } else { - $linkedId = $this->_oldSku[$linkedSku]['entity_id']; - } + $linkSkus = explode($this->getMultipleValueSeparator(), $rowData[$linkName . 'sku']); + + foreach ($linkSkus as $linkedSku) { + $linkedSku = trim($linkedSku); + if ((!is_null( + $this->skuProcessor->getNewSku($linkedSku) + ) || isset( + $this->_oldSku[$linkedSku] + )) && $linkedSku != $sku + ) { + $newSku = $this->skuProcessor->getNewSku($linkedSku); + if (!empty($newSku)) { + $linkedId = $newSku['entity_id']; + } else { + $linkedId = $this->_oldSku[$linkedSku]['entity_id']; + } - if ($linkedId == null) { - // Import file links to a SKU which is skipped for some reason, which leads to a "NULL" - // link causing fatal errors. - $this->_logger->critical( - new \Exception( - sprintf( - 'WARNING: Orphaned link skipped: From SKU %s (ID %d) to SKU %s, ' . - 'Link type id: %d', - $sku, - $productId, - $linkedSku, - $linkId + if ($linkedId == null) { + // Import file links to a SKU which is skipped for some reason, which leads to a "NULL" + // link causing fatal errors. + $this->_logger->critical( + new \Exception( + sprintf( + 'WARNING: Orphaned link skipped: From SKU %s (ID %d) to SKU %s, ' . + 'Link type id: %d', + $sku, + $productId, + $linkedSku, + $linkId + ) ) - ) - ); - continue; - } + ); + continue; + } - $linkKey = "{$productId}-{$linkedId}-{$linkId}"; - - if (!isset($linkRows[$linkKey])) { - $linkRows[$linkKey] = [ - 'link_id' => $nextLinkId, - 'product_id' => $productId, - 'linked_product_id' => $linkedId, - 'link_type_id' => $linkId, - ]; - if (!empty($rowData[$linkName . 'position'])) { - $positionRows[] = [ + $linkKey = "{$productId}-{$linkedId}-{$linkId}"; + + if (!isset($linkRows[$linkKey])) { + $linkRows[$linkKey] = [ 'link_id' => $nextLinkId, - 'product_link_attribute_id' => $positionAttrId[$linkId], - 'value' => $rowData[$linkName . 'position'], + 'product_id' => $productId, + 'linked_product_id' => $linkedId, + 'link_type_id' => $linkId, ]; + if (!empty($rowData[$linkName . 'position'])) { + $positionRows[] = [ + 'link_id' => $nextLinkId, + 'product_link_attribute_id' => $positionAttrId[$linkId], + 'value' => $rowData[$linkName . 'position'], + ]; + } + $nextLinkId++; } - $nextLinkId++; } } } @@ -791,7 +1092,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity { foreach ($attributesData as $tableName => $skuData) { $tableData = []; - + $where = []; foreach ($skuData as $sku => $attributes) { $productId = $this->skuProcessor->getNewSku($sku)['entity_id']; @@ -809,19 +1110,25 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity we default to the default scope values. In this case, remove all the existing store based values stored in the table. */ - $where = $this->_connection->quoteInto( - 'store_id NOT IN (?)', - array_keys($storeValues) - ) . $this->_connection->quoteInto( - ' AND attribute_id = ?', - $attributeId - ) . $this->_connection->quoteInto( - ' AND entity_id = ?', - $productId - ); - $this->_connection->delete($tableName, $where); + $where[] = $this->_connection->quoteInto( + '(store_id NOT IN (?)', + array_keys($storeValues) + ) . $this->_connection->quoteInto( + ' AND attribute_id = ?', + $attributeId + ) . $this->_connection->quoteInto( + ' AND entity_id = ?)', + $productId + ); + if (count($where) >= self::ATTRIBUTE_DELETE_BUNCH) { + $this->_connection->delete($tableName, implode(' OR ', $where)); + $where = []; + } } } + if (!empty($where)) { + $this->_connection->delete($tableName, implode(' OR ', $where)); + } $this->_connection->insertOnDuplicate($tableName, $tableData, ['value']); } return $this; @@ -937,36 +1244,9 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity } $rowScope = $this->getRowScope($rowData); - if (self::SCOPE_DEFAULT == $rowScope) { - $rowSku = $rowData[self::COL_SKU]; + $rowSku = $rowData[self::COL_SKU]; - // 1. Entity phase - if (isset($this->_oldSku[$rowSku])) { - // existing row - $entityRowsUp[] = [ - 'updated_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), - 'entity_id' => $this->_oldSku[$rowSku]['entity_id'], - ]; - } else { - // new row - if (!$productLimit || $productsQty < $productLimit) { - $entityRowsIn[$rowSku] = [ - 'attribute_set_id' => $this->skuProcessor->getNewSku($rowSku)['attr_set_id'], - 'type_id' => $this->skuProcessor->getNewSku($rowSku)['type_id'], - 'sku' => $rowSku, - 'has_options' => isset($rowData['has_options']) ? $rowData['has_options'] : 0, - 'created_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), - 'updated_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), - ]; - $productsQty++; - } else { - $rowSku = null; - // sign for child rows to be skipped - $this->_rowsToSkip[$rowNum] = true; - continue; - } - } - } elseif (null === $rowSku) { + if (null === $rowSku) { $this->_rowsToSkip[$rowNum] = true; // skip rows when SKU is NULL continue; @@ -977,21 +1257,43 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity $rowData[self::COL_ATTR_SET] = $this->skuProcessor->getNewSku($rowSku)['attr_set_code']; } + // 1. Entity phase + if (isset($this->_oldSku[$rowSku])) { + // existing row + $entityRowsUp[] = [ + 'updated_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), + 'entity_id' => $this->_oldSku[$rowSku]['entity_id'], + ]; + } else { + if (!$productLimit || $productsQty < $productLimit) { + $entityRowsIn[$rowSku] = [ + 'attribute_set_id' => $this->skuProcessor->getNewSku($rowSku)['attr_set_id'], + 'type_id' => $this->skuProcessor->getNewSku($rowSku)['type_id'], + 'sku' => $rowSku, + 'has_options' => isset($rowData['has_options']) ? $rowData['has_options'] : 0, + 'created_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), + 'updated_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), + ]; + $productsQty++; + } else { + $rowSku = null; + // sign for child rows to be skipped + $this->_rowsToSkip[$rowNum] = true; + continue; + } + } + // 2. Product-to-Website phase - if (!empty($rowData['_product_websites'])) { - $websites[$rowSku][$this->storeResolver->getWebsiteCodeToId($rowData['_product_websites'])] = true; + if (!empty($rowData[self::COL_PRODUCT_WEBSITES])) { + $websites[$rowSku][$this->storeResolver->getWebsiteCodeToId($rowData[self::COL_PRODUCT_WEBSITES])] = true; } // 3. Categories phase - $categoryPath = empty($rowData[self::COL_CATEGORY]) ? '' : $rowData[self::COL_CATEGORY]; - if (!empty($rowData[self::COL_ROOT_CATEGORY])) { - $categoryId = $this->categoryProcessor->getCategoryWithRoot( - $rowData[self::COL_ROOT_CATEGORY], - $categoryPath - ); - $categories[$rowSku][$categoryId] = true; - } elseif (!empty($categoryPath)) { - $categories[$rowSku][$this->categoryProcessor->getCategory($categoryPath)] = true; + $categoriesString = empty($rowData[self::COL_CATEGORY]) ? '' : $rowData[self::COL_CATEGORY]; + if (!empty($categoriesString)) { + foreach ($this->categoryProcessor->upsertCategories($categoriesString) as $categoryId) { + $categories[$rowSku][$categoryId] = true; + } } // 4.1. Tier prices phase @@ -1020,22 +1322,54 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity } // 5. Media gallery phase + $mediaGalleryImages = array(); + $mediaGalleryLabels = array(); + if (!empty($rowData[self::COL_MEDIA_IMAGE])) { + $mediaGalleryImages = explode($this->getMultipleValueSeparator(), $rowData[self::COL_MEDIA_IMAGE]); + $mediaGalleryLabels = isset($rowData['_media_image_label']) ? explode($this->getMultipleValueSeparator(), $rowData['_media_image_label']) : array(); + if (count($mediaGalleryLabels) > count($mediaGalleryImages)) { + $mediaGalleryLabels = array_slice($mediaGalleryLabels, 0, count($mediaGalleryImages)); + } elseif (count($mediaGalleryLabels) < count($mediaGalleryImages)) { + $mediaGalleryLabels = array_pad($mediaGalleryLabels, count($mediaGalleryImages), ''); + } + } + foreach ($this->_imagesArrayKeys as $imageCol) { - if (!empty($rowData[$imageCol])) { - if (!array_key_exists($rowData[$imageCol], $uploadedGalleryFiles)) { - $uploadedGalleryFiles[$rowData[$imageCol]] = $this->_uploadMediaFiles($rowData[$imageCol]); - } + if (!empty($rowData[$imageCol]) && ($imageCol != self::COL_MEDIA_IMAGE) && !in_array($rowData[$imageCol], $mediaGalleryImages)) { + $mediaGalleryImages[] = $rowData[$imageCol]; + $mediaGalleryLabels[] = isset($rowData[$imageCol . '_label']) ? $rowData[$imageCol . '_label'] : ''; + } + } + + $rowData[self::COL_MEDIA_IMAGE] = array(); + + foreach ($mediaGalleryImages as $mediaImage) { + if (!array_key_exists($mediaImage, $uploadedGalleryFiles)) { + $uploadedGalleryFiles[$mediaImage] = $this->_uploadMediaFiles( + trim($mediaImage) + ); + } + $rowData[self::COL_MEDIA_IMAGE][] = $uploadedGalleryFiles[$mediaImage]; + } + + foreach ($this->_imagesArrayKeys as $imageCol) { + if (!empty($rowData[$imageCol]) && ($imageCol != self::COL_MEDIA_IMAGE)) { $rowData[$imageCol] = $uploadedGalleryFiles[$rowData[$imageCol]]; } } - if (!empty($rowData['_media_image'])) { - $mediaGallery[$rowSku][] = [ - 'attribute_id' => $rowData['_media_attribute_id'], - 'label' => $rowData['_media_label'], - 'position' => $rowData['_media_position'], - 'disabled' => $rowData['_media_is_disabled'], - 'value' => $rowData['_media_image'], - ]; + + if (!empty($rowData[self::COL_MEDIA_IMAGE]) && is_array($rowData[self::COL_MEDIA_IMAGE])) { + $position = 0; + + foreach($rowData[self::COL_MEDIA_IMAGE] as $media_image) { + $mediaGallery[$rowSku][] = [ + 'attribute_id' => $this->getMediaGalleryAttributeId(), + 'label' => isset($mediaGalleryLabels[$position]) ? $mediaGalleryLabels[$position] : '', + 'position' => $position++, + 'disabled' => '', + 'value' => $media_image, + ]; + } } // 6. Attributes phase @@ -1062,20 +1396,29 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity } } + $productTypeModel = $this->_productTypeModels[$productType]; + if (!empty($rowData['tax_class_name'])) { + $rowData['tax_class_id'] = $this->taxClassProcessor->upsertTaxClass($rowData['tax_class_name'], $productTypeModel); + } + if ($this->getBehavior() == \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND || empty($rowData[self::COL_SKU]) ) { - $rowData = $this->_productTypeModels[$productType]->clearEmptyData($rowData); + $rowData = $productTypeModel->clearEmptyData($rowData); } - $rowData = $this->_productTypeModels[$productType]->prepareAttributesWithDefaultValueForSave( + $rowData = $productTypeModel->prepareAttributesWithDefaultValueForSave( $rowData, !isset($this->_oldSku[$rowSku]) ); $product = $this->_proxyProdFactory->create(['data' => $rowData]); foreach ($rowData as $attrCode => $attrValue) { - $attribute = $resource->getAttribute($attrCode); + if (!isset($this->_attributeCache[$attrCode])) { + $this->_attributeCache[$attrCode] = $resource->getAttribute($attrCode); + } + $attribute = $this->_attributeCache[$attrCode]; + if ('multiselect' != $attribute->getFrontendInput() && self::SCOPE_NULL == $rowScope) { // skip attribute processing for SCOPE_NULL rows continue; @@ -1101,6 +1444,9 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity } elseif (self::SCOPE_STORE == $attribute->getIsGlobal()) { $storeIds = [$rowStore]; } + if (!isset($this->_oldSku[$rowSku])) { + $storeIds[] = 0; + } } foreach ($storeIds as $storeId) { if ('multiselect' == $attribute->getFrontendInput()) { @@ -1135,6 +1481,8 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity )->_saveProductAttributes( $attributes ); + + $this->_eventManager->dispatch('catalog_product_import_bunch_save_after', ['adapter' => $this, 'bunch' => $bunch]); } return $this; } @@ -1230,14 +1578,24 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity $this->_fileUploader->init(); - $tmpPath = $this->_mediaDirectory->getAbsolutePath('import'); + $dirConfig = DirectoryList::getDefaultConfig(); + $dirAddon = $dirConfig[DirectoryList::MEDIA][DirectoryList::PATH]; + + $DS = DIRECTORY_SEPARATOR; + + if (!empty($this->_parameters[\Magento\ImportExport\Model\Import::FIELD_NAME_IMG_FILE_DIR])) { + $tmpPath = $this->_parameters[\Magento\ImportExport\Model\Import::FIELD_NAME_IMG_FILE_DIR]; + } else { + $tmpPath = $dirAddon . $DS . $this->_mediaDirectory->getRelativePath('import'); + } + if (!$this->_fileUploader->setTmpDir($tmpPath)) { throw new \Magento\Framework\Exception\LocalizedException( __('File directory \'%1\' is not readable.', $tmpPath) ); } $destinationDir = "catalog/product"; - $destinationPath = $this->_mediaDirectory->getAbsolutePath($destinationDir); + $destinationPath = $dirAddon . $DS . $this->_mediaDirectory->getRelativePath($destinationDir); $this->_mediaDirectory->create($destinationDir); if (!$this->_fileUploader->setDestDir($destinationPath)) { @@ -1272,6 +1630,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity * @param array $mediaGalleryData * @return $this * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _saveMediaGallery(array $mediaGalleryData) { @@ -1294,9 +1653,11 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity 'catalog_product_entity_media_gallery_value' ); } - + $productIds = []; + $multiInsertData = []; foreach ($mediaGalleryData as $productSku => $mediaGalleryRows) { $productId = $this->skuProcessor->getNewSku($productSku)['entity_id']; + $productIds[] = $productId; $insertedGalleryImgs = []; if (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND != $this->getBehavior()) { @@ -1305,7 +1666,6 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity $this->_connection->quoteInto('entity_id IN (?)', $productId) ); } - foreach ($mediaGalleryRows as $insertValue) { if (!in_array($insertValue['value'], $insertedGalleryImgs)) { $valueArr = [ @@ -1313,49 +1673,58 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity 'entity_id' => $productId, 'value' => $insertValue['value'], ]; - - $this->_connection->insertOnDuplicate($mediaGalleryTableName, $valueArr, ['entity_id']); - + $multiInsertData[] = $valueArr; $insertedGalleryImgs[] = $insertValue['value']; } - - $newMediaValues = $this->_connection->fetchPairs( - $this->_connection->select()->from( - $mediaGalleryTableName, - ['value', 'value_id'] - )->where( - 'entity_id IN (?)', - $productId - ) - ); - - if (array_key_exists($insertValue['value'], $newMediaValues)) { - $insertValue['value_id'] = $newMediaValues[$insertValue['value']]; + } + } + $this->_connection->insertOnDuplicate($mediaGalleryTableName, $multiInsertData, ['entity_id']); + $multiInsertData = []; + $newMediaValues = $this->_connection->fetchAssoc( + $this->_connection->select()->from( + $mediaGalleryTableName, + ['value_id', 'value', 'entity_id'] + )->where( + 'entity_id IN (?)', + $productIds + ) + ); + foreach ($mediaGalleryData as $productSku => $mediaGalleryRows) { + foreach ($mediaGalleryRows as $insertValue) { + foreach ($newMediaValues as $value_id => $values) { + if ($values['value'] == $insertValue['value']) { + $insertValue['value_id'] = $value_id; + $insertValue['entity_id'] = $values['entity_id']; + unset($newMediaValues[$value_id]); + break; + } } - - $valueArr = [ - 'value_id' => $insertValue['value_id'], - 'store_id' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, - 'entity_id' => $productId, - 'label' => $insertValue['label'], - 'position' => $insertValue['position'], - 'disabled' => $insertValue['disabled'], - ]; - - try { - $this->_connection->insertOnDuplicate($mediaValueTableName, $valueArr, ['value_id']); - } catch (\Exception $e) { - $this->_connection->delete( - $mediaGalleryTableName, - $this->_connection->quoteInto('value_id IN (?)', $newMediaValues) - ); + if (isset($insertValue['value_id'])) { + $valueArr = [ + 'value_id' => $insertValue['value_id'], + 'store_id' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, + 'entity_id' => $insertValue['entity_id'], + 'label' => $insertValue['label'], + 'position' => $insertValue['position'], + 'disabled' => $insertValue['disabled'], + ]; + $multiInsertData[] = $valueArr; } } } + try { + $this->_connection->insertOnDuplicate($mediaValueTableName, $multiInsertData, ['value_id']); + } catch (\Exception $e) { + $this->_connection->delete( + $mediaGalleryTableName, + $this->_connection->quoteInto('value_id IN (?)', $newMediaValues) + ); + } return $this; } + /** * Save product websites. * @@ -1413,10 +1782,6 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity if (!$this->isRowAllowedToImport($rowData, $rowNum)) { continue; } - // only SCOPE_DEFAULT can contain stock data - if (self::SCOPE_DEFAULT != $this->getRowScope($rowData)) { - continue; - } $row = []; $row['product_id'] = $this->skuProcessor->getNewSku($rowData[self::COL_SKU])['entity_id']; @@ -1533,11 +1898,11 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity */ public function getRowScope(array $rowData) { - if (!empty($rowData[self::COL_SKU]) && strlen(trim($rowData[self::COL_SKU]))) { - return self::SCOPE_DEFAULT; + if (empty($rowData[self::COL_SKU])) { + return self::SCOPE_NULL; } if (empty($rowData[self::COL_STORE])) { - return self::SCOPE_NULL; + return self::SCOPE_DEFAULT; } return self::SCOPE_STORE; } @@ -1562,10 +1927,6 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity } $this->_validatedRows[$rowNum] = true; - if (!is_null($this->skuProcessor->getNewSku($rowData[self::COL_SKU]))) { - $this->addRowError(ValidatorInterface::ERROR_DUPLICATE_SKU, $rowNum); - return false; - } $rowScope = $this->getRowScope($rowData); // BEHAVIOR_DELETE use specific validation logic @@ -1583,68 +1944,68 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity } } - if (self::SCOPE_DEFAULT == $rowScope) { - // SKU is specified, row is SCOPE_DEFAULT, new product block begins - $this->_processedEntitiesCount++; - - $sku = $rowData[self::COL_SKU]; - - if (isset($this->_oldSku[$sku])) { - // can we get all necessary data from existent DB product? - // check for supported type of existing product - if (isset($this->_productTypeModels[$this->_oldSku[$sku]['type_id']])) { - $this->skuProcessor->addNewSku( - $sku, - [ - 'entity_id' => $this->_oldSku[$sku]['entity_id'], - 'type_id' => $this->_oldSku[$sku]['type_id'], - 'attr_set_id' => $this->_oldSku[$sku]['attr_set_id'], - 'attr_set_code' => $this->_attrSetIdToName[$this->_oldSku[$sku]['attr_set_id']], - ] - ); - } else { - $this->addRowError(ValidatorInterface::ERROR_TYPE_UNSUPPORTED, $rowNum); - // child rows of legacy products with unsupported types are orphans - $sku = false; - } + $sku = $rowData[self::COL_SKU]; + if (null === $sku) { + $this->addRowError(ValidatorInterface::ERROR_SKU_IS_EMPTY, $rowNum); + } elseif (false === $sku) { + $this->addRowError(ValidatorInterface::ERROR_ROW_IS_ORPHAN, $rowNum); + } elseif (self::SCOPE_STORE == $rowScope + && !$this->storeResolver->getStoreCodeToId($rowData[self::COL_STORE]) + ) { + $this->addRowError(ValidatorInterface::ERROR_INVALID_STORE, $rowNum); + } + + // SKU is specified, row is SCOPE_DEFAULT, new product block begins + $this->_processedEntitiesCount++; + + $sku = $rowData[self::COL_SKU]; + + if (isset($this->_oldSku[$sku])) { + // can we get all necessary data from existent DB product? + // check for supported type of existing product + if (isset($this->_productTypeModels[$this->_oldSku[$sku]['type_id']])) { + $this->skuProcessor->addNewSku( + $sku, + [ + 'entity_id' => $this->_oldSku[$sku]['entity_id'], + 'type_id' => $this->_oldSku[$sku]['type_id'], + 'attr_set_id' => $this->_oldSku[$sku]['attr_set_id'], + 'attr_set_code' => $this->_attrSetIdToName[$this->_oldSku[$sku]['attr_set_id']], + ] + ); } else { - // validate new product type and attribute set - if (!isset($rowData[self::COL_TYPE]) || !isset($this->_productTypeModels[$rowData[self::COL_TYPE]])) { - $this->addRowError(ValidatorInterface::ERROR_INVALID_TYPE, $rowNum); - } elseif (!isset( - $rowData[self::COL_ATTR_SET] - ) || !isset( - $this->_attrSetNameToId[$rowData[self::COL_ATTR_SET]] - ) - ) { - $this->addRowError(ValidatorInterface::ERROR_INVALID_ATTR_SET, $rowNum); - } elseif (is_null($this->skuProcessor->getNewSku($sku))) { - $this->skuProcessor->addNewSku( - $sku, - [ - 'entity_id' => null, - 'type_id' => $rowData[self::COL_TYPE], - 'attr_set_id' => $this->_attrSetNameToId[$rowData[self::COL_ATTR_SET]], - 'attr_set_code' => $rowData[self::COL_ATTR_SET], - ] - ); - } - if (isset($this->_invalidRows[$rowNum])) { - // mark SCOPE_DEFAULT row as invalid for future child rows if product not in DB already - $sku = false; - } + $this->addRowError(ValidatorInterface::ERROR_TYPE_UNSUPPORTED, $rowNum); + // child rows of legacy products with unsupported types are orphans + $sku = false; } } else { - if (null === $sku) { - $this->addRowError(ValidatorInterface::ERROR_SKU_IS_EMPTY, $rowNum); - } elseif (false === $sku) { - $this->addRowError(ValidatorInterface::ERROR_ROW_IS_ORPHAN, $rowNum); - } elseif (self::SCOPE_STORE == $rowScope - && !$this->storeResolver->getStoreCodeToId($rowData[self::COL_STORE]) + // validate new product type and attribute set + if (!isset($rowData[self::COL_TYPE]) || !isset($this->_productTypeModels[$rowData[self::COL_TYPE]])) { + $this->addRowError(ValidatorInterface::ERROR_INVALID_TYPE, $rowNum); + } elseif (!isset( + $rowData[self::COL_ATTR_SET] + ) || !isset( + $this->_attrSetNameToId[$rowData[self::COL_ATTR_SET]] + ) ) { - $this->addRowError(ValidatorInterface::ERROR_INVALID_STORE, $rowNum); + $this->addRowError(ValidatorInterface::ERROR_INVALID_ATTR_SET, $rowNum); + } elseif (is_null($this->skuProcessor->getNewSku($sku))) { + $this->skuProcessor->addNewSku( + $sku, + [ + 'entity_id' => null, + 'type_id' => $rowData[self::COL_TYPE], + 'attr_set_id' => $this->_attrSetNameToId[$rowData[self::COL_ATTR_SET]], + 'attr_set_code' => $rowData[self::COL_ATTR_SET], + ] + ); + } + if (isset($this->_invalidRows[$rowNum])) { + // mark SCOPE_DEFAULT row as invalid for future child rows if product not in DB already + $sku = false; } } + if (!isset($this->_invalidRows[$rowNum])) { $newSku = $this->skuProcessor->getNewSku($sku); // set attribute set code into row data for followed attribute validation in type model @@ -1666,6 +2027,76 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity return !isset($this->_invalidRows[$rowNum]); } + /** + * Parse attributes names and values string to array. + * + * @param array $rowData + * + * @return array + */ + private function _parseAdditionalAttributes($rowData) + { + if (empty($rowData['additional_attributes'])) { + return $rowData; + } + + $attributeNameValuePairs = explode($this->getMultipleValueSeparator(), $rowData['additional_attributes']); + foreach ($attributeNameValuePairs as $attributeNameValuePair) { + $nameAndValue = explode(self::PAIR_NAME_VALUE_SEPARATOR, $attributeNameValuePair); + if (!empty($nameAndValue)) { + $rowData[$nameAndValue[0]] = isset($nameAndValue[1]) ? $nameAndValue[1] : ''; + } + } + return $rowData; + } + + /** + * Set values in use_config_ fields. + * + * @param array $rowData + * + * @return array + */ + private function _setStockUseConfigFieldsValues($rowData) + { + $useConfigFields = array(); + foreach ($rowData as $key => $value) { + if (isset($this->defaultStockData[$key]) && isset($this->defaultStockData[self::INVENTORY_USE_CONFIG_PREFIX . $key]) && !empty($value)) { + $useConfigFields[self::INVENTORY_USE_CONFIG_PREFIX . $key] = ($value == self::INVENTORY_USE_CONFIG) ? 1 : 0; + } + } + $rowData = array_merge($rowData, $useConfigFields); + return $rowData; + } + + /** + * Custom fields mapping for changed purposes of fields and field names. + * + * @param array $rowData + * + * @return array + */ + private function _customFieldsMapping($rowData) + { + foreach ($this->_fieldsMap as $systemFieldName => $fileFieldName) { + if (isset($rowData[$fileFieldName])) { + $rowData[$systemFieldName] = $rowData[$fileFieldName]; + } + } + + $rowData = $this->_parseAdditionalAttributes($rowData); + + $rowData = $this->_setStockUseConfigFieldsValues($rowData); + if (isset($rowData['status'])) { + if (($rowData['status'] == \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) || $rowData['status'] == 'yes') { + $rowData['status'] = \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED; + } else { + $rowData['status'] = \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED; + } + } + return $rowData; + } + /** * Validate data rows and save bunches to DB * @@ -1681,6 +2112,9 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity return $this; } $rowData = $source->current(); + + $rowData = $this->_customFieldsMapping($rowData); + $this->validateRow($rowData, $source->key()); $this->_processedRowsCount++; $source->next(); @@ -1692,23 +2126,42 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity /** * Get array of affected products * - * @return int[] + * @return array */ - public function getAffectedEntityIds() + public function getAffectedProducts() { - $productIds = []; + $products = []; while ($bunch = $this->_dataSourceModel->getNextBunch()) { foreach ($bunch as $rowNum => $rowData) { if (!$this->isRowAllowedToImport($rowData, $rowNum)) { continue; } - $newSku = $this->skuProcessor->getNewSku($rowData[self::COL_SKU]); - if (empty($newSku) || !isset($newSku['entity_id'])) { - continue; + if ($product = $this->_populateToUrlGeneration($rowData)) { + $products[] = $product; } - $productIds[] = $newSku['entity_id']; } } - return $productIds; + return $products; + } + + /** + * Create product model from imported data for URL rewrite purposes. + * + * @param $rowData + * + * @return \Magento\Framework\Model\AbstractModel|void + * + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function _populateToUrlGeneration($rowData) + { + $product = $this->catalogProductFactory->create(); + $newSku = $this->skuProcessor->getNewSku($rowData[self::COL_SKU]); + if (empty($newSku) || !isset($newSku['entity_id'])) { + return; + } + $rowData['entity_id'] = $newSku['entity_id']; + $product->addData($rowData); + return $product; } } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php index cb80769ab0110d233a4c4ae691e8ca63e7b53c94..a5c582de7247e6db7298b9d1e01a7d8b6a1582db 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php @@ -7,6 +7,16 @@ namespace Magento\CatalogImportExport\Model\Import\Product; class CategoryProcessor { + /** + * Delimiter in import file between categories. + */ + const DELIMITER_CATEGORIES = '|'; + + /** + * Delimiter in category path. + */ + const DELIMITER_CATEGORY = '/'; + /** * @var \Magento\Catalog\Model\Resource\Category\CollectionFactory */ @@ -20,19 +30,23 @@ class CategoryProcessor protected $categories = []; /** - * Categories text-path to ID hash with roots checking. + * Instance of catalog category factory. * - * @var array + * @var \Magento\Catalog\Model\CategoryFactory */ - protected $categoriesWithRoots = []; + protected $categoryFactory; /** * @param \Magento\Catalog\Model\Resource\Category\CollectionFactory $categoryColFactory + * @param \Magento\Catalog\Model\CategoryFactory $categoryFactory */ public function __construct( - \Magento\Catalog\Model\Resource\Category\CollectionFactory $categoryColFactory + \Magento\Catalog\Model\Resource\Category\CollectionFactory $categoryColFactory, + \Magento\Catalog\Model\CategoryFactory $categoryFactory ) { $this->categoryColFactory = $categoryColFactory; + $this->categoryFactory = $categoryFactory; + $this->initCategories(); } /** @@ -40,26 +54,20 @@ class CategoryProcessor */ protected function initCategories() { - if (empty($this->categories) && empty($this->categoriesWithRoots)) { - $collection = $this->categoryColFactory->create()->addNameToResult(); + if (empty($this->categories)) { + $collection = $this->categoryColFactory->create(); + $collection->addNameToResult(); /* @var $collection \Magento\Catalog\Model\Resource\Category\Collection */ foreach ($collection as $category) { - $structure = explode('/', $category->getPath()); + $structure = explode(self::DELIMITER_CATEGORY, $category->getPath()); $pathSize = count($structure); if ($pathSize > 1) { $path = []; for ($i = 1; $i < $pathSize; $i++) { - $path[] = $collection->getItemById($structure[$i])->getName(); - } - $rootCategoryName = array_shift($path); - if (!isset($this->categoriesWithRoots[$rootCategoryName])) { - $this->categoriesWithRoots[$rootCategoryName] = []; - } - $index = implode('/', $path); - $this->categoriesWithRoots[$rootCategoryName][$index] = $category->getId(); - if ($pathSize > 2) { - $this->categories[$index] = $category->getId(); + $path[] = $collection->getItemById((int)$structure[$i])->getName(); } + $index = implode(self::DELIMITER_CATEGORY, $path); + $this->categories[$index] = $category->getId(); } } } @@ -67,27 +75,73 @@ class CategoryProcessor } /** - * @param string $root - * @param null|string $index - * @return mixed + * Creates a category. + * + * @param string $name + * @param int $parentId + * + * @return int */ - public function getCategoryWithRoot($root, $index = null) + protected function createCategory($name, $parentId) { - $this->initCategories(); - $returnVal = isset($this->categoriesWithRoots[$root]) ? $this->categoriesWithRoots[$root] : null; - if (empty($returnVal) || $index === null) { - return $returnVal; + /** @var \Magento\Catalog\Model\Category $category */ + $category = $this->categoryFactory->create(); + $parentCategory = $this->categoryFactory->create()->load($parentId); + $category->setPath($parentCategory->getPath()); + $category->setParentId($parentId); + $category->setName($name); + $category->setIsActive(true); + $category->setIncludeInMenu(true); + $category->setAttributeSetId($category->getDefaultAttributeSetId()); + $category->save(); + + return $category->getId(); + } + + + /** + * Returns ID of category by string path creating nonexistent ones. + * + * @param string $categoryPath + * + * @return int + */ + protected function upsertCategory($categoryPath) + { + if (!isset($this->categories[$categoryPath])) { + $pathParts = explode(self::DELIMITER_CATEGORY, $categoryPath); + $parentId = \Magento\Catalog\Model\Category::TREE_ROOT_ID; + $path = ''; + + foreach ($pathParts as $pathPart) { + $path .= $pathPart; + if (!isset($this->categories[$path])) { + $this->categories[$path] = $this->createCategory($pathPart, $parentId); + } + $parentId = $this->categories[$path]; + $path .= self::DELIMITER_CATEGORY; + } } - return isset($returnVal[$index]) ? $returnVal[$index] : null; + + return $this->categories[$categoryPath]; } /** - * @param string $index - * @return null|string + * Returns IDs of categories by string path creating nonexistent ones. + * + * @param string $categoriesString + * + * @return array */ - public function getCategory($index) + public function upsertCategories($categoriesString) { - $this->initCategories(); - return isset($this->categories[$index]) ? $this->categories[$index] : null; + $categoriesIds = []; + $categories = explode(self::DELIMITER_CATEGORIES, $categoriesString); + + foreach ($categories as $category) { + $categoriesIds[] = $this->upsertCategory($category); + } + + return $categoriesIds; } } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php index 1f0e83871d4f29837b390a0b992f1756134f55de..14c1e38ade3b17ffa07f25691eedd4d9590aa9d4 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php @@ -8,6 +8,8 @@ namespace Magento\CatalogImportExport\Model\Import\Product; +use Magento\CatalogImportExport\Model\Import\Product; + /** * Entity class which provide possibility to import product custom options * @@ -502,7 +504,6 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity if (!$this->_oldCustomOptions) { $oldCustomOptions = []; $optionTitleTable = $this->_tables['catalog_product_option_title']; - $productIds = array_values($this->_productsSkuToId); foreach ($this->_storeCodeToId as $storeId) { $addCustomOptions = function ( \Magento\Catalog\Model\Product\Option $customOption @@ -526,7 +527,6 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity }; /** @var $collection \Magento\Catalog\Model\Resource\Product\Option\Collection */ $this->_optionCollection->reset(); - $this->_optionCollection->addProductToFilter($productIds); $this->_optionCollection->getSelect()->join( ['option_title' => $optionTitleTable], 'option_title.option_id = main_table.option_id', @@ -888,19 +888,27 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity } $this->_validatedRows[$rowNumber] = true; - if ($this->_isRowWithCustomOption($rowData)) { - if ($this->_isMainOptionRow($rowData)) { - if (!$this->_validateMainRow($rowData, $rowNumber)) { - return false; + $multiRowData = $this->_getMultiRowFormat($rowData); + + foreach ($multiRowData as $optionData) { + + $combinedData = array_merge($rowData, $optionData); + + if ($this->_isRowWithCustomOption($combinedData)) { + if ($this->_isMainOptionRow($combinedData)) { + if (!$this->_validateMainRow($combinedData, $rowNumber)) { + return false; + } } - } - if ($this->_isSecondaryOptionRow($rowData)) { - if (!$this->_validateSecondaryRow($rowData, $rowNumber)) { - return false; + if ($this->_isSecondaryOptionRow($combinedData)) { + if (!$this->_validateSecondaryRow($combinedData, $rowNumber)) { + return false; + } } + return true; } - return true; } + return false; } @@ -1015,10 +1023,59 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity } } + /** + * Get multiRow format from one line data. + * + * @param array $rowData + * + * @return array + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function _getMultiRowFormat($rowData) + { + // Parse custom options. + $rowData = $this->_parseCustomOptions($rowData); + $multiRow = array(); + if (empty($rowData['custom_options'])) { + return $multiRow; + } + + $i = 0; + + foreach ($rowData['custom_options'] as $name => $customOption) { + $i++; + foreach ($customOption as $rowOrder => $optionRow) { + $row = array( + self::COLUMN_STORE => '', + self::COLUMN_TYPE => $name ? $optionRow['type'] : '', + self::COLUMN_TITLE => $name, + self::COLUMN_IS_REQUIRED => $optionRow['required'], + self::COLUMN_SORT_ORDER => $i, + self::COLUMN_ROW_TITLE => isset($optionRow['option_title']) ? $optionRow['option_title'] : '', + self::COLUMN_ROW_SKU => $optionRow['sku'], + self::COLUMN_ROW_SORT => $rowOrder, + self::COLUMN_PREFIX . 'sku' => $optionRow['sku'] + ); + + $percent_suffix = isset($optionRow['price_type']) && ($optionRow['price_type'] == 'percent') ? '%' : ''; + $row[self::COLUMN_ROW_PRICE] = isset($optionRow['price']) ? $optionRow['price'] . $percent_suffix : ''; + $row[self::COLUMN_PREFIX . 'price'] = $row[self::COLUMN_ROW_PRICE]; + + $name = ''; + + $multiRow[] = $row; + } + + } + + return $multiRow; + } + /** * Import data rows * * @return boolean + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function _importData() { @@ -1042,33 +1099,41 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity $childCount = []; foreach ($bunch as $rowNumber => $rowData) { - if (!$this->isRowAllowedToImport($rowData, $rowNumber)) { - continue; - } - if (!$this->_parseRequiredData($rowData)) { - continue; - } - $optionData = $this->_collectOptionMainData( - $rowData, - $prevOptionId, - $nextOptionId, - $products, - $prices - ); - if ($optionData != null) { - $options[] = $optionData; + + $multiRowData = $this->_getMultiRowFormat($rowData); + + foreach ($multiRowData as $optionData) { + + $combinedData = array_merge($rowData, $optionData); + + if (!$this->isRowAllowedToImport($combinedData, $rowNumber)) { + continue; + } + if (!$this->_parseRequiredData($combinedData)) { + continue; + } + $optionData = $this->_collectOptionMainData( + $combinedData, + $prevOptionId, + $nextOptionId, + $products, + $prices + ); + if ($optionData != null) { + $options[] = $optionData; + } + $this->_collectOptionTypeData( + $combinedData, + $prevOptionId, + $nextValueId, + $typeValues, + $typePrices, + $typeTitles, + $parentCount, + $childCount + ); + $this->_collectOptionTitle($combinedData, $prevOptionId, $titles); } - $this->_collectOptionTypeData( - $rowData, - $prevOptionId, - $nextValueId, - $typeValues, - $typePrices, - $typeTitles, - $parentCount, - $childCount - ); - $this->_collectOptionTitle($rowData, $prevOptionId, $titles); } // Save prepared custom options data !!! @@ -1080,6 +1145,7 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity if ($this->getBehavior() == \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND) { $this->_compareOptionsWithExisting($options, $titles, $prices, $typeValues); } + $this->_saveOptions( $options )->_saveTitles( @@ -1658,4 +1724,59 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity return $this; } + + /** + * Parse custom options string to inner format. + * + * @param array $rowData + * @return array + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + protected function _parseCustomOptions($rowData) + { + $beforeOptionValueSkuDelimiter = ';'; + if (empty($rowData['custom_options'])) { + return $rowData; + } + $rowData['custom_options'] = str_replace($beforeOptionValueSkuDelimiter, $this->_productEntity->getMultipleValueSeparator(), $rowData['custom_options']); + $options = array(); + $optionValues = explode(Product::PSEUDO_MULTI_LINE_SEPARATOR, $rowData['custom_options']); + $k = 0; + $name = ''; + foreach ($optionValues as $optionValue) { + $optionValueParams = explode($this->_productEntity->getMultipleValueSeparator(), $optionValue); + foreach ($optionValueParams as $nameAndValue) { + $nameAndValue = explode('=', $nameAndValue); + if (!empty($nameAndValue)) { + $value = isset($nameAndValue[1]) ? $nameAndValue[1] : ''; + $value = trim($value); + $fieldName = trim($nameAndValue[0]); + if ($value && ($fieldName == 'name')) { + if ($name != $value) { + $name = $value; + $k = 0; + } + } + if ($name) { + $options[$name][$k][$fieldName] = $value; + } + } + } + $options[$name][$k]['_custom_option_store'] = $rowData[Product::COL_STORE_VIEW_CODE]; + $k++; + } + $rowData['custom_options'] = $options; + return $rowData; + } + + /** + * Clear product sku to id array. + * + * @return $this + */ + public function clearProductsSkuToId() + { + $this->_productsSkuToId = null; + return $this; + } } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/SkuProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/SkuProcessor.php index 42f103ed712c9791f3471c6592579e2c8affda22..4f63a08de880fd4a690e16cd7fa19987da4dcfa2 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/SkuProcessor.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/SkuProcessor.php @@ -55,26 +55,30 @@ class SkuProcessor } /** + * Get old skus array. + * * @return array */ public function getOldSkus() { if (!$this->oldSkus) { - $columns = ['entity_id', 'type_id', 'attribute_set_id', 'sku']; - foreach ($this->productFactory->create()->getProductEntitiesInfo($columns) as $info) { - $typeId = $info['type_id']; - $sku = $info['sku']; - $this->oldSkus[$sku] = [ - 'type_id' => $typeId, - 'attr_set_id' => $info['attribute_set_id'], - 'entity_id' => $info['entity_id'], - 'supported_type' => isset($this->productTypeModels[$typeId]), - ]; - } + $this->oldSkus = $this->_getSkus(); } return $this->oldSkus; } + /** + * Reload old skus. + * + * @return $this + */ + public function reloadOldSkus() + { + $this->oldSkus = $this->_getSkus(); + + return $this; + } + /** * @param string $sku * @param array $data @@ -111,4 +115,26 @@ class SkuProcessor } return $this->newSkus; } + + /** + * Get skus data. + * + * @return array + */ + protected function _getSkus() + { + $oldSkus = []; + $columns = ['entity_id', 'type_id', 'attribute_set_id', 'sku']; + foreach ($this->productFactory->create()->getProductEntitiesInfo($columns) as $info) { + $typeId = $info['type_id']; + $sku = $info['sku']; + $oldSkus[$sku] = [ + 'type_id' => $typeId, + 'attr_set_id' => $info['attribute_set_id'], + 'entity_id' => $info['entity_id'], + 'supported_type' => isset($this->productTypeModels[$typeId]), + ]; + } + return $oldSkus; + } } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/StoreResolver.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/StoreResolver.php index af478e82e4c3f9786d8ea72fcded969a083bd76d..c61c0a5f24c44cebfbb06ae97e9fc872a236ebbb 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/StoreResolver.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/StoreResolver.php @@ -8,6 +8,8 @@ namespace Magento\CatalogImportExport\Model\Import\Product; class StoreResolver { /** + * Store manager instance. + * * @var \Magento\Store\Model\StoreManagerInterface */ protected $storeManager; diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/TaxClassProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/TaxClassProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..3326e7d6d82ebfa314916894119f63fe35d7de62 --- /dev/null +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/TaxClassProcessor.php @@ -0,0 +1,107 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogImportExport\Model\Import\Product; + +use Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType; +use Magento\Tax\Model\ClassModel; + +class TaxClassProcessor +{ + /** + * Tax attribute code. + */ + const ATRR_CODE = 'tax_class_id'; + + /** + * Tax classes. + * + * @var array + */ + protected $taxClasses; + + /** + * Instance of tax class collection factory. + * + * @var \Magento\Tax\Model\Resource\TaxClass\CollectionFactory + */ + protected $collectionFactory; + + /** + * Instance of tax model factory. + * + * @var \Magento\Tax\Model\ClassModelFactory + */ + protected $classModelFactory; + + /** + * @param \Magento\Tax\Model\Resource\TaxClass\CollectionFactory $collectionFactory + * @param \Magento\Tax\Model\ClassModelFactory $classModelFactory + */ + public function __construct( + \Magento\Tax\Model\Resource\TaxClass\CollectionFactory $collectionFactory, + \Magento\Tax\Model\ClassModelFactory $classModelFactory + ) { + $this->collectionFactory = $collectionFactory; + $this->classModelFactory = $classModelFactory; + $this->initTaxClasses(); + } + + /** + * Initiate tax classes. + * + * @return $this + */ + protected function initTaxClasses() + { + if (empty($this->taxClasses)) { + $collection = $this->collectionFactory->create(); + $collection->addFieldToFilter('class_type', ClassModel::TAX_CLASS_TYPE_PRODUCT); + /* @var $collection \Magento\Tax\Model\Resource\TaxClass\Collection */ + foreach ($collection as $taxClass) { + $this->taxClasses[$taxClass->getClassName()] = $taxClass->getId(); + } + } + return $this; + } + + /** + * Creates new tax class. + * + * @param string $taxClassName + * @param AbstractType $productTypeModel + * @return integer + */ + protected function createTaxClass($taxClassName, AbstractType $productTypeModel) + { + /** @var \Magento\Tax\Model\ClassModelFactory $taxClass */ + $taxClass = $this->classModelFactory->create(); + $taxClass->setClassType(ClassModel::TAX_CLASS_TYPE_PRODUCT); + $taxClass->setClassName($taxClassName); + $taxClass->save(); + + $id = $taxClass->getId(); + + $productTypeModel->addAttributeOption(self::ATRR_CODE, $id, $id); + + return $id; + } + + /** + * Instantiate instance of tax class. + * + * @param string $taxClassName + * @param AbstractType $productTypeModel + * @return object + */ + public function upsertTaxClass($taxClassName, AbstractType $productTypeModel) + { + if (!isset($this->taxClasses[$taxClassName])) { + $this->taxClasses[$taxClassName] = $this->createTaxClass($taxClassName, $productTypeModel); + } + + return $this->taxClasses[$taxClassName]; + } +} diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php old mode 100644 new mode 100755 index 36ee69ed7d7189ab2644878e9739acfb1c1af4ec..cd1eb38139c05433098c3a17edc6f234f656a7a6 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php @@ -5,8 +5,6 @@ */ namespace Magento\CatalogImportExport\Model\Import\Product\Type; -use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface; - /** * Import entity abstract product type model * @@ -59,6 +57,13 @@ abstract class AbstractType */ protected $_specialAttributes = []; + /** + * Custom entity type fields mapping. + * + * @var string[] + */ + protected $_customFieldsMapping = []; + /** * Product entity object. * @@ -196,6 +201,26 @@ abstract class AbstractType return $this; } + /** + * In case we've dynamically added new attribute option during import we need + * to add it to our cache in order to keep it up to date. + * + * @param string $code + * @param string $optionKey + * @param string $optionValue + * + * @return $this + */ + public function addAttributeOption($code, $optionKey, $optionValue) + { + foreach ($this->_attributes as $attrSetName => $attrSetValue) { + if (isset($attrSetValue[$code])) { + $this->_attributes[$attrSetName][$code]['options'][$optionKey] = $optionValue; + } + } + return $this; + } + /** * Have we check attribute for is_required? Used as last chance to disable this type of check. * @@ -242,6 +267,16 @@ abstract class AbstractType return $this->_specialAttributes; } + /** + * Return entity custom Fields mapping. + * + * @return string[] + */ + public function getCustomFieldsMapping() + { + return $this->_customFieldsMapping; + } + /** * Validate row attributes. Pass VALID row data ONLY as argument. * @@ -272,7 +307,9 @@ abstract class AbstractType )) ) { $this->_entityModel->addRowError( - RowValidatorInterface::ERROR_VALUE_IS_REQUIRED, + // @codingStandardsIgnoreStart + \Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface::ERROR_VALUE_IS_REQUIRED, + // @codingStandardsIgnoreEnd $rowNum, $attrCode ); diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Simple.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Simple.php index ae7fe1e06d1456c6d2afe32a5e581e91e06983f6..64800b676a69a47015d08963f0b7ceaf3f85b1dc 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Simple.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Simple.php @@ -22,5 +22,8 @@ class Simple extends \Magento\CatalogImportExport\Model\Import\Product\Type\Abst 'related_tgtr_position_limit', 'upsell_tgtr_position_behavior', 'upsell_tgtr_position_limit', + 'thumbnail_label', + 'small_image_label', + 'image_label', ]; } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Category.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Category.php deleted file mode 100644 index cbfb96ba47539586e25062356036771f0dc18498..0000000000000000000000000000000000000000 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Category.php +++ /dev/null @@ -1,63 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\CatalogImportExport\Model\Import\Product\Validator; - -use Magento\Framework\Validator\AbstractValidator; -use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface; -use Magento\CatalogImportExport\Model\Import\Product; - -class Category extends AbstractValidator implements RowValidatorInterface -{ - /** - * @var \Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor - */ - protected $categoryProcessor; - - /** - * @param Product\CategoryProcessor $categoryProcessor - */ - public function __construct( - \Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor $categoryProcessor - ) { - $this->categoryProcessor = $categoryProcessor; - } - - /** - * {@inheritdoc} - */ - public function init() - { - return $this; - } - - /** - * {@inheritdoc} - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function isValid($value) - { - $this->_clearMessages(); - $emptyCategory = empty($value[Product::COL_CATEGORY]); - $emptyRootCategory = empty($value[Product::COL_ROOT_CATEGORY]); - $hasCategory = $emptyCategory - ? false - : $this->categoryProcessor->getCategory($value[Product::COL_CATEGORY]) !== null; - $category = $emptyRootCategory - ? null - : $this->categoryProcessor->getCategoryWithRoot($value[Product::COL_ROOT_CATEGORY]); - if (!$emptyCategory && !$hasCategory || !$emptyRootCategory && !isset( - $category - ) || !$emptyRootCategory && !$emptyCategory && !isset( - $category[$value[Product::COL_CATEGORY]] - ) - ) { - $this->_addMessages([self::ERROR_INVALID_CATEGORY]); - return false; - } - return true; - } -} diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Media.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Media.php index 076477d1d4d7b6b2cb388d35d5b1c7df8763b8cb..fd3b69e0ac5a79c00d01502c1638878dadd5e910 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Media.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Media.php @@ -24,10 +24,6 @@ class Media extends AbstractValidator implements RowValidatorInterface public function isValid($value) { $this->_clearMessages(); - if (!empty($value['_media_image']) && empty($value['_media_attribute_id'])) { - $this->_addMessages([self::ERROR_MEDIA_DATA_INCOMPLETE]); - return false; - } return true; } } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index fb61cb45feadbad14fc9ec39cda0e10ecbeff880..d694b7720237f590ec31b5bd06dbbb7c09852966 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -6,6 +6,7 @@ namespace Magento\CatalogImportExport\Model\Import; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Filesystem\DriverPool; /** * Import entity product model @@ -15,16 +16,22 @@ use Magento\Framework\App\Filesystem\DirectoryList; class Uploader extends \Magento\MediaStorage\Model\File\Uploader { /** + * Temp directory. + * * @var string */ protected $_tmpDir = ''; /** + * Destination directory. + * * @var string */ protected $_destDir = ''; /** + * All mime types. + * * @var array */ protected $_allowedMimeTypes = [ @@ -37,22 +44,56 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader const DEFAULT_FILE_TYPE = 'application/octet-stream'; /** + * Image factory. + * * @var \Magento\Framework\Image\AdapterFactory */ protected $_imageFactory; /** + * Validator. + * * @var \Magento\MediaStorage\Model\File\Validator\NotProtectedExtension */ protected $_validator; + /** + * Instance of filesystem directory write interface. + * + * @var \Magento\Framework\Filesystem\Directory\WriteInterface + */ + protected $_directory; + + /** + * Instance of filesystem read factory. + * + * @var \Magento\Framework\Filesystem\File\ReadFactory + */ + protected $_readFactory; + + /** + * Instance of media file storage database. + * + * @var \Magento\MediaStorage\Helper\File\Storage\Database + */ + protected $_coreFileStorageDb; + + /** + * Instance of media file storage. + * + * @var \Magento\MediaStorage\Helper\File\Storage + */ + protected $_coreFileStorage; + /** * @param \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDb * @param \Magento\MediaStorage\Helper\File\Storage $coreFileStorage * @param \Magento\Framework\Image\AdapterFactory $imageFactory * @param \Magento\MediaStorage\Model\File\Validator\NotProtectedExtension $validator * @param \Magento\Framework\Filesystem $filesystem - * @param string $filePath + * @param \Magento\Framework\Filesystem\File\ReadFactory $readFactory + * @param null $filePath + * @throws \Magento\Framework\Exception\LocalizedException */ public function __construct( \Magento\MediaStorage\Helper\File\Storage\Database $coreFileStorageDb, @@ -60,6 +101,7 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader \Magento\Framework\Image\AdapterFactory $imageFactory, \Magento\MediaStorage\Model\File\Validator\NotProtectedExtension $validator, \Magento\Framework\Filesystem $filesystem, + \Magento\Framework\Filesystem\File\ReadFactory $readFactory, $filePath = null ) { if ($filePath !== null) { @@ -70,10 +112,11 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader $this->_coreFileStorage = $coreFileStorage; $this->_validator = $validator; $this->_directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT); + $this->_readFactory = $readFactory; } /** - * Initiate uploader defoult settings + * Initiate uploader default settings * * @return void */ @@ -96,6 +139,16 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader */ public function move($fileName) { + if (preg_match('/\bhttps?:\/\//i', $fileName, $matches)) { + $url = str_replace($matches[0], '', $fileName); + $read = $this->_readFactory->create($url, DriverPool::HTTP); + $fileName = preg_replace('/[^a-z0-9\._-]+/i', '', $fileName); + $this->_directory->writeFile( + $this->_directory->getRelativePath($this->getTmpDir() . '/' . $fileName), + $read->readAll() + ); + } + $filePath = $this->_directory->getRelativePath($this->getTmpDir() . '/' . $fileName); $this->_setUploadFile($filePath); $result = $this->save($this->getDestDir()); @@ -130,7 +183,8 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader */ protected function _readFileInfo($filePath) { - $fileInfo = pathinfo($filePath); + $fullFilePath = $this->_directory->getAbsolutePath($filePath); + $fileInfo = pathinfo($fullFilePath); return [ 'name' => $fileInfo['basename'], 'type' => $this->_getMimeTypeByExt($fileInfo['extension']), diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/CategoryProcessorTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/CategoryProcessorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..60b967d192bf83d065491cb6c10440f6d9aa6314 --- /dev/null +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/CategoryProcessorTest.php @@ -0,0 +1,108 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogImportExport\Test\Unit\Model\Import\Product; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\CatalogImportExport\Model\Import\Product\Validator; +use Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor; + +class CategoryProcessorTest extends \PHPUnit_Framework_TestCase +{ + const PARENT_CATEGORY_ID = 1; + + const CHILD_CATEGORY_ID = 2; + + const CHILD_CATEGORY_NAME = 'Child'; + + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + protected $objectManager; + + /** @var ObjectManagerHelper */ + protected $objectManagerHelper; + + /** + * @var \Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + protected $categoryProcessor; + + /** + * @var \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + */ + protected $product; + + protected function setUp() + { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->objectManagerHelper = new ObjectManagerHelper($this); + + $childCategory = $this->getMockBuilder('Magento\Catalog\Model\Category') + ->disableOriginalConstructor() + ->getMock(); + $childCategory->method('getId')->will($this->returnValue(self::CHILD_CATEGORY_ID)); + $childCategory->method('getName')->will($this->returnValue('Child')); + $childCategory->method('getPath')->will($this->returnValue( + self::PARENT_CATEGORY_ID . CategoryProcessor::DELIMITER_CATEGORY + . self::CHILD_CATEGORY_ID + )); + + $parentCategory = $this->getMockBuilder('Magento\Catalog\Model\Category') + ->disableOriginalConstructor() + ->getMock(); + $parentCategory->method('getId')->will($this->returnValue(self::PARENT_CATEGORY_ID)); + $parentCategory->method('getName')->will($this->returnValue('Parent')); + $parentCategory->method('getPath')->will($this->returnValue(self::PARENT_CATEGORY_ID)); + + $categoryCollection = + $this->objectManagerHelper->getCollectionMock( + 'Magento\Catalog\Model\Resource\Category\Collection', + [ + self::PARENT_CATEGORY_ID => $parentCategory, + self::CHILD_CATEGORY_ID => $childCategory, + ] + ); + $map = [ + [self::PARENT_CATEGORY_ID, $parentCategory], + [self::CHILD_CATEGORY_ID, $childCategory], + ]; + $categoryCollection->expects($this->any()) + ->method('getItemById') + ->will($this->returnValueMap($map)); + + $categoryColFactory = $this->getMock( + 'Magento\Catalog\Model\Resource\Category\CollectionFactory', + ['create'], + [], + '', + false + ); + + $categoryColFactory->method('create')->will($this->returnValue($categoryCollection)); + + $categoryFactory = $this->getMock( + 'Magento\Catalog\Model\CategoryFactory', + ['create'], + [], + '', + false + ); + + $categoryFactory->method('create')->will($this->returnValue($childCategory)); + + $this->categoryProcessor = + new \Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor( + $categoryColFactory, + $categoryFactory + ); + } + + public function testUpsertCategories() + { + $categoryIds = $this->categoryProcessor->upsertCategories(self::CHILD_CATEGORY_NAME); + $this->assertArrayHasKey(self::CHILD_CATEGORY_ID, array_flip($categoryIds)); + } +} diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/SkuProcessorTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/SkuProcessorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..12061e38ebed7e2d55bbbc716438bf3058d84c2c --- /dev/null +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/SkuProcessorTest.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogImportExport\Test\Unit\Model\Import\Product; + +use Magento\CatalogImportExport\Model\Import\Product\SkuProcessor as SkuProcessor; + +class SkuProcessorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Catalog\Model\ProductFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productFactory; + + /** + * @var SkuProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + protected $skuProcessor; + + public function setUp() + { + $this->productFactory = $this->getMock( + '\Magento\Catalog\Model\ProductFactory', + [], + [], + '', + false + ); + $this->skuProcessor = $this->getMock( + 'Magento\CatalogImportExport\Model\Import\Product\SkuProcessor', + ['_getSkus'], + [ + $this->productFactory + ], + '' + ); + } + + public function testReloadOldSkus() + { + $skuValue = 'value'; + + $this->skuProcessor + ->expects($this->once()) + ->method('_getSkus') + ->willReturn($skuValue); + + $this->skuProcessor->reloadOldSkus(); + $oldSkus = $this->getPropertyValue($this->skuProcessor, 'oldSkus'); + + $this->assertEquals($skuValue, $oldSkus); + } + + public function testGetOldSkusIfNotSet() + { + $expectedOldSkus = 'value'; + $this->setPropertyValue($this->skuProcessor, 'oldSkus', null); + $this->skuProcessor + ->expects($this->once()) + ->method('_getSkus') + ->willReturn($expectedOldSkus); + + $result = $this->skuProcessor->getOldSkus(); + + $this->assertEquals($expectedOldSkus, $result); + } + + public function testGetOldSkusIfSet() + { + $expectedOldSkus = 'value'; + $this->setPropertyValue($this->skuProcessor, 'oldSkus', 'value'); + $this->skuProcessor + ->expects($this->never()) + ->method('_getSkus'); + + $result = $this->skuProcessor->getOldSkus(); + + $this->assertEquals($expectedOldSkus, $result); + } + + /** + * Set object property. + * + * @param object $object + * @param string $property + * @param mixed $value + */ + protected function setPropertyValue(&$object, $property, $value) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionProperty = $reflection->getProperty($property); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($object, $value); + + return $object; + } + + /** + * Get object property. + * + * @param object $object + * @param string $property + */ + protected function getPropertyValue(&$object, $property) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionProperty = $reflection->getProperty($property); + $reflectionProperty->setAccessible(true); + + return $reflectionProperty->getValue($object); + } +} diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/TaxClassProcessorTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/TaxClassProcessorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3a51af93e41586094e6711b25b313230bef339a0 --- /dev/null +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/TaxClassProcessorTest.php @@ -0,0 +1,106 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogImportExport\Test\Unit\Model\Import\Product; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\CatalogImportExport\Model\Import\Product\Validator; + +class TaxClassProcessorTest extends \PHPUnit_Framework_TestCase +{ + const TEST_TAX_CLASS_NAME = 'className'; + + const TEST_TAX_CLASS_ID = 1; + + const TEST_JUST_CREATED_TAX_CLASS_ID = 2; + + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + protected $objectManager; + + /** @var ObjectManagerHelper */ + protected $objectManagerHelper; + + /** + * @var \Magento\CatalogImportExport\Model\Import\Product\TaxClassProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + protected $taxClassProcessor; + + /** + * @var \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + */ + protected $product; + + protected function setUp() + { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->objectManagerHelper = new ObjectManagerHelper($this); + + $taxClass = $this->getMockBuilder('Magento\Tax\Model\ClassModel') + ->disableOriginalConstructor() + ->getMock(); + $taxClass->method('getClassName')->will($this->returnValue(self::TEST_TAX_CLASS_NAME)); + $taxClass->method('getId')->will($this->returnValue(self::TEST_TAX_CLASS_ID)); + + $taxClassCollection = + $this->objectManagerHelper->getCollectionMock( + 'Magento\Tax\Model\Resource\TaxClass\Collection', + [$taxClass] + ); + + $taxClassCollectionFactory = $this->getMock( + 'Magento\Tax\Model\Resource\TaxClass\CollectionFactory', + ['create'], + [], + '', + false + ); + + $taxClassCollectionFactory->method('create')->will($this->returnValue($taxClassCollection)); + + $anotherTaxClass = $this->getMockBuilder('Magento\Tax\Model\ClassModel') + ->disableOriginalConstructor() + ->getMock(); + $anotherTaxClass->method('getClassName')->will($this->returnValue(self::TEST_TAX_CLASS_NAME)); + $anotherTaxClass->method('getId')->will($this->returnValue(self::TEST_JUST_CREATED_TAX_CLASS_ID)); + + $taxClassFactory = $this->getMock( + 'Magento\Tax\Model\ClassModelFactory', + ['create'], + [], + '', + false + ); + + $taxClassFactory->method('create')->will($this->returnValue($anotherTaxClass)); + + $this->taxClassProcessor = + new \Magento\CatalogImportExport\Model\Import\Product\TaxClassProcessor( + $taxClassCollectionFactory, + $taxClassFactory + ); + + $this->product = + $this->getMockForAbstractClass( + 'Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType', + [], + '', + false + ); + } + + public function testUpsertTaxClassExist() + { + $taxClassId = $this->taxClassProcessor->upsertTaxClass(self::TEST_TAX_CLASS_NAME, $this->product); + $this->assertEquals(self::TEST_TAX_CLASS_ID, $taxClassId); + } + + public function testUpsertTaxClassNotExist() + { + $taxClassId = $this->taxClassProcessor->upsertTaxClass('noExistClassName', $this->product); + $this->assertEquals(self::TEST_JUST_CREATED_TAX_CLASS_ID, $taxClassId); + } +} diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/AbstractTypeTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/AbstractTypeTest.php index 5f4185031e587b3b6444343325c5cc304d7347c0..1e4151eca14dbbd3c4300983b825c28eb74d3c63 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/AbstractTypeTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/AbstractTypeTest.php @@ -1,4 +1,5 @@ <?php + /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. @@ -6,9 +7,12 @@ namespace Magento\CatalogImportExport\Test\Unit\Model\Import\Product\Type; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType as AbstractType; /** * Test class for import product AbstractType class + * + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ class AbstractTypeTest extends \PHPUnit_Framework_TestCase { @@ -27,6 +31,11 @@ class AbstractTypeTest extends \PHPUnit_Framework_TestCase */ protected $objectManagerHelper; + /** + * @var AbstractType|\PHPUnit_Framework_MockObject_MockObject + */ + protected $abstractType; + protected function setUp() { $this->entityModel = $this->getMock( @@ -122,6 +131,45 @@ class AbstractTypeTest extends \PHPUnit_Framework_TestCase 'params' => [$this->entityModel, 'simple'], ] ); + + $this->abstractType = $this->getMockBuilder( + '\Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType' + ) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + } + + /** + * @dataProvider addAttributeOptionDataProvider + */ + public function testAddAttributeOption($code, $optionKey, $optionValue, $initAttributes, $resultAttributes) + { + $this->setPropertyValue($this->abstractType, '_attributes', $initAttributes); + + $this->abstractType->addAttributeOption($code, $optionKey, $optionValue); + + $this->assertEquals($resultAttributes, $this->getPropertyValue($this->abstractType, '_attributes')); + } + + public function testAddAttributeOptionReturn() + { + $code = 'attr set name value key'; + $optionKey = 'option key'; + $optionValue = 'option value'; + + $result = $this->abstractType->addAttributeOption($code, $optionKey, $optionValue); + + $this->assertEquals($result, $this->abstractType); + } + + public function testGetCustomFieldsMapping() + { + $expectedResult = ['value']; + $this->setPropertyValue($this->abstractType, '_customFieldsMapping', $expectedResult); + + $result = $this->abstractType->getCustomFieldsMapping(); + + $this->assertEquals($expectedResult, $result); } public function testIsRowValidSuccess() @@ -147,4 +195,71 @@ class AbstractTypeTest extends \PHPUnit_Framework_TestCase ->willReturnSelf(); $this->assertFalse($this->simpleType->isRowValid($rowData, $rowNum)); } + + public function addAttributeOptionDataProvider() + { + return [ + [ + '$code' => 'attr set name value key', + '$optionKey' => 'option key', + '$optionValue' => 'option value', + '$initAttributes' => [ + 'attr set name' => [ + 'attr set name value key' => [], + ], + ], + '$resultAttributes' => [ + 'attr set name' => [ + 'attr set name value key' => [ + 'options' => [ + 'option key' => 'option value' + ] + ] + ], + ], + ], + [ + '$code' => 'attr set name value key', + '$optionKey' => 'option key', + '$optionValue' => 'option value', + '$initAttributes' => [ + 'attr set name' => [ + 'not equal to code value' => [], + ], + ], + '$resultAttributes' => [ + 'attr set name' => [ + 'not equal to code value' => [], + ], + ] + ], + ]; + } + + /** + * @param $object + * @param $property + */ + protected function getPropertyValue(&$object, $property) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionProperty = $reflection->getProperty($property); + $reflectionProperty->setAccessible(true); + + return $reflectionProperty->getValue($object); + } + + /** + * @param $object + * @param $property + * @param $value + */ + protected function setPropertyValue(&$object, $property, $value) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionProperty = $reflection->getProperty($property); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($object, $value); + return $object; + } } diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/OptionTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/OptionTest.php index 57aa38a39d16721114a731920249284875dcb5cd..883039c4054c796396c3a7ae6337acb233521c40 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/OptionTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/OptionTest.php @@ -7,6 +7,9 @@ namespace Magento\CatalogImportExport\Test\Unit\Model\Import\Product\Type; /** * Test class for import product options module + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class OptionTest extends \PHPUnit_Framework_TestCase { @@ -49,6 +52,13 @@ class OptionTest extends \PHPUnit_Framework_TestCase */ protected $_model; + /** + * Test model mock + * + * @var \Magento\CatalogImportExport\Model\Import\Product\Option + */ + protected $_modelMock; + /** * Parent product entity * @@ -66,7 +76,6 @@ class OptionTest extends \PHPUnit_Framework_TestCase ['option_id' => 3, 'store_id' => 0, 'title' => 'Test Date and Time Title'], ['option_id' => 4, 'store_id' => 0, 'title' => 'Test Select'], ['option_id' => 5, 'store_id' => 0, 'title' => 'Test Radio'], - ['option_id' => 5, 'store_id' => 1, 'title' => 'Option New Store View'] ]; /** @@ -75,6 +84,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase * @var array */ protected $_expectedPrices = [ + 2 => ['option_id' => 2, 'store_id' => 0, 'price_type' => 'fixed', 'price' => 0], 3 => ['option_id' => 3, 'store_id' => 0, 'price_type' => 'fixed', 'price' => 2] ]; @@ -99,9 +109,7 @@ class OptionTest extends \PHPUnit_Framework_TestCase ['option_type_id' => 2, 'store_id' => 0, 'title' => 'Option 1'], ['option_type_id' => 3, 'store_id' => 0, 'title' => 'Option 2'], ['option_type_id' => 4, 'store_id' => 0, 'title' => 'Option 1'], - ['option_type_id' => 4, 'store_id' => 1, 'title' => 'Option 1 New Store View'], ['option_type_id' => 5, 'store_id' => 0, 'title' => 'Option 2'], - ['option_type_id' => 5, 'store_id' => 1, 'title' => 'Option 2 New Store View'] ]; /** @@ -174,9 +182,9 @@ class OptionTest extends \PHPUnit_Framework_TestCase */ protected $_expectedTypeValues = [ ['option_type_id' => 2, 'sort_order' => 0, 'sku' => '3-1-select', 'option_id' => 4], - ['option_type_id' => 3, 'sort_order' => 0, 'sku' => '3-2-select', 'option_id' => 4], + ['option_type_id' => 3, 'sort_order' => 1, 'sku' => '3-2-select', 'option_id' => 4], ['option_type_id' => 4, 'sort_order' => 0, 'sku' => '4-1-radio', 'option_id' => 5], - ['option_type_id' => 5, 'sort_order' => 0, 'sku' => '4-2-radio', 'option_id' => 5] + ['option_type_id' => 5, 'sort_order' => 1, 'sku' => '4-2-radio', 'option_id' => 5] ]; /** @@ -223,7 +231,8 @@ class OptionTest extends \PHPUnit_Framework_TestCase $scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'); - $this->_model = new \Magento\CatalogImportExport\Model\Import\Product\Option( + $modelClassName = '\Magento\CatalogImportExport\Model\Import\Product\Option'; + $modelClassArgs = [ $this->getMock('Magento\ImportExport\Model\Resource\Import\Data', [], [], '', false), $this->getMock('Magento\Framework\App\Resource', [], [], '', false), $this->getMock('Magento\ImportExport\Model\Resource\Helper', [], [], '', false), @@ -247,7 +256,16 @@ class OptionTest extends \PHPUnit_Framework_TestCase $scopeConfig, new \Magento\Framework\Stdlib\DateTime(), $this->_getModelDependencies($addExpectations, $deleteBehavior, $doubleOptions) - ); + ]; + + $class = new \ReflectionClass($modelClassName); + $this->_model = $class->newInstanceArgs($modelClassArgs); + // Create model mock with rewritten _getMultiRowFormat method to support test data with the old format. + $this->_modelMock = $this-> + getMockBuilder($modelClassName)-> + setConstructorArgs($modelClassArgs)-> + setMethods(['_getMultiRowFormat'])-> + getMock(); } /** @@ -355,8 +373,8 @@ class OptionTest extends \PHPUnit_Framework_TestCase 'id' => $elementIndex, 'entity_id' => $elementIndex, 'product_id' => $elementIndex, - 'type' => $csvDataRow[\Magento\CatalogImportExport\Model\Import\Product\Option::COLUMN_TYPE], - 'title' => $csvDataRow[\Magento\CatalogImportExport\Model\Import\Product\Option::COLUMN_TITLE] + 'type' => $csvDataRow[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE], + 'title' => $csvDataRow[\Magento\CatalogImportExport\Model\Import\Product::COL_NAME] ]; } } @@ -385,11 +403,10 @@ class OptionTest extends \PHPUnit_Framework_TestCase $logger = $this->getMock('Psr\Log\LoggerInterface'); $entityFactory = $this->getMock('Magento\Framework\Data\Collection\EntityFactory', [], [], '', false); - $optionCollection = $this->getMock( - 'Magento\Framework\Data\Collection\Db', - ['reset', 'addProductToFilter', 'getSelect', 'getNewEmptyItem'], - [$entityFactory, $logger, $fetchStrategy] - ); + $optionCollection = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->setConstructorArgs([$entityFactory, $logger, $fetchStrategy]) + ->setMethods(['reset', 'addProductToFilter', 'getSelect', 'getNewEmptyItem']) + ->getMockForAbstractClass(); $select = $this->getMock('Zend_Db_Select', ['join', 'where'], [], '', false); $select->expects($this->any())->method('join')->will($this->returnSelf()); @@ -442,11 +459,11 @@ class OptionTest extends \PHPUnit_Framework_TestCase * * @SuppressWarnings(PHPMD.UnusedFormalParameter) * - * @param \Magento\Framework\Data\Collection\Db $collection + * @param \Magento\Framework\Data\Collection\AbstractDb $collection * @param int $pageSize * @param array $callbacks */ - public function iterate(\Magento\Framework\Data\Collection\Db $collection, $pageSize, array $callbacks) + public function iterate(\Magento\Framework\Data\Collection\AbstractDb $collection, $pageSize, array $callbacks) { foreach ($collection as $option) { foreach ($callbacks as $callback) { @@ -629,6 +646,22 @@ class OptionTest extends \PHPUnit_Framework_TestCase return $data; } + /** + * Set method _getMultiRowFormat for model mock + * Make model bypass format converting, used to pass tests' with old data. + * @todo should be refactored/removed when all old options are converted into the new format. + * + * @param array $rowData + * old format data + * @return void + */ + private function _bypassModelMethodGetMultiRowFormat($rowData) + { + $this->_modelMock->expects($this->any()) + ->method('_getMultiRowFormat') + ->will($this->returnValue([$rowData])); + } + /** * Test for validation of row without custom option * @@ -637,7 +670,8 @@ class OptionTest extends \PHPUnit_Framework_TestCase public function testValidateRowNoCustomOption() { $rowData = include __DIR__ . '/_files/row_data_no_custom_option.php'; - $this->assertFalse($this->_model->validateRow($rowData, 0)); + $this->_bypassModelMethodGetMultiRowFormat($rowData); + $this->assertFalse($this->_modelMock->validateRow($rowData, 0)); } /** @@ -659,10 +693,12 @@ class OptionTest extends \PHPUnit_Framework_TestCase */ public function testValidateRow(array $rowData, array $errors) { + $this->_bypassModelMethodGetMultiRowFormat($rowData); + if (empty($errors)) { - $this->assertTrue($this->_model->validateRow($rowData, 0)); + $this->assertTrue($this->_modelMock->validateRow($rowData, 0)); } else { - $this->assertFalse($this->_model->validateRow($rowData, 0)); + $this->assertFalse($this->_modelMock->validateRow($rowData, 0)); } $this->assertAttributeEquals($errors, '_errors', $this->_productEntity); } @@ -691,16 +727,19 @@ class OptionTest extends \PHPUnit_Framework_TestCase $this->_testStores = ['admin' => 0]; $this->setUp(); if ($behavior) { - $this->_model->setParameters(['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND]); + $this->_modelMock->setParameters(['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND]); } + + $this->_bypassModelMethodGetMultiRowFormat($rowData); + for ($i = 0; $i < $numberOfValidations; $i++) { - $this->_model->validateRow($rowData, $i); + $this->_modelMock->validateRow($rowData, $i); } if (empty($errors)) { - $this->assertTrue($this->_model->validateAmbiguousData()); + $this->assertTrue($this->_modelMock->validateAmbiguousData()); } else { - $this->assertFalse($this->_model->validateAmbiguousData()); + $this->assertFalse($this->_modelMock->validateAmbiguousData()); } $this->assertAttributeEquals($errors, '_errors', $this->_productEntity); } @@ -910,4 +949,47 @@ class OptionTest extends \PHPUnit_Framework_TestCase ); $this->assertTrue($model->importData()); } + + public function testClearProductsSkuToId() + { + $this->setPropertyValue($this->_modelMock, '_productsSkuToId', 'value'); + + $this->_modelMock->clearProductsSkuToId(); + + $productsSkuToId = $this->getPropertyValue($this->_modelMock, '_productsSkuToId'); + + $this->assertNull($productsSkuToId); + } + + /** + * Set object property. + * + * @param object $object + * @param string $property + * @param mixed $value + */ + protected function setPropertyValue(&$object, $property, $value) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionProperty = $reflection->getProperty($property); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($object, $value); + + return $object; + } + + /** + * Get object property. + * + * @param object $object + * @param string $property + */ + protected function getPropertyValue(&$object, $property) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionProperty = $reflection->getProperty($property); + $reflectionProperty->setAccessible(true); + + return $reflectionProperty->getValue($object); + } } diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/product_with_custom_options.csv b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/product_with_custom_options.csv old mode 100644 new mode 100755 index bba9a0fa99c897ef8c3aa704e169fa0d2f4306cc..92cad357803c7234d7629e1ddccbb79fc55eb5f7 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/product_with_custom_options.csv +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/product_with_custom_options.csv @@ -1,12 +1,2 @@ -sku,_store,_attribute_set,_type,_category,_root_category,_product_websites,color,cost,country_of_manufacture,created_at,custom_design,custom_design_from,custom_design_to,custom_layout_update,description,enable_googlecheckout,gallery,gift_message_available,gift_wrapping_available,gift_wrapping_price,has_options,image,image_label,is_returnable,manufacturer,media_gallery,meta_description,meta_keyword,meta_title,minimal_price,msrp,msrp_display_actual_price_type,msrp_enabled,name,news_from_date,news_to_date,options_container,page_layout,price,related_tgtr_position_behavior,related_tgtr_position_limit,required_options,short_description,small_image,small_image_label,special_from_date,special_price,special_to_date,status,tax_class_id,thumbnail,thumbnail_label,updated_at,upsell_tgtr_position_behavior,upsell_tgtr_position_limit,url_key,url_path,visibility,weight,qty,min_qty,use_config_min_qty,is_qty_decimal,backorders,use_config_backorders,min_sale_qty,use_config_min_sale_qty,max_sale_qty,use_config_max_sale_qty,is_in_stock,notify_stock_qty,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,_related_sku,_related_position,_crosssell_sku,_crosssell_position,_upsell_sku,_upsell_position,_associated_sku,_associated_default_qty,_associated_position,_tier_price_website,_tier_price_customer_group,_tier_price_qty,_tier_price_price,_group_price_website,_group_price_customer_group,_group_price_price,_media_attribute_id,_media_image,_media_label,_media_position,_media_is_disabled,_custom_option_store,_custom_option_type,_custom_option_title,_custom_option_is_required,_custom_option_price,_custom_option_sku,_custom_option_max_characters,_custom_option_sort_order,_custom_option_row_title,_custom_option_row_price,_custom_option_row_sku,_custom_option_row_sort -simple,,Default,simple,,,base,,,,,,,,,,1,,,,,1,,,"Use config",,,,,,,,,,"New Product",,,"Block after Info Column",,10.0000,,,1,,,,,,,1,,,,"2012-07-13 12:04:17",,,new-product,new-product.html,4,,100.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,0,1,1,0.0000,1,0,0,,,,,,,,,,,,,,,,,,,,,,,field,"Test Field Title",1,,1-text,100,0,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,date_time,"Test Date and Time Title",1,2.0000,2-date,,0,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,drop_down,"Test Select",1,,,,0,"Option 1",3.0000,3-1-select,0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"Option 2",3.0000,3-2-select,0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,default,,,,,,,,"Option 2",,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,radio,"Test Radio",1,,,,0,"Option 1",3.0000,4-1-radio,0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"Option 2",3.0000,4-2-radio,0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,default,,,,,,,,"Option 1",,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,default,,,,,,,,"Option 2",,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,new_store_view,,"Option New Store View",,,,,,"Option 1 New Store View",,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,new_store_view,,,,,,,,"Option 2 New Store View",,, +sku,website_code,store_view_code,attribute_set_code,product_type,name,description,short_description,weight,product_online,visibility,product_websites,categories,price,special_price,special_price_from_date,special_price_to_date,tax_class_name,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,additional_images,additional_image_labels,configurable_variation_labels,configurable_variations,bundle_price_type,bundle_sku_type,bundle_weight_type,bundle_values,downloadble_samples,downloadble_links,associated_skus,related_skus,crosssell_skus,upsell_skus,custom_options,additional_attributes,manage_stock,is_in_stock,qty,out_of_stock_qty,is_qty_decimal,allow_backorders,min_cart_qty,max_cart_qty,notify_on_stock_below,qty_increments,enable_qty_increments,is_decimal_divided,new_from_date,new_to_date,gift_message_available,created_at,updated_at,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_price,msrp_display_actual_price_type,map_enabled +simple,base,,Default,simple,New Product,,,,,,,,10,,,,,new-product,,,,,,,,,,,,,,,,,,,,,,,,"name=Test Field Title,type=field,required=1;sku=1-text,price=0,price_type=fixed|name=Test Date and Time Title,type=date_time,required=1,price=2,option_title=custom option 1,sku=2-date|name=Test Select,type=drop_down,required=1,price=3,option_title=Option 1,sku=3-1-select|name=Test Select,type=drop_down,required=1,price=3,option_title=Option 2,sku=3-2-select|name=Test Radio,type=radio,required=1,price=3,option_title=Option 1,sku=4-1-radio|name=Test Radio,type=radio,required=1,price=3,option_title=Option 2,sku=4-2-radio",,,,,,,,,,,,,,,,,,,,,,,,Block after Info Column,,, diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/row_data_ambiguity_different_type.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/row_data_ambiguity_different_type.php index 519106d6dc084f9153a70a241db377b9c227779d..aad45100276802dfd14c8cb9fb7679cd9edecca7 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/row_data_ambiguity_different_type.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/row_data_ambiguity_different_type.php @@ -7,7 +7,7 @@ return [ 'sku' => 'simple', '_custom_option_type' => 'date_time', - '_custom_option_title' => 'Test Field Title', + '_custom_option_title' => 'New Product', '_custom_option_is_required' => '1', '_custom_option_price' => '3.0000', '_custom_option_sku' => 'option-sku', diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/row_data_ambiguity_several_db_rows.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/row_data_ambiguity_several_db_rows.php index 235e0713c4dec6a8595136437d032de87a33c33a..42ab692736494c594c5e83a001fff04b6f873ab7 100644 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/row_data_ambiguity_several_db_rows.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Type/_files/row_data_ambiguity_several_db_rows.php @@ -7,7 +7,7 @@ return [ 'sku' => 'simple', '_custom_option_type' => 'field', - '_custom_option_title' => 'Test Field Title', + '_custom_option_title' => 'New Product', '_custom_option_is_required' => '1', '_custom_option_price' => '3.0000', '_custom_option_sku' => 'option-sku', diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/MediaTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/MediaTest.php old mode 100644 new mode 100755 index e2277ef4aae49936e5df3b4eb89ae626910df567..cb0a32acff56ea7b574a179703daa9028d892a0b --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/MediaTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/Validator/MediaTest.php @@ -47,6 +47,20 @@ class MediaTest extends \PHPUnit_Framework_TestCase $this->assertEquals($expected['messages'], $messages); } + public function testIsValidClearMessagesCall() + { + $media = $this->getMock( + '\Magento\CatalogImportExport\Model\Import\Product\Validator\Media', + ['_clearMessages'], + [], + '', + false + ); + $media->expects($this->once())->method('_clearMessages'); + + $media->isValid([]); + } + /** * @return array */ @@ -63,7 +77,7 @@ class MediaTest extends \PHPUnit_Framework_TestCase ], 'invalid' => [ ['_media_image' => 1], - ['result' => false,'messages' => [0 => 'mediaDataIsIncomplete']], + ['result' => true,'messages' => []], ] ]; } diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/ValidatorTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/ValidatorTest.php old mode 100644 new mode 100755 index 2e802c5958cc31151d9751fdfc24d86cb3507348..d0db94e92962e9fef4e12723f2567162a4b4bd09 --- a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/ValidatorTest.php +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/Product/ValidatorTest.php @@ -20,29 +20,29 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase protected $validators = []; /** @var Validator\Media|\PHPUnit_Framework_MockObject_MockObject */ - protected $validator1; + protected $validatorOne; - /** @var Validator\Category|\PHPUnit_Framework_MockObject_MockObject */ - protected $validator2; + /** @var Validator\Website|\PHPUnit_Framework_MockObject_MockObject */ + protected $validatorTwo; protected function setUp() { - $this->validator1 = $this->getMock( + $this->validatorOne = $this->getMock( 'Magento\CatalogImportExport\Model\Import\Product\Validator\Media', [], [], '', false ); - $this->validator2 = $this->getMock( - 'Magento\CatalogImportExport\Model\Import\Product\Validator\Category', + $this->validatorTwo = $this->getMock( + 'Magento\CatalogImportExport\Model\Import\Product\Validator\Website', [], [], '', false ); - $this->validators = [$this->validator1, $this->validator2]; + $this->validators = [$this->validatorOne, $this->validatorTwo]; $this->objectManagerHelper = new ObjectManagerHelper($this); $this->validator = $this->objectManagerHelper->getObject( 'Magento\CatalogImportExport\Model\Import\Product\Validator', @@ -53,8 +53,8 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase public function testIsValidCorrect() { $value = 'val'; - $this->validator1->expects($this->once())->method('isValid')->with($value)->willReturn(true); - $this->validator2->expects($this->once())->method('isValid')->with($value)->willReturn(true); + $this->validatorOne->expects($this->once())->method('isValid')->with($value)->willReturn(true); + $this->validatorTwo->expects($this->once())->method('isValid')->with($value)->willReturn(true); $result = $this->validator->isValid($value); $this->assertTrue($result); } @@ -62,10 +62,10 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase public function testIsValidIncorrect() { $value = 'val'; - $this->validator1->expects($this->once())->method('isValid')->with($value)->willReturn(true); - $this->validator2->expects($this->once())->method('isValid')->with($value)->willReturn(false); + $this->validatorOne->expects($this->once())->method('isValid')->with($value)->willReturn(true); + $this->validatorTwo->expects($this->once())->method('isValid')->with($value)->willReturn(false); $messages = ['errorMessage']; - $this->validator2->expects($this->once())->method('getMessages')->willReturn($messages); + $this->validatorTwo->expects($this->once())->method('getMessages')->willReturn($messages); $result = $this->validator->isValid($value); $this->assertFalse($result); $this->assertEquals($messages, $this->validator->getMessages()); @@ -73,8 +73,8 @@ class ValidatorTest extends \PHPUnit_Framework_TestCase public function testInit() { - $this->validator1->expects($this->once())->method('init'); - $this->validator2->expects($this->once())->method('init'); + $this->validatorOne->expects($this->once())->method('init'); + $this->validatorTwo->expects($this->once())->method('init'); $this->validator->init(); } } diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php new file mode 100755 index 0000000000000000000000000000000000000000..758e4e0eef502ba678d58127d705293617e2843c --- /dev/null +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/ProductTest.php @@ -0,0 +1,1637 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogImportExport\Test\Unit\Model\Import; + +use Magento\CatalogImportExport\Model\Import\Product; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Stdlib\DateTime; +use Zend\Server\Reflection\ReflectionClass; + +/** + * Class ProductTest + * @package Magento\CatalogImportExport\Test\Unit\Model\Import + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ProductTest extends \PHPUnit_Framework_TestCase +{ + const MEDIA_DIRECTORY = 'media/import'; + + const ENTITY_TYPE_ID = 1; + + const ENTITY_TYPE_CODE = 'catalog_product'; + + const ENTITY_ID = 13; + + /** @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $_connection; + + /** @var \Magento\Framework\Json\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ + protected $jsonHelper; + + /** @var \Magento\ImportExport\Model\Resource\Import\Data|\PHPUnit_Framework_MockObject_MockObject */ + protected $_dataSourceModel; + + /** @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject */ + protected $resource; + + /** @var \Magento\ImportExport\Model\Resource\Helper|\PHPUnit_Framework_MockObject_MockObject */ + protected $_resourceHelper; + + /** @var \Magento\Framework\Stdlib\String|\PHPUnit_Framework_MockObject_MockObject */ + protected $string; + + /** @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $_eventManager; + + /** @var \Magento\CatalogInventory\Api\StockRegistryInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $stockRegistry; + + /** @var \Magento\CatalogImportExport\Model\Import\Product\OptionFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $optionFactory; + + /** @var \Magento\CatalogInventory\Api\StockConfigurationInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $stockConfiguration; + + /** @var \Magento\CatalogInventory\Model\Spi\StockStateProviderInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $stockStateProvider; + + /** @var \Magento\CatalogImportExport\Model\Import\Product\Option|\PHPUnit_Framework_MockObject_MockObject */ + protected $optionEntity; + + /** @var \Magento\Framework\Stdlib\DateTime|\PHPUnit_Framework_MockObject_MockObject */ + protected $dateTime; + + /** @var array */ + protected $data; + + /** @var \Magento\ImportExport\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ + protected $importExportData; + + /** @var \Magento\ImportExport\Model\Resource\Import\Data|\PHPUnit_Framework_MockObject_MockObject */ + protected $importData; + + /** @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject */ + protected $config; + + /** @var \Magento\ImportExport\Model\Resource\Helper|\PHPUnit_Framework_MockObject_MockObject */ + protected $resourceHelper; + + /** @var \Magento\Catalog\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */ + protected $_catalogData; + + /** @var \Magento\ImportExport\Model\Import\Config|\PHPUnit_Framework_MockObject_MockObject */ + protected $_importConfig; + + // @codingStandardsIgnoreStart + /** @var \Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $_resourceFactory; + + /** @var \Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $_setColFactory; + + /** @var \Magento\CatalogImportExport\Model\Import\Product\Type\Factory|\PHPUnit_Framework_MockObject_MockObject */ + protected $_productTypeFactory; + + /** @var \Magento\Catalog\Model\Resource\Product\LinkFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $_linkFactory; + + /** @var \Magento\CatalogImportExport\Model\Import\Proxy\ProductFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $_proxyProdFactory; + + /** @var \Magento\CatalogImportExport\Model\Import\UploaderFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $_uploaderFactory; + + /** @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject */ + protected $_filesystem; + + /** @var \Magento\Framework\Filesystem\Directory\WriteInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $_mediaDirectory; + + /** @var \Magento\CatalogInventory\Model\Resource\Stock\ItemFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $_stockResItemFac; + + /** @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $_localeDate; + + /** @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject */ + protected $indexerRegistry; + + /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $_logger; + + /** @var \Magento\CatalogImportExport\Model\Import\Product\StoreResolver|\PHPUnit_Framework_MockObject_MockObject */ + protected $storeResolver; + + /** @var \Magento\CatalogImportExport\Model\Import\Product\SkuProcessor|\PHPUnit_Framework_MockObject_MockObject */ + protected $skuProcessor; + + /** @var \Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor|\PHPUnit_Framework_MockObject_MockObject */ + protected $categoryProcessor; + + /** @var \Magento\CatalogImportExport\Model\Import\Product\Validator|\PHPUnit_Framework_MockObject_MockObject */ + protected $validator; + + /** @var \Magento\Framework\Model\Resource\Db\ObjectRelationProcessor|\PHPUnit_Framework_MockObject_MockObject */ + protected $objectRelationProcessor; + + /** @var \Magento\Framework\Model\Resource\Db\TransactionManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $transactionManager; + + /** @var \Magento\Catalog\Model\ProductFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $catalogProductFactory; + + /** @var \Magento\CatalogImportExport\Model\Import\Product\TaxClassProcessor|\PHPUnit_Framework_MockObject_MockObject */ + // @codingStandardsIgnoreEnd + protected $taxClassProcessor; + + /** @var \Magento\CatalogImportExport\Model\Import\Product */ + protected $importProduct; + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + protected function setUp() + { + /* For parent object construct */ + $this->jsonHelper = + $this->getMockBuilder('\Magento\Framework\Json\Helper\Data') + ->disableOriginalConstructor() + ->getMock(); + $this->importExportData = + $this->getMockBuilder('\Magento\ImportExport\Helper\Data') + ->disableOriginalConstructor() + ->getMock(); + $this->_dataSourceModel = + $this->getMockBuilder('\Magento\ImportExport\Model\Resource\Import\Data') + ->disableOriginalConstructor() + ->getMock(); + $this->config = + $this->getMockBuilder('\Magento\Eav\Model\Config') + ->disableOriginalConstructor() + ->getMock(); + $this->resource = + $this->getMockBuilder('\Magento\Framework\App\Resource') + ->disableOriginalConstructor() + ->getMock(); + $this->resourceHelper = + $this->getMockBuilder('\Magento\ImportExport\Model\Resource\Helper') + ->disableOriginalConstructor() + ->getMock(); + $this->string = + $this->getMockBuilder('\Magento\Framework\Stdlib\String') + ->disableOriginalConstructor() + ->getMock(); + + /* For object construct */ + $this->_eventManager = + $this->getMockBuilder('\Magento\Framework\Event\ManagerInterface') + ->getMock(); + $this->stockRegistry = + $this->getMockBuilder('\Magento\CatalogInventory\Api\StockRegistryInterface') + ->getMock(); + $this->stockConfiguration = + $this->getMockBuilder('\Magento\CatalogInventory\Api\StockConfigurationInterface') + ->getMock(); + $this->stockStateProvider = + $this->getMockBuilder('\Magento\CatalogInventory\Model\Spi\StockStateProviderInterface') + ->getMock(); + $this->_catalogData = + $this->getMockBuilder('\Magento\Catalog\Helper\Data') + ->disableOriginalConstructor() + ->getMock(); + $this->_importConfig = + $this->getMockBuilder('\Magento\ImportExport\Model\Import\Config') + ->disableOriginalConstructor() + ->getMock(); + $this->_resourceFactory = $this->getMock( + '\Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceFactory', + ['create'], + [], + '', + false + ); + $this->_setColFactory = $this->getMock( + '\Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory', + ['create'], + [], + '', + false + ); + $this->_productTypeFactory = $this->getMock( + '\Magento\CatalogImportExport\Model\Import\Product\Type\Factory', + ['create'], + [], + '', + false + ); + $this->_linkFactory = $this->getMock( + '\Magento\Catalog\Model\Resource\Product\LinkFactory', + ['create'], + [], + '', + false + ); + $this->_proxyProdFactory = $this->getMock( + '\Magento\CatalogImportExport\Model\Import\Proxy\ProductFactory', + ['create'], + [], + '', + false + ); + $this->_uploaderFactory = $this->getMock( + '\Magento\CatalogImportExport\Model\Import\UploaderFactory', + ['create'], + [], + '', + false + ); + $this->_filesystem = + $this->getMockBuilder('\Magento\Framework\Filesystem') + ->disableOriginalConstructor() + ->getMock(); + $this->_mediaDirectory = + $this->getMockBuilder('\Magento\Framework\Filesystem\Directory\WriteInterface') + ->getMock(); + $this->_stockResItemFac = $this->getMock( + '\Magento\CatalogInventory\Model\Resource\Stock\ItemFactory', + ['create'], + [], + '', + false + ); + $this->_localeDate = + $this->getMockBuilder('\Magento\Framework\Stdlib\DateTime\TimezoneInterface') + ->getMock(); + $this->dateTime = + $this->getMockBuilder('\Magento\Framework\Stdlib\DateTime') + ->disableOriginalConstructor() + ->getMock(); + $this->indexerRegistry = + $this->getMockBuilder('\Magento\Indexer\Model\IndexerRegistry') + ->disableOriginalConstructor() + ->getMock(); + $this->_logger = + $this->getMockBuilder('\Psr\Log\LoggerInterface') + ->getMock(); + $this->storeResolver = + $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product\StoreResolver') + ->disableOriginalConstructor() + ->getMock(); + $this->skuProcessor = + $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product\SkuProcessor') + ->disableOriginalConstructor() + ->getMock(); + $this->categoryProcessor = + $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor') + ->disableOriginalConstructor() + ->getMock(); + $this->validator = + $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product\Validator') + ->disableOriginalConstructor() + ->getMock(); + $this->objectRelationProcessor = + $this->getMockBuilder('\Magento\Framework\Model\Resource\Db\ObjectRelationProcessor') + ->disableOriginalConstructor() + ->getMock(); + $this->transactionManager = + $this->getMockBuilder('\Magento\Framework\Model\Resource\Db\TransactionManagerInterface') + ->getMock(); + $this->catalogProductFactory = $this->getMock( + '\Magento\Catalog\Model\ProductFactory', + ['create'], + [], + '', + false + ); + + $this->taxClassProcessor = + $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product\TaxClassProcessor') + ->disableOriginalConstructor() + ->getMock(); + + $this->data = []; + + $this->_objectConstructor() + ->_parentObjectConstructor() + ->_initAttributeSets() + ->_initTypeModels() + ->_initSkus(); + + $this->importProduct = new Product( + $this->jsonHelper, + $this->importExportData, + $this->_dataSourceModel, + $this->config, + $this->resource, + $this->resourceHelper, + $this->string, + $this->_eventManager, + $this->stockRegistry, + $this->stockConfiguration, + $this->stockStateProvider, + $this->_catalogData, + $this->_importConfig, + $this->_resourceFactory, + $this->optionFactory, + $this->_setColFactory, + $this->_productTypeFactory, + $this->_linkFactory, + $this->_proxyProdFactory, + $this->_uploaderFactory, + $this->_filesystem, + $this->_stockResItemFac, + $this->_localeDate, + $this->dateTime, + $this->_logger, + $this->indexerRegistry, + $this->storeResolver, + $this->skuProcessor, + $this->categoryProcessor, + $this->validator, + $this->catalogProductFactory, + $this->objectRelationProcessor, + $this->transactionManager, + $this->taxClassProcessor, + $this->data + ); + } + + /** + * @return $this + */ + protected function _objectConstructor() + { + $this->optionFactory = $this->getMock( + '\Magento\CatalogImportExport\Model\Import\Product\OptionFactory', + ['create'], + [], + '', + false + ); + $this->optionEntity = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product\Option') + ->disableOriginalConstructor()->getMock(); + $this->optionFactory->expects($this->once())->method('create')->willReturn($this->optionEntity); + + $this->_filesystem->expects($this->once()) + ->method('getDirectoryWrite') + ->with(DirectoryList::ROOT) + ->will($this->returnValue(self::MEDIA_DIRECTORY)); + + $this->validator->expects($this->once())->method('init'); + return $this; + } + + /** + * @return $this + */ + protected function _parentObjectConstructor() + { + $type = $this->getMockBuilder('Magento\Eav\Model\Entity\Type')->disableOriginalConstructor()->getMock(); + $type->expects($this->any())->method('getEntityTypeId')->will($this->returnValue(self::ENTITY_TYPE_ID)); + $this->config->expects($this->any())->method('getEntityType')->with(self::ENTITY_TYPE_CODE)->willReturn($type); + + $this->_connection = $this->getMock('\Magento\Framework\DB\Adapter\AdapterInterface'); + $this->resource->expects($this->any())->method('getConnection')->willReturn($this->_connection); + return $this; + } + + /** + * @return $this + */ + protected function _initAttributeSets() + { + $attributeSetOne = $this->getMockBuilder('\Magento\Eav\Model\Entity\Attribute\Set') + ->disableOriginalConstructor() + ->getMock(); + $attributeSetOne->expects($this->any()) + ->method('getAttributeSetName') + ->willReturn('attributeSet1'); + $attributeSetOne->expects($this->any()) + ->method('getId') + ->willReturn('1'); + $attributeSetTwo = $this->getMockBuilder('\Magento\Eav\Model\Entity\Attribute\Set') + ->disableOriginalConstructor() + ->getMock(); + $attributeSetTwo->expects($this->any()) + ->method('getAttributeSetName') + ->willReturn('attributeSet2'); + $attributeSetTwo->expects($this->any()) + ->method('getId') + ->willReturn('2'); + $attributeSetCol = [$attributeSetOne, $attributeSetTwo]; + $collection = $this->getMockBuilder('\Magento\Eav\Model\Resource\Entity\Attribute\Set\Collection') + ->disableOriginalConstructor() + ->getMock(); + $collection->expects($this->once()) + ->method('setEntityTypeFilter') + ->with(self::ENTITY_TYPE_ID) + ->willReturn($attributeSetCol); + $this->_setColFactory->expects($this->once()) + ->method('create') + ->willReturn($collection); + return $this; + } + + /** + * @return $this + */ + protected function _initTypeModels() + { + $entityTypes = [ + 'simple' => [ + 'model' => 'simple_product', + 'params' => [], + ]]; + $productTypeInstance = + $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType') + ->disableOriginalConstructor()->getMock(); + $productTypeInstance->expects($this->once()) + ->method('isSuitable') + ->willReturn(true); + $productTypeInstance->expects($this->once()) + ->method('getParticularAttributes') + ->willReturn([]); + $productTypeInstance->expects($this->once()) + ->method('getCustomFieldsMapping') + ->willReturn([]); + $this->_importConfig->expects($this->once()) + ->method('getEntityTypes') + ->with(self::ENTITY_TYPE_CODE) + ->willReturn($entityTypes); + $this->_productTypeFactory->expects($this->once())->method('create')->willReturn($productTypeInstance); + return $this; + } + + /** + * @return $this + */ + protected function _initSkus() + { + $this->skuProcessor->expects($this->once())->method('setTypeModels'); + $this->skuProcessor->expects($this->once())->method('getOldSkus'); + return $this; + } + + public function testGetAffectedProducts() + { + $testProduct = 'test_product'; + $rowData = ['data']; + $rowNum = 666; + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['isRowAllowedToImport', '_populateToUrlGeneration']) + ->getMock(); + + $this->_dataSourceModel->expects($this->exactly(2))->method('getNextBunch')->willReturnOnConsecutiveCalls( + [ + $rowNum => $rowData + ], + null + ); + $this->setPropertyValue($importProduct, '_dataSourceModel', $this->_dataSourceModel); + $importProduct->expects($this->once()) + ->method('isRowAllowedToImport') + ->with($rowData, $rowNum)->willReturn(true); + $importProduct->expects($this->once())->method('_populateToUrlGeneration') + ->with($rowData) + ->willReturn($testProduct); + + $this->assertEquals([$testProduct], $importProduct->getAffectedProducts()); + } + + public function testSaveProductAttributes() + { + $testTable = 'test_table'; + $attributeId = 'test_attribute_id'; + $storeId = 'test_store_id'; + $testSku = 'test_sku'; + $attributesData = [ + $testTable => [ + $testSku => [ + $attributeId => [ + $storeId => [ + 'foo' => 'bar' + ] + ] + ] + ] + ]; + $this->skuProcessor->expects($this->once()) + ->method('getNewSku') + ->with($testSku) + ->willReturn(['entity_id' => self::ENTITY_ID]); + $this->_connection->expects($this->any()) + ->method('quoteInto') + ->willReturnCallback([$this, 'returnQuoteCallback']); + $this->_connection + ->expects($this->once()) + ->method('delete') + ->with( + $this->equalTo($testTable), + $this->equalTo( + '(store_id NOT IN (' + . $storeId . ') AND attribute_id = ' + . $attributeId . ' AND entity_id = ' + . self::ENTITY_ID . ')' + ) + ); + + $tableData[] = [ + 'entity_id' => self::ENTITY_ID, + 'attribute_id' => $attributeId, + 'store_id' => $storeId, + 'value' => $attributesData[$testTable][$testSku][$attributeId][$storeId], + ]; + $this->_connection->expects($this->once()) + ->method('insertOnDuplicate') + ->with($testTable, $tableData, ['value']); + $object = $this->invokeMethod($this->importProduct, '_saveProductAttributes', [$attributesData]); + $this->assertEquals($this->importProduct, $object); + } + + /** + * @dataProvider isAttributeValidAssertAttrValidDataProvider + */ + public function testIsAttributeValidAssertAttrValid($attrParams, $rowData) + { + $attrCode = 'code'; + $rowNum = 0; + $string = $this->getMockBuilder('\Magento\Framework\Stdlib\String')->setMethods(null)->getMock(); + $this->setPropertyValue($this->importProduct, 'string', $string); + + $result = $this->importProduct->isAttributeValid($attrCode, $attrParams, $rowData, $rowNum); + $this->assertTrue($result); + } + + /** + * @dataProvider isAttributeValidAssertAttrInvalidDataProvider + */ + public function testIsAttributeValidAssertAttrInvalid($attrParams, $rowData) + { + $attrCode = 'code'; + $rowNum = 0; + $string = $this->getMockBuilder('\Magento\Framework\Stdlib\String')->setMethods(null)->getMock(); + $this->setPropertyValue($this->importProduct, 'string', $string); + + $result = $this->importProduct->isAttributeValid($attrCode, $attrParams, $rowData, $rowNum); + $this->assertFalse($result); + } + + public function testIsAttributeValidNotValidAddErrorCall() + { + $attrCode = 'code'; + $attrParams = [ + 'type' => 'decimal', + ]; + $rowData = [ + $attrCode => 'incorrect' + ]; + $rowNum = 0; + + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['addRowError']) + ->getMock(); + $importProduct->expects($this->once())->method('addRowError'); + + $importProduct->isAttributeValid($attrCode, $attrParams, $rowData, $rowNum); + } + + public function testIsAttributeValidOnDuplicateAddErrorCall() + { + $attrCode = 'code'; + $attrCodeVal = 1000; + $expectedSkuVal = 'sku_val'; + $testSkuVal = 'some_sku'; + $attrParams = [ + 'type' => 'decimal', + 'is_unique' => true, + ]; + $rowData = [ + $attrCode => $attrCodeVal, + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => $expectedSkuVal + ]; + $rowNum = 0; + + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['addRowError']) + ->getMock(); + $importProduct->expects($this->once())->method('addRowError'); + $this->setPropertyValue($importProduct, '_uniqueAttributes', [ + $attrCode => [$attrCodeVal => $testSkuVal] + ]); + + $importProduct->expects($this->once())->method('addRowError'); + + $return = $importProduct->isAttributeValid($attrCode, $attrParams, $rowData, $rowNum); + + $this->assertFalse($return); + } + + public function testIsAttributeValidAddIntoUniqueueAttributes() + { + $attrCode = 'code'; + $attrCodeVal = 1000; + $expectedSkuVal = 'sku_val'; + $attrParams = [ + 'type' => 'decimal', + 'is_unique' => true, + ]; + $rowData = [ + $attrCode => $attrCodeVal, + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => $expectedSkuVal + ]; + $rowNum = 0; + + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(null) + ->getMock(); + + $importProduct->isAttributeValid($attrCode, $attrParams, $rowData, $rowNum); + + $_uniqueAttributes = $this->getPropertyValue($importProduct, '_uniqueAttributes'); + $this->assertEquals($expectedSkuVal, $_uniqueAttributes[$attrCode][$rowData[$attrCode]]); + } + + public function testGetMultipleValueSeparatorDefault() + { + $this->setPropertyValue($this->importProduct, '_parameters', null); + $this->assertEquals( + \Magento\CatalogImportExport\Model\Import\Product::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, + $this->importProduct->getMultipleValueSeparator() + ); + } + + public function testGetMultipleValueSeparatorFromParameters() + { + $expectedSeparator = 'value'; + $this->setPropertyValue($this->importProduct, '_parameters', [ + \Magento\ImportExport\Model\Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR => $expectedSeparator, + ]); + + $this->assertEquals( + $expectedSeparator, + $this->importProduct->getMultipleValueSeparator() + ); + } + + public function testDeleteProductsForReplacement() + { + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods([ + 'setParameters', '_deleteProducts' + ]) + ->getMock(); + + $importProduct->expects($this->once())->method('setParameters')->with( + [ + 'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE, + ] + ); + $importProduct->expects($this->once())->method('_deleteProducts'); + + $result = $importProduct->deleteProductsForReplacement(); + + $this->assertEquals($importProduct, $result); + } + + public function testGetMediaGalleryAttributeIdIfNotSetYet() + { + // reset possible existing id + $this->setPropertyValue($this->importProduct, '_mediaGalleryAttributeId', null); + + $expectedId = '100'; + $attribute = $this->getMockBuilder('\Magento\Eav\Model\Entity\Attribute\AbstractAttribute') + ->disableOriginalConstructor() + ->setMethods(['getId']) + ->getMockForAbstractClass(); + $attribute->expects($this->once())->method('getId')->willReturn($expectedId); + $resource = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Proxy\Product\Resource') + ->disableOriginalConstructor() + ->setMethods(['getAttribute']) + ->getMock(); + $resource->expects($this->once())->method('getAttribute')->willReturn($attribute); + $this->_resourceFactory->expects($this->once())->method('create')->willReturn($resource); + + $result = $this->importProduct->getMediaGalleryAttributeId(); + $this->assertEquals($expectedId, $result); + } + + + /** + * @dataProvider getRowScopeDataProvider + */ + public function testGetRowScope($rowData, $expectedResult) + { + $result = $this->importProduct->getRowScope($rowData); + $this->assertEquals($expectedResult, $result); + } + + /** + * @dataProvider validateRowIsAlreadyValidatedDataProvider + */ + public function testValidateRowIsAlreadyValidated($isInvalidRow, $expectedResult) + { + $rowNum = 0; + $this->setPropertyValue($this->importProduct, '_validatedRows', [$rowNum => true]); + $this->setPropertyValue($this->importProduct, '_invalidRows', [$rowNum => $isInvalidRow]); + $result = $this->importProduct->validateRow([], $rowNum); + $this->assertEquals($expectedResult, $result); + } + + /** + * @dataProvider validateRowDeleteBehaviourDataProvider + */ + public function testValidateRowDeleteBehaviour($rowScope, $oldSku, $expectedResult) + { + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['getBehavior', 'getRowScope']) + ->getMock(); + $importProduct + ->expects($this->once()) + ->method('getBehavior') + ->willReturn(\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE); + $importProduct->expects($this->once())->method('getRowScope')->willReturn($rowScope); + $skuKey = \Magento\CatalogImportExport\Model\Import\Product::COL_SKU; + $rowData = [ + $skuKey => 'sku', + ]; + $this->setPropertyValue($importProduct, '_oldSku', [$rowData[$skuKey] => $oldSku]); + $rowNum = 0; + $result = $importProduct->validateRow($rowData, $rowNum); + $this->assertEquals($expectedResult, $result); + } + + public function testValidateRowDeleteBehaviourAddRowErrorCall() + { + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['getBehavior', 'getRowScope', 'addRowError']) + ->getMock(); + + $importProduct->expects($this->once())->method('getBehavior') + ->willReturn(\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE); + $importProduct->expects($this->once())->method('getRowScope') + ->willReturn(\Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT); + $importProduct->expects($this->once())->method('addRowError'); + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => 'sku', + ]; + + $importProduct->validateRow($rowData, 0); + } + + public function testValidateRowValidatorCheck() + { + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['addRowError', 'getOptionEntity']) + ->getMock(); + + $this->validator->expects($this->once())->method('isValid')->willReturn(false); + $messages = ['validator message']; + $this->validator->expects($this->once())->method('getMessages')->willReturn($messages); + $importProduct->expects($this->at(0))->method('addRowError')->with($messages[0]); + $this->setPropertyValue($importProduct, 'validator', $this->validator); + //suppress option validation + $this->_rewriteGetOptionEntityInImportProduct($importProduct); + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => 'sku', + ]; + $rowNum = 0; + $this->setPropertyValue($importProduct, '_invalidRows', [$rowNum => '']); + + $importProduct->validateRow($rowData, $rowNum); + } + + /** + * @dataProvider validateRowCheckSpecifiedSkuDataProvider + */ + public function testValidateRowCheckSpecifiedSku($sku, $expectedError) + { + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['addRowError', 'getOptionEntity', 'getRowScope']) + ->getMock(); + + $rowNum = 0; + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => $sku, + \Magento\CatalogImportExport\Model\Import\Product::COL_STORE => '', + ]; + + $this->storeResolver->expects($this->any())->method('getStoreCodeToId')->willReturn(null); + $this->setPropertyValue($importProduct, 'storeResolver', $this->storeResolver); + $this->setPropertyValue($importProduct, 'skuProcessor', $this->skuProcessor); + + $this->_suppressValidateRowOptionValidatorInvalidRows($importProduct); + + $importProduct + ->expects($this->once()) + ->method('getRowScope') + ->willReturn(\Magento\CatalogImportExport\Model\Import\Product::SCOPE_STORE); + $importProduct->expects($this->at(1))->method('addRowError')->with($expectedError, $rowNum)->willReturn(null); + + $importProduct->validateRow($rowData, $rowNum); + } + + public function testValidateRowProcessEntityIncrement() + { + $count = 0; + $rowNum = 0; + $this->setPropertyValue($this->importProduct, '_processedEntitiesCount', $count); + $rowData = [\Magento\CatalogImportExport\Model\Import\Product::COL_SKU => '']; + //suppress validator + $this->_setValidatorMockInImportProduct($this->importProduct); + $this->importProduct->validateRow($rowData, $rowNum); + $this->assertEquals(++$count, $this->importProduct->getProcessedEntitiesCount()); + } + + public function testValidateRowValidateExistingProductTypeAddNewSku() + { + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['addRowError', 'getOptionEntity']) + ->getMock(); + $sku = 'sku'; + $rowNum = 0; + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => $sku, + ]; + $oldSku = [ + $sku => [ + 'entity_id' => 'entity_id_val', + 'type_id' => 'type_id_val', + 'attr_set_id' => 'attr_set_id_val', + ], + ]; + + $_productTypeModels = [ + $oldSku[$sku]['type_id'] => 'type_id_val_val', + ]; + $this->setPropertyValue($importProduct, '_productTypeModels', $_productTypeModels); + + $_attrSetIdToName = [ + $oldSku[$sku]['attr_set_id'] => 'attr_set_code_val' + ]; + $this->setPropertyValue($importProduct, '_attrSetIdToName', $_attrSetIdToName); + + $this->setPropertyValue($importProduct, '_oldSku', $oldSku); + + $expectedData = [ + 'entity_id' => $oldSku[$sku]['entity_id'], //entity_id_val + 'type_id' => $oldSku[$sku]['type_id'],// type_id_val + 'attr_set_id' => $oldSku[$sku]['attr_set_id'], //attr_set_id_val + 'attr_set_code' => $_attrSetIdToName[$oldSku[$sku]['attr_set_id']],//attr_set_id_val + ]; + $this->skuProcessor->expects($this->once())->method('addNewSku')->with($sku, $expectedData); + $this->setPropertyValue($importProduct, 'skuProcessor', $this->skuProcessor); + + $this->_suppressValidateRowOptionValidatorInvalidRows($importProduct); + + $importProduct->validateRow($rowData, $rowNum); + } + + public function testValidateRowValidateExistingProductTypeAddErrorRowCall() + { + $sku = 'sku'; + $rowNum = 0; + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => $sku, + ]; + $oldSku = [ + $sku => [ + 'type_id' => 'type_id_val', + ], + ]; + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['addRowError', 'getOptionEntity']) + ->getMock(); + + $this->setPropertyValue($importProduct, '_oldSku', $oldSku); + $importProduct->expects($this->once())->method('addRowError')->with( + \Magento\CatalogImportExport\Model\Import\Product\Validator::ERROR_TYPE_UNSUPPORTED, + $rowNum + ); + + $this->_suppressValidateRowOptionValidatorInvalidRows($importProduct); + + $importProduct->validateRow($rowData, $rowNum); + } + + public function testValidateRowValidateExistingProductTypeResetSku() + { + $sku = 'sku'; + $rowNum = 0; + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => $sku, + ]; + $oldSku = [ + $sku => [ + 'type_id' => 'type_id_val', + ], + ]; + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['addRowError', 'getOptionEntity']) + ->getMock(); + + $this->setPropertyValue($importProduct, '_oldSku', $oldSku); + + //suppress option validation + $this->_rewriteGetOptionEntityInImportProduct($importProduct); + //suppress validator + $this->_setValidatorMockInImportProduct($importProduct); + + $expectedSku = false; + $newSku = [ + 'attr_set_code' => 'new_attr_set_code', + 'type_id' => 'new_type_id_val', + ]; + $this->skuProcessor->expects($this->once())->method('getNewSku')->with($expectedSku)->willReturn($newSku); + $this->setPropertyValue($importProduct, 'skuProcessor', $this->skuProcessor); + $productType = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType') + ->disableOriginalConstructor() + ->getMock(); + $this->setPropertyValue($importProduct, '_productTypeModels', [ + $newSku['type_id'] => $productType + ]); + + $importProduct->validateRow($rowData, $rowNum); + } + + /** + * @dataProvider validateRowValidateNewProductTypeAddRowErrorCallDataProvider + */ + public function testValidateRowValidateNewProductTypeAddRowErrorCall( + $colType, + $productTypeModelsColType, + $colAttrSet, + $attrSetNameToIdColAttrSet, + $error + ) { + $sku = 'sku'; + $rowNum = 0; + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => $sku, + \Magento\CatalogImportExport\Model\Import\Product::COL_TYPE => $colType, + \Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET => $colAttrSet, + ]; + $_attrSetNameToId = [ + $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET] => $attrSetNameToIdColAttrSet, + ]; + $_productTypeModels = [ + $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE] => $productTypeModelsColType, + ]; + $oldSku = [ + $sku => null, + ]; + + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['addRowError', 'getOptionEntity']) + ->getMock(); + + $this->setPropertyValue($importProduct, '_oldSku', $oldSku); + $this->setPropertyValue($importProduct, '_productTypeModels', $_productTypeModels); + $this->setPropertyValue($importProduct, '_attrSetNameToId', $_attrSetNameToId); + + $importProduct->expects($this->once())->method('addRowError')->with( + $error, + $rowNum + ); + $this->_suppressValidateRowOptionValidatorInvalidRows($importProduct); + + $importProduct->validateRow($rowData, $rowNum); + } + + public function testValidateRowValidateNewProductTypeGetNewSkuCall() + { + $sku = 'sku'; + $rowNum = 0; + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => $sku, + \Magento\CatalogImportExport\Model\Import\Product::COL_TYPE => 'value', + \Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET => 'value', + ]; + $_productTypeModels = [ + $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE] => 'value', + ]; + $oldSku = [ + $sku => null, + ]; + $_attrSetNameToId = [ + $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET] => 'attr_set_code_val' + ]; + $expectedData = [ + 'entity_id' => null, + 'type_id' => $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE],//value + //attr_set_id_val + 'attr_set_id' => + $_attrSetNameToId[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET]], + 'attr_set_code' => $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET],//value + ]; + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['addRowError', 'getOptionEntity']) + ->getMock(); + + $this->setPropertyValue($importProduct, '_oldSku', $oldSku); + $this->setPropertyValue($importProduct, '_productTypeModels', $_productTypeModels); + $this->setPropertyValue($importProduct, '_attrSetNameToId', $_attrSetNameToId); + + $this->skuProcessor->expects($this->once())->method('getNewSku')->willReturn(null); + $this->skuProcessor->expects($this->once())->method('addNewSku')->with($sku, $expectedData); + $this->setPropertyValue($importProduct, 'skuProcessor', $this->skuProcessor); + + $this->_suppressValidateRowOptionValidatorInvalidRows($importProduct); + + $importProduct->validateRow($rowData, $rowNum); + } + + public function testValidateRowValidateNewProductTypeResetSku() + { + $this->markTestSkipped( + 'No chance to assert sku resetting due to mutually exclusive condition: + !isset($this->_invalidRows[$rowNum]) and isset($this->_invalidRows[$rowNum]) should be true simultaneously' + ); + } + + public function testValidateDefaultScopeNotValidAttributesResetSku() + { + $this->markTestSkipped('No chance to assert sku resetting because it is not used later in method.'); + } + + public function testValidateRowSetAttributeSetCodeIntoRowData() + { + $sku = 'sku'; + $rowNum = 0; + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => $sku, + \Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET => 'col_attr_set_val', + ]; + $expectedAttrSetCode = 'new_attr_set_code'; + $newSku = [ + 'attr_set_code' => $expectedAttrSetCode, + 'type_id' => 'new_type_id_val', + ]; + $expectedRowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => $sku, + \Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET => $newSku['attr_set_code'], + ]; + $oldSku = [ + $sku => [ + 'type_id' => 'type_id_val', + ], + ]; + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['addRowError', 'getOptionEntity']) + ->getMock(); + + $this->setPropertyValue($importProduct, '_oldSku', $oldSku); + $this->skuProcessor->expects($this->any())->method('getNewSku')->willReturn($newSku); + $this->setPropertyValue($importProduct, 'skuProcessor', $this->skuProcessor); + + $productType = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType') + ->disableOriginalConstructor() + ->getMock(); + $productType->expects($this->once())->method('isRowValid')->with($expectedRowData); + $this->setPropertyValue($importProduct, '_productTypeModels', [ + $newSku['type_id'] => $productType + ]); + + //suppress option validation + $this->_rewriteGetOptionEntityInImportProduct($importProduct); + //suppress validator + $this->_setValidatorMockInImportProduct($importProduct); + + $importProduct->validateRow($rowData, $rowNum); + } + + public function testValidateValidateOptionEntity() + { + $sku = 'sku'; + $rowNum = 0; + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => $sku, + \Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET => 'col_attr_set_val', + ]; + $oldSku = [ + $sku => [ + 'type_id' => 'type_id_val', + ], + ]; + $importProduct = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product') + ->disableOriginalConstructor() + ->setMethods(['addRowError', 'getOptionEntity']) + ->getMock(); + + $this->setPropertyValue($importProduct, '_oldSku', $oldSku); + + //suppress validator + $this->_setValidatorMockInImportProduct($importProduct); + $this->setPropertyValue($importProduct, '_invalidRows', [0 => '']); + + $option = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product\Option') + ->disableOriginalConstructor() + ->getMock(); + $option->expects($this->once())->method('validateRow')->with($rowData, $rowNum); + $importProduct->expects($this->once())->method('getOptionEntity')->willReturn($option); + + $importProduct->validateRow($rowData, $rowNum); + } + + /** + * @dataProvider populateToUrlGenerationReturnNullDataProvider + */ + public function testPopulateToUrlGenerationReturnNull($rowData, $newSku) + { + $productMock = $this->getMock( + '\Magento\Catalog\Model\Product', + ['addData'], + [], + '', + false + ); + + $this->catalogProductFactory + ->expects($this->once()) + ->method('create') + ->willReturn($productMock); + + $this->skuProcessor + ->expects($this->once()) + ->method('getNewSku') + ->willReturn($newSku); + + $result = $this->importProduct->_populateToUrlGeneration($rowData); + + $this->assertNull($result); + + } + + public function testPopulateToUrlGenerationReturnProduct() + { + $rowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => 'value' + ]; + $newSku = [ + 'entity_id' => 'new sku value', + ]; + $expectedRowData = [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => 'value', + 'entity_id' => $newSku['entity_id'], + ]; + $productMock = $this->getMock( + '\Magento\Catalog\Model\Product', + ['addData'], + [], + '', + false + ); + + $productMock + ->expects($this->once()) + ->method('addData') + ->with($expectedRowData); + + $this->catalogProductFactory + ->expects($this->once()) + ->method('create') + ->willReturn($productMock); + + $this->skuProcessor + ->expects($this->once()) + ->method('getNewSku') + ->willReturn($newSku); + + $result = $this->importProduct->_populateToUrlGeneration($rowData); + + $this->assertEquals($productMock, $result); + } + + public function populateToUrlGenerationReturnNullDataProvider() + { + return [ + [ + '$rowData' => [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => 'value' + ], + '$newSku' => [ + 'entity_id' => null, + ], + ], + [ + '$rowData' => [ + \Magento\CatalogImportExport\Model\Import\Product::COL_SKU => 'value' + ], + '$newSku' => [], + ], + ]; + } + + public function validateRowValidateNewProductTypeAddRowErrorCallDataProvider() + { + return [ + [ + '$colType' => null, + '$productTypeModelsColType' => 'value', + '$colAttrSet' => null, + '$attrSetNameToIdColAttrSet' => null, + '$error' => \Magento\CatalogImportExport\Model\Import\Product\Validator::ERROR_INVALID_TYPE + ], + [ + '$colType' => 'value', + '$productTypeModelsColType' => null, + '$colAttrSet' => null, + '$attrSetNameToIdColAttrSet' => null, + '$error' => \Magento\CatalogImportExport\Model\Import\Product\Validator::ERROR_INVALID_TYPE, + ], + [ + '$colType' => 'value', + '$productTypeModelsColType' => 'value', + '$colAttrSet' => null, + '$attrSetNameToIdColAttrSet' => 'value', + '$error' => \Magento\CatalogImportExport\Model\Import\Product\Validator::ERROR_INVALID_ATTR_SET, + ], + [ + '$colType' => 'value', + '$productTypeModelsColType' => 'value', + '$colAttrSet' => 'value', + '$attrSetNameToIdColAttrSet' => null, + '$error' => \Magento\CatalogImportExport\Model\Import\Product\Validator::ERROR_INVALID_ATTR_SET, + ], + ]; + } + + public function validateRowCheckSpecifiedSkuDataProvider() + { + return [ + [ + '$sku' => null, + '$expectedError' => \Magento\CatalogImportExport\Model\Import\Product\Validator::ERROR_SKU_IS_EMPTY, + ], + [ + '$sku' => false, + '$expectedError' => \Magento\CatalogImportExport\Model\Import\Product\Validator::ERROR_ROW_IS_ORPHAN, + ], + [ + '$sku' => 'sku', + '$expectedError' => \Magento\CatalogImportExport\Model\Import\Product\Validator::ERROR_INVALID_STORE, + ], + ]; + } + + public function validateRowDeleteBehaviourDataProvider() + { + return [ + [ + '$rowScope' => \Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT, + '$oldSku' => null, + '$expectedResult' => false, + ], + [ + '$rowScope' => null, + '$oldSku' => null, + '$expectedResult' => true, + ], + [ + '$rowScope' => null, + '$oldSku' => true, + '$expectedResult' => true, + ], + [ + '$rowScope' => \Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT, + '$oldSku' => true, + '$expectedResult' => true, + ], + ]; + } + + /** + * @return array + */ + public function isAttributeValidAssertAttrValidDataProvider() + { + return [ + [ + '$attrParams' => [ + 'type' => 'varchar', + ], + '$rowData' => [ + 'code' => str_repeat( + 'a', + \Magento\CatalogImportExport\Model\Import\Product::DB_MAX_VARCHAR_LENGTH - 1 + ), + ], + ], + [ + '$attrParams' => [ + 'type' => 'decimal', + ], + '$rowData' => [ + 'code' => 10, + ], + ], + [ + '$attrParams' => [ + 'type' => 'select', + 'options' => ['code' => 1] + ], + '$rowData' => [ + 'code' => 'code', + ], + ], + [ + '$attrParams' => [ + 'type' => 'multiselect', + 'options' => ['code' => 1] + ], + '$rowData' => [ + 'code' => 'code', + ], + ], + [ + '$attrParams' => [ + 'type' => 'int', + ], + '$rowData' => [ + 'code' => 1000, + ], + ], + [ + '$attrParams' => [ + 'type' => 'datetime', + ], + '$rowData' => [ + 'code' => "5 September 2015", + ], + ], + [ + '$attrParams' => [ + 'type' => 'text', + ], + '$rowData' => [ + 'code' => str_repeat( + 'a', + \Magento\CatalogImportExport\Model\Import\Product::DB_MAX_TEXT_LENGTH - 1 + ), + ], + ], + ]; + } + + /** + * @return array + */ + public function isAttributeValidAssertAttrInvalidDataProvider() + { + return [ + [ + '$attrParams' => [ + 'type' => 'varchar', + ], + '$rowData' => [ + 'code' => str_repeat( + 'a', + \Magento\CatalogImportExport\Model\Import\Product::DB_MAX_VARCHAR_LENGTH + 1 + ), + ], + ], + [ + '$attrParams' => [ + 'type' => 'decimal', + ], + '$rowData' => [ + 'code' => 'incorrect', + ], + ], + [ + '$attrParams' => [ + 'type' => 'select', + 'not options' => null, + ], + '$rowData' => [ + 'code' => 'code', + ], + ], + [ + '$attrParams' => [ + 'type' => 'multiselect', + 'not options' => null, + ], + '$rowData' => [ + 'code' => 'code', + ], + ], + [ + '$attrParams' => [ + 'type' => 'int', + ], + '$rowData' => [ + 'code' => 'not int', + ], + ], + [ + '$attrParams' => [ + 'type' => 'datetime', + ], + '$rowData' => [ + 'code' => "incorrect datetime", + ], + ], + [ + '$attrParams' => [ + 'type' => 'text', + ], + '$rowData' => [ + 'code' => str_repeat( + 'a', + \Magento\CatalogImportExport\Model\Import\Product::DB_MAX_TEXT_LENGTH + 1 + ), + ], + ], + ]; + } + + /** + * @return array + */ + public function getRowScopeDataProvider() + { + $colSku = \Magento\CatalogImportExport\Model\Import\Product::COL_SKU; + $colStore = \Magento\CatalogImportExport\Model\Import\Product::COL_STORE; + + return [ + [ + '$rowData' => [ + $colSku => null, + $colStore => 'store', + ], + '$expectedResult' => \Magento\CatalogImportExport\Model\Import\Product::SCOPE_NULL + ], + [ + '$rowData' => [ + $colSku => 'sku', + $colStore => null, + ], + '$expectedResult' => \Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT + ], + [ + '$rowData' => [ + $colSku => 'sku', + $colStore => 'store', + ], + '$expectedResult' => \Magento\CatalogImportExport\Model\Import\Product::SCOPE_STORE + ], + ]; + } + + /** + * @return array + */ + public function validateRowIsAlreadyValidatedDataProvider() + { + return [ + [ + '$isInvalidRow' => true, + '$expectedResult' => false, + ], + [ + '$isInvalidRow' => null, + '$expectedResult' => true, + ], + ]; + } + + /** + * @return mixed + */ + public function returnQuoteCallback() + { + $args = func_get_args(); + return str_replace('?', (is_array($args[1]) ? implode(',', $args[1]) : $args[1]), $args[0]); + } + + /** + * @param $object + * @param $methodName + * @param array $parameters + * @return mixed + */ + protected function invokeMethod(&$object, $methodName, array $parameters = []) + { + $reflection = new \ReflectionClass(get_class($object)); + $method = $reflection->getMethod($methodName); + $method->setAccessible(true); + + return $method->invokeArgs($object, $parameters); + } + + /** + * @param $object + * @param $property + * @param $value + */ + protected function setPropertyValue(&$object, $property, $value) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionProperty = $reflection->getProperty($property); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($object, $value); + return $object; + } + + /** + * @param $object + * @param $property + */ + protected function getPropertyValue(&$object, $property) + { + $reflection = new \ReflectionClass(get_class($object)); + $reflectionProperty = $reflection->getProperty($property); + $reflectionProperty->setAccessible(true); + + return $reflectionProperty->getValue($object); + } + + /** + * @param $object + * @param $methodName + * @param array $parameters + * @return mixed + */ + protected function overrideMethod(&$object, $methodName, array $parameters = []) + { + $reflection = new \ReflectionClass(get_class($object)); + + $method = $reflection->getMethod($methodName); + + return $method->invokeArgs($object, $parameters); + } + + /** + * Used in group of validateRow method's tests. + * Suppress part of validateRow func-ty to run some tests separately and bypass errors. + * + * @see _rewriteGetOptionEntityInImportProduct() + * @see _setValidatorMockInImportProduct() + * @param \Magento\CatalogImportExport\Model\Import\Product + * Param should go with rewritten getOptionEntity method. + * @return \Magento\CatalogImportExport\Model\Import\Product\Option|\PHPUnit_Framework_MockObject_MockObject + */ + private function _suppressValidateRowOptionValidatorInvalidRows($importProduct) + { + //suppress option validation + $this->_rewriteGetOptionEntityInImportProduct($importProduct); + //suppress validator + $this->_setValidatorMockInImportProduct($importProduct); + $this->setPropertyValue($importProduct, '_invalidRows', [0 => '']); + + return $importProduct; + } + + /** + * Used in group of validateRow method's tests. + * Set validator mock in importProduct, return true for isValid method. + * + * @param \Magento\CatalogImportExport\Model\Import\Product + * @return \Magento\CatalogImportExport\Model\Import\Product\Validator|\PHPUnit_Framework_MockObject_MockObject + */ + private function _setValidatorMockInImportProduct($importProduct) + { + $this->validator->expects($this->once())->method('isValid')->willReturn(true); + $this->setPropertyValue($importProduct, 'validator', $this->validator); + + return $importProduct; + } + + /** + * Used in group of validateRow method's tests. + * Make getOptionEntity return option mock. + * + * @param \Magento\CatalogImportExport\Model\Import\Product + * Param should go with rewritten getOptionEntity method. + * @return \Magento\CatalogImportExport\Model\Import\Product\Option|\PHPUnit_Framework_MockObject_MockObject + */ + private function _rewriteGetOptionEntityInImportProduct($importProduct) + { + $option = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Product\Option') + ->disableOriginalConstructor() + ->getMock(); + $importProduct->expects($this->once())->method('getOptionEntity')->willReturn($option); + + return $importProduct; + } +} diff --git a/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4d765a348668e52db0ac6344d2359c6f867bc90e --- /dev/null +++ b/app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php @@ -0,0 +1,186 @@ +<?php + +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CatalogImportExport\Test\Unit\Model\Import; + +class UploaderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\MediaStorage\Helper\File\Storage\Database|\PHPUnit_Framework_MockObject_MockObject + */ + protected $coreFileStorageDb; + + /** + * @var \Magento\MediaStorage\Helper\File\Storage|\PHPUnit_Framework_MockObject_MockObject + */ + protected $coreFileStorage; + + /** + * @var \Magento\Framework\Image\AdapterFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $imageFactory; + + /** + * @var \Magento\MediaStorage\Model\File\Validator\NotProtectedExtension|\PHPUnit_Framework_MockObject_MockObject + */ + protected $validator; + + /** + * @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + protected $filesystem; + + /** + * @var \Magento\Framework\Filesystem\File\ReadFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $readFactory; + + /** + * @var \Magento\Framework\Filesystem\Directory\Writer| \PHPUnit_Framework_MockObject_MockObject + */ + protected $directoryMock; + + /** + * @var \Magento\CatalogImportExport\Model\Import\Uploader|\PHPUnit_Framework_MockObject_MockObject + */ + protected $uploader; + + protected function setUp() + { + $this->coreFileStorageDb = $this->getMockBuilder('\Magento\MediaStorage\Helper\File\Storage\Database') + ->disableOriginalConstructor() + ->getMock(); + + $this->coreFileStorage = $this->getMockBuilder('\Magento\MediaStorage\Helper\File\Storage') + ->disableOriginalConstructor() + ->getMock(); + + $this->imageFactory = $this->getMockBuilder('\Magento\Framework\Image\AdapterFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->validator = $this->getMockBuilder('\Magento\MediaStorage\Model\File\Validator\NotProtectedExtension') + ->disableOriginalConstructor() + ->getMock(); + + $this->readFactory = $this->getMockBuilder('\Magento\Framework\Filesystem\File\ReadFactory') + ->disableOriginalConstructor() + ->getMock(); + + $this->directoryMock = $this->getMockBuilder('\Magento\Framework\Filesystem\Directory\Writer') + ->setMethods(['writeFile', 'getRelativePath']) + ->disableOriginalConstructor() + ->getMock(); + + $this->filesystem = $this->getMockBuilder('\Magento\Framework\Filesystem') + ->disableOriginalConstructor() + ->setMethods(['getDirectoryWrite']) + ->getMock(); + $this->filesystem->expects($this->any()) + ->method('getDirectoryWrite') + ->will($this->returnValue($this->directoryMock)); + + $this->uploader = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Uploader') + ->setConstructorArgs([ + $this->coreFileStorageDb, + $this->coreFileStorage, + $this->imageFactory, + $this->validator, + $this->filesystem, + $this->readFactory, + ]) + ->getMock(); + } + + /** + * @dataProvider moveFileUrlDataProvider + */ + public function testMoveFileUrl($fileUrl, $expectedHost, $expectedFileName) + { + $expectedRelativeFilePath = $this->uploader->getTmpDir() . '/' . $expectedFileName; + $this->directoryMock->expects($this->any())->method('getRelativePath')->with($expectedRelativeFilePath); + // Check writeFile() method invoking. + $this->directoryMock->expects($this->any())->method('writeFile')->will($this->returnValue(null)); + + // Create adjusted reader which does not validate path. + $readMock = $this->getMockBuilder('Magento\Framework\Filesystem\File\Read') + ->disableOriginalConstructor() + ->setMethods(['readAll']) + ->getMock(); + // Check readAll() method invoking. + $readMock->expects($this->once())->method('readAll')->will($this->returnValue(null)); + + $this->readFactory = $this->getMockBuilder('\Magento\Framework\Filesystem\File\ReadFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + // Check create() method invoking with expected argument. + $this->readFactory->expects($this->once()) + ->method('create') + ->will($this->returnValue($readMock))->with($expectedHost); + + $uploaderMock = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Uploader') + ->setConstructorArgs([ + $this->coreFileStorageDb, + $this->coreFileStorage, + $this->imageFactory, + $this->validator, + $this->filesystem, + $this->readFactory, + ]) + ->setMethods(['_setUploadFile', 'save', 'getTmpDir']) + ->getMock(); + + //Check invoking of getTmpDir(), _setUploadFile(), save() methods. + $uploaderMock->expects($this->any())->method('getTmpDir')->will($this->returnValue('')); + $uploaderMock->expects($this->once())->method('_setUploadFile')->will($this->returnSelf()); + $uploaderMock->expects($this->once())->method('save')->will($this->returnValue(['name' => null])); + + $uploaderMock->move($fileUrl); + } + + public function testMoveFileName() + { + $fileName = 'test_uploader_file'; + $expectedRelativeFilePath = $this->uploader->getTmpDir() . '/' . $fileName; + $this->directoryMock->expects($this->any())->method('getRelativePath')->with($expectedRelativeFilePath); + + $uploaderMock = $this->getMockBuilder('\Magento\CatalogImportExport\Model\Import\Uploader') + ->setConstructorArgs([ + $this->coreFileStorageDb, + $this->coreFileStorage, + $this->imageFactory, + $this->validator, + $this->filesystem, + $this->readFactory, + ]) + ->setMethods(['_setUploadFile', 'save', 'getTmpDir']) + ->getMock(); + + //Check invoking of getTmpDir(), _setUploadFile(), save() methods. + $uploaderMock->expects($this->once())->method('getTmpDir')->will($this->returnValue('')); + $uploaderMock->expects($this->once())->method('_setUploadFile')->will($this->returnSelf()); + $uploaderMock->expects($this->once())->method('save')->will($this->returnValue(['name' => null])); + + $uploaderMock->move($fileName); + } + + public function moveFileUrlDataProvider() + { + return [ + [ + '$fileUrl' => 'http://test_uploader_file', + '$expectedHost' => 'test_uploader_file', + '$expectedFileName' => 'httptest_uploader_file', + ], + [ + '$fileUrl' => 'https://!:^&`;file', + '$expectedHost' => '!:^&`;file', + '$expectedFileName' => 'httpsfile', + ], + ]; + } +} diff --git a/app/code/Magento/CatalogImportExport/composer.json b/app/code/Magento/CatalogImportExport/composer.json index 1ab9375dad08c585e3599ef4f77445e5c77dc546..fe82fc10d1355d83dbc6a71cbe7ec882504f4f0d 100644 --- a/app/code/Magento/CatalogImportExport/composer.json +++ b/app/code/Magento/CatalogImportExport/composer.json @@ -3,20 +3,21 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-import-export": "0.74.0-beta10", - "magento/module-indexer": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-import-export": "0.74.0-beta13", + "magento/module-indexer": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "ext-ctype": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CatalogImportExport/etc/di.xml b/app/code/Magento/CatalogImportExport/etc/di.xml index 9fda72ab31642864790ce7c2d92ce038021c7f38..7229759817235f3347a2943f9534db663f49b318 100644 --- a/app/code/Magento/CatalogImportExport/etc/di.xml +++ b/app/code/Magento/CatalogImportExport/etc/di.xml @@ -18,7 +18,6 @@ <type name="Magento\CatalogImportExport\Model\Import\Product\Validator"> <arguments> <argument name="validators" xsi:type="array"> - <item name="Ñategory" xsi:type="object">Magento\CatalogImportExport\Model\Import\Product\Validator\Category</item> <item name="groupPrice" xsi:type="object">Magento\CatalogImportExport\Model\Import\Product\Validator\GroupPrice</item> <item name="media" xsi:type="object">Magento\CatalogImportExport\Model\Import\Product\Validator\Media</item> <item name="superProductsSku" xsi:type="object">Magento\CatalogImportExport\Model\Import\Product\Validator\SuperProductsSku</item> diff --git a/app/code/Magento/CatalogInventory/Model/Adminhtml/Stock/Item.php b/app/code/Magento/CatalogInventory/Model/Adminhtml/Stock/Item.php index 56c05595a2c4c93020ab65fe15be63086dbba902..92704735fe73e9978cb0f321f9058a28ff4933e1 100644 --- a/app/code/Magento/CatalogInventory/Model/Adminhtml/Stock/Item.php +++ b/app/code/Magento/CatalogInventory/Model/Adminhtml/Stock/Item.php @@ -36,7 +36,7 @@ class Item extends \Magento\CatalogInventory\Model\Stock\Item * @param StockItemRepositoryInterface $stockItemRepository * @param GroupManagementInterface $groupManagement * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -52,7 +52,7 @@ class Item extends \Magento\CatalogInventory\Model\Stock\Item StockItemRepositoryInterface $stockItemRepository, GroupManagementInterface $groupManagement, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/CatalogInventory/Model/Config/Backend/AbstractValue.php b/app/code/Magento/CatalogInventory/Model/Config/Backend/AbstractValue.php index 5ba08d312361ab354aafa312642afcbf2b8986cd..8d19df64396b0a392492c7682f691c7f7de502d3 100644 --- a/app/code/Magento/CatalogInventory/Model/Config/Backend/AbstractValue.php +++ b/app/code/Magento/CatalogInventory/Model/Config/Backend/AbstractValue.php @@ -28,7 +28,7 @@ abstract class AbstractValue extends \Magento\Framework\App\Config\Value * @param \Magento\CatalogInventory\Api\StockIndexInterface $stockIndex * @param \Magento\CatalogInventory\Model\Indexer\Stock\Processor $stockIndexerProcessor * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -38,7 +38,7 @@ abstract class AbstractValue extends \Magento\Framework\App\Config\Value \Magento\CatalogInventory\Api\StockIndexInterface $stockIndex, \Magento\CatalogInventory\Model\Indexer\Stock\Processor $stockIndexerProcessor, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_stockIndexerProcessor = $stockIndexerProcessor; diff --git a/app/code/Magento/CatalogInventory/Model/Stock/Item.php b/app/code/Magento/CatalogInventory/Model/Stock/Item.php index 15fb84875aafeac95108233e7f4ea482fc295a26..ede0023bdd3aef9a658064fa327fc56fe57041ce 100644 --- a/app/code/Magento/CatalogInventory/Model/Stock/Item.php +++ b/app/code/Magento/CatalogInventory/Model/Stock/Item.php @@ -100,7 +100,7 @@ class Item extends AbstractExtensibleModel implements StockItemInterface * @param StockRegistryInterface $stockRegistry * @param StockItemRepositoryInterface $stockItemRepository * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -115,7 +115,7 @@ class Item extends AbstractExtensibleModel implements StockItemInterface StockRegistryInterface $stockRegistry, StockItemRepositoryInterface $stockItemRepository, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/CatalogInventory/Model/Stock/Status.php b/app/code/Magento/CatalogInventory/Model/Stock/Status.php index 4b91ba19d267e8dea109408f44978215d7c3f29c..bd4b37d40da7a0f5f580db229e580b9703d7e48d 100644 --- a/app/code/Magento/CatalogInventory/Model/Stock/Status.php +++ b/app/code/Magento/CatalogInventory/Model/Stock/Status.php @@ -42,7 +42,7 @@ class Status extends AbstractExtensibleModel implements StockStatusInterface * @param AttributeValueFactory $customAttributeFactory * @param StockRegistryInterface $stockRegistry * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -52,7 +52,7 @@ class Status extends AbstractExtensibleModel implements StockStatusInterface AttributeValueFactory $customAttributeFactory, StockRegistryInterface $stockRegistry, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/CatalogInventory/Model/System/Config/Backend/Minsaleqty.php b/app/code/Magento/CatalogInventory/Model/System/Config/Backend/Minsaleqty.php index c7910eac3b76f6e486fedf4c56b6b019d50ea3f2..0c7a808023c1b13585d9d12ede668a0bbc8f4e39 100644 --- a/app/code/Magento/CatalogInventory/Model/System/Config/Backend/Minsaleqty.php +++ b/app/code/Magento/CatalogInventory/Model/System/Config/Backend/Minsaleqty.php @@ -23,7 +23,7 @@ class Minsaleqty extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\CatalogInventory\Helper\Minsaleqty $catalogInventoryMinsaleqty * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -32,7 +32,7 @@ class Minsaleqty extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\CatalogInventory\Helper\Minsaleqty $catalogInventoryMinsaleqty, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_catalogInventoryMinsaleqty = $catalogInventoryMinsaleqty; diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json index 53a6c49f0c71db330e5c0fe5fa469537b435f393..17807abf00284e37befeee24f9146e7822ab1675 100644 --- a/app/code/Magento/CatalogInventory/composer.json +++ b/app/code/Magento/CatalogInventory/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-indexer": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-indexer": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CatalogInventory/etc/service_data_attributes.xml b/app/code/Magento/CatalogInventory/etc/extension_attributes.xml similarity index 91% rename from app/code/Magento/CatalogInventory/etc/service_data_attributes.xml rename to app/code/Magento/CatalogInventory/etc/extension_attributes.xml index 587b98b401a0981d8ca14b75242f0adac67312a2..aeb9bc602fbae927efd85d59a8019da5df6b4669 100644 --- a/app/code/Magento/CatalogInventory/etc/service_data_attributes.xml +++ b/app/code/Magento/CatalogInventory/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> <attribute code="stock_item" type="Magento\CatalogInventory\Api\Data\StockItemInterface"> <resources> @@ -13,4 +13,4 @@ </resources> </attribute> </extension_attributes> -</config> +</config> \ No newline at end of file diff --git a/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Main.php b/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Main.php index 60c9971f2da7be9f2501f0e8ff1ece128fa045ca..9b50207884c18ed1b9a124e751c4a485cf2c347b 100644 --- a/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Main.php +++ b/app/code/Magento/CatalogRule/Block/Adminhtml/Promo/Catalog/Edit/Tab/Main.php @@ -194,8 +194,8 @@ class Main extends Generic implements TabInterface 'date', [ 'name' => 'from_date', - 'label' => __('From Date'), - 'title' => __('From Date'), + 'label' => __('From'), + 'title' => __('From'), 'input_format' => \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT, 'date_format' => $dateFormat ] @@ -205,8 +205,8 @@ class Main extends Generic implements TabInterface 'date', [ 'name' => 'to_date', - 'label' => __('To Date'), - 'title' => __('To Date'), + 'label' => __('To'), + 'title' => __('To'), 'input_format' => \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT, 'date_format' => $dateFormat ] diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Delete.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Delete.php index 008b21e02ea8d993d5957459663fc60ab9ec041a..5806ef74e41cd5d93d147ba617509f4693df7f59 100644 --- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Delete.php +++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/Delete.php @@ -30,7 +30,7 @@ class Delete extends \Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { $this->messageManager->addError( - __('An error occurred while deleting the rule. Please review the log and try again.') + __('We can\'t delete this rule right now. Please review the log and try again.') ); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); $this->_redirect('catalog_rule/*/edit', ['id' => $this->getRequest()->getParam('id')]); diff --git a/app/code/Magento/CatalogRule/Model/Rule.php b/app/code/Magento/CatalogRule/Model/Rule.php index b38efb9b2276ff0e6510cced940ce451ce6f6540..84bfce2b0c8337189bcc4120e6a1b665b21dbb2c 100644 --- a/app/code/Magento/CatalogRule/Model/Rule.php +++ b/app/code/Magento/CatalogRule/Model/Rule.php @@ -165,7 +165,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\CatalogRule\Model\Indexer\Rule\RuleProductProcessor $ruleProductProcessor * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $relatedCacheTypes * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -187,7 +187,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\CatalogRule\Model\Indexer\Rule\RuleProductProcessor $ruleProductProcessor, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $relatedCacheTypes = [], array $data = [] ) { diff --git a/app/code/Magento/CatalogRule/Setup/InstallSchema.php b/app/code/Magento/CatalogRule/Setup/InstallSchema.php index 610434b70a4448f545de5db717fc93e15dfced94..5c4700a3fb0ae645f1861a08a69526b407ed7e1d 100644 --- a/app/code/Magento/CatalogRule/Setup/InstallSchema.php +++ b/app/code/Magento/CatalogRule/Setup/InstallSchema.php @@ -56,14 +56,14 @@ class InstallSchema implements InstallSchemaInterface \Magento\Framework\DB\Ddl\Table::TYPE_DATE, null, [], - 'From Date' + 'From' ) ->addColumn( 'to_date', \Magento\Framework\DB\Ddl\Table::TYPE_DATE, null, [], - 'To Date' + 'To' ) ->addColumn( 'is_active', diff --git a/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php b/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php index 4b3d8d2edd1875f00b0244b31f82a2796e6bc60e..1d41561cc8cbf9de928157c212e2f8c46882224e 100644 --- a/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php +++ b/app/code/Magento/CatalogRule/Test/Unit/Model/RuleTest.php @@ -72,7 +72,7 @@ class RuleTest extends \PHPUnit_Framework_TestCase $this->productModel = $this->getMock( 'Magento\Catalog\Model\Product', [ - '__wakeup', 'getId' + '__wakeup', 'getId', 'setData' ], [], '', diff --git a/app/code/Magento/CatalogRule/composer.json b/app/code/Magento/CatalogRule/composer.json index 9d501b98952786c42ce0f7d3a1975b605ae940c1..3611281f1c69d49dd4efc8f6044045e0f33614c9 100644 --- a/app/code/Magento/CatalogRule/composer.json +++ b/app/code/Magento/CatalogRule/composer.json @@ -3,19 +3,19 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-rule": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-indexer": "0.74.0-beta10", - "magento/module-import-export": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-rule": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-indexer": "0.74.0-beta13", + "magento/module-import-export": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CatalogRule/view/adminhtml/layout/catalog_rule_promo_catalog_block.xml b/app/code/Magento/CatalogRule/view/adminhtml/layout/catalog_rule_promo_catalog_block.xml index 12c6ed311741b02e937ec3ec3082e1a7d4dc7858..d73e06da7d2557f19b1dbcf771cd1c4b263e0d8c 100644 --- a/app/code/Magento/CatalogRule/view/adminhtml/layout/catalog_rule_promo_catalog_block.xml +++ b/app/code/Magento/CatalogRule/view/adminhtml/layout/catalog_rule_promo_catalog_block.xml @@ -43,7 +43,7 @@ </block> <block class="Magento\Backend\Block\Widget\Grid\Column" as="from_date"> <arguments> - <argument name="header" xsi:type="string" translate="true">Start on</argument> + <argument name="header" xsi:type="string" translate="true">Start</argument> <argument name="type" xsi:type="string">date</argument> <argument name="index" xsi:type="string">from_date</argument> <argument name="column_css_class" xsi:type="string">col-date</argument> @@ -52,7 +52,7 @@ </block> <block class="Magento\Backend\Block\Widget\Grid\Column" as="to_date"> <arguments> - <argument name="header" xsi:type="string" translate="true">End on</argument> + <argument name="header" xsi:type="string" translate="true">End</argument> <argument name="type" xsi:type="string">date</argument> <argument name="default" xsi:type="string">--</argument> <argument name="index" xsi:type="string">to_date</argument> diff --git a/app/code/Magento/CatalogSearch/Block/Advanced/Form.php b/app/code/Magento/CatalogSearch/Block/Advanced/Form.php index f0672c490da62796b2e9fbff531f0687cee4dcc9..479e4dfa72ee70e753f045cb145b52e76a276a1b 100644 --- a/app/code/Magento/CatalogSearch/Block/Advanced/Form.php +++ b/app/code/Magento/CatalogSearch/Block/Advanced/Form.php @@ -14,7 +14,7 @@ namespace Magento\CatalogSearch\Block\Advanced; use Magento\CatalogSearch\Model\Advanced; use Magento\Directory\Model\CurrencyFactory; use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; -use Magento\Framework\Data\Collection\Db; +use Magento\Framework\Data\Collection\AbstractDb as DbCollection; use Magento\Framework\View\Element\AbstractBlock; use Magento\Framework\View\Element\BlockInterface; use Magento\Framework\View\Element\Template; @@ -78,7 +78,7 @@ class Form extends Template /** * Retrieve collection of product searchable attributes * - * @return Db + * @return DbCollection */ public function getSearchableAttributes() { diff --git a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Field/Resolver.php b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Field/Resolver.php index c5a09ffe608838c978c6f1ca4ca1719c9ab1aee7..f358659563ada4422a774b61585c34f0f232f2af 100644 --- a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Field/Resolver.php +++ b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Field/Resolver.php @@ -5,15 +5,63 @@ */ namespace Magento\CatalogSearch\Model\Adapter\Mysql\Field; +use Magento\Catalog\Model\Resource\Product\Attribute\Collection as AttributeCollection; +use Magento\Framework\Search\Adapter\Mysql\Field\FieldFactory; +use Magento\Framework\Search\Adapter\Mysql\Field\FieldInterface; use Magento\Framework\Search\Adapter\Mysql\Field\ResolverInterface; class Resolver implements ResolverInterface { + /** + * @var AttributeCollection + */ + private $attributeCollection; + /** + * @var FieldFactory + */ + private $fieldFactory; + + /** + * @param AttributeCollection $attributeCollection + * @param FieldFactory $fieldFactory + */ + public function __construct( + AttributeCollection $attributeCollection, + FieldFactory $fieldFactory + ) { + $this->attributeCollection = $attributeCollection; + $this->fieldFactory = $fieldFactory; + } + /** * {@inheritdoc} */ - public function resolve($fields) + public function resolve(array $fields) { - return 'data_index'; + $resolvedFields = []; + foreach ($fields as $field) { + if ('*' === $field) { + $resolvedFields = [ + $this->fieldFactory->create( + [ + 'attributeId' => null, + 'column' => 'data_index', + 'type' => FieldInterface::TYPE_FULLTEXT + ] + ) + ]; + break; + } + $attribute = $this->attributeCollection->getItemByColumnValue('attribute_code', $field); + $attributeId = $attribute ? $attribute->getId() : 0; + $resolvedFields[$field] = $this->fieldFactory->create( + [ + 'attributeId' => $attributeId, + 'column' => 'data_index', + 'type' => FieldInterface::TYPE_FULLTEXT + ] + ); + } + return $resolvedFields; } } diff --git a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php index 16fea125bdaf16b3f41197c88b812345414a5f40..ba0f61f5119a673433a8d6b8793694827cf064ae 100644 --- a/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php +++ b/app/code/Magento/CatalogSearch/Model/Adapter/Mysql/Filter/Preprocessor.php @@ -11,6 +11,7 @@ use Magento\Framework\App\ScopeResolverInterface; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\Search\Adapter\Mysql\ConditionManager; use Magento\Framework\Search\Adapter\Mysql\Filter\PreprocessorInterface; +use Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer; use Magento\Framework\Search\Request\FilterInterface; class Preprocessor implements PreprocessorInterface @@ -65,24 +66,24 @@ class Preprocessor implements PreprocessorInterface * {@inheritdoc} * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ - public function process(FilterInterface $filter, $isNegation, $query) + public function process(FilterInterface $filter, $isNegation, $query, QueryContainer $queryContainer) { - return $resultQuery = $this->processQueryWithField($filter, $isNegation, $query); + return $resultQuery = $this->processQueryWithField($filter, $isNegation, $query, $queryContainer); } /** * @param FilterInterface $filter * @param bool $isNegation * @param string $query + * @param QueryContainer $queryContainer * @return string - * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - private function processQueryWithField(FilterInterface $filter, $isNegation, $query) + private function processQueryWithField(FilterInterface $filter, $isNegation, $query, QueryContainer $queryContainer) { $currentStoreId = $this->scopeResolver->getScope()->getId(); $attribute = $this->config->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $filter->getField()); - $select = $this->getSelect(); + $select = $this->getConnection()->select(); $table = $attribute->getBackendTable(); if ($filter->getField() == 'price') { $query = str_replace('price', 'min_price', $query); @@ -96,17 +97,23 @@ class Preprocessor implements PreprocessorInterface ->where($query); } else { if ($filter->getType() == FilterInterface::TYPE_TERM) { - $field = $filter->getField(); - $mapper = function ($value) use ($field, $isNegation) { - return ($isNegation ? '-' : '') . $this->attributePrefix . $field . '_' . $value; - }; if (is_array($filter->getValue())) { - $value = implode(' ', array_map($mapper, $filter->getValue())); + $value = sprintf( + '%s IN (%s)', + ($isNegation ? 'NOT' : ''), + implode(',', $filter->getValue()) + ); } else { - $value = $mapper($filter->getValue()); + $value = ($isNegation ? '!' : '') . '= ' . $filter->getValue(); } - - return 'MATCH (data_index) AGAINST (' . $this->getConnection()->quote($value) . ' IN BOOLEAN MODE)'; + $filterQuery = sprintf( + 'cpie.store_id = %d AND cpie.attribute_id = %d AND cpie.value %s', + $this->scopeResolver->getScope()->getId(), + $attribute->getId(), + $value + ); + $queryContainer->addFilter($filterQuery); + return ''; } $ifNullCondition = $this->getConnection()->getIfNullSql('current_store.value', 'main_table.value'); @@ -139,12 +146,4 @@ class Preprocessor implements PreprocessorInterface { return $this->resource->getConnection(Resource::DEFAULT_READ_RESOURCE); } - - /** - * @return \Magento\Framework\DB\Select - */ - private function getSelect() - { - return $this->getConnection()->select(); - } } diff --git a/app/code/Magento/CatalogSearch/Model/Adminhtml/System/Config/Backend/Engine.php b/app/code/Magento/CatalogSearch/Model/Adminhtml/System/Config/Backend/Engine.php index b72299fd5fadbd88fc8773752ccd0d6a02c90106..eb1f48340c3fffa285954b8c6e66ddc690dc0bd2 100644 --- a/app/code/Magento/CatalogSearch/Model/Adminhtml/System/Config/Backend/Engine.php +++ b/app/code/Magento/CatalogSearch/Model/Adminhtml/System/Config/Backend/Engine.php @@ -19,7 +19,7 @@ class Engine extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Indexer\Model\IndexerRegistry $indexerRegistry * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -28,7 +28,7 @@ class Engine extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Indexer\Model\IndexerRegistry $indexerRegistry, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->indexerRegistry = $indexerRegistry; diff --git a/app/code/Magento/CatalogSearch/Model/Fulltext.php b/app/code/Magento/CatalogSearch/Model/Fulltext.php index 63080d4d1a76f607901b3b0d5450c124f4bee783..f202d5352e409481ae7773c35f0fca5305edf6e9 100644 --- a/app/code/Magento/CatalogSearch/Model/Fulltext.php +++ b/app/code/Magento/CatalogSearch/Model/Fulltext.php @@ -6,7 +6,7 @@ namespace Magento\CatalogSearch\Model; use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\Data\Collection\Db; +use Magento\Framework\Data\Collection\AbstractDb as DbCollection; use Magento\Framework\Model\Context; use Magento\Framework\Model\Resource\AbstractResource; use Magento\Framework\Registry; @@ -48,7 +48,7 @@ class Fulltext extends \Magento\Framework\Model\AbstractModel * @param QueryFactory $queryFactory * @param ScopeConfigInterface $scopeConfig * @param AbstractResource $resource - * @param Db $resourceCollection + * @param DbCollection $resourceCollection * @param array $data */ public function __construct( @@ -57,7 +57,7 @@ class Fulltext extends \Magento\Framework\Model\AbstractModel QueryFactory $queryFactory, ScopeConfigInterface $scopeConfig, AbstractResource $resource = null, - Db $resourceCollection = null, + DbCollection $resourceCollection = null, array $data = [] ) { $this->queryFactory = $queryFactory; diff --git a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php index e32fe344ec5842387781c19ac6ed9f0a548afa67..5b220270b0f1be52431477cce1fc3aa73b1900f6 100644 --- a/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php +++ b/app/code/Magento/CatalogSearch/Model/Indexer/Fulltext/Action/Full.php @@ -627,7 +627,7 @@ class Full { if (!isset($this->productEmulators[$typeId])) { $productEmulator = new \Magento\Framework\Object(); - $productEmulator->setIdFieldName('entity_id')->setTypeId($typeId); + $productEmulator->setTypeId($typeId); $this->productEmulators[$typeId] = $productEmulator; } return $this->productEmulators[$typeId]; @@ -651,15 +651,20 @@ class Full $attributeCode = $attribute->getAttributeCode(); if (isset($productData[$attributeCode])) { + + if ('store_id' === $attributeCode) { + continue; + } + $value = $this->getAttributeValue($attribute->getId(), $productData[$attributeCode], $storeId); if ($value) { - if (isset($index[$attributeCode])) { - if (!is_array($index[$attributeCode])) { - $index[$attributeCode] = [$index[$attributeCode]]; + if (isset($index[$attribute->getId()])) { + if (!is_array($index[$attribute->getId()])) { + $index[$attribute->getId()] = [$index[$attribute->getId()]]; } - $index[$attributeCode][] = $value; + $index[$attribute->getId()][] = $value; } else { - $index[$attributeCode] = $value; + $index[$attribute->getId()] = $value; } } } @@ -669,12 +674,10 @@ class Full foreach ($attributeData as $attributeId => $attributeValue) { $value = $this->getAttributeValue($attributeId, $attributeValue, $storeId); if (!empty($value)) { - $attributeCode = $this->getSearchableAttribute($attributeId)->getAttributeCode(); - - if (isset($index[$attributeCode])) { - $index[$attributeCode][$entityId] = $value; + if (isset($index[$attributeId])) { + $index[$attributeId][$entityId] = $value; } else { - $index[$attributeCode] = [$entityId => $value]; + $index[$attributeId] = [$entityId => $value]; } } } diff --git a/app/code/Magento/CatalogSearch/Model/Resource/Engine.php b/app/code/Magento/CatalogSearch/Model/Resource/Engine.php index 15b56ec7b331e6b86069a03172c0656e7f892185..8fb3a099d233d7b3971e6a57764a7641fd6fb127 100644 --- a/app/code/Magento/CatalogSearch/Model/Resource/Engine.php +++ b/app/code/Magento/CatalogSearch/Model/Resource/Engine.php @@ -66,7 +66,7 @@ class Engine extends AbstractDb implements EngineInterface */ protected function _construct() { - $this->_init('catalogsearch_fulltext', 'product_id'); + $this->_init('catalogsearch_fulltext_index_default', 'product_id'); } /** @@ -102,9 +102,15 @@ class Engine extends AbstractDb implements EngineInterface public function saveEntityIndexes($storeId, $entityIndexes, $entity = 'product') { $data = []; - $storeId = (int)$storeId; - foreach ($entityIndexes as $entityId => $index) { - $data[] = ['product_id' => (int)$entityId, 'store_id' => $storeId, 'data_index' => $index]; + foreach ($entityIndexes as $entityId => $productAttributes) { + foreach ($productAttributes as $attributeId => $indexValue) { + $data[] = [ + 'product_id' => (int)$entityId, + 'attribute_id' =>(int)$attributeId, + 'store_id' => (int)$storeId, + 'data_index' => $indexValue + ]; + } } if ($data) { @@ -187,10 +193,6 @@ class Engine extends AbstractDb implements EngineInterface { $where = []; - if ($storeId !== null) { - $where[] = $this->_getWriteAdapter() - ->quoteInto('store_id=?', $storeId); - } if ($entityId !== null) { $where[] = $this->_getWriteAdapter() ->quoteInto('product_id IN (?)', $entityId); diff --git a/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php b/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php index e592285ee1278b388f19683a0f203991bb788c70..e31202f8d229ea581b8e65be2af054166eceff25 100644 --- a/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php @@ -142,7 +142,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection impl /** * Retrieve collection of all attributes * - * @return \Magento\Framework\Data\Collection\Db + * @return \Magento\Framework\Data\Collection\AbstractDb */ protected function _getAttributesCollection() { diff --git a/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php b/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php index e47ba631ebfca2072f261e3ccd600f48c66b4702..f1b3c6300ca2ada0292fd5977c36ddbece2185d3 100644 --- a/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php +++ b/app/code/Magento/CatalogSearch/Model/Search/IndexBuilder.php @@ -10,6 +10,7 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Resource; use Magento\Framework\DB\Select; use Magento\Framework\Search\Adapter\Mysql\IndexBuilderInterface; +use Magento\Framework\Search\Adapter\Mysql\ScoreBuilder; use Magento\Framework\Search\RequestInterface; use Magento\Store\Model\ScopeInterface; use Magento\Store\Model\StoreManagerInterface; @@ -54,16 +55,27 @@ class IndexBuilder implements IndexBuilderInterface */ public function build(RequestInterface $request) { + $tableName = [$request->getIndex(), 'index_default']; $select = $this->getSelect() ->from( - ['search_index' => $this->resource->getTableName($request->getIndex())], - ['entity_id' => 'search_index.product_id'] + ['search_index' => $this->resource->getTableName($tableName)], + ['entity_id' => 'product_id'] ) ->joinLeft( ['category_index' => $this->resource->getTableName('catalog_category_product_index')], 'search_index.product_id = category_index.product_id' . ' AND search_index.store_id = category_index.store_id', [] + ) + ->joinLeft( + ['cea' => $this->resource->getTableName('catalog_eav_attribute')], + 'search_index.attribute_id = cea.attribute_id', + [ScoreBuilder::WEIGHT_FIELD] + ) + ->joinLeft( + ['cpie' => $this->resource->getTableName('catalog_product_index_eav')], + 'search_index.product_id = cpie.entity_id AND search_index.attribute_id = cpie.attribute_id', + [] ); $isShowOutOfStock = $this->config->isSetFlag( diff --git a/app/code/Magento/CatalogSearch/Setup/UpgradeSchema.php b/app/code/Magento/CatalogSearch/Setup/UpgradeSchema.php new file mode 100644 index 0000000000000000000000000000000000000000..4b7bbb9266c087a6ec913c2afded852d0d336412 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Setup/UpgradeSchema.php @@ -0,0 +1,71 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogSearch\Setup; + + +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\DB\Ddl\Table; +use Magento\Framework\Setup\UpgradeSchemaInterface; +use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\Setup\SchemaSetupInterface; + +/** + * @codeCoverageIgnore + */ +class UpgradeSchema implements UpgradeSchemaInterface +{ + /** + * {@inheritdoc} + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) + { + $installer = $setup; + $connection = $installer->getConnection(); + if (version_compare($context->getVersion(), '2.0.1') < 0) { + $connection->dropTable($installer->getTable('catalogsearch_fulltext')); + $table = $connection->newTable($installer->getTable('catalogsearch_fulltext_index_default')) + ->addColumn( + 'FTS_DOC_ID', + Table::TYPE_BIGINT, + null, + ['unsigned' => true, 'nullable' => false, 'auto_increment' => true, 'primary' => true], + 'Entity ID' + )->addColumn( + 'product_id', + Table::TYPE_INTEGER, + 10, + ['unsigned' => true, 'nullable' => false], + 'Product ID' + )->addColumn( + 'attribute_id', + Table::TYPE_INTEGER, + 10, + ['unsigned' => true, 'nullable' => false] + )->addColumn( + 'store_id', + \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, + null, + ['unsigned' => true, 'nullable' => false], + 'Store ID' + )->addColumn( + 'data_index', + Table::TYPE_TEXT, + '4g', + ['nullable' => true], + 'Data index' + )->addIndex( + 'FTI_CATALOGSEARCH_FULLTEXT_DATA_INDEX', + ['data_index'], + ['type' => AdapterInterface::INDEX_TYPE_FULLTEXT] + ); + $connection->createTable($table); + } + } +} diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Helper/DataTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Helper/DataTest.php index 124fc689dc8c900729b999fbd4a85ab06ff9e709..d1541d30e53088792cfbda5184f7b2567b8cda3e 100644 --- a/app/code/Magento/CatalogSearch/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/CatalogSearch/Test/Unit/Helper/DataTest.php @@ -109,14 +109,14 @@ class DataTest extends \PHPUnit_Framework_TestCase { return [ [ - null, + [], [ 'index' => [], 'separator' => '--' ], ], [ - 'element1--element2--element3--element4', + ['element1','element2','element3--element4'], [ 'index' => [ 'element1', diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Adapter/Mysql/Filter/PreprocessorTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Adapter/Mysql/Filter/PreprocessorTest.php index 30fd139dc32165f7fb5f393ac53b5777ca7b0910..90f0213cc7e9c3e9682b1e9c581c25bf5eb63239 100644 --- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Adapter/Mysql/Filter/PreprocessorTest.php +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Adapter/Mysql/Filter/PreprocessorTest.php @@ -170,7 +170,11 @@ class PreprocessorTest extends \PHPUnit_Framework_TestCase ->method('__toString') ->will($this->returnValue('TEST QUERY PART')); - $actualResult = $this->target->process($this->filter, $isNegation, $query); + $queryContainer = $this->getMockBuilder('\Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer') + ->disableOriginalConstructor() + ->getMock(); + + $actualResult = $this->target->process($this->filter, $isNegation, $query, $queryContainer); $this->assertSame($expectedResult, $this->removeWhitespaces($actualResult)); } @@ -195,7 +199,11 @@ class PreprocessorTest extends \PHPUnit_Framework_TestCase ->with(\Magento\Catalog\Model\Product::ENTITY, 'category_ids') ->will($this->returnValue($this->attribute)); - $actualResult = $this->target->process($this->filter, $isNegation, $query); + $queryContainer = $this->getMockBuilder('\Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer') + ->disableOriginalConstructor() + ->getMock(); + + $actualResult = $this->target->process($this->filter, $isNegation, $query, $queryContainer); $this->assertSame($expectedResult, $this->removeWhitespaces($actualResult)); } @@ -232,7 +240,11 @@ class PreprocessorTest extends \PHPUnit_Framework_TestCase ->method('__toString') ->will($this->returnValue('TEST QUERY PART')); - $actualResult = $this->target->process($this->filter, $isNegation, $query); + $queryContainer = $this->getMockBuilder('\Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer') + ->disableOriginalConstructor() + ->getMock(); + + $actualResult = $this->target->process($this->filter, $isNegation, $query, $queryContainer); $this->assertSame($expectedResult, $this->removeWhitespaces($actualResult)); } @@ -284,7 +296,11 @@ class PreprocessorTest extends \PHPUnit_Framework_TestCase ->method('__toString') ->will($this->returnValue('TEST QUERY PART')); - $actualResult = $this->target->process($this->filter, $isNegation, $query); + $queryContainer = $this->getMockBuilder('\Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer') + ->disableOriginalConstructor() + ->getMock(); + + $actualResult = $this->target->process($this->filter, $isNegation, $query, $queryContainer); $this->assertSame($expectedResult, $this->removeWhitespaces($actualResult)); } diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Resource/EngineTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Resource/EngineTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1bbc0dc38873ab9f81029d4279ff8203b5b40927 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Resource/EngineTest.php @@ -0,0 +1,119 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogSearch\Test\Unit\Model\Resource; + + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class EngineTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\CatalogSearch\Model\Resource\Engine + */ + private $target; + + /** + * @var Resource|\PHPUnit_Framework_MockObject_MockObject + */ + private $resource; + + /** + * @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $connection; + /** + * @var \Magento\Framework\Model\Resource\Db\Context|\PHPUnit_Framework_MockObject_MockObject + */ + private $context; + + protected function setUp() + { + $this->context = $this->getMockBuilder('\Magento\Framework\Model\Resource\Db\Context') + ->disableOriginalConstructor() + ->getMock(); + $this->resource = $resource = $this->getMockBuilder('\Magento\Framework\App\Resource') + ->disableOriginalConstructor() + ->setMethods(['getConnection', 'getTableName']) + ->getMock(); + $this->context->expects($this->once()) + ->method('getResources') + ->willReturn($this->resource); + $this->connection = $this->getMockBuilder('\Magento\Framework\DB\Adapter\AdapterInterface') + ->disableOriginalConstructor() + ->setMethods(['getIfNullSql']) + ->getMockForAbstractClass(); + $resource->expects($this->any()) + ->method('getConnection') + ->with(\Magento\Framework\App\Resource::DEFAULT_WRITE_RESOURCE) + ->will($this->returnValue($this->connection)); + + $objectManager = new ObjectManager($this); + $this->target = $objectManager->getObject( + '\Magento\CatalogSearch\Model\Resource\Engine', + [ + 'context' => $this->context, + ] + ); + $this->target; + } + + /** + * @dataProvider saveEntityIndexesDataProvider + */ + public function testSaveEntityIndexes($storeId, $entityIndexes, $expected) + { + if ($expected) { + $this->connection->expects($this->once()) + ->method('insertOnDuplicate') + ->with(null, $expected, ['data_index']) + ->willReturnSelf(); + } + $this->target->saveEntityIndexes($storeId, $entityIndexes); + } + + public function saveEntityIndexesDataProvider() + { + return [ + 'empty' => [ + null, + [], + [] + ], + 'correctData' => [ + 13, + [ + 28 => [ + 123 => 'Value of 123', + 845 => 'Value of 845', + 'options' => 'Some | Index | Value' + ] + ], + [ + [ + 'product_id' => 28, + 'attribute_id' => 123, + 'store_id' => 13, + 'data_index' => 'Value of 123' + ], + [ + 'product_id' => 28, + 'attribute_id' => 845, + 'store_id' => 13, + 'data_index' => 'Value of 845' + ], + [ + 'product_id' => 28, + 'attribute_id' => 0, + 'store_id' => 13, + 'data_index' => 'Some | Index | Value' + ] + + ] + ] + ]; + } +} diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php index b571f782ac7dfc2390a14c63b084205f2252c1a8..05b7f8003be39e2ca172c483a943b24041cd5c9a 100644 --- a/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Search/IndexBuilderTest.php @@ -41,7 +41,7 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase { $this->select = $this->getMockBuilder('\Magento\Framework\DB\Select') ->disableOriginalConstructor() - ->setMethods(['from', 'joinLeft', 'where']) + ->setMethods(['from', 'joinLeft', 'where', 'joinInner']) ->getMock(); $this->adapter = $this->getMockBuilder('\Magento\Framework\DB\Adapter\AdapterInterface') @@ -86,40 +86,10 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase public function testBuildWithOutOfStock() { - $tableSuffix = '_table'; + $tableSuffix = 'index_default'; $index = 'test_name_of_index'; - $this->request->expects($this->once()) - ->method('getIndex') - ->will($this->returnValue($index)); - - $this->resource->expects($this->any()) - ->method('getTableName') - ->will( - $this->returnCallback( - function ($index) use ($tableSuffix) { - return $index . $tableSuffix; - } - ) - ); - - $this->select->expects($this->once()) - ->method('from') - ->with( - ['search_index' => $index . $tableSuffix], - ['entity_id' => 'search_index.product_id'] - ) - ->will($this->returnSelf()); - - $this->select->expects($this->at(1)) - ->method('joinLeft') - ->with( - ['category_index' => 'catalog_category_product_index' . $tableSuffix], - 'search_index.product_id = category_index.product_id' - . ' AND search_index.store_id = category_index.store_id', - [] - ) - ->will($this->returnSelf()); + $this->mockBuild($index, $tableSuffix); $this->config->expects($this->once()) ->method('isSetFlag') @@ -132,9 +102,41 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase public function testBuildWithoutOutOfStock() { - $tableSuffix = '_table'; + $tableSuffix = 'index_default'; $index = 'test_index_name'; + $this->mockBuild($index, $tableSuffix); + + $this->config->expects($this->once()) + ->method('isSetFlag') + ->with('cataloginventory/options/show_out_of_stock') + ->will($this->returnValue(false)); + $this->adapter->expects($this->once())->method('quoteInto') + ->with(' AND stock_index.website_id = ?', 1)->willReturn(' AND stock_index.website_id = 1'); + $website = $this->getMockBuilder('Magento\Store\Model\Website')->disableOriginalConstructor()->getMock(); + $website->expects($this->once())->method('getId')->willReturn(1); + $this->storeManager->expects($this->once())->method('getWebsite')->willReturn($website); + + $this->select->expects($this->at(4)) + ->method('joinLeft') + ->with( + ['stock_index' => 'cataloginventory_stock_status'], + 'search_index.product_id = stock_index.product_id' + . ' AND stock_index.website_id = 1', + [] + ) + ->will($this->returnSelf()); + $this->select->expects($this->once()) + ->method('where') + ->with('stock_index.stock_status = ?', 1) + ->will($this->returnSelf()); + + $result = $this->target->build($this->request); + $this->assertSame($this->select, $result); + } + + protected function mockBuild($index, $tableSuffix) + { $this->request->expects($this->once()) ->method('getIndex') ->will($this->returnValue($index)); @@ -143,8 +145,8 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase ->method('getTableName') ->will( $this->returnCallback( - function ($index) use ($tableSuffix) { - return $index . $tableSuffix; + function ($index) { + return is_array($index) ? $index[0] . $index[1] : $index; } ) ); @@ -153,45 +155,35 @@ class IndexBuilderTest extends \PHPUnit_Framework_TestCase ->method('from') ->with( ['search_index' => $index . $tableSuffix], - ['entity_id' => 'search_index.product_id'] + ['entity_id' => 'product_id'] ) ->will($this->returnSelf()); $this->select->expects($this->at(1)) ->method('joinLeft') ->with( - ['category_index' => 'catalog_category_product_index' . $tableSuffix], + ['category_index' => 'catalog_category_product_index'], 'search_index.product_id = category_index.product_id' . ' AND search_index.store_id = category_index.store_id', [] ) ->will($this->returnSelf()); - $this->config->expects($this->once()) - ->method('isSetFlag') - ->with('cataloginventory/options/show_out_of_stock') - ->will($this->returnValue(false)); - $this->adapter->expects($this->once())->method('quoteInto') - ->with(' AND stock_index.website_id = ?', 1)->willReturn(' AND stock_index.website_id = 1'); - $website = $this->getMockBuilder('Magento\Store\Model\Website')->disableOriginalConstructor()->getMock(); - $website->expects($this->once())->method('getId')->willReturn(1); - $this->storeManager->expects($this->once())->method('getWebsite')->willReturn($website); - $this->select->expects($this->at(2)) ->method('joinLeft') ->with( - ['stock_index' => 'cataloginventory_stock_status' . $tableSuffix], - 'search_index.product_id = stock_index.product_id' - . ' AND stock_index.website_id = 1', - [] + ['cea' => 'catalog_eav_attribute'], + 'search_index.attribute_id = cea.attribute_id', + ['search_weight'] ) ->will($this->returnSelf()); - $this->select->expects($this->once()) - ->method('where') - ->with('stock_index.stock_status = ?', 1) - ->will($this->returnSelf()); - - $result = $this->target->build($this->request); - $this->assertSame($this->select, $result); + $this->select->expects($this->at(3)) + ->method('joinLeft') + ->with( + ['cpie' => $this->resource->getTableName('catalog_product_index_eav')], + 'search_index.product_id = cpie.entity_id AND search_index.attribute_id = cpie.attribute_id', + [] + ) + ->willReturnSelf(); } } diff --git a/app/code/Magento/CatalogSearch/composer.json b/app/code/Magento/CatalogSearch/composer.json index e1b1f2abc447f111511ae44d29f6248c6c073307..307467c3c6217b54f23acdee9766524ef5817723 100644 --- a/app/code/Magento/CatalogSearch/composer.json +++ b/app/code/Magento/CatalogSearch/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-search": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-indexer": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-search": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-indexer": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CatalogSearch/etc/di.xml b/app/code/Magento/CatalogSearch/etc/di.xml index 6e20a7176214251945e7fbe56e011e6655348782..4a0862b9084cba2da75a179de8017e7f14f1406e 100644 --- a/app/code/Magento/CatalogSearch/etc/di.xml +++ b/app/code/Magento/CatalogSearch/etc/di.xml @@ -203,6 +203,7 @@ <argument name="indexProviders" xsi:type="array"> <item name="catalogsearch_fulltext" xsi:type="object">Magento\CatalogSearch\Model\Search\IndexBuilder</item> </argument> + <argument name="entityMetadata" xsi:type="object">Magento\Framework\Search\ProductEntityMetadata</argument> </arguments> </type> <type name="Magento\CatalogSearch\Model\Adapter\Mysql\Filter\Preprocessor"> diff --git a/app/code/Magento/CatalogSearch/etc/module.xml b/app/code/Magento/CatalogSearch/etc/module.xml index 269b6462350b0291650c8acd6cc06019b0a54993..f6e5cf9e590fee3959c490366d049c06c269f8b0 100644 --- a/app/code/Magento/CatalogSearch/etc/module.xml +++ b/app/code/Magento/CatalogSearch/etc/module.xml @@ -6,7 +6,7 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd"> - <module name="Magento_CatalogSearch" setup_version="2.0.0"> + <module name="Magento_CatalogSearch" setup_version="2.0.1"> <sequence> <module name="Magento_Search"/> <module name="Magento_Catalog"/> diff --git a/app/code/Magento/CatalogSearch/etc/search_request.xml b/app/code/Magento/CatalogSearch/etc/search_request.xml index ec3bcda4df72f54fce489558147198ac718a4c89..a0d6fdc454bbf73a60edbd733e458e86b577d4d2 100644 --- a/app/code/Magento/CatalogSearch/etc/search_request.xml +++ b/app/code/Magento/CatalogSearch/etc/search_request.xml @@ -19,8 +19,8 @@ <queryReference clause="must" ref="visibility"/> </query> <query xsi:type="matchQuery" value="$search_term$" name="search"> - <match field="sku" boost="1"/> - <match field="*" boost="1"/> + <match field="sku"/> + <match field="*"/> </query> <query xsi:type="filteredQuery" name="category"> <filterReference clause="must" ref="category_filter"/> diff --git a/app/code/Magento/CatalogSearch/view/frontend/layout/catalogsearch_result_index.xml b/app/code/Magento/CatalogSearch/view/frontend/layout/catalogsearch_result_index.xml index bf0b49e4d69ab316b97ca0b22a0e92232511f68c..b3c7f66aef61059bbe1e053d6d560e7e282453f0 100644 --- a/app/code/Magento/CatalogSearch/view/frontend/layout/catalogsearch_result_index.xml +++ b/app/code/Magento/CatalogSearch/view/frontend/layout/catalogsearch_result_index.xml @@ -12,7 +12,7 @@ <block class="Magento\CatalogSearch\Block\Result" name="search.result" template="result.phtml" cacheable="false"> <block class="Magento\CatalogSearch\Block\SearchResult\ListProduct" name="search_result_list" template="product/list.phtml" cacheable="false"> <arguments> - <!-- If position of argument is depend on image size changable in VDE: + <!-- If argument's position depends on image size changeable in VDE: positions:list-secondary,grid-secondary,list-actions,grid-actions,list-primary,grid-primary --> <argument name="positioned" xsi:type="string">positions:list-secondary</argument> diff --git a/app/code/Magento/CatalogUrlRewrite/Model/CategoryUrlPathGenerator.php b/app/code/Magento/CatalogUrlRewrite/Model/CategoryUrlPathGenerator.php index 6e7547e9ce886d153588d177030161eb8b609af7..d978d726a58c7c889309cd4d0d21402124e2eee7 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/CategoryUrlPathGenerator.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/CategoryUrlPathGenerator.php @@ -56,7 +56,7 @@ class CategoryUrlPathGenerator /** * Build category URL path * - * @param \Magento\Catalog\Api\Data\CategoryInterface|\Magento\Framework\Object $category + * @param \Magento\Catalog\Api\Data\CategoryInterface|\Magento\Framework\Model\AbstractModel $category * @return string */ public function getUrlPath($category) diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Product/Plugin/Import.php b/app/code/Magento/CatalogUrlRewrite/Model/Product/Plugin/Import.php index 26245cc85594baf0381c5f7e4ab313d9da1c0238..dafdfb270ab00ccd5eaf02f771cc47714e64afa1 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Product/Plugin/Import.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Product/Plugin/Import.php @@ -11,6 +11,7 @@ use Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator; use Magento\ImportExport\Model\Import as ImportExport; use Magento\UrlRewrite\Model\UrlPersistInterface; use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; +use Magento\Framework\Event\Observer; class Import { @@ -41,49 +42,54 @@ class Import } /** - * @param ImportProduct $import - * @param bool $result - * @return bool + * Action after data import. + * Save new url rewrites and remove old if exist. + * + * @param Observer $observer + * + * @return void */ - public function afterImportData(ImportProduct $import, $result) + public function afterImportData(Observer $observer) { - if ($import->getAffectedEntityIds()) { - foreach ($import->getAffectedEntityIds() as $productId) { - $product = $this->productRepository->getById($productId); - $productUrls = $this->productUrlRewriteGenerator->generate($product); - if ($productUrls) { - $this->urlPersist->replace($productUrls); - } + $import = $observer->getEvent()->getAdapter(); + if ($products = $observer->getEvent()->getBunch()) { + $productUrls = []; + foreach ($products as $product) { + $productObject = $import->_populateToUrlGeneration($product); + $productUrls = array_merge($productUrls, $this->productUrlRewriteGenerator->generate($productObject)); + } + if ($productUrls) { + $this->urlPersist->replace($productUrls); } - } elseif (ImportExport::BEHAVIOR_DELETE == $import->getBehavior()) { - $this->clearProductUrls($import); } - - return $result; } /** - * @param ImportProduct $import + * Clear product urls. + * + * @param Observer $observer + * * @return void */ - protected function clearProductUrls(ImportProduct $import) + public function clearProductUrls(Observer $observer) { - $oldSku = $import->getOldSku(); - while ($bunch = $import->getNextBunch()) { + $oldSku = $observer->getEvent()->getAdapter()->getOldSku(); + if ($products = $observer->getEvent()->getBunch()) { $idToDelete = []; - foreach ($bunch as $rowNum => $rowData) { - if ($import->validateRow($rowData, $rowNum) - && ImportProduct::SCOPE_DEFAULT == $import->getRowScope($rowData) - ) { - $idToDelete[] = $oldSku[$rowData[ImportProduct::COL_SKU]]['entity_id']; + foreach ($products as $product) { + if (!isset($oldSku[$product[ImportProduct::COL_SKU]])) { + continue; } + $productData = $oldSku[$product[ImportProduct::COL_SKU]]; + $idToDelete[] = $productData['entity_id']; } - foreach ($idToDelete as $productId) { + if (!empty($idToDelete)) { $this->urlPersist->deleteByData([ - UrlRewrite::ENTITY_ID => $productId, + UrlRewrite::ENTITY_ID => $idToDelete, UrlRewrite::ENTITY_TYPE => ProductUrlRewriteGenerator::ENTITY_TYPE, ]); } + } } } diff --git a/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlPathGenerator.php b/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlPathGenerator.php index 0f6b98df7a716ff9c34dfc7f3e68882e548eb470..90e65b9094f5e01163510cbfea5e8db9ea8cd2f1 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlPathGenerator.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/ProductUrlPathGenerator.php @@ -5,6 +5,8 @@ */ namespace Magento\CatalogUrlRewrite\Model; +use Magento\Store\Model\Store; + class ProductUrlPathGenerator { const XML_PATH_PRODUCT_URL_SUFFIX = 'catalog/seo/product_url_suffix'; @@ -25,19 +27,25 @@ class ProductUrlPathGenerator /** @var \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator */ protected $categoryUrlPathGenerator; + /** @var \Magento\Catalog\Api\ProductRepositoryInterface */ + protected $productRepository; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param CategoryUrlPathGenerator $categoryUrlPathGenerator + * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator + \Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator $categoryUrlPathGenerator, + \Magento\Catalog\Api\ProductRepositoryInterface $productRepository ) { $this->storeManager = $storeManager; $this->scopeConfig = $scopeConfig; $this->categoryUrlPathGenerator = $categoryUrlPathGenerator; + $this->productRepository = $productRepository; } /** @@ -52,12 +60,28 @@ class ProductUrlPathGenerator { $path = $product->getData('url_path'); if ($path === null) { - $path = $this->generateUrlKey($product); + $path = $product->getUrlKey() === false + ? $this->prepareProductDefaultUrlKey($product) + : $this->prepareProductUrlKey($product); } - return $category === null ? $path + return $category === null + ? $path : $this->categoryUrlPathGenerator->getUrlPath($category) . '/' . $path; } + /** + * Prepare URL Key with stored product data (fallback for "Use Default Value" logic) + * + * @param \Magento\Catalog\Model\Product $product + * @return string + */ + protected function prepareProductDefaultUrlKey(\Magento\Catalog\Model\Product $product) + { + $storedProduct = $this->productRepository->getById($product->getId()); + $storedUrlKey = $storedProduct->getUrlKey(); + return $storedUrlKey ?: $product->formatUrlKey($storedProduct->getName()); + } + /** * Retrieve Product Url path with suffix * @@ -91,6 +115,17 @@ class ProductUrlPathGenerator * @return string */ public function generateUrlKey($product) + { + return $product->getUrlKey() === false ? false : $this->prepareProductUrlKey($product); + } + + /** + * Prepare url key for product + * + * @param \Magento\Catalog\Model\Product $product + * @return string + */ + protected function prepareProductUrlKey(\Magento\Catalog\Model\Product $product) { $urlKey = $product->getUrlKey(); return $product->formatUrlKey($urlKey === '' || $urlKey === null ? $product->getName() : $urlKey); diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ObjectRegistryTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ObjectRegistryTest.php index 99b04bd322c4ef09a2dd19970f4f2a60fec1454b..d5f435f096377d13428f5c092817f1dba9d6324a 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ObjectRegistryTest.php +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ObjectRegistryTest.php @@ -18,8 +18,7 @@ class ObjectRegistryTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->object = $this->getMock('Magento\Framework\Object'); - $this->object->expects($this->any())->method('getId')->will($this->returnValue(1)); + $this->object = new \Magento\Framework\Object(['id' => 1]); $this->objectRegistry = (new ObjectManager($this))->getObject( 'Magento\CatalogUrlRewrite\Model\ObjectRegistry', ['entities' => [$this->object]] diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Product/Plugin/ImportTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Product/Plugin/ImportTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1c52dee5f25bfdbcc2528e7b897d18ca2115557c --- /dev/null +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Product/Plugin/ImportTest.php @@ -0,0 +1,121 @@ +<?php + +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\CatalogUrlRewrite\Test\Unit\Model\Product\Plugin; + +use Magento\ImportExport\Model\Import as ImportExport; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +class ImportTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @var \Magento\UrlRewrite\Model\UrlPersistInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $urlPersist; + + /** + * @var \Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productUrlRewriteGenerator; + + /** + * @var \Magento\Catalog\Api\ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productRepository; + + /** + * @var \Magento\CatalogUrlRewrite\Model\Product\Plugin\Import|\PHPUnit_Framework_MockObject_MockObject + */ + protected $import; + + /** + * @var \Magento\Framework\Event\Observer|\PHPUnit_Framework_MockObject_MockObject + */ + protected $observer; + + /** + * @var \Magento\Framework\Event|\PHPUnit_Framework_MockObject_MockObject + */ + protected $event; + + /** + * @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject + */ + protected $adapter; + + /** + * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject + */ + protected $object; + + /** + * @var ObjectManagerHelper + */ + protected $objectManagerHelper; + + public function setUp() + { + $this->object = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false); + $this->adapter = $this->getMock( + 'Magento\Framework\DB\Adapter\Pdo\Mysql', + ['getOldSku', '_populateToUrlGeneration'], + [], + '', + false + ); + $this->adapter->expects($this->any())->method('_populateToUrlGeneration')->willReturn($this->object); + $this->adapter->expects($this->any())->method('getOldSku')->willReturn([ + 'sku' => ['sku' => 'sku', 'url_key' => 'value1', 'entity_id' => '1'], + 'sku2' => ['sku' => 'sku2', 'url_key' => 'value2', 'entity_id' => '2'] + ]); + $this->event = $this->getMock('\Magento\Framework\Event', ['getAdapter', 'getBunch'], [], '', false); + $this->event->expects($this->any())->method('getAdapter')->willReturn($this->adapter); + $this->event->expects($this->any())->method('getBunch')->willReturn([ + ['sku' => 'sku', 'url_key' => 'value1'], ['sku' => 'sku3', 'url_key' => 'value3'] + ]); + $this->observer = $this->getMock('\Magento\Framework\Event\Observer', ['getEvent'], [], '', false); + $this->observer->expects($this->any())->method('getEvent')->willReturn($this->event); + $this->urlPersist = $this->getMockBuilder('\Magento\UrlRewrite\Model\UrlPersistInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->productUrlRewriteGenerator = + $this->getMockBuilder('\Magento\CatalogUrlRewrite\Model\ProductUrlRewriteGenerator') + ->disableOriginalConstructor() + ->setMethods(['generate']) + ->getMock(); + $this->productRepository = $this->getMockBuilder('\Magento\Catalog\Api\ProductRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->import = $this->objectManagerHelper->getObject( + '\Magento\CatalogUrlRewrite\Model\Product\Plugin\Import', + [ + 'urlPersist' => $this->urlPersist, + 'productUrlRewriteGenerator' => $this->productUrlRewriteGenerator, + 'productRepository' => $this->productRepository, + ] + ); + } + + /** + * Test for afterImportData() + */ + public function testAfterImportData() + { + $this->productUrlRewriteGenerator->expects($this->any())->method('generate')->willReturn(['url1', 'url2']); + $this->import->afterImportData($this->observer); + } + + /** + * Test for clearProductUrls() + */ + public function testClearProductUrls() + { + $this->import->clearProductUrls($this->observer); + } +} diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ProductUrlPathGeneratorTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ProductUrlPathGeneratorTest.php index 64a88b42b8d7649131e3dd29a39cf32edfa8faa3..7b733303bf4d4d16803cd889754af67408136a3d 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ProductUrlPathGeneratorTest.php +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/ProductUrlPathGeneratorTest.php @@ -5,10 +5,9 @@ */ namespace Magento\CatalogUrlRewrite\Test\Unit\Model; -use \Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator; - -use Magento\Store\Model\ScopeInterface; +use Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Store\Model\ScopeInterface; class ProductUrlPathGeneratorTest extends \PHPUnit_Framework_TestCase { @@ -27,13 +26,26 @@ class ProductUrlPathGeneratorTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */ protected $product; + /** @var \Magento\Catalog\Api\ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $productRepository; + /** @var \Magento\Catalog\Model\Category|\PHPUnit_Framework_MockObject_MockObject */ protected $category; protected function setUp() { $this->category = $this->getMock('Magento\Catalog\Model\Category', [], [], '', false); - $productMethods = ['__wakeup', 'getData', 'getUrlKey', 'getName', 'formatUrlKey', 'getId']; + $productMethods = [ + '__wakeup', + 'getData', + 'getUrlKey', + 'getName', + 'formatUrlKey', + 'getId', + 'load', + 'setStoreId', + ]; + $this->product = $this->getMock('Magento\Catalog\Model\Product', $productMethods, [], '', false); $this->storeManager = $this->getMock('Magento\Store\Model\StoreManagerInterface'); $this->scopeConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'); @@ -44,13 +56,16 @@ class ProductUrlPathGeneratorTest extends \PHPUnit_Framework_TestCase '', false ); + $this->productRepository = $this->getMock('Magento\Catalog\Api\ProductRepositoryInterface'); + $this->productRepository->expects($this->any())->method('getById')->willReturn($this->product); $this->productUrlPathGenerator = (new ObjectManager($this))->getObject( 'Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator', [ 'storeManager' => $this->storeManager, 'scopeConfig' => $this->scopeConfig, - 'categoryUrlPathGenerator' => $this->categoryUrlPathGenerator + 'categoryUrlPathGenerator' => $this->categoryUrlPathGenerator, + 'productRepository' => $this->productRepository, ] ); } @@ -64,6 +79,7 @@ class ProductUrlPathGeneratorTest extends \PHPUnit_Framework_TestCase 'path based on url key' => ['url-key', null, 'url-key'], 'path based on product name 1' => ['', 'product-name', 'product-name'], 'path based on product name 2' => [null, 'product-name', 'product-name'], + 'path based on product name 3' => [false, 'product-name', 'product-name'] ]; } @@ -77,13 +93,34 @@ class ProductUrlPathGeneratorTest extends \PHPUnit_Framework_TestCase { $this->product->expects($this->once())->method('getData')->with('url_path') ->will($this->returnValue(null)); - $this->product->expects($this->once())->method('getUrlKey')->will($this->returnValue($urlKey)); + $this->product->expects($this->any())->method('getUrlKey')->will($this->returnValue($urlKey)); $this->product->expects($this->any())->method('getName')->will($this->returnValue($productName)); $this->product->expects($this->once())->method('formatUrlKey')->will($this->returnArgument(0)); $this->assertEquals($result, $this->productUrlPathGenerator->getUrlPath($this->product, null)); } + /** + * @param $productUrlKey + * @param $expectedUrlKey + * + * @dataProvider generateUrlKeyDataProvider + */ + public function testGenerateUrlKey($productUrlKey, $expectedUrlKey) + { + $this->product->expects($this->any())->method('getUrlKey')->will($this->returnValue($productUrlKey)); + $this->product->expects($this->any())->method('formatUrlKey')->will($this->returnValue($productUrlKey)); + $this->assertEquals($expectedUrlKey, $this->productUrlPathGenerator->generateUrlKey($this->product)); + } + + public function generateUrlKeyDataProvider() + { + return [ + 'URL Key use default' => [false, false], + 'URL Key empty' => ['product-url', 'product-url'], + ]; + } + public function testGetUrlPath() { $this->product->expects($this->once())->method('getData')->with('url_path') @@ -93,6 +130,29 @@ class ProductUrlPathGeneratorTest extends \PHPUnit_Framework_TestCase $this->assertEquals('url-path', $this->productUrlPathGenerator->getUrlPath($this->product, null)); } + /** + * + * @dataProvider getUrlPathDefaultUrlKeyDataProvider + */ + public function testGetUrlPathDefaultUrlKey($storedUrlKey, $productName, $expectedUrlKey) + { + $this->product->expects($this->once())->method('getData')->with('url_path') + ->will($this->returnValue(null)); + $this->product->expects($this->any())->method('getUrlKey')->willReturnOnConsecutiveCalls(false, $storedUrlKey); + $this->product->expects($this->any())->method('getName')->will($this->returnValue($productName)); + $this->product->expects($this->any())->method('formatUrlKey')->will($this->returnArgument(0)); + $this->assertEquals($expectedUrlKey, $this->productUrlPathGenerator->getUrlPath($this->product, null)); + } + + public function getUrlPathDefaultUrlKeyDataProvider() + { + return [ + ['default-store-view-url-key', null, 'default-store-view-url-key'], + [false, 'default-store-view-product-name', 'default-store-view-product-name'] + ]; + + } + public function testGetUrlPathWithCategory() { $this->product->expects($this->once())->method('getData')->with('url_path') @@ -124,7 +184,7 @@ class ProductUrlPathGeneratorTest extends \PHPUnit_Framework_TestCase ); } - public function testGetUrlPathWithSuffixAndCategoryAnsStore() + public function testGetUrlPathWithSuffixAndCategoryAndStore() { $storeId = 1; $this->product->expects($this->once())->method('getData')->with('url_path') diff --git a/app/code/Magento/CatalogUrlRewrite/composer.json b/app/code/Magento/CatalogUrlRewrite/composer.json index 86627ada189f9923d95f6543729bea17e8eb8e01..a4fdb35d55615c085511be97e462cfba358b6794 100644 --- a/app/code/Magento/CatalogUrlRewrite/composer.json +++ b/app/code/Magento/CatalogUrlRewrite/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-backend": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-catalog-import-export": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-import-export": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-url-rewrite": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-backend": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-catalog-import-export": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-import-export": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-url-rewrite": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml old mode 100644 new mode 100755 index f8ebe710c95fa752db5aab2ec0c9bd10c91bdf33..f25e169050bfc2166fce1fa1882fc26ff04be9e8 --- a/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml +++ b/app/code/Magento/CatalogUrlRewrite/etc/adminhtml/di.xml @@ -12,9 +12,6 @@ <type name="Magento\Store\Model\Resource\Group"> <plugin name="group_plugin" type="Magento\CatalogUrlRewrite\Model\Category\Plugin\Store\Group"/> </type> - <type name="Magento\CatalogImportExport\Model\Import\Product"> - <plugin name="import_save_plugin" type="Magento\CatalogUrlRewrite\Model\Product\Plugin\Import"/> - </type> <type name="Magento\Catalog\Model\Resource\Category"> <plugin name="category_move_plugin" type="Magento\CatalogUrlRewrite\Model\Category\Plugin\Category\Move"/> <plugin name="category_delete_plugin" type="Magento\CatalogUrlRewrite\Model\Category\Plugin\Category\Remove"/> diff --git a/app/code/Magento/CatalogUrlRewrite/etc/events.xml b/app/code/Magento/CatalogUrlRewrite/etc/events.xml old mode 100644 new mode 100755 index d56dff9193a7161064fc457b4a7212c3c75bd753..a47a6860bcfdb62c9a9eabaf89df6106aa8ec0fc --- a/app/code/Magento/CatalogUrlRewrite/etc/events.xml +++ b/app/code/Magento/CatalogUrlRewrite/etc/events.xml @@ -12,4 +12,10 @@ <event name="catalog_category_save_after"> <observer name="process_url_rewrite_saving" instance="Magento\CatalogUrlRewrite\Model\Category\Observer" method="processUrlRewriteSaving"/> </event> + <event name="catalog_product_import_bunch_save_after"> + <observer name="catalog_product_import_rewrites_generation" instance="Magento\CatalogUrlRewrite\Model\Product\Plugin\Import" method="afterImportData"/> + </event> + <event name="catalog_product_import_bunch_delete_after"> + <observer name="catalog_product_import_rewrites_delete" instance="Magento\CatalogUrlRewrite\Model\Product\Plugin\Import" method="clearProductUrls"/> + </event> </config> diff --git a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php index cc89420d21afb1d570004658abc9f4bd88504fa3..c62346b5e0ff6d51740a3a14fe6cc43d77f3e2ba 100644 --- a/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php +++ b/app/code/Magento/CatalogWidget/Block/Product/ProductsList.php @@ -106,7 +106,6 @@ class ProductsList extends \Magento\Catalog\Block\Product\AbstractProduct implem $context, $data ); - $this->_isScopePrivate = true; } /** @@ -206,13 +205,10 @@ class ProductsList extends \Magento\Catalog\Block\Product\AbstractProduct implem $collection = $this->productCollectionFactory->create(); $collection->setVisibility($this->catalogProductVisibility->getVisibleInCatalogIds()); - $collection = $this->_addProductAttributesAndPrices( - $collection - )->addStoreFilter()->setPageSize( - $this->getProductsPerPage() - )->setCurPage( - $this->getRequest()->getParam(self::PAGE_VAR_NAME, 1) - ); + $collection = $this->_addProductAttributesAndPrices($collection) + ->addStoreFilter() + ->setPageSize($this->getPageSize()) + ->setCurPage($this->getRequest()->getParam(self::PAGE_VAR_NAME, 1)); $conditions = $this->getConditions(); $conditions->collectValidatedAttributes($collection); @@ -239,7 +235,7 @@ class ProductsList extends \Magento\Catalog\Block\Product\AbstractProduct implem } /** - * Retrieve how much products should be displayed + * Retrieve how many products should be displayed * * @return int */ @@ -257,7 +253,7 @@ class ProductsList extends \Magento\Catalog\Block\Product\AbstractProduct implem } /** - * Retrieve how much products should be displayed + * Retrieve how many products should be displayed * * @return int */ @@ -282,6 +278,16 @@ class ProductsList extends \Magento\Catalog\Block\Product\AbstractProduct implem return (bool)$this->getData('show_pager'); } + /** + * Retrieve how many products should be displayed on page + * + * @return int + */ + protected function getPageSize() + { + return $this->showPager() ? $this->getProductsPerPage() : $this->getProductsCount(); + } + /** * Render pagination HTML * diff --git a/app/code/Magento/CatalogWidget/Model/Rule.php b/app/code/Magento/CatalogWidget/Model/Rule.php index 33c2f190011c2b06b27e5839edea70a07dcb6c36..2a0988671f70a5f80056f143b537cc603a39c0a5 100644 --- a/app/code/Magento/CatalogWidget/Model/Rule.php +++ b/app/code/Magento/CatalogWidget/Model/Rule.php @@ -23,7 +23,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param Rule\Condition\CombineFactory $conditionsFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -33,7 +33,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\CatalogWidget\Model\Rule\Condition\CombineFactory $conditionsFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->conditionsFactory = $conditionsFactory; diff --git a/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/ProductsListTest.php b/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/ProductsListTest.php index 071da448f502dc36cd1cf816d45ceae2ff8c735f..d4559628ef0844bd47821c365eb9f3093e20ca2f 100644 --- a/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/ProductsListTest.php +++ b/app/code/Magento/CatalogWidget/Test/Unit/Block/Product/ProductsListTest.php @@ -115,17 +115,17 @@ class ProductsListTest extends \PHPUnit_Framework_TestCase { $store = $this->getMockBuilder('\Magento\Store\Model\Store') ->disableOriginalConstructor()->setMethods(['getId'])->getMock(); - $store->expects($this->once())->method('getId')->will($this->returnValue(1)); - $this->storeManager->expects($this->once())->method('getStore')->will($this->returnValue($store)); + $store->expects($this->once())->method('getId')->willReturn(1); + $this->storeManager->expects($this->once())->method('getStore')->willReturn($store); $theme = $this->getMock('\Magento\Framework\View\Design\ThemeInterface'); - $theme->expects($this->once())->method('getId')->will($this->returnValue('blank')); - $this->design->expects($this->once())->method('getDesignTheme')->will($this->returnValue($theme)); + $theme->expects($this->once())->method('getId')->willReturn('blank'); + $this->design->expects($this->once())->method('getDesignTheme')->willReturn($theme); - $this->httpContext->expects($this->once())->method('getValue')->will($this->returnValue('context_group')); + $this->httpContext->expects($this->once())->method('getValue')->willReturn('context_group'); $this->productsList->setData('conditions', 'some_serialized_conditions'); - $this->request->expects($this->once())->method('getParam')->with('np')->will($this->returnValue(1)); + $this->request->expects($this->once())->method('getParam')->with('np')->willReturn(1); $cacheKey = ['CATALOG_PRODUCTS_LIST_WIDGET', 1, 'blank', 'context_group', 1, 5, 'some_serialized_conditions']; $this->assertEquals($cacheKey, $this->productsList->getCacheKeyInfo()); @@ -137,7 +137,7 @@ class ProductsListTest extends \PHPUnit_Framework_TestCase ->setMethods(['getId']) ->disableOriginalConstructor() ->getMock(); - $product->expects($this->once())->method('getId')->will($this->returnValue(1)); + $product->expects($this->once())->method('getId')->willReturn(1); $priceRenderer = $this->getMockBuilder('\Magento\Framework\Pricing\Render') ->setMethods(['render']) @@ -151,8 +151,8 @@ class ProductsListTest extends \PHPUnit_Framework_TestCase 'zone' => 'item_list', 'price_id' => 'old-price-1-some-price-type' ]) - ->will($this->returnValue('<html>')); - $this->layout->expects($this->once())->method('getBlock')->will($this->returnValue($priceRenderer)); + ->willReturn('<html>'); + $this->layout->expects($this->once())->method('getBlock')->willReturn($priceRenderer); $this->assertEquals('<html>', $this->productsList->getProductPriceHtml( $product, @@ -176,7 +176,7 @@ class ProductsListTest extends \PHPUnit_Framework_TestCase ->setMethods(['getSize']) ->disableOriginalConstructor() ->getMock(); - $collection->expects($this->once())->method('getSize')->will($this->returnValue(3)); + $collection->expects($this->once())->method('getSize')->willReturn(3); $this->productsList->setData('show_pager', true); $this->productsList->setData('products_per_page', 2); @@ -194,23 +194,32 @@ class ProductsListTest extends \PHPUnit_Framework_TestCase 'setCollection', ])->disableOriginalConstructor()->getMock(); - $pagerBlock->expects($this->once())->method('setUseContainer')->will($this->returnSelf()); - $pagerBlock->expects($this->once())->method('setShowAmounts')->will($this->returnSelf()); - $pagerBlock->expects($this->once())->method('setShowPerPage')->will($this->returnSelf()); - $pagerBlock->expects($this->once())->method('setPageVarName')->will($this->returnSelf()); - $pagerBlock->expects($this->once())->method('setLimit')->will($this->returnSelf()); - $pagerBlock->expects($this->once())->method('setTotalLimit')->will($this->returnSelf()); - $pagerBlock->expects($this->once())->method('setCollection')->with($collection)->will($this->returnSelf()); + $pagerBlock->expects($this->once())->method('setUseContainer')->willReturnSelf(); + $pagerBlock->expects($this->once())->method('setShowAmounts')->willReturnSelf(); + $pagerBlock->expects($this->once())->method('setShowPerPage')->willReturnSelf(); + $pagerBlock->expects($this->once())->method('setPageVarName')->willReturnSelf(); + $pagerBlock->expects($this->once())->method('setLimit')->willReturnSelf(); + $pagerBlock->expects($this->once())->method('setTotalLimit')->willReturnSelf(); + $pagerBlock->expects($this->once())->method('setCollection')->with($collection)->willReturnSelf(); - $pagerBlock->expects($this->once())->method('toHtml')->will($this->returnValue('<pager_html>')); - $this->layout->expects($this->once())->method('createBlock')->will($this->returnValue($pagerBlock)); + $pagerBlock->expects($this->once())->method('toHtml')->willReturn('<pager_html>'); + $this->layout->expects($this->once())->method('createBlock')->willReturn($pagerBlock); $this->assertEquals('<pager_html>', $this->productsList->getPagerHtml()); } - public function testCreateCollection() + /** + * Test public `createCollection` method and protected `getPageSize` method via `createCollection` + * + * @param bool $pagerEnable + * @param int $productsCount + * @param int $productsPerPage + * @param int $expectedPageSize + * @dataProvider createCollectionDataProvider + */ + public function testCreateCollection($pagerEnable, $productsCount, $productsPerPage, $expectedPageSize) { $this->visibility->expects($this->once())->method('getVisibleInCatalogIds') - ->will($this->returnValue([Visibility::VISIBILITY_IN_CATALOG, Visibility::VISIBILITY_BOTH])); + ->willReturn([Visibility::VISIBILITY_IN_CATALOG, Visibility::VISIBILITY_BOTH]); $collection = $this->getMockBuilder('\Magento\Catalog\Model\Resource\Product\Collection') ->setMethods([ 'setVisibility', @@ -226,17 +235,17 @@ class ProductsListTest extends \PHPUnit_Framework_TestCase ->getMock(); $collection->expects($this->once())->method('setVisibility') ->with([Visibility::VISIBILITY_IN_CATALOG, Visibility::VISIBILITY_BOTH]) - ->will($this->returnSelf()); - $collection->expects($this->once())->method('addMinimalPrice')->will($this->returnSelf()); - $collection->expects($this->once())->method('addFinalPrice')->will($this->returnSelf()); - $collection->expects($this->once())->method('addTaxPercents')->will($this->returnSelf()); - $collection->expects($this->once())->method('addAttributeToSelect')->will($this->returnSelf()); - $collection->expects($this->once())->method('addUrlRewrite')->will($this->returnSelf()); - $collection->expects($this->once())->method('addStoreFilter')->will($this->returnSelf()); - $collection->expects($this->once())->method('setPageSize')->will($this->returnSelf()); - $collection->expects($this->once())->method('setCurPage')->will($this->returnSelf()); - - $this->collectionFactory->expects($this->once())->method('create')->will($this->returnValue($collection)); + ->willReturnSelf(); + $collection->expects($this->once())->method('addMinimalPrice')->willReturnSelf(); + $collection->expects($this->once())->method('addFinalPrice')->willReturnSelf(); + $collection->expects($this->once())->method('addTaxPercents')->willReturnSelf(); + $collection->expects($this->once())->method('addAttributeToSelect')->willReturnSelf(); + $collection->expects($this->once())->method('addUrlRewrite')->willReturnSelf(); + $collection->expects($this->once())->method('addStoreFilter')->willReturnSelf(); + $collection->expects($this->once())->method('setPageSize')->with($expectedPageSize)->willReturnSelf(); + $collection->expects($this->once())->method('setCurPage')->willReturnSelf(); + + $this->collectionFactory->expects($this->once())->method('create')->willReturn($collection); $this->productsList->setData('conditions_encoded', 'some_serialized_conditions'); $conditions = $this->getMockBuilder('\Magento\Rule\Model\Condition\Combine') @@ -245,18 +254,46 @@ class ProductsListTest extends \PHPUnit_Framework_TestCase ->getMock(); $conditions->expects($this->once())->method('collectValidatedAttributes') ->with($collection) - ->will($this->returnSelf()); + ->willReturnSelf(); $this->builder->expects($this->once())->method('attachConditionToCollection') ->with($collection, $conditions) - ->will($this->returnSelf()); + ->willReturnSelf(); + + $this->rule->expects($this->once())->method('loadPost')->willReturnSelf(); + $this->rule->expects($this->once())->method('getConditions')->willReturn($conditions); - $this->rule->expects($this->once())->method('loadPost')->will($this->returnSelf()); - $this->rule->expects($this->once())->method('getConditions')->will($this->returnValue($conditions)); + + if ($productsPerPage) { + $this->productsList->setData('products_per_page', $productsPerPage); + } else { + $this->productsList->unsetData('products_per_page'); + } + + $this->productsList->setData('show_pager', $pagerEnable); + $this->productsList->setData('products_count', $productsCount); $this->assertSame($collection, $this->productsList->createCollection()); } + public function createCollectionDataProvider() + { + return [ + [true, 1, null, 5], + [true, 5, null, 5], + [true, 10, null, 5], + [true, 1, 2, 2], + [true, 5, 3, 3], + [true, 10, 7, 7], + [false, 1, null, 1], + [false, 3, null, 3], + [false, 5, null, 5], + [false, 1, 3, 1], + [false, 3, 5, 3], + [false, 5, 10, 5] + ]; + } + public function testGetProductsCount() { $this->assertEquals(10, $this->productsList->getProductsCount()); @@ -297,4 +334,9 @@ class ProductsListTest extends \PHPUnit_Framework_TestCase $this->productsList->setTitle('Custom Title'); $this->assertEquals('Custom Title', $this->productsList->getTitle()); } + + public function testScope() + { + $this->assertFalse($this->productsList->isScopePrivate()); + } } diff --git a/app/code/Magento/CatalogWidget/composer.json b/app/code/Magento/CatalogWidget/composer.json index 5a4e7e3c6cfc30e8edd006d9acb305f7baf53244..633cc2a7cc48e4ab5bcf48ef3a976ae1bbb6302f 100644 --- a/app/code/Magento/CatalogWidget/composer.json +++ b/app/code/Magento/CatalogWidget/composer.json @@ -3,19 +3,19 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-widget": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-rule": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-wishlist": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-widget": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-rule": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-wishlist": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml b/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml index 1acdd16634d204616a1e49aa8288782df91a885c..e8c7579eab664dafcf26305c85f752cf974153c3 100644 --- a/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml +++ b/app/code/Magento/CatalogWidget/view/frontend/templates/product/widget/content/grid.phtml @@ -101,8 +101,8 @@ <a href="#" data-post='<?php echo $block->getAddToWishlistParams($_item); ?>' class="action towishlist" data-action="add-to-wishlist" - title="<?php echo __('Add to Wishlist') ?>"> - <span><?php echo __('Add to Wishlist') ?></span> + title="<?php echo __('Add to Wish List') ?>"> + <span><?php echo __('Add to Wish List') ?></span> </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare): ?> diff --git a/app/code/Magento/Checkout/Model/Cart.php b/app/code/Magento/Checkout/Model/Cart.php index b023e8eda142fc9c3cefededf0b1ea027a308a3c..0762ae9e18e9c24e0e1cbb91a32c41d4834168fc 100644 --- a/app/code/Magento/Checkout/Model/Cart.php +++ b/app/code/Magento/Checkout/Model/Cart.php @@ -501,9 +501,7 @@ class Cart extends Object implements CartInterface if ($qty > 0) { $item->setQty($qty); - $itemInQuote = $this->getQuote()->getItemById($item->getId()); - - if (!$itemInQuote && $item->getHasError()) { + if ($item->getHasError()) { throw new \Magento\Framework\Exception\LocalizedException(__($item->getMessage())); } @@ -527,6 +525,7 @@ class Cart extends Object implements CartInterface 'checkout_cart_update_items_after', ['cart' => $this, 'info' => $infoDataObject] ); + return $this; } diff --git a/app/code/Magento/Checkout/composer.json b/app/code/Magento/Checkout/composer.json index ba0fac8c01e9aab3840003e7a5a6705f578d3f44..db8918bca762e2ed96a00a597bc0291a0138e96e 100644 --- a/app/code/Magento/Checkout/composer.json +++ b/app/code/Magento/Checkout/composer.json @@ -3,32 +3,32 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-payment": "0.74.0-beta10", - "magento/module-shipping": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-gift-message": "0.74.0-beta10", - "magento/module-wishlist": "0.74.0-beta10", - "magento/module-page-cache": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/module-msrp": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-ui": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-payment": "0.74.0-beta13", + "magento/module-shipping": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-gift-message": "0.74.0-beta13", + "magento/module-wishlist": "0.74.0-beta13", + "magento/module-page-cache": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/module-msrp": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-ui": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-cookie": "0.74.0-beta10" + "magento/module-cookie": "0.74.0-beta13" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml index d72d04fe0e3cf63c6a43b25b4fa326ceb8614c80..5db66984f7812e8bd62978befb585a2eaa8434f9 100644 --- a/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml +++ b/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml @@ -178,7 +178,7 @@ </item> <!-- Value of region_id field is filtered by the value of county_id attribute --> <item name="filterBy" xsi:type="array"> - <item name="target" xsi:type="string"><![CDATA[<%= provider %>:<%= parentScope %>.country_id]]></item> + <item name="target" xsi:type="string">${ $.provider }:${ $.parentScope }.country_id</item> <item name="field" xsi:type="string">country_id</item> </item> </item> diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml index d34488d2b6705b02414f638e09e1f318e4e1ee93..a78b7d152131dd4a66c17f4d2e66afbcdfc60019 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml @@ -38,7 +38,7 @@ <div class="cart main actions"> <?php if ($block->getContinueShoppingUrl()): ?> <a class="action continue" - href="<?php echo $block->getContinueShoppingUrl() ?>" + href="<?php echo $block->escapeUrl($block->getContinueShoppingUrl()) ?>" title="<?php echo $block->escapeHtml(__('Continue Shopping')); ?>"> <span><?php echo __('Continue Shopping') ?></span> </a> diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml index 7d0ceffcb8b3a16a0178b1cd72c42ed1a4f573d2..a189143ba870fd923daab34f7dad81d062ed393d 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/item/default.phtml @@ -124,7 +124,7 @@ $canApplyMsrp = $helper->isShowBeforeOrderConfirm($product) && $helper->isMinima <a href="#" data-post='<?php echo $this->helper('Magento\Wishlist\Helper\Data')->getMoveFromCartParams($_item->getId()); ?>' class="use-ajax action towishlist"> - <span><?php echo __('Move to Wishlist'); ?></span> + <span><?php echo __('Move to Wish List'); ?></span> </a> <?php endif ?> <?php endif ?> diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/noItems.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/noItems.phtml index 9fe14c75f86a8eda4d403233b02c2f8c9f5cee93..338399e00ee85b333fb8bc93023d7743d5b617cc 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/noItems.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/noItems.phtml @@ -9,6 +9,7 @@ <div class="cart-empty"> <?php echo $block->getChildHtml('checkout_cart_empty_widget'); ?> <p><?php echo __('You have no items in your shopping cart.') ?></p> - <p><?php echo __('Click <a href="%1">here</a> to continue shopping.', $block->getContinueShoppingUrl()) ?></p> + <p><?php echo __('Click <a href="%1">here</a> to continue shopping.', + $block->escapeUrl($block->getContinueShoppingUrl())) ?></p> <?php echo $block->getChildHtml('shopping.cart.table.after'); ?> </div> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/failure.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/failure.phtml index e2e1ea242d5c501779892f18edd2c9468a5cce44..b39d5f71940ab8aa1e988b4e25cc3ce19f7dce43 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/failure.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/onepage/failure.phtml @@ -9,4 +9,4 @@ ?> <?php if ($block->getRealOrderId()) : ?><p><?php echo __('Order #') . $block->getRealOrderId() ?></p><?php endif ?> <?php if ($error = $block->getErrorMessage()) : ?><p><?php echo $error ?></p><?php endif ?> -<p><?php echo __('Click <a href="%1">here</a> to continue shopping.', $block->getContinueShoppingUrl()) ?></p> +<p><?php echo __('Click <a href="%1">here</a> to continue shopping.', $block->escapeUrl($block->getContinueShoppingUrl())) ?></p> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js b/app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js index 899f38b32e1201e3c81d92ab3a2c90c790231101..29789e906e65a43a1f86eeb9ab9da7becb06a8ed 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/opc-checkout-method.js @@ -183,7 +183,7 @@ define([ if (json.isGuestCheckoutAllowed) { if( !guestChecked && !registerChecked ){ - alert( $.mage.__('Please choose to register or to checkout as a guest.') ); + alert( $.mage.__('You can create an account or check out as a guest.') ); return false; } diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opc-payment-info.js b/app/code/Magento/Checkout/view/frontend/web/js/opc-payment-info.js index c590c9835a37cce35a837a11d9e4a8029c2e37fa..ac9a1781c49921ae2a7b50b308e19d7667a726c6 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/opc-payment-info.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/opc-payment-info.js @@ -132,7 +132,7 @@ define([ return true; } - alert($.mage.__('Please specify payment method.')); + alert($.mage.__('Please choose a payment method.')); return false; }, diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-method.js b/app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-method.js index 074ee318a67c39815588c909d6a7c21cf7c0a422..ba64095ce8b714ae1f97cf97372e2e68c532e4e5 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-method.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/opc-shipping-method.js @@ -63,7 +63,7 @@ define([ _validateShippingMethod: function() { var methods = this.element.find('[name="shipping_method"]'); if (methods.length === 0) { - alert($.mage.__('We are not able to ship to the selected shipping address. Please choose another address or edit the current address.')); + alert($.mage.__('We can\'t ship to this address. Please enter another address or edit this one.')); return false; } if (methods.filter(':checked').length) { diff --git a/app/code/Magento/Checkout/view/frontend/web/js/opcheckout.js b/app/code/Magento/Checkout/view/frontend/web/js/opcheckout.js index 0cad0456668bde83d30b2d4ac982cda33d82b9f8..0875a61b5b92995b18d31e0c115ec8905f59fdc4 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/opcheckout.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/opcheckout.js @@ -156,7 +156,7 @@ define([ this.element.find(this.options.checkout.registerCustomerPasswordSelector).show(); } else { - alert($.mage.__('Please choose to register or to checkout as a guest.')); + alert($.mage.__('You can create an account or check out as a guest.')); return false; } @@ -427,7 +427,7 @@ define([ var methods = this.element.find('[name="shipping_method"]'); if (methods.length === 0) { - alert($.mage.__('We are not able to ship to the selected shipping address. Please choose another address or edit the current address.')); + alert($.mage.__('We can\'t ship to this address. Please enter another address or edit this one.')); return false; } @@ -562,7 +562,7 @@ define([ return true; } - alert($.mage.__('Please specify payment method.')); + alert($.mage.__('Please choose a payment method.')); return false; }, diff --git a/app/code/Magento/Checkout/view/frontend/web/js/payment.js b/app/code/Magento/Checkout/view/frontend/web/js/payment.js index f306e375d47fd2ea155da2ad637189636a69e481..8c880cd694bf166f711e99e3a1f435cc76dce883 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/payment.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/payment.js @@ -85,7 +85,7 @@ define([ } else if (methods.filter('input:radio:checked').length) { isValid = true; } else { - alert($.mage.__('Please specify payment method.')); + alert($.mage.__('Please choose a payment method.')); } return isValid; diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js index 21d555cdd7b2af98c37ffdd1293065437e0c76ed..313ba3b923d06aa5caf03cef5330f719244471af 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js @@ -38,7 +38,7 @@ define( }, setPaymentMethod: function() { if (!this.activeMethod()) { - alert($t('Please specify payment method.')); + alert($t('Please choose a payment method.')); return; } diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address.js index 17b75243a4ee65600ac6e59b1361a64f8d50bd11..aaa5529851d792e13ed91dcb28c29f66773efd24 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address.js @@ -58,18 +58,22 @@ define( return !quote.isVirtual(); }, selectShippingAddress: function() { - var additionalData = {}; - var billingAddress = quote.getBillingAddress()(); + var additionalFields, + addressData, + additionalData = {}, + billingAddress = quote.getBillingAddress()(); + if (!billingAddress.customerAddressId || !this.visible()) { /** * All the the input fields that are not a part of the address but need to be submitted * in the same request must have data-scope attribute set */ - var additionalFields = $('input[data-scope="additionalAddressData"]').serializeArray(); + additionalFields = $('input[data-scope="additionalAddressData"]').serializeArray(); additionalFields.forEach(function (field) { additionalData[field.name] = field.value; }); } + if (!newAddressSelected()) { selectShippingAddress( addressList.getAddressById(this.selectedAddressId()), @@ -80,23 +84,32 @@ define( if (this.visible()) { this.validate(); } + if (!this.source.get('params.invalid')) { - var addressData = this.source.get('shippingAddress'); + addressData = this.source.get('shippingAddress'); selectShippingAddress(addressData, this.sameAsBilling(), additionalData); } } }, sameAsBillingClick: function() { + var billingAddress, + shippingAddress, + property; + addressList.isBillingSameAsShipping = !addressList.isBillingSameAsShipping; + if (this.sameAsBilling()) { - var billingAddress = quote.getBillingAddress()(); + billingAddress = quote.getBillingAddress()(); + if (billingAddress.customerAddressId) { this.selectedAddressId(billingAddress.customerAddressId); newAddressSelected(false); + } else { // copy billing address data to shipping address form if customer uses new address for billing - var shippingAddress = this.source.get('shippingAddress'); - for (var property in billingAddress) { + shippingAddress = this.source.get('shippingAddress'); + + for (property in billingAddress) { if (billingAddress.hasOwnProperty(property) && shippingAddress.hasOwnProperty(property)) { if (typeof billingAddress[property] === 'string') { this.source.set('shippingAddress.' + property, billingAddress[property]); @@ -105,6 +118,7 @@ define( } } } + this.selectedAddressId(null); newAddressSelected(true); } @@ -113,9 +127,11 @@ define( }, onAddressChange: function() { var billingAddress = quote.getBillingAddress(); + if (this.selectedAddressId() !== billingAddress().customerAddressId) { this.sameAsBilling(false); } + if (this.selectedAddressId() === null) { newAddressSelected(true); } else { diff --git a/app/code/Magento/CheckoutAgreements/composer.json b/app/code/Magento/CheckoutAgreements/composer.json index c175a84cfc0e72f5b725a8f212e49ae087d487b5..bea7e49ea19fc077686d3e7ba0e73bec7beb2978 100644 --- a/app/code/Magento/CheckoutAgreements/composer.json +++ b/app/code/Magento/CheckoutAgreements/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-ui": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-ui": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Cms/Api/BlockRepositoryInterface.php b/app/code/Magento/Cms/Api/BlockRepositoryInterface.php index 02b45d199fe59c88408694f043d6c9ff751cb8ad..730fb978b54474fa998c452bb8e2074dccc746c7 100644 --- a/app/code/Magento/Cms/Api/BlockRepositoryInterface.php +++ b/app/code/Magento/Cms/Api/BlockRepositoryInterface.php @@ -16,8 +16,8 @@ interface BlockRepositoryInterface /** * Save block. * - * @param Data\BlockInterface $block - * @return Data\BlockInterface + * @param \Magento\Cms\Api\Data\BlockInterface $block + * @return \Magento\Cms\Api\Data\BlockInterface * @throws \Magento\Framework\Exception\LocalizedException */ public function save(Data\BlockInterface $block); @@ -26,7 +26,7 @@ interface BlockRepositoryInterface * Retrieve block. * * @param int $blockId - * @return Data\BlockInterface + * @return \Magento\Cms\Api\Data\BlockInterface * @throws \Magento\Framework\Exception\LocalizedException */ public function getById($blockId); @@ -34,16 +34,16 @@ interface BlockRepositoryInterface /** * Retrieve blocks matching the specified criteria. * - * @param SearchCriteriaInterface $searchCriteria - * @return \Magento\Framework\Api\SearchResultsInterface + * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria + * @return \Magento\Cms\Api\Data\BlockSearchResultsInterface * @throws \Magento\Framework\Exception\LocalizedException */ - public function getList(SearchCriteriaInterface $searchCriteria); + public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria); /** * Delete block. * - * @param Data\BlockInterface $block + * @param \Magento\Cms\Api\Data\BlockInterface $block * @return bool true on success * @throws \Magento\Framework\Exception\LocalizedException */ diff --git a/app/code/Magento/Cms/Api/Data/BlockInterface.php b/app/code/Magento/Cms/Api/Data/BlockInterface.php index a6602de2fd2c1e0ee040cd351faec1d74057d863..c399ae2467e5e312cd5c9d5c13a18e63d9b6a942 100644 --- a/app/code/Magento/Cms/Api/Data/BlockInterface.php +++ b/app/code/Magento/Cms/Api/Data/BlockInterface.php @@ -26,7 +26,7 @@ interface BlockInterface /** * Get ID * - * @return int + * @return int|null */ public function getId(); @@ -40,35 +40,35 @@ interface BlockInterface /** * Get title * - * @return string + * @return string|null */ public function getTitle(); /** * Get content * - * @return string + * @return string|null */ public function getContent(); /** * Get creation time * - * @return string + * @return string|null */ public function getCreationTime(); /** * Get update time * - * @return string + * @return string|null */ public function getUpdateTime(); /** * Is active * - * @return bool + * @return bool|null */ public function isActive(); diff --git a/app/code/Magento/Cms/Api/Data/PageInterface.php b/app/code/Magento/Cms/Api/Data/PageInterface.php index 03e292c4c258ad66bc8f2bf2d57abd425d507db7..d59c99b0879826c376f228324f58af619098ff65 100644 --- a/app/code/Magento/Cms/Api/Data/PageInterface.php +++ b/app/code/Magento/Cms/Api/Data/PageInterface.php @@ -37,7 +37,7 @@ interface PageInterface /** * Get ID * - * @return int + * @return int|null */ public function getId(); @@ -51,112 +51,112 @@ interface PageInterface /** * Get title * - * @return string + * @return string|null */ public function getTitle(); /** * Get page layout * - * @return string + * @return string|null */ public function getPageLayout(); /** * Get meta keywords * - * @return string + * @return string|null */ public function getMetaKeywords(); /** * Get meta description * - * @return string + * @return string|null */ public function getMetaDescription(); /** * Get content heading * - * @return string + * @return string|null */ public function getContentHeading(); /** * Get content * - * @return string + * @return string|null */ public function getContent(); /** * Get creation time * - * @return string + * @return string|null */ public function getCreationTime(); /** * Get update time * - * @return string + * @return string|null */ public function getUpdateTime(); /** * Get sort order * - * @return string + * @return string|null */ public function getSortOrder(); /** * Get layout update xml * - * @return string + * @return string|null */ public function getLayoutUpdateXml(); /** * Get custom theme * - * @return string + * @return string|null */ public function getCustomTheme(); /** * Get custom root template * - * @return string + * @return string|null */ public function getCustomRootTemplate(); /** * Get custom layout update xml * - * @return string + * @return string|null */ public function getCustomLayoutUpdateXml(); /** * Get custom theme from * - * @return string + * @return string|null */ public function getCustomThemeFrom(); /** * Get custom theme to * - * @return string + * @return string|null */ public function getCustomThemeTo(); /** * Is active * - * @return bool + * @return bool|null */ public function isActive(); diff --git a/app/code/Magento/Cms/Api/PageRepositoryInterface.php b/app/code/Magento/Cms/Api/PageRepositoryInterface.php index b65ce6a83f9257c255acec4a278b7d9649159997..04a8517d8a2eb0278609bf9d19c7747c2ade9862 100644 --- a/app/code/Magento/Cms/Api/PageRepositoryInterface.php +++ b/app/code/Magento/Cms/Api/PageRepositoryInterface.php @@ -16,17 +16,17 @@ interface PageRepositoryInterface /** * Save page. * - * @param Data\PageInterface $page - * @return Data\PageInterface + * @param \Magento\Cms\Api\Data\PageInterface $page + * @return \Magento\Cms\Api\Data\PageInterface * @throws \Magento\Framework\Exception\LocalizedException */ - public function save(Data\PageInterface $page); + public function save(\Magento\Cms\Api\Data\PageInterface $page); /** * Retrieve page. * * @param int $pageId - * @return Data\PageInterface + * @return \Magento\Cms\Api\Data\PageInterface * @throws \Magento\Framework\Exception\LocalizedException */ public function getById($pageId); @@ -34,20 +34,20 @@ interface PageRepositoryInterface /** * Retrieve pages matching the specified criteria. * - * @param SearchCriteriaInterface $searchCriteria - * @return \Magento\Framework\Api\SearchResultsInterface + * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria + * @return \Magento\Cms\Api\Data\PageSearchResultsInterface * @throws \Magento\Framework\Exception\LocalizedException */ - public function getList(SearchCriteriaInterface $searchCriteria); + public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria); /** * Delete page. * - * @param Data\PageInterface $page + * @param \Magento\Cms\Api\Data\PageInterface $page * @return bool true on success * @throws \Magento\Framework\Exception\LocalizedException */ - public function delete(Data\PageInterface $page); + public function delete(\Magento\Cms\Api\Data\PageInterface $page); /** * Delete page by ID. diff --git a/app/code/Magento/Cms/Model/BlockRepository.php b/app/code/Magento/Cms/Model/BlockRepository.php index be1498fc8667553ba1f4ad4f8ccd93ac61d57b97..32c12f0d8dba6d257234ab5af0ed9b71744f88b6 100644 --- a/app/code/Magento/Cms/Model/BlockRepository.php +++ b/app/code/Magento/Cms/Model/BlockRepository.php @@ -12,6 +12,7 @@ use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Exception\CouldNotDeleteException; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Reflection\DataObjectProcessor; /** * Class BlockRepository @@ -45,7 +46,12 @@ class BlockRepository implements BlockRepositoryInterface protected $dataObjectHelper; /** - * @var Data\BlockInterfaceFactory + * @var DataObjectProcessor + */ + protected $dataObjectProcessor; + + /** + * @var \Magento\Cms\Api\Data\BlockInterfaceFactory */ protected $dataBlockFactory; @@ -56,14 +62,16 @@ class BlockRepository implements BlockRepositoryInterface * @param Resource\Block\CollectionFactory $blockCollectionFactory * @param Data\BlockSearchResultsInterfaceFactory $searchResultsFactory * @param DataObjectHelper $dataObjectHelper + * @param DataObjectProcessor $dataObjectProcessor */ public function __construct( Resource\Block $resource, BlockFactory $blockFactory, - Data\BlockInterfaceFactory $dataBlockFactory, + \Magento\Cms\Api\Data\BlockInterfaceFactory $dataBlockFactory, Resource\Block\CollectionFactory $blockCollectionFactory, Data\BlockSearchResultsInterfaceFactory $searchResultsFactory, - DataObjectHelper $dataObjectHelper + DataObjectHelper $dataObjectHelper, + DataObjectProcessor $dataObjectProcessor ) { $this->resource = $resource; $this->blockFactory = $blockFactory; @@ -71,12 +79,13 @@ class BlockRepository implements BlockRepositoryInterface $this->searchResultsFactory = $searchResultsFactory; $this->dataObjectHelper = $dataObjectHelper; $this->dataBlockFactory = $dataBlockFactory; + $this->dataObjectProcessor = $dataObjectProcessor; } /** * Save Block data * - * @param Data\BlockInterface $block + * @param \Magento\Cms\Api\Data\BlockInterface $block * @return Block * @throws CouldNotSaveException */ @@ -112,28 +121,23 @@ class BlockRepository implements BlockRepositoryInterface * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) - * @param SearchCriteriaInterface $criteria + * @param \Magento\Framework\Api\SearchCriteriaInterface $criteria * @return Resource\Block\Collection */ - public function getList(SearchCriteriaInterface $criteria) + public function getList(\Magento\Framework\Api\SearchCriteriaInterface $criteria) { $searchResults = $this->searchResultsFactory->create(); $searchResults->setSearchCriteria($criteria); $collection = $this->blockCollectionFactory->create(); foreach ($criteria->getFilterGroups() as $filterGroup) { - $fields = []; - $conditions = []; foreach ($filterGroup->getFilters() as $filter) { if ($filter->getField() === 'store_id') { $collection->addStoreFilter($filter->getValue(), false); continue; } $condition = $filter->getConditionType() ?: 'eq'; - $fields[] = ['attribute' => $filter->getField(), $condition => $filter->getValue()]; - } - if ($fields) { - $collection->addFieldToFilter($fields, $conditions); + $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } $searchResults->setTotalCount($collection->getSize()); @@ -151,11 +155,16 @@ class BlockRepository implements BlockRepositoryInterface $blocks = []; /** @var Block $blockModel */ foreach ($collection as $blockModel) { - $blocks[] = $this->dataObjectHelper->populateWithArray( - $this->dataBlockFactory->create(), + $blockData = $this->dataBlockFactory->create(); + $this->dataObjectHelper->populateWithArray( + $blockData, $blockModel->getData(), 'Magento\Cms\Api\Data\BlockInterface' ); + $blocks[] = $this->dataObjectProcessor->buildOutputDataArray( + $blockData, + 'Magento\Cms\Api\Data\BlockInterface' + ); } $searchResults->setItems($blocks); return $searchResults; @@ -164,7 +173,7 @@ class BlockRepository implements BlockRepositoryInterface /** * Delete Block * - * @param Data\BlockInterface $block + * @param \Magento\Cms\Api\Data\BlockInterface $block * @return bool * @throws CouldNotDeleteException */ diff --git a/app/code/Magento/Cms/Model/PageRepository.php b/app/code/Magento/Cms/Model/PageRepository.php index 82fbba3748d12cdb9dd26ec4dd0d62c9f6c50455..b8499344a92e2a02e3926e2bb06510383621053c 100644 --- a/app/code/Magento/Cms/Model/PageRepository.php +++ b/app/code/Magento/Cms/Model/PageRepository.php @@ -12,6 +12,7 @@ use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Exception\CouldNotDeleteException; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Reflection\DataObjectProcessor; /** * Class PageRepository @@ -45,7 +46,12 @@ class PageRepository implements PageRepositoryInterface protected $dataObjectHelper; /** - * @var Data\PageInterfaceFactory + * @var DataObjectProcessor + */ + protected $dataObjectProcessor; + + /** + * @var \Magento\Cms\Api\Data\PageInterfaceFactory */ protected $dataPageFactory; @@ -56,6 +62,7 @@ class PageRepository implements PageRepositoryInterface * @param Resource\Page\CollectionFactory $pageCollectionFactory * @param Data\PageSearchResultsInterfaceFactory $searchResultsFactory * @param DataObjectHelper $dataObjectHelper + * @param DataObjectProcessor $dataObjectProcessor */ public function __construct( Resource\Page $resource, @@ -63,7 +70,8 @@ class PageRepository implements PageRepositoryInterface Data\PageInterfaceFactory $dataPageFactory, Resource\Page\CollectionFactory $pageCollectionFactory, Data\PageSearchResultsInterfaceFactory $searchResultsFactory, - DataObjectHelper $dataObjectHelper + DataObjectHelper $dataObjectHelper, + DataObjectProcessor $dataObjectProcessor ) { $this->resource = $resource; $this->pageFactory = $pageFactory; @@ -71,16 +79,17 @@ class PageRepository implements PageRepositoryInterface $this->searchResultsFactory = $searchResultsFactory; $this->dataObjectHelper = $dataObjectHelper; $this->dataPageFactory = $dataPageFactory; + $this->dataObjectProcessor = $dataObjectProcessor; } /** * Save Page data * - * @param Data\PageInterface $page + * @param \Magento\Cms\Api\Data\PageInterface $page * @return Page * @throws CouldNotSaveException */ - public function save(Data\PageInterface $page) + public function save(\Magento\Cms\Api\Data\PageInterface $page) { try { $this->resource->save($page); @@ -112,28 +121,23 @@ class PageRepository implements PageRepositoryInterface * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) - * @param SearchCriteriaInterface $criteria + * @param \Magento\Framework\Api\SearchCriteriaInterface $criteria * @return Resource\Page\Collection */ - public function getList(SearchCriteriaInterface $criteria) + public function getList(\Magento\Framework\Api\SearchCriteriaInterface $criteria) { $searchResults = $this->searchResultsFactory->create(); $searchResults->setSearchCriteria($criteria); $collection = $this->pageCollectionFactory->create(); foreach ($criteria->getFilterGroups() as $filterGroup) { - $fields = []; - $conditions = []; foreach ($filterGroup->getFilters() as $filter) { if ($filter->getField() === 'store_id') { $collection->addStoreFilter($filter->getValue(), false); continue; } $condition = $filter->getConditionType() ?: 'eq'; - $fields[] = ['attribute' => $filter->getField(), $condition => $filter->getValue()]; - } - if ($fields) { - $collection->addFieldToFilter($fields, $conditions); + $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } $searchResults->setTotalCount($collection->getSize()); @@ -151,11 +155,16 @@ class PageRepository implements PageRepositoryInterface $pages = []; /** @var Page $pageModel */ foreach ($collection as $pageModel) { - $pages[] = $this->dataObjectHelper->populateWithArray( - $this->dataPageFactory->create(), + $pageData = $this->dataPageFactory->create(); + $this->dataObjectHelper->populateWithArray( + $pageData, $pageModel->getData(), 'Magento\Cms\Api\Data\PageInterface' ); + $pages[] = $this->dataObjectProcessor->buildOutputDataArray( + $pageData, + 'Magento\Cms\Api\Data\PageInterface' + ); } $searchResults->setItems($pages); return $searchResults; @@ -164,11 +173,11 @@ class PageRepository implements PageRepositoryInterface /** * Delete Page * - * @param Data\PageInterface $page + * @param \Magento\Cms\Api\Data\PageInterface $page * @return bool * @throws CouldNotDeleteException */ - public function delete(Data\PageInterface $page) + public function delete(\Magento\Cms\Api\Data\PageInterface $page) { try { $this->resource->delete($page); diff --git a/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php b/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php index 2adc979aacac0827c5211b171a53ba3d4945a2ef..154f74fac0ff7c47d8ee3c4ef1dfc9e18171a661 100644 --- a/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php +++ b/app/code/Magento/Cms/Model/Wysiwyg/Images/Storage.php @@ -462,7 +462,7 @@ class Storage extends \Magento\Framework\Object $result = $uploader->save($targetPath); if (!$result) { - throw new \Magento\Framework\Exception\LocalizedException(__('We cannot upload the file.')); + throw new \Magento\Framework\Exception\LocalizedException(__('We can\'t upload the file right now.')); } // create thumbnail @@ -690,7 +690,9 @@ class Storage extends \Magento\Framework\Object { $root = $this->_sanitizePath($this->_cmsWysiwygImages->getStorageRoot()); if ($root == $path) { - throw new \Magento\Framework\Exception\LocalizedException(__('We cannot delete root directory %1.', $path)); + throw new \Magento\Framework\Exception\LocalizedException( + __('We can\'t delete root directory %1 right now.', $path) + ); } if (strpos($path, $root) !== 0) { throw new \Magento\Framework\Exception\LocalizedException( diff --git a/app/code/Magento/Cms/Setup/InstallData.php b/app/code/Magento/Cms/Setup/InstallData.php index 7c5cddfd914c1b648ae8a657b4c84aa07e4f22af..32f64b54b5502303c0077d214291bb35fe0a5373 100644 --- a/app/code/Magento/Cms/Setup/InstallData.php +++ b/app/code/Magento/Cms/Setup/InstallData.php @@ -252,6 +252,10 @@ class InstallData implements InstallDataInterface <th>EXTERNAL_NO_CACHE</th> <td>A flag, which indicates whether caching is disabled or not.</td> </tr> + <tr> + <th>FORM_KEY</th> + <td>Stores form key used by page cache functionality.</td> + </tr> <tr> <th>FRONTEND</th> <td>You sesssion ID on the server.</td> @@ -302,11 +306,11 @@ class InstallData implements InstallDataInterface </tr> <tr> <th>WISHLIST</th> - <td>An encrypted list of products added to your Wishlist.</td> + <td>An encrypted list of products added to your Wish List.</td> </tr> <tr> <th>WISHLIST_CNT</th> - <td>The number of items in your Wishlist.</td> + <td>The number of items in your Wish List.</td> </tr> </tbody> </table> diff --git a/app/code/Magento/Cms/Test/Unit/Model/BlockRepositoryTest.php b/app/code/Magento/Cms/Test/Unit/Model/BlockRepositoryTest.php index e5c3c9dd155437c9ff54c4a7e3e3312096bfea88..923efe26c3c1e43bf72588c0b73b5f0df748fc70 100644 --- a/app/code/Magento/Cms/Test/Unit/Model/BlockRepositoryTest.php +++ b/app/code/Magento/Cms/Test/Unit/Model/BlockRepositoryTest.php @@ -43,6 +43,11 @@ class BlockRepositoryTest extends \PHPUnit_Framework_TestCase */ protected $dataHelper; + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Reflection\DataObjectProcessor + */ + protected $dataObjectProcessor; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Model\Resource\Block\Collection */ @@ -56,6 +61,9 @@ class BlockRepositoryTest extends \PHPUnit_Framework_TestCase $this->blockResource = $this->getMockBuilder('Magento\Cms\Model\Resource\Block') ->disableOriginalConstructor() ->getMock(); + $this->dataObjectProcessor = $this->getMockBuilder('Magento\Framework\Reflection\DataObjectProcessor') + ->disableOriginalConstructor() + ->getMock(); $blockFactory = $this->getMockBuilder('Magento\Cms\Model\BlockFactory') ->disableOriginalConstructor() ->setMethods(['create']) @@ -112,7 +120,8 @@ class BlockRepositoryTest extends \PHPUnit_Framework_TestCase $blockDataFactory, $collectionFactory, $blockSearchResultFactory, - $this->dataHelper + $this->dataHelper, + $this->dataObjectProcessor ); } @@ -216,42 +225,18 @@ class BlockRepositoryTest extends \PHPUnit_Framework_TestCase $storeFilter = $this->getMockBuilder('Magento\Framework\Api\Filter')->getMock(); $sortOrder = $this->getMockBuilder('Magento\Framework\Api\SortOrder')->getMock(); - $criteria->expects($this->once()) - ->method('getFilterGroups') - ->willReturn([$filterGroup]); - $criteria->expects($this->once()) - ->method('getSortOrders') - ->willReturn([$sortOrder]); - $criteria->expects($this->once()) - ->method('getCurrentPage') - ->willReturn($currentPage); - $criteria->expects($this->once()) - ->method('getPageSize') - ->willReturn($pageSize); - $filterGroup->expects($this->once()) - ->method('getFilters') - ->willReturn([$storeFilter, $filter]); - $filter->expects($this->once()) - ->method('getConditionType') - ->willReturn($condition); - $filter->expects($this->any()) - ->method('getField') - ->willReturn($field); - $filter->expects($this->once()) - ->method('getValue') - ->willReturn($value); - $storeFilter->expects($this->any()) - ->method('getField') - ->willReturn('store_id'); - $storeFilter->expects($this->once()) - ->method('getValue') - ->willReturn(1); - $sortOrder->expects($this->once()) - ->method('getField') - ->willReturn($sortField); - $sortOrder->expects($this->once()) - ->method('getDirection') - ->willReturn(SearchCriteriaInterface::SORT_DESC); + $criteria->expects($this->once())->method('getFilterGroups')->willReturn([$filterGroup]); + $criteria->expects($this->once())->method('getSortOrders')->willReturn([$sortOrder]); + $criteria->expects($this->once())->method('getCurrentPage')->willReturn($currentPage); + $criteria->expects($this->once())->method('getPageSize')->willReturn($pageSize); + $filterGroup->expects($this->once())->method('getFilters')->willReturn([$storeFilter, $filter]); + $filter->expects($this->once())->method('getConditionType')->willReturn($condition); + $filter->expects($this->any())->method('getField')->willReturn($field); + $filter->expects($this->once())->method('getValue')->willReturn($value); + $storeFilter->expects($this->any())->method('getField')->willReturn('store_id'); + $storeFilter->expects($this->once())->method('getValue')->willReturn(1); + $sortOrder->expects($this->once())->method('getField')->willReturn($sortField); + $sortOrder->expects($this->once())->method('getDirection')->willReturn(SearchCriteriaInterface::SORT_DESC); /** @var \Magento\Framework\Api\SearchCriteriaInterface $criteria */ @@ -262,37 +247,21 @@ class BlockRepositoryTest extends \PHPUnit_Framework_TestCase ->willReturnSelf(); $this->collection->expects($this->once()) ->method('addFieldToFilter') - ->with([['attribute' => $field, $condition => $value]], []) - ->willReturnSelf(); - $this->blockSearchResult->expects($this->once()) - ->method('setTotalCount') - ->with($total) - ->willReturnSelf(); - $this->collection->expects($this->once()) - ->method('getSize') - ->willReturn($total); - $this->collection->expects($this->once()) - ->method('setCurPage') - ->with($currentPage) - ->willReturnSelf(); - $this->collection->expects($this->once()) - ->method('setPageSize') - ->with($pageSize) - ->willReturnSelf(); - $this->collection->expects($this->once()) - ->method('addOrder') - ->with($sortField, 'DESC') - ->willReturnSelf(); - $this->block->expects($this->once()) - ->method('getData') - ->willReturn(['data']); - $this->blockSearchResult->expects($this->once()) - ->method('setItems') - ->with(['someData']) + ->with($field, [$condition => $value]) ->willReturnSelf(); + $this->blockSearchResult->expects($this->once())->method('setTotalCount')->with($total)->willReturnSelf(); + $this->collection->expects($this->once())->method('getSize')->willReturn($total); + $this->collection->expects($this->once())->method('setCurPage')->with($currentPage)->willReturnSelf(); + $this->collection->expects($this->once())->method('setPageSize')->with($pageSize)->willReturnSelf(); + $this->collection->expects($this->once())->method('addOrder')->with($sortField, 'DESC')->willReturnSelf(); + $this->block->expects($this->once())->method('getData')->willReturn(['data']); + $this->blockSearchResult->expects($this->once())->method('setItems')->with(['someData'])->willReturnSelf(); $this->dataHelper->expects($this->once()) ->method('populateWithArray') - ->with($this->blockData, ['data'], 'Magento\Cms\Api\Data\BlockInterface') + ->with($this->blockData, ['data'], 'Magento\Cms\Api\Data\BlockInterface'); + $this->dataObjectProcessor->expects($this->once()) + ->method('buildOutputDataArray') + ->with($this->blockData, 'Magento\Cms\Api\Data\BlockInterface') ->willReturn('someData'); $this->assertEquals($this->blockSearchResult, $this->repository->getList($criteria)); diff --git a/app/code/Magento/Cms/Test/Unit/Model/PageRepositoryTest.php b/app/code/Magento/Cms/Test/Unit/Model/PageRepositoryTest.php index a5127dc51823910b45ebcc68d6c1cca26e53541a..79b7b46e4a136e137ef76ab1baf9b990dd780415 100644 --- a/app/code/Magento/Cms/Test/Unit/Model/PageRepositoryTest.php +++ b/app/code/Magento/Cms/Test/Unit/Model/PageRepositoryTest.php @@ -43,6 +43,11 @@ class PageRepositoryTest extends \PHPUnit_Framework_TestCase */ protected $dataHelper; + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Reflection\DataObjectProcessor + */ + protected $dataObjectProcessor; + /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Cms\Model\Resource\Page\Collection */ @@ -56,6 +61,9 @@ class PageRepositoryTest extends \PHPUnit_Framework_TestCase $this->pageResource = $this->getMockBuilder('Magento\Cms\Model\Resource\Page') ->disableOriginalConstructor() ->getMock(); + $this->dataObjectProcessor = $this->getMockBuilder('Magento\Framework\Reflection\DataObjectProcessor') + ->disableOriginalConstructor() + ->getMock(); $pageFactory = $this->getMockBuilder('Magento\Cms\Model\PageFactory') ->disableOriginalConstructor() ->setMethods(['create']) @@ -112,7 +120,8 @@ class PageRepositoryTest extends \PHPUnit_Framework_TestCase $pageDataFactory, $collectionFactory, $pageSearchResultFactory, - $this->dataHelper + $this->dataHelper, + $this->dataObjectProcessor ); } @@ -216,83 +225,40 @@ class PageRepositoryTest extends \PHPUnit_Framework_TestCase $storeFilter = $this->getMockBuilder('Magento\Framework\Api\Filter')->getMock(); $sortOrder = $this->getMockBuilder('Magento\Framework\Api\SortOrder')->getMock(); - $criteria->expects($this->once()) - ->method('getFilterGroups') - ->willReturn([$filterGroup]); - $criteria->expects($this->once()) - ->method('getSortOrders') - ->willReturn([$sortOrder]); - $criteria->expects($this->once()) - ->method('getCurrentPage') - ->willReturn($currentPage); - $criteria->expects($this->once()) - ->method('getPageSize') - ->willReturn($pageSize); - $filterGroup->expects($this->once()) - ->method('getFilters') - ->willReturn([$storeFilter, $filter]); - $filter->expects($this->once()) - ->method('getConditionType') - ->willReturn($condition); - $filter->expects($this->any()) - ->method('getField') - ->willReturn($field); - $filter->expects($this->once()) - ->method('getValue') - ->willReturn($value); - $storeFilter->expects($this->any()) - ->method('getField') - ->willReturn('store_id'); - $storeFilter->expects($this->once()) - ->method('getValue') - ->willReturn(1); - $sortOrder->expects($this->once()) - ->method('getField') - ->willReturn($sortField); - $sortOrder->expects($this->once()) - ->method('getDirection') - ->willReturn(SearchCriteriaInterface::SORT_DESC); + $criteria->expects($this->once())->method('getFilterGroups')->willReturn([$filterGroup]); + $criteria->expects($this->once())->method('getSortOrders')->willReturn([$sortOrder]); + $criteria->expects($this->once())->method('getCurrentPage')->willReturn($currentPage); + $criteria->expects($this->once())->method('getPageSize')->willReturn($pageSize); + $filterGroup->expects($this->once())->method('getFilters')->willReturn([$storeFilter, $filter]); + $filter->expects($this->once())->method('getConditionType')->willReturn($condition); + $filter->expects($this->any())->method('getField')->willReturn($field); + $filter->expects($this->once())->method('getValue')->willReturn($value); + $storeFilter->expects($this->any())->method('getField')->willReturn('store_id'); + $storeFilter->expects($this->once())->method('getValue')->willReturn(1); + $sortOrder->expects($this->once())->method('getField')->willReturn($sortField); + $sortOrder->expects($this->once())->method('getDirection')->willReturn(SearchCriteriaInterface::SORT_DESC); /** @var \Magento\Framework\Api\SearchCriteriaInterface $criteria */ $this->collection->addItem($this->page); - $this->pageSearchResult->expects($this->once()) - ->method('setSearchCriteria') - ->with($criteria) - ->willReturnSelf(); + $this->pageSearchResult->expects($this->once())->method('setSearchCriteria')->with($criteria)->willReturnSelf(); $this->collection->expects($this->once()) ->method('addFieldToFilter') - ->with([['attribute' => $field, $condition => $value]], []) - ->willReturnSelf(); - $this->pageSearchResult->expects($this->once()) - ->method('setTotalCount') - ->with($total) - ->willReturnSelf(); - $this->collection->expects($this->once()) - ->method('getSize') - ->willReturn($total); - $this->collection->expects($this->once()) - ->method('setCurPage') - ->with($currentPage) - ->willReturnSelf(); - $this->collection->expects($this->once()) - ->method('setPageSize') - ->with($pageSize) - ->willReturnSelf(); - $this->collection->expects($this->once()) - ->method('addOrder') - ->with($sortField, 'DESC') - ->willReturnSelf(); - $this->page->expects($this->once()) - ->method('getData') - ->willReturn(['data']); - $this->pageSearchResult->expects($this->once()) - ->method('setItems') - ->with(['someData']) + ->with($field, [$condition => $value]) ->willReturnSelf(); + $this->pageSearchResult->expects($this->once())->method('setTotalCount')->with($total)->willReturnSelf(); + $this->collection->expects($this->once())->method('getSize')->willReturn($total); + $this->collection->expects($this->once())->method('setCurPage')->with($currentPage)->willReturnSelf(); + $this->collection->expects($this->once())->method('setPageSize')->with($pageSize)->willReturnSelf(); + $this->collection->expects($this->once())->method('addOrder')->with($sortField, 'DESC')->willReturnSelf(); + $this->page->expects($this->once())->method('getData')->willReturn(['data']); + $this->pageSearchResult->expects($this->once())->method('setItems')->with(['someData'])->willReturnSelf(); $this->dataHelper->expects($this->once()) ->method('populateWithArray') - ->with($this->pageData, ['data'], 'Magento\Cms\Api\Data\PageInterface') + ->with($this->pageData, ['data'], 'Magento\Cms\Api\Data\PageInterface'); + $this->dataObjectProcessor->expects($this->once()) + ->method('buildOutputDataArray') + ->with($this->pageData, 'Magento\Cms\Api\Data\PageInterface') ->willReturn('someData'); $this->assertEquals($this->pageSearchResult, $this->repository->getList($criteria)); diff --git a/app/code/Magento/Cms/Test/Unit/Model/PageTest.php b/app/code/Magento/Cms/Test/Unit/Model/PageTest.php index 8d08e7402b896f5dd655380a0d5a831389c30538..66ea59baf8942d98e5834e2fba66dd5092a05c88 100644 --- a/app/code/Magento/Cms/Test/Unit/Model/PageTest.php +++ b/app/code/Magento/Cms/Test/Unit/Model/PageTest.php @@ -68,9 +68,9 @@ class PageTest extends \PHPUnit_Framework_TestCase ] ) ->getMock(), - $this->getMockBuilder('Magento\Framework\Data\Collection\Db') + $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') ->disableOriginalConstructor() - ->getMock(), + ->getMockForAbstractClass(), ] ) ->setMethods( diff --git a/app/code/Magento/Cms/Test/Unit/Model/Wysiwyg/Images/StorageTest.php b/app/code/Magento/Cms/Test/Unit/Model/Wysiwyg/Images/StorageTest.php index 22a3e421ff3f3a649a93c42c9be8d6f126a0da21..a24fae248edabe1f9b89dbe38fff026f542fc29a 100644 --- a/app/code/Magento/Cms/Test/Unit/Model/Wysiwyg/Images/StorageTest.php +++ b/app/code/Magento/Cms/Test/Unit/Model/Wysiwyg/Images/StorageTest.php @@ -259,7 +259,7 @@ class StorageTest extends \PHPUnit_Framework_TestCase { $this->setExpectedException( '\Magento\Framework\Exception\LocalizedException', - sprintf('We cannot delete root directory %s.', self::STORAGE_ROOT_DIR) + sprintf('We can\'t delete root directory %s right now.', self::STORAGE_ROOT_DIR) ); $this->_model->deleteDirectory(self::STORAGE_ROOT_DIR); } diff --git a/app/code/Magento/Cms/composer.json b/app/code/Magento/Cms/composer.json index 6dfb05b5a766c5834ac80fee0d96226727d1a89b..73cbc55bc1d1818796bc345b579f2eb594d2d192 100644 --- a/app/code/Magento/Cms/composer.json +++ b/app/code/Magento/Cms/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/module-widget": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-email": "0.74.0-beta10", - "magento/module-ui": "0.74.0-beta10", - "magento/module-variable": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/module-widget": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-email": "0.74.0-beta13", + "magento/module-ui": "0.74.0-beta13", + "magento/module-variable": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Cms/etc/webapi.xml b/app/code/Magento/Cms/etc/webapi.xml new file mode 100644 index 0000000000000000000000000000000000000000..10b3d1a119d6b8cf569ac91c65bd6ab64cae7b5e --- /dev/null +++ b/app/code/Magento/Cms/etc/webapi.xml @@ -0,0 +1,72 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../app/code/Magento/Webapi/etc/webapi.xsd"> + <!-- Cms Page --> + <route url="/V1/cmsPage/:pageId" method="GET"> + <service class="Magento\Cms\Api\PageRepositoryInterface" method="getById"/> + <resources> + <resource ref="Magento_Cms::page"/> + </resources> + </route> + <route url="/V1/cmsPage/search" method="GET"> + <service class="Magento\Cms\Api\PageRepositoryInterface" method="getList"/> + <resources> + <resource ref="Magento_Cms::page"/> + </resources> + </route> + <route url="/V1/cmsPage" method="POST"> + <service class="Magento\Cms\Api\PageRepositoryInterface" method="save"/> + <resources> + <resource ref="Magento_Cms::page"/> + </resources> + </route> + <route url="/V1/cmsPage/:id" method="PUT"> + <service class="Magento\Cms\Api\PageRepositoryInterface" method="save"/> + <resources> + <resource ref="Magento_Cms::page"/> + </resources> + </route> + <route url="/V1/cmsPage/:pageId" method="DELETE"> + <service class="Magento\Cms\Api\PageRepositoryInterface" method="deleteById"/> + <resources> + <resource ref="Magento_Cms::page"/> + </resources> + </route> + <!-- Cms Block --> + <route url="/V1/cmsBlock/:blockId" method="GET"> + <service class="Magento\Cms\Api\BlockRepositoryInterface" method="getById"/> + <resources> + <resource ref="Magento_Cms::block"/> + </resources> + </route> + <route url="/V1/cmsBlock/search" method="GET"> + <service class="Magento\Cms\Api\BlockRepositoryInterface" method="getList"/> + <resources> + <resource ref="Magento_Cms::block"/> + </resources> + </route> + <route url="/V1/cmsBlock" method="POST"> + <service class="Magento\Cms\Api\BlockRepositoryInterface" method="save"/> + <resources> + <resource ref="Magento_Cms::block"/> + </resources> + </route> + <route url="/V1/cmsBlock/:id" method="PUT"> + <service class="Magento\Cms\Api\BlockRepositoryInterface" method="save"/> + <resources> + <resource ref="Magento_Cms::block"/> + </resources> + </route> + <route url="/V1/cmsBlock/:blockId" method="DELETE"> + <service class="Magento\Cms\Api\BlockRepositoryInterface" method="deleteById"/> + <resources> + <resource ref="Magento_Cms::block"/> + </resources> + </route> +</routes> diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_listing.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_block_listing.xml deleted file mode 100644 index 22788b865327bc82bdaa19f196bcbb469bdaeea1..0000000000000000000000000000000000000000 --- a/app/code/Magento/Cms/view/adminhtml/layout/cms_block_listing.xml +++ /dev/null @@ -1,129 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> - <body> - <referenceBlock name="listing"> - <arguments> - <argument name="name" xsi:type="string">cms_block_listing</argument> - <argument name="dataSource" xsi:type="object">Magento\Cms\Model\Resource\Block\Collection</argument> - <argument name="save_parameters_in_session" xsi:type="string">1</argument> - <argument name="configuration" xsi:type="array"> - <item name="page_actions" xsi:type="array"> - <item name="add" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Add New Block</item> - </item> - </item> - </argument> - <argument name="meta" xsi:type="array"> - <item name="defaults" xsi:type="array"> - <item name="visible" xsi:type="boolean">true</item> - <item name="filterable" xsi:type="boolean">true</item> - <item name="sortable" xsi:type="boolean">true</item> - </item> - <item name="index_field" xsi:type="string">block_id</item> - <item name="item_action" xsi:type="string">edit</item> - <item name="fields" xsi:type="array"> - <item name="block_id" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">ID</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">text</item> - <item name="filter_type" xsi:type="string">filter_range</item> - </item> - <item name="title" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Title</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">text</item> - <item name="filter_type" xsi:type="string">filter_input</item> - </item> - <item name="identifier" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Identifier</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">text</item> - <item name="filter_type" xsi:type="string">filter_input</item> - </item> - <item name="store_id" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Store View</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">store</item> - <item name="sortable" xsi:type="boolean">false</item> - <item name="filter_type" xsi:type="string">filter_store</item> - <item name="options_provider" xsi:type="string">Magento\Store\Ui\DataProvider\Options</item> - </item> - <item name="is_active" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Status</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">text</item> - <item name="filter_type" xsi:type="string">filter_select</item> - <item name="options" xsi:type="array"> - <item name="disable" xsi:type="array"> - <item name="value" xsi:type="string">0</item> - <item name="label" xsi:type="string" translate="true">Disabled</item> - </item> - <item name="enable" xsi:type="array"> - <item name="value" xsi:type="string">1</item> - <item name="label" xsi:type="string" translate="true">Enabled</item> - </item> - </item> - </item> - <item name="creation_time" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Created</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">date</item> - <item name="filter_type" xsi:type="string">filter_date</item> - </item> - <item name="update_time" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Modified</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">date</item> - <item name="filter_type" xsi:type="string">filter_date</item> - </item> - <item name="actions" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Action</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">actions</item> - <item name="filterable" xsi:type="boolean">false</item> - <item name="sortable" xsi:type="boolean">false</item> - <item name="visible" xsi:type="boolean">false</item> - </item> - </item> - </argument> - </arguments> - </referenceBlock> - <referenceBlock name="sorting"> - <arguments> - <argument name="config" xsi:type="array"> - <item name="field" xsi:type="string">block_id</item> - </argument> - </arguments> - </referenceBlock> - <referenceBlock name="filters"> - <arguments> - <argument name="config" xsi:type="array"> - <item name="types" xsi:type="array"> - <item name="filter_store" xsi:type="array"> - <item name="module" xsi:type="string">store</item> - <item name="control" xsi:type="string">Magento_Store/js/listing/filter/store</item> - </item> - </item> - </argument> - </arguments> - </referenceBlock> - <referenceBlock name="massactions"> - <arguments> - <argument name="config" xsi:type="array"> - <item name="actions" xsi:type="array"> - <item name="delete" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Delete</item> - <item name="url" xsi:type="string">cms/block/massDelete</item> - </item> - </item> - </argument> - </arguments> - </referenceBlock> - </body> -</page> diff --git a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_listing.xml b/app/code/Magento/Cms/view/adminhtml/layout/cms_page_listing.xml deleted file mode 100644 index 55a8f042883487aa8d6e88524a7e6cbf1ebe6bf6..0000000000000000000000000000000000000000 --- a/app/code/Magento/Cms/view/adminhtml/layout/cms_page_listing.xml +++ /dev/null @@ -1,126 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> - <body> - <referenceBlock name="listing"> - <arguments> - <argument name="name" xsi:type="string">cms_page_listing</argument> - <argument name="dataSource" xsi:type="object">Magento\Cms\Model\Resource\Page\Collection</argument> - <argument name="save_parameters_in_session" xsi:type="string">1</argument> - <argument name="configuration" xsi:type="array"> - <item name="page_actions" xsi:type="array"> - <item name="add" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Add New Page</item> - </item> - </item> - </argument> - <argument name="meta" xsi:type="array"> - <item name="defaults" xsi:type="array"> - <item name="visible" xsi:type="boolean">true</item> - <item name="filterable" xsi:type="boolean">true</item> - <item name="sortable" xsi:type="boolean">true</item> - </item> - <item name="index_field" xsi:type="string">page_id</item> - <item name="item_action" xsi:type="string">edit</item> - <item name="fields" xsi:type="array"> - <item name="page_id" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">ID</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">text</item> - <item name="filter_type" xsi:type="string">filter_range</item> - </item> - <item name="title" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Title</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">text</item> - <item name="filter_type" xsi:type="string">filter_input</item> - </item> - <item name="identifier" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">URL Key</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">text</item> - <item name="filter_type" xsi:type="string">filter_input</item> - </item> - <item name="page_layout" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Layout</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">text</item> - <item name="filter_type" xsi:type="string">filter_select</item> - <item name="options_provider" xsi:type="string">Magento\Cms\Ui\DataProvider\Page\Options\PageLayout</item> - </item> - <item name="store_id" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Store View</item> - <item name="align" xsi:type="string">left</item> - <item name="sortable" xsi:type="boolean">false</item> - <item name="data_type" xsi:type="string">store</item> - <item name="filter_type" xsi:type="string">filter_store</item> - <item name="options_provider" xsi:type="string">Magento\Store\Ui\DataProvider\Options</item> - </item> - <item name="is_active" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Status</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">text</item> - <item name="filter_type" xsi:type="string">filter_select</item> - <item name="options_provider" xsi:type="string">Magento\Cms\Ui\DataProvider\Page\Options\IsActive</item> - </item> - <item name="creation_time" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Created</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">date</item> - <item name="filter_type" xsi:type="string">filter_date</item> - </item> - <item name="update_time" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Modified</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">date</item> - <item name="filter_type" xsi:type="string">filter_date</item> - </item> - <item name="actions" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Action</item> - <item name="align" xsi:type="string">left</item> - <item name="data_type" xsi:type="string">actions</item> - <item name="filterable" xsi:type="boolean">false</item> - <item name="sortable" xsi:type="boolean">false</item> - </item> - </item> - </argument> - </arguments> - </referenceBlock> - <referenceBlock name="massactions"> - <arguments> - <argument name="config" xsi:type="array"> - <item name="actions" xsi:type="array"> - <item name="delete" xsi:type="array"> - <item name="label" xsi:type="string" translate="true">Delete</item> - <item name="url" xsi:type="string">cms/page/massDelete</item> - </item> - </item> - </argument> - </arguments> - </referenceBlock> - <referenceBlock name="filters"> - <arguments> - <argument name="config" xsi:type="array"> - <item name="types" xsi:type="array"> - <item name="filter_store" xsi:type="array"> - <item name="module" xsi:type="string">store</item> - <item name="control" xsi:type="string">Magento_Store/js/listing/filter/store</item> - </item> - </item> - </argument> - </arguments> - </referenceBlock> - <referenceBlock name="sorting"> - <arguments> - <argument name="config" xsi:type="array"> - <item name="field" xsi:type="string">page_id</item> - </argument> - </arguments> - </referenceBlock> - </body> -</page> diff --git a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml index b8f4b086bbf1573bbf24339b2a09cfb4ec414dd5..7d154b524cdacc874bbf5a52daf8dc7dcda81d65 100644 --- a/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml +++ b/app/code/Magento/Cms/view/adminhtml/ui_component/cms_page_listing.xml @@ -376,6 +376,7 @@ <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/sortable</item> </item> <item name="config" xsi:type="array"> + <item name="bodyTmpl" xsi:type="string">ui/grid/cells/html</item> <item name="sortable" xsi:type="boolean">false</item> <item name="dataType" xsi:type="string">text</item> <item name="align" xsi:type="string">left</item> diff --git a/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/Resource/Page.php b/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/Resource/Page.php index 56f773366f7e1ee6d27bc1eb3ef2c94498961b80..ba342b2e1e0694782d1ee16359f19c3cdcb688be 100644 --- a/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/Resource/Page.php +++ b/app/code/Magento/CmsUrlRewrite/Plugin/Cms/Model/Resource/Page.php @@ -5,18 +5,38 @@ */ namespace Magento\CmsUrlRewrite\Plugin\Cms\Model\Resource; +use Magento\UrlRewrite\Model\UrlPersistInterface; +use Magento\CmsUrlRewrite\Model\CmsPageUrlPathGenerator; +use Magento\CmsUrlRewrite\Model\CmsPageUrlRewriteGenerator; +use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; + /** - * Before save plugin for \Magento\Cms\Model\Resource\Page: + * Before save and around delete plugin for \Magento\Cms\Model\Resource\Page: * - autogenerates url_key if the merchant didn't fill this field + * - remove all url rewrites for cms page on delete */ class Page { - /** @var \Magento\CmsUrlRewrite\Model\CmsPageUrlPathGenerator */ + /** + * @var \Magento\CmsUrlRewrite\Model\CmsPageUrlPathGenerator + */ protected $cmsPageUrlPathGenerator; - public function __construct(\Magento\CmsUrlRewrite\Model\CmsPageUrlPathGenerator $cmsPageUrlPathGenerator) - { + /** + * @var UrlPersistInterface + */ + protected $urlPersist; + + /** + * @param CmsPageUrlPathGenerator $cmsPageUrlPathGenerator + * @param UrlPersistInterface $urlPersist + */ + public function __construct( + CmsPageUrlPathGenerator $cmsPageUrlPathGenerator, + UrlPersistInterface $urlPersist + ) { $this->cmsPageUrlPathGenerator = $cmsPageUrlPathGenerator; + $this->urlPersist = $urlPersist; } /** @@ -38,4 +58,32 @@ class Page $object->setData('identifier', $this->cmsPageUrlPathGenerator->generateUrlKey($object)); } } + + /** + * On delete handler to remove related url rewrites + * + * @param \Magento\Cms\Model\Resource\Page $subject + * @param \Closure $proceed + * @param \Magento\Framework\Model\AbstractModel $page + * @return \Magento\Cms\Model\Resource\Page + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundDelete( + \Magento\Cms\Model\Resource\Page $subject, + \Closure $proceed, + \Magento\Framework\Model\AbstractModel $page + ) { + $result = $proceed($page); + if ($page->isDeleted()) { + $this->urlPersist->deleteByData( + [ + UrlRewrite::ENTITY_ID => $page->getId(), + UrlRewrite::ENTITY_TYPE => CmsPageUrlRewriteGenerator::ENTITY_TYPE, + ] + ); + } + + return $result; + } } diff --git a/app/code/Magento/CmsUrlRewrite/Test/Unit/Plugin/Cms/Model/Resource/PageTest.php b/app/code/Magento/CmsUrlRewrite/Test/Unit/Plugin/Cms/Model/Resource/PageTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0b2a082ef37e16c9d84990c0744f25c52b86dfe9 --- /dev/null +++ b/app/code/Magento/CmsUrlRewrite/Test/Unit/Plugin/Cms/Model/Resource/PageTest.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\CmsUrlRewrite\Test\Unit\Plugin\Cms\Model\Resource; + +use Magento\UrlRewrite\Service\V1\Data\UrlRewrite; +use Magento\CmsUrlRewrite\Model\CmsPageUrlRewriteGenerator; + +class PageTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\CmsUrlRewrite\Plugin\Cms\Model\Resource\Page + */ + protected $pageObject; + + /** + * @var \Magento\UrlRewrite\Model\UrlPersistInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $urlPersistMock; + + /** + * @var \Magento\Cms\Model\Page|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cmsPageMock; + + /** + * @var \Magento\Cms\Model\Resource\Page|\PHPUnit_Framework_MockObject_MockObject + */ + protected $cmsPageResourceMock; + + /** + * @var \Closure + */ + protected $closureMock; + + public function setUp() + { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->closureMock = function () { + return 'URL Rewrite Result'; + }; + + $this->urlPersistMock = $this->getMockBuilder('Magento\UrlRewrite\Model\UrlPersistInterface') + ->getMockForAbstractClass(); + + $this->cmsPageMock = $this->getMockBuilder('Magento\Cms\Model\Page') + ->disableOriginalConstructor() + ->getMock(); + + $this->cmsPageResourceMock = $this->getMockBuilder('Magento\Cms\Model\Resource\Page') + ->disableOriginalConstructor() + ->getMock(); + + $this->pageObject = $objectManager->getObject( + 'Magento\CmsUrlRewrite\Plugin\Cms\Model\Resource\Page', + [ + 'urlPersist' => $this->urlPersistMock + ] + ); + } + + public function testAroundDeletePositive() + { + $productId = 100; + + $this->cmsPageMock->expects($this->once()) + ->method('getId') + ->willReturn($productId); + + $this->cmsPageMock->expects($this->once()) + ->method('isDeleted') + ->willReturn(true); + + $this->urlPersistMock->expects($this->once()) + ->method('deleteByData') + ->with( + [ + UrlRewrite::ENTITY_ID => $productId, + UrlRewrite::ENTITY_TYPE => CmsPageUrlRewriteGenerator::ENTITY_TYPE + ] + ); + + $this->assertEquals( + 'URL Rewrite Result', + $this->pageObject->aroundDelete( + $this->cmsPageResourceMock, + $this->closureMock, + $this->cmsPageMock + ) + ); + } + + public function testAroundDeleteNegative() + { + $this->cmsPageMock->expects($this->once()) + ->method('isDeleted') + ->willReturn(false); + + $this->urlPersistMock->expects($this->never()) + ->method('deleteByData'); + + $this->assertEquals( + 'URL Rewrite Result', + $this->pageObject->aroundDelete( + $this->cmsPageResourceMock, + $this->closureMock, + $this->cmsPageMock + ) + ); + } +} diff --git a/app/code/Magento/CmsUrlRewrite/composer.json b/app/code/Magento/CmsUrlRewrite/composer.json index b455b7aa09e2b94aa21e0a71545a8ede84074021..f469ccf9a8a16e50c34bcc66cac4a59c1dc7df58 100644 --- a/app/code/Magento/CmsUrlRewrite/composer.json +++ b/app/code/Magento/CmsUrlRewrite/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-cms": "0.74.0-beta10", - "magento/module-url-rewrite": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-cms": "0.74.0-beta13", + "magento/module-url-rewrite": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Config/Block/System/Config/Form/Field/Factory.php b/app/code/Magento/Config/Block/System/Config/Form/Field/Factory.php index ed6e5fd2669b37e0cabc8f067e9da40aab20a2c6..dd8d8accacb476b200c5eceb6cb15e9579613a1c 100644 --- a/app/code/Magento/Config/Block/System/Config/Form/Field/Factory.php +++ b/app/code/Magento/Config/Block/System/Config/Form/Field/Factory.php @@ -4,11 +4,13 @@ * See COPYING.txt for license details. */ -/** - * \Magento\Config\Block\System\Config\Form\Field object factory - */ namespace Magento\Config\Block\System\Config\Form\Field; +/** + * Magento\Config\Block\System\Config\Form\Field Class Factory + * + * @codeCoverageIgnore + */ class Factory { /** diff --git a/app/code/Magento/Config/Block/System/Config/Form/Fieldset/Factory.php b/app/code/Magento/Config/Block/System/Config/Form/Fieldset/Factory.php index abf93dfccb5db4c4fb4c840fa00b245e55005a99..5cb02fb70512a02174cb60e6145c3095d0ba85af 100644 --- a/app/code/Magento/Config/Block/System/Config/Form/Fieldset/Factory.php +++ b/app/code/Magento/Config/Block/System/Config/Form/Fieldset/Factory.php @@ -4,11 +4,13 @@ * See COPYING.txt for license details. */ -/** - * \Magento\Config\Block\System\Config\Form\Fieldset object factory - */ namespace Magento\Config\Block\System\Config\Form\Fieldset; +/** + * Magento\Config\Block\System\Config\Form\Fieldset object factory + * + * @codeCoverageIgnore + */ class Factory { /** diff --git a/app/code/Magento/Config/Model/Config/Backend/Admin/Custom.php b/app/code/Magento/Config/Model/Config/Backend/Admin/Custom.php index 79b67fa1eb22705b6f1c9ff5bd7d44ad1b5aca66..300b9bd89f898fb92bf574df310b9a1858cd6b88 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Admin/Custom.php +++ b/app/code/Magento/Config/Model/Config/Backend/Admin/Custom.php @@ -35,7 +35,7 @@ class Custom extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\App\Config\Storage\WriterInterface $configWriter * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -44,7 +44,7 @@ class Custom extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\App\Config\Storage\WriterInterface $configWriter, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_configWriter = $configWriter; diff --git a/app/code/Magento/Config/Model/Config/Backend/Admin/Robots.php b/app/code/Magento/Config/Model/Config/Backend/Admin/Robots.php index 90ccace9242ab9d37883f69e0155ff3eb3501f23..4ff70c1b8c35b0381bfad23fcce200a71dc8d2bd 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Admin/Robots.php +++ b/app/code/Magento/Config/Model/Config/Backend/Admin/Robots.php @@ -29,7 +29,7 @@ class Robots extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -38,7 +38,7 @@ class Robots extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\Filesystem $filesystem, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $config, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php b/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php index 1358c71309cb1d5b33761823190c0e7782e9f81e..8479a0433f5cc9c0400f40d43349daf62edeb42b 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php +++ b/app/code/Magento/Config/Model/Config/Backend/Admin/Usecustom.php @@ -24,7 +24,7 @@ class Usecustom extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\App\Config\Storage\WriterInterface $configWriter * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -33,7 +33,7 @@ class Usecustom extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\App\Config\Storage\WriterInterface $configWriter, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_configWriter = $configWriter; diff --git a/app/code/Magento/Config/Model/Config/Backend/Admin/Usesecretkey.php b/app/code/Magento/Config/Model/Config/Backend/Admin/Usesecretkey.php index 0e120571dbdb0dc5be9d8e3d4aeb910d9dcd0500..806445b166791f2993739e7cb793483420fcff53 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Admin/Usesecretkey.php +++ b/app/code/Magento/Config/Model/Config/Backend/Admin/Usesecretkey.php @@ -22,7 +22,7 @@ class Usesecretkey extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Backend\Model\UrlInterface $backendUrl * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -31,7 +31,7 @@ class Usesecretkey extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Backend\Model\UrlInterface $backendUrl, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_backendUrl = $backendUrl; diff --git a/app/code/Magento/Config/Model/Config/Backend/Baseurl.php b/app/code/Magento/Config/Model/Config/Backend/Baseurl.php index 3c51993ca6e1e886558342fd81850ff5102823eb..aa8bb94c54e137b54f3e36507750072de9819dc8 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Baseurl.php +++ b/app/code/Magento/Config/Model/Config/Backend/Baseurl.php @@ -18,7 +18,7 @@ class Baseurl extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\View\Asset\MergeService $mergeService * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -27,7 +27,7 @@ class Baseurl extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\View\Asset\MergeService $mergeService, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_mergeService = $mergeService; diff --git a/app/code/Magento/Config/Model/Config/Backend/Currency/AbstractCurrency.php b/app/code/Magento/Config/Model/Config/Backend/Currency/AbstractCurrency.php index ae104e0d81938dc0791eefc1abc8da7fbc514e6d..cc9f548670eb92b90592b4cb0b598fe90f85faaf 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Currency/AbstractCurrency.php +++ b/app/code/Magento/Config/Model/Config/Backend/Currency/AbstractCurrency.php @@ -30,7 +30,7 @@ abstract class AbstractCurrency extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -39,7 +39,7 @@ abstract class AbstractCurrency extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_scopeConfig = $scopeConfig; diff --git a/app/code/Magento/Config/Model/Config/Backend/Currency/Allow.php b/app/code/Magento/Config/Model/Config/Backend/Currency/Allow.php index 5103829ca9c727eca0c514a364604491ae1b3e24..f277f3ae33e53a3985ea24c8c34daae856758f9a 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Currency/Allow.php +++ b/app/code/Magento/Config/Model/Config/Backend/Currency/Allow.php @@ -24,7 +24,7 @@ class Allow extends AbstractCurrency * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\Locale\CurrencyInterface $localeCurrency * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -34,7 +34,7 @@ class Allow extends AbstractCurrency \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\Locale\CurrencyInterface $localeCurrency, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_localeCurrency = $localeCurrency; diff --git a/app/code/Magento/Config/Model/Config/Backend/Currency/Cron.php b/app/code/Magento/Config/Model/Config/Backend/Currency/Cron.php index 2eeef2f988099f45d2bc4daab2fca7dd80959b46..e484afe0c421f74e70618587345496a8e2aa6ba3 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Currency/Cron.php +++ b/app/code/Magento/Config/Model/Config/Backend/Currency/Cron.php @@ -23,7 +23,7 @@ class Cron extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\App\Config\ValueFactory $configValueFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -32,7 +32,7 @@ class Cron extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\App\Config\ValueFactory $configValueFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_configValueFactory = $configValueFactory; diff --git a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php index af53ce1458b67fa1a169ebd28e81f29e50c865af..932a1aa0d2772b4c821d909a5aeac0aa170f50e7 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Encrypted.php +++ b/app/code/Magento/Config/Model/Config/Backend/Encrypted.php @@ -24,7 +24,7 @@ class Encrypted extends \Magento\Framework\App\Config\Value implements * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\Encryption\EncryptorInterface $encryptor * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -33,7 +33,7 @@ class Encrypted extends \Magento\Framework\App\Config\Value implements \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\Encryption\EncryptorInterface $encryptor, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_encryptor = $encryptor; diff --git a/app/code/Magento/Config/Model/Config/Backend/File.php b/app/code/Magento/Config/Model/Config/Backend/File.php index a08ed7d4f23894640e6592728f9a2c6a8eb1432b..1d9e16a47cddb76c9d5808f8d80846497a6ffae2 100644 --- a/app/code/Magento/Config/Model/Config/Backend/File.php +++ b/app/code/Magento/Config/Model/Config/Backend/File.php @@ -51,7 +51,7 @@ class File extends \Magento\Framework\App\Config\Value * @param \Magento\Config\Model\Config\Backend\File\RequestData\RequestDataInterface $requestData * @param Filesystem $filesystem * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -62,7 +62,7 @@ class File extends \Magento\Framework\App\Config\Value \Magento\Config\Model\Config\Backend\File\RequestData\RequestDataInterface $requestData, Filesystem $filesystem, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_uploaderFactory = $uploaderFactory; diff --git a/app/code/Magento/Config/Model/Config/Backend/Image/Adapter.php b/app/code/Magento/Config/Model/Config/Backend/Image/Adapter.php index ac890c1450891fea9810336404778f715af721ea..7e8e88e4613a97961ea63cdd55719f85cfed8a82 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Image/Adapter.php +++ b/app/code/Magento/Config/Model/Config/Backend/Image/Adapter.php @@ -24,7 +24,7 @@ class Adapter extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\Image\AdapterFactory $imageFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -33,7 +33,7 @@ class Adapter extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\Image\AdapterFactory $imageFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $config, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Config/Model/Config/Backend/Locale.php b/app/code/Magento/Config/Model/Config/Backend/Locale.php index 3d057fd6df864d23061ba4d1d762e265482eb595..334a9f3e51c8715a405884c61bd8d42d4d3bbacd 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Locale.php +++ b/app/code/Magento/Config/Model/Config/Backend/Locale.php @@ -42,7 +42,7 @@ class Locale extends \Magento\Framework\App\Config\Value * @param \Magento\Store\Model\StoreFactory $storeFactory * @param \Magento\Framework\Locale\CurrencyInterface $localeCurrency * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -56,7 +56,7 @@ class Locale extends \Magento\Framework\App\Config\Value \Magento\Store\Model\StoreFactory $storeFactory, \Magento\Framework\Locale\CurrencyInterface $localeCurrency, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_configsFactory = $configsFactory; diff --git a/app/code/Magento/Config/Model/Config/Backend/Log/Cron.php b/app/code/Magento/Config/Model/Config/Backend/Log/Cron.php index fc3f318ed5df7588b354e6a88fe50a91de5dc1fa..8c9e76de4710e6198a266dc9d86ecdb1be2f9b79 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Log/Cron.php +++ b/app/code/Magento/Config/Model/Config/Backend/Log/Cron.php @@ -31,7 +31,7 @@ class Cron extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\App\Config\ValueFactory $configValueFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param string $runModelPath * @param array $data */ @@ -41,7 +41,7 @@ class Cron extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\App\Config\ValueFactory $configValueFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, $runModelPath = '', array $data = [] ) { diff --git a/app/code/Magento/Config/Model/Config/Backend/Secure.php b/app/code/Magento/Config/Model/Config/Backend/Secure.php index 03e6a9ebaae92368d0eaf530c0299af370e4ccd0..85e556bac9345dd07c4a355f74879953f7950dee 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Secure.php +++ b/app/code/Magento/Config/Model/Config/Backend/Secure.php @@ -17,7 +17,7 @@ class Secure extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\View\Asset\MergeService $mergeService * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -26,7 +26,7 @@ class Secure extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\View\Asset\MergeService $mergeService, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_mergeService = $mergeService; diff --git a/app/code/Magento/Config/Model/Config/Backend/Store.php b/app/code/Magento/Config/Model/Config/Backend/Store.php index 34c4186b4eee3e496e96cc7ce8edb5b706f83730..0efe327b7cf35c370541959a323b66f6f5b3962c 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Store.php +++ b/app/code/Magento/Config/Model/Config/Backend/Store.php @@ -22,7 +22,7 @@ class Store extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\App\Config\MutableScopeConfigInterface $mutableConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -31,7 +31,7 @@ class Store extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\App\Config\MutableScopeConfigInterface $mutableConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $config, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Config/Model/Config/Backend/Translate.php b/app/code/Magento/Config/Model/Config/Backend/Translate.php index 092213f16ce541ea848280c95248d1da4835ccae..04b9f7a3a688dee96fda1a09a7fe0507450788ee 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Translate.php +++ b/app/code/Magento/Config/Model/Config/Backend/Translate.php @@ -39,7 +39,7 @@ class Translate extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -49,7 +49,7 @@ class Translate extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_scopeConfig = $scopeConfig; diff --git a/app/code/Magento/Config/Model/Config/Compiler/IncludeElement.php b/app/code/Magento/Config/Model/Config/Compiler/IncludeElement.php new file mode 100644 index 0000000000000000000000000000000000000000..bfbad7dfaaceafabd81c36131a0e5081d4fabe42 --- /dev/null +++ b/app/code/Magento/Config/Model/Config/Compiler/IncludeElement.php @@ -0,0 +1,113 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Model\Config\Compiler; + +use Magento\Framework\Object; +use Magento\Framework\Filesystem; +use Magento\Framework\Module\Dir\Reader; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Element\ElementInterface; + +/** + * Class IncludeElement + */ +class IncludeElement implements ElementInterface +{ + const INCLUDE_PATH = 'path'; + + /** + * @var Reader + */ + protected $moduleReader; + + /** + * @var Filesystem + */ + protected $filesystem; + + /** + * Constructor + * + * @param Reader $moduleReader + * @param Filesystem $filesystem + */ + public function __construct(Reader $moduleReader, Filesystem $filesystem) + { + $this->filesystem = $filesystem; + $this->moduleReader = $moduleReader; + } + + /** + * Compiles the Element node + * + * @param CompilerInterface $compiler + * @param \DOMElement $node + * @param Object $processedObject + * @param Object $context + * @return void + */ + public function compile(CompilerInterface $compiler, \DOMElement $node, Object $processedObject, Object $context) + { + $ownerDocument = $node->ownerDocument; + $parentNode = $node->parentNode; + + $document = new \DOMDocument(); + $document->loadXML($this->getContent($node->getAttribute(static::INCLUDE_PATH))); + + foreach ($this->getChildNodes($document->documentElement) as $child) { + $compiler->compile($child, $processedObject, $context); + } + + $newFragment = $ownerDocument->createDocumentFragment(); + foreach ($document->documentElement->childNodes as $child) { + $newFragment->appendXML($document->saveXML($child)); + } + + $parentNode->replaceChild($newFragment, $node); + } + + /** + * Get child nodes + * + * @param \DOMElement $node + * @return \DOMElement[] + */ + protected function getChildNodes(\DOMElement $node) + { + $childNodes = []; + foreach ($node->childNodes as $child) { + $childNodes[] = $child; + } + + return $childNodes; + } + + /** + * Get content include file (in adminhtml area) + * + * @param string $includePath + * @return string + * @throws LocalizedException + */ + protected function getContent($includePath) + { + $modulesDirectory = $this->filesystem->getDirectoryRead(DirectoryList::MODULES); + + // <include path="Magento_Payment::my_payment.xml" /> + list($moduleName, $filename) = explode('::', $includePath); + + $file = $this->moduleReader->getModuleDir('etc', $moduleName) . '/adminhtml/' . $filename; + $path = $modulesDirectory->getRelativePath($file); + + if ($modulesDirectory->isExist($path) && $modulesDirectory->isFile($path)) { + return $modulesDirectory->readFile($path); + } + + throw new LocalizedException(__('The file "' . $path . '" does not exist')); + } +} diff --git a/app/code/Magento/Config/Model/Config/Structure/Reader.php b/app/code/Magento/Config/Model/Config/Structure/Reader.php index 1d0d1f17a07ed02622dfa9763deb379a07cf4c6c..06af36609cdcd535e123353f2b481f2a3edae1bb 100644 --- a/app/code/Magento/Config/Model/Config/Structure/Reader.php +++ b/app/code/Magento/Config/Model/Config/Structure/Reader.php @@ -8,6 +8,13 @@ */ namespace Magento\Config\Model\Config\Structure; +use Magento\Framework\Object; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface; + +/** + * Class Reader + */ class Reader extends \Magento\Framework\Config\Reader\Filesystem { /** @@ -25,10 +32,18 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem ]; /** + * @var CompilerInterface + */ + protected $compiler; + + /** + * Constructor + * * @param \Magento\Framework\Config\FileResolverInterface $fileResolver * @param Converter $converter * @param \Magento\Config\Model\Config\SchemaLocator $schemaLocator * @param \Magento\Framework\Config\ValidationStateInterface $validationState + * @param CompilerInterface $compiler * @param string $fileName * @param array $idAttributes * @param string $domDocumentClass @@ -39,11 +54,13 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem Converter $converter, \Magento\Config\Model\Config\SchemaLocator $schemaLocator, \Magento\Framework\Config\ValidationStateInterface $validationState, + CompilerInterface $compiler, $fileName = 'system.xml', $idAttributes = [], $domDocumentClass = 'Magento\Framework\Config\Dom', $defaultScope = 'global' ) { + $this->compiler = $compiler; parent::__construct( $fileResolver, $converter, @@ -55,4 +72,66 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem $defaultScope ); } + + /** + * Read configuration files + * + * @param array $fileList + * @return array + * @throws LocalizedException + */ + protected function _readFiles($fileList) + { + + /** @var \Magento\Framework\Config\Dom $configMerger */ + $configMerger = null; + foreach ($fileList as $key => $content) { + try { + $content = $this->processingDocument($content); + if (!$configMerger) { + $configMerger = $this->_createConfigMerger($this->_domDocumentClass, $content); + } else { + $configMerger->merge($content); + } + } catch (\Magento\Framework\Config\Dom\ValidationException $e) { + throw new LocalizedException( + new \Magento\Framework\Phrase("Invalid XML in file %1:\n%2", [$key, $e->getMessage()]) + ); + } + } + + if ($this->_isValidated) { + $errors = []; + if ($configMerger && !$configMerger->validate($this->_schemaFile, $errors)) { + $message = "Invalid Document \n"; + throw new LocalizedException( + new \Magento\Framework\Phrase($message . implode("\n", $errors)) + ); + } + } + + $output = []; + if ($configMerger) { + $output = $this->_converter->convert($configMerger->getDom()); + } + + return $output; + } + + /** + * Processing nodes of the document before merging + * + * @param string $content + * @return string + */ + protected function processingDocument($content) + { + $object = new Object(); + $document = new \DOMDocument(); + + $document->loadXML($content); + $this->compiler->compile($document->documentElement, $object, $object); + + return $document->saveXML(); + } } diff --git a/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/FileTest.php b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/FileTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f6d51f1ec4914736e66e9ac2cbea42a088beb926 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/FileTest.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Tests for \Magento\Framework\Data\Form\Field\File + */ +namespace Magento\Config\Test\Unit\Block\System\Config\Form\Field; + +class FileTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Config\Block\System\Config\Form\Field\File + */ + protected $file; + + /** + * @var array + */ + protected $testData; + + protected function setUp() + { + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->testData = [ + 'before_element_html' => 'test_before_element_html', + 'html_id' => 'test_id', + 'name' => 'test_name', + 'value' => 'test_value', + 'title' => 'test_title', + 'disabled' => true, + 'after_element_js' => 'test_after_element_js', + 'after_element_html' => 'test_after_element_html', + 'html_id_prefix' => 'test_id_prefix_', + 'html_id_suffix' => '_test_id_suffix', + ]; + + $this->file = $objectManager->getObject( + 'Magento\Config\Block\System\Config\Form\Field\File', + ['data' => $this->testData] + ); + + $formMock = new \Magento\Framework\Object(); + $formMock->setHtmlIdPrefix($this->testData['html_id_prefix']); + $formMock->setHtmlIdSuffix($this->testData['html_id_suffix']); + $this->file->setForm($formMock); + } + + public function testGetElementHtml() + { + $html = $this->file->getElementHtml(); + + $expectedHtmlId = $this->testData['html_id_prefix'] + . $this->testData['html_id'] + . $this->testData['html_id_suffix']; + + $this->assertContains('<label class="addbefore" for="' . $expectedHtmlId . '"', $html); + $this->assertContains($this->testData['before_element_html'], $html); + $this->assertContains('<input id="' . $expectedHtmlId . '"', $html); + $this->assertContains('name="' . $this->testData['name'] . '"', $html); + $this->assertContains('value="' . $this->testData['value'] . '"', $html); + $this->assertContains('disabled="disabled"', $html); + $this->assertContains('type="file"', $html); + $this->assertContains($this->testData['after_element_js'], $html); + $this->assertContains('<label class="addafter" for="' . $expectedHtmlId . '"', $html); + $this->assertContains($this->testData['after_element_html'], $html); + $this->assertContains('<input type="checkbox" name="' . $this->testData['name'] . '[delete]"', $html); + } +} diff --git a/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/HeadingTest.php b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/HeadingTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ab54b904cf61c1021f3cc807ed41438f0805b2ba --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/HeadingTest.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Tests for \Magento\Framework\Data\Form\Field\Heading + */ +namespace Magento\Config\Test\Unit\Block\System\Config\Form\Field; + +class HeadingTest extends \PHPUnit_Framework_TestCase +{ + public function testRender() + { + $htmlId = 'test_HTML_id'; + $label = 'test_label'; + + $elementMock = $this->getMockBuilder('Magento\Framework\Data\Form\Element\AbstractElement') + ->disableOriginalConstructor() + ->setMethods(['getHtmlId', 'getLabel']) + ->getMock(); + $elementMock->expects($this->any())->method('getHtmlId')->willReturn($htmlId); + $elementMock->expects($this->any())->method('getLabel')->willReturn($label); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $heading = $objectManager->getObject('Magento\Config\Block\System\Config\Form\Field\Heading', []); + + $html = $heading->render($elementMock); + + $this->assertEquals( + '<tr class="system-fieldset-sub-head" id="row_' . $htmlId . '">' . + '<td colspan="5">' . + '<h4 id="' . $htmlId . '">' . $label . '</h4>' . + '</td>' . + '</tr>', + $html + ); + } +} diff --git a/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/ImageTest.php b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/ImageTest.php index 40d61425c3afe9a492069afae65f89bab051fe78..0d17790ad566c134cb521dcc8130dd2410b49dff 100644 --- a/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/ImageTest.php +++ b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/ImageTest.php @@ -7,17 +7,12 @@ // @codingStandardsIgnoreFile /** - * Tests for \Magento\Framework\Data\Form\Element\Image + * Tests for \Magento\Framework\Data\Form\Field\Image */ namespace Magento\Config\Test\Unit\Block\System\Config\Form\Field; class ImageTest extends \PHPUnit_Framework_TestCase { - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $_objectManagerMock; - /** * @var \Magento\Framework\Url|\PHPUnit_Framework_MockObject_MockObject */ @@ -26,30 +21,36 @@ class ImageTest extends \PHPUnit_Framework_TestCase /** * @var \Magento\Config\Block\System\Config\Form\Field\Image */ - protected $_image; + protected $image; + + /** + * @var array + */ + protected $testData; protected function setUp() { - $factoryMock = $this->getMock('Magento\Framework\Data\Form\Element\Factory', [], [], '', false); - $collectionFactoryMock = $this->getMock( - 'Magento\Framework\Data\Form\Element\CollectionFactory', - [], - [], - '', - false - ); - $escaperMock = $this->getMock('Magento\Framework\Escaper', [], [], '', false); + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->urlBuilderMock = $this->getMock('Magento\Framework\Url', [], [], '', false); - $this->_image = new \Magento\Config\Block\System\Config\Form\Field\Image( - $factoryMock, - $collectionFactoryMock, - $escaperMock, - $this->urlBuilderMock + $this->image = $objectManager->getObject( + 'Magento\Config\Block\System\Config\Form\Field\Image', + [ + 'urlBuilder' => $this->urlBuilderMock, + ] ); + + $this->testData = [ + 'html_id_prefix' => 'test_id_prefix_', + 'html_id' => 'test_id', + 'html_id_suffix' => '_test_id_suffix', + 'path' => 'catalog/product/placeholder', + 'value' => 'test_value', + ]; + $formMock = new \Magento\Framework\Object(); - $formMock->getHtmlIdPrefix('id_prefix'); - $formMock->getHtmlIdPrefix('id_suffix'); - $this->_image->setForm($formMock); + $formMock->setHtmlIdPrefix($this->testData['html_id_prefix']); + $formMock->setHtmlIdSuffix($this->testData['html_id_suffix']); + $this->image->setForm($formMock); } /** @@ -62,8 +63,9 @@ class ImageTest extends \PHPUnit_Framework_TestCase $this->urlBuilderMock->expects($this->once())->method('getBaseUrl') ->with(['_type' => $type])->will($this->returnValue($url)); - $this->_image->setValue('test_value'); - $this->_image->setFieldConfig( + $this->image->setValue($this->testData['value']); + $this->image->setHtmlId($this->testData['html_id']); + $this->image->setFieldConfig( [ 'id' => 'placeholder', 'type' => 'image', @@ -76,25 +78,33 @@ class ImageTest extends \PHPUnit_Framework_TestCase 'upload_dir' => [ 'config' => 'system/filesystem/media', 'scope_info' => '1', - 'value' => 'catalog/product/placeholder', + 'value' => $this->testData['path'], ], 'base_url' => [ 'type' => $type, 'scope_info' => '1', - 'value' => 'catalog/product/placeholder', + 'value' => $this->testData['path'], ], '_elementType' => 'field', 'path' => 'catalog/placeholder', ]); - $html = $this->_image->getElementHtml(); + $expectedHtmlId = $this->testData['html_id_prefix'] + . $this->testData['html_id'] + . $this->testData['html_id_suffix']; + + $html = $this->image->getElementHtml(); $this->assertContains('class="input-file"', $html); $this->assertContains('<input', $html); $this->assertContains('type="file"', $html); $this->assertContains('value="test_value"', $html); $this->assertContains( - '<a href="' . $url - . 'catalog/product/placeholder/test_value" onclick="imagePreview(\'_image\'); return false;"', + '<a href="' + . $url + . $this->testData['path'] + . '/' + . $this->testData['value'] + . '" onclick="imagePreview(\'' . $expectedHtmlId . '_image\'); return false;"', $html ); $this->assertContains('<input type="checkbox"', $html); diff --git a/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/NotificationTest.php b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/NotificationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..66420949643be2c020aac886e93a68f97210c8ea --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/NotificationTest.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Tests for \Magento\Framework\Data\Form\Field\Notification + */ +namespace Magento\Config\Test\Unit\Block\System\Config\Form\Field; + +class NotificationTest extends \PHPUnit_Framework_TestCase +{ + public function testRender() + { + $testCacheValue = '1433259723'; + $testDatetime = (new \DateTime(null, new \DateTimeZone('UTC')))->setTimestamp($testCacheValue); + $formattedDate = (\IntlDateFormatter::formatObject($testDatetime)); + $htmlId = 'test_HTML_id'; + $label = 'test_label'; + + $cacheMock = $this->getMockBuilder('Magento\Framework\App\CacheInterface') + ->disableOriginalConstructor() + ->setMethods(['load', 'getFrontend', 'remove', 'save', 'clean']) + ->getMock(); + $cacheMock->expects($this->any())->method('load')->willReturn($testCacheValue); + + $localeDateMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime\TimezoneInterface') + ->disableOriginalConstructor() + ->getMock(); + $localeDateMock->expects($this->any())->method('date')->willReturn($testDatetime); + $localeDateMock->expects($this->any())->method('getDateTimeFormat')->willReturn(null); + + $elementMock = $this->getMockBuilder('Magento\Framework\Data\Form\Element\AbstractElement') + ->disableOriginalConstructor() + ->setMethods(['getHtmlId', 'getLabel']) + ->getMock(); + $elementMock->expects($this->any())->method('getHtmlId')->willReturn($htmlId); + $elementMock->expects($this->any())->method('getLabel')->willReturn($label); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $notification = $objectManager->getObject( + 'Magento\Config\Block\System\Config\Form\Field\Notification', + [ + 'cache' => $cacheMock, + 'localeDate' => $localeDateMock, + ] + ); + + $html = $notification->render($elementMock); + + $this->assertEquals( + '<tr id="row_' . $htmlId . '">' . + '<td class="label">' . + '<label for="' . $htmlId . '">' . $label . '</label>' . + '</td>' . + '<td class="value">' . + $formattedDate . + '</td>' . + '<td class="scope-label"></td>' . + '<td class=""></td>' . + '</tr>', + $html + ); + } +} diff --git a/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/RegexceptionsTest.php b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/RegexceptionsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bcfca56b6d4fc68b49ab4528e7569e20b10fd626 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Field/RegexceptionsTest.php @@ -0,0 +1,132 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Tests for \Magento\Framework\Data\Form\Field\Regexceptions + */ +namespace Magento\Config\Test\Unit\Block\System\Config\Form\Field; + +class RegexceptionsTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var array + */ + protected $cellParameters; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $labelFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $labelMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $elementFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $elementMock; + + /** + * @var \Magento\Config\Block\System\Config\Form\Field\Regexceptions + */ + protected $object; + + protected function setUp() + { + $this->cellParameters = [ + 'size' => 'testSize', + 'style' => 'testStyle', + 'class' => 'testClass', + ]; + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->labelFactoryMock = $this->getMockBuilder('Magento\Framework\View\Design\Theme\LabelFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->labelMock = $this->getMockBuilder('Magento\Framework\View\Design\Theme\Label') + ->disableOriginalConstructor() + ->getMock(); + $this->elementFactoryMock = $this->getMockBuilder('Magento\Framework\Data\Form\Element\Factory') + ->disableOriginalConstructor() + ->getMock(); + $this->elementMock = $this->getMockBuilder('Magento\Framework\Data\Form\Element\AbstractElement') + ->disableOriginalConstructor() + ->setMethods( + ['setForm', 'setName', 'setHtmlId', 'setValues', 'getName', 'getHtmlId', 'getValues', 'getElementHtml'] + ) + ->getMock(); + + $data = [ + 'elementFactory' => $this->elementFactoryMock, + 'labelFactory' => $this->labelFactoryMock, + 'data' => [ + 'element' => $this->elementMock + ], + ]; + $this->object = $objectManager->getObject('Magento\Config\Block\System\Config\Form\Field\Regexceptions', $data); + } + + public function testRenderCellTemplateValueColumn() + { + $columnName = 'value'; + $expectedResult = 'testValueElementHtml'; + + $this->elementFactoryMock->expects($this->once())->method('create')->willReturn($this->elementMock); + $this->elementMock->expects($this->once())->method('setForm')->willReturnSelf(); + $this->elementMock->expects($this->once())->method('setName')->willReturnSelf(); + $this->elementMock->expects($this->once())->method('setHtmlId')->willReturnSelf(); + $this->elementMock->expects($this->once())->method('setValues')->willReturnSelf(); + $this->elementMock->expects($this->once())->method('getElementHtml')->willReturn($expectedResult); + + $this->labelFactoryMock->expects($this->once())->method('create')->willReturn($this->labelMock); + $this->labelMock->expects($this->once())->method('getLabelsCollection')->willReturn([]); + + $this->object->addColumn( + $columnName, + $this->cellParameters + ); + + $this->assertEquals( + $expectedResult, + $this->object->renderCellTemplate($columnName) + ); + } + + public function testRenderCellTemplateOtherColumn() + { + $columnName = 'testCellName'; + + $this->object->addColumn( + $columnName, + $this->cellParameters + ); + + $actual = $this->object->renderCellTemplate($columnName); + foreach ($this->cellParameters as $parameter) { + $this->assertContains($parameter, $actual, 'Parameter \'' . $parameter . '\' missing in render output.'); + } + } + + public function testRenderCellTemplateWrongColumnName() + { + $columnName = 'testCellName'; + $wrongColumnName = 'wrongTestCellName'; + + $this->object->addColumn($wrongColumnName, $this->cellParameters); + + $this->setExpectedException('\Exception', 'Wrong column name specified.'); + + $this->object->renderCellTemplate($columnName); + } +} diff --git a/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Fieldset/Modules/DisableOutputTest.php b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Fieldset/Modules/DisableOutputTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6f5fa46f65a237ea26bf676537d91aac3c6d4ade --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Block/System/Config/Form/Fieldset/Modules/DisableOutputTest.php @@ -0,0 +1,108 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\Block\System\Config\Form\Fieldset\Modules; + +class DisableOutputTest extends \PHPUnit_Framework_TestCase +{ + public function testRender() + { + $testData = [ + 'htmlId' => 'test_field_id', + 'label' => 'test_label', + 'elementHTML' => 'test_html', + 'legend' => 'test_legend', + 'comment' => 'test_comment', + ]; + + $testModuleList = [ + 'testModuleWithConfigData', + 'testModuleNoConfigData', + ]; + + $configData = ['advanced/modules_disable_output/testModuleWithConfigData' => 'testModuleData']; + + $fieldMock = $this->getMockBuilder('Magento\Config\Block\System\Config\Form\Field') + ->disableOriginalConstructor() + ->getMock(); + + $layoutMock = $this->getMockBuilder('Magento\Framework\View\Layout') + ->disableOriginalConstructor() + ->getMock(); + $layoutMock->expects($this->once()) + ->method('getBlockSingleton') + ->with('Magento\Config\Block\System\Config\Form\Field') + ->willReturn($fieldMock); + + $groupMock = $this->getMockBuilder('Magento\Config\Model\Config\Structure\Element\Group') + ->disableOriginalConstructor() + ->getMock(); + $groupMock->expects($this->once())->method('getFieldsetCss')->willReturn('test_fieldset_css'); + + $elementMock = $this->getMockBuilder('Magento\Framework\Data\Form\Element\Text') + ->disableOriginalConstructor() + ->setMethods( + [ + 'getHtmlId', 'getExpanded', 'getElements', 'getLegend', + 'getComment', 'addField', 'setRenderer', 'toHtml' + ] + )->getMock(); + + $elementMock->expects($this->any()) + ->method('getHtmlId') + ->willReturn($testData['htmlId']); + + $elementMock->expects($this->any())->method('getExpanded')->willReturn(true); + $elementMock->expects($this->any())->method('getLegend')->willReturn($testData['legend']); + $elementMock->expects($this->any())->method('getComment')->willReturn($testData['comment']); + $elementMock->expects($this->any())->method('addField')->willReturn($elementMock); + $elementMock->expects($this->any())->method('setRenderer')->willReturn($elementMock); + $elementMock->expects($this->any())->method('toHtml')->willReturn('test_element_html'); + + $moduleListMock = $this->getMockBuilder('Magento\Framework\Module\ModuleList') + ->disableOriginalConstructor() + ->getMock(); + $moduleListMock->expects($this->any())->method('getNames')->willReturn( + array_merge(['Magento_Backend'], $testModuleList) + ); + + $factory = $this->getMockBuilder('Magento\Framework\Data\Form\Element\Factory') + ->disableOriginalConstructor() + ->getMock(); + + $factoryColl = $this->getMockBuilder('Magento\Framework\Data\Form\Element\CollectionFactory') + ->disableOriginalConstructor() + ->getMock(); + + $formMock = $this->getMockBuilder('Magento\Framework\Data\Form\AbstractForm') + ->disableOriginalConstructor() + ->setConstructorArgs([$factory, $factoryColl]) + ->getMock(); + + $formMock->expects($this->any())->method('getConfigValue')->willReturn('testConfigData'); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $object = $objectManager->getObject( + 'Magento\Config\Block\System\Config\Form\Fieldset\Modules\DisableOutput', + [ + 'moduleList' => $moduleListMock, + 'layout' => $layoutMock, + 'data' => [ + 'group' => $groupMock, + 'form' => $formMock, + 'config_data' => $configData, + ], + ] + ); + + $collection = $objectManager->getObject('Magento\Framework\Data\Form\Element\Collection'); + $elementMock->expects($this->any())->method('getElements')->willReturn($collection); + + $actualHtml = $object->render($elementMock); + $this->assertContains('test_element_html', $actualHtml); + $this->assertContains('test_field_id', $actualHtml); + $this->assertContains('test_comment', $actualHtml); + } +} diff --git a/app/code/Magento/Config/Test/Unit/Model/Compiler/IncludeElementTest.php b/app/code/Magento/Config/Test/Unit/Model/Compiler/IncludeElementTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f00651dd2b91d886e6cfcbeab11429880804fe4c --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Model/Compiler/IncludeElementTest.php @@ -0,0 +1,158 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\Model\Compiler; + +use Magento\Framework\App\Filesystem\DirectoryList; + +/** + * Class IncludeElementTest + */ +class IncludeElementTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Config\Model\Config\Compiler\IncludeElement + */ + protected $includeElement; + + /** + * @var \Magento\Framework\Module\Dir\Reader|\PHPUnit_Framework_MockObject_MockObject + */ + protected $moduleReaderMock; + + /** + * @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + protected $filesystemMock; + + /** + * Set up + * + * @return void + */ + protected function setUp() + { + $this->moduleReaderMock = $this->getMockBuilder('Magento\Framework\Module\Dir\Reader') + ->disableOriginalConstructor() + ->getMock(); + $this->filesystemMock = $this->getMockBuilder('Magento\Framework\Filesystem') + ->disableOriginalConstructor() + ->getMock(); + + $this->includeElement = new \Magento\Config\Model\Config\Compiler\IncludeElement( + $this->moduleReaderMock, + $this->filesystemMock + ); + } + + /** + * @return void + */ + public function testCompileSuccess() + { + $xmlContent = '<rootConfig><include path="Module_Name::path/to/file.xml"/></rootConfig>'; + + $document = new \DOMDocument(); + $document->loadXML($xmlContent); + + $compilerMock = $this->getMockBuilder('Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface') + ->getMockForAbstractClass(); + $processedObjectMock = $this->getMockBuilder('Magento\Framework\Object') + ->disableOriginalConstructor() + ->getMock(); + + $this->getContentStep(); + + $compilerMock->expects($this->exactly(2)) + ->method('compile') + ->with($this->isInstanceOf('\DOMElement'), $processedObjectMock, $processedObjectMock); + + $this->includeElement->compile( + $compilerMock, + $document->documentElement->firstChild, + $processedObjectMock, + $processedObjectMock + ); + + $this->assertEquals( + '<?xml version="1.0"?><rootConfig><item id="1"><test/></item><item id="2"/></rootConfig>', + str_replace(PHP_EOL, '', $document->saveXML()) + ); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage The file "relative/path/to/file.xml" does not exist + */ + public function testCompileException() + { + $xmlContent = '<rootConfig><include path="Module_Name::path/to/file.xml"/></rootConfig>'; + + $document = new \DOMDocument(); + $document->loadXML($xmlContent); + + $compilerMock = $this->getMockBuilder('Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface') + ->getMockForAbstractClass(); + $processedObjectMock = $this->getMockBuilder('Magento\Framework\Object') + ->disableOriginalConstructor() + ->getMock(); + + $this->getContentStep(false); + + $compilerMock->expects($this->never()) + ->method('compile') + ->with($this->isInstanceOf('\DOMElement'), $processedObjectMock, $processedObjectMock); + + $this->includeElement->compile( + $compilerMock, + $document->documentElement->firstChild, + $processedObjectMock, + $processedObjectMock + ); + } + + /** + * @param bool $check + */ + protected function getContentStep($check = true) + { + $resultPath = 'relative/path/to/file.xml'; + $includeXmlContent = '<config><item id="1"><test/></item><item id="2"></item></config>'; + + $modulesDirectoryMock = $this->getMockBuilder('Magento\Framework\Filesystem\Directory\ReadInterface') + ->getMockForAbstractClass(); + + $this->filesystemMock->expects($this->once()) + ->method('getDirectoryRead') + ->with(DirectoryList::MODULES) + ->willReturn($modulesDirectoryMock); + + $this->moduleReaderMock->expects($this->once()) + ->method('getModuleDir') + ->with('etc', 'Module_Name') + ->willReturn('path/in/application/module'); + + $modulesDirectoryMock->expects($this->once()) + ->method('getRelativePath') + ->with('path/in/application/module/adminhtml/path/to/file.xml') + ->willReturn($resultPath); + + $modulesDirectoryMock->expects($this->once()) + ->method('isExist') + ->with($resultPath) + ->willReturn($check); + + if ($check) { + $modulesDirectoryMock->expects($this->once()) + ->method('isFile') + ->with($resultPath) + ->willReturn($check); + $modulesDirectoryMock->expects($this->once()) + ->method('readFile') + ->with($resultPath) + ->willReturn($includeXmlContent); + } + } +} diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/Backend/BaseurlTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Backend/BaseurlTest.php index d40f091ba995db7b5a4cc8a066631d5014c617e8..d9bc25a401bee968b95d6ab8229a9df9c3135c29 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Config/Backend/BaseurlTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Backend/BaseurlTest.php @@ -34,7 +34,9 @@ class BaseurlTest extends \PHPUnit_Framework_TestCase $resource = $this->getMock('Magento\Config\Model\Resource\Config\Data', [], [], '', false); $resource->expects($this->any())->method('addCommitCallback')->will($this->returnValue($resource)); - $resourceCollection = $this->getMock('Magento\Framework\Data\Collection\Db', [], [], '', false); + $resourceCollection = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $mergeService = $this->getMock('Magento\Framework\View\Asset\MergeService', [], [], '', false); $coreRegistry = $this->getMock('Magento\Framework\Registry', [], [], '', false); $coreConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'); diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SecureTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SecureTest.php index e21ed34e24f02b9b989fdad4da719a55bd45af12..d1726eabc1f4ee54b96bdfaf828c7f9c38e05108 100644 --- a/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SecureTest.php +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Backend/SecureTest.php @@ -30,7 +30,9 @@ class SecureTest extends \PHPUnit_Framework_TestCase $resource = $this->getMock('Magento\Config\Model\Resource\Config\Data', [], [], '', false); $resource->expects($this->any())->method('addCommitCallback')->will($this->returnValue($resource)); - $resourceCollection = $this->getMock('Magento\Framework\Data\Collection\Db', [], [], '', false); + $resourceCollection = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $mergeService = $this->getMock('Magento\Framework\View\Asset\MergeService', [], [], '', false); $coreRegistry = $this->getMock('Magento\Framework\Registry', [], [], '', false); $coreConfig = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'); diff --git a/app/code/Magento/Config/Test/Unit/Model/Config/Structure/ReaderTest.php b/app/code/Magento/Config/Test/Unit/Model/Config/Structure/ReaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3a7e0b1a7ac829f5f11c28283640bbe76a0ea057 --- /dev/null +++ b/app/code/Magento/Config/Test/Unit/Model/Config/Structure/ReaderTest.php @@ -0,0 +1,102 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Config\Test\Unit\Model\Config\Structure; + +/** + * Class ReaderTest + */ +class ReaderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Config\Model\Config\Structure\Reader + */ + protected $reader; + + /** + * @var \Magento\Framework\Config\FileResolverInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $fileResolverMock; + + /** + * @var \Magento\Config\Model\Config\Structure\Converter|\PHPUnit_Framework_MockObject_MockObject + */ + protected $converterMock; + + /** + * @var \Magento\Config\Model\Config\SchemaLocator|\PHPUnit_Framework_MockObject_MockObject + */ + protected $schemaLocatorMock; + + /** + * @var \Magento\Framework\Config\ValidationStateInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $validationStateMock; + + /** + * @var \Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $compilerMock; + + /** + * Set up + * + * @return void + */ + protected function setUp() + { + $this->fileResolverMock = $this->getMockBuilder('Magento\Framework\Config\FileResolverInterface') + ->getMockForAbstractClass(); + $this->converterMock = $this->getMockBuilder('Magento\Config\Model\Config\Structure\Converter') + ->disableOriginalConstructor() + ->getMock(); + $this->schemaLocatorMock = $this->getMockBuilder('Magento\Config\Model\Config\SchemaLocator') + ->disableOriginalConstructor() + ->getMock(); + $this->validationStateMock = $this->getMockBuilder('Magento\Framework\Config\ValidationStateInterface') + ->getMockForAbstractClass(); + $this->compilerMock = $this->getMockBuilder('Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface') + ->getMockForAbstractClass(); + + $this->reader = new \Magento\Config\Model\Config\Structure\Reader( + $this->fileResolverMock, + $this->converterMock, + $this->schemaLocatorMock, + $this->validationStateMock, + $this->compilerMock + ); + } + + /** + * Test the successful execution of the 'read' method + * + * @return void + */ + public function testReadSuccessNotValidatedCase() + { + $content = '<config><item name="test1"></item><item name="test2"></item></config>'; + $expectedResult = ['result_data']; + $fileList = ['file' => $content]; + + $this->fileResolverMock->expects($this->once()) + ->method('get') + ->with('system.xml', 'global') + ->willReturn($fileList); + + $this->compilerMock->expects($this->once()) + ->method('compile') + ->with( + $this->isInstanceOf('\DOMElement'), + $this->isInstanceOf('Magento\Framework\Object'), + $this->isInstanceOf('Magento\Framework\Object') + ); + $this->converterMock->expects($this->once()) + ->method('convert') + ->with($this->isInstanceOf('\DOMDocument')) + ->willReturn($expectedResult); + + $this->assertEquals($expectedResult, $this->reader->read()); + } +} diff --git a/app/code/Magento/Config/composer.json b/app/code/Magento/Config/composer.json index b09b7ab2e271ca1504af14461a6e7ca79f680c80..99e065fbf08f55ac4666e3c27b6944de65d9f4e0 100644 --- a/app/code/Magento/Config/composer.json +++ b/app/code/Magento/Config/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-cron": "0.74.0-beta10", - "magento/module-email": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-cron": "0.74.0-beta13", + "magento/module-email": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Config/etc/di.xml b/app/code/Magento/Config/etc/di.xml index 44792432ccea7b93d1bc637196eb49893d2d584a..1ead2f9a3418a2587f84577d7a274416eddc9da7 100644 --- a/app/code/Magento/Config/etc/di.xml +++ b/app/code/Magento/Config/etc/di.xml @@ -9,6 +9,22 @@ <preference for="Magento\Config\Model\Config\Structure\SearchInterface" type="Magento\Config\Model\Config\Structure" /> <preference for="Magento\Config\Model\Config\Backend\File\RequestData\RequestDataInterface" type="Magento\Config\Model\Config\Backend\File\RequestData" /> <preference for="Magento\Framework\App\Config\Resource\ConfigInterface" type="Magento\Config\Model\Resource\Config" /> + <virtualType name="Magento\Framework\View\TemplateEngine\Xhtml\ConfigCompiler" type="Magento\Framework\View\TemplateEngine\Xhtml\Compiler" shared="false"> + <arguments> + <argument name="compilerText" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Text</argument> + <argument name="compilerAttribute" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Attribute</argument> + <argument name="compilerCdata" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Cdata</argument> + <argument name="compilerComment" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Comment</argument> + <argument name="elementCompilers" xsi:type="array"> + <item name="include" xsi:type="object">Magento\Config\Model\Config\Compiler\IncludeElement</item> + </argument> + </arguments> + </virtualType> + <type name="Magento\Config\Model\Config\Structure\Reader"> + <arguments> + <argument name="compiler" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\ConfigCompiler</argument> + </arguments> + </type> <type name="Magento\Config\Controller\Adminhtml\System\Config\Save"> <arguments> <argument name="cache" xsi:type="object">Magento\Framework\App\Cache\Type\Layout</argument> diff --git a/app/code/Magento/Config/etc/system_file.xsd b/app/code/Magento/Config/etc/system_file.xsd index aa27838b6d21f04f1e613c901614f0374fd59b5e..f0ededa2efadbbacdf98ab5111ced942e917cab7 100644 --- a/app/code/Magento/Config/etc/system_file.xsd +++ b/app/code/Magento/Config/etc/system_file.xsd @@ -6,20 +6,21 @@ */ --> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> - <xs:element name="config"> - <xs:complexType> - <xs:sequence> - <xs:element ref="system" minOccurs="1" maxOccurs="1" /> - </xs:sequence> - </xs:complexType> - </xs:element> + <xs:element name="config" type="configDeclaration"/> + + <xs:complexType name="configDeclaration"> + <xs:sequence> + <xs:element ref="system" minOccurs="1" maxOccurs="1" /> + </xs:sequence> + </xs:complexType> <xs:element name="system"> <xs:complexType> <xs:sequence> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element ref="tab" /> - <xs:element ref="section"/> + <xs:element ref="section" /> + <xs:element name="include" type="includeType"/> </xs:choice> </xs:sequence> </xs:complexType> @@ -64,6 +65,15 @@ <xs:attribute name="extends" type="xs:string" use="optional" /> </xs:attributeGroup> + <xs:complexType name="includeType"> + <xs:annotation> + <xs:documentation> + Include Resource. Recursive complex type + </xs:documentation> + </xs:annotation> + <xs:attribute name="path" type="typePath" use="required" /> + </xs:complexType> + <xs:element name="tab"> <xs:annotation> <xs:documentation> @@ -95,6 +105,7 @@ <xs:element name="header_css" type="xs:string" /> <xs:element name="resource" type="typeAclResourceId" /> <xs:element ref="group" /> + <xs:element name="include" type="includeType"/> </xs:choice> </xs:sequence> @@ -136,6 +147,7 @@ <xs:element ref="group" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="depends" /> <xs:element ref="attribute" /> + <xs:element name="include" type="includeType"/> </xs:choice> </xs:sequence> @@ -420,6 +432,22 @@ </xs:restriction> </xs:simpleType> + <xs:simpleType name="typePath"> + <xs:annotation> + <xs:documentation> + <![CDATA[ + Path identifier. Item can has only [a-zA-Z0-9/_:]. Minimal length 8 symbol. Case sensitive. + For example: <Magento_Module>::path/to/file.xml (path in the "etc/adminhtml" area in module) + ]]> + </xs:documentation> + </xs:annotation> + + <xs:restriction base="xs:string"> + <xs:pattern value="[A-Z]+[a-z0-9]{1,}_[A-Z]+[A-Z0-9a-z]{1,}::[A-Za-z_0-9/.]{1,}" /> + <xs:minLength value="8" /> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="typeModule"> <xs:annotation> <xs:documentation> diff --git a/app/code/Magento/Config/etc/system_include.xsd b/app/code/Magento/Config/etc/system_include.xsd new file mode 100644 index 0000000000000000000000000000000000000000..2c39b82927d2bb9bf12e848388cf4ee46c911a51 --- /dev/null +++ b/app/code/Magento/Config/etc/system_include.xsd @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:include schemaLocation="system_file.xsd"/> + <xs:element name="include" type="include" /> + <xs:complexType name="include"> + <xs:group minOccurs="1" maxOccurs="unbounded" ref="insertNodes"/> + </xs:complexType> + <xs:group name="insertNodes"> + <xs:choice> + <xs:element ref="group" /> + <xs:element ref="tab" /> + <xs:element ref="section" /> + <xs:element ref="include" /> + </xs:choice> + </xs:group> +</xs:schema> diff --git a/app/code/Magento/Config/view/adminhtml/templates/system/config/form/field/array.phtml b/app/code/Magento/Config/view/adminhtml/templates/system/config/form/field/array.phtml index c85f9314837ffee94569cc233fa906700dfb177a..5bdb6bc3a8916bff873fbfe552ce966c8889d130 100644 --- a/app/code/Magento/Config/view/adminhtml/templates/system/config/form/field/array.phtml +++ b/app/code/Magento/Config/view/adminhtml/templates/system/config/form/field/array.phtml @@ -14,26 +14,28 @@ $_colspan = $block->isAddAfter() ? 2 : 1; ?> <div class="design_theme_ua_regexp" id="grid<?php echo $_htmlId; ?>"> - <table class="admin__control-table"> - <thead> - <tr> - <?php foreach ($block->getColumns() as $columnName => $column): ?> - <th><?php echo $column['label']; ?></th> - <?php endforeach;?> - <th class="col-actions" colspan="<?php echo $_colspan; ?>">Action</th> - </tr> - </thead> - <tfoot> - <tr> - <td colspan="<?php echo count($block->getColumns())+$_colspan; ?>" class="col-actions-add"> - <button id="addToEndBtn<?php echo $_htmlId; ?>" class="action- add" title="<?php echo __('Add'); ?>" type="button"> - <span><?php echo $block->getAddButtonLabel(); ?><?php echo __('Add'); ?></span> - </button> - </td> - </tr> - </tfoot> - <tbody id="addRow<?php echo $_htmlId; ?>"></tbody> - </table> + <div class="admin__control-table-wrapper"> + <table class="admin__control-table"> + <thead> + <tr> + <?php foreach ($block->getColumns() as $columnName => $column): ?> + <th><?php echo $column['label']; ?></th> + <?php endforeach;?> + <th class="col-actions" colspan="<?php echo $_colspan; ?>">Action</th> + </tr> + </thead> + <tfoot> + <tr> + <td colspan="<?php echo count($block->getColumns())+$_colspan; ?>" class="col-actions-add"> + <button id="addToEndBtn<?php echo $_htmlId; ?>" class="action-add" title="<?php echo __('Add'); ?>" type="button"> + <span><?php echo $block->getAddButtonLabel(); ?><?php echo __('Add'); ?></span> + </button> + </td> + </tr> + </tfoot> + <tbody id="addRow<?php echo $_htmlId; ?>"></tbody> + </table> + </div> <input type="hidden" name="<?php echo $block->getElement()->getName(); ?>[__empty]" value="" /> <script> @@ -54,10 +56,10 @@ $_colspan = $block->isAddAfter() ? 2 : 1; <?php endforeach; ?> <?php if ($block->isAddAfter()): ?> - + '<td><button class="action- add" type="button" id="addAfterBtn<%- _id %>"><span><?php echo __('Add after'); ?><\/span><\/button><\/td>' + + '<td><button class="action-add" type="button" id="addAfterBtn<%- _id %>"><span><?php echo __('Add after'); ?><\/span><\/button><\/td>' <?php endif; ?> - + '<td class="col-actions"><button onclick="arrayRow<?php echo $_htmlId ?>.del(\'<%- _id %>\')" class="action- delete" type="button"><span><?php echo __('Delete'); ?><\/span><\/button><\/td>' + + '<td class="col-actions"><button onclick="arrayRow<?php echo $_htmlId ?>.del(\'<%- _id %>\')" class="action-delete" type="button"><span><?php echo __('Delete'); ?><\/span><\/button><\/td>' +'<\/tr>' ), diff --git a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php index a824f8912a40f08b162436bdbacaef326a68ad2a..f4d09840686aaa5f4748d131fc186af51e6f9909 100644 --- a/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableImportExport/Model/Import/Product/Type/Configurable.php @@ -7,6 +7,14 @@ */ namespace Magento\ConfigurableImportExport\Model\Import\Product\Type; +use Magento\CatalogImportExport\Model\Import\Product as ImportProduct; + +/** + * Importing configurable products + * @package Magento\ConfigurableImportExport\Model\Import\Product\Type + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + */ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType { /** @@ -125,26 +133,70 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ protected $_resource; /** + * Instance of mysql database adapter. + * + * @var \Magento\Framework\DB\Adapter\Pdo\Mysql + */ + protected $_connection; + + /** + * Instance of product collection factory. + * * @var \Magento\Catalog\Model\Resource\Product\CollectionFactory */ protected $_productColFac; + /** + * Product data. + * + * @var array + */ + protected $_productData; + + /** + * Product super data. + * + * @var array + */ + protected $_productSuperData; + + /** + * Simple product ids to delete. + * + * @var array + */ + protected $_simpleIdsToDelete; + + /** + * Super attributes data. + * + * @var array + */ + protected $_superAttributesData; + + /** + * Next attribute id. + * + * @var null|int + */ + protected $_nextAttrId; + /** * @param \Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory $attrSetColFac * @param \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $prodAttrColFac * @param array $params + * @param \Magento\Framework\App\Resource $resource * @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypesConfig * @param \Magento\ImportExport\Model\Resource\Helper $resourceHelper - * @param \Magento\Framework\App\Resource $resource * @param \Magento\Catalog\Model\Resource\Product\CollectionFactory $_productColFac */ public function __construct( \Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory $attrSetColFac, \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $prodAttrColFac, array $params, + \Magento\Framework\App\Resource $resource, \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypesConfig, \Magento\ImportExport\Model\Resource\Helper $resourceHelper, - \Magento\Framework\App\Resource $resource, \Magento\Catalog\Model\Resource\Product\CollectionFactory $_productColFac ) { $this->_productTypesConfig = $productTypesConfig; @@ -152,6 +204,7 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ $this->_resource = $resource; $this->_productColFac = $_productColFac; parent::__construct($attrSetColFac, $prodAttrColFac, $params); + $this->_connection = $this->_entityModel->getConnection(); } /** @@ -252,6 +305,7 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ * @param array $newSku - imported variations list * @param array $oldSku - present variations list * @return $this + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function _loadSkuSuperAttributeValues($bunch, $newSku, $oldSku) { @@ -260,11 +314,20 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ $productIds = []; foreach ($bunch as $rowData) { - if (!empty($rowData['_super_products_sku'])) { - if (isset($newSku[$rowData['_super_products_sku']])) { - $productIds[] = $newSku[$rowData['_super_products_sku']]['entity_id']; - } elseif (isset($oldSku[$rowData['_super_products_sku']])) { - $productIds[] = $oldSku[$rowData['_super_products_sku']]['entity_id']; + $dataWithExtraVirtualRows = $this->_parseVariations($rowData); + if (!empty($dataWithExtraVirtualRows)) { + array_unshift($dataWithExtraVirtualRows, $rowData); + } else { + $dataWithExtraVirtualRows[] = $rowData; + } + + foreach ($dataWithExtraVirtualRows as $data) { + if (!empty($data['_super_products_sku'])) { + if (isset($newSku[$data['_super_products_sku']])) { + $productIds[] = $newSku[$data['_super_products_sku']]['entity_id']; + } elseif (isset($oldSku[$data['_super_products_sku']])) { + $productIds[] = $oldSku[$data['_super_products_sku']]['entity_id']; + } } } } @@ -298,23 +361,22 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ protected function _loadSkuSuperData() { if (!$this->_skuSuperData) { - $connection = $this->_entityModel->getConnection(); $mainTable = $this->_resource->getTableName('catalog_product_super_attribute'); $priceTable = $this->_resource->getTableName('catalog_product_super_attribute_pricing'); - $select = $connection->select()->from( + $select = $this->_connection->select()->from( ['m' => $mainTable], ['product_id', 'attribute_id', 'product_super_attribute_id'] )->joinLeft( ['p' => $priceTable], - $connection->quoteIdentifier( + $this->_connection->quoteIdentifier( 'p.product_super_attribute_id' - ) . ' = ' . $connection->quoteIdentifier( + ) . ' = ' . $this->_connection->quoteIdentifier( 'm.product_super_attribute_id' ), ['value_index'] ); - foreach ($connection->fetchAll($select) as $row) { + foreach ($this->_connection->fetchAll($select) as $row) { $attrId = $row['attribute_id']; $productId = $row['product_id']; if ($row['value_index']) { @@ -329,31 +391,30 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ /** * Validate and prepare data about super attributes and associated products. * - * @param array $superData - * @param array $superAttributes * @return $this * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - protected function _processSuperData(array $superData, array &$superAttributes) + protected function _processSuperData() { - if ($superData) { + if ($this->_productSuperData) { $usedCombs = []; // is associated products applicable? - foreach (array_keys($superData['assoc_ids']) as $assocId) { - if (!isset($this->_skuSuperAttributeValues[$superData['attr_set_code']][$assocId])) { + foreach (array_keys($this->_productSuperData['assoc_ids']) as $assocId) { + if (!isset($this->_skuSuperAttributeValues[$this->_productSuperData['attr_set_code']][$assocId])) { continue; } - if ($superData['used_attributes']) { - $skuSuperValues = $this->_skuSuperAttributeValues[$superData['attr_set_code']][$assocId]; + if ($this->_productSuperData['used_attributes']) { + $skuSuperValues = $this + ->_skuSuperAttributeValues[$this->_productSuperData['attr_set_code']][$assocId]; $usedCombParts = []; - foreach ($superData['used_attributes'] as $usedAttrId => $usedValues) { + foreach ($this->_productSuperData['used_attributes'] as $usedAttrId => $usedValues) { if (empty($skuSuperValues[$usedAttrId]) || !isset($usedValues[$skuSuperValues[$usedAttrId]])) { // invalid value or value does not exists for associated product continue; } $usedCombParts[] = $skuSuperValues[$usedAttrId]; - $superData['used_attributes'][$usedAttrId][$skuSuperValues[$usedAttrId]] = true; + $this->_productSuperData['used_attributes'][$usedAttrId][$skuSuperValues[$usedAttrId]] = true; } $comb = implode('|', $usedCombParts); @@ -363,60 +424,397 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ } $usedCombs[$comb] = true; } - $superAttributes['super_link'][] = [ + $this->_superAttributesData['super_link'][] = [ 'product_id' => $assocId, - 'parent_id' => $superData['product_id'], + 'parent_id' => $this->_productSuperData['product_id'], ]; - $superAttributes['relation'][] = [ - 'parent_id' => $superData['product_id'], + $this->_superAttributesData['relation'][] = [ + 'parent_id' => $this->_productSuperData['product_id'], 'child_id' => $assocId, ]; } // clean up unused values pricing - foreach ($superData['used_attributes'] as $usedAttrId => $usedValues) { + //@codingStandardsIgnoreStart + foreach ($this->_productSuperData['used_attributes'] as $usedAttrId => $usedValues) { foreach ($usedValues as $optionId => $isUsed) { - if (!$isUsed && isset($superAttributes['pricing'][$superData['product_id']][$usedAttrId])) { - foreach ($superAttributes['pricing'][$superData['product_id']][$usedAttrId] as $k => $params) { - if ($optionId == $params['value_index']) { - unset($superAttributes['pricing'][$superData['product_id']][$usedAttrId][$k]); + if (!$isUsed && isset($this->_superAttributesData['pricing'])) { + foreach ($this->_superAttributesData['pricing'] as $k => $params) { + if (($optionId == $params['value_index']) && ($usedAttrId == $params['product_super_attribute_id'])) { + unset($this->_superAttributesData['pricing'][$this->_productSuperData['product_id']][$usedAttrId][$k]); } } } } } + //@codingStandardsIgnoreEnd } return $this; } /** - * Save product type specific data. + * Parse variations string to inner format. * - * @throws \Exception - * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + * @param array $rowData + * + * @return array * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function saveData() + protected function _parseVariations($rowData) + { + $prices = $this->_parseVariationPrices($rowData); + $additionalRows = []; + if (!isset($rowData['configurable_variations'])) { + return $additionalRows; + } + $variations = explode(ImportProduct::PSEUDO_MULTI_LINE_SEPARATOR, $rowData['configurable_variations']); + foreach ($variations as $variation) { + $fieldAndValuePairsText = explode($this->_entityModel->getMultipleValueSeparator(), $variation); + $additionalRow = []; + + $fieldAndValuePairs = []; + foreach ($fieldAndValuePairsText as $nameAndValue) { + $nameAndValue = explode(ImportProduct::PAIR_NAME_VALUE_SEPARATOR, $nameAndValue); + if (!empty($nameAndValue)) { + $value = isset($nameAndValue[1]) ? trim($nameAndValue[1]) : ''; + $fieldName = trim($nameAndValue[0]); + if ($fieldName) { + $fieldAndValuePairs[$fieldName] = $value; + } + } + } + + if (!empty($fieldAndValuePairs['sku'])) { + $additionalRow['_super_products_sku'] = $fieldAndValuePairs['sku']; + unset($fieldAndValuePairs['sku']); + $additionalRow['display'] = isset($fieldAndValuePairs['display']) ? $fieldAndValuePairs['display'] : 1; + unset($fieldAndValuePairs['display']); + foreach ($fieldAndValuePairs as $attrCode => $attrValue) { + $additionalRow['_super_attribute_code'] = $attrCode; + $additionalRow['_super_attribute_option'] = $attrValue; + $additionalRow['_super_attribute_price_corr'] = isset($prices[$attrCode][$attrValue]) + ? $prices[$attrCode][$attrValue] + : ''; + $additionalRows[] = $additionalRow; + $additionalRow = []; + } + } + } + return $additionalRows; + } + + /** + * Parse variation labels to array + * ...attribute_code => label ... + * ...attribute_code2 => label2 ... + * + * @param array $rowData + * + * @return array + */ + protected function _parseVariationLabels($rowData) + { + $labels = []; + if (!isset($rowData['configurable_variation_labels'])) { + return $labels; + } + $pairFieldAndValue = explode( + $this->_entityModel->getMultipleValueSeparator(), + $rowData['configurable_variation_labels'] + ); + + foreach ($pairFieldAndValue as $nameAndValue) { + $nameAndValue = explode(ImportProduct::PAIR_NAME_VALUE_SEPARATOR, $nameAndValue); + if (!empty($nameAndValue)) { + $value = isset($nameAndValue[1]) ? trim($nameAndValue[1]) : ''; + $attrCode = trim($nameAndValue[0]); + if ($attrCode) { + $labels[$attrCode] = $value; + } + } + } + return $labels; + } + + /** + * Parse variation prices to array + * ...[attribute_code][value] => price1 ... + * ...[attribute_code][value2] => price2 ... + * + * @param array $rowData + * + * @return array + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + protected function _parseVariationPrices($rowData) + { + $prices = []; + if (!isset($rowData['configurable_variation_prices'])) { + return $prices; + } + $optionRows = explode(ImportProduct::PSEUDO_MULTI_LINE_SEPARATOR, $rowData['configurable_variation_prices']); + foreach ($optionRows as $optionRow) { + + $pairFieldAndValue = explode($this->_entityModel->getMultipleValueSeparator(), $optionRow); + + $oneOptionValuePrice = []; + foreach ($pairFieldAndValue as $nameAndValue) { + $nameAndValue = explode(ImportProduct::PAIR_NAME_VALUE_SEPARATOR, $nameAndValue); + if (!empty($nameAndValue)) { + $value = isset($nameAndValue[1]) ? trim($nameAndValue[1]) : ''; + $paramName = trim($nameAndValue[0]); + if ($paramName) { + $oneOptionValuePrice[$paramName] = $value; + } + } + } + + if (!empty($oneOptionValuePrice['name']) && + !empty($oneOptionValuePrice['value']) && + isset($oneOptionValuePrice['price']) + ) { + $prices[$oneOptionValuePrice['name']][$oneOptionValuePrice['value']] = $oneOptionValuePrice['price']; + } + } + return $prices; + } + + /** + * Delete unnecessary links. + * + * @return $this + */ + protected function _deleteData() + { + $linkTable = $this->_resource->getTableName('catalog_product_super_link'); + $relationTable = $this->_resource->getTableName('catalog_product_relation'); + + if (($this->_entityModel->getBehavior() == \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND) + && !empty($this->_productSuperData['product_id']) + && !empty($this->_simpleIdsToDelete) + ) { + $quoted = $this->_connection->quoteInto('IN (?)', [$this->_productSuperData['product_id']]); + $quotedChildren = $this->_connection->quoteInto('IN (?)', $this->_simpleIdsToDelete); + $this->_connection->delete($linkTable, "parent_id {$quoted} AND product_id {$quotedChildren}"); + $this->_connection->delete($relationTable, "parent_id {$quoted} AND child_id {$quotedChildren}"); + } + return $this; + } + + /** + * Collected link data insertion. + * + * @return $this + * @throws \Zend_Db_Exception + */ + protected function _insertData() { - $connection = $this->_entityModel->getConnection(); $mainTable = $this->_resource->getTableName('catalog_product_super_attribute'); $labelTable = $this->_resource->getTableName('catalog_product_super_attribute_label'); $priceTable = $this->_resource->getTableName('catalog_product_super_attribute_pricing'); $linkTable = $this->_resource->getTableName('catalog_product_super_link'); $relationTable = $this->_resource->getTableName('catalog_product_relation'); + + $mainData = []; + foreach ($this->_superAttributesData['attributes'] as $productId => $attributesData) { + foreach ($attributesData as $attrId => $row) { + $row['product_id'] = $productId; + $row['attribute_id'] = $attrId; + $mainData[] = $row; + } + } + if ($mainData) { + $this->_connection->insertOnDuplicate($mainTable, $mainData); + } + if ($this->_superAttributesData['labels']) { + $this->_connection->insertOnDuplicate($labelTable, $this->_superAttributesData['labels']); + } + if ($this->_superAttributesData['pricing']) { + $this->_connection->insertOnDuplicate( + $priceTable, + $this->_superAttributesData['pricing'], + ['is_percent', 'pricing_value'] + ); + } + if ($this->_superAttributesData['super_link']) { + $this->_connection->insertOnDuplicate($linkTable, $this->_superAttributesData['super_link']); + } + if ($this->_superAttributesData['relation']) { + $this->_connection->insertOnDuplicate($relationTable, $this->_superAttributesData['relation']); + } + return $this; + } + + /** + * Get new supper attribute id. + * + * @return int + */ + protected function _getNextAttrId() + { + if (!$this->_nextAttrId) { + $mainTable = $this->_resource->getTableName('catalog_product_super_attribute'); + $this->_nextAttrId = $this->_resourceHelper->getNextAutoincrement($mainTable); + } + $this->_nextAttrId++; + return $this->_nextAttrId; + } + + /** + * Collect super data. + * + * @param array $rowData + * @return $this + */ + protected function _collectSuperData($rowData) + { + $productId = $this->_productData['entity_id']; + + $this->_processSuperData(); + + $this->_productSuperData = [ + 'product_id' => $productId, + 'attr_set_code' => $this->_productData['attr_set_code'], + 'used_attributes' => empty($this->_skuSuperData[$productId]) ? [] : $this + ->_skuSuperData[$productId], + 'assoc_ids' => [], + ]; + + $additionalRows = $this->_parseVariations($rowData); + $variationLabels = $this->_parseVariationLabels($rowData); + //@codingStandardsIgnoreStart + foreach ($additionalRows as $data) { + $this->_collectAssocIds($data); + + if (!isset($this->_superAttributes[$data['_super_attribute_code']])) { + continue; + } + $attrParams = $this->_superAttributes[$data['_super_attribute_code']]; + + if ($this->_getSuperAttributeId($productId, $attrParams['id'])) { + $productSuperAttrId = $this->_getSuperAttributeId($productId, $attrParams['id']); + } elseif (isset($this->_superAttributesData['attributes'][$productId][$attrParams['id']])) { + $productSuperAttrId = $this->_superAttributesData['attributes'][$productId][$attrParams['id']]['product_super_attribute_id']; + $this->_collectSuperDataLabels($data, $productSuperAttrId, $productId, $variationLabels); + } else { + $productSuperAttrId = $this->_getNextAttrId(); + $this->_collectSuperDataLabels($data, $productSuperAttrId, $productId, $variationLabels); + } + + if ($productSuperAttrId) { + $this->_collectSuperDataPrice($data, $productSuperAttrId); + } + } + //@codingStandardsIgnoreEnd + + return $this; + } + + /** + * Collect super data price. + * + * @param array $data + * @param integer|string $productSuperAttrId + * @return $this + */ + protected function _collectSuperDataPrice($data, $productSuperAttrId) + { + $attrParams = $this->_superAttributes[$data['_super_attribute_code']]; + if (isset($data['_super_attribute_option']) && strlen($data['_super_attribute_option'])) { + $optionId = $attrParams['options'][strtolower($data['_super_attribute_option'])]; + + if (!isset($this->_productSuperData['used_attributes'][$attrParams['id']][$optionId])) { + $this->_productSuperData['used_attributes'][$attrParams['id']][$optionId] = false; + } + if (!empty($data['_super_attribute_price_corr'])) { + $this->_superAttributesData['pricing'][] = [ + 'product_super_attribute_id' => $productSuperAttrId, + 'value_index' => $optionId, + 'is_percent' => '%' == substr($data['_super_attribute_price_corr'], -1), + 'pricing_value' => (double)rtrim($data['_super_attribute_price_corr'], '%'), + 'website_id' => 0, + ]; + } + } + return $this; + } + + /** + * Collect assoc ids and simpleIds to break links. + * + * @param array $data + * @return $this + */ + protected function _collectAssocIds($data) + { + $newSku = $this->_entityModel->getNewSku(); + $oldSku = $this->_entityModel->getOldSku(); + if (!empty($data['_super_products_sku'])) { + $superProductId = ''; + if (isset($newSku[$data['_super_products_sku']])) { + $superProductId = $newSku[$data['_super_products_sku']]['entity_id']; + } elseif (isset($oldSku[$data['_super_products_sku']])) { + $superProductId = $oldSku[$data['_super_products_sku']]['entity_id']; + } + + if ($superProductId) { + if (isset($data['display']) && $data['display'] == 0) { + $this->_simpleIdsToDelete[] = $superProductId; + } else { + $this->_productSuperData['assoc_ids'][$superProductId] = true; + } + } + } + return $this; + } + + /** + * Collect super data price. + * + * @param array $data + * @param integer|string $productSuperAttrId + * @param integer|string $productId + * @param array $variationLabels + * @return $this + */ + protected function _collectSuperDataLabels($data, $productSuperAttrId, $productId, $variationLabels) + { + $attrParams = $this->_superAttributes[$data['_super_attribute_code']]; + $this->_superAttributesData['attributes'][$productId][$attrParams['id']] = [ + 'product_super_attribute_id' => $productSuperAttrId, + 'position' => 0, + ]; + $label = isset($variationLabels[$data['_super_attribute_code']]) + ? $variationLabels[$data['_super_attribute_code']] + : $attrParams['frontend_label']; + $this->_superAttributesData['labels'][] = [ + 'product_super_attribute_id' => $productSuperAttrId, + 'store_id' => 0, + 'use_default' => $label ? 0 : 1, + 'value' => $label, + ]; + return $this; + } + + /** + * Save product type specific data. + * + * @throws \Exception + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType + */ + public function saveData() + { $newSku = $this->_entityModel->getNewSku(); $oldSku = $this->_entityModel->getOldSku(); - $productSuperData = []; - $productData = null; - $nextAttrId = $this->_resourceHelper->getNextAutoincrement($mainTable); + $this->_productSuperData = []; + $this->_productData = null; if ($this->_entityModel->getBehavior() == \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND) { $this->_loadSkuSuperData(); } while ($bunch = $this->_entityModel->getNextBunch()) { - $superAttributes = [ + $this->_superAttributesData = [ 'attributes' => [], 'labels' => [], 'pricing' => [], @@ -424,6 +822,8 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ 'relation' => [], ]; + $this->_simpleIdsToDelete = []; + $this->_loadSkuSuperAttributeValues($bunch, $newSku, $oldSku); foreach ($bunch as $rowNum => $rowData) { @@ -432,112 +832,52 @@ class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Typ } // remember SCOPE_DEFAULT row data $scope = $this->_entityModel->getRowScope($rowData); - if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT == $scope) { - $productData = $newSku[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]]; + if ((\Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT == $scope) && + !empty($rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU])) { - if ($this->_type != $productData['type_id']) { - $productData = null; - continue; - } - $productId = $productData['entity_id']; - - $this->_processSuperData($productSuperData, $superAttributes); - - $productSuperData = [ - 'product_id' => $productId, - 'attr_set_code' => $productData['attr_set_code'], - 'used_attributes' => empty($this->_skuSuperData[$productId]) ? [] : $this - ->_skuSuperData[$productId], - 'assoc_ids' => [], - ]; - } elseif (null === $productData) { - continue; - } - if (!empty($rowData['_super_products_sku'])) { - if (isset($newSku[$rowData['_super_products_sku']])) { - $productSuperData['assoc_ids'][$newSku[$rowData['_super_products_sku']]['entity_id']] = true; - } elseif (isset($oldSku[$rowData['_super_products_sku']])) { - $productSuperData['assoc_ids'][$oldSku[$rowData['_super_products_sku']]['entity_id']] = true; - } - } - if (empty($rowData['_super_attribute_code'])) { - continue; - } - $attrParams = $this->_superAttributes[$rowData['_super_attribute_code']]; - - if ($this->_getSuperAttributeId($productId, $attrParams['id'])) { - $productSuperAttrId = $this->_getSuperAttributeId($productId, $attrParams['id']); - } elseif (!isset($superAttributes['attributes'][$productId][$attrParams['id']])) { - $productSuperAttrId = $nextAttrId++; - $superAttributes['attributes'][$productId][$attrParams['id']] = [ - 'product_super_attribute_id' => $productSuperAttrId, - 'position' => 0, - ]; - $superAttributes['labels'][] = [ - 'product_super_attribute_id' => $productSuperAttrId, - 'store_id' => 0, - 'use_default' => 1, - 'value' => $attrParams['frontend_label'], - ]; - } - if (isset($rowData['_super_attribute_option']) && strlen($rowData['_super_attribute_option'])) { - $optionId = $attrParams['options'][strtolower($rowData['_super_attribute_option'])]; + $this->_productData = isset($newSku[$rowData[ImportProduct::COL_SKU]]) + ? $newSku[$rowData[ImportProduct::COL_SKU]] + : $oldSku[$rowData[ImportProduct::COL_SKU]]; - if (!isset($productSuperData['used_attributes'][$attrParams['id']][$optionId])) { - $productSuperData['used_attributes'][$attrParams['id']][$optionId] = false; - } - if (!empty($rowData['_super_attribute_price_corr'])) { - $superAttributes['pricing'][] = [ - 'product_super_attribute_id' => $productSuperAttrId, - 'value_index' => $optionId, - 'is_percent' => '%' == substr($rowData['_super_attribute_price_corr'], -1), - 'pricing_value' => (double)rtrim($rowData['_super_attribute_price_corr'], '%'), - 'website_id' => 0, - ]; + if ($this->_type != $this->_productData['type_id']) { + $this->_productData = null; + continue; } + $this->_collectSuperData($rowData); } } + // save last product super data - $this->_processSuperData($productSuperData, $superAttributes); + $this->_processSuperData(); - // remove old data if needed - if ($this->_entityModel->getBehavior() != \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND && - $superAttributes['attributes'] - ) { - $quoted = $connection->quoteInto('IN (?)', array_keys($superAttributes['attributes'])); - $connection->delete($mainTable, "product_id {$quoted}"); - $connection->delete($linkTable, "parent_id {$quoted}"); - $connection->delete($relationTable, "parent_id {$quoted}"); - } - $mainData = []; + $this->_deleteData(); - foreach ($superAttributes['attributes'] as $productId => $attributesData) { - foreach ($attributesData as $attrId => $row) { - $row['product_id'] = $productId; - $row['attribute_id'] = $attrId; - $mainData[] = $row; - } - } - if ($mainData) { - $connection->insertOnDuplicate($mainTable, $mainData); - } - if ($superAttributes['labels']) { - $connection->insertOnDuplicate($labelTable, $superAttributes['labels']); - } - if ($superAttributes['pricing']) { - $connection->insertOnDuplicate( - $priceTable, - $superAttributes['pricing'], - ['is_percent', 'pricing_value'] - ); - } - if ($superAttributes['super_link']) { - $connection->insertOnDuplicate($linkTable, $superAttributes['super_link']); - } - if ($superAttributes['relation']) { - $connection->insertOnDuplicate($relationTable, $superAttributes['relation']); - } + $this->_insertData(); } return $this; } + + /** + * Validate row attributes. Pass VALID row data ONLY as argument. + * + * @param array $rowData + * @param int $rowNum + * @param bool $isNewProduct Optional + * + * @return bool + */ + public function isRowValid(array $rowData, $rowNum, $isNewProduct = true) + { + $error = false; + $dataWithExtraVirtualRows = $this->_parseVariations($rowData); + if (!empty($dataWithExtraVirtualRows)) { + array_unshift($dataWithExtraVirtualRows, $rowData); + } else { + $dataWithExtraVirtualRows[] = $rowData; + } + foreach ($dataWithExtraVirtualRows as $data) { + $error |= !parent::isRowValid($data, $rowNum, $isNewProduct); + } + return !$error; + } } diff --git a/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Import/Product/Type/ConfigurableTest.php b/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Import/Product/Type/ConfigurableTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b52fd0ba0e09426c11afdd830c5202c707434659 --- /dev/null +++ b/app/code/Magento/ConfigurableImportExport/Test/Unit/Model/Import/Product/Type/ConfigurableTest.php @@ -0,0 +1,600 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ConfigurableImportExport\Test\Unit\Model\Import\Product\Type; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; +use \Magento\ConfigurableImportExport; + +/** + * Class ConfigurableTest + * @package Magento\ConfigurableImportExport\Test\Unit\Model\Import\Product\Type + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ConfigurableTest extends \PHPUnit_Framework_TestCase +{ + /** @var ConfigurableImportExport\Model\Import\Product\Type\Configurable */ + protected $configurable; + + /** @var ObjectManagerHelper */ + protected $objectManagerHelper; + + /** + * @var \Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $setCollectionFactory; + + /** + * @var \Magento\Eav\Model\Resource\Entity\Attribute\Set\Collection|\PHPUnit_Framework_MockObject_MockObject + */ + protected $setCollection; + + /** + * @var \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $attrCollectionFactory; + + /** + * @var \Magento\Catalog\Model\Resource\Product\Attribute\Collection|\PHPUnit_Framework_MockObject_MockObject + */ + protected $attrCollection; + + /** + * @var \Magento\Catalog\Model\Resource\Product\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productCollectionFactory; + + /** + * @var \Magento\Catalog\Model\Resource\Product\Collection|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productCollection; + + /** + * @var \Magento\Catalog\Model\ProductTypes\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $productTypesConfig; + + /** + * @var [] + */ + protected $params; + + /** + * @var \Magento\CatalogImportExport\Model\Import\Product|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_entityModel; + + /** @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject */ + protected $_resource; + + /** @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject */ + protected $_connection; + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + protected function setUp() + { + $this->setCollectionFactory = $this->getMock( + 'Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory', + ['create'], + [], + '', + false + ); + $this->setCollection = $this->getMock( + 'Magento\Eav\Model\Resource\Entity\Attribute\Set\Collection', + ['setEntityTypeFilter'], + [], + '', + false + ); + + $this->setCollectionFactory->expects($this->any())->method('create')->will( + $this->returnValue($this->setCollection) + ); + + $item = new \Magento\Framework\Object([ + 'id' => 1, + 'attribute_set_name' => 'Default', + '_attribute_set' => 'Default' + ]); + + $this->setCollection->expects($this->any()) + ->method('setEntityTypeFilter') + ->will($this->returnValue([$item])); + + $this->attrCollectionFactory = $this->getMock( + 'Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory', + ['create'], + [], + '', + false + ); + + $this->attrCollection = $this->getMock( + '\Magento\Catalog\Model\Resource\Product\Attribute\Collection', + ['setAttributeSetFilter'], + [], + '', + false + ); + + $superAttributes = []; + foreach ($this->_getSuperAttributes() as $superAttribute) { + $item = $this->getMock( + '\Magento\Eav\Model\Entity\Attribute\AbstractAttribute', + ['isStatic'], + $superAttribute, + '', + false + ); + $item->setData($superAttribute); + $item->method('isStatic') + ->will($this->returnValue(false)); + $superAttributes[] = $item; + } + + $this->attrCollectionFactory->expects($this->any())->method('create')->will( + $this->returnValue($this->attrCollection) + ); + + $this->attrCollection->expects($this->any()) + ->method('setAttributeSetFilter') + ->will($this->returnValue($superAttributes)); + + $this->_entityModel = $this->getMock( + 'Magento\CatalogImportExport\Model\Import\Product', + [ + 'getNewSku', + 'getOldSku', + 'getNextBunch', + 'isRowAllowedToImport', + 'getConnection', + 'getAttrSetIdToName', + 'getAttributeOptions' + ], + [], + '', + false + ); + $this->params = [ + 0 => $this->_entityModel, + 1 => 'configurable' + ]; + + $this->objectManagerHelper = new ObjectManagerHelper($this); + + $this->_connection = $this->getMock( + 'Magento\Framework\DB\Adapter\Pdo\Mysql', + [ + 'select', + 'fetchAll', + 'fetchPairs', + 'joinLeft', + 'insertOnDuplicate', + 'delete', + 'quoteInto' + ], + [], + '', + false + ); + + $this->_connection->expects($this->any())->method('insertOnDuplicate')->willReturnSelf(); + $this->_connection->expects($this->any())->method('delete')->willReturnSelf(); + $this->_connection->expects($this->any())->method('quoteInto')->willReturn(''); + + $this->_resource = $this->getMock('Magento\Framework\App\Resource', [], [], '', false); + $this->_entityModel->expects($this->any())->method('getConnection')->will( + $this->returnValue($this->_connection) + ); + + $this->productCollectionFactory = $this->getMock( + '\Magento\Catalog\Model\Resource\Product\CollectionFactory', + ['create'], + [], + '', + false + ); + + $this->productCollection = $this->getMock( + '\Magento\Catalog\Model\Resource\Product\Collection', + ['addFieldToFilter', 'addAttributeToSelect'], + [], + '', + false + ); + + $products = []; + $testProducts = [ + ['id' => 1, 'attribute_set_id' => 4, 'testattr2'=> 1, 'testattr3'=> 1], + ['id' => 2, 'attribute_set_id' => 4, 'testattr2'=> 1, 'testattr3'=> 1], + ['id' => 20, 'attribute_set_id' => 4, 'testattr2'=> 1, 'testattr3'=> 1], + ]; + foreach ($testProducts as $product) { + $item = $this->getMock( + '\Magento\Framework\Object', + ['getAttributeSetId'], + [], + '', + false + ); + $item->setData($product); + $item->expects($this->any())->method('getAttributeSetId')->willReturn(4); + + $products[] = $item; + } + + $this->productCollectionFactory->expects($this->any())->method('create')->will( + $this->returnValue($this->productCollection) + ); + + $this->productCollection->expects($this->any())->method('addFieldToFilter')->will( + $this->returnValue($this->productCollection) + ); + + $this->productCollection->expects($this->any())->method('addAttributeToSelect')->will( + $this->returnValue($products) + ); + + $this->_entityModel->expects($this->any())->method('getAttributeOptions')->will($this->returnValue([ + 'attr2val1' => '1', + 'attr2val2' => '2', + 'attr2val3' => '3', + 'testattr3v1' => '4', + 'testattr30v1' => '4', + 'testattr3v2' => '5', + 'testattr3v3' => '6', + ])); + + $this->configurable = $this->objectManagerHelper->getObject( + 'Magento\ConfigurableImportExport\Model\Import\Product\Type\Configurable', + [ + 'attrSetColFac' => $this->setCollectionFactory, + 'prodAttrColFac' => $this->attrCollectionFactory, + 'params' => $this->params, + '_productColFac' => $this->productCollectionFactory + ] + ); + } + + /** + * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + protected function _getBunch() + { + return [[ + 'sku' => 'configurableskuI22', + 'store_view_code' => null, + 'attribute_set_code' => 'Default', + 'product_type' => 'configurable', + 'name' => 'Configurable Product 21', + 'product_websites' => 'website_1', + 'configurable_variation_prices' => + 'name=testattr2,' + . 'value=attr2val1,' + . 'price=13|name=testattr3,' + . 'value=testattr3v1,' + . 'price=17|name=testattr3,' + . 'value=testattr3v2,' + . 'price=19', + 'configurable_variation_labels' => 'testattr2=Select Color, testattr3=Select Size', + 'configurable_variations' => + 'sku=testconf2-attr2val1-testattr3v1,' + . 'testattr2=attr2val1,' + . 'testattr3=testattr3v1,' + . 'display=1|sku=testconf2-attr2val1-testattr3v2,' + . 'testattr2=attr2val1,' + . 'testattr3=testattr3v2,' + . 'display=0', + '_store' => null, + '_attribute_set' => 'Default', + '_type' => 'configurable', + '_product_websites' => 'website_1', + ], + [ + 'sku' => 'testSimple', + 'store_view_code' => null, + 'attribute_set_code' => 'Default', + 'product_type' => 'simple', + 'name' => 'Test simple', + 'product_websites' => 'website_1', + '_store' => null, + '_attribute_set' => 'Default', + '_type' => 'simple', + '_product_websites' => 'website_1', + ], + [ + 'sku' => 'testSimpleToSkip', + 'store_view_code' => null, + 'attribute_set_code' => 'Default', + 'product_type' => 'simple', + 'name' => 'Test simple to Skip', + 'product_websites' => 'website_1', + '_store' => null, + '_attribute_set' => 'Default', + '_type' => 'simple', + '_product_websites' => 'website_1', + ], + [ + 'sku' => 'configurableskuI22withoutLabels', + 'store_view_code' => null, + 'attribute_set_code' => 'Default', + 'product_type' => 'configurable', + 'name' => 'Configurable Product 21 Without Labels', + 'product_websites' => 'website_1', + 'configurable_variation_prices' => + 'name=testattr2,' + . 'value=attr2val1,' + . 'price=13|name=testattr3,' + . 'value=testattr3v1,' + . 'price=17|name=testattr3,' + . 'value=testattr3v2,' + . 'price=19', + 'configurable_variations' => ' + sku=testconf2-attr2val1-testattr3v1,testattr2=attr2val1,testattr3=testattr3v1,display=1| + sku=testconf2-attr2val1-testattr30v1,testattr2=attr2val1,testattr3=testattr3v1,display=1| + sku=testconf2-attr2val1-testattr3v2,testattr2=attr2val1,testattr3=testattr3v2,display=0| + sku=testconf2-attr2val2-testattr3v2,testattr2=attr2val1,testattr4=testattr3v2,display=1| + sku=testSimpleOld,testattr2=attr2val1,testattr4=testattr3v2,display=1', + '_store' => null, + '_attribute_set' => 'Default', + '_type' => 'configurable', + '_product_websites' => 'website_1', + ], + [ + 'sku' => 'configurableskuI22withoutVariations', + 'store_view_code' => null, + 'attribute_set_code' => 'Default', + 'product_type' => 'configurable', + 'name' => 'Configurable Product 21 Without Labels', + 'product_websites' => 'website_1', + 'configurable_variation_prices' => + 'name=testattr2,' + . 'value=attr2val1,' + . 'price=13|name=testattr3,' + . 'value=testattr3v1,' + . 'price=17|name=testattr3,' + . 'value=testattr3v2,' + . 'price=19', + '_store' => null, + '_attribute_set' => 'Default', + '_type' => 'configurable', + '_product_websites' => 'website_1', + ], + [ + 'sku' => 'configurableskuI22Duplicated', + 'store_view_code' => null, + 'attribute_set_code' => 'Default', + 'product_type' => 'configurable', + 'name' => 'Configurable Product 21', + 'product_websites' => 'website_1', + 'configurable_variation_prices' => + 'name=testattr2,' + . 'value=attr2val1,' + . 'price=13|name=testattr3,' + . 'value=testattr3v1,' + . 'price=17|name=testattr3,' + . 'value=testattr3v2,price=19', + 'configurable_variation_labels' => 'testattr2=Select Color, testattr3=Select Size', + 'configurable_variations' => + 'sku=testconf2-attr2val1-testattr3v1,' + . 'testattr2=attr2val1,' + . 'testattr3=testattr3v1,' + . 'testattr3=testattr3v2,' + . 'display=1|' + . 'sku=testconf2-attr2val1-testattr3v2,' + . 'testattr2=attr2val1,' + . 'testattr3=testattr3v1,' + . 'testattr3=testattr3v2,' + . 'display=1|' + . 'sku=testconf2-attr2val1-testattr3v3,' + . 'testattr2=attr2val1,' + . 'testattr3=testattr3v1,' + . 'testattr3=testattr3v2,' + . 'display=1', + '_store' => null, + '_attribute_set' => 'Default', + '_type' => 'configurable', + '_product_websites' => 'website_1', + ], + [ + 'sku' => 'testSimpleOld', + 'store_view_code' => null, + 'attribute_set_code' => 'Default', + 'product_type' => 'simple', + 'name' => 'Test simple to Skip', + 'product_websites' => 'website_1', + '_store' => null, + '_attribute_set' => 'Default', + '_type' => 'simple', + '_product_websites' => 'website_1', + ] + ]; + } + + protected function _getSuperAttributes() + { + return [ + 'testattr2' => [ + 'id' => '131', + 'code' => 'testattr2', + 'attribute_code' => 'testattr2', + 'is_global' => '1', + 'is_visible' => '1', + 'is_static' => '0', + 'is_required' => '0', + 'is_unique' => '0', + 'frontend_label' => 'testattr2', + 'is_static' => false, + 'backend_type' => 'select', + 'apply_to' => + [], + 'type' => 'select', + 'default_value' => null, + 'options' => [ + 'attr2val1' => '6', + 'attr2val2' => '7', + 'attr2val3' => '8', + ] + ], + + 'testattr3' => [ + 'id' => '132', + 'code' => 'testattr3', + 'attribute_code' => 'testattr3', + 'is_global' => '1', + 'is_visible' => '1', + 'is_static' => '0', + 'is_required' => '0', + 'is_unique' => '0', + 'frontend_label' => 'testattr3', + 'is_static' => false, + 'backend_type' => 'select', + 'apply_to' => [], + 'type' => 'select', + 'default_value' => null, + 'options' => + [ + 'testattr3v1' => '9', + 'testattr3v2' => '10', + 'testattr3v3' => '11', + ], + ] + ]; + } + + public function testSaveData() + { + $this->_entityModel->expects($this->any())->method('getNewSku')->will($this->returnValue([ + 'configurableskuI22' => + ['entity_id' => 1, 'type_id' => 'configurable', 'attr_set_code' => 'Default'], + 'testconf2-attr2val1-testattr3v1' => + ['entity_id' => 2, 'type_id' => 'simple', 'attr_set_code' => 'Default'], + 'testconf2-attr2val1-testattr30v1' => + ['entity_id' => 20, 'type_id' => 'simple', 'attr_set_code' => 'Default'], + 'testconf2-attr2val1-testattr3v2' => + ['entity_id' => 3, 'type_id' => 'simple', 'attr_set_code' => 'Default'], + 'testSimple' => + ['entity_id' => 4, 'type_id' => 'simple', 'attr_set_code' => 'Default'], + 'testSimpleToSkip' => + ['entity_id' => 5, 'type_id' => 'simple', 'attr_set_code' => 'Default'], + 'configurableskuI22withoutLabels' => + ['entity_id' => 6, 'type_id' => 'configurable', 'attr_set_code' => 'Default'], + 'configurableskuI22withoutVariations' => + ['entity_id' => 7, 'type_id' => 'configurable', 'attr_set_code' => 'Default'], + 'configurableskuI22Duplicated' => + ['entity_id' => 8, 'type_id' => 'configurable', 'attr_set_code' => 'Default'], + 'configurableskuI22BadPrice' => + ['entity_id' => 9, 'type_id' => 'configurable', 'attr_set_code' => 'Default'], + ])); + + $select = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $this->_connection->expects($this->any())->method('select')->will($this->returnValue($select)); + $select->expects($this->any())->method('from')->will($this->returnSelf()); + $select->expects($this->any())->method('where')->will($this->returnSelf()); + $select->expects($this->any())->method('joinLeft')->will($this->returnSelf()); + $this->_connection->expects($this->any())->method('fetchAll')->with($select)->will($this->returnValue([ + ['attribute_id' => 131, 'product_id' => 1, 'value_index' => 1, 'product_super_attribute_id' => 131], + + ['attribute_id' => 131, 'product_id' => 2, 'value_index' => 1, 'product_super_attribute_id' => 131], + ['attribute_id' => 131, 'product_id' => 2, 'value_index' => 2, 'product_super_attribute_id' => 131], + ['attribute_id' => 131, 'product_id' => 2, 'value_index' => 3, 'product_super_attribute_id' => 131], + + ['attribute_id' => 131, 'product_id' => 20, 'value_index' => 1, 'product_super_attribute_id' => 131], + ['attribute_id' => 131, 'product_id' => 20, 'value_index' => 2, 'product_super_attribute_id' => 131], + ['attribute_id' => 131, 'product_id' => 20, 'value_index' => 3, 'product_super_attribute_id' => 131], + + ['attribute_id' => 132, 'product_id' => 1, 'value_index' => 1, 'product_super_attribute_id' => 132], + ['attribute_id' => 132, 'product_id' => 1, 'value_index' => 2, 'product_super_attribute_id' => 132], + ['attribute_id' => 132, 'product_id' => 1, 'value_index' => 3, 'product_super_attribute_id' => 132], + ['attribute_id' => 132, 'product_id' => 1, 'value_index' => 4, 'product_super_attribute_id' => 132], + ['attribute_id' => 132, 'product_id' => 1, 'value_index' => 5, 'product_super_attribute_id' => 132], + ['attribute_id' => 132, 'product_id' => 1, 'value_index' => 6, 'product_super_attribute_id' => 132], + + ['attribute_id' => 132, 'product_id' => 3, 'value_index' => 3, 'product_super_attribute_id' => 132], + ['attribute_id' => 132, 'product_id' => 4, 'value_index' => 4, 'product_super_attribute_id' => 132], + ['attribute_id' => 132, 'product_id' => 5, 'value_index' => 5, 'product_super_attribute_id' => 132], + ])); + $this->_connection->expects($this->any())->method('fetchPairs')->with($select)->will( + $this->returnValue([]) + ); + + $bunch = $this->_getBunch(); + $this->_entityModel->expects($this->at(2))->method('getNextBunch')->will($this->returnValue($bunch)); + $this->_entityModel->expects($this->at(3))->method('getNextBunch')->will($this->returnValue([])); + $this->_entityModel->expects($this->any()) + ->method('isRowAllowedToImport') + ->will($this->returnCallback([$this, 'isRowAllowedToImport'])); + + $this->_entityModel->expects($this->any())->method('getOldSku')->will($this->returnValue([ + 'testSimpleOld' => ['entity_id' => 10, 'type_id' => 'simple', 'attr_set_code' => 'Default'], + ])); + + $this->_entityModel->expects($this->any())->method('getAttrSetIdToName')->willReturn([4 => 'Default']); + + $this->configurable->saveData(); + } + + /** + * @param $rowData + * @param $rowNum + * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function isRowAllowedToImport($rowData, $rowNum) + { + if ($rowNum == 2) { + return false; + } + return true; + } + + public function testIsRowValid() + { + $bunch = $this->_getBunch(); + $badProduct = [ + 'sku' => 'configurableskuI22BadPrice', + 'store_view_code' => null, + 'attribute_set_code' => 'Default', + 'product_type' => 'configurable', + 'name' => 'Configurable Product 21 BadPrice', + 'product_websites' => 'website_1', + 'configurable_variation_prices' => + 'name=testattr2,' + . 'value=attr2val1,' + . 'price=aaa|name=testattr3,' + . 'value=testattr3v1,' + . 'price=17|name=testattr3,' + . 'value=testattr3v2,' + . 'price=19', + 'configurable_variation_labels' => 'testattr2=Select Color, testattr3=Select Size', + 'configurable_variations' => + 'sku=testconf2-attr2val1-testattr3v1,' + . 'testattr2=attr2val1_DOESNT_EXIST,' + . 'testattr3=testattr3v1,' + . 'display=1|sku=testconf2-attr2val1-testattr3v2,' + . 'testattr2=attr2val1,' + . 'testattr3=testattr3v2,' + . 'display=0', + '_store' => null, + '_attribute_set' => 'Default', + '_type' => 'configurable', + '_product_websites' => 'website_1', + ]; + $bunch[] = $badProduct; + + foreach ($bunch as $rowData) { + $this->configurable->isRowValid( + $rowData, + 0, + !isset($this->_oldSku[$rowData['sku']]) + ); + } + } +} diff --git a/app/code/Magento/ConfigurableImportExport/composer.json b/app/code/Magento/ConfigurableImportExport/composer.json index 62ab074be966683f46b43969337318f4fc9a2b52..54fb284e622096d698a49ea4154a0ad47fe4f037 100644 --- a/app/code/Magento/ConfigurableImportExport/composer.json +++ b/app/code/Magento/ConfigurableImportExport/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-catalog-import-export": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-import-export": "0.74.0-beta10", - "magento/module-configurable-product": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-catalog-import-export": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-import-export": "0.74.0-beta13", + "magento/module-configurable-product": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/ConfigurableProduct/Api/Data/OptionInterface.php b/app/code/Magento/ConfigurableProduct/Api/Data/OptionInterface.php index 1c60ed2762efbb9c8e1a4fc6bd62c511dc98f7f1..da2626f10a2213ce90afb6064a6f8b4fd6ac9deb 100644 --- a/app/code/Magento/ConfigurableProduct/Api/Data/OptionInterface.php +++ b/app/code/Magento/ConfigurableProduct/Api/Data/OptionInterface.php @@ -90,4 +90,15 @@ interface OptionInterface extends \Magento\Framework\Api\ExtensibleDataInterface public function setExtensionAttributes( \Magento\ConfigurableProduct\Api\Data\OptionExtensionInterface $extensionAttributes ); + + /** + * @return int|null + */ + public function getProductId(); + + /** + * @param int|null $value + * @return $this + */ + public function setProductId($value); } diff --git a/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php b/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php index 68cdb235bdeb03bd1e15e7b2146d92586236aac0..3f5d820c2d46ff3e04a97f469e96dd7d84c0dbe4 100644 --- a/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php +++ b/app/code/Magento/ConfigurableProduct/Model/OptionRepository.php @@ -6,6 +6,9 @@ */ namespace Magento\ConfigurableProduct\Model; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Catalog\Model\Product; +use Magento\ConfigurableProduct\Api\Data\OptionInterface; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Exception\StateException; use Magento\Framework\Exception\InputException; @@ -54,6 +57,11 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit */ protected $configurableAttributeFactory; + /** + * @var Resource\Product\Type\Configurable + */ + private $configurableTypeResource; + /** * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository * @param \Magento\ConfigurableProduct\Api\Data\OptionValueInterfaceFactory $optionValueFactory @@ -62,6 +70,7 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $productAttributeRepository * @param ConfigurableType\AttributeFactory $configurableAttributeFactory + * @param Resource\Product\Type\Configurable $configurableTypeResource */ public function __construct( \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, @@ -70,7 +79,8 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit \Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Attribute $optionResource, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Catalog\Api\ProductAttributeRepositoryInterface $productAttributeRepository, - \Magento\ConfigurableProduct\Model\Product\Type\Configurable\AttributeFactory $configurableAttributeFactory + \Magento\ConfigurableProduct\Model\Product\Type\Configurable\AttributeFactory $configurableAttributeFactory, + \Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable $configurableTypeResource ) { $this->productRepository = $productRepository; $this->optionValueFactory = $optionValueFactory; @@ -79,6 +89,7 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit $this->storeManager = $storeManager; $this->productAttributeRepository = $productAttributeRepository; $this->configurableAttributeFactory = $configurableAttributeFactory; + $this->configurableTypeResource = $configurableTypeResource; } /** @@ -118,8 +129,16 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit /** * {@inheritdoc} */ - public function delete(\Magento\ConfigurableProduct\Api\Data\OptionInterface $option) + public function delete(OptionInterface $option) { + $product = $this->getProductById($option->getProductId()); + try { + $this->configurableTypeResource->saveProducts($product, []); + } catch (\Exception $exception) { + throw new StateException( + __('Cannot delete variations from product: %1', $option->getProductId()) + ); + } try { $this->optionResource->delete($option); } catch (\Exception $exception) { @@ -149,12 +168,12 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit * {@inheritdoc} * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - public function save($sku, \Magento\ConfigurableProduct\Api\Data\OptionInterface $option) + public function save($sku, OptionInterface $option) { /** @var $configurableAttribute \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute */ $configurableAttribute = $this->configurableAttributeFactory->create(); if ($option->getId()) { - /** @var \Magento\Catalog\Model\Product $product */ + /** @var Product $product */ $product = $this->getProduct($sku); $configurableAttribute->load($option->getId()); if (!$configurableAttribute->getId() || $configurableAttribute->getProductId() != $product->getId()) { @@ -182,7 +201,7 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit } } else { $this->validateNewOptionData($option); - /** @var \Magento\Catalog\Model\Product $product */ + /** @var Product $product */ $product = $this->productRepository->get($sku); $allowedTypes = [ProductType::TYPE_SIMPLE, ProductType::TYPE_VIRTUAL, ConfigurableType::TYPE_CODE]; if (!in_array($product->getTypeId(), $allowedTypes)) { @@ -225,7 +244,7 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit * Retrieve product instance by sku * * @param string $sku - * @return \Magento\Catalog\Model\Product + * @return ProductInterface * @throws InputException */ private function getProduct($sku) @@ -239,15 +258,33 @@ class OptionRepository implements \Magento\ConfigurableProduct\Api\OptionReposit return $product; } + /** + * Retrieve product instance by id + * + * @param int $id + * @return ProductInterface + * @throws InputException + */ + private function getProductById($id) + { + $product = $this->productRepository->getById($id); + if (\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE !== $product->getTypeId()) { + throw new InputException( + __('Only implemented for configurable product: %1', $id) + ); + } + return $product; + } + /** * Ensure that all necessary data is available for a new option creation. * - * @param \Magento\ConfigurableProduct\Api\Data\OptionInterface $option + * @param OptionInterface $option * @return void * @throws InputException * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - public function validateNewOptionData(\Magento\ConfigurableProduct\Api\Data\OptionInterface $option) + public function validateNewOptionData(OptionInterface $option) { $inputException = new InputException(); if (!$option->getAttributeId()) { diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php index 8cf22a9b6dc3b4127baa3b8e9c8e5a9c0ade4dce..f0e57dc28f48ac55646003c6e96db3ec04fe52c6 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable/Attribute.php @@ -11,8 +11,6 @@ namespace Magento\ConfigurableProduct\Model\Product\Type\Configurable; /** * @method Attribute _getResource() * @method Attribute getResource() - * @method int getProductId() - * @method Attribute setProductId(int $value) * @method Attribute setProductAttribute(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute $value) * @method \Magento\Eav\Model\Entity\Attribute\AbstractAttribute getProductAttribute() */ @@ -27,6 +25,7 @@ class Attribute extends \Magento\Framework\Model\AbstractExtensibleModel impleme const KEY_POSITION = 'position'; const KEY_IS_USE_DEFAULT = 'is_use_default'; const KEY_VALUES = 'values'; + const KEY_PRODUCT_ID = 'product_id'; /**#@-*/ /** @@ -212,5 +211,21 @@ class Attribute extends \Magento\Framework\Model\AbstractExtensibleModel impleme ) { return $this->_setExtensionAttributes($extensionAttributes); } + + /** + * {@inheritdoc} + */ + public function getProductId() + { + return $this->getData(self::KEY_PRODUCT_ID); + } + + /** + * {@inheritdoc} + */ + public function setProductId($value) + { + return $this->setData(self::KEY_PRODUCT_ID, $value); + } //@codeCoverageIgnoreEnd } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php index 5bf9e0b3106d36f26e023d3f077418ce26639137..ad7c2b21a3cb9dea499951ea67bbe80e828ab4f2 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php @@ -6,6 +6,8 @@ namespace Magento\ConfigurableProduct\Test\Unit\Model; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable; + class OptionRepositoryTest extends \PHPUnit_Framework_TestCase { /** @@ -23,15 +25,37 @@ class OptionRepositoryTest extends \PHPUnit_Framework_TestCase */ protected $productMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $configurableTypeResource; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $optionResource; + protected function setUp() { $this->productRepositoryMock = $this->getMock('\Magento\Catalog\Api\ProductRepositoryInterface'); $this->productMock = $this->getMock('\Magento\Catalog\Api\Data\ProductInterface'); + $this->configurableTypeResource = $this->getMockBuilder( + 'Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable' + ) + ->disableOriginalConstructor() + ->getMock(); + $this->optionResource = $this->getMockBuilder( + 'Magento\ConfigurableProduct\Model\Resource\Product\Type\Configurable\Attribute' + ) + ->disableOriginalConstructor() + ->getMock(); $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->model = $objectManager->getObject( '\Magento\ConfigurableProduct\Model\OptionRepository', [ 'productRepository' => $this->productRepositoryMock, + 'configurableTypeResource' => $this->configurableTypeResource, + 'optionResource' => $this->optionResource, ] ); } @@ -47,7 +71,7 @@ class OptionRepositoryTest extends \PHPUnit_Framework_TestCase ->willReturn($this->productMock); $this->productMock->expects($this->once()) ->method('getTypeId') - ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + ->willReturn(Configurable::TYPE_CODE); $optionMock = $this->getMock('\Magento\ConfigurableProduct\Api\Data\OptionInterface'); $optionMock->expects($this->once()) @@ -86,6 +110,136 @@ class OptionRepositoryTest extends \PHPUnit_Framework_TestCase $this->model->get($productSku, $optionId); } + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage Only implemented for configurable product: 3 + */ + public function testGetNotProductById() + { + $productId = 3; + + $option = $this->getMockBuilder('Magento\ConfigurableProduct\Api\Data\OptionInterface') + ->disableOriginalConstructor() + ->setMethods(['getProductId']) + ->getMockForAbstractClass(); + $option->expects($this->once()) + ->method('getProductId') + ->willReturn($productId); + + $this->productRepositoryMock->expects($this->once()) + ->method('getById') + ->with($productId) + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn('simple'); + + $this->model->delete($option); + } + + /** + * @expectedException \Magento\Framework\Exception\StateException + * @expectedExceptionMessage Cannot delete variations from product: 3 + */ + public function testDeleteCantSaveProducts() + { + $productId = 3; + + $option = $this->getMockBuilder('Magento\ConfigurableProduct\Api\Data\OptionInterface') + ->disableOriginalConstructor() + ->setMethods(['getProductId']) + ->getMockForAbstractClass(); + $option->expects($this->any()) + ->method('getProductId') + ->willReturn($productId); + + $this->productRepositoryMock->expects($this->once()) + ->method('getById') + ->with($productId) + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(Configurable::TYPE_CODE); + + $this->configurableTypeResource->expects($this->once()) + ->method('saveProducts') + ->with($this->productMock) + ->willThrowException(new \Exception()); + $this->model->delete($option); + } + + /** + * @expectedException \Magento\Framework\Exception\StateException + * @expectedExceptionMessage Cannot delete option with id: 33 + */ + public function testDeleteCantDeleteOption() + { + $productId = 3; + $optionId = 33; + + $option = $this->getMockBuilder('Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute') + ->disableOriginalConstructor() + ->setMethods(['getProductId', 'getId']) + ->getMockForAbstractClass(); + $option->expects($this->any()) + ->method('getProductId') + ->willReturn($productId); + $option->expects($this->once()) + ->method('getId') + ->willReturn($optionId); + + $this->productRepositoryMock->expects($this->once()) + ->method('getById') + ->with($productId) + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(Configurable::TYPE_CODE); + + $this->configurableTypeResource->expects($this->once()) + ->method('saveProducts') + ->with($this->productMock); + $this->optionResource->expects($this->once()) + ->method('delete') + ->with($option) + ->willThrowException(new \Exception()); + $this->model->delete($option); + } + + public function testDelete() + { + $productId = 3; + $optionId = 33; + + $option = $this->getMockBuilder('Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute') + ->disableOriginalConstructor() + ->setMethods(['getProductId', 'getId']) + ->getMockForAbstractClass(); + $option->expects($this->any()) + ->method('getProductId') + ->willReturn($productId); + $option->expects($this->any()) + ->method('getId') + ->willReturn($optionId); + + $this->productRepositoryMock->expects($this->once()) + ->method('getById') + ->with($productId) + ->willReturn($this->productMock); + $this->productMock->expects($this->once()) + ->method('getTypeId') + ->willReturn(Configurable::TYPE_CODE); + + $this->configurableTypeResource->expects($this->once()) + ->method('saveProducts') + ->with($this->productMock); + $this->optionResource->expects($this->once()) + ->method('delete') + ->with($option); + $result = $this->model->delete($option); + $this->assertTrue($result); + } + /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException * @expectedExceptionMessage Requested option doesn't exist: 3 @@ -101,7 +255,7 @@ class OptionRepositoryTest extends \PHPUnit_Framework_TestCase ->willReturn($this->productMock); $this->productMock->expects($this->once()) ->method('getTypeId') - ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + ->willReturn(Configurable::TYPE_CODE); $this->productMock->expects($this->once()) ->method('getExtensionAttributes') @@ -125,7 +279,7 @@ class OptionRepositoryTest extends \PHPUnit_Framework_TestCase ->willReturn($this->productMock); $this->productMock->expects($this->once()) ->method('getTypeId') - ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + ->willReturn(Configurable::TYPE_CODE); $optionMock = $this->getMock('\Magento\ConfigurableProduct\Api\Data\OptionInterface'); $optionMock->expects($this->once()) @@ -154,7 +308,7 @@ class OptionRepositoryTest extends \PHPUnit_Framework_TestCase ->willReturn($this->productMock); $this->productMock->expects($this->once()) ->method('getTypeId') - ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + ->willReturn(Configurable::TYPE_CODE); $optionMock = $this->getMock('\Magento\ConfigurableProduct\Api\Data\OptionInterface'); $productExtensionMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtension') @@ -180,7 +334,7 @@ class OptionRepositoryTest extends \PHPUnit_Framework_TestCase ->willReturn($this->productMock); $this->productMock->expects($this->once()) ->method('getTypeId') - ->willReturn(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE); + ->willReturn(Configurable::TYPE_CODE); $this->productMock->expects($this->once()) ->method('getExtensionAttributes') diff --git a/app/code/Magento/ConfigurableProduct/composer.json b/app/code/Magento/ConfigurableProduct/composer.json index ef09882fbef5ae8739ccfec8cf19dde8f94b2b7f..a59d294e11653be15c3407afdddc78db584f82eb 100644 --- a/app/code/Magento/ConfigurableProduct/composer.json +++ b/app/code/Magento/ConfigurableProduct/composer.json @@ -3,27 +3,27 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-msrp": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-catalog-rule": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-msrp": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-catalog-rule": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-webapi": "0.74.0-beta10" + "magento/module-webapi": "0.74.0-beta13" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/ConfigurableProduct/etc/service_data_attributes.xml b/app/code/Magento/ConfigurableProduct/etc/extension_attributes.xml similarity index 91% rename from app/code/Magento/ConfigurableProduct/etc/service_data_attributes.xml rename to app/code/Magento/ConfigurableProduct/etc/extension_attributes.xml index 74edcdbf65a91e08cc384b50b416deff63e8780c..5fd3eba9ce1956d153f67551d0c0469e9018016a 100644 --- a/app/code/Magento/ConfigurableProduct/etc/service_data_attributes.xml +++ b/app/code/Magento/ConfigurableProduct/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> <attribute code="configurable_product_options" type="Magento\ConfigurableProduct\Api\Data\OptionInterface[]" /> <attribute code="configurable_product_links" type="int[]" /> diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml index b7beb5d05ede61ae3e4acbbce177002e5c56b8a4..afca50b7cf56af119cbc73d10265246f0d079abf 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/matrix.phtml @@ -296,7 +296,7 @@ jQuery(function ($) { parentElement.find('[name$="[image]"]').val(data.result.file); parentElement.find('[data-toggle=dropdown]').show(); } else { - alert($.mage.__('File extension not known or unsupported type.')); + alert($.mage.__('We don\'t recognize or support this file extension type.')); } }, start: function(event) { 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 79550544efa591d61aae0e1bcda7c5ee67f51f9c..8cb617bd96520052dbf467993fdc619186f363ac 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/product/product.css +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/product/product.css @@ -160,8 +160,6 @@ #product-variations-matrix .action-choose:hover, #product-variations-matrix .action-choose[disabled] { color: #b8b3a7; - float: right; - margin: 2px 0 0 5px; } #product-variations-matrix .action-choose:hover { @@ -187,28 +185,15 @@ color: #a09a8c; } -#product-variations-matrix .col-name > input { - width: 88%; +#product-variations-matrix .col-name > input, +#product-variations-matrix .col-sku > input { + width: 90%; } #product-variations-matrix .col-actions { width: 60px; } -#product-variations-matrix .col-name { - width: 29%; -} - -#product-variations-matrix .col-sku { - width: 20%; -} - -#product-variations-matrix .col-display, -#product-variations-matrix .col-qty, -#product-variations-matrix .col-weight { - width: 5%; -} - /* Select Associated Product popup window */ #configurable_associated_products_grid .filter-actions, #configurable_associated_products_grid .filter { diff --git a/app/code/Magento/Contact/Test/Unit/Model/System/Config/Backend/LinksTest.php b/app/code/Magento/Contact/Test/Unit/Model/System/Config/Backend/LinksTest.php index 52e7baec18ed0e6f6a4dd310df47d6f3d3dcf6a9..e48189a75f8866092197401a073d038168efc883 100644 --- a/app/code/Magento/Contact/Test/Unit/Model/System/Config/Backend/LinksTest.php +++ b/app/code/Magento/Contact/Test/Unit/Model/System/Config/Backend/LinksTest.php @@ -19,7 +19,7 @@ class LinksTest extends \PHPUnit_Framework_TestCase $this->getMock('\Magento\Framework\Registry', [], [], '', false), $this->getMockForAbstractClass('\Magento\Framework\App\Config\ScopeConfigInterface', [], '', false), $this->getMockForAbstractClass('\Magento\Framework\Model\Resource\AbstractResource', [], '', false), - $this->getMock('\Magento\Framework\Data\Collection\Db', [], [], '', false) + $this->getMock('\Magento\Framework\Data\Collection\AbstractDb', [], [], '', false) ); } diff --git a/app/code/Magento/Contact/composer.json b/app/code/Magento/Contact/composer.json index 87e4a2b25ad981d6c6fde7c3862c1f741313a40b..855dc95f1b15efa4b57d63915006bfb38028b121 100644 --- a/app/code/Magento/Contact/composer.json +++ b/app/code/Magento/Contact/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-cms": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-cms": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Cookie/Model/Config/Backend/Domain.php b/app/code/Magento/Cookie/Model/Config/Backend/Domain.php index 6ac47403b6f80744c6998478674dc97386651a2b..afd06423f8c0919bfbd35c83cab9a9a49ce7533e 100644 --- a/app/code/Magento/Cookie/Model/Config/Backend/Domain.php +++ b/app/code/Magento/Cookie/Model/Config/Backend/Domain.php @@ -19,7 +19,7 @@ class Domain extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\Session\Config\Validator\CookieDomainValidator $configValidator * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -28,7 +28,7 @@ class Domain extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\Session\Config\Validator\CookieDomainValidator $configValidator, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->configValidator = $configValidator; diff --git a/app/code/Magento/Cookie/Model/Config/Backend/Lifetime.php b/app/code/Magento/Cookie/Model/Config/Backend/Lifetime.php index e2f835e645ae58fe0b6fbde9766b7b94628b18c1..03cfa2c6b1392ab993121a9c6090d6a4ea71ab65 100644 --- a/app/code/Magento/Cookie/Model/Config/Backend/Lifetime.php +++ b/app/code/Magento/Cookie/Model/Config/Backend/Lifetime.php @@ -19,7 +19,7 @@ class Lifetime extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\Session\Config\Validator\CookieLifetimeValidator $configValidator * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -28,7 +28,7 @@ class Lifetime extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\Session\Config\Validator\CookieLifetimeValidator $configValidator, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->configValidator = $configValidator; diff --git a/app/code/Magento/Cookie/Model/Config/Backend/Path.php b/app/code/Magento/Cookie/Model/Config/Backend/Path.php index ce23a44915ef3dab36bec236da36da13e3831bd9..e147df2d926c6ba579fba8574762968e52fc8d80 100644 --- a/app/code/Magento/Cookie/Model/Config/Backend/Path.php +++ b/app/code/Magento/Cookie/Model/Config/Backend/Path.php @@ -19,7 +19,7 @@ class Path extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\Session\Config\Validator\CookiePathValidator $configValidator * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -28,7 +28,7 @@ class Path extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\Session\Config\Validator\CookiePathValidator $configValidator, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->configValidator = $configValidator; diff --git a/app/code/Magento/Cookie/composer.json b/app/code/Magento/Cookie/composer.json index eba14c7530fbf2e7c176006b597a3da0323a3c58..f407a5b8678efc0b356538691028f981353d3ba4 100644 --- a/app/code/Magento/Cookie/composer.json +++ b/app/code/Magento/Cookie/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.4.11|~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-backend": "0.74.0-beta10" + "magento/module-backend": "0.74.0-beta13" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Cron/Model/Config/Backend/Product/Alert.php b/app/code/Magento/Cron/Model/Config/Backend/Product/Alert.php index 02cdf583571cfaf92223f98d730a590326537c63..ec0b6fe4634c73889cc1984b1a564491ebab308f 100644 --- a/app/code/Magento/Cron/Model/Config/Backend/Product/Alert.php +++ b/app/code/Magento/Cron/Model/Config/Backend/Product/Alert.php @@ -39,7 +39,7 @@ class Alert extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\App\Config\ValueFactory $configValueFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param string $runModelPath * @param array $data */ @@ -49,7 +49,7 @@ class Alert extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\App\Config\ValueFactory $configValueFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, $runModelPath = '', array $data = [] ) { diff --git a/app/code/Magento/Cron/Model/Config/Backend/Sitemap.php b/app/code/Magento/Cron/Model/Config/Backend/Sitemap.php index 425dd36671b275388604c32239a0d1fa4b988cbb..383357c9c204e802e877983d8a910cb91d159d06 100644 --- a/app/code/Magento/Cron/Model/Config/Backend/Sitemap.php +++ b/app/code/Magento/Cron/Model/Config/Backend/Sitemap.php @@ -39,7 +39,7 @@ class Sitemap extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\App\Config\ValueFactory $configValueFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param string $runModelPath * @param array $data */ @@ -49,7 +49,7 @@ class Sitemap extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\App\Config\ValueFactory $configValueFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, $runModelPath = '', array $data = [] ) { diff --git a/app/code/Magento/Cron/Model/Schedule.php b/app/code/Magento/Cron/Model/Schedule.php index 1725413c3f27ff1be624769a5b94c97a23a5f0a1..7ab51af8cda0a222981940937ee51bf7f733cc9b 100644 --- a/app/code/Magento/Cron/Model/Schedule.php +++ b/app/code/Magento/Cron/Model/Schedule.php @@ -48,14 +48,14 @@ class Schedule extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( \Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Cron/composer.json b/app/code/Magento/Cron/composer.json index 9e3e1e7a39296fc6d2ae1f07b8fdd193e82edf4a..2b1ebf6e958d6c4629e5205532dfc0b182d8d6a6 100644 --- a/app/code/Magento/Cron/composer.json +++ b/app/code/Magento/Cron/composer.json @@ -3,13 +3,13 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CurrencySymbol/Block/Adminhtml/System/Currency/Rate/Services.php b/app/code/Magento/CurrencySymbol/Block/Adminhtml/System/Currency/Rate/Services.php index d2c9634aedae3f4aa710e9daf92c004234fabb88..83fb075ea68c07a51dee0dc137366de0e5dfe440 100644 --- a/app/code/Magento/CurrencySymbol/Block/Adminhtml/System/Currency/Rate/Services.php +++ b/app/code/Magento/CurrencySymbol/Block/Adminhtml/System/Currency/Rate/Services.php @@ -52,6 +52,8 @@ class Services extends \Magento\Backend\Block\Template $this->_srcCurrencyFactory->create()->toOptionArray() )->setId( 'rate_services' + )->setClass( + 'admin__control-select' )->setName( 'rate_services' )->setValue( diff --git a/app/code/Magento/CurrencySymbol/composer.json b/app/code/Magento/CurrencySymbol/composer.json index 1fc6c1ea5b3ebc37f5227952d13e1b5d519f32f1..87a1ae6197aed04f3647858aaf8ae5c6c3b727f7 100644 --- a/app/code/Magento/CurrencySymbol/composer.json +++ b/app/code/Magento/CurrencySymbol/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-page-cache": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-page-cache": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/CurrencySymbol/view/adminhtml/layout/adminhtml_system_currency_index.xml b/app/code/Magento/CurrencySymbol/view/adminhtml/layout/adminhtml_system_currency_index.xml new file mode 100644 index 0000000000000000000000000000000000000000..950253bcdb1df18879f605699d4f8a0ef9295a9e --- /dev/null +++ b/app/code/Magento/CurrencySymbol/view/adminhtml/layout/adminhtml_system_currency_index.xml @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <update handle="styles" /> + <body/> +</page> 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 53cf44e1e0ea79cf3297651c08024398512b7e95..b686fdf6b692d43e8bad384884afb4fdc3921fc7 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 @@ -15,7 +15,7 @@ <form action="<?php echo $block->getImportFormAction() ?>" method="post" class="import-service"> <?php echo $block->getBlockHtml('formkey')?> - <fieldset class="admin__fieldset"> + <fieldset class="admin__fieldset admin__fieldset-import-service"> <?php echo $block->getServicesHtml() ?> <?php echo $block->getImportButtonHtml() ?> </fieldset> diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Wishlist.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Wishlist.php index 1c8bb3796964ad0de668520c4c07bc27bcab7576..7dee117053287c40f3a2e043c6b01943e386fcc7 100644 --- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Wishlist.php +++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Wishlist.php @@ -59,7 +59,7 @@ class Wishlist extends \Magento\Backend\Block\Widget\Grid\Extended $this->setSortable(false); $this->setPagerVisibility(false); $this->setFilterVisibility(false); - $this->setEmptyText(__("There are no items in customer's wishlist at the moment")); + $this->setEmptyText(__("There are no items in customer's Wish List at the moment.")); } /** diff --git a/app/code/Magento/Customer/Controller/Address/Delete.php b/app/code/Magento/Customer/Controller/Address/Delete.php index 6c3344487794c66ae3649fa5e9ca48f28080d17f..6df5648c821c5405f09966d15039114428dfbc41 100644 --- a/app/code/Magento/Customer/Controller/Address/Delete.php +++ b/app/code/Magento/Customer/Controller/Address/Delete.php @@ -22,10 +22,10 @@ class Delete extends \Magento\Customer\Controller\Address $this->_addressRepository->deleteById($addressId); $this->messageManager->addSuccess(__('The address has been deleted.')); } else { - $this->messageManager->addError(__('An error occurred while deleting the address.')); + $this->messageManager->addError(__('We can\'t delete the address right now.')); } } catch (\Exception $other) { - $this->messageManager->addException($other, __('An error occurred while deleting the address.')); + $this->messageManager->addException($other, __('We can\'t delete the address right now.')); } } return $this->resultRedirectFactory->create()->setPath('*/*/index'); diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php b/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php index 86f7dd3c2e12aca27cb2ffc0a505e6bf5aa76467..044dfb7524fc3547af78a1f93ed92495f487f53e 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Customer/InvalidateToken.php @@ -8,9 +8,22 @@ namespace Magento\Customer\Controller\Adminhtml\Customer; use Magento\Integration\Api\CustomerTokenServiceInterface; +use Magento\Customer\Api\AccountManagementInterface; +use Magento\Customer\Api\AddressRepositoryInterface; +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Customer\Api\Data\AddressInterfaceFactory; +use Magento\Customer\Api\Data\CustomerInterfaceFactory; +use Magento\Customer\Model\Address\Mapper; +use Magento\Framework\ObjectFactory; +use Magento\Framework\Api\DataObjectHelper; /** - * Class to invalidate tokens for customers + * Class to invalidate tokens for customers + * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.NumberOfChildren) */ class InvalidateToken extends \Magento\Customer\Controller\Adminhtml\Index { @@ -20,13 +33,91 @@ class InvalidateToken extends \Magento\Customer\Controller\Adminhtml\Index protected $tokenService; /** - * Inject dependencies. - * * @param CustomerTokenServiceInterface $tokenService + * @param \Magento\Backend\App\Action\Context $context + * @param \Magento\Framework\Registry $coreRegistry + * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory + * @param \Magento\Customer\Model\CustomerFactory $customerFactory + * @param \Magento\Customer\Model\AddressFactory $addressFactory + * @param \Magento\Customer\Model\Metadata\FormFactory $formFactory + * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory + * @param \Magento\Customer\Helper\View $viewHelper + * @param \Magento\Framework\Math\Random $random + * @param CustomerRepositoryInterface $customerRepository + * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter + * @param Mapper $addressMapper + * @param AccountManagementInterface $customerAccountManagement + * @param AddressRepositoryInterface $addressRepository + * @param CustomerInterfaceFactory $customerDataFactory + * @param AddressInterfaceFactory $addressDataFactory + * @param \Magento\Customer\Model\Customer\Mapper $customerMapper + * @param \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor + * @param DataObjectHelper $dataObjectHelper + * @param ObjectFactory $objectFactory + * @param \Magento\Framework\View\LayoutFactory $layoutFactory + * @param \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory + * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory + * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory + * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ - public function __construct(CustomerTokenServiceInterface $tokenService) - { + public function __construct( + \Magento\Backend\App\Action\Context $context, + \Magento\Framework\Registry $coreRegistry, + \Magento\Framework\App\Response\Http\FileFactory $fileFactory, + \Magento\Customer\Model\CustomerFactory $customerFactory, + \Magento\Customer\Model\AddressFactory $addressFactory, + \Magento\Customer\Model\Metadata\FormFactory $formFactory, + \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory, + \Magento\Customer\Helper\View $viewHelper, + \Magento\Framework\Math\Random $random, + CustomerRepositoryInterface $customerRepository, + \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter, + Mapper $addressMapper, + AccountManagementInterface $customerAccountManagement, + AddressRepositoryInterface $addressRepository, + CustomerInterfaceFactory $customerDataFactory, + AddressInterfaceFactory $addressDataFactory, + \Magento\Customer\Model\Customer\Mapper $customerMapper, + \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor, + DataObjectHelper $dataObjectHelper, + ObjectFactory $objectFactory, + \Magento\Framework\View\LayoutFactory $layoutFactory, + \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory, + \Magento\Framework\View\Result\PageFactory $resultPageFactory, + \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory, + \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, + CustomerTokenServiceInterface $tokenService + ) { $this->tokenService = $tokenService; + parent::__construct( + $context, + $coreRegistry, + $fileFactory, + $customerFactory, + $addressFactory, + $formFactory, + $subscriberFactory, + $viewHelper, + $random, + $customerRepository, + $extensibleDataObjectConverter, + $addressMapper, + $customerAccountManagement, + $addressRepository, + $customerDataFactory, + $addressDataFactory, + $customerMapper, + $dataObjectProcessor, + $dataObjectHelper, + $objectFactory, + $layoutFactory, + $resultLayoutFactory, + $resultPageFactory, + $resultForwardFactory, + $resultJsonFactory + ); } /** diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php b/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php index b701d653dc030d2436527e924c5761f369e9da99..35439a7e3cf9eefea800b14cd3c4cf0a4235e91c 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index/Validate.php @@ -19,7 +19,7 @@ class Validate extends \Magento\Customer\Controller\Adminhtml\Index protected function _validateCustomer($response) { $customer = null; - $errors = null; + $errors = []; try { /** @var CustomerInterface $customer */ @@ -48,7 +48,7 @@ class Validate extends \Magento\Customer\Controller\Adminhtml\Index $data, '\Magento\Customer\Api\Data\CustomerInterface' ); - $errors = $this->customerAccountManagement->validate($customer); + $errors = $this->customerAccountManagement->validate($customer)->getMessages(); } catch (\Magento\Framework\Validator\Exception $exception) { /* @var $error Error */ foreach ($exception->getMessages(\Magento\Framework\Message\MessageInterface::TYPE_ERROR) as $error) { @@ -56,10 +56,12 @@ class Validate extends \Magento\Customer\Controller\Adminhtml\Index } } - if (!$errors->isValid()) { - foreach ($errors->getMessages() as $error) { - $this->messageManager->addError($error); + if ($errors) { + $messages = $response->hasMessages() ? $response->getMessages() : []; + foreach ($errors as $error) { + $messages[] = $error; } + $response->setMessages($messages); $response->setError(1); } @@ -90,9 +92,11 @@ class Validate extends \Magento\Customer\Controller\Adminhtml\Index $errors = $addressForm->validateData($formData); if ($errors !== true) { + $messages = $response->hasMessages() ? $response->getMessages() : []; foreach ($errors as $error) { - $this->messageManager->addError($error); + $messages[] = $error; } + $response->setMessages($messages); $response->setError(1); } } @@ -114,9 +118,8 @@ class Validate extends \Magento\Customer\Controller\Adminhtml\Index } $resultJson = $this->resultJsonFactory->create(); if ($response->getError()) { - $layout = $this->layoutFactory->create(); - $layout->initMessages(); - $response->setHtmlMessage($layout->getMessagesBlock()->getGroupedHtml()); + $response->setError(true); + $response->setMessages($response->getMessages()); } $resultJson->setData($response); diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Wishlist/Product/Composite/Wishlist.php b/app/code/Magento/Customer/Controller/Adminhtml/Wishlist/Product/Composite/Wishlist.php index 6829fa73a0db6b555fe17a9481745aafc8fd1366..68786e84077fe21664a181f608fb2f2883bdbb4b 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Wishlist/Product/Composite/Wishlist.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Wishlist/Product/Composite/Wishlist.php @@ -36,14 +36,14 @@ class Wishlist extends \Magento\Backend\App\Action { $wishlistItemId = (int)$this->getRequest()->getParam('id'); if (!$wishlistItemId) { - throw new CoreException(__('No wishlist item ID is defined.')); + throw new CoreException(__('Please define Wish List item ID.')); } /* @var $wishlistItem \Magento\Wishlist\Model\Item */ $wishlistItem = $this->_objectManager->create('Magento\Wishlist\Model\Item')->loadWithOptions($wishlistItemId); if (!$wishlistItem->getWishlistId()) { - throw new CoreException(__('Please load the wish list item.')); + throw new CoreException(__('Please load Wish List item.')); } $this->_wishlist = $this->_objectManager->create('Magento\Wishlist\Model\Wishlist') diff --git a/app/code/Magento/Customer/Model/Address.php b/app/code/Magento/Customer/Model/Address.php index a1ffc03d91261066f380a8228f892352be105ae7..be22772a636b88dbd138ffc2ff22750ae62f8f30 100644 --- a/app/code/Magento/Customer/Model/Address.php +++ b/app/code/Magento/Customer/Model/Address.php @@ -58,7 +58,7 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress * @param CustomerFactory $customerFactory * @param \Magento\Framework\Reflection\DataObjectProcessor $dataProcessor * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -79,7 +79,7 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress CustomerFactory $customerFactory, \Magento\Framework\Reflection\DataObjectProcessor $dataProcessor, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->dataProcessor = $dataProcessor; diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php index 0d227ae85ed6eddd5eee12a7feff43601e76a168..115a04de04631453f055d6bf9910415315868117 100644 --- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php +++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php @@ -128,7 +128,7 @@ class AbstractAddress extends AbstractExtensibleModel implements AddressModelInt * @param RegionInterfaceFactory $regionDataFactory * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -147,7 +147,7 @@ class AbstractAddress extends AbstractExtensibleModel implements AddressModelInt RegionInterfaceFactory $regionDataFactory, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_directoryData = $directoryData; diff --git a/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php b/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php index b25f4c6d0b3a3cb83b3693f1d2d7c08fb4859247..5870718e4634eb99d597a6be6cce894d690fa20e 100644 --- a/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php +++ b/app/code/Magento/Customer/Model/Config/Backend/Address/Street.php @@ -29,7 +29,7 @@ class Street extends \Magento\Framework\App\Config\Value * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Eav\Model\Config $eavConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -39,7 +39,7 @@ class Street extends \Magento\Framework\App\Config\Value \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Eav\Model\Config $eavConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_eavConfig = $eavConfig; diff --git a/app/code/Magento/Customer/Model/Config/Backend/CreateAccount/DisableAutoGroupAssignDefault.php b/app/code/Magento/Customer/Model/Config/Backend/CreateAccount/DisableAutoGroupAssignDefault.php index 81261bcd28fe4ed1a383e0df327c31e78edf0471..347fe6ad2e69f04eb3db3a4f6bd30d4d95531a71 100644 --- a/app/code/Magento/Customer/Model/Config/Backend/CreateAccount/DisableAutoGroupAssignDefault.php +++ b/app/code/Magento/Customer/Model/Config/Backend/CreateAccount/DisableAutoGroupAssignDefault.php @@ -18,7 +18,7 @@ class DisableAutoGroupAssignDefault extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Eav\Model\Config $eavConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -27,7 +27,7 @@ class DisableAutoGroupAssignDefault extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Eav\Model\Config $eavConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->eavConfig = $eavConfig; diff --git a/app/code/Magento/Customer/Model/Config/Backend/Show/Customer.php b/app/code/Magento/Customer/Model/Config/Backend/Show/Customer.php index 639238500a6df12a3e22f940b051e04ea3fd0261..58b1009006af86a3c1388a4fc56b5a47790d99b1 100644 --- a/app/code/Magento/Customer/Model/Config/Backend/Show/Customer.php +++ b/app/code/Magento/Customer/Model/Config/Backend/Show/Customer.php @@ -29,7 +29,7 @@ class Customer extends \Magento\Framework\App\Config\Value * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Eav\Model\Config $eavConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -39,7 +39,7 @@ class Customer extends \Magento\Framework\App\Config\Value \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Eav\Model\Config $eavConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_eavConfig = $eavConfig; diff --git a/app/code/Magento/Customer/Model/Config/Share.php b/app/code/Magento/Customer/Model/Config/Share.php index 33d1047ce52e5a8e2d539b1f205946e1fcef0231..8af6d52a9891dac9edb85a667a6595202467fe7c 100644 --- a/app/code/Magento/Customer/Model/Config/Share.php +++ b/app/code/Magento/Customer/Model/Config/Share.php @@ -43,7 +43,7 @@ class Share extends \Magento\Framework\App\Config\Value implements \Magento\Fram * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Customer\Model\Resource\Customer $customerResource * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -53,7 +53,7 @@ class Share extends \Magento\Framework\App\Config\Value implements \Magento\Fram \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Customer\Model\Resource\Customer $customerResource, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_storeManager = $storeManager; diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php index 776c8e74e1ace9aa8cc4205174c6fb0977032368..c00ab143dde9c09b8d427ea81a4570b38f2e478e 100644 --- a/app/code/Magento/Customer/Model/Customer.php +++ b/app/code/Magento/Customer/Model/Customer.php @@ -218,7 +218,7 @@ class Customer extends \Magento\Framework\Model\AbstractModel * @param DataObjectProcessor $dataObjectProcessor * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper * @param CustomerMetadataInterface $metadataService - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -240,7 +240,7 @@ class Customer extends \Magento\Framework\Model\AbstractModel DataObjectProcessor $dataObjectProcessor, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, \Magento\Customer\Api\CustomerMetadataInterface $metadataService, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->metadataService = $metadataService; @@ -1010,11 +1010,11 @@ class Customer extends \Magento\Framework\Model\AbstractModel { $errors = []; if (!\Zend_Validate::is(trim($this->getFirstname()), 'NotEmpty')) { - $errors[] = __('The first name cannot be empty.'); + $errors[] = __('Please enter a first name.'); } if (!\Zend_Validate::is(trim($this->getLastname()), 'NotEmpty')) { - $errors[] = __('The last name cannot be empty.'); + $errors[] = __('Please enter a last name.'); } if (!\Zend_Validate::is($this->getEmail(), 'EmailAddress')) { diff --git a/app/code/Magento/Customer/Model/Group.php b/app/code/Magento/Customer/Model/Group.php index b11d73f55bfac12c7f9b6f7a28cc271441543e8e..a912f5b56382e89d818719b02351b9e60a718ad3 100644 --- a/app/code/Magento/Customer/Model/Group.php +++ b/app/code/Magento/Customer/Model/Group.php @@ -65,7 +65,7 @@ class Group extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor * @param \Magento\Tax\Model\ClassModelFactory $classModelFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -76,7 +76,7 @@ class Group extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor, \Magento\Tax\Model\ClassModelFactory $classModelFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_storesConfig = $storesConfig; diff --git a/app/code/Magento/Customer/Model/Metadata/Form/AbstractData.php b/app/code/Magento/Customer/Model/Metadata/Form/AbstractData.php index d762fb121b6ab9a08f519fe82bfe86fcc9e5f3d4..25cf89edca73aec235c4558bc8afeaf154d9b8b7 100644 --- a/app/code/Magento/Customer/Model/Metadata/Form/AbstractData.php +++ b/app/code/Magento/Customer/Model/Metadata/Form/AbstractData.php @@ -370,42 +370,42 @@ abstract class AbstractData \Zend_Validate_EmailAddress::INVALID_LOCAL_PART ); $validator->setMessage( - __('"%1" exceeds the allowed length.', $label), + __('"%1" uses too many characters.', $label), \Zend_Validate_EmailAddress::LENGTH_EXCEEDED ); $validator->setMessage( - __("'%value%' appears to be an IP address, but IP addresses are not allowed."), + __("'%value%' looks like an IP address, which is not an acceptable format."), \Zend_Validate_Hostname::IP_ADDRESS_NOT_ALLOWED ); $validator->setMessage( - __("'%value%' appears to be a DNS hostname but cannot match TLD against known list."), + __("'%value%' looks like a DNS hostname but we cannot match the TLD against known list."), \Zend_Validate_Hostname::UNKNOWN_TLD ); $validator->setMessage( - __("'%value%' appears to be a DNS hostname but contains a dash in an invalid position."), + __("'%value%' looks like a DNS hostname but contains a dash in an invalid position."), \Zend_Validate_Hostname::INVALID_DASH ); $validator->setMessage( __( - "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'." + "'%value%' looks like a DNS hostname but we cannot match it against the hostname schema for TLD '%tld%'." ), \Zend_Validate_Hostname::INVALID_HOSTNAME_SCHEMA ); $validator->setMessage( - __("'%value%' appears to be a DNS hostname but cannot extract TLD part."), + __("'%value%' looks like a DNS hostname but cannot extract TLD part."), \Zend_Validate_Hostname::UNDECIPHERABLE_TLD ); $validator->setMessage( - __("'%value%' does not appear to be a valid local network name."), + __("'%value%' does not look like a valid local network name."), \Zend_Validate_Hostname::INVALID_LOCAL_NAME ); $validator->setMessage( - __("'%value%' appears to be a local network name but local network names are not allowed."), + __("'%value%' looks like a local network name, which is not an acceptable format."), \Zend_Validate_Hostname::LOCAL_NAME_NOT_ALLOWED ); $validator->setMessage( __( - "'%value%' appears to be a DNS hostname but the given punycode notation cannot be decoded." + "'%value%' appears to be a DNS hostname, but the given punycode notation cannot be decoded." ), \Zend_Validate_Hostname::CANNOT_DECODE_PUNYCODE ); diff --git a/app/code/Magento/Customer/Model/Renderer/Region.php b/app/code/Magento/Customer/Model/Renderer/Region.php index 1704789268f6374d644ab26810d24e0d5ebdc2fc..34a33f91974cdcc1229f05170cf5944895e6bf68 100644 --- a/app/code/Magento/Customer/Model/Renderer/Region.php +++ b/app/code/Magento/Customer/Model/Renderer/Region.php @@ -19,7 +19,7 @@ class Region implements \Magento\Framework\Data\Form\Element\Renderer\RendererIn * * Structure: * array( - * [$countryId] => \Magento\Framework\Data\Collection\Db + * [$countryId] => \Magento\Framework\Data\Collection\AbstractDb * ) * * @var array diff --git a/app/code/Magento/Customer/Model/Resource/CustomerRepository.php b/app/code/Magento/Customer/Model/Resource/CustomerRepository.php index af1b716d8f2308983a3622f919e354317de25df0..b20ce2bb0d5994139764b85e4406050b39c05a46 100644 --- a/app/code/Magento/Customer/Model/Resource/CustomerRepository.php +++ b/app/code/Magento/Customer/Model/Resource/CustomerRepository.php @@ -13,6 +13,7 @@ use Magento\Framework\Api\ImageProcessorInterface; use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Api\ExtensionAttributesFactory; /** * Customer repository. @@ -80,6 +81,11 @@ class CustomerRepository implements \Magento\Customer\Api\CustomerRepositoryInte */ protected $imageProcessor; + /** + * @var ExtensionAttributesFactory + */ + protected $extensionAttributesFactory; + /** * @param \Magento\Customer\Model\CustomerFactory $customerFactory * @param \Magento\Customer\Model\Data\CustomerSecureFactory $customerSecureFactory @@ -93,6 +99,7 @@ class CustomerRepository implements \Magento\Customer\Api\CustomerRepositoryInte * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter * @param DataObjectHelper $dataObjectHelper * @param ImageProcessorInterface $imageProcessor + * @param ExtensionAttributesFactory $extensionAttributesFactory * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -107,7 +114,8 @@ class CustomerRepository implements \Magento\Customer\Api\CustomerRepositoryInte \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter, DataObjectHelper $dataObjectHelper, - ImageProcessorInterface $imageProcessor + ImageProcessorInterface $imageProcessor, + ExtensionAttributesFactory $extensionAttributesFactory ) { $this->customerFactory = $customerFactory; $this->customerSecureFactory = $customerSecureFactory; @@ -121,6 +129,7 @@ class CustomerRepository implements \Magento\Customer\Api\CustomerRepositoryInte $this->extensibleDataObjectConverter = $extensibleDataObjectConverter; $this->dataObjectHelper = $dataObjectHelper; $this->imageProcessor = $imageProcessor; + $this->extensionAttributesFactory = $extensionAttributesFactory; } /** @@ -270,6 +279,7 @@ class CustomerRepository implements \Magento\Customer\Api\CustomerRepositoryInte } $collection->setCurPage($searchCriteria->getCurrentPage()); $collection->setPageSize($searchCriteria->getPageSize()); + $this->extensionAttributesFactory->process($collection, 'Magento\Customer\Model\Data\Customer'); $customers = []; /** @var \Magento\Customer\Model\Customer $customerModel */ foreach ($collection as $customerModel) { diff --git a/app/code/Magento/Customer/Model/Visitor.php b/app/code/Magento/Customer/Model/Visitor.php index 132fd35acc9d1c66adc5be763fd2214760fb6247..681713b895c65dd63f1564e23dc612a8173101f3 100644 --- a/app/code/Magento/Customer/Model/Visitor.php +++ b/app/code/Magento/Customer/Model/Visitor.php @@ -61,7 +61,7 @@ class Visitor extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Session\SessionManagerInterface $session * @param \Magento\Framework\HTTP\Header $httpHeader * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param array $ignoredUserAgents @@ -78,7 +78,7 @@ class Visitor extends \Magento\Framework\Model\AbstractModel \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $ignoredUserAgents = [], array $ignores = [], array $data = [] diff --git a/app/code/Magento/Customer/Setup/CustomerSetup.php b/app/code/Magento/Customer/Setup/CustomerSetup.php index f0c0de3c5e57a52eda6bd3e9d9220b7097d2dcf7..d96f2469f983ec0f74863f13965229c789002a27 100644 --- a/app/code/Magento/Customer/Setup/CustomerSetup.php +++ b/app/code/Magento/Customer/Setup/CustomerSetup.php @@ -345,7 +345,7 @@ class CustomerSetup extends EavSetup 'entity_attribute_collection' => 'Magento\Customer\Model\Resource\Address\Attribute\Collection', 'attributes' => [ 'prefix' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'Prefix', 'input' => 'text', 'required' => false, @@ -355,7 +355,7 @@ class CustomerSetup extends EavSetup 'position' => 10, ], 'firstname' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'First Name', 'input' => 'text', 'sort_order' => 20, @@ -363,7 +363,7 @@ class CustomerSetup extends EavSetup 'position' => 20, ], 'middlename' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'Middle Name/Initial', 'input' => 'text', 'required' => false, @@ -373,7 +373,7 @@ class CustomerSetup extends EavSetup 'position' => 30, ], 'lastname' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'Last Name', 'input' => 'text', 'sort_order' => 40, @@ -381,7 +381,7 @@ class CustomerSetup extends EavSetup 'position' => 40, ], 'suffix' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'Suffix', 'input' => 'text', 'required' => false, @@ -391,7 +391,7 @@ class CustomerSetup extends EavSetup 'position' => 50, ], 'company' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'Company', 'input' => 'text', 'required' => false, @@ -400,7 +400,7 @@ class CustomerSetup extends EavSetup 'position' => 60, ], 'street' => [ - 'type' => 'text', + 'type' => 'static', 'label' => 'Street Address', 'input' => 'multiline', 'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\DefaultBackend', @@ -410,7 +410,7 @@ class CustomerSetup extends EavSetup 'position' => 70, ], 'city' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'City', 'input' => 'text', 'sort_order' => 80, @@ -418,7 +418,7 @@ class CustomerSetup extends EavSetup 'position' => 80, ], 'country_id' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'Country', 'input' => 'select', 'source' => 'Magento\Customer\Model\Resource\Address\Attribute\Source\Country', @@ -426,7 +426,7 @@ class CustomerSetup extends EavSetup 'position' => 90, ], 'region' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'State/Province', 'input' => 'text', 'backend' => 'Magento\Customer\Model\Resource\Address\Attribute\Backend\Region', @@ -435,7 +435,7 @@ class CustomerSetup extends EavSetup 'position' => 100, ], 'region_id' => [ - 'type' => 'int', + 'type' => 'static', 'label' => 'State/Province', 'input' => 'hidden', 'source' => 'Magento\Customer\Model\Resource\Address\Attribute\Source\Region', @@ -444,7 +444,7 @@ class CustomerSetup extends EavSetup 'position' => 100, ], 'postcode' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'Zip/Postal Code', 'input' => 'text', 'sort_order' => 110, @@ -454,7 +454,7 @@ class CustomerSetup extends EavSetup 'required' => false, ], 'telephone' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'Phone Number', 'input' => 'text', 'sort_order' => 120, @@ -462,7 +462,7 @@ class CustomerSetup extends EavSetup 'position' => 120, ], 'fax' => [ - 'type' => 'varchar', + 'type' => 'static', 'label' => 'Fax', 'input' => 'text', 'required' => false, diff --git a/app/code/Magento/Customer/Setup/InstallData.php b/app/code/Magento/Customer/Setup/InstallData.php index 95af7e5644ab84e2eb8ffe0f18b70979a26f6c95..9449f8d456d9192fb6fb8b6cdd7bfeb7bda3df30 100644 --- a/app/code/Magento/Customer/Setup/InstallData.php +++ b/app/code/Magento/Customer/Setup/InstallData.php @@ -73,7 +73,7 @@ class InstallData implements InstallDataInterface $attributesInfo = [ 'vat_id' => [ 'label' => 'VAT number', - 'type' => 'varchar', + 'type' => 'static', 'input' => 'text', 'position' => 140, 'visible' => true, @@ -83,17 +83,17 @@ class InstallData implements InstallDataInterface 'label' => 'VAT number validity', 'visible' => false, 'required' => false, - 'type' => 'int', + 'type' => 'static', ], 'vat_request_id' => [ 'label' => 'VAT number validation request ID', - 'type' => 'varchar', + 'type' => 'static', 'visible' => false, 'required' => false, ], 'vat_request_date' => [ 'label' => 'VAT number validation request date', - 'type' => 'varchar', + 'type' => 'static', 'visible' => false, 'required' => false, ], @@ -101,7 +101,7 @@ class InstallData implements InstallDataInterface 'label' => 'VAT number validation request success', 'visible' => false, 'required' => false, - 'type' => 'int', + 'type' => 'static', ], ]; diff --git a/app/code/Magento/Customer/Setup/InstallSchema.php b/app/code/Magento/Customer/Setup/InstallSchema.php index 5e47379b79c69f5dd51ad278e614d040d1341ce3..fc3458c5fdc5dac291626b636daebee3389da34f 100644 --- a/app/code/Magento/Customer/Setup/InstallSchema.php +++ b/app/code/Magento/Customer/Setup/InstallSchema.php @@ -282,6 +282,120 @@ class InstallSchema implements InstallSchemaInterface null, ['unsigned' => true, 'nullable' => false, 'default' => '1'], 'Is Active' + )->addColumn( + 'city', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => false], + 'City' + )->addColumn( + 'company', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => true, 'default' => null], + 'Company' + )->addColumn( + 'country_id', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => false], + 'Country' + )->addColumn( + 'fax', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => true, 'default' => null], + 'Fax' + )->addColumn( + 'firstname', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => false], + 'First Name' + )->addColumn( + 'lastname', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => false], + 'Last Name' + )->addColumn( + 'middlename', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => true, 'default' => null], + 'Middle Name' + )->addColumn( + 'postcode', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => true, 'default' => null], + 'Zip/Postal Code' + )->addColumn( + 'prefix', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 40, + ['nullable' => true, 'default' => null], + 'Prefix' + )->addColumn( + 'region', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => true, 'default' => null], + 'State/Province' + )->addColumn( + 'region_id', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['unsigned' => true, 'nullable' => true, 'default' => null], + 'State/Province' + )->addColumn( + 'street', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + null, + ['nullable' => false], + 'Street Address' + )->addColumn( + 'suffix', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 40, + ['nullable' => true, 'default' => null], + 'Suffix' + )->addColumn( + 'telephone', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => false], + 'Phone Number' + )->addColumn( + 'vat_id', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => true, 'default' => null], + 'VAT number' + )->addColumn( + 'vat_is_valid', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['unsigned' => true, 'nullable' => true, 'default' => null], + 'VAT number validity' + )->addColumn( + 'vat_request_date', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => true, 'default' => null], + 'VAT number validation request date' + )->addColumn( + 'vat_request_id', + \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, + 255, + ['nullable' => true, 'default' => null], + 'VAT number validation request ID' + )->addColumn( + 'vat_request_success', + \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, + null, + ['unsigned' => true, 'nullable' => true, 'default' => null], + 'VAT number validation request success' )->addIndex( $installer->getIdxName('customer_address_entity', ['parent_id']), ['parent_id'] 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 new file mode 100644 index 0000000000000000000000000000000000000000..f4065cc205e8155c13d00a43dc55b0e21cb136a1 --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Controller/Adminhtml/Index/ValidateTest.php @@ -0,0 +1,276 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Customer\Test\Unit\Controller\Adminhtml\Index; + +class ValidateTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\RequestInterface + */ + protected $request; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\ResponseInterface + */ + protected $response; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Customer\Api\Data\CustomerInterface + */ + protected $customer; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Customer\Api\Data\CustomerInterfaceFactory + */ + protected $customerDataFactory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Customer\Model\Metadata\FormFactory + */ + protected $formFactory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Customer\Model\Metadata\Form + */ + protected $form; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Api\ExtensibleDataObjectConverter + */ + protected $extensibleDataObjectConverter; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Api\DataObjectHelper + */ + protected $dataObjectHelper; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Customer\Api\AccountManagementInterface + */ + protected $customerAccountManagement; + + /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Controller\Result\JsonFactory */ + protected $resultJsonFactory; + + /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Controller\Result\Json */ + protected $resultJson; + + /** @var \Magento\Customer\Controller\Adminhtml\Index\Validate */ + protected $controller; + + public function setUp() + { + $this->customer = $this->getMockForAbstractClass( + 'Magento\Customer\Api\Data\CustomerInterface', + [], + '', + false, + true, + true + ); + $this->customer->expects($this->once())->method('getWebsiteId')->willReturn(2); + $this->customerDataFactory = $this->getMock( + 'Magento\Customer\Api\Data\CustomerInterfaceFactory', + ['create'], + [], + '', + false + ); + $this->customerDataFactory->expects($this->once())->method('create')->willReturn($this->customer); + $this->form = $this->getMock( + 'Magento\Customer\Model\Metadata\Form', + [], + [], + '', + false + ); + $this->request = $this->getMockForAbstractClass( + 'Magento\Framework\App\RequestInterface', + [], + '', + false, + true, + true, + ['getPost'] + ); + $this->response = $this->getMockForAbstractClass( + 'Magento\Framework\App\ResponseInterface', + [], + '', + false + ); + $this->formFactory = $this->getMock('Magento\Customer\Model\Metadata\FormFactory', ['create'], [], '', false); + $this->formFactory->expects($this->atLeastOnce())->method('create')->willReturn($this->form); + $this->extensibleDataObjectConverter = $this->getMock( + 'Magento\Framework\Api\ExtensibleDataObjectConverter', + [], + [], + '', + false + ); + $this->dataObjectHelper = $this->getMock('Magento\Framework\Api\DataObjectHelper', [], [], '', false); + $this->dataObjectHelper->expects($this->once())->method('populateWithArray'); + $this->customerAccountManagement = $this->getMockForAbstractClass( + 'Magento\Customer\Api\AccountManagementInterface', + [], + '', + false, + true, + true + ); + $this->resultJson = $this->getMock('Magento\Framework\Controller\Result\Json', [], [], '', false); + $this->resultJson->expects($this->once())->method('setData'); + $this->resultJsonFactory = $this->getMock( + 'Magento\Framework\Controller\Result\JsonFactory', + ['create'], + [], + '', + false + ); + $this->resultJsonFactory->expects($this->once())->method('create')->willReturn($this->resultJson); + + $objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->controller = $objectHelper->getObject( + 'Magento\Customer\Controller\Adminhtml\Index\Validate', + [ + 'request' => $this->request, + 'response' => $this->response, + 'customerDataFactory' => $this->customerDataFactory, + 'formFactory' => $this->formFactory, + 'extensibleDataObjectConverter' => $this->extensibleDataObjectConverter, + 'customerAccountManagement' => $this->customerAccountManagement, + 'resultJsonFactory' => $this->resultJsonFactory, + 'dataObjectHelper' => $this->dataObjectHelper, + ] + ); + } + + public function testExecute() + { + $this->request->expects($this->once()) + ->method('getPost') + ->willReturn([ + '_template_' => null, + 'address_index' => null + ]); + + $this->form->expects($this->once())->method('setInvisibleIgnored'); + $this->form->expects($this->atLeastOnce())->method('extractData')->willReturn([]); + + $error = $this->getMock('Magento\Framework\Message\Error', [], [], '', false); + $this->form->expects($this->once()) + ->method('validateData') + ->willReturn([$error]); + + $this->extensibleDataObjectConverter->expects($this->once()) + ->method('toFlatArray') + ->willReturn([]); + + $validationResult = $this->getMockForAbstractClass( + 'Magento\Customer\Api\Data\ValidationResultsInterface', + [], + '', + false, + true, + true + ); + $validationResult->expects($this->once()) + ->method('getMessages') + ->willReturn(['Error message']); + + $this->customerAccountManagement->expects($this->once()) + ->method('validate') + ->willReturn($validationResult); + + $this->controller->execute(); + } + + public function testExecuteWithoutAddresses() + { + $this->request->expects($this->once()) + ->method('getPost') + ->willReturn(null); + $this->form->expects($this->once()) + ->method('setInvisibleIgnored'); + $this->form->expects($this->atLeastOnce()) + ->method('extractData') + ->willReturn([]); + + $error = $this->getMock('Magento\Framework\Message\Error', [], [], '', false); + $this->form->expects($this->never()) + ->method('validateData') + ->willReturn([$error]); + + $this->extensibleDataObjectConverter->expects($this->once()) + ->method('toFlatArray') + ->willReturn([]); + + $validationResult = $this->getMockForAbstractClass( + 'Magento\Customer\Api\Data\ValidationResultsInterface', + [], + '', + false, + true, + true + ); + $validationResult->expects($this->once()) + ->method('getMessages') + ->willReturn(['Error message']); + + $this->customerAccountManagement->expects($this->once()) + ->method('validate') + ->willReturn($validationResult); + + $this->controller->execute(); + } + + public function testExecuteWithException() + { + $this->request->expects($this->once()) + ->method('getPost') + ->willReturn(null); + $this->form->expects($this->once()) + ->method('setInvisibleIgnored'); + $this->form->expects($this->atLeastOnce()) + ->method('extractData') + ->willReturn([]); + + $this->form->expects($this->never()) + ->method('validateData'); + + $this->extensibleDataObjectConverter->expects($this->once()) + ->method('toFlatArray') + ->willReturn([]); + + $validationResult = $this->getMockForAbstractClass( + 'Magento\Customer\Api\Data\ValidationResultsInterface', + [], + '', + false, + true, + true + ); + $error = $this->getMock('Magento\Framework\Message\Error', [], [], '', false); + $error->expects($this->once()) + ->method('getText') + ->willReturn('Error text'); + + $exception = $this->getMock('Magento\Framework\Validator\Exception', [], [], '', false); + $exception->expects($this->once()) + ->method('getMessages') + ->willReturn([$error]); + $validationResult->expects($this->once()) + ->method('getMessages') + ->willThrowException($exception); + + $this->customerAccountManagement->expects($this->once()) + ->method('validate') + ->willReturn($validationResult); + + $this->controller->execute(); + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php b/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php index 3d6df9fb22a018c89e5123293caa2fd190719cc2..486b1fa269ab2279da34fdc40fd6fbff0ba665f2 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Address/AbstractAddressTest.php @@ -32,7 +32,7 @@ class AbstractAddressTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Customer\Model\Resource\Customer|\PHPUnit_Framework_MockObject_MockObject */ protected $resourceMock; - /** @var \Magento\Framework\Data\Collection\Db|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Framework\Data\Collection\AbstractDb|\PHPUnit_Framework_MockObject_MockObject */ protected $resourceCollectionMock; /** @var \Magento\Customer\Model\Address\AbstractAddress */ @@ -78,13 +78,9 @@ class AbstractAddressTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($countryMock)); $this->resourceMock = $this->getMock('Magento\Customer\Model\Resource\Customer', [], [], '', false); - $this->resourceCollectionMock = $this->getMock( - 'Magento\Framework\Data\Collection\Db', - [], - [], - '', - false - ); + $this->resourceCollectionMock = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->model = $objectManager->getObject( 'Magento\Customer\Model\Address\AbstractAddress', @@ -107,11 +103,9 @@ class AbstractAddressTest extends \PHPUnit_Framework_TestCase $countryId = 1; $this->prepareGetRegion($countryId); - $this->model->setData([ - 'region_id' => 1, - 'region' => '', - 'country_id' => $countryId, - ]); + $this->model->setData('region_id', 1); + $this->model->setData('region', ''); + $this->model->setData('country_id', $countryId); $this->assertEquals('RegionName', $this->model->getRegion()); } @@ -120,11 +114,9 @@ class AbstractAddressTest extends \PHPUnit_Framework_TestCase $countryId = 2; $this->prepareGetRegion($countryId); - $this->model->setData([ - 'region_id' => '', - 'region' => 2, - 'country_id' => $countryId, - ]); + $this->model->setData('region_id', ''); + $this->model->setData('region', 2); + $this->model->setData('country_id', $countryId); $this->assertEquals('RegionName', $this->model->getRegion()); } @@ -132,10 +124,8 @@ class AbstractAddressTest extends \PHPUnit_Framework_TestCase { $this->regionFactoryMock->expects($this->never())->method('create'); - $this->model->setData([ - 'region_id' => '', - 'region' => 'RegionName', - ]); + $this->model->setData('region_id', ''); + $this->model->setData('region', 'RegionName'); $this->assertEquals('RegionName', $this->model->getRegion()); } @@ -151,11 +141,9 @@ class AbstractAddressTest extends \PHPUnit_Framework_TestCase $countryId = 1; $this->prepareGetRegionCode($countryId); - $this->model->setData([ - 'region_id' => 3, - 'region' => '', - 'country_id' => $countryId, - ]); + $this->model->setData('region_id', 3); + $this->model->setData('region', ''); + $this->model->setData('country_id', $countryId); $this->assertEquals('UK', $this->model->getRegionCode()); } @@ -164,11 +152,9 @@ class AbstractAddressTest extends \PHPUnit_Framework_TestCase $countryId = 2; $this->prepareGetRegionCode($countryId); - $this->model->setData([ - 'region_id' => '', - 'region' => 4, - 'country_id' => $countryId, - ]); + $this->model->setData('region_id', ''); + $this->model->setData('region', 4); + $this->model->setData('country_id', $countryId); $this->assertEquals('UK', $this->model->getRegionCode()); } @@ -176,10 +162,8 @@ class AbstractAddressTest extends \PHPUnit_Framework_TestCase { $this->regionFactoryMock->expects($this->never())->method('create'); - $this->model->setData([ - 'region_id' => '', - 'region' => 'UK', - ]); + $this->model->setData('region_id', ''); + $this->model->setData('region', 'UK'); $this->assertEquals('UK', $this->model->getRegionCode()); } @@ -251,7 +235,9 @@ class AbstractAddressTest extends \PHPUnit_Framework_TestCase $this->directoryDataMock->expects($this->never()) ->method('isRegionRequired'); - $this->model->setData($data); + foreach ($data as $key => $value) { + $this->model->setData($key, $value); + } $this->assertEquals($expected, $this->model->validate()); } diff --git a/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php b/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php index 5f91793ec706725c0ce7b0123a5479408623571d..eeaa18aa02bd24ec917371b4752424dd5bfeac58 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php @@ -164,8 +164,8 @@ class CustomerTest extends \PHPUnit_Framework_TestCase 'gender' => 'm', ]; return [ - [array_diff_key($data, ['firstname' => '']), ['The first name cannot be empty.']], - [array_diff_key($data, ['lastname' => '']), ['The last name cannot be empty.']], + [array_diff_key($data, ['firstname' => '']), ['Please enter a first name.']], + [array_diff_key($data, ['lastname' => '']), ['Please enter a last name.']], [array_diff_key($data, ['email' => '']), ['Please correct this email address: "".']], [ array_merge($data, ['email' => 'wrong@email']), diff --git a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/AbstractDataTest.php b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/AbstractDataTest.php index fc84b9baacb86b7f8957dc30d4442c4f13378ca1..e2b9d3c6119ad018277abdfe107ad624a4b1d9d6 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/AbstractDataTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/Metadata/Form/AbstractDataTest.php @@ -261,7 +261,7 @@ class AbstractDataTest extends \PHPUnit_Framework_TestCase // @codingStandardsIgnoreStart \Zend_Validate_EmailAddress::INVALID_HOSTNAME => '"mylabel" is not a valid hostname.', \Zend_Validate_Hostname::INVALID_HOSTNAME => "'#\$' does not match the expected structure for a DNS hostname", - \Zend_Validate_Hostname::INVALID_LOCAL_NAME => "'#\$' does not appear to be a valid local network name." + \Zend_Validate_Hostname::INVALID_LOCAL_NAME => "'#\$' does not look like a valid local network name." // @codingStandardsIgnoreEnd ] ], diff --git a/app/code/Magento/Customer/composer.json b/app/code/Magento/Customer/composer.json index 204791f628792b5cb3a661c6c438aea6b0091c05..69fc3efec3823f3e47c02b91eb7c6dc6d3a9a20e 100644 --- a/app/code/Magento/Customer/composer.json +++ b/app/code/Magento/Customer/composer.json @@ -3,33 +3,33 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-newsletter": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-wishlist": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-review": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-page-cache": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-authorization": "0.74.0-beta10", - "magento/module-integration": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/module-ui": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-newsletter": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-wishlist": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-review": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-page-cache": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-authorization": "0.74.0-beta13", + "magento/module-integration": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/module-ui": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-cookie": "0.74.0-beta10" + "magento/module-cookie": "0.74.0-beta13" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Customer/view/adminhtml/templates/tab/cart.phtml b/app/code/Magento/Customer/view/adminhtml/templates/tab/cart.phtml index a25f849851d8281a4e33d0afdf7cd77a3b1b0956..7c3f93191d4d30d5b9ab13e6a00f5fed2997d090 100644 --- a/app/code/Magento/Customer/view/adminhtml/templates/tab/cart.phtml +++ b/app/code/Magento/Customer/view/adminhtml/templates/tab/cart.phtml @@ -55,7 +55,7 @@ require([ alert('<?php echo $block->escapeJsQuote(__('No item specified.')) ?>'); return false; } - if(!confirm('<?php echo $block->escapeJsQuote(__('Are you sure that you want to remove this item?')) ?>')) { + if(!confirm('<?php echo $block->escapeJsQuote(__('Are you sure you want to remove this item?')) ?>')) { return false; } diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Address.php b/app/code/Magento/CustomerImportExport/Model/Import/Address.php index 72df1baa354b859376a8b58461e91f862e049e55..c14103870f1908fa1f9340a987634151b0c72398 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/Address.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Address.php @@ -313,23 +313,6 @@ class Address extends AbstractCustomer return $this->_customerEntity; } - /** - * Get region parameters - * - * @return array - */ - protected function _getRegionParameters() - { - if (!$this->_regionParameters) { - $this->_regionParameters = []; - /** @var $regionIdAttribute \Magento\Customer\Model\Attribute */ - $regionIdAttribute = $this->_eavConfig->getAttribute($this->getEntityTypeCode(), 'region_id'); - $this->_regionParameters['table'] = $regionIdAttribute->getBackend()->getTable(); - $this->_regionParameters['attribute_id'] = $regionIdAttribute->getId(); - } - return $this->_regionParameters; - } - /** * Get next address entity ID * @@ -395,7 +378,8 @@ class Address extends AbstractCustomer protected function _importData() { while ($bunch = $this->_dataSourceModel->getNextBunch()) { - $addUpdateRows = []; + $newRows = []; + $updateRows = []; $attributes = []; $defaults = []; // customer default addresses (billing/shipping) data @@ -409,7 +393,12 @@ class Address extends AbstractCustomer if ($this->getBehavior($rowData) == \Magento\ImportExport\Model\Import::BEHAVIOR_ADD_UPDATE) { $addUpdateResult = $this->_prepareDataForUpdate($rowData); - $addUpdateRows[] = $addUpdateResult['entity_row']; + if ($addUpdateResult['entity_row_new']) { + $newRows[] = $addUpdateResult['entity_row_new']; + } + if ($addUpdateResult['entity_row_update']) { + $updateRows[] = $addUpdateResult['entity_row_update']; + } $attributes = $this->_mergeEntityAttributes($addUpdateResult['attributes'], $attributes); $defaults = $this->_mergeEntityAttributes($addUpdateResult['defaults'], $defaults); } elseif ($this->getBehavior($rowData) == \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE) { @@ -418,7 +407,8 @@ class Address extends AbstractCustomer } $this->_saveAddressEntities( - $addUpdateRows + $newRows, + $updateRows )->_saveAddressAttributes( $attributes )->_saveCustomerDefaults( @@ -462,26 +452,15 @@ class Address extends AbstractCustomer $email = strtolower($rowData[self::COLUMN_EMAIL]); $customerId = $this->_getCustomerId($email, $rowData[self::COLUMN_WEBSITE]); - $regionParameters = $this->_getRegionParameters(); - $regionIdTable = $regionParameters['table']; - $regionIdAttributeId = $regionParameters['attribute_id']; - - // get address attributes - $addressAttributes = []; - foreach ($this->_attributes as $attributeAlias => $attributeParams) { - if (isset($rowData[$attributeAlias]) && strlen($rowData[$attributeAlias])) { - if ('select' == $attributeParams['type']) { - $value = $attributeParams['options'][strtolower($rowData[$attributeAlias])]; - } elseif ('datetime' == $attributeParams['type']) { - $value = (new \DateTime())->setTimestamp(strtotime($rowData[$attributeAlias])); - $value = $value->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT); - } else { - $value = $rowData[$attributeAlias]; - } - $addressAttributes[$attributeParams['id']] = $value; - } - } + // entity table data + $entityRowNew = []; + $entityRowUpdate = []; + // attribute values + $attributes = []; + // customer default addresses + $defaults = []; + $newAddress = true; // get address id if (isset( $this->_addresses[$customerId] @@ -490,30 +469,44 @@ class Address extends AbstractCustomer $this->_addresses[$customerId] ) ) { + $newAddress = false; $addressId = $rowData[self::COLUMN_ADDRESS_ID]; } else { $addressId = $this->_getNextEntityId(); } - - // entity table data $entityRow = [ 'entity_id' => $addressId, 'parent_id' => $customerId, - 'created_at' => (new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT), 'updated_at' => (new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT), ]; - // attribute values - $attributes = []; - foreach ($this->_attributes as $attributeParams) { - if (isset($addressAttributes[$attributeParams['id']])) { - $attributes[$attributeParams['table']][$addressId][$attributeParams['id']] - = $addressAttributes[$attributeParams['id']]; + foreach ($this->_attributes as $attributeAlias => $attributeParams) { + if (array_key_exists($attributeAlias, $rowData)) { + if (!strlen($rowData[$attributeAlias])) { + if ($newAddress) { + $value = null; + } else { + continue; + } + } elseif ($newAddress && !strlen($rowData[$attributeAlias])) { + + } elseif ('select' == $attributeParams['type']) { + $value = $attributeParams['options'][strtolower($rowData[$attributeAlias])]; + } elseif ('datetime' == $attributeParams['type']) { + $value = (new \DateTime())->setTimestamp(strtotime($rowData[$attributeAlias])); + $value = $value->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT); + } else { + $value = $rowData[$attributeAlias]; + } + if ($attributeParams['is_static']) { + $entityRow[$attributeAlias] = $value; + } else { + $attributes[$attributeParams['table']][$addressId][$attributeParams['id']]= $value; + } } } - // customer default addresses - $defaults = []; + foreach (self::getDefaultAddressAttributeMapping() as $columnName => $attributeCode) { if (!empty($rowData[$columnName])) { /** @var $attribute \Magento\Eav\Model\Entity\Attribute\AbstractAttribute */ @@ -529,32 +522,52 @@ class Address extends AbstractCustomer if (isset($this->_countryRegions[$countryNormalized][$regionNormalized])) { $regionId = $this->_countryRegions[$countryNormalized][$regionNormalized]; - $attributes[$regionIdTable][$addressId][$regionIdAttributeId] = $regionId; - $tableName = $this->_attributes[self::COLUMN_REGION]['table']; - $regionColumnNameId = $this->_attributes[self::COLUMN_REGION]['id']; - $attributes[$tableName][$addressId][$regionColumnNameId] = $this->_regions[$regionId]; + $entityRow[self::COLUMN_REGION] = $this->_regions[$regionId]; + $entityRow['region_id'] = $regionId; } } - return ['entity_row' => $entityRow, 'attributes' => $attributes, 'defaults' => $defaults]; + if ($newAddress) { + $entityRowNew = $entityRow; + $entityRowNew['created_at'] = + (new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT); + } else { + $entityRowUpdate = $entityRow; + } + + return [ + 'entity_row_new' => $entityRowNew, + 'entity_row_update' => $entityRowUpdate, + 'attributes' => $attributes, + 'defaults' => $defaults + ]; } /** * Update and insert data in entity table * - * @param array $entityRows Rows for insert + * @param array $addRows Rows for insert + * @param array $updateRows Rows for update * @return $this */ - protected function _saveAddressEntities(array $entityRows) + protected function _saveAddressEntities(array $addRows, array $updateRows) { - if ($entityRows) { - $this->_connection->insertOnDuplicate($this->_entityTable, $entityRows, ['updated_at']); + if ($addRows) { + $this->_connection->insertMultiple($this->_entityTable, $addRows); + } + if ($updateRows) { + //list of updated fields can be different for addresses. We can not use insertOnDuplicate for whole rows. + foreach ($updateRows as $row) { + $fields = array_diff(array_keys($row), ['entity_id', 'parent_id', 'created_at']); + $this->_connection->insertOnDuplicate($this->_entityTable, $row, $fields); + } + } return $this; } /** - * Save customer address attributes + * Save custom customer address attributes * * @param array $attributesData * @return $this diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php index c42ed953406b1d1dd4b3146575777f203d77a538..1d9e2b6fa9208d3d2e842ab42384d1a501871cc3 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php @@ -222,8 +222,6 @@ class Customer extends AbstractCustomer 'suffix', 'dob', 'password_hash', - 'default_billing', - 'default_shipping', 'taxvat', 'confirmation', 'gender', diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Export/AddressTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Export/AddressTest.php index c65ced0ca675d39810394b2217b2fdc16fe02722..ebc2e782689585f7bc21613697894d8d88aebb16 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Export/AddressTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Export/AddressTest.php @@ -159,13 +159,10 @@ class AddressTest extends \PHPUnit_Framework_TestCase $this->returnCallback([$this, 'iterate']) ); - $customerCollection = $this->getMock( - 'Magento\Framework\Data\Collection\Db', - ['addAttributeToSelect'], - [], - '', - false - ); + $customerCollection = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->setMethods(['addAttributeToSelect']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $customerEntity = $this->getMock('stdClass', ['filterEntityCollection', 'setParameters']); $customerEntity->expects($this->any())->method('filterEntityCollection')->will($this->returnArgument(0)); @@ -213,11 +210,11 @@ class AddressTest extends \PHPUnit_Framework_TestCase * * @SuppressWarnings(PHPMD.UnusedFormalParameter) * - * @param \Magento\Framework\Data\Collection\Db $collection + * @param \Magento\Framework\Data\Collection\AbstractDb $collection * @param int $pageSize * @param array $callbacks */ - public function iterate(\Magento\Framework\Data\Collection\Db $collection, $pageSize, array $callbacks) + public function iterate(\Magento\Framework\Data\Collection\AbstractDb $collection, $pageSize, array $callbacks) { $resource = $this->getMock( 'Magento\Customer\Model\Resource\Customer', diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php index bcfdb86cdf64d6cd64b388e0ced47f1a27e2a006..f7c815c5e73f5b21f14145c903b932eea69ec182 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php @@ -335,7 +335,8 @@ class AddressTest extends \PHPUnit_Framework_TestCase ], ]; $updateResult = [ - 'entity_row' => $this->_customBehaviour['update_id'], + 'entity_row_new' => [], + 'entity_row_update' => $this->_customBehaviour['update_id'], 'attributes' => [], 'defaults' => [], ]; @@ -678,13 +679,15 @@ class AddressTest extends \PHPUnit_Framework_TestCase /** * Validation method for _saveAddressEntities (callback for _saveAddressEntities) * - * @param array $addUpdateRows + * @param array $addRows + * @param array $updateRows * @return Address|\PHPUnit_Framework_MockObject_MockObject */ - public function validateSaveAddressEntities(array $addUpdateRows) + public function validateSaveAddressEntities(array $addRows, array $updateRows) { - $this->assertCount(1, $addUpdateRows); - $this->assertContains($this->_customBehaviour['update_id'], $addUpdateRows); + $this->assertCount(0, $addRows); + $this->assertCount(1, $updateRows); + $this->assertContains($this->_customBehaviour['update_id'], $updateRows); return $this->_model; } diff --git a/app/code/Magento/CustomerImportExport/composer.json b/app/code/Magento/CustomerImportExport/composer.json index 2f897331fc7b692bca0042257825afb3a742136c..0fca4e85cc1316d04098a0685fdc613ab7af42c1 100644 --- a/app/code/Magento/CustomerImportExport/composer.json +++ b/app/code/Magento/CustomerImportExport/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-import-export": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-import-export": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Launch.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Launch.php index 661a25f4cd1237fec110669243f16f95e1df75e2..05878003f284a8302cf55f4c51b10f9be8d50dfc 100644 --- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Launch.php +++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Launch.php @@ -159,7 +159,7 @@ class Launch extends \Magento\DesignEditor\Controller\Adminhtml\System\Design\Ed $this->_redirect('adminhtml/*/'); return; } catch (\Exception $e) { - $this->messageManager->addException($e, __('Sorry, there was an unknown error.')); + $this->messageManager->addException($e, __('Sorry, something went wrong.')); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); $this->_redirect('adminhtml/*/'); return; diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Save.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Save.php index bc03a26180f23e2903a6701ab0ee8a82eb0e4eab..33321d063c0cc6fd5675ef00ac09cd9766c20166 100644 --- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Save.php +++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Save.php @@ -30,7 +30,7 @@ class Save extends \Magento\DesignEditor\Controller\Adminhtml\System\Design\Edit $response = ['message' => $message]; } catch (\Exception $e) { $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); - $response = ['error' => true, 'message' => __('Sorry, there was an unknown error.')]; + $response = ['error' => true, 'message' => __('Sorry, something went wrong.')]; } /** @var $jsonHelper \Magento\Framework\Json\Helper\Data */ diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/ReorderJs.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/ReorderJs.php index 5e52f16ee8c43edcbbc95f80f38f54563712acf7..50cc432f216be85bdf7887266e1a9d67828d85bf 100644 --- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/ReorderJs.php +++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/ReorderJs.php @@ -30,7 +30,7 @@ class ReorderJs extends \Magento\DesignEditor\Controller\Adminhtml\System\Design $result = ['error' => true, 'message' => $e->getMessage()]; $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } catch (\Exception $e) { - $result = ['error' => true, 'message' => __('We cannot upload the CSS file.')]; + $result = ['error' => true, 'message' => __('We can\'t upload the CSS file right now.')]; $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } $this->getResponse()->representJson( diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/Upload.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/Upload.php index d9865cc72492834481d4e62cbf89a0c7ea21c96f..04fdade46f68285b8d3ce36d0dbbaafe109a865a 100644 --- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/Upload.php +++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/Upload.php @@ -42,7 +42,7 @@ class Upload extends \Magento\DesignEditor\Controller\Adminhtml\System\Design\Ed $response = ['error' => true, 'message' => $e->getMessage()]; $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } catch (\Exception $e) { - $response = ['error' => true, 'message' => __('We cannot upload the CSS file.')]; + $response = ['error' => true, 'message' => __('We can\'t upload the CSS file right now.')]; $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } $this->getResponse()->representJson( diff --git a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadJs.php b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadJs.php index 936cf10780bc636b1e0cb3e9102ed75469c402f0..9e6f855450ad3729300d20e3407c08f6648f58ef 100644 --- a/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadJs.php +++ b/app/code/Magento/DesignEditor/Controller/Adminhtml/System/Design/Editor/Tools/UploadJs.php @@ -36,7 +36,7 @@ class UploadJs extends \Magento\DesignEditor\Controller\Adminhtml\System\Design\ $response = ['error' => true, 'message' => $e->getMessage()]; $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } catch (\Exception $e) { - $response = ['error' => true, 'message' => __('We cannot upload the JS file.')]; + $response = ['error' => true, 'message' => __('We can\'t upload the JS file right now.')]; $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } $this->getResponse()->representJson( diff --git a/app/code/Magento/DesignEditor/composer.json b/app/code/Magento/DesignEditor/composer.json index 1a8de8c3cdee2fc9301f0a31a5dc8eb812eca904..c74e983baf4c68378fe6735571211cdf05e11cb0 100644 --- a/app/code/Magento/DesignEditor/composer.json +++ b/app/code/Magento/DesignEditor/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-translation": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-translation": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/DesignEditor/view/adminhtml/templates/editor/tools/code/js.phtml b/app/code/Magento/DesignEditor/view/adminhtml/templates/editor/tools/code/js.phtml index 8958f0301853197e9e989924c60f02b5dc0260b5..4e26d52a4cd5d532f8a11b2de08baf674ff40663 100644 --- a/app/code/Magento/DesignEditor/view/adminhtml/templates/editor/tools/code/js.phtml +++ b/app/code/Magento/DesignEditor/view/adminhtml/templates/editor/tools/code/js.phtml @@ -208,7 +208,7 @@ require([ }); }, this), error: $.proxy(function () { - alert($.mage.__('Sorry, there was an unknown error.')); + alert($.mage.__('Sorry, something went wrong.')); }, this) }); } diff --git a/app/code/Magento/DesignEditor/view/adminhtml/web/js/custom-css.js b/app/code/Magento/DesignEditor/view/adminhtml/web/js/custom-css.js index 35e5b14497da8282087f18efc5fc204b7755950b..1455c9a71012e44f7f168c7bf1914e3e90c31d2f 100644 --- a/app/code/Magento/DesignEditor/view/adminhtml/web/js/custom-css.js +++ b/app/code/Magento/DesignEditor/view/adminhtml/web/js/custom-css.js @@ -70,7 +70,7 @@ define([ this._prepareUpdateButton(); }, this), error: function() { - alert($.mage.__('Sorry, there was an unknown error.')); + alert($.mage.__('Sorry, something went wrong.')); } }); $('.vde-tools-content').trigger('resize.vdeToolsResize'); diff --git a/app/code/Magento/DesignEditor/view/adminhtml/web/js/image-sizing.js b/app/code/Magento/DesignEditor/view/adminhtml/web/js/image-sizing.js index 200fdc42b6777394f5ff68aaf9556de33e3cc6cf..5ee0a8767a743942194b901bae016fe9a4b3a684 100644 --- a/app/code/Magento/DesignEditor/view/adminhtml/web/js/image-sizing.js +++ b/app/code/Magento/DesignEditor/view/adminhtml/web/js/image-sizing.js @@ -174,7 +174,7 @@ define([ this.element.trigger('refreshIframe'); }, this), error: $.proxy(function() { - alert($.mage.__('Sorry, there was an unknown error.')); + alert($.mage.__('Sorry, something went wrong.')); }, this) }); } diff --git a/app/code/Magento/DesignEditor/view/adminhtml/web/js/infinitescroll.js b/app/code/Magento/DesignEditor/view/adminhtml/web/js/infinitescroll.js index 4f9cb4344455aef740e443000f5ddc7b411cab5c..613237d14fa670f887c4077d749a9ec2938de0c3 100644 --- a/app/code/Magento/DesignEditor/view/adminhtml/web/js/infinitescroll.js +++ b/app/code/Magento/DesignEditor/view/adminhtml/web/js/infinitescroll.js @@ -137,7 +137,7 @@ error: $.proxy(function() { this.setLocked(false); this.options.url = ''; - throw Error($.mage.__('Something went wrong while loading the theme.')); + throw Error($.mage.__('We can\'t load the theme right now.')); }, this) }); }, diff --git a/app/code/Magento/DesignEditor/view/adminhtml/web/js/quick-style-element.js b/app/code/Magento/DesignEditor/view/adminhtml/web/js/quick-style-element.js index b60d34cc137d1518bb906a22d2d9ce99d7401b3e..28820ebe322415c8d9bed3401e0977cd552ffd53 100644 --- a/app/code/Magento/DesignEditor/view/adminhtml/web/js/quick-style-element.js +++ b/app/code/Magento/DesignEditor/view/adminhtml/web/js/quick-style-element.js @@ -70,7 +70,7 @@ define([ this.element.trigger('refreshIframe'); }, this), error: function() { - alert($.mage.__('Sorry, there was an unknown error.')); + alert($.mage.__('Sorry, something went wrong.')); } }); } diff --git a/app/code/Magento/DesignEditor/view/adminhtml/web/js/quick-style-uploader.js b/app/code/Magento/DesignEditor/view/adminhtml/web/js/quick-style-uploader.js index b14f9c05dfb502233766611b54051c672171bbce..04fc0919ea8774af2400442b86ec92e2ba91dbe5 100644 --- a/app/code/Magento/DesignEditor/view/adminhtml/web/js/quick-style-uploader.js +++ b/app/code/Magento/DesignEditor/view/adminhtml/web/js/quick-style-uploader.js @@ -101,7 +101,7 @@ define([ } }, this), error: function() { - alert($.mage.__('Sorry, there was an unknown error.')); + alert($.mage.__('Sorry, something went wrong.')); } }); }, diff --git a/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-assign.js b/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-assign.js index 05da6050e258b8d780f974b11395c315d9d7d5c5..ee24310855c7a74399760809e6a6184ec5ad4caa 100644 --- a/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-assign.js +++ b/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-assign.js @@ -408,7 +408,7 @@ define([ this.assignThemeSuccess(response, stores, themeId); }, this), error: $.proxy(function() { - var message = $.mage.__('Sorry, there was an unknown error.'); + var message = $.mage.__('Sorry, something went wrong.'); this._dialog.messages.set(message, 'error'); }, this) }); diff --git a/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-revert.js b/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-revert.js index 783d43c09d1d467cc7be23e935655b70c69a08b1..0b53489c8a2ee8e1ea243ee096533c2084fba52a 100644 --- a/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-revert.js +++ b/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-revert.js @@ -89,13 +89,13 @@ define([ async: false, success: $.proxy(function(data) { if (data.error) { - throw Error($.mage.__('Some problem with revert action')); + throw Error($.mage.__('We can\'t revert right now.')); return; } document.location.reload(); }, this), error: function() { - throw Error($.mage.__('Some problem with revert action')); + throw Error($.mage.__('We can\'t revert right now.')); } }); }, diff --git a/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-save.js b/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-save.js index 616225fb4f3329c24ee92f46c0957d474fa0edca..e350d1ac8ff38ab1259800b04fa61a79d599da7d 100644 --- a/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-save.js +++ b/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-save.js @@ -219,13 +219,13 @@ define([ success: function(data) { if (data.error) { /** @todo add error validator */ - throw Error($.mage.__('Some problem with save action')); + throw Error($.mage.__('We can\'t save right now.')); return; } postResult = data.success; }, error: function(data) { - throw Error($.mage.__('Some problem with save action')); + throw Error($.mage.__('We can\'t save right now.')); } }); return postResult; diff --git a/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-selector.js b/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-selector.js index f59b25065634b691e5c900292c1559513b08df88..dc092ec2ace035fd44403a33ee6724cc6d69ff59 100644 --- a/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-selector.js +++ b/app/code/Magento/DesignEditor/view/adminhtml/web/js/theme-selector.js @@ -108,7 +108,7 @@ define([ }, this), error: $.proxy(function() { this._cancelEdit(); - alert($.mage.__('Sorry, there was an unknown error.')); + alert($.mage.__('Sorry, something went wrong.')); }, this) }); }, diff --git a/app/code/Magento/Developer/Model/Config/Backend/AllowedIps.php b/app/code/Magento/Developer/Model/Config/Backend/AllowedIps.php index 48656d5729843a386c95c1ce5da9fdf975e12032..49be834c93dfdb3eb46457e943bd877e97075082 100644 --- a/app/code/Magento/Developer/Model/Config/Backend/AllowedIps.php +++ b/app/code/Magento/Developer/Model/Config/Backend/AllowedIps.php @@ -25,7 +25,7 @@ class AllowedIps extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\Message\ManagerInterface $messageManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -34,7 +34,7 @@ class AllowedIps extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->messageManager = $messageManager; diff --git a/app/code/Magento/Developer/Test/Unit/Model/Less/FileGenerator/PublicationDecoratorTest.php b/app/code/Magento/Developer/Test/Unit/Model/Less/FileGenerator/PublicationDecoratorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c84d9222c81f9a716d3bba73530cf090916ab5b0 --- /dev/null +++ b/app/code/Magento/Developer/Test/Unit/Model/Less/FileGenerator/PublicationDecoratorTest.php @@ -0,0 +1,58 @@ +<?php +/*** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Developer\Test\Unit\Model\Less\FileGenerator; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class PublicationDecoratorTest extends \PHPUnit_Framework_TestCase +{ + /** + * Calls generate method to access protected method generateRelatedFile + */ + public function testGenerateRelatedFile() + { + $publisherMock = $this->getMockBuilder('Magento\Framework\App\View\Asset\Publisher') + ->disableOriginalConstructor() + ->getMock(); + $assetRepoMock = $this->getMockBuilder('Magento\Framework\View\Asset\Repository') + ->disableOriginalConstructor() + ->getMock(); + $relatedAssetMock = $this->getMockBuilder('Magento\Framework\View\Asset\File') + ->disableOriginalConstructor() + ->getMock(); + $importGeneratorMock = $this->getMockBuilder('Magento\Framework\Less\PreProcessor\Instruction\Import') + ->disableOriginalConstructor() + ->getMock(); + $localAssetMock = $this->getMockBuilder('Magento\Framework\View\Asset\LocalInterface') + ->disableOriginalConstructor() + ->getMock(); + $relatedFileId = 'file_id'; + + $relatedFiles = [[$relatedFileId, $localAssetMock]]; + $importGeneratorMock->expects($this->any()) + ->method('getRelatedFiles') + ->will($this->onConsecutiveCalls($relatedFiles, [])); + $assetRepoMock->expects($this->any()) + ->method('createRelated') + ->willReturn($relatedAssetMock); + $publisherMock->expects($this->once()) + ->method('publish') + ->with($relatedAssetMock); + + $args = [ + 'assetRepo' => $assetRepoMock, + 'publisher' => $publisherMock + ]; + + $model = (new ObjectManager($this))->getObject( + 'Magento\Developer\Model\Less\FileGenerator\PublicationDecorator', + $args + ); + + $model->generate($importGeneratorMock); + } +} diff --git a/app/code/Magento/Developer/composer.json b/app/code/Magento/Developer/composer.json index 9046c5e1965f096882846df15d4d0aea93c5e930..159132b761c1f3ac35336599634434a2cf489651 100644 --- a/app/code/Magento/Developer/composer.json +++ b/app/code/Magento/Developer/composer.json @@ -3,12 +3,12 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Dhl/composer.json b/app/code/Magento/Dhl/composer.json index 0a23310309470c3e053d5bb4cf56e259f4892d44..844caf08a5f13cf23065ae0ed66adcc52014cb3b 100644 --- a/app/code/Magento/Dhl/composer.json +++ b/app/code/Magento/Dhl/composer.json @@ -3,22 +3,22 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-shipping": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-shipping": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Directory/Model/Country.php b/app/code/Magento/Directory/Model/Country.php index 65c1590086e707c9c5f95c6dc80bf4270742c107..3ba9d8ca20c7eaf7586c290b4238c53f9c0eb40e 100644 --- a/app/code/Magento/Directory/Model/Country.php +++ b/app/code/Magento/Directory/Model/Country.php @@ -45,7 +45,7 @@ class Country extends \Magento\Framework\Model\AbstractModel * @param Country\FormatFactory $formatFactory * @param Resource\Region\CollectionFactory $regionCollectionFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -55,7 +55,7 @@ class Country extends \Magento\Framework\Model\AbstractModel \Magento\Directory\Model\Country\FormatFactory $formatFactory, \Magento\Directory\Model\Resource\Region\CollectionFactory $regionCollectionFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Directory/Model/Currency.php b/app/code/Magento/Directory/Model/Currency.php index bcab343e2400232eba4853cf374b35fd67c54e90..13b1cbf821338ade269c242c970224ee1bff51d8 100644 --- a/app/code/Magento/Directory/Model/Currency.php +++ b/app/code/Magento/Directory/Model/Currency.php @@ -74,7 +74,7 @@ class Currency extends \Magento\Framework\Model\AbstractModel * @param Currency\FilterFactory $currencyFilterFactory * @param \Magento\Framework\Locale\CurrencyInterface $localeCurrency * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -87,7 +87,7 @@ class Currency extends \Magento\Framework\Model\AbstractModel \Magento\Directory\Model\Currency\FilterFactory $currencyFilterFactory, \Magento\Framework\Locale\CurrencyInterface $localeCurrency, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/Directory/composer.json b/app/code/Magento/Directory/composer.json index c53d2d669e8b49c98e9eaa72aaa2b1f18bcf430b..bc48bec5995d1768c6b6963bd2d72689a5bca4cf 100644 --- a/app/code/Magento/Directory/composer.json +++ b/app/code/Magento/Directory/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" 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 81d3f24b019f4610cb74f90d1e9d82e1faec0107..98d362efb02158e06283e5aa2bd2258f6a533633 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 @@ -43,6 +43,7 @@ function setPostcodeOptional(zipElement, country) { } else { zipElement.addClassName('required-entry'); zipElement.up('div.field').addClassName('required'); + zipElement.up('div.field').addClassName('_required'); } } diff --git a/app/code/Magento/Downloadable/Model/Link.php b/app/code/Magento/Downloadable/Model/Link.php index 66703a9dccb811ce294d5c4b39b053db7ec07cc2..3942fe6db5a4e649f17be859fff41fa88121e765 100644 --- a/app/code/Magento/Downloadable/Model/Link.php +++ b/app/code/Magento/Downloadable/Model/Link.php @@ -57,7 +57,7 @@ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements C * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -66,7 +66,7 @@ class Link extends \Magento\Framework\Model\AbstractExtensibleModel implements C \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/Downloadable/Model/Link/Purchased.php b/app/code/Magento/Downloadable/Model/Link/Purchased.php index 57eb988c3ce2b0822d814ca57c2c09b1379d4b67..c82de66bdd83eca045667eea7199821b7cfde3b4 100644 --- a/app/code/Magento/Downloadable/Model/Link/Purchased.php +++ b/app/code/Magento/Downloadable/Model/Link/Purchased.php @@ -24,8 +24,8 @@ namespace Magento\Downloadable\Model\Link; * @method \Magento\Downloadable\Model\Link\Purchased setCustomerId(int $value) * @method string getProductName() * @method \Magento\Downloadable\Model\Link\Purchased setProductName(string $value) - * @method string getProductSku() - * @method \Magento\Downloadable\Model\Link\Purchased setProductSku(string $value) + * @method string getSku() + * @method \Magento\Downloadable\Model\Link\Purchased setSku(string $value) * @method string getLinkSectionTitle() * @method \Magento\Downloadable\Model\Link\Purchased setLinkSectionTitle(string $value) * diff --git a/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/AbstractItems.php b/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/AbstractItems.php index 913d2f31f15cf928e1be3f38e5503b40d24c650e..368e87d057346d61a6c8ff04ba94208576cf49b8 100644 --- a/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/AbstractItems.php +++ b/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/AbstractItems.php @@ -48,7 +48,7 @@ abstract class AbstractItems extends \Magento\Sales\Model\Order\Pdf\Items\Abstra * @param \Magento\Downloadable\Model\Link\PurchasedFactory $purchasedFactory * @param \Magento\Downloadable\Model\Resource\Link\Purchased\Item\CollectionFactory $itemsFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -62,7 +62,7 @@ abstract class AbstractItems extends \Magento\Sales\Model\Order\Pdf\Items\Abstra \Magento\Downloadable\Model\Link\PurchasedFactory $purchasedFactory, \Magento\Downloadable\Model\Resource\Link\Purchased\Item\CollectionFactory $itemsFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_scopeConfig = $scopeConfig; diff --git a/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/Creditmemo.php b/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/Creditmemo.php index 63a063842af1a697af18dca537728709b4b74b4d..98b2f5cdc1c147e90965d9dd4408e5e07ff79664 100644 --- a/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/Creditmemo.php +++ b/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/Creditmemo.php @@ -26,7 +26,7 @@ class Creditmemo extends \Magento\Downloadable\Model\Sales\Order\Pdf\Items\Abstr * @param \Magento\Downloadable\Model\Resource\Link\Purchased\Item\CollectionFactory $itemsFactory * @param \Magento\Framework\Stdlib\String $string * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -41,7 +41,7 @@ class Creditmemo extends \Magento\Downloadable\Model\Sales\Order\Pdf\Items\Abstr \Magento\Downloadable\Model\Resource\Link\Purchased\Item\CollectionFactory $itemsFactory, \Magento\Framework\Stdlib\String $string, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->string = $string; @@ -113,7 +113,7 @@ class Creditmemo extends \Magento\Downloadable\Model\Sales\Order\Pdf\Items\Abstr // draw Total (inc) $subtotal = $item->getRowTotal() + $item->getTaxAmount() + - $item->getHiddenTaxAmount() - + $item->getDiscountTaxCompensationAmount() - $item->getDiscountAmount(); $lines[0][] = [ 'text' => $order->formatPriceTxt($subtotal), diff --git a/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/Invoice.php b/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/Invoice.php index 1bd20800ae0383b8639da82874783266a95e91b2..61732c5695a079aa36fd4bbf0f58c26c175b5901 100644 --- a/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/Invoice.php +++ b/app/code/Magento/Downloadable/Model/Sales/Order/Pdf/Items/Invoice.php @@ -26,7 +26,7 @@ class Invoice extends \Magento\Downloadable\Model\Sales\Order\Pdf\Items\Abstract * @param \Magento\Downloadable\Model\Resource\Link\Purchased\Item\CollectionFactory $itemsFactory * @param \Magento\Framework\Stdlib\String $string * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -41,7 +41,7 @@ class Invoice extends \Magento\Downloadable\Model\Sales\Order\Pdf\Items\Abstract \Magento\Downloadable\Model\Resource\Link\Purchased\Item\CollectionFactory $itemsFactory, \Magento\Framework\Stdlib\String $string, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->string = $string; diff --git a/app/code/Magento/Downloadable/Model/Sample.php b/app/code/Magento/Downloadable/Model/Sample.php index 4909fe6a39e649e071b47859b77a136eb31a1241..c8fe44159d1a54b88d494d2c1d39ab0ae486bd30 100644 --- a/app/code/Magento/Downloadable/Model/Sample.php +++ b/app/code/Magento/Downloadable/Model/Sample.php @@ -37,7 +37,7 @@ class Sample extends \Magento\Framework\Model\AbstractExtensibleModel implements * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -46,7 +46,7 @@ class Sample extends \Magento\Framework\Model\AbstractExtensibleModel implements \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/Sales/Order/Pdf/Items/CreditmemoTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/Sales/Order/Pdf/Items/CreditmemoTest.php index 5a74daa0875c29173afe36e56fcbf1c0b02634ea..5cca484119b73930802c1cea3f90ae4892de6cbc 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Model/Sales/Order/Pdf/Items/CreditmemoTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Model/Sales/Order/Pdf/Items/CreditmemoTest.php @@ -159,7 +159,7 @@ class CreditmemoTest extends \PHPUnit_Framework_TestCase 'discount_amount' => 5.00, 'qty' => 1, 'tax_amount' => 2.00, - 'hidden_tax_amount' => 0.00, + 'discount_tax_compensation_amount' => 0.00, 'order_item' => new \Magento\Framework\Object( [ 'product_options' => [ diff --git a/app/code/Magento/Downloadable/composer.json b/app/code/Magento/Downloadable/composer.json index 16adcb3869b6b7dde5d683688a1f3fec6e90c177..15f14f91214a75f64c9e6493480b1d972d830b95 100644 --- a/app/code/Magento/Downloadable/composer.json +++ b/app/code/Magento/Downloadable/composer.json @@ -3,28 +3,28 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-wishlist": "0.74.0-beta10", - "magento/module-gift-message": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-msrp": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-wishlist": "0.74.0-beta13", + "magento/module-gift-message": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-msrp": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Downloadable/etc/service_data_attributes.xml b/app/code/Magento/Downloadable/etc/extension_attributes.xml similarity index 92% rename from app/code/Magento/Downloadable/etc/service_data_attributes.xml rename to app/code/Magento/Downloadable/etc/extension_attributes.xml index 80cc1cb0abf9ff457b97d12eddc9b3b6ee519784..66e38c2f8e83b4010dfb92ace4be43d32f8dc197 100644 --- a/app/code/Magento/Downloadable/etc/service_data_attributes.xml +++ b/app/code/Magento/Downloadable/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> <attribute code="downloadable_product_links" type="Magento\Downloadable\Api\Data\LinkInterface[]" /> <attribute code="downloadable_product_samples" type="Magento\Downloadable\Api\Data\SampleInterface[]" /> diff --git a/app/code/Magento/Downloadable/view/frontend/templates/checkout/cart/item/default.phtml b/app/code/Magento/Downloadable/view/frontend/templates/checkout/cart/item/default.phtml index b1b38150bd6acf8b53700272f443bc5c1516d608..62441265c7402ef642fcc8027a3a2beb7d93b788 100644 --- a/app/code/Magento/Downloadable/view/frontend/templates/checkout/cart/item/default.phtml +++ b/app/code/Magento/Downloadable/view/frontend/templates/checkout/cart/item/default.phtml @@ -107,7 +107,7 @@ $canApplyMsrp = $helper->isShowBeforeOrderConfirm($product) && $helper->isMinima <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllowInCart()) : ?> <?php if ($isVisibleProduct): ?> <a href="#" data-post='<?php echo $this->helper('Magento\Wishlist\Helper\Data')->getMoveFromCartParams($_item->getId()); ?>' class="use-ajax action towishlist"> - <span><?php echo __('Move to Wishlist'); ?></span> + <span><?php echo __('Move to Wish List'); ?></span> </a> <?php endif ?> <?php endif ?> diff --git a/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractMain.php b/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractMain.php index 0bff79e95a10f965f28c2a0f4e77a07ebca45af0..2b6b39bc13cb91c3e29ea27e7821d23ae6cbb5d6 100644 --- a/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractMain.php +++ b/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractMain.php @@ -148,7 +148,7 @@ abstract class AbstractMain extends \Magento\Backend\Block\Widget\Form\Generic 'label' => __('Attribute Code'), 'title' => __('Attribute Code'), 'note' => __( - 'For internal use. Must be unique with no spaces. Maximum length of attribute code must be less than %1 symbols', + 'This is used internally. Make sure you don\'t use spaces or more than %1 symbols.', \Magento\Eav\Model\Entity\Attribute::ATTRIBUTE_CODE_MAX_LENGTH ), 'class' => $validateClass, diff --git a/app/code/Magento/Eav/Model/Attribute/Data/AbstractData.php b/app/code/Magento/Eav/Model/Attribute/Data/AbstractData.php index 124830186527cbb2dc6da670aee811abf1556156..a33d207d0bb1035bfee9957587ca49b36b2fef57 100644 --- a/app/code/Magento/Eav/Model/Attribute/Data/AbstractData.php +++ b/app/code/Magento/Eav/Model/Attribute/Data/AbstractData.php @@ -352,7 +352,7 @@ abstract class AbstractData __("'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'") __("'%value%' does not appear to be a valid local network name") __("'%value%' does not appear to be a valid URI hostname") - __("'%value%' appears to be an IP address, but IP addresses are not allowed") + __("'%value%' appears to be an IP address but IP addresses are not allowed") __("'%value%' appears to be a local network name but local network names are not allowed") __("'%value%' appears to be a DNS hostname but cannot extract TLD part") __("'%value%' appears to be a DNS hostname but cannot match TLD against known list") @@ -393,42 +393,42 @@ abstract class AbstractData \Zend_Validate_EmailAddress::INVALID_LOCAL_PART ); $validator->setMessage( - __('"%1" exceeds the allowed length.', $label), + __('"%1" uses too many characters.', $label), \Zend_Validate_EmailAddress::LENGTH_EXCEEDED ); $validator->setMessage( - __("'%value%' appears to be an IP address, but IP addresses are not allowed."), + __("'%value%' looks like an IP address, which is not an acceptable format."), \Zend_Validate_Hostname::IP_ADDRESS_NOT_ALLOWED ); $validator->setMessage( - __("'%value%' appears to be a DNS hostname but cannot match TLD against known list."), + __("'%value%' looks like a DNS hostname but we cannot match the TLD against known list."), \Zend_Validate_Hostname::UNKNOWN_TLD ); $validator->setMessage( - __("'%value%' appears to be a DNS hostname but contains a dash in an invalid position."), + __("'%value%' looks like a DNS hostname but contains a dash in an invalid position."), \Zend_Validate_Hostname::INVALID_DASH ); $validator->setMessage( __( - "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'." + "'%value%' looks like a DNS hostname but we cannot match it against the hostname schema for TLD '%tld%'." ), \Zend_Validate_Hostname::INVALID_HOSTNAME_SCHEMA ); $validator->setMessage( - __("'%value%' appears to be a DNS hostname but cannot extract TLD part."), + __("'%value%' looks like a DNS hostname but cannot extract TLD part."), \Zend_Validate_Hostname::UNDECIPHERABLE_TLD ); $validator->setMessage( - __("'%value%' does not appear to be a valid local network name."), + __("'%value%' does not look like a valid local network name."), \Zend_Validate_Hostname::INVALID_LOCAL_NAME ); $validator->setMessage( - __("'%value%' appears to be a local network name but local network names are not allowed."), + __("'%value%' looks like a local network name, which is not an acceptable format."), \Zend_Validate_Hostname::LOCAL_NAME_NOT_ALLOWED ); $validator->setMessage( __( - "'%value%' appears to be a DNS hostname but the given punycode notation cannot be decoded." + "'%value%' appears to be a DNS hostname, but the given punycode notation cannot be decoded." ), \Zend_Validate_Hostname::CANNOT_DECODE_PUNYCODE ); diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php index c8fa8214eab58921da003c19e9a5c55b4a3d66c1..c4969c8a280d0373513797e8ee6c34ca1f6a210e 100755 --- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php +++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php @@ -13,8 +13,8 @@ use Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend; use Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend; use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource; use Magento\Framework\App\Config\Element; -use Magento\Framework\Model\AbstractModel; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Model\AbstractModel; use Magento\Framework\Model\Resource\Db\ObjectRelationProcessor; use Magento\Framework\Model\Resource\Db\TransactionManagerInterface; @@ -1152,11 +1152,11 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract /** * Save entity's attributes into the object's resource * - * @param \Magento\Framework\Object $object + * @param \Magento\Framework\Model\AbstractModel $object * @return $this * @throws \Exception */ - public function save(\Magento\Framework\Object $object) + public function save(\Magento\Framework\Model\AbstractModel $object) { /** * Direct deleted items to delete method @@ -1245,7 +1245,7 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract * 'newObject', 'entityRow', 'insert', 'update', 'delete' * ) * - * @param \Magento\Framework\Object $newObject + * @param \Magento\Framework\Model\AbstractModel $newObject * @return array * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) @@ -1723,7 +1723,7 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract $connection = $this->transactionManager->start($this->_getWriteAdapter()); if (is_numeric($object)) { $id = (int) $object; - } elseif ($object instanceof \Magento\Framework\Object) { + } elseif ($object instanceof \Magento\Framework\Model\AbstractModel) { $object->beforeDelete(); $id = (int) $object->getId(); } @@ -1748,12 +1748,12 @@ abstract class AbstractEntity extends \Magento\Framework\Model\Resource\Abstract $this->_afterDelete($object); - if ($object instanceof \Magento\Framework\Object) { + if ($object instanceof \Magento\Framework\Model\AbstractModel) { $object->isDeleted(true); $object->afterDelete(); } $this->transactionManager->commit(); - if ($object instanceof \Magento\Framework\Object) { + if ($object instanceof \Magento\Framework\Model\AbstractModel) { $object->afterDeleteCommit(); } } catch (\Exception $e) { diff --git a/app/code/Magento/Eav/Model/Entity/Attribute.php b/app/code/Magento/Eav/Model/Entity/Attribute.php index 5682724a47726b8504a4862eca31b2c8c75b2bfb..12ee3803ffac190a84a1ca0497b558733a751a58 100755 --- a/app/code/Magento/Eav/Model/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute.php @@ -81,7 +81,7 @@ class Attribute extends \Magento\Eav\Model\Entity\Attribute\AbstractAttribute im * @param \Magento\Catalog\Model\Product\ReservedAttributeList $reservedAttributeList * @param \Magento\Framework\Locale\ResolverInterface $localeResolver * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -102,7 +102,7 @@ class Attribute extends \Magento\Eav\Model\Entity\Attribute\AbstractAttribute im \Magento\Catalog\Model\Product\ReservedAttributeList $reservedAttributeList, \Magento\Framework\Locale\ResolverInterface $localeResolver, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -241,7 +241,7 @@ class Attribute extends \Magento\Eav\Model\Entity\Attribute\AbstractAttribute im ) ) { throw new LocalizedException( - __('Maximum length of attribute code must be less than %1 symbols', self::ATTRIBUTE_CODE_MAX_LENGTH) + __('An attribute code must be fewer than %1 characters.', self::ATTRIBUTE_CODE_MAX_LENGTH) ); } diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 9dbc048d711ecb5ddbcb936e1cdad322200c61c7..ce15220c8365e7baf1bf2bb960843b18bccf8735 100755 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -125,7 +125,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens * @param \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -143,7 +143,7 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Set.php b/app/code/Magento/Eav/Model/Entity/Attribute/Set.php index 446f4fd65a88ba119a7ad37caa67d681aa327ffd..efb38108d692a720cc3cde831995da6588e55b58 100755 --- a/app/code/Magento/Eav/Model/Entity/Attribute/Set.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/Set.php @@ -82,7 +82,7 @@ class Set extends \Magento\Framework\Model\AbstractExtensibleModel implements * @param \Magento\Eav\Model\Entity\AttributeFactory $attributeFactory * @param \Magento\Eav\Model\Resource\Entity\Attribute $resourceAttribute * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -96,7 +96,7 @@ class Set extends \Magento\Framework\Model\AbstractExtensibleModel implements \Magento\Eav\Model\Entity\AttributeFactory $attributeFactory, \Magento\Eav\Model\Resource\Entity\Attribute $resourceAttribute, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -265,7 +265,7 @@ class Set extends \Magento\Framework\Model\AbstractExtensibleModel implements } if (!$this->_getResource()->validate($this, $attributeSetName)) { - throw new LocalizedException(__('An attribute set with the "%1" name already exists.', $attributeSetName)); + throw new LocalizedException(__('An attribute set named "%1" already exists.', $attributeSetName)); } return true; diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 72712e67c4406c2c2485649571e70ee145701992..96465ce1dfb580896dec931e5ee40ea2c7fec76a 100755 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -14,7 +14,7 @@ use Magento\Framework\Exception\LocalizedException; * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Db +abstract class AbstractCollection extends \Magento\Framework\Data\Collection\AbstractDb { /** * Array of items with item id key @@ -364,11 +364,11 @@ abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Db } /** - * Wrapper for compatibility with \Magento\Framework\Data\Collection\Db + * Wrapper for compatibility with \Magento\Framework\Data\Collection\AbstractDb * * @param mixed $attribute * @param mixed $condition - * @return $this|\Magento\Framework\Data\Collection\Db + * @return $this|\Magento\Framework\Data\Collection\AbstractDb */ public function addFieldToFilter($attribute, $condition = null) { diff --git a/app/code/Magento/Eav/Model/Entity/Type.php b/app/code/Magento/Eav/Model/Entity/Type.php index 5a9b28ce9a45bf25ccb7f4ed2ffc6bc155b1dfc2..46307fdeda4c1b604a83fdeec63ba7b294ca75b0 100644 --- a/app/code/Magento/Eav/Model/Entity/Type.php +++ b/app/code/Magento/Eav/Model/Entity/Type.php @@ -87,7 +87,7 @@ class Type extends \Magento\Framework\Model\AbstractModel * @param \Magento\Eav\Model\Entity\StoreFactory $storeFactory * @param \Magento\Framework\Validator\UniversalFactory $universalFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -98,7 +98,7 @@ class Type extends \Magento\Framework\Model\AbstractModel \Magento\Eav\Model\Entity\StoreFactory $storeFactory, \Magento\Framework\Validator\UniversalFactory $universalFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Eav/Model/Form.php b/app/code/Magento/Eav/Model/Form.php index 2d822310584f4214b1991f9a8c70d0d913798c10..b4924593b708f0ee8604617dcf613e90e1c933df 100644 --- a/app/code/Magento/Eav/Model/Form.php +++ b/app/code/Magento/Eav/Model/Form.php @@ -161,10 +161,12 @@ abstract class Form \Magento\Framework\Validator\ConfigFactory $validatorConfigFactory ) { if (empty($this->_moduleName)) { - throw new \Magento\Framework\Exception\LocalizedException(__('Current module pathname is undefined')); + throw new \Magento\Framework\Exception\LocalizedException(__('The current module pathname is undefined.')); } if (empty($this->_entityTypeCode)) { - throw new \Magento\Framework\Exception\LocalizedException(__('Current module EAV entity is undefined')); + throw new \Magento\Framework\Exception\LocalizedException( + __('The current module EAV entity is undefined.') + ); } $this->_storeManager = $storeManager; $this->_eavConfig = $eavConfig; @@ -276,7 +278,7 @@ abstract class Form public function getFormCode() { if (empty($this->_formCode)) { - throw new \Magento\Framework\Exception\LocalizedException(__('Form code is not defined')); + throw new \Magento\Framework\Exception\LocalizedException(__('The form code is not defined.')); } return $this->_formCode; } @@ -304,7 +306,7 @@ abstract class Form public function getEntity() { if ($this->_entity === null) { - throw new \Magento\Framework\Exception\LocalizedException(__('Entity instance is not defined')); + throw new \Magento\Framework\Exception\LocalizedException(__('The entity instance is not defined.')); } return $this->_entity; } diff --git a/app/code/Magento/Eav/Model/Form/Element.php b/app/code/Magento/Eav/Model/Form/Element.php index 864c7020552bd7595455dca861a29f3aa52a64a8..1caa6b67ef83a3a77f8999326d63378c0e1c7e3d 100644 --- a/app/code/Magento/Eav/Model/Form/Element.php +++ b/app/code/Magento/Eav/Model/Form/Element.php @@ -41,7 +41,7 @@ class Element extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Eav\Model\Config $eavConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -49,7 +49,7 @@ class Element extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Eav\Model\Config $eavConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Eav/Model/Form/Fieldset.php b/app/code/Magento/Eav/Model/Form/Fieldset.php index 5f0bcd0e50d6b01d444143f3244d3ed8b81a52d8..1b6f1da1b1e6b626cc6f5187cf744e884e427d1d 100644 --- a/app/code/Magento/Eav/Model/Form/Fieldset.php +++ b/app/code/Magento/Eav/Model/Form/Fieldset.php @@ -37,7 +37,7 @@ class Fieldset extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -45,7 +45,7 @@ class Fieldset extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Eav/Model/Form/Type.php b/app/code/Magento/Eav/Model/Form/Type.php index ba0256b2dd90bd4c41d138a5b19458d60efe14dd..af6ec9848d4ed0c8c33cd5a36802b997763adfd4 100644 --- a/app/code/Magento/Eav/Model/Form/Type.php +++ b/app/code/Magento/Eav/Model/Form/Type.php @@ -47,7 +47,7 @@ class Type extends \Magento\Framework\Model\AbstractModel * @param \Magento\Eav\Model\Form\FieldsetFactory $fieldsetFactory * @param \Magento\Eav\Model\Form\ElementFactory $elementFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -56,7 +56,7 @@ class Type extends \Magento\Framework\Model\AbstractModel \Magento\Eav\Model\Form\FieldsetFactory $fieldsetFactory, \Magento\Eav\Model\Form\ElementFactory $elementFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Eav/Model/Resource/Entity/Attribute.php b/app/code/Magento/Eav/Model/Resource/Entity/Attribute.php index 22831a03847de46639e722538eeac43e88a417d9..1d6de506075d30f89149161248136f22fb7f6ab5 100644 --- a/app/code/Magento/Eav/Model/Resource/Entity/Attribute.php +++ b/app/code/Magento/Eav/Model/Resource/Entity/Attribute.php @@ -159,7 +159,7 @@ class Attribute extends \Magento\Framework\Model\Resource\Db\AbstractDb $frontendLabel = $object->getFrontendLabel(); if (is_array($frontendLabel)) { if (!isset($frontendLabel[0]) || $frontendLabel[0] === null || $frontendLabel[0] == '') { - throw new \Magento\Framework\Exception\LocalizedException(__('Frontend label is not defined')); + throw new \Magento\Framework\Exception\LocalizedException(__('The storefront label is not defined.')); } $object->setFrontendLabel($frontendLabel[0])->setStoreLabels($frontendLabel); } diff --git a/app/code/Magento/Eav/Model/Resource/Form/Attribute/Collection.php b/app/code/Magento/Eav/Model/Resource/Form/Attribute/Collection.php index 6c220b914289a8a4f95cc9eaef5f04c82aa7bef3..47ef760a2cfa03a629ebb56df3d6376586311d2c 100644 --- a/app/code/Magento/Eav/Model/Resource/Form/Attribute/Collection.php +++ b/app/code/Magento/Eav/Model/Resource/Form/Attribute/Collection.php @@ -84,10 +84,12 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac protected function _construct() { if (empty($this->_moduleName)) { - throw new \Magento\Framework\Exception\LocalizedException(__('Current module pathname is undefined')); + throw new \Magento\Framework\Exception\LocalizedException(__('The current module pathname is undefined.')); } if (empty($this->_entityTypeCode)) { - throw new \Magento\Framework\Exception\LocalizedException(__('Current module EAV entity is undefined')); + throw new \Magento\Framework\Exception\LocalizedException( + __('The current module EAV entity is undefined.') + ); } } diff --git a/app/code/Magento/Eav/Model/Validator/Attribute/Backend.php b/app/code/Magento/Eav/Model/Validator/Attribute/Backend.php index 82149dd8606a1cf96c47549d999180ed3ddf3aa3..1f75908775b65cd3f21756bd81454e030209893c 100644 --- a/app/code/Magento/Eav/Model/Validator/Attribute/Backend.php +++ b/app/code/Magento/Eav/Model/Validator/Attribute/Backend.php @@ -44,7 +44,7 @@ class Backend extends \Magento\Framework\Validator\AbstractValidator $result = $backend->validate($entity); if (false === $result) { $this->_messages[$attribute->getAttributeCode()][] = __( - 'The value of attribute "%1" is invalid', + 'The value of attribute "%1" is invalid.', $attribute->getAttributeCode() ); } elseif (is_string($result)) { diff --git a/app/code/Magento/Eav/Setup/EavSetup.php b/app/code/Magento/Eav/Setup/EavSetup.php index cccb9d3b0286efc053a86b5fa752cc2a6f189577..7764a2f5aad33adcb64ec553c415858be428ecc5 100755 --- a/app/code/Magento/Eav/Setup/EavSetup.php +++ b/app/code/Magento/Eav/Setup/EavSetup.php @@ -728,7 +728,7 @@ class EavSetup ) ) { throw new LocalizedException( - __('Maximum length of attribute code must be less than %1 symbols', $attributeCodeMaxLength) + __('An attribute code must be fewer than %1 characters.', $attributeCodeMaxLength) ); } diff --git a/app/code/Magento/Eav/Test/Unit/Model/ConfigTest.php b/app/code/Magento/Eav/Test/Unit/Model/ConfigTest.php index afb72584604e4dd4df86b693bacb6ac5d8aa9090..2d5119df63c3dbcf285b8b4c8b35280d9caebd72 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/ConfigTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/ConfigTest.php @@ -95,7 +95,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase ->method('getData') ->willReturn([]); $entityAttributeMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute') - ->setMethods(['dummy']) + ->setMethods(['setData']) ->disableOriginalConstructor() ->getMock(); $factoryCalls = [ @@ -133,7 +133,7 @@ class ConfigTest extends \PHPUnit_Framework_TestCase ->will($this->returnValueMap($factoryCalls)); $entityType = $this->getMockBuilder('\Magento\Eav\Model\Entity\Type') - ->setMethods(['getEntity']) + ->setMethods(['getEntity', 'setData', 'getData']) ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractTest.php index 281ad4e85345573bdfc8a6e715589f97f6320853..3034b99b8714fa00a525568147f29c554be3db85 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractTest.php @@ -216,7 +216,9 @@ class AbstractTest extends \PHPUnit_Framework_TestCase false ); $object->setEntityTypeId(1); - $object->setData($productData); + foreach ($productData as $key => $value) { + $object->setData($key, $value); + } $object->expects($this->any())->method('getOrigData')->will($this->returnValue($productOrigData)); $entityType = new \Magento\Framework\Object(); diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/SetTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/SetTest.php index 7a81bd55d364ff3423c2e2d4cb884827f4fa4c83..b9e4fdddd2ff8c232dd9e9f3e3c42cec66a3dcad 100755 --- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/SetTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/SetTest.php @@ -73,7 +73,7 @@ class SetTest extends \PHPUnit_Framework_TestCase { return [ ['', 'Attribute set name is empty.'], - ['existing_name', 'An attribute set with the "existing_name" name already exists.'] + ['existing_name', 'An attribute set named "existing_name" already exists.'] ]; } } diff --git a/app/code/Magento/Eav/composer.json b/app/code/Magento/Eav/composer.json index 429f9dbfb31e019938865ac281d0cdd7fdba478d..5f243b8986208869e385aebfcbb4b57e28615de6 100644 --- a/app/code/Magento/Eav/composer.json +++ b/app/code/Magento/Eav/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Delete.php b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Delete.php index 0f2c544f9ac3ce7b051b41bf5476d461b3e4b9c7..fb512eaf866d99630a5f6e54a4dc4757e0bfd041 100644 --- a/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Delete.php +++ b/app/code/Magento/Email/Controller/Adminhtml/Email/Template/Delete.php @@ -37,7 +37,7 @@ class Delete extends \Magento\Email\Controller\Adminhtml\Email\Template $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { $this->messageManager->addError( - __('An error occurred while deleting email template data. Please review log and try again.') + __('We can\'t delete email template data right now. Please review log and try again.') ); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); // save data in session diff --git a/app/code/Magento/Email/Test/Unit/Model/BackendTemplateTest.php b/app/code/Magento/Email/Test/Unit/Model/BackendTemplateTest.php index 6a51e983e3b53191e4265d5f9f7d857825c86d1f..f6580836c13c027e666169406c1cdcf828689a7b 100644 --- a/app/code/Magento/Email/Test/Unit/Model/BackendTemplateTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/BackendTemplateTest.php @@ -37,6 +37,11 @@ class BackendTemplateTest extends \PHPUnit_Framework_TestCase */ protected $resourceModelMock; + /** + * @var \Magento\Framework\App\ObjectManager + */ + protected $objectManagerBackup; + protected function setUp() { $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -54,6 +59,13 @@ class BackendTemplateTest extends \PHPUnit_Framework_TestCase ->method('get') ->with('Magento\Email\Model\Resource\Template') ->will($this->returnValue($this->resourceModelMock)); + + try { + $this->objectManagerBackup = \Magento\Framework\App\ObjectManager::getInstance(); + } catch (\RuntimeException $e) { + $this->objectManagerBackup = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER) + ->create($_SERVER); + } \Magento\Framework\App\ObjectManager::setInstance($objectManagerMock); $this->model = $helper->getObject( @@ -62,6 +74,12 @@ class BackendTemplateTest extends \PHPUnit_Framework_TestCase ); } + protected function tearDown() + { + parent::tearDown(); + \Magento\Framework\App\ObjectManager::setInstance($this->objectManagerBackup); + } + public function testGetSystemConfigPathsWhereUsedAsDefaultNoTemplateCode() { $this->assertEquals([], $this->model->getSystemConfigPathsWhereUsedAsDefault()); diff --git a/app/code/Magento/Email/composer.json b/app/code/Magento/Email/composer.json index feb023fbf36308c7038a4cac71fa945c47fdb568..e1be936adc070dc4d55a948b467c7e147cd8193d 100644 --- a/app/code/Magento/Email/composer.json +++ b/app/code/Magento/Email/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-cms": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-variable": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-cms": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-variable": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Fedex/composer.json b/app/code/Magento/Fedex/composer.json index eab709fc7018fa412e11593450785a04d2e86376..2fe10a640638848100355b7e0b1c66a8b5244292 100644 --- a/app/code/Magento/Fedex/composer.json +++ b/app/code/Magento/Fedex/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-shipping": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-shipping": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GiftMessage/Model/Message.php b/app/code/Magento/GiftMessage/Model/Message.php index be07b6cfb242c50d11fc7a9cf691d91b717150ef..553888c5249384676d6a5528f31d94842b2912a7 100644 --- a/app/code/Magento/GiftMessage/Model/Message.php +++ b/app/code/Magento/GiftMessage/Model/Message.php @@ -28,9 +28,9 @@ class Message extends \Magento\Framework\Model\AbstractExtensibleModel implement * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory * @param AttributeValueFactory $customAttributeFactory - * @param Resource\Message $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection * @param TypeFactory $typeFactory + * @param Resource\Message $resource + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -38,9 +38,9 @@ class Message extends \Magento\Framework\Model\AbstractExtensibleModel implement \Magento\Framework\Registry $registry, \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, AttributeValueFactory $customAttributeFactory, - \Magento\GiftMessage\Model\Resource\Message $resource, - \Magento\Framework\Data\Collection\Db $resourceCollection, \Magento\GiftMessage\Model\TypeFactory $typeFactory, + \Magento\GiftMessage\Model\Resource\Message $resource = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_typeFactory = $typeFactory; diff --git a/app/code/Magento/GiftMessage/composer.json b/app/code/Magento/GiftMessage/composer.json index da5aef1129cbc0381944e3c590d265bc4c4337f1..2e2e4b6a8e46e6c2d9cb6a63e3b6a69c5ef0c69d 100644 --- a/app/code/Magento/GiftMessage/composer.json +++ b/app/code/Magento/GiftMessage/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-multishipping": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-multishipping": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/setup/src/Magento/Setup/Test/Unit/Module/Di/_files/service_data_attributes.xml b/app/code/Magento/GiftMessage/etc/extension_attributes.xml similarity index 95% rename from setup/src/Magento/Setup/Test/Unit/Module/Di/_files/service_data_attributes.xml rename to app/code/Magento/GiftMessage/etc/extension_attributes.xml index bc8a926dfb86f1a247e0ddbcceade7545b42b660..604ebb9dc9ab6850e9e98729f20a2ac9b9bfb5e1 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/Di/_files/service_data_attributes.xml +++ b/app/code/Magento/GiftMessage/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Sales\Api\Data\OrderInterface"> <attribute code="gift_message" type="Magento\GiftMessage\Api\Data\MessageInterface" /> </extension_attributes> diff --git a/app/code/Magento/GoogleAdwords/Model/Config/Backend/AbstractConversion.php b/app/code/Magento/GoogleAdwords/Model/Config/Backend/AbstractConversion.php index 9920ac9efcd94ac6dc08c92175b671c67e867d65..f8d836a793d2957ca4c3f6f0c9f38af10b2d8030 100644 --- a/app/code/Magento/GoogleAdwords/Model/Config/Backend/AbstractConversion.php +++ b/app/code/Magento/GoogleAdwords/Model/Config/Backend/AbstractConversion.php @@ -29,7 +29,7 @@ abstract class AbstractConversion extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\Validator\ObjectFactory $validatorCompositeFactory * @param \Magento\GoogleAdwords\Model\Validator\Factory $validatorFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -39,7 +39,7 @@ abstract class AbstractConversion extends \Magento\Framework\App\Config\Value \Magento\Framework\Validator\ObjectFactory $validatorCompositeFactory, \Magento\GoogleAdwords\Model\Validator\Factory $validatorFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $config, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/GoogleAdwords/composer.json b/app/code/Magento/GoogleAdwords/composer.json index 96d5d7fc9e756d60ecd4a7a3121f9bc38e1d3e15..304cc1bf791158d545194f29f2c3be44a9b8c097 100644 --- a/app/code/Magento/GoogleAdwords/composer.json +++ b/app/code/Magento/GoogleAdwords/composer.json @@ -3,13 +3,13 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GoogleAnalytics/composer.json b/app/code/Magento/GoogleAnalytics/composer.json index 5e10a5dfec28e2b5a85d82199997973111045c47..92aee5dbd021df882f73761a6b368c905fdcc83e 100644 --- a/app/code/Magento/GoogleAnalytics/composer.json +++ b/app/code/Magento/GoogleAnalytics/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-cookie": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-cookie": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GoogleOptimizer/composer.json b/app/code/Magento/GoogleOptimizer/composer.json index fd1e99507fd5fc939b8367794a6e35c168f84ed7..f046d154cbcf7acf581a241c374e026df489efc2 100644 --- a/app/code/Magento/GoogleOptimizer/composer.json +++ b/app/code/Magento/GoogleOptimizer/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-google-analytics": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-cms": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-google-analytics": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-cms": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GoogleShopping/Model/Attribute.php b/app/code/Magento/GoogleShopping/Model/Attribute.php index adbe22f41a86b983e875e59cf36cc2beae5b1915..5c3218e9a12a09bda40989da09c5678cd63c3fa7 100644 --- a/app/code/Magento/GoogleShopping/Model/Attribute.php +++ b/app/code/Magento/GoogleShopping/Model/Attribute.php @@ -75,7 +75,7 @@ class Attribute extends \Magento\Framework\Model\AbstractModel * @param \Magento\GoogleShopping\Helper\Product $gsProduct * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -86,7 +86,7 @@ class Attribute extends \Magento\Framework\Model\AbstractModel \Magento\GoogleShopping\Helper\Product $gsProduct, \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice, \Magento\GoogleShopping\Model\Resource\Attribute $resource, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_productFactory = $productFactory; diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/ContentLanguage.php b/app/code/Magento/GoogleShopping/Model/Attribute/ContentLanguage.php index e78e3b68c2f1d995c31965e33e8538d70f3657d0..cbea4b5dfac6e2299f21b99ffbb9120c17fc2752 100644 --- a/app/code/Magento/GoogleShopping/Model/Attribute/ContentLanguage.php +++ b/app/code/Magento/GoogleShopping/Model/Attribute/ContentLanguage.php @@ -28,7 +28,7 @@ class ContentLanguage extends \Magento\GoogleShopping\Model\Attribute\DefaultAtt * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource * @param \Magento\GoogleShopping\Model\Config $config - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -41,7 +41,7 @@ class ContentLanguage extends \Magento\GoogleShopping\Model\Attribute\DefaultAtt \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice, \Magento\GoogleShopping\Model\Resource\Attribute $resource, \Magento\GoogleShopping\Model\Config $config, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_config = $config; diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Destinations.php b/app/code/Magento/GoogleShopping/Model/Attribute/Destinations.php index 43dc01798d763a0d517a2c0eef59bf653c227d25..48664c35f7e49692819081fead54f2a372345414 100644 --- a/app/code/Magento/GoogleShopping/Model/Attribute/Destinations.php +++ b/app/code/Magento/GoogleShopping/Model/Attribute/Destinations.php @@ -28,7 +28,7 @@ class Destinations extends \Magento\GoogleShopping\Model\Attribute\DefaultAttrib * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource * @param \Magento\GoogleShopping\Model\Config $config - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -41,7 +41,7 @@ class Destinations extends \Magento\GoogleShopping\Model\Attribute\DefaultAttrib \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice, \Magento\GoogleShopping\Model\Resource\Attribute $resource, \Magento\GoogleShopping\Model\Config $config, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_config = $config; diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/GoogleProductCategory.php b/app/code/Magento/GoogleShopping/Model/Attribute/GoogleProductCategory.php index 1ac9b00897baee8d298808acc0c356a16c97bc1b..15d32dfd7a5cb2043d806875a4c15f2d6a1e0ab7 100644 --- a/app/code/Magento/GoogleShopping/Model/Attribute/GoogleProductCategory.php +++ b/app/code/Magento/GoogleShopping/Model/Attribute/GoogleProductCategory.php @@ -36,7 +36,7 @@ class GoogleProductCategory extends \Magento\GoogleShopping\Model\Attribute\Defa * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource * @param \Magento\GoogleShopping\Model\TypeFactory $typeFactory * @param \Magento\GoogleShopping\Model\Config $config - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -50,7 +50,7 @@ class GoogleProductCategory extends \Magento\GoogleShopping\Model\Attribute\Defa \Magento\GoogleShopping\Model\Resource\Attribute $resource, \Magento\GoogleShopping\Model\TypeFactory $typeFactory, \Magento\GoogleShopping\Model\Config $config, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_typeFactory = $typeFactory; diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/ImageLink.php b/app/code/Magento/GoogleShopping/Model/Attribute/ImageLink.php index e286f926ea2ca575528a1aba0bc07a69bc9071ae..51494b4110146c64de363af18508ec84ca171be0 100644 --- a/app/code/Magento/GoogleShopping/Model/Attribute/ImageLink.php +++ b/app/code/Magento/GoogleShopping/Model/Attribute/ImageLink.php @@ -26,7 +26,7 @@ class ImageLink extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource * @param \Magento\Catalog\Helper\Product $catalogProduct - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -39,7 +39,7 @@ class ImageLink extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice, \Magento\GoogleShopping\Model\Resource\Attribute $resource, \Magento\Catalog\Helper\Product $catalogProduct, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_catalogProduct = $catalogProduct; diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Link.php b/app/code/Magento/GoogleShopping/Model/Attribute/Link.php index 1e9b15cd96b556b55fada2f964136dab97b9f013..93e3a8915a2169b8b321c3b196992eb3c1817879 100644 --- a/app/code/Magento/GoogleShopping/Model/Attribute/Link.php +++ b/app/code/Magento/GoogleShopping/Model/Attribute/Link.php @@ -26,7 +26,7 @@ class Link extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -39,7 +39,7 @@ class Link extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice, \Magento\GoogleShopping\Model\Resource\Attribute $resource, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_scopeConfig = $scopeConfig; diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Price.php b/app/code/Magento/GoogleShopping/Model/Attribute/Price.php index a75a1f1a774fb21782fce489c671a8783e8ea4db..8bad75e3c70feb5f6c672528df84ff924df587f7 100644 --- a/app/code/Magento/GoogleShopping/Model/Attribute/Price.php +++ b/app/code/Magento/GoogleShopping/Model/Attribute/Price.php @@ -77,7 +77,7 @@ class Price extends DefaultAttribute * @param \Magento\Catalog\Helper\Data $catalogData * @param PriceCurrencyInterface $priceCurrency * @param \Magento\Customer\Api\GroupManagementInterface $groupManagement - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -96,7 +96,7 @@ class Price extends DefaultAttribute \Magento\Catalog\Helper\Data $catalogData, PriceCurrencyInterface $priceCurrency, \Magento\Customer\Api\GroupManagementInterface $groupManagement, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->groupManagement = $groupManagement; diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/ProductType.php b/app/code/Magento/GoogleShopping/Model/Attribute/ProductType.php index 9be717ab564b6981c6e527319631dce30853c65f..470e8aff4a0d8aeb0e2365e5bbc4938c0f25f338 100644 --- a/app/code/Magento/GoogleShopping/Model/Attribute/ProductType.php +++ b/app/code/Magento/GoogleShopping/Model/Attribute/ProductType.php @@ -28,7 +28,7 @@ class ProductType extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribu * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -41,7 +41,7 @@ class ProductType extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribu \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice, \Magento\GoogleShopping\Model\Resource\Attribute $resource, \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->categoryRepository = $categoryRepository; diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/TargetCountry.php b/app/code/Magento/GoogleShopping/Model/Attribute/TargetCountry.php index ca24c2f97d22f743da7c37ae9dd432134bb4b6a6..5da60c01122698d4350eaa3c16d3b9cd33066bfa 100644 --- a/app/code/Magento/GoogleShopping/Model/Attribute/TargetCountry.php +++ b/app/code/Magento/GoogleShopping/Model/Attribute/TargetCountry.php @@ -28,7 +28,7 @@ class TargetCountry extends \Magento\GoogleShopping\Model\Attribute\DefaultAttri * @param \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice * @param \Magento\GoogleShopping\Model\Resource\Attribute $resource * @param \Magento\GoogleShopping\Model\Config $config - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -41,7 +41,7 @@ class TargetCountry extends \Magento\GoogleShopping\Model\Attribute\DefaultAttri \Magento\Catalog\Model\Product\CatalogPrice $catalogPrice, \Magento\GoogleShopping\Model\Resource\Attribute $resource, \Magento\GoogleShopping\Model\Config $config, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_config = $config; diff --git a/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php b/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php index 098171523d9ccbf26591cdcbc48f2f7988c368ce..e99b7cdd7ba1b9b4ce8e5ae7e6ec15994ddf1c2b 100644 --- a/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php +++ b/app/code/Magento/GoogleShopping/Model/Attribute/Tax.php @@ -91,7 +91,7 @@ class Tax extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute * @param \Magento\Directory\Model\RegionFactory $regionFactory * @param \Magento\Customer\Api\GroupManagementInterface $groupManagement * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -111,7 +111,7 @@ class Tax extends \Magento\GoogleShopping\Model\Attribute\DefaultAttribute \Magento\Directory\Model\RegionFactory $regionFactory, \Magento\Customer\Api\GroupManagementInterface $groupManagement, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_config = $config; diff --git a/app/code/Magento/GoogleShopping/Model/Item.php b/app/code/Magento/GoogleShopping/Model/Item.php index 9d5eafa0a7f275a11b3843f56b173457e79db344..13f888d62acda6dc7795069634414a0a1aaae378 100644 --- a/app/code/Magento/GoogleShopping/Model/Item.php +++ b/app/code/Magento/GoogleShopping/Model/Item.php @@ -59,12 +59,12 @@ class Item extends \Magento\Framework\Model\AbstractModel /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry - * @param \Magento\GoogleShopping\Model\Service\ItemFactory $itemFactory - * @param \Magento\GoogleShopping\Model\TypeFactory $typeFactory + * @param Service\ItemFactory $itemFactory + * @param TypeFactory $typeFactory * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository - * @param \Magento\GoogleShopping\Model\Resource\Item $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection - * @param \Magento\GoogleShopping\Model\Config $config + * @param Config $config + * @param Resource\Item $resource + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -73,9 +73,9 @@ class Item extends \Magento\Framework\Model\AbstractModel \Magento\GoogleShopping\Model\Service\ItemFactory $itemFactory, \Magento\GoogleShopping\Model\TypeFactory $typeFactory, \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, - \Magento\GoogleShopping\Model\Resource\Item $resource, - \Magento\Framework\Data\Collection\Db $resourceCollection, \Magento\GoogleShopping\Model\Config $config, + \Magento\GoogleShopping\Model\Resource\Item $resource = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/GoogleShopping/Model/Type.php b/app/code/Magento/GoogleShopping/Model/Type.php index 0aeb448db8b68acf969a6c2955c2d58e5c4083c4..b9d9d99ee0f13a150848bbd8aa379ed28350b4e4 100644 --- a/app/code/Magento/GoogleShopping/Model/Type.php +++ b/app/code/Magento/GoogleShopping/Model/Type.php @@ -62,7 +62,7 @@ class Type extends \Magento\Framework\Model\AbstractModel * @param \Magento\GoogleShopping\Helper\Product $gsProduct * @param \Magento\GoogleShopping\Helper\Data $googleShoppingHelper * @param \Magento\GoogleShopping\Model\Resource\Type $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -75,7 +75,7 @@ class Type extends \Magento\Framework\Model\AbstractModel \Magento\GoogleShopping\Helper\Product $gsProduct, \Magento\GoogleShopping\Helper\Data $googleShoppingHelper, \Magento\GoogleShopping\Model\Resource\Type $resource, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_collectionFactory = $collectionFactory; diff --git a/app/code/Magento/GoogleShopping/composer.json b/app/code/Magento/GoogleShopping/composer.json index 281e361b1d92ae5e1cf16bf9560c056bc14795ab..564c50bd7a9c4929da303ab754797a91b5c26994 100644 --- a/app/code/Magento/GoogleShopping/composer.json +++ b/app/code/Magento/GoogleShopping/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GroupedImportExport/Model/Import/Product/Type/Grouped.php b/app/code/Magento/GroupedImportExport/Model/Import/Product/Type/Grouped.php index 2fbdbb4a86cba805b9da673bb695355458ff8c68..026d2a602ab17ecd98e9843f45c189658288af8c 100644 --- a/app/code/Magento/GroupedImportExport/Model/Import/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedImportExport/Model/Import/Product/Type/Grouped.php @@ -7,8 +7,15 @@ */ namespace Magento\GroupedImportExport\Model\Import\Product\Type; +use Magento\CatalogImportExport\Model\Import\Product; + class Grouped extends \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType { + /** + * Default delimiter for sku and qty. + */ + const SKU_QTY_DELIMITER = '='; + /** * Column names that holds values with particular meaning. * @@ -60,48 +67,51 @@ class Grouped extends \Magento\CatalogImportExport\Model\Import\Product\Type\Abs 'relation' => [] ]; foreach ($bunch as $rowNum => $rowData) { - $associatedSku = isset($rowData['_associated_sku']) ? $rowData['_associated_sku'] : null; - if (!$this->_entityModel->isRowAllowedToImport($rowData, $rowNum) || empty($associatedSku)) { + $associatedSkusQty = isset($rowData['associated_skus']) ? $rowData['associated_skus'] : null; + if (!$this->_entityModel->isRowAllowedToImport($rowData, $rowNum) || empty($associatedSkusQty)) { continue; } - if (isset($newSku[$associatedSku])) { - $linkedProductId = $newSku[$associatedSku]['entity_id']; - } elseif (isset($oldSku[$associatedSku])) { - $linkedProductId = $oldSku[$associatedSku]['entity_id']; - } else { - continue; - } - $scope = $this->_entityModel->getRowScope($rowData); - if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT == $scope) { - $productData = $newSku[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]]; - } else { - $colAttrSet = \Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET; - $rowData[$colAttrSet] = $productData['attr_set_code']; - $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE] = $productData['type_id']; - } - $productId = $productData['entity_id']; + $associatedSkusAndQtyPairs = explode(Product::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $associatedSkusQty); + $position = 0; + foreach ($associatedSkusAndQtyPairs as $associatedSkuAndQty) { + ++$position; + $associatedSkuAndQty = explode(self::SKU_QTY_DELIMITER, $associatedSkuAndQty); + $associatedSku = isset($associatedSkuAndQty[0]) ? trim($associatedSkuAndQty[0]) : null; + if (isset($newSku[$associatedSku])) { + $linkedProductId = $newSku[$associatedSku]['entity_id']; + } elseif (isset($oldSku[$associatedSku])) { + $linkedProductId = $oldSku[$associatedSku]['entity_id']; + } else { + continue; + } + $scope = $this->_entityModel->getRowScope($rowData); + if (Product::SCOPE_DEFAULT == $scope) { + $productData = $newSku[$rowData[Product::COL_SKU]]; + } else { + $colAttrSet = Product::COL_ATTR_SET; + $rowData[$colAttrSet] = $productData['attr_set_code']; + $rowData[Product::COL_TYPE] = $productData['type_id']; + } + $productId = $productData['entity_id']; - if ($this->_type != $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE]) { - continue; - } - $linksData['product_ids'][$productId] = true; - $linksData['relation'][] = ['parent_id' => $productId, 'child_id' => $linkedProductId]; - $qty = empty($rowData['_associated_default_qty']) ? 0 : $rowData['_associated_default_qty']; - $pos = empty($rowData['_associated_position']) ? 0 : $rowData['_associated_position']; - - if ($pos) { + if ($this->_type != $rowData[Product::COL_TYPE]) { + continue; + } + $linksData['product_ids'][$productId] = true; + $linksData['relation'][] = ['parent_id' => $productId, 'child_id' => $linkedProductId]; + $qty = empty($associatedSkuAndQty[1]) ? 0 : trim($associatedSkuAndQty[1]); $linksData['attr_product_ids'][$productId] = true; $linksData['position']["{$productId} {$linkedProductId}"] = [ 'product_link_attribute_id' => $attributes['position']['id'], - 'value' => $pos - ]; - } - if ($qty) { - $linksData['attr_product_ids'][$productId] = true; - $linksData['qty']["{$productId} {$linkedProductId}"] = [ - 'product_link_attribute_id' => $attributes['qty']['id'], - 'value' => $qty + 'value' => $position ]; + if ($qty) { + $linksData['attr_product_ids'][$productId] = true; + $linksData['qty']["{$productId} {$linkedProductId}"] = [ + 'product_link_attribute_id' => $attributes['qty']['id'], + 'value' => $qty + ]; + } } } $this->links->saveLinksData($linksData); diff --git a/app/code/Magento/GroupedImportExport/Test/Unit/Model/Import/Product/Type/GroupedTest.php b/app/code/Magento/GroupedImportExport/Test/Unit/Model/Import/Product/Type/GroupedTest.php index e18667c5843ee374e877eb6ccd11c59904823f28..64a39e61c950eca69b3af88c3c94a7a4f5e2c6ed 100644 --- a/app/code/Magento/GroupedImportExport/Test/Unit/Model/Import/Product/Type/GroupedTest.php +++ b/app/code/Magento/GroupedImportExport/Test/Unit/Model/Import/Product/Type/GroupedTest.php @@ -79,7 +79,7 @@ class GroupedTest extends \PHPUnit_Framework_TestCase ); $this->entityModel = $this->getMock( 'Magento\CatalogImportExport\Model\Import\Product', - ['getNewSku', 'getNextBunch', 'isRowAllowedToImport', 'getRowScope'], + ['getNewSku', 'getOldSku', 'getNextBunch', 'isRowAllowedToImport', 'getRowScope'], [], '', false @@ -108,32 +108,121 @@ class GroupedTest extends \PHPUnit_Framework_TestCase ); } - public function testSaveData() + /** + * Test for method saveData() + * + * @param array $skus + * @param array $bunch + * + * @dataProvider testSaveDataProvider + */ + public function testSaveData($skus, $bunch) + { + $this->entityModel->expects($this->once())->method('getNewSku')->will($this->returnValue($skus['newSku'])); + $this->entityModel->expects($this->once())->method('getOldSku')->will($this->returnValue($skus['oldSku'])); + $attributes = ['position' => ['id' => 0], 'qty' => ['id' => 0]]; + $this->links->expects($this->once())->method('getAttributes')->will($this->returnValue($attributes)); + + $this->entityModel->expects($this->at(2))->method('getNextBunch')->will($this->returnValue([$bunch])); + $this->entityModel->expects($this->any())->method('isRowAllowedToImport')->will($this->returnValue(true)); + $this->entityModel->expects($this->any())->method('getRowScope')->will($this->returnValue( + \Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT + )); + + $this->links->expects($this->once())->method('saveLinksData'); + $this->grouped->saveData(); + } + + /** + * Data provider for saveData() + * + * @return array + */ + public function testSaveDataProvider() + { + return [ + [ + 'skus' => [ + 'newSku' => [ + 'sku_assoc1' => ['entity_id' => 1], + 'productSku' => ['entity_id' => 3, 'attr_set_code' => 'Default', 'type_id' => 'grouped'] + ], + 'oldSku' => ['sku_assoc2' => ['entity_id' => 2]] + ], + 'bunch' => [ + 'associated_skus' => 'sku_assoc1=1, sku_assoc2=2', + 'sku' => 'productSku', + 'product_type' => 'grouped' + ] + ], + [ + 'skus' => [ + 'newSku' => [ + 'productSku' => ['entity_id' => 1, 'attr_set_code' => 'Default', 'type_id' => 'grouped'] + ], + 'oldSku' => [] + ], + 'bunch' => [ + 'associated_skus' => '', + 'sku' => 'productSku', + 'product_type' => 'grouped' + ] + ], + [ + 'skus' => ['newSku' => [],'oldSku' => []], + 'bunch' => [ + 'associated_skus' => 'sku_assoc1=1, sku_assoc2=2', + 'sku' => 'productSku', + 'product_type' => 'grouped' + ] + ], + [ + 'skus' => [ + 'newSku' => [ + 'sku_assoc1' => ['entity_id' => 1], + 'productSku' => ['entity_id' => 3, 'attr_set_code' => 'Default', 'type_id' => 'grouped'] + ], + 'oldSku' => [] + ], + 'bunch' => [ + 'associated_skus' => 'sku_assoc1=1', + 'sku' => 'productSku', + 'product_type' => 'simple' + ] + ] + ]; + } + + /** + * Test saveData() with store row scope + */ + public function testSaveDataScopeStore() { - $associatedSku = 'sku_assoc'; - $productSku = 'productSku'; $this->entityModel->expects($this->once())->method('getNewSku')->will($this->returnValue([ - $associatedSku => ['entity_id' => 1], - $productSku => ['entity_id' => 2] + 'sku_assoc1' => ['entity_id' => 1], + 'productSku' => ['entity_id' => 2, 'attr_set_code' => 'Default', 'type_id' => 'grouped'] + ])); + $this->entityModel->expects($this->once())->method('getOldSku')->will($this->returnValue([ + 'sku_assoc2' => ['entity_id' => 3] ])); $attributes = ['position' => ['id' => 0], 'qty' => ['id' => 0]]; $this->links->expects($this->once())->method('getAttributes')->will($this->returnValue($attributes)); $bunch = [[ - '_associated_sku' => $associatedSku, - 'sku' => $productSku, - '_type' => 'grouped', - '_associated_default_qty' => 4, - '_associated_position' => 6 + 'associated_skus' => 'sku_assoc1=1, sku_assoc2=2', + 'sku' => 'productSku', + 'product_type' => 'grouped' ]]; - $this->entityModel->expects($this->at(0))->method('getNextBunch')->will($this->returnValue($bunch)); - $this->entityModel->expects($this->at(1))->method('getNextBunch')->will($this->returnValue($bunch)); + $this->entityModel->expects($this->at(2))->method('getNextBunch')->will($this->returnValue($bunch)); $this->entityModel->expects($this->any())->method('isRowAllowedToImport')->will($this->returnValue(true)); - $this->entityModel->expects($this->any())->method('getRowScope')->will($this->returnValue( + $this->entityModel->expects($this->at(4))->method('getRowScope')->will($this->returnValue( \Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT )); + $this->entityModel->expects($this->at(5))->method('getRowScope')->will($this->returnValue( + \Magento\CatalogImportExport\Model\Import\Product::SCOPE_STORE + )); - $this->links->expects($this->once())->method("saveLinksData"); + $this->links->expects($this->once())->method('saveLinksData'); $this->grouped->saveData(); } } diff --git a/app/code/Magento/GroupedImportExport/composer.json b/app/code/Magento/GroupedImportExport/composer.json index 87c869bbc82156cccb8ee2c213c4851ca263f0f6..d17ec6ec9e8dfa34f60b13a34725d2c7fea5abca 100644 --- a/app/code/Magento/GroupedImportExport/composer.json +++ b/app/code/Magento/GroupedImportExport/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-import-export": "0.74.0-beta10", - "magento/module-catalog-import-export": "0.74.0-beta10", - "magento/module-grouped-product": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-import-export": "0.74.0-beta13", + "magento/module-catalog-import-export": "0.74.0-beta13", + "magento/module-grouped-product": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GroupedProduct/Model/Product/Initialization/Helper/ProductLinks/Plugin/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Initialization/Helper/ProductLinks/Plugin/Grouped.php index 474c903e0df58c3237d796d50cfa7d128f65990f..7aa7ccba11758bf7841dfdd735563b95501cd7a2 100644 --- a/app/code/Magento/GroupedProduct/Model/Product/Initialization/Helper/ProductLinks/Plugin/Grouped.php +++ b/app/code/Magento/GroupedProduct/Model/Product/Initialization/Helper/ProductLinks/Plugin/Grouped.php @@ -5,6 +5,8 @@ */ namespace Magento\GroupedProduct\Model\Product\Initialization\Helper\ProductLinks\Plugin; +use Magento\GroupedProduct\Model\Product\Type\Grouped as TypeGrouped; + class Grouped { /** @@ -22,8 +24,9 @@ class Grouped \Magento\Catalog\Model\Product $product, array $links ) { - if (isset($links['associated']) && !$product->getGroupedReadonly()) { - $product->setGroupedLinkData((array)$links['associated']); + if ($product->getTypeId() == TypeGrouped::TYPE_CODE && !$product->getGroupedReadonly()) { + $links = isset($links['associated']) ? $links['associated'] : $product->getGroupedLinkData(); + $product->setGroupedLinkData((array)$links); } } } diff --git a/app/code/Magento/GroupedProduct/Test/Unit/Model/Product/Initialization/Helper/ProductLinks/Plugin/GroupedTest.php b/app/code/Magento/GroupedProduct/Test/Unit/Model/Product/Initialization/Helper/ProductLinks/Plugin/GroupedTest.php index 97ae5e92e936756064e1d94101565765dc9718bc..985ca564579493494f778b40910bb04f09f29bd6 100644 --- a/app/code/Magento/GroupedProduct/Test/Unit/Model/Product/Initialization/Helper/ProductLinks/Plugin/GroupedTest.php +++ b/app/code/Magento/GroupedProduct/Test/Unit/Model/Product/Initialization/Helper/ProductLinks/Plugin/GroupedTest.php @@ -6,6 +6,8 @@ */ namespace Magento\GroupedProduct\Test\Unit\Model\Product\Initialization\Helper\ProductLinks\Plugin; +use Magento\GroupedProduct\Model\Product\Type\Grouped; +use Magento\Catalog\Model\Product\Type; class GroupedTest extends \PHPUnit_Framework_TestCase { @@ -15,12 +17,12 @@ class GroupedTest extends \PHPUnit_Framework_TestCase protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */ protected $productMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks|\PHPUnit_Framework_MockObject_MockObject */ protected $subjectMock; @@ -28,7 +30,7 @@ class GroupedTest extends \PHPUnit_Framework_TestCase { $this->productMock = $this->getMock( 'Magento\Catalog\Model\Product', - ['getGroupedReadonly', 'setGroupedLinkData', '__wakeup'], + ['getGroupedReadonly', 'setGroupedLinkData', '__wakeup', 'getTypeId'], [], '', false @@ -43,22 +45,49 @@ class GroupedTest extends \PHPUnit_Framework_TestCase $this->model = new \Magento\GroupedProduct\Model\Product\Initialization\Helper\ProductLinks\Plugin\Grouped(); } - public function testBeforeInitializeLinksRequestDoesNotHaveGrouped() + /** + * @dataProvider productTypeDataProvider + */ + public function testBeforeInitializeLinksRequestDoesNotHaveGrouped($productType) { + $this->productMock->expects($this->once())->method('getTypeId')->will($this->returnValue($productType)); $this->productMock->expects($this->never())->method('getGroupedReadonly'); $this->productMock->expects($this->never())->method('setGroupedLinkData'); $this->model->beforeInitializeLinks($this->subjectMock, $this->productMock, []); } - public function testBeforeInitializeLinksRequestHasGrouped() + public function productTypeDataProvider() { + return [ + [Type::TYPE_SIMPLE], + [Type::TYPE_BUNDLE], + [Type::TYPE_VIRTUAL] + ]; + } + + /** + * @dataProvider linksDataProvider + */ + public function testBeforeInitializeLinksRequestHasGrouped($linksData) + { + $this->productMock->expects($this->once())->method('getTypeId')->will($this->returnValue(Grouped::TYPE_CODE)); $this->productMock->expects($this->once())->method('getGroupedReadonly')->will($this->returnValue(false)); - $this->productMock->expects($this->once())->method('setGroupedLinkData')->with(['value']); - $this->model->beforeInitializeLinks($this->subjectMock, $this->productMock, ['associated' => 'value']); + $this->productMock->expects($this->once())->method('setGroupedLinkData')->with($linksData); + $this->model->beforeInitializeLinks($this->subjectMock, $this->productMock, ['associated' => $linksData]); + } + + public function linksDataProvider() + { + return [ + [['associated' => [5 => ['id' => '2', 'qty' => '100', 'position' => '1']]]], + [['associated' => []]], + [[]] + ]; } public function testBeforeInitializeLinksProductIsReadonly() { + $this->productMock->expects($this->once())->method('getTypeId')->will($this->returnValue(Grouped::TYPE_CODE)); $this->productMock->expects($this->once())->method('getGroupedReadonly')->will($this->returnValue(true)); $this->productMock->expects($this->never())->method('setGroupedLinkData'); $this->model->beforeInitializeLinks($this->subjectMock, $this->productMock, ['associated' => 'value']); diff --git a/app/code/Magento/GroupedProduct/composer.json b/app/code/Magento/GroupedProduct/composer.json index 897075edb8c312b7bc8234459e74223b304fc316..d108bccbced3c09fa8991ae13fbf15296e7075f4 100644 --- a/app/code/Magento/GroupedProduct/composer.json +++ b/app/code/Magento/GroupedProduct/composer.json @@ -3,22 +3,22 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/module-msrp": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/module-msrp": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/GroupedProduct/etc/service_data_attributes.xml b/app/code/Magento/GroupedProduct/etc/extension_attributes.xml similarity index 89% rename from app/code/Magento/GroupedProduct/etc/service_data_attributes.xml rename to app/code/Magento/GroupedProduct/etc/extension_attributes.xml index 0618cc9286cfd8ccb0cab46f6a505b05a39c4ee2..cf0d9d57bfabc7609acd4b6fd56cddf602d484a1 100644 --- a/app/code/Magento/GroupedProduct/etc/service_data_attributes.xml +++ b/app/code/Magento/GroupedProduct/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Catalog\Api\Data\ProductLinkInterface"> <attribute code="qty" type="float" /> </extension_attributes> diff --git a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php index b78e802b32e4e4f65fd81cac88aada787699c862..fd6f58306f1f4fecb8ef37e950fcfc17262fc8c8 100644 --- a/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php +++ b/app/code/Magento/ImportExport/Block/Adminhtml/Import/Edit/Form.php @@ -57,6 +57,7 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic * Add fieldsets * * @return $this + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ protected function _prepareForm() { @@ -104,7 +105,34 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic 'label' => __('Import Behavior'), 'required' => true, 'disabled' => true, - 'values' => $this->_behaviorFactory->create($behaviorClass)->toOptionArray() + 'values' => $this->_behaviorFactory->create($behaviorClass)->toOptionArray(), + 'class' => $behaviorCode, + ] + ); + $fieldsets[$behaviorCode]->addField( + $behaviorCode . \Magento\ImportExport\Model\Import::FIELD_FIELD_SEPARATOR, + 'text', + [ + 'name' => \Magento\ImportExport\Model\Import::FIELD_FIELD_SEPARATOR, + 'label' => __('Field separator'), + 'title' => __('Field separator'), + 'required' => true, + 'disabled' => true, + 'class' => $behaviorCode, + 'value' => ',', + ] + ); + $fieldsets[$behaviorCode]->addField( + $behaviorCode . \Magento\ImportExport\Model\Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR, + 'text', + [ + 'name' => \Magento\ImportExport\Model\Import::FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR, + 'label' => __('Multiple value separator'), + 'title' => __('Multiple value separator'), + 'required' => true, + 'disabled' => true, + 'class' => $behaviorCode, + 'value' => ',', ] ); } @@ -125,6 +153,21 @@ class Form extends \Magento\Backend\Block\Widget\Form\Generic 'class' => 'input-file' ] ); + $fieldsets['upload']->addField( + \Magento\ImportExport\Model\Import::FIELD_NAME_IMG_FILE_DIR, + 'text', + [ + 'name' => \Magento\ImportExport\Model\Import::FIELD_NAME_IMG_FILE_DIR, + 'label' => __('Images File Directory'), + 'title' => __('Images File Directory'), + 'required' => false, + 'class' => 'input-text', + 'note' => __( + 'For Type "Local Server" use relative path to Magento installation, + e.g. var/export, var/import, var/export/some/dir' + ), + ] + ); $form->setUseContainer(true); $this->setForm($form); diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Start.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Start.php index dcded711cc100f602bf879833e837002c6a834c6..f8124344e9dfc5873bda193da4b3b88d11c4948e 100644 --- a/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Start.php +++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Start.php @@ -27,6 +27,7 @@ class Start extends ImportController $importModel = $this->_objectManager->create('Magento\ImportExport\Model\Import'); try { + $importModel->setData($data); $importModel->importSource(); $importModel->invalidateIndex(); $resultBlock->addAction('show', 'import_validation_container') diff --git a/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Validate.php b/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Validate.php index 64e267e253b726dd671a2ca6dd0876053e82667c..76e47f3b50e45a9ddccd0cadb530bf0b22534608 100644 --- a/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Validate.php +++ b/app/code/Magento/ImportExport/Controller/Adminhtml/Import/Validate.php @@ -75,7 +75,8 @@ class Validate extends ImportController $source = ImportAdapter::findAdapterFor( $import->uploadSource(), $this->_objectManager->create('Magento\Framework\Filesystem') - ->getDirectoryWrite(DirectoryList::ROOT) + ->getDirectoryWrite(DirectoryList::ROOT), + $data[$import::FIELD_FIELD_SEPARATOR] ); $validationResult = $import->validateSource($source); diff --git a/app/code/Magento/ImportExport/Model/Export.php b/app/code/Magento/ImportExport/Model/Export.php index 227fd2fab3c54d489adb565b8fd1187a01fee832..b445d0239e0a99a1694039dfd88a0284b7909a65 100644 --- a/app/code/Magento/ImportExport/Model/Export.php +++ b/app/code/Magento/ImportExport/Model/Export.php @@ -12,6 +12,7 @@ namespace Magento\ImportExport\Model; * Export model * * @author Magento Core Team <core@magentocommerce.com> + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Export extends \Magento\ImportExport\Model\AbstractModel { @@ -213,16 +214,44 @@ class Export extends \Magento\ImportExport\Model\AbstractModel return self::FILTER_TYPE_DATE; } elseif ('decimal' == $attribute->getBackendType() || 'int' == $attribute->getBackendType()) { return self::FILTER_TYPE_NUMBER; - } elseif ($attribute->isStatic() || - 'varchar' == $attribute->getBackendType() || - 'text' == $attribute->getBackendType() - ) { + } elseif ('varchar' == $attribute->getBackendType() || 'text' == $attribute->getBackendType()) { return self::FILTER_TYPE_INPUT; + } elseif ($attribute->isStatic()) { + return self::getStaticAttributeFilterType($attribute); } else { throw new \Magento\Framework\Exception\LocalizedException(__('Cannot determine attribute filter type')); } } + /** + * Determine filter type for static attribute. + * + * @static + * @param \Magento\Eav\Model\Entity\Attribute $attribute + * @return string + */ + public static function getStaticAttributeFilterType(\Magento\Eav\Model\Entity\Attribute $attribute) + { + if ($attribute->getAttributeCode() == 'category_ids') { + return self::FILTER_TYPE_INPUT; + } + $columns = $attribute->getFlatColumns(); + switch ($columns[$attribute->getAttributeCode()]['type']) { + case \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER: + case \Magento\Framework\DB\Ddl\Table::TYPE_BIGINT: + $type = self::FILTER_TYPE_NUMBER; + break; + case \Magento\Framework\DB\Ddl\Table::TYPE_DATE: + case \Magento\Framework\DB\Ddl\Table::TYPE_DATETIME: + case \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP: + $type = self::FILTER_TYPE_DATE; + break; + default: + $type = self::FILTER_TYPE_INPUT; + } + return $type; + } + /** * MIME-type for 'Content-Type' header. * diff --git a/app/code/Magento/ImportExport/Model/Export/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Export/AbstractEntity.php index 5c9932f95d3c5af590a906cf01950478c8cbc716..643d3aa3ab938b2d42f7a3e62bbee331dc9c4c35 100644 --- a/app/code/Magento/ImportExport/Model/Export/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Export/AbstractEntity.php @@ -286,10 +286,10 @@ abstract class AbstractEntity /** * Iterate through given collection page by page and export items * - * @param \Magento\Framework\Data\Collection\Db $collection + * @param \Magento\Framework\Data\Collection\AbstractDb $collection * @return void */ - protected function _exportCollectionByPages(\Magento\Framework\Data\Collection\Db $collection) + protected function _exportCollectionByPages(\Magento\Framework\Data\Collection\AbstractDb $collection) { $this->_byPagesIterator->iterate($collection, $this->_pageSize, [[$this, 'exportItem']]); } @@ -344,7 +344,7 @@ abstract class AbstractEntity /** * Get entity collection * - * @return \Magento\Framework\Data\Collection\Db + * @return \Magento\Framework\Data\Collection\AbstractDb */ abstract protected function _getEntityCollection(); diff --git a/app/code/Magento/ImportExport/Model/Export/Entity/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Export/Entity/AbstractEntity.php index c9581ad7e7471d57896b42c72676edbf430324da..1cbca0d192b6f0297b975540842476ad9712642b 100644 --- a/app/code/Magento/ImportExport/Model/Export/Entity/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Export/Entity/AbstractEntity.php @@ -191,7 +191,7 @@ abstract class AbstractEntity * Get entity collection * * @param bool $resetCollection - * @return \Magento\Framework\Data\Collection\Db + * @return \Magento\Framework\Data\Collection\AbstractDb */ abstract protected function _getEntityCollection($resetCollection = false); diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php index 54c06276c1bb05692050265339c34a9c401f2705..eaea84beddeb0612ea8db14d071aed9cc782d75b 100644 --- a/app/code/Magento/ImportExport/Model/Import.php +++ b/app/code/Magento/ImportExport/Model/Import.php @@ -40,10 +40,32 @@ class Import extends \Magento\ImportExport\Model\AbstractModel /**#@+ * Form field names (and IDs) */ + + /** + * Import source file. + */ const FIELD_NAME_SOURCE_FILE = 'import_file'; + /** + * Import image archive. + */ const FIELD_NAME_IMG_ARCHIVE_FILE = 'import_image_archive'; + /** + * Import images file directory. + */ + const FIELD_NAME_IMG_FILE_DIR = 'import_images_file_dir'; + + /** + * Import field separator. + */ + const FIELD_FIELD_SEPARATOR = '_import_field_separator'; + + /** + * Import multiple value separator. + */ + const FIELD_FIELD_MULTIPLE_VALUE_SEPARATOR = '_import_multiple_value_separator'; + /**#@-*/ /**#@+ @@ -213,7 +235,8 @@ class Import extends \Magento\ImportExport\Model\AbstractModel { return \Magento\ImportExport\Model\Import\Adapter::findAdapterFor( $sourceFile, - $this->_filesystem->getDirectoryWrite(DirectoryList::ROOT) + $this->_filesystem->getDirectoryWrite(DirectoryList::ROOT), + $this->getData(self::FIELD_FIELD_SEPARATOR) ); } @@ -410,12 +433,8 @@ class Import extends \Magento\ImportExport\Model\AbstractModel */ public function importSource() { - $this->setData( - [ - 'entity' => $this->getDataSourceModel()->getEntityTypeCode(), - 'behavior' => $this->getDataSourceModel()->getBehavior(), - ] - ); + $this->setData('entity', $this->getDataSourceModel()->getEntityTypeCode()); + $this->setData('behavior', $this->getDataSourceModel()->getBehavior()); $this->addLogComment(__('Begin import of "%1" with "%2" behavior', $this->getEntity(), $this->getBehavior())); diff --git a/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php index 5a21fd560d5d49f6ca4e8d4d2b02b4e3ca19e7f3..e512c99ce330200b703b69e1e82a05b370f5e920 100644 --- a/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php @@ -710,6 +710,7 @@ abstract class AbstractEntity * * @return $this * @throws \Magento\Framework\Exception\LocalizedException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function validateData() { diff --git a/app/code/Magento/ImportExport/Model/Import/Adapter.php b/app/code/Magento/ImportExport/Model/Import/Adapter.php index d6211b013ef480eb3465818e88656ec742f8562f..3b364f6daea8af9809b7ec3647c50065d873a5d6 100644 --- a/app/code/Magento/ImportExport/Model/Import/Adapter.php +++ b/app/code/Magento/ImportExport/Model/Import/Adapter.php @@ -19,11 +19,14 @@ class Adapter * * @param string $type Adapter type ('csv', 'xml' etc.) * @param Write $directory + * @param string $source * @param mixed $options OPTIONAL Adapter constructor options + * * @return AbstractSource + * * @throws \Magento\Framework\Exception\LocalizedException */ - public static function factory($type, $directory, $options = null) + public static function factory($type, $directory, $source, $options = null) { if (!is_string($type) || !$type) { throw new \Magento\Framework\Exception\LocalizedException( @@ -37,7 +40,7 @@ class Adapter __('\'%1\' file extension is not supported', $type) ); } - $adapter = new $adapterClass($options, $directory); + $adapter = new $adapterClass($source, $directory, $options); if (!$adapter instanceof AbstractSource) { throw new \Magento\Framework\Exception\LocalizedException( @@ -52,10 +55,12 @@ class Adapter * * @param string $source Source file path. * @param Write $directory + * @param mixed $options OPTIONAL Adapter constructor options + * * @return AbstractSource */ - public static function findAdapterFor($source, $directory) + public static function findAdapterFor($source, $directory, $options = null) { - return self::factory(pathinfo($source, PATHINFO_EXTENSION), $directory, $source); + return self::factory(pathinfo($source, PATHINFO_EXTENSION), $directory, $source, $options); } } diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php index e690fb3e07636ccefbf914fcd55514112baacd2c..2d74a95768d34fc9189dbdf2109b6cb1408b20d6 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php @@ -6,6 +6,7 @@ namespace Magento\ImportExport\Model\Import\Entity; use Magento\ImportExport\Model\Import\AbstractSource; +use Magento\ImportExport\Model\Import as ImportExport; /** * Import entity abstract model @@ -697,6 +698,7 @@ abstract class AbstractEntity * * @return $this * @throws \Magento\Framework\Exception\LocalizedException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function validateData() { @@ -708,30 +710,32 @@ abstract class AbstractEntity ); } - // check attribute columns names validity - $columnNumber = 0; - $emptyHeaderColumns = []; - $invalidColumns = []; - foreach ($this->getSource()->getColNames() as $columnName) { - $columnNumber++; - if (!$this->isAttributeParticular($columnName)) { - if (trim($columnName) == '') { - $emptyHeaderColumns[] = $columnNumber; - } elseif (!preg_match('/^[a-z][a-z0-9_]*$/', $columnName)) { - $invalidColumns[] = $columnName; + if (ImportExport::BEHAVIOR_DELETE != $this->getBehavior()) { + // check attribute columns names validity + $columnNumber = 0; + $emptyHeaderColumns = []; + $invalidColumns = []; + foreach ($this->getSource()->getColNames() as $columnName) { + $columnNumber++; + if (!$this->isAttributeParticular($columnName)) { + if (trim($columnName) == '') { + $emptyHeaderColumns[] = $columnNumber; + } elseif (!preg_match('/^[a-z][a-z0-9_]*$/', $columnName)) { + $invalidColumns[] = $columnName; + } } } - } - if ($emptyHeaderColumns) { - throw new \Magento\Framework\Exception\LocalizedException( - __('Columns number: "%1" have empty headers', implode('", "', $emptyHeaderColumns)) - ); - } - if ($invalidColumns) { - throw new \Magento\Framework\Exception\LocalizedException( - __('Column names: "%1" are invalid', implode('", "', $invalidColumns)) - ); + if ($emptyHeaderColumns) { + throw new \Magento\Framework\Exception\LocalizedException( + __('Columns number: "%1" have empty headers', implode('", "', $emptyHeaderColumns)) + ); + } + if ($invalidColumns) { + throw new \Magento\Framework\Exception\LocalizedException( + __('Column names: "%1" are invalid', implode('", "', $invalidColumns)) + ); + } } // initialize validation related attributes diff --git a/app/code/Magento/ImportExport/Model/Import/Source/Csv.php b/app/code/Magento/ImportExport/Model/Import/Source/Csv.php index 386f4aea620f1bbf7b80bf0b236725958e502337..faf10f18e324a1017fcfd07561bcbf1a1fc0772c 100644 --- a/app/code/Magento/ImportExport/Model/Import/Source/Csv.php +++ b/app/code/Magento/ImportExport/Model/Import/Source/Csv.php @@ -16,9 +16,11 @@ class Csv extends \Magento\ImportExport\Model\Import\AbstractSource protected $_file; /** + * Delimiter. + * * @var string */ - protected $_delimiter = ''; + protected $_delimiter = ','; /** * @var string @@ -47,7 +49,9 @@ class Csv extends \Magento\ImportExport\Model\Import\AbstractSource } catch (\Magento\Framework\Exception\FileSystemException $e) { throw new \LogicException("Unable to open file: '{$file}'"); } - $this->_delimiter = $delimiter; + if ($delimiter) { + $this->_delimiter = $delimiter; + } $this->_enclosure = $enclosure; parent::__construct($this->_getNextRow()); } diff --git a/app/code/Magento/ImportExport/Model/Import/Source/Zip.php b/app/code/Magento/ImportExport/Model/Import/Source/Zip.php new file mode 100644 index 0000000000000000000000000000000000000000..ee8b22cf8e892f00bfe57832b1350ca89e5c60d6 --- /dev/null +++ b/app/code/Magento/ImportExport/Model/Import/Source/Zip.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\ImportExport\Model\Import\Source; + +/** + * Zip import adapter. + */ +class Zip extends Csv +{ + /** + * @param string $file + * @param \Magento\Framework\Filesystem\Directory\Write $directory + * @param string $options + */ + public function __construct( + $file, + \Magento\Framework\Filesystem\Directory\Write $directory, + $options + ) { + $zip = new \Magento\Framework\Archive\Zip(); + $file = $zip->unpack( + $directory->getRelativePath($file), + $directory->getRelativePath(preg_replace('/\.zip$/i', '.csv', $file)) + ); + parent::__construct($file, $directory, $options); + } +} diff --git a/app/code/Magento/ImportExport/Model/Resource/CollectionByPagesIterator.php b/app/code/Magento/ImportExport/Model/Resource/CollectionByPagesIterator.php index f77c8e1cd3a4890de6a6f4f10d0a3f95001ee0b3..2c8ddbd285038133cf8f45ecf3e70978141a0b3c 100644 --- a/app/code/Magento/ImportExport/Model/Resource/CollectionByPagesIterator.php +++ b/app/code/Magento/ImportExport/Model/Resource/CollectionByPagesIterator.php @@ -15,14 +15,14 @@ class CollectionByPagesIterator /** * Load collection page by page and apply callbacks to each collection item * - * @param \Magento\Framework\Data\Collection\Db $collection Collection to load page by page + * @param \Magento\Framework\Data\Collection\AbstractDb $collection Collection to load page by page * @param int $pageSize Number of items to fetch from db in one query * @param array $callbacks Array of callbacks which should be applied to each collection item * @return void */ - public function iterate(\Magento\Framework\Data\Collection\Db $collection, $pageSize, array $callbacks) + public function iterate(\Magento\Framework\Data\Collection\AbstractDb $collection, $pageSize, array $callbacks) { - /** @var $paginatedCollection \Magento\Framework\Data\Collection\Db */ + /** @var $paginatedCollection \Magento\Framework\Data\Collection\AbstractDb */ $paginatedCollection = null; $pageNumber = 1; do { diff --git a/app/code/Magento/ImportExport/Model/Source/Import/Behavior/Basic.php b/app/code/Magento/ImportExport/Model/Source/Import/Behavior/Basic.php index a001a2e10ba64b5ee7c0cb7651d4bf75b186b9f5..08af104c52914eb6a5ecb3d2aeede1f5b227eed5 100644 --- a/app/code/Magento/ImportExport/Model/Source/Import/Behavior/Basic.php +++ b/app/code/Magento/ImportExport/Model/Source/Import/Behavior/Basic.php @@ -16,7 +16,7 @@ class Basic extends \Magento\ImportExport\Model\Source\Import\AbstractBehavior public function toArray() { return [ - \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND => __('Append Complex Data'), + \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND => __('Add/Update'), \Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE => __('Replace Existing Complex Data'), \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE => __('Delete Entities') ]; diff --git a/app/code/Magento/ImportExport/Test/Unit/Block/Adminhtml/Import/Edit/FormTest.php b/app/code/Magento/ImportExport/Test/Unit/Block/Adminhtml/Import/Edit/FormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cdafbd029a2fdf11b3599c63ba712586d5c63090 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Unit/Block/Adminhtml/Import/Edit/FormTest.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ImportExport\Test\Unit\Block\Adminhtml\Import\Edit; + +class FormTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Basic import model + * + * @var \Magento\ImportExport\Model\Import|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_importModel; + + /** + * @var \Magento\ImportExport\Model\Source\Import\EntityFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_entityFactory; + + /** + * @var \Magento\ImportExport\Model\Source\Import\Behavior\Factory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_behaviorFactory; + + /** + * @var \Magento\ImportExport\Block\Adminhtml\Import\Edit\Form|\PHPUnit_Framework_MockObject_MockObject + */ + protected $form; + + public function setUp() + { + $context = $this->getMockBuilder('\Magento\Backend\Block\Template\Context') + ->disableOriginalConstructor() + ->getMock(); + $registry = $this->getMockBuilder('\Magento\Framework\Registry') + ->disableOriginalConstructor() + ->getMock(); + $formFactory = $this->getMockBuilder('\Magento\Framework\Data\FormFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->_importModel = $this->getMockBuilder('\Magento\ImportExport\Model\Import') + ->disableOriginalConstructor() + ->getMock(); + $this->_entityFactory = $this->getMockBuilder('\Magento\ImportExport\Model\Source\Import\EntityFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->_behaviorFactory = $this->getMockBuilder('\Magento\ImportExport\Model\Source\Import\Behavior\Factory') + ->disableOriginalConstructor() + ->getMock(); + + $this->form = $this->getMockBuilder('\Magento\ImportExport\Block\Adminhtml\Import\Edit\Form') + ->setConstructorArgs([ + $context, + $registry, + $formFactory, + $this->_importModel, + $this->_entityFactory, + $this->_behaviorFactory, + ]) + ->getMock(); + } + + /** + * Test for protected method prepareForm() + * + * @todo to implement it. + */ + public function testPrepareForm() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } +} diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/AdapterTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/Import/AdapterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a3f3767b727f18874226d6513f433aa829c67e50 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/AdapterTest.php @@ -0,0 +1,37 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\ImportExport\Test\Unit\Model\Import; + +use Magento\ImportExport\Model\Import\Adapter as Adapter; + +class AdapterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Adapter|\PHPUnit_Framework_MockObject_MockObject + */ + protected $adapter; + + public function setUp() + { + $this->adapter = $this->getMock( + '\Magento\ImportExport\Model\Import\Adapter', + [], + [], + '', + false + ); + } + + public function testFactory() + { + $this->markTestSkipped('Skipped because factory method has static modifier'); + } + + public function testFindAdapterFor() + { + $this->markTestSkipped('Skipped because findAdapterFor method has static modifier'); + } +} diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Entity/AbstractTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Entity/AbstractTest.php index 915632e86021748869ee024f05cf1e6e1da9026e..91cc1444acbcf6c6fef0cefbf304c29678c1a512 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Entity/AbstractTest.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Entity/AbstractTest.php @@ -77,6 +77,30 @@ class AbstractTest extends \PHPUnit_Framework_TestCase $this->_model->validateData(); } + /** + * Test for method validateData() for delete behaviour + * + * @covers \Magento\ImportExport\Model\Import\AbstractEntity::validateData + */ + public function testValidateDataEmptyColumnNameForDeleteBehaviour() + { + $this->_createSourceAdapterMock(['']); + $this->_model->setParameters(['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE]); + $this->_model->validateData(); + } + + /** + * Test for method validateData() for delete behaviour + * + * @covers \Magento\ImportExport\Model\Import\Entity\AbstractEntity::validateData + */ + public function testValidateDataColumnNameWithWhitespacesForDeleteBehaviour() + { + $this->_createSourceAdapterMock([' ']); + $this->_model->setParameters(['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE]); + $this->_model->validateData(); + } + /** * Test for method validateData() * diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Import/Source/ZipTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Source/ZipTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bc92564b228e06d04005e9e64558c85f90858a10 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Import/Source/ZipTest.php @@ -0,0 +1,103 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ImportExport\Test\Unit\Model\Import\Source; + +class ZipTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\Filesystem\Directory\Write|\PHPUnit_Framework_MockObject_MockObject + */ + protected $directory; + + /** + * @var \Magento\ImportExport\Model\Import\Source\Zip|\PHPUnit_Framework_MockObject_MockObject + */ + protected $zip; + + public function setUp() + { + $this->directory = $this->getMockBuilder('\Magento\Framework\Filesystem\Directory\Write') + ->disableOriginalConstructor() + ->setMethods(['getRelativePath']) + ->getMock(); + } + + public function testConstructorInternalCalls() + { + $this->directory->expects($this->any())->method('getRelativePath'); + $fileName = 'test_file'; + $this->_invokeConstructor($fileName); + } + + /** + * Test destination argument for the second getRelativePath after preg_replace. + * + * @depends testConstructorInternalCalls + * @dataProvider constructorFileDestinationMatchDataProvider + */ + public function testConstructorFileDestinationMatch($fileName, $expectedfileName) + { + $this->directory->expects($this->at(0))->method('getRelativePath')->with($fileName); + $this->directory->expects($this->at(1))->method('getRelativePath')->with($expectedfileName); + $this->_invokeConstructor($fileName); + } + + public function constructorFileDestinationMatchDataProvider() + { + return [ + [ + '$fileName' => 'test_file.txt', + '$expectedfileName' => 'test_file.txt', + ], + [ + '$fileName' => 'test_file.zip', + '$expectedfileName' => 'test_file.csv', + ], + [ + '$fileName' => '.ziptest_.zip.file.zip.ZIP', + '$expectedfileName' => '.ziptest_.zip.file.zip.csv', + ] + ]; + } + + /** + * Instantiate zip mock and invoke its constructor. + * + * @param string $fileName + */ + protected function _invokeConstructor($fileName) + { + try { + $this->zip = $this->getMockBuilder( + '\Magento\ImportExport\Model\Import\Source\Zip' + ) + ->setConstructorArgs( + [ + $fileName, + $this->directory, + [], + ] + ) + ->getMock(); + + $reflectedClass = new \ReflectionClass( + '\Magento\ImportExport\Model\Import\Source\Zip' + ); + $constructor = $reflectedClass->getConstructor(); + $constructor->invoke( + $this->zip, + [ + $fileName, + $this->directory, + [], + ] + ); + } catch (\PHPUnit_Framework_Error $e) { + // Suppress any errors due to no control of Zip object dependency instantiation. + } + } +} diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2b46e0799adaa68d7094c15c186fcd17581845d9 --- /dev/null +++ b/app/code/Magento/ImportExport/Test/Unit/Model/ImportTest.php @@ -0,0 +1,334 @@ +<?php + +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ImportExport\Test\Unit\Model; + +/** + * Class ImportTest + * @package Magento\ImportExport\Test\Unit\Model + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ImportTest extends \PHPUnit_Framework_TestCase +{ + + /** + * Entity adapter. + * + * @var \Magento\ImportExport\Model\Import\Entity\AbstractEntity|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_entityAdapter; + + /** + * Import export data + * + * @var \Magento\ImportExport\Helper\Data|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_importExportData = null; + + /** + * @var \Magento\ImportExport\Model\Import\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_importConfig; + + /** + * @var \Magento\ImportExport\Model\Import\Entity\Factory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_entityFactory; + + /** + * @var \Magento\ImportExport\Model\Resource\Import\Data|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_importData; + + /** + * @var \Magento\ImportExport\Model\Export\Adapter\CsvFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_csvFactory; + + /** + * @var \Magento\Framework\HTTP\Adapter\FileTransferFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_httpFactory; + + /** + * @var \Magento\MediaStorage\Model\File\UploaderFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_uploaderFactory; + + /** + * @var \Magento\Indexer\Model\IndexerRegistry|\PHPUnit_Framework_MockObject_MockObject + */ + protected $indexerRegistry; + + /** + * @var \Magento\ImportExport\Model\Source\Import\Behavior\Factory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_behaviorFactory; + + /** + * @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_filesystem; + + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $_coreConfig; + + /** + * @var \Magento\ImportExport\Model\Import|\PHPUnit_Framework_MockObject_MockObject + */ + protected $import; + + public function setUp() + { + $logger = $this->getMockBuilder('\Psr\Log\LoggerInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->_filesystem = $this->getMockBuilder('\Magento\Framework\Filesystem') + ->disableOriginalConstructor() + ->getMock(); + $this->_importExportData = $this->getMockBuilder('\Magento\ImportExport\Helper\Data') + ->disableOriginalConstructor() + ->getMock(); + $this->_coreConfig = $this->getMockBuilder('\Magento\Framework\App\Config\ScopeConfigInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->_importConfig = $this->getMockBuilder('\Magento\ImportExport\Model\Import\ConfigInterface') + ->disableOriginalConstructor() + ->setMethods(['getEntityTypeCode', 'getBehavior']) + ->getMockForAbstractClass(); + $this->_entityFactory = $this->getMockBuilder('\Magento\ImportExport\Model\Import\Entity\Factory') + ->disableOriginalConstructor() + ->getMock(); + $this->_importData = $this->getMockBuilder('\Magento\ImportExport\Model\Resource\Import\Data') + ->disableOriginalConstructor() + ->getMock(); + $this->_csvFactory = $this->getMockBuilder('\Magento\ImportExport\Model\Export\Adapter\CsvFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->_httpFactory = $this->getMockBuilder('\Magento\Framework\HTTP\Adapter\FileTransferFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->_uploaderFactory = $this->getMockBuilder('\Magento\MediaStorage\Model\File\UploaderFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->_behaviorFactory = $this->getMockBuilder('\Magento\ImportExport\Model\Source\Import\Behavior\Factory') + ->disableOriginalConstructor() + ->getMock(); + $this->indexerRegistry = $this->getMockBuilder('\Magento\Indexer\Model\IndexerRegistry') + ->disableOriginalConstructor() + ->getMock(); + + $this->import = $this->getMockBuilder('\Magento\ImportExport\Model\Import') + ->setConstructorArgs([ + $logger, + $this->_filesystem, + $this->_importExportData, + $this->_coreConfig, + $this->_importConfig, + $this->_entityFactory, + $this->_importData, + $this->_csvFactory, + $this->_httpFactory, + $this->_uploaderFactory, + $this->_behaviorFactory, + $this->indexerRegistry, + ]) + ->setMethods([ + 'getDataSourceModel', + '_getEntityAdapter', + 'setData', + 'getProcessedEntitiesCount', + 'getProcessedRowsCount', + 'getInvalidRowsCount', + 'getErrorsCount', + 'getEntity', + 'getBehavior', + ]) + ->getMock(); + + $this->_entityAdapter = $this->getMockBuilder('\Magento\ImportExport\Model\Import\Entity\AbstractEntity') + ->disableOriginalConstructor() + ->setMethods(['importData']) + ->getMockForAbstractClass(); + + } + + public function testImportSource() + { + $entityTypeCode = 'code'; + $this->_importData->expects($this->any()) + ->method('getEntityTypeCode') + ->will($this->returnValue($entityTypeCode)); + $behaviour = 'behaviour'; + $this->_importData->expects($this->once()) + ->method('getBehavior') + ->will($this->returnValue($behaviour)); + $this->import->expects($this->any()) + ->method('getDataSourceModel') + ->will($this->returnValue($this->_importData)); + + $this->import->expects($this->any())->method('setData')->withConsecutive( + ['entity', $entityTypeCode], + ['behavior', $behaviour] + ); + $phraseClass = '\Magento\Framework\Phrase'; + $this->import->expects($this->any()) + ->method('addLogComment') + ->with($this->isInstanceOf($phraseClass)); + $this->_entityAdapter->expects($this->once()) + ->method('importData') + ->will($this->returnSelf()); + $this->import->expects($this->once()) + ->method('_getEntityAdapter') + ->will($this->returnValue($this->_entityAdapter)); + + $importOnceMethodsReturnNull = [ + 'getEntity', + 'getBehavior', + 'getProcessedRowsCount', + 'getProcessedEntitiesCount', + 'getInvalidRowsCount', + 'getErrorsCount', + ]; + + foreach ($importOnceMethodsReturnNull as $method) { + $this->import->expects($this->once())->method($method)->will($this->returnValue(null)); + } + + $this->import->importSource(); + } + + /** + * @todo to implement it. + */ + public function testGetOperationResultMessages() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testGetAttributeType() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testGetEntity() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testGetErrorsCount() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testGetErrorsLimit() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testGetInvalidRowsCount() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testGetNotices() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testGetProcessedEntitiesCount() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testGetProcessedRowsCount() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testGetWorkingDir() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testIsImportAllowed() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testUploadSource() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testValidateSource() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testInvalidateIndex() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testGetEntityBehaviors() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } + + /** + * @todo to implement it. + */ + public function testGetUniqueEntityBehaviors() + { + $this->markTestIncomplete('This test has not been implemented yet.'); + } +} diff --git a/app/code/Magento/ImportExport/Test/Unit/Model/Resource/CollectionByPagesIteratorTest.php b/app/code/Magento/ImportExport/Test/Unit/Model/Resource/CollectionByPagesIteratorTest.php index a39d5b55bd0e14bc709046e19d478765d87df42a..4c8c2f1ee80dcabab31bf31a5e867d1fc963814c 100644 --- a/app/code/Magento/ImportExport/Test/Unit/Model/Resource/CollectionByPagesIteratorTest.php +++ b/app/code/Magento/ImportExport/Test/Unit/Model/Resource/CollectionByPagesIteratorTest.php @@ -3,12 +3,13 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ +namespace Magento\ImportExport\Test\Unit\Model\Resource; + +use \Magento\Framework\Data\Collection\AbstractDb; /** * Test class for \Magento\ImportExport\Model\Resource\CollectionByPagesIterator */ -namespace Magento\ImportExport\Test\Unit\Model\Resource; - class CollectionByPagesIteratorTest extends \PHPUnit_Framework_TestCase { /** @@ -44,12 +45,11 @@ class CollectionByPagesIteratorTest extends \PHPUnit_Framework_TestCase $entityFactory = $this->getMock('Magento\Framework\Data\Collection\EntityFactory', [], [], '', false); $logger = $this->getMock('Psr\Log\LoggerInterface'); - /** @var $collectionMock \Magento\Framework\Data\Collection\Db|\PHPUnit_Framework_MockObject_MockObject */ - $collectionMock = $this->getMock( - 'Magento\Framework\Data\Collection\Db', - ['clear', 'setPageSize', 'setCurPage', 'count', 'getLastPageNumber', 'getSelect'], - [$entityFactory, $logger, $fetchStrategy] - ); + /** @var $collectionMock AbstractDb|\PHPUnit_Framework_MockObject_MockObject */ + $collectionMock = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->setConstructorArgs([$entityFactory, $logger, $fetchStrategy]) + ->setMethods(['clear', 'setPageSize', 'setCurPage', 'count', 'getLastPageNumber', 'getSelect']) + ->getMockForAbstractClass(); $collectionMock->expects($this->any())->method('getSelect')->will($this->returnValue($select)); diff --git a/app/code/Magento/ImportExport/composer.json b/app/code/Magento/ImportExport/composer.json index 794c3924537940519437eedd84ec1e45a3c3226f..e7cbb957d07e0c2be37df045848e2ba04994930c 100644 --- a/app/code/Magento/ImportExport/composer.json +++ b/app/code/Magento/ImportExport/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-indexer": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-indexer": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "ext-ctype": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/ImportExport/i18n/de_DE.csv b/app/code/Magento/ImportExport/i18n/de_DE.csv index 461247982b4b1e8019e18cb7a6dd49bb76222568..9a86f78898167ad3aca1a4427da80abf19bca894 100644 --- a/app/code/Magento/ImportExport/i18n/de_DE.csv +++ b/app/code/Magento/ImportExport/i18n/de_DE.csv @@ -79,7 +79,11 @@ Import/Export,Import/Export "Please specify a source.","Please specify a source." "Cannot get autoincrement value","Cannot get autoincrement value" "Error in data structure: %1 values are mixed","Error in data structure: %1 values are mixed" -"Append Complex Data","Append Complex Data" +"Add/Update","Add/Update" +"Field separator","Field separator" +"Multiple value separator","Multiple value separator" +"Images File Directory","Images File Directory" +"For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir","For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir" "Replace Existing Complex Data","Replace Existing Complex Data" "Delete Entities","Delete Entities" "Add/Update Complex Data","Add/Update Complex Data" diff --git a/app/code/Magento/ImportExport/i18n/en_US.csv b/app/code/Magento/ImportExport/i18n/en_US.csv index e30360177816976b7747ee3761c3aad87a1d1b3a..727046f58ac8128f06380edba23fefc1626727ca 100644 --- a/app/code/Magento/ImportExport/i18n/en_US.csv +++ b/app/code/Magento/ImportExport/i18n/en_US.csv @@ -79,7 +79,11 @@ Import/Export,Import/Export "Please specify a source.","Please specify a source." "Cannot get autoincrement value","Cannot get autoincrement value" "Error in data structure: %1 values are mixed","Error in data structure: %1 values are mixed" -"Append Complex Data","Append Complex Data" +"Add/Update","Add/Update" +"Field separator","Field separator" +"Multiple value separator","Multiple value separator" +"Images File Directory","Images File Directory" +"For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir","For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir" "Replace Existing Complex Data","Replace Existing Complex Data" "Delete Entities","Delete Entities" "Add/Update Complex Data","Add/Update Complex Data" diff --git a/app/code/Magento/ImportExport/i18n/es_ES.csv b/app/code/Magento/ImportExport/i18n/es_ES.csv index 17ea3c0d24ab67eefce3ca594e11c9b04908b44d..7ad44414b61b0a2ff35f85846dd04869a0d60799 100644 --- a/app/code/Magento/ImportExport/i18n/es_ES.csv +++ b/app/code/Magento/ImportExport/i18n/es_ES.csv @@ -79,7 +79,11 @@ Import/Export,Importar/Exportar "Please specify a source.","Please specify a source." "Cannot get autoincrement value","Cannot get autoincrement value" "Error in data structure: %1 values are mixed","Error in data structure: %1 values are mixed" -"Append Complex Data","Append Complex Data" +"Add/Update","Add/Update" +"Field separator","Field separator" +"Multiple value separator","Multiple value separator" +"Images File Directory","Images File Directory" +"For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir","For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir" "Replace Existing Complex Data","Replace Existing Complex Data" "Delete Entities","Delete Entities" "Add/Update Complex Data","Add/Update Complex Data" diff --git a/app/code/Magento/ImportExport/i18n/fr_FR.csv b/app/code/Magento/ImportExport/i18n/fr_FR.csv index d23749c9eea903b478bc3956b6d93c655bb80f9b..fa3f5d0a723720f53042db14fa3411e337771778 100644 --- a/app/code/Magento/ImportExport/i18n/fr_FR.csv +++ b/app/code/Magento/ImportExport/i18n/fr_FR.csv @@ -79,7 +79,11 @@ Import/Export,"Importer / Exporter" "Please specify a source.","Please specify a source." "Cannot get autoincrement value","Cannot get autoincrement value" "Error in data structure: %1 values are mixed","Error in data structure: %1 values are mixed" -"Append Complex Data","Append Complex Data" +"Add/Update","Add/Update" +"Field separator","Field separator" +"Multiple value separator","Multiple value separator" +"Images File Directory","Images File Directory" +"For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir","For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir" "Replace Existing Complex Data","Replace Existing Complex Data" "Delete Entities","Delete Entities" "Add/Update Complex Data","Add/Update Complex Data" diff --git a/app/code/Magento/ImportExport/i18n/nl_NL.csv b/app/code/Magento/ImportExport/i18n/nl_NL.csv index 9c4ea12ab2505a50e2633e6fed66c776fa51a0f3..900f14c5ae73a53330208348dd9d05edd4a19d17 100644 --- a/app/code/Magento/ImportExport/i18n/nl_NL.csv +++ b/app/code/Magento/ImportExport/i18n/nl_NL.csv @@ -79,7 +79,11 @@ Import/Export,Import/Export "Please specify a source.","Please specify a source." "Cannot get autoincrement value","Cannot get autoincrement value" "Error in data structure: %1 values are mixed","Error in data structure: %1 values are mixed" -"Append Complex Data","Append Complex Data" +"Add/Update","Add/Update" +"Field separator","Field separator" +"Multiple value separator","Multiple value separator" +"Images File Directory","Images File Directory" +"For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir","For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir" "Replace Existing Complex Data","Replace Existing Complex Data" "Delete Entities","Delete Entities" "Add/Update Complex Data","Add/Update Complex Data" diff --git a/app/code/Magento/ImportExport/i18n/pt_BR.csv b/app/code/Magento/ImportExport/i18n/pt_BR.csv index 9df23544ea03d2b712e9f69b2c5aac2b09ad39be..d05faf9f0d311142e076fb2b20f3ad05de7e2be4 100644 --- a/app/code/Magento/ImportExport/i18n/pt_BR.csv +++ b/app/code/Magento/ImportExport/i18n/pt_BR.csv @@ -79,7 +79,11 @@ Import/Export,Importação/Exportação "Please specify a source.","Please specify a source." "Cannot get autoincrement value","Cannot get autoincrement value" "Error in data structure: %1 values are mixed","Error in data structure: %1 values are mixed" -"Append Complex Data","Append Complex Data" +"Add/Update","Add/Update" +"Field separator","Field separator" +"Multiple value separator","Multiple value separator" +"Images File Directory","Images File Directory" +"For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir","For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir" "Replace Existing Complex Data","Replace Existing Complex Data" "Delete Entities","Delete Entities" "Add/Update Complex Data","Add/Update Complex Data" diff --git a/app/code/Magento/ImportExport/i18n/zh_CN.csv b/app/code/Magento/ImportExport/i18n/zh_CN.csv index d477cb317a70b44d03cc11eadd67fcd0aa3dfa60..64e0a7d30a712142f5b21ee4884f46638700d399 100644 --- a/app/code/Magento/ImportExport/i18n/zh_CN.csv +++ b/app/code/Magento/ImportExport/i18n/zh_CN.csv @@ -79,7 +79,11 @@ Import/Export,导入/导出 "Please specify a source.","Please specify a source." "Cannot get autoincrement value","Cannot get autoincrement value" "Error in data structure: %1 values are mixed","Error in data structure: %1 values are mixed" -"Append Complex Data","Append Complex Data" +"Add/Update","Add/Update" +"Field separator","Field separator" +"Multiple value separator","Multiple value separator" +"Images File Directory","Images File Directory" +"For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir","For Type ""Local Server"" use relative path to Magento installation, e.g. var/export, var/import, var/export/some/dir" "Replace Existing Complex Data","Replace Existing Complex Data" "Delete Entities","Delete Entities" "Add/Update Complex Data","Add/Update Complex Data" diff --git a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml index 095bd45d6fea4f1004ecda1829223aaf19af0cf8..661218ae1e3fcda2041e094df42564425e48a4b8 100644 --- a/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml +++ b/app/code/Magento/ImportExport/view/adminhtml/templates/import/form/before.phtml @@ -61,17 +61,23 @@ require(['jquery', 'prototype'], function(jQuery){ */ showBehaviorFieldset: function(behaviorId, isShow) { var behaviorFieldset = jQuery('#' + behaviorId + '_fieldset'), - behavior = jQuery('#' + behaviorId); + behaviorFields = jQuery('.' + behaviorId); if (isShow) { behaviorFieldset.show(); - behavior.prop('disabled', false); - behavior.addClass('required-entry'); } else { behaviorFieldset.hide(); this.resetSelectIndex(behaviorId); - behavior.prop('disabled', 'disabled'); - behavior.removeClass('required-entry'); } + behaviorFields.each(function(k, behaviorField){ + behaviorField = jQuery(behaviorField); + if (isShow) { + behaviorField.prop('disabled', false); + behaviorField.addClass('required-entry'); + } else { + behaviorField.prop('disabled', 'disabled'); + behaviorField.removeClass('required-entry'); + } + }); }, /** diff --git a/app/code/Magento/Indexer/Model/Indexer.php b/app/code/Magento/Indexer/Model/Indexer.php index 87d4dd8d5e81d9b3251acc8e0775fe1f392abf20..71c4fe3b1993b241d1ad3bfcffb1420842ab0feb 100644 --- a/app/code/Magento/Indexer/Model/Indexer.php +++ b/app/code/Magento/Indexer/Model/Indexer.php @@ -66,6 +66,58 @@ class Indexer extends \Magento\Framework\Object implements IndexerInterface parent::__construct($data); } + /** + * Return ID + * + * @codeCoverageIgnore + * + * @return string + */ + public function getId() + { + return $this->getData($this->_idFieldName); + } + + /** + * Set ID + * + * @codeCoverageIgnore + * + * @param string $id + * @return $this + */ + public function setId($id) + { + $this->setData($this->_idFieldName, $id); + return $this; + } + + /** + * Id field name setter + * + * @codeCoverageIgnore + * + * @param string $name + * @return $this + */ + public function setIdFieldName($name) + { + $this->_idFieldName = $name; + return $this; + } + + /** + * Id field name getter + * + * @codeCoverageIgnore + * + * @return string + */ + public function getIdFieldName() + { + return $this->_idFieldName; + } + /** * Return indexer's view ID * diff --git a/app/code/Magento/Indexer/composer.json b/app/code/Magento/Indexer/composer.json index 55cd74ff041cf9bbe3e20a4f1fd7d46ccb936c25..5334b4ad74bf65576c1ccec4ad8f4294e9dddf87 100644 --- a/app/code/Magento/Indexer/composer.json +++ b/app/code/Magento/Indexer/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-page-cache": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-page-cache": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Indexer/etc/indexer.xsd b/app/code/Magento/Indexer/etc/indexer.xsd index ca243ed0844d7bee0d0e5a27852496a87eb829d6..3360194c9c0b18166dfb3ea6ad58f2dabe3dd2e0 100644 --- a/app/code/Magento/Indexer/etc/indexer.xsd +++ b/app/code/Magento/Indexer/etc/indexer.xsd @@ -42,6 +42,12 @@ <xs:sequence> <xs:element name="title" type="translatableType" /> <xs:element name="description" type="translatableType" /> + <xs:element name="fields" type="fieldsType" minOccurs="0" maxOccurs="1"> + <xs:unique name="uniqueField"> + <xs:selector xpath="field"/> + <xs:field xpath="@name"/> + </xs:unique> + </xs:element> </xs:sequence> <xs:attribute name="id" type="xs:string" use="required" /> <xs:attribute name="view_id" type="viewIdType" use="required" /> @@ -78,4 +84,79 @@ </xs:restriction> </xs:simpleType> + <xs:complexType name="fieldsType"> + <xs:annotation> + <xs:documentation> + Index fields declaration. + </xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="field" type="fieldTypeAbstract" minOccurs="1" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="handler" type="classType" use="required"/> + </xs:complexType> + + <xs:complexType name="fieldTypeAbstract"> + <xs:annotation> + <xs:documentation> + Index field declaration. + </xs:documentation> + </xs:annotation> + <xs:attribute name="name" type="xs:string" use="required"/> + <xs:attribute name="origin" type="originType" use="required"/> + <xs:attribute name="handler" type="classType" use="required"/> + </xs:complexType> + + <xs:simpleType name="originType"> + <xs:annotation> + <xs:documentation> + Origin can contain only [a-zA-Z0-9_.]. + </xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:pattern value="[a-zA-Z0-9_]+\.[a-zA-Z0-9_]+" /> + </xs:restriction> + </xs:simpleType> + + <xs:complexType name="match"> + <xs:complexContent> + <xs:extension base="fieldTypeAbstract"> + <xs:sequence> + <xs:element type="filterType" name="filter" minOccurs="0" maxOccurs="1" /> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> + + <xs:complexType name="filterType"> + <xs:annotation> + <xs:documentation> + Index field filter. + </xs:documentation> + </xs:annotation> + <xs:attribute name="class" type="classType" use="required"/> + </xs:complexType> + + <xs:complexType name="both"> + <xs:complexContent> + <xs:extension base="match"/> + </xs:complexContent> + </xs:complexType> + + <xs:complexType name="filter"> + <xs:complexContent> + <xs:extension base="fieldTypeAbstract"> + <xs:attribute type="dataType" name="dataType" use="required" /> + </xs:extension> + </xs:complexContent> + </xs:complexType> + + <xs:simpleType name="dataType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="int" /> + <xs:enumeration value="float" /> + <xs:enumeration value="varchar" /> + </xs:restriction> + </xs:simpleType> + </xs:schema> diff --git a/app/code/Magento/Integration/Model/AdminTokenService.php b/app/code/Magento/Integration/Model/AdminTokenService.php index d201b5e2a072c7937f2415f9238937fb1c39fa99..84c0fcd168ff238f5499e50e64cf89f800de2236 100644 --- a/app/code/Magento/Integration/Model/AdminTokenService.php +++ b/app/code/Magento/Integration/Model/AdminTokenService.php @@ -79,7 +79,9 @@ class AdminTokenService implements \Magento\Integration\Api\AdminTokenServiceInt * Constant cannot be created in Auth Model since it uses legacy translation that doesn't support it. * Need to make sure that this is refactored once exception handling is updated in Auth Model. */ - throw new AuthenticationException(__('Please correct the user name or password.')); + throw new AuthenticationException( + __('You did not sign in correctly or your account is temporarily disabled.') + ); } return $this->tokenModelFactory->create()->createAdminToken($this->userModel->getId())->getToken(); } diff --git a/app/code/Magento/Integration/Model/Config/Integration/Reader.php b/app/code/Magento/Integration/Model/Config/Integration/Reader.php index e3b110695e80319fa5f2f5506275eee153833f29..eeb16cda0a8752321c11146d5bec54b3c85f0a9f 100644 --- a/app/code/Magento/Integration/Model/Config/Integration/Reader.php +++ b/app/code/Magento/Integration/Model/Config/Integration/Reader.php @@ -7,6 +7,8 @@ namespace Magento\Integration\Model\Config\Integration; /** * Service config data reader. + * + * @codeCoverageIgnore */ class Reader extends \Magento\Framework\Config\Reader\Filesystem { diff --git a/app/code/Magento/Integration/Model/CredentialsValidator.php b/app/code/Magento/Integration/Model/CredentialsValidator.php index 18a8938658951fb3c6cdfa8b7521c18646b60d66..17935cf1fa84eb3e8d378be51cc66025a385c5f2 100644 --- a/app/code/Magento/Integration/Model/CredentialsValidator.php +++ b/app/code/Magento/Integration/Model/CredentialsValidator.php @@ -27,7 +27,7 @@ class CredentialsValidator if (!is_string($username) || strlen($username) == 0) { $exception->addError(__(InputException::REQUIRED_FIELD, ['fieldName' => 'username'])); } - if (!is_string($username) || strlen($password) == 0) { + if (!is_string($password) || strlen($password) == 0) { $exception->addError(__(InputException::REQUIRED_FIELD, ['fieldName' => 'password'])); } if ($exception->wasErrorAdded()) { diff --git a/app/code/Magento/Integration/Model/Integration.php b/app/code/Magento/Integration/Model/Integration.php index 24b082fd8ade7437238d317dc3ad8dec9fb194af..981466605e40fa74931860f413cf22034ee6ff58 100644 --- a/app/code/Magento/Integration/Model/Integration.php +++ b/app/code/Magento/Integration/Model/Integration.php @@ -78,7 +78,7 @@ class Integration extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -86,7 +86,7 @@ class Integration extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_dateTime = $dateTime; diff --git a/app/code/Magento/Integration/Model/IntegrationFactory.php b/app/code/Magento/Integration/Model/IntegrationFactory.php deleted file mode 100644 index 7890a2c6441fe2d323da64793b2b2ac3ede9bd94..0000000000000000000000000000000000000000 --- a/app/code/Magento/Integration/Model/IntegrationFactory.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Factory for \Magento\Integration\Model\Integration - * - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Integration\Model; - -class IntegrationFactory -{ - /** - * @var \Magento\Framework\ObjectManagerInterface - */ - protected $_objectManager; - - /** - * @param \Magento\Framework\ObjectManagerInterface $objectManager - */ - public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager) - { - $this->_objectManager = $objectManager; - } - - /** - * Create a new instance of \Magento\Integration\Model\Integration - * - * @param array $data Data for integration - * @return \Magento\Integration\Model\Integration - */ - public function create(array $data = []) - { - $integration = $this->_objectManager->create('Magento\Integration\Model\Integration', []); - $integration->setData($data); - return $integration; - } -} diff --git a/app/code/Magento/Integration/Model/IntegrationService.php b/app/code/Magento/Integration/Model/IntegrationService.php index c106e2b8dac7596b6c26b9364d64772e29af1853..f06116ca2a8cd1439615feec484c97975708d1ce 100644 --- a/app/code/Magento/Integration/Model/IntegrationService.php +++ b/app/code/Magento/Integration/Model/IntegrationService.php @@ -45,7 +45,7 @@ class IntegrationService implements \Magento\Integration\Api\IntegrationServiceI public function create(array $integrationData) { $this->_checkIntegrationByName($integrationData['name']); - $integration = $this->_integrationFactory->create($integrationData); + $integration = $this->_integrationFactory->create()->setData($integrationData); $integration->save(); $consumerName = 'Integration' . $integration->getId(); $consumer = $this->_oauthService->createConsumer(['name' => $consumerName]); diff --git a/app/code/Magento/Integration/Model/Oauth/Consumer.php b/app/code/Magento/Integration/Model/Oauth/Consumer.php index 7a40e1b5b693290f2efe84935a9a01f002be0daf..b5651c5644c5b2d76bdb8fd87cc76c6adab019d2 100644 --- a/app/code/Magento/Integration/Model/Oauth/Consumer.php +++ b/app/code/Magento/Integration/Model/Oauth/Consumer.php @@ -31,12 +31,12 @@ class Consumer extends \Magento\Framework\Model\AbstractModel implements Consume /** * @var \Magento\Framework\Url\Validator */ - protected $_urlValidator; + protected $urlValidator; /** - * @var \Magento\Integration\Model\Oauth\Consumer\Validator\KeyLengthFactory + * @var \Magento\Integration\Model\Oauth\Consumer\Validator\KeyLength */ - protected $_keyLengthFactory; + protected $keyLengthValidator; /** * @var \Magento\Integration\Helper\Oauth\Data @@ -46,25 +46,25 @@ class Consumer extends \Magento\Framework\Model\AbstractModel implements Consume /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry - * @param \Magento\Integration\Model\Oauth\Consumer\Validator\KeyLengthFactory $keyLengthFactory + * @param \Magento\Integration\Model\Oauth\Consumer\Validator\KeyLength $keyLength * @param \Magento\Framework\Url\Validator $urlValidator * @param \Magento\Integration\Helper\Oauth\Data $dataHelper * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( \Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, - \Magento\Integration\Model\Oauth\Consumer\Validator\KeyLengthFactory $keyLengthFactory, + \Magento\Integration\Model\Oauth\Consumer\Validator\KeyLength $keyLength, \Magento\Framework\Url\Validator $urlValidator, \Magento\Integration\Helper\Oauth\Data $dataHelper, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { - $this->_keyLengthFactory = $keyLengthFactory; - $this->_urlValidator = $urlValidator; + $this->keyLengthValidator = $keyLength; + $this->urlValidator = $urlValidator; $this->dataHelper = $dataHelper; parent::__construct($context, $registry, $resource, $resourceCollection, $data); } @@ -87,9 +87,7 @@ class Consumer extends \Magento\Framework\Model\AbstractModel implements Consume */ public function beforeSave() { - if (!$this->getId()) { - $this->setUpdatedAt(time()); - } + $this->setUpdatedAt(time()); $this->validate(); parent::beforeSave(); return $this; @@ -104,29 +102,27 @@ class Consumer extends \Magento\Framework\Model\AbstractModel implements Consume $this->setCallbackUrl(trim($this->getCallbackUrl())); $this->setRejectedCallbackUrl(trim($this->getRejectedCallbackUrl())); - if ($this->getCallbackUrl() && !$this->_urlValidator->isValid($this->getCallbackUrl())) { + if ($this->getCallbackUrl() && !$this->urlValidator->isValid($this->getCallbackUrl())) { throw new \Magento\Framework\Exception\LocalizedException(__('Invalid Callback URL')); } - if ($this->getRejectedCallbackUrl() && !$this->_urlValidator->isValid($this->getRejectedCallbackUrl())) { + if ($this->getRejectedCallbackUrl() && !$this->urlValidator->isValid($this->getRejectedCallbackUrl())) { throw new \Magento\Framework\Exception\LocalizedException(__('Invalid Rejected Callback URL')); } } - /** @var $validatorLength \Magento\Integration\Model\Oauth\Consumer\Validator\KeyLength */ - $validatorLength = $this->_keyLengthFactory->create( - ['options' => ['length' => \Magento\Framework\Oauth\Helper\Oauth::LENGTH_CONSUMER_KEY]] - ); - - $validatorLength->setName('Consumer Key'); - if (!$validatorLength->isValid($this->getKey())) { - $messages = $validatorLength->getMessages(); + $this->keyLengthValidator + ->setLength(\Magento\Framework\Oauth\Helper\Oauth::LENGTH_CONSUMER_KEY) + ->setName('Consumer Key'); + if (!$this->keyLengthValidator->isValid($this->getKey())) { + $messages = $this->keyLengthValidator->getMessages(); throw new \Magento\Framework\Exception\LocalizedException(__(array_shift($messages))); } - $validatorLength->setLength(\Magento\Framework\Oauth\Helper\Oauth::LENGTH_CONSUMER_SECRET); - $validatorLength->setName('Consumer Secret'); - if (!$validatorLength->isValid($this->getSecret())) { - $messages = $validatorLength->getMessages(); + $this->keyLengthValidator + ->setLength(\Magento\Framework\Oauth\Helper\Oauth::LENGTH_CONSUMER_SECRET) + ->setName('Consumer Secret'); + if (!$this->keyLengthValidator->isValid($this->getSecret())) { + $messages = $this->keyLengthValidator->getMessages(); throw new \Magento\Framework\Exception\LocalizedException(__(array_shift($messages))); } return true; diff --git a/app/code/Magento/Integration/Model/Oauth/Consumer/Validator/KeyLength.php b/app/code/Magento/Integration/Model/Oauth/Consumer/Validator/KeyLength.php index 04e5a4c54d910d0147f3432f2ffdf12e495fcc15..bfe90a706b4f9e8e563be5a6776449e1440d9724 100644 --- a/app/code/Magento/Integration/Model/Oauth/Consumer/Validator/KeyLength.php +++ b/app/code/Magento/Integration/Model/Oauth/Consumer/Validator/KeyLength.php @@ -11,14 +11,33 @@ namespace Magento\Integration\Model\Oauth\Consumer\Validator; class KeyLength extends \Zend_Validate_StringLength { /** - * Key name + * Default key name * * @var string */ protected $_name = 'Key'; /** - * Sets validator options + * @var array + */ + protected $_messageTemplates = [ + self::INVALID => "Invalid type given for %name%. String expected", + self::TOO_SHORT => "%name% '%value%' is less than %min% characters long", + self::TOO_LONG => "%name% '%value%' is more than %max% characters long", + ]; + + /** + * Additional variables available for validation failure messages + * + * @var array + */ + protected $_messageVariables = ['min' => '_min', 'max' => '_max', 'name' => '_name']; + + /** + * Sets KeyLength validator options + * + * Default encoding is set to utf-8 if none provided + * New option name added to allow adding key name in validation error messages * * @param integer|array|\Zend_Config $options */ @@ -42,26 +61,6 @@ class KeyLength extends \Zend_Validate_StringLength parent::__construct($options); } - /** - * Init validation failure message template definitions - * - * @return $this - */ - protected function _initMessageTemplates() - { - $_messageTemplates[self::TOO_LONG] = __("%name% '%value%' is too long. It must has length %min% symbols."); - $_messageTemplates[self::TOO_SHORT] = __("%name% '%value%' is too short. It must has length %min% symbols."); - - return $this; - } - - /** - * Additional variables available for validation failure messages - * - * @var array - */ - protected $_messageVariables = ['min' => '_min', 'max' => '_max', 'name' => '_name']; - /** * Set length * diff --git a/app/code/Magento/Integration/Model/Oauth/ConsumerFactory.php b/app/code/Magento/Integration/Model/Oauth/ConsumerFactory.php deleted file mode 100644 index 73d7a2ada83fbbdb7c5a2f163a05d30931980c2e..0000000000000000000000000000000000000000 --- a/app/code/Magento/Integration/Model/Oauth/ConsumerFactory.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * Consumer builder factory. - * - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Integration\Model\Oauth; - -class ConsumerFactory -{ - /** - * @var \Magento\Framework\ObjectManagerInterface - */ - protected $_objectManager; - - /** - * @param \Magento\Framework\ObjectManagerInterface $objectManager - */ - public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager) - { - $this->_objectManager = $objectManager; - } - - /** - * Create consumer model. - * - * @param array $data - * @return \Magento\Integration\Model\Oauth\Consumer - */ - public function create(array $data = []) - { - $consumer = $this->_objectManager->create('Magento\Integration\Model\Oauth\Consumer', []); - $consumer->setData($data); - return $consumer; - } -} diff --git a/app/code/Magento/Integration/Model/Oauth/Nonce.php b/app/code/Magento/Integration/Model/Oauth/Nonce.php index 7c187b4d877cbea281894173715d014bb5d469bc..97b7bc853a6c68fad953abd2086bd1e7159509c3 100644 --- a/app/code/Magento/Integration/Model/Oauth/Nonce.php +++ b/app/code/Magento/Integration/Model/Oauth/Nonce.php @@ -31,7 +31,7 @@ class Nonce extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Integration\Helper\Oauth\Data $oauthData * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -39,7 +39,7 @@ class Nonce extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Integration\Helper\Oauth\Data $oauthData, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Integration/Model/Oauth/NonceFactory.php b/app/code/Magento/Integration/Model/Oauth/NonceFactory.php deleted file mode 100644 index 32933b4d172a1f7d4ff3a4919964c2bc0073e695..0000000000000000000000000000000000000000 --- a/app/code/Magento/Integration/Model/Oauth/NonceFactory.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Integration\Model\Oauth; - -/** - * Nonce builder factory. - */ -class NonceFactory -{ - /** - * @var \Magento\Framework\ObjectManagerInterface - */ - protected $_objectManager; - - /** - * @param \Magento\Framework\ObjectManagerInterface $objectManager - */ - public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager) - { - $this->_objectManager = $objectManager; - } - - /** - * Create nonce model. - * - * @param array $arguments - * @return \Magento\Integration\Model\Oauth\Nonce - */ - public function create($arguments = []) - { - return $this->_objectManager->create('Magento\Integration\Model\Oauth\Nonce', $arguments); - } -} diff --git a/app/code/Magento/Integration/Model/Oauth/Token.php b/app/code/Magento/Integration/Model/Oauth/Token.php index 88f2efb713cff4cbf69bdf568d608d32951a63f0..92d9fe6e749744c56e1e5a3bfff370f1c21f43b5 100644 --- a/app/code/Magento/Integration/Model/Oauth/Token.php +++ b/app/code/Magento/Integration/Model/Oauth/Token.php @@ -97,7 +97,7 @@ class Token extends \Magento\Framework\Model\AbstractModel * @param \Magento\Integration\Helper\Oauth\Data $oauthData * @param OauthHelper $oauthHelper * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -111,7 +111,7 @@ class Token extends \Magento\Framework\Model\AbstractModel \Magento\Integration\Helper\Oauth\Data $oauthData, OauthHelper $oauthHelper, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Integration/Model/OauthService.php b/app/code/Magento/Integration/Model/OauthService.php index f51ddae4653281d34e97d41240313175b2d8e199..7f89b1372e94b7edb012d071fedcf327f10754ee 100644 --- a/app/code/Magento/Integration/Model/OauthService.php +++ b/app/code/Magento/Integration/Model/OauthService.php @@ -101,7 +101,7 @@ class OauthService implements \Magento\Integration\Api\OauthServiceInterface try { $consumerData['key'] = $this->_oauthHelper->generateConsumerKey(); $consumerData['secret'] = $this->_oauthHelper->generateConsumerSecret(); - $consumer = $this->_consumerFactory->create($consumerData); + $consumer = $this->_consumerFactory->create()->setData($consumerData); $consumer->save(); return $consumer; } catch (\Magento\Framework\Exception\LocalizedException $exception) { diff --git a/app/code/Magento/Integration/Test/Unit/Helper/Oauth/ConsumerTest.php b/app/code/Magento/Integration/Test/Unit/Helper/Oauth/ConsumerTest.php index 10bbc439425e1939e03f7125d297e9c26fad0177..5d2c505d26cd8457d7e7d354c83a01e0ed0dde60 100644 --- a/app/code/Magento/Integration/Test/Unit/Helper/Oauth/ConsumerTest.php +++ b/app/code/Magento/Integration/Test/Unit/Helper/Oauth/ConsumerTest.php @@ -39,9 +39,10 @@ class ConsumerTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->_consumerFactory = $this->getMockBuilder( - 'Magento\Integration\Model\Oauth\ConsumerFactory' - )->disableOriginalConstructor()->getMock(); + $this->_consumerFactory = $this->getMockBuilder('Magento\Integration\Model\Oauth\ConsumerFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); $this->_consumerMock = $this->getMockBuilder( 'Magento\Integration\Model\Oauth\Consumer' )->disableOriginalConstructor()->getMock(); @@ -123,6 +124,7 @@ class ConsumerTest extends \PHPUnit_Framework_TestCase $secret = $this->_generateRandomString(\Magento\Framework\Oauth\Helper\Oauth::LENGTH_CONSUMER_SECRET); $consumerData = ['name' => 'Integration Name', 'key' => $key, 'secret' => $secret]; + $this->_consumerMock->expects($this->once())->method('setData')->will($this->returnSelf()); $this->_consumerMock->expects($this->once())->method('save')->will($this->returnSelf()); /** @var \Magento\Integration\Model\Oauth\Consumer $consumer */ diff --git a/app/code/Magento/Integration/Test/Unit/Model/AuthorizationServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/AuthorizationServiceTest.php index 3f491861f042eb490b921b0ed144b45610bed65b..50943355d83682a7bbb890f59e6964c2dbd16c85 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/AuthorizationServiceTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/AuthorizationServiceTest.php @@ -5,29 +5,61 @@ */ namespace Magento\Integration\Test\Unit\Model; -use Magento\Integration\Model\AuthorizationService; +use Magento\Authorization\Model\Resource\Rules; use Magento\Authorization\Model\Role; use Magento\Authorization\Model\UserContextInterface; +use Magento\Framework\Acl\RootResource; +use Magento\Integration\Model\AuthorizationService; class AuthorizationServiceTest extends \PHPUnit_Framework_TestCase { - /** @var \PHPUnit_Framework_MockObject_MockObject|Role */ + /** + * Sample role Id + */ + const ROLE_ID = 1; + + /** + * Sample integration id + */ + const INTEGRATION_ID = 22; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|Role + */ protected $roleMock; - /** @var AuthorizationService */ + /** + * @var AuthorizationService + */ protected $integrationAuthorizationService; + /** + * @var \PHPUnit_Framework_MockObject_MockObject|Rules + */ + protected $rulesMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject|RootResource + */ + protected $rootAclResourceMock; + + /** + * @var array + */ + protected $resources; + protected function setUp() { $this->roleMock = $this->getMock( 'Magento\Authorization\Model\Role', - ['load', 'delete', '__wakeup'], + ['load', 'delete', '__wakeup', 'getId', 'save'], [], '', false ); $this->roleMock->expects($this->any())->method('load')->will($this->returnSelf()); $this->roleMock->expects($this->any())->method('delete')->will($this->returnSelf()); + $this->roleMock->expects($this->any())->method('save')->will($this->returnSelf()); /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Authorization\Model\RoleFactory $roleFactoryMock */ $roleFactoryMock = $this->getMock( @@ -39,22 +71,160 @@ class AuthorizationServiceTest extends \PHPUnit_Framework_TestCase ); $roleFactoryMock->expects($this->any())->method('create')->will($this->returnValue($this->roleMock)); + $roleCollectionFactoryMock = $this->getMock( + 'Magento\Authorization\Model\Resource\Role\CollectionFactory', + ['create'], + [], + '', + false + ); + $roleCollectionMock = $this->getMock( + 'Magento\Authorization\Model\Resource\Role\Collection', + ['setUserFilter', 'getFirstItem'], + [], + '', + false + ); + $roleCollectionMock->expects($this->any())->method('setUserFilter')->will($this->returnSelf()); + $roleCollectionMock->expects($this->any())->method('getFirstItem')->will($this->returnValue($this->roleMock)); + + $roleCollectionFactoryMock->expects($this->any()) + ->method('create') + ->will($this->returnValue($roleCollectionMock)); + + $rulesFactoryMock = $this->getMock('Magento\Authorization\Model\RulesFactory', ['create'], [], '', false); + $this->rulesMock = $this->getMock( + 'Magento\Authorization\Model\Rules', + ['setRoleId', 'setResources', 'saveRel'], + [], + '', + false + ); + $rulesFactoryMock->expects($this->any()) + ->method('create') + ->will($this->returnValue($this->rulesMock)); + + $this->rootAclResourceMock = $this->getMock('Magento\Framework\Acl\RootResource', ['getId'], [], '', false); + $this->integrationAuthorizationService = new AuthorizationService( $this->getMock('Magento\Framework\Acl\Builder', [], [], '', false), $roleFactoryMock, - $this->getMock('Magento\Authorization\Model\Resource\Role\CollectionFactory', [], [], '', false), - $this->getMock('Magento\Authorization\Model\RulesFactory', [], [], '', false), + $roleCollectionFactoryMock, + $rulesFactoryMock, $this->getMock('Magento\Authorization\Model\Resource\Rules\CollectionFactory', [], [], '', false), $this->getMock('Psr\Log\LoggerInterface'), - $this->getMock('Magento\Framework\Acl\RootResource', [], [], '', false) + $this->rootAclResourceMock ); } public function testRemovePermissions() { - $integrationId = 22; - $roleName = UserContextInterface::USER_TYPE_INTEGRATION . $integrationId; + $roleName = UserContextInterface::USER_TYPE_INTEGRATION . self::INTEGRATION_ID; $this->roleMock->expects($this->once())->method('load')->with($roleName)->will($this->returnSelf()); - $this->integrationAuthorizationService->removePermissions($integrationId); + $this->integrationAuthorizationService->removePermissions(self::INTEGRATION_ID); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Error happened while deleting role and permissions. Check exception log for details. + */ + public function testRemovePermissionsException() + { + $roleName = UserContextInterface::USER_TYPE_INTEGRATION . self::INTEGRATION_ID; + $this->roleMock->expects($this->once()) + ->method('load') + ->with($roleName) + ->will($this->throwException(new \Exception)); + $this->integrationAuthorizationService->removePermissions(self::INTEGRATION_ID); + } + + public function testGrantPermissions() + { + $this->resources = [ + 'Magento_Sales::sales', + 'Magento_Sales::sales_operations', + 'Magento_Cart::cart', + 'Magento_Cart::manage' + ]; + + $this->roleMock->expects($this->any())->method('getId')->will($this->returnValue(self::ROLE_ID)); + $this->rulesMock->expects($this->any())->method('setRoleId')->with(self::ROLE_ID)->will($this->returnSelf()); + $this->rulesMock->expects($this->any()) + ->method('setResources') + ->with($this->resources) + ->will($this->returnSelf()); + $this->rulesMock->expects($this->any())->method('saveRel')->will($this->returnSelf()); + + $this->integrationAuthorizationService->grantPermissions(self::INTEGRATION_ID, $this->resources); + } + + public function testGrantPermissionsNoRole() + { + $calculatedRoleId = UserContextInterface::USER_TYPE_INTEGRATION . self::INTEGRATION_ID; + + $this->resources = [ + 'Magento_Sales::sales', + 'Magento_Sales::sales_operations', + 'Magento_Cart::cart', + 'Magento_Cart::manage' + ]; + + //Return invalid role + $this->roleMock->expects($this->any()) + ->method('getId') + ->will($this->onConsecutiveCalls(null, $calculatedRoleId)); + // Verify if the method is called with the newly created role + $this->rulesMock->expects($this->any()) + ->method('setRoleId') + ->with($calculatedRoleId) + ->will($this->returnSelf()); + + $this->rulesMock->expects($this->any()) + ->method('setResources') + ->with($this->resources) + ->will($this->returnSelf()); + $this->rulesMock->expects($this->any())->method('saveRel')->will($this->returnSelf()); + + $this->integrationAuthorizationService->grantPermissions(self::INTEGRATION_ID, $this->resources); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Error happened while granting permissions. Check exception log for details. + */ + public function testGrantPermissionsException() + { + $this->resources = [ + 'Magento_Sales::sales', + 'Magento_Sales::sales_operations', + 'Magento_Cart::cart', + 'Magento_Cart::manage' + ]; + + $this->roleMock->expects($this->any())->method('getId')->will($this->returnValue(self::ROLE_ID)); + $this->rulesMock->expects($this->any())->method('setRoleId')->with(self::ROLE_ID)->will($this->returnSelf()); + $this->rulesMock->expects($this->any()) + ->method('setResources') + ->with($this->resources) + ->will($this->returnSelf()); + $this->rulesMock->expects($this->any())->method('saveRel')->will($this->throwException(new \Exception)); + + $this->integrationAuthorizationService->grantPermissions(self::INTEGRATION_ID, $this->resources); + } + + public function testGrantAllPermissions() + { + $rootResource = 'Magento_All:all'; + + $this->rootAclResourceMock->expects($this->any())->method('getId')->will($this->returnValue($rootResource)); + $this->roleMock->expects($this->any())->method('getId')->will($this->returnValue(self::ROLE_ID)); + $this->rulesMock->expects($this->any())->method('setRoleId')->with(self::ROLE_ID)->will($this->returnSelf()); + $this->rulesMock->expects($this->any()) + ->method('setResources') + ->with([$rootResource]) + ->will($this->returnSelf()); + $this->rulesMock->expects($this->any())->method('saveRel')->will($this->returnSelf()); + + $this->integrationAuthorizationService->grantAllPermissions(self::INTEGRATION_ID); } } diff --git a/app/code/Magento/Integration/Test/Unit/Model/Config/Integration/SchemaLocatorTest.php b/app/code/Magento/Integration/Test/Unit/Model/Config/Integration/SchemaLocatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..107252d03661b752920d23da06c6b389474367d8 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Config/Integration/SchemaLocatorTest.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model\Config\Integration; + +use Magento\Integration\Model\Config\Integration\SchemaLocator; + +class SchemaLocatorTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Framework\Module\Dir\Reader|\PHPUnit_Framework_MockObject_MockObject */ + protected $moduleReader; + + /** @var string */ + protected $moduleDir; + + /** @var SchemaLocator */ + protected $schemaLocator; + + protected function setUp() + { + $this->moduleDir = 'moduleDirectory'; + $this->moduleReader = $this->getMock('Magento\Framework\Module\Dir\Reader', [], [], '', false); + $this->moduleReader->expects($this->any()) + ->method('getModuleDir') + ->willReturn($this->moduleDir); + $this->schemaLocator = new SchemaLocator($this->moduleReader); + } + + public function testGetSchema() + { + $this->assertEquals($this->moduleDir . '/integration/api.xsd', $this->schemaLocator->getSchema()); + } + + public function testGetPerFileSchema() + { + $this->assertNull($this->schemaLocator->getPerFileSchema()); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/ConfigTest.php b/app/code/Magento/Integration/Test/Unit/Model/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fecb6c0c0b36d6ef2b13af54002e0b8aad320090 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/ConfigTest.php @@ -0,0 +1,75 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model; + +use Magento\Integration\Model\Config; +use Magento\Integration\Model\Cache\Type; + +/** + * Unit test for \Magento\Integration\Model\Config + */ +class ConfigTest extends \PHPUnit_Framework_TestCase +{ + /** + * Integration config model + * + * @var Config + */ + protected $configModel; + + /** + * @var Type|\PHPUnit_Framework_MockObject_MockObject + */ + protected $configCacheTypeMock; + + /** + * @var \Magento\Integration\Model\Config\Reader|\PHPUnit_Framework_MockObject_MockObject + */ + protected $configReaderMock; + + public function setUp() + { + $this->configCacheTypeMock = $this->getMockBuilder('Magento\Integration\Model\Cache\Type') + ->disableOriginalConstructor() + ->getMock(); + $this->configReaderMock = $this->getMockBuilder('Magento\Integration\Model\Config\Reader') + ->disableOriginalConstructor() + ->getMock(); + $this->configModel = new Config( + $this->configCacheTypeMock, + $this->configReaderMock + ); + } + + public function testGetIntegrationsFromConfigCacheType() + { + $integrations = ['foo', 'bar', 'baz']; + $this->configCacheTypeMock->expects($this->once()) + ->method('load') + ->with(Config::CACHE_ID) + ->will($this->returnValue(serialize($integrations))); + + $this->assertEquals($integrations, $this->configModel->getIntegrations()); + } + + public function testGetIntegrationsFromConfigReader() + { + $integrations = ['foo', 'bar', 'baz']; + $this->configCacheTypeMock->expects($this->once()) + ->method('load') + ->with(Config::CACHE_ID) + ->will($this->returnValue(null)); + $this->configCacheTypeMock->expects($this->once()) + ->method('save') + ->with(serialize($integrations), Config::CACHE_ID, [Type::CACHE_TAG]) + ->will($this->returnValue(null)); + $this->configReaderMock->expects($this->once()) + ->method('read') + ->will($this->returnValue($integrations)); + + $this->assertEquals($integrations, $this->configModel->getIntegrations()); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/CredentialsValidatorTest.php b/app/code/Magento/Integration/Test/Unit/Model/CredentialsValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bde4aab14565a9d1077cf53c25c10b1cf41d9414 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/CredentialsValidatorTest.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model; + +/** + * Unit test for \Magento\Integration\Model\CredentialsValidator + */ +class CredentialsValidatorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Integration\Model\CredentialsValidator + */ + protected $credentialsValidator; + + public function setUp() + { + $this->credentialsValidator = new \Magento\Integration\Model\CredentialsValidator(); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage username is a required field. + */ + public function testValidateNoUsername() + { + $username = ''; + $password = 'my_password'; + + $this->credentialsValidator->validate($username, $password); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage password is a required field. + */ + public function testValidateNoPassword() + { + $username = 'my_username'; + $password = ''; + + $this->credentialsValidator->validate($username, $password); + } + + public function testValidateValidCredentials() + { + $username = 'my_username'; + $password = 'my_password'; + + $this->credentialsValidator->validate($username, $password); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/IntegrationConfigTest.php b/app/code/Magento/Integration/Test/Unit/Model/IntegrationConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..61d239abc7258f5f1f41cabb076f2a7cfc825af4 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/IntegrationConfigTest.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model; + +use Magento\Integration\Model\IntegrationConfig; +use Magento\Integration\Model\Cache\TypeIntegration; + +/** + * Unit test for \Magento\Integration\Model\IntegrationConfig + */ +class IntegrationConfigTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var IntegrationConfig + */ + protected $integrationConfigModel; + + /** + * @var TypeIntegration|\PHPUnit_Framework_MockObject_MockObject + */ + protected $configCacheTypeMock; + + /** + * @var \Magento\Integration\Model\Config\Integration\Reader|\PHPUnit_Framework_MockObject_MockObject + */ + protected $configReaderMock; + + public function setUp() + { + $this->configCacheTypeMock = $this->getMockBuilder('Magento\Integration\Model\Cache\TypeIntegration') + ->disableOriginalConstructor() + ->getMock(); + $this->configReaderMock = $this->getMockBuilder('Magento\Integration\Model\Config\Integration\Reader') + ->disableOriginalConstructor() + ->getMock(); + $this->integrationConfigModel = new IntegrationConfig( + $this->configCacheTypeMock, + $this->configReaderMock + ); + } + + public function testGetIntegrationsFromConfigCacheType() + { + $integrations = ['foo', 'bar', 'baz']; + $this->configCacheTypeMock->expects($this->once()) + ->method('load') + ->with(IntegrationConfig::CACHE_ID) + ->will($this->returnValue(serialize($integrations))); + + $this->assertEquals($integrations, $this->integrationConfigModel->getIntegrations()); + } + + public function testGetIntegrationsFromConfigReader() + { + $integrations = ['foo', 'bar', 'baz']; + $this->configCacheTypeMock->expects($this->once()) + ->method('load') + ->with(IntegrationConfig::CACHE_ID) + ->will($this->returnValue(null)); + $this->configCacheTypeMock->expects($this->once()) + ->method('save') + ->with(serialize($integrations), IntegrationConfig::CACHE_ID, [TypeIntegration::CACHE_TAG]) + ->will($this->returnValue(null)); + $this->configReaderMock->expects($this->once()) + ->method('read') + ->will($this->returnValue($integrations)); + + $this->assertEquals($integrations, $this->integrationConfigModel->getIntegrations()); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/IntegrationFactoryTest.php b/app/code/Magento/Integration/Test/Unit/Model/IntegrationFactoryTest.php deleted file mode 100644 index 4971b4599d6b377e9d50b85def2a196dbd58bded..0000000000000000000000000000000000000000 --- a/app/code/Magento/Integration/Test/Unit/Model/IntegrationFactoryTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Integration\Test\Unit\Model; - -use Magento\Integration\Block\Adminhtml\Integration\Edit\Tab\Info; - -class IntegrationFactoryTest extends \PHPUnit_Framework_TestCase -{ - public function testCreate() - { - /** @var \PHPUnit_Framework_MockObject_MockObject */ - $mockObjectManager = $this->getMock('Magento\Framework\ObjectManagerInterface'); - - $data = [ - Info::DATA_NAME => 'nameTest', - Info::DATA_ID => '1', - Info::DATA_EMAIL => 'test@magento.com', - Info::DATA_ENDPOINT => 'http://magento.ll/endpoint', - ]; - $mockIntegration = $this->getMockBuilder( - 'Magento\Integration\Model\Integration' - )->disableOriginalConstructor()->getMock(); - $mockIntegration->expects($this->any())->method('setData')->will($this->returnSelf()); - $mockIntegration->expects($this->any())->method('getData')->will($this->returnValue($data)); - $mockObjectManager->expects($this->any())->method('create')->will($this->returnValue($mockIntegration)); - /* @var \Magento\Integration\Model\IntegrationFactory */ - $integrationFactory = new \Magento\Integration\Model\IntegrationFactory($mockObjectManager); - $integration = $integrationFactory->create($data); - $this->assertEquals($data, $integration->getData(), 'The integration data is not set correctly'); - } -} diff --git a/app/code/Magento/Integration/Test/Unit/Model/IntegrationServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/IntegrationServiceTest.php index f3e8d48ec022fa213f49fe418791af02a6b88d94..c3e6f3a913a206d859899bca6147d58e8d1ae195 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/IntegrationServiceTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/IntegrationServiceTest.php @@ -42,9 +42,10 @@ class IntegrationServiceTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->_integrationFactory = $this->getMockBuilder( - 'Magento\Integration\Model\IntegrationFactory' - )->disableOriginalConstructor()->getMock(); + $this->_integrationFactory = $this->getMockBuilder('Magento\Integration\Model\IntegrationFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); $this->_integrationMock = $this->getMockBuilder( 'Magento\Integration\Model\Integration' )->disableOriginalConstructor()->setMethods( diff --git a/app/code/Magento/Integration/Test/Unit/Model/IntegrationTest.php b/app/code/Magento/Integration/Test/Unit/Model/IntegrationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ee0e19489de2377d1aaf0945738d2e415d8f4b72 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/IntegrationTest.php @@ -0,0 +1,147 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model; + +/** + * Unit test for \Magento\Integration\Model\Integration + */ +class IntegrationTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Integration\Model\Integration + */ + protected $integrationModel; + + /** + * @var \Magento\Framework\Model\Context|\PHPUnit_Framework_MockObject_MockObject + */ + protected $contextMock; + + /** + * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + */ + protected $registryMock; + + /** + * @var \Magento\Framework\Stdlib\DateTime|\PHPUnit_Framework_MockObject_MockObject + */ + protected $dateTimeMock; + + /** + * @var \Magento\Framework\Model\Resource\AbstractResource|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceMock; + + /** + * @var \Magento\Framework\Data\Collection\AbstractDb|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceCollectionMock; + + public function setUp() + { + $this->contextMock = $this->getMock( + 'Magento\Framework\Model\Context', + ['getEventDispatcher'], + [], + '', + false + ); + $eventManagerMock = $this->getMockForAbstractClass( + 'Magento\Framework\Event\ManagerInterface', + [], + '', + false, + true, + true, + ['dispatch'] + ); + $this->contextMock->expects($this->once()) + ->method('getEventDispatcher') + ->will($this->returnValue($eventManagerMock)); + $this->registryMock = $this->getMock( + 'Magento\Framework\Registry', + [], + [], + '', + false + ); + $this->dateTimeMock = $this->getMock( + 'Magento\Framework\Stdlib\DateTime', + [], + [], + '', + false + ); + $this->resourceMock = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\AbstractResource', + [], + '', + false, + true, + true, + ['getIdFieldName', 'load', 'selectActiveIntegrationByConsumerId'] + ); + $this->resourceCollectionMock = $this->getMock( + 'Magento\Framework\Data\Collection\AbstractDb', + [], + [], + '', + false + ); + $this->integrationModel = new \Magento\Integration\Model\Integration( + $this->contextMock, + $this->registryMock, + $this->dateTimeMock, + $this->resourceMock, + $this->resourceCollectionMock + ); + } + + public function testBeforeSave() + { + $timeStamp = '0000'; + $this->dateTimeMock->expects($this->exactly(2)) + ->method('formatDate') + ->will($this->returnValue($timeStamp)); + $this->integrationModel->beforeSave(); + $this->assertEquals($timeStamp, $this->integrationModel->getCreatedAt()); + $this->assertEquals($timeStamp, $this->integrationModel->getUpdatedAt()); + } + + public function testLoadByConsumerId() + { + $consumerId = 1; + $this->resourceMock->expects($this->once()) + ->method('load') + ->with($this->integrationModel, $consumerId, \Magento\Integration\Model\Integration::CONSUMER_ID); + + $this->integrationModel->loadByConsumerId($consumerId); + $this->assertFalse($this->integrationModel->hasDataChanges()); + } + + public function testLoadActiveIntegrationByConsumerId() + { + $consumerId = 1; + $integrationData = [ + 'integration_id' => 1, + 'name' => 'Test Integration' + ]; + + $this->resourceMock->expects($this->once()) + ->method('selectActiveIntegrationByConsumerId') + ->with($consumerId) + ->will($this->returnValue($integrationData)); + + $this->integrationModel->loadActiveIntegrationByConsumerId($consumerId); + $this->assertEquals($integrationData, $this->integrationModel->getData()); + } + + public function testGetStatus() + { + $this->integrationModel->setStatus(1); + $this->assertEquals(1, $this->integrationModel->getStatus()); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/Oauth/Consumer/Validator/KeyLengthTest.php b/app/code/Magento/Integration/Test/Unit/Model/Oauth/Consumer/Validator/KeyLengthTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3ae849796e300e71d162b76eb4aa92374c5539b9 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Oauth/Consumer/Validator/KeyLengthTest.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Integration\Test\Unit\Model\Oauth\Consumer\Validator; + +use Magento\Integration\Model\Oauth\Consumer\Validator\KeyLength; + +class KeyLengthTest extends \PHPUnit_Framework_TestCase +{ + /** + * Sample length + */ + const KEY_LENGTH = 32; + + /** + * @var \Magento\Integration\Model\Oauth\Consumer\Validator\KeyLength + */ + protected $keyLengthValidator; + + protected function setUp() + { + $options = ['length' => KeyLengthTest::KEY_LENGTH]; + $this->keyLengthValidator = new KeyLength($options); + } + + public function testSetLength() + { + $this->assertEquals(KeyLengthTest::KEY_LENGTH, $this->keyLengthValidator->getLength()); + $this->assertEquals(KeyLengthTest::KEY_LENGTH, $this->keyLengthValidator->getMin()); + $this->assertEquals(KeyLengthTest::KEY_LENGTH, $this->keyLengthValidator->getMax()); + } + + public function testIsValidLong() + { + $invalidToken = 'asjdkhbcaklsjhlkasjdhlkajhsdljahksdlkafjsljdhskjhksj'; + $this->keyLengthValidator->isValid($invalidToken); + $expected = ['stringLengthTooLong' => "Key '{$invalidToken}' is more than 32 characters long"]; + $this->assertEquals($expected, $this->keyLengthValidator->getMessages()); + } + + public function testIsValidShort() + { + $invalidToken = 'fajdhkahkjha'; + $this->keyLengthValidator->isValid($invalidToken); + $expected = ['stringLengthTooShort' => "Key '{$invalidToken}' is less than 32 characters long"]; + $this->assertEquals($expected, $this->keyLengthValidator->getMessages()); + } + + public function testIsValidShortCustomKeyName() + { + $invalidToken = 'fajdhkahkjha'; + $this->keyLengthValidator->setName('Custom Key'); + $this->keyLengthValidator->isValid($invalidToken); + $expected = ['stringLengthTooShort' => "Custom Key '{$invalidToken}' is less than 32 characters long"]; + $this->assertEquals($expected, $this->keyLengthValidator->getMessages()); + } + + /** + * @expectedException \Exception + * @expectedExceptionMessage Invalid type given for Key. String expected + */ + public function testIsValidInvalidType() + { + $invalidTokenType = 1; + $this->keyLengthValidator->isValid($invalidTokenType); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/Oauth/ConsumerTest.php b/app/code/Magento/Integration/Test/Unit/Model/Oauth/ConsumerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b8f957b46eb88bd6af7169a3746c82298200548e --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Oauth/ConsumerTest.php @@ -0,0 +1,235 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model\Oauth; + +use Magento\Framework\Url\Validator as UrlValidator; +use Magento\Integration\Model\Oauth\Consumer\Validator\KeyLength; + +/** + * Test for \Magento\Integration\Model\Oauth\Consumer + */ +class ConsumerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Integration\Model\Oauth\Consumer + */ + protected $consumerModel; + + /** + * @var \Magento\Framework\Model\Context|\PHPUnit_Framework_MockObject_MockObject + */ + protected $contextMock; + + /** + * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + */ + protected $registryMock; + + /** + * @var KeyLength + */ + protected $keyLengthValidator; + + /** + * @var \Magento\Integration\Model\Oauth\Consumer\Validator\KeyLengthFactory + */ + protected $keyLengthValidatorFactory; + + /** + * @var UrlValidator + */ + protected $urlValidator; + + /** + * @var \Magento\Integration\Helper\Oauth\Data|\PHPUnit_Framework_MockObject_MockObject + */ + protected $oauthDataMock; + + /** + * @var \Magento\Framework\Model\Resource\AbstractResource|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceMock; + + /** + * @var \Magento\Framework\Data\Collection\AbstractDb|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceCollectionMock; + + /** + * @var array + */ + protected $validDataArray; + + public function setUp() + { + $this->contextMock = $this->getMock( + 'Magento\Framework\Model\Context', + ['getEventDispatcher'], + [], + '', + false + ); + $eventManagerMock = $this->getMockForAbstractClass( + 'Magento\Framework\Event\ManagerInterface', + [], + '', + false, + true, + true, + ['dispatch'] + ); + $this->contextMock->expects($this->once()) + ->method('getEventDispatcher') + ->will($this->returnValue($eventManagerMock)); + + $this->registryMock = $this->getMock( + 'Magento\Framework\Registry', + [], + [], + '', + false + ); + + $this->keyLengthValidator = new KeyLength(); + + $this->urlValidator = new UrlValidator(); + + $this->oauthDataMock = $this->getMock( + 'Magento\Integration\Helper\Oauth\Data', + ['getConsumerExpirationPeriod'], + [], + '', + false + ); + $this->oauthDataMock->expects($this->any()) + ->method('getConsumerExpirationPeriod') + ->will($this->returnValue(\Magento\Integration\Helper\Oauth\Data::CONSUMER_EXPIRATION_PERIOD_DEFAULT)); + + $this->resourceMock = $this->getMock( + 'Magento\Integration\Model\Resource\Oauth\Consumer', + ['getTimeInSecondsSinceCreation', 'getIdFieldName', 'selectByCompositeKey', 'deleteOldEntries'], + [], + '', + false, + true, + true + ); + $this->resourceCollectionMock = $this->getMock( + 'Magento\Framework\Data\Collection\AbstractDb', + [], + [], + '', + false + ); + $this->consumerModel = new \Magento\Integration\Model\Oauth\Consumer( + $this->contextMock, + $this->registryMock, + $this->keyLengthValidator, + $this->urlValidator, + $this->oauthDataMock, + $this->resourceMock, + $this->resourceCollectionMock + ); + + $this->validDataArray = [ + 'key' => md5(uniqid()), + 'secret' => md5(uniqid()), + 'callback_url' => 'http://example.com/callback', + 'rejected_callback_url' => 'http://example.com/rejectedCallback' + ]; + } + + public function testBeforeSave() + { + try { + $this->consumerModel->setData($this->validDataArray); + $this->consumerModel->beforeSave(); + } catch (\Exception $e) { + $this->fail('Exception not expected for beforeSave with valid data.'); + } + } + + public function testValidate() + { + $this->consumerModel->setData($this->validDataArray); + $this->assertTrue($this->consumerModel->validate()); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Invalid Callback URL + */ + public function testValidateInvalidData() + { + $this->validDataArray['callback_url'] = 'invalid'; + $this->consumerModel->setData($this->validDataArray); + $this->consumerModel->validate(); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Invalid Callback URL + */ + public function testValidateInvalidCallback() + { + $this->validDataArray['callback_url'] = 'invalid'; + $this->consumerModel->setData($this->validDataArray); + $this->consumerModel->validate(); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Invalid Rejected Callback URL + */ + public function testValidateInvalidRejectedCallback() + { + $this->validDataArray['rejected_callback_url'] = 'invalid'; + $this->consumerModel->setData($this->validDataArray); + $this->consumerModel->validate(); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Consumer Key 'invalid' is less than 32 characters long + */ + public function testValidateInvalidConsumerKey() + { + $this->validDataArray['key'] = 'invalid'; + $this->consumerModel->setData($this->validDataArray); + $this->consumerModel->validate(); + } + + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + * @expectedExceptionMessage Consumer Secret 'invalid' is less than 32 characters long + */ + public function testValidateInvalidConsumerSecret() + { + $this->validDataArray['secret'] = 'invalid'; + $this->consumerModel->setData($this->validDataArray); + $this->consumerModel->validate(); + } + + public function testGetConsumerExpirationPeriodValid() + { + $this->resourceMock->expects($this->once()) + ->method('getTimeInSecondsSinceCreation') + ->will($this->returnValue(30)); + + $this->consumerModel->setCreatedAt(time()); + $this->assertTrue($this->consumerModel->isValidForTokenExchange()); + } + + public function testGetConsumerExpirationPeriodExpired() + { + $this->resourceMock->expects($this->once()) + ->method('getTimeInSecondsSinceCreation') + ->will($this->returnValue(400)); + + $this->consumerModel->setCreatedAt(time()); + $this->assertFalse($this->consumerModel->isValidForTokenExchange()); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/Oauth/NonceTest.php b/app/code/Magento/Integration/Test/Unit/Model/Oauth/NonceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e99a0bb74220cffe7f570b9de9eae2173ac1a260 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Oauth/NonceTest.php @@ -0,0 +1,151 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Integration\Test\Unit\Model\Oauth; + +/** + * Unit test for \Magento\Integration\Model\Oauth\Nonce + */ +class NonceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Integration\Model\Oauth\Nonce + */ + protected $nonceModel; + + /** + * @var \Magento\Framework\Model\Context|\PHPUnit_Framework_MockObject_MockObject + */ + protected $contextMock; + + /** + * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + */ + protected $registryMock; + + /** + * @var \Magento\Integration\Helper\Oauth\Data|\PHPUnit_Framework_MockObject_MockObject + */ + protected $oauthDataMock; + + /** + * @var \Magento\Framework\Model\Resource\AbstractResource|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceMock; + + /** + * @var \Magento\Framework\Data\Collection\AbstractDb|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceCollectionMock; + + protected function setUp() + { + $this->contextMock = $this->getMock( + 'Magento\Framework\Model\Context', + ['getEventDispatcher'], + [], + '', + false + ); + $eventManagerMock = $this->getMockForAbstractClass( + 'Magento\Framework\Event\ManagerInterface', + [], + '', + false, + true, + true, + ['dispatch'] + ); + $this->contextMock->expects($this->once()) + ->method('getEventDispatcher') + ->will($this->returnValue($eventManagerMock)); + $this->registryMock = $this->getMock( + 'Magento\Framework\Registry', + [], + [], + '', + false + ); + $this->oauthDataMock = $this->getMock( + 'Magento\Integration\Helper\Oauth\Data', + [], + [], + '', + false + ); + $this->resourceMock = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\AbstractResource', + [], + '', + false, + true, + true, + ['getIdFieldName', 'selectByCompositeKey', 'deleteOldEntries'] + ); + $this->resourceCollectionMock = $this->getMock( + 'Magento\Framework\Data\Collection\AbstractDb', + [], + [], + '', + false + ); + $this->nonceModel = new \Magento\Integration\Model\Oauth\Nonce( + $this->contextMock, + $this->registryMock, + $this->oauthDataMock, + $this->resourceMock, + $this->resourceCollectionMock + ); + } + + public function testAfterSave() + { + $this->oauthDataMock->expects($this->once()) + ->method('isCleanupProbability') + ->will($this->returnValue(true)); + + $this->oauthDataMock->expects($this->once()) + ->method('getCleanupExpirationPeriod') + ->will($this->returnValue(30)); + + $this->resourceMock->expects($this->once()) + ->method('deleteOldEntries') + ->with(30) + ->will($this->returnValue(1)); + + $this->assertEquals($this->nonceModel, $this->nonceModel->afterSave()); + } + + public function testAfterSaveNoCleanupProbability() + { + $this->oauthDataMock->expects($this->once()) + ->method('isCleanupProbability') + ->will($this->returnValue(false)); + + $this->oauthDataMock->expects($this->never()) + ->method('getCleanupExpirationPeriod'); + + $this->resourceMock->expects($this->never()) + ->method('deleteOldEntries'); + + $this->assertEquals($this->nonceModel, $this->nonceModel->afterSave()); + } + + public function testLoadByCompositeKey() + { + $expectedData = ['testData']; + $nonce = 'testNonce'; + $consumerId = 1; + + $this->resourceMock->expects($this->once()) + ->method('selectByCompositeKey') + ->with($nonce, $consumerId) + ->will($this->returnValue($expectedData)); + $this->nonceModel->loadByCompositeKey($nonce, $consumerId); + + $this->assertEquals($expectedData, $this->nonceModel->getData()); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/Oauth/Token/ProviderTest.php b/app/code/Magento/Integration/Test/Unit/Model/Oauth/Token/ProviderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3674abc62df1a0cfe02ccb5ce763d034960e6997 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Oauth/Token/ProviderTest.php @@ -0,0 +1,741 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Integration\Test\Unit\Model\Oauth\Token; + +use Magento\Authorization\Model\UserContextInterface; +use Magento\Integration\Model\Oauth\Token; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +/** + * Unit test for \Magento\Integration\Model\Oauth\Token\Provider + */ +class ProviderTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Integration\Model\Oauth\Token\Provider */ + protected $tokenProvider; + + /** @var \Magento\Integration\Model\Oauth\ConsumerFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $consumerFactoryMock; + + /** @var \Magento\Integration\Model\Oauth\TokenFactory|\PHPUnit_Framework_MockObject_MockObject */ + protected $tokenFactoryMock; + + /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $loggerMock; + + /** @var \Magento\Framework\Oauth\ConsumerInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $consumerMock; + + /** @var \Magento\Integration\Model\Oauth\Token|\PHPUnit_Framework_MockObject_MockObject */ + protected $requestTokenMock; + + /** @var \Magento\Integration\Model\Oauth\Token|\PHPUnit_Framework_MockObject_MockObject */ + protected $accessTokenMock; + + protected function setUp() + { + $objectManagerHelper = new ObjectManagerHelper($this); + + $this->consumerFactoryMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\ConsumerFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->tokenFactoryMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\TokenFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->loggerMock = $this->getMockBuilder('Psr\Log\LoggerInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->consumerMock = $this->getMockBuilder('Magento\Framework\Oauth\ConsumerInterface') + ->setMethods( + [ + 'load', + 'loadByKey', + 'validate', + 'getId', + 'getKey', + 'getSecret', + 'getCallbackUrl', + 'getCreatedAt', + 'isValidForTokenExchange' + ] + ) + ->disableOriginalConstructor() + ->getMock(); + + $this->requestTokenMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\Token') + ->setMethods( + [ + 'loadByConsumerIdAndUserType', + 'load', + 'getId', + 'getConsumerId', + 'getType', + 'getSecret', + 'getToken', + 'getVerifier', + 'createRequestToken', + 'convertToAccess' + ] + ) + ->disableOriginalConstructor() + ->getMock(); + + $this->accessTokenMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\Token') + ->setMethods( + [ + 'getToken', + 'getSecret', + 'load', + 'getId', + 'getConsumerId', + 'getType', + 'getRevoked' + ] + ) + ->disableOriginalConstructor() + ->getMock(); + + $this->tokenProvider = $objectManagerHelper->getObject( + 'Magento\Integration\Model\Oauth\Token\Provider', + [ + 'consumerFactory' => $this->consumerFactoryMock, + 'tokenFactory' => $this->tokenFactoryMock, + 'logger' => $this->loggerMock, + ] + ); + } + + public function testValidateConsumer() + { + $this->consumerMock->expects($this->once())->method('isValidForTokenExchange')->willReturn(true); + $this->assertEquals(true, $this->tokenProvider->validateConsumer($this->consumerMock)); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Consumer key has expired + */ + public function testValidateConsumerException() + { + $this->consumerMock->expects($this->once())->method('isValidForTokenExchange')->willReturn(false); + $this->tokenProvider->validateConsumer($this->consumerMock); + } + + public function testGetIntegrationTokenByConsumerId() + { + $consumerId = 1; + $tokenId = 1; + + $this->requestTokenMock->expects($this->once()) + ->method('loadByConsumerIdAndUserType') + ->with($consumerId, UserContextInterface::USER_TYPE_INTEGRATION); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->requestTokenMock); + + $this->requestTokenMock->expects($this->once())->method('getId')->willReturn($tokenId); + + $actualToken = $this->tokenProvider->getIntegrationTokenByConsumerId($consumerId); + $this->assertEquals($this->requestTokenMock, $actualToken); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage A token with consumer ID 1 does not exist + */ + public function testGetIntegrationTokenByConsumerIdException() + { + $consumerId = 1; + $tokenId = false; + + $this->requestTokenMock->expects($this->once()) + ->method('loadByConsumerIdAndUserType') + ->with($consumerId, UserContextInterface::USER_TYPE_INTEGRATION); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->requestTokenMock); + + $this->requestTokenMock->expects($this->once())->method('getId')->willReturn($tokenId); + + $this->tokenProvider->getIntegrationTokenByConsumerId($consumerId); + } + + public function testCreateRequestToken() + { + $consumerId = 1; + $tokenId = 1; + $tokenString = '12345678901234567890123456789012'; + $secret = 'secret'; + + $tokenMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\Token') + ->setMethods( + [ + 'loadByConsumerIdAndUserType', + 'getId', + 'getType', + 'createRequestToken' + ] + ) + ->disableOriginalConstructor() + ->getMock(); + + $tokenMock->expects($this->once()) + ->method('loadByConsumerIdAndUserType') + ->with($consumerId, UserContextInterface::USER_TYPE_INTEGRATION); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($tokenMock); + + $tokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + $tokenMock->expects($this->once())->method('createRequestToken')->willReturn( + $this->requestTokenMock + ); + $tokenMock->expects($this->any())->method('getType')->willReturn(Token::TYPE_VERIFIER); + + $this->consumerMock->expects($this->once())->method('getId')->willReturn($consumerId); + $this->consumerMock->expects($this->once())->method('getCallbackUrl'); + + $this->requestTokenMock->expects($this->any())->method('getToken')->willReturn($tokenString); + $this->requestTokenMock->expects($this->any())->method('getSecret')->willReturn($secret); + $response = $this->tokenProvider->createRequestToken($this->consumerMock); + + $this->assertArrayHasKey('oauth_token', $response); + $this->assertArrayHasKey('oauth_token_secret', $response); + $this->assertEquals($tokenString, $response['oauth_token']); + $this->assertEquals($secret, $response['oauth_token_secret']); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Cannot create request token because consumer token is not a verifier token + */ + public function testCreateRequestTokenIncorrectType() + { + $consumerId = 1; + $tokenId = 1; + + $tokenMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\Token') + ->setMethods( + [ + 'loadByConsumerIdAndUserType', + 'getId', + 'getType', + 'createRequestToken' + ] + ) + ->disableOriginalConstructor() + ->getMock(); + + $tokenMock->expects($this->once()) + ->method('loadByConsumerIdAndUserType') + ->with($consumerId, UserContextInterface::USER_TYPE_INTEGRATION); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($tokenMock); + + $tokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + $tokenMock->expects($this->any())->method('getType')->willReturn('incorrectType'); + + $this->consumerMock->expects($this->once())->method('getId')->willReturn($consumerId); + + $this->tokenProvider->createRequestToken($this->consumerMock); + } + + public function testGetAccessToken() + { + $consumerId = 1; + $tokenId = 1; + $tokenString = '12345678901234567890123456789012'; + $secret = 'secret'; + + $this->consumerMock->expects($this->once())->method('getId')->willReturn($consumerId); + + $this->requestTokenMock->expects($this->once()) + ->method('loadByConsumerIdAndUserType') + ->with($consumerId, UserContextInterface::USER_TYPE_INTEGRATION); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->requestTokenMock); + + $this->requestTokenMock->expects($this->once())->method('getId')->willReturn($tokenId); + $this->requestTokenMock->expects($this->once())->method('getType')->willReturn(Token::TYPE_REQUEST); + $this->requestTokenMock->expects($this->once())->method('convertToAccess')->willReturn($this->accessTokenMock); + $this->accessTokenMock->expects($this->once())->method('getToken')->willReturn($tokenString); + $this->accessTokenMock->expects($this->once())->method('getSecret')->willReturn($secret); + + $response = $this->tokenProvider->getAccessToken($this->consumerMock); + $this->assertArrayHasKey('oauth_token', $response); + $this->assertArrayHasKey('oauth_token_secret', $response); + $this->assertEquals($tokenString, $response['oauth_token']); + $this->assertEquals($secret, $response['oauth_token_secret']); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Cannot get access token because consumer token is not a request token + */ + public function testGetAccessTokenIsNotRequestToken() + { + $consumerId = 1; + $tokenId = 1; + + $this->consumerMock->expects($this->once())->method('getId')->willReturn($consumerId); + + $this->requestTokenMock->expects($this->once()) + ->method('loadByConsumerIdAndUserType') + ->with($consumerId, UserContextInterface::USER_TYPE_INTEGRATION); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->requestTokenMock); + + $this->requestTokenMock->expects($this->once())->method('getId')->willReturn($tokenId); + $this->requestTokenMock->expects($this->once())->method('getType')->willReturn('isNotRequestToken'); + + $this->tokenProvider->getAccessToken($this->consumerMock); + } + + public function testValidateRequestToken() + { + $requestTokenString = '12345678901234567890123456789012'; + $oauthVerifier = '12345678901234567890123456789012'; + $consumerId = 1; + $tokenId = 1; + $secret = 'secret'; + + $this->requestTokenMock->expects($this->once()) + ->method('load') + ->with($requestTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->requestTokenMock); + $this->requestTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + $this->requestTokenMock->expects($this->once())->method('getConsumerId')->willReturn($consumerId); + + $this->requestTokenMock->expects($this->once())->method('getType')->willReturn(Token::TYPE_REQUEST); + $this->requestTokenMock->expects($this->once())->method('getSecret')->willReturn($secret); + $this->requestTokenMock->expects($this->once())->method('getVerifier')->willReturn($oauthVerifier); + + $this->assertEquals( + $secret, + $this->tokenProvider->validateRequestToken($requestTokenString, $this->consumerMock, $oauthVerifier) + ); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Specified token does not exist + */ + public function testValidateRequestTokenNotExistentToken() + { + $requestTokenString = '12345678901234567890123456789012'; + $oauthVerifier = '12345678901234567890123456789012'; + + $this->requestTokenMock->expects($this->once()) + ->method('load') + ->with($requestTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->requestTokenMock); + $this->requestTokenMock->expects($this->any())->method('getId')->willReturn(0); + + $this->tokenProvider->validateRequestToken($requestTokenString, $this->consumerMock, $oauthVerifier); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Token is not the correct length + */ + public function testValidateRequestTokenIncorrectLengthToken() + { + $requestTokenString = '123'; + $oauthVerifier = '12345678901234567890123456789012'; + + $this->tokenProvider->validateRequestToken($requestTokenString, $this->consumerMock, $oauthVerifier); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Verifier is invalid + */ + public function testValidateRequestTokenInvalidVerifier() + { + $requestTokenString = '12345678901234567890123456789012'; + $oauthVerifier = 1; + $consumerId = 1; + $tokenId = 1; + + $this->requestTokenMock->expects($this->once()) + ->method('load') + ->with($requestTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->requestTokenMock); + $this->requestTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + $this->requestTokenMock->expects($this->once())->method('getConsumerId')->willReturn($consumerId); + + $this->requestTokenMock->expects($this->once())->method('getType')->willReturn(Token::TYPE_REQUEST); + $this->requestTokenMock->expects($this->once())->method('getVerifier')->willReturn($oauthVerifier); + + $this->tokenProvider->validateRequestToken($requestTokenString, $this->consumerMock, $oauthVerifier); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Verifier is not the correct length + */ + public function testValidateRequestTokenIncorrectLengthVerifier() + { + $requestTokenString = '12345678901234567890123456789012'; + $oauthVerifier = '123'; + $consumerId = 1; + $tokenId = 1; + + $this->requestTokenMock->expects($this->once()) + ->method('load') + ->with($requestTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->requestTokenMock); + $this->requestTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + $this->requestTokenMock->expects($this->once())->method('getConsumerId')->willReturn($consumerId); + + $this->requestTokenMock->expects($this->once())->method('getType')->willReturn(Token::TYPE_REQUEST); + $this->requestTokenMock->expects($this->once())->method('getVerifier')->willReturn($oauthVerifier); + + $this->tokenProvider->validateRequestToken($requestTokenString, $this->consumerMock, $oauthVerifier); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Token verifier and verifier token do not match + */ + public function testValidateRequestTokenNotMatchedVerifier() + { + $requestTokenString = '12345678901234567890123456789012'; + $oauthVerifier = '12345678901234567890123456789012'; + $notMatchedVerifier = '123'; + $consumerId = 1; + $tokenId = 1; + + $this->requestTokenMock->expects($this->once()) + ->method('load') + ->with($requestTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->requestTokenMock); + $this->requestTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + $this->requestTokenMock->expects($this->once())->method('getConsumerId')->willReturn($consumerId); + + $this->requestTokenMock->expects($this->once())->method('getType')->willReturn(Token::TYPE_REQUEST); + $this->requestTokenMock->expects($this->once())->method('getVerifier')->willReturn($notMatchedVerifier); + + $this->tokenProvider->validateRequestToken($requestTokenString, $this->consumerMock, $oauthVerifier); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Request token is not associated with the specified consumer + */ + public function testValidateRequestTokenNotAssociatedToken() + { + $requestTokenString = '12345678901234567890123456789012'; + $oauthVerifier = '12345678901234567890123456789012'; + $consumerId = 1; + $notCustomerId = 2; + $tokenId = 1; + + $this->requestTokenMock->expects($this->once()) + ->method('load') + ->with($requestTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->requestTokenMock); + $this->requestTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + $this->requestTokenMock->expects($this->once())->method('getConsumerId')->willReturn($notCustomerId); + + $this->tokenProvider->validateRequestToken($requestTokenString, $this->consumerMock, $oauthVerifier); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Token is already being used + */ + public function testValidateRequestTokenAlreadyUsedToken() + { + $requestTokenString = '12345678901234567890123456789012'; + $oauthVerifier = '12345678901234567890123456789012'; + $consumerId = 1; + $tokenId = 1; + + $this->requestTokenMock->expects($this->once()) + ->method('load') + ->with($requestTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->requestTokenMock); + $this->requestTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + $this->requestTokenMock->expects($this->once())->method('getConsumerId')->willReturn($consumerId); + + $this->requestTokenMock->expects($this->once())->method('getType')->willReturn('alreadyUsedToken'); + + $this->tokenProvider->validateRequestToken($requestTokenString, $this->consumerMock, $oauthVerifier); + } + + public function testValidateAccessTokenRequest() + { + $accessTokenString = '12345678901234567890123456789012'; + $tokenId = 1; + $consumerId = 1; + $secret = 'secret'; + + $this->accessTokenMock->expects($this->once()) + ->method('load') + ->with($accessTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->accessTokenMock); + $this->accessTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + $this->accessTokenMock->expects($this->once())->method('getConsumerId')->willReturn($consumerId); + + $this->accessTokenMock->expects($this->once())->method('getType')->willReturn(Token::TYPE_ACCESS); + $this->accessTokenMock->expects($this->once())->method('getRevoked')->willReturn(0); + + $this->accessTokenMock->expects($this->once())->method('getSecret')->willReturn($secret); + + $this->assertEquals( + $secret, + $this->tokenProvider->validateAccessTokenRequest($accessTokenString, $this->consumerMock) + ); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Token is not associated with the specified consumer + */ + public function testValidateAccessTokenRequestNotAssociatedToken() + { + $accessTokenString = '12345678901234567890123456789012'; + $tokenId = 1; + $consumerId = 1; + $notCustomerId = 2; + + $this->accessTokenMock->expects($this->once()) + ->method('load') + ->with($accessTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->accessTokenMock); + $this->accessTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + $this->accessTokenMock->expects($this->once())->method('getConsumerId')->willReturn($notCustomerId); + + $this->tokenProvider->validateAccessTokenRequest($accessTokenString, $this->consumerMock); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Token is not an access token + */ + public function testValidateAccessTokenRequestNotAccessToken() + { + $accessTokenString = '12345678901234567890123456789012'; + $tokenId = 1; + $consumerId = 1; + + $this->accessTokenMock->expects($this->once()) + ->method('load') + ->with($accessTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->accessTokenMock); + $this->accessTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + $this->accessTokenMock->expects($this->once())->method('getConsumerId')->willReturn($consumerId); + + $this->accessTokenMock->expects($this->once())->method('getType')->willReturn('notAccessToken'); + + $this->tokenProvider->validateAccessTokenRequest($accessTokenString, $this->consumerMock); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Access token has been revoked + */ + public function testValidateAccessTokenRequestRevokedToken() + { + $accessTokenString = '12345678901234567890123456789012'; + $tokenId = 1; + $consumerId = 1; + + $this->accessTokenMock->expects($this->once()) + ->method('load') + ->with($accessTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->accessTokenMock); + $this->accessTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + $this->accessTokenMock->expects($this->once())->method('getConsumerId')->willReturn($consumerId); + + $this->accessTokenMock->expects($this->once())->method('getType')->willReturn(Token::TYPE_ACCESS); + $this->accessTokenMock->expects($this->once())->method('getRevoked')->willReturn(1); + + $this->tokenProvider->validateAccessTokenRequest($accessTokenString, $this->consumerMock); + } + + public function testValidateAccessToken() + { + $accessTokenString = '12345678901234567890123456789012'; + $tokenId = 1; + $consumerId = 1; + + $this->accessTokenMock->expects($this->once()) + ->method('load') + ->with($accessTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->accessTokenMock); + $this->accessTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->accessTokenMock->expects($this->any())->method('getConsumerId')->willReturn($consumerId); + + $this->consumerFactoryMock->expects($this->any())->method('create')->willReturn($this->consumerMock); + $this->consumerMock->expects($this->any())->method('load')->willReturnSelf(); + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + + $this->accessTokenMock->expects($this->once())->method('getType')->willReturn(Token::TYPE_ACCESS); + $this->accessTokenMock->expects($this->once())->method('getRevoked')->willReturn(0); + $this->assertEquals( + $consumerId, + $this->tokenProvider->validateAccessToken($accessTokenString) + ); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage A consumer with the ID 1 does not exist + */ + public function testValidateAccessTokenNotExistentConsumer() + { + $accessTokenString = '12345678901234567890123456789012'; + $tokenId = 1; + $consumerId = 1; + + $this->accessTokenMock->expects($this->once()) + ->method('load') + ->with($accessTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->accessTokenMock); + $this->accessTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->accessTokenMock->expects($this->any())->method('getConsumerId')->willReturn($consumerId); + + $this->consumerFactoryMock->expects($this->any())->method('create')->willReturn($this->consumerMock); + $this->consumerMock->expects($this->any())->method('load')->willReturnSelf(); + $this->consumerMock->expects($this->any())->method('getId')->willReturn(0); + + $this->tokenProvider->validateAccessToken($accessTokenString); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Token is not an access token + */ + public function testValidateAccessTokenNotAccessToken() + { + $accessTokenString = '12345678901234567890123456789012'; + $tokenId = 1; + $consumerId = 1; + + $this->accessTokenMock->expects($this->once()) + ->method('load') + ->with($accessTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->accessTokenMock); + $this->accessTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->accessTokenMock->expects($this->any())->method('getConsumerId')->willReturn($consumerId); + + $this->consumerFactoryMock->expects($this->any())->method('create')->willReturn($this->consumerMock); + $this->consumerMock->expects($this->any())->method('load')->willReturnSelf(); + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + + $this->accessTokenMock->expects($this->once())->method('getType')->willReturn('notAccessToken'); + $this->tokenProvider->validateAccessToken($accessTokenString); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Access token has been revoked + */ + public function testValidateAccessTokenRevoked() + { + $accessTokenString = '12345678901234567890123456789012'; + $tokenId = 1; + $consumerId = 1; + + $this->accessTokenMock->expects($this->once()) + ->method('load') + ->with($accessTokenString, 'token') + ->willReturnSelf(); + $this->tokenFactoryMock->expects($this->once())->method('create')->willReturn($this->accessTokenMock); + $this->accessTokenMock->expects($this->any())->method('getId')->willReturn($tokenId); + + $this->accessTokenMock->expects($this->any())->method('getConsumerId')->willReturn($consumerId); + + $this->consumerFactoryMock->expects($this->any())->method('create')->willReturn($this->consumerMock); + $this->consumerMock->expects($this->any())->method('load')->willReturnSelf(); + $this->consumerMock->expects($this->any())->method('getId')->willReturn($consumerId); + + $this->accessTokenMock->expects($this->once())->method('getType')->willReturn(Token::TYPE_ACCESS); + $this->accessTokenMock->expects($this->once())->method('getRevoked')->willReturn(1); + + $this->tokenProvider->validateAccessToken($accessTokenString); + } + + public function testValidateOauthToken() + { + $tokenString = '12345678901234567890123456789012'; + $this->assertTrue($this->tokenProvider->validateOauthToken($tokenString)); + } + + public function testGetConsumerByKey() + { + $consumerKeyString = '12345678901234567890123456789012'; + $consumerId = 1; + + $this->consumerFactoryMock->expects($this->once())->method('create')->willReturn($this->consumerMock); + $this->consumerMock->expects($this->once())->method('loadByKey')->with($consumerKeyString)->willReturnSelf(); + $this->consumerMock->expects($this->once())->method('getId')->willReturn($consumerId); + + $this->assertEquals($this->consumerMock, $this->tokenProvider->getConsumerByKey($consumerKeyString)); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Consumer key is not the correct length + */ + public function testGetConsumerByKeyWrongConsumerKey() + { + $consumerKeyString = '123'; + $this->tokenProvider->getConsumerByKey($consumerKeyString); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage A consumer having the specified key does not exist + */ + public function testGetConsumerByKeyNonExistentConsumer() + { + $consumerKeyString = '12345678901234567890123456789012'; + $consumerId = null; + + $this->consumerFactoryMock->expects($this->once())->method('create')->willReturn($this->consumerMock); + $this->consumerMock->expects($this->once())->method('loadByKey')->with($consumerKeyString)->willReturnSelf(); + $this->consumerMock->expects($this->once())->method('getId')->willReturn($consumerId); + + $this->tokenProvider->getConsumerByKey($consumerKeyString); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/Oauth/TokenTest.php b/app/code/Magento/Integration/Test/Unit/Model/Oauth/TokenTest.php new file mode 100644 index 0000000000000000000000000000000000000000..86cc9171c52cc1c017947ea19c8f89862fb364d2 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Oauth/TokenTest.php @@ -0,0 +1,527 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Integration\Test\Unit\Model\Oauth; + +use Magento\Integration\Model\Oauth\Consumer\Validator\KeyLengthFactory; +use Magento\Integration\Model\Oauth\Token; +use Magento\Framework\Oauth\Helper\Oauth as OauthHelper; +use Magento\Authorization\Model\UserContextInterface; +use Magento\Framework\TestFramework\Unit\Matcher\MethodInvokedAtIndex; + +/** + * Unit test for \Magento\Integration\Model\Oauth\Nonce + */ +class TokenTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Integration\Model\Oauth\Token + */ + protected $tokenModel; + + /** + * @var \Magento\Framework\Model\Context|\PHPUnit_Framework_MockObject_MockObject + */ + protected $contextMock; + + /** + * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + */ + protected $registryMock; + + /** + * @var KeyLengthFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $keyLengthFactoryMock; + + /** + * @var \Magento\Integration\Model\Oauth\Consumer\Validator\KeyLength|\PHPUnit_Framework_MockObject_MockObject + */ + protected $validatorKeyLengthMock; + + /** + * @var \Magento\Framework\Url\Validator|\PHPUnit_Framework_MockObject_MockObject + */ + protected $validatorMock; + + /** + * @var \Magento\Framework\Stdlib\DateTime|\PHPUnit_Framework_MockObject_MockObject + */ + protected $dateTimeMock; + + /** + * @var \Magento\Integration\Model\Oauth\ConsumerFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $consumerFactoryMock; + + /** + * @var \Magento\Integration\Helper\Oauth\Data|\PHPUnit_Framework_MockObject_MockObject + */ + protected $oauthDataMock; + + /** + * @var \Magento\Framework\Oauth\Helper\Oauth|\PHPUnit_Framework_MockObject_MockObject + */ + protected $oauthHelperMock; + + /** + * @var \Magento\Framework\Model\Resource\AbstractResource|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceMock; + + protected function setUp() + { + $this->contextMock = $this->getMockBuilder('Magento\Framework\Model\Context') + ->setMethods(['getEventDispatcher']) + ->disableOriginalConstructor() + ->getMock(); + + $this->registryMock = $this->getMockBuilder('Magento\Framework\Registry') + ->disableOriginalConstructor() + ->getMock(); + + $this->validatorKeyLengthMock = $this->getMockBuilder( + 'Magento\Integration\Model\Oauth\Consumer\Validator\KeyLength' + ) + ->setMethods(['isValid', 'setLength', 'setName', 'getMessages']) + ->disableOriginalConstructor() + ->getMock(); + + $this->keyLengthFactoryMock = $this->getMockBuilder( + 'Magento\Integration\Model\Oauth\Consumer\Validator\KeyLengthFactory' + ) + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->validatorMock = $this->getMockBuilder('Magento\Framework\Url\Validator') + ->disableOriginalConstructor() + ->getMock(); + + $this->dateTimeMock = $this->getMockBuilder('Magento\Framework\Stdlib\DateTime') + ->disableOriginalConstructor() + ->getMock(); + + $this->consumerFactoryMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\ConsumerFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->oauthDataMock = $this->getMockBuilder('Magento\Integration\Helper\Oauth\Data') + ->setMethods(['isCleanupProbability', 'getCleanupExpirationPeriod']) + ->disableOriginalConstructor() + ->getMock(); + + $this->oauthHelperMock = $this->getMockBuilder('Magento\Framework\Oauth\Helper\Oauth') + ->disableOriginalConstructor() + ->getMock(); + + $this->resourceMock = $this->getMockBuilder('Magento\Framework\Model\Resource\AbstractResource') + ->setMethods( + [ + 'getIdFieldName', + 'deleteOldEntries', + '_construct', + '_getReadAdapter', + '_getWriteAdapter', + 'selectTokenByType', + 'save', + 'selectTokenByConsumerIdAndUserType', + 'selectTokenByAdminId', + 'selectTokenByCustomerId', + 'load' + ] + ) + ->disableOriginalConstructor() + ->getMock(); + + $this->resourceMock->expects($this->any()) + ->method('getIdFieldName') + ->willReturn('id'); + + $eventManagerMock = $this->getMockBuilder('Magento\Framework\Event\ManagerInterface') + ->setMethods(['dispatch']) + ->disableOriginalConstructor() + ->getMock(); + + $this->contextMock->expects($this->once()) + ->method('getEventDispatcher') + ->willReturn($eventManagerMock); + + $this->tokenModel = new \Magento\Integration\Model\Oauth\Token( + $this->contextMock, + $this->registryMock, + $this->keyLengthFactoryMock, + $this->validatorMock, + $this->dateTimeMock, + $this->consumerFactoryMock, + $this->oauthDataMock, + $this->oauthHelperMock, + $this->resourceMock + ); + } + + public function testAfterSave() + { + $this->oauthDataMock->expects($this->once())->method('isCleanupProbability')->willReturn(true); + $this->oauthDataMock->expects($this->once())->method('getCleanupExpirationPeriod')->willReturn(30); + $this->resourceMock->expects($this->once())->method('deleteOldEntries')->with(30); + + $this->assertEquals($this->tokenModel, $this->tokenModel->afterSave()); + } + + public function testAfterSaveNoCleanupProbability() + { + $this->oauthDataMock->expects($this->once())->method('isCleanupProbability')->willReturn(false); + $this->oauthDataMock->expects($this->never())->method('getCleanupExpirationPeriod'); + $this->resourceMock->expects($this->never())->method('deleteOldEntries'); + + $this->assertEquals($this->tokenModel, $this->tokenModel->afterSave()); + } + + public function testCreateVerifierToken() + { + $consumerId = 1; + + $this->resourceMock->expects($this->once()) + ->method('selectTokenByType') + ->with($consumerId, Token::TYPE_VERIFIER) + ->willReturn(['id' => 123]); + + $this->oauthHelperMock->expects($this->never())->method('generateToken'); + $this->oauthHelperMock->expects($this->never())->method('generateTokenSecret'); + $this->oauthHelperMock->expects($this->never())->method('generateVerifier'); + $this->validatorMock->expects($this->never())->method('isValid'); + $this->keyLengthFactoryMock->expects($this->never())->method('create'); + $this->resourceMock->expects($this->never())->method('save'); + $this->assertEquals($this->tokenModel, $this->tokenModel->createVerifierToken($consumerId)); + } + + public function testCreateVerifierTokenIfNoTokenId() + { + $consumerId = 1; + $secret = 'secret'; + $token = 'token'; + $verifier = 'verifier'; + + $this->oauthHelperMock->expects($this->once())->method('generateTokenSecret')->willReturn($secret); + $this->oauthHelperMock->expects($this->once())->method('generateToken')->willReturn($token); + $this->oauthHelperMock->expects($this->once())->method('generateVerifier')->willReturn($verifier); + + $this->resourceMock->expects($this->once()) + ->method('selectTokenByType') + ->with($consumerId, Token::TYPE_VERIFIER) + ->willReturn([]); + + $this->tokenModel->setCallbackUrl(OauthHelper::CALLBACK_ESTABLISHED); + + $this->keyLengthFactoryMock->expects($this->once())->method('create')->willReturn( + $this->validatorKeyLengthMock + ); + $this->validatorKeyLengthMock->expects($this->exactly(3))->method('setLength'); + $this->validatorKeyLengthMock->expects($this->exactly(3))->method('setName'); + $this->validatorKeyLengthMock->expects($this->exactly(3))->method('isValid')->willReturn(true); + $this->resourceMock->expects($this->once())->method('save'); + $this->assertEquals($this->tokenModel, $this->tokenModel->createVerifierToken($consumerId)); + } + + /** + * @expectedException \Magento\Framework\Oauth\Exception + * @expectedExceptionMessage Cannot convert to access token due to token is not request type + */ + public function testConvertToAccessIfIsNotRequestType() + { + $this->tokenModel->setType('isNotRequestType'); + $this->tokenModel->convertToAccess(); + } + + public function testConvertToAccess() + { + $token = 'token'; + $secret = 'secret'; + + $this->tokenModel->setType(Token::TYPE_REQUEST); + $this->oauthHelperMock->expects($this->once())->method('generateToken')->willReturn($token); + $this->oauthHelperMock->expects($this->once())->method('generateTokenSecret')->willReturn($secret); + $this->resourceMock->expects($this->once())->method('save'); + + $result = $this->tokenModel->convertToAccess(); + $this->assertEquals($this->tokenModel, $result); + $this->assertEquals($token, $result->getToken()); + $this->assertEquals($secret, $result->getSecret()); + $this->assertEquals(UserContextInterface::USER_TYPE_INTEGRATION, $result->getUserType()); + } + + public function testCreateAdminToken() + { + $userId = 1; + $token = 'token'; + $secret = 'secret'; + + $this->oauthHelperMock->expects($this->once())->method('generateToken')->willReturn($token); + $this->oauthHelperMock->expects($this->once())->method('generateTokenSecret')->willReturn($secret); + $this->resourceMock->expects($this->once())->method('save'); + + $result = $this->tokenModel->createAdminToken($userId); + $this->assertEquals($this->tokenModel, $result); + $this->assertEquals($token, $result->getToken()); + $this->assertEquals($secret, $result->getSecret()); + $this->assertEquals($userId, $result->getAdminId()); + $this->assertEquals(UserContextInterface::USER_TYPE_ADMIN, $result->getUserType()); + } + + public function testCreateCustomerToken() + { + $userId = 1; + $token = 'token'; + $secret = 'secret'; + + $this->oauthHelperMock->expects($this->once())->method('generateToken')->willReturn($token); + $this->oauthHelperMock->expects($this->once())->method('generateTokenSecret')->willReturn($secret); + $this->resourceMock->expects($this->once())->method('save'); + + $result = $this->tokenModel->createCustomerToken($userId); + $this->assertEquals($this->tokenModel, $result); + $this->assertEquals($token, $result->getToken()); + $this->assertEquals($secret, $result->getSecret()); + $this->assertEquals($userId, $result->getCustomerId()); + $this->assertNotEquals($userId, $result->getAdminId()); + $this->assertEquals(UserContextInterface::USER_TYPE_CUSTOMER, $result->getUserType()); + } + + public function testCreateRequestToken() + { + $entityId = 1; + $callbackUrl = OauthHelper::CALLBACK_ESTABLISHED; + $token = 'token'; + $secret = 'secret'; + + $this->oauthHelperMock->expects($this->once())->method('generateTokenSecret')->willReturn($secret); + $this->oauthHelperMock->expects($this->once())->method('generateToken')->willReturn($token); + + $this->tokenModel->setCallbackUrl($callbackUrl); + $this->keyLengthFactoryMock->expects($this->once())->method('create')->willReturn( + $this->validatorKeyLengthMock + ); + $this->validatorKeyLengthMock->expects($this->exactly(2))->method('setLength'); + $this->validatorKeyLengthMock->expects($this->exactly(2))->method('setName'); + $this->validatorKeyLengthMock->expects($this->exactly(2))->method('isValid')->willReturn(true); + $this->resourceMock->expects($this->once())->method('save'); + + $actualToken = $this->tokenModel->createRequestToken($entityId, $callbackUrl); + $this->assertEquals($this->tokenModel, $actualToken); + $this->assertEquals($this->tokenModel->getSecret(), $actualToken->getSecret()); + $this->assertEquals($this->tokenModel->getToken(), $actualToken->getToken()); + } + + public function testToString() + { + $token = 'token'; + $secret = 'secret'; + $expectedResponse = "oauth_token={$token}&oauth_token_secret={$secret}"; + + $this->tokenModel->setToken($token)->setSecret($secret); + + $this->assertEquals($expectedResponse, sprintf($this->tokenModel)); + } + + public function testBeforeSave() + { + $this->assertEquals($this->tokenModel, $this->tokenModel->beforeSave()); + } + + public function testGetVerifier() + { + $verifier = 'testVerifier'; + $this->tokenModel->setData('verifier', $verifier); + $this->assertEquals($verifier, $this->tokenModel->getVerifier()); + } + + public function testLoadByConsumerIdAndUserType() + { + $consumerId = 1; + $userType = 1; + $tokenData = 'testToken'; + $data = ['token' => $tokenData]; + + $this->resourceMock->expects($this->once())->method('selectTokenByConsumerIdAndUserType')->willReturn($data); + $actualToken = $this->tokenModel->loadByConsumerIdAndUserType($consumerId, $userType); + $this->assertEquals($this->tokenModel, $actualToken); + $this->assertEquals($tokenData, $actualToken->getToken()); + } + + public function testLoadByAdminId() + { + $adminId = 1; + $tokenData = 'testToken'; + $data = ['token' => $tokenData]; + + $this->resourceMock->expects($this->once())->method('selectTokenByAdminId')->willReturn($data); + $actualToken = $this->tokenModel->loadByAdminId($adminId); + $this->assertEquals($this->tokenModel, $actualToken); + $this->assertEquals($tokenData, $actualToken->getToken()); + } + + public function testLoadByCustomerId() + { + $customerId = 1; + $tokenData = 'testToken'; + $data = ['token' => $tokenData]; + + $this->resourceMock->expects($this->once())->method('selectTokenByCustomerId')->willReturn($data); + $actualToken = $this->tokenModel->loadByCustomerId($customerId); + $this->assertEquals($this->tokenModel, $actualToken); + $this->assertEquals($tokenData, $actualToken->getToken()); + } + + public function testLoad() + { + $token = 'testToken'; + + $this->resourceMock->expects($this->once())->method('load'); + $actualToken = $this->tokenModel->loadByToken($token); + $this->assertEquals($this->tokenModel, $actualToken); + } + + public function testValidateIfNotCallbackEstablishedAndNotValid() + { + $exceptionMessage = 'exceptionMessage'; + + $this->tokenModel->setCallbackUrl('notCallbackEstablished'); + $this->validatorMock->expects($this->once())->method('isValid')->willReturn(false); + $this->validatorMock->expects($this->once())->method('getMessages')->willReturn([$exceptionMessage]); + + $this->setExpectedException('\Magento\Framework\Oauth\Exception', $exceptionMessage); + + $this->tokenModel->validate(); + } + + public function testValidateIfSecretNotValid() + { + $exceptionMessage = 'exceptionMessage'; + + $this->tokenModel->setCallbackUrl('notCallbackEstablished'); + $this->validatorMock->expects($this->once())->method('isValid')->willReturn(true); + + $this->keyLengthFactoryMock->expects($this->once())->method('create')->willReturn( + $this->validatorKeyLengthMock + ); + $this->validatorKeyLengthMock->expects($this->once())->method('isValid')->willReturn(false); + $this->validatorKeyLengthMock->expects($this->once())->method('getMessages')->willReturn([$exceptionMessage]); + + $this->setExpectedException('\Magento\Framework\Oauth\Exception', $exceptionMessage); + + $this->tokenModel->validate(); + } + + public function testValidateIfTokenNotValid() + { + $exceptionMessage = 'exceptionMessage'; + $token = 'token'; + $secret = 'secret'; + + $this->tokenModel->setCallbackUrl('notCallbackEstablished'); + $this->validatorMock->expects($this->once())->method('isValid')->willReturn(true); + + $this->keyLengthFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->validatorKeyLengthMock); + + $this->tokenModel->setSecret($secret); + $this->tokenModel->setToken($token); + $this->validatorKeyLengthMock->expects($this->exactly(2))->method('isValid')->willReturnMap( + [ + [$secret, true], + [$token, false] + ] + ); + $this->validatorKeyLengthMock->expects($this->once())->method('getMessages')->willReturn([$exceptionMessage]); + $this->setExpectedException('\Magento\Framework\Oauth\Exception', $exceptionMessage); + + $this->tokenModel->validate(); + } + + public function testValidateIfVerifierNotValid() + { + $exceptionMessage = 'exceptionMessage'; + $secret = 'secret'; + $token = 'token'; + $verifier = 'isSetAndNotValid'; + + $this->tokenModel->setCallbackUrl('notCallbackEstablished'); + $this->validatorMock->expects($this->once())->method('isValid')->willReturn(true); + + $this->keyLengthFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->validatorKeyLengthMock); + + $this->tokenModel->setSecret($secret); + $this->tokenModel->setToken($token); + $this->tokenModel->setData('verifier', $verifier); + $this->validatorKeyLengthMock->expects($this->exactly(3))->method('isValid')->willReturnMap( + [ + [$secret, true], + [$token, true], + [$verifier, false], + ] + ); + $this->validatorKeyLengthMock->expects($this->once())->method('getMessages')->willReturn([$exceptionMessage]); + $this->setExpectedException('\Magento\Framework\Oauth\Exception', $exceptionMessage); + + $this->tokenModel->validate(); + } + + public function testValidateIfVerifierIsNotSet() + { + $token = 'token'; + $secret = 'secret'; + $verifier = null; + + $this->tokenModel->setCallbackUrl('notCallbackEstablished'); + $this->validatorMock->expects($this->once())->method('isValid')->willReturn(true); + + $this->keyLengthFactoryMock->expects($this->once())->method('create')->willReturn( + $this->validatorKeyLengthMock + ); + + $this->tokenModel->setSecret($secret); + $this->tokenModel->setToken($token); + $this->tokenModel->setData('verifier', $verifier); + $this->validatorKeyLengthMock->expects($this->exactly(2))->method('isValid')->willReturnMap( + [ + [$secret, true], + [$token, true], + ] + ); + $this->assertTrue($this->tokenModel->validate()); + } + + public function testValidate() + { + $token = 'token'; + $secret = 'secret'; + $verifier = 'verifier'; + + $this->tokenModel->setCallbackUrl('notCallbackEstablished'); + $this->validatorMock->expects($this->once())->method('isValid')->willReturn(true); + + $this->keyLengthFactoryMock->expects($this->once())->method('create')->willReturn( + $this->validatorKeyLengthMock + ); + + $this->tokenModel->setSecret($secret); + $this->tokenModel->setToken($token); + $this->tokenModel->setData('verifier', $verifier); + $this->validatorKeyLengthMock->expects($this->exactly(3))->method('isValid')->willReturnMap( + [ + [$secret, true], + [$token, true], + [$verifier, true], + ] + ); + $this->assertTrue($this->tokenModel->validate()); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/OauthServiceTest.php b/app/code/Magento/Integration/Test/Unit/Model/OauthServiceTest.php index 2346d34ff8e32547c922718ddfe4a8abdf9ed29e..ba9c3cd3563fd58bf431f11aa021f11fc40ebad2 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/OauthServiceTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/OauthServiceTest.php @@ -51,9 +51,10 @@ class OauthServiceTest extends \PHPUnit_Framework_TestCase */ protected function setUp() { - $this->_consumerFactory = $this->getMockBuilder( - 'Magento\Integration\Model\Oauth\ConsumerFactory' - )->disableOriginalConstructor()->getMock(); + $this->_consumerFactory = $this->getMockBuilder('Magento\Integration\Model\Oauth\ConsumerFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); $this->_tokenProviderMock = $this->getMockBuilder( 'Magento\Integration\Model\Oauth\Token\Provider' )->disableOriginalConstructor()->getMock(); diff --git a/app/code/Magento/Integration/Test/Unit/Model/Plugin/IntegrationTest.php b/app/code/Magento/Integration/Test/Unit/Model/Plugin/IntegrationTest.php index d1b9cdc11d9a1b65acdd36c77497f87972eea5c3..be92904717a1a41205b2207ee393eaea48e6cfe7 100644 --- a/app/code/Magento/Integration/Test/Unit/Model/Plugin/IntegrationTest.php +++ b/app/code/Magento/Integration/Test/Unit/Model/Plugin/IntegrationTest.php @@ -5,9 +5,11 @@ */ namespace Magento\Integration\Test\Unit\Model\Plugin; -use Magento\Authorization\Model\Acl\AclRetriever; use Magento\Integration\Model\Integration; +/** + * Unit test for \Magento\Integration\Model\Plugin\Integration + */ class IntegrationTest extends \PHPUnit_Framework_TestCase { /** @@ -18,15 +20,17 @@ class IntegrationTest extends \PHPUnit_Framework_TestCase protected $integrationPlugin; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Integration\Api\IntegrationServiceInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $subjectMock; - /** @var AclRetriever */ + /** + * @var \Magento\Authorization\Model\Acl\AclRetriever|\PHPUnit_Framework_MockObject_MockObject + */ protected $aclRetrieverMock; /** - * @var \Magento\Integration\Api\AuthorizationServiceInterface + * @var \Magento\Integration\Api\AuthorizationServiceInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $integrationAuthServiceMock; @@ -61,4 +65,121 @@ class IntegrationTest extends \PHPUnit_Framework_TestCase ->with($integrationId); $this->integrationPlugin->afterDelete($this->subjectMock, $integrationsData); } + + public function testAfterCreateAllResources() + { + $integrationId = 1; + $integrationModelMock = $this->getMockBuilder('Magento\Integration\Model\Integration') + ->disableOriginalConstructor() + ->getMock(); + $integrationModelMock->expects($this->exactly(2)) + ->method('getId') + ->will($this->returnValue($integrationId)); + $integrationModelMock->expects($this->once()) + ->method('getData') + ->with('all_resources') + ->will($this->returnValue(1)); + + $this->integrationAuthServiceMock->expects($this->once()) + ->method('grantAllPermissions') + ->with($integrationId); + + $this->integrationPlugin->afterCreate($this->subjectMock, $integrationModelMock); + } + + public function testAfterCreateSomeResources() + { + $integrationId = 1; + $integrationModelMock = $this->getMockBuilder('Magento\Integration\Model\Integration') + ->disableOriginalConstructor() + ->getMock(); + $integrationModelMock->expects($this->exactly(2)) + ->method('getId') + ->will($this->returnValue($integrationId)); + $integrationModelMock->expects($this->at(1)) + ->method('getData') + ->with('all_resources') + ->will($this->returnValue(null)); + $integrationModelMock->expects($this->at(2)) + ->method('getData') + ->with('resource') + ->will($this->returnValue(['testResource'])); + $integrationModelMock->expects($this->at(4)) + ->method('getData') + ->with('resource') + ->will($this->returnValue(['testResource'])); + + $this->integrationAuthServiceMock->expects($this->once()) + ->method('grantPermissions') + ->with($integrationId, ['testResource']); + + $this->integrationPlugin->afterCreate($this->subjectMock, $integrationModelMock); + } + + public function testAfterCreateNoResource() + { + $integrationId = 1; + $integrationModelMock = $this->getMockBuilder('Magento\Integration\Model\Integration') + ->disableOriginalConstructor() + ->getMock(); + $integrationModelMock->expects($this->exactly(2)) + ->method('getId') + ->will($this->returnValue($integrationId)); + $integrationModelMock->expects($this->at(1)) + ->method('getData') + ->with('all_resources') + ->will($this->returnValue(null)); + $integrationModelMock->expects($this->at(2)) + ->method('getData') + ->with('resource') + ->will($this->returnValue(null)); + + $this->integrationAuthServiceMock->expects($this->once()) + ->method('grantPermissions') + ->with($integrationId, []); + + $this->integrationPlugin->afterCreate($this->subjectMock, $integrationModelMock); + } + + public function testAfterUpdateAllResources() + { + $integrationId = 1; + $integrationModelMock = $this->getMockBuilder('Magento\Integration\Model\Integration') + ->disableOriginalConstructor() + ->getMock(); + $integrationModelMock->expects($this->exactly(2)) + ->method('getId') + ->will($this->returnValue($integrationId)); + $integrationModelMock->expects($this->once()) + ->method('getData') + ->with('all_resources') + ->will($this->returnValue(1)); + + $this->integrationAuthServiceMock->expects($this->once()) + ->method('grantAllPermissions') + ->with($integrationId); + + $this->integrationPlugin->afterUpdate($this->subjectMock, $integrationModelMock); + } + + public function testAfterGet() + { + $integrationId = 1; + $integrationModelMock = $this->getMockBuilder('Magento\Integration\Model\Integration') + ->disableOriginalConstructor() + ->getMock(); + $integrationModelMock->expects($this->exactly(2)) + ->method('getId') + ->will($this->returnValue($integrationId)); + $integrationModelMock->expects($this->once()) + ->method('setData') + ->with('resource', ['testResource']); + + $this->aclRetrieverMock->expects($this->once()) + ->method('getAllowedResourcesByUser') + ->with(\Magento\Authorization\Model\UserContextInterface::USER_TYPE_INTEGRATION, $integrationId) + ->will($this->returnValue(['testResource'])); + + $this->integrationPlugin->afterGet($this->subjectMock, $integrationModelMock); + } } diff --git a/app/code/Magento/Integration/Test/Unit/Model/Resource/Integration/CollectionTest.php b/app/code/Magento/Integration/Test/Unit/Model/Resource/Integration/CollectionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..18b43bd9628e04956850ca499c4f16e53fe95121 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Resource/Integration/CollectionTest.php @@ -0,0 +1,78 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model\Resource\Integration; + +/** + * Unit test for \Magento\Integration\Model\Resource\Integration\Collection + */ +class CollectionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject + */ + protected $select; + + /** + * @var \Magento\Integration\Model\Resource\Integration\Collection|\PHPUnit_Framework_MockObject_MockObject + */ + protected $collection; + + public function setUp() + { + $this->select = $this->getMockBuilder('Magento\Framework\DB\Select') + ->disableOriginalConstructor() + ->getMock(); + + $connection = $this->getMockBuilder('Magento\Framework\DB\Adapter\Pdo\Mysql') + ->disableOriginalConstructor() + ->getMock(); + $connection->expects($this->any()) + ->method('select') + ->will($this->returnValue($this->select)); + + $resource = $this->getMockBuilder('Magento\Framework\Model\Resource\Db\AbstractDb') + ->disableOriginalConstructor() + ->setMethods(['__wakeup', 'getReadConnection']) + ->getMockForAbstractClass(); + $resource->expects($this->any()) + ->method('getReadConnection') + ->will($this->returnValue($connection)); + + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $arguments = $objectManagerHelper->getConstructArguments( + 'Magento\Integration\Model\Resource\Integration\Collection', + ['resource' => $resource] + ); + + $this->collection = $this->getMockBuilder('Magento\Integration\Model\Resource\Integration\Collection') + ->setConstructorArgs($arguments) + ->setMethods(['addFilter', '_translateCondition', 'getMainTable']) + ->getMock(); + } + + public function testAddUnsecureUrlsFilter() + { + $this->collection->expects($this->at(0)) + ->method('_translateCondition') + ->with('endpoint', ['like' => 'http:%']) + ->will($this->returnValue('endpoint like \'http:%\'')); + + $this->collection->expects($this->at(1)) + ->method('_translateCondition') + ->with('identity_link_url', ['like' => 'http:%']) + ->will($this->returnValue('identity_link_url like \'http:%\'')); + + $this->select->expects($this->once()) + ->method('where') + ->with( + $this->equalTo('(endpoint like \'http:%\') OR (identity_link_url like \'http:%\')'), + $this->equalTo(null), + $this->equalTo(\Magento\Framework\DB\Select::TYPE_CONDITION) + ); + + $this->collection->addUnsecureUrlsFilter(); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/Resource/IntegrationTest.php b/app/code/Magento/Integration/Test/Unit/Model/Resource/IntegrationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1bfe7839c2d2ba9eb1c981fb9eb2372be2060886 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Resource/IntegrationTest.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model\Resource; + +/** + * Unit test for \Magento\Integration\Model\Resource\Integration + */ +class IntegrationTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $selectMock; + + /** + * @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject + */ + protected $adapterMock; + + /** + * @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceMock; + + /** + * @var \Magento\Framework\Model\Resource\Db\Context|\PHPUnit_Framework_MockObject_MockObject + */ + protected $contextMock; + + /** + * @var \Magento\Integration\Model\Resource\Integration + */ + protected $integrationResourceModel; + + protected function setUp() + { + $this->selectMock = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $this->selectMock->expects($this->any())->method('from')->will($this->returnValue($this->selectMock)); + $this->selectMock->expects($this->any())->method('where')->will($this->returnValue($this->selectMock)); + + $this->adapterMock = $this->getMock('Magento\Framework\DB\Adapter\Pdo\Mysql', [], [], '', false); + $this->adapterMock->expects($this->any())->method('select')->willReturn($this->selectMock); + + $this->resourceMock = $this->getMock('Magento\Framework\App\Resource', [], [], '', false); + $this->resourceMock->expects($this->any())->method('getConnection')->willReturn($this->adapterMock); + + $this->contextMock = $this->getMock('Magento\Framework\Model\Resource\Db\Context', [], [], '', false); + $this->contextMock->expects($this->once())->method('getResources')->willReturn($this->resourceMock); + + $this->integrationResourceModel = new \Magento\Integration\Model\Resource\Integration($this->contextMock); + } + + public function testSelectActiveIntegrationByConsumerId() + { + $consumerId = 1; + $this->adapterMock->expects($this->once())->method('fetchRow')->with($this->selectMock); + $this->integrationResourceModel->selectActiveIntegrationByConsumerId($consumerId); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/ConsumerTest.php b/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/ConsumerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e5e053b04a7fef1a9134c1fd55d8d1510a179a59 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/ConsumerTest.php @@ -0,0 +1,85 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model\Resource\Oauth; + +/** + * Unit test for \Magento\Integration\Model\Resource\Oauth\Consumer + */ +class ConsumerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject + */ + protected $adapterMock; + + /** + * @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceMock; + + /** + * @var \Magento\Integration\Model\Oauth\Consumer + */ + protected $consumerMock; + + /** + * @var \Magento\Integration\Model\Resource\Oauth\Consumer + */ + protected $consumerResource; + + public function setUp() + { + $this->consumerMock = $this->getMock( + 'Magento\Integration\Model\Oauth\Consumer', + ['setUpdatedAt', 'getId'], + [], + '', + false + ); + + $this->adapterMock = $this->getMock('Magento\Framework\DB\Adapter\Pdo\Mysql', [], [], '', false); + + $this->resourceMock = $this->getMock('Magento\Framework\App\Resource', [], [], '', false); + $this->resourceMock->expects($this->any())->method('getConnection')->willReturn($this->adapterMock); + + $contextMock = $this->getMock('Magento\Framework\Model\Resource\Db\Context', [], [], '', false); + $contextMock->expects($this->once())->method('getResources')->willReturn($this->resourceMock); + $this->consumerResource = new \Magento\Integration\Model\Resource\Oauth\Consumer( + $contextMock, + new \Magento\Framework\Stdlib\DateTime() + ); + } + + public function testBeforeSave() + { + $this->consumerMock->expects($this->once())->method('setUpdatedAt'); + $this->assertInstanceOf( + 'Magento\Integration\Model\Resource\Oauth\Consumer', + $this->consumerResource->_beforeSave($this->consumerMock) + ); + } + + public function testAfterDelete() + { + $this->adapterMock->expects($this->exactly(2))->method('delete'); + $this->assertInstanceOf( + 'Magento\Integration\Model\Resource\Oauth\Consumer', + $this->consumerResource->_afterDelete($this->consumerMock) + ); + } + + public function testGetTimeInSecondsSinceCreation() + { + $selectMock = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $selectMock->expects($this->any())->method('from')->will($this->returnValue($selectMock)); + $selectMock->expects($this->any())->method('reset')->will($this->returnValue($selectMock)); + $selectMock->expects($this->any())->method('columns')->will($this->returnValue($selectMock)); + $selectMock->expects($this->any())->method('where')->will($this->returnValue($selectMock)); + $this->adapterMock->expects($this->any())->method('select')->willReturn($selectMock); + $this->adapterMock->expects($this->once())->method('fetchOne'); + $this->consumerResource->getTimeInSecondsSinceCreation(1); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/NonceTest.php b/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/NonceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b27048acf857e58da3535b8265ecd2fe61f78d46 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/NonceTest.php @@ -0,0 +1,57 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model\Resource\Oauth; + +/** + * Unit test for \Magento\Integration\Model\Resource\Oauth\Nonce + */ +class NonceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject + */ + protected $adapterMock; + + /** + * @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceMock; + + /** + * @var \Magento\Integration\Model\Resource\Oauth\Nonce + */ + protected $nonceResource; + + public function setUp() + { + $this->adapterMock = $this->getMock('Magento\Framework\DB\Adapter\Pdo\Mysql', [], [], '', false); + + $this->resourceMock = $this->getMock('Magento\Framework\App\Resource', [], [], '', false); + $this->resourceMock->expects($this->any())->method('getConnection')->willReturn($this->adapterMock); + + $contextMock = $this->getMock('\Magento\Framework\Model\Resource\Db\Context', [], [], '', false); + $contextMock->expects($this->once())->method('getResources')->willReturn($this->resourceMock); + + $this->nonceResource = new \Magento\Integration\Model\Resource\Oauth\Nonce($contextMock); + } + + public function testDeleteOldEntries() + { + $this->adapterMock->expects($this->once())->method('delete'); + $this->adapterMock->expects($this->once())->method('quoteInto'); + $this->nonceResource->deleteOldEntries(5); + } + + public function testSelectByCompositeKey() + { + $selectMock = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $selectMock->expects($this->once())->method('from')->will($this->returnValue($selectMock)); + $selectMock->expects($this->exactly(2))->method('where')->will($this->returnValue($selectMock)); + $this->adapterMock->expects($this->once())->method('select')->willReturn($selectMock); + $this->adapterMock->expects($this->once())->method('fetchRow'); + $this->nonceResource->selectByCompositeKey('nonce', 5); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/Token/CollectionTest.php b/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/Token/CollectionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ed4e6fe0a73103d1a606b635de122c0f22b7f5b2 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/Token/CollectionTest.php @@ -0,0 +1,111 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model\Resource\Oauth\Token; + +/** + * Unit test for \Magento\Integration\Model\Resource\Oauth\Token\Collection + */ +class CollectionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject + */ + protected $select; + + /** + * @var \Magento\Integration\Model\Resource\Oauth\Token\Collection|\PHPUnit_Framework_MockObject_MockObject + */ + protected $collection; + + public function setUp() + { + $this->select = $this->getMockBuilder('Magento\Framework\DB\Select') + ->disableOriginalConstructor() + ->getMock(); + + $connection = $this->getMockBuilder('Magento\Framework\DB\Adapter\Pdo\Mysql') + ->disableOriginalConstructor() + ->getMock(); + $connection->expects($this->any()) + ->method('select') + ->will($this->returnValue($this->select)); + + $resource = $this->getMockBuilder('Magento\Framework\Model\Resource\Db\AbstractDb') + ->disableOriginalConstructor() + ->setMethods(['__wakeup', 'getReadConnection']) + ->getMockForAbstractClass(); + $resource->expects($this->any()) + ->method('getReadConnection') + ->will($this->returnValue($connection)); + + $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $arguments = $objectManagerHelper->getConstructArguments( + 'Magento\Integration\Model\Resource\Oauth\Token\Collection', + ['resource' => $resource] + ); + + $this->collection = $this->getMockBuilder('Magento\Integration\Model\Resource\Oauth\Token\Collection') + ->setConstructorArgs($arguments) + ->setMethods(['addFilter', 'getSelect', 'getTable', '_initSelect']) + ->getMock(); + } + + public function testJoinConsumerAsApplication() + { + $this->select->expects($this->once())->method('joinLeft'); + $this->collection->expects($this->once())->method('getSelect')->willReturn($this->select); + $this->collection->joinConsumerAsApplication(); + } + + public function testAddFilterByCustomerId() + { + $id = 1; + $this->collection->expects($this->once()) + ->method('addFilter') + ->with('main_table.customer_id', $id) + ->willReturn($this->collection); + $this->collection->addFilterByCustomerId($id); + } + + public function testAddFilterByConsumerId() + { + $id = 1; + $this->collection->expects($this->once()) + ->method('addFilter') + ->with('main_table.consumer_id', $id) + ->willReturn($this->collection); + $this->collection->addFilterByConsumerId($id); + } + + public function testAddFilterByType() + { + $type = 'type'; + $this->collection->expects($this->once()) + ->method('addFilter') + ->with('main_table.type', $type) + ->willReturn($this->collection); + $this->collection->addFilterByType($type); + } + + public function testAddFilterById() + { + $id = 1; + $this->collection->expects($this->once()) + ->method('addFilter') + ->with('main_table.entity_id', ['in' => $id], 'public') + ->willReturn($this->collection); + $this->collection->addFilterById($id); + } + + public function testAddFilterByRevoked() + { + $this->collection->expects($this->once()) + ->method('addFilter') + ->with('main_table.revoked', 1, 'public') + ->willReturn($this->collection); + $this->collection->addFilterByRevoked(true); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/TokenTest.php b/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/TokenTest.php new file mode 100644 index 0000000000000000000000000000000000000000..75b18d616769493d379b7e15725baf5321f31661 --- /dev/null +++ b/app/code/Magento/Integration/Test/Unit/Model/Resource/Oauth/TokenTest.php @@ -0,0 +1,107 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Test\Unit\Model\Resource\Oauth; + +/** + * Unit test for \Magento\Integration\Model\Resource\Oauth\Token + */ +class TokenTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject + */ + protected $adapterMock; + + /** + * @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceMock; + + /** + * @var \Magento\Integration\Model\Resource\Oauth\Token + */ + protected $tokenResource; + + public function setUp() + { + $this->adapterMock = $this->getMock('Magento\Framework\DB\Adapter\Pdo\Mysql', [], [], '', false); + + $this->resourceMock = $this->getMock('Magento\Framework\App\Resource', [], [], '', false); + $this->resourceMock->expects($this->any())->method('getConnection')->willReturn($this->adapterMock); + + $contextMock = $this->getMock('\Magento\Framework\Model\Resource\Db\Context', [], [], '', false); + $contextMock->expects($this->once())->method('getResources')->willReturn($this->resourceMock); + + $this->tokenResource = new \Magento\Integration\Model\Resource\Oauth\Token( + $contextMock, + new \Magento\Framework\Stdlib\DateTime() + ); + } + + public function testCleanOldAuthorizedTokensExcept() + { + $tokenMock = $this->getMock( + 'Magento\Integration\Model\Oauth\Token', + ['getId', 'getAuthorized', 'getConsumerId', 'getCustomerId', 'getAdminId'], + [], + '', + false + ); + $tokenMock->expects($this->any())->method('getId')->willReturn(1); + $tokenMock->expects($this->once())->method('getAuthorized')->willReturn(true); + $tokenMock->expects($this->any())->method('getCustomerId')->willReturn(1); + $this->adapterMock->expects($this->any())->method('quoteInto'); + $this->adapterMock->expects($this->once())->method('delete'); + $this->tokenResource->cleanOldAuthorizedTokensExcept($tokenMock); + } + + public function testDeleteOldEntries() + { + $this->adapterMock->expects($this->once())->method('delete'); + $this->adapterMock->expects($this->once())->method('quoteInto'); + $this->tokenResource->deleteOldEntries(5); + } + + public function testSelectTokenByType() + { + $selectMock = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $selectMock->expects($this->once())->method('from')->will($this->returnValue($selectMock)); + $selectMock->expects($this->exactly(2))->method('where')->will($this->returnValue($selectMock)); + $this->adapterMock->expects($this->once())->method('select')->willReturn($selectMock); + $this->adapterMock->expects($this->once())->method('fetchRow'); + $this->tokenResource->selectTokenByType(5, 'nonce'); + } + + public function testSelectTokenByConsumerIdAndUserType() + { + $selectMock = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $selectMock->expects($this->once())->method('from')->will($this->returnValue($selectMock)); + $selectMock->expects($this->exactly(2))->method('where')->will($this->returnValue($selectMock)); + $this->adapterMock->expects($this->once())->method('select')->willReturn($selectMock); + $this->adapterMock->expects($this->once())->method('fetchRow'); + $this->tokenResource->selectTokenByConsumerIdAndUserType(5, 'nonce'); + } + + public function testSelectTokenByAdminId() + { + $selectMock = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $selectMock->expects($this->once())->method('from')->will($this->returnValue($selectMock)); + $selectMock->expects($this->exactly(2))->method('where')->will($this->returnValue($selectMock)); + $this->adapterMock->expects($this->once())->method('select')->willReturn($selectMock); + $this->adapterMock->expects($this->once())->method('fetchRow'); + $this->tokenResource->selectTokenByAdminId(5); + } + + public function testSelectTokenByCustomerId() + { + $selectMock = $this->getMock('Magento\Framework\DB\Select', [], [], '', false); + $selectMock->expects($this->once())->method('from')->will($this->returnValue($selectMock)); + $selectMock->expects($this->exactly(2))->method('where')->will($this->returnValue($selectMock)); + $this->adapterMock->expects($this->once())->method('select')->willReturn($selectMock); + $this->adapterMock->expects($this->once())->method('fetchRow'); + $this->tokenResource->selectTokenByCustomerId(5); + } +} diff --git a/app/code/Magento/Integration/Test/Unit/Oauth/OauthTest.php b/app/code/Magento/Integration/Test/Unit/Oauth/OauthTest.php index 525614047c7d8349f42092e865229a631dcc12f6..5012a69aed0f22d926a05d5b8cd02b5a55fe6578 100644 --- a/app/code/Magento/Integration/Test/Unit/Oauth/OauthTest.php +++ b/app/code/Magento/Integration/Test/Unit/Oauth/OauthTest.php @@ -59,6 +59,7 @@ class OauthTest extends \PHPUnit_Framework_TestCase { $this->_consumerFactory = $this->getMockBuilder('Magento\Integration\Model\Oauth\ConsumerFactory') ->disableOriginalConstructor() + ->setMethods(['create']) ->getMock(); $this->_consumerMock = $this->getMockBuilder('Magento\Integration\Model\Oauth\Consumer') ->disableOriginalConstructor()->setMethods( @@ -79,9 +80,10 @@ class OauthTest extends \PHPUnit_Framework_TestCase $this->_consumerFactory->expects($this->any()) ->method('create') ->will($this->returnValue($this->_consumerMock)); - $this->_nonceFactory = $this->getMockBuilder( - 'Magento\Integration\Model\Oauth\NonceFactory' - )->disableOriginalConstructor()->getMock(); + $this->_nonceFactory = $this->getMockBuilder('Magento\Integration\Model\Oauth\NonceFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); $this->_tokenFactory = $this->getMockBuilder( 'Magento\Integration\Model\Oauth\TokenFactory' )->disableOriginalConstructor()->setMethods(['create'])->getMock(); diff --git a/app/code/Magento/Integration/composer.json b/app/code/Magento/Integration/composer.json index 8d6d9ba3d6454b1a0cb45d16abcdeac58ace3827..e7522cbdd35551484344ff6d2e89df0259344269 100644 --- a/app/code/Magento/Integration/composer.json +++ b/app/code/Magento/Integration/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-user": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-authorization": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-user": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-authorization": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/LayeredNavigation/composer.json b/app/code/Magento/LayeredNavigation/composer.json index f61ca72c1657c9c925f05fd48e93f1ca077e6b39..bdc20c0270c5158053c633cfcfad014a842cbcb3 100644 --- a/app/code/Magento/LayeredNavigation/composer.json +++ b/app/code/Magento/LayeredNavigation/composer.json @@ -3,13 +3,13 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Log/Model/Aggregation.php b/app/code/Magento/Log/Model/Aggregation.php index 30046eeb81353401489020c17e019ec12b862301..ccfca2cdec7bd4619deba3187a397a573f1242d9 100644 --- a/app/code/Magento/Log/Model/Aggregation.php +++ b/app/code/Magento/Log/Model/Aggregation.php @@ -32,7 +32,7 @@ class Aggregation extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -40,7 +40,7 @@ class Aggregation extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_storeManager = $storeManager; diff --git a/app/code/Magento/Log/Model/Cron.php b/app/code/Magento/Log/Model/Cron.php index 80396b78c15d65db02107c5660b066aa72969fa8..d69cc88970d734dd54df0d5ed0e8b2a4b1a795c2 100644 --- a/app/code/Magento/Log/Model/Cron.php +++ b/app/code/Magento/Log/Model/Cron.php @@ -64,7 +64,7 @@ class Cron extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -77,7 +77,7 @@ class Cron extends \Magento\Framework\Model\AbstractModel \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_transportBuilder = $transportBuilder; diff --git a/app/code/Magento/Log/Model/Customer.php b/app/code/Magento/Log/Model/Customer.php index 00eb53e17253721a9925c43839cf34b8ca21e58c..6910ab9b23663a8bf2cc8dbb5af7fe025b164f49 100644 --- a/app/code/Magento/Log/Model/Customer.php +++ b/app/code/Magento/Log/Model/Customer.php @@ -35,7 +35,7 @@ class Customer extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -43,7 +43,7 @@ class Customer extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->dateTime = $dateTime; diff --git a/app/code/Magento/Log/Model/Log.php b/app/code/Magento/Log/Model/Log.php index e82acd114d3415cde1630ea2346b2aaeac0cc899..3ef8615027d8264d3d50ebe1673aaa24a2920193 100644 --- a/app/code/Magento/Log/Model/Log.php +++ b/app/code/Magento/Log/Model/Log.php @@ -39,7 +39,7 @@ class Log extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -47,7 +47,7 @@ class Log extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_scopeConfig = $scopeConfig; diff --git a/app/code/Magento/Log/Model/Visitor.php b/app/code/Magento/Log/Model/Visitor.php index 99f9ff81530b7e25d732a8d805eb9b4500be7ea1..814027ee574cd58f719ac28b38d5583d74e7ffe0 100644 --- a/app/code/Magento/Log/Model/Visitor.php +++ b/app/code/Magento/Log/Model/Visitor.php @@ -61,7 +61,7 @@ class Visitor extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\HTTP\PhpEnvironment\ServerAddress $serverAddress * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -75,7 +75,7 @@ class Visitor extends \Magento\Framework\Model\AbstractModel \Magento\Framework\HTTP\PhpEnvironment\ServerAddress $serverAddress, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->session = $session; diff --git a/app/code/Magento/Log/Model/Visitor/Online.php b/app/code/Magento/Log/Model/Visitor/Online.php index 3b5e0af57a5aaf192c25943d46fb905e13772389..941fd2f460f71f3a6ce55915220eb0943e53d724 100644 --- a/app/code/Magento/Log/Model/Visitor/Online.php +++ b/app/code/Magento/Log/Model/Visitor/Online.php @@ -42,7 +42,7 @@ class Online extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -50,7 +50,7 @@ class Online extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_scopeConfig = $scopeConfig; diff --git a/app/code/Magento/Log/composer.json b/app/code/Magento/Log/composer.json index 5e8b4ac8119e041d841a426c6d08d95be5b78e2d..1e5b22c27320a7ab072789131a4b60f59b9dbdac 100644 --- a/app/code/Magento/Log/composer.json +++ b/app/code/Magento/Log/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php b/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php index 90b7f43c733e17866358b48124a7e66d19710b16..8dd702290d52fb08624e480ec299802c624425fc 100644 --- a/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php +++ b/app/code/Magento/MediaStorage/Model/Config/Backend/Storage/Media/Database.php @@ -20,7 +20,7 @@ class Database extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\MediaStorage\Helper\File\Storage $coreFileStorage * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -29,7 +29,7 @@ class Database extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\MediaStorage\Helper\File\Storage $coreFileStorage, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_coreFileStorage = $coreFileStorage; diff --git a/app/code/Magento/MediaStorage/Model/File/Storage.php b/app/code/Magento/MediaStorage/Model/File/Storage.php index b4558c799b1c8d984adc330454dbdeed8f3bac39..34e56f70aaaf5400dfd72bcda4385c2128f3e211 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage.php @@ -99,7 +99,7 @@ class Storage extends AbstractModel * @param \Magento\MediaStorage\Model\File\Storage\DatabaseFactory $databaseFactory * @param Filesystem $filesystem * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -114,7 +114,7 @@ class Storage extends AbstractModel \Magento\MediaStorage\Model\File\Storage\DatabaseFactory $databaseFactory, Filesystem $filesystem, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_coreFileStorage = $coreFileStorage; diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Database.php b/app/code/Magento/MediaStorage/Model/File/Storage/Database.php index e8d515a8caa45de7b3063759ac383c6d961d0510..033454066bc0fa692fa27b37de0dd97a533c8f2b 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Database.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Database.php @@ -50,7 +50,7 @@ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\Abstrac * @param \Magento\MediaStorage\Helper\File\Media $mediaHelper * @param \Magento\MediaStorage\Model\Resource\File\Storage\Database $resource * @param Directory\DatabaseFactory $directoryFactory - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param null $connectionName * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -64,7 +64,7 @@ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\Abstrac \Magento\MediaStorage\Helper\File\Media $mediaHelper, \Magento\MediaStorage\Model\Resource\File\Storage\Database $resource, \Magento\MediaStorage\Model\File\Storage\Directory\DatabaseFactory $directoryFactory, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, $connectionName = null, array $data = [] ) { diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php b/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php index 7c1c1401b2dca8d27a90654b4bebd42f2779ff8d..ff1a6db2e212ed1fbd5574145876d3c611b152a6 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Database/AbstractDatabase.php @@ -43,7 +43,7 @@ abstract class AbstractDatabase extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Stdlib\DateTime\DateTime $dateModel * @param \Magento\Framework\App\Config\ScopeConfigInterface $configuration * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param string|null $connectionName * @param array $data */ @@ -54,7 +54,7 @@ abstract class AbstractDatabase extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Stdlib\DateTime\DateTime $dateModel, \Magento\Framework\App\Config\ScopeConfigInterface $configuration, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, $connectionName = null, array $data = [] ) { diff --git a/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php b/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php index 4f5df338945d53755dde65aec7fc7ac5a02b7dbc..e6907df84f8eefe219fc21c017ad93a20badccb8 100644 --- a/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php +++ b/app/code/Magento/MediaStorage/Model/File/Storage/Directory/Database.php @@ -40,7 +40,7 @@ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\Abstrac * @param \Magento\Framework\App\Config\ScopeConfigInterface $configuration * @param DatabaseFactory $directoryFactory * @param \Magento\MediaStorage\Model\Resource\File\Storage\Directory\Database $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param null $connectionName * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -53,7 +53,7 @@ class Database extends \Magento\MediaStorage\Model\File\Storage\Database\Abstrac \Magento\Framework\App\Config\ScopeConfigInterface $configuration, \Magento\MediaStorage\Model\File\Storage\Directory\DatabaseFactory $directoryFactory, \Magento\MediaStorage\Model\Resource\File\Storage\Directory\Database $resource, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, $connectionName = null, array $data = [] ) { diff --git a/app/code/Magento/MediaStorage/composer.json b/app/code/Magento/MediaStorage/composer.json index 4a4ffe77dcaa76e5231ab813c5dfdc08942d2663..d6eb3484a3966987d8d3278506a3ba04abba6b52 100644 --- a/app/code/Magento/MediaStorage/composer.json +++ b/app/code/Magento/MediaStorage/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Msrp/composer.json b/app/code/Magento/Msrp/composer.json index 88350cabe0722ff928eb5d9395c97a90f463ad86..264b8eb51dba8d26cd6487ab3a4c05374119152b 100644 --- a/app/code/Magento/Msrp/composer.json +++ b/app/code/Magento/Msrp/composer.json @@ -3,19 +3,19 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-bundle": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-downloadable": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-grouped-product": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-bundle": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-downloadable": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-grouped-product": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php b/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php index 169e10c71954ce08875b0eda6407624f34fb3308..b788293e230d31cd69f765ebcedcf335c141e45f 100644 --- a/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php +++ b/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php @@ -464,14 +464,13 @@ class Multishipping extends \Magento\Framework\Object $qty = isset($data['qty']) ? (int)$data['qty'] : 1; //$qty = $qty > 0 ? $qty : 1; $addressId = isset($data['address']) ? $data['address'] : false; - - if (!$this->isAddressIdApplicable($addressId)) { - throw new LocalizedException(__('Please check shipping address information.')); - } - $quoteItem = $this->getQuote()->getItemById($quoteItemId); if ($addressId && $quoteItem) { + if (!$this->isAddressIdApplicable($addressId)) { + throw new LocalizedException(__('Please check shipping address information.')); + } + /** * Skip item processing if qty 0 */ diff --git a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php index b274d73a1e466626285fe5c492ceffa8f0cc5b05..415bdd643029d628a34bfd067816cf4cac2cfb84 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php @@ -133,18 +133,11 @@ class MultishippingTest extends \PHPUnit_Framework_TestCase ] ] ]; - $customerAddressId = 42; - - $customerAddressMock = $this->getMock('\Magento\Customer\Model\Data\Address', [], [], '', false); - $customerAddressMock->expects($this->atLeastOnce())->method('getId')->willReturn($customerAddressId); - $customerAddresses = [$customerAddressMock]; - $this->quoteMock->expects($this->once())->method('getAllShippingAddresses')->willReturn([]); $this->checkoutSessionMock->expects($this->any())->method('getQuote')->willReturn($this->quoteMock); $this->helperMock->expects($this->once())->method('getMaximumQty')->willReturn(500); - $this->customerMock->expects($this->once())->method('getAddresses')->willReturn($customerAddresses); $this->quoteMock->expects($this->once())->method('getItemById')->with(array_keys($info[0])[0]) ->willReturn(null); @@ -189,7 +182,10 @@ class MultishippingTest extends \PHPUnit_Framework_TestCase $customerAddressMock->expects($this->atLeastOnce())->method('getId')->willReturn($customerAddressId); $customerAddresses = [$customerAddressMock]; + $quoteItemMock = $this->getMock('\Magento\Quote\Model\Quote\Item', [], [], '', false); + $this->quoteMock->expects($this->once())->method('getItemById')->willReturn($quoteItemMock); $this->quoteMock->expects($this->once())->method('getAllShippingAddresses')->willReturn([]); + $this->checkoutSessionMock->expects($this->any())->method('getQuote')->willReturn($this->quoteMock); $this->helperMock->expects($this->once())->method('getMaximumQty')->willReturn(500); $this->customerMock->expects($this->once())->method('getAddresses')->willReturn($customerAddresses); diff --git a/app/code/Magento/Multishipping/composer.json b/app/code/Magento/Multishipping/composer.json index a2580b07eccef0b326d5bf509b00c6b47c9ee0a3..1d8a0325c2eb0998dc4e53af4125e2204ad25f50 100644 --- a/app/code/Magento/Multishipping/composer.json +++ b/app/code/Magento/Multishipping/composer.json @@ -3,19 +3,19 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-payment": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-payment": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Newsletter/Controller/Adminhtml/Template/Delete.php b/app/code/Magento/Newsletter/Controller/Adminhtml/Template/Delete.php index 2119e1e7a2100dde344beac4be9e5ecfe9a03498..188e800f3bfaedfe3954271913103fd6d0216fdf 100644 --- a/app/code/Magento/Newsletter/Controller/Adminhtml/Template/Delete.php +++ b/app/code/Magento/Newsletter/Controller/Adminhtml/Template/Delete.php @@ -28,7 +28,7 @@ class Delete extends \Magento\Newsletter\Controller\Adminhtml\Template } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { - $this->messageManager->addException($e, __('An error occurred while deleting this template.')); + $this->messageManager->addException($e, __('We can\'t delete this template right now.')); } } $this->_redirect('*/template'); diff --git a/app/code/Magento/Newsletter/Model/Problem.php b/app/code/Magento/Newsletter/Model/Problem.php index 38a7098a12871b690dd94397f32f61b6721c27ea..db5033788deebbd974785a1763110bfd06beff8c 100644 --- a/app/code/Magento/Newsletter/Model/Problem.php +++ b/app/code/Magento/Newsletter/Model/Problem.php @@ -44,7 +44,7 @@ class Problem extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -52,7 +52,7 @@ class Problem extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Newsletter/Model/Subscriber.php b/app/code/Magento/Newsletter/Model/Subscriber.php index 5fa2c3aa052638f3841cefcc5ddfe6bf1ef4358a..68059af6e30d6c89558f242ef6dcfbf92224cc36 100644 --- a/app/code/Magento/Newsletter/Model/Subscriber.php +++ b/app/code/Magento/Newsletter/Model/Subscriber.php @@ -134,7 +134,7 @@ class Subscriber extends \Magento\Framework\Model\AbstractModel * @param AccountManagementInterface $customerAccountManagement * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -150,7 +150,7 @@ class Subscriber extends \Magento\Framework\Model\AbstractModel AccountManagementInterface $customerAccountManagement, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_newsletterData = $newsletterData; diff --git a/app/code/Magento/Newsletter/composer.json b/app/code/Magento/Newsletter/composer.json index e4284220e9e6833f1e3ef198cd6a0aad07d91ef1..5e9806a6fab8fd93f56c0a0ccca0256ca1771bc6 100644 --- a/app/code/Magento/Newsletter/composer.json +++ b/app/code/Magento/Newsletter/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-widget": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-cms": "0.74.0-beta10", - "magento/module-email": "0.74.0-beta10", - "magento/module-cron": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-require-js": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-widget": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-cms": "0.74.0-beta13", + "magento/module-email": "0.74.0-beta13", + "magento/module-cron": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-require-js": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/OfflinePayments/Test/Unit/Block/Form/AbstractInstructionTest.php b/app/code/Magento/OfflinePayments/Test/Unit/Block/Form/AbstractInstructionTest.php index d9f94e686004ded3a949ded75f800b0b4505c992..5a48ca4ba98c189a1899a0e33b17c10d5596d9e0 100644 --- a/app/code/Magento/OfflinePayments/Test/Unit/Block/Form/AbstractInstructionTest.php +++ b/app/code/Magento/OfflinePayments/Test/Unit/Block/Form/AbstractInstructionTest.php @@ -23,13 +23,9 @@ class AbstractInstructionTest extends \PHPUnit_Framework_TestCase public function testGetInstructions() { - $method = $this->getMock( - 'Magento\Payment\Model\MethodInterface', - ['getConfigData', 'getCode', 'getFormBlockType', 'getTitle'], - [], - '', - false - ); + $method = $this->getMockBuilder('Magento\Payment\Model\MethodInterface') + ->getMockForAbstractClass(); + $method->expects($this->once()) ->method('getConfigData') ->willReturn('instructions'); diff --git a/app/code/Magento/OfflinePayments/Test/Unit/Model/ObserverTest.php b/app/code/Magento/OfflinePayments/Test/Unit/Model/ObserverTest.php index 6c0813747188b004a9374996e254f6357d725ebc..45c5732aeb1de947ab8645a6460978100b48d31b 100644 --- a/app/code/Magento/OfflinePayments/Test/Unit/Model/ObserverTest.php +++ b/app/code/Magento/OfflinePayments/Test/Unit/Model/ObserverTest.php @@ -43,13 +43,10 @@ class ObserverTest extends \PHPUnit_Framework_TestCase $payment->expects($this->once()) ->method('setAdditionalInformation') ->with('instructions', 'payment configuration'); - $method = $this->getMock( - 'Magento\Payment\Model\MethodInterface', - ['getInstructions', 'getFormBlockType', 'getTitle', 'getCode'], - [], - '', - false - ); + $method = $this->getMockBuilder('\Magento\OfflinePayments\Model\Banktransfer') + ->disableOriginalConstructor() + ->getMock(); + $method->expects($this->once()) ->method('getInstructions') ->willReturn('payment configuration'); @@ -96,13 +93,9 @@ class ObserverTest extends \PHPUnit_Framework_TestCase ] ); - $method = $this->getMock( - 'Magento\Payment\Model\MethodInterface', - ['getPayableTo', 'getMailingAddress', 'getFormBlockType', 'getTitle', 'getCode'], - [], - '', - false - ); + $method = $this->getMockBuilder('Magento\OfflinePayments\Model\Checkmo') + ->disableOriginalConstructor() + ->getMock(); $method->expects($this->once()) ->method('getPayableTo') ->willReturn('payable to'); diff --git a/app/code/Magento/OfflinePayments/composer.json b/app/code/Magento/OfflinePayments/composer.json index 63562f6f49931ea736c668a0d42ab7a275dbee93..90045a9378f6e5f6b38fe5824ccfb2deea5770b6 100644 --- a/app/code/Magento/OfflinePayments/composer.json +++ b/app/code/Magento/OfflinePayments/composer.json @@ -3,13 +3,13 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-payment": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-payment": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/OfflineShipping/Model/Config/Backend/Tablerate.php b/app/code/Magento/OfflineShipping/Model/Config/Backend/Tablerate.php index c0b311a1073addee40ce31187c130a2d8f7dfc98..fa5987a754a1a9fe5f5ec014e9602242dbcfefd8 100644 --- a/app/code/Magento/OfflineShipping/Model/Config/Backend/Tablerate.php +++ b/app/code/Magento/OfflineShipping/Model/Config/Backend/Tablerate.php @@ -25,7 +25,7 @@ class Tablerate extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\OfflineShipping\Model\Resource\Carrier\TablerateFactory $tablerateFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -34,7 +34,7 @@ class Tablerate extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\OfflineShipping\Model\Resource\Carrier\TablerateFactory $tablerateFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_tablerateFactory = $tablerateFactory; diff --git a/app/code/Magento/OfflineShipping/composer.json b/app/code/Magento/OfflineShipping/composer.json index 0d80d78d0d461201ebc160e72ccaf62dd34f04c6..9e6c4caa47f24bf81041f76336168cdaf9256b15 100644 --- a/app/code/Magento/OfflineShipping/composer.json +++ b/app/code/Magento/OfflineShipping/composer.json @@ -3,21 +3,21 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-shipping": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-sales-rule": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-shipping": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-sales-rule": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/PageCache/Block/Javascript.php b/app/code/Magento/PageCache/Block/Javascript.php index 1b310190f3305b7d04a854c9692adb873aca7cd9..bfc3b4a1a1e8b64e376b0889fa5bd75a4bfb08fe 100644 --- a/app/code/Magento/PageCache/Block/Javascript.php +++ b/app/code/Magento/PageCache/Block/Javascript.php @@ -26,6 +26,11 @@ class Javascript extends \Magento\Framework\View\Element\Template ] ), 'handles' => $this->_layout->getUpdate()->getHandles(), + 'originalRequest' => [ + 'route' => $this->getRequest()->getRouteName(), + 'controller' => $this->getRequest()->getControllerName(), + 'action' => $this->getRequest()->getActionName(), + ], 'versionCookieName' => \Magento\Framework\App\PageCache\Version::COOKIE_NAME ]; return json_encode($params); diff --git a/app/code/Magento/PageCache/Controller/Block/Render.php b/app/code/Magento/PageCache/Controller/Block/Render.php index 8afaeb27e5c3a552d83e8a72d1a940ddab4434ba..1544cca2cfacb36dfa57fa75fd8ae1138e42a8f5 100644 --- a/app/code/Magento/PageCache/Controller/Block/Render.php +++ b/app/code/Magento/PageCache/Controller/Block/Render.php @@ -21,12 +21,27 @@ class Render extends \Magento\PageCache\Controller\Block } // disable profiling during private content handling AJAX call \Magento\Framework\Profiler::reset(); + $currentRoute = $this->getRequest()->getRouteName(); + $currentControllerName = $this->getRequest()->getControllerName(); + $currentActionName = $this->getRequest()->getActionName(); + + $origRequest = $this->getRequest()->getParam('originalRequest'); + $origRequest = json_decode($origRequest, true); + $this->getRequest()->setRouteName($origRequest['route']); + $this->getRequest()->setControllerName($origRequest['controller']); + $this->getRequest()->setActionName($origRequest['action']); + /** @var \Magento\Framework\View\Element\BlockInterface[] $blocks */ $blocks = $this->_getBlocks(); $data = []; + foreach ($blocks as $blockName => $blockInstance) { $data[$blockName] = $blockInstance->toHtml(); } + $this->getRequest()->setRouteName($currentRoute); + $this->getRequest()->setControllerName($currentControllerName); + $this->getRequest()->setActionName($currentActionName); + $this->getResponse()->setPrivateHeaders(\Magento\PageCache\Helper\Data::PRIVATE_MAX_AGE_CACHE); $this->translateInline->processResponseBody($data); $this->getResponse()->appendBody(json_encode($data)); diff --git a/app/code/Magento/PageCache/Test/Unit/Block/JavascriptTest.php b/app/code/Magento/PageCache/Test/Unit/Block/JavascriptTest.php index 21bcec6253bf058de334d01ec83d0d4b3f667bfc..56a23aa1ac84f28e78958214c2e6db5b2c190e70 100644 --- a/app/code/Magento/PageCache/Test/Unit/Block/JavascriptTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Block/JavascriptTest.php @@ -47,8 +47,25 @@ class JavascriptTest extends \PHPUnit_Framework_TestCase $this->contextMock = $this->getMockBuilder('Magento\Framework\View\Element\Template\Context') ->disableOriginalConstructor() ->getMock(); - $this->requestMock = $this->getMockBuilder('Magento\Framework\App\RequestInterface') - ->getMock(); + $this->requestMock = $this->getMock( + 'Magento\Framework\App\RequestInterface', + [ + 'getRouteName', + 'getControllerName', + 'getModuleName', + 'getActionName', + 'getParam', + 'setParams', + 'getParams', + 'setModuleName', + 'isSecure', + 'setActionName', + 'getCookie' + ], + [], + '', + false + ); $this->layoutMock = $this->getMockBuilder('Magento\Framework\View\LayoutInterface') ->disableOriginalConstructor() ->getMock(); @@ -96,6 +113,15 @@ class JavascriptTest extends \PHPUnit_Framework_TestCase $this->requestMock->expects($this->once()) ->method('isSecure') ->willReturn($isSecure); + $this->requestMock->expects($this->once()) + ->method('getRouteName') + ->will($this->returnValue('route')); + $this->requestMock->expects($this->once()) + ->method('getControllerName') + ->will($this->returnValue('controller')); + $this->requestMock->expects($this->once()) + ->method('getActionName') + ->will($this->returnValue('action')); $this->urlBuilderMock->expects($this->once()) ->method('getUrl') ->willReturn($url); @@ -120,4 +146,59 @@ class JavascriptTest extends \PHPUnit_Framework_TestCase ] ]; } + + /** + * @covers \Magento\PageCache\Block\Javascript::getScriptOptions + * @param string $url + * @param string $route + * @param string $controller + * @param string $action + * @param string $expectedResult + * @dataProvider getScriptOptionsPrivateContentDataProvider + */ + public function testGetScriptOptionsPrivateContent($url, $route, $controller, $action, $expectedResult) + { + $handles = [ + 'some', + 'handles', + 'here' + ]; + $this->requestMock->expects($this->once()) + ->method('isSecure') + ->willReturn(false); + + $this->requestMock->expects($this->once()) + ->method('getRouteName') + ->will($this->returnValue($route)); + + $this->requestMock->expects($this->once()) + ->method('getControllerName') + ->will($this->returnValue($controller)); + + $this->requestMock->expects($this->once()) + ->method('getActionName') + ->will($this->returnValue($action)); + + $this->urlBuilderMock->expects($this->once()) + ->method('getUrl') + ->willReturn($url); + + $this->layoutUpdateMock->expects($this->once()) + ->method('getHandles') + ->willReturn($handles); + $this->assertRegExp($expectedResult, $this->blockJavascript->getScriptOptions()); + } + + public function getScriptOptionsPrivateContentDataProvider() + { + return [ + 'http' => [ + 'url' => 'http://some-name.com/page_cache/block/render', + 'route' => 'route', + 'controller' => 'controller', + 'action' => 'action', + 'expectedResult' => '~"originalRequest":{"route":"route","controller":"controller","action":"action"}~' + ], + ]; + } } diff --git a/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php b/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php index 85cf666fb90c0d16d9cd31d700872965d20921dd..0bd7fcee22587e778d4cf4d8a849cfa9b030d11a 100644 --- a/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php +++ b/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php @@ -88,11 +88,11 @@ class RenderTest extends \PHPUnit_Framework_TestCase public function testExecuteNoParams() { $this->requestMock->expects($this->once())->method('isAjax')->will($this->returnValue(true)); - $this->requestMock->expects($this->at(1)) + $this->requestMock->expects($this->at(8)) ->method('getParam') ->with($this->equalTo('blocks'), $this->equalTo('')) ->will($this->returnValue('')); - $this->requestMock->expects($this->at(2)) + $this->requestMock->expects($this->at(9)) ->method('getParam') ->with($this->equalTo('handles'), $this->equalTo('')) ->will($this->returnValue('')); @@ -103,6 +103,7 @@ class RenderTest extends \PHPUnit_Framework_TestCase { $blocks = ['block1', 'block2']; $handles = ['handle1', 'handle2']; + $originalRequest = '{"route":"route","controller":"controller","action":"action"}'; $expectedData = ['block1' => 'data1', 'block2' => 'data2']; $blockInstance1 = $this->getMock( @@ -124,11 +125,26 @@ class RenderTest extends \PHPUnit_Framework_TestCase $blockInstance2->expects($this->once())->method('toHtml')->will($this->returnValue($expectedData['block2'])); $this->requestMock->expects($this->once())->method('isAjax')->will($this->returnValue(true)); + $this->requestMock->expects($this->at(1)) + ->method('getRouteName') + ->will($this->returnValue('magento_pagecache')); + $this->requestMock->expects($this->at(2)) + ->method('getControllerName') + ->will($this->returnValue('block')); + $this->requestMock->expects($this->at(3)) + ->method('getActionName') + ->will($this->returnValue('render')); + $this->requestMock->expects($this->at(4)) + ->method('getParam') + ->with($this->equalTo('originalRequest')) + ->will($this->returnValue($originalRequest)); + + $this->requestMock->expects($this->at(8)) ->method('getParam') ->with($this->equalTo('blocks'), $this->equalTo('')) ->will($this->returnValue(json_encode($blocks))); - $this->requestMock->expects($this->at(2)) + $this->requestMock->expects($this->at(9)) ->method('getParam') ->with($this->equalTo('handles'), $this->equalTo('')) ->will($this->returnValue(json_encode($handles))); diff --git a/app/code/Magento/PageCache/composer.json b/app/code/Magento/PageCache/composer.json index 17e81a593a01bac468feef37dc2a1f52b1ab165d..bc812b12e6d5c3b4ed3047b46623a6a0b2fb5f19 100644 --- a/app/code/Magento/PageCache/composer.json +++ b/app/code/Magento/PageCache/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js b/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js index bc7708cf4dc88c424b67f4d1a33cf329342feb50..27e13bfa211da677b79dced7c82c4f2c4b8e60b6 100644 --- a/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js +++ b/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js @@ -239,6 +239,7 @@ define([ data = { blocks: [], handles: this.options.handles, + originalRequest: this.options.originalRequest, version: version }; @@ -247,6 +248,7 @@ define([ } data.blocks = JSON.stringify(data.blocks.sort()); data.handles = JSON.stringify(data.handles); + data.originalRequest = JSON.stringify(data.originalRequest); $.ajax({ url: this.options.url, data: data, diff --git a/app/code/Magento/Payment/Block/Transparent/Form.php b/app/code/Magento/Payment/Block/Transparent/Form.php index 3237e6e21191af8c37ce16ff0085007d5b8d190a..73df0c39c87d95c38a5336530d42802c9c913101 100644 --- a/app/code/Magento/Payment/Block/Transparent/Form.php +++ b/app/code/Magento/Payment/Block/Transparent/Form.php @@ -168,7 +168,7 @@ class Form extends \Magento\Payment\Block\Form\Cc */ public function getMethodConfigData($fieldName) { - return $this->getMethod()->getConfigInterface()->getConfigValue($fieldName); + return $this->getMethod()->getConfigInterface()->getValue($fieldName); } /** diff --git a/app/code/Magento/Payment/Gateway/Command/CommandPool.php b/app/code/Magento/Payment/Gateway/Command/CommandPool.php new file mode 100644 index 0000000000000000000000000000000000000000..a6cafee447b83df75cc689ac349d57ed3c83bb8a --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Command/CommandPool.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Command; + +use Magento\Framework\ObjectManager\TMap; +use Magento\Payment\Gateway\CommandInterface; +use Magento\Framework\Exception\NotFoundException; + +class CommandPool implements CommandPoolInterface +{ + /** + * @var CommandInterface[] + */ + private $commands; + + /** + * @param TMap $commands + */ + public function __construct( + TMap $commands + ) { + $this->commands = $commands; + } + + /** + * Retrieves operation + * + * @param string $commandCode + * @return CommandInterface + * @throws NotFoundException + */ + public function get($commandCode) + { + if (!isset($this->commands[$commandCode])) { + throw new NotFoundException(__('Command %1 does not exist.', $commandCode)); + } + + return $this->commands[$commandCode]; + } +} diff --git a/app/code/Magento/Payment/Gateway/Command/CommandPoolInterface.php b/app/code/Magento/Payment/Gateway/Command/CommandPoolInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..317ebdd2c8fc6dade957c1955f5be5f351de3517 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Command/CommandPoolInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Command; + +use Magento\Framework\Exception\NotFoundException; +use Magento\Payment\Gateway\CommandInterface; + +interface CommandPoolInterface +{ + /** + * Retrieves operation + * + * @param string $commandCode + * @return CommandInterface + * @throws NotFoundException + */ + public function get($commandCode); +} diff --git a/app/code/Magento/Payment/Gateway/Command/GatewayCommand.php b/app/code/Magento/Payment/Gateway/Command/GatewayCommand.php new file mode 100644 index 0000000000000000000000000000000000000000..e2f5e25f75bad6c96dde6d0b2c2800e1f08af2f2 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Command/GatewayCommand.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Command; + +use Magento\Payment\Gateway\CommandInterface; +use Magento\Payment\Gateway\Http\ClientInterface; +use Magento\Payment\Gateway\Request; +use Magento\Payment\Gateway\Response; + +class GatewayCommand implements CommandInterface +{ + /** + * @var \Magento\Payment\Gateway\Request\BuilderInterface + */ + private $requestBuilder; + + /** + * @var \Magento\Payment\Gateway\Http\TransferBuilderInterface + */ + private $transferBuilder; + + /** + * @var \Magento\Payment\Gateway\Http\ClientInterface + */ + private $gateway; + + /** + * @var \Magento\Payment\Gateway\Response\HandlerInterface + */ + private $responseHandler; + + /** + * @param \Magento\Payment\Gateway\Request\BuilderInterface $requestBuilder + * @param \Magento\Payment\Gateway\Http\TransferBuilderInterface $transferBuilder + * @param \Magento\Payment\Gateway\Http\ClientInterface $gateway + * @param \Magento\Payment\Gateway\Response\HandlerInterface $responseHandler + */ + public function __construct( + \Magento\Payment\Gateway\Request\BuilderInterface $requestBuilder, + \Magento\Payment\Gateway\Http\TransferBuilderInterface $transferBuilder, + ClientInterface $gateway, + \Magento\Payment\Gateway\Response\HandlerInterface $responseHandler + ) { + + $this->requestBuilder = $requestBuilder; + $this->transferBuilder = $transferBuilder; + $this->gateway = $gateway; + $this->responseHandler = $responseHandler; + } + + /** + * Executes command basing on business object + * + * @param array $commandSubject + * @return void + */ + public function execute(array $commandSubject) + { + // @TODO implement exceptions catching + $transferO = $this->transferBuilder->build( + $this->requestBuilder->build($commandSubject) + ); + + $response = $this->gateway->placeRequest($transferO); + + $this->responseHandler->handle( + $commandSubject, + $response + ); + } +} diff --git a/app/code/Magento/Payment/Gateway/CommandInterface.php b/app/code/Magento/Payment/Gateway/CommandInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..1537c4d21a80da92d1de2956def17c5bed6815f5 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/CommandInterface.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway; + +interface CommandInterface +{ + /** + * Executes command basing on business object + * + * @param array $commandSubject + * @return void + */ + public function execute(array $commandSubject); +} diff --git a/app/code/Magento/Payment/Gateway/Config/Config.php b/app/code/Magento/Payment/Gateway/Config/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..b860b2d886e7e9801d3f41476e24671e669d23a3 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Config/Config.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Config; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Payment\Gateway\ConfigInterface; +use Magento\Store\Model\ScopeInterface; + +class Config implements ConfigInterface +{ + const DEFAULT_PATH_PATTERN = 'payment/%s/%s'; + + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * @var string + */ + private $methodCode; + + /** + * @var string + */ + private $pathPattern; + + /** + * @param ScopeConfigInterface $scopeConfig + * @param string $methodCode + * @param string $pathPattern + */ + public function __construct( + ScopeConfigInterface $scopeConfig, + $methodCode, + $pathPattern = self::DEFAULT_PATH_PATTERN + ) { + $this->scopeConfig = $scopeConfig; + $this->methodCode = $methodCode; + $this->pathPattern = $pathPattern; + } + + /** + * Retrieve information from payment configuration + * + * @param string $field + * @param int|null $storeId + * + * @return mixed + */ + public function getValue($field, $storeId = null) + { + return $this->scopeConfig->getValue( + sprintf($this->pathPattern, $this->methodCode, $field), + ScopeInterface::SCOPE_STORE, + $storeId + ); + } +} diff --git a/app/code/Magento/Payment/Gateway/Config/ConfigValueHandler.php b/app/code/Magento/Payment/Gateway/Config/ConfigValueHandler.php new file mode 100644 index 0000000000000000000000000000000000000000..17566610aa29e171681ff4ade6829053e0a49c51 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Config/ConfigValueHandler.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Config; + +use Magento\Payment\Gateway\ConfigInterface; + +class ConfigValueHandler implements ValueHandlerInterface +{ + /** + * @var \Magento\Payment\Gateway\ConfigInterface + */ + private $configInterface; + + /** + * @param \Magento\Payment\Gateway\ConfigInterface $configInterface + */ + public function __construct( + ConfigInterface $configInterface + ) { + $this->configInterface = $configInterface; + } + + /** + * Retrieve method configured value + * + * @param string $field + * @param int|null $storeId + * + * @return mixed + */ + public function handle($field, $storeId = null) + { + return $this->configInterface->getValue($field, $storeId); + } +} diff --git a/app/code/Magento/Payment/Gateway/Config/ValueHandlerInterface.php b/app/code/Magento/Payment/Gateway/Config/ValueHandlerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..5f857ea3cf539bceec121eb2af09120147774bb3 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Config/ValueHandlerInterface.php @@ -0,0 +1,19 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Config; + +interface ValueHandlerInterface +{ + /** + * Retrieve method configured value + * + * @param string $field + * @param int|null $storeId + * + * @return mixed + */ + public function handle($field, $storeId = null); +} diff --git a/app/code/Magento/Payment/Gateway/Config/ValueHandlerPool.php b/app/code/Magento/Payment/Gateway/Config/ValueHandlerPool.php new file mode 100644 index 0000000000000000000000000000000000000000..ec00f81b18046caea8c2c397384fd492bb8dbc4b --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Config/ValueHandlerPool.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Config; + +use Magento\Framework\ObjectManager\TMap; + +class ValueHandlerPool implements \Magento\Payment\Gateway\Config\ValueHandlerPoolInterface +{ + /** + * Default handler code + */ + const DEFAULT_HANDLER = 'default'; + + /** + * @var ValueHandlerInterface[] + */ + private $handlers; + + /** + * @param TMap $handlers + */ + public function __construct( + TMap $handlers + ) { + if (!isset($handlers[self::DEFAULT_HANDLER])) { + throw new \LogicException('Default handler should be provided.'); + } + + $this->handlers = $handlers; + } + + /** + * Retrieves an appropriate configuration value handler + * + * @param string $field + * @return ValueHandlerInterface + */ + public function get($field) + { + return isset ($this->handlers[$field]) + ? $this->handlers[$field] + : $this->handlers[self::DEFAULT_HANDLER]; + } +} diff --git a/app/code/Magento/Payment/Gateway/Config/ValueHandlerPoolInterface.php b/app/code/Magento/Payment/Gateway/Config/ValueHandlerPoolInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..7b771b1d8b3b5df753b5d45f438f640b6db5c979 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Config/ValueHandlerPoolInterface.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Config; + +use Magento\Framework\Exception\NotFoundException; + +interface ValueHandlerPoolInterface +{ + /** + * Retrieves an appropriate configuration value handler + * + * @param string $field + * @return ValueHandlerInterface + * @throws NotFoundException + */ + public function get($field); +} diff --git a/app/code/Magento/Payment/Gateway/ConfigInterface.php b/app/code/Magento/Payment/Gateway/ConfigInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..10c6e0e69d9befce024281437ff4ff173ddba0c4 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/ConfigInterface.php @@ -0,0 +1,19 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway; + +interface ConfigInterface +{ + /** + * Retrieve information from payment configuration + * + * @param string $field + * @param int|null $storeId + * + * @return mixed + */ + public function getValue($field, $storeId = null); +} diff --git a/app/code/Magento/Payment/Gateway/Data/AddressAdapterInterface.php b/app/code/Magento/Payment/Gateway/Data/AddressAdapterInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..aeb1f0432f4ccf4ad45752f7835b8182cbdf7b42 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Data/AddressAdapterInterface.php @@ -0,0 +1,93 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Data; + +interface AddressAdapterInterface +{ + /** + * Get region name + * + * @return string + */ + public function getRegion(); + + /** + * Get country id + * + * @return string + */ + public function getCountryId(); + + /** + * Get street line 1 + * + * @return string + */ + public function getStreetLine1(); + + /** + * Get street line 2 + * + * @return string + */ + public function getStreetLine2(); + + /** + * Get telephone number + * + * @return string + */ + public function getTelephone(); + + /** + * Get postcode + * + * @return string + */ + public function getPostcode(); + + /** + * Get city name + * + * @return string + */ + public function getCity(); + + /** + * Get first name + * + * @return string + */ + public function getFirstname(); + + /** + * Get last name + * + * @return string + */ + public function getLastname(); + + /** + * Get middle name + * + * @return string|null + */ + public function getMiddlename(); + + /** + * Get customer id + * + * @return int|null + */ + public function getCustomerId(); + + /** + * Get billing/shipping email + * + * @return string + */ + public function getEmail(); +} diff --git a/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php b/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php new file mode 100644 index 0000000000000000000000000000000000000000..54f312ccb5afb19081456e15a1a96a48ad526385 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Data/Order/AddressAdapter.php @@ -0,0 +1,147 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Data\Order; + +use Magento\Payment\Gateway\Data\AddressAdapterInterface; +use Magento\Sales\Api\Data\OrderAddressInterface; + +class AddressAdapter implements AddressAdapterInterface +{ + /** + * @var OrderAddressInterface + */ + private $address; + + /** + * @param OrderAddressInterface $address + */ + public function __construct(OrderAddressInterface $address) + { + $this->address = $address; + } + + /** + * Get region name + * + * @return string + */ + public function getRegion() + { + return $this->address->getRegion(); + } + + /** + * Get country id + * + * @return string + */ + public function getCountryId() + { + return $this->address->getCountryId(); + } + + /** + * Get street line 1 + * + * @return string + */ + public function getStreetLine1() + { + $street = $this->address->getStreet(); + return isset($street[0]) ? $street[0]: ''; + } + + /** + * Get street line 2 + * + * @return string + */ + public function getStreetLine2() + { + $street = $this->address->getStreet(); + return isset($street[1]) ? $street[1]: ''; + } + + /** + * Get telephone number + * + * @return string + */ + public function getTelephone() + { + return $this->address->getTelephone(); + } + + /** + * Get postcode + * + * @return string + */ + public function getPostcode() + { + return $this->address->getPostcode(); + } + + /** + * Get city name + * + * @return string + */ + public function getCity() + { + return $this->address->getCity(); + } + + /** + * Get first name + * + * @return string + */ + public function getFirstname() + { + return $this->address->getFirstname(); + } + + /** + * Get last name + * + * @return string + */ + public function getLastname() + { + return $this->address->getLastname(); + } + + /** + * Get middle name + * + * @return string|null + */ + public function getMiddlename() + { + return $this->address->getMiddlename(); + } + + /** + * Get customer id + * + * @return int|null + */ + public function getCustomerId() + { + return $this->address->getCustomerId(); + } + + /** + * Get billing/shipping email + * + * @return string + */ + public function getEmail() + { + return $this->address->getEmail(); + } +} diff --git a/app/code/Magento/Payment/Gateway/Data/Order/OrderAdapter.php b/app/code/Magento/Payment/Gateway/Data/Order/OrderAdapter.php new file mode 100644 index 0000000000000000000000000000000000000000..08ad153f611280c1709efe4660a42d9e02c10888 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Data/Order/OrderAdapter.php @@ -0,0 +1,89 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Data\Order; + +use Magento\Payment\Gateway\Data\AddressAdapterInterface; +use Magento\Payment\Gateway\Data\OrderAdapterInterface; +use Magento\Sales\Api\Data\OrderInterface; + +class OrderAdapter implements OrderAdapterInterface +{ + /** + * @var OrderInterface + */ + private $order; + + /** + * @var AddressAdapter + */ + private $addressAdapterFactory; + + /** + * @param OrderInterface $order + * @param AddressAdapterFactory $addressAdapterFactory + */ + public function __construct( + OrderInterface $order, + AddressAdapterFactory $addressAdapterFactory + ) { + $this->order = $order; + $this->addressAdapterFactory = $addressAdapterFactory; + } + + /** + * Returns currency code + * + * @return string + */ + public function getCurrencyCode() + { + return $this->order->getBaseCurrencyCode(); + } + + /** + * Returns order increment id + * + * @return string + */ + public function getOrderIncrementId() + { + return $this->order->getIncrementId(); + } + + /** + * Returns customer ID + * + * @return int|null + */ + public function getCustomerId() + { + return $this->order->getCustomerId(); + } + + /** + * Returns billing address + * + * @return AddressAdapterInterface + */ + public function getBillingAddress() + { + return $this->addressAdapterFactory->create( + ['address' => $this->order->getBillingAddress()] + ); + } + + /** + * Returns shipping address + * + * @return AddressAdapterInterface + */ + public function getShippingAddress() + { + return $this->addressAdapterFactory->create( + ['address' => $this->order->getShippingAddress()] + ); + } +} diff --git a/app/code/Magento/Payment/Gateway/Data/OrderAdapterInterface.php b/app/code/Magento/Payment/Gateway/Data/OrderAdapterInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..60698aa7d943dc28d60a7555d1c4788621d9bf39 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Data/OrderAdapterInterface.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Data; + +interface OrderAdapterInterface +{ + /** + * Returns currency code + * + * @return string + */ + public function getCurrencyCode(); + + /** + * Returns order increment id + * + * @return string + */ + public function getOrderIncrementId(); + + /** + * Returns customer ID + * + * @return int|null + */ + public function getCustomerId(); + + /** + * Returns billing address + * + * @return AddressAdapterInterface + */ + public function getBillingAddress(); + + /** + * Returns shipping address + * + * @return AddressAdapterInterface + */ + public function getShippingAddress(); +} diff --git a/app/code/Magento/Payment/Gateway/Data/PaymentDataObject.php b/app/code/Magento/Payment/Gateway/Data/PaymentDataObject.php new file mode 100644 index 0000000000000000000000000000000000000000..7ee976994ae00be936c8b191d87f6771f88550f1 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Data/PaymentDataObject.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Data; + +use Magento\Payment\Model\InfoInterface; + +class PaymentDataObject implements PaymentDataObjectInterface +{ + /** + * @var OrderAdapterInterface + */ + private $order; + + /** + * @var InfoInterface + */ + private $payment; + + /** + * @param OrderAdapterInterface $order + * @param InfoInterface $payment + */ + public function __construct( + OrderAdapterInterface $order, + InfoInterface $payment + ) { + $this->order = $order; + $this->payment = $payment; + } + + /** + * Returns order + * + * @return OrderAdapterInterface + */ + public function getOrder() + { + return $this->order; + } + + /** + * Returns payment + * + * @return InfoInterface + */ + public function getPayment() + { + return $this->payment; + } +} diff --git a/app/code/Magento/Payment/Gateway/Data/PaymentDataObjectFactory.php b/app/code/Magento/Payment/Gateway/Data/PaymentDataObjectFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..6f7b28887854384ff9d0342580741061c0f58c79 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Data/PaymentDataObjectFactory.php @@ -0,0 +1,72 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Data; + +use Magento\Framework\ObjectManagerInterface; +use Magento\Payment\Model\InfoInterface; +use Magento\Sales\Model\Order\Payment; + +class PaymentDataObjectFactory +{ + /** + * Object Manager instance + * + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var Order\OrderAdapterFactory + */ + private $orderAdapterFactory; + + /** + * @var Quote\QuoteAdapterFactory + */ + private $quoteAdapterFactory; + + /** + * Factory constructor + * + * @param ObjectManagerInterface $objectManager + * @param Order\OrderAdapterFactory $orderAdapterFactory + * @param Quote\QuoteAdapterFactory $quoteAdapterFactory + */ + public function __construct( + ObjectManagerInterface $objectManager, + Order\OrderAdapterFactory $orderAdapterFactory, + Quote\QuoteAdapterFactory $quoteAdapterFactory + ) { + $this->objectManager = $objectManager; + $this->orderAdapterFactory = $orderAdapterFactory; + $this->quoteAdapterFactory = $quoteAdapterFactory; + } + + /** + * Creates Payment Data Object + * + * @param InfoInterface $paymentInfo + * @return PaymentDataObject + */ + public function create(InfoInterface $paymentInfo) + { + if ($paymentInfo instanceof Payment) { + $data['order'] = $this->orderAdapterFactory->create( + ['order' => $paymentInfo->getOrder()] + ); + } elseif ($paymentInfo instanceof \Magento\Quote\Model\Quote\Payment) { + $data['order'] = $this->quoteAdapterFactory->create( + ['quote' => $paymentInfo->getQuote()] + ); + } + $data['payment'] = $paymentInfo; + + return $this->objectManager->create( + 'Magento\Payment\Gateway\Data\PaymentDataObject', + $data + ); + } +} diff --git a/app/code/Magento/Payment/Gateway/Data/PaymentDataObjectInterface.php b/app/code/Magento/Payment/Gateway/Data/PaymentDataObjectInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..e751364101f444a4585164196f96adfbc042fb75 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Data/PaymentDataObjectInterface.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Data; + +use Magento\Payment\Model\InfoInterface; + +interface PaymentDataObjectInterface +{ + /** + * Returns order + * + * @return OrderAdapterInterface + */ + public function getOrder(); + + /** + * Returns payment + * + * @return InfoInterface + */ + public function getPayment(); +} diff --git a/app/code/Magento/Payment/Gateway/Data/Quote/AddressAdapter.php b/app/code/Magento/Payment/Gateway/Data/Quote/AddressAdapter.php new file mode 100644 index 0000000000000000000000000000000000000000..dd846efe7a702d073ff734dba7a3466d43cece60 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Data/Quote/AddressAdapter.php @@ -0,0 +1,147 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Data\Quote; + +use Magento\Payment\Gateway\Data\AddressAdapterInterface; +use Magento\Quote\Api\Data\AddressInterface; + +class AddressAdapter implements AddressAdapterInterface +{ + /** + * @var AddressInterface + */ + private $address; + + /** + * @param AddressInterface $address + */ + public function __construct(AddressInterface $address) + { + $this->address = $address; + } + + /** + * Get region name + * + * @return string + */ + public function getRegion() + { + return $this->address->getRegion(); + } + + /** + * Get country id + * + * @return string + */ + public function getCountryId() + { + return $this->address->getCountryId(); + } + + /** + * Get street line 1 + * + * @return string + */ + public function getStreetLine1() + { + $street = $this->address->getStreet(); + return isset($street[0]) ? $street[0]: ''; + } + + /** + * Get street line 2 + * + * @return string + */ + public function getStreetLine2() + { + $street = $this->address->getStreet(); + return isset($street[1]) ? $street[1]: ''; + } + + /** + * Get telephone number + * + * @return string + */ + public function getTelephone() + { + return $this->address->getTelephone(); + } + + /** + * Get postcode + * + * @return string + */ + public function getPostcode() + { + return $this->address->getPostcode(); + } + + /** + * Get city name + * + * @return string + */ + public function getCity() + { + return $this->address->getCity(); + } + + /** + * Get first name + * + * @return string + */ + public function getFirstname() + { + return $this->address->getFirstname(); + } + + /** + * Get last name + * + * @return string + */ + public function getLastname() + { + return $this->address->getLastname(); + } + + /** + * Get middle name + * + * @return string|null + */ + public function getMiddlename() + { + return $this->address->getMiddlename(); + } + + /** + * Get customer id + * + * @return int|null + */ + public function getCustomerId() + { + return $this->address->getCustomerId(); + } + + /** + * Get billing/shipping email + * + * @return string + */ + public function getEmail() + { + return $this->address->getEmail(); + } +} diff --git a/app/code/Magento/Payment/Gateway/Data/Quote/QuoteAdapter.php b/app/code/Magento/Payment/Gateway/Data/Quote/QuoteAdapter.php new file mode 100644 index 0000000000000000000000000000000000000000..b6ed86aa58522080817e7837695245fadde89875 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Data/Quote/QuoteAdapter.php @@ -0,0 +1,89 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Data\Quote; + +use Magento\Payment\Gateway\Data\OrderAdapterInterface; +use Magento\Quote\Api\Data\CartInterface; +use Magento\Payment\Gateway\Data\AddressAdapterInterface; + +class QuoteAdapter implements OrderAdapterInterface +{ + /** + * @var CartInterface + */ + private $quote; + + /** + * @var AddressAdapter + */ + private $addressAdapterFactory; + + /** + * @param CartInterface $quote + * @param AddressAdapterFactory $addressAdapterFactory + */ + public function __construct( + CartInterface $quote, + AddressAdapterFactory $addressAdapterFactory + ) { + $this->quote = $quote; + $this->addressAdapterFactory = $addressAdapterFactory; + } + + /** + * Returns currency code + * + * @return string + */ + public function getCurrencyCode() + { + return $this->quote->getCurrency()->getBaseCurrencyCode(); + } + + /** + * Returns order increment id + * + * @return string + */ + public function getOrderIncrementId() + { + return $this->quote->getReservedOrderId(); + } + + /** + * Returns customer ID + * + * @return int|null + */ + public function getCustomerId() + { + return $this->quote->getCustomer()->getId(); + } + + /** + * Returns billing address + * + * @return AddressAdapterInterface + */ + public function getBillingAddress() + { + return $this->addressAdapterFactory->create( + ['address' => $this->quote->getBillingAddress()] + ); + } + + /** + * Returns shipping address + * + * @return AddressAdapterInterface + */ + public function getShippingAddress() + { + return $this->addressAdapterFactory->create( + ['address' => $this->quote->getShippingAddress()] + ); + } +} diff --git a/app/code/Magento/Payment/Gateway/Http/Client/Zend.php b/app/code/Magento/Payment/Gateway/Http/Client/Zend.php new file mode 100644 index 0000000000000000000000000000000000000000..fb3b64434c605912f383c3fd77b4a9b91b6fc5b7 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Http/Client/Zend.php @@ -0,0 +1,71 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Http\Client; + +use Magento\Framework\HTTP\ZendClientFactory; +use Magento\Framework\HTTP\ZendClient; +use Magento\Payment\Gateway\Http\ClientInterface; + +class Zend implements ClientInterface +{ + /** + * @var ZendClientFactory + */ + private $clientFactory; + + /** + * @var \Magento\Payment\Gateway\Http\ConverterInterface + */ + private $converter; + + /** + * @param ZendClientFactory $clientFactory + * @param \Magento\Payment\Gateway\Http\ConverterInterface $converter + */ + public function __construct( + ZendClientFactory $clientFactory, + \Magento\Payment\Gateway\Http\ConverterInterface $converter + ) { + $this->clientFactory = $clientFactory; + $this->converter = $converter; + } + + /** + * {inheritdoc} + */ + public function placeRequest(\Magento\Payment\Gateway\Http\TransferInterface $transferObject) + { + /** @var ZendClient $client */ + $client = $this->clientFactory->create(); + + $client->setConfig($transferObject->getClientConfig()); + $client->setMethod($transferObject->getMethod()); + + switch($transferObject->getMethod()) { + case \Zend_Http_Client::GET: + $client->setParameterGet($transferObject->getBody()); + break; + case \Zend_Http_Client::POST: + $client->setParameterPost($transferObject->getBody()); + break; + default: + throw new \LogicException(sprintf('Unsupported HTTP method %s', $transferObject->getMethod())); + } + + $client->setHeaders($transferObject->getHeaders()); + $client->setUrlEncodeBody($transferObject->shouldEncode()); + $client->setUri($transferObject->getUri()); + + try { + $response = $client->request(); + return $this->converter->convert($response->getBody()); + } catch (\Zend_Http_Client_Exception $e) { + throw new \Magento\Payment\Gateway\Http\ClientException(__($e->getMessage())); + } catch (\Magento\Payment\Gateway\Http\ConverterException $e) { + throw $e; + } + } +} diff --git a/app/code/Magento/Payment/Gateway/Http/ClientException.php b/app/code/Magento/Payment/Gateway/Http/ClientException.php new file mode 100644 index 0000000000000000000000000000000000000000..c06404dfaa5870ec02491d6a959734553efc78b4 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Http/ClientException.php @@ -0,0 +1,12 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Http; + +use Magento\Framework\Exception\LocalizedException; + +class ClientException extends LocalizedException +{ +} diff --git a/app/code/Magento/Payment/Gateway/Http/ClientInterface.php b/app/code/Magento/Payment/Gateway/Http/ClientInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..e42ec92b5319f5db0af271c928c95eac33519267 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Http/ClientInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Http; + +use Magento\Payment\Gateway\Response; + +interface ClientInterface +{ + /** + * Places request to gateway. Returns result as ENV array + * + * @param \Magento\Payment\Gateway\Http\TransferInterface $transferObject + * @return array + * @throws \Magento\Payment\Gateway\Http\ClientException + * @throws \Magento\Payment\Gateway\Http\ConverterException + */ + public function placeRequest(\Magento\Payment\Gateway\Http\TransferInterface $transferObject); +} diff --git a/app/code/Magento/Payment/Gateway/Http/ConverterException.php b/app/code/Magento/Payment/Gateway/Http/ConverterException.php new file mode 100644 index 0000000000000000000000000000000000000000..69b59028b5ddc5422d5c3c1286c237f36b98f33c --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Http/ConverterException.php @@ -0,0 +1,12 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Http; + +use Magento\Framework\Exception\LocalizedException; + +class ConverterException extends LocalizedException +{ +} diff --git a/app/code/Magento/Payment/Gateway/Http/ConverterInterface.php b/app/code/Magento/Payment/Gateway/Http/ConverterInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..776ea4b11673d8589dfca68b53c203da27986bda --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Http/ConverterInterface.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Http; + +interface ConverterInterface +{ + /** + * Converts gateway response to ENV structure + * + * @param string $response + * @return array + * @throws \Magento\Payment\Gateway\Http\ConverterException + */ + public function convert($response); +} diff --git a/app/code/Magento/Payment/Gateway/Http/TransferBuilderInterface.php b/app/code/Magento/Payment/Gateway/Http/TransferBuilderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..b1a98abfa9af370c64c5e009ddda1185e917e3be --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Http/TransferBuilderInterface.php @@ -0,0 +1,19 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Http; + +use Magento\Payment\Gateway\Http\TransferInterface; + +interface TransferBuilderInterface +{ + /** + * Builds gateway transfer object + * + * @param array $requestENV + * @return TransferInterface + */ + public function build(array $requestENV); +} diff --git a/app/code/Magento/Payment/Gateway/Http/TransferInterface.php b/app/code/Magento/Payment/Gateway/Http/TransferInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..abd3d530b2ac59ff37b88ee738d29d79a864e8a8 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Http/TransferInterface.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Http; + +interface TransferInterface +{ + /** + * Returns gateway client configuration + * + * @return array + */ + public function getClientConfig(); + + /** + * Returns method used to place request + * + * @return string|int + */ + public function getMethod(); + + /** + * Returns headers + * + * @return array + */ + public function getHeaders(); + + /** + * Whether body should be encoded before place + * + * @return bool + */ + public function shouldEncode(); + + /** + * Returns request body + * + * @return string + */ + public function getBody(); + + /** + * Returns URI + * + * @return string + */ + public function getUri(); +} diff --git a/app/code/Magento/Payment/Gateway/Request/BuilderComposite.php b/app/code/Magento/Payment/Gateway/Request/BuilderComposite.php new file mode 100644 index 0000000000000000000000000000000000000000..33e7df313156a02863e4c1db01d2ffeca9c35816 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Request/BuilderComposite.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Request; + +use Magento\Framework\ObjectManager\TMap; + +class BuilderComposite implements BuilderInterface +{ + /** + * @var BuilderInterface[] + */ + private $builders; + + /** + * @param TMap $builders + */ + public function __construct( + TMap $builders + ) { + $this->builders = $builders; + } + + /** + * Builds ENV request + * + * @param array $buildSubject + * @return array + */ + public function build(array $buildSubject) + { + $result = []; + foreach ($this->builders as $builder) { + // @TODO implement exceptions catching + $result = array_merge($result, $builder->build($buildSubject)); + } + return $result; + } +} diff --git a/app/code/Magento/Payment/Gateway/Request/BuilderInterface.php b/app/code/Magento/Payment/Gateway/Request/BuilderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..4f4398f6c8952af722941b4ee671d4332aedf73e --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Request/BuilderInterface.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Request; + +interface BuilderInterface +{ + /** + * Builds ENV request + * + * @param array $buildSubject + * @return array + */ + public function build(array $buildSubject); +} diff --git a/app/code/Magento/Payment/Gateway/Response/HandlerChain.php b/app/code/Magento/Payment/Gateway/Response/HandlerChain.php new file mode 100644 index 0000000000000000000000000000000000000000..91205ccc844a35733ca07ff903f6390bcba3c332 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Response/HandlerChain.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Response; + +use Magento\Framework\ObjectManager\TMap; + +class HandlerChain implements HandlerInterface +{ + /** + * @var HandlerInterface[] + */ + private $handlers; + + /** + * @param TMap $handlers + */ + public function __construct( + TMap $handlers + ) { + $this->handlers = $handlers; + } + + /** + * Handles response + * + * @param array $handlingSubject + * @param array $response + * @return void + */ + public function handle(array $handlingSubject, array $response) + { + foreach ($this->handlers as $handler) { + // @TODO implement exceptions catching + $handler->handle($handlingSubject, $response); + } + } +} diff --git a/app/code/Magento/Payment/Gateway/Response/HandlerInterface.php b/app/code/Magento/Payment/Gateway/Response/HandlerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..788ca0ebfee16cbd18cc4c4125b375d486f96e25 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Response/HandlerInterface.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Response; + +interface HandlerInterface +{ + /** + * Handles response + * + * @param array $handlingSubject + * @param array $response + * @return void + */ + public function handle(array $handlingSubject, array $response); +} diff --git a/app/code/Magento/Payment/Gateway/Validator/CountryValidator.php b/app/code/Magento/Payment/Gateway/Validator/CountryValidator.php new file mode 100644 index 0000000000000000000000000000000000000000..3a0ff81186df3aff134f5e14c79d5a7f409a2e7b --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Validator/CountryValidator.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Validator; + +use Magento\Framework\Exception\NotFoundException; +use Magento\Payment\Gateway\ConfigInterface; +use Magento\Payment\Gateway\Validator\ResultInterfaceFactory; + +class CountryValidator implements ValidatorInterface +{ + /** + * @var \Magento\Payment\Gateway\ConfigInterface + */ + private $config; + + /** + * @var ResultInterfaceFactory + */ + private $resultFactory; + + /** + * @param \Magento\Payment\Gateway\ConfigInterface $config + * @param ResultInterfaceFactory $resultFactory + */ + public function __construct( + ConfigInterface $config, + ResultInterfaceFactory $resultFactory + ) { + $this->config = $config; + $this->resultFactory = $resultFactory; + } + + /** + * @param array $validationSubject + * @return bool + * @throws NotFoundException + * @throws \Exception + */ + public function validate(array $validationSubject) + { + $isValid = true; + $storeId = $validationSubject['storeId']; + + if ((int)$this->config->getValue('allowspecific', $storeId) === 1) { + $availableCountries = explode( + ',', + $this->config->getValue('specificcountry', $storeId) + ); + + if (!in_array($validationSubject['country'], $availableCountries)) { + $isValid = false; + } + } + + return $this->resultFactory->create( + [ + 'isValid' => $isValid + ] + ); + } +} diff --git a/app/code/Magento/Payment/Gateway/Validator/Result.php b/app/code/Magento/Payment/Gateway/Validator/Result.php new file mode 100644 index 0000000000000000000000000000000000000000..0171677d02a66d3e4f4e15d7ff0efbf20aaa13a6 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Validator/Result.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Validator; + +use Magento\Framework\Phrase; + +class Result implements ResultInterface +{ + /** + * @var bool + */ + private $isValid; + + /** + * @var Phrase[] + */ + private $failsDescription; + + /** + * @param bool $isValid + * @param array $failsDescription + */ + public function __construct( + $isValid, + array $failsDescription = [] + ) { + $this->isValid = (bool)$isValid; + $this->failsDescription = $failsDescription; + } + + /** + * Returns validation result + * + * @return bool + */ + public function isValid() + { + return $this->isValid; + } + + /** + * Returns list of fails description + * + * @return Phrase[] + */ + public function getFailsDescription() + { + return $this->failsDescription; + } +} diff --git a/app/code/Magento/Payment/Gateway/Validator/ResultInterface.php b/app/code/Magento/Payment/Gateway/Validator/ResultInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..ce6a60df7a68595a49dde5aeef12708737457ea6 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Validator/ResultInterface.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Validator; + +use Magento\Framework\Phrase; + +interface ResultInterface +{ + /** + * Returns validation result + * + * @return bool + */ + public function isValid(); + + /** + * Returns list of fails description + * + * @return Phrase[] + */ + public function getFailsDescription(); +} diff --git a/app/code/Magento/Payment/Gateway/Validator/ValidatorComposite.php b/app/code/Magento/Payment/Gateway/Validator/ValidatorComposite.php new file mode 100644 index 0000000000000000000000000000000000000000..6ee690a2500ee6e520656acc67c5a138ed8a3783 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Validator/ValidatorComposite.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Validator; + +use Magento\Framework\ObjectManager\TMap; +use Magento\Payment\Gateway\Validator\ResultInterfaceFactory; + +class ValidatorComposite implements ValidatorInterface +{ + /** + * @var ValidatorInterface[] + */ + private $validators; + + /** + * @var ResultInterfaceFactory + */ + private $resultFactory; + + /** + * @param ResultInterfaceFactory $resultFactory + * @param TMap $validators + */ + public function __construct( + ResultInterfaceFactory $resultFactory, + TMap $validators + ) { + $this->validators = $validators; + $this->resultFactory = $resultFactory; + } + + /** + * Performs domain level validation for business object + * + * @param array $validationSubject + * @return ResultInterface + */ + public function validate(array $validationSubject) + { + $isValid = true; + $failsDescriptionAggregate = []; + foreach ($this->validators as $validator) { + $result = $validator->validate($validationSubject); + if (!$result->isValid()) { + $isValid = false; + $failsDescriptionAggregate = array_merge( + $failsDescriptionAggregate, + $result->getFailsDescription() + ); + } + } + + return $this->resultFactory->create( + [ + 'isValid' => $isValid, + 'failsDescription' => $failsDescriptionAggregate + ] + ); + } +} diff --git a/app/code/Magento/Payment/Gateway/Validator/ValidatorInterface.php b/app/code/Magento/Payment/Gateway/Validator/ValidatorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..9c501871832489e62b17e499f4553d96268b0761 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Validator/ValidatorInterface.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Validator; + +interface ValidatorInterface +{ + /** + * Performs domain-related validation for business object + * + * @param array $validationSubject + * @return ResultInterface + */ + public function validate(array $validationSubject); +} diff --git a/app/code/Magento/Payment/Gateway/Validator/ValidatorPool.php b/app/code/Magento/Payment/Gateway/Validator/ValidatorPool.php new file mode 100644 index 0000000000000000000000000000000000000000..c2f2b347de8acff129afbc85f596a16788961754 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Validator/ValidatorPool.php @@ -0,0 +1,42 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Validator; + +use Magento\Framework\Exception\NotFoundException; +use Magento\Framework\ObjectManager\TMap; + +class ValidatorPool implements \Magento\Payment\Gateway\Validator\ValidatorPoolInterface +{ + /** + * @var ValidatorInterface[] + */ + private $validators; + + /** + * @param TMap $validators + */ + public function __construct( + TMap $validators + ) { + $this->validators = $validators; + } + + /** + * Returns configured validator + * + * @param string $code + * @return ValidatorInterface + * @throws NotFoundException + */ + public function get($code) + { + if (!isset($this->validators[$code])) { + throw new NotFoundException(__('Validator for field %1 does not exist.', $code)); + } + + return $this->validators[$code]; + } +} diff --git a/app/code/Magento/Payment/Gateway/Validator/ValidatorPoolInterface.php b/app/code/Magento/Payment/Gateway/Validator/ValidatorPoolInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..d5f1ad25b70056d8cb8000cfd8385fbab9ea8b79 --- /dev/null +++ b/app/code/Magento/Payment/Gateway/Validator/ValidatorPoolInterface.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Gateway\Validator; + +use Magento\Framework\Exception\NotFoundException; + +interface ValidatorPoolInterface +{ + /** + * Returns configured validator + * + * @param string $code + * @return \Magento\Payment\Gateway\Validator\ValidatorInterface + * @throws NotFoundException + */ + public function get($code); +} diff --git a/app/code/Magento/Payment/Helper/Data.php b/app/code/Magento/Payment/Helper/Data.php index a848b6dafd3345a0cc9bfeca3df93d946ced63fd..9e2450a79d67793dfa4f75ca55ab75504940978a 100644 --- a/app/code/Magento/Payment/Helper/Data.php +++ b/app/code/Magento/Payment/Helper/Data.php @@ -115,7 +115,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper /** * Get and sort available payment methods for specified or current store * - * @param null|string|bool|int|Store $store + * @param null|string|bool|int $store * @param Quote|null $quote * @return AbstractMethod[] */ @@ -141,28 +141,25 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper /* if the payment method cannot be used at this time */ continue; } - $sortOrder = (int)$methodInstance->getConfigData('sort_order', $store); - $methodInstance->setSortOrder($sortOrder); $res[] = $methodInstance; } - uasort($res, [$this, '_sortMethods']); + @uasort( + $res, + function (MethodInterface $a, MethodInterface $b) { + if ((int)$a->getConfigData('sort_order') < (int)$b->getConfigData('sort_order')) { + return -1; + } - return $res; - } + if ((int)$a->getConfigData('sort_order') > (int)$b->getConfigData('sort_order')) { + return 1; + } - /** - * Sort payments methods - * - * @param MethodInterface $a - * @param MethodInterface $b - * @return int - */ - protected function _sortMethods($a, $b) - { - return (int)$a->getSortOrder() < - (int)$b->getSortOrder() ? -1 : ((int)$a->getSortOrder() > - (int)$b->getSortOrder() ? 1 : 0); + return 0; + } + ); + + return $res; } /** diff --git a/app/code/Magento/Payment/Model/CcGenericConfigProvider.php b/app/code/Magento/Payment/Model/CcGenericConfigProvider.php index 432756f744c80888114231cc0dbcf1c572a04d59..e3acac6d8c2071f6a649ab62a9129278757d197d 100644 --- a/app/code/Magento/Payment/Model/CcGenericConfigProvider.php +++ b/app/code/Magento/Payment/Model/CcGenericConfigProvider.php @@ -16,25 +16,22 @@ class CcGenericConfigProvider implements ConfigProviderInterface protected $ccConfig; /** - * @var string[] - */ - protected $methodCodes = []; - - /** - * @var Method\AbstractMethod[] + * @var MethodInterface[] */ protected $methods = []; /** * @param CcConfig $ccConfig * @param PaymentHelper $paymentHelper + * @param array $methodCodes */ public function __construct( CcConfig $ccConfig, - PaymentHelper $paymentHelper + PaymentHelper $paymentHelper, + array $methodCodes = [] ) { $this->ccConfig = $ccConfig; - foreach ($this->methodCodes as $code) { + foreach ($methodCodes as $code) { $this->methods[$code] = $paymentHelper->getMethodInstance($code); } } @@ -45,8 +42,8 @@ class CcGenericConfigProvider implements ConfigProviderInterface public function getConfig() { $config = []; - foreach ($this->methodCodes as $methodCode) { - if ($this->methods[$methodCode]->isAvailable()) { + foreach ($this->methods as $methodCode => $method) { + if ($method->isAvailable()) { $config = array_merge_recursive($config, [ 'payment' => [ 'ccform' => [ @@ -56,9 +53,9 @@ class CcGenericConfigProvider implements ConfigProviderInterface 'hasVerification' => [$methodCode => $this->hasVerification($methodCode)], 'hasSsCardType' => [$methodCode => $this->hasSsCardType($methodCode)], 'ssStartYears' => [$methodCode => $this->getSsStartYears()], - 'cvvImageUrl' => [$methodCode => $this->getCvvImageUrl()], - ], - ], + 'cvvImageUrl' => [$methodCode => $this->getCvvImageUrl()] + ] + ] ]); } } diff --git a/app/code/Magento/Payment/Model/Checks/CanUseCheckout.php b/app/code/Magento/Payment/Model/Checks/CanUseCheckout.php index 62a4866cc94b5246a66c6b1108025fcfb95ee0ca..f49e40ec596e85410a57c2f9c26085ffba33ad46 100644 --- a/app/code/Magento/Payment/Model/Checks/CanUseCheckout.php +++ b/app/code/Magento/Payment/Model/Checks/CanUseCheckout.php @@ -5,6 +5,7 @@ */ namespace Magento\Payment\Model\Checks; +use Magento\Payment\Model\MethodInterface; use Magento\Quote\Model\Quote; class CanUseCheckout implements SpecificationInterface @@ -12,11 +13,11 @@ class CanUseCheckout implements SpecificationInterface /** * Check whether payment method is applicable to quote * - * @param PaymentMethodChecksInterface $paymentMethod + * @param MethodInterface $paymentMethod * @param Quote $quote * @return bool */ - public function isApplicable(PaymentMethodChecksInterface $paymentMethod, Quote $quote) + public function isApplicable(MethodInterface $paymentMethod, Quote $quote) { return $paymentMethod->canUseCheckout(); } diff --git a/app/code/Magento/Payment/Model/Checks/CanUseForCountry.php b/app/code/Magento/Payment/Model/Checks/CanUseForCountry.php index 0a5920ad18120f2f861dbdbf36f50da7d87284ac..46e129662cc7859f315e00ab6207e12ceee599ba 100644 --- a/app/code/Magento/Payment/Model/Checks/CanUseForCountry.php +++ b/app/code/Magento/Payment/Model/Checks/CanUseForCountry.php @@ -5,17 +5,18 @@ */ namespace Magento\Payment\Model\Checks; +use Magento\Payment\Model\MethodInterface; use Magento\Quote\Model\Quote; class CanUseForCountry implements SpecificationInterface { /** * Check whether payment method is applicable to quote - * @param PaymentMethodChecksInterface $paymentMethod + * @param MethodInterface $paymentMethod * @param Quote $quote * @return bool */ - public function isApplicable(PaymentMethodChecksInterface $paymentMethod, Quote $quote) + public function isApplicable(MethodInterface $paymentMethod, Quote $quote) { return $paymentMethod->canUseForCountry($quote->getBillingAddress()->getCountry()); } diff --git a/app/code/Magento/Payment/Model/Checks/CanUseForCurrency.php b/app/code/Magento/Payment/Model/Checks/CanUseForCurrency.php index 0087598de9c14ba93be23f5d065b44ba5b295e46..58e4df48e634fc6ed4edb1dbb725ae09c392703c 100644 --- a/app/code/Magento/Payment/Model/Checks/CanUseForCurrency.php +++ b/app/code/Magento/Payment/Model/Checks/CanUseForCurrency.php @@ -5,6 +5,7 @@ */ namespace Magento\Payment\Model\Checks; +use Magento\Payment\Model\MethodInterface; use Magento\Quote\Model\Quote; class CanUseForCurrency implements SpecificationInterface @@ -13,11 +14,11 @@ class CanUseForCurrency implements SpecificationInterface * Check whether payment method is applicable to quote * Purposed to allow use in controllers some logic that was implemented in blocks only before * - * @param PaymentMethodChecksInterface $paymentMethod + * @param MethodInterface $paymentMethod * @param \Magento\Quote\Model\Quote $quote * @return bool */ - public function isApplicable(PaymentMethodChecksInterface $paymentMethod, Quote $quote) + public function isApplicable(MethodInterface $paymentMethod, Quote $quote) { return $paymentMethod->canUseForCurrency($quote->getStore()->getBaseCurrencyCode()); } diff --git a/app/code/Magento/Payment/Model/Checks/CanUseInternal.php b/app/code/Magento/Payment/Model/Checks/CanUseInternal.php index 49b558cc4a253881b0e9f085da9c7889a057e36d..a7dd1d712a1fea2fe92e7da1a1d2170acb83263c 100644 --- a/app/code/Magento/Payment/Model/Checks/CanUseInternal.php +++ b/app/code/Magento/Payment/Model/Checks/CanUseInternal.php @@ -5,6 +5,7 @@ */ namespace Magento\Payment\Model\Checks; +use Magento\Payment\Model\MethodInterface; use Magento\Quote\Model\Quote; class CanUseInternal implements SpecificationInterface @@ -13,11 +14,11 @@ class CanUseInternal implements SpecificationInterface * Check whether payment method is applicable to quote * Purposed to allow use in controllers some logic that was implemented in blocks only before * - * @param PaymentMethodChecksInterface $paymentMethod + * @param MethodInterface $paymentMethod * @param \Magento\Quote\Model\Quote $quote * @return bool */ - public function isApplicable(PaymentMethodChecksInterface $paymentMethod, Quote $quote) + public function isApplicable(MethodInterface $paymentMethod, Quote $quote) { return $paymentMethod->canUseInternal(); } diff --git a/app/code/Magento/Payment/Model/Checks/Composite.php b/app/code/Magento/Payment/Model/Checks/Composite.php index c96af9b1a949a1067109f8cae811daaa9419e02e..e26874ec83fc02194d17495c5d8f059e09bc649d 100644 --- a/app/code/Magento/Payment/Model/Checks/Composite.php +++ b/app/code/Magento/Payment/Model/Checks/Composite.php @@ -5,6 +5,7 @@ */ namespace Magento\Payment\Model\Checks; +use Magento\Payment\Model\MethodInterface; use Magento\Quote\Model\Quote; class Composite implements SpecificationInterface @@ -23,11 +24,11 @@ class Composite implements SpecificationInterface /** * Check whether payment method is applicable to quote * - * @param PaymentMethodChecksInterface $paymentMethod + * @param MethodInterface $paymentMethod * @param \Magento\Quote\Model\Quote $quote * @return bool */ - public function isApplicable(PaymentMethodChecksInterface $paymentMethod, Quote $quote) + public function isApplicable(MethodInterface $paymentMethod, Quote $quote) { foreach ($this->list as $specification) { if (!$specification->isApplicable($paymentMethod, $quote)) { diff --git a/app/code/Magento/Payment/Model/Checks/PaymentMethodChecksInterface.php b/app/code/Magento/Payment/Model/Checks/PaymentMethodChecksInterface.php deleted file mode 100644 index 9d2ad43801e5ebda0834b4c4adff7019e4631b65..0000000000000000000000000000000000000000 --- a/app/code/Magento/Payment/Model/Checks/PaymentMethodChecksInterface.php +++ /dev/null @@ -1,66 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Payment\Model\Checks; - -/** - * Payment method interface for specification checks - */ -interface PaymentMethodChecksInterface -{ - /** - * Retrieve payment method code - * - * @return string - * @api - */ - public function getCode(); - - /** - * Using internal pages for input payment data - * Can be used in admin - * - * @return bool - * @api - */ - public function canUseInternal(); - - /** - * Can be used in regular checkout - * - * @return bool - * @api - */ - public function canUseCheckout(); - - /** - * To check billing country is allowed for the payment method - * - * @param string $country - * @return bool - * @api - */ - public function canUseForCountry($country); - - /** - * Check method for processing with base currency - * - * @param string $currencyCode - * @return bool - * @api - */ - public function canUseForCurrency($currencyCode); - - /** - * Retrieve information from payment configuration - * - * @param string $field - * @param int|string|null|\Magento\Store\Model\Store $storeId - * - * @return mixed - * @api - */ - public function getConfigData($field, $storeId = null); -} diff --git a/app/code/Magento/Payment/Model/Checks/SpecificationInterface.php b/app/code/Magento/Payment/Model/Checks/SpecificationInterface.php index 9a93c05d0c26f531a5ffc80ff11d17e78bcdb5a9..2acd8f9255e936c99120d5b680edc38f0eb29c93 100644 --- a/app/code/Magento/Payment/Model/Checks/SpecificationInterface.php +++ b/app/code/Magento/Payment/Model/Checks/SpecificationInterface.php @@ -5,6 +5,7 @@ */ namespace Magento\Payment\Model\Checks; +use Magento\Payment\Model\MethodInterface; use Magento\Quote\Model\Quote; /** @@ -15,9 +16,9 @@ interface SpecificationInterface /** * Check whether payment method is applicable to quote * - * @param PaymentMethodChecksInterface $paymentMethod + * @param MethodInterface $paymentMethod * @param \Magento\Quote\Model\Quote $quote * @return bool */ - public function isApplicable(PaymentMethodChecksInterface $paymentMethod, Quote $quote); + public function isApplicable(MethodInterface $paymentMethod, Quote $quote); } diff --git a/app/code/Magento/Payment/Model/Checks/TotalMinMax.php b/app/code/Magento/Payment/Model/Checks/TotalMinMax.php index 1503da90a7ecf752e2a2ef718cdcd91bf32753b7..418e5e884e3f873f55b5c83fae583e1ebd9dc56e 100644 --- a/app/code/Magento/Payment/Model/Checks/TotalMinMax.php +++ b/app/code/Magento/Payment/Model/Checks/TotalMinMax.php @@ -5,6 +5,7 @@ */ namespace Magento\Payment\Model\Checks; +use Magento\Payment\Model\MethodInterface; use Magento\Quote\Model\Quote; class TotalMinMax implements SpecificationInterface @@ -22,11 +23,11 @@ class TotalMinMax implements SpecificationInterface /** * Check whether payment method is applicable to quote * - * @param PaymentMethodChecksInterface $paymentMethod + * @param MethodInterface $paymentMethod * @param \Magento\Quote\Model\Quote $quote * @return bool */ - public function isApplicable(PaymentMethodChecksInterface $paymentMethod, Quote $quote) + public function isApplicable(MethodInterface $paymentMethod, Quote $quote) { $total = $quote->getBaseGrandTotal(); $minTotal = $paymentMethod->getConfigData(self::MIN_ORDER_TOTAL); diff --git a/app/code/Magento/Payment/Model/Checks/ZeroTotal.php b/app/code/Magento/Payment/Model/Checks/ZeroTotal.php index f28b43300124acf8dd77159eaeba845820761211..689dcb6d38921a8a410b173787826b0dedd4a771 100644 --- a/app/code/Magento/Payment/Model/Checks/ZeroTotal.php +++ b/app/code/Magento/Payment/Model/Checks/ZeroTotal.php @@ -5,6 +5,7 @@ */ namespace Magento\Payment\Model\Checks; +use Magento\Payment\Model\MethodInterface; use Magento\Quote\Model\Quote; class ZeroTotal implements SpecificationInterface @@ -13,11 +14,11 @@ class ZeroTotal implements SpecificationInterface * Check whether payment method is applicable to quote * Purposed to allow use in controllers some logic that was implemented in blocks only before * - * @param PaymentMethodChecksInterface $paymentMethod + * @param MethodInterface $paymentMethod * @param \Magento\Quote\Model\Quote $quote * @return bool */ - public function isApplicable(PaymentMethodChecksInterface $paymentMethod, Quote $quote) + public function isApplicable(MethodInterface $paymentMethod, Quote $quote) { return !($quote->getBaseGrandTotal() < 0.0001 && $paymentMethod->getCode() != 'free'); } diff --git a/app/code/Magento/Payment/Model/Config.php b/app/code/Magento/Payment/Model/Config.php index 9d782ce97998d70e2a78f63ecd92a51fa7a1a2ed..b60c24faeacae2f90f6c3cb07d41a2f8187e1f60 100644 --- a/app/code/Magento/Payment/Model/Config.php +++ b/app/code/Magento/Payment/Model/Config.php @@ -95,7 +95,8 @@ class Config if (isset($data['active']) && (bool)$data['active'] && isset($data['model'])) { /** @var AbstractMethod|null $methodModel Actually it's wrong interface */ $methodModel = $this->_paymentMethodFactory->create($data['model']); - $methodModel->setId($code)->setStore(null); + $methodModel->setId($code); + $methodModel->setStore(null); if ($methodModel->getConfigData('active', null)) { $methods[$code] = $methodModel; } diff --git a/app/code/Magento/Payment/Model/IframeConfigProvider.php b/app/code/Magento/Payment/Model/IframeConfigProvider.php index 4e995b0c22ab54457c6a72a6ec941cda8117d0a0..a3a48f64f6205766194ecf4a94c7253d81eee099 100644 --- a/app/code/Magento/Payment/Model/IframeConfigProvider.php +++ b/app/code/Magento/Payment/Model/IframeConfigProvider.php @@ -11,9 +11,15 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\UrlInterface; use Magento\Framework\View\Asset\Repository; use Magento\Payment\Helper\Data as PaymentHelper; +use Magento\Payment\Model\Method\TransparentInterface; use Psr\Log\LoggerInterface; -abstract class IframeConfigProvider implements ConfigProviderInterface +/** + * Class IframeConfigProvider + * @package Magento\Payment\Model + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class IframeConfigProvider implements ConfigProviderInterface { /** * @var Repository @@ -53,19 +59,22 @@ abstract class IframeConfigProvider implements ConfigProviderInterface * @param UrlInterface $urlBuilder * @param LoggerInterface $logger * @param PaymentHelper $paymentHelper + * @param string $methodCode */ public function __construct( Repository $assetRepo, RequestInterface $request, UrlInterface $urlBuilder, LoggerInterface $logger, - PaymentHelper $paymentHelper + PaymentHelper $paymentHelper, + $methodCode ) { $this->assetRepo = $assetRepo; $this->request = $request; $this->urlBuilder = $urlBuilder; $this->logger = $logger; - $this->method = $paymentHelper->getMethodInstance($this->methodCode); + $this->methodCode = $methodCode; + $this->method = $paymentHelper->getMethodInstance($methodCode); } /** @@ -83,8 +92,8 @@ abstract class IframeConfigProvider implements ConfigProviderInterface 'cgiUrl' => [$this->methodCode => $this->getCgiUrl()], 'placeOrderUrl' => [$this->methodCode => $this->getPlaceOrderUrl()], 'saveOrderUrl' => [$this->methodCode => $this->getSaveOrderUrl()], - ], - ], + ] + ] ]; } @@ -197,6 +206,9 @@ abstract class IframeConfigProvider implements ConfigProviderInterface */ protected function getMethodConfigData($fieldName) { - return $this->method->getConfigInterface()->getConfigValue($fieldName); + if ($this->method instanceof TransparentInterface) { + return $this->method->getConfigInterface()->getValue($fieldName); + } + return $this->method->getConfigData($fieldName); } } diff --git a/app/code/Magento/Payment/Model/Info.php b/app/code/Magento/Payment/Model/Info.php index 28de02b2dbf7b21ffea4e399750cef3412356711..87e62e44808f5996f8ececaa0c5215edb778063e 100644 --- a/app/code/Magento/Payment/Model/Info.php +++ b/app/code/Magento/Payment/Model/Info.php @@ -39,7 +39,7 @@ class Info extends AbstractExtensibleModel implements InfoInterface * @param \Magento\Payment\Helper\Data $paymentData * @param \Magento\Framework\Encryption\EncryptorInterface $encryptor * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -50,7 +50,7 @@ class Info extends AbstractExtensibleModel implements InfoInterface \Magento\Payment\Helper\Data $paymentData, \Magento\Framework\Encryption\EncryptorInterface $encryptor, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_paymentData = $paymentData; diff --git a/app/code/Magento/Payment/Model/Method/AbstractMethod.php b/app/code/Magento/Payment/Model/Method/AbstractMethod.php index ce7e1fd8495ca525780e0fa159696e5c1f429ccc..c9bc85c757d5c71b4c5b423637ce17d9a3456346 100644 --- a/app/code/Magento/Payment/Model/Method/AbstractMethod.php +++ b/app/code/Magento/Payment/Model/Method/AbstractMethod.php @@ -8,7 +8,7 @@ namespace Magento\Payment\Model\Method; -use Magento\Payment\Model\Checks\PaymentMethodChecksInterface; +use Magento\Payment\Model\InfoInterface; use Magento\Payment\Model\MethodInterface; use Magento\Sales\Model\Order\Invoice; use Magento\Sales\Model\Order\Payment; @@ -16,14 +16,12 @@ use Magento\Quote\Api\Data\PaymentMethodInterface; /** * Payment method abstract model - * @method AbstractMethod setStore() * @SuppressWarnings(PHPMD.ExcessivePublicCount) * @SuppressWarnings(PHPMD.TooManyFields) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibleModel implements MethodInterface, - PaymentMethodChecksInterface, PaymentMethodInterface { const ACTION_ORDER = 'order'; @@ -208,7 +206,7 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl protected $_scopeConfig; /** - * @var \Psr\Log\LoggerInterface + * @var Logger */ protected $logger; @@ -219,9 +217,11 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory * @param \Magento\Payment\Helper\Data $paymentData * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + * @param Logger $logger * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( \Magento\Framework\Model\Context $context, @@ -230,8 +230,9 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory, \Magento\Payment\Helper\Data $paymentData, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, + \Magento\Payment\Model\Method\Logger $logger, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -245,7 +246,7 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl ); $this->_paymentData = $paymentData; $this->_scopeConfig = $scopeConfig; - $this->logger = $context->getLogger(); + $this->logger = $logger; $this->initializeData($data); } @@ -262,6 +263,22 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl } } + /** + * {inheritdoc} + */ + public function setStore($storeId) + { + $this->setData('store', (int)$storeId); + } + + /** + * {inheritdoc} + */ + public function getStore() + { + return $this->getData('store'); + } + /** * Check order availability * @@ -341,13 +358,11 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl /** * Check void availability - * - * @param \Magento\Framework\Object $payment - * @return bool - * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @return bool + * @internal param \Magento\Framework\Object $payment * @api */ - public function canVoid(\Magento\Framework\Object $payment) + public function canVoid() { return $this->_canVoid; } @@ -398,13 +413,13 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl /** * Fetch transaction info * - * @param \Magento\Payment\Model\InfoInterface $payment + * @param InfoInterface $payment * @param string $transactionId * @return array * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @api */ - public function fetchTransactionInfo(\Magento\Payment\Model\InfoInterface $payment, $transactionId) + public function fetchTransactionInfo(InfoInterface $payment, $transactionId) { return []; } @@ -512,19 +527,31 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl /** * Retrieve payment information model object * - * @return \Magento\Payment\Model\InfoInterface + * @return InfoInterface * @throws \Magento\Framework\Exception\LocalizedException * @api */ public function getInfoInstance() { $instance = $this->getData('info_instance'); - if (!$instance instanceof \Magento\Payment\Model\InfoInterface) { + if (!$instance instanceof InfoInterface) { throw new \Magento\Framework\Exception\LocalizedException(__('We cannot retrieve the payment information object instance.')); } return $instance; } + /** + * Retrieve payment information model object + * + * @param InfoInterface $info + * @return void + * @api + */ + public function setInfoInstance(InfoInterface $info) + { + $this->setData('info_instance', $info); + } + /** * Validate payment method information object * @@ -554,15 +581,13 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl /** * Order payment abstract method * - * @param \Magento\Framework\Object $payment + * @param \Magento\Framework\Object|InfoInterface $payment * @param float $amount - * * @return $this * @throws \Magento\Framework\Exception\LocalizedException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @api */ - public function order(\Magento\Framework\Object $payment, $amount) + public function order(\Magento\Payment\Model\InfoInterface $payment, $amount) { if (!$this->canOrder()) { throw new \Magento\Framework\Exception\LocalizedException(__('The order action is not available.')); @@ -573,15 +598,13 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl /** * Authorize payment abstract method * - * @param \Magento\Framework\Object $payment + * @param \Magento\Framework\Object|InfoInterface $payment * @param float $amount - * * @return $this * @throws \Magento\Framework\Exception\LocalizedException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @api */ - public function authorize(\Magento\Framework\Object $payment, $amount) + public function authorize(\Magento\Payment\Model\InfoInterface $payment, $amount) { if (!$this->canAuthorize()) { throw new \Magento\Framework\Exception\LocalizedException(__('The authorize action is not available.')); @@ -592,15 +615,13 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl /** * Capture payment abstract method * - * @param \Magento\Framework\Object $payment + * @param \Magento\Framework\Object|InfoInterface $payment * @param float $amount - * * @return $this * @throws \Magento\Framework\Exception\LocalizedException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @api */ - public function capture(\Magento\Framework\Object $payment, $amount) + public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount) { if (!$this->canCapture()) { throw new \Magento\Framework\Exception\LocalizedException(__('The capture action is not available.')); @@ -609,49 +630,16 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl return $this; } - /** - * Set capture transaction ID to invoice for informational purposes - * - * Candidate to be deprecated - * - * @param Invoice $invoice - * @param Payment $payment - * @return $this - * @api - */ - public function processInvoice($invoice, $payment) - { - $invoice->setTransactionId($payment->getLastTransId()); - return $this; - } - - /** - * Set refund transaction id to payment object for informational purposes - * Candidate to be deprecated: - * there can be multiple refunds per payment, thus payment.refund_transaction_id doesn't make big sense - * - * @param Invoice $invoice - * @param Payment $payment - * @return $this - * @api - */ - public function processBeforeRefund($invoice, $payment) - { - $payment->setRefundTransactionId($invoice->getTransactionId()); - return $this; - } - /** * Refund specified amount for payment * - * @param \Magento\Framework\Object $payment + * @param \Magento\Framework\Object|InfoInterface $payment * @param float $amount * @return $this * @throws \Magento\Framework\Exception\LocalizedException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @api */ - public function refund(\Magento\Framework\Object $payment, $amount) + public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount) { if (!$this->canRefund()) { throw new \Magento\Framework\Exception\LocalizedException(__('The refund action is not available.')); @@ -659,29 +647,14 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl return $this; } - /** - * Set transaction ID into creditmemo for informational purposes - * @param \Magento\Sales\Model\Order\Creditmemo $creditmemo - * @param Payment $payment - * @return $this - * @api - */ - public function processCreditmemo($creditmemo, $payment) - { - $creditmemo->setTransactionId($payment->getLastTransId()); - return $this; - } - /** * Cancel payment abstract method * - * @param \Magento\Framework\Object $payment - * + * @param \Magento\Framework\Object|InfoInterface $payment * @return $this - * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @api */ - public function cancel(\Magento\Framework\Object $payment) + public function cancel(\Magento\Payment\Model\InfoInterface $payment) { return $this; } @@ -689,14 +662,14 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl /** * Void payment abstract method * - * @param \Magento\Framework\Object $payment + * @param \Magento\Framework\Object|InfoInterface $payment * @return $this * @throws \Magento\Framework\Exception\LocalizedException * @api */ - public function void(\Magento\Framework\Object $payment) + public function void(\Magento\Payment\Model\InfoInterface $payment) { - if (!$this->canVoid($payment)) { + if (!$this->canVoid()) { throw new \Magento\Framework\Exception\LocalizedException(__('Void action is not available.')); } return $this; @@ -704,13 +677,10 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl /** * Whether this method can accept or deny payment - * - * @param \Magento\Payment\Model\InfoInterface $payment * @return bool - * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @api */ - public function canReviewPayment(\Magento\Payment\Model\InfoInterface $payment) + public function canReviewPayment() { return $this->_canReviewPayment; } @@ -718,14 +688,14 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl /** * Attempt to accept a payment that us under review * - * @param \Magento\Payment\Model\InfoInterface $payment + * @param InfoInterface $payment * @return false * @throws \Magento\Framework\Exception\LocalizedException * @api */ - public function acceptPayment(\Magento\Payment\Model\InfoInterface $payment) + public function acceptPayment(InfoInterface $payment) { - if (!$this->canReviewPayment($payment)) { + if (!$this->canReviewPayment()) { throw new \Magento\Framework\Exception\LocalizedException(__('The payment review action is unavailable.')); } return false; @@ -734,14 +704,14 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl /** * Attempt to deny a payment that us under review * - * @param \Magento\Payment\Model\InfoInterface $payment + * @param InfoInterface $payment * @return false * @throws \Magento\Framework\Exception\LocalizedException * @api */ - public function denyPayment(\Magento\Payment\Model\InfoInterface $payment) + public function denyPayment(InfoInterface $payment) { - if (!$this->canReviewPayment($payment)) { + if (!$this->canReviewPayment()) { throw new \Magento\Framework\Exception\LocalizedException(__('The payment review action is unavailable.')); } return false; @@ -757,17 +727,6 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl return $this->getConfigData('title'); } - /** - * Retrieve fraud message if exists - * - * @return string - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function getFraudMessage() - { - return $this->getInfoInstance()->getAdditionalInformation('fraud_msg'); - } - /** * Retrieve information from payment configuration * @@ -802,17 +761,6 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl return $this; } - /** - * Prepare info instance for save - * - * @return $this - * @api - */ - public function prepareSave() - { - return $this; - } - /** * Check whether payment method can be used * @@ -880,14 +828,12 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl /** * Log debug data to file * - * @param mixed $debugData + * @param array $debugData * @return void */ protected function _debug($debugData) { - if ($this->getDebugFlag()) { - $this->logger->debug(var_export($debugData, true)); - } + $this->logger->debug($debugData, $this->getDebugReplacePrivateDataKeys(), $this->getDebugFlag()); } /** @@ -899,7 +845,7 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl */ public function getDebugFlag() { - return $this->getConfigData('debug'); + return (bool)(int)$this->getConfigData('debug'); } /** @@ -915,23 +861,12 @@ abstract class AbstractMethod extends \Magento\Framework\Model\AbstractExtensibl } /** - * {@inheritdoc} - * - * @return \Magento\Quote\Api\Data\PaymentMethodExtensionInterface|null - */ - public function getExtensionAttributes() - { - return $this->_getExtensionAttributes(); - } - - /** - * {@inheritdoc} + * Return replace keys for debug data * - * @param \Magento\Quote\Api\Data\PaymentMethodExtensionInterface $extensionAttributes - * @return $this + * @return array */ - public function setExtensionAttributes(\Magento\Quote\Api\Data\PaymentMethodExtensionInterface $extensionAttributes) + public function getDebugReplacePrivateDataKeys() { - return $this->_setExtensionAttributes($extensionAttributes); + return (array) $this->_debugReplacePrivateDataKeys; } } diff --git a/app/code/Magento/Payment/Model/Method/Adapter.php b/app/code/Magento/Payment/Model/Method/Adapter.php new file mode 100644 index 0000000000000000000000000000000000000000..acb0e56809e30c3c677aebc4bffc5611ac7112f1 --- /dev/null +++ b/app/code/Magento/Payment/Model/Method/Adapter.php @@ -0,0 +1,583 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Model\Method; + +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NotFoundException; +use Magento\Payment\Model\InfoInterface; +use Magento\Payment\Model\MethodInterface; + +/** + * Payment method facade. Abstract method adapter + * @SuppressWarnings(PHPMD.ExcessivePublicCount) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class Adapter implements MethodInterface +{ + /** + * @var \Magento\Payment\Gateway\Config\ValueHandlerPoolInterface + */ + private $valueHandlerPool; + + /** + * @var \Magento\Payment\Gateway\Validator\ValidatorPoolInterface + */ + private $validatorPool; + + /** + * @var \Magento\Payment\Gateway\Command\CommandPoolInterface + */ + private $commandPool; + + /** + * @var int + */ + private $storeId; + + /** + * @var string + */ + private $formBlockType; + + /** + * @var string + */ + private $infoBlockType; + + /** + * @var InfoInterface + */ + private $infoInstance; + + /** + * @var string + */ + private $code; + + /** + * @var \Magento\Framework\Event\ManagerInterface + */ + private $eventManager; + + /** + * @var \Magento\Payment\Gateway\Data\PaymentDataObjectFactory + */ + private $paymentDataObjectFactory; + + /** + * @param \Magento\Framework\Event\ManagerInterface $eventManager + * @param \Magento\Payment\Gateway\Config\ValueHandlerPoolInterface $valueHandlerPool + * @param \Magento\Payment\Gateway\Validator\ValidatorPoolInterface $validatorPool + * @param \Magento\Payment\Gateway\Command\CommandPoolInterface $commandPool + * @param \Magento\Payment\Gateway\Data\PaymentDataObjectFactory $paymentDataObjectFactory + * @param string $code + * @param string $formBlockType + * @param string $infoBlockType + */ + public function __construct( + \Magento\Framework\Event\ManagerInterface $eventManager, + \Magento\Payment\Gateway\Config\ValueHandlerPoolInterface $valueHandlerPool, + \Magento\Payment\Gateway\Validator\ValidatorPoolInterface $validatorPool, + \Magento\Payment\Gateway\Command\CommandPoolInterface $commandPool, + \Magento\Payment\Gateway\Data\PaymentDataObjectFactory $paymentDataObjectFactory, + $code, + $formBlockType, + $infoBlockType + ) { + $this->valueHandlerPool = $valueHandlerPool; + $this->validatorPool = $validatorPool; + $this->commandPool = $commandPool; + $this->code = $code; + $this->infoBlockType = $infoBlockType; + $this->formBlockType = $formBlockType; + $this->eventManager = $eventManager; + $this->paymentDataObjectFactory = $paymentDataObjectFactory; + } + + /** + * {inheritdoc} + */ + public function canOrder() + { + return $this->canPerformCommand('order'); + } + + /** + * {inheritdoc} + */ + public function canAuthorize() + { + return $this->canPerformCommand('authorize'); + } + + /** + * {inheritdoc} + */ + public function canCapture() + { + return $this->canPerformCommand('capture'); + } + + /** + * {inheritdoc} + */ + public function canCapturePartial() + { + return $this->canPerformCommand('capture_partial'); + } + + /** + * {inheritdoc} + */ + public function canCaptureOnce() + { + return $this->canPerformCommand('capture_once'); + } + + /** + * {inheritdoc} + */ + public function canRefund() + { + return $this->canPerformCommand('refund'); + } + + /** + * {inheritdoc} + */ + public function canRefundPartialPerInvoice() + { + return $this->canPerformCommand('refund_partial_per_invoice'); + } + + /** + * {inheritdoc} + */ + public function canVoid() + { + return $this->canPerformCommand('void'); + } + + /** + * {inheritdoc} + */ + public function canUseInternal() + { + return (bool)$this->getConfiguredValue('can_use_internal'); + } + + /** + * {inheritdoc} + */ + public function canUseCheckout() + { + return (bool)$this->getConfiguredValue('can_use_checkout'); + } + + /** + * {inheritdoc} + */ + public function canEdit() + { + return (bool)$this->getConfiguredValue('can_edit'); + } + + /** + * {inheritdoc} + */ + public function canFetchTransactionInfo() + { + return $this->canPerformCommand('fetch_transaction_info'); + } + + /** + * {inheritdoc} + */ + public function canReviewPayment() + { + return $this->canPerformCommand('review_payment'); + } + + /** + * {inheritdoc} + */ + public function isGateway() + { + return (bool)$this->getConfiguredValue('is_gateway'); + } + + /** + * {inheritdoc} + */ + public function isOffline() + { + return (bool)$this->getConfiguredValue('is_offline'); + } + + /** + * {inheritdoc} + */ + public function isInitializeNeeded() + { + return false; + } + + /** + * {inheritdoc} + */ + public function isAvailable($quote = null) + { + $checkResult = new \StdClass(); + $isActive = $this->isActive($quote ? $quote->getStoreId() : null); + $checkResult->isAvailable = $isActive; + $checkResult->isDeniedInConfig = !$isActive; + + // for future use in observers + $this->eventManager->dispatch( + 'payment_method_is_active', + [ + 'result' => $checkResult, + 'method_instance' => $this, + 'quote' => $quote + ] + ); + + return $checkResult->isAvailable; + } + + /** + * {inheritdoc} + */ + public function isActive($storeId = null) + { + return $this->getConfigData('active', $storeId); + } + + /** + * {inheritdoc} + */ + public function canUseForCountry($country) + { + try { + $validator = $this->validatorPool->get('country'); + } catch (NotFoundException $e) { + return true; + } + + $result = $validator->validate(['country' => $country, 'storeId' => $this->getStore()]); + return $result->isValid(); + } + + /** + * {inheritdoc} + */ + public function canUseForCurrency($currencyCode) + { + try { + $validator = $this->validatorPool->get('currency'); + } catch (NotFoundException $e) { + return true; + } + + $result = $validator->validate(['currency' => $currencyCode, 'storeId' => $this->getStore()]); + return $result->isValid(); + } + + /** + * Whether payment command is supported and can be executed + * + * @param string $commandCode + * @return bool + */ + private function canPerformCommand($commandCode) + { + return (bool)$this->getConfiguredValue('can_' . $commandCode); + } + + /** + * Unifies configured value handling logic + * + * @param string $field + * @return mixed + */ + private function getConfiguredValue($field) + { + $handler = $this->valueHandlerPool->get($field); + return $handler->handle($field, $this->getStore()); + } + + /** + * {inheritdoc} + */ + public function validate() + { + try { + $validator = $this->validatorPool->get('global'); + } catch (NotFoundException $e) { + return $this; + } + + $result = $validator->validate( + ['payment' => $this->getInfoInstance(), 'storeId' => $this->getStore()] + ); + + if (!$result->isValid()) { + throw new LocalizedException( + implode("\n", $result->getFailsDescription()) + ); + } + + return $this; + } + + /** + * {inheritdoc} + */ + public function fetchTransactionInfo(InfoInterface $payment, $transactionId) + { + $this->executeCommand( + 'fetch_transaction_information', + $payment, + ['transactionId' => $transactionId] + ); + } + + /** + * {inheritdoc} + */ + public function order(InfoInterface $payment, $amount) + { + $this->executeCommand( + 'order', + $payment, + ['amount' => $amount] + ); + return $this; + } + + /** + * {inheritdoc} + */ + public function authorize(InfoInterface $payment, $amount) + { + $this->executeCommand( + 'authorize', + $payment, + ['amount' => $amount] + ); + return $this; + } + + /** + * {inheritdoc} + */ + public function capture(InfoInterface $payment, $amount) + { + $this->executeCommand( + 'capture', + $payment, + ['amount' => $amount] + ); + + return $this; + } + + /** + * {inheritdoc} + */ + public function refund(InfoInterface $payment, $amount) + { + $this->executeCommand( + 'refund', + $payment, + ['amount' => $amount] + ); + return $this; + } + + /** + * {inheritdoc} + */ + public function cancel(InfoInterface $payment) + { + $this->executeCommand( + 'cancel', + $payment + ); + return $this; + } + + /** + * {inheritdoc} + */ + public function void(InfoInterface $payment) + { + $this->executeCommand( + 'void', + $payment + ); + return $this; + } + + /** + * {inheritdoc} + */ + public function acceptPayment(InfoInterface $payment) + { + $this->executeCommand( + 'accept_payment', + $payment + ); + return $this; + } + + /** + * {inheritdoc} + */ + public function denyPayment(InfoInterface $payment) + { + $this->executeCommand( + 'deny_payment', + $payment + ); + return false; + } + + /** + * Performs command + * + * @param string $commandCode + * @param InfoInterface $payment + * @param array $arguments + * @return void + * @throws NotFoundException + * @throws \Exception + */ + private function executeCommand($commandCode, InfoInterface $payment, array $arguments = []) + { + if ($this->canPerformCommand($commandCode)) { + try { + $command = $this->commandPool->get($commandCode); + $arguments['payment'] = $this->paymentDataObjectFactory->create($payment); + $command->execute($arguments); + } catch (NotFoundException $e) { + throw $e; + } + } + } + + /** + * {inheritdoc} + */ + public function getCode() + { + return $this->code; + } + + /** + * {inheritdoc} + */ + public function getTitle() + { + return $this->getConfiguredValue('title'); + } + + /** + * {inheritdoc} + */ + public function setStore($storeId) + { + $this->storeId = (int)$storeId; + } + + /** + * {inheritdoc} + */ + public function getStore() + { + return $this->storeId; + } + + /** + * {inheritdoc} + */ + public function getFormBlockType() + { + return $this->formBlockType; + } + + /** + * {inheritdoc} + */ + public function getInfoBlockType() + { + return $this->infoBlockType; + } + + /** + * {inheritdoc} + */ + public function getInfoInstance() + { + if (!$this->infoInstance instanceof InfoInterface) { + throw new LocalizedException( + __('We cannot retrieve the payment information object instance.') + ); + } + + return $this->infoInstance; + } + + /** + * {inheritdoc} + */ + public function setInfoInstance(InfoInterface $info) + { + $this->infoInstance = $info; + } + + /** + * {inheritdoc} + */ + public function getConfigData($field, $storeId = null) + { + if ($storeId === null) { + return $this->getConfiguredValue($field); + } + + $handler = $this->valueHandlerPool->get($field); + return $handler->handle($field, (int)$storeId); + } + + /** + * {inheritdoc} + */ + public function assignData($data) + { + if (is_array($data)) { + $this->getInfoInstance()->addData($data); + } elseif ($data instanceof \Magento\Framework\Object) { + $this->getInfoInstance()->addData($data->getData()); + } + return $this; + } + + /** + * {inheritdoc} + */ + public function initialize($paymentAction, $stateObject) + { + return $this; + } + + /** + * {inheritdoc} + */ + public function getConfigPaymentAction() + { + return $this->getConfiguredValue('payment_action'); + } +} diff --git a/app/code/Magento/Payment/Model/Method/Cc.php b/app/code/Magento/Payment/Model/Method/Cc.php index 7e9e8c018116910a54dff0dab95c93c4a72ea0a9..dd8bd650bc73b33a23a681a9ad2d4a41403562a3 100644 --- a/app/code/Magento/Payment/Model/Method/Cc.php +++ b/app/code/Magento/Payment/Model/Method/Cc.php @@ -43,10 +43,11 @@ class Cc extends \Magento\Payment\Model\Method\AbstractMethod * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory * @param \Magento\Payment\Helper\Data $paymentData * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + * @param Logger $logger * @param \Magento\Framework\Module\ModuleListInterface $moduleList * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -57,10 +58,11 @@ class Cc extends \Magento\Payment\Model\Method\AbstractMethod \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory, \Magento\Payment\Helper\Data $paymentData, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, + \Magento\Payment\Model\Method\Logger $logger, \Magento\Framework\Module\ModuleListInterface $moduleList, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -70,6 +72,7 @@ class Cc extends \Magento\Payment\Model\Method\AbstractMethod $customAttributeFactory, $paymentData, $scopeConfig, + $logger, $resource, $resourceCollection, $data @@ -114,22 +117,6 @@ class Cc extends \Magento\Payment\Model\Method\AbstractMethod return $this; } - /** - * Prepare info instance for save - * - * @return $this - */ - public function prepareSave() - { - $info = $this->getInfoInstance(); - if ($this->_canSaveCc) { - $info->setCcNumberEnc($info->encrypt($info->getCcNumber())); - } - //$info->setCcCidEnc($info->encrypt($info->getCcCid())); - $info->setCcNumber(null)->setCcCid(null); - return $this; - } - /** * Validate payment method information object * diff --git a/app/code/Magento/Payment/Model/Method/ConfigInterface.php b/app/code/Magento/Payment/Model/Method/ConfigInterface.php index 600f4fdb53a8c0eada317308eeda14a9a26907ee..c2bf71e518065128cba1783b758899b2209dba8d 100644 --- a/app/code/Magento/Payment/Model/Method/ConfigInterface.php +++ b/app/code/Magento/Payment/Model/Method/ConfigInterface.php @@ -10,14 +10,6 @@ namespace Magento\Payment\Model\Method; * * @author Magento Core Team <core@magentocommerce.com> */ -interface ConfigInterface +interface ConfigInterface extends \Magento\Payment\Gateway\ConfigInterface { - /** - * Config field getter - * The specified key can be either in camelCase or under_score format - * - * @param string $key - * @return mixed - */ - public function getConfigValue($key); } diff --git a/app/code/Magento/Payment/Model/Method/Free.php b/app/code/Magento/Payment/Model/Method/Free.php index 40d9cb98f24a5a5944cc2554cfbc95b4d0cb7154..48e7a721f0178949b2f92fa5c726984f3a1c885e 100644 --- a/app/code/Magento/Payment/Model/Method/Free.php +++ b/app/code/Magento/Payment/Model/Method/Free.php @@ -50,9 +50,10 @@ class Free extends \Magento\Payment\Model\Method\AbstractMethod * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory * @param \Magento\Payment\Helper\Data $paymentData * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + * @param Logger $logger * @param PriceCurrencyInterface $priceCurrency * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -63,9 +64,10 @@ class Free extends \Magento\Payment\Model\Method\AbstractMethod \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory, \Magento\Payment\Helper\Data $paymentData, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, + \Magento\Payment\Model\Method\Logger $logger, PriceCurrencyInterface $priceCurrency, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -75,6 +77,7 @@ class Free extends \Magento\Payment\Model\Method\AbstractMethod $customAttributeFactory, $paymentData, $scopeConfig, + $logger, $resource, $resourceCollection, $data diff --git a/app/code/Magento/Payment/Model/Method/Logger.php b/app/code/Magento/Payment/Model/Method/Logger.php index 9c9e54e5e23636527f64eaff58997e6bb0de70c7..107de086bb90d5ed63e45850d082f67700fbc19f 100644 --- a/app/code/Magento/Payment/Model/Method/Logger.php +++ b/app/code/Magento/Payment/Model/Method/Logger.php @@ -14,6 +14,7 @@ use Psr\Log\LoggerInterface; */ class Logger { + const DEBUG_KEYS_MASK = '****'; /** * @var LoggerInterface */ @@ -30,15 +31,40 @@ class Logger /** * Logs payment related information used for debug * - * @param mixed $logData - * @param ConfigInterface $config - * + * @param array $debugData + * @param array $debugReplaceKeys + * @param bool $debugFlag * @return void */ - public function debug($logData, ConfigInterface $config) + public function debug(array $debugData, array $debugReplaceKeys, $debugFlag) { - if ($config->getConfigValue('debug')) { - $this->logger->debug(var_export($logData, true)); + if ($debugFlag == true && !empty($debugData) && !empty($debugReplaceKeys)) { + $debugData = $this->filterDebugData( + $debugData, + $debugReplaceKeys + ); + $this->logger->debug(var_export($debugData, true)); + } + } + + /** + * Recursive filter data by private conventions + * + * @param array $debugData + * @param array $debugReplacePrivateDataKeys + * @return array + */ + protected function filterDebugData(array $debugData, array $debugReplacePrivateDataKeys) + { + $debugReplacePrivateDataKeys = array_map('strtolower', $debugReplacePrivateDataKeys); + + foreach (array_keys($debugData) as $key) { + if (in_array(strtolower($key), $debugReplacePrivateDataKeys)) { + $debugData[$key] = self::DEBUG_KEYS_MASK; + } elseif (is_array($debugData[$key])) { + $debugData[$key] = $this->filterDebugData($debugData[$key], $debugReplacePrivateDataKeys); + } } + return $debugData; } } diff --git a/app/code/Magento/Payment/Model/Method/TransparentInterface.php b/app/code/Magento/Payment/Model/Method/TransparentInterface.php index eebb8594cc2ea9a0259edd508aef77bd6fa1c9b2..b5e673b6fd5636d3d2cb83cf54c9b3cb259d1f83 100644 --- a/app/code/Magento/Payment/Model/Method/TransparentInterface.php +++ b/app/code/Magento/Payment/Model/Method/TransparentInterface.php @@ -17,7 +17,7 @@ interface TransparentInterface extends MethodInterface /** * Returns payment method configured config * - * @return ConfigInterface + * @return \Magento\Payment\Gateway\ConfigInterface */ public function getConfigInterface(); } diff --git a/app/code/Magento/Payment/Model/MethodInterface.php b/app/code/Magento/Payment/Model/MethodInterface.php index f800703d73e3cf04cbbd8294c70262e5fb60ae0a..8ff23d1a0bf0dedb91950f90d0dcf69eecfce82c 100644 --- a/app/code/Magento/Payment/Model/MethodInterface.php +++ b/app/code/Magento/Payment/Model/MethodInterface.php @@ -4,11 +4,11 @@ * See COPYING.txt for license details. */ +namespace Magento\Payment\Model; + /** * Payment interface */ -namespace Magento\Payment\Model; - interface MethodInterface { /** @@ -24,6 +24,7 @@ interface MethodInterface * * @return string * @api + * @deprecated */ public function getFormBlockType(); @@ -34,4 +35,345 @@ interface MethodInterface * @api */ public function getTitle(); + + /** + * Store id setter + * @param int $storeId + * @return void + */ + public function setStore($storeId); + + /** + * Store id getter + * @return int + */ + public function getStore(); + + /** + * Check order availability + * + * @return bool + * @api + */ + public function canOrder(); + + /** + * Check authorize availability + * + * @return bool + * @api + */ + public function canAuthorize(); + + /** + * Check capture availability + * + * @return bool + * @api + */ + public function canCapture(); + + /** + * Check partial capture availability + * + * @return bool + * @api + */ + public function canCapturePartial(); + + /** + * Check whether capture can be performed once and no further capture possible + * + * @return bool + * @api + */ + public function canCaptureOnce(); + + /** + * Check refund availability + * + * @return bool + * @api + */ + public function canRefund(); + + /** + * Check partial refund availability for invoice + * + * @return bool + * @api + */ + public function canRefundPartialPerInvoice(); + + /** + * Check void availability + * @return bool + * @api + */ + public function canVoid(); + + /** + * Using internal pages for input payment data + * Can be used in admin + * + * @return bool + */ + public function canUseInternal(); + + /** + * Can be used in regular checkout + * + * @return bool + */ + public function canUseCheckout(); + + /** + * Can be edit order (renew order) + * + * @return bool + * @api + */ + public function canEdit(); + + /** + * Check fetch transaction info availability + * + * @return bool + * @api + */ + public function canFetchTransactionInfo(); + + /** + * Fetch transaction info + * + * @param InfoInterface $payment + * @param string $transactionId + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @api + */ + public function fetchTransactionInfo(InfoInterface $payment, $transactionId); + + /** + * Retrieve payment system relation flag + * + * @return bool + * @api + */ + public function isGateway(); + + /** + * Retrieve payment method online/offline flag + * + * @return bool + * @api + */ + public function isOffline(); + + /** + * Flag if we need to run payment initialize while order place + * + * @return bool + * @api + */ + public function isInitializeNeeded(); + + /** + * To check billing country is allowed for the payment method + * + * @param string $country + * @return bool + */ + public function canUseForCountry($country); + + /** + * Check method for processing with base currency + * + * @param string $currencyCode + * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function canUseForCurrency($currencyCode); + + /** + * Retrieve block type for display method information + * + * @return string + * @api + * @deprecated + */ + public function getInfoBlockType(); + + /** + * Retrieve payment information model object + * + * @return InfoInterface + * @throws \Magento\Framework\Exception\LocalizedException + * @api + * @deprecated + */ + public function getInfoInstance(); + + /** + * Retrieve payment information model object + * + * @param InfoInterface $info + * @return void + * @api + * @deprecated + */ + public function setInfoInstance(InfoInterface $info); + + /** + * Validate payment method information object + * + * @return $this + * @throws \Magento\Framework\Exception\LocalizedException + * @api + */ + public function validate(); + + /** + * Order payment abstract method + * + * @param \Magento\Framework\Object|InfoInterface $payment + * @param float $amount + * @return $this + * @api + */ + public function order(\Magento\Payment\Model\InfoInterface $payment, $amount); + + /** + * Authorize payment abstract method + * + * @param \Magento\Framework\Object|InfoInterface $payment + * @param float $amount + * @return $this + * @api + */ + public function authorize(\Magento\Payment\Model\InfoInterface $payment, $amount); + + /** + * Capture payment abstract method + * + * @param \Magento\Framework\Object|InfoInterface $payment + * @param float $amount + * @return $this + * @api + */ + public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount); + + /** + * Refund specified amount for payment + * + * @param \Magento\Framework\Object|InfoInterface $payment + * @param float $amount + * @return $this + * @api + */ + public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount); + + /** + * Cancel payment abstract method + * + * @param \Magento\Framework\Object|InfoInterface $payment + * @return $this + * @api + */ + public function cancel(\Magento\Payment\Model\InfoInterface $payment); + + /** + * Void payment abstract method + * + * @param \Magento\Framework\Object|InfoInterface $payment + * @return $this + * @api + */ + public function void(\Magento\Payment\Model\InfoInterface $payment); + + /** + * Whether this method can accept or deny payment + * @return bool + * @api + */ + public function canReviewPayment(); + + /** + * Attempt to accept a payment that us under review + * + * @param InfoInterface $payment + * @return false + * @throws \Magento\Framework\Exception\LocalizedException + * @api + */ + public function acceptPayment(InfoInterface $payment); + + /** + * Attempt to deny a payment that us under review + * + * @param InfoInterface $payment + * @return false + * @throws \Magento\Framework\Exception\LocalizedException + * @api + */ + public function denyPayment(InfoInterface $payment); + + /** + * Retrieve information from payment configuration + * + * @param string $field + * @param int|string|null|\Magento\Store\Model\Store $storeId + * + * @return mixed + */ + public function getConfigData($field, $storeId = null); + + /** + * Assign data to info model instance + * + * @param array|\Magento\Framework\Object $data + * @return $this + * @api + * @deprecated + */ + public function assignData($data); + + /** + * Check whether payment method can be used + * + * @param \Magento\Quote\Api\Data\CartInterface|null $quote + * @return bool + */ + public function isAvailable($quote = null); + + /** + * Is active + * + * @param int|null $storeId + * @return bool + */ + public function isActive($storeId = null); + + /** + * Method that will be executed instead of authorize or capture + * if flag isInitializeNeeded set to true + * + * @param string $paymentAction + * @param object $stateObject + * + * @return $this + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @api + * @deprecated + */ + public function initialize($paymentAction, $stateObject); + + /** + * Get config payment action url + * Used to universalize payment actions when processing payment place + * + * @return string + * @api + */ + public function getConfigPaymentAction(); } diff --git a/app/code/Magento/Payment/Test/Unit/Block/FormTest.php b/app/code/Magento/Payment/Test/Unit/Block/FormTest.php index 9f01df530fa1520c38e79312f2f309de3b4df336..c99001dbf2df028b6e8425f55e111133353d77f6 100644 --- a/app/code/Magento/Payment/Test/Unit/Block/FormTest.php +++ b/app/code/Magento/Payment/Test/Unit/Block/FormTest.php @@ -90,13 +90,9 @@ class FormTest extends \PHPUnit_Framework_TestCase ->method('getData') ->with($field) ->will($this->returnValue($value)); - $method = $this->getMock( - 'Magento\Payment\Model\MethodInterface', - ['getInfoInstance', 'getFormBlockType', 'getTitle', 'getCode'], - [], - '', - false - ); + $method = $this->getMockBuilder( + 'Magento\Payment\Model\MethodInterface' + )->getMockForAbstractClass(); $method->expects($this->any()) ->method('getInfoInstance') ->will($this->returnValue($methodInstance)); diff --git a/app/code/Magento/Payment/Test/Unit/Block/Info/InstructionsTest.php b/app/code/Magento/Payment/Test/Unit/Block/Info/InstructionsTest.php index ac1d630862772692bf364c276ccb6c8dd835d640..96dfbcc56a7a9bc14facb5a7ec212a774611ea55 100644 --- a/app/code/Magento/Payment/Test/Unit/Block/Info/InstructionsTest.php +++ b/app/code/Magento/Payment/Test/Unit/Block/Info/InstructionsTest.php @@ -43,13 +43,9 @@ class InstructionsTest extends \PHPUnit_Framework_TestCase public function testGetInstruction() { - $methodInstance = $this->getMock( - 'Magento\Payment\Model\MethodInterface', - ['getConfigData', 'getCode', 'getFormBlockType', 'getTitle'], - [], - '', - false - ); + $methodInstance = $this->getMockBuilder( + 'Magento\Payment\Model\MethodInterface' + )->getMockForAbstractClass(); $methodInstance->expects($this->once()) ->method('getConfigData') ->with('instructions') diff --git a/app/code/Magento/Payment/Test/Unit/Block/Info/SubstitutionTest.php b/app/code/Magento/Payment/Test/Unit/Block/Info/SubstitutionTest.php index 330fd41befb2009bda2cdf10ccee850e3629dc3a..a3c496ee2968d29d7b37c757680aa93c9e755dc9 100644 --- a/app/code/Magento/Payment/Test/Unit/Block/Info/SubstitutionTest.php +++ b/app/code/Magento/Payment/Test/Unit/Block/Info/SubstitutionTest.php @@ -126,9 +126,7 @@ class SubstitutionTest extends \PHPUnit_Framework_TestCase )->getMock(); $methodMock = $this->getMockBuilder( 'Magento\Payment\Model\MethodInterface' - )->disableOriginalConstructor()->setMethods( - [] - )->getMock(); + )->getMockForAbstractClass(); $infoMock->expects($this->once())->method('getMethodInstance')->will($this->returnValue($methodMock)); $this->block->setInfo($infoMock); diff --git a/app/code/Magento/Payment/Test/Unit/Block/Transparent/FormTest.php b/app/code/Magento/Payment/Test/Unit/Block/Transparent/FormTest.php index b361cc1881eec8ae1c463dbf7b2ead8d1ce39a19..6a6342ef7ab7e0725b991d3ce42b0f076218c9df 100644 --- a/app/code/Magento/Payment/Test/Unit/Block/Transparent/FormTest.php +++ b/app/code/Magento/Payment/Test/Unit/Block/Transparent/FormTest.php @@ -99,7 +99,7 @@ class FormTest extends \PHPUnit_Framework_TestCase */ public function testGetMethodConfigData($fieldName, $fieldValue, $expected) { - $this->initializeMethodWithConfigMock([[$fieldName, $fieldValue]]); + $this->initializeMethodWithConfigMock([[$fieldName, null, $fieldValue]]); $this->form->setMethod($this->methodMock); @@ -117,7 +117,7 @@ class FormTest extends \PHPUnit_Framework_TestCase ->getMock(); $configInterface->expects($this->any()) - ->method('getConfigValue') + ->method('getValue') ->willReturnMap($configMap); $this->methodMock->expects($this->any()) @@ -155,9 +155,9 @@ class FormTest extends \PHPUnit_Framework_TestCase { $this->initializeMethodWithConfigMock( [ - ['sandbox_flag', $sandboxFlag], - ['cgi_url_test_mode', $cgiUrlTestMode], - ['cgi_url', $cgiUrl] + ['sandbox_flag', null, $sandboxFlag], + ['cgi_url_test_mode', null, $cgiUrlTestMode], + ['cgi_url', null, $cgiUrl] ] ); @@ -198,7 +198,7 @@ class FormTest extends \PHPUnit_Framework_TestCase { $orderUrlPattern = 'order_url'; $builtOrderUrl = 'built_url'; - $this->initializeMethodWithConfigMock([['place_order_url', $orderUrlPattern]]); + $this->initializeMethodWithConfigMock([['place_order_url', null, $orderUrlPattern]]); $this->urlBuilderMock->expects($this->once()) ->method('getUrl') @@ -213,7 +213,7 @@ class FormTest extends \PHPUnit_Framework_TestCase public function testGetDateDelim() { $dateDelimiter = '/'; - $this->initializeMethodWithConfigMock([['date_delim', $dateDelimiter]]); + $this->initializeMethodWithConfigMock([['date_delim', null, $dateDelimiter]]); $this->form->setMethod($this->methodMock); @@ -223,7 +223,7 @@ class FormTest extends \PHPUnit_Framework_TestCase public function testGetCardFieldsMap() { $ccfields = 'x_card_code,x_exp_date,x_card_num'; - $this->initializeMethodWithConfigMock([['ccfields', $ccfields]]); + $this->initializeMethodWithConfigMock([['ccfields', null, $ccfields]]); $this->form->setMethod($this->methodMock); diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Command/CommandPoolTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Command/CommandPoolTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e39384caf7849e52bef212c734d5f88f76aed083 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Command/CommandPoolTest.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Command; + +use Magento\Payment\Gateway\Command\CommandPool; + +class CommandPoolTest extends \PHPUnit_Framework_TestCase +{ + public function testGet() + { + $commandI = $this->getMockBuilder('Magento\Payment\Gateway\CommandInterface') + ->getMockForAbstractClass(); + $tMap = $this->getMockBuilder('Magento\Framework\ObjectManager\TMap') + ->disableOriginalConstructor() + ->getMock(); + $tMap->expects(static::once()) + ->method('offsetExists') + ->with('command') + ->willReturn(true); + $tMap->expects(static::once()) + ->method('offsetGet') + ->with('command') + ->willReturn($commandI); + + $pool = new CommandPool($tMap); + + static::assertSame($commandI, $pool->get('command')); + } + + public function testGetException() + { + $this->setExpectedException('Magento\Framework\Exception\NotFoundException'); + $tMap = $this->getMockBuilder('Magento\Framework\ObjectManager\TMap') + ->disableOriginalConstructor() + ->getMock(); + $tMap->expects(static::once()) + ->method('offsetExists') + ->with('command') + ->willReturn(false); + + $pool = new CommandPool($tMap); + $pool->get('command'); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Command/GatewayCommandTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Command/GatewayCommandTest.php new file mode 100644 index 0000000000000000000000000000000000000000..849138ac08114dc69b17ba59f76aa98115080a03 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Command/GatewayCommandTest.php @@ -0,0 +1,82 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Command; + +class GatewayCommandTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Payment\Gateway\Command\GatewayCommand */ + protected $model; + + /** + * @var \Magento\Payment\Gateway\Request\BuilderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $requestBuilderMock; + + /** + * @var \Magento\Payment\Gateway\Http\TransferBuilderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $transferBuilderMock; + + /** + * @var \Magento\Payment\Gateway\Http\ClientInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $gatewayMock; + + /** + * @var \Magento\Payment\Gateway\Response\HandlerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $responseHandlerMock; + + protected function setUp() + { + $this->requestBuilderMock = $this->getMockBuilder('Magento\Payment\Gateway\Request\BuilderInterface') + ->getMockForAbstractClass(); + $this->transferBuilderMock = $this->getMockBuilder('Magento\Payment\Gateway\Http\TransferBuilderInterface') + ->getMockForAbstractClass(); + $this->gatewayMock = $this->getMockBuilder('Magento\Payment\Gateway\Http\ClientInterface') + ->getMockForAbstractClass(); + $this->responseHandlerMock = $this->getMockBuilder('Magento\Payment\Gateway\Response\HandlerInterface') + ->getMockForAbstractClass(); + + $this->model = new \Magento\Payment\Gateway\Command\GatewayCommand( + $this->requestBuilderMock, + $this->transferBuilderMock, + $this->gatewayMock, + $this->responseHandlerMock + ); + } + + public function testExecute() + { + $commandSubject = ['authorize']; + $request = ['request_field1' => 'request_value1', 'request_field2' => 'request_value2']; + $response = ['response_field1' => 'response_value1']; + + $transferO = $this->getMockBuilder('Magento\Payment\Gateway\Http\TransferInterface') + ->getMockForAbstractClass(); + + $this->requestBuilderMock->expects($this->once()) + ->method('build') + ->with($commandSubject) + ->willReturn($request); + + $this->transferBuilderMock->expects($this->once()) + ->method('build') + ->with($request) + ->willReturn($transferO); + + $this->gatewayMock->expects($this->once()) + ->method('placeRequest') + ->with($transferO) + ->willReturn($response); + + $this->responseHandlerMock->expects($this->once()) + ->method('handle') + ->with($commandSubject, $response); + + $this->model->execute($commandSubject); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Config/ConfigTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Config/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a3b265b7251448aed9614b0810af6925c47e10c3 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Config/ConfigTest.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Config; + +use Magento\Payment\Gateway\Config\Config; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; + +/** + * Class ConfigTest + */ +class ConfigTest extends \PHPUnit_Framework_TestCase +{ + /** @var Config */ + protected $model; + + /** + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $scopeConfigMock; + + protected function setUp() + { + $this->scopeConfigMock = $this->getMockBuilder('Magento\Framework\App\Config\ScopeConfigInterface') + ->getMockForAbstractClass(); + } + + public function testGetValue() + { + $field = 'field'; + $storeId = 1; + $methodCode = 'code'; + $pathPattern = 'pattern/%s/%s'; + $expected = 'expected value'; + + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->with( + sprintf($pathPattern, $methodCode, $field), + ScopeInterface::SCOPE_STORE, + $storeId + )->willReturn($expected); + + $this->model = new Config($this->scopeConfigMock, $methodCode, $pathPattern); + $this->assertEquals($expected, $this->model->getValue($field, $storeId)); + } + + public function testGetValueWithDefaultPathPattern() + { + $field = 'field'; + $storeId = 1; + $methodCode = 'code'; + $expected = 'expected value'; + + $this->scopeConfigMock->expects($this->once()) + ->method('getValue') + ->with( + sprintf(Config::DEFAULT_PATH_PATTERN, $methodCode, $field), + ScopeInterface::SCOPE_STORE, + $storeId + )->willReturn($expected); + + $this->model = new Config($this->scopeConfigMock, $methodCode); + $this->assertEquals($expected, $this->model->getValue($field, $storeId)); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Config/ConfigValueHandlerTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Config/ConfigValueHandlerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..eebebfdadf275d0ae66013340594630543dce94e --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Config/ConfigValueHandlerTest.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Config; + +use Magento\Payment\Gateway\ConfigInterface; +use Magento\Payment\Gateway\Config\ConfigValueHandler; + +/** + * Class ConfigValueHandlerTest + */ +class ConfigValueHandlerTest extends \PHPUnit_Framework_TestCase +{ + /** @var ConfigValueHandler */ + protected $model; + + /** + * @var ConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $configMock; + + protected function setUp() + { + $this->configMock = $this->getMockBuilder('Magento\Payment\Gateway\ConfigInterface')->getMockForAbstractClass(); + $this->model = new ConfigValueHandler($this->configMock); + } + + public function testHandle() + { + $field = 'field'; + $storeId = 1; + $expected = 'some value'; + + $this->configMock->expects($this->once()) + ->method('getValue') + ->with($field, $storeId) + ->willReturn($expected); + + $this->assertEquals($expected, $this->model->handle($field, $storeId)); + } + + public function testHandleWithoutStoreId() + { + $field = 'field'; + $expected = 'some value'; + + $this->configMock->expects($this->once()) + ->method('getValue') + ->with($field, null) + ->willReturn($expected); + + $this->assertEquals($expected, $this->model->handle($field)); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Config/ValueHandlerPoolTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Config/ValueHandlerPoolTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a10523f6496ce70ff9247ac11b89e7edf23d8101 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Config/ValueHandlerPoolTest.php @@ -0,0 +1,58 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Config; + +use Magento\Payment\Gateway\Config\ValueHandlerPool; + +class ValueHandlerPoolTest extends \PHPUnit_Framework_TestCase +{ + public function testConstructorException() + { + $this->setExpectedException('LogicException'); + $tMap = $this->getMockBuilder('Magento\Framework\ObjectManager\TMap') + ->disableOriginalConstructor() + ->getMock(); + $tMap->expects(static::once()) + ->method('offsetExists') + ->with(ValueHandlerPool::DEFAULT_HANDLER) + ->willReturn(false); + new ValueHandlerPool($tMap); + } + + public function testGet() + { + $defaultHandler = $this->getMockBuilder('Magento\Payment\Gateway\Config\ValueHandlerInterface') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $someValueHandler = $this->getMockBuilder('Magento\Payment\Gateway\Config\ValueHandlerInterface') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $tMap = $this->getMockBuilder('Magento\Framework\ObjectManager\TMap') + ->disableOriginalConstructor() + ->getMock(); + $tMap->expects(static::exactly(4)) + ->method('offsetExists') + ->willReturnMap( + [ + [ValueHandlerPool::DEFAULT_HANDLER, true], + ['some_value', true] + ] + ); + $tMap->expects(static::exactly(3)) + ->method('offsetGet') + ->willReturnMap( + [ + [ValueHandlerPool::DEFAULT_HANDLER, $defaultHandler], + ['some_value', $someValueHandler] + ] + ); + + $pool = new ValueHandlerPool($tMap); + static::assertSame($someValueHandler, $pool->get('some_value')); + static::assertSame($defaultHandler, $pool->get(ValueHandlerPool::DEFAULT_HANDLER)); + static::assertSame($defaultHandler, $pool->get('no_custom_logic_required')); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Data/Order/AddressAdapterTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Data/Order/AddressAdapterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a31a859d54194ff9093018fef6c0d34d10fb199d --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Data/Order/AddressAdapterTest.php @@ -0,0 +1,140 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Data\Order; + +use Magento\Payment\Gateway\Data\Order\AddressAdapter; +use Magento\Sales\Api\Data\OrderAddressInterface; + +/** + * Class AddressAdapterTest + */ +class AddressAdapterTest extends \PHPUnit_Framework_TestCase +{ + /** @var AddressAdapter */ + protected $model; + + /** + * @var OrderAddressInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderAddressMock; + + protected function setUp() + { + $this->orderAddressMock = $this->getMockBuilder('Magento\Sales\Api\Data\OrderAddressInterface') + ->getMockForAbstractClass(); + + $this->model = new AddressAdapter($this->orderAddressMock); + } + + public function testGetRegion() + { + $expected = 'California'; + $this->orderAddressMock->expects($this->once())->method('getRegion')->willReturn($expected); + $this->assertEquals($expected, $this->model->getRegion()); + } + + public function testGetCountryId() + { + $expected = '10'; + $this->orderAddressMock->expects($this->once())->method('getCountryId')->willReturn($expected); + $this->assertEquals($expected, $this->model->getCountryId()); + } + + /** + * @param $street array|null + * @param $expected string + * @dataProvider testStreetLine1DataProvider + */ + public function testStreetLine1($street, $expected) + { + $this->orderAddressMock->expects($this->once())->method('getStreet')->willReturn($street); + $this->assertEquals($expected, $this->model->getStreetLine1()); + } + + public function testStreetLine1DataProvider() + { + return [ + [['Street Line 1'], 'Street Line 1'], //$street, $expected + [null, ''] + ]; + } + + /** + * @param $street array|null + * @param $expected string + * @dataProvider testStreetLine2DataProvider + */ + public function testStreetLine2($street, $expected) + { + $this->orderAddressMock->expects($this->once())->method('getStreet')->willReturn($street); + $this->assertEquals($expected, $this->model->getStreetLine2()); + } + + public function testStreetLine2DataProvider() + { + return [ + [['Street Line 1', 'Street Line 2',], 'Street Line 2'], //$street, $expected + [['Street Line 1'], ''], + [null, ''] + ]; + } + + public function testGetTelephone() + { + $expected = '555-234-456'; + $this->orderAddressMock->expects($this->once())->method('getTelephone')->willReturn($expected); + $this->assertEquals($expected, $this->model->getTelephone()); + } + + public function testGetPostcode() + { + $expected = '90232'; + $this->orderAddressMock->expects($this->once())->method('getPostcode')->willReturn($expected); + $this->assertEquals($expected, $this->model->getPostcode()); + } + + public function testGetCity() + { + $expected = 'New York'; + $this->orderAddressMock->expects($this->once())->method('getCity')->willReturn($expected); + $this->assertEquals($expected, $this->model->getCity()); + } + + public function testGetFirstname() + { + $expected = 'John'; + $this->orderAddressMock->expects($this->once())->method('getFirstname')->willReturn($expected); + $this->assertEquals($expected, $this->model->getFirstname()); + } + + public function testGetLastname() + { + $expected = 'Doe'; + $this->orderAddressMock->expects($this->once())->method('getLastname')->willReturn($expected); + $this->assertEquals($expected, $this->model->getLastname()); + } + + public function testGetMiddlename() + { + $expected = 'Middlename'; + $this->orderAddressMock->expects($this->once())->method('getMiddlename')->willReturn($expected); + $this->assertEquals($expected, $this->model->getMiddlename()); + } + + public function testGetCustomerId() + { + $expected = 1; + $this->orderAddressMock->expects($this->once())->method('getCustomerId')->willReturn($expected); + $this->assertEquals($expected, $this->model->getCustomerId()); + } + + public function testGetEmail() + { + $expected = 'test@gmail.com'; + $this->orderAddressMock->expects($this->once())->method('getEmail')->willReturn($expected); + $this->assertEquals($expected, $this->model->getEmail()); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Data/Order/OrderAdapterTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Data/Order/OrderAdapterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e83d50be32403aaf75031c0f8535ebd991371051 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Data/Order/OrderAdapterTest.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Data\Order; + +use Magento\Payment\Gateway\Data\Order\OrderAdapter; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Payment\Gateway\Data\AddressAdapterInterface; + +/** + * Class OrderAdapterTest + */ +class OrderAdapterTest extends \PHPUnit_Framework_TestCase +{ + /** @var OrderAdapter */ + protected $model; + + /** + * @var OrderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderMock; + + /** + * @var \Magento\Payment\Gateway\Data\Order\AddressAdapterFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $addressAdapterFactoryMock; + + protected function setUp() + { + $this->orderMock = $this->getMockBuilder('Magento\Sales\Api\Data\OrderInterface') + ->getMockForAbstractClass(); + + $this->addressAdapterFactoryMock = + $this->getMockBuilder('Magento\Payment\Gateway\Data\Order\AddressAdapterFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new OrderAdapter($this->orderMock, $this->addressAdapterFactoryMock); + } + + public function testGetCurrencyCode() + { + $expected = 'USD'; + $this->orderMock->expects($this->once())->method('getBaseCurrencyCode')->willReturn($expected); + $this->assertEquals($expected, $this->model->getCurrencyCode()); + } + + public function testGetOrderIncrementId() + { + $expected = '1'; + $this->orderMock->expects($this->once())->method('getIncrementId')->willReturn($expected); + $this->assertEquals($expected, $this->model->getOrderIncrementId()); + } + + public function testGetCustomerId() + { + $expected = 1; + $this->orderMock->expects($this->once())->method('getCustomerId')->willReturn($expected); + $this->assertEquals($expected, $this->model->getCustomerId()); + } + + public function testGetBillingAddress() + { + /** @var AddressAdapterInterface $addressAdapterMock */ + $addressAdapterMock = $this->getMockBuilder('Magento\Payment\Gateway\Data\AddressAdapterInterface') + ->getMockForAbstractClass(); + /** @var \Magento\Sales\Api\Data\OrderAddressInterface $orderAddressMock */ + $orderAddressMock = $this->getMockBuilder('Magento\Sales\Api\Data\OrderAddressInterface') + ->getMockForAbstractClass(); + $this->addressAdapterFactoryMock->expects($this->once()) + ->method('create') + ->with(['address' => $orderAddressMock]) + ->willReturn($addressAdapterMock); + $this->orderMock->expects($this->once())->method('getBillingAddress')->willReturn($orderAddressMock); + + $this->assertSame($addressAdapterMock, $this->model->getBillingAddress()); + } + + public function testGetShippingAddress() + { + /** @var AddressAdapterInterface $addressAdapterMock */ + $addressAdapterMock = $this->getMockBuilder('Magento\Payment\Gateway\Data\AddressAdapterInterface') + ->getMockForAbstractClass(); + /** @var \Magento\Sales\Api\Data\OrderAddressInterface $orderAddressMock */ + $orderAddressMock = $this->getMockBuilder('Magento\Sales\Api\Data\OrderAddressInterface') + ->getMockForAbstractClass(); + $this->addressAdapterFactoryMock->expects($this->once()) + ->method('create') + ->with(['address' => $orderAddressMock]) + ->willReturn($addressAdapterMock); + $this->orderMock->expects($this->once())->method('getShippingAddress')->willReturn($orderAddressMock); + + $this->assertSame($addressAdapterMock, $this->model->getShippingAddress()); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectFactoryTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectFactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6639d50caed10db14e98b87dddc6e98c40ffb67a --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectFactoryTest.php @@ -0,0 +1,148 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Data; + +use Magento\Payment\Gateway\Data\PaymentDataObjectFactory; +use Magento\Framework\ObjectManagerInterface; +use Magento\Sales\Model\Order\Payment; +use Magento\Payment\Gateway\Data\Order\OrderAdapter; +use Magento\Sales\Model\Order; + +/** + * Class PaymentDataObjectFactoryTest + */ +class PaymentDataObjectFactoryTest extends \PHPUnit_Framework_TestCase +{ + /** @var PaymentDataObjectFactory */ + protected $model; + + /** + * @var ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $objectManagerMock; + + /** + * @var \Magento\Payment\Gateway\Data\Order\OrderAdapterFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderAdapterFactoryMock; + + /** + * @var \Magento\Payment\Gateway\Data\Quote\QuoteAdapterFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $quoteAdapterFactoryMock; + + /** + * @var \Magento\Payment\Gateway\Data\PaymentDataObject|\PHPUnit_Framework_MockObject_MockObject + */ + protected $paymentDataObjectMock; + + protected function setUp() + { + $this->objectManagerMock = $this->getMockBuilder('Magento\Framework\ObjectManagerInterface') + ->getMockForAbstractClass(); + + $this->orderAdapterFactoryMock = + $this->getMockBuilder('Magento\Payment\Gateway\Data\Order\OrderAdapterFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->quoteAdapterFactoryMock = + $this->getMockBuilder('Magento\Payment\Gateway\Data\Quote\QuoteAdapterFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->paymentDataObjectMock = + $this->getMockBuilder('Magento\Payment\Gateway\Data\PaymentDataObject') + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new PaymentDataObjectFactory( + $this->objectManagerMock, + $this->orderAdapterFactoryMock, + $this->quoteAdapterFactoryMock + ); + } + + public function testCreatePaymentDataObjectFromOrder() + { + /** @var Order $orderMock */ + $orderMock = $this->getMockBuilder('Magento\Sales\Model\Order') + ->disableOriginalConstructor() + ->getMock(); + + /** @var OrderAdapter $orderAdapterMock */ + $orderAdapterMock = $this->getMockBuilder('Magento\Payment\Gateway\Data\Order\OrderAdapter') + ->disableOriginalConstructor() + ->getMock(); + + /** @var \Magento\Sales\Model\Order\Payment $paymentInfoMock */ + $paymentInfoMock = $this->getMockBuilder('Magento\Sales\Model\Order\Payment') + ->disableOriginalConstructor() + ->getMock(); + + $paymentInfoMock->expects($this->once()) + ->method('getOrder') + ->willReturn($orderMock); + + $this->orderAdapterFactoryMock->expects($this->once()) + ->method('create') + ->with(['order' => $orderMock]) + ->willReturn($orderAdapterMock); + + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->with( + 'Magento\Payment\Gateway\Data\PaymentDataObject', + [ + 'order' => $orderAdapterMock, + 'payment' => $paymentInfoMock + ] + )->willReturn($this->paymentDataObjectMock); + + $this->assertSame($this->paymentDataObjectMock, $this->model->create($paymentInfoMock)); + } + + public function testCreatePaymentDataObjectFromQuote() + { + /** @var \Magento\Quote\Model\Quote $quoteMock */ + $quoteMock = $this->getMockBuilder('Magento\Quote\Model\Quote') + ->disableOriginalConstructor() + ->getMock(); + + /** @var OrderAdapter $orderAdapterMock */ + $quoteAdapterMock = $this->getMockBuilder('Magento\Payment\Gateway\Data\Quote\QuoteAdapter') + ->disableOriginalConstructor() + ->getMock(); + + /** @var \Magento\Quote\Model\Quote\Payment $paymentInfoMock */ + $paymentInfoMock = $this->getMockBuilder('Magento\Quote\Model\Quote\Payment') + ->disableOriginalConstructor() + ->getMock(); + + $paymentInfoMock->expects($this->once()) + ->method('getQuote') + ->willReturn($quoteMock); + + $this->quoteAdapterFactoryMock->expects($this->once()) + ->method('create') + ->with(['quote' => $quoteMock]) + ->willReturn($quoteAdapterMock); + + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->with( + 'Magento\Payment\Gateway\Data\PaymentDataObject', + [ + 'order' => $quoteAdapterMock, + 'payment' => $paymentInfoMock + ] + )->willReturn($this->paymentDataObjectMock); + + $this->assertSame($this->paymentDataObjectMock, $this->model->create($paymentInfoMock)); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php new file mode 100644 index 0000000000000000000000000000000000000000..514aa9b161301859c6460d9bd95ae7e0cc71f50f --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Data/PaymentDataObjectTest.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Data; + +use Magento\Payment\Gateway\Data\PaymentDataObject; +use Magento\Payment\Gateway\Data\OrderAdapterInterface; +use Magento\Payment\Model\InfoInterface; + +/** + * Class PaymentDataObjectTest + */ +class PaymentDataObjectTest extends \PHPUnit_Framework_TestCase +{ + /** @var PaymentDataObject */ + protected $model; + + /** + * @var OrderAdapterInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderMock; + + /** + * @var InfoInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $paymentMock; + + protected function setUp() + { + $this->orderMock = $this->getMockBuilder('Magento\Payment\Gateway\Data\OrderAdapterInterface') + ->getMockForAbstractClass(); + + $this->paymentMock = $this->getMockBuilder('Magento\Payment\Model\InfoInterface') + ->getMockForAbstractClass(); + + $this->model = new PaymentDataObject($this->orderMock, $this->paymentMock); + } + + public function testGetOrder() + { + $this->assertSame($this->orderMock, $this->model->getOrder()) ; + } + + public function testGetPayment() + { + $this->assertSame($this->paymentMock, $this->model->getPayment()) ; + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Data/Quote/AddressAdapterTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Data/Quote/AddressAdapterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5674f0eba1c82adf6c6e812ee4079d2953625e58 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Data/Quote/AddressAdapterTest.php @@ -0,0 +1,140 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Data\Quote; + +use Magento\Payment\Gateway\Data\Quote\AddressAdapter; +use Magento\Quote\Api\Data\AddressInterface; + +/** + * Class AddressAdapterTest + */ +class AddressAdapterTest extends \PHPUnit_Framework_TestCase +{ + /** @var AddressAdapter */ + protected $model; + + /** + * @var AddressInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $quoteAddressMock; + + protected function setUp() + { + $this->quoteAddressMock = $this->getMockBuilder('Magento\Quote\Api\Data\AddressInterface') + ->getMockForAbstractClass(); + + $this->model = new AddressAdapter($this->quoteAddressMock); + } + + public function testGetRegion() + { + $expected = 'California'; + $this->quoteAddressMock->expects($this->once())->method('getRegion')->willReturn($expected); + $this->assertEquals($expected, $this->model->getRegion()); + } + + public function testGetCountryId() + { + $expected = '10'; + $this->quoteAddressMock->expects($this->once())->method('getCountryId')->willReturn($expected); + $this->assertEquals($expected, $this->model->getCountryId()); + } + + /** + * @param $street array|null + * @param $expected string + * @dataProvider testStreetLine1DataProvider + */ + public function testStreetLine1($street, $expected) + { + $this->quoteAddressMock->expects($this->once())->method('getStreet')->willReturn($street); + $this->assertEquals($expected, $this->model->getStreetLine1()); + } + + public function testStreetLine1DataProvider() + { + return [ + [['Street Line 1'], 'Street Line 1'], //$street, $expected + [null, ''] + ]; + } + + /** + * @param $street array|null + * @param $expected string + * @dataProvider testStreetLine2DataProvider + */ + public function testStreetLine2($street, $expected) + { + $this->quoteAddressMock->expects($this->once())->method('getStreet')->willReturn($street); + $this->assertEquals($expected, $this->model->getStreetLine2()); + } + + public function testStreetLine2DataProvider() + { + return [ + [['Street Line 1', 'Street Line 2',], 'Street Line 2'], //$street, $expected + [['Street Line 1'], ''], + [null, ''] + ]; + } + + public function testGetTelephone() + { + $expected = '555-234-456'; + $this->quoteAddressMock->expects($this->once())->method('getTelephone')->willReturn($expected); + $this->assertEquals($expected, $this->model->getTelephone()); + } + + public function testGetPostcode() + { + $expected = '90232'; + $this->quoteAddressMock->expects($this->once())->method('getPostcode')->willReturn($expected); + $this->assertEquals($expected, $this->model->getPostcode()); + } + + public function testGetCity() + { + $expected = 'New York'; + $this->quoteAddressMock->expects($this->once())->method('getCity')->willReturn($expected); + $this->assertEquals($expected, $this->model->getCity()); + } + + public function testGetFirstname() + { + $expected = 'John'; + $this->quoteAddressMock->expects($this->once())->method('getFirstname')->willReturn($expected); + $this->assertEquals($expected, $this->model->getFirstname()); + } + + public function testGetLastname() + { + $expected = 'Doe'; + $this->quoteAddressMock->expects($this->once())->method('getLastname')->willReturn($expected); + $this->assertEquals($expected, $this->model->getLastname()); + } + + public function testGetMiddlename() + { + $expected = 'Middlename'; + $this->quoteAddressMock->expects($this->once())->method('getMiddlename')->willReturn($expected); + $this->assertEquals($expected, $this->model->getMiddlename()); + } + + public function testGetCustomerId() + { + $expected = 1; + $this->quoteAddressMock->expects($this->once())->method('getCustomerId')->willReturn($expected); + $this->assertEquals($expected, $this->model->getCustomerId()); + } + + public function testGetEmail() + { + $expected = 'test@gmail.com'; + $this->quoteAddressMock->expects($this->once())->method('getEmail')->willReturn($expected); + $this->assertEquals($expected, $this->model->getEmail()); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Data/Quote/QuoteAdapterTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Data/Quote/QuoteAdapterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9b7e57bd8267892d55ae3d83f0c719e1d7cd5a97 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Data/Quote/QuoteAdapterTest.php @@ -0,0 +1,104 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Data\Quote; + +use Magento\Payment\Gateway\Data\Quote\QuoteAdapter; +use Magento\Quote\Api\Data\CartInterface; +use Magento\Payment\Gateway\Data\AddressAdapterInterface; + +/** + * Class QuoteAdapterTest + */ +class QuoteAdapterTest extends \PHPUnit_Framework_TestCase +{ + /** @var QuoteAdapter */ + protected $model; + + /** + * @var CartInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $quoteMock; + + /** + * @var \Magento\Payment\Gateway\Data\Quote\AddressAdapterFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $addressAdapterFactoryMock; + + protected function setUp() + { + $this->quoteMock = $this->getMockBuilder('Magento\Quote\Api\Data\CartInterface') + ->getMockForAbstractClass(); + + $this->addressAdapterFactoryMock = + $this->getMockBuilder('Magento\Payment\Gateway\Data\Quote\AddressAdapterFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new QuoteAdapter($this->quoteMock, $this->addressAdapterFactoryMock); + } + + public function testGetCurrencyCode() + { + $expected = 'USD'; + /** @var \Magento\Quote\Api\Data\CurrencyInterface $currencyrMock */ + $currencyMock = $this->getMockBuilder('Magento\Quote\Api\Data\CurrencyInterface')->getMockForAbstractClass(); + $currencyMock->expects($this->once())->method('getBaseCurrencyCode')->willReturn($expected); + $this->quoteMock->expects($this->once())->method('getCurrency')->willReturn($currencyMock); + $this->assertEquals($expected, $this->model->getCurrencyCode()); + } + + public function testGetOrderIncrementId() + { + $expected = '1'; + $this->quoteMock->expects($this->once())->method('getReservedOrderId')->willReturn($expected); + $this->assertEquals($expected, $this->model->getOrderIncrementId()); + } + + public function testGetCustomerId() + { + $expected = 1; + /** @var \Magento\Customer\Api\Data\CustomerInterface $customerMock */ + $customerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface')->getMockForAbstractClass(); + $customerMock->expects($this->once())->method('getId')->willReturn($expected); + $this->quoteMock->expects($this->once())->method('getCustomer')->willReturn($customerMock); + $this->assertEquals($expected, $this->model->getCustomerId()); + } + + public function testGetBillingAddress() + { + /** @var AddressAdapterInterface $addressAdapterMock */ + $addressAdapterMock = $this->getMockBuilder('Magento\Payment\Gateway\Data\AddressAdapterInterface') + ->getMockForAbstractClass(); + /** @var \Magento\Quote\Api\Data\AddressInterface $quoteAddressMock */ + $quoteAddressMock = $this->getMockBuilder('Magento\Quote\Api\Data\AddressInterface') + ->getMockForAbstractClass(); + $this->addressAdapterFactoryMock->expects($this->once()) + ->method('create') + ->with(['address' => $quoteAddressMock]) + ->willReturn($addressAdapterMock); + $this->quoteMock->expects($this->once())->method('getBillingAddress')->willReturn($quoteAddressMock); + + $this->assertSame($addressAdapterMock, $this->model->getBillingAddress()); + } + + public function testGetShippingAddress() + { + /** @var AddressAdapterInterface $addressAdapterMock */ + $addressAdapterMock = $this->getMockBuilder('Magento\Payment\Gateway\Data\AddressAdapterInterface') + ->getMockForAbstractClass(); + /** @var \Magento\Quote\Api\Data\AddressInterface $quoteAddressMock */ + $quoteAddressMock = $this->getMockBuilder('Magento\Quote\Api\Data\AddressInterface') + ->getMockForAbstractClass(); + $this->addressAdapterFactoryMock->expects($this->once()) + ->method('create') + ->with(['address' => $quoteAddressMock]) + ->willReturn($addressAdapterMock); + $this->quoteMock->expects($this->once())->method('getShippingAddress')->willReturn($quoteAddressMock); + + $this->assertSame($addressAdapterMock, $this->model->getShippingAddress()); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Http/Client/ZendTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Http/Client/ZendTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ec6e6a3e04af5b6d5ceae94cc7bd46edad4d25b0 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Http/Client/ZendTest.php @@ -0,0 +1,150 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Http\Client; + +use Magento\Payment\Gateway\Http\Client\Zend; +use Magento\Payment\Gateway\Http\ConverterInterface; +use Magento\Framework\HTTP\ZendClientFactory; +use Magento\Framework\HTTP\ZendClient; +use Magento\Payment\Gateway\Http\TransferInterface; + +/** + * Class ZendTest + */ +class ZendTest extends \PHPUnit_Framework_TestCase +{ + /** @var Zend */ + protected $model; + + /** + * @var ConverterInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $converterMock; + + /** + * @var ZendClientFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $zendClientFactoryMock; + + /** + * @var ZendClient|\PHPUnit_Framework_MockObject_MockObject + */ + protected $clientMock; + + /** + * @var TransferInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $transferObjectMock; + + protected function setUp() + { + $this->converterMock = $this->getMockBuilder('Magento\Payment\Gateway\Http\ConverterInterface') + ->getMockForAbstractClass(); + + $this->zendClientFactoryMock = $this->getMockBuilder('Magento\Framework\HTTP\ZendClientFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + + $this->clientMock = $this->getMockBuilder('Magento\Framework\HTTP\ZendClient') + ->disableOriginalConstructor() + ->getMock(); + + $this->transferObjectMock = $this->getMockBuilder('Magento\Payment\Gateway\Http\TransferInterface') + ->getMockForAbstractClass(); + + $this->model = new Zend($this->zendClientFactoryMock, $this->converterMock); + } + + public function testPlaceRequest() + { + $this->setClientTransferObjects(); + $responseBody = 'Response body content'; + + $zendHttpResponseMock = $this->getMockBuilder('Zend_Http_Response')->disableOriginalConstructor()->getMock(); + $zendHttpResponseMock->expects($this->once())->method('getBody')->willReturn($responseBody); + + $this->clientMock->expects($this->once())->method('request')->willReturn($zendHttpResponseMock); + $this->converterMock->expects($this->once())->method('convert')->with($responseBody); + $this->zendClientFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->clientMock); + + $this->model->placeRequest($this->transferObjectMock); + } + + /** + * Tests failing client gateway request + * + * @expectedException \Magento\Payment\Gateway\Http\ClientException + */ + public function testPlaceRequestClientFail() + { + $this->setClientTransferObjects(); + + $this->clientMock->expects($this->once()) + ->method('request') + ->willThrowException(new \Zend_Http_Client_Exception); + + $this->converterMock->expects($this->never())->method('convert'); + + $this->zendClientFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->clientMock); + + $this->model->placeRequest($this->transferObjectMock); + } + + /** + * Tests failing response converting + * + * @expectedException \Magento\Payment\Gateway\Http\ConverterException + */ + public function testPlaceRequestConvertResponseFail() + { + $this->setClientTransferObjects(); + $responseBody = 'Response body content'; + + $zendHttpResponseMock = $this->getMockBuilder('Zend_Http_Response')->disableOriginalConstructor()->getMock(); + $zendHttpResponseMock->expects($this->once())->method('getBody')->willReturn($responseBody); + + $this->clientMock->expects($this->once())->method('request')->willReturn($zendHttpResponseMock); + $this->converterMock->expects($this->once()) + ->method('convert') + ->with($responseBody) + ->willThrowException(new \Magento\Payment\Gateway\Http\ConverterException(__())); + + $this->zendClientFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->clientMock); + + $this->model->placeRequest($this->transferObjectMock); + } + + private function setClientTransferObjects() + { + $config = ['key1' => 'value1', 'key2' => 'value2']; + $method = \Zend_Http_Client::POST; + $headers = ['key1' => 'value1', 'key2' => 'value2']; + $body = 'Body content'; + $uri = 'https://example.com/listener'; + $shouldEncode = true; + + $this->transferObjectMock->expects($this->once())->method('getClientConfig')->willReturn($config); + $this->transferObjectMock->expects($this->atLeastOnce())->method('getMethod')->willReturn($method); + $this->transferObjectMock->expects($this->once())->method('getHeaders')->willReturn($headers); + $this->transferObjectMock->expects($this->once())->method('getBody')->willReturn($body); + $this->transferObjectMock->expects($this->once())->method('shouldEncode')->willReturn($shouldEncode); + $this->transferObjectMock->expects($this->once())->method('getUri')->willReturn($uri); + + $this->clientMock->expects($this->once())->method('setConfig')->with($config)->willReturnSelf(); + $this->clientMock->expects($this->once())->method('setMethod')->with($method)->willReturnSelf(); + $this->clientMock->expects($this->once())->method('setParameterPost')->with($body)->willReturnSelf(); + $this->clientMock->expects($this->once())->method('setHeaders')->with($headers)->willReturnSelf(); + $this->clientMock->expects($this->once())->method('setUrlEncodeBody')->with($shouldEncode)->willReturnSelf(); + $this->clientMock->expects($this->once())->method('setUri')->with($uri)->willReturnSelf(); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Request/BuilderCompositeTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Request/BuilderCompositeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..39d9339d2d93402eee7865cd31b946dfd1097ac3 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Request/BuilderCompositeTest.php @@ -0,0 +1,80 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Request; + +use Magento\Payment\Gateway\Request\BuilderComposite; + +class BuilderCompositeTest extends \PHPUnit_Framework_TestCase +{ + public function testBuildEmpty() + { + $tMap = $this->getMockBuilder('Magento\Framework\ObjectManager\TMap') + ->disableOriginalConstructor() + ->getMock(); + $tMap->expects(static::once()) + ->method('getIterator') + ->willReturn(new \ArrayIterator([])); + $builder = new BuilderComposite($tMap); + static::assertEquals([], $builder->build([])); + } + + public function testBuild() + { + $expectedRequest = [ + 'user' => 'Mrs G. Crump', + 'url' => 'https://url.in', + 'amount' => 10.00, + 'currecy' => 'pound', + 'address' => '46 Egernon Crescent', + 'item' => 'gas cooker', + 'quantity' => 1 + ]; + + $customerBuilder = $this->getMockBuilder('Magento\Payment\Gateway\Request\BuilderInterface') + ->getMockForAbstractClass(); + $productBuilder = $this->getMockBuilder('Magento\Payment\Gateway\Request\BuilderInterface') + ->getMockForAbstractClass(); + $magentoBuilder = $this->getMockBuilder('Magento\Payment\Gateway\Request\BuilderInterface') + ->getMockForAbstractClass(); + + $customerBuilder->expects(static::once()) + ->method('build') + ->willReturn( + [ + 'user' => 'Mrs G. Crump', + 'address' => '46 Egernon Crescent' + ] + ); + $productBuilder->expects(static::once()) + ->method('build') + ->willReturn( + [ + 'amount' => 10.00, + 'currecy' => 'pound', + 'item' => 'gas cooker', + 'quantity' => 1 + ] + ); + $magentoBuilder->expects(static::once()) + ->method('build') + ->willReturn( + [ + 'url' => 'https://url.in' + ] + ); + + $tMap = $this->getMockBuilder('Magento\Framework\ObjectManager\TMap') + ->disableOriginalConstructor() + ->getMock(); + $tMap->expects(static::once()) + ->method('getIterator') + ->willReturn(new \ArrayIterator([$customerBuilder, $productBuilder, $magentoBuilder])); + + $builder = new BuilderComposite($tMap); + + static::assertEquals($expectedRequest, $builder->build([])); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Response/HandlerChainTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Response/HandlerChainTest.php new file mode 100644 index 0000000000000000000000000000000000000000..716fe3246ae1d8fa17f6d051e1babd42ddf2779e --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Response/HandlerChainTest.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Response; + +use Magento\Payment\Gateway\Response\HandlerChain; + +class HandlerChainTest extends \PHPUnit_Framework_TestCase +{ + public function testHandle() + { + $handler1 = $this->getMockBuilder('Magento\Payment\Gateway\Response\HandlerInterface') + ->getMockForAbstractClass(); + $handler2 = $this->getMockBuilder('Magento\Payment\Gateway\Response\HandlerInterface') + ->getMockForAbstractClass(); + + $tMap = $this->getMockBuilder('Magento\Framework\ObjectManager\TMap') + ->disableOriginalConstructor() + ->getMock(); + $tMap->expects(static::once()) + ->method('getIterator') + ->willReturn(new \ArrayIterator([$handler1, $handler2])); + + $handlingSubject = []; + $response = []; + $handler1->expects(static::once()) + ->method('handle') + ->with($handlingSubject, $response); + $handler2->expects(static::once()) + ->method('handle') + ->with($handlingSubject, $response); + + $chain = new HandlerChain($tMap); + $chain->handle($handlingSubject, $response); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Validator/CountryValidatorTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Validator/CountryValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..38ac5d69dd3d01176e8f53c8f45a1057dc5ed17c --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Validator/CountryValidatorTest.php @@ -0,0 +1,105 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Validator; + +class CountryValidatorTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Payment\Gateway\Validator\CountryValidator */ + protected $model; + + /** + * @var \Magento\Payment\Gateway\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $configMock; + + /** + * @var \Magento\Payment\Gateway\Validator\ResultInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultFactoryMock; + + /** + * @var \Magento\Payment\Gateway\Validator\Result|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultMock; + + protected function setUp() + { + $this->configMock = $this->getMockBuilder('Magento\Payment\Gateway\ConfigInterface') + ->getMockForAbstractClass(); + $this->resultFactoryMock = $this->getMockBuilder('Magento\Payment\Gateway\Validator\ResultInterfaceFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $this->resultMock = $this->getMockBuilder('Magento\Payment\Gateway\Validator\Result') + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new \Magento\Payment\Gateway\Validator\CountryValidator( + $this->configMock, + $this->resultFactoryMock + ); + } + + + /** + * @dataProvider validateAllowspecificTrueDataProvider + */ + public function testValidateAllowspecificTrue($storeId, $country, $allowspecific, $specificcountry, $isValid) + { + $validationSubject = ['storeId' => $storeId, 'country' => $country]; + + $this->configMock->expects($this->at(0)) + ->method('getValue') + ->with('allowspecific', $storeId) + ->willReturn($allowspecific); + $this->configMock->expects($this->at(1)) + ->method('getValue') + ->with('specificcountry', $storeId) + ->willReturn($specificcountry); + + $this->resultFactoryMock->expects($this->once()) + ->method('create') + ->with(['isValid' => $isValid]) + ->willReturn($this->resultMock); + + $this->assertSame($this->resultMock, $this->model->validate($validationSubject)); + } + + public function validateAllowspecificTrueDataProvider() + { + return [ + [1, 'US', 1, 'US,UK,CA', true], //$storeId, $country, $allowspecific, $specificcountry, $isValid + [1, 'BJ', 1, 'US,UK,CA', false] + ]; + } + + /** + * @dataProvider validateAllowspecificFalseDataProvider + */ + public function testValidateAllowspecificFalse($storeId, $allowspecific, $isValid) + { + $validationSubject = ['storeId' => $storeId]; + + $this->configMock->expects($this->at(0)) + ->method('getValue') + ->with('allowspecific', $storeId) + ->willReturn($allowspecific); + + $this->resultFactoryMock->expects($this->once()) + ->method('create') + ->with(['isValid' => $isValid]) + ->willReturn($this->resultMock); + + $this->assertSame($this->resultMock, $this->model->validate($validationSubject)); + } + + public function validateAllowspecificFalseDataProvider() + { + return [ + [1, 0, true] //$storeId, $allowspecific, $isValid + ]; + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Validator/ResultTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Validator/ResultTest.php new file mode 100644 index 0000000000000000000000000000000000000000..44395de89e5f771509afcee9a94e3edba65c5b6a --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Validator/ResultTest.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Validator; + +use Magento\Payment\Gateway\Validator\Result; + +/** + * Class ResultTest + */ +class ResultTest extends \PHPUnit_Framework_TestCase +{ + /** @var Result */ + protected $model; + + /** + * @param $isValid mixed + * @param $failsDescription array + * @param $expectedIsValid mixed + * @param $expectedFailsDescription array + * @dataProvider resultDataProvider + */ + public function testResult($isValid, $failsDescription, $expectedIsValid, $expectedFailsDescription) + { + $this->model = new Result($isValid, $failsDescription); + $this->assertEquals($expectedIsValid, $this->model->isValid()); + $this->assertEquals($expectedFailsDescription, $this->model->getFailsDescription()); + } + + public function resultDataProvider() + { + $phraseMock = $this->getMockBuilder('Magento\Framework\Phrase')->disableOriginalConstructor()->getMock(); + return [ + [true, [$phraseMock, $phraseMock], true, [$phraseMock, $phraseMock]], + ['', [], false, []], + ]; + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Validator/ValidatorCompositeTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Validator/ValidatorCompositeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9150e83f0e7363cee65f589cbb8980728f7ac580 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Validator/ValidatorCompositeTest.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Validator; + +use Magento\Payment\Gateway\Validator\ValidatorComposite; + +class ValidatorCompositeTest extends \PHPUnit_Framework_TestCase +{ + public function testValidate() + { + $validationSubject = []; + $validator1 = $this->getMockBuilder('Magento\Payment\Gateway\Validator\ValidatorInterface') + ->getMockForAbstractClass(); + $validator2 = $this->getMockBuilder('Magento\Payment\Gateway\Validator\ValidatorInterface') + ->getMockForAbstractClass(); + + $tMap = $this->getMockBuilder('Magento\Framework\ObjectManager\TMap') + ->disableOriginalConstructor() + ->getMock(); + $tMap->expects(static::once()) + ->method('getIterator') + ->willReturn(new \ArrayIterator([$validator1, $validator2])); + + $resultSuccess = $this->getMockBuilder('Magento\Payment\Gateway\Validator\ResultInterface') + ->getMockForAbstractClass(); + $resultSuccess->expects(static::once()) + ->method('isValid') + ->willReturn(true); + $resultFail = $this->getMockBuilder('Magento\Payment\Gateway\Validator\ResultInterface') + ->getMockForAbstractClass(); + $resultFail->expects(static::once()) + ->method('isValid') + ->willReturn(false); + $resultFail->expects(static::once()) + ->method('getFailsDescription') + ->willReturn(['Fail']); + + $validator1->expects(static::once()) + ->method('validate') + ->with($validationSubject) + ->willReturn($resultSuccess); + $validator2->expects(static::once()) + ->method('validate') + ->with($validationSubject) + ->willReturn($resultFail); + + $compositeResult = $this->getMockBuilder('Magento\Payment\Gateway\Validator\ResultInterface') + ->getMockForAbstractClass(); + $resultFactory = $this->getMockBuilder('Magento\Payment\Gateway\Validator\ResultInterfaceFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $resultFactory->expects(static::once()) + ->method('create') + ->with( + [ + 'isValid' => false, + 'failsDescription' => ['Fail'] + ] + ) + ->willReturn($compositeResult); + + + $validatorComposite = new ValidatorComposite($resultFactory, $tMap); + static::assertSame($compositeResult, $validatorComposite->validate($validationSubject)); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Gateway/Validator/ValidatorPoolTest.php b/app/code/Magento/Payment/Test/Unit/Gateway/Validator/ValidatorPoolTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c48aca93d6e370462cce2ce0824c5d3927baef56 --- /dev/null +++ b/app/code/Magento/Payment/Test/Unit/Gateway/Validator/ValidatorPoolTest.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Payment\Test\Unit\Gateway\Validator; + +use Magento\Payment\Gateway\Validator\ValidatorPool; + +class ValidatorPoolTest extends \PHPUnit_Framework_TestCase +{ + public function testGet() + { + $commandI = $this->getMockBuilder('Magento\Payment\Gateway\Validator\ValidatorInterface') + ->getMockForAbstractClass(); + $tMap = $this->getMockBuilder('Magento\Framework\ObjectManager\TMap') + ->disableOriginalConstructor() + ->getMock(); + $tMap->expects(static::once()) + ->method('offsetExists') + ->with('validator') + ->willReturn(true); + $tMap->expects(static::once()) + ->method('offsetGet') + ->with('validator') + ->willReturn($commandI); + + $pool = new ValidatorPool($tMap); + + static::assertSame($commandI, $pool->get('validator')); + } + + public function testGetException() + { + $this->setExpectedException('Magento\Framework\Exception\NotFoundException'); + $tMap = $this->getMockBuilder('Magento\Framework\ObjectManager\TMap') + ->disableOriginalConstructor() + ->getMock(); + $tMap->expects(static::once()) + ->method('offsetExists') + ->with('validator') + ->willReturn(false); + + $pool = new ValidatorPool($tMap); + $pool->get('validator'); + } +} diff --git a/app/code/Magento/Payment/Test/Unit/Helper/DataTest.php b/app/code/Magento/Payment/Test/Unit/Helper/DataTest.php index 9ccb26792c6ba62b85b8f4c3e3f2b1a3dbeb615a..b8335bf3e91539b2aa2f1a6d399a3d9c027d4f35 100644 --- a/app/code/Magento/Payment/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Payment/Test/Unit/Helper/DataTest.php @@ -132,32 +132,24 @@ class DataTest extends \PHPUnit_Framework_TestCase ->with(sprintf('%s/%s/model', Data::XML_PATH_PAYMENT_METHODS, 'empty')) ->will($this->returnValue(null)); - $methodInstanceMockA = $this->getMock( - 'Magento\Framework\Object', - ['isAvailable', 'getConfigData'], - [], - '', - false - ); + $methodInstanceMockA = $this->getMockBuilder('Magento\Payment\Model\MethodInterface') + ->getMockForAbstractClass(); $methodInstanceMockA->expects($this->any()) ->method('isAvailable') ->will($this->returnValue(true)); $methodInstanceMockA->expects($this->any()) ->method('getConfigData') + ->with('sort_order', null) ->will($this->returnValue($methodA['data']['sort_order'])); - $methodInstanceMockB = $this->getMock( - 'Magento\Framework\Object', - ['isAvailable', 'getConfigData'], - [], - '', - false - ); + $methodInstanceMockB = $this->getMockBuilder('Magento\Payment\Model\MethodInterface') + ->getMockForAbstractClass(); $methodInstanceMockB->expects($this->any()) ->method('isAvailable') ->will($this->returnValue(true)); $methodInstanceMockB->expects($this->any()) ->method('getConfigData') + ->with('sort_order', null) ->will($this->returnValue($methodB['data']['sort_order'])); $this->methodFactory->expects($this->at(0)) @@ -169,7 +161,10 @@ class DataTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($methodInstanceMockB)); $sortedMethods = $this->helper->getStoreMethods(); - $this->assertTrue(array_shift($sortedMethods)->getSortOrder() < array_shift($sortedMethods)->getSortOrder()); + $this->assertTrue( + array_shift($sortedMethods)->getConfigData('sort_order') + < array_shift($sortedMethods)->getConfigData('sort_order') + ); } public function testGetMethodFormBlock() @@ -177,9 +172,7 @@ class DataTest extends \PHPUnit_Framework_TestCase list($blockType, $methodCode) = ['method_block_type', 'method_code']; $methodMock = $this->getMockBuilder('Magento\Payment\Model\MethodInterface') - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); + ->getMockForAbstractClass(); $layoutMock = $this->getMockBuilder('Magento\Framework\View\LayoutInterface') ->disableOriginalConstructor() ->setMethods([]) @@ -204,9 +197,7 @@ class DataTest extends \PHPUnit_Framework_TestCase $blockType = 'method_block_type'; $methodMock = $this->getMockBuilder('Magento\Payment\Model\MethodInterface') - ->disableOriginalConstructor() - ->setMethods(['getCode', 'getFormBlockType', 'getTitle', 'getInfoBlockType']) - ->getMock(); + ->getMockForAbstractClass(); $infoMock = $this->getMockBuilder('Magento\Payment\Model\Info') ->disableOriginalConstructor() ->setMethods([]) @@ -231,9 +222,7 @@ class DataTest extends \PHPUnit_Framework_TestCase list($storeId, $blockHtml, $secureMode, $blockType) = [1, 'HTML MARKUP', true, 'method_block_type']; $methodMock = $this->getMockBuilder('Magento\Payment\Model\MethodInterface') - ->disableOriginalConstructor() - ->setMethods(['getCode', 'getFormBlockType', 'getTitle', 'getInfoBlockType', 'setStore']) - ->getMock(); + ->getMockForAbstractClass(); $infoMock = $this->getMockBuilder('Magento\Payment\Model\Info') ->disableOriginalConstructor() ->setMethods([]) diff --git a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseCheckoutTest.php b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseCheckoutTest.php index 7fce93dec6e0b9bf56e66bd5e3aad739b31f58f7..c2559ec7116f4fd7a2a8fceef7d3ff8874de0613 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseCheckoutTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseCheckoutTest.php @@ -30,7 +30,7 @@ class CanUseCheckoutTest extends \PHPUnit_Framework_TestCase [] )->getMock(); $paymentMethod = $this->getMockBuilder( - 'Magento\Payment\Model\Checks\PaymentMethodChecksInterface' + '\Magento\Payment\Model\MethodInterface' )->disableOriginalConstructor()->setMethods([])->getMock(); $paymentMethod->expects($this->once())->method('canUseCheckout')->will( $this->returnValue($expectation) diff --git a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountryTest.php b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountryTest.php index 695ac5730a08256bab06e7ce6e3a971c0d485af5..c9f1407a98349f0e0ab3efc8f91895d60916ef3a 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountryTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCountryTest.php @@ -43,7 +43,7 @@ class CanUseForCountryTest extends \PHPUnit_Framework_TestCase $quoteMock->expects($this->once())->method('getBillingAddress')->will($this->returnValue($billingAddressMock)); $paymentMethod = $this->getMockBuilder( - 'Magento\Payment\Model\Checks\PaymentMethodChecksInterface' + '\Magento\Payment\Model\MethodInterface' )->disableOriginalConstructor()->setMethods([])->getMock(); $paymentMethod->expects($this->once())->method('canUseForCountry')->with( self::EXPECTED_COUNTRY_ID diff --git a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCurrencyTest.php b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCurrencyTest.php index b2fc9ab682823ac82da424ecf5cafdf8802775d7..5c63783fa71f4f404bde5a3c7d10eb306053a55d 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCurrencyTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseForCurrencyTest.php @@ -32,7 +32,7 @@ class CanUseForCurrencyTest extends \PHPUnit_Framework_TestCase public function testIsApplicable($expectation) { $paymentMethod = $this->getMockBuilder( - 'Magento\Payment\Model\Checks\PaymentMethodChecksInterface' + '\Magento\Payment\Model\MethodInterface' )->disableOriginalConstructor()->setMethods([])->getMock(); $paymentMethod->expects($this->once())->method('canUseForCurrency')->with( self::EXPECTED_CURRENCY_CODE diff --git a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseInternalTest.php b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseInternalTest.php index d4c7aed842020ce04c2e020f46c687e819454d8a..57a8dc14221ee8b842b18499ca42c1634423e1d7 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseInternalTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Checks/CanUseInternalTest.php @@ -30,7 +30,7 @@ class CanUseInternalTest extends \PHPUnit_Framework_TestCase [] )->getMock(); $paymentMethod = $this->getMockBuilder( - 'Magento\Payment\Model\Checks\PaymentMethodChecksInterface' + '\Magento\Payment\Model\MethodInterface' )->disableOriginalConstructor()->setMethods([])->getMock(); $paymentMethod->expects($this->once())->method('canUseInternal')->will( $this->returnValue($expectation) diff --git a/app/code/Magento/Payment/Test/Unit/Model/Checks/CompositeTest.php b/app/code/Magento/Payment/Test/Unit/Model/Checks/CompositeTest.php index 1b29080f60005cad9723eb8299adbca1ffad5ccb..66bace1fa1d16812c74db87689d3ebe8d0cfa8de 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Checks/CompositeTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Checks/CompositeTest.php @@ -20,7 +20,7 @@ class CompositeTest extends \PHPUnit_Framework_TestCase [] )->getMock(); $paymentMethod = $this->getMockBuilder( - 'Magento\Payment\Model\Checks\PaymentMethodChecksInterface' + '\Magento\Payment\Model\MethodInterface' )->disableOriginalConstructor()->setMethods([])->getMock(); $specification = $this->getMockBuilder( diff --git a/app/code/Magento/Payment/Test/Unit/Model/Checks/TotalMinMaxTest.php b/app/code/Magento/Payment/Test/Unit/Model/Checks/TotalMinMaxTest.php index 8d2ff95196eaa1d0248eab1e9021ba9f5936a851..76d1d9bc012e211728de7eaefc9aaf9e26203d04 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Checks/TotalMinMaxTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Checks/TotalMinMaxTest.php @@ -28,7 +28,7 @@ class TotalMinMaxTest extends \PHPUnit_Framework_TestCase public function testIsApplicable($baseGrandTotal, $expectation) { $paymentMethod = $this->getMockBuilder( - 'Magento\Payment\Model\Checks\PaymentMethodChecksInterface' + '\Magento\Payment\Model\MethodInterface' )->disableOriginalConstructor()->setMethods([])->getMock(); $paymentMethod->expects($this->at(0))->method('getConfigData')->with( TotalMinMax::MIN_ORDER_TOTAL diff --git a/app/code/Magento/Payment/Test/Unit/Model/Checks/ZeroTotalTest.php b/app/code/Magento/Payment/Test/Unit/Model/Checks/ZeroTotalTest.php index f9c17121b3b9c68fb4fcc8ec6a3cb14afdb963c5..6683062f33cf65388077cf7d1752fa2a938a39fe 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Checks/ZeroTotalTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Checks/ZeroTotalTest.php @@ -18,7 +18,7 @@ class ZeroTotalTest extends \PHPUnit_Framework_TestCase */ public function testIsApplicable($code, $total, $expectation) { - $paymentMethod = $this->getMockBuilder('Magento\Payment\Model\Checks\PaymentMethodChecksInterface') + $paymentMethod = $this->getMockBuilder('\Magento\Payment\Model\MethodInterface') ->disableOriginalConstructor() ->setMethods([]) ->getMock(); diff --git a/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php b/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php index ae82d7436da935940a66d6abb8134fa3a61a42ac..e60cac556829239b65ca402a6dbecd93a2714541 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/InfoTest.php @@ -45,9 +45,7 @@ class InfoTest extends \PHPUnit_Framework_TestCase false ); $this->methodInstanceMock = $this->getMockBuilder('Magento\Payment\Model\MethodInterface') - ->disableOriginalConstructor() - ->setMethods(['setInfoInstance', 'getCode', 'getFormBlockType', 'getTitle']) - ->getMock(); + ->getMockForAbstractClass(); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->info = $this->objectManagerHelper->getObject( diff --git a/app/code/Magento/Payment/Test/Unit/Model/Method/AbstractMethodTest.php b/app/code/Magento/Payment/Test/Unit/Model/Method/AbstractMethodTest.php index c0b23e09f14df4cb1148f4c53fd36d333df46422..60e8f1d6f33ecbe4bff9b655ee7f19a178adaa07 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Method/AbstractMethodTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Method/AbstractMethodTest.php @@ -35,6 +35,11 @@ class AbstractMethodTest extends \PHPUnit_Framework_TestCase */ protected $quoteMock; + /** + * @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $loggerMock; + protected function setUp() { $this->scopeConfigMock = $this->getMockBuilder('Magento\Framework\App\Config\ScopeConfigInterface') @@ -50,22 +55,35 @@ class AbstractMethodTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->setMethods(['getEventDispatcher']) ->getMock(); - $contextMock->expects($this->once()) ->method('getEventDispatcher') ->willReturn($this->eventManagerMock); + $this->loggerMock = $this->getMockBuilder('\Magento\Payment\Model\Method\Logger') + ->setConstructorArgs([$this->getMockForAbstractClass('Psr\Log\LoggerInterface')]) + ->setMethods(['debug']) + ->getMock(); $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->payment = $helper->getObject( 'Magento\Payment\Test\Unit\Model\Method\AbstractMethod\Stub', [ 'scopeConfig' => $this->scopeConfigMock, - 'context' => $contextMock + 'context' => $contextMock, + 'logger' => $this->loggerMock ] ); } + public function testDebugData() + { + $debugData = ['masked' => '123']; + $this->loggerMock->expects($this->once()) + ->method('debug') + ->with($this->equalTo($debugData)); + + $this->payment->debugData($debugData); + } + /** * @param bool $result * diff --git a/app/code/Magento/Payment/Test/Unit/Model/Method/FreeTest.php b/app/code/Magento/Payment/Test/Unit/Model/Method/FreeTest.php index 9976a46c96dee56bd06824421b160a98ef2e91e2..54bab15e4387c28958ac917efedbe0624b2de01e 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Method/FreeTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Method/FreeTest.php @@ -39,6 +39,10 @@ class FreeTest extends \PHPUnit_Framework_TestCase ); $customAttributeFactory = $this->getMock('\Magento\Framework\Api\AttributeValueFactory', [], [], '', false); + $loggerMock = $this->getMockBuilder('\Magento\Payment\Model\Method\Logger') + ->setConstructorArgs([$this->getMockForAbstractClass('Psr\Log\LoggerInterface')]) + ->getMock(); + $this->methodFree = new \Magento\Payment\Model\Method\Free( $context, $registry, @@ -46,6 +50,7 @@ class FreeTest extends \PHPUnit_Framework_TestCase $customAttributeFactory, $paymentData, $this->scopeConfig, + $loggerMock, $this->currencyPrice ); } diff --git a/app/code/Magento/Payment/Test/Unit/Model/Method/LoggerTest.php b/app/code/Magento/Payment/Test/Unit/Model/Method/LoggerTest.php index 75efef237b33a53a318e56ca50920d21f644418f..b56caf5903208f67a51713cef223b8602387a608 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/Method/LoggerTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/Method/LoggerTest.php @@ -6,7 +6,6 @@ namespace Magento\Payment\Test\Unit\Model\Method; -use Magento\Payment\Model\Method\ConfigInterface; use Magento\Payment\Model\Method\Logger; use Psr\Log\LoggerInterface; @@ -18,39 +17,48 @@ class LoggerTest extends \PHPUnit_Framework_TestCase /** @var LoggerInterface | \PHPUnit_Framework_MockObject_MockObject */ private $loggerMock; - /** @var ConfigInterface | \PHPUnit_Framework_MockObject_MockObject */ - private $configMock; - protected function setUp() { $this->loggerMock = $this->getMockForAbstractClass('Psr\Log\LoggerInterface'); - $this->configMock = $this->getMockForAbstractClass('Magento\Payment\Model\Method\ConfigInterface'); - $this->logger = new Logger($this->loggerMock); } public function testDebugOn() { - $this->configMock->expects($this->once()) - ->method('getConfigValue') - ->with('debug') - ->willReturn(true); + $debugData = + [ + 'request' => ['masked' => '123', 'unmasked' => '123'] + ]; + $expectedDebugData = + [ + 'request' => ['masked' => Logger::DEBUG_KEYS_MASK, 'unmasked' => '123'] + ]; + $debugReplaceKeys = + [ + 'masked' + ]; + $this->loggerMock->expects($this->once()) ->method('debug') - ->with("'test_value'"); + ->with(var_export($expectedDebugData, true)); - $this->logger->debug('test_value', $this->configMock); + $this->logger->debug($debugData, $debugReplaceKeys, true); } public function testDebugOff() { - $this->configMock->expects($this->once()) - ->method('getConfigValue') - ->with('debug') - ->willReturn(false); + $debugData = + [ + 'request' => ['masked' => '123', 'unmasked' => '123'] + ]; + $debugReplaceKeys = + [ + 'masked' + ]; + $this->loggerMock->expects($this->never()) ->method('debug'); - $this->logger->debug('', $this->configMock); + $this->logger->debug($debugData, $debugReplaceKeys, false); } } diff --git a/app/code/Magento/Payment/Test/Unit/Model/ObserverTest.php b/app/code/Magento/Payment/Test/Unit/Model/ObserverTest.php index 0a6d16e5dd30fc1815f7e1b8cc7759ae0d103c92..806ba8fbfefb19c8cfb946608f2fcd4010ea100a 100644 --- a/app/code/Magento/Payment/Test/Unit/Model/ObserverTest.php +++ b/app/code/Magento/Payment/Test/Unit/Model/ObserverTest.php @@ -210,7 +210,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase $order->expects($this->once())->method('getPayment')->will($this->returnValue($paymentMock)); $methodInstance = $this->getMockBuilder( 'Magento\Payment\Model\MethodInterface' - )->disableOriginalConstructor()->setMethods([])->getMock(); + )->getMockForAbstractClass(); $paymentMock->expects($this->once())->method('getMethodInstance')->will($this->returnValue($methodInstance)); $methodInstance->expects($this->once())->method('getCode')->will($this->returnValue($methodCode)); return $order; @@ -223,10 +223,9 @@ class ObserverTest extends \PHPUnit_Framework_TestCase */ private function _getPreparedActiveMethods() { - $mockedMethods = ['getCode', 'getFormBlockType', 'getTitle', 'getConfigData']; $method1 = $this->getMockBuilder( 'Magento\Payment\Model\MethodInterface' - )->disableOriginalConstructor()->setMethods($mockedMethods)->getMock(); + )->getMockForAbstractClass(); $method1->expects($this->once())->method('getConfigData')->with('order_status')->will( $this->returnValue(self::ORDER_STATUS) ); @@ -236,7 +235,7 @@ class ObserverTest extends \PHPUnit_Framework_TestCase $method2 = $this->getMockBuilder( 'Magento\Payment\Model\MethodInterface' - )->disableOriginalConstructor()->setMethods($mockedMethods)->getMock(); + )->getMockForAbstractClass(); $method2->expects($this->once())->method('getConfigData')->with('order_status')->will( $this->returnValue('not_a_status') ); diff --git a/app/code/Magento/Payment/composer.json b/app/code/Magento/Payment/composer.json index e935e442304bd7bb05f4cf96092513f6c912104d..87f3a9ef1cd080f2b0da3e1e42532f71dc39d4b4 100644 --- a/app/code/Magento/Payment/composer.json +++ b/app/code/Magento/Payment/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Payment/etc/di.xml b/app/code/Magento/Payment/etc/di.xml index d25b560a5b318c54f38b41c20d9ebed68d904445..07b42bce07cf670108f2868596308c7270e395e2 100644 --- a/app/code/Magento/Payment/etc/di.xml +++ b/app/code/Magento/Payment/etc/di.xml @@ -24,4 +24,5 @@ <argument name="dataStorage" xsi:type="object">Magento\Payment\Model\Config\Data</argument> </arguments> </type> + <preference for="Magento\Payment\Gateway\Validator\ResultInterface" type="Magento\Payment\Gateway\Validator\Result"/> </config> diff --git a/app/code/Magento/Persistent/Model/Session.php b/app/code/Magento/Persistent/Model/Session.php index 78c0fb856a495bce053418ecbc584b5884c752cb..0808055413f46edd7de89e00021e406c44d8439c 100644 --- a/app/code/Magento/Persistent/Model/Session.php +++ b/app/code/Magento/Persistent/Model/Session.php @@ -108,7 +108,7 @@ class Session extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Math\Random $mathRandom * @param \Magento\Framework\Session\Config\ConfigInterface $sessionConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -124,7 +124,7 @@ class Session extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Math\Random $mathRandom, \Magento\Framework\Session\Config\ConfigInterface $sessionConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->jsonHelper = $jsonHelper; diff --git a/app/code/Magento/Persistent/composer.json b/app/code/Magento/Persistent/composer.json index 3a01e0892a2064c2a460d4de2696aaa9978b8d97..379f16a66b2f4879c1c315c5a33c6d93cd69f64b 100644 --- a/app/code/Magento/Persistent/composer.json +++ b/app/code/Magento/Persistent/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-cron": "0.74.0-beta10", - "magento/module-page-cache": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-cron": "0.74.0-beta13", + "magento/module-page-cache": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Persistent/etc/service_data_attributes.xml b/app/code/Magento/Persistent/etc/extension_attributes.xml similarity index 90% rename from app/code/Magento/Persistent/etc/service_data_attributes.xml rename to app/code/Magento/Persistent/etc/extension_attributes.xml index db88666b03bcf7386d357b0c7dcec6cbd357e2da..f5b2f2859e9decbabc36032460559afc00b99d48 100644 --- a/app/code/Magento/Persistent/etc/service_data_attributes.xml +++ b/app/code/Magento/Persistent/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Quote\Api\Data\AddressAdditionalDataInterface"> <attribute code="persistent_remember_me" type="string" /> </extension_attributes> diff --git a/app/code/Magento/ProductAlert/Model/Email.php b/app/code/Magento/ProductAlert/Model/Email.php index 2df2a71c76b0adaa1eb1681f49977e8714651452..b9ea04d16e067f40e9f21774eedeef2051f37b57 100644 --- a/app/code/Magento/ProductAlert/Model/Email.php +++ b/app/code/Magento/ProductAlert/Model/Email.php @@ -118,7 +118,7 @@ class Email extends \Magento\Framework\Model\AbstractModel * @param \Magento\Store\Model\App\Emulation $appEmulation * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -133,7 +133,7 @@ class Email extends \Magento\Framework\Model\AbstractModel \Magento\Store\Model\App\Emulation $appEmulation, \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_productAlertData = $productAlertData; diff --git a/app/code/Magento/ProductAlert/Model/Price.php b/app/code/Magento/ProductAlert/Model/Price.php index b0aa95a400066e0be72c78dac11e062f7cea8adc..c5a029032532ee7aff7ef6d38aa326c3f43e4e3c 100644 --- a/app/code/Magento/ProductAlert/Model/Price.php +++ b/app/code/Magento/ProductAlert/Model/Price.php @@ -43,7 +43,7 @@ class Price extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\ProductAlert\Model\Resource\Price\Customer\CollectionFactory $customerColFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -51,7 +51,7 @@ class Price extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\ProductAlert\Model\Resource\Price\Customer\CollectionFactory $customerColFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_customerColFactory = $customerColFactory; diff --git a/app/code/Magento/ProductAlert/Model/Stock.php b/app/code/Magento/ProductAlert/Model/Stock.php index 9e3b26a497f8acca0e7157c93116ab8466c5be9e..517f14e5b2201d480494de862ec15d63ed379020 100644 --- a/app/code/Magento/ProductAlert/Model/Stock.php +++ b/app/code/Magento/ProductAlert/Model/Stock.php @@ -41,7 +41,7 @@ class Stock extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\ProductAlert\Model\Resource\Stock\Customer\CollectionFactory $customerColFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -49,7 +49,7 @@ class Stock extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\ProductAlert\Model\Resource\Stock\Customer\CollectionFactory $customerColFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_customerColFactory = $customerColFactory; diff --git a/app/code/Magento/ProductAlert/composer.json b/app/code/Magento/ProductAlert/composer.json index 0dc14f2fe107187de43c830ff484028c9c717920..3e993546d08a901e3e7f7feda86c18e19e2cfd7e 100644 --- a/app/code/Magento/ProductAlert/composer.json +++ b/app/code/Magento/ProductAlert/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Quote/Api/Data/PaymentMethodInterface.php b/app/code/Magento/Quote/Api/Data/PaymentMethodInterface.php index 6b6b79efdaba8775eb085400d7083b161a9f07a2..9bd4e7c82a46c113620caf85a26e416b6438fcf1 100644 --- a/app/code/Magento/Quote/Api/Data/PaymentMethodInterface.php +++ b/app/code/Magento/Quote/Api/Data/PaymentMethodInterface.php @@ -9,7 +9,7 @@ namespace Magento\Quote\Api\Data; * Interface PaymentMethodInterface * @api */ -interface PaymentMethodInterface extends \Magento\Framework\Api\ExtensibleDataInterface +interface PaymentMethodInterface { /** * Get payment method code @@ -24,21 +24,4 @@ interface PaymentMethodInterface extends \Magento\Framework\Api\ExtensibleDataIn * @return string */ public function getTitle(); - - /** - * Retrieve existing extension attributes object or create a new one. - * - * @return \Magento\Quote\Api\Data\PaymentMethodExtensionInterface|null - */ - public function getExtensionAttributes(); - - /** - * Set an extension attributes object. - * - * @param \Magento\Quote\Api\Data\PaymentMethodExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes( - \Magento\Quote\Api\Data\PaymentMethodExtensionInterface $extensionAttributes - ); } diff --git a/app/code/Magento/Quote/Model/AddressDetails.php b/app/code/Magento/Quote/Model/AddressDetails.php index 7fe5833a6296c4fff87b88c788094506e307dc7d..ba3e3bf697708ee8c0d9fc6c0b5c161c6adb3ab3 100644 --- a/app/code/Magento/Quote/Model/AddressDetails.php +++ b/app/code/Magento/Quote/Model/AddressDetails.php @@ -11,6 +11,7 @@ namespace Magento\Quote\Model; class AddressDetails extends \Magento\Framework\Model\AbstractExtensibleModel implements \Magento\Quote\Api\Data\AddressDetailsInterface { + //@codeCoverageIgnoreStart /** * @{inheritdoc} */ @@ -75,6 +76,23 @@ class AddressDetails extends \Magento\Framework\Model\AbstractExtensibleModel im return $this->setData(self::FORMATTED_SHIPPING_ADDRESS, $formattedShippingAddress); } + /** + * @{inheritdoc} + */ + public function getTotals() + { + return $this->getData(self::TOTALS); + } + + /** + * @{inheritdoc} + */ + public function setTotals($totals) + { + return $this->setData(self::TOTALS, $totals); + } + //@codeCoverageIgnoreEnd + /** * {@inheritdoc} * @@ -96,20 +114,4 @@ class AddressDetails extends \Magento\Framework\Model\AbstractExtensibleModel im ) { return $this->_setExtensionAttributes($extensionAttributes); } - - /** - * @{inheritdoc} - */ - public function getTotals() - { - return $this->getData(self::TOTALS); - } - - /** - * @{inheritdoc} - */ - public function setTotals($totals) - { - return $this->setData(self::TOTALS, $totals); - } } diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php index 377ba1d34f937857dc446288129b6cb389284e1d..9cc216d09012c88f121e7e80c35db7e165e505b5 100644 --- a/app/code/Magento/Quote/Model/Quote.php +++ b/app/code/Magento/Quote/Model/Quote.php @@ -356,7 +356,7 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter * @param Cart\CurrencyFactory $currencyFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -394,7 +394,7 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter, \Magento\Quote\Model\Cart\CurrencyFactory $currencyFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->quoteValidator = $quoteValidator; @@ -1337,8 +1337,9 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C { $items = []; foreach ($this->getItemsCollection() as $item) { + /** @var \Magento\Quote\Model\Resource\Quote\Item $item */ if (!$item->isDeleted()) { - $items[] = $item; + $items[$item->getId()] = $item; } } return $items; @@ -2099,6 +2100,8 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C /** * Sets flag, whether this quote has some error associated with it. * + * @codeCoverageIgnore + * * @param bool $flag * @return $this */ @@ -2494,6 +2497,8 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C /** * Sets the payment method that is used to process the cart. * + * @codeCoverageIgnore + * * @param string $checkoutMethod * @return $this */ @@ -2505,6 +2510,8 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C /** * Prevent quote from saving * + * @codeCoverageIgnore + * * @return $this */ public function preventSaving() @@ -2516,6 +2523,8 @@ class Quote extends AbstractExtensibleModel implements \Magento\Quote\Api\Data\C /** * Check if model can be saved * + * @codeCoverageIgnore + * * @return bool */ public function isPreventSaving() diff --git a/app/code/Magento/Quote/Model/Quote/Address.php b/app/code/Magento/Quote/Model/Quote/Address.php index d8af21ff7e3e76528df4493d59f9cea8331837d4..2d091f08d1db37e3320f316540eaabce7d3895f9 100644 --- a/app/code/Magento/Quote/Model/Quote/Address.php +++ b/app/code/Magento/Quote/Model/Quote/Address.php @@ -72,14 +72,14 @@ use Magento\Customer\Api\Data\RegionInterfaceFactory; * @method Address setBaseSubtotalTotalInclTax(float $value) * @method int getGiftMessageId() * @method Address setGiftMessageId(int $value) - * @method float getHiddenTaxAmount() - * @method Address setHiddenTaxAmount(float $value) - * @method float getBaseHiddenTaxAmount() - * @method Address setBaseHiddenTaxAmount(float $value) - * @method float getShippingHiddenTaxAmount() - * @method Address setShippingHiddenTaxAmount(float $value) - * @method float getBaseShippingHiddenTaxAmnt() - * @method Address setBaseShippingHiddenTaxAmnt(float $value) + * @method float getDiscountTaxCompensationAmount() + * @method Address setDiscountTaxCompensationAmount(float $value) + * @method float getBaseDiscountTaxCompensationAmount() + * @method Address setBaseDiscountTaxCompensationAmount(float $value) + * @method float getShippingDiscountTaxCompensationAmount() + * @method Address setShippingDiscountTaxCompensationAmount(float $value) + * @method float getBaseShippingDiscountTaxCompensationAmnt() + * @method Address setBaseShippingDiscountTaxCompensationAmnt(float $value) * @method float getShippingInclTax() * @method Address setShippingInclTax(float $value) * @method float getBaseShippingInclTax() @@ -251,7 +251,7 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress implements * @param Address\Validator $validator * @param \Magento\Customer\Model\Address\Mapper $addressMapper * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param Address\CustomAttributeListInterface $attributeList * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -285,7 +285,7 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress implements \Magento\Customer\Model\Address\Mapper $addressMapper, Address\CustomAttributeListInterface $attributeList, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_scopeConfig = $scopeConfig; @@ -1294,43 +1294,44 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress implements } /** - * Get all total amount values + * Get subtotal amount with applied discount in base currency * - * @return array + * @return float */ - public function getAllTotalAmounts() + public function getBaseSubtotalWithDiscount() { - return $this->_totalAmounts; + return $this->getBaseSubtotal() + $this->getBaseDiscountAmount(); } /** - * Get all total amount values in base currency + * Get subtotal amount with applied discount * - * @return array + * @return float */ - public function getAllBaseTotalAmounts() + public function getSubtotalWithDiscount() { - return $this->_baseTotalAmounts; + return $this->getSubtotal() + $this->getDiscountAmount(); } + //@codeCoverageIgnoreStart /** - * Get subtotal amount with applied discount in base currency + * Get all total amount values * - * @return float + * @return array */ - public function getBaseSubtotalWithDiscount() + public function getAllTotalAmounts() { - return $this->getBaseSubtotal() + $this->getBaseDiscountAmount(); + return $this->_totalAmounts; } /** - * Get subtotal amount with applied discount + * Get all total amount values in base currency * - * @return float + * @return array */ - public function getSubtotalWithDiscount() + public function getAllBaseTotalAmounts() { - return $this->getSubtotal() + $this->getDiscountAmount(); + return $this->_baseTotalAmounts; } /** @@ -1343,7 +1344,6 @@ class Address extends \Magento\Customer\Model\Address\AbstractAddress implements /** * {@inheritdoc} - * @codeCoverageIgnoreStart */ public function getCountryId() { diff --git a/app/code/Magento/Quote/Model/Quote/Address/Item.php b/app/code/Magento/Quote/Model/Quote/Address/Item.php index 9f2a99f8328895fab081bdf4351d72dc07ee3eb4..aa5eea6d35e74aaa2205589bfcb9f4ffb51939b3 100644 --- a/app/code/Magento/Quote/Model/Quote/Address/Item.php +++ b/app/code/Magento/Quote/Model/Quote/Address/Item.php @@ -79,10 +79,10 @@ use Magento\Quote\Model\Quote; * @method \Magento\Quote\Model\Quote\Address\Item setBaseRowTotalInclTax(float $value) * @method int getGiftMessageId() * @method \Magento\Quote\Model\Quote\Address\Item setGiftMessageId(int $value) - * @method float getHiddenTaxAmount() - * @method \Magento\Quote\Model\Quote\Address\Item setHiddenTaxAmount(float $value) - * @method float getBaseHiddenTaxAmount() - * @method \Magento\Quote\Model\Quote\Address\Item setBaseHiddenTaxAmount(float $value) + * @method float getDiscountTaxCompensationAmount() + * @method \Magento\Quote\Model\Quote\Address\Item setDiscountTaxCompensationAmount(float $value) + * @method float getBaseDiscountTaxCompensationAmount() + * @method \Magento\Quote\Model\Quote\Address\Item setBaseDiscountTaxCompensationAmount(float $value) * * @author Magento Core Team <core@magentocommerce.com> */ diff --git a/app/code/Magento/Quote/Model/Quote/Item.php b/app/code/Magento/Quote/Model/Quote/Item.php index 8dab6a6d2bf42f326b6397b3e239e943003954a0..56ea708036533251670e39c59ed59569732de0b2 100644 --- a/app/code/Magento/Quote/Model/Quote/Item.php +++ b/app/code/Magento/Quote/Model/Quote/Item.php @@ -88,10 +88,10 @@ use Magento\Framework\Api\ExtensionAttributesFactory; * @method \Magento\Quote\Model\Quote\Item setBaseWeeeTaxDisposition(float $value) * @method float getBaseWeeeTaxRowDisposition() * @method \Magento\Quote\Model\Quote\Item setBaseWeeeTaxRowDisposition(float $value) - * @method float getHiddenTaxAmount() - * @method \Magento\Quote\Model\Quote\Item setHiddenTaxAmount(float $value) - * @method float getBaseHiddenTaxAmount() - * @method \Magento\Quote\Model\Quote\Item setBaseHiddenTaxAmount(float $value) + * @method float getDiscountTaxCompensationAmount() + * @method \Magento\Quote\Model\Quote\Item setDiscountTaxCompensationAmount(float $value) + * @method float getBaseDiscountTaxCompensationAmount() + * @method \Magento\Quote\Model\Quote\Item setBaseDiscountTaxCompensationAmount(float $value) * @method null|bool getHasConfigurationUnavailableError() * @method \Magento\Quote\Model\Quote\Item setHasConfigurationUnavailableError(bool $value) * @method \Magento\Quote\Model\Quote\Item unsHasConfigurationUnavailableError() @@ -191,7 +191,7 @@ class Item extends \Magento\Quote\Model\Quote\Item\AbstractItem implements \Mage * @param Item\Compare $quoteItemCompare * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -209,7 +209,7 @@ class Item extends \Magento\Quote\Model\Quote\Item\AbstractItem implements \Mage \Magento\Quote\Model\Quote\Item\Compare $quoteItemCompare, \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_errorInfos = $statusListFactory->create(); @@ -288,6 +288,8 @@ class Item extends \Magento\Quote\Model\Quote\Item\AbstractItem implements \Mage /** * Retrieve quote model object * + * @codeCoverageIgnore + * * @return \Magento\Quote\Model\Quote */ public function getQuote() @@ -316,16 +318,14 @@ class Item extends \Magento\Quote\Model\Quote\Item\AbstractItem implements \Mage */ public function addQty($qty) { - $oldQty = $this->getQty(); - $qty = $this->_prepareQty($qty); - /** * We can't modify quantity of existing items which have parent * This qty declared just once during add process and is not editable */ if (!$this->getParentItem() || !$this->getId()) { + $qty = $this->_prepareQty($qty); $this->setQtyToAdd($qty); - $this->setQty($oldQty + $qty); + $this->setQty($this->getQty() + $qty); } return $this; } @@ -395,6 +395,8 @@ class Item extends \Magento\Quote\Model\Quote\Item\AbstractItem implements \Mage /** * Set option product with Qty * + * @codeCoverageIgnore + * * @param array $qtyOptions * @return $this */ @@ -528,6 +530,8 @@ class Item extends \Magento\Quote\Model\Quote\Item\AbstractItem implements \Mage /** * Return real product type of item * + * @codeCoverageIgnore + * * @return string */ public function getRealProductType() @@ -569,6 +573,8 @@ class Item extends \Magento\Quote\Model\Quote\Item\AbstractItem implements \Mage /** * Get all item options * + * @codeCoverageIgnore + * * @return \Magento\Quote\Model\Quote\Item\Option[] */ public function getOptions() @@ -579,6 +585,8 @@ class Item extends \Magento\Quote\Model\Quote\Item\AbstractItem implements \Mage /** * Get all item options as array with codes in array key * + * @codeCoverageIgnore + * * @return array */ public function getOptionsByCode() @@ -741,6 +749,8 @@ class Item extends \Magento\Quote\Model\Quote\Item\AbstractItem implements \Mage /** * Mar option save requirement * + * @codeCoverageIgnore + * * @param bool $flag * @return void */ @@ -752,6 +762,8 @@ class Item extends \Magento\Quote\Model\Quote\Item\AbstractItem implements \Mage /** * Were options saved * + * @codeCoverageIgnore + * * @return bool */ public function isOptionsSaved() diff --git a/app/code/Magento/Quote/Model/Quote/Item/AbstractItem.php b/app/code/Magento/Quote/Model/Quote/Item/AbstractItem.php index cf31c9912203d5d871d1339a287d713144f3d452..9c8a8666360b25f7dd967403737e17f09231f635 100644 --- a/app/code/Magento/Quote/Model/Quote/Item/AbstractItem.php +++ b/app/code/Magento/Quote/Model/Quote/Item/AbstractItem.php @@ -88,7 +88,7 @@ abstract class AbstractItem extends \Magento\Framework\Model\AbstractExtensibleM * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -99,7 +99,7 @@ abstract class AbstractItem extends \Magento\Framework\Model\AbstractExtensibleM \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/Quote/Model/Quote/Item/Processor.php b/app/code/Magento/Quote/Model/Quote/Item/Processor.php index 3e62bc5cc8c499376c94d4089c5d61a51304508b..9c0894a785ef5b343be81f6d03b95e221bb6139e 100644 --- a/app/code/Magento/Quote/Model/Quote/Item/Processor.php +++ b/app/code/Magento/Quote/Model/Quote/Item/Processor.php @@ -11,6 +11,7 @@ use Magento\Quote\Model\Quote\Item; use Magento\Store\Model\StoreManagerInterface; use Magento\Framework\App\State; use Magento\Framework\Object; +use Magento\Quote\Api\Data\CartItemInterface; /** * Class Processor @@ -74,7 +75,7 @@ class Processor $item->setProduct($product); if ($request->getResetCount() && !$product->getStickWithinParent() && $item->getId() === $request->getId()) { - $item->setData('qty', 0); + $item->setData(CartItemInterface::KEY_QTY, 0); } return $item; @@ -84,7 +85,7 @@ class Processor * Set qty and custom price for quote item * * @param Item $item - * @param Object $request + * @param \Magento\Framework\Object $request * @param Product $candidate * @return void */ @@ -93,6 +94,9 @@ class Processor /** * We specify qty after we know about parent (for stock) */ + if ($request->getResetCount()) { + $item->setData(CartItemInterface::KEY_QTY, 0); + } $item->addQty($candidate->getCartQty()); $customPrice = $request->getCustomPrice(); diff --git a/app/code/Magento/Quote/Model/Quote/Payment.php b/app/code/Magento/Quote/Model/Quote/Payment.php index f071b845cbb1fe3509696882da93882829db3f2a..bb98b0d85ca3ac9d216eddcfac9a52f661249c4b 100644 --- a/app/code/Magento/Quote/Model/Quote/Payment.php +++ b/app/code/Magento/Quote/Model/Quote/Payment.php @@ -67,7 +67,7 @@ class Payment extends \Magento\Payment\Model\Info implements \Magento\Quote\Api\ * @param \Magento\Framework\Encryption\EncryptorInterface $encryptor * @param \Magento\Payment\Model\Checks\SpecificationFactory $methodSpecificationFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -80,7 +80,7 @@ class Payment extends \Magento\Payment\Model\Info implements \Magento\Quote\Api\ \Magento\Framework\Encryption\EncryptorInterface $encryptor, \Magento\Payment\Model\Checks\SpecificationFactory $methodSpecificationFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->methodSpecificationFactory = $methodSpecificationFactory; @@ -123,6 +123,8 @@ class Payment extends \Magento\Payment\Model\Info implements \Magento\Quote\Api\ /** * Retrieve quote model instance * + * @codeCoverageIgnore + * * @return \Magento\Quote\Model\Quote */ public function getQuote() @@ -182,12 +184,6 @@ class Payment extends \Magento\Payment\Model\Info implements \Magento\Quote\Api\ if ($this->getQuote()) { $this->setQuoteId($this->getQuote()->getId()); } - try { - $method = $this->getMethodInstance(); - } catch (\Magento\Framework\Exception\LocalizedException $e) { - return parent::beforeSave(); - } - $method->prepareSave(); return parent::beforeSave(); } @@ -227,7 +223,8 @@ class Payment extends \Magento\Payment\Model\Info implements \Magento\Quote\Api\ public function getMethodInstance() { $method = parent::getMethodInstance(); - return $method->setStore($this->getQuote()->getStore()); + $method->setStore($this->getQuote()->getStore()->getStoreId()); + return $method; } /** diff --git a/app/code/Magento/Quote/Model/QuoteIdMask.php b/app/code/Magento/Quote/Model/QuoteIdMask.php index 953fe1d7af87e232fca36fd79b9d79d0e69d367d..326ca21d76881a547c901677dd09f5d0d059485d 100644 --- a/app/code/Magento/Quote/Model/QuoteIdMask.php +++ b/app/code/Magento/Quote/Model/QuoteIdMask.php @@ -24,7 +24,7 @@ class QuoteIdMask extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Math\Random $randomDataGenerator * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -32,7 +32,7 @@ class QuoteIdMask extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Framework\Math\Random $randomDataGenerator, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->randomDataGenerator = $randomDataGenerator; diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php index 2d4b3c2810ec595d84be9bb5aef127795103d9c6..f341b5894b9fb0a5a5da68f92c6a5b04e79fe2ca 100644 --- a/app/code/Magento/Quote/Model/QuoteManagement.php +++ b/app/code/Magento/Quote/Model/QuoteManagement.php @@ -281,17 +281,14 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface $customer = $this->customerRepository->getById($customerId); try { - $this->quoteRepository->getActiveForCustomer($customerId); - throw new CouldNotSaveException(__('Cannot create quote')); + $quote = $this->quoteRepository->getActiveForCustomer($customerId); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { - + /** @var \Magento\Quote\Model\Quote $quote */ + $quote = $this->quoteRepository->create(); + $quote->setStoreId($storeId); + $quote->setCustomer($customer); + $quote->setCustomerIsGuest(0); } - - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->quoteRepository->create(); - $quote->setStoreId($storeId); - $quote->setCustomer($customer); - $quote->setCustomerIsGuest(0); return $quote; } @@ -375,15 +372,6 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface protected function resolveItems(QuoteEntity $quote) { $quoteItems = $quote->getAllItems(); - for ($i = 0; $i < count($quoteItems) - 1; $i++) { - for ($j = 0; $j < count($quoteItems) - $i - 1; $j++) { - if ($quoteItems[$i]->getParentItemId() == $quoteItems[$j]->getId()) { - $tempItem = $quoteItems[$i]; - $quoteItems[$i] = $quoteItems[$j]; - $quoteItems[$j] = $tempItem; - } - } - } $orderItems = []; foreach ($quoteItems as $quoteItem) { $parentItem = (isset($orderItems[$quoteItem->getParentItemId()])) ? diff --git a/app/code/Magento/Quote/Model/Resource/Quote.php b/app/code/Magento/Quote/Model/Resource/Quote.php index 990902300124466ee9cdc4a3437425e9f5841156..c9ac55ba5414bb7a9368eb495b62bbdf952bad44 100644 --- a/app/code/Magento/Quote/Model/Resource/Quote.php +++ b/app/code/Magento/Quote/Model/Resource/Quote.php @@ -156,8 +156,11 @@ class Quote extends AbstractDb */ public function getReservedOrderId($quote) { - return $this->sequenceManager->getSequence(\Magento\Sales\Model\Order::ENTITY, (int)$quote->getStoreId()) - ->getNextValue(); + return $this->sequenceManager->getSequence( + \Magento\Sales\Model\Order::ENTITY, + $quote->getStore()->getGroup()->getDefaultStoreId() + ) + ->getNextValue(); } /** diff --git a/app/code/Magento/Quote/Setup/InstallSchema.php b/app/code/Magento/Quote/Setup/InstallSchema.php index 9e810569a1bd9c4c5babceac6d8e1b3ff76b235f..a53dc4d8440c23d78cdcdfce563e58aaa4971e43 100644 --- a/app/code/Magento/Quote/Setup/InstallSchema.php +++ b/app/code/Magento/Quote/Setup/InstallSchema.php @@ -640,29 +640,29 @@ class InstallSchema implements InstallSchemaInterface [], 'Base Subtotal Total Incl Tax' )->addColumn( - 'hidden_tax_amount', + 'discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Amount' + 'Discount Tax Compensation Amount' )->addColumn( - 'base_hidden_tax_amount', + 'base_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Amount' + 'Base Discount Tax Compensation Amount' )->addColumn( - 'shipping_hidden_tax_amount', + 'shipping_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Shipping Hidden Tax Amount' + 'Shipping Discount Tax Compensation Amount' )->addColumn( - 'base_shipping_hidden_tax_amnt', + 'base_shipping_discount_tax_compensation_amnt', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Shipping Hidden Tax Amount' + 'Base Shipping Discount Tax Compensation Amount' )->addColumn( 'shipping_incl_tax', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, @@ -935,17 +935,17 @@ class InstallSchema implements InstallSchemaInterface [], 'Base Row Total Incl Tax' )->addColumn( - 'hidden_tax_amount', + 'discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Amount' + 'Discount Tax Compensation Amount' )->addColumn( - 'base_hidden_tax_amount', + 'base_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Amount' + 'Base Discount Tax Compensation Amount' )->addIndex( $installer->getIdxName('quote_item', ['parent_item_id']), ['parent_item_id'] @@ -1209,17 +1209,17 @@ class InstallSchema implements InstallSchemaInterface [], 'Base Row Total Incl Tax' )->addColumn( - 'hidden_tax_amount', + 'discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Amount' + 'Discount Tax Compensation Amount' )->addColumn( - 'base_hidden_tax_amount', + 'base_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Amount' + 'Base Discount Tax Compensation Amount' )->addIndex( $installer->getIdxName('quote_address_item', ['quote_address_id']), ['quote_address_id'] diff --git a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php index 55c75dad00a980c93035de2637207ef108e08c0a..c81db89b83e9b7409f8a07d582ff710f53da9dea 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/PaymentMethodManagementTest.php @@ -162,7 +162,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $quoteMock->expects($this->exactly(2))->method('isVirtual')->willReturn(true); $quoteMock->expects($this->exactly(2))->method('getBillingAddress')->willReturn($billingAddressMock); - $methodInstance = $this->getMock('Magento\Payment\Model\Checks\PaymentMethodChecksInterface'); + $methodInstance = $this->getMockForAbstractClass('Magento\Payment\Model\MethodInterface'); $paymentMock->expects($this->once())->method('getMethodInstance')->willReturn($methodInstance); $this->zeroTotalMock->expects($this->once()) @@ -279,7 +279,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $quoteMock->expects($this->exactly(2))->method('isVirtual')->willReturn(true); $quoteMock->expects($this->exactly(2))->method('getBillingAddress')->willReturn($billingAddressMock); - $methodInstance = $this->getMock('Magento\Payment\Model\Checks\PaymentMethodChecksInterface'); + $methodInstance = $this->getMockForAbstractClass('Magento\Payment\Model\MethodInterface'); $paymentMock->expects($this->once())->method('getMethodInstance')->willReturn($methodInstance); $this->zeroTotalMock->expects($this->once()) @@ -344,7 +344,7 @@ class PaymentMethodManagementTest extends \PHPUnit_Framework_TestCase $quoteMock->expects($this->exactly(2))->method('isVirtual')->willReturn(false); $quoteMock->expects($this->exactly(4))->method('getShippingAddress')->willReturn($shippingAddressMock); - $methodInstance = $this->getMock('Magento\Payment\Model\Checks\PaymentMethodChecksInterface'); + $methodInstance = $this->getMockForAbstractClass('Magento\Payment\Model\MethodInterface'); $paymentMock->expects($this->once())->method('getMethodInstance')->willReturn($methodInstance); $this->zeroTotalMock->expects($this->once()) diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php index 809a16cc5339f42b05cc92340b617991ff9ba841..b27d2ca465a3ed917f61c7973ae980f9619ada18 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Item/ProcessorTest.php @@ -5,9 +5,9 @@ */ namespace Magento\Quote\Test\Unit\Model\Quote\Item; -use \Magento\Quote\Model\Quote\Item\Processor; - -use \Magento\Catalog\Model\Product; +use Magento\Catalog\Model\Product; +use Magento\Quote\Api\Data\CartItemInterface; +use Magento\Quote\Model\Quote\Item\Processor; use Magento\Quote\Model\Quote\ItemFactory; use Magento\Quote\Model\Quote\Item; use Magento\Store\Model\StoreManagerInterface; @@ -109,7 +109,7 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase $this->productMock = $this->getMock( 'Magento\Catalog\Model\Product', - ['getCustomOptions', '__wakeup', 'getParentProductId'], + ['getCustomOptions', '__wakeup', 'getParentProductId', 'getCartQty'], [], '', false @@ -239,31 +239,60 @@ class ProcessorTest extends \PHPUnit_Framework_TestCase $qty = 3000000000; $customPrice = 400000000; + $this->productMock->expects($this->any()) + ->method('getCartQty') + ->will($this->returnValue($qty)); + $this->itemMock->expects($this->any()) ->method('addQty') - ->will($this->returnValue($qty)); + ->with($qty); + + $this->objectMock->expects($this->any()) + ->method('getCustomPrice') + ->will($this->returnValue($customPrice)); $this->itemMock->expects($this->any()) ->method('setCustomPrice') ->will($this->returnValue($customPrice)); - $this->itemMock->expects($this->any()) ->method('setOriginalCustomPrice') ->will($this->returnValue($customPrice)); - $this->itemMock->expects($this->any()) - ->method('addQty') - ->will($this->returnValue($qty)); + $this->processor->prepare($this->itemMock, $this->objectMock, $this->productMock); + } + + public function testPrepareResetCount() + { + $qty = 3000000000; + $customPrice = 400000000; + $this->objectMock->expects($this->any()) + ->method('getResetCount') + ->will($this->returnValue(true)); + + $this->itemMock->expects($this->any()) + ->method('setData') + ->with(CartItemInterface::KEY_QTY, 0); $this->productMock->expects($this->any()) ->method('getCartQty') ->will($this->returnValue($qty)); + $this->itemMock->expects($this->any()) + ->method('addQty') + ->with($qty); + $this->objectMock->expects($this->any()) ->method('getCustomPrice') ->will($this->returnValue($customPrice)); + $this->itemMock->expects($this->any()) + ->method('setCustomPrice') + ->will($this->returnValue($customPrice)); + $this->itemMock->expects($this->any()) + ->method('setOriginalCustomPrice') + ->will($this->returnValue($customPrice)); + $this->processor->prepare($this->itemMock, $this->objectMock, $this->productMock); } } diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php index aa6099192147fe2557b93e465f822f1b30753d57..4ff569e76dca003a046a259776cd68c53bb2a15e 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php @@ -75,7 +75,7 @@ class ToOrderPaymentTest extends \PHPUnit_Framework_TestCase */ public function testConvert() { - $methodInterface = $this->getMock('Magento\Payment\Model\MethodInterface', [], [], '', false); + $methodInterface = $this->getMockForAbstractClass('Magento\Payment\Model\MethodInterface'); $paymentData = ['test' => 'test2']; $data = ['some_id' => 1]; diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php index 8fe61be981cb78a8a5477baee888bff634a779c8..56885a81d78648500927d8b77992e9cddea8a2ee 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php @@ -303,10 +303,7 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase $this->assertEquals($quoteId, $this->model->createEmptyCartForCustomer($userId)); } - /** - * @expectedException \Magento\Framework\Exception\CouldNotSaveException - */ - public function testCreateEmptyCartForCustomerException() + public function testCreateEmptyCartForCustomerReturnExistsQuote() { $storeId = 345; $userId = 567; @@ -316,10 +313,10 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase $this->quoteRepositoryMock ->expects($this->once()) ->method('getActiveForCustomer') - ->with($userId); + ->with($userId)->willReturn($quoteMock); $this->quoteRepositoryMock->expects($this->never())->method('create')->willReturn($quoteMock); - $this->quoteRepositoryMock->expects($this->never())->method('save')->with($quoteMock); + $this->quoteRepositoryMock->expects($this->once())->method('save')->with($quoteMock); $this->storeManagerMock->expects($this->once())->method('getStore')->willReturnSelf(); $this->storeManagerMock->expects($this->once())->method('getStoreId')->willReturn($storeId); diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php index 98c15827761b57e360b5d4967ecaa4afe13683ea..96815ef257fa1a8ea02280dd0043d0125ec74378 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php @@ -147,7 +147,7 @@ class QuoteTest extends \PHPUnit_Framework_TestCase 'Magento\Quote\Model\Quote\Address', [ 'isDeleted', 'getCollection', 'getId', 'getCustomerAddressId', - '__wakeup', 'getAddressType', 'getDeleteImmediately', 'validateMinimumAmount' + '__wakeup', 'getAddressType', 'getDeleteImmediately', 'validateMinimumAmount', 'setData' ], [], '', @@ -742,12 +742,18 @@ class QuoteTest extends \PHPUnit_Framework_TestCase ->with($id) ->will($this->returnSelf()); + $this->quoteAddressMock->expects($this->any()) + ->method('getAddressType') + ->will($this->returnValue(\Magento\Customer\Model\Address\AbstractAddress::TYPE_SHIPPING)); $this->quoteAddressMock->expects($this->any()) ->method('getAddressType') ->will($this->returnValue(\Magento\Customer\Model\Address\AbstractAddress::TYPE_SHIPPING)); $this->quoteAddressMock->expects($this->any()) ->method('isDeleted') ->will($this->returnValue(false)); + $this->quoteAddressMock->expects($this->any()) + ->method('setData') + ->will($this->returnSelf()); $this->quoteAddressMock->expects($this->once()) ->method('getId') ->will($this->returnValue($id)); diff --git a/app/code/Magento/Quote/composer.json b/app/code/Magento/Quote/composer.json index a37e6d0f991c8ae4df9fe31a4d52fc0f36f5f0fe..f58331308612ac84cf4b8e0e7a42328671b2450e 100644 --- a/app/code/Magento/Quote/composer.json +++ b/app/code/Magento/Quote/composer.json @@ -3,26 +3,26 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-catalog-rule": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-authorization": "0.74.0-beta10", - "magento/module-payment": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-shipping": "0.74.0-beta10", - "magento/module-sales-sequence": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-catalog-rule": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-authorization": "0.74.0-beta13", + "magento/module-payment": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-shipping": "0.74.0-beta13", + "magento/module-sales-sequence": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Quote/etc/fieldset.xml b/app/code/Magento/Quote/etc/fieldset.xml index 56ace3faf1e755e1edd9b7c6912bcf280345755f..eaeaf0a917857bae55716cb2cb3201d0fc07d35d 100644 --- a/app/code/Magento/Quote/etc/fieldset.xml +++ b/app/code/Magento/Quote/etc/fieldset.xml @@ -84,16 +84,16 @@ <field name="base_grand_total"> <aspect name="to_order" /> </field> - <field name="hidden_tax_amount"> + <field name="discount_tax_compensation_amount"> <aspect name="to_order" /> </field> - <field name="base_hidden_tax_amount"> + <field name="base_discount_tax_compensation_amount"> <aspect name="to_order" /> </field> - <field name="shipping_hidden_tax_amount"> + <field name="shipping_discount_tax_compensation_amount"> <aspect name="to_order" /> </field> - <field name="base_shipping_hidden_tax_amount"> + <field name="base_shipping_discount_tax_compensation_amount"> <aspect name="to_order" /> </field> <field name="prefix"> @@ -251,10 +251,10 @@ <field name="store_id"> <aspect name="to_order_item" /> </field> - <field name="hidden_tax_amount"> + <field name="discount_tax_compensation_amount"> <aspect name="to_order_item" /> </field> - <field name="base_hidden_tax_amount"> + <field name="base_discount_tax_compensation_amount"> <aspect name="to_order_item" /> </field> <field name="product_id"> diff --git a/app/code/Magento/Reports/Block/Adminhtml/Wishlist/Grid.php b/app/code/Magento/Reports/Block/Adminhtml/Wishlist/Grid.php index a95ae01a562c15b069ff5cf2a4d043635a821f1f..5bf34e223697af53011009c677639955ef78b89c 100644 --- a/app/code/Magento/Reports/Block/Adminhtml/Wishlist/Grid.php +++ b/app/code/Magento/Reports/Block/Adminhtml/Wishlist/Grid.php @@ -79,7 +79,7 @@ class Grid extends \Magento\Backend\Block\Widget\Grid\Extended $this->addColumn( 'bought_from_wishlists', [ - 'header' => __('Wishlist Purchase'), + 'header' => __('Wish List Purchase'), 'width' => '50px', 'align' => 'right', 'sortable' => false, diff --git a/app/code/Magento/Reports/Model/Event.php b/app/code/Magento/Reports/Model/Event.php index 4a82b497b6aa65416182261e930b7b1550cd12eb..83275febc57204d376cd7edb8680f824efb70e62 100644 --- a/app/code/Magento/Reports/Model/Event.php +++ b/app/code/Magento/Reports/Model/Event.php @@ -55,7 +55,7 @@ class Event extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Stdlib\DateTime\DateTimeFactory $dateFactory * @param \Magento\Reports\Model\Event\TypeFactory $eventTypeFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -64,7 +64,7 @@ class Event extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Stdlib\DateTime\DateTimeFactory $dateFactory, \Magento\Reports\Model\Event\TypeFactory $eventTypeFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Reports/Model/Grouped/Collection.php b/app/code/Magento/Reports/Model/Grouped/Collection.php index 4628d5542e6cbffc1e5528d7bb7c1697cfe4564c..6f8e9d561dad6cd65a5ea80b76e2a15465c1f50f 100644 --- a/app/code/Magento/Reports/Model/Grouped/Collection.php +++ b/app/code/Magento/Reports/Model/Grouped/Collection.php @@ -5,7 +5,7 @@ */ namespace Magento\Reports\Model\Grouped; -use Magento\Framework\Data\Collection\Db; +use Magento\Framework\Data\Collection\AbstractDb as DbCollection; class Collection extends \Magento\Framework\Data\Collection { @@ -62,7 +62,7 @@ class Collection extends \Magento\Framework\Data\Collection /** * Setter for resource collection * - * @param Db $collection + * @param DbCollection $collection * @return $this */ public function setResourceCollection($collection) diff --git a/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php b/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php index 6f6f216e634e88817fc9bcfe35fc379f73b11e73..76a4438f813ad54ca06e20afd8368f970b4ca33e 100644 --- a/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php +++ b/app/code/Magento/Reports/Model/Product/Index/AbstractIndex.php @@ -57,7 +57,7 @@ abstract class AbstractIndex extends \Magento\Framework\Model\AbstractModel * @param \Magento\Catalog\Model\Product\Visibility $productVisibility * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -71,7 +71,7 @@ abstract class AbstractIndex extends \Magento\Framework\Model\AbstractModel \Magento\Catalog\Model\Product\Visibility $productVisibility, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Reports/Model/Product/Index/Compared.php b/app/code/Magento/Reports/Model/Product/Index/Compared.php index 2bf6917f348786a75cce710579f3fa04b588278e..f58560c353b7e8320f6a653869260df5b1a3a2d7 100644 --- a/app/code/Magento/Reports/Model/Product/Index/Compared.php +++ b/app/code/Magento/Reports/Model/Product/Index/Compared.php @@ -47,7 +47,7 @@ class Compared extends \Magento\Reports\Model\Product\Index\AbstractIndex * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Catalog\Helper\Product\Compare $productCompare * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -62,7 +62,7 @@ class Compared extends \Magento\Reports\Model\Product\Index\AbstractIndex \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Catalog\Helper\Product\Compare $productCompare, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/Reports/Model/Resource/Event.php b/app/code/Magento/Reports/Model/Resource/Event.php index 912cc7ceaa4536b5aa2c6f397753322907585a06..4b7ae784054c88b16131654ecbbeed25b4ffcd89 100644 --- a/app/code/Magento/Reports/Model/Resource/Event.php +++ b/app/code/Magento/Reports/Model/Resource/Event.php @@ -76,7 +76,7 @@ class Event extends \Magento\Framework\Model\Resource\Db\AbstractDb * The collection id field is used without corellation, so it must be unique. * DESC ordering by event will be added to the collection * - * @param \Magento\Framework\Data\Collection\Db $collection + * @param \Magento\Framework\Data\Collection\AbstractDb $collection * @param int $eventTypeId * @param int $eventSubjectId * @param int $subtype @@ -84,7 +84,7 @@ class Event extends \Magento\Framework\Model\Resource\Db\AbstractDb * @return $this */ public function applyLogToCollection( - \Magento\Framework\Data\Collection\Db $collection, + \Magento\Framework\Data\Collection\AbstractDb $collection, $eventTypeId, $eventSubjectId, $subtype, diff --git a/app/code/Magento/Reports/composer.json b/app/code/Magento/Reports/composer.json index 4b4db815f19c22872db3f2074e6fda8844ee1435..099550f07e1ea5ec1812cf7466c1f75732a52e60 100644 --- a/app/code/Magento/Reports/composer.json +++ b/app/code/Magento/Reports/composer.json @@ -3,28 +3,28 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-cms": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-widget": "0.74.0-beta10", - "magento/module-log": "0.74.0-beta10", - "magento/module-wishlist": "0.74.0-beta10", - "magento/module-review": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-downloadable": "0.74.0-beta10", - "magento/module-sales-rule": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-cms": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-widget": "0.74.0-beta13", + "magento/module-log": "0.74.0-beta13", + "magento/module-wishlist": "0.74.0-beta13", + "magento/module-review": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-downloadable": "0.74.0-beta13", + "magento/module-sales-rule": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Reports/view/adminhtml/templates/report/wishlist.phtml b/app/code/Magento/Reports/view/adminhtml/templates/report/wishlist.phtml index b97ac80411bf16a91be6b386f4963e7dc550ee99..2c1822789c8126bd5dce05a7acd60acccea40b27 100644 --- a/app/code/Magento/Reports/view/adminhtml/templates/report/wishlist.phtml +++ b/app/code/Magento/Reports/view/adminhtml/templates/report/wishlist.phtml @@ -8,21 +8,21 @@ <div class="switcher f-left" style="margin: 10px 10px 10px 0px; padding:15px;"> <?php - echo __('Customers that have wish list: %1%', $block->getCustomerWithWishlist()) + echo __('Customers that have Wish List: %1%', $block->getCustomerWithWishlist()) ?> </div> <div class="switcher" style="float: right; margin: 10px 0px 10px 10px; padding:15px;"> <?php - echo __('Number of wish lists: %1', $block->getWishlistsCount()) + echo __('Number of Wish Lists: %1', $block->getWishlistsCount()) ?><br /> <?php - echo __('Number of items bought from a wish list: %1', $block->getItemsBought()) + echo __('Number of items bought from a Wish List: %1', $block->getItemsBought()) ?><br /> - <?php echo __('Number of times wish lists have been shared (emailed): %1', $block->getSharedCount()) + <?php echo __('Number of times Wish Lists have been shared (emailed): %1', $block->getSharedCount()) ?><br /> - <?php echo __('Number of wish list referrals: %1', $block->getReferralsCount()) + <?php echo __('Number of Wish List referrals: %1', $block->getReferralsCount()) ?><br /> - <?php echo __('Number of wish list conversions: %1', $block->getConversionsCount()) + <?php echo __('Number of Wish List conversions: %1', $block->getConversionsCount()) ?><br /> </div> diff --git a/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml b/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml index 47e2cf321ceefa5feb36e5b8561d1145cfd493ae..92ec5562534636c996013ff94f90d0aaf3793284 100644 --- a/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/product/widget/viewed/item.phtml @@ -71,8 +71,8 @@ $rating = 'short'; <div class="secondary-addto-links" data-role="add-to-links"> <?php if ($this->helper('Magento\Wishlist\Helper\Data')->isAllow()): ?> - <a href="#" data-post='<?php echo $block->getAddToWishlistParams($item); ?>' class="action towishlist" data-action="add-to-wishlist" title="<?php echo __('Add to Wishlist') ?>"> - <span><?php echo __('Add to Wishlist') ?></span> + <a href="#" data-post='<?php echo $block->getAddToWishlistParams($item); ?>' class="action towishlist" data-action="add-to-wishlist" title="<?php echo __('Add to Wish List') ?>"> + <span><?php echo __('Add to Wish List') ?></span> </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl()): ?> diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml index 049c254f8e1f7040bab0a48b8bef60a6d0d04643..f0fa5daabd61b0c3c1f87dbeb1ca8545f6d4ed19 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_grid.phtml @@ -102,8 +102,8 @@ if ($exist = $block->getRecentlyComparedProducts()) { data-post='<?php echo $block->getAddToWishlistParams($_item); ?>' data-action="add-to-wishlist" class="action towishlist" - title="<?php echo __('Add to Wishlist') ?>"> - <span><?php echo __('Add to Wishlist') ?></span> + title="<?php echo __('Add to Wish List') ?>"> + <span><?php echo __('Add to Wish List') ?></span> </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare): ?> diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml index 7da7a3fa01980766c16fbb41bb17e56b73a1973f..bbad16529bbdcd45b7113ef93048a7a4d90bb533 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/compared/content/compared_list.phtml @@ -103,8 +103,8 @@ if ($exist = $block->getRecentlyComparedProducts()) { data-post='<?php echo $block->getAddToWishlistParams($_item); ?>' data-action="add-to-wishlist" class="action towishlist" - title="<?php echo __('Add to Wishlist') ?>"> - <span><?php echo __('Add to Wishlist') ?></span> + title="<?php echo __('Add to Wish List') ?>"> + <span><?php echo __('Add to Wish List') ?></span> </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare): ?> diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml index d63d0f976b671fe9ac71a1117c4dd62f0f896877..0d2dbdb5ebe8104f8a09f1e6eead8bd9f993e0f4 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_grid.phtml @@ -102,8 +102,8 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr <a href="#" class="action towishlist" data-action="add-to-wishlist" data-post='<?php echo $block->getAddToWishlistParams($_item); ?>' - title="<?php echo __('Add to Wishlist') ?>"> - <span><?php echo __('Add to Wishlist') ?></span> + title="<?php echo __('Add to Wish List') ?>"> + <span><?php echo __('Add to Wish List') ?></span> </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare): ?> diff --git a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml index 055e30e68a05e5fc6720f5b06f038ee01f978eea..de44d8433d8c9e763574eb618d3ceda4a038250d 100644 --- a/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml +++ b/app/code/Magento/Reports/view/frontend/templates/widget/viewed/content/viewed_list.phtml @@ -105,8 +105,8 @@ if ($exist = ($block->getRecentlyViewedProducts() && $block->getRecentlyViewedPr <a href="#" class="action towishlist" data-action="add-to-wishlist" data-post='<?php echo $block->getAddToWishlistParams($_item); ?>' - title="<?php echo __('Add to Wishlist') ?>"> - <span><?php echo __('Add to Wishlist') ?></span> + title="<?php echo __('Add to Wish List') ?>"> + <span><?php echo __('Add to Wish List') ?></span> </a> <?php endif; ?> <?php if ($block->getAddToCompareUrl() && $showCompare): ?> diff --git a/app/code/Magento/RequireJs/composer.json b/app/code/Magento/RequireJs/composer.json index 74929a83bfdd03ba3bc26395bb1609d2fbfcf588..c921a04022f146ff8fe438985fd98d93ef9c3fbe 100644 --- a/app/code/Magento/RequireJs/composer.json +++ b/app/code/Magento/RequireJs/composer.json @@ -3,11 +3,11 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Review/Model/Rating.php b/app/code/Magento/Review/Model/Rating.php index 985477f4c7d30526ca4df550e86617db2bdd12b3..c1fb92638986d1a88c04cc2f85788868ddf0330b 100644 --- a/app/code/Magento/Review/Model/Rating.php +++ b/app/code/Magento/Review/Model/Rating.php @@ -45,7 +45,7 @@ class Rating extends \Magento\Framework\Model\AbstractModel * @param \Magento\Review\Model\Rating\OptionFactory $ratingOptionFactory * @param \Magento\Review\Model\Resource\Rating\Option\CollectionFactory $ratingCollectionF * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -54,7 +54,7 @@ class Rating extends \Magento\Framework\Model\AbstractModel \Magento\Review\Model\Rating\OptionFactory $ratingOptionFactory, \Magento\Review\Model\Resource\Rating\Option\CollectionFactory $ratingCollectionF, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_ratingOptionFactory = $ratingOptionFactory; @@ -132,7 +132,7 @@ class Rating extends \Magento\Framework\Model\AbstractModel * * @param int $entityPkValue * @param bool $onlyForCurrentStore - * @return \Magento\Framework\Data\Collection\Db + * @return \Magento\Framework\Data\Collection\AbstractDb */ public function getEntitySummary($entityPkValue, $onlyForCurrentStore = true) { diff --git a/app/code/Magento/Review/Model/Resource/Review/Summary/Collection.php b/app/code/Magento/Review/Model/Resource/Review/Summary/Collection.php index c87dbe996c5db2079db27d7b742f14f0fd6c61e4..7a14b8f0b433eabf7fa3096cfadbafaadc14e0f1 100644 --- a/app/code/Magento/Review/Model/Resource/Review/Summary/Collection.php +++ b/app/code/Magento/Review/Model/Resource/Review/Summary/Collection.php @@ -10,35 +10,14 @@ namespace Magento\Review\Model\Resource\Review\Summary; * * @author Magento Core Team <core@magentocommerce.com> */ -class Collection extends \Magento\Framework\Data\Collection\Db +class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection { /** - * Summary table name - * - * @var string - */ - protected $_summaryTable; - - /** - * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory - * @param \Psr\Log\LoggerInterface $logger - * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy - * @param \Magento\Framework\App\Resource $resource + * {@inheritdoc} */ - public function __construct( - \Magento\Framework\Data\Collection\EntityFactory $entityFactory, - \Psr\Log\LoggerInterface $logger, - \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, - \Magento\Framework\App\Resource $resource - ) { - $this->_setIdFieldName('primary_id'); - - parent::__construct($entityFactory, $logger, $fetchStrategy, $resource->getConnection('review_read')); - $this->_summaryTable = $resource->getTableName('review_entity_summary'); - - $this->_select->from($this->_summaryTable); - - $this->setItemObjectClass('Magento\Review\Model\Review\Summary'); + protected function _construct() + { + $this->_init('Magento\Review\Model\Review\Summary', 'Magento\Review\Model\Resource\Review\Summary'); } /** diff --git a/app/code/Magento/Review/Model/Review.php b/app/code/Magento/Review/Model/Review.php index 3660815cf0249498575242fc03feea81a36ef0a7..63405dde14c7588458537f1d9ee4f47a5e38dc8b 100644 --- a/app/code/Magento/Review/Model/Review.php +++ b/app/code/Magento/Review/Model/Review.php @@ -120,7 +120,7 @@ class Review extends \Magento\Framework\Model\AbstractModel * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\UrlInterface $urlModel * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -135,7 +135,7 @@ class Review extends \Magento\Framework\Model\AbstractModel \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\UrlInterface $urlModel, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->productCollectionFactory = $productFactory; diff --git a/app/code/Magento/Review/Model/Review/Status.php b/app/code/Magento/Review/Model/Review/Status.php index cc4c9ec309994b7d259ff72cbbadcac9557aa7a3..d1cd3e530a27e07e38d75db2aac3a4f4e0f5acd5 100644 --- a/app/code/Magento/Review/Model/Review/Status.php +++ b/app/code/Magento/Review/Model/Review/Status.php @@ -18,14 +18,14 @@ class Status extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( \Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Review/Test/Unit/Model/Resource/Review/Summary/CollectionTest.php b/app/code/Magento/Review/Test/Unit/Model/Resource/Review/Summary/CollectionTest.php index 3157bd17c7ad9effbc3b5567735c78d62381b6e9..32ee1c22708cf2376ceda10d2207103e787e8a90 100644 --- a/app/code/Magento/Review/Test/Unit/Model/Resource/Review/Summary/CollectionTest.php +++ b/app/code/Magento/Review/Test/Unit/Model/Resource/Review/Summary/CollectionTest.php @@ -31,7 +31,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase protected $loggerMock; /** - * @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Model\Resource\Db\AbstractDb|\PHPUnit_Framework_MockObject_MockObject */ protected $resourceMock; @@ -62,13 +62,10 @@ class CollectionTest extends \PHPUnit_Framework_TestCase false ); $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface'); - $this->resourceMock = $this->getMock( - 'Magento\Framework\App\Resource', - [], - [], - '', - false - ); + $this->resourceMock = $this->getMockBuilder('Magento\Framework\Model\Resource\Db\AbstractDb') + ->setMethods(['getReadConnection', 'getMainTable', 'getTable']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $this->adapterMock = $this->getMock( 'Zend_Db_Adapter_Pdo_Mysql', ['select', 'query'], @@ -85,17 +82,25 @@ class CollectionTest extends \PHPUnit_Framework_TestCase ->method('select') ->will($this->returnValue($this->selectMock)); $this->resourceMock->expects($this->once()) - ->method('getConnection') + ->method('getReadConnection') ->will($this->returnValue($this->adapterMock)); $this->resourceMock->expects($this->once()) - ->method('getTableName') + ->method('getMainTable') + ->willReturn('main_table_name'); + + $this->resourceMock->expects($this->once()) + ->method('getTable') ->will($this->returnArgument(0)); - $this->collection = new Collection( - $this->entityFactoryMock, - $this->loggerMock, - $this->fetchStrategyMock, - $this->resourceMock + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->collection = $objectManager->getObject( + 'Magento\Review\Model\Resource\Review\Summary\Collection', + [ + 'entityFactory' => $this->entityFactoryMock, + 'logger' => $this->loggerMock, + 'fetchStrategy' => $this->fetchStrategyMock, + 'resource' => $this->resourceMock + ] ); } @@ -112,7 +117,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase ->with($this->selectMock, $this->anything()) ->will($this->returnValue($statementMock)); - $objectMock = $this->getMock('Magento\Framework\Object', ['setData'], []); + $objectMock = $this->getMock('Magento\Framework\Model\AbstractModel', ['setData'], [], '', false); $objectMock->expects($this->once()) ->method('setData') ->with($data); @@ -123,7 +128,7 @@ class CollectionTest extends \PHPUnit_Framework_TestCase $item = $this->collection->fetchItem(); $this->assertEquals($objectMock, $item); - $this->assertEquals('primary_id', $item->getIdFieldName()); + $this->assertEquals('id', $item->getIdFieldName()); } public function testLoad() diff --git a/app/code/Magento/Review/composer.json b/app/code/Magento/Review/composer.json index 74196584566fcdb4a8f9f11a64c76b576b217bc9..45201df67e97c0cfec3850649adf2b8fdcfbfa74 100644 --- a/app/code/Magento/Review/composer.json +++ b/app/code/Magento/Review/composer.json @@ -3,22 +3,22 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-newsletter": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-ui": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-newsletter": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-ui": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-cookie": "0.74.0-beta10" + "magento/module-cookie": "0.74.0-beta13" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Rss/Model/System/Config/Backend/Links.php b/app/code/Magento/Rss/Model/System/Config/Backend/Links.php index da830f54de6eb13c82c6176f0380ca17008d2cf0..bb295ee056d949f8f0e4cb31ef83585d16210db1 100644 --- a/app/code/Magento/Rss/Model/System/Config/Backend/Links.php +++ b/app/code/Magento/Rss/Model/System/Config/Backend/Links.php @@ -22,7 +22,7 @@ class Links extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -31,7 +31,7 @@ class Links extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_cacheTypeList = $cacheTypeList; diff --git a/app/code/Magento/Rss/composer.json b/app/code/Magento/Rss/composer.json index a5f8afae24a0c13643a7a307f2fa240af291295c..9e085b9677094ac04fb063a23147c319500255be 100644 --- a/app/code/Magento/Rss/composer.json +++ b/app/code/Magento/Rss/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Rule/Model/AbstractModel.php b/app/code/Magento/Rule/Model/AbstractModel.php index 786635077534fa972b45ed061ec5b28cf2b0142f..8aedb81590ed17eb55dc379c90a3058160af320a 100644 --- a/app/code/Magento/Rule/Model/AbstractModel.php +++ b/app/code/Magento/Rule/Model/AbstractModel.php @@ -78,7 +78,7 @@ abstract class AbstractModel extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Data\FormFactory $formFactory * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -87,7 +87,7 @@ abstract class AbstractModel extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Data\FormFactory $formFactory, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_formFactory = $formFactory; diff --git a/app/code/Magento/Rule/composer.json b/app/code/Magento/Rule/composer.json index 9b391372d65b2ff744dad8cc033ffe6ecdc24d42..d6e66b999c893133d222d72c447801d2b2bff85e 100644 --- a/app/code/Magento/Rule/composer.json +++ b/app/code/Magento/Rule/composer.json @@ -3,16 +3,16 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Sales/Api/Data/CreditmemoCommentInterface.php b/app/code/Magento/Sales/Api/Data/CreditmemoCommentInterface.php index 246eaee49d645c529d9ec60c6f3ecc26fd9dd253..48c2131dca9fc83ba11c2578dd104ddcc19d0177 100644 --- a/app/code/Magento/Sales/Api/Data/CreditmemoCommentInterface.php +++ b/app/code/Magento/Sales/Api/Data/CreditmemoCommentInterface.php @@ -54,7 +54,7 @@ interface CreditmemoCommentInterface extends \Magento\Framework\Api\ExtensibleDa /** * Gets the credit memo created-at timestamp. * - * @return string Created-at timestamp. + * @return string|null Created-at timestamp. */ public function getCreatedAt(); @@ -69,7 +69,7 @@ interface CreditmemoCommentInterface extends \Magento\Framework\Api\ExtensibleDa /** * Gets the credit memo ID. * - * @return int Credit memo ID. + * @return int|null Credit memo ID. */ public function getEntityId(); diff --git a/app/code/Magento/Sales/Api/Data/CreditmemoInterface.php b/app/code/Magento/Sales/Api/Data/CreditmemoInterface.php index 18a23bde8430efc5244a56ffc35927e3c9bbd8ad..5b156e06e6c96e2a3e0a21fa6120bca8f0afe16f 100644 --- a/app/code/Magento/Sales/Api/Data/CreditmemoInterface.php +++ b/app/code/Magento/Sales/Api/Data/CreditmemoInterface.php @@ -186,21 +186,21 @@ interface CreditmemoInterface extends \Magento\Framework\Api\ExtensibleDataInter */ const UPDATED_AT = 'updated_at'; /* - * Hidden tax amount. + * Discount tax compensation amount. */ - const HIDDEN_TAX_AMOUNT = 'hidden_tax_amount'; + const DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount'; /* - * Base hidden tax amount. + * Base discount tax compensation amount. */ - const BASE_HIDDEN_TAX_AMOUNT = 'base_hidden_tax_amount'; + const BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'base_discount_tax_compensation_amount'; /* - * Shipping hidden tax amount. + * Shipping discount tax compensation amount. */ - const SHIPPING_HIDDEN_TAX_AMOUNT = 'shipping_hidden_tax_amount'; + const SHIPPING_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'shipping_discount_tax_compensation_amount'; /* - * Base shipping hidden tax amount. + * Base shipping discount tax compensation amount. */ - const BASE_SHIPPING_HIDDEN_TAX_AMNT = 'base_shipping_hidden_tax_amnt'; + const BASE_SHIPPING_DISCOUNT_TAX_COMPENSATION_AMNT = 'base_shipping_discount_tax_compensation_amnt'; /* * Shipping including tax. */ @@ -225,35 +225,35 @@ interface CreditmemoInterface extends \Magento\Framework\Api\ExtensibleDataInter /** * Gets the credit memo adjustment. * - * @return float Credit memo adjustment. + * @return float|null Credit memo adjustment. */ public function getAdjustment(); /** * Gets the credit memo negative adjustment. * - * @return float Credit memo negative adjustment. + * @return float|null Credit memo negative adjustment. */ public function getAdjustmentNegative(); /** * Gets the credit memo positive adjustment. * - * @return float Credit memo positive adjustment. + * @return float|null Credit memo positive adjustment. */ public function getAdjustmentPositive(); /** * Gets the credit memo base adjustment. * - * @return float Credit memo base adjustment. + * @return float|null Credit memo base adjustment. */ public function getBaseAdjustment(); /** * Gets the credit memo negative base adjustment. * - * @return float Credit memo negative base adjustment. + * @return float|null Credit memo negative base adjustment. */ public function getBaseAdjustmentNegative(); @@ -268,7 +268,7 @@ interface CreditmemoInterface extends \Magento\Framework\Api\ExtensibleDataInter /** * Gets the credit memo positive base adjustment. * - * @return float Credit memo positive base adjustment. + * @return float|null Credit memo positive base adjustment. */ public function getBaseAdjustmentPositive(); @@ -283,105 +283,105 @@ interface CreditmemoInterface extends \Magento\Framework\Api\ExtensibleDataInter /** * Gets the credit memo base currency code. * - * @return string Credit memo base currency code. + * @return string|null Credit memo base currency code. */ public function getBaseCurrencyCode(); /** * Gets the credit memo base discount amount. * - * @return float Credit memo base discount amount. + * @return float|null Credit memo base discount amount. */ public function getBaseDiscountAmount(); /** * Gets the credit memo base grand total. * - * @return float Credit memo base grand total. + * @return float|null Credit memo base grand total. */ public function getBaseGrandTotal(); /** - * Gets the credit memo base hidden tax amount. + * Gets the credit memo base discount tax compensation amount. * - * @return float Credit memo base hidden tax amount. + * @return float Credit memo base discount tax compensation amount. */ - public function getBaseHiddenTaxAmount(); + public function getBaseDiscountTaxCompensationAmount(); /** * Gets the credit memo base shipping amount. * - * @return float Credit memo base shipping amount. + * @return float|null Credit memo base shipping amount. */ public function getBaseShippingAmount(); /** - * Gets the credit memo base shipping hidden tax amount. + * Gets the credit memo base shipping discount tax compensation amount. * - * @return float Credit memo base shipping hidden tax amount. + * @return float Credit memo base shipping discount tax compensation amount. */ - public function getBaseShippingHiddenTaxAmnt(); + public function getBaseShippingDiscountTaxCompensationAmnt(); /** * Gets the credit memo base shipping including tax. * - * @return float Credit memo base shipping including tax. + * @return float|null Credit memo base shipping including tax. */ public function getBaseShippingInclTax(); /** * Gets the credit memo base shipping tax amount. * - * @return float Credit memo base shipping tax amount. + * @return float|null Credit memo base shipping tax amount. */ public function getBaseShippingTaxAmount(); /** * Gets the credit memo base subtotal. * - * @return float Credit memo base subtotal. + * @return float|null Credit memo base subtotal. */ public function getBaseSubtotal(); /** * Gets the credit memo base subtotal including tax. * - * @return float Credit memo base subtotal including tax. + * @return float|null Credit memo base subtotal including tax. */ public function getBaseSubtotalInclTax(); /** * Gets the credit memo base tax amount. * - * @return float Credit memo base tax amount. + * @return float|null Credit memo base tax amount. */ public function getBaseTaxAmount(); /** * Gets the credit memo base-to-global rate. * - * @return float Credit memo base-to-global rate. + * @return float|null Credit memo base-to-global rate. */ public function getBaseToGlobalRate(); /** * Gets the credit memo base-to-order rate. * - * @return float Credit memo base-to-order rate. + * @return float|null Credit memo base-to-order rate. */ public function getBaseToOrderRate(); /** * Gets the credit memo billing address ID. * - * @return int Credit memo billing address ID. + * @return int|null Credit memo billing address ID. */ public function getBillingAddressId(); /** * Gets the credit memo created-at timestamp. * - * @return string Credit memo created-at timestamp. + * @return string|null Credit memo created-at timestamp. */ public function getCreatedAt(); @@ -396,35 +396,35 @@ interface CreditmemoInterface extends \Magento\Framework\Api\ExtensibleDataInter /** * Gets the credit memo status. * - * @return int Credit memo status. + * @return int|null Credit memo status. */ public function getCreditmemoStatus(); /** * Gets the credit memo discount amount. * - * @return float Credit memo discount amount. + * @return float|null Credit memo discount amount. */ public function getDiscountAmount(); /** * Gets the credit memo discount description. * - * @return string Credit memo discount description. + * @return string|null Credit memo discount description. */ public function getDiscountDescription(); /** * Gets the credit memo email sent flag value. * - * @return int Credit memo email sent flag value. + * @return int|null Credit memo email sent flag value. */ public function getEmailSent(); /** * Gets the credit memo ID. * - * @return int Credit memo ID. + * @return int|null Credit memo ID. */ public function getEntityId(); @@ -439,42 +439,42 @@ interface CreditmemoInterface extends \Magento\Framework\Api\ExtensibleDataInter /** * Gets the credit memo global currency code. * - * @return string Credit memo global currency code. + * @return string|null Credit memo global currency code. */ public function getGlobalCurrencyCode(); /** * Gets the credit memo grand total. * - * @return float Credit memo grand total. + * @return float|null Credit memo grand total. */ public function getGrandTotal(); /** - * Gets the credit memo hidden tax amount. + * Gets the credit memo discount tax compensation amount. * - * @return float Credit memo hidden tax amount. + * @return float Credit memo discount tax compensation amount. */ - public function getHiddenTaxAmount(); + public function getDiscountTaxCompensationAmount(); /** * Gets the credit memo increment ID. * - * @return string Credit memo increment ID. + * @return string|null Credit memo increment ID. */ public function getIncrementId(); /** * Gets the credit memo invoice ID. * - * @return int Credit memo invoice ID. + * @return int|null Credit memo invoice ID. */ public function getInvoiceId(); /** * Gets the credit memo order currency code. * - * @return string Credit memo order currency code. + * @return string|null Credit memo order currency code. */ public function getOrderCurrencyCode(); @@ -488,97 +488,97 @@ interface CreditmemoInterface extends \Magento\Framework\Api\ExtensibleDataInter /** * Gets the credit memo shipping address ID. * - * @return int Credit memo shipping address ID. + * @return int|null Credit memo shipping address ID. */ public function getShippingAddressId(); /** * Gets the credit memo shipping amount. * - * @return float Credit memo shipping amount. + * @return float|null Credit memo shipping amount. */ public function getShippingAmount(); /** - * Gets the credit memo shipping hidden tax amount. + * Gets the credit memo shipping discount tax compensation amount. * - * @return float Credit memo shipping hidden tax amount. + * @return float Credit memo shipping discount tax compensation amount. */ - public function getShippingHiddenTaxAmount(); + public function getShippingDiscountTaxCompensationAmount(); /** * Gets the credit memo shipping including tax. * - * @return float Credit memo shipping including tax. + * @return float|null Credit memo shipping including tax. */ public function getShippingInclTax(); /** * Gets the credit memo shipping tax amount. * - * @return float Credit memo shipping tax amount. + * @return float|null Credit memo shipping tax amount. */ public function getShippingTaxAmount(); /** * Gets the credit memo state. * - * @return int Credit memo state. + * @return int|null Credit memo state. */ public function getState(); /** * Gets the credit memo store currency code. * - * @return string Credit memo store currency code. + * @return string|null Credit memo store currency code. */ public function getStoreCurrencyCode(); /** * Gets the credit memo store ID. * - * @return int Credit memo store ID. + * @return int|null Credit memo store ID. */ public function getStoreId(); /** * Gets the credit memo store-to-base rate. * - * @return float Credit memo store-to-base rate. + * @return float|null Credit memo store-to-base rate. */ public function getStoreToBaseRate(); /** * Gets the credit memo store-to-order rate. * - * @return float Credit memo store-to-order rate. + * @return float|null Credit memo store-to-order rate. */ public function getStoreToOrderRate(); /** * Gets the credit memo subtotal. * - * @return float Credit memo subtotal. + * @return float|null Credit memo subtotal. */ public function getSubtotal(); /** * Gets the credit memo subtotal including tax. * - * @return float Credit memo subtotal including tax. + * @return float|null Credit memo subtotal including tax. */ public function getSubtotalInclTax(); /** * Gets the credit memo tax amount. * - * @return float Credit memo tax amount. + * @return float|null Credit memo tax amount. */ public function getTaxAmount(); /** * Gets the credit memo transaction ID. * - * @return string Credit memo transaction ID. + * @return string|null Credit memo transaction ID. */ public function getTransactionId(); @@ -593,7 +593,7 @@ interface CreditmemoInterface extends \Magento\Framework\Api\ExtensibleDataInter /** * Gets the credit memo updated-at timestamp. * - * @return string Credit memo updated-at timestamp. + * @return string|null Credit memo updated-at timestamp. */ public function getUpdatedAt(); @@ -916,36 +916,36 @@ interface CreditmemoInterface extends \Magento\Framework\Api\ExtensibleDataInter public function setUpdatedAt($timestamp); /** - * Sets the credit memo hidden tax amount. + * Sets the credit memo discount tax compensation amount. * * @param float $amount * @return $this */ - public function setHiddenTaxAmount($amount); + public function setDiscountTaxCompensationAmount($amount); /** - * Sets the credit memo base hidden tax amount. + * Sets the credit memo base discount tax compensation amount. * * @param float $amount * @return $this */ - public function setBaseHiddenTaxAmount($amount); + public function setBaseDiscountTaxCompensationAmount($amount); /** - * Sets the credit memo shipping hidden tax amount. + * Sets the credit memo shipping discount tax compensation amount. * * @param float $amount * @return $this */ - public function setShippingHiddenTaxAmount($amount); + public function setShippingDiscountTaxCompensationAmount($amount); /** - * Sets the credit memo base shipping hidden tax amount. + * Sets the credit memo base shipping discount tax compensation amount. * * @param float $amnt * @return $this */ - public function setBaseShippingHiddenTaxAmnt($amnt); + public function setBaseShippingDiscountTaxCompensationAmnt($amnt); /** * Sets the credit memo shipping including tax. diff --git a/app/code/Magento/Sales/Api/Data/CreditmemoItemInterface.php b/app/code/Magento/Sales/Api/Data/CreditmemoItemInterface.php index ff7e1b5f35500f47129d84cd230fd1f19b4cbe1e..7950fa77a140e46913511847f00894db4bdb0da7 100644 --- a/app/code/Magento/Sales/Api/Data/CreditmemoItemInterface.php +++ b/app/code/Magento/Sales/Api/Data/CreditmemoItemInterface.php @@ -108,13 +108,13 @@ interface CreditmemoItemInterface extends \Magento\Framework\Api\ExtensibleDataI */ const NAME = 'name'; /* - * Hidden tax amount. + * Discount tax compensation amount. */ - const HIDDEN_TAX_AMOUNT = 'hidden_tax_amount'; + const DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount'; /* - * Base hidden tax amount. + * Base discount tax compensation amount. */ - const BASE_HIDDEN_TAX_AMOUNT = 'base_hidden_tax_amount'; + const BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'base_discount_tax_compensation_amount'; /* * WEEE tax disposition. */ @@ -155,7 +155,7 @@ interface CreditmemoItemInterface extends \Magento\Framework\Api\ExtensibleDataI /** * Gets the additional data for a credit memo item. * - * @return string Additional data. + * @return string|null Additional data. */ public function getAdditionalData(); @@ -174,11 +174,11 @@ interface CreditmemoItemInterface extends \Magento\Framework\Api\ExtensibleDataI public function getBaseDiscountAmount(); /** - * Gets the base hidden tax amount for a credit memo item. + * Gets the base discount tax compensation amount for a credit memo item. * * @return float */ - public function getBaseHiddenTaxAmount(); + public function getBaseDiscountTaxCompensationAmount(); /** * Gets the base price for a credit memo item. @@ -190,70 +190,70 @@ interface CreditmemoItemInterface extends \Magento\Framework\Api\ExtensibleDataI /** * Gets the base price including tax for a credit memo item. * - * @return float Base price including tax. + * @return float|null Base price including tax. */ public function getBasePriceInclTax(); /** * Gets the base row total for a credit memo item. * - * @return float Base row total. + * @return float|null Base row total. */ public function getBaseRowTotal(); /** * Gets the base row total including tax for a credit memo item. * - * @return float Base row total including tax. + * @return float|null Base row total including tax. */ public function getBaseRowTotalInclTax(); /** * Gets the base tax amount for a credit memo item. * - * @return float Base tax amount. + * @return float|null Base tax amount. */ public function getBaseTaxAmount(); /** * Gets the base WEEE tax applied amount for a credit memo item. * - * @return float Base WEEE tax applied amount. + * @return float|null Base WEEE tax applied amount. */ public function getBaseWeeeTaxAppliedAmount(); /** * Gets the base WEEE tax applied row amount for a credit memo item. * - * @return float Base WEEE tax applied row amount. + * @return float|null Base WEEE tax applied row amount. */ public function getBaseWeeeTaxAppliedRowAmnt(); /** * Gets the base WEEE tax disposition for a credit memo item. * - * @return float Base WEEE tax disposition. + * @return float|null Base WEEE tax disposition. */ public function getBaseWeeeTaxDisposition(); /** * Gets the base WEEE tax row disposition for a credit memo item. * - * @return float Base WEEE tax row disposition. + * @return float|null Base WEEE tax row disposition. */ public function getBaseWeeeTaxRowDisposition(); /** * Gets the description for a credit memo item. * - * @return string Description. + * @return string|null Description. */ public function getDescription(); /** * Gets the discount amount for a credit memo item. * - * @return float Discount amount. + * @return float|null Discount amount. */ public function getDiscountAmount(); @@ -273,16 +273,16 @@ interface CreditmemoItemInterface extends \Magento\Framework\Api\ExtensibleDataI public function setEntityId($entityId); /** - * Gets the hidden tax amount for a credit memo item. + * Gets the discount tax compensation amount for a credit memo item. * - * @return float Hidden tax amount. + * @return float Discount tax compensation amount. */ - public function getHiddenTaxAmount(); + public function getDiscountTaxCompensationAmount(); /** * Gets the name for a credit memo item. * - * @return string Name. + * @return string|null Name. */ public function getName(); @@ -296,28 +296,28 @@ interface CreditmemoItemInterface extends \Magento\Framework\Api\ExtensibleDataI /** * Gets the parent ID for a credit memo item. * - * @return int Parent ID. + * @return int|null Parent ID. */ public function getParentId(); /** * Gets the price for a credit memo item. * - * @return float Price. + * @return float|null Price. */ public function getPrice(); /** * Gets the price including tax for a credit memo item. * - * @return float Price including tax. + * @return float|null Price including tax. */ public function getPriceInclTax(); /** * Gets the product ID for a credit memo item. * - * @return int Product ID. + * @return int|null Product ID. */ public function getProductId(); @@ -331,63 +331,63 @@ interface CreditmemoItemInterface extends \Magento\Framework\Api\ExtensibleDataI /** * Gets the row total for a credit memo item. * - * @return float Row total. + * @return float|null Row total. */ public function getRowTotal(); /** * Gets the row total including tax for a credit memo item. * - * @return float Row total including tax. + * @return float|null Row total including tax. */ public function getRowTotalInclTax(); /** * Gets the SKU for a credit memo item. * - * @return string SKU. + * @return string|null SKU. */ public function getSku(); /** * Gets the tax amount for a credit memo item. * - * @return float Tax amount. + * @return float|null Tax amount. */ public function getTaxAmount(); /** * Gets the WEEE tax applied for a credit memo item. * - * @return string WEEE tax applied. + * @return string|null WEEE tax applied. */ public function getWeeeTaxApplied(); /** * Gets the WEEE tax applied amount for a credit memo item. * - * @return float WEEE tax applied amount. + * @return float|null WEEE tax applied amount. */ public function getWeeeTaxAppliedAmount(); /** * Gets the WEEE tax applied row amount for a credit memo item. * - * @return float WEEE tax applied row amount. + * @return float|null WEEE tax applied row amount. */ public function getWeeeTaxAppliedRowAmount(); /** * Gets the WEEE tax disposition for a credit memo item. * - * @return float WEEE tax disposition. + * @return float|null WEEE tax disposition. */ public function getWeeeTaxDisposition(); /** * Gets the WEEE tax row disposition for a credit memo item. * - * @return float WEEE tax row disposition. + * @return float|null WEEE tax row disposition. */ public function getWeeeTaxRowDisposition(); @@ -560,20 +560,20 @@ interface CreditmemoItemInterface extends \Magento\Framework\Api\ExtensibleDataI public function setName($name); /** - * Sets the hidden tax amount for a credit memo item. + * Sets the discount tax compensation amount for a credit memo item. * * @param float $amount * @return $this */ - public function setHiddenTaxAmount($amount); + public function setDiscountTaxCompensationAmount($amount); /** - * Sets the base hidden tax amount for a credit memo item. + * Sets the base discount tax compensation amount for a credit memo item. * * @param float $amount * @return $this */ - public function setBaseHiddenTaxAmount($amount); + public function setBaseDiscountTaxCompensationAmount($amount); /** * Sets the WEEE tax disposition for a credit memo item. diff --git a/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php b/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php index 06dc4919b4bff3bea4a6c710dae44bd5acd6f7fd..120a52b45091b54a6a7241caacbf7ec7f261b88d 100644 --- a/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php +++ b/app/code/Magento/Sales/Api/Data/InvoiceCommentInterface.php @@ -52,7 +52,7 @@ interface InvoiceCommentInterface extends \Magento\Framework\Api\ExtensibleDataI /** * Gets the created-at timestamp for the invoice. * - * @return string Created-at timestamp. + * @return string|null Created-at timestamp. */ public function getCreatedAt(); @@ -67,7 +67,7 @@ interface InvoiceCommentInterface extends \Magento\Framework\Api\ExtensibleDataI /** * Gets the ID for the invoice. * - * @return int Invoice ID. + * @return int|null Invoice ID. */ public function getEntityId(); diff --git a/app/code/Magento/Sales/Api/Data/InvoiceInterface.php b/app/code/Magento/Sales/Api/Data/InvoiceInterface.php index c69386840857f7c13ae41ead0e47d73750bdb220..bdc69205d061d9cd8ab926871adec550fc4ee7a9 100644 --- a/app/code/Magento/Sales/Api/Data/InvoiceInterface.php +++ b/app/code/Magento/Sales/Api/Data/InvoiceInterface.php @@ -161,21 +161,21 @@ interface InvoiceInterface extends \Magento\Framework\Api\ExtensibleDataInterfac */ const UPDATED_AT = 'updated_at'; /* - * Hidden tax amount. + * Discount tax compensation amount. */ - const HIDDEN_TAX_AMOUNT = 'hidden_tax_amount'; + const DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount'; /* - * Base hidden tax amount. + * Base discount tax compensation amount. */ - const BASE_HIDDEN_TAX_AMOUNT = 'base_hidden_tax_amount'; + const BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'base_discount_tax_compensation_amount'; /* - * Shipping hidden tax amount. + * Shipping discount tax compensation amount. */ - const SHIPPING_HIDDEN_TAX_AMOUNT = 'shipping_hidden_tax_amount'; + const SHIPPING_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'shipping_discount_tax_compensation_amount'; /* - * Base shipping hidden tax amount. + * Base shipping discount tax compensation amount. */ - const BASE_SHIPPING_HIDDEN_TAX_AMNT = 'base_shipping_hidden_tax_amnt'; + const BASE_SHIPPING_DISCOUNT_TAX_COMPENSATION_AMNT = 'base_shipping_discount_tax_compensation_amnt'; /* * Shipping including tax. */ @@ -204,119 +204,119 @@ interface InvoiceInterface extends \Magento\Framework\Api\ExtensibleDataInterfac /** * Gets the base currency code for the invoice. * - * @return string Base currency code. + * @return string|null Base currency code. */ public function getBaseCurrencyCode(); /** * Gets the base discount amount for the invoice. * - * @return float Base discount amount. + * @return float|null Base discount amount. */ public function getBaseDiscountAmount(); /** * Gets the base grand total for the invoice. * - * @return float Base grand total. + * @return float|null Base grand total. */ public function getBaseGrandTotal(); /** - * Gets the base hidden tax amount for the invoice. + * Gets the base discount tax compensation amount for the invoice. * - * @return float Base hidden tax amount. + * @return float Base discount tax compensation amount. */ - public function getBaseHiddenTaxAmount(); + public function getBaseDiscountTaxCompensationAmount(); /** * Gets the base shipping amount for the invoice. * - * @return float Base shipping amount. + * @return float|null Base shipping amount. */ public function getBaseShippingAmount(); /** - * Gets the base shipping hidden tax amount for the invoice. + * Gets the base shipping discount tax compensation amount for the invoice. * - * @return float Base shipping hidden tax amount. + * @return float Base shipping discount tax compensation amount. */ - public function getBaseShippingHiddenTaxAmnt(); + public function getBaseShippingDiscountTaxCompensationAmnt(); /** * Gets the base shipping including tax for the invoice. * - * @return float Base shipping including tax. + * @return float|null Base shipping including tax. */ public function getBaseShippingInclTax(); /** * Gets the base shipping tax amount for the invoice. * - * @return float Base shipping tax amount. + * @return float|null Base shipping tax amount. */ public function getBaseShippingTaxAmount(); /** * Gets the base subtotal for the invoice. * - * @return float Base subtotal. + * @return float|null Base subtotal. */ public function getBaseSubtotal(); /** * Gets the base subtotal including tax for the invoice. * - * @return float Base subtotal including tax. + * @return float|null Base subtotal including tax. */ public function getBaseSubtotalInclTax(); /** * Gets the base tax amount for the invoice. * - * @return float Base tax amount. + * @return float|null Base tax amount. */ public function getBaseTaxAmount(); /** * Gets the base total refunded for the invoice. * - * @return float Base total refunded. + * @return float|null Base total refunded. */ public function getBaseTotalRefunded(); /** * Gets the base-to-global rate for the invoice. * - * @return float Base-to-global rate. + * @return float|null Base-to-global rate. */ public function getBaseToGlobalRate(); /** * Gets the base-to-order rate for the invoice. * - * @return float Base-to-order rate. + * @return float|null Base-to-order rate. */ public function getBaseToOrderRate(); /** * Gets the billing address ID for the invoice. * - * @return int Billing address ID. + * @return int|null Billing address ID. */ public function getBillingAddressId(); /** * Gets the can void flag value for the invoice. * - * @return int Can void flag value. + * @return int|null Can void flag value. */ public function getCanVoidFlag(); /** * Gets the created-at timestamp for the invoice. * - * @return string Created-at timestamp. + * @return string|null Created-at timestamp. */ public function getCreatedAt(); @@ -331,28 +331,28 @@ interface InvoiceInterface extends \Magento\Framework\Api\ExtensibleDataInterfac /** * Gets the discount amount for the invoice. * - * @return float Discount amount. + * @return float|null Discount amount. */ public function getDiscountAmount(); /** * Gets the discount description for the invoice. * - * @return string Discount description. + * @return string|null Discount description. */ public function getDiscountDescription(); /** * Gets the email-sent flag value for the invoice. * - * @return int Email-sent flag value. + * @return int|null Email-sent flag value. */ public function getEmailSent(); /** * Gets the ID for the invoice. * - * @return int Invoice ID. + * @return int|null Invoice ID. */ public function getEntityId(); @@ -367,42 +367,42 @@ interface InvoiceInterface extends \Magento\Framework\Api\ExtensibleDataInterfac /** * Gets the global currency code for the invoice. * - * @return string Global currency code. + * @return string|null Global currency code. */ public function getGlobalCurrencyCode(); /** * Gets the grand total for the invoice. * - * @return float Grand total. + * @return float|null Grand total. */ public function getGrandTotal(); /** - * Gets the hidden tax amount for the invoice. + * Gets the discount tax compensation amount for the invoice. * - * @return float Hidden tax amount. + * @return float Discount tax compensation amount. */ - public function getHiddenTaxAmount(); + public function getDiscountTaxCompensationAmount(); /** * Gets the increment ID for the invoice. * - * @return string Increment ID. + * @return string|null Increment ID. */ public function getIncrementId(); /** * Gets the is-used-for-refund flag value for the invoice. * - * @return int Is-used-for-refund flag value. + * @return int|null Is-used-for-refund flag value. */ public function getIsUsedForRefund(); /** * Gets the order currency code for the invoice. * - * @return string Order currency code. + * @return string|null Order currency code. */ public function getOrderCurrencyCode(); @@ -416,91 +416,91 @@ interface InvoiceInterface extends \Magento\Framework\Api\ExtensibleDataInterfac /** * Gets the shipping address ID for the invoice. * - * @return int Shipping address ID. + * @return int|null Shipping address ID. */ public function getShippingAddressId(); /** * Gets the shipping amount for the invoice. * - * @return float Shipping amount. + * @return float|null Shipping amount. */ public function getShippingAmount(); /** - * Gets the shipping hidden tax amount for the invoice. + * Gets the shipping discount tax compensation amount for the invoice. * - * @return float Shipping hidden tax amount. + * @return float Shipping discount tax compensation amount. */ - public function getShippingHiddenTaxAmount(); + public function getShippingDiscountTaxCompensationAmount(); /** * Gets the shipping including tax for the invoice. * - * @return float Shipping including tax. + * @return float|null Shipping including tax. */ public function getShippingInclTax(); /** * Gets the shipping tax amount for the invoice. * - * @return float Shipping tax amount. + * @return float|null Shipping tax amount. */ public function getShippingTaxAmount(); /** * Gets the state for the invoice. * - * @return int State. + * @return int|null State. */ public function getState(); /** * Gets the store currency code for the invoice. * - * @return string Store currency code. + * @return string|null Store currency code. */ public function getStoreCurrencyCode(); /** * Gets the store ID for the invoice. * - * @return int Store ID. + * @return int|null Store ID. */ public function getStoreId(); /** * Gets the store-to-base rate for the invoice. * - * @return float Store-to-base rate. + * @return float|null Store-to-base rate. */ public function getStoreToBaseRate(); /** * Gets the store-to-order rate for the invoice. * - * @return float Store-to-order rate. + * @return float|null Store-to-order rate. */ public function getStoreToOrderRate(); /** * Gets the subtotal for the invoice. * - * @return float Subtotal. + * @return float|null Subtotal. */ public function getSubtotal(); /** * Gets the subtotal including tax for the invoice. * - * @return float Subtotal including tax. + * @return float|null Subtotal including tax. */ public function getSubtotalInclTax(); /** * Gets the tax amount for the invoice. * - * @return float Tax amount. + * @return float|null Tax amount. */ public function getTaxAmount(); @@ -514,7 +514,7 @@ interface InvoiceInterface extends \Magento\Framework\Api\ExtensibleDataInterfac /** * Gets the transaction ID for the invoice. * - * @return string Transaction ID. + * @return string|null Transaction ID. */ public function getTransactionId(); @@ -529,7 +529,7 @@ interface InvoiceInterface extends \Magento\Framework\Api\ExtensibleDataInterfac /** * Gets the updated-at timestamp for the invoice. * - * @return string Updated-at timestamp. + * @return string|null Updated-at timestamp. */ public function getUpdatedAt(); @@ -828,36 +828,36 @@ interface InvoiceInterface extends \Magento\Framework\Api\ExtensibleDataInterfac public function setIncrementId($id); /** - * Sets the hidden tax amount for the invoice. + * Sets the discount tax compensation amount for the invoice. * * @param float $amount * @return $this */ - public function setHiddenTaxAmount($amount); + public function setDiscountTaxCompensationAmount($amount); /** - * Sets the base hidden tax amount for the invoice. + * Sets the base discount tax compensation amount for the invoice. * * @param float $amount * @return $this */ - public function setBaseHiddenTaxAmount($amount); + public function setBaseDiscountTaxCompensationAmount($amount); /** - * Sets the shipping hidden tax amount for the invoice. + * Sets the shipping discount tax compensation amount for the invoice. * * @param float $amount * @return $this */ - public function setShippingHiddenTaxAmount($amount); + public function setShippingDiscountTaxCompensationAmount($amount); /** - * Sets the base shipping hidden tax amount for the invoice. + * Sets the base shipping discount tax compensation amount for the invoice. * * @param float $amnt * @return $this */ - public function setBaseShippingHiddenTaxAmnt($amnt); + public function setBaseShippingDiscountTaxCompensationAmnt($amnt); /** * Sets the shipping including tax for the invoice. diff --git a/app/code/Magento/Sales/Api/Data/InvoiceItemInterface.php b/app/code/Magento/Sales/Api/Data/InvoiceItemInterface.php index 013f8d143bd2220fe72db0a175adb04970c69bac..565a6da1641c1669bd117ea7a88686488e387c2b 100644 --- a/app/code/Magento/Sales/Api/Data/InvoiceItemInterface.php +++ b/app/code/Magento/Sales/Api/Data/InvoiceItemInterface.php @@ -105,99 +105,98 @@ interface InvoiceItemInterface extends \Magento\Framework\Api\ExtensibleDataInte */ const NAME = 'name'; /* - * Hidden tax amount. + * Discount tax compensation amount. */ - const HIDDEN_TAX_AMOUNT = 'hidden_tax_amount'; + const DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount'; /* - * Base hidden tax amount. + * Base discount tax compensation amount. */ - const BASE_HIDDEN_TAX_AMOUNT = 'base_hidden_tax_amount'; + const BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'base_discount_tax_compensation_amount'; /** * Invoice */ const INVOICE = 'invoice'; - /** * Gets the additional data for the invoice item. * - * @return string Additional data. + * @return string|null Additional data. */ public function getAdditionalData(); /** * Gets the base cost for the invoice item. * - * @return float Base cost. + * @return float|null Base cost. */ public function getBaseCost(); /** * Gets the base discount amount for the invoice item. * - * @return float Base discount amount. + * @return float|null Base discount amount. */ public function getBaseDiscountAmount(); /** - * Gets the base hidden tax amount for the invoice item. + * Gets the base discount tax compensation amount for the invoice item. * - * @return float Base hidden tax amount. + * @return float Base discount tax compensation amount. */ - public function getBaseHiddenTaxAmount(); + public function getBaseDiscountTaxCompensationAmount(); /** * Gets the base price for the invoice item. * - * @return float Base price. + * @return float|null Base price. */ public function getBasePrice(); /** * Gets the base price including tax for the invoice item. * - * @return float Base price including tax. + * @return float|null Base price including tax. */ public function getBasePriceInclTax(); /** * Gets the base row total for the invoice item. * - * @return float Base row total. + * @return float|null Base row total. */ public function getBaseRowTotal(); /** * Gets the base row total including tax for the invoice item. * - * @return float Base row total including tax. + * @return float|null Base row total including tax. */ public function getBaseRowTotalInclTax(); /** * Gets the base tax amount for the invoice item. * - * @return float Base tax amount. + * @return float|null Base tax amount. */ public function getBaseTaxAmount(); /** * Gets the description for the invoice item. * - * @return string Description. + * @return string|null Description. */ public function getDescription(); /** * Gets the discount amount for the invoice item. * - * @return float Discount amount. + * @return float|null Discount amount. */ public function getDiscountAmount(); /** * Gets the ID for the invoice item. * - * @return int Invoice item ID. + * @return int|null Invoice item ID. */ public function getEntityId(); @@ -210,16 +209,16 @@ interface InvoiceItemInterface extends \Magento\Framework\Api\ExtensibleDataInte public function setEntityId($entityId); /** - * Gets the hidden tax amount for the invoice item. + * Gets the discount tax compensation amount for the invoice item. * - * @return float Hidden tax amount. + * @return float Discount tax compensation amount. */ - public function getHiddenTaxAmount(); + public function getDiscountTaxCompensationAmount(); /** * Gets the name for the invoice item. * - * @return string Name. + * @return string|null Name. */ public function getName(); @@ -233,28 +232,28 @@ interface InvoiceItemInterface extends \Magento\Framework\Api\ExtensibleDataInte /** * Gets the parent ID for the invoice item. * - * @return int Parent ID. + * @return int|null Parent ID. */ public function getParentId(); /** * Gets the price for the invoice item. * - * @return float Price. + * @return float|null Price. */ public function getPrice(); /** * Gets the price including tax for the invoice item. * - * @return float Price including tax. + * @return float|null Price including tax. */ public function getPriceInclTax(); /** * Gets the product ID for the invoice item. * - * @return int Product ID. + * @return int|null Product ID. */ public function getProductId(); @@ -268,14 +267,14 @@ interface InvoiceItemInterface extends \Magento\Framework\Api\ExtensibleDataInte /** * Gets the row total for the invoice item. * - * @return float Row total. + * @return float|null Row total. */ public function getRowTotal(); /** * Gets the row total including tax for the invoice item. * - * @return float Row total including tax. + * @return float|null Row total including tax. */ public function getRowTotalInclTax(); @@ -289,7 +288,7 @@ interface InvoiceItemInterface extends \Magento\Framework\Api\ExtensibleDataInte /** * Gets the tax amount for the invoice item. * - * @return float Tax amount. + * @return float|null Tax amount. */ public function getTaxAmount(); @@ -462,20 +461,20 @@ interface InvoiceItemInterface extends \Magento\Framework\Api\ExtensibleDataInte public function setName($name); /** - * Sets the hidden tax amount for the invoice item. + * Sets the discount tax compensation amount for the invoice item. * * @param float $amount * @return $this */ - public function setHiddenTaxAmount($amount); + public function setDiscountTaxCompensationAmount($amount); /** - * Sets the base hidden tax amount for the invoice item. + * Sets the base discount tax compensation amount for the invoice item. * * @param float $amount * @return $this */ - public function setBaseHiddenTaxAmount($amount); + public function setBaseDiscountTaxCompensationAmount($amount); /** * Retrieve existing extension attributes object or create a new one. diff --git a/app/code/Magento/Sales/Api/Data/OrderAddressInterface.php b/app/code/Magento/Sales/Api/Data/OrderAddressInterface.php index d7b863b782f2bc4af5db2466e659273bdc724af8..dfd663234daec616b0e77161aed4f89ae858bd5f 100644 --- a/app/code/Magento/Sales/Api/Data/OrderAddressInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderAddressInterface.php @@ -137,7 +137,7 @@ interface OrderAddressInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the company for the order address. * - * @return string Company. + * @return string|null Company. */ public function getCompany(); @@ -151,28 +151,28 @@ interface OrderAddressInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the country address ID for the order address. * - * @return int Country address ID. + * @return int|null Country address ID. */ public function getCustomerAddressId(); /** * Gets the customer ID for the order address. * - * @return int Customer ID. + * @return int|null Customer ID. */ public function getCustomerId(); /** * Gets the email address for the order address. * - * @return string Email address. + * @return string|null Email address. */ public function getEmail(); /** * Gets the ID for the order address. * - * @return int Order address ID. + * @return int|null Order address ID. */ public function getEntityId(); @@ -187,7 +187,7 @@ interface OrderAddressInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the fax number for the order address. * - * @return string Fax number. + * @return string|null Fax number. */ public function getFax(); @@ -208,14 +208,14 @@ interface OrderAddressInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the middle name for the order address. * - * @return string Middle name. + * @return string|null Middle name. */ public function getMiddlename(); /** * Gets the parent ID for the order address. * - * @return int Parent ID. + * @return int|null Parent ID. */ public function getParentId(); @@ -229,28 +229,28 @@ interface OrderAddressInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the prefix for the order address. * - * @return string Prefix. + * @return string|null Prefix. */ public function getPrefix(); /** * Gets the quote address ID for the order address. * - * @return int Quote address ID. + * @return int|null Quote address ID. */ public function getQuoteAddressId(); /** * Gets the region for the order address. * - * @return string Region. + * @return string|null Region. */ public function getRegion(); /** * Gets the region ID for the order address. * - * @return int Region ID. + * @return int|null Region ID. */ public function getRegionId(); @@ -264,7 +264,7 @@ interface OrderAddressInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the suffix for the order address. * - * @return string Suffix. + * @return string|null Suffix. */ public function getSuffix(); @@ -278,35 +278,35 @@ interface OrderAddressInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the VAT ID for the order address. * - * @return string VAT ID. + * @return string|null VAT ID. */ public function getVatId(); /** * Gets the VAT-is-valid flag value for the order address. * - * @return int VAT-is-valid flag value. + * @return int|null VAT-is-valid flag value. */ public function getVatIsValid(); /** * Gets the VAT request date for the order address. * - * @return string VAT request date. + * @return string|null VAT request date. */ public function getVatRequestDate(); /** * Gets the VAT request ID for the order address. * - * @return string VAT request ID. + * @return string|null VAT request ID. */ public function getVatRequestId(); /** * Gets the VAT-request-success flag value for the order address. * - * @return int VAT-request-success flag value. + * @return int|null VAT-request-success flag value. */ public function getVatRequestSuccess(); diff --git a/app/code/Magento/Sales/Api/Data/OrderInterface.php b/app/code/Magento/Sales/Api/Data/OrderInterface.php index 37ca125b00de84a34dbfa563072e2518dad4bc54..a4376b9eb81a74af2698b0c7eeebb0457b790a03 100644 --- a/app/code/Magento/Sales/Api/Data/OrderInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderInterface.php @@ -515,37 +515,37 @@ interface OrderInterface extends \Magento\Framework\Api\ExtensibleDataInterface */ const CUSTOMER_GENDER = 'customer_gender'; /* - * Hidden tax amount. + * Discount tax compensation amount. */ - const HIDDEN_TAX_AMOUNT = 'hidden_tax_amount'; + const DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount'; /* - * Base hidden tax amount. + * Base discount tax compensation amount. */ - const BASE_HIDDEN_TAX_AMOUNT = 'base_hidden_tax_amount'; + const BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'base_discount_tax_compensation_amount'; /* - * Shipping hidden tax amount. + * Shipping discount tax compensation amount. */ - const SHIPPING_HIDDEN_TAX_AMOUNT = 'shipping_hidden_tax_amount'; + const SHIPPING_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'shipping_discount_tax_compensation_amount'; /* - * Base shipping hidden tax amount. + * Base shipping discount tax compensation amount. */ - const BASE_SHIPPING_HIDDEN_TAX_AMNT = 'base_shipping_hidden_tax_amnt'; + const BASE_SHIPPING_DISCOUNT_TAX_COMPENSATION_AMNT = 'base_shipping_discount_tax_compensation_amnt'; /* - * Hidden tax invoiced. + * Discount tax compensation invoiced. */ - const HIDDEN_TAX_INVOICED = 'hidden_tax_invoiced'; + const DISCOUNT_TAX_COMPENSATION_INVOICED = 'discount_tax_compensation_invoiced'; /* - * Base hidden tax invoiced. + * Base discount tax compensation invoiced. */ - const BASE_HIDDEN_TAX_INVOICED = 'base_hidden_tax_invoiced'; + const BASE_DISCOUNT_TAX_COMPENSATION_INVOICED = 'base_discount_tax_compensation_invoiced'; /* - * Hidden tax refunded. + * Discount tax compensation refunded. */ - const HIDDEN_TAX_REFUNDED = 'hidden_tax_refunded'; + const DISCOUNT_TAX_COMPENSATION_REFUNDED = 'discount_tax_compensation_refunded'; /* - * Base hidden tax refunded. + * Base discount tax compensation refunded. */ - const BASE_HIDDEN_TAX_REFUNDED = 'base_hidden_tax_refunded'; + const BASE_DISCOUNT_TAX_COMPENSATION_REFUNDED = 'base_discount_tax_compensation_refunded'; /* * Shipping including tax. */ @@ -582,70 +582,70 @@ interface OrderInterface extends \Magento\Framework\Api\ExtensibleDataInterface /** * Gets the negative adjustment value for the order. * - * @return float Negative adjustment value. + * @return float|null Negative adjustment value. */ public function getAdjustmentNegative(); /** * Gets the positive adjustment value for the order. * - * @return float Positive adjustment value. + * @return float|null Positive adjustment value. */ public function getAdjustmentPositive(); /** * Gets the applied rule IDs for the order. * - * @return string Applied rule IDs. + * @return string|null Applied rule IDs. */ public function getAppliedRuleIds(); /** * Gets the base negative adjustment value for the order. * - * @return float Base negative adjustment value. + * @return float|null Base negative adjustment value. */ public function getBaseAdjustmentNegative(); /** * Gets the base positive adjustment value for the order. * - * @return float Base positive adjustment value. + * @return float|null Base positive adjustment value. */ public function getBaseAdjustmentPositive(); /** * Gets the base currency code for the order. * - * @return string Base currency code. + * @return string|null Base currency code. */ public function getBaseCurrencyCode(); /** * Gets the base discount amount for the order. * - * @return float Base discount amount. + * @return float|null Base discount amount. */ public function getBaseDiscountAmount(); /** * Gets the base discount canceled for the order. * - * @return float Base discount canceled. + * @return float|null Base discount canceled. */ public function getBaseDiscountCanceled(); /** * Gets the base discount invoiced amount for the order. * - * @return float Base discount invoiced. + * @return float|null Base discount invoiced. */ public function getBaseDiscountInvoiced(); /** * Gets the base discount refunded amount for the order. * - * @return float Base discount refunded. + * @return float|null Base discount refunded. */ public function getBaseDiscountRefunded(); @@ -657,261 +657,261 @@ interface OrderInterface extends \Magento\Framework\Api\ExtensibleDataInterface public function getBaseGrandTotal(); /** - * Gets the base hidden tax amount for the order. + * Gets the base discount tax compensation amount for the order. * - * @return float Base hidden tax amount. + * @return float Base discount tax compensation amount. */ - public function getBaseHiddenTaxAmount(); + public function getBaseDiscountTaxCompensationAmount(); /** - * Gets the base hidden tax invoiced amount for the order. + * Gets the base discount tax compensation invoiced amount for the order. * - * @return float Base hidden tax invoiced. + * @return float Base discount tax compensation invoiced. */ - public function getBaseHiddenTaxInvoiced(); + public function getBaseDiscountTaxCompensationInvoiced(); /** - * Gets the base hidden tax refunded amount for the order. + * Gets the base discount tax compensation refunded amount for the order. * - * @return float Base hidden tax refunded. + * @return float Base discount tax compensation refunded. */ - public function getBaseHiddenTaxRefunded(); + public function getBaseDiscountTaxCompensationRefunded(); /** * Gets the base shipping amount for the order. * - * @return float Base shipping amount. + * @return float|null Base shipping amount. */ public function getBaseShippingAmount(); /** * Gets the base shipping canceled for the order. * - * @return float Base shipping canceled. + * @return float|null Base shipping canceled. */ public function getBaseShippingCanceled(); /** * Gets the base shipping discount amount for the order. * - * @return float Base shipping discount amount. + * @return float|null Base shipping discount amount. */ public function getBaseShippingDiscountAmount(); /** - * Gets the base shipping hidden tax amount for the order. + * Gets the base shipping discount tax compensation amount for the order. * - * @return float Base shipping hidden tax amount. + * @return float Base shipping discount tax compensation amount. */ - public function getBaseShippingHiddenTaxAmnt(); + public function getBaseShippingDiscountTaxCompensationAmnt(); /** * Gets the base shipping including tax for the order. * - * @return float Base shipping including tax. + * @return float|null Base shipping including tax. */ public function getBaseShippingInclTax(); /** * Gets the base shipping invoiced amount for the order. * - * @return float Base shipping invoiced. + * @return float|null Base shipping invoiced. */ public function getBaseShippingInvoiced(); /** * Gets the base shipping refunded amount for the order. * - * @return float Base shipping refunded. + * @return float|null Base shipping refunded. */ public function getBaseShippingRefunded(); /** * Gets the base shipping tax amount for the order. * - * @return float Base shipping tax amount. + * @return float|null Base shipping tax amount. */ public function getBaseShippingTaxAmount(); /** * Gets the base shipping tax refunded amount for the order. * - * @return float Base shipping tax refunded. + * @return float|null Base shipping tax refunded. */ public function getBaseShippingTaxRefunded(); /** * Gets the base subtotal for the order. * - * @return float Base subtotal. + * @return float|null Base subtotal. */ public function getBaseSubtotal(); /** * Gets the base subtotal canceled for the order. * - * @return float Base subtotal canceled. + * @return float|null Base subtotal canceled. */ public function getBaseSubtotalCanceled(); /** * Gets the base subtotal including tax for the order. * - * @return float Base subtotal including tax. + * @return float|null Base subtotal including tax. */ public function getBaseSubtotalInclTax(); /** * Gets the base subtotal invoiced amount for the order. * - * @return float Base subtotal invoiced. + * @return float|null Base subtotal invoiced. */ public function getBaseSubtotalInvoiced(); /** * Gets the base subtotal refunded amount for the order. * - * @return float Base subtotal refunded. + * @return float|null Base subtotal refunded. */ public function getBaseSubtotalRefunded(); /** * Gets the base tax amount for the order. * - * @return float Base tax amount. + * @return float|null Base tax amount. */ public function getBaseTaxAmount(); /** * Gets the base tax canceled for the order. * - * @return float Base tax canceled. + * @return float|null Base tax canceled. */ public function getBaseTaxCanceled(); /** * Gets the base tax invoiced amount for the order. * - * @return float Base tax invoiced. + * @return float|null Base tax invoiced. */ public function getBaseTaxInvoiced(); /** * Gets the base tax refunded amount for the order. * - * @return float Base tax refunded. + * @return float|null Base tax refunded. */ public function getBaseTaxRefunded(); /** * Gets the base total canceled for the order. * - * @return float Base total canceled. + * @return float|null Base total canceled. */ public function getBaseTotalCanceled(); /** * Gets the base total due for the order. * - * @return float Base total due. + * @return float|null Base total due. */ public function getBaseTotalDue(); /** * Gets the base total invoiced amount for the order. * - * @return float Base total invoiced. + * @return float|null Base total invoiced. */ public function getBaseTotalInvoiced(); /** * Gets the base total invoiced cost for the order. * - * @return float Base total invoiced cost. + * @return float|null Base total invoiced cost. */ public function getBaseTotalInvoicedCost(); /** * Gets the base total offline refunded amount for the order. * - * @return float Base total offline refunded. + * @return float|null Base total offline refunded. */ public function getBaseTotalOfflineRefunded(); /** * Gets the base total online refunded amount for the order. * - * @return float Base total online refunded. + * @return float|null Base total online refunded. */ public function getBaseTotalOnlineRefunded(); /** * Gets the base total paid for the order. * - * @return float Base total paid. + * @return float|null Base total paid. */ public function getBaseTotalPaid(); /** * Gets the base total quantity ordered for the order. * - * @return float Base total quantity ordered. + * @return float|null Base total quantity ordered. */ public function getBaseTotalQtyOrdered(); /** * Gets the base total refunded amount for the order. * - * @return float Base total refunded. + * @return float|null Base total refunded. */ public function getBaseTotalRefunded(); /** * Gets the base-to-global rate for the order. * - * @return float Base-to-global rate. + * @return float|null Base-to-global rate. */ public function getBaseToGlobalRate(); /** * Gets the base-to-order rate for the order. * - * @return float Base-to-order rate. + * @return float|null Base-to-order rate. */ public function getBaseToOrderRate(); /** * Gets the billing address ID for the order. * - * @return int Billing address ID. + * @return int|null Billing address ID. */ public function getBillingAddressId(); /** * Gets the can-ship-partially flag value for the order. * - * @return int Can-ship-partially flag value. + * @return int|null Can-ship-partially flag value. */ public function getCanShipPartially(); /** * Gets the can-ship-partially-item flag value for the order. * - * @return int Can-ship-partially-item flag value. + * @return int|null Can-ship-partially-item flag value. */ public function getCanShipPartiallyItem(); /** * Gets the coupon code for the order. * - * @return string Coupon code. + * @return string|null Coupon code. */ public function getCouponCode(); /** * Gets the created-at timestamp for the order. * - * @return string Created-at timestamp. + * @return string|null Created-at timestamp. */ public function getCreatedAt(); @@ -926,7 +926,7 @@ interface OrderInterface extends \Magento\Framework\Api\ExtensibleDataInterface /** * Gets the customer date-of-birth (DOB) for the order. * - * @return string Customer date-of-birth (DOB). + * @return string|null Customer date-of-birth (DOB). */ public function getCustomerDob(); @@ -940,140 +940,140 @@ interface OrderInterface extends \Magento\Framework\Api\ExtensibleDataInterface /** * Gets the customer first name for the order. * - * @return string Customer first name. + * @return string|null Customer first name. */ public function getCustomerFirstname(); /** * Gets the customer gender for the order. * - * @return int Customer gender. + * @return int|null Customer gender. */ public function getCustomerGender(); /** * Gets the customer group ID for the order. * - * @return int Customer group ID. + * @return int|null Customer group ID. */ public function getCustomerGroupId(); /** * Gets the customer ID for the order. * - * @return int Customer ID. + * @return int|null Customer ID. */ public function getCustomerId(); /** * Gets the customer-is-guest flag value for the order. * - * @return int Customer-is-guest flag value. + * @return int|null Customer-is-guest flag value. */ public function getCustomerIsGuest(); /** * Gets the customer last name for the order. * - * @return string Customer last name. + * @return string|null Customer last name. */ public function getCustomerLastname(); /** * Gets the customer middle name for the order. * - * @return string Customer middle name. + * @return string|null Customer middle name. */ public function getCustomerMiddlename(); /** * Gets the customer note for the order. * - * @return string Customer note. + * @return string|null Customer note. */ public function getCustomerNote(); /** * Gets the customer-note-notify flag value for the order. * - * @return int Customer-note-notify flag value. + * @return int|null Customer-note-notify flag value. */ public function getCustomerNoteNotify(); /** * Gets the customer prefix for the order. * - * @return string Customer prefix. + * @return string|null Customer prefix. */ public function getCustomerPrefix(); /** * Gets the customer suffix for the order. * - * @return string Customer suffix. + * @return string|null Customer suffix. */ public function getCustomerSuffix(); /** * Gets the customer value-added tax (VAT) for the order. * - * @return string Customer value-added tax (VAT). + * @return string|null Customer value-added tax (VAT). */ public function getCustomerTaxvat(); /** * Gets the discount amount for the order. * - * @return float Discount amount. + * @return float|null Discount amount. */ public function getDiscountAmount(); /** * Gets the discount canceled for the order. * - * @return float Discount canceled. + * @return float|null Discount canceled. */ public function getDiscountCanceled(); /** * Gets the discount description for the order. * - * @return string Discount description. + * @return string|null Discount description. */ public function getDiscountDescription(); /** * Gets the discount invoiced amount for the order. * - * @return float Discount invoiced. + * @return float|null Discount invoiced. */ public function getDiscountInvoiced(); /** * Gets the discount refunded amount for the order. * - * @return float Discount refunded amount. + * @return float|null Discount refunded amount. */ public function getDiscountRefunded(); /** * Gets the edit increment value for the order. * - * @return int Edit increment value. + * @return int|null Edit increment value. */ public function getEditIncrement(); /** * Gets the email-sent flag value for the order. * - * @return int Email-sent flag value. + * @return int|null Email-sent flag value. */ public function getEmailSent(); /** * Gets the ID for the order. * - * @return int Order ID. + * @return int|null Order ID. */ public function getEntityId(); @@ -1088,28 +1088,28 @@ interface OrderInterface extends \Magento\Framework\Api\ExtensibleDataInterface /** * Gets the external customer ID for the order. * - * @return string External customer ID. + * @return string|null External customer ID. */ public function getExtCustomerId(); /** * Gets the external order ID for the order. * - * @return string External order ID. + * @return string|null External order ID. */ public function getExtOrderId(); /** * Gets the forced-shipment-with-invoice flag value for the order. * - * @return int Forced-shipment-with-invoice flag value. + * @return int|null Forced-shipment-with-invoice flag value. */ public function getForcedShipmentWithInvoice(); /** * Gets the global currency code for the order. * - * @return string Global currency code. + * @return string|null Global currency code. */ public function getGlobalCurrencyCode(); @@ -1121,418 +1121,418 @@ interface OrderInterface extends \Magento\Framework\Api\ExtensibleDataInterface public function getGrandTotal(); /** - * Gets the hidden tax amount for the order. + * Gets the discount tax compensation amount for the order. * - * @return float Hidden tax amount. + * @return float Discount tax compensation amount. */ - public function getHiddenTaxAmount(); + public function getDiscountTaxCompensationAmount(); /** - * Gets the hidden tax invoiced amount for the order. + * Gets the discount tax compensation invoiced amount for the order. * - * @return float Hidden tax invoiced amount. + * @return float Discount tax compensation invoiced amount. */ - public function getHiddenTaxInvoiced(); + public function getDiscountTaxCompensationInvoiced(); /** - * Gets the hidden tax refunded amount for the order. + * Gets the discount tax compensation refunded amount for the order. * - * @return float Hidden tax refunded amount. + * @return float Discount tax compensation refunded amount. */ - public function getHiddenTaxRefunded(); + public function getDiscountTaxCompensationRefunded(); /** * Gets the hold before state for the order. * - * @return string Hold before state. + * @return string|null Hold before state. */ public function getHoldBeforeState(); /** * Gets the hold before status for the order. * - * @return string Hold before status. + * @return string|null Hold before status. */ public function getHoldBeforeStatus(); /** * Gets the increment ID for the order. * - * @return string Increment ID. + * @return string|null Increment ID. */ public function getIncrementId(); /** * Gets the is-virtual flag value for the order. * - * @return int Is-virtual flag value. + * @return int|null Is-virtual flag value. */ public function getIsVirtual(); /** * Gets the order currency code for the order. * - * @return string Order currency code. + * @return string|null Order currency code. */ public function getOrderCurrencyCode(); /** * Gets the original increment ID for the order. * - * @return string Original increment ID. + * @return string|null Original increment ID. */ public function getOriginalIncrementId(); /** * Gets the payment authorization amount for the order. * - * @return float Payment authorization amount. + * @return float|null Payment authorization amount. */ public function getPaymentAuthorizationAmount(); /** * Gets the payment authorization expiration date for the order. * - * @return int Payment authorization expiration date. + * @return int|null Payment authorization expiration date. */ public function getPaymentAuthExpiration(); /** * Gets the protect code for the order. * - * @return string Protect code. + * @return string|null Protect code. */ public function getProtectCode(); /** * Gets the quote address ID for the order. * - * @return int Quote address ID. + * @return int|null Quote address ID. */ public function getQuoteAddressId(); /** * Gets the quote ID for the order. * - * @return int Quote ID. + * @return int|null Quote ID. */ public function getQuoteId(); /** * Gets the relation child ID for the order. * - * @return string Relation child ID. + * @return string|null Relation child ID. */ public function getRelationChildId(); /** * Gets the relation child real ID for the order. * - * @return string Relation child real ID. + * @return string|null Relation child real ID. */ public function getRelationChildRealId(); /** * Gets the relation parent ID for the order. * - * @return string Relation parent ID. + * @return string|null Relation parent ID. */ public function getRelationParentId(); /** * Gets the relation parent real ID for the order. * - * @return string Relation parent real ID. + * @return string|null Relation parent real ID. */ public function getRelationParentRealId(); /** * Gets the remote IP address for the order. * - * @return string Remote IP address. + * @return string|null Remote IP address. */ public function getRemoteIp(); /** * Gets the shipping address ID for the order. * - * @return int Shipping address ID. + * @return int|null Shipping address ID. */ public function getShippingAddressId(); /** * Gets the shipping amount for the order. * - * @return float Shipping amount. + * @return float|null Shipping amount. */ public function getShippingAmount(); /** * Gets the shipping canceled amount for the order. * - * @return float Shipping canceled amount. + * @return float|null Shipping canceled amount. */ public function getShippingCanceled(); /** * Gets the shipping description for the order. * - * @return string Shipping description. + * @return string|null Shipping description. */ public function getShippingDescription(); /** * Gets the shipping discount amount for the order. * - * @return float Shipping discount amount. + * @return float|null Shipping discount amount. */ public function getShippingDiscountAmount(); /** - * Gets the shipping hidden tax amount for the order. + * Gets the shipping discount tax compensation amount for the order. * - * @return float Shipping hidden tax amount. + * @return float Shipping discount tax compensation amount. */ - public function getShippingHiddenTaxAmount(); + public function getShippingDiscountTaxCompensationAmount(); /** * Gets the shipping including tax amount for the order. * - * @return float Shipping including tax amount. + * @return float|null Shipping including tax amount. */ public function getShippingInclTax(); /** * Gets the shipping invoiced amount for the order. * - * @return float Shipping invoiced amount. + * @return float|null Shipping invoiced amount. */ public function getShippingInvoiced(); /** * Gets the shipping method for the order. * - * @return string Shipping method. + * @return string|null Shipping method. */ public function getShippingMethod(); /** * Gets the shipping refunded amount for the order. * - * @return float Shipping refunded amount. + * @return float|null Shipping refunded amount. */ public function getShippingRefunded(); /** * Gets the shipping tax amount for the order. * - * @return float Shipping tax amount. + * @return float|null Shipping tax amount. */ public function getShippingTaxAmount(); /** * Gets the shipping tax refunded amount for the order. * - * @return float Shipping tax refunded amount. + * @return float|null Shipping tax refunded amount. */ public function getShippingTaxRefunded(); /** * Gets the state for the order. * - * @return string State. + * @return string|null State. */ public function getState(); /** * Gets the status for the order. * - * @return string Status. + * @return string|null Status. */ public function getStatus(); /** * Gets the store currency code for the order. * - * @return string Store currency code. + * @return string|null Store currency code. */ public function getStoreCurrencyCode(); /** * Gets the store ID for the order. * - * @return int Store ID. + * @return int|null Store ID. */ public function getStoreId(); /** * Gets the store name for the order. * - * @return string Store name. + * @return string|null Store name. */ public function getStoreName(); /** * Gets the store-to-base rate for the order. * - * @return float Store-to-base rate. + * @return float|null Store-to-base rate. */ public function getStoreToBaseRate(); /** * Gets the store-to-order rate for the order. * - * @return float Store-to-order rate. + * @return float|null Store-to-order rate. */ public function getStoreToOrderRate(); /** * Gets the subtotal for the order. * - * @return float Subtotal. + * @return float|null Subtotal. */ public function getSubtotal(); /** * Gets the subtotal canceled amount for the order. * - * @return float Subtotal canceled amount. + * @return float|null Subtotal canceled amount. */ public function getSubtotalCanceled(); /** * Gets the subtotal including tax amount for the order. * - * @return float Subtotal including tax amount. + * @return float|null Subtotal including tax amount. */ public function getSubtotalInclTax(); /** * Gets the subtotal invoiced amount for the order. * - * @return float Subtotal invoiced amount. + * @return float|null Subtotal invoiced amount. */ public function getSubtotalInvoiced(); /** * Gets the subtotal refunded amount for the order. * - * @return float Subtotal refunded amount. + * @return float|null Subtotal refunded amount. */ public function getSubtotalRefunded(); /** * Gets the tax amount for the order. * - * @return float Tax amount. + * @return float|null Tax amount. */ public function getTaxAmount(); /** * Gets the tax canceled amount for the order. * - * @return float Tax canceled amount. + * @return float|null Tax canceled amount. */ public function getTaxCanceled(); /** * Gets the tax invoiced amount for the order. * - * @return float Tax invoiced amount. + * @return float|null Tax invoiced amount. */ public function getTaxInvoiced(); /** * Gets the tax refunded amount for the order. * - * @return float Tax refunded amount. + * @return float|null Tax refunded amount. */ public function getTaxRefunded(); /** * Gets the total canceled for the order. * - * @return float Total canceled. + * @return float|null Total canceled. */ public function getTotalCanceled(); /** * Gets the total due for the order. * - * @return float Total due. + * @return float|null Total due. */ public function getTotalDue(); /** * Gets the total invoiced amount for the order. * - * @return float Total invoiced amount. + * @return float|null Total invoiced amount. */ public function getTotalInvoiced(); /** * Gets the total item count for the order. * - * @return int Total item count. + * @return int|null Total item count. */ public function getTotalItemCount(); /** * Gets the total offline refunded amount for the order. * - * @return float Total offline refunded amount. + * @return float|null Total offline refunded amount. */ public function getTotalOfflineRefunded(); /** * Gets the total online refunded amount for the order. * - * @return float Total online refunded amount. + * @return float|null Total online refunded amount. */ public function getTotalOnlineRefunded(); /** * Gets the total paid for the order. * - * @return float Total paid. + * @return float|null Total paid. */ public function getTotalPaid(); /** * Gets the total quantity ordered for the order. * - * @return float Total quantity ordered. + * @return float|null Total quantity ordered. */ public function getTotalQtyOrdered(); /** * Gets the total amount refunded amount for the order. * - * @return float Total amount refunded. + * @return float|null Total amount refunded. */ public function getTotalRefunded(); /** * Gets the updated-at timestamp for the order. * - * @return string Updated-at timestamp. + * @return string|null Updated-at timestamp. */ public function getUpdatedAt(); /** * Gets the weight for the order. * - * @return float Weight. + * @return float|null Weight. */ public function getWeight(); /** * Gets the X-Forwarded-For HTTP header field for the order. - * - * This field identifies the originating IP address of a client + * + * This field identifies the originating IP address of a client * connecting to a web server through an HTTP proxy or load balancer. * - * @return string X-Forwarded-For field value. + * @return string|null X-Forwarded-For field value. */ public function getXForwardedFor(); @@ -1599,7 +1599,7 @@ interface OrderInterface extends \Magento\Framework\Api\ExtensibleDataInterface /** * Gets addresses for the order. * - * @return \Magento\Sales\Api\Data\OrderAddressInterface[] Array of addresses. + * @return \Magento\Sales\Api\Data\OrderAddressInterface[]|null Array of addresses. */ public function getAddresses(); @@ -1614,7 +1614,7 @@ interface OrderInterface extends \Magento\Framework\Api\ExtensibleDataInterface /** * Gets status histories for the order. * - * @return \Magento\Sales\Api\Data\OrderStatusHistoryInterface[] Array of status histories. + * @return \Magento\Sales\Api\Data\OrderStatusHistoryInterface[]|null Array of status histories. */ public function getStatusHistories(); @@ -2603,68 +2603,68 @@ interface OrderInterface extends \Magento\Framework\Api\ExtensibleDataInterface public function setCustomerGender($customerGender); /** - * Sets the hidden tax amount for the order. + * Sets the discount tax compensation amount for the order. * * @param float $amount * @return $this */ - public function setHiddenTaxAmount($amount); + public function setDiscountTaxCompensationAmount($amount); /** - * Sets the base hidden tax amount for the order. + * Sets the base discount tax compensation amount for the order. * * @param float $amount * @return $this */ - public function setBaseHiddenTaxAmount($amount); + public function setBaseDiscountTaxCompensationAmount($amount); /** - * Sets the shipping hidden tax amount for the order. + * Sets the shipping discount tax compensation amount for the order. * * @param float $amount * @return $this */ - public function setShippingHiddenTaxAmount($amount); + public function setShippingDiscountTaxCompensationAmount($amount); /** - * Sets the base shipping hidden tax amount for the order. + * Sets the base shipping discount tax compensation amount for the order. * * @param float $amnt * @return $this */ - public function setBaseShippingHiddenTaxAmnt($amnt); + public function setBaseShippingDiscountTaxCompensationAmnt($amnt); /** - * Sets the hidden tax invoiced amount for the order. + * Sets the discount tax compensation invoiced amount for the order. * - * @param float $hiddenTaxInvoiced + * @param float $discountTaxCompensationInvoiced * @return $this */ - public function setHiddenTaxInvoiced($hiddenTaxInvoiced); + public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoiced); /** - * Sets the base hidden tax invoiced amount for the order. + * Sets the base discount tax compensation invoiced amount for the order. * - * @param float $baseHiddenTaxInvoiced + * @param float $baseDiscountTaxCompensationInvoiced * @return $this */ - public function setBaseHiddenTaxInvoiced($baseHiddenTaxInvoiced); + public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensationInvoiced); /** - * Sets the hidden tax refunded amount for the order. + * Sets the discount tax compensation refunded amount for the order. * - * @param float $hiddenTaxRefunded + * @param float $discountTaxCompensationRefunded * @return $this */ - public function setHiddenTaxRefunded($hiddenTaxRefunded); + public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefunded); /** - * Sets the base hidden tax refunded amount for the order. + * Sets the base discount tax compensation refunded amount for the order. * - * @param float $baseHiddenTaxRefunded + * @param float $baseDiscountTaxCompensationRefunded * @return $this */ - public function setBaseHiddenTaxRefunded($baseHiddenTaxRefunded); + public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensationRefunded); /** * Sets the shipping including tax amount for the order. diff --git a/app/code/Magento/Sales/Api/Data/OrderItemInterface.php b/app/code/Magento/Sales/Api/Data/OrderItemInterface.php index 8dec85a858189e0231ac1bca2e095300b10ffea1..f049f0b8273d3ffb5c8136f18b89e3da8317198c 100644 --- a/app/code/Magento/Sales/Api/Data/OrderItemInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderItemInterface.php @@ -243,37 +243,37 @@ interface OrderItemInterface extends \Magento\Framework\Api\ExtensibleDataInterf */ const BASE_ROW_TOTAL_INCL_TAX = 'base_row_total_incl_tax'; /* - * Hidden tax amount. + * Discount tax compensation amount. */ - const HIDDEN_TAX_AMOUNT = 'hidden_tax_amount'; + const DISCOUNT_TAX_COMPENSATION_AMOUNT = 'discount_tax_compensation_amount'; /* - * Base hidden tax amount. + * Base discount tax compensation amount. */ - const BASE_HIDDEN_TAX_AMOUNT = 'base_hidden_tax_amount'; + const BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT = 'base_discount_tax_compensation_amount'; /* - * Hidden tax invoiced. + * Discount tax compensation invoiced. */ - const HIDDEN_TAX_INVOICED = 'hidden_tax_invoiced'; + const DISCOUNT_TAX_COMPENSATION_INVOICED = 'discount_tax_compensation_invoiced'; /* - * Base hidden tax invoiced. + * Base discount tax compensation invoiced. */ - const BASE_HIDDEN_TAX_INVOICED = 'base_hidden_tax_invoiced'; + const BASE_DISCOUNT_TAX_COMPENSATION_INVOICED = 'base_discount_tax_compensation_invoiced'; /* - * Hidden tax refunded. + * Discount tax compensation refunded. */ - const HIDDEN_TAX_REFUNDED = 'hidden_tax_refunded'; + const DISCOUNT_TAX_COMPENSATION_REFUNDED = 'discount_tax_compensation_refunded'; /* - * Base hidden tax refunded. + * Base discount tax compensation refunded. */ - const BASE_HIDDEN_TAX_REFUNDED = 'base_hidden_tax_refunded'; + const BASE_DISCOUNT_TAX_COMPENSATION_REFUNDED = 'base_discount_tax_compensation_refunded'; /* * Tax canceled flag */ const TAX_CANCELED = 'tax_canceled'; /* - * Hidden-tax-canceled flag. + * Discount-tax-compensation-canceled flag. */ - const HIDDEN_TAX_CANCELED = 'hidden_tax_canceled'; + const DISCOUNT_TAX_COMPENSATION_CANCELED = 'discount_tax_compensation_canceled'; /* * Tax refunded. */ @@ -400,182 +400,182 @@ interface OrderItemInterface extends \Magento\Framework\Api\ExtensibleDataInterf /** * Gets the additional data for the order item. * - * @return string Additional data. + * @return string|null Additional data. */ public function getAdditionalData(); /** * Gets the amount refunded for the order item. * - * @return float Amount refunded. + * @return float|null Amount refunded. */ public function getAmountRefunded(); /** * Gets the applied rule IDs for the order item. * - * @return string Applied rule IDs. + * @return string|null Applied rule IDs. */ public function getAppliedRuleIds(); /** * Gets the base amount refunded for the order item. * - * @return float Base amount refunded. + * @return float|null Base amount refunded. */ public function getBaseAmountRefunded(); /** * Gets the base cost for the order item. * - * @return float Base cost. + * @return float|null Base cost. */ public function getBaseCost(); /** * Gets the base discount amount for the order item. * - * @return float Base discount amount. + * @return float|null Base discount amount. */ public function getBaseDiscountAmount(); /** * Gets the base discount invoiced for the order item. * - * @return float Base discount invoiced. + * @return float|null Base discount invoiced. */ public function getBaseDiscountInvoiced(); /** * Gets the base discount refunded for the order item. * - * @return float Base discount refunded. + * @return float|null Base discount refunded. */ public function getBaseDiscountRefunded(); /** - * Gets the base hidden tax amount for the order item. + * Gets the base discount tax compensation amount for the order item. * - * @return float Base hidden tax amount. + * @return float Base discount tax compensation amount. */ - public function getBaseHiddenTaxAmount(); + public function getBaseDiscountTaxCompensationAmount(); /** - * Gets the base hidden tax invoiced for the order item. + * Gets the base discount tax compensation invoiced for the order item. * - * @return float Base hidden tax invoiced. + * @return float Base discount tax compensation invoiced. */ - public function getBaseHiddenTaxInvoiced(); + public function getBaseDiscountTaxCompensationInvoiced(); /** - * Gets the base hidden tax refunded for the order item. + * Gets the base discount tax compensation refunded for the order item. * - * @return float Base hidden tax refunded. + * @return float Base discount tax compensation refunded. */ - public function getBaseHiddenTaxRefunded(); + public function getBaseDiscountTaxCompensationRefunded(); /** * Gets the base original price for the order item. * - * @return float Base original price. + * @return float|null Base original price. */ public function getBaseOriginalPrice(); /** * Gets the base price for the order item. * - * @return float Base price. + * @return float|null Base price. */ public function getBasePrice(); /** * Gets the base price including tax for the order item. * - * @return float Base price including tax. + * @return float|null Base price including tax. */ public function getBasePriceInclTax(); /** * Gets the base row invoiced for the order item. * - * @return float Base row invoiced. + * @return float|null Base row invoiced. */ public function getBaseRowInvoiced(); /** * Gets the base row total for the order item. * - * @return float Base row total. + * @return float|null Base row total. */ public function getBaseRowTotal(); /** * Gets the base row total including tax for the order item. * - * @return float Base row total including tax. + * @return float|null Base row total including tax. */ public function getBaseRowTotalInclTax(); /** * Gets the base tax amount for the order item. * - * @return float Base tax amount. + * @return float|null Base tax amount. */ public function getBaseTaxAmount(); /** * Gets the base tax before discount for the order item. * - * @return float Base tax before discount. + * @return float|null Base tax before discount. */ public function getBaseTaxBeforeDiscount(); /** * Gets the base tax invoiced for the order item. * - * @return float Base tax invoiced. + * @return float|null Base tax invoiced. */ public function getBaseTaxInvoiced(); /** * Gets the base tax refunded for the order item. * - * @return float Base tax refunded. + * @return float|null Base tax refunded. */ public function getBaseTaxRefunded(); /** * Gets the base WEEE tax applied amount for the order item. * - * @return float Base WEEE tax applied amount. + * @return float|null Base WEEE tax applied amount. */ public function getBaseWeeeTaxAppliedAmount(); /** * Gets the base WEEE tax applied row amount for the order item. * - * @return float Base WEEE tax applied row amount. + * @return float|null Base WEEE tax applied row amount. */ public function getBaseWeeeTaxAppliedRowAmnt(); /** * Gets the base WEEE tax disposition for the order item. * - * @return float Base WEEE tax disposition. + * @return float|null Base WEEE tax disposition. */ public function getBaseWeeeTaxDisposition(); /** * Gets the base WEEE tax row disposition for the order item. * - * @return float Base WEEE tax row disposition. + * @return float|null Base WEEE tax row disposition. */ public function getBaseWeeeTaxRowDisposition(); /** * Gets the created-at timestamp for the order item. * - * @return string Created-at timestamp. + * @return string|null Created-at timestamp. */ public function getCreatedAt(); @@ -590,266 +590,266 @@ interface OrderItemInterface extends \Magento\Framework\Api\ExtensibleDataInterf /** * Gets the description for the order item. * - * @return string Description. + * @return string|null Description. */ public function getDescription(); /** * Gets the discount amount for the order item. * - * @return float Discount amount. + * @return float|null Discount amount. */ public function getDiscountAmount(); /** * Gets the discount invoiced for the order item. * - * @return float Discount invoiced. + * @return float|null Discount invoiced. */ public function getDiscountInvoiced(); /** * Gets the discount percent for the order item. * - * @return float Discount percent. + * @return float|null Discount percent. */ public function getDiscountPercent(); /** * Gets the discount refunded for the order item. * - * @return float Discount refunded. + * @return float|null Discount refunded. */ public function getDiscountRefunded(); /** * Gets the event ID for the order item. * - * @return int Event ID. + * @return int|null Event ID. */ public function getEventId(); /** * Gets the external order item ID for the order item. * - * @return string External order item ID. + * @return string|null External order item ID. */ public function getExtOrderItemId(); /** * Gets the free-shipping flag value for the order item. * - * @return int Free-shipping flag value. + * @return int|null Free-shipping flag value. */ public function getFreeShipping(); /** * Gets the GW base price for the order item. * - * @return float GW base price. + * @return float|null GW base price. */ public function getGwBasePrice(); /** * Gets the GW base price invoiced for the order item. * - * @return float GW base price invoiced. + * @return float|null GW base price invoiced. */ public function getGwBasePriceInvoiced(); /** * Gets the GW base price refunded for the order item. * - * @return float GW base price refunded. + * @return float|null GW base price refunded. */ public function getGwBasePriceRefunded(); /** * Gets the GW base tax amount for the order item. * - * @return float GW base tax amount. + * @return float|null GW base tax amount. */ public function getGwBaseTaxAmount(); /** * Gets the GW base tax amount invoiced for the order item. * - * @return float GW base tax amount invoiced. + * @return float|null GW base tax amount invoiced. */ public function getGwBaseTaxAmountInvoiced(); /** * Gets the GW base tax amount refunded for the order item. * - * @return float GW base tax amount refunded. + * @return float|null GW base tax amount refunded. */ public function getGwBaseTaxAmountRefunded(); /** * Gets the GW ID for the order item. * - * @return int GW ID. + * @return int|null GW ID. */ public function getGwId(); /** * Gets the GW price for the order item. * - * @return float GW price. + * @return float|null GW price. */ public function getGwPrice(); /** * Gets the GW price invoiced for the order item. * - * @return float GW price invoiced. + * @return float|null GW price invoiced. */ public function getGwPriceInvoiced(); /** * Gets the GW price refunded for the order item. * - * @return float GW price refunded. + * @return float|null GW price refunded. */ public function getGwPriceRefunded(); /** * Gets the GW tax amount for the order item. * - * @return float GW tax amount. + * @return float|null GW tax amount. */ public function getGwTaxAmount(); /** * Gets the GW tax amount invoiced for the order item. * - * @return float GW tax amount invoiced. + * @return float|null GW tax amount invoiced. */ public function getGwTaxAmountInvoiced(); /** * Gets the GW tax amount refunded for the order item. * - * @return float GW tax amount refunded. + * @return float|null GW tax amount refunded. */ public function getGwTaxAmountRefunded(); /** - * Gets the hidden tax amount for the order item. + * Gets the discount tax compensation amount for the order item. * - * @return float Hidden tax amount. + * @return float Discount tax compensation amount. */ - public function getHiddenTaxAmount(); + public function getDiscountTaxCompensationAmount(); /** - * Gets the hidden tax canceled for the order item. + * Gets the discount tax compensation canceled for the order item. * - * @return float Hidden tax canceled. + * @return float Discount tax compensation canceled. */ - public function getHiddenTaxCanceled(); + public function getDiscountTaxCompensationCanceled(); /** - * Gets the hidden tax invoiced for the order item. + * Gets the discount tax compensation invoiced for the order item. * - * @return float Hidden tax invoiced. + * @return float Discount tax compensation invoiced. */ - public function getHiddenTaxInvoiced(); + public function getDiscountTaxCompensationInvoiced(); /** - * Gets the hidden tax refunded for the order item. + * Gets the discount tax compensation refunded for the order item. * - * @return float Hidden tax refunded. + * @return float Discount tax compensation refunded. */ - public function getHiddenTaxRefunded(); + public function getDiscountTaxCompensationRefunded(); /** * Gets the is-quantity-decimal flag value for the order item. * - * @return int Is-quantity-decimal flag value. + * @return int|null Is-quantity-decimal flag value. */ public function getIsQtyDecimal(); /** * Gets the is-virtual flag value for the order item. * - * @return int Is-virtual flag value. + * @return int|null Is-virtual flag value. */ public function getIsVirtual(); /** * Gets the item ID for the order item. * - * @return int Item ID. + * @return int|null Item ID. */ public function getItemId(); /** * Gets the locked DO invoice flag value for the order item. * - * @return int Locked DO invoice flag value. + * @return int|null Locked DO invoice flag value. */ public function getLockedDoInvoice(); /** * Gets the locked DO ship flag value for the order item. * - * @return int Locked DO ship flag value. + * @return int|null Locked DO ship flag value. */ public function getLockedDoShip(); /** * Gets the name for the order item. * - * @return string Name. + * @return string|null Name. */ public function getName(); /** * Gets the no discount flag value for the order item. * - * @return int No-discount flag value. + * @return int|null No-discount flag value. */ public function getNoDiscount(); /** * Gets the order ID for the order item. * - * @return int Order ID. + * @return int|null Order ID. */ public function getOrderId(); /** * Gets the original price for the order item. * - * @return float Original price. + * @return float|null Original price. */ public function getOriginalPrice(); /** * Gets the parent item ID for the order item. * - * @return int Parent item ID. + * @return int|null Parent item ID. */ public function getParentItemId(); /** * Gets the price for the order item. * - * @return float Price. + * @return float|null Price. */ public function getPrice(); /** * Gets the price including tax for the order item. * - * @return float Price including tax. + * @return float|null Price including tax. */ public function getPriceInclTax(); /** * Gets the product ID for the order item. * - * @return int Product ID. + * @return int|null Product ID. */ public function getProductId(); @@ -871,91 +871,91 @@ interface OrderItemInterface extends \Magento\Framework\Api\ExtensibleDataInterf /** * Gets the product type for the order item. * - * @return string Product type. + * @return string|null Product type. */ public function getProductType(); /** * Gets the quantity backordered for the order item. * - * @return float Quantity backordered. + * @return float|null Quantity backordered. */ public function getQtyBackordered(); /** * Gets the quantity canceled for the order item. * - * @return float Quantity canceled. + * @return float|null Quantity canceled. */ public function getQtyCanceled(); /** * Gets the quantity invoiced for the order item. * - * @return float Quantity invoiced. + * @return float|null Quantity invoiced. */ public function getQtyInvoiced(); /** * Gets the quantity ordered for the order item. * - * @return float Quantity ordered. + * @return float|null Quantity ordered. */ public function getQtyOrdered(); /** * Gets the quantity refunded for the order item. * - * @return float Quantity refunded. + * @return float|null Quantity refunded. */ public function getQtyRefunded(); /** * Gets the quantity returned for the order item. * - * @return float Quantity returned. + * @return float|null Quantity returned. */ public function getQtyReturned(); /** * Gets the quantity shipped for the order item. * - * @return float Quantity shipped. + * @return float|null Quantity shipped. */ public function getQtyShipped(); /** * Gets the quote item ID for the order item. * - * @return int Quote item ID. + * @return int|null Quote item ID. */ public function getQuoteItemId(); /** * Gets the row invoiced for the order item. * - * @return float Row invoiced. + * @return float|null Row invoiced. */ public function getRowInvoiced(); /** * Gets the row total for the order item. * - * @return float Row total. + * @return float|null Row total. */ public function getRowTotal(); /** * Gets the row total including tax for the order item. * - * @return float Row total including tax. + * @return float|null Row total including tax. */ public function getRowTotalInclTax(); /** * Gets the row weight for the order item. * - * @return float Row weight. + * @return float|null Row weight. */ public function getRowWeight(); @@ -969,98 +969,98 @@ interface OrderItemInterface extends \Magento\Framework\Api\ExtensibleDataInterf /** * Gets the store ID for the order item. * - * @return int Store ID. + * @return int|null Store ID. */ public function getStoreId(); /** * Gets the tax amount for the order item. * - * @return float Tax amount. + * @return float|null Tax amount. */ public function getTaxAmount(); /** * Gets the tax before discount for the order item. * - * @return float Tax before discount. + * @return float|null Tax before discount. */ public function getTaxBeforeDiscount(); /** * Gets the tax canceled for the order item. * - * @return float Tax canceled. + * @return float|null Tax canceled. */ public function getTaxCanceled(); /** * Gets the tax invoiced for the order item. * - * @return float Tax invoiced. + * @return float|null Tax invoiced. */ public function getTaxInvoiced(); /** * Gets the tax percent for the order item. * - * @return float Tax percent. + * @return float|null Tax percent. */ public function getTaxPercent(); /** * Gets the tax refunded for the order item. * - * @return float Tax refunded. + * @return float|null Tax refunded. */ public function getTaxRefunded(); /** * Gets the updated-at timestamp for the order item. * - * @return string Updated-at timestamp. + * @return string|null Updated-at timestamp. */ public function getUpdatedAt(); /** * Gets the WEEE tax applied for the order item. * - * @return string WEEE tax applied. + * @return string|null WEEE tax applied. */ public function getWeeeTaxApplied(); /** * Gets the WEEE tax applied amount for the order item. * - * @return float WEEE tax applied amount. + * @return float|null WEEE tax applied amount. */ public function getWeeeTaxAppliedAmount(); /** * Gets the WEEE tax applied row amount for the order item. * - * @return float WEEE tax applied row amount. + * @return float|null WEEE tax applied row amount. */ public function getWeeeTaxAppliedRowAmount(); /** * Gets the WEEE tax disposition for the order item. * - * @return float WEEE tax disposition. + * @return float|null WEEE tax disposition. */ public function getWeeeTaxDisposition(); /** * Gets the WEEE tax row disposition for the order item. * - * @return float WEEE tax row disposition. + * @return float|null WEEE tax row disposition. */ public function getWeeeTaxRowDisposition(); /** * Gets the weight for the order item. * - * @return float Weight. + * @return float|null Weight. */ public function getWeight(); @@ -1512,52 +1512,52 @@ interface OrderItemInterface extends \Magento\Framework\Api\ExtensibleDataInterf public function setBaseRowTotalInclTax($amount); /** - * Sets the hidden tax amount for the order item. + * Sets the discount tax compensation amount for the order item. * * @param float $amount * @return $this */ - public function setHiddenTaxAmount($amount); + public function setDiscountTaxCompensationAmount($amount); /** - * Sets the base hidden tax amount for the order item. + * Sets the base discount tax compensation amount for the order item. * * @param float $amount * @return $this */ - public function setBaseHiddenTaxAmount($amount); + public function setBaseDiscountTaxCompensationAmount($amount); /** - * Sets the hidden tax invoiced for the order item. + * Sets the discount tax compensation invoiced for the order item. * - * @param float $hiddenTaxInvoiced + * @param float $discountTaxCompensationInvoiced * @return $this */ - public function setHiddenTaxInvoiced($hiddenTaxInvoiced); + public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoiced); /** - * Sets the base hidden tax invoiced for the order item. + * Sets the base discount tax compensation invoiced for the order item. * - * @param float $baseHiddenTaxInvoiced + * @param float $baseDiscountTaxCompensationInvoiced * @return $this */ - public function setBaseHiddenTaxInvoiced($baseHiddenTaxInvoiced); + public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensationInvoiced); /** - * Sets the hidden tax refunded for the order item. + * Sets the discount tax compensation refunded for the order item. * - * @param float $hiddenTaxRefunded + * @param float $discountTaxCompensationRefunded * @return $this */ - public function setHiddenTaxRefunded($hiddenTaxRefunded); + public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefunded); /** - * Sets the base hidden tax refunded for the order item. + * Sets the base discount tax compensation refunded for the order item. * - * @param float $baseHiddenTaxRefunded + * @param float $baseDiscountTaxCompensationRefunded * @return $this */ - public function setBaseHiddenTaxRefunded($baseHiddenTaxRefunded); + public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensationRefunded); /** * Sets the tax canceled for the order item. @@ -1568,12 +1568,12 @@ interface OrderItemInterface extends \Magento\Framework\Api\ExtensibleDataInterf public function setTaxCanceled($taxCanceled); /** - * Sets the hidden tax canceled for the order item. + * Sets the discount tax compensation canceled for the order item. * - * @param float $hiddenTaxCanceled + * @param float $discountTaxCompensationCanceled * @return $this */ - public function setHiddenTaxCanceled($hiddenTaxCanceled); + public function setDiscountTaxCompensationCanceled($discountTaxCompensationCanceled); /** * Sets the tax refunded for the order item. diff --git a/app/code/Magento/Sales/Api/Data/OrderPaymentInterface.php b/app/code/Magento/Sales/Api/Data/OrderPaymentInterface.php index 54efdc168711b842a5236b3fc14057a76d978a4f..385c7b1668d99cf0b6cd9285e248a6295f35bd3f 100644 --- a/app/code/Magento/Sales/Api/Data/OrderPaymentInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderPaymentInterface.php @@ -245,7 +245,7 @@ interface OrderPaymentInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the additional data for the order payment. * - * @return string Additional data. + * @return string|null Additional data. */ public function getAdditionalData(); @@ -259,175 +259,175 @@ interface OrderPaymentInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the address status for the order payment. * - * @return string Address status. + * @return string|null Address status. */ public function getAddressStatus(); /** * Gets the amount authorized for the order payment. * - * @return float Amount authorized. + * @return float|null Amount authorized. */ public function getAmountAuthorized(); /** * Gets the amount canceled for the order payment. * - * @return float Amount canceled. + * @return float|null Amount canceled. */ public function getAmountCanceled(); /** * Gets the amount ordered for the order payment. * - * @return float Amount ordered. + * @return float|null Amount ordered. */ public function getAmountOrdered(); /** * Gets the amount paid for the order payment. * - * @return float Amount paid. + * @return float|null Amount paid. */ public function getAmountPaid(); /** * Gets the amount refunded for the order payment. * - * @return float Amount refunded. + * @return float|null Amount refunded. */ public function getAmountRefunded(); /** * Gets the anet transaction method for the order payment. * - * @return string Anet transaction method. + * @return string|null Anet transaction method. */ public function getAnetTransMethod(); /** * Gets the base amount authorized for the order payment. * - * @return float Base amount authorized. + * @return float|null Base amount authorized. */ public function getBaseAmountAuthorized(); /** * Gets the base amount canceled for the order payment. * - * @return float Base amount canceled. + * @return float|null Base amount canceled. */ public function getBaseAmountCanceled(); /** * Gets the base amount ordered for the order payment. * - * @return float Base amount ordered. + * @return float|null Base amount ordered. */ public function getBaseAmountOrdered(); /** * Gets the base amount paid for the order payment. * - * @return float Base amount paid. + * @return float|null Base amount paid. */ public function getBaseAmountPaid(); /** * Gets the base amount paid online for the order payment. * - * @return float Base amount paid online. + * @return float|null Base amount paid online. */ public function getBaseAmountPaidOnline(); /** * Gets the base amount refunded for the order payment. * - * @return float Base amount refunded. + * @return float|null Base amount refunded. */ public function getBaseAmountRefunded(); /** * Gets the base amount refunded online for the order payment. * - * @return float Base amount refunded online. + * @return float|null Base amount refunded online. */ public function getBaseAmountRefundedOnline(); /** * Gets the base shipping amount for the order payment. * - * @return float Base shipping amount. + * @return float|null Base shipping amount. */ public function getBaseShippingAmount(); /** * Gets the base shipping captured for the order payment. * - * @return float Base shipping captured amount. + * @return float|null Base shipping captured amount. */ public function getBaseShippingCaptured(); /** * Gets the base shipping refunded amount for the order payment. * - * @return float Base shipping refunded amount. + * @return float|null Base shipping refunded amount. */ public function getBaseShippingRefunded(); /** * Gets the credit card approval for the order payment. * - * @return string Credit card approval. + * @return string|null Credit card approval. */ public function getCcApproval(); /** * Gets the credit card avs status for the order payment. * - * @return string Credit card avs status. + * @return string|null Credit card avs status. */ public function getCcAvsStatus(); /** * Gets the credit card cid status for the order payment. * - * @return string Credit card CID status. + * @return string|null Credit card CID status. */ public function getCcCidStatus(); /** * Gets the credit card debug request body for the order payment. * - * @return string Credit card debug request body. + * @return string|null Credit card debug request body. */ public function getCcDebugRequestBody(); /** * Gets the credit card debug response body for the order payment. * - * @return string Credit card debug response body. + * @return string|null Credit card debug response body. */ public function getCcDebugResponseBody(); /** * Gets the credit card debug response serialized for the order payment. * - * @return string Credit card debug response serialized. + * @return string|null Credit card debug response serialized. */ public function getCcDebugResponseSerialized(); /** * Gets the credit card expiration month for the order payment. * - * @return string Credit card expiration month. + * @return string|null Credit card expiration month. */ public function getCcExpMonth(); /** * Gets the credit card expiration year for the order payment. * - * @return string Credit card expiration year. + * @return string|null Credit card expiration year. */ public function getCcExpYear(); @@ -441,112 +441,112 @@ interface OrderPaymentInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the encrypted credit card number for the order payment. * - * @return string Encrypted credit card number. + * @return string|null Encrypted credit card number. */ public function getCcNumberEnc(); /** * Gets the credit card owner for the order payment. * - * @return string Credit card number. + * @return string|null Credit card number. */ public function getCcOwner(); /** * Gets the credit card secure verify for the order payment. * - * @return string Credit card secure verify. + * @return string|null Credit card secure verify. */ public function getCcSecureVerify(); /** * Gets the credit card SS issue for the order payment. * - * @return string Credit card SS issue. + * @return string|null Credit card SS issue. */ public function getCcSsIssue(); /** * Gets the credit card SS start month for the order payment. * - * @return string Credit card SS start month. + * @return string|null Credit card SS start month. */ public function getCcSsStartMonth(); /** * Gets the credit card SS start year for the order payment. * - * @return string Credit card SS start year. + * @return string|null Credit card SS start year. */ public function getCcSsStartYear(); /** * Gets the credit card status for the order payment. * - * @return string Credit card status. + * @return string|null Credit card status. */ public function getCcStatus(); /** * Gets the credit card status description for the order payment. * - * @return string Credit card status description. + * @return string|null Credit card status description. */ public function getCcStatusDescription(); /** * Gets the credit card transaction id for the order payment. * - * @return string Credit card transaction ID. + * @return string|null Credit card transaction ID. */ public function getCcTransId(); /** * Gets the credit card type for the order payment. * - * @return string Credit card type. + * @return string|null Credit card type. */ public function getCcType(); /** * Gets the eCheck account name for the order payment. * - * @return string eCheck account name. + * @return string|null eCheck account name. */ public function getEcheckAccountName(); /** * Gets the eCheck account type for the order payment. * - * @return string eCheck account type. + * @return string|null eCheck account type. */ public function getEcheckAccountType(); /** * Gets the eCheck bank name for the order payment. * - * @return string eCheck bank name. + * @return string|null eCheck bank name. */ public function getEcheckBankName(); /** * Gets the eCheck routing number for the order payment. * - * @return string eCheck routing number. + * @return string|null eCheck routing number. */ public function getEcheckRoutingNumber(); /** * Gets the eCheck type for the order payment. * - * @return string eCheck type. + * @return string|null eCheck type. */ public function getEcheckType(); /** * Gets the entity ID for the order payment. * - * @return int Entity ID. + * @return int|null Entity ID. */ public function getEntityId(); @@ -561,7 +561,7 @@ interface OrderPaymentInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the last transaction ID for the order payment. * - * @return string Last transaction ID. + * @return string|null Last transaction ID. */ public function getLastTransId(); @@ -575,49 +575,49 @@ interface OrderPaymentInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the parent ID for the order payment. * - * @return int Parent ID. + * @return int|null Parent ID. */ public function getParentId(); /** * Gets the PO number for the order payment. * - * @return string PO number. + * @return string|null PO number. */ public function getPoNumber(); /** * Gets the protection eligibility for the order payment. * - * @return string Protection eligibility. + * @return string|null Protection eligibility. */ public function getProtectionEligibility(); /** * Gets the quote payment ID for the order payment. * - * @return int Quote payment ID. + * @return int|null Quote payment ID. */ public function getQuotePaymentId(); /** * Gets the shipping amount for the order payment. * - * @return float Shipping amount. + * @return float|null Shipping amount. */ public function getShippingAmount(); /** * Gets the shipping captured for the order payment. * - * @return float Shipping captured. + * @return float|null Shipping captured. */ public function getShippingCaptured(); /** * Gets the shipping refunded for the order payment. * - * @return float Shipping refunded. + * @return float|null Shipping refunded. */ public function getShippingRefunded(); diff --git a/app/code/Magento/Sales/Api/Data/OrderStatusHistoryInterface.php b/app/code/Magento/Sales/Api/Data/OrderStatusHistoryInterface.php index 30f6f471db03def19df2b61f4d55299217316994..e6cea90ba3da3facdcc269700ae6d99d5bad9df6 100644 --- a/app/code/Magento/Sales/Api/Data/OrderStatusHistoryInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderStatusHistoryInterface.php @@ -61,7 +61,7 @@ interface OrderStatusHistoryInterface extends \Magento\Framework\Api\ExtensibleD /** * Gets the created-at timestamp for the order status history. * - * @return string Created-at timestamp. + * @return string|null Created-at timestamp. */ public function getCreatedAt(); @@ -76,7 +76,7 @@ interface OrderStatusHistoryInterface extends \Magento\Framework\Api\ExtensibleD /** * Gets the ID for the order status history. * - * @return int Order status history ID. + * @return int|null Order status history ID. */ public function getEntityId(); @@ -91,7 +91,7 @@ interface OrderStatusHistoryInterface extends \Magento\Framework\Api\ExtensibleD /** * Gets the entity name for the order status history. * - * @return string Entity name. + * @return string|null Entity name. */ public function getEntityName(); @@ -119,7 +119,7 @@ interface OrderStatusHistoryInterface extends \Magento\Framework\Api\ExtensibleD /** * Gets the status for the order status history. * - * @return string Status. + * @return string|null Status. */ public function getStatus(); diff --git a/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php index 17b0f122a8871df5112d2c1c5c0f8ae052090188..0f60e6c19dc1d453efc3dd4e2135eec27292ada0 100644 --- a/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php +++ b/app/code/Magento/Sales/Api/Data/ShipmentCommentInterface.php @@ -52,7 +52,7 @@ interface ShipmentCommentInterface extends \Magento\Framework\Api\ExtensibleData /** * Gets the created-at timestamp for the shipment comment. * - * @return string Created-at timestamp. + * @return string|null Created-at timestamp. */ public function getCreatedAt(); @@ -67,7 +67,7 @@ interface ShipmentCommentInterface extends \Magento\Framework\Api\ExtensibleData /** * Gets the ID for the shipment comment. * - * @return int Shipment comment ID. + * @return int|null Shipment comment ID. */ public function getEntityId(); diff --git a/app/code/Magento/Sales/Api/Data/ShipmentInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentInterface.php index 92d75fd2674253f9615006af0baadc8264d8d4e1..0319108dd4b75b42e83d0868fed80f75bd67bcde 100644 --- a/app/code/Magento/Sales/Api/Data/ShipmentInterface.php +++ b/app/code/Magento/Sales/Api/Data/ShipmentInterface.php @@ -93,14 +93,14 @@ interface ShipmentInterface extends \Magento\Framework\Api\ExtensibleDataInterfa /** * Gets the billing address ID for the shipment. * - * @return int Billing address ID. + * @return int|null Billing address ID. */ public function getBillingAddressId(); /** * Gets the created-at timestamp for the shipment. * - * @return string Created-at timestamp. + * @return string|null Created-at timestamp. */ public function getCreatedAt(); @@ -115,21 +115,21 @@ interface ShipmentInterface extends \Magento\Framework\Api\ExtensibleDataInterfa /** * Gets the customer ID for the shipment. * - * @return int Customer ID. + * @return int|null Customer ID. */ public function getCustomerId(); /** * Gets the email-sent flag value for the shipment. * - * @return int Email-sent flag value. + * @return int|null Email-sent flag value. */ public function getEmailSent(); /** * Gets the ID for the shipment. * - * @return int Shipment ID. + * @return int|null Shipment ID. */ public function getEntityId(); @@ -144,7 +144,7 @@ interface ShipmentInterface extends \Magento\Framework\Api\ExtensibleDataInterfa /** * Gets the increment ID for the shipment. * - * @return string Increment ID. + * @return string|null Increment ID. */ public function getIncrementId(); @@ -173,49 +173,49 @@ interface ShipmentInterface extends \Magento\Framework\Api\ExtensibleDataInterfa /** * Gets the shipment status. * - * @return int Shipment status. + * @return int|null Shipment status. */ public function getShipmentStatus(); /** * Gets the shipping address ID for the shipment. * - * @return int Shipping address ID. + * @return int|null Shipping address ID. */ public function getShippingAddressId(); /** * Gets the shipping label for the shipment. * - * @return string Shipping label. + * @return string|null Shipping label. */ public function getShippingLabel(); /** * Gets the store ID for the shipment. * - * @return int Store ID. + * @return int|null Store ID. */ public function getStoreId(); /** * Gets the total quantity for the shipment. * - * @return float Total quantity. + * @return float|null Total quantity. */ public function getTotalQty(); /** * Gets the total weight for the shipment. * - * @return float Total weight. + * @return float|null Total weight. */ public function getTotalWeight(); /** * Gets the updated-at timestamp for the shipment. * - * @return string Updated-at timestamp. + * @return string|null Updated-at timestamp. */ public function getUpdatedAt(); diff --git a/app/code/Magento/Sales/Api/Data/ShipmentItemInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentItemInterface.php index e6819d60fa9dffe4ee1dfc4fc4f2f08c2604bab5..cde384511f553e0e307e87b128fba0a52b4329f7 100644 --- a/app/code/Magento/Sales/Api/Data/ShipmentItemInterface.php +++ b/app/code/Magento/Sales/Api/Data/ShipmentItemInterface.php @@ -69,21 +69,21 @@ interface ShipmentItemInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the additional data for the shipment item. * - * @return string Additional data. + * @return string|null Additional data. */ public function getAdditionalData(); /** * Gets the description for the shipment item. * - * @return string Description. + * @return string|null Description. */ public function getDescription(); /** * Gets the ID for the shipment item. * - * @return int Shipment item ID. + * @return int|null Shipment item ID. */ public function getEntityId(); @@ -98,7 +98,7 @@ interface ShipmentItemInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the name for the shipment item. * - * @return string Name. + * @return string|null Name. */ public function getName(); @@ -112,21 +112,21 @@ interface ShipmentItemInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the parent ID for the shipment item. * - * @return int Parent ID. + * @return int|null Parent ID. */ public function getParentId(); /** * Gets the price for the shipment item. * - * @return float Price. + * @return float|null Price. */ public function getPrice(); /** * Gets the product ID for the shipment item. * - * @return int Product ID. + * @return int|null Product ID. */ public function getProductId(); @@ -140,21 +140,21 @@ interface ShipmentItemInterface extends \Magento\Framework\Api\ExtensibleDataInt /** * Gets the row total for the shipment item. * - * @return float Row total. + * @return float|null Row total. */ public function getRowTotal(); /** * Gets the SKU for the shipment item. * - * @return string SKU. + * @return string|null SKU. */ public function getSku(); /** * Gets the weight for the shipment item. * - * @return float Weight. + * @return float|null Weight. */ public function getWeight(); diff --git a/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php b/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php index 5a8a77987cc7153e42e58381147350cf8e734971..b167cd6993b1ec05615c1ca350570fa70894ba85 100644 --- a/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php +++ b/app/code/Magento/Sales/Api/Data/ShipmentTrackInterface.php @@ -73,7 +73,7 @@ interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataIn /** * Gets the created-at timestamp for the shipment package. * - * @return string Created-at timestamp. + * @return string|null Created-at timestamp. */ public function getCreatedAt(); @@ -95,7 +95,7 @@ interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataIn /** * Gets the ID for the shipment package. * - * @return int Shipment package ID. + * @return int|null Shipment package ID. */ public function getEntityId(); @@ -145,7 +145,7 @@ interface ShipmentTrackInterface extends \Magento\Framework\Api\ExtensibleDataIn /** * Gets the updated-at timestamp for the shipment package. * - * @return string Updated-at timestamp. + * @return string|null Updated-at timestamp. */ public function getUpdatedAt(); diff --git a/app/code/Magento/Sales/Block/Adminhtml/CustomerOrdersTab.php b/app/code/Magento/Sales/Block/Adminhtml/CustomerOrdersTab.php index 622a547e3d8254c50b9f39527b75eea46534eda6..f44c57d8e7c7e1ef2452f2067560ad126329b67c 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/CustomerOrdersTab.php +++ b/app/code/Magento/Sales/Block/Adminhtml/CustomerOrdersTab.php @@ -53,6 +53,8 @@ class CustomerOrdersTab extends TabWrapper /** * Return Tab label * + * @codeCoverageIgnore + * * @return \Magento\Framework\Phrase */ public function getTabLabel() diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Comments/View.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Comments/View.php index ea065d8eea7a6dc695f3c1d2c023e39af251f1a6..a4d4d9bf826b870f023f909c7d39b434b9b2c735 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Comments/View.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Comments/View.php @@ -19,18 +19,26 @@ class View extends \Magento\Backend\Block\Template */ protected $_salesData = null; + /** + * @var \Magento\Sales\Helper\Admin + */ + private $adminHelper; + /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Sales\Helper\Data $salesData + * @param \Magento\Sales\Helper\Admin $adminHelper * @param array $data */ public function __construct( \Magento\Backend\Block\Template\Context $context, \Magento\Sales\Helper\Data $salesData, + \Magento\Sales\Helper\Admin $adminHelper, array $data = [] ) { $this->_salesData = $salesData; parent::__construct($context, $data); + $this->adminHelper = $adminHelper; } /** @@ -96,4 +104,16 @@ class View extends \Magento\Backend\Block\Template } return true; } + + /** + * Replace links in string + * + * @param array|string $data + * @param null|array $allowedTags + * @return string + */ + public function escapeHtml($data, $allowedTags = null) + { + return $this->adminHelper->escapeHtmlWithLinks($data, $allowedTags); + } } diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Items/Grid.php b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Items/Grid.php index fe33696ba778625a5c27be6b4bf8b43f7fcfd75e..bc134343538f629ca2037c9c974b1d0e7b77e3c9 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Items/Grid.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/Create/Items/Grid.php @@ -289,7 +289,7 @@ class Grid extends \Magento\Sales\Block\Adminhtml\Order\Create\AbstractCreate return $address->getSubtotal() + $address->getTaxAmount() + $address->getDiscountAmount() - + $address->getHiddenTaxAmount(); + + $address->getDiscountTaxCompensationAmount(); } else { return $address->getSubtotal() + $address->getDiscountAmount(); } diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php b/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php index d0284f3175fdc79c07fd9938f5634fa76cab7ef9..6281760afb70987e6b7029e42d6a98cd0529c2f4 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/View/History.php @@ -26,21 +26,29 @@ class History extends \Magento\Backend\Block\Template */ protected $_salesData = null; + /** + * @var \Magento\Sales\Helper\Admin + */ + private $adminHelper; + /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Sales\Helper\Data $salesData * @param \Magento\Framework\Registry $registry + * @param \Magento\Sales\Helper\Admin $adminHelper * @param array $data */ public function __construct( \Magento\Backend\Block\Template\Context $context, \Magento\Sales\Helper\Data $salesData, \Magento\Framework\Registry $registry, + \Magento\Sales\Helper\Admin $adminHelper, array $data = [] ) { $this->_coreRegistry = $registry; $this->_salesData = $salesData; parent::__construct($context, $data); + $this->adminHelper = $adminHelper; } /** @@ -122,4 +130,16 @@ class History extends \Magento\Backend\Block\Template { return $history->isCustomerNotificationNotApplicable(); } + + /** + * Replace links in string + * + * @param array|string $data + * @param null|array $allowedTags + * @return string + */ + public function escapeHtml($data, $allowedTags = null) + { + return $this->adminHelper->escapeHtmlWithLinks($data, $allowedTags); + } } diff --git a/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/History.php b/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/History.php index 04a27b73b15d0b94e0264d735e9569d94ce80eb3..4e6b7a05035dd36b30c70e89f6de0555f618b31d 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/History.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Order/View/Tab/History.php @@ -26,18 +26,26 @@ class History extends \Magento\Backend\Block\Template implements \Magento\Backen */ protected $_coreRegistry = null; + /** + * @var \Magento\Sales\Helper\Admin + */ + private $adminHelper; + /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Framework\Registry $registry + * @param \Magento\Sales\Helper\Admin $adminHelper * @param array $data */ public function __construct( \Magento\Backend\Block\Template\Context $context, \Magento\Framework\Registry $registry, + \Magento\Sales\Helper\Admin $adminHelper, array $data = [] ) { $this->_coreRegistry = $registry; parent::__construct($context, $data); + $this->adminHelper = $adminHelper; } /** @@ -192,8 +200,9 @@ class History extends \Magento\Backend\Block\Template implements \Magento\Backen */ public function getItemComment(array $item) { - $allowedTags = ['b', 'br', 'strong', 'i', 'u']; - return isset($item['comment']) ? $this->escapeHtml($item['comment'], $allowedTags) : ''; + $allowedTags = ['b', 'br', 'strong', 'i', 'u', 'a']; + return isset($item['comment']) + ? $this->adminHelper->escapeHtmlWithLinks($item['comment'], $allowedTags) : ''; } /** diff --git a/app/code/Magento/Sales/Block/Adminhtml/Transactions/Detail.php b/app/code/Magento/Sales/Block/Adminhtml/Transactions/Detail.php index 8eed288ca073359398473eb23997870c5b03db36..3d6fdb28085788b0e415bd1977109b6cd6c4571b 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Transactions/Detail.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Transactions/Detail.php @@ -26,17 +26,25 @@ class Detail extends \Magento\Backend\Block\Widget\Container */ protected $_coreRegistry = null; + /** + * @var \Magento\Sales\Helper\Admin + */ + private $adminHelper; + /** * @param \Magento\Backend\Block\Widget\Context $context * @param \Magento\Framework\Registry $registry + * @param \Magento\Sales\Helper\Admin $adminHelper * @param array $data */ public function __construct( \Magento\Backend\Block\Widget\Context $context, \Magento\Framework\Registry $registry, + \Magento\Sales\Helper\Admin $adminHelper, array $data = [] ) { $this->_coreRegistry = $registry; + $this->adminHelper = $adminHelper; parent::__construct($context, $data); } @@ -97,7 +105,10 @@ class Detail extends \Magento\Backend\Block\Widget\Container */ protected function _toHtml() { - $this->setTxnIdHtml($this->escapeHtml($this->_txn->getTxnId())); + $this->setTxnIdHtml($this->adminHelper->escapeHtmlWithLinks( + $this->_txn->getHtmlTxnId(), + ['a'] + )); $this->setParentTxnIdUrlHtml( $this->escapeHtml($this->getUrl('sales/transactions/view', ['txn_id' => $this->_txn->getParentId()])) diff --git a/app/code/Magento/Sales/Block/Order/Info.php b/app/code/Magento/Sales/Block/Order/Info.php index c0cc355c7844ab0985db090385e117988eb58b2e..e3ff4f826239c900a3bef0886e03d6dbc94215b4 100644 --- a/app/code/Magento/Sales/Block/Order/Info.php +++ b/app/code/Magento/Sales/Block/Order/Info.php @@ -57,6 +57,7 @@ class Info extends \Magento\Framework\View\Element\Template $this->addressRenderer = $addressRenderer; $this->paymentHelper = $paymentHelper; $this->coreRegistry = $registry; + $this->_isScopePrivate = true; parent::__construct($context, $data); } diff --git a/app/code/Magento/Sales/Block/Order/Item/Renderer/DefaultRenderer.php b/app/code/Magento/Sales/Block/Order/Item/Renderer/DefaultRenderer.php index c6ea7d810dc0948e6984bf152d6783cb2278ec28..d71bfe9ecd44dbabc046964e5598de5d0a848e59 100644 --- a/app/code/Magento/Sales/Block/Order/Item/Renderer/DefaultRenderer.php +++ b/app/code/Magento/Sales/Block/Order/Item/Renderer/DefaultRenderer.php @@ -253,7 +253,7 @@ class DefaultRenderer extends \Magento\Framework\View\Element\Template { $totalAmount = $item->getRowTotal() + $item->getTaxAmount() - + $item->getHiddenTaxAmount() + + $item->getDiscountTaxCompensationAmount() + $item->getWeeeTaxAppliedRowAmount() - $item->getDiscountAmount(); diff --git a/app/code/Magento/Sales/Block/Order/PrintShipment.php b/app/code/Magento/Sales/Block/Order/PrintShipment.php index 13633511bc839245af1e89da69b8e0d42cebf4b5..49254ff813b0efa66d39ffa3df78ff49636c8a33 100644 --- a/app/code/Magento/Sales/Block/Order/PrintShipment.php +++ b/app/code/Magento/Sales/Block/Order/PrintShipment.php @@ -25,20 +25,28 @@ class PrintShipment extends \Magento\Sales\Block\Items\AbstractItems */ protected $_paymentHelper; + /** + * @var \Magento\Sales\Model\Order\Address\Renderer + */ + protected $addressRenderer; + /** * @param \Magento\Framework\View\Element\Template\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Payment\Helper\Data $paymentHelper + * @param \Magento\Sales\Model\Order\Address\Renderer $addressRenderer * @param array $data */ public function __construct( \Magento\Framework\View\Element\Template\Context $context, \Magento\Framework\Registry $registry, \Magento\Payment\Helper\Data $paymentHelper, + \Magento\Sales\Model\Order\Address\Renderer $addressRenderer, array $data = [] ) { $this->_paymentHelper = $paymentHelper; $this->_coreRegistry = $registry; + $this->addressRenderer = $addressRenderer; parent::__construct($context, $data); } @@ -75,7 +83,17 @@ class PrintShipment extends \Magento\Sales\Block\Items\AbstractItems protected function _prepareItem(AbstractBlock $renderer) { $renderer->setPrintStatus(true); - return parent::_prepareItem($renderer); } + + /** + * Returns string with formatted address + * + * @param Address $address + * @return null|string + */ + public function getFormattedAddress(\Magento\Sales\Model\Order\Address $address) + { + return $this->addressRenderer->format($address, 'html'); + } } diff --git a/app/code/Magento/Sales/Controller/AbstractController/Reorder.php b/app/code/Magento/Sales/Controller/AbstractController/Reorder.php index 7010d3bd5c04140599a3bce2c7ac35322c2d66c8..d2a5e2d42be54c0831b2c47fb201d948cb2d3811 100644 --- a/app/code/Magento/Sales/Controller/AbstractController/Reorder.php +++ b/app/code/Magento/Sales/Controller/AbstractController/Reorder.php @@ -65,7 +65,7 @@ abstract class Reorder extends Action\Action } return $resultRedirect->setPath('*/*/history'); } catch (\Exception $e) { - $this->messageManager->addException($e, __('We cannot add this item to your shopping cart.')); + $this->messageManager->addException($e, __('We can\'t add this item to your cart right now.')); return $resultRedirect->setPath('checkout/cart'); } } diff --git a/app/code/Magento/Sales/Helper/Admin.php b/app/code/Magento/Sales/Helper/Admin.php index 3aca5adcd8320004e31656e8ace26e730d14288a..2ee1bf065611dfca3484f6c19553c19fa6031668 100644 --- a/app/code/Magento/Sales/Helper/Admin.php +++ b/app/code/Magento/Sales/Helper/Admin.php @@ -22,21 +22,29 @@ class Admin extends \Magento\Framework\App\Helper\AbstractHelper */ protected $priceCurrency; + /** + * @var \Magento\Framework\Escaper + */ + protected $escaper; + /** * @param \Magento\Framework\App\Helper\Context $context * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Sales\Model\Config $salesConfig * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency + * @param \Magento\Framework\Escaper $escaper */ public function __construct( \Magento\Framework\App\Helper\Context $context, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Sales\Model\Config $salesConfig, - \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency + \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, + \Magento\Framework\Escaper $escaper ) { $this->priceCurrency = $priceCurrency; $this->_storeManager = $storeManager; $this->_salesConfig = $salesConfig; + $this->escaper = $escaper; parent::__construct($context); } @@ -127,4 +135,29 @@ class Admin extends \Magento\Framework\App\Helper\AbstractHelper } return $collection; } + + /** + * Escape string preserving links + * + * @param string $data + * @param null|array $allowedTags + * @return string + */ + public function escapeHtmlWithLinks($data, $allowedTags = null) + { + if (!empty($data) && is_array($allowedTags) && in_array('a', $allowedTags)) { + $links = []; + $i = 1; + $data = str_replace('%', '%%', $data); + $regexp = '@(<a[^>]*>(?:[^<]|<[^/]|</[^a]|</a[^>])*</a>)@'; + while (preg_match($regexp, $data, $matches)) { + $links[] = $matches[1]; + $data = str_replace($matches[1], '%' . $i . '$s', $data); + ++$i; + } + $data = $this->escaper->escapeHtml($data, $allowedTags); + return vsprintf($data, $links); + } + return $this->escaper->escapeHtml($data, $allowedTags); + } } diff --git a/app/code/Magento/Sales/Model/AbstractModel.php b/app/code/Magento/Sales/Model/AbstractModel.php index fb0388bc92a200b0be128ba4ff16c97fce647d33..9f409bcbd76bb2dfacf96116b06584e6c70d12b3 100644 --- a/app/code/Magento/Sales/Model/AbstractModel.php +++ b/app/code/Magento/Sales/Model/AbstractModel.php @@ -22,7 +22,7 @@ abstract class AbstractModel extends AbstractExtensibleModel * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -31,7 +31,7 @@ abstract class AbstractModel extends AbstractExtensibleModel \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, AttributeValueFactory $customAttributeFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/Sales/Model/Observer/IndexGrid.php b/app/code/Magento/Sales/Model/Observer/IndexGrid.php index fdf54b0f8f48a0aeafe7a4b3ecf172be97b04996..d0c99b16c5d0bf285578b12e9177ee6dcea772b1 100644 --- a/app/code/Magento/Sales/Model/Observer/IndexGrid.php +++ b/app/code/Magento/Sales/Model/Observer/IndexGrid.php @@ -59,7 +59,7 @@ class IndexGrid public function syncInsert(\Magento\Framework\Event\Observer $observer) { if (!$this->globalConfig->getValue('dev/grid/async_indexing')) { - $this->entityGrid->refresh($observer->getDataObject()->getId()); + $this->entityGrid->refresh($observer->getObject()->getId()); } } diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 5e9d8557608e6c1dfd65497e57d1e3c138529b29..902d0719ee99723301c41fbc6012133cfe47121d 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -287,7 +287,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface * @param PriceCurrencyInterface $priceCurrency * @param \Magento\Catalog\Model\Resource\Product\CollectionFactory $productListFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -316,7 +316,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface PriceCurrencyInterface $priceCurrency, \Magento\Catalog\Model\Resource\Product\CollectionFactory $productListFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_storeManager = $storeManager; @@ -511,7 +511,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface */ public function canVoidPayment() { - return $this->_canVoidOrder() ? $this->getPayment()->canVoid($this->getPayment()) : false; + return $this->_canVoidOrder() ? $this->getPayment()->canVoid() : false; } /** @@ -1884,6 +1884,8 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface /** * Returns increment id * + * @codeCoverageIgnore + * * @return string */ public function getIncrementId() @@ -1907,6 +1909,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface /** * {@inheritdoc} + * @codeCoverageIgnore */ public function setItems($items) { @@ -1929,6 +1932,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface /** * {@inheritdoc} + * @codeCoverageIgnore */ public function setPayments(array $payments = null) { @@ -1951,12 +1955,49 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface /** * {@inheritdoc} + * @codeCoverageIgnore */ public function setAddresses(array $addresses = null) { return $this->setData(OrderInterface::ADDRESSES, $addresses); } + /** + * @return \Magento\Sales\Api\Data\OrderStatusHistoryInterface[] + */ + public function getStatusHistories() + { + if ($this->getData(OrderInterface::STATUS_HISTORIES) == null) { + $this->setData( + OrderInterface::STATUS_HISTORIES, + $this->getStatusHistoryCollection()->getItems() + ); + } + return $this->getData(OrderInterface::STATUS_HISTORIES); + } + + /** + * {@inheritdoc} + * + * @return \Magento\Sales\Api\Data\OrderExtensionInterface|null + */ + public function getExtensionAttributes() + { + return $this->_getExtensionAttributes(); + } + + /** + * {@inheritdoc} + * + * @param \Magento\Sales\Api\Data\OrderExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes(\Magento\Sales\Api\Data\OrderExtensionInterface $extensionAttributes) + { + return $this->_setExtensionAttributes($extensionAttributes); + } + + //@codeCoverageIgnoreStart /** * Returns adjustment_negative * @@ -2068,33 +2109,33 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface } /** - * Returns base_hidden_tax_amount + * Returns base_discount_tax_compensation_amount * * @return float */ - public function getBaseHiddenTaxAmount() + public function getBaseDiscountTaxCompensationAmount() { - return $this->getData(OrderInterface::BASE_HIDDEN_TAX_AMOUNT); + return $this->getData(OrderInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** - * Returns base_hidden_tax_invoiced + * Returns base_discount_tax_compensation_invoiced * * @return float */ - public function getBaseHiddenTaxInvoiced() + public function getBaseDiscountTaxCompensationInvoiced() { - return $this->getData(OrderInterface::BASE_HIDDEN_TAX_INVOICED); + return $this->getData(OrderInterface::BASE_DISCOUNT_TAX_COMPENSATION_INVOICED); } /** - * Returns base_hidden_tax_refunded + * Returns base_discount_tax_compensation_refunded * * @return float */ - public function getBaseHiddenTaxRefunded() + public function getBaseDiscountTaxCompensationRefunded() { - return $this->getData(OrderInterface::BASE_HIDDEN_TAX_REFUNDED); + return $this->getData(OrderInterface::BASE_DISCOUNT_TAX_COMPENSATION_REFUNDED); } /** @@ -2128,13 +2169,13 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface } /** - * Returns base_shipping_hidden_tax_amnt + * Returns base_shipping_discount_tax_compensation_amnt * * @return float */ - public function getBaseShippingHiddenTaxAmnt() + public function getBaseShippingDiscountTaxCompensationAmnt() { - return $this->getData(OrderInterface::BASE_SHIPPING_HIDDEN_TAX_AMNT); + return $this->getData(OrderInterface::BASE_SHIPPING_DISCOUNT_TAX_COMPENSATION_AMNT); } /** @@ -2696,33 +2737,33 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface } /** - * Returns hidden_tax_amount + * Returns discount_tax_compensation_amount * * @return float */ - public function getHiddenTaxAmount() + public function getDiscountTaxCompensationAmount() { - return $this->getData(OrderInterface::HIDDEN_TAX_AMOUNT); + return $this->getData(OrderInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** - * Returns hidden_tax_invoiced + * Returns discount_tax_compensation_invoiced * * @return float */ - public function getHiddenTaxInvoiced() + public function getDiscountTaxCompensationInvoiced() { - return $this->getData(OrderInterface::HIDDEN_TAX_INVOICED); + return $this->getData(OrderInterface::DISCOUNT_TAX_COMPENSATION_INVOICED); } /** - * Returns hidden_tax_refunded + * Returns discount_tax_compensation_refunded * * @return float */ - public function getHiddenTaxRefunded() + public function getDiscountTaxCompensationRefunded() { - return $this->getData(OrderInterface::HIDDEN_TAX_REFUNDED); + return $this->getData(OrderInterface::DISCOUNT_TAX_COMPENSATION_REFUNDED); } /** @@ -2926,13 +2967,13 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface } /** - * Returns shipping_hidden_tax_amount + * Returns shipping_discount_tax_compensation_amount * * @return float */ - public function getShippingHiddenTaxAmount() + public function getShippingDiscountTaxCompensationAmount() { - return $this->getData(OrderInterface::SHIPPING_HIDDEN_TAX_AMOUNT); + return $this->getData(OrderInterface::SHIPPING_DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -3255,41 +3296,6 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface return $this->getData(OrderInterface::X_FORWARDED_FOR); } - /** - * @return \Magento\Sales\Api\Data\OrderStatusHistoryInterface[] - */ - public function getStatusHistories() - { - if ($this->getData(OrderInterface::STATUS_HISTORIES) == null) { - $this->setData( - OrderInterface::STATUS_HISTORIES, - $this->getStatusHistoryCollection()->getItems() - ); - } - return $this->getData(OrderInterface::STATUS_HISTORIES); - } - - /** - * {@inheritdoc} - * - * @return \Magento\Sales\Api\Data\OrderExtensionInterface|null - */ - public function getExtensionAttributes() - { - return $this->_getExtensionAttributes(); - } - - /** - * {@inheritdoc} - * - * @param \Magento\Sales\Api\Data\OrderExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes(\Magento\Sales\Api\Data\OrderExtensionInterface $extensionAttributes) - { - return $this->_setExtensionAttributes($extensionAttributes); - } - /** * {@inheritdoc} */ @@ -3298,7 +3304,6 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface return $this->setData(OrderInterface::STATUS_HISTORIES, $statusHistories); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ @@ -4270,65 +4275,74 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface /** * {@inheritdoc} */ - public function setHiddenTaxAmount($amount) + public function setDiscountTaxCompensationAmount($amount) { - return $this->setData(OrderInterface::HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(OrderInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setBaseHiddenTaxAmount($amount) + public function setBaseDiscountTaxCompensationAmount($amount) { - return $this->setData(OrderInterface::BASE_HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(OrderInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setShippingHiddenTaxAmount($amount) + public function setShippingDiscountTaxCompensationAmount($amount) { - return $this->setData(OrderInterface::SHIPPING_HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(OrderInterface::SHIPPING_DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setBaseShippingHiddenTaxAmnt($amnt) + public function setBaseShippingDiscountTaxCompensationAmnt($amnt) { - return $this->setData(OrderInterface::BASE_SHIPPING_HIDDEN_TAX_AMNT, $amnt); + return $this->setData(OrderInterface::BASE_SHIPPING_DISCOUNT_TAX_COMPENSATION_AMNT, $amnt); } /** * {@inheritdoc} */ - public function setHiddenTaxInvoiced($hiddenTaxInvoiced) + public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoiced) { - return $this->setData(OrderInterface::HIDDEN_TAX_INVOICED, $hiddenTaxInvoiced); + return $this->setData(OrderInterface::DISCOUNT_TAX_COMPENSATION_INVOICED, $discountTaxCompensationInvoiced); } /** * {@inheritdoc} */ - public function setBaseHiddenTaxInvoiced($baseHiddenTaxInvoiced) + public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensationInvoiced) { - return $this->setData(OrderInterface::BASE_HIDDEN_TAX_INVOICED, $baseHiddenTaxInvoiced); + return $this->setData( + OrderInterface::BASE_DISCOUNT_TAX_COMPENSATION_INVOICED, + $baseDiscountTaxCompensationInvoiced + ); } /** * {@inheritdoc} */ - public function setHiddenTaxRefunded($hiddenTaxRefunded) + public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefunded) { - return $this->setData(OrderInterface::HIDDEN_TAX_REFUNDED, $hiddenTaxRefunded); + return $this->setData( + OrderInterface::DISCOUNT_TAX_COMPENSATION_REFUNDED, + $discountTaxCompensationRefunded + ); } /** * {@inheritdoc} */ - public function setBaseHiddenTaxRefunded($baseHiddenTaxRefunded) + public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensationRefunded) { - return $this->setData(OrderInterface::BASE_HIDDEN_TAX_REFUNDED, $baseHiddenTaxRefunded); + return $this->setData( + OrderInterface::BASE_DISCOUNT_TAX_COMPENSATION_REFUNDED, + $baseDiscountTaxCompensationRefunded + ); } /** diff --git a/app/code/Magento/Sales/Model/Order/Address.php b/app/code/Magento/Sales/Model/Order/Address.php index 4d5d86cc06960ca8169b7e080390b6f312737412..9486d6e0fb34b74714d5e102c6d1bb1a289c48ab 100644 --- a/app/code/Magento/Sales/Model/Order/Address.php +++ b/app/code/Magento/Sales/Model/Order/Address.php @@ -62,7 +62,7 @@ class Address extends AbstractModel implements OrderAddressInterface, AddressMod * @param \Magento\Sales\Model\OrderFactory $orderFactory * @param \Magento\Directory\Model\RegionFactory $regionFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -73,7 +73,7 @@ class Address extends AbstractModel implements OrderAddressInterface, AddressMod \Magento\Sales\Model\OrderFactory $orderFactory, \Magento\Directory\Model\RegionFactory $regionFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $data = $this->implodeStreetField($data); @@ -104,6 +104,8 @@ class Address extends AbstractModel implements OrderAddressInterface, AddressMod /** * Set order * + * @codeCoverageIgnore + * * @param \Magento\Sales\Model\Order $order * @return $this */ @@ -229,6 +231,32 @@ class Address extends AbstractModel implements OrderAddressInterface, AddressMod return $this->order; } + /** + * Retrieve street field of an address + * + * @return string[] + */ + public function getStreet() + { + if (is_array($this->getData(OrderAddressInterface::STREET))) { + return $this->getData(OrderAddressInterface::STREET); + } + return explode(PHP_EOL, $this->getData(OrderAddressInterface::STREET)); + } + + /** + * Get street line by number + * + * @param int $number + * @return string + */ + public function getStreetLine($number) + { + $lines = $this->getStreet(); + return isset($lines[$number - 1]) ? $lines[$number - 1] : ''; + } + + //@codeCoverageIgnoreStart /** * Returns address_type * @@ -420,31 +448,6 @@ class Address extends AbstractModel implements OrderAddressInterface, AddressMod return $this->getData(OrderAddressInterface::REGION_ID); } - /** - * Retrieve street field of an address - * - * @return string[] - */ - public function getStreet() - { - if (is_array($this->getData(OrderAddressInterface::STREET))) { - return $this->getData(OrderAddressInterface::STREET); - } - return explode(PHP_EOL, $this->getData(OrderAddressInterface::STREET)); - } - - /** - * Get street line by number - * - * @param int $number - * @return string - */ - public function getStreetLine($number) - { - $lines = $this->getStreet(); - return isset($lines[$number - 1]) ? $lines[$number - 1] : ''; - } - /** * Returns suffix * @@ -515,7 +518,6 @@ class Address extends AbstractModel implements OrderAddressInterface, AddressMod return $this->getData(OrderAddressInterface::VAT_REQUEST_SUCCESS); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo.php b/app/code/Magento/Sales/Model/Order/Creditmemo.php index 7fbc58d77171b57ccf708e81a9a4ad77a827293b..d0c564c01bf619a5babab63eefe194733eb8242c 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo.php @@ -129,7 +129,7 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt * @param \Magento\Sales\Model\Resource\Order\Creditmemo\Comment\CollectionFactory $commentCollectionFactory * @param PriceCurrencyInterface $priceCurrency * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -147,7 +147,7 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt \Magento\Sales\Model\Resource\Order\Creditmemo\Comment\CollectionFactory $commentCollectionFactory, PriceCurrencyInterface $priceCurrency, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_creditmemoConfig = $creditmemoConfig; @@ -398,7 +398,7 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt * If we not retrieve negative answer from payment yet */ if (is_null($canVoid)) { - $canVoid = $this->getOrder()->getPayment()->canVoid($this); + $canVoid = $this->getOrder()->getPayment()->canVoid(); if ($canVoid === false) { $this->setCanVoidFlag(false); $this->_saveBeforeDestruct = true; @@ -443,8 +443,8 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt $order->setBaseTaxRefunded($order->getBaseTaxRefunded() + $this->getBaseTaxAmount()); $order->setTaxRefunded($order->getTaxRefunded() + $this->getTaxAmount()); - $order->setBaseHiddenTaxRefunded($order->getBaseHiddenTaxRefunded() + $this->getBaseHiddenTaxAmount()); - $order->setHiddenTaxRefunded($order->getHiddenTaxRefunded() + $this->getHiddenTaxAmount()); + $order->setBaseDiscountTaxCompensationRefunded($order->getBaseDiscountTaxCompensationRefunded() + $this->getBaseDiscountTaxCompensationAmount()); + $order->setDiscountTaxCompensationRefunded($order->getDiscountTaxCompensationRefunded() + $this->getDiscountTaxCompensationAmount()); $order->setBaseShippingRefunded($order->getBaseShippingRefunded() + $this->getBaseShippingAmount()); $order->setShippingRefunded($order->getShippingRefunded() + $this->getShippingAmount()); @@ -767,16 +767,6 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt return !($this->getGrandTotal() <= 0 && !$this->getAllowZeroGrandTotal()); } - /** - * Returns discount_description - * - * @return string - */ - public function getDiscountDescription() - { - return $this->getData(CreditmemoInterface::DISCOUNT_DESCRIPTION); - } - /** * Return creditmemo items * @@ -793,6 +783,33 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt return $this->getData(CreditmemoInterface::ITEMS); } + /** + * Return creditmemo comments + * + * @return \Magento\Sales\Api\Data\CreditmemoCommentInterface[]|null + */ + public function getComments() + { + if ($this->getData(CreditmemoInterface::COMMENTS) == null) { + $this->setData( + CreditmemoInterface::COMMENTS, + $this->getCommentsCollection()->getItems() + ); + } + return $this->getData(CreditmemoInterface::COMMENTS); + } + + //@codeCoverageIgnoreStart + /** + * Returns discount_description + * + * @return string + */ + public function getDiscountDescription() + { + return $this->getData(CreditmemoInterface::DISCOUNT_DESCRIPTION); + } + /** * {@inheritdoc} */ @@ -914,13 +931,13 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt } /** - * Returns base_hidden_tax_amount + * Returns base_discount_tax_compensation_amount * * @return float */ - public function getBaseHiddenTaxAmount() + public function getBaseDiscountTaxCompensationAmount() { - return $this->getData(CreditmemoInterface::BASE_HIDDEN_TAX_AMOUNT); + return $this->getData(CreditmemoInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -934,13 +951,13 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt } /** - * Returns base_shipping_hidden_tax_amnt + * Returns base_shipping_discount_tax_compensation_amnt * * @return float */ - public function getBaseShippingHiddenTaxAmnt() + public function getBaseShippingDiscountTaxCompensationAmnt() { - return $this->getData(CreditmemoInterface::BASE_SHIPPING_HIDDEN_TAX_AMNT); + return $this->getData(CreditmemoInterface::BASE_SHIPPING_DISCOUNT_TAX_COMPENSATION_AMNT); } /** @@ -1092,13 +1109,13 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt } /** - * Returns hidden_tax_amount + * Returns discount_tax_compensation_amount * * @return float */ - public function getHiddenTaxAmount() + public function getDiscountTaxCompensationAmount() { - return $this->getData(CreditmemoInterface::HIDDEN_TAX_AMOUNT); + return $this->getData(CreditmemoInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -1152,13 +1169,13 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt } /** - * Returns shipping_hidden_tax_amount + * Returns shipping_discount_tax_compensation_amount * * @return float */ - public function getShippingHiddenTaxAmount() + public function getShippingDiscountTaxCompensationAmount() { - return $this->getData(CreditmemoInterface::SHIPPING_HIDDEN_TAX_AMOUNT); + return $this->getData(CreditmemoInterface::SHIPPING_DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -1292,22 +1309,6 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt return $this->getData(CreditmemoInterface::UPDATED_AT); } - /** - * Return creditmemo comments - * - * @return \Magento\Sales\Api\Data\CreditmemoCommentInterface[]|null - */ - public function getComments() - { - if ($this->getData(CreditmemoInterface::COMMENTS) == null) { - $this->setData( - CreditmemoInterface::COMMENTS, - $this->getCommentsCollection()->getItems() - ); - } - return $this->getData(CreditmemoInterface::COMMENTS); - } - /** * {@inheritdoc} */ @@ -1316,7 +1317,6 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt return $this->setData(CreditmemoInterface::COMMENTS, $comments); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ @@ -1584,33 +1584,33 @@ class Creditmemo extends AbstractModel implements EntityInterface, CreditmemoInt /** * {@inheritdoc} */ - public function setHiddenTaxAmount($amount) + public function setDiscountTaxCompensationAmount($amount) { - return $this->setData(CreditmemoInterface::HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(CreditmemoInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setBaseHiddenTaxAmount($amount) + public function setBaseDiscountTaxCompensationAmount($amount) { - return $this->setData(CreditmemoInterface::BASE_HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(CreditmemoInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setShippingHiddenTaxAmount($amount) + public function setShippingDiscountTaxCompensationAmount($amount) { - return $this->setData(CreditmemoInterface::SHIPPING_HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(CreditmemoInterface::SHIPPING_DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setBaseShippingHiddenTaxAmnt($amnt) + public function setBaseShippingDiscountTaxCompensationAmnt($amnt) { - return $this->setData(CreditmemoInterface::BASE_SHIPPING_HIDDEN_TAX_AMNT, $amnt); + return $this->setData(CreditmemoInterface::BASE_SHIPPING_DISCOUNT_TAX_COMPENSATION_AMNT, $amnt); } /** diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo/Comment.php b/app/code/Magento/Sales/Model/Order/Creditmemo/Comment.php index 2dac94c26b818bc2eab23acc83aea3079166a9d5..bb4ef3957d0487eee3c7581c872a5e8550f6ce3e 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo/Comment.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo/Comment.php @@ -34,7 +34,7 @@ class Comment extends AbstractModel implements CreditmemoCommentInterface * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -45,7 +45,7 @@ class Comment extends AbstractModel implements CreditmemoCommentInterface AttributeValueFactory $customAttributeFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -73,6 +73,8 @@ class Comment extends AbstractModel implements CreditmemoCommentInterface /** * Declare Creditmemo instance * + * @codeCoverageIgnore + * * @param \Magento\Sales\Model\Order\Creditmemo $creditmemo * @return $this */ @@ -85,6 +87,8 @@ class Comment extends AbstractModel implements CreditmemoCommentInterface /** * Retrieve Creditmemo instance * + * @codeCoverageIgnore + * * @return \Magento\Sales\Model\Order\Creditmemo */ public function getCreditmemo() @@ -105,6 +109,7 @@ class Comment extends AbstractModel implements CreditmemoCommentInterface return $this->_storeManager->getStore(); } + //@codeCoverageIgnoreStart /** * Returns comment * @@ -163,7 +168,6 @@ class Comment extends AbstractModel implements CreditmemoCommentInterface return $this->getData(CreditmemoCommentInterface::PARENT_ID); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo/Item.php b/app/code/Magento/Sales/Model/Order/Creditmemo/Item.php index 35d522427429f1d01def7ad15a2f784ee2e7f31f..a0d05ec5933d920a07643a1b0cc1d21ee06ab07a 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo/Item.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo/Item.php @@ -49,7 +49,7 @@ class Item extends AbstractModel implements CreditmemoItemInterface * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Sales\Model\Order\ItemFactory $orderItemFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -59,7 +59,7 @@ class Item extends AbstractModel implements CreditmemoItemInterface AttributeValueFactory $customAttributeFactory, \Magento\Sales\Model\Order\ItemFactory $orderItemFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -176,8 +176,12 @@ class Item extends AbstractModel implements CreditmemoItemInterface $orderItem->setQtyRefunded($orderItem->getQtyRefunded() + $this->getQty()); $orderItem->setTaxRefunded($orderItem->getTaxRefunded() + $this->getTaxAmount()); $orderItem->setBaseTaxRefunded($orderItem->getBaseTaxRefunded() + $this->getBaseTaxAmount()); - $orderItem->setHiddenTaxRefunded($orderItem->getHiddenTaxRefunded() + $this->getHiddenTaxAmount()); - $orderItem->setBaseHiddenTaxRefunded($orderItem->getBaseHiddenTaxRefunded() + $this->getBaseHiddenTaxAmount()); + $orderItem->setDiscountTaxCompensationRefunded( + $orderItem->getDiscountTaxCompensationRefunded() + $this->getDiscountTaxCompensationAmount() + ); + $orderItem->setBaseDiscountTaxCompensationRefunded( + $orderItem->getBaseDiscountTaxCompensationRefunded() + $this->getBaseDiscountTaxCompensationAmount() + ); $orderItem->setAmountRefunded($orderItem->getAmountRefunded() + $this->getRowTotal()); $orderItem->setBaseAmountRefunded($orderItem->getBaseAmountRefunded() + $this->getBaseRowTotal()); $orderItem->setDiscountRefunded($orderItem->getDiscountRefunded() + $this->getDiscountAmount()); @@ -194,11 +198,15 @@ class Item extends AbstractModel implements CreditmemoItemInterface $this->getOrderItem()->setQtyRefunded($this->getOrderItem()->getQtyRefunded() - $this->getQty()); $this->getOrderItem()->setTaxRefunded( $this->getOrderItem()->getTaxRefunded() - - $this->getOrderItem()->getBaseTaxAmount() * $this->getQty() / $this->getOrderItem()->getQtyOrdered() + $this->getOrderItem()->getBaseTaxAmount() * + $this->getQty() / + $this->getOrderItem()->getQtyOrdered() ); - $this->getOrderItem()->setHiddenTaxRefunded( - $this->getOrderItem()->getHiddenTaxRefunded() - - $this->getOrderItem()->getHiddenTaxAmount() * $this->getQty() / $this->getOrderItem()->getQtyOrdered() + $this->getOrderItem()->setDiscountTaxCompensationRefunded( + $this->getOrderItem()->getDiscountTaxCompensationRefunded() - + $this->getOrderItem()->getDiscountTaxCompensationAmount() * + $this->getQty() / + $this->getOrderItem()->getQtyOrdered() ); return $this; } @@ -284,13 +292,13 @@ class Item extends AbstractModel implements CreditmemoItemInterface } /** - * Returns base_hidden_tax_amount + * Returns base_discount_tax_compensation_amount * * @return float */ - public function getBaseHiddenTaxAmount() + public function getBaseDiscountTaxCompensationAmount() { - return $this->getData(CreditmemoItemInterface::BASE_HIDDEN_TAX_AMOUNT); + return $this->getData(CreditmemoItemInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -404,13 +412,13 @@ class Item extends AbstractModel implements CreditmemoItemInterface } /** - * Returns hidden_tax_amount + * Returns discount_tax_compensation_amount * * @return float */ - public function getHiddenTaxAmount() + public function getDiscountTaxCompensationAmount() { - return $this->getData(CreditmemoItemInterface::HIDDEN_TAX_AMOUNT); + return $this->getData(CreditmemoItemInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -737,17 +745,17 @@ class Item extends AbstractModel implements CreditmemoItemInterface /** * {@inheritdoc} */ - public function setHiddenTaxAmount($amount) + public function setDiscountTaxCompensationAmount($amount) { - return $this->setData(CreditmemoItemInterface::HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(CreditmemoItemInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setBaseHiddenTaxAmount($amount) + public function setBaseDiscountTaxCompensationAmount($amount) { - return $this->setData(CreditmemoItemInterface::BASE_HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(CreditmemoItemInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php index 3502252f9cad1d1112c56b606f1f76295c4ecb41..3d8eea7469b80f47dff4b5ed24b8e9eb7a50db4b 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php @@ -21,8 +21,8 @@ class Tax extends AbstractTotal $baseShippingTaxAmount = 0; $totalTax = 0; $baseTotalTax = 0; - $totalHiddenTax = 0; - $baseTotalHiddenTax = 0; + $totalDiscountTaxCompensation = 0; + $baseTotalDiscountTaxCompensation = 0; $order = $creditmemo->getOrder(); @@ -43,25 +43,29 @@ class Tax extends AbstractTotal $tax = $orderItemTax - $orderItem->getTaxRefunded(); $baseTax = $baseOrderItemTax - $orderItem->getTaxRefunded(); - $hiddenTax = $orderItem->getHiddenTaxInvoiced() - $orderItem->getHiddenTaxRefunded(); - $baseHiddenTax = $orderItem->getBaseHiddenTaxInvoiced() - $orderItem->getBaseHiddenTaxRefunded(); + $discountTaxCompensation = $orderItem->getDiscountTaxCompensationInvoiced() - + $orderItem->getDiscountTaxCompensationRefunded(); + $baseDiscountTaxCompensation = $orderItem->getBaseDiscountTaxCompensationInvoiced() - + $orderItem->getBaseDiscountTaxCompensationRefunded(); if (!$item->isLast()) { $availableQty = $orderItemQty - $orderItem->getQtyRefunded(); $tax = $creditmemo->roundPrice($tax / $availableQty * $item->getQty()); $baseTax = $creditmemo->roundPrice($baseTax / $availableQty * $item->getQty(), 'base'); - $hiddenTax = $creditmemo->roundPrice($hiddenTax / $availableQty * $item->getQty()); - $baseHiddenTax = $creditmemo->roundPrice($baseHiddenTax / $availableQty * $item->getQty(), 'base'); + $discountTaxCompensation = + $creditmemo->roundPrice($discountTaxCompensation / $availableQty * $item->getQty()); + $baseDiscountTaxCompensation = + $creditmemo->roundPrice($baseDiscountTaxCompensation / $availableQty * $item->getQty(), 'base'); } $item->setTaxAmount($tax); $item->setBaseTaxAmount($baseTax); - $item->setHiddenTaxAmount($hiddenTax); - $item->setBaseHiddenTaxAmount($baseHiddenTax); + $item->setDiscountTaxCompensationAmount($discountTaxCompensation); + $item->setBaseDiscountTaxCompensationAmount($baseDiscountTaxCompensation); $totalTax += $tax; $baseTotalTax += $baseTax; - $totalHiddenTax += $hiddenTax; - $baseTotalHiddenTax += $baseHiddenTax; + $totalDiscountTaxCompensation += $discountTaxCompensation; + $baseTotalDiscountTaxCompensation += $baseDiscountTaxCompensation; } } @@ -72,16 +76,21 @@ class Tax extends AbstractTotal $taxFactor = $creditmemo->getBaseShippingAmount() / $order->getBaseShippingAmount(); $shippingTaxAmount = $invoice->getShippingTaxAmount() * $taxFactor; $baseShippingTaxAmount = $invoice->getBaseShippingTaxAmount() * $taxFactor; - $totalHiddenTax += $invoice->getShippingHiddenTaxAmount() * $taxFactor; - $baseTotalHiddenTax += $invoice->getBaseShippingHiddenTaxAmnt() * $taxFactor; - $shippingHiddenTaxAmount = $invoice->getShippingHiddenTaxAmount() * $taxFactor; - $baseShippingHiddenTaxAmount = $invoice->getBaseShippingHiddenTaxAmnt() * $taxFactor; + $totalDiscountTaxCompensation += $invoice->getShippingDiscountTaxCompensationAmount() * $taxFactor; + $baseTotalDiscountTaxCompensation += + $invoice->getBaseShippingDiscountTaxCompensationAmnt() * $taxFactor; + $shippingDiscountTaxCompensationAmount = + $invoice->getShippingDiscountTaxCompensationAmount() * $taxFactor; + $baseShippingDiscountTaxCompensationAmount = + $invoice->getBaseShippingDiscountTaxCompensationAmnt() * $taxFactor; $shippingTaxAmount = $creditmemo->roundPrice($shippingTaxAmount); $baseShippingTaxAmount = $creditmemo->roundPrice($baseShippingTaxAmount, 'base'); - $totalHiddenTax = $creditmemo->roundPrice($totalHiddenTax); - $baseTotalHiddenTax = $creditmemo->roundPrice($baseTotalHiddenTax, 'base'); - $shippingHiddenTaxAmount = $creditmemo->roundPrice($shippingHiddenTaxAmount); - $baseShippingHiddenTaxAmount = $creditmemo->roundPrice($baseShippingHiddenTaxAmount, 'base'); + $totalDiscountTaxCompensation = $creditmemo->roundPrice($totalDiscountTaxCompensation); + $baseTotalDiscountTaxCompensation = $creditmemo->roundPrice($baseTotalDiscountTaxCompensation, 'base'); + $shippingDiscountTaxCompensationAmount = + $creditmemo->roundPrice($shippingDiscountTaxCompensationAmount); + $baseShippingDiscountTaxCompensationAmount = + $creditmemo->roundPrice($baseShippingDiscountTaxCompensationAmount, 'base'); if ($taxFactor < 1 && $invoice->getShippingTaxAmount() > 0) { $isPartialShippingRefunded = true; } @@ -96,8 +105,8 @@ class Tax extends AbstractTotal $shippingTaxAmount = 0; $baseShippingTaxAmount = 0; - $shippingHiddenTaxAmount = 0; - $baseShippingHiddenTaxAmount = 0; + $shippingDiscountTaxCompensationAmount = 0; + $baseShippingDiscountTaxCompensationAmount = 0; $shippingDelta = $baseOrderShippingAmount - $baseOrderShippingRefundedAmount; @@ -106,66 +115,74 @@ class Tax extends AbstractTotal $basePart = $creditmemo->getBaseShippingAmount() / $baseOrderShippingAmount; $shippingTaxAmount = $order->getShippingTaxAmount() * $part; $baseShippingTaxAmount = $order->getBaseShippingTaxAmount() * $basePart; - $shippingHiddenTaxAmount = $order->getShippingHiddenTaxAmount() * $part; - $baseShippingHiddenTaxAmount = $order->getBaseShippingHiddenTaxAmnt() * $basePart; + $shippingDiscountTaxCompensationAmount = $order->getShippingDiscountTaxCompensationAmount() * $part; + $baseShippingDiscountTaxCompensationAmount = + $order->getBaseShippingDiscountTaxCompensationAmnt() * $basePart; $shippingTaxAmount = $creditmemo->roundPrice($shippingTaxAmount); $baseShippingTaxAmount = $creditmemo->roundPrice($baseShippingTaxAmount, 'base'); - $shippingHiddenTaxAmount = $creditmemo->roundPrice($shippingHiddenTaxAmount); - $baseShippingHiddenTaxAmount = $creditmemo->roundPrice($baseShippingHiddenTaxAmount, 'base'); + $shippingDiscountTaxCompensationAmount = + $creditmemo->roundPrice($shippingDiscountTaxCompensationAmount); + $baseShippingDiscountTaxCompensationAmount = + $creditmemo->roundPrice($baseShippingDiscountTaxCompensationAmount, 'base'); if ($part < 1 && $order->getShippingTaxAmount() > 0) { $isPartialShippingRefunded = true; } } elseif ($shippingDelta == $creditmemo->getBaseShippingAmount()) { $shippingTaxAmount = $order->getShippingTaxAmount() - $order->getShippingTaxRefunded(); $baseShippingTaxAmount = $order->getBaseShippingTaxAmount() - $order->getBaseShippingTaxRefunded(); - $shippingHiddenTaxAmount = $order->getShippingHiddenTaxAmount() - - $order->getShippingHiddenTaxRefunded(); - $baseShippingHiddenTaxAmount = $order->getBaseShippingHiddenTaxAmnt() - - $order->getBaseShippingHiddenTaxRefunded(); + $shippingDiscountTaxCompensationAmount = $order->getShippingDiscountTaxCompensationAmount() - + $order->getShippingDiscountTaxCompensationRefunded(); + $baseShippingDiscountTaxCompensationAmount = $order->getBaseShippingDiscountTaxCompensationAmnt() - + $order->getBaseShippingDiscountTaxCompensationRefunded(); } $totalTax += $shippingTaxAmount; $baseTotalTax += $baseShippingTaxAmount; - $totalHiddenTax += $shippingHiddenTaxAmount; - $baseTotalHiddenTax += $baseShippingHiddenTaxAmount; + $totalDiscountTaxCompensation += $shippingDiscountTaxCompensationAmount; + $baseTotalDiscountTaxCompensation += $baseShippingDiscountTaxCompensationAmount; } $allowedTax = $order->getTaxInvoiced() - $order->getTaxRefunded() - $creditmemo->getTaxAmount(); $allowedBaseTax = $order->getBaseTaxInvoiced() - $order->getBaseTaxRefunded() - $creditmemo->getBaseTaxAmount(); - $allowedHiddenTax = $order->getHiddenTaxInvoiced() + - $order->getShippingHiddenTaxAmount() - - $order->getHiddenTaxRefunded() - - $order->getShippingHiddenTaxRefunded() - - $creditmemo->getHiddenTaxAmount() - - $creditmemo->getShippingHiddenTaxAmount(); - $allowedBaseHiddenTax = $order->getBaseHiddenTaxInvoiced() + - $order->getBaseShippingHiddenTaxAmnt() - - $order->getBaseHiddenTaxRefunded() - - $order->getBaseShippingHiddenTaxRefunded() - - $creditmemo->getBaseShippingHiddenTaxAmnt() - - $creditmemo->getBaseHiddenTaxAmount(); + $allowedDiscountTaxCompensation = $order->getDiscountTaxCompensationInvoiced() + + $order->getShippingDiscountTaxCompensationAmount() - + $order->getDiscountTaxCompensationRefunded() - + $order->getShippingDiscountTaxCompensationRefunded() - + $creditmemo->getDiscountTaxCompensationAmount() - + $creditmemo->getShippingDiscountTaxCompensationAmount(); + $allowedBaseDiscountTaxCompensation = $order->getBaseDiscountTaxCompensationInvoiced() + + $order->getBaseShippingDiscountTaxCompensationAmnt() - + $order->getBaseDiscountTaxCompensationRefunded() - + $order->getBaseShippingDiscountTaxCompensationRefunded() - + $creditmemo->getBaseShippingDiscountTaxCompensationAmnt() - + $creditmemo->getBaseDiscountTaxCompensationAmount(); if ($creditmemo->isLast() && !$isPartialShippingRefunded) { $totalTax = $allowedTax; $baseTotalTax = $allowedBaseTax; - $totalHiddenTax = $allowedHiddenTax; - $baseTotalHiddenTax = $allowedBaseHiddenTax; + $totalDiscountTaxCompensation = $allowedDiscountTaxCompensation; + $baseTotalDiscountTaxCompensation = $allowedBaseDiscountTaxCompensation; } else { $totalTax = min($allowedTax, $totalTax); $baseTotalTax = min($allowedBaseTax, $baseTotalTax); - $totalHiddenTax = min($allowedHiddenTax, $totalHiddenTax); - $baseTotalHiddenTax = min($allowedBaseHiddenTax, $baseTotalHiddenTax); + $totalDiscountTaxCompensation = + min($allowedDiscountTaxCompensation, $totalDiscountTaxCompensation); + $baseTotalDiscountTaxCompensation = + min($allowedBaseDiscountTaxCompensation, $baseTotalDiscountTaxCompensation); } $creditmemo->setTaxAmount($creditmemo->getTaxAmount() + $totalTax); $creditmemo->setBaseTaxAmount($creditmemo->getBaseTaxAmount() + $baseTotalTax); - $creditmemo->setHiddenTaxAmount($totalHiddenTax); - $creditmemo->setBaseHiddenTaxAmount($baseTotalHiddenTax); + $creditmemo->setDiscountTaxCompensationAmount($totalDiscountTaxCompensation); + $creditmemo->setBaseDiscountTaxCompensationAmount($baseTotalDiscountTaxCompensation); $creditmemo->setShippingTaxAmount($shippingTaxAmount); $creditmemo->setBaseShippingTaxAmount($baseShippingTaxAmount); - $creditmemo->setGrandTotal($creditmemo->getGrandTotal() + $totalTax + $totalHiddenTax); - $creditmemo->setBaseGrandTotal($creditmemo->getBaseGrandTotal() + $baseTotalTax + $baseTotalHiddenTax); + $creditmemo->setGrandTotal($creditmemo->getGrandTotal() + $totalTax + $totalDiscountTaxCompensation); + $creditmemo->setBaseGrandTotal( + $creditmemo->getBaseGrandTotal() + + $baseTotalTax + $baseTotalDiscountTaxCompensation + ); return $this; } } diff --git a/app/code/Magento/Sales/Model/Order/Invoice.php b/app/code/Magento/Sales/Model/Order/Invoice.php index 8042de931cedc8bf0748d3b1c10f1df1b6cc6e3d..0d093fedb883ae3e326732971001af21b1a78281 100644 --- a/app/code/Magento/Sales/Model/Order/Invoice.php +++ b/app/code/Magento/Sales/Model/Order/Invoice.php @@ -129,7 +129,7 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface * @param Invoice\CommentFactory $invoiceCommentFactory * @param \Magento\Sales\Model\Resource\Order\Invoice\Comment\CollectionFactory $commentCollectionFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -145,7 +145,7 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface \Magento\Sales\Model\Order\Invoice\CommentFactory $invoiceCommentFactory, \Magento\Sales\Model\Resource\Order\Invoice\Comment\CollectionFactory $commentCollectionFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_invoiceConfig = $invoiceConfig; @@ -299,7 +299,7 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface { if ($this->getState() == self::STATE_PAID) { if ($this->getCanVoidFlag() === null) { - return (bool)$this->getOrder()->getPayment()->canVoid($this); + return (bool)$this->getOrder()->getPayment()->canVoid(); } } return (bool)$this->getCanVoidFlag(); @@ -418,8 +418,12 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface $order->setTaxInvoiced($order->getTaxInvoiced() - $this->getTaxAmount()); $order->setBaseTaxInvoiced($order->getBaseTaxInvoiced() - $this->getBaseTaxAmount()); - $order->setHiddenTaxInvoiced($order->getHiddenTaxInvoiced() - $this->getHiddenTaxAmount()); - $order->setBaseHiddenTaxInvoiced($order->getBaseHiddenTaxInvoiced() - $this->getBaseHiddenTaxAmount()); + $order->setDiscountTaxCompensationInvoiced( + $order->getDiscountTaxCompensationInvoiced() - $this->getDiscountTaxCompensationAmount() + ); + $order->setBaseDiscountTaxCompensationInvoiced( + $order->getBaseDiscountTaxCompensationInvoiced() - $this->getBaseDiscountTaxCompensationAmount() + ); $order->setShippingTaxInvoiced($order->getShippingTaxInvoiced() - $this->getShippingTaxAmount()); $order->setBaseShippingTaxInvoiced($order->getBaseShippingTaxInvoiced() - $this->getBaseShippingTaxAmount()); @@ -623,8 +627,12 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface $order->setTaxInvoiced($order->getTaxInvoiced() + $this->getTaxAmount()); $order->setBaseTaxInvoiced($order->getBaseTaxInvoiced() + $this->getBaseTaxAmount()); - $order->setHiddenTaxInvoiced($order->getHiddenTaxInvoiced() + $this->getHiddenTaxAmount()); - $order->setBaseHiddenTaxInvoiced($order->getBaseHiddenTaxInvoiced() + $this->getBaseHiddenTaxAmount()); + $order->setDiscountTaxCompensationInvoiced( + $order->getDiscountTaxCompensationInvoiced() + $this->getDiscountTaxCompensationAmount() + ); + $order->setBaseDiscountTaxCompensationInvoiced( + $order->getBaseDiscountTaxCompensationInvoiced() + $this->getBaseDiscountTaxCompensationAmount() + ); $order->setShippingTaxInvoiced($order->getShippingTaxInvoiced() + $this->getShippingTaxAmount()); $order->setBaseShippingTaxInvoiced($order->getBaseShippingTaxInvoiced() + $this->getBaseShippingTaxAmount()); @@ -754,6 +762,41 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface return parent::_afterSave(); } + /** + * Returns invoice items + * + * @return \Magento\Sales\Api\Data\InvoiceItemInterface[] + */ + public function getItems() + { + if ($this->getData(InvoiceInterface::ITEMS) === null && $this->getId()) { + $collection = $this->_invoiceItemCollectionFactory->create()->setInvoiceFilter($this->getId()); + foreach ($collection as $item) { + $item->setInvoice($this); + } + $this->setData(InvoiceInterface::ITEMS, $collection->getItems()); + } + return $this->getData(InvoiceInterface::ITEMS); + } + + /** + * Return invoice comments + * + * @return \Magento\Sales\Api\Data\InvoiceCommentInterface[] + */ + public function getComments() + { + if ($this->getData(InvoiceInterface::COMMENTS) === null && $this->getId()) { + $collection = $this->_commentCollectionFactory->create()->setInvoiceFilter($this->getId()); + foreach ($collection as $comment) { + $comment->setInvoice($this); + } + $this->setData(InvoiceInterface::COMMENTS, $collection->getItems()); + } + return $this->getData(InvoiceInterface::COMMENTS); + } + + //@codeCoverageIgnoreStart /** * Returns increment id * @@ -784,23 +827,6 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface return $this->getData(InvoiceInterface::DISCOUNT_DESCRIPTION); } - /** - * Returns invoice items - * - * @return \Magento\Sales\Api\Data\InvoiceItemInterface[] - */ - public function getItems() - { - if ($this->getData(InvoiceInterface::ITEMS) === null && $this->getId()) { - $collection = $this->_invoiceItemCollectionFactory->create()->setInvoiceFilter($this->getId()); - foreach ($collection as $item) { - $item->setInvoice($this); - } - $this->setData(InvoiceInterface::ITEMS, $collection->getItems()); - } - return $this->getData(InvoiceInterface::ITEMS); - } - /** * {@inheritdoc} */ @@ -840,13 +866,13 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface } /** - * Returns base_hidden_tax_amount + * Returns base_discount_tax_compensation_amount * * @return float */ - public function getBaseHiddenTaxAmount() + public function getBaseDiscountTaxCompensationAmount() { - return $this->getData(InvoiceInterface::BASE_HIDDEN_TAX_AMOUNT); + return $this->getData(InvoiceInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -860,13 +886,13 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface } /** - * Returns base_shipping_hidden_tax_amnt + * Returns base_shipping_discount_tax_compensation_amnt * * @return float */ - public function getBaseShippingHiddenTaxAmnt() + public function getBaseShippingDiscountTaxCompensationAmnt() { - return $this->getData(InvoiceInterface::BASE_SHIPPING_HIDDEN_TAX_AMNT); + return $this->getData(InvoiceInterface::BASE_SHIPPING_DISCOUNT_TAX_COMPENSATION_AMNT); } /** @@ -1018,13 +1044,13 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface } /** - * Returns hidden_tax_amount + * Returns discount_tax_compensation_amount * * @return float */ - public function getHiddenTaxAmount() + public function getDiscountTaxCompensationAmount() { - return $this->getData(InvoiceInterface::HIDDEN_TAX_AMOUNT); + return $this->getData(InvoiceInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -1078,13 +1104,13 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface } /** - * Returns shipping_hidden_tax_amount + * Returns shipping_discount_tax_compensation_amount * * @return float */ - public function getShippingHiddenTaxAmount() + public function getShippingDiscountTaxCompensationAmount() { - return $this->getData(InvoiceInterface::SHIPPING_HIDDEN_TAX_AMOUNT); + return $this->getData(InvoiceInterface::SHIPPING_DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -1228,24 +1254,6 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface return $this->getData(InvoiceInterface::UPDATED_AT); } - /** - * Return invoice comments - * - * @return \Magento\Sales\Api\Data\InvoiceCommentInterface[] - */ - public function getComments() - { - if ($this->getData(InvoiceInterface::COMMENTS) === null && $this->getId()) { - $collection = $this->_commentCollectionFactory->create()->setInvoiceFilter($this->getId()); - foreach ($collection as $comment) { - $comment->setInvoice($this); - } - $this->setData(InvoiceInterface::COMMENTS, $collection->getItems()); - } - return $this->getData(InvoiceInterface::COMMENTS); - } - - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ @@ -1521,33 +1529,33 @@ class Invoice extends AbstractModel implements EntityInterface, InvoiceInterface /** * {@inheritdoc} */ - public function setHiddenTaxAmount($amount) + public function setDiscountTaxCompensationAmount($amount) { - return $this->setData(InvoiceInterface::HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(InvoiceInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setBaseHiddenTaxAmount($amount) + public function setBaseDiscountTaxCompensationAmount($amount) { - return $this->setData(InvoiceInterface::BASE_HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(InvoiceInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setShippingHiddenTaxAmount($amount) + public function setShippingDiscountTaxCompensationAmount($amount) { - return $this->setData(InvoiceInterface::SHIPPING_HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(InvoiceInterface::SHIPPING_DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setBaseShippingHiddenTaxAmnt($amnt) + public function setBaseShippingDiscountTaxCompensationAmnt($amnt) { - return $this->setData(InvoiceInterface::BASE_SHIPPING_HIDDEN_TAX_AMNT, $amnt); + return $this->setData(InvoiceInterface::BASE_SHIPPING_DISCOUNT_TAX_COMPENSATION_AMNT, $amnt); } /** diff --git a/app/code/Magento/Sales/Model/Order/Invoice/Comment.php b/app/code/Magento/Sales/Model/Order/Invoice/Comment.php index e7b99dea1593ed699d4f76e6f745256f780e8075..8e6190f47f2f467e2ea696a2c39c8cbfb153c0a0 100644 --- a/app/code/Magento/Sales/Model/Order/Invoice/Comment.php +++ b/app/code/Magento/Sales/Model/Order/Invoice/Comment.php @@ -34,7 +34,7 @@ class Comment extends AbstractModel implements InvoiceCommentInterface * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -45,7 +45,7 @@ class Comment extends AbstractModel implements InvoiceCommentInterface AttributeValueFactory $customAttributeFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/Sales/Model/Order/Invoice/Item.php b/app/code/Magento/Sales/Model/Order/Invoice/Item.php index 5e29ee78a7afa62532f60e3f1325071f54e0083b..f30f9ec162f9a6c226f1cce65ebc9e3566b5b0a3 100644 --- a/app/code/Magento/Sales/Model/Order/Invoice/Item.php +++ b/app/code/Magento/Sales/Model/Order/Invoice/Item.php @@ -61,7 +61,7 @@ class Item extends AbstractModel implements InvoiceItemInterface * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Sales\Model\Order\ItemFactory $orderItemFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -71,7 +71,7 @@ class Item extends AbstractModel implements InvoiceItemInterface AttributeValueFactory $customAttributeFactory, \Magento\Sales\Model\Order\ItemFactory $orderItemFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -110,6 +110,8 @@ class Item extends AbstractModel implements InvoiceItemInterface /** * Retrieve invoice instance * + * @codeCoverageIgnore + * * @return \Magento\Sales\Model\Order\Invoice */ public function getInvoice() @@ -150,6 +152,8 @@ class Item extends AbstractModel implements InvoiceItemInterface /** * Declare qty * + * @codeCoverageIgnore + * * @param float $qty * @return $this */ @@ -170,8 +174,12 @@ class Item extends AbstractModel implements InvoiceItemInterface $orderItem->setTaxInvoiced($orderItem->getTaxInvoiced() + $this->getTaxAmount()); $orderItem->setBaseTaxInvoiced($orderItem->getBaseTaxInvoiced() + $this->getBaseTaxAmount()); - $orderItem->setHiddenTaxInvoiced($orderItem->getHiddenTaxInvoiced() + $this->getHiddenTaxAmount()); - $orderItem->setBaseHiddenTaxInvoiced($orderItem->getBaseHiddenTaxInvoiced() + $this->getBaseHiddenTaxAmount()); + $orderItem->setDiscountTaxCompensationInvoiced( + $orderItem->getDiscountTaxCompensationInvoiced() + $this->getDiscountTaxCompensationAmount() + ); + $orderItem->setBaseDiscountTaxCompensationInvoiced( + $orderItem->getBaseDiscountTaxCompensationInvoiced() + $this->getBaseDiscountTaxCompensationAmount() + ); $orderItem->setDiscountInvoiced($orderItem->getDiscountInvoiced() + $this->getDiscountAmount()); $orderItem->setBaseDiscountInvoiced($orderItem->getBaseDiscountInvoiced() + $this->getBaseDiscountAmount()); @@ -193,8 +201,12 @@ class Item extends AbstractModel implements InvoiceItemInterface $orderItem->setTaxInvoiced($orderItem->getTaxInvoiced() - $this->getTaxAmount()); $orderItem->setBaseTaxInvoiced($orderItem->getBaseTaxInvoiced() - $this->getBaseTaxAmount()); - $orderItem->setHiddenTaxInvoiced($orderItem->getHiddenTaxInvoiced() - $this->getHiddenTaxAmount()); - $orderItem->setBaseHiddenTaxInvoiced($orderItem->getBaseHiddenTaxInvoiced() - $this->getBaseHiddenTaxAmount()); + $orderItem->setDiscountTaxCompensationInvoiced( + $orderItem->getDiscountTaxCompensationInvoiced() - $this->getDiscountTaxCompensationAmount() + ); + $orderItem->setBaseDiscountTaxCompensationInvoiced( + $orderItem->getBaseDiscountTaxCompensationInvoiced() - $this->getBaseDiscountTaxCompensationAmount() + ); $orderItem->setDiscountInvoiced($orderItem->getDiscountInvoiced() - $this->getDiscountAmount()); $orderItem->setBaseDiscountInvoiced($orderItem->getBaseDiscountInvoiced() - $this->getBaseDiscountAmount()); @@ -253,6 +265,7 @@ class Item extends AbstractModel implements InvoiceItemInterface return false; } + //@codeCoverageIgnoreStart /** * Returns additional_data * @@ -284,13 +297,13 @@ class Item extends AbstractModel implements InvoiceItemInterface } /** - * Returns base_hidden_tax_amount + * Returns base_discount_tax_compensation_amount * * @return float */ - public function getBaseHiddenTaxAmount() + public function getBaseDiscountTaxCompensationAmount() { - return $this->getData(InvoiceItemInterface::BASE_HIDDEN_TAX_AMOUNT); + return $this->getData(InvoiceItemInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -364,13 +377,13 @@ class Item extends AbstractModel implements InvoiceItemInterface } /** - * Returns hidden_tax_amount + * Returns discount_tax_compensation_amount * * @return float */ - public function getHiddenTaxAmount() + public function getDiscountTaxCompensationAmount() { - return $this->getData(InvoiceItemInterface::HIDDEN_TAX_AMOUNT); + return $this->getData(InvoiceItemInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** @@ -483,7 +496,6 @@ class Item extends AbstractModel implements InvoiceItemInterface return $this->getData(InvoiceItemInterface::TAX_AMOUNT); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ @@ -647,17 +659,17 @@ class Item extends AbstractModel implements InvoiceItemInterface /** * {@inheritdoc} */ - public function setHiddenTaxAmount($amount) + public function setDiscountTaxCompensationAmount($amount) { - return $this->setData(InvoiceItemInterface::HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(InvoiceItemInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setBaseHiddenTaxAmount($amount) + public function setBaseDiscountTaxCompensationAmount($amount) { - return $this->setData(InvoiceItemInterface::BASE_HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(InvoiceItemInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** diff --git a/app/code/Magento/Sales/Model/Order/Invoice/Total/Tax.php b/app/code/Magento/Sales/Model/Order/Invoice/Total/Tax.php index d1d2cee1f3ec2ac6ee6ad92a7c84b6ee57ac7bec..4db15c4787dabe3fac3476b6e8a73764c250e929 100644 --- a/app/code/Magento/Sales/Model/Order/Invoice/Total/Tax.php +++ b/app/code/Magento/Sales/Model/Order/Invoice/Total/Tax.php @@ -13,13 +13,14 @@ class Tax extends AbstractTotal * @param \Magento\Sales\Model\Order\Invoice $invoice * @return $this * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function collect(\Magento\Sales\Model\Order\Invoice $invoice) { $totalTax = 0; $baseTotalTax = 0; - $totalHiddenTax = 0; - $baseTotalHiddenTax = 0; + $totalDiscountTaxCompensation = 0; + $baseTotalDiscountTaxCompensation = 0; $order = $invoice->getOrder(); @@ -28,7 +29,7 @@ class Tax extends AbstractTotal $orderItem = $item->getOrderItem(); $orderItemQty = $orderItem->getQtyOrdered(); - if (($orderItem->getTaxAmount() || $orderItem->getHiddenTaxAmount()) && $orderItemQty) { + if (($orderItem->getTaxAmount() || $orderItem->getDiscountTaxCompensationAmount()) && $orderItemQty) { if ($item->getOrderItem()->isDummy() || $item->getQty() <= 0) { continue; } @@ -38,68 +39,79 @@ class Tax extends AbstractTotal */ $tax = $orderItem->getTaxAmount() - $orderItem->getTaxInvoiced(); $baseTax = $orderItem->getBaseTaxAmount() - $orderItem->getBaseTaxInvoiced(); - $hiddenTax = $orderItem->getHiddenTaxAmount() - $orderItem->getHiddenTaxInvoiced(); - $baseHiddenTax = $orderItem->getBaseHiddenTaxAmount() - $orderItem->getBaseHiddenTaxInvoiced(); + $discountTaxCompensation = $orderItem->getDiscountTaxCompensationAmount() - + $orderItem->getDiscountTaxCompensationInvoiced(); + $baseDiscountTaxCompensation = $orderItem->getBaseDiscountTaxCompensationAmount() - + $orderItem->getBaseDiscountTaxCompensationInvoiced(); if (!$item->isLast()) { $availableQty = $orderItemQty - $orderItem->getQtyInvoiced(); $tax = $invoice->roundPrice($tax / $availableQty * $item->getQty()); $baseTax = $invoice->roundPrice($baseTax / $availableQty * $item->getQty(), 'base'); - $hiddenTax = $invoice->roundPrice($hiddenTax / $availableQty * $item->getQty()); - $baseHiddenTax = $invoice->roundPrice($baseHiddenTax / $availableQty * $item->getQty(), 'base'); + $discountTaxCompensation = $invoice->roundPrice( + $discountTaxCompensation / $availableQty * $item->getQty() + ); + $baseDiscountTaxCompensation = $invoice->roundPrice( + $baseDiscountTaxCompensation / + $availableQty * $item->getQty(), + 'base' + ); } $item->setTaxAmount($tax); $item->setBaseTaxAmount($baseTax); - $item->setHiddenTaxAmount($hiddenTax); - $item->setBaseHiddenTaxAmount($baseHiddenTax); + $item->setDiscountTaxCompensationAmount($discountTaxCompensation); + $item->setBaseDiscountTaxCompensationAmount($baseDiscountTaxCompensation); $totalTax += $tax; $baseTotalTax += $baseTax; - $totalHiddenTax += $hiddenTax; - $baseTotalHiddenTax += $baseHiddenTax; + $totalDiscountTaxCompensation += $discountTaxCompensation; + $baseTotalDiscountTaxCompensation += $baseDiscountTaxCompensation; } } if ($this->_canIncludeShipping($invoice)) { $totalTax += $order->getShippingTaxAmount(); $baseTotalTax += $order->getBaseShippingTaxAmount(); - $totalHiddenTax += $order->getShippingHiddenTaxAmount(); - $baseTotalHiddenTax += $order->getBaseShippingHiddenTaxAmnt(); + $totalDiscountTaxCompensation += $order->getShippingDiscountTaxCompensationAmount(); + $baseTotalDiscountTaxCompensation += $order->getBaseShippingDiscountTaxCompensationAmnt(); $invoice->setShippingTaxAmount($order->getShippingTaxAmount()); $invoice->setBaseShippingTaxAmount($order->getBaseShippingTaxAmount()); - $invoice->setShippingHiddenTaxAmount($order->getShippingHiddenTaxAmount()); - $invoice->setBaseShippingHiddenTaxAmnt($order->getBaseShippingHiddenTaxAmnt()); + $invoice->setShippingDiscountTaxCompensationAmount($order->getShippingDiscountTaxCompensationAmount()); + $invoice->setBaseShippingDiscountTaxCompensationAmnt($order->getBaseShippingDiscountTaxCompensationAmnt()); } $allowedTax = $order->getTaxAmount() - $order->getTaxInvoiced(); $allowedBaseTax = $order->getBaseTaxAmount() - $order->getBaseTaxInvoiced(); - $allowedHiddenTax = $order->getHiddenTaxAmount() + - $order->getShippingHiddenTaxAmount() - - $order->getHiddenTaxInvoiced() - - $order->getShippingHiddenTaxInvoiced(); - $allowedBaseHiddenTax = $order->getBaseHiddenTaxAmount() + - $order->getBaseShippingHiddenTaxAmnt() - - $order->getBaseHiddenTaxInvoiced() - - $order->getBaseShippingHiddenTaxInvoiced(); + $allowedDiscountTaxCompensation = $order->getDiscountTaxCompensationAmount() + + $order->getShippingDiscountTaxCompensationAmount() - + $order->getDiscountTaxCompensationInvoiced() - + $order->getShippingDiscountTaxCompensationInvoiced(); + $allowedBaseDiscountTaxCompensation = $order->getBaseDiscountTaxCompensationAmount() + + $order->getBaseShippingDiscountTaxCompensationAmnt() - + $order->getBaseDiscountTaxCompensationInvoiced() - + $order->getBaseShippingDiscountTaxCompensationInvoiced(); if ($invoice->isLast()) { $totalTax = $allowedTax; $baseTotalTax = $allowedBaseTax; - $totalHiddenTax = $allowedHiddenTax; - $baseTotalHiddenTax = $allowedBaseHiddenTax; + $totalDiscountTaxCompensation = $allowedDiscountTaxCompensation; + $baseTotalDiscountTaxCompensation = $allowedBaseDiscountTaxCompensation; } else { $totalTax = min($allowedTax, $totalTax); $baseTotalTax = min($allowedBaseTax, $baseTotalTax); - $totalHiddenTax = min($allowedHiddenTax, $totalHiddenTax); - $baseTotalHiddenTax = min($allowedBaseHiddenTax, $baseTotalHiddenTax); + $totalDiscountTaxCompensation = min($allowedDiscountTaxCompensation, $totalDiscountTaxCompensation); + $baseTotalDiscountTaxCompensation = min( + $allowedBaseDiscountTaxCompensation, + $baseTotalDiscountTaxCompensation + ); } $invoice->setTaxAmount($totalTax); $invoice->setBaseTaxAmount($baseTotalTax); - $invoice->setHiddenTaxAmount($totalHiddenTax); - $invoice->setBaseHiddenTaxAmount($baseTotalHiddenTax); + $invoice->setDiscountTaxCompensationAmount($totalDiscountTaxCompensation); + $invoice->setBaseDiscountTaxCompensationAmount($baseTotalDiscountTaxCompensation); - $invoice->setGrandTotal($invoice->getGrandTotal() + $totalTax + $totalHiddenTax); - $invoice->setBaseGrandTotal($invoice->getBaseGrandTotal() + $baseTotalTax + $baseTotalHiddenTax); + $invoice->setGrandTotal($invoice->getGrandTotal() + $totalTax + $totalDiscountTaxCompensation); + $invoice->setBaseGrandTotal($invoice->getBaseGrandTotal() + $baseTotalTax + $baseTotalDiscountTaxCompensation); return $this; } diff --git a/app/code/Magento/Sales/Model/Order/Item.php b/app/code/Magento/Sales/Model/Order/Item.php index 602cde0a32e3ccbbc03195aa4933e4fdb81b3079..c4d7f501e4a00d97c7ba72a9f0adcdaae7c6a07e 100644 --- a/app/code/Magento/Sales/Model/Order/Item.php +++ b/app/code/Magento/Sales/Model/Order/Item.php @@ -106,7 +106,7 @@ class Item extends AbstractModel implements OrderItemInterface * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -119,7 +119,7 @@ class Item extends AbstractModel implements OrderItemInterface \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -401,9 +401,9 @@ class Item extends AbstractModel implements OrderItemInterface $this->setTaxCanceled( $this->getTaxCanceled() + $this->getBaseTaxAmount() * $this->getQtyCanceled() / $this->getQtyOrdered() ); - $this->setHiddenTaxCanceled( - $this->getHiddenTaxCanceled() + - $this->getHiddenTaxAmount() * $this->getQtyCanceled() / $this->getQtyOrdered() + $this->setDiscountTaxCompensationCanceled( + $this->getDiscountTaxCompensationCanceled() + + $this->getDiscountTaxCompensationAmount() * $this->getQtyCanceled() / $this->getQtyOrdered() ); } return $this; @@ -688,6 +688,7 @@ class Item extends AbstractModel implements OrderItemInterface return $this->_storeManager->getStore(); } + //@codeCoverageIgnoreStart /** * Returns additional_data * @@ -769,33 +770,33 @@ class Item extends AbstractModel implements OrderItemInterface } /** - * Returns base_hidden_tax_amount + * Returns base_discount_tax_compensation_amount * * @return float */ - public function getBaseHiddenTaxAmount() + public function getBaseDiscountTaxCompensationAmount() { - return $this->getData(OrderItemInterface::BASE_HIDDEN_TAX_AMOUNT); + return $this->getData(OrderItemInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** - * Returns base_hidden_tax_invoiced + * Returns base_discount_tax_compensation_invoiced * * @return float */ - public function getBaseHiddenTaxInvoiced() + public function getBaseDiscountTaxCompensationInvoiced() { - return $this->getData(OrderItemInterface::BASE_HIDDEN_TAX_INVOICED); + return $this->getData(OrderItemInterface::BASE_DISCOUNT_TAX_COMPENSATION_INVOICED); } /** - * Returns base_hidden_tax_refunded + * Returns base_discount_tax_compensation_refunded * * @return float */ - public function getBaseHiddenTaxRefunded() + public function getBaseDiscountTaxCompensationRefunded() { - return $this->getData(OrderItemInterface::BASE_HIDDEN_TAX_REFUNDED); + return $this->getData(OrderItemInterface::BASE_DISCOUNT_TAX_COMPENSATION_REFUNDED); } /** @@ -1167,43 +1168,43 @@ class Item extends AbstractModel implements OrderItemInterface } /** - * Returns hidden_tax_amount + * Returns discount_tax_compensation_amount * * @return float */ - public function getHiddenTaxAmount() + public function getDiscountTaxCompensationAmount() { - return $this->getData(OrderItemInterface::HIDDEN_TAX_AMOUNT); + return $this->getData(OrderItemInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT); } /** - * Returns hidden_tax_canceled + * Returns discount_tax_compensation_canceled * * @return float */ - public function getHiddenTaxCanceled() + public function getDiscountTaxCompensationCanceled() { - return $this->getData(OrderItemInterface::HIDDEN_TAX_CANCELED); + return $this->getData(OrderItemInterface::DISCOUNT_TAX_COMPENSATION_CANCELED); } /** - * Returns hidden_tax_invoiced + * Returns discount_tax_compensation_invoiced * * @return float */ - public function getHiddenTaxInvoiced() + public function getDiscountTaxCompensationInvoiced() { - return $this->getData(OrderItemInterface::HIDDEN_TAX_INVOICED); + return $this->getData(OrderItemInterface::DISCOUNT_TAX_COMPENSATION_INVOICED); } /** - * Returns hidden_tax_refunded + * Returns discount_tax_compensation_refunded * * @return float */ - public function getHiddenTaxRefunded() + public function getDiscountTaxCompensationRefunded() { - return $this->getData(OrderItemInterface::HIDDEN_TAX_REFUNDED); + return $this->getData(OrderItemInterface::DISCOUNT_TAX_COMPENSATION_REFUNDED); } /** @@ -1606,7 +1607,6 @@ class Item extends AbstractModel implements OrderItemInterface return $this->getData(OrderItemInterface::WEIGHT); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ @@ -2042,49 +2042,55 @@ class Item extends AbstractModel implements OrderItemInterface /** * {@inheritdoc} */ - public function setHiddenTaxAmount($amount) + public function setDiscountTaxCompensationAmount($amount) { - return $this->setData(OrderItemInterface::HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(OrderItemInterface::DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setBaseHiddenTaxAmount($amount) + public function setBaseDiscountTaxCompensationAmount($amount) { - return $this->setData(OrderItemInterface::BASE_HIDDEN_TAX_AMOUNT, $amount); + return $this->setData(OrderItemInterface::BASE_DISCOUNT_TAX_COMPENSATION_AMOUNT, $amount); } /** * {@inheritdoc} */ - public function setHiddenTaxInvoiced($hiddenTaxInvoiced) + public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoiced) { - return $this->setData(OrderItemInterface::HIDDEN_TAX_INVOICED, $hiddenTaxInvoiced); + return $this->setData(OrderItemInterface::DISCOUNT_TAX_COMPENSATION_INVOICED, $discountTaxCompensationInvoiced); } /** * {@inheritdoc} */ - public function setBaseHiddenTaxInvoiced($baseHiddenTaxInvoiced) + public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensationInvoiced) { - return $this->setData(OrderItemInterface::BASE_HIDDEN_TAX_INVOICED, $baseHiddenTaxInvoiced); + return $this->setData( + OrderItemInterface::BASE_DISCOUNT_TAX_COMPENSATION_INVOICED, + $baseDiscountTaxCompensationInvoiced + ); } /** * {@inheritdoc} */ - public function setHiddenTaxRefunded($hiddenTaxRefunded) + public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefunded) { - return $this->setData(OrderItemInterface::HIDDEN_TAX_REFUNDED, $hiddenTaxRefunded); + return $this->setData(OrderItemInterface::DISCOUNT_TAX_COMPENSATION_REFUNDED, $discountTaxCompensationRefunded); } /** * {@inheritdoc} */ - public function setBaseHiddenTaxRefunded($baseHiddenTaxRefunded) + public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensationRefunded) { - return $this->setData(OrderItemInterface::BASE_HIDDEN_TAX_REFUNDED, $baseHiddenTaxRefunded); + return $this->setData( + OrderItemInterface::BASE_DISCOUNT_TAX_COMPENSATION_REFUNDED, + $baseDiscountTaxCompensationRefunded + ); } /** @@ -2098,9 +2104,9 @@ class Item extends AbstractModel implements OrderItemInterface /** * {@inheritdoc} */ - public function setHiddenTaxCanceled($hiddenTaxCanceled) + public function setDiscountTaxCompensationCanceled($discountTaxCompensationCanceled) { - return $this->setData(OrderItemInterface::HIDDEN_TAX_CANCELED, $hiddenTaxCanceled); + return $this->setData(OrderItemInterface::DISCOUNT_TAX_COMPENSATION_CANCELED, $discountTaxCompensationCanceled); } /** diff --git a/app/code/Magento/Sales/Model/Order/Payment.php b/app/code/Magento/Sales/Model/Order/Payment.php index 8bb5b416876d01ee5ad58c0f4c742a64c36d6885..6ecf8a298cd1a663af73808e5c79eb6b664d458a 100644 --- a/app/code/Magento/Sales/Model/Order/Payment.php +++ b/app/code/Magento/Sales/Model/Order/Payment.php @@ -112,7 +112,7 @@ class Payment extends Info implements OrderPaymentInterface * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param PriceCurrencyInterface $priceCurrency * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -129,7 +129,7 @@ class Payment extends Info implements OrderPaymentInterface \Magento\Store\Model\StoreManagerInterface $storeManager, PriceCurrencyInterface $priceCurrency, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->priceCurrency = $priceCurrency; @@ -163,6 +163,8 @@ class Payment extends Info implements OrderPaymentInterface /** * Declare order model object * + * @codeCoverageIgnore + * * @param Order $order * @return $this */ @@ -175,6 +177,8 @@ class Payment extends Info implements OrderPaymentInterface /** * Retrieve order model object * + * @codeCoverageIgnore + * * @return Order */ public function getOrder() @@ -396,9 +400,11 @@ class Payment extends Info implements OrderPaymentInterface * Capture attempt will happen only when invoice is not yet paid and the transaction can be paid */ if ($invoice->getTransactionId()) { - $this->getMethodInstance()->setStore( + $method = $this->getMethodInstance(); + $method->setStore( $order->getStoreId() - )->fetchTransactionInfo( + ); + $method->fetchTransactionInfo( $this, $invoice->getTransactionId() ); @@ -406,7 +412,11 @@ class Payment extends Info implements OrderPaymentInterface $status = false; if (!$invoice->getIsPaid() && !$this->getIsTransactionPending()) { // attempt to capture: this can trigger "is_transaction_pending" - $this->getMethodInstance()->setStore($order->getStoreId())->capture($this, $amountToCapture); + $method = $this->getMethodInstance(); + $method->setStore( + $order->getStoreId() + ); + $method->capture($this, $amountToCapture); $transaction = $this->_addTransaction( Transaction::TYPE_CAPTURE, @@ -441,7 +451,8 @@ class Payment extends Info implements OrderPaymentInterface $order->setState($state) ->setStatus($status) ->addStatusHistoryComment($message); - $this->getMethodInstance()->processInvoice($invoice, $this); + + $invoice->setTransactionId($this->getLastTransId()); return $this; } throw new \Magento\Framework\Exception\LocalizedException( @@ -601,13 +612,12 @@ class Payment extends Info implements OrderPaymentInterface /** * Check order payment void availability * - * @param \Magento\Framework\Object $document * @return bool */ - public function canVoid(\Magento\Framework\Object $document) + public function canVoid() { if (null === $this->_canVoidLookup) { - $this->_canVoidLookup = (bool)$this->getMethodInstance()->canVoid($document); + $this->_canVoidLookup = (bool)$this->getMethodInstance()->canVoid(); if ($this->_canVoidLookup) { $authTransaction = $this->getAuthorizationTransaction(); $this->_canVoidLookup = (bool)$authTransaction && !(int)$authTransaction->getIsClosed(); @@ -681,16 +691,14 @@ class Payment extends Info implements OrderPaymentInterface try { $gateway->setStore( $this->getOrder()->getStoreId() - )->processBeforeRefund( - $invoice, - $this - )->refund( + ); + $this->setRefundTransactionId($invoice->getTransactionId()); + $gateway->refund( $this, $baseAmountToRefund - )->processCreditmemo( - $creditmemo, - $this ); + + $creditmemo->setTransactionId($this->getLastTransId()); } catch (\Magento\Framework\Exception\LocalizedException $e) { if (!$captureTxn) { throw new \Magento\Framework\Exception\LocalizedException( @@ -872,7 +880,7 @@ class Payment extends Info implements OrderPaymentInterface public function cancel() { $isOnline = true; - if (!$this->canVoid($this)) { + if (!$this->canVoid()) { $isOnline = false; } @@ -896,7 +904,7 @@ class Payment extends Info implements OrderPaymentInterface */ public function canReviewPayment() { - return (bool)$this->getMethodInstance()->canReviewPayment($this); + return (bool)$this->getMethodInstance()->canReviewPayment(); } /** @@ -917,7 +925,8 @@ class Payment extends Info implements OrderPaymentInterface $transactionId = $this->getLastTransId(); /** @var \Magento\Payment\Model\Method\AbstractMethod $method */ - $method = $this->getMethodInstance()->setStore($this->getOrder()->getStoreId()); + $method = $this->getMethodInstance(); + $method->setStore($this->getOrder()->getStoreId()); if ($method->acceptPayment($this)) { $invoice = $this->_getInvoiceForTransactionId($transactionId); $message = $this->_appendTransactionToMessage( @@ -939,15 +948,19 @@ class Payment extends Info implements OrderPaymentInterface /** * Accept order with payment method instance * + * @param bool $isOnline * @return $this + * @throws \Magento\Framework\Exception\LocalizedException */ - public function deny() + public function deny($isOnline = true) { - $transactionId = $this->getLastTransId(); + $transactionId = $isOnline ? $this->getLastTransId() : $this->getTransactionId(); - /** @var \Magento\Payment\Model\Method\AbstractMethod $method */ - $method = $this->getMethodInstance()->setStore($this->getOrder()->getStoreId()); - if ($method->denyPayment($this)) { + $result = $isOnline ? + $this->getMethodInstance()->setStore($this->getOrder()->getStoreId())->denyPayment($this) : + (bool)$this->getNotificationResult(); + + if ($result) { $invoice = $this->_getInvoiceForTransactionId($transactionId); $message = $this->_appendTransactionToMessage( $transactionId, @@ -955,9 +968,11 @@ class Payment extends Info implements OrderPaymentInterface ); $this->cancelInvoiceAndRegisterCancellation($invoice, $message); } else { + $txt = $isOnline ? + 'There is no need to deny this payment.' : 'Registered notification about denied payment.'; $message = $this->_appendTransactionToMessage( $transactionId, - $this->_prependMessage(__('There is no need to deny this payment.')) + $this->_prependMessage(__($txt)) ); $this->setOrderStatePaymentReview($message, $transactionId); } @@ -967,16 +982,21 @@ class Payment extends Info implements OrderPaymentInterface /** * Performs registered payment update. * - * @throws \Magento\Framework\Exception\LocalizedException + * @param bool $isOnline * @return $this + * @throws \Magento\Framework\Exception\LocalizedException */ - public function update() + public function update($isOnline = true) { - $transactionId = $this->getLastTransId(); + $transactionId = $isOnline ? $this->getLastTransId() : $this->getTransactionId(); $invoice = $this->_getInvoiceForTransactionId($transactionId); - $this->getMethodInstance()->setStore($this->getOrder()->getStoreId()) - ->fetchTransactionInfo($this, $transactionId); + + if ($isOnline) { + $method = $this->getMethodInstance(); + $method->setStore($this->getOrder()->getStoreId()); + $method->fetchTransactionInfo($this, $transactionId); + } if ($this->getIsTransactionApproved()) { $message = $this->_appendTransactionToMessage( @@ -1081,9 +1101,12 @@ class Payment extends Info implements OrderPaymentInterface // do ordering $order = $this->getOrder(); + $state = Order::STATE_PROCESSING; $status = false; - $this->getMethodInstance()->setStore($order->getStoreId())->order($this, $amount); + $method = $this->getMethodInstance(); + $method->setStore($order->getStoreId()); + $method->order($this, $amount); if ($this->getSkipOrderProcessing()) { return $this; @@ -1146,7 +1169,9 @@ class Payment extends Info implements OrderPaymentInterface $status = false; if ($isOnline) { // invoke authorization on gateway - $this->getMethodInstance()->setStore($order->getStoreId())->authorize($this, $amount); + $method = $this->getMethodInstance(); + $method->setStore($order->getStoreId()); + $method->authorize($this, $amount); } // similar logic of "payment review" order as in capturing @@ -1207,7 +1232,9 @@ class Payment extends Info implements OrderPaymentInterface // attempt to void if ($isOnline) { - $this->getMethodInstance()->setStore($order->getStoreId())->{$gatewayCallback}($this); + $method = $this->getMethodInstance(); + $method->setStore($order->getStoreId()); + $method->{$gatewayCallback}($this); } if ($this->_isTransactionExists()) { return $this; @@ -1365,16 +1392,18 @@ class Payment extends Info implements OrderPaymentInterface */ public function importTransactionInfo(Transaction $transactionTo) { - $data = $this->getMethodInstance()->setStore( + $method = $this->getMethodInstance(); + $method->setStore( $this->getOrder()->getStoreId() - )->fetchTransactionInfo( + ); + $method->fetchTransactionInfo( $this, $transactionTo->getTxnId() ); - if ($data) { + if ($method) { $transactionTo->setAdditionalInformation( Transaction::RAW_DETAILS, - $data + $method ); } return $this; @@ -1421,7 +1450,7 @@ class Payment extends Info implements OrderPaymentInterface protected function _appendTransactionToMessage($transaction, $message) { if ($transaction) { - $txnId = is_object($transaction) ? $transaction->getTxnId() : $transaction; + $txnId = is_object($transaction) ? $transaction->getHtmlTxnId() : $transaction; $message .= ' ' . __('Transaction ID: "%1"', $txnId); } return $message; @@ -1441,8 +1470,8 @@ class Payment extends Info implements OrderPaymentInterface if (is_string($preparedMessage)) { return $preparedMessage . ' ' . $messagePrependTo; } elseif (is_object( - $preparedMessage - ) && $preparedMessage instanceof \Magento\Sales\Model\Order\Status\History + $preparedMessage + ) && $preparedMessage instanceof \Magento\Sales\Model\Order\Status\History ) { $comment = $preparedMessage->getComment() . ' ' . $messagePrependTo; $preparedMessage->setComment($comment); @@ -1666,8 +1695,8 @@ class Payment extends Info implements OrderPaymentInterface } foreach ($this->getOrder()->getInvoiceCollection() as $invoice) { if ($invoice->getState() == \Magento\Sales\Model\Order\Invoice::STATE_OPEN && $invoice->load( - $invoice->getId() - ) + $invoice->getId() + ) ) { $invoice->setTransactionId($transactionId); return $invoice; @@ -1676,6 +1705,7 @@ class Payment extends Info implements OrderPaymentInterface return false; } + //@codeCoverageIgnoreStart /** * Returns account_status * @@ -2196,7 +2226,6 @@ class Payment extends Info implements OrderPaymentInterface return $this->getData(OrderPaymentInterface::SHIPPING_REFUNDED); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ diff --git a/app/code/Magento/Sales/Model/Order/Payment/Info.php b/app/code/Magento/Sales/Model/Order/Payment/Info.php index aa7339078b6923bb6b32f58a878bf991f9b04928..b67a4e592a64410ab50bba1c423ebd01f96a7b58 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Info.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Info.php @@ -43,7 +43,7 @@ class Info extends AbstractModel implements InfoInterface * @param \Magento\Payment\Helper\Data $paymentData * @param \Magento\Framework\Encryption\EncryptorInterface $encryptor * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -54,7 +54,7 @@ class Info extends AbstractModel implements InfoInterface \Magento\Payment\Helper\Data $paymentData, \Magento\Framework\Encryption\EncryptorInterface $encryptor, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->paymentData = $paymentData; diff --git a/app/code/Magento/Sales/Model/Order/Payment/Transaction.php b/app/code/Magento/Sales/Model/Order/Payment/Transaction.php index 16cc9b45365adec1da8225d0c7ef6cd27ba813f1..17b73b17d60901aee38a946b98cb744c8ad8e86c 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Transaction.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Transaction.php @@ -159,7 +159,7 @@ class Transaction extends AbstractModel implements TransactionInterface * @param \Magento\Framework\Stdlib\DateTime\DateTimeFactory $dateFactory * @param TransactionFactory $transactionFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -173,7 +173,7 @@ class Transaction extends AbstractModel implements TransactionInterface \Magento\Framework\Stdlib\DateTime\DateTimeFactory $dateFactory, TransactionFactory $transactionFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_paymentFactory = $paymentFactory; @@ -911,6 +911,7 @@ class Transaction extends AbstractModel implements TransactionInterface $this->_verifyTxnType(); } + //@codeCoverageIgnoreStart /** * Returns transaction_id * @@ -979,6 +980,17 @@ class Transaction extends AbstractModel implements TransactionInterface return $this->getData(TransactionInterface::TXN_ID); } + /** + * Get HTML format for transaction id + * + * @return string + */ + public function getHtmlTxnId() + { + $this->_eventManager->dispatch($this->_eventPrefix . '_html_txn_id', $this->_getEventData()); + return isset($this->_data['html_txn_id']) ? $this->_data['html_txn_id'] : $this->getTxnId(); + } + /** * Returns parent_txn_id * @@ -1009,7 +1021,6 @@ class Transaction extends AbstractModel implements TransactionInterface return $this->getData(TransactionInterface::IS_CLOSED); } - //@codeCoverageIgnoreStart /** * Gets the created-at timestamp for the transaction. * diff --git a/app/code/Magento/Sales/Model/Order/Pdf/Items/AbstractItems.php b/app/code/Magento/Sales/Model/Order/Pdf/Items/AbstractItems.php index 3f97b6fa8a2cca4ea58c5fcf1d1ce8bbed4225ac..716543b5ddb2c608450278fbbbccc0c3099dec5a 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/Items/AbstractItems.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/Items/AbstractItems.php @@ -72,7 +72,7 @@ abstract class AbstractItems extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Filesystem $filesystem , * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -82,7 +82,7 @@ abstract class AbstractItems extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Filesystem $filesystem, \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->filterManager = $filterManager; diff --git a/app/code/Magento/Sales/Model/Order/Pdf/Items/Creditmemo/DefaultCreditmemo.php b/app/code/Magento/Sales/Model/Order/Pdf/Items/Creditmemo/DefaultCreditmemo.php index 7c8129a9384f4c864b44ea02b2f8d8befb877b7c..2f96bd2454fd87f62e338e33eebd839611c6e0b7 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/Items/Creditmemo/DefaultCreditmemo.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/Items/Creditmemo/DefaultCreditmemo.php @@ -25,7 +25,7 @@ class DefaultCreditmemo extends \Magento\Sales\Model\Order\Pdf\Items\AbstractIte * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\String $string * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -36,7 +36,7 @@ class DefaultCreditmemo extends \Magento\Sales\Model\Order\Pdf\Items\AbstractIte \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\String $string, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->string = $string; @@ -105,7 +105,7 @@ class DefaultCreditmemo extends \Magento\Sales\Model\Order\Pdf\Items\AbstractIte // draw Total (inc) $subtotal = $item->getRowTotal() + $item->getTaxAmount() + - $item->getHiddenTaxAmount() - + $item->getDiscountTaxCompensationAmount() - $item->getDiscountAmount(); $lines[0][] = [ 'text' => $order->formatPriceTxt($subtotal), diff --git a/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php b/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php index 9a37a691e662be1c1b7bff52e10175bc3bdb6c24..33e00f83d5d9ec96d398c6dbfc87f622dbd4c3a5 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/Items/Invoice/DefaultInvoice.php @@ -25,7 +25,7 @@ class DefaultInvoice extends \Magento\Sales\Model\Order\Pdf\Items\AbstractItems * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\String $string * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -36,7 +36,7 @@ class DefaultInvoice extends \Magento\Sales\Model\Order\Pdf\Items\AbstractItems \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\String $string, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->string = $string; diff --git a/app/code/Magento/Sales/Model/Order/Pdf/Items/Shipment/DefaultShipment.php b/app/code/Magento/Sales/Model/Order/Pdf/Items/Shipment/DefaultShipment.php index ef3ed60981db1074a5181711e4173f8ee01d1f26..3343f6827f8603d4e7300a44d3e3e1f0a0ae85fe 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/Items/Shipment/DefaultShipment.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/Items/Shipment/DefaultShipment.php @@ -25,7 +25,7 @@ class DefaultShipment extends \Magento\Sales\Model\Order\Pdf\Items\AbstractItems * @param \Magento\Framework\Filter\FilterManager $filterManager * @param \Magento\Framework\Stdlib\String $string * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -36,7 +36,7 @@ class DefaultShipment extends \Magento\Sales\Model\Order\Pdf\Items\AbstractItems \Magento\Framework\Filter\FilterManager $filterManager, \Magento\Framework\Stdlib\String $string, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->string = $string; diff --git a/app/code/Magento/Sales/Model/Order/Shipment.php b/app/code/Magento/Sales/Model/Order/Shipment.php index 6763a4895dfe30891530cdeb2c25a61e47047c14..8156180723e2a5971576ea9719a6e11be132cb2f 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment.php +++ b/app/code/Magento/Sales/Model/Order/Shipment.php @@ -104,7 +104,7 @@ class Shipment extends AbstractModel implements EntityInterface, ShipmentInterfa * @param Shipment\CommentFactory $commentFactory * @param \Magento\Sales\Model\Resource\Order\Shipment\Comment\CollectionFactory $commentCollectionFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -119,7 +119,7 @@ class Shipment extends AbstractModel implements EntityInterface, ShipmentInterfa \Magento\Sales\Model\Order\Shipment\CommentFactory $commentFactory, \Magento\Sales\Model\Resource\Order\Shipment\Comment\CollectionFactory $commentCollectionFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_orderFactory = $orderFactory; @@ -204,6 +204,8 @@ class Shipment extends AbstractModel implements EntityInterface, ShipmentInterfa /** * Return order history item identifier * + * @codeCoverageIgnore + * * @return string */ public function getEntityType() @@ -520,6 +522,8 @@ class Shipment extends AbstractModel implements EntityInterface, ShipmentInterfa /** * Returns increment id * + * @codeCoverageIgnore + * * @return string */ public function getIncrementId() @@ -530,6 +534,8 @@ class Shipment extends AbstractModel implements EntityInterface, ShipmentInterfa /** * Returns packages * + * @codeCoverageIgnore + * * @return string */ public function getPackages() @@ -539,6 +545,7 @@ class Shipment extends AbstractModel implements EntityInterface, ShipmentInterfa /** * {@inheritdoc} + * @codeCoverageIgnore */ public function setPackages(array $packages = null) { @@ -567,6 +574,8 @@ class Shipment extends AbstractModel implements EntityInterface, ShipmentInterfa /** * Sets items * + * @codeCoverageIgnore + * * @param mixed $items * @return $this */ @@ -594,6 +603,7 @@ class Shipment extends AbstractModel implements EntityInterface, ShipmentInterfa return $this->getData(ShipmentInterface::TRACKS); } + //@codeCoverageIgnoreStart /** * Returns tracks * @@ -744,7 +754,6 @@ class Shipment extends AbstractModel implements EntityInterface, ShipmentInterfa return $this->setData(ShipmentInterface::COMMENTS, $comments); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Comment.php b/app/code/Magento/Sales/Model/Order/Shipment/Comment.php index d1e9a5ac880bce77a0cef548f077e6e09ce754e7..10b1d2a32acad79184867fd33973230e1f9af194 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment/Comment.php +++ b/app/code/Magento/Sales/Model/Order/Shipment/Comment.php @@ -34,7 +34,7 @@ class Comment extends AbstractModel implements ShipmentCommentInterface * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -45,7 +45,7 @@ class Comment extends AbstractModel implements ShipmentCommentInterface AttributeValueFactory $customAttributeFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -73,6 +73,8 @@ class Comment extends AbstractModel implements ShipmentCommentInterface /** * Declare Shipment instance * + * @codeCoverageIgnore + * * @param \Magento\Sales\Model\Order\Shipment $shipment * @return $this */ @@ -85,6 +87,8 @@ class Comment extends AbstractModel implements ShipmentCommentInterface /** * Retrieve Shipment instance * + * @codeCoverageIgnore + * * @return \Magento\Sales\Model\Order\Shipment */ public function getShipment() @@ -105,6 +109,7 @@ class Comment extends AbstractModel implements ShipmentCommentInterface return $this->_storeManager->getStore(); } + //@codeCoverageIgnoreStart /** * Returns comment * @@ -163,7 +168,6 @@ class Comment extends AbstractModel implements ShipmentCommentInterface return $this->getData(ShipmentCommentInterface::PARENT_ID); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Item.php b/app/code/Magento/Sales/Model/Order/Shipment/Item.php index 8a158869d1cf02c8d93c6224ba5fd229c089bfb1..6197a179feb81a05999a6df5b642f418a00523fd 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment/Item.php +++ b/app/code/Magento/Sales/Model/Order/Shipment/Item.php @@ -51,7 +51,7 @@ class Item extends AbstractModel implements ShipmentItemInterface * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Sales\Model\Order\ItemFactory $orderItemFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -61,7 +61,7 @@ class Item extends AbstractModel implements ShipmentItemInterface AttributeValueFactory $customAttributeFactory, \Magento\Sales\Model\Order\ItemFactory $orderItemFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -89,6 +89,8 @@ class Item extends AbstractModel implements ShipmentItemInterface /** * Declare Shipment instance * + * @codeCoverageIgnore + * * @param \Magento\Sales\Model\Order\Shipment $shipment * @return $this */ @@ -101,6 +103,8 @@ class Item extends AbstractModel implements ShipmentItemInterface /** * Retrieve Shipment instance * + * @codeCoverageIgnore + * * @return \Magento\Sales\Model\Order\Shipment */ public function getShipment() @@ -177,6 +181,7 @@ class Item extends AbstractModel implements ShipmentItemInterface return $this; } + //@codeCoverageIgnoreStart /** * Returns additional_data * @@ -287,7 +292,6 @@ class Item extends AbstractModel implements ShipmentItemInterface return $this->getData(ShipmentItemInterface::WEIGHT); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Track.php b/app/code/Magento/Sales/Model/Order/Shipment/Track.php index f5b15181cb8fcb89a5ddb301b28a4290573010ec..35de2cdfe45e90c339516b7cefd398895578be44 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment/Track.php +++ b/app/code/Magento/Sales/Model/Order/Shipment/Track.php @@ -56,7 +56,7 @@ class Track extends AbstractModel implements ShipmentTrackInterface * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -68,7 +68,7 @@ class Track extends AbstractModel implements ShipmentTrackInterface \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -97,6 +97,8 @@ class Track extends AbstractModel implements ShipmentTrackInterface /** * Tracking number getter * + * @codeCoverageIgnore + * * @return string */ public function getNumber() @@ -107,6 +109,8 @@ class Track extends AbstractModel implements ShipmentTrackInterface /** * Tracking number setter * + * @codeCoverageIgnore + * * @param string $number * @return \Magento\Framework\Object */ @@ -118,6 +122,8 @@ class Track extends AbstractModel implements ShipmentTrackInterface /** * Declare Shipment instance * + * @codeCoverageIgnore + * * @param \Magento\Sales\Model\Order\Shipment $shipment * @return $this */ @@ -201,6 +207,7 @@ class Track extends AbstractModel implements ShipmentTrackInterface return parent::addData($data); } + //@codeCoverageIgnoreStart /** * Returns track_number * @@ -309,7 +316,6 @@ class Track extends AbstractModel implements ShipmentTrackInterface return $this->getData(ShipmentTrackInterface::WEIGHT); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ diff --git a/app/code/Magento/Sales/Model/Order/Status.php b/app/code/Magento/Sales/Model/Order/Status.php index 08d6786e108bd5bcb7bf863f3221826b9237b15c..278697d93737346400fe0b6754e370f9a0697fba 100644 --- a/app/code/Magento/Sales/Model/Order/Status.php +++ b/app/code/Magento/Sales/Model/Order/Status.php @@ -27,7 +27,7 @@ class Status extends \Magento\Sales\Model\AbstractModel * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -37,7 +37,7 @@ class Status extends \Magento\Sales\Model\AbstractModel \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/Sales/Model/Order/Status/History.php b/app/code/Magento/Sales/Model/Order/Status/History.php index b442ebba05f7df7af8691e42949e79c174b0cb74..489ba26f1a70e32cc14c503bd0099f255e7984fd 100644 --- a/app/code/Magento/Sales/Model/Order/Status/History.php +++ b/app/code/Magento/Sales/Model/Order/Status/History.php @@ -49,7 +49,7 @@ class History extends AbstractModel implements OrderStatusHistoryInterface * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -60,7 +60,7 @@ class History extends AbstractModel implements OrderStatusHistoryInterface AttributeValueFactory $customAttributeFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( @@ -126,6 +126,8 @@ class History extends AbstractModel implements OrderStatusHistoryInterface /** * Retrieve order instance * + * @codeCoverageIgnore + * * @return \Magento\Sales\Model\Order */ public function getOrder() @@ -175,6 +177,7 @@ class History extends AbstractModel implements OrderStatusHistoryInterface return $this; } + //@codeCoverageIgnoreStart /** * Returns comment * @@ -263,7 +266,6 @@ class History extends AbstractModel implements OrderStatusHistoryInterface return $this->getData(OrderStatusHistoryInterface::STATUS); } - //@codeCoverageIgnoreStart /** * {@inheritdoc} */ diff --git a/app/code/Magento/Sales/Model/Order/Tax.php b/app/code/Magento/Sales/Model/Order/Tax.php index 75e37abdc17506d3941607d7766873e7b5bd63d0..aac639ebb8200c3a34911296156eec8be0e3ce6a 100644 --- a/app/code/Magento/Sales/Model/Order/Tax.php +++ b/app/code/Magento/Sales/Model/Order/Tax.php @@ -29,8 +29,6 @@ namespace Magento\Sales\Model\Order; * @method \Magento\Sales\Model\Order\Tax setProcess(int $value) * @method float getBaseRealAmount() * @method \Magento\Sales\Model\Order\Tax setBaseRealAmount(float $value) - * @method int getHidden() - * @method \Magento\Sales\Model\Order\Tax setHidden(int $value) * * @author Magento Core Team <core@magentocommerce.com> */ diff --git a/app/code/Magento/Sales/Model/Resource/EntityAbstract.php b/app/code/Magento/Sales/Model/Resource/EntityAbstract.php index 681bbf2886ec14ae2c01f2e7adae01084217c7f3..44989d28a214cc6f2531e7313591ac3d9bf27d68 100644 --- a/app/code/Magento/Sales/Model/Resource/EntityAbstract.php +++ b/app/code/Magento/Sales/Model/Resource/EntityAbstract.php @@ -58,26 +58,31 @@ abstract class EntityAbstract extends AbstractDb */ protected $entitySnapshot; + /** + * @var EntityRelationComposite + */ + protected $entityRelationComposite; + /** * @param \Magento\Framework\Model\Resource\Db\Context $context * @param Attribute $attribute * @param Manager $sequenceManager * @param EntitySnapshot $entitySnapshot - * @param string|null $resourcePrefix - * @param GridInterface|null $gridAggregator + * @param EntityRelationComposite $entityRelationComposite + * @param string $resourcePrefix */ public function __construct( \Magento\Framework\Model\Resource\Db\Context $context, \Magento\Sales\Model\Resource\Attribute $attribute, Manager $sequenceManager, EntitySnapshot $entitySnapshot, - $resourcePrefix = null, - \Magento\Sales\Model\Resource\GridInterface $gridAggregator = null + EntityRelationComposite $entityRelationComposite, + $resourcePrefix = null ) { $this->attribute = $attribute; $this->sequenceManager = $sequenceManager; - $this->gridAggregator = $gridAggregator; $this->entitySnapshot = $entitySnapshot; + $this->entityRelationComposite = $entityRelationComposite; if ($resourcePrefix === null) { $resourcePrefix = 'sales'; } @@ -125,13 +130,12 @@ abstract class EntityAbstract extends AbstractDb */ protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object) { - /** @var \Magento\Sales\Model\AbstractModel $object */ if ($object instanceof EntityInterface && $object->getIncrementId() == null) { $object->setIncrementId( $this->sequenceManager->getSequence( $object->getEntityType(), - $object->getStore()->getId() + $object->getStore()->getGroup()->getDefaultStoreId() )->getNextValue() ); } @@ -191,18 +195,6 @@ abstract class EntityAbstract extends AbstractDb return $this; } - /** - * Process entity relations - * - * @param \Magento\Framework\Model\AbstractModel $object - * @return $this - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - protected function processRelations(\Magento\Framework\Model\AbstractModel $object) - { - return $this; - } - /** * Save entity * @@ -216,7 +208,7 @@ abstract class EntityAbstract extends AbstractDb return $this->delete($object); } if (!$this->entitySnapshot->isModified($object)) { - $this->processRelations($object); + $this->entityRelationComposite->processRelations($object); return $this; } $this->beginTransaction(); @@ -238,9 +230,7 @@ abstract class EntityAbstract extends AbstractDb $bind = $this->_prepareDataForSave($object); unset($bind[$this->getIdFieldName()]); $this->_getWriteAdapter()->insert($this->getMainTable(), $bind); - $object->setId($this->_getWriteAdapter()->lastInsertId($this->getMainTable())); - if ($this->_useIsObjectNew) { $object->isObjectNew(false); } @@ -249,7 +239,7 @@ abstract class EntityAbstract extends AbstractDb $this->_afterSave($object); $this->entitySnapshot->registerSnapshot($object); $object->afterSave(); - $this->processRelations($object); + $this->entityRelationComposite->processRelations($object); } $this->addCommitCallback([$object, 'afterCommitCallback'])->commit(); $object->setHasDataChanges(false); diff --git a/app/code/Magento/Sales/Model/Resource/EntityRelationComposite.php b/app/code/Magento/Sales/Model/Resource/EntityRelationComposite.php new file mode 100644 index 0000000000000000000000000000000000000000..3c367791a20f82990084b87525e54e77455596e2 --- /dev/null +++ b/app/code/Magento/Sales/Model/Resource/EntityRelationComposite.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\Resource; + +use Magento\Sales\Model\AbstractModel; +use Magento\Framework\Event\ManagerInterface as EventManager; + +/** + * Class EntityRelationComposite + */ +class EntityRelationComposite +{ + /** + * @var array + */ + protected $relationProcessors; + + /** + * @var EventManager + */ + protected $eventManager; + + /** + * @param EventManager $eventManager + * @param array $relationProcessors + */ + public function __construct( + EventManager $eventManager, + array $relationProcessors = [] + ) { + $this->eventManager = $eventManager; + $this->relationProcessors = $relationProcessors; + } + + /** + * @param AbstractModel $object + * @return void + */ + public function processRelations(AbstractModel $object) + { + foreach ($this->relationProcessors as $processor) { + /**@var $processor \Magento\Sales\Model\Resource\EntityRelationInterface*/ + $processor->processRelation($object); + } + $this->eventManager->dispatch( + $object->getEventPrefix(). '_process_relation', + [ + 'object' => $object + ] + ); + } +} diff --git a/app/code/Magento/Sales/Model/Resource/EntityRelationInterface.php b/app/code/Magento/Sales/Model/Resource/EntityRelationInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..72d26e580e8dff1b8940b82ca4433c5cfa27e69f --- /dev/null +++ b/app/code/Magento/Sales/Model/Resource/EntityRelationInterface.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\Resource; + +/** + * Interface EntityRelationInterface + */ +interface EntityRelationInterface +{ + /** + * Process object relations + * + * @param \Magento\Sales\Model\AbstractModel $object + * @return void + */ + public function processRelation(\Magento\Sales\Model\AbstractModel $object); +} diff --git a/app/code/Magento/Sales/Model/Resource/Order.php b/app/code/Magento/Sales/Model/Resource/Order.php index 326b6a5cee1717298673568efb840e76be5bb183..24b205c079d7266f3f010806d039466e25f2b25c 100644 --- a/app/code/Magento/Sales/Model/Resource/Order.php +++ b/app/code/Magento/Sales/Model/Resource/Order.php @@ -9,7 +9,6 @@ use Magento\Framework\App\Resource as AppResource; use Magento\Framework\Math\Random; use Magento\SalesSequence\Model\Manager; use Magento\Sales\Model\Resource\EntityAbstract as SalesResource; -use Magento\Sales\Model\Resource\Order\Handler\Address as AddressHandler; use Magento\Sales\Model\Resource\Order\Handler\State as StateHandler; use Magento\Sales\Model\Spi\OrderResourceInterface; @@ -40,11 +39,6 @@ class Order extends SalesResource implements OrderResourceInterface */ protected $stateHandler; - /** - * @var AddressHandler - */ - protected $addressHandler; - /** * Model Initialization * @@ -60,22 +54,28 @@ class Order extends SalesResource implements OrderResourceInterface * @param Attribute $attribute * @param Manager $sequenceManager * @param EntitySnapshot $entitySnapshot - * @param AddressHandler $addressHandler + * @param EntityRelationComposite $entityRelationComposite * @param StateHandler $stateHandler - * @param null $resourcePrefix + * @param string $resourcePrefix */ public function __construct( \Magento\Framework\Model\Resource\Db\Context $context, Attribute $attribute, Manager $sequenceManager, EntitySnapshot $entitySnapshot, - AddressHandler $addressHandler, + EntityRelationComposite $entityRelationComposite, StateHandler $stateHandler, $resourcePrefix = null ) { $this->stateHandler = $stateHandler; - $this->addressHandler = $addressHandler; - parent::__construct($context, $attribute, $sequenceManager, $entitySnapshot, $resourcePrefix); + parent::__construct( + $context, + $attribute, + $sequenceManager, + $entitySnapshot, + $entityRelationComposite, + $resourcePrefix + ); } /** @@ -139,7 +139,6 @@ class Order extends SalesResource implements OrderResourceInterface protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object) { /** @var \Magento\Sales\Model\Order $object */ - $this->addressHandler->removeEmptyAddresses($object); $this->stateHandler->check($object); if (!$object->getId()) { /** @var \Magento\Store\Model\Store $store */ @@ -149,7 +148,7 @@ class Order extends SalesResource implements OrderResourceInterface $store->getGroup()->getName(), $store->getName(), ]; - $object->setStoreName(implode("\n", $name)); + $object->setStoreName(implode(PHP_EOL, $name)); $object->setTotalItemCount($this->calculateItems($object)); } $object->setData( @@ -162,46 +161,4 @@ class Order extends SalesResource implements OrderResourceInterface } return parent::_beforeSave($object); } - - /** - * @param \Magento\Framework\Model\AbstractModel $object - * @return $this - */ - protected function processRelations(\Magento\Framework\Model\AbstractModel $object) - { - /** @var \Magento\Sales\Model\Order $object */ - $this->addressHandler->process($object); - - if (null !== $object->getItems()) { - /** @var \Magento\Sales\Model\Order\Item $item */ - foreach ($object->getItems() as $item) { - $item->setOrderId($object->getId()); - $item->setOrder($object); - $item->save(); - } - } - if (null !== $object->getPayments()) { - /** @var \Magento\Sales\Model\Order\Payment $payment */ - foreach ($object->getPayments() as $payment) { - $payment->setParentId($object->getId()); - $payment->setOrder($object); - $payment->save(); - } - } - if (null !== $object->getStatusHistories()) { - /** @var \Magento\Sales\Model\Order\Status\History $statusHistory */ - foreach ($object->getStatusHistories() as $statusHistory) { - $statusHistory->setParentId($object->getId()); - $statusHistory->save(); - $statusHistory->setOrder($object); - } - } - if (null !== $object->getRelatedObjects()) { - foreach ($object->getRelatedObjects() as $relatedObject) { - $relatedObject->save(); - $relatedObject->setOrder($object); - } - } - return parent::processRelations($object); - } } diff --git a/app/code/Magento/Sales/Model/Resource/Order/Address.php b/app/code/Magento/Sales/Model/Resource/Order/Address.php index b11ffd3c45827ca6b6cc0c8fa37bf5a5cb4caf37..a8b2b3ca7376dc6599a232b91bae14dd57983ded 100644 --- a/app/code/Magento/Sales/Model/Resource/Order/Address.php +++ b/app/code/Magento/Sales/Model/Resource/Order/Address.php @@ -36,22 +36,31 @@ class Address extends SalesResource implements OrderAddressResourceInterface * @param \Magento\Sales\Model\Resource\Attribute $attribute * @param \Magento\SalesSequence\Model\Manager $sequenceManager * @param EntitySnapshot $entitySnapshot + * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite * @param \Magento\Sales\Model\Order\Address\Validator $validator * @param \Magento\Sales\Model\Resource\GridPool $gridPool - * @param string|null $resourcePrefix + * @param string $resourcePrefix */ public function __construct( \Magento\Framework\Model\Resource\Db\Context $context, \Magento\Sales\Model\Resource\Attribute $attribute, \Magento\SalesSequence\Model\Manager $sequenceManager, EntitySnapshot $entitySnapshot, + \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite, \Magento\Sales\Model\Order\Address\Validator $validator, \Magento\Sales\Model\Resource\GridPool $gridPool, $resourcePrefix = null ) { $this->_validator = $validator; $this->gridPool = $gridPool; - parent::__construct($context, $attribute, $sequenceManager, $entitySnapshot, $resourcePrefix); + parent::__construct( + $context, + $attribute, + $sequenceManager, + $entitySnapshot, + $entityRelationComposite, + $resourcePrefix + ); } /** diff --git a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo.php b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo.php index b2dab0f476b8a99da5cc62196419897a73391393..f0a5c4d693428efed1a537f29db22df1af9758cb 100644 --- a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo.php +++ b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo.php @@ -36,23 +36,6 @@ class Creditmemo extends SalesResource implements CreditmemoResourceInterface $this->_init('sales_creditmemo', 'entity_id'); } - /** - * @param \Magento\Framework\Model\Resource\Db\Context $context - * @param Attribute $attribute - * @param Manager $sequenceManager - * @param EntitySnapshot $entitySnapshot - * @param string|null $resourcePrefix - */ - public function __construct( - \Magento\Framework\Model\Resource\Db\Context $context, - Attribute $attribute, - Manager $sequenceManager, - EntitySnapshot $entitySnapshot, - $resourcePrefix = null - ) { - parent::__construct($context, $attribute, $sequenceManager, $entitySnapshot, $resourcePrefix); - } - /** * Perform actions before object save * @@ -69,28 +52,4 @@ class Creditmemo extends SalesResource implements CreditmemoResourceInterface return parent::_beforeSave($object); } - - /** - * Perform actions after object save - * - * @param \Magento\Framework\Model\AbstractModel $object - * @return $this - */ - protected function processRelations(\Magento\Framework\Model\AbstractModel $object) - { - /** @var \Magento\Sales\Model\Order\Creditmemo $object */ - if (null !== $object->getItems()) { - foreach ($object->getItems() as $item) { - $item->setParentId($object->getId()); - $item->save(); - } - } - - if (null !== $object->getComments()) { - foreach ($object->getComments() as $comment) { - $comment->save(); - } - } - return parent::processRelations($object); - } } diff --git a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Comment.php b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Comment.php index aca0ff4e7508ff89996378412d1cc0b154bdc3a3..3056759346691ebb39edfbd90f0cbb5adb160382 100644 --- a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Comment.php +++ b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Comment.php @@ -35,19 +35,28 @@ class Comment extends EntityAbstract implements CreditmemoCommentResourceInterfa * @param \Magento\Sales\Model\Resource\Attribute $attribute * @param \Magento\SalesSequence\Model\Manager $sequenceManager * @param EntitySnapshot $entitySnapshot + * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite * @param \Magento\Sales\Model\Order\Creditmemo\Comment\Validator $validator - * @param string|null $resourcePrefix + * @param string $resourcePrefix */ public function __construct( \Magento\Framework\Model\Resource\Db\Context $context, \Magento\Sales\Model\Resource\Attribute $attribute, \Magento\SalesSequence\Model\Manager $sequenceManager, EntitySnapshot $entitySnapshot, + \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite, \Magento\Sales\Model\Order\Creditmemo\Comment\Validator $validator, $resourcePrefix = null ) { $this->validator = $validator; - parent::__construct($context, $attribute, $sequenceManager, $entitySnapshot, $resourcePrefix); + parent::__construct( + $context, + $attribute, + $sequenceManager, + $entitySnapshot, + $entityRelationComposite, + $resourcePrefix + ); } /** diff --git a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Relation.php b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Relation.php new file mode 100644 index 0000000000000000000000000000000000000000..674e9552b7ae54cc956fa539c09ed3fef49e1933 --- /dev/null +++ b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Relation.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\Resource\Order\Creditmemo; + +use Magento\Sales\Model\Resource\EntityRelationInterface; + +/** + * Class Relation + */ +class Relation implements EntityRelationInterface +{ + /** + * @var Item + */ + protected $creditmemoItemResource; + + /** + * @var Comment + */ + protected $creditmemoCommentResource; + + /** + * @param Item $creditmemoItemResource + * @param Comment $creditmemoCommentResource + */ + public function __construct( + \Magento\Sales\Model\Resource\Order\Creditmemo\Item $creditmemoItemResource, + \Magento\Sales\Model\Resource\Order\Creditmemo\Comment $creditmemoCommentResource + ) { + $this->creditmemoItemResource = $creditmemoItemResource; + $this->creditmemoCommentResource = $creditmemoCommentResource; + } + + /** + * Process relations for CreditMemo + * + * @param \Magento\Sales\Model\AbstractModel $object + * @throws \Exception + * @return void + */ + public function processRelation(\Magento\Sales\Model\AbstractModel $object) + { + /** @var \Magento\Sales\Model\Order\Creditmemo $object */ + if (null !== $object->getItems()) { + foreach ($object->getItems() as $item) { + $item->setParentId($object->getId()); + $this->creditmemoItemResource->save($item); + } + } + if (null !== $object->getComments()) { + foreach ($object->getComments() as $comment) { + $this->creditmemoCommentResource->save($comment); + } + } + } +} diff --git a/app/code/Magento/Sales/Model/Resource/Order/Invoice.php b/app/code/Magento/Sales/Model/Resource/Order/Invoice.php index 346d85f342b6c9a710a33e46302febde371bb89a..6fb7504394cf8f3c813089146dbeb577b19cb448 100644 --- a/app/code/Magento/Sales/Model/Resource/Order/Invoice.php +++ b/app/code/Magento/Sales/Model/Resource/Order/Invoice.php @@ -34,23 +34,6 @@ class Invoice extends SalesResource implements InvoiceResourceInterface $this->_init('sales_invoice', 'entity_id'); } - /** - * @param \Magento\Framework\Model\Resource\Db\Context $context - * @param Attribute $attribute - * @param Manager $sequenceManager - * @param EntitySnapshot $entitySnapshot - * @param string|null $resourcePrefix - */ - public function __construct( - \Magento\Framework\Model\Resource\Db\Context $context, - Attribute $attribute, - Manager $sequenceManager, - EntitySnapshot $entitySnapshot, - $resourcePrefix = null - ) { - parent::__construct($context, $attribute, $sequenceManager, $entitySnapshot, $resourcePrefix); - } - /** * Perform actions before object save * @@ -67,32 +50,4 @@ class Invoice extends SalesResource implements InvoiceResourceInterface return parent::_beforeSave($object); } - - /** - * Perform actions before object save - * - * @param \Magento\Framework\Model\AbstractModel|\Magento\Framework\Object $object - * @return $this - */ - protected function processRelations(\Magento\Framework\Model\AbstractModel $object) - { - /** @var \Magento\Sales\Model\Order\Invoice $object */ - if (null !== $object->getItems()) { - /** - * Save invoice items - */ - foreach ($object->getItems() as $item) { - $item->setParentId($object->getId()); - $item->setOrderItem($item->getOrderItem()); - $item->save(); - } - } - - if (null !== $object->getComments()) { - foreach ($object->getComments() as $comment) { - $comment->save(); - } - } - return parent::processRelations($object); - } } diff --git a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Comment.php b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Comment.php index f1ee7de58b2fbcee010811d7249e97c4e295a306..f54208f1e5d5d11edc3ea35408223a2423752ea0 100644 --- a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Comment.php +++ b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Comment.php @@ -35,21 +35,28 @@ class Comment extends EntityAbstract implements InvoiceCommentResourceInterface * @param \Magento\Sales\Model\Resource\Attribute $attribute * @param \Magento\SalesSequence\Model\Manager $sequenceManager * @param EntitySnapshot $entitySnapshot + * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite * @param \Magento\Sales\Model\Order\Invoice\Comment\Validator $validator - * @param string|null $resourcePrefix - * @param \Magento\Sales\Model\Resource\GridInterface $gridAggregator + * @param string $resourcePrefix */ public function __construct( \Magento\Framework\Model\Resource\Db\Context $context, \Magento\Sales\Model\Resource\Attribute $attribute, \Magento\SalesSequence\Model\Manager $sequenceManager, EntitySnapshot $entitySnapshot, + \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite, \Magento\Sales\Model\Order\Invoice\Comment\Validator $validator, - $resourcePrefix = null, - \Magento\Sales\Model\Resource\GridInterface $gridAggregator = null + $resourcePrefix = null ) { $this->validator = $validator; - parent::__construct($context, $attribute, $sequenceManager, $entitySnapshot, $resourcePrefix, $gridAggregator); + parent::__construct( + $context, + $attribute, + $sequenceManager, + $entitySnapshot, + $entityRelationComposite, + $resourcePrefix + ); } /** diff --git a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Relation.php b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Relation.php new file mode 100644 index 0000000000000000000000000000000000000000..80f10e6adbaad2b6d2a61cdbfd17d9f2223ca2ec --- /dev/null +++ b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Relation.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\Resource\Order\Invoice; + +use Magento\Sales\Model\Resource\EntityRelationInterface; +use Magento\Sales\Model\Resource\Order\Invoice\Item as InvoiceItemResource; +use Magento\Sales\Model\Resource\Order\Invoice\Comment as InvoiceCommentResource; + +/** + * Class Relation + */ +class Relation implements EntityRelationInterface +{ + /** + * @var InvoiceItemResource + */ + protected $invoiceItemResource; + + /** + * @var InvoiceCommentResource + */ + protected $invoiceCommentResource; + + /** + * @param InvoiceItemResource $invoiceItemResource + * @param InvoiceCommentResource $invoiceCommentResource + */ + public function __construct( + InvoiceItemResource $invoiceItemResource, + InvoiceCommentResource $invoiceCommentResource + ) { + $this->invoiceItemResource = $invoiceItemResource; + $this->invoiceCommentResource = $invoiceCommentResource; + } + + /** + * Process relations for Shipment + * + * @param \Magento\Sales\Model\AbstractModel $object + * @return void + * @throws \Exception + */ + public function processRelation(\Magento\Sales\Model\AbstractModel $object) + { + /** @var $object \Magento\Sales\Model\Order\Invoice */ + if (null !== $object->getItems()) { + foreach ($object->getItems() as $item) { + /** @var \Magento\Sales\Model\Order\Invoice\Item */ + $item->setParentId($object->getId()); + $item->setOrderItem($item->getOrderItem()); + $this->invoiceItemResource->save($item); + } + } + + if (null !== $object->getComments()) { + foreach ($object->getComments() as $comment) { + /** @var \Magento\Sales\Model\Order\Invoice\Comment */ + $this->invoiceCommentResource->save($comment); + } + } + } +} diff --git a/app/code/Magento/Sales/Model/Resource/Order/Relation.php b/app/code/Magento/Sales/Model/Resource/Order/Relation.php new file mode 100644 index 0000000000000000000000000000000000000000..749de294fe06d4057c2a990d875821bc5e45840c --- /dev/null +++ b/app/code/Magento/Sales/Model/Resource/Order/Relation.php @@ -0,0 +1,103 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\Resource\Order; + +use Magento\Sales\Model\AbstractModel; +use Magento\Sales\Model\Resource\Order\Handler\Address as AddressHandler; +use Magento\Sales\Model\Resource\EntityRelationInterface; +use Magento\Sales\Model\Resource\Order\Item as OrderItemResource; +use Magento\Sales\Model\Resource\Order\Payment as OrderPaymentResource; +use Magento\Sales\Model\Resource\Order\Status\History as OrderStatusHistoryResource; + +/** + * Class Relation + */ +class Relation implements EntityRelationInterface +{ + /** + * @var AddressHandler + */ + protected $addressHandler; + + /** + * @var OrderItemResource + */ + protected $orderItemResource; + + /** + * @var OrderPaymentResource + */ + protected $orderPaymentResource; + + /** + * @var OrderStatusHistoryResource + */ + protected $orderStatusHistoryResource; + + /** + * @param AddressHandler $addressHandler + * @param OrderItemResource $orderItemResource + * @param OrderPaymentResource $orderPaymentResource + * @param OrderStatusHistoryResource $orderStatusHistoryResource + */ + public function __construct( + AddressHandler $addressHandler, + OrderItemResource $orderItemResource, + OrderPaymentResource $orderPaymentResource, + OrderStatusHistoryResource $orderStatusHistoryResource + ) { + $this->addressHandler = $addressHandler; + $this->orderItemResource = $orderItemResource; + $this->orderPaymentResource = $orderPaymentResource; + $this->orderStatusHistoryResource = $orderStatusHistoryResource; + } + + /** + * Save relations for Order + * + * @param AbstractModel $object + * @return void + * @throws \Exception + */ + public function processRelation(AbstractModel $object) + { + /** @var \Magento\Sales\Model\Order $object */ + $this->addressHandler->removeEmptyAddresses($object); + $this->addressHandler->process($object); + if (null !== $object->getItems()) { + /** @var \Magento\Sales\Model\Order\Item $item */ + foreach ($object->getItems() as $item) { + $item->setOrderId($object->getId()); + $item->setOrder($object); + $this->orderItemResource->save($item); + } + } + if (null !== $object->getPayments()) { + /** @var \Magento\Sales\Model\Order\Payment $payment */ + foreach ($object->getPayments() as $payment) { + $payment->setParentId($object->getId()); + $payment->setOrder($object); + $this->orderPaymentResource->save($payment); + } + } + if (null !== $object->getStatusHistories()) { + /** @var \Magento\Sales\Model\Order\Status\History $statusHistory */ + foreach ($object->getStatusHistories() as $statusHistory) { + $statusHistory->setParentId($object->getId()); + $statusHistory->setOrder($object); + $this->orderStatusHistoryResource->save($statusHistory); + + } + } + if (null !== $object->getRelatedObjects()) { + foreach ($object->getRelatedObjects() as $relatedObject) { + $relatedObject->setOrder($object); + $relatedObject->save(); + } + } + } +} diff --git a/app/code/Magento/Sales/Model/Resource/Order/Shipment.php b/app/code/Magento/Sales/Model/Resource/Order/Shipment.php index 577876a9e33142156c807b9d9ed4858895d86811..8fe7b8afa972e655edfcaed864336d697ef0791f 100644 --- a/app/code/Magento/Sales/Model/Resource/Order/Shipment.php +++ b/app/code/Magento/Sales/Model/Resource/Order/Shipment.php @@ -44,23 +44,6 @@ class Shipment extends SalesResource implements ShipmentResourceInterface $this->_init('sales_shipment', 'entity_id'); } - /** - * @param \Magento\Framework\Model\Resource\Db\Context $context - * @param Attribute $attribute - * @param Manager $sequenceManager - * @param EntitySnapshot $entitySnapshot - * @param string|null $resourcePrefix - */ - public function __construct( - \Magento\Framework\Model\Resource\Db\Context $context, - Attribute $attribute, - Manager $sequenceManager, - EntitySnapshot $entitySnapshot, - $resourcePrefix = null - ) { - parent::__construct($context, $attribute, $sequenceManager, $entitySnapshot, $resourcePrefix); - } - /** * Perform actions before object save * @@ -82,35 +65,4 @@ class Shipment extends SalesResource implements ShipmentResourceInterface return parent::_beforeSave($object); } - - /** - * Perform actions after object save - * - * @param \Magento\Framework\Model\AbstractModel $object - * @return $this - */ - protected function processRelations(\Magento\Framework\Model\AbstractModel $object) - { - /** @var \Magento\Sales\Model\Order\Shipment $object */ - if (null !== $object->getItems()) { - foreach ($object->getItems() as $item) { - $item->setParentId($object->getId()); - $item->save(); - } - } - - if (null !== $object->getTracks()) { - foreach ($object->getTracks() as $track) { - $track->save(); - } - } - - if (null !== $object->getComments()) { - foreach ($object->getComments() as $comment) { - $comment->save(); - } - } - - return parent::processRelations($object); - } } diff --git a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Comment.php b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Comment.php index affdf26d6138cf22136b4680666b682482697efb..0379873ee76fb01c21ce4b02d95cec43c174406d 100644 --- a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Comment.php +++ b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Comment.php @@ -35,19 +35,28 @@ class Comment extends EntityAbstract implements ShipmentCommentResourceInterface * @param \Magento\Sales\Model\Resource\Attribute $attribute * @param \Magento\SalesSequence\Model\Manager $sequenceManager * @param EntitySnapshot $entitySnapshot + * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite * @param \Magento\Sales\Model\Order\Shipment\Comment\Validator $validator - * @param string|null $resourcePrefix + * @param string $resourcePrefix */ public function __construct( \Magento\Framework\Model\Resource\Db\Context $context, \Magento\Sales\Model\Resource\Attribute $attribute, \Magento\SalesSequence\Model\Manager $sequenceManager, EntitySnapshot $entitySnapshot, + \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite, \Magento\Sales\Model\Order\Shipment\Comment\Validator $validator, $resourcePrefix = null ) { $this->validator = $validator; - parent::__construct($context, $attribute, $sequenceManager, $entitySnapshot, $resourcePrefix); + parent::__construct( + $context, + $attribute, + $sequenceManager, + $entitySnapshot, + $entityRelationComposite, + $resourcePrefix + ); } /** diff --git a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Relation.php b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Relation.php new file mode 100644 index 0000000000000000000000000000000000000000..8d25d48c40e2195d5dcb1c14e82c3b1e050eba28 --- /dev/null +++ b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Relation.php @@ -0,0 +1,76 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\Resource\Order\Shipment; + +use Magento\Sales\Model\Resource\EntityRelationInterface; +use Magento\Sales\Model\Resource\Order\Shipment\Item as ShipmentItemResource; +use Magento\Sales\Model\Resource\Order\Shipment\Comment as ShipmentCommentResource; +use Magento\Sales\Model\Resource\Order\Shipment\Track as ShipmentTrackResource; + +/** + * Class Relation + */ +class Relation implements EntityRelationInterface +{ + /** + * @var ShipmentItemResource + */ + protected $shipmentItemResource; + + /** + * @var ShipmentTrackResource + */ + protected $shipmentTrackResource; + + /** + * @var ShipmentCommentResource + */ + protected $shipmentCommentResource; + + /** + * @param Item $shipmentItemResource + * @param Track $shipmentTrackResource + * @param Comment $shipmentCommentResource + */ + public function __construct( + ShipmentItemResource $shipmentItemResource, + ShipmentTrackResource $shipmentTrackResource, + ShipmentCommentResource $shipmentCommentResource + ) { + $this->shipmentItemResource = $shipmentItemResource; + $this->shipmentTrackResource = $shipmentTrackResource; + $this->shipmentCommentResource = $shipmentCommentResource; + } + + /** + * Process relations for Shipment + * + * @param \Magento\Sales\Model\AbstractModel $object + * @return void + * @throws \Exception + */ + public function processRelation(\Magento\Sales\Model\AbstractModel $object) + { + /** @var \Magento\Sales\Model\Order\Shipment $object */ + if (null !== $object->getItems()) { + foreach ($object->getItems() as $item) { + $item->setParentId($object->getId()); + $this->shipmentItemResource->save($item); + } + } + if (null !== $object->getTracks()) { + foreach ($object->getTracks() as $track) { + $this->shipmentTrackResource->save($track); + } + } + if (null !== $object->getComments()) { + foreach ($object->getComments() as $comment) { + $this->shipmentCommentResource->save($comment); + } + } + } +} diff --git a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Track.php b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Track.php index cdbdbf78d8986d36f593886eb1cd0144e79670bf..07dfa2beb992ecc46df47024df476e44e5ab70bd 100644 --- a/app/code/Magento/Sales/Model/Resource/Order/Shipment/Track.php +++ b/app/code/Magento/Sales/Model/Resource/Order/Shipment/Track.php @@ -35,19 +35,28 @@ class Track extends SalesResource implements ShipmentTrackResourceInterface * @param \Magento\Sales\Model\Resource\Attribute $attribute * @param \Magento\SalesSequence\Model\Manager $sequenceManager * @param EntitySnapshot $entitySnapshot + * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite * @param \Magento\Sales\Model\Order\Shipment\Track\Validator $validator - * @param string|null $resourcePrefix + * @param string $resourcePrefix */ public function __construct( \Magento\Framework\Model\Resource\Db\Context $context, \Magento\Sales\Model\Resource\Attribute $attribute, \Magento\SalesSequence\Model\Manager $sequenceManager, EntitySnapshot $entitySnapshot, + \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite, \Magento\Sales\Model\Order\Shipment\Track\Validator $validator, $resourcePrefix = null ) { $this->validator = $validator; - parent::__construct($context, $attribute, $sequenceManager, $entitySnapshot, $resourcePrefix); + parent::__construct( + $context, + $attribute, + $sequenceManager, + $entitySnapshot, + $entityRelationComposite, + $resourcePrefix + ); } /** diff --git a/app/code/Magento/Sales/Model/Resource/Order/Status/History.php b/app/code/Magento/Sales/Model/Resource/Order/Status/History.php index c7aadebf49e3b9b659528753b0f8edc7766c81d7..8c13fdef8880954947e7c6c6f26f0d7b98b6cc22 100644 --- a/app/code/Magento/Sales/Model/Resource/Order/Status/History.php +++ b/app/code/Magento/Sales/Model/Resource/Order/Status/History.php @@ -27,19 +27,28 @@ class History extends EntityAbstract implements OrderStatusHistoryResourceInterf * @param \Magento\Sales\Model\Resource\Attribute $attribute * @param \Magento\SalesSequence\Model\Manager $sequenceManager * @param EntitySnapshot $entitySnapshot + * @param \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite * @param Validator $validator - * @param string|null $resourcePrefix + * @param string $resourcePrefix */ public function __construct( \Magento\Framework\Model\Resource\Db\Context $context, \Magento\Sales\Model\Resource\Attribute $attribute, \Magento\SalesSequence\Model\Manager $sequenceManager, EntitySnapshot $entitySnapshot, + \Magento\Sales\Model\Resource\EntityRelationComposite $entityRelationComposite, Validator $validator, $resourcePrefix = null ) { $this->validator = $validator; - parent::__construct($context, $attribute, $sequenceManager, $entitySnapshot, $resourcePrefix); + parent::__construct( + $context, + $attribute, + $sequenceManager, + $entitySnapshot, + $entityRelationComposite, + $resourcePrefix + ); } /** diff --git a/app/code/Magento/Sales/Model/Resource/Sale/Collection.php b/app/code/Magento/Sales/Model/Resource/Sale/Collection.php index 57cb4addd4b76f9b293bfc8b9d82c1f6992cf297..ade497aa07d9c330c0056fa3c394caa6e14715e5 100644 --- a/app/code/Magento/Sales/Model/Resource/Sale/Collection.php +++ b/app/code/Magento/Sales/Model/Resource/Sale/Collection.php @@ -10,12 +10,11 @@ use Magento\Store\Model\StoreManagerInterface; use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; use Magento\Framework\Event\ManagerInterface; use Psr\Log\LoggerInterface as Logger; -use Magento\Sales\Model\Resource\Order; /** * Sales Collection */ -class Collection extends \Magento\Framework\Data\Collection\Db +class Collection extends \Magento\Framework\Model\Resource\Db\Collection\AbstractCollection { /** * Totals data @@ -45,18 +44,6 @@ class Collection extends \Magento\Framework\Data\Collection\Db */ protected $_orderStateCondition = null; - /** - * Core event manager proxy - * - * @var ManagerInterface - */ - protected $_eventManager = null; - - /** - * @var Order - */ - protected $_orderResource; - /** * @var \Magento\Store\Model\Resource\Store\CollectionFactory */ @@ -72,24 +59,34 @@ class Collection extends \Magento\Framework\Data\Collection\Db * @param Logger $logger * @param FetchStrategyInterface $fetchStrategy * @param ManagerInterface $eventManager - * @param Order $resource * @param \Magento\Store\Model\Resource\Store\CollectionFactory $storeCollectionFactory - * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param StoreManagerInterface $storeManager */ public function __construct( EntityFactory $entityFactory, Logger $logger, FetchStrategyInterface $fetchStrategy, ManagerInterface $eventManager, - Order $resource, \Magento\Store\Model\Resource\Store\CollectionFactory $storeCollectionFactory, StoreManagerInterface $storeManager ) { - $this->_eventManager = $eventManager; - $this->_orderResource = $resource; $this->_storeCollectionFactory = $storeCollectionFactory; $this->_storeManager = $storeManager; - parent::__construct($entityFactory, $logger, $fetchStrategy, $this->_orderResource->getReadConnection()); + parent::__construct( + $entityFactory, + $logger, + $fetchStrategy, + $eventManager + ); + } + + /** + * {@inheritdoc} + */ + protected function _construct() + { + parent::_construct(); + $this->_init('Magento\Sales\Model\Order', 'Magento\Sales\Model\Resource\Order'); } /** @@ -136,22 +133,21 @@ class Collection extends \Magento\Framework\Data\Collection\Db */ protected function _beforeLoad() { - $this->getSelect()->from( - ['sales' => $this->_orderResource->getMainTable()], - [ - 'store_id', - 'lifetime' => new \Zend_Db_Expr('SUM(sales.base_grand_total)'), - 'base_lifetime' => new \Zend_Db_Expr('SUM(sales.base_grand_total * sales.base_to_global_rate)'), - 'avgsale' => new \Zend_Db_Expr('AVG(sales.base_grand_total)'), - 'base_avgsale' => new \Zend_Db_Expr('AVG(sales.base_grand_total * sales.base_to_global_rate)'), - 'num_orders' => new \Zend_Db_Expr('COUNT(sales.base_grand_total)') - ] - )->group( - 'sales.store_id' - ); + $this->getSelect() + ->columns( + [ + 'store_id', + 'lifetime' => new \Zend_Db_Expr('SUM(base_grand_total)'), + 'base_lifetime' => new \Zend_Db_Expr('SUM(base_grand_total * base_to_global_rate)'), + 'avgsale' => new \Zend_Db_Expr('AVG(base_grand_total)'), + 'base_avgsale' => new \Zend_Db_Expr('AVG(base_grand_total * base_to_global_rate)'), + 'num_orders' => new \Zend_Db_Expr('COUNT(base_grand_total)') + ] + ) + ->group('store_id'); if ($this->_customerId) { - $this->addFieldToFilter('sales.customer_id', $this->_customerId); + $this->addFieldToFilter('customer_id', $this->_customerId); } if ($this->_state !== null) { diff --git a/app/code/Magento/Sales/Setup/InstallSchema.php b/app/code/Magento/Sales/Setup/InstallSchema.php index a51b0b23971e7b422626ec75cf866ee62ab21185..a46e9c09e84a1b9b2e640d57860745c4b2e41a71 100644 --- a/app/code/Magento/Sales/Setup/InstallSchema.php +++ b/app/code/Magento/Sales/Setup/InstallSchema.php @@ -774,53 +774,53 @@ class InstallSchema implements InstallSchemaInterface [], 'Customer Gender' )->addColumn( - 'hidden_tax_amount', + 'discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Amount' + 'Discount Tax Compensation Amount' )->addColumn( - 'base_hidden_tax_amount', + 'base_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Amount' + 'Base Discount Tax Compensation Amount' )->addColumn( - 'shipping_hidden_tax_amount', + 'shipping_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Shipping Hidden Tax Amount' + 'Shipping Discount Tax Compensation Amount' )->addColumn( - 'base_shipping_hidden_tax_amnt', + 'base_shipping_discount_tax_compensation_amnt', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Shipping Hidden Tax Amount' + 'Base Shipping Discount Tax Compensation Amount' )->addColumn( - 'hidden_tax_invoiced', + 'discount_tax_compensation_invoiced', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Invoiced' + 'Discount Tax Compensation Invoiced' )->addColumn( - 'base_hidden_tax_invoiced', + 'base_discount_tax_compensation_invoiced', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Invoiced' + 'Base Discount Tax Compensation Invoiced' )->addColumn( - 'hidden_tax_refunded', + 'discount_tax_compensation_refunded', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Refunded' + 'Discount Tax Compensation Refunded' )->addColumn( - 'base_hidden_tax_refunded', + 'base_discount_tax_compensation_refunded', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Refunded' + 'Base Discount Tax Compensation Refunded' )->addColumn( 'shipping_incl_tax', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, @@ -1611,41 +1611,41 @@ class InstallSchema implements InstallSchemaInterface [], 'Base Row Total Incl Tax' )->addColumn( - 'hidden_tax_amount', + 'discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Amount' + 'Discount Tax Compensation Amount' )->addColumn( - 'base_hidden_tax_amount', + 'base_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Amount' + 'Base Discount Tax Compensation Amount' )->addColumn( - 'hidden_tax_invoiced', + 'discount_tax_compensation_invoiced', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Invoiced' + 'Discount Tax Compensation Invoiced' )->addColumn( - 'base_hidden_tax_invoiced', + 'base_discount_tax_compensation_invoiced', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Invoiced' + 'Base Discount Tax Compensation Invoiced' )->addColumn( - 'hidden_tax_refunded', + 'discount_tax_compensation_refunded', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Refunded' + 'Discount Tax Compensation Refunded' )->addColumn( - 'base_hidden_tax_refunded', + 'base_discount_tax_compensation_refunded', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Refunded' + 'Base Discount Tax Compensation Refunded' )->addColumn( 'tax_canceled', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, @@ -1653,11 +1653,11 @@ class InstallSchema implements InstallSchemaInterface [], 'Tax Canceled' )->addColumn( - 'hidden_tax_canceled', + 'discount_tax_compensation_canceled', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Canceled' + 'Discount Tax Compensation Canceled' )->addColumn( 'tax_refunded', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, @@ -2759,29 +2759,29 @@ class InstallSchema implements InstallSchemaInterface [], 'Updated At' )->addColumn( - 'hidden_tax_amount', + 'discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Amount' + 'Discount Tax Compensation Amount' )->addColumn( - 'base_hidden_tax_amount', + 'base_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Amount' + 'Base Discount Tax Compensation Amount' )->addColumn( - 'shipping_hidden_tax_amount', + 'shipping_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Shipping Hidden Tax Amount' + 'Shipping Discount Tax Compensation Amount' )->addColumn( - 'base_shipping_hidden_tax_amnt', + 'base_shipping_discount_tax_compensation_amnt', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Shipping Hidden Tax Amount' + 'Base Shipping Discount Tax Compensation Amount' )->addColumn( 'shipping_incl_tax', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, @@ -3128,17 +3128,17 @@ class InstallSchema implements InstallSchemaInterface [], 'Name' )->addColumn( - 'hidden_tax_amount', + 'discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Amount' + 'Discount Tax Compensation Amount' )->addColumn( - 'base_hidden_tax_amount', + 'base_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Amount' + 'Base Discount Tax Compensation Amount' )->addColumn( 'tax_ratio', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, @@ -3469,29 +3469,29 @@ class InstallSchema implements InstallSchemaInterface [], 'Updated At' )->addColumn( - 'hidden_tax_amount', + 'discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Amount' + 'Discount Tax Compensation Amount' )->addColumn( - 'base_hidden_tax_amount', + 'base_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Amount' + 'Base Discount Tax Compensation Amount' )->addColumn( - 'shipping_hidden_tax_amount', + 'shipping_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Shipping Hidden Tax Amount' + 'Shipping Discount Tax Compensation Amount' )->addColumn( - 'base_shipping_hidden_tax_amnt', + 'base_shipping_discount_tax_compensation_amnt', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Shipping Hidden Tax Amount' + 'Base Shipping Discount Tax Compensation Amount' )->addColumn( 'shipping_incl_tax', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, @@ -3874,17 +3874,17 @@ class InstallSchema implements InstallSchemaInterface [], 'Name' )->addColumn( - 'hidden_tax_amount', + 'discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Hidden Tax Amount' + 'Discount Tax Compensation Amount' )->addColumn( - 'base_hidden_tax_amount', + 'base_discount_tax_compensation_amount', \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, '12,4', [], - 'Base Hidden Tax Amount' + 'Base Discount Tax Compensation Amount' )->addColumn( 'tax_ratio', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, @@ -5024,12 +5024,6 @@ class InstallSchema implements InstallSchemaInterface '12,4', [], 'Base Real Amount' - )->addColumn( - 'hidden', - \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, - null, - ['unsigned' => true, 'nullable' => false, 'default' => '0'], - 'Hidden' )->addIndex( $installer->getIdxName('sales_order_tax', ['order_id', 'priority', 'position']), ['order_id', 'priority', 'position'] diff --git a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Comments/ViewTest.php b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Comments/ViewTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4a0654e76bd9564e299a082136160b22127860c2 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Comments/ViewTest.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Test\Unit\Block\Adminhtml\Order\Comments; + +class ViewTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Helper\Admin|\PHPUnit_Framework_MockObject_MockObject + */ + protected $adminHelperMock; + + /** + * @var \Magento\Sales\Block\Adminhtml\Order\Comments\View + */ + protected $commentsView; + + protected function setUp() + { + $this->adminHelperMock = $this->getMockBuilder('Magento\Sales\Helper\Admin') + ->disableOriginalConstructor() + ->getMock(); + + $this->commentsView = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( + 'Magento\Sales\Block\Adminhtml\Order\Comments\View', + [ + 'adminHelper' => $this->adminHelperMock + ] + ); + } + + /** + * @param string $data + * @param string $expected + * @param null|array $allowedTags + * @dataProvider escapeHtmlDataProvider + */ + public function testEscapeHtml($data, $expected, $allowedTags = null) + { + $this->adminHelperMock + ->expects($this->any()) + ->method('escapeHtmlWithLinks') + ->will($this->returnValue($expected)); + $actual = $this->commentsView->escapeHtml($data, $allowedTags); + $this->assertEquals($expected, $actual); + } + + /** + * @return array + */ + public function escapeHtmlDataProvider() + { + return [ + [ + '<a>some text in tags</a>', + '<a>some text in tags</a>', + 'allowedTags' => null + ], + [ + 'Transaction ID: "<a target="_blank" href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', + 'Transaction ID: "<a target="_blank" href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', + 'allowedTags' => ['b', 'br', 'strong', 'i', 'u', 'a'] + ], + [ + '<a>some text in tags</a>', + '<a>some text in tags</a>', + 'allowedTags' => ['a'] + ] + ]; + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Create/Items/GridTest.php b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Create/Items/GridTest.php index 702ff9abb36b9d40025f4c14d64b57921841cfee..f2ea36b5e32c0ddc84111a2234a7369f1fa6fb6a 100644 --- a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Create/Items/GridTest.php +++ b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/Create/Items/GridTest.php @@ -372,7 +372,7 @@ class GridTest extends \PHPUnit_Framework_TestCase { $quoteAddressMock = $this->getMock( '\Magento\Quote\Model\Quote\Address', - ['getSubtotal', 'getTaxAmount','getHiddenTaxAmount','getDiscountAmount'], + ['getSubtotal', 'getTaxAmount','getDiscountTaxCompensationAmount','getDiscountAmount'], [], '', false @@ -399,8 +399,8 @@ class GridTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($orderData['taxAmount'])); $quoteAddressMock->expects($this->any()) - ->method('getHiddenTaxAmount') - ->will($this->returnValue($orderData['hiddenTaxAmount'])); + ->method('getDiscountTaxCompensationAmount') + ->will($this->returnValue($orderData['discountTaxCompensationAmount'])); $quoteAddressMock->expects($this->once()) ->method('getDiscountAmount') @@ -419,7 +419,7 @@ class GridTest extends \PHPUnit_Framework_TestCase 'orderData' => [ 'subTotal' => 32.59, 'taxAmount' => 8.2, - 'hiddenTaxAmount' => 1.72, + 'discountTaxCompensationAmount' => 1.72, 'discountAmount' => -10.24 ], 'displayTotalsIncludeTax'=> true, @@ -429,7 +429,7 @@ class GridTest extends \PHPUnit_Framework_TestCase 'orderData' => [ 'subTotal' => 66.67, 'taxAmount' => 20, - 'hiddenTaxAmount' => 8, + 'discountTaxCompensationAmount' => 8, 'discountAmount' => -34.67 ], 'displayTotalsIncludeTax'=> false, diff --git a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/View/HistoryTest.php b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/View/HistoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b79f002a15f1efc171d3b9c225574a47591ff53e --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/View/HistoryTest.php @@ -0,0 +1,73 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Test\Unit\Block\Adminhtml\Order\View; + +class HistoryTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Helper\Admin|\PHPUnit_Framework_MockObject_MockObject + */ + protected $adminHelperMock; + + /** + * @var \Magento\Sales\Block\Adminhtml\Order\View\History + */ + protected $viewHistory; + + protected function setUp() + { + $this->adminHelperMock = $this->getMockBuilder('Magento\Sales\Helper\Admin') + ->disableOriginalConstructor() + ->getMock(); + + $this->viewHistory = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( + 'Magento\Sales\Block\Adminhtml\Order\View\History', + [ + 'adminHelper' => $this->adminHelperMock + ] + ); + } + + /** + * @param string $data + * @param string $expected + * @param null|array $allowedTags + * @dataProvider escapeHtmlDataProvider + */ + public function testEscapeHtml($data, $expected, $allowedTags = null) + { + $this->adminHelperMock + ->expects($this->any()) + ->method('escapeHtmlWithLinks') + ->will($this->returnValue($expected)); + $actual = $this->viewHistory->escapeHtml($data, $allowedTags); + $this->assertEquals($expected, $actual); + } + + /** + * @return array + */ + public function escapeHtmlDataProvider() + { + return [ + [ + '<a>some text in tags</a>', + '<a>some text in tags</a>', + 'allowedTags' => null + ], + [ + 'Transaction ID: "<a target="_blank" href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', + 'Transaction ID: "<a target="_blank" href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', + 'allowedTags' => ['b', 'br', 'strong', 'i', 'u', 'a'] + ], + [ + '<a>some text in tags</a>', + '<a>some text in tags</a>', + 'allowedTags' => ['a'] + ] + ]; + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/View/Tab/HistoryTest.php b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/View/Tab/HistoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5a06e1fabdb2dc5641063b814d374f1e254a622d --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Block/Adminhtml/Order/View/Tab/HistoryTest.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Test\Unit\Block\Adminhtml\Order\View\Tab; + +/** + * Order History tab test + */ +class HistoryTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + protected $objectManager; + + /** + * @var \Magento\Sales\Helper\Admin|\PHPUnit_Framework_MockObject_MockObject + */ + protected $adminHelperMock; + + /** + * @var \Magento\Sales\Block\Adminhtml\Order\View\Tab\History + */ + protected $commentsHistory; + + /** + * @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject + */ + protected $coreRegistryMock; + + protected function setUp() + { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->coreRegistryMock = $this->getMock('Magento\Framework\Registry', [], [], '', false); + $this->adminHelperMock = $this->getMock('\Magento\Sales\Helper\Admin', [], [], '', false); + + $this->commentsHistory = $this->objectManager->getObject( + 'Magento\Sales\Block\Adminhtml\Order\View\Tab\History', + [ + 'adminHelper' => $this->adminHelperMock, + 'registry' => $this->coreRegistryMock + ] + ); + } + + public function testGetItemComment() + { + $expectation = 'Authorized amount of £20.00 Transaction ID: "XXX123123XXX"'; + $item['comment'] = 'Authorized amount of £20.00 Transaction ID: "XXX123123XXX"'; + $this->adminHelperMock->expects($this->once()) + ->method('escapeHtmlWithLinks') + ->with($item['comment'], ['b', 'br', 'strong', 'i', 'u', 'a']) + ->willReturn($expectation); + $this->assertEquals($expectation, $this->commentsHistory->getItemComment($item)); + } + + public function testGetItemCommentIsNotSet() + { + $item = []; + $this->adminHelperMock->expects($this->never())->method('escapeHtmlWithLinks'); + $this->assertEquals('', $this->commentsHistory->getItemComment($item)); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Block/Order/Item/Renderer/DefaultRendererTest.php b/app/code/Magento/Sales/Test/Unit/Block/Order/Item/Renderer/DefaultRendererTest.php index 60be7a3732baef1aa30be9c4fa1d74fc5991485a..a01e87ee740c7c12aabae277a3aca2d7fb02168b 100644 --- a/app/code/Magento/Sales/Test/Unit/Block/Order/Item/Renderer/DefaultRendererTest.php +++ b/app/code/Magento/Sales/Test/Unit/Block/Order/Item/Renderer/DefaultRendererTest.php @@ -65,7 +65,7 @@ class DefaultRendererTest extends \PHPUnit_Framework_TestCase 'getRowTotal', 'getTaxAmount', 'getDiscountAmount', - 'getHiddenTaxAmount', + 'getDiscountTaxCompensationAmount', 'getWeeeTaxAppliedRowAmount', ]; $this->itemMock = $this->getMockBuilder('\Magento\Sales\Model\Order\Item') @@ -138,11 +138,11 @@ class DefaultRendererTest extends \PHPUnit_Framework_TestCase { $rowTotal = 100; $taxAmount = 10; - $hiddenTaxAmount = 2; + $discountTaxCompensationAmount = 2; $discountAmount = 20; $weeeTaxAppliedRowAmount = 10; - $expectedResult = $rowTotal + $taxAmount + $hiddenTaxAmount - $discountAmount + $weeeTaxAppliedRowAmount; + $expectedResult = $rowTotal + $taxAmount + $discountTaxCompensationAmount - $discountAmount + $weeeTaxAppliedRowAmount; $this->itemMock->expects($this->once()) ->method('getRowTotal') ->will($this->returnValue($rowTotal)); @@ -150,8 +150,8 @@ class DefaultRendererTest extends \PHPUnit_Framework_TestCase ->method('getTaxAmount') ->will($this->returnValue($taxAmount)); $this->itemMock->expects($this->once()) - ->method('getHiddenTaxAmount') - ->will($this->returnValue($hiddenTaxAmount)); + ->method('getDiscountTaxCompensationAmount') + ->will($this->returnValue($discountTaxCompensationAmount)); $this->itemMock->expects($this->once()) ->method('getDiscountAmount') ->will($this->returnValue($discountAmount)); diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/ReviewPaymentTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/ReviewPaymentTest.php index 63dae97d9093ce63f13d9e625fac52e3a88ec665..b2d3cd81597345f3163dfa3ae21a9342806828af 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/ReviewPaymentTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/ReviewPaymentTest.php @@ -77,7 +77,7 @@ class ReviewPaymentTest extends \PHPUnit_Framework_TestCase $this->paymentMock = $this->getMock( 'Magento\Sales\Model\Order\Payment', - ['registerPaymentReviewAction', 'update'], + ['update'], [], '', false diff --git a/app/code/Magento/Sales/Test/Unit/Helper/AdminTest.php b/app/code/Magento/Sales/Test/Unit/Helper/AdminTest.php index 219b6cc65bedf4e4a5a4465027319abc72ffa2e2..d9ccb49706544b75e567dbb9435ba45092fe4219 100644 --- a/app/code/Magento/Sales/Test/Unit/Helper/AdminTest.php +++ b/app/code/Magento/Sales/Test/Unit/Helper/AdminTest.php @@ -44,6 +44,11 @@ class AdminTest extends \PHPUnit_Framework_TestCase */ protected $priceCurrency; + /** + * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject + */ + protected $escaperMock; + protected function setUp() { $this->contextMock = $this->getMockBuilder('Magento\Framework\App\Helper\Context') @@ -57,6 +62,10 @@ class AdminTest extends \PHPUnit_Framework_TestCase ->getMock(); $this->priceCurrency = $this->getMockBuilder('\Magento\Framework\Pricing\PriceCurrencyInterface')->getMock(); + $this->escaperMock = $this->getMockBuilder('Magento\Framework\Escaper') + ->disableOriginalConstructor() + ->getMock(); + $this->adminHelper = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( 'Magento\Sales\Helper\Admin', [ @@ -64,6 +73,7 @@ class AdminTest extends \PHPUnit_Framework_TestCase 'storeManager' => $this->storeManagerMock, 'salesConfig' => $this->salesConfigMock, 'priceCurrency' => $this->priceCurrency, + 'escaper' => $this->escaperMock ] ); @@ -306,4 +316,44 @@ class AdminTest extends \PHPUnit_Framework_TestCase ['other', 'validProductType', 1], ]; } + + /** + * @param string $data + * @param string $expected + * @param null|array $allowedTags + * @dataProvider escapeHtmlWithLinksDataProvider + */ + public function testEscapeHtmlWithLinks($data, $expected, $allowedTags = null) + { + $this->escaperMock + ->expects($this->any()) + ->method('escapeHtml') + ->will($this->returnValue($expected)); + $actual = $this->adminHelper->escapeHtmlWithLinks($data, $allowedTags); + $this->assertEquals($expected, $actual); + } + + /** + * @return array + */ + public function escapeHtmlWithLinksDataProvider() + { + return [ + [ + '<a>some text in tags</a>', + '<a>some text in tags</a>', + 'allowedTags' => null + ], + [ + 'Transaction ID: "<a target="_blank" href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', + 'Transaction ID: "<a target="_blank" href="https://www.paypal.com/?id=XX123XX">XX123XX</a>"', + 'allowedTags' => ['b', 'br', 'strong', 'i', 'u', 'a'] + ], + [ + '<a>some text in tags</a>', + '<a>some text in tags</a>', + 'allowedTags' => ['a'] + ] + ]; + } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Email/TemplateTest.php b/app/code/Magento/Sales/Test/Unit/Model/Email/TemplateTest.php index c8c3632bb160226bbf95918724fe1423fdad2755..37c29c2be223a85d35eb22fa196c757480c062ed 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Email/TemplateTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Email/TemplateTest.php @@ -25,6 +25,11 @@ class TemplateTest extends \PHPUnit_Framework_TestCase */ private $mockViewFilesystem; + /** + * @var \Magento\Framework\App\ObjectManager + */ + protected $objectManagerBackup; + public function setUp() { $this->mockViewFilesystem = $this->getMockBuilder('\Magento\Framework\View\FileSystem') @@ -38,6 +43,13 @@ class TemplateTest extends \PHPUnit_Framework_TestCase ->method('get') ->with('Magento\Email\Model\Resource\Template') ->will($this->returnValue($objectManagerHelper->getObject('Magento\Email\Model\Resource\Template'))); + + try { + $this->objectManagerBackup = \Magento\Framework\App\ObjectManager::getInstance(); + } catch (\RuntimeException $e) { + $this->objectManagerBackup = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER) + ->create($_SERVER); + } \Magento\Framework\App\ObjectManager::setInstance($objectManagerMock); $this->template = $objectManagerHelper->getObject( @@ -51,9 +63,7 @@ class TemplateTest extends \PHPUnit_Framework_TestCase protected function tearDown() { parent::tearDown(); - $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); - $objectManager = $magentoObjectManagerFactory->create($_SERVER); - \Magento\Framework\App\ObjectManager::setInstance($objectManager); + \Magento\Framework\App\ObjectManager::setInstance($this->objectManagerBackup); } public function testIncludeTemplate() diff --git a/app/code/Magento/Sales/Test/Unit/Model/Observer/IndexGridTest.php b/app/code/Magento/Sales/Test/Unit/Model/Observer/IndexGridTest.php new file mode 100644 index 0000000000000000000000000000000000000000..11ba16ec146294e2ae7efd8acf2aa35c66e79344 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Observer/IndexGridTest.php @@ -0,0 +1,133 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Unit\Model\Observer; + +/** + * Class IndexGridTest + */ +class IndexGridTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Model\Observer\IndexGrid + */ + protected $indexGrid; + + /** + * @var \Magento\Sales\Model\Resource\GridInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $gridAggregatorMock; + + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $scopeConfigurationMock; + + /** + * @var \Magento\Framework\Event\Observer|\PHPUnit_Framework_MockObject_MockObject + */ + protected $eventObserverMock; + + /** + * @var \Magento\Sales\Model\AbstractModel|\PHPUnit_Framework_MockObject_MockObject + */ + protected $salesModelMock; + + public function setUp() + { + $this->gridAggregatorMock = $this->getMockBuilder('Magento\Sales\Model\Resource\GridInterface') + ->getMockForAbstractClass(); + $this->scopeConfigurationMock = $this->getMockBuilder('Magento\Framework\App\Config\ScopeConfigInterface') + ->getMockForAbstractClass(); + $this->eventObserverMock = $this->getMockBuilder('Magento\Framework\Event\Observer') + ->disableOriginalConstructor() + ->setMethods( + [ + 'getObject', + 'getDataObject' + ] + ) + ->getMock(); + $this->salesModelMock = $this->getMockBuilder('Magento\Sales\Model\AbstractModel') + ->disableOriginalConstructor() + ->setMethods( + [ + 'getId' + ] + ) + ->getMockForAbstractClass(); + $this->indexGrid = new \Magento\Sales\Model\Observer\IndexGrid( + $this->gridAggregatorMock, + $this->scopeConfigurationMock + ); + } + + public function testSyncInsert() + { + $this->eventObserverMock->expects($this->once()) + ->method('getObject') + ->willReturn($this->salesModelMock); + $this->salesModelMock->expects($this->once()) + ->method('getId') + ->willReturn('sales-id-value'); + $this->scopeConfigurationMock->expects($this->once()) + ->method('getValue') + ->with('dev/grid/async_indexing', 'default', null) + ->willReturn(false); + $this->gridAggregatorMock->expects($this->once()) + ->method('refresh') + ->with('sales-id-value'); + $this->indexGrid->syncInsert($this->eventObserverMock); + } + + public function testSyncInsertDisabled() + { + $this->scopeConfigurationMock->expects($this->once()) + ->method('getValue') + ->with('dev/grid/async_indexing', 'default', null) + ->willReturn(true); + $this->gridAggregatorMock->expects($this->never()) + ->method('refresh') + ->with('sales-id-value'); + $this->indexGrid->syncInsert($this->eventObserverMock); + } + + public function testSyncRemove() + { + $this->eventObserverMock->expects($this->once()) + ->method('getDataObject') + ->willReturn($this->salesModelMock); + $this->salesModelMock->expects($this->once()) + ->method('getId') + ->willReturn('sales-id-value'); + $this->gridAggregatorMock->expects($this->once()) + ->method('purge') + ->with('sales-id-value'); + $this->indexGrid->syncRemove($this->eventObserverMock); + } + + public function testAsyncInsert() + { + $this->scopeConfigurationMock->expects($this->once()) + ->method('getValue') + ->with('dev/grid/async_indexing', 'default', null) + ->willReturn(true); + $this->gridAggregatorMock->expects($this->once()) + ->method('refreshBySchedule'); + $this->indexGrid->asyncInsert(); + } + + public function testAsyncInsertDisabled() + { + $this->scopeConfigurationMock->expects($this->once()) + ->method('getValue') + ->with('dev/grid/async_indexing', 'default', null) + ->willReturn(false); + $this->gridAggregatorMock->expects($this->never()) + ->method('refreshBySchedule'); + $this->indexGrid->asyncInsert(); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/AddressTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/AddressTest.php index 985723b3f8523b125e92ad77a98b2fa9aff694b8..3a3318311511f384a5ee2e9885b01608abb6b2be 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/AddressTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/AddressTest.php @@ -94,13 +94,9 @@ class AddressTest extends \PHPUnit_Framework_TestCase */ public function testGetRegionCodeRegion($region, $regionId) { - $this->address->setData( - [ - 'region' => $region, - 'region_id' => $regionId, - 'country_id' => 1 - ] - ); + $this->address->setData('region', $region); + $this->address->setData('region_id', $regionId); + $this->address->setData('country_id', 1); $this->regionFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->regionMock); @@ -119,13 +115,9 @@ class AddressTest extends \PHPUnit_Framework_TestCase public function testGetRegionCodeRegionFailure() { - $this->address->setData( - [ - 'region' => 1, - 'region_id' => 1, - 'country_id' => 1 - ] - ); + $this->address->setData('region', 1); + $this->address->setData('region_id', 1); + $this->address->setData('country_id', 1); $this->regionFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->regionMock); @@ -143,15 +135,11 @@ class AddressTest extends \PHPUnit_Framework_TestCase public function testGetName() { - $this->address->setData( - [ - 'suffix' => 'suffix', - 'prefix' => 'prefix', - 'firstname' => 'firstname', - 'middlename' => 'middlename', - 'lastname' => 'lastname' - ] - ); + $this->address->setData('suffix', 'suffix'); + $this->address->setData('prefix', 'prefix'); + $this->address->setData('firstname', 'firstname'); + $this->address->setData('middlename', 'middlename'); + $this->address->setData('lastname', 'lastname'); $this->assertEquals('prefix firstname middlename lastname suffix', $this->address->getName()); } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/ItemTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/ItemTest.php index 0673aa120a217ae4daa1d549b441a2969c510d81..2d453189d607ff9669676312db79538430eafc7e 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/ItemTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/ItemTest.php @@ -177,10 +177,10 @@ class ItemTest extends \PHPUnit_Framework_TestCase ->method('getBaseTaxRefunded') ->willReturn(1); $orderItemMock->expects($this->once()) - ->method('getHiddenTaxRefunded') + ->method('getDiscountTaxCompensationRefunded') ->willReturn(1); $orderItemMock->expects($this->once()) - ->method('getBaseHiddenTaxRefunded') + ->method('getBaseDiscountTaxCompensationRefunded') ->willReturn(1); $orderItemMock->expects($this->once()) ->method('getAmountRefunded') @@ -198,8 +198,8 @@ class ItemTest extends \PHPUnit_Framework_TestCase 'qty' => 1, 'tax_amount' => 1, 'base_tax_amount' => 1, - 'hidden_tax_amount' => 1, - 'base_hidden_tax_amount' => 1, + 'discount_tax_compensation_amount' => 1, + 'base_discount_tax_compensation_amount' => 1, 'row_total' => 1, 'base_row_total' => 1, 'discount_amount' => 1, @@ -223,9 +223,9 @@ class ItemTest extends \PHPUnit_Framework_TestCase 'getBaseTaxAmount', 'getQtyOrdered', 'setTaxRefunded', - 'setHiddenTaxRefunded', - 'getHiddenTaxRefunded', - 'getHiddenTaxAmount' + 'setDiscountTaxCompensationRefunded', + 'getDiscountTaxCompensationRefunded', + 'getDiscountTaxCompensationAmount' ] ) ->getMock(); @@ -249,13 +249,13 @@ class ItemTest extends \PHPUnit_Framework_TestCase ->with(5); $orderItemMock->expects($this->once()) - ->method('setHiddenTaxRefunded') + ->method('setDiscountTaxCompensationRefunded') ->with(0); $orderItemMock->expects($this->once()) - ->method('getHiddenTaxRefunded') + ->method('getDiscountTaxCompensationRefunded') ->willReturn(10); $orderItemMock->expects($this->once()) - ->method('getHiddenTaxAmount') + ->method('getDiscountTaxCompensationAmount') ->willReturn(10); $this->item->setData('qty', 1); diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php index cf4124f653cfa2080e3b6f81e51f5fc63e44cabf..e4a36e24263c5656e4f3ef82a7dffec6c5f799ee 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php @@ -151,8 +151,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'data_fields' => [ 'shipping_tax_amount' => 2.45, 'base_shipping_tax_amount' => 2.45, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 53.56, 'base_tax_amount' => 53.56, 'tax_invoiced' => 24.33, @@ -171,8 +171,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_refunded' => 0, 'base_tax_invoiced' => 8.11, 'base_tax_refunded' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'qty_refunded' => 0, ], 'is_last' => false, @@ -185,8 +185,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_invoiced' => 16.22, 'base_tax_refunded' => 0, 'base_tax_invoiced' => 16.22, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'qty_refunded' => 0, ], 'is_last' => false, @@ -204,8 +204,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase [ 'shipping_tax_amount' => 2.45, 'base_shipping_tax_amount' => 2.45, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, ] ), ], @@ -240,8 +240,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'data_fields' => [ 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 16.09, 'base_tax_amount' => 16.09, 'tax_invoiced' => 11.14, @@ -260,8 +260,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_refunded' => 0, 'base_tax_invoiced' => 8.26, 'base_tax_refunded' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'qty_refunded' => 0, ], 'is_last' => false, @@ -279,8 +279,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase [ 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, ] ), ], @@ -313,8 +313,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'base_shipping_tax_amount' => 1.24, 'shipping_tax_refunded' => 1.24, 'base_shipping_tax_refunded' => 1.24, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 16.09, 'base_tax_amount' => 16.09, 'tax_invoiced' => 16.09, @@ -336,8 +336,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_refunded' => 8.26, 'base_tax_invoiced' => 12.38, 'base_tax_refunded' => 8.26, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'qty_refunded' => 2, ], 'is_last' => true, @@ -355,8 +355,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase [ 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, ] ), ], @@ -378,7 +378,7 @@ class TaxTest extends \PHPUnit_Framework_TestCase ]; // scenario 4: 3 items, 2 invoiced, price includes tax - // partial credit memo, make sure that hidden tax is calculated correctly + // partial credit memo, make sure that discount tax compensation is calculated correctly $result['partial_invoice_partial_creditmemo_price_incl_tax'] = [ 'order_data' => [ 'data_fields' => [ @@ -386,20 +386,20 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'base_shipping_tax_amount' => 0, 'shipping_tax_refunded' => 0, 'base_shipping_tax_refunded' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 13.72, 'base_tax_amount' => 13.72, 'tax_invoiced' => 9.15, 'base_tax_invoiced' => 9.15, 'tax_refunded' => 0, 'base_tax_refunded' => 0, - 'hidden_tax_amount' => 11.43, - 'base_hidden_tax_amount' => 11.43, - 'hidden_tax_invoiced' => 7.62, - 'base_hidden_tax_invoiced' => 7.62, - 'hidden_tax_refunded' => 0, - 'base_hidden_tax_refunded' => 0, + 'discount_tax_compensation_amount' => 11.43, + 'base_discount_tax_compensation_amount' => 11.43, + 'discount_tax_compensation_invoiced' => 7.62, + 'base_discount_tax_compensation_invoiced' => 7.62, + 'discount_tax_compensation_refunded' => 0, + 'base_discount_tax_compensation_refunded' => 0, 'shipping_amount' => 0, 'shipping_amount_refunded' => 0, 'base_shipping_amount' => 0, @@ -415,10 +415,10 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_refunded' => 0, 'base_tax_invoiced' => 7.62, 'base_tax_refunded' => 0, - 'hidden_tax_amount' => 11.43, - 'base_hidden_tax_amount' => 11.43, - 'hidden_tax_invoiced' => 7.62, - 'base_hidden_tax_invoiced' => 7.62, + 'discount_tax_compensation_amount' => 11.43, + 'base_discount_tax_compensation_amount' => 11.43, + 'discount_tax_compensation_invoiced' => 7.62, + 'base_discount_tax_compensation_invoiced' => 7.62, 'qty_refunded' => 0, ], 'is_last' => false, @@ -436,8 +436,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase [ 'shipping_tax_amount' => 0, 'base_shipping_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, ] ), ], @@ -467,8 +467,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'base_shipping_tax_amount' => 1.24, 'shipping_tax_refunded' => 0, 'base_shipping_tax_refunded' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 16.09, 'base_tax_amount' => 16.09, 'tax_invoiced' => 16.09, @@ -490,8 +490,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_refunded' => 8.26, 'base_tax_invoiced' => 12.38, 'base_tax_refunded' => 8.26, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'qty_refunded' => 2, ], 'is_last' => true, @@ -510,8 +510,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase [ 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, ] ), ], diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/ItemTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/ItemTest.php index 914ba25fe30275275a45d622ae1f6e3b0aca122e..a5d00ec9cd813e1df644cf9e69cacfd5bf36ec61 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/ItemTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/ItemTest.php @@ -61,9 +61,11 @@ class ItemTest extends \PHPUnit_Framework_TestCase 'Magento\Sales\Model\Order\Item', [ 'load', 'isDummy', 'getIsQtyDecimal', 'getQtyToInvoice', 'getQtyInvoiced', 'getTaxInvoiced', - 'getBaseTaxInvoiced', 'getHiddenTaxInvoiced', 'getBaseHiddenTaxInvoiced', 'getDiscountInvoiced', + 'getBaseTaxInvoiced', 'getDiscountTaxCompensationInvoiced', + 'getBaseDiscountTaxCompensationInvoiced', 'getDiscountInvoiced', 'getBaseDiscountInvoiced', 'getRowInvoiced', 'getBaseRowInvoiced', 'setQtyInvoiced', 'setTaxInvoiced', - 'setBaseTaxInvoiced', 'setHiddenTaxInvoiced', 'setBaseHiddenTaxInvoiced', 'setDiscountInvoiced', + 'setBaseTaxInvoiced', 'setDiscountTaxCompensationInvoiced', + 'setBaseDiscountTaxCompensationInvoiced', 'setDiscountInvoiced', 'setBaseDiscountInvoiced', 'setRowInvoiced', 'setBaseRowInvoiced', 'getQtyOrdered', 'getRowTotal', 'getBaseRowTotal', 'getRowTotalInclTax', 'getBaseRowTotalInclTax' ], @@ -110,8 +112,8 @@ class ItemTest extends \PHPUnit_Framework_TestCase $this->orderItemMock->expects($this->once())->method('getQtyInvoiced')->willReturn(1); $this->orderItemMock->expects($this->once())->method('getTaxInvoiced')->willReturn(1); $this->orderItemMock->expects($this->once())->method('getBaseTaxInvoiced')->willReturn(1); - $this->orderItemMock->expects($this->once())->method('getHiddenTaxInvoiced')->willReturn(1); - $this->orderItemMock->expects($this->once())->method('getBaseHiddenTaxInvoiced')->willReturn(1); + $this->orderItemMock->expects($this->once())->method('getDiscountTaxCompensationInvoiced')->willReturn(1); + $this->orderItemMock->expects($this->once())->method('getBaseDiscountTaxCompensationInvoiced')->willReturn(1); $this->orderItemMock->expects($this->once())->method('getDiscountInvoiced')->willReturn(1); $this->orderItemMock->expects($this->once())->method('getBaseDiscountInvoiced')->willReturn(1); $this->orderItemMock->expects($this->once())->method('getRowInvoiced')->willReturn(1); @@ -119,20 +121,23 @@ class ItemTest extends \PHPUnit_Framework_TestCase $this->orderItemMock->expects($this->once())->method('setQtyInvoiced')->with(2)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setTaxInvoiced')->with(2)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setBaseTaxInvoiced')->with(2)->willReturnSelf(); - $this->orderItemMock->expects($this->once())->method('setHiddenTaxInvoiced')->with(2)->willReturnSelf(); - $this->orderItemMock->expects($this->once())->method('setBaseHiddenTaxInvoiced')->with(2)->willReturnSelf(); + $this->orderItemMock->expects($this->once()) + ->method('setDiscountTaxCompensationInvoiced')->with(2)->willReturnSelf(); + $this->orderItemMock->expects($this->once()) + ->method('setBaseDiscountTaxCompensationInvoiced')->with(2)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setDiscountInvoiced')->with(2)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setBaseDiscountInvoiced')->with(2)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setRowInvoiced')->with(2)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setBaseRowInvoiced')->with(2)->willReturnSelf(); + $this->item->setData( [ 'order_item_id' => 1, 'qty' => 1, 'tax_amount' => 1, 'base_tax_amount' => 1, - 'hidden_tax_amount' => 1, - 'base_hidden_tax_amount' => 1, + 'discount_tax_compensation_amount' => 1, + 'base_discount_tax_compensation_amount' => 1, 'discount_amount' => 1, 'base_discount_amount' => 1, 'row_total' => 1, @@ -149,8 +154,8 @@ class ItemTest extends \PHPUnit_Framework_TestCase $this->orderItemMock->expects($this->once())->method('getQtyInvoiced')->willReturn(1); $this->orderItemMock->expects($this->once())->method('getTaxInvoiced')->willReturn(1); $this->orderItemMock->expects($this->once())->method('getBaseTaxInvoiced')->willReturn(1); - $this->orderItemMock->expects($this->once())->method('getHiddenTaxInvoiced')->willReturn(1); - $this->orderItemMock->expects($this->once())->method('getBaseHiddenTaxInvoiced')->willReturn(1); + $this->orderItemMock->expects($this->once())->method('getDiscountTaxCompensationInvoiced')->willReturn(1); + $this->orderItemMock->expects($this->once())->method('getBaseDiscountTaxCompensationInvoiced')->willReturn(1); $this->orderItemMock->expects($this->once())->method('getDiscountInvoiced')->willReturn(1); $this->orderItemMock->expects($this->once())->method('getBaseDiscountInvoiced')->willReturn(1); $this->orderItemMock->expects($this->once())->method('getRowInvoiced')->willReturn(1); @@ -158,20 +163,23 @@ class ItemTest extends \PHPUnit_Framework_TestCase $this->orderItemMock->expects($this->once())->method('setQtyInvoiced')->with(0)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setTaxInvoiced')->with(0)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setBaseTaxInvoiced')->with(0)->willReturnSelf(); - $this->orderItemMock->expects($this->once())->method('setHiddenTaxInvoiced')->with(0)->willReturnSelf(); - $this->orderItemMock->expects($this->once())->method('setBaseHiddenTaxInvoiced')->with(0)->willReturnSelf(); + $this->orderItemMock->expects($this->once())->method('setDiscountTaxCompensationInvoiced') + ->with(0)->willReturnSelf(); + $this->orderItemMock->expects($this->once())->method('setBaseDiscountTaxCompensationInvoiced') + ->with(0)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setDiscountInvoiced')->with(0)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setBaseDiscountInvoiced')->with(0)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setRowInvoiced')->with(0)->willReturnSelf(); $this->orderItemMock->expects($this->once())->method('setBaseRowInvoiced')->with(0)->willReturnSelf(); + $this->item->setData( [ 'order_item_id' => 1, 'qty' => 1, 'tax_amount' => 1, 'base_tax_amount' => 1, - 'hidden_tax_amount' => 1, - 'base_hidden_tax_amount' => 1, + 'discount_tax_compensation_amount' => 1, + 'base_discount_tax_compensation_amount' => 1, 'discount_amount' => 1, 'base_discount_amount' => 1, 'row_total' => 1, @@ -183,10 +191,8 @@ class ItemTest extends \PHPUnit_Framework_TestCase public function testCalcRowTotal() { - $this->item->setData([ - 'order_item_id' => 1, - 'qty' => 2 - ]); + $this->item->setData('order_item_id', 1); + $this->item->setData('qty', 2); $this->item->setInvoice($this->invoiceMock); $this->invoiceMock->expects($this->once())->method('getOrder')->willReturn($this->orderMock); $this->orderMock->expects($this->once())->method('getItemById')->with(1)->willReturn($this->orderItemMock); diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/Total/TaxTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/Total/TaxTest.php index 1b99da0a0f7b0581667f8f3a76cbee8144518a23..e62a83b88e72b9a58d95e2a4028e0d45076b9401 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/Total/TaxTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Invoice/Total/TaxTest.php @@ -148,8 +148,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'data_fields' => [ 'shipping_tax_amount' => 2.45, 'base_shipping_tax_amount' => 2.45, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 53.56, 'base_tax_amount' => 53.56, ], @@ -163,8 +163,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_invoiced' => 0, 'base_tax_amount' => 24.32, 'base_tax_invoiced' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'qty_invoiced' => 0, ], 'is_last' => false, @@ -177,8 +177,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_invoiced' => 0, 'base_tax_amount' => 24.33, 'base_tax_invoiced' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'qty_invoiced' => 0, ], 'is_last' => false, @@ -224,8 +224,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'data_fields' => [ 'shipping_tax_amount' => 2.45, 'base_shipping_tax_amount' => 2.45, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 53.56, 'base_tax_amount' => 53.56, ], @@ -239,8 +239,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_invoiced' => 8.11, 'base_tax_amount' => 24.32, 'base_tax_invoiced' => 8.11, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'qty_invoiced' => 1, ], 'is_last' => false, @@ -253,8 +253,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_invoiced' => 16.22, 'base_tax_amount' => 24.33, 'base_tax_invoiced' => 16.22, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'qty_invoiced' => 2, ], 'is_last' => false, @@ -295,8 +295,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'data_fields' => [ 'shipping_tax_amount' => 2.45, 'base_shipping_tax_amount' => 2.45, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 53.56, 'base_tax_amount' => 53.56, ], @@ -310,8 +310,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_invoiced' => 16.22, 'base_tax_amount' => 24.32, 'base_tax_invoiced' => 16.22, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'qty_invoiced' => 2, ], 'is_last' => true, @@ -324,8 +324,8 @@ class TaxTest extends \PHPUnit_Framework_TestCase 'tax_invoiced' => 16.22, 'base_tax_amount' => 24.33, 'base_tax_invoiced' => 16.22, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'qty_invoiced' => 2, ], 'is_last' => true, diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceTest.php index c4ae521d2b5c0714ed77c3ca62cbf274a78f939c..0c64b01b99d7822b5e0dd5db92bb5bb52b3cc170 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceTest.php @@ -112,8 +112,6 @@ class InvoiceTest extends \PHPUnit_Framework_TestCase )->method( 'canVoid', '__wakeup' - )->with( - $this->equalTo($this->model) )->will( $this->returnValue($canVoid) ); diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/InfoTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/InfoTest.php index 572ea62f5df8232a9ef5c1b895e049ed88ec60be..e3a94e1a99832bc19ec8d44bbfdfc4a48bb1e6e5 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/InfoTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/InfoTest.php @@ -45,9 +45,7 @@ class InfoTest extends \PHPUnit_Framework_TestCase false ); $this->methodInstanceMock = $this->getMockBuilder('Magento\Payment\Model\MethodInterface') - ->disableOriginalConstructor() - ->setMethods(['setInfoInstance', 'getCode', 'getFormBlockType', 'getTitle']) - ->getMock(); + ->getMockForAbstractClass(); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->info = $this->objectManagerHelper->getObject( diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/TransactionTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/TransactionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e7139d8070eca02f7665983a78d38448abd2a770 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/TransactionTest.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Unit\Model\Order\Payment; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + +class TransactionTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Sales\Model\Order\Payment\Transaction */ + protected $transaction; + + /** @var ObjectManagerHelper */ + protected $objectManagerHelper; + + /** @var \Magento\Framework\Model\Context|\PHPUnit_Framework_MockObject_MockObject */ + protected $contextMock; + + /** @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ + protected $eventManagerMock; + + protected function setUp() + { + $this->contextMock = $this->getMockBuilder('\Magento\Framework\Model\Context') + ->setMethods(['getEventDispatcher']) + ->disableOriginalConstructor() + ->getMock(); + $this->eventManagerMock = $this->getMockBuilder('\Magento\Framework\Event\ManagerInterface') + ->setMethods(['dispatch']) + ->getMockForAbstractClass(); + + $this->contextMock->expects($this->once()) + ->method('getEventDispatcher') + ->willReturn($this->eventManagerMock); + + $this->objectManagerHelper = new ObjectManagerHelper($this); + $this->transaction = $this->objectManagerHelper->getObject( + '\Magento\Sales\Model\Order\Payment\Transaction', + [ + 'context' => $this->contextMock + ] + ); + } + + public function testGetHtmlTxnId() + { + $this->eventManagerMock->expects($this->once()) + ->method('dispatch'); + + $this->transaction->setData('html_txn_id', 'test'); + + + $this->assertEquals('test', $this->transaction->getHtmlTxnId()); + } + + public function testGetHtmlTxnIdIsNull() + { + $this->eventManagerMock->expects($this->once()) + ->method('dispatch'); + + $this->transaction->setData('txn_id', 'test'); + + + $this->assertEquals('test', $this->transaction->getHtmlTxnId()); + $this->assertEquals(null, $this->transaction->getData('html_txn_id')); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php index fe5e70a1a7b81c56e0477b3192083c84802ecc15..62e3684db0609f9491807fe013f6f793ca84fda5 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php @@ -182,14 +182,14 @@ class PaymentTest extends \PHPUnit_Framework_TestCase $this->transactionFactory = $this->getMock( 'Magento\Sales\Model\Order\Payment\TransactionFactory', - ['create'], + [], [], '', false ); $this->transactionCollectionFactory = $this->getMock( 'Magento\Sales\Model\Resource\Order\Payment\Transaction\CollectionFactory', - ['create'], + [], [], '', false @@ -241,7 +241,6 @@ class PaymentTest extends \PHPUnit_Framework_TestCase // check fix for partial refunds in Payflow Pro $this->paymentMethodMock->expects($this->once()) ->method('canVoid') - ->with($this->payment) ->willReturn(false); $this->assertEquals($this->payment, $this->payment->cancel()); @@ -586,6 +585,26 @@ class PaymentTest extends \PHPUnit_Framework_TestCase $this->payment->deny(); } + /** + * Test offline IPN calls + */ + public function testDenyPaymentIpn() + { + $isOnline = false; + $message = sprintf('Denied the payment online Transaction ID: "%s"', $this->transactionId); + + $this->payment->setTransactionId($this->transactionId); + $this->payment->setNotificationResult(true); + + $this->mockInvoice($this->transactionId); + $this->mockResultFalseMethods($message); + + $this->helperMock->expects($this->never()) + ->method('getMethodInstance'); + + $this->payment->deny($isOnline); + } + /** * @dataProvider acceptPaymentFalseProvider * @param bool $isFraudDetected @@ -658,6 +677,44 @@ class PaymentTest extends \PHPUnit_Framework_TestCase $this->payment->deny(); } + /** + * Test offline IPN call, negative + */ + public function testDenyPaymentIpnNegativeStateReview() + { + $isOnline = false; + $message = sprintf('Registered notification about denied payment. Transaction ID: "%s"', $this->transactionId); + + $orderState = Order::STATE_PAYMENT_REVIEW; + + $this->payment->setTransactionId($this->transactionId); + $this->payment->setNotificationResult(false); + + $this->orderMock->expects($this->once()) + ->method('getState') + ->willReturn($orderState); + + $this->orderMock->expects($this->never()) + ->method('setState'); + $this->orderMock->expects($this->once()) + ->method('addStatusHistoryComment') + ->with($message); + + $this->helperMock->expects($this->never()) + ->method('getMethodInstance') + ->will($this->returnValue($this->paymentMethodMock)); + + $this->paymentMethodMock->expects($this->never()) + ->method('setStore') + ->will($this->returnSelf()); + + $this->paymentMethodMock->expects($this->never()) + ->method('denyPayment') + ->with($this->payment); + + $this->payment->deny($isOnline); + } + /** * @param int $transactionId * @param int $countCall @@ -710,6 +767,41 @@ class PaymentTest extends \PHPUnit_Framework_TestCase $this->assertEquals($baseGrandTotal, $this->payment->getBaseAmountPaidOnline()); } + /** + * Test update calls from IPN controller + */ + public function testUpdateOnlineTransactionApprovedIpn() + { + $isOnline = false; + $message = sprintf('Registered update about approved payment. Transaction ID: "%s"', $this->transactionId); + + $storeId = 50; + $baseGrandTotal = 299.99; + + $this->payment->setTransactionId($this->transactionId); + $this->payment->setData('is_transaction_approved', true); + + $this->mockInvoice($this->transactionId); + $this->mockResultTrueMethods($this->transactionId, $baseGrandTotal, $message); + + $this->orderMock->expects($this->never()) + ->method('getStoreId') + ->willReturn($storeId); + $this->helperMock->expects($this->never()) + ->method('getMethodInstance') + ->will($this->returnValue($this->paymentMethodMock)); + $this->paymentMethodMock->expects($this->never()) + ->method('setStore') + ->with($storeId) + ->willReturn($this->paymentMethodMock); + $this->paymentMethodMock->expects($this->never()) + ->method('fetchTransactionInfo') + ->with($this->payment, $this->transactionId); + + $this->payment->update($isOnline); + $this->assertEquals($baseGrandTotal, $this->payment->getBaseAmountPaidOnline()); + } + public function testUpdateOnlineTransactionDenied() { $message = sprintf('Registered update about denied payment. Transaction ID: "%s"', $this->transactionId); @@ -1153,6 +1245,7 @@ class PaymentTest extends \PHPUnit_Framework_TestCase 'setTxnType', 'isFailsafe', 'getTxnId', + 'getHtmlTxnId', 'getTxnType' ], [], @@ -1193,6 +1286,9 @@ class PaymentTest extends \PHPUnit_Framework_TestCase $newTransaction->expects($this->once())->method('setTxnId')->with( $this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND )->willReturn($newTransaction); + $newTransaction->expects($this->atLeastOnce())->method('getHtmlTxnId')->willReturn( + $this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND + ); $newTransaction->expects($this->atLeastOnce())->method('getTxnId')->willReturn( $this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND ); diff --git a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php index a147cdaa901ccb13c0304df862912b9433e93ab9..bb549f3640583338a880744c08372f8870f0139c 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php @@ -482,8 +482,6 @@ class OrderTest extends \PHPUnit_Framework_TestCase $this->any() )->method( 'canVoid' - )->with( - new \PHPUnit_Framework_Constraint_IsIdentical($payment) )->will( $this->returnValue($expected) ); @@ -653,13 +651,10 @@ class OrderTest extends \PHPUnit_Framework_TestCase true, ['setOrder'] ); - $dbMock = $this->getMock( - 'Magento\Framework\Data\Collection\Db', - ['setOrder'], - [], - '', - false - ); + $dbMock = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->setMethods(['setOrder']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $collectionMock = $this->getMock( 'Magento\Sales\Model\Resource\Order\Status\History\Collection', [ diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/EntityRelationCompositeTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/EntityRelationCompositeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9da63a991cd7e6b5b973b1e2bc429fe4807a1efa --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/EntityRelationCompositeTest.php @@ -0,0 +1,79 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Unit\Model\Resource; + +/** + * Class EntityRelationCompositeTest + */ +class EntityRelationCompositeTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Model\Resource\EntityRelationComposite + */ + protected $entityRelationComposite; + + /** + * @var \Magento\Sales\Model\AbstractModel|\PHPUnit_Framework_MockObject_MockObject + */ + protected $salesModelMock; + + /** + * @var \Magento\Sales\Model\Resource\EntityRelationInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $relationProcessorMock; + + /** + * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $eventManagerMock; + + public function setUp() + { + $this->salesModelMock = $this->getMockBuilder('Magento\Sales\Model\AbstractModel') + ->disableOriginalConstructor() + ->setMethods( + [ + 'getEventPrefix' + ] + ) + ->getMockForAbstractClass(); + $this->relationProcessorMock = $this->getMockBuilder('Magento\Sales\Model\AbstractModel') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->eventManagerMock = $this->getMockBuilder('Magento\Framework\Event\ManagerInterface') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->relationProcessorMock = $this->getMockBuilder('Magento\Sales\Model\Resource\EntityRelationInterface') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->entityRelationComposite = new \Magento\Sales\Model\Resource\EntityRelationComposite( + $this->eventManagerMock, + [ + 'default' => $this->relationProcessorMock + ] + ); + } + + public function testProcessRelations() + { + $this->relationProcessorMock->expects($this->once()) + ->method('processRelation') + ->with($this->salesModelMock); + $this->salesModelMock->expects($this->once()) + ->method('getEventPrefix') + ->willReturn('sales_event_prefix'); + $this->eventManagerMock->expects($this->once()) + ->method('dispatch') + ->with( + 'sales_event_prefix_process_relation', + [ + 'object' => $this->salesModelMock + ] + ); + $this->entityRelationComposite->processRelations($this->salesModelMock); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Creditmemo/RelationTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Creditmemo/RelationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4bcc1d94ad54d3373a3c0cc5fc6c868b675ee6e1 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Creditmemo/RelationTest.php @@ -0,0 +1,114 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Unit\Model\Resource\Order\Creditmemo; + +/** + * Class RelationTest + */ +class RelationTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Model\Resource\Order\Creditmemo\Relation + */ + protected $relationProcessor; + + /** + * @var \Magento\Sales\Model\Resource\Order\Creditmemo\Item|\PHPUnit_Framework_MockObject_MockObject + */ + protected $itemResourceMock; + + /** + * @var \Magento\Sales\Model\Order\Creditmemo\Comment|\PHPUnit_Framework_MockObject_MockObject + */ + protected $commentMock; + + /** + * @var \Magento\Sales\Model\Order\Creditmemo|\PHPUnit_Framework_MockObject_MockObject + */ + protected $creditmemoMock; + + /** + * @var \Magento\Sales\Model\Order\Creditmemo\Item|\PHPUnit_Framework_MockObject_MockObject + */ + protected $itemMock; + + /** + * @var \Magento\Sales\Model\Resource\Order\Creditmemo\Comment|\PHPUnit_Framework_MockObject_MockObject + */ + protected $commentResourceMock; + + public function setUp() + { + $this->itemResourceMock = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Creditmemo\Item') + ->disableOriginalConstructor() + ->setMethods( + [ + 'save' + ] + ) + ->getMock(); + $this->commentResourceMock = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Creditmemo\Comment') + ->disableOriginalConstructor() + ->setMethods( + [ + 'save' + ] + ) + ->getMock(); + $this->creditmemoMock = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') + ->disableOriginalConstructor() + ->setMethods( + [ + 'getId', + 'getItems', + 'getComments' + ] + ) + ->getMock(); + $this->itemMock = $this->getMockBuilder('Magento\Sales\Model\Order\Item') + ->disableOriginalConstructor() + ->setMethods( + [ + 'setParentId' + ] + ) + ->getMock(); + $this->commentMock = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $this->relationProcessor = new \Magento\Sales\Model\Resource\Order\Creditmemo\Relation( + $this->itemResourceMock, + $this->commentResourceMock + ); + } + + public function testProcessRelations() + { + $this->creditmemoMock->expects($this->once()) + ->method('getId') + ->willReturn('creditmemo-id-value'); + $this->creditmemoMock->expects($this->exactly(2)) + ->method('getItems') + ->willReturn([$this->itemMock]); + $this->creditmemoMock->expects($this->exactly(2)) + ->method('getComments') + ->willReturn([$this->commentMock]); + $this->itemMock->expects($this->once()) + ->method('setParentId') + ->with('creditmemo-id-value') + ->willReturnSelf(); + $this->itemResourceMock->expects($this->once()) + ->method('save') + ->with($this->itemMock) + ->willReturnSelf(); + $this->commentResourceMock->expects($this->once()) + ->method('save') + ->with($this->commentMock) + ->willReturnSelf(); + $this->relationProcessor->processRelation($this->creditmemoMock); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Invoice/RelationTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Invoice/RelationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..852901f95893bf00816c1f70b8b9aafdc869dac9 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Invoice/RelationTest.php @@ -0,0 +1,127 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Unit\Model\Resource\Order\Invoice; + +/** + * Class RelationTest + */ +class RelationTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Model\Resource\Order\Invoice\Relation + */ + protected $relationProcessor; + + /** + * @var \Magento\Sales\Model\Resource\Order\Invoice\Item|\PHPUnit_Framework_MockObject_MockObject + */ + protected $invoiceItemResourceMock; + + /** + * @var \Magento\Sales\Model\Resource\Order\Invoice\Comment|\PHPUnit_Framework_MockObject_MockObject + */ + protected $invoiceCommentResourceMock; + + /** + * @var \Magento\Sales\Model\Order\Invoice|\PHPUnit_Framework_MockObject_MockObject + */ + protected $invoiceMock; + + /** + * @var \Magento\Sales\Model\Order\Invoice\Item|\PHPUnit_Framework_MockObject_MockObject + */ + protected $invoiceItemMock; + + /** + * @var \Magento\Sales\Model\Order\Invoice\Comment|\PHPUnit_Framework_MockObject_MockObject + */ + protected $invoiceCommentMock; + + /** + * @var \Magento\Sales\Model\Order\Item|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderItemMock; + + public function setUp() + { + $this->invoiceItemResourceMock = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Invoice\Item') + ->disableOriginalConstructor() + ->setMethods( + [ + 'save' + ] + ) + ->getMock(); + $this->invoiceCommentResourceMock = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Invoice\Comment') + ->disableOriginalConstructor() + ->setMethods( + [ + 'save' + ] + ) + ->getMock(); + $this->invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + ->disableOriginalConstructor() + ->setMethods( + [ + 'getId', + 'getItems', + 'getComments' + ] + ) + ->getMock(); + $this->invoiceItemMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice\Item') + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + $this->invoiceCommentMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice\Comment') + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + $this->orderItemMock = $this->getMockBuilder('Magento\Sales\Model\Order\Item') + ->disableOriginalConstructor() + ->setMethods([]) + ->getMock(); + $this->relationProcessor = new \Magento\Sales\Model\Resource\Order\Invoice\Relation( + $this->invoiceItemResourceMock, + $this->invoiceCommentResourceMock + ); + } + + public function testProcessRelation() + { + $this->invoiceMock->expects($this->once()) + ->method('getId') + ->willReturn('invoice-id-value'); + $this->invoiceMock->expects($this->exactly(2)) + ->method('getItems') + ->willReturn([$this->invoiceItemMock]); + $this->invoiceItemMock->expects($this->once()) + ->method('setParentId') + ->with('invoice-id-value') + ->willReturnSelf(); + $this->invoiceItemMock->expects($this->once()) + ->method('getOrderItem') + ->willReturn($this->orderItemMock); + $this->invoiceItemMock->expects($this->once()) + ->method('setOrderItem') + ->with($this->orderItemMock) + ->willReturnSelf(); + $this->invoiceItemResourceMock->expects($this->once()) + ->method('save') + ->with($this->invoiceItemMock) + ->willReturnSelf(); + $this->invoiceMock->expects($this->exactly(2)) + ->method('getComments') + ->willReturn([$this->invoiceCommentMock]); + $this->invoiceCommentResourceMock->expects($this->once()) + ->method('save') + ->with($this->invoiceCommentMock) + ->willReturnSelf(); + $this->relationProcessor->processRelation($this->invoiceMock); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/RelationTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/RelationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..be73d50dff71f3d61e2e7f3af41fc4e352420517 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/RelationTest.php @@ -0,0 +1,233 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Unit\Model\Resource\Order; + +/** + * Class RelationTest + */ +class RelationTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Model\Resource\Order\Relation + */ + protected $relationProcessor; + /** + * @var \Magento\Sales\Model\Resource\Order\Handler\Address|\PHPUnit_Framework_MockObject_MockObject + */ + protected $addressHandlerMock; + + /** + * @var \Magento\Sales\Model\Resource\Order\Item|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderItemResourceMock; + + /** + * @var \Magento\Sales\Model\Resource\Order\Payment|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderPaymentResourceMock; + + /** + * @var \Magento\Sales\Model\Resource\Order\Status\History|\PHPUnit_Framework_MockObject_MockObject + */ + protected $statusHistoryResource; + + /** + * @var \Magento\Sales\Model\Order|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderMock; + + /** + * @var \Magento\Sales\Model\Order\Item|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderItemMock; + + /** + * @var \Magento\Sales\Model\Order\Payment|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderPaymentMock; + + /** + * @var \Magento\Sales\Model\Order\Status\History|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderStatusHistoryMock; + + /** + * @var \Magento\Sales\Model\Order\Invoice|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderInvoiceMock; + + public function setUp() + { + $this->addressHandlerMock = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Handler\Address') + ->disableOriginalConstructor() + ->setMethods( + [ + 'removeEmptyAddresses', + 'process' + ] + ) + ->getMock(); + $this->orderItemResourceMock = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Item') + ->disableOriginalConstructor() + ->setMethods( + [ + 'save' + ] + ) + ->getMock(); + $this->orderPaymentResourceMock = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Payment') + ->disableOriginalConstructor() + ->setMethods( + [ + 'save' + ] + ) + ->getMock(); + $this->statusHistoryResource = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Status\History') + ->disableOriginalConstructor() + ->setMethods( + [ + 'save' + ] + ) + ->getMock(); + $this->orderMock = $this->getMockBuilder('Magento\Sales\Model\Order') + ->disableOriginalConstructor() + ->setMethods( + [ + 'getId', + 'getItems', + 'getPayments', + 'getStatusHistories', + 'getRelatedObjects' + ] + ) + ->getMock(); + $this->orderItemMock = $this->getMockBuilder('Magento\Sales\Model\Order\Item') + ->disableOriginalConstructor() + ->setMethods( + [ + 'setOrderId', + 'setOrder' + ] + ) + ->getMock(); + $this->orderPaymentMock = $this->getMockBuilder('Magento\Sales\Model\Order\Payment') + ->disableOriginalConstructor() + ->setMethods( + [ + 'setParentId', + 'setOrder' + ] + ) + ->getMock(); + $this->orderStatusHistoryMock = $this->getMockBuilder('Magento\Sales\Model\Order\Item') + ->disableOriginalConstructor() + ->setMethods( + [ + 'setParentId', + 'setOrder' + ] + ) + ->getMock(); + $this->orderStatusHistoryMock = $this->getMockBuilder('Magento\Sales\Model\Order\Status\History') + ->disableOriginalConstructor() + ->setMethods( + [ + 'setParentId', + 'setOrder' + ] + ) + ->getMock(); + $this->orderInvoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + ->disableOriginalConstructor() + ->setMethods( + [ + 'setOrder', + 'save' + ] + ) + ->getMock(); + $this->relationProcessor = new \Magento\Sales\Model\Resource\Order\Relation( + $this->addressHandlerMock, + $this->orderItemResourceMock, + $this->orderPaymentResourceMock, + $this->statusHistoryResource + ); + } + + public function testProcessRelation() + { + $this->addressHandlerMock->expects($this->once()) + ->method('removeEmptyAddresses') + ->with($this->orderMock) + ->willReturnSelf(); + $this->addressHandlerMock->expects($this->once()) + ->method('process') + ->with($this->orderMock) + ->willReturnSelf(); + $this->orderMock->expects($this->exactly(2)) + ->method('getItems') + ->willReturn([$this->orderItemMock]); + $this->orderMock->expects($this->exactly(3)) + ->method('getId') + ->willReturn('order-id-value'); + $this->orderItemMock->expects($this->once()) + ->method('setOrderId') + ->with('order-id-value') + ->willReturnSelf(); + $this->orderItemMock->expects($this->once()) + ->method('setOrder') + ->with($this->orderMock) + ->willReturnSelf(); + $this->orderItemResourceMock->expects($this->once()) + ->method('save') + ->with($this->orderItemMock) + ->willReturnSelf(); + $this->orderMock->expects($this->exactly(2)) + ->method('getPayments') + ->willReturn([$this->orderPaymentMock]); + $this->orderPaymentMock->expects($this->once()) + ->method('setParentId') + ->with('order-id-value') + ->willReturnSelf(); + $this->orderPaymentMock->expects($this->once()) + ->method('setOrder') + ->with($this->orderMock) + ->willReturnSelf(); + $this->orderPaymentResourceMock->expects($this->once()) + ->method('save') + ->with($this->orderPaymentMock) + ->willReturnSelf(); + $this->orderMock->expects($this->exactly(2)) + ->method('getStatusHistories') + ->willReturn([$this->orderStatusHistoryMock]); + $this->orderStatusHistoryMock->expects($this->once()) + ->method('setParentId') + ->with('order-id-value') + ->willReturnSelf(); + $this->orderStatusHistoryMock->expects($this->once()) + ->method('setOrder') + ->with($this->orderMock) + ->willReturnSelf(); + $this->statusHistoryResource->expects($this->once()) + ->method('save') + ->with($this->orderStatusHistoryMock) + ->willReturnSelf(); + $this->orderMock->expects($this->exactly(2)) + ->method('getRelatedObjects') + ->willReturn([$this->orderInvoiceMock]); + $this->orderInvoiceMock->expects($this->once()) + ->method('setOrder') + ->with($this->orderMock) + ->willReturnSelf(); + $this->orderInvoiceMock->expects($this->once()) + ->method('save') + ->willReturnSelf(); + $this->relationProcessor->processRelation($this->orderMock); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Shipment/RelationTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Shipment/RelationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8a6a11b7872f0d4c5bc58099a292b0f4dd3a69f4 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/Order/Shipment/RelationTest.php @@ -0,0 +1,144 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Test\Unit\Model\Resource\Order\Shipment; + +/** + * Class RelationTest + */ +class RelationTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Model\Resource\Order\Shipment\Relation + */ + protected $relationProcessor; + + /** + * @var \Magento\Sales\Model\Resource\Order\Shipment\Item|\PHPUnit_Framework_MockObject_MockObject + */ + protected $itemResourceMock; + + /** + * @var \Magento\Sales\Model\Resource\Order\Shipment\Track|\PHPUnit_Framework_MockObject_MockObject + */ + protected $trackResourceMock; + + /** + * @var \Magento\Sales\Model\Resource\Order\Shipment\Comment|\PHPUnit_Framework_MockObject_MockObject + */ + protected $commentResourceMock; + + /** + * @var \Magento\Sales\Model\Order\Shipment\Comment|\PHPUnit_Framework_MockObject_MockObject + */ + protected $commentMock; + + /** + * @var \Magento\Sales\Model\Order\Shipment\Track|\PHPUnit_Framework_MockObject_MockObject + */ + protected $trackMock; + + /** + * @var \Magento\Sales\Model\Order\Shipment|\PHPUnit_Framework_MockObject_MockObject + */ + protected $shipmentMock; + + /** + * @var \Magento\Sales\Model\Order\Shipment\Item|\PHPUnit_Framework_MockObject_MockObject + */ + protected $itemMock; + + public function setUp() + { + $this->itemResourceMock = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Shipment\Item') + ->disableOriginalConstructor() + ->setMethods( + [ + 'save' + ] + ) + ->getMock(); + $this->commentResourceMock = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Shipment\Comment') + ->disableOriginalConstructor() + ->setMethods( + [ + 'save' + ] + ) + ->getMock(); + $this->trackResourceMock = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Shipment\Track') + ->disableOriginalConstructor() + ->setMethods( + [ + 'save' + ] + ) + ->getMock(); + $this->shipmentMock = $this->getMockBuilder('Magento\Sales\Model\Order\Shipment') + ->disableOriginalConstructor() + ->setMethods( + [ + 'getId', + 'getItems', + 'getTracks', + 'getComments' + ] + ) + ->getMock(); + $this->itemMock = $this->getMockBuilder('Magento\Sales\Model\Order\Item') + ->disableOriginalConstructor() + ->setMethods( + [ + 'setParentId' + ] + ) + ->getMock(); + $this->trackMock = $this->getMockBuilder('Magento\Sales\Model\Order\Shipment\Track') + ->disableOriginalConstructor() + ->getMock(); + $this->commentMock = $this->getMockBuilder('Magento\Sales\Model\Order\Shipment') + ->disableOriginalConstructor() + ->getMock(); + $this->relationProcessor = new \Magento\Sales\Model\Resource\Order\Shipment\Relation( + $this->itemResourceMock, + $this->trackResourceMock, + $this->commentResourceMock + ); + } + + public function testProcessRelations() + { + $this->shipmentMock->expects($this->once()) + ->method('getId') + ->willReturn('shipment-id-value'); + $this->shipmentMock->expects($this->exactly(2)) + ->method('getItems') + ->willReturn([$this->itemMock]); + $this->shipmentMock->expects($this->exactly(2)) + ->method('getComments') + ->willReturn([$this->commentMock]); + $this->shipmentMock->expects($this->exactly(2)) + ->method('getTracks') + ->willReturn([$this->trackMock]); + $this->itemMock->expects($this->once()) + ->method('setParentId') + ->with('shipment-id-value') + ->willReturnSelf(); + $this->itemResourceMock->expects($this->once()) + ->method('save') + ->with($this->itemMock) + ->willReturnSelf(); + $this->commentResourceMock->expects($this->once()) + ->method('save') + ->with($this->commentMock) + ->willReturnSelf(); + $this->trackResourceMock->expects($this->once()) + ->method('save') + ->with($this->trackMock) + ->willReturnSelf(); + $this->relationProcessor->processRelation($this->shipmentMock); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Resource/OrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Resource/OrderTest.php index efeb4c7fd5abd00c11b94d99f8a2f31996c43125..397e6b0374502cd78ccc7084e3ac7ddc8fd20dfa 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Resource/OrderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Resource/OrderTest.php @@ -7,6 +7,8 @@ namespace Magento\Sales\Test\Unit\Model\Resource; use \Magento\Sales\Model\Resource\Order; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; + /** * Class OrderTest * @@ -23,18 +25,6 @@ class OrderTest extends \PHPUnit_Framework_TestCase * @var \Magento\Framework\App\Resource|\PHPUnit_Framework_MockObject_MockObject */ protected $resourceMock; - /** - * @var \Magento\Sales\Model\Resource\Attribute|\PHPUnit_Framework_MockObject_MockObject - */ - protected $attributeMock; - /** - * @var \Magento\Sales\Model\Resource\Order\Handler\Address|\PHPUnit_Framework_MockObject_MockObject - */ - protected $addressHandlerMock; - /** - * @var \Magento\Sales\Model\Resource\Order\Handler\State|\PHPUnit_Framework_MockObject_MockObject - */ - protected $stateHandlerMock; /** * @var \Magento\SalesSequence\Model\Manager|\PHPUnit_Framework_MockObject_MockObject */ @@ -43,10 +33,6 @@ class OrderTest extends \PHPUnit_Framework_TestCase * @var \Magento\SalesSequence\Model\Sequence|\PHPUnit_Framework_MockObject_MockObject */ protected $salesSequenceMock; - /** - * @var \Magento\Sales\Model\Resource\Order\Grid|\PHPUnit_Framework_MockObject_MockObject - */ - protected $gridAggregatorMock; /** * @var \Magento\Sales\Model\Order|\PHPUnit_Framework_MockObject_MockObject */ @@ -59,26 +45,6 @@ class OrderTest extends \PHPUnit_Framework_TestCase * @var \Magento\Store\Model\Group|\PHPUnit_Framework_MockObject_MockObject */ protected $storeGroupMock; - /** - * \Magento\Sales\Model\Website|\PHPUnit_Framework_MockObject_MockObject - */ - protected $websiteMock; - /** - * @var \Magento\Customer\Model\Customer|\PHPUnit_Framework_MockObject_MockObject - */ - protected $customerMock; - /** - * @var \Magento\Sales\Model\Resource\Order\Item\Collection|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderItemCollectionMock; - /** - * @var \Magento\Sales\Model\Resource\Order\Payment\Collection|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderPaymentCollectionMock; - /** - * @var \Magento\Sales\Model\Resource\Order\Status\History\Collection|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderStatusHistoryCollectionMock; /** * @var \Magento\Framework\DB\Adapter\Pdo\Mysql|\PHPUnit_Framework_MockObject_MockObject */ @@ -88,55 +54,24 @@ class OrderTest extends \PHPUnit_Framework_TestCase */ protected $entitySnapshotMock; + /** + * @var \Magento\Sales\Model\Resource\EntityRelationComposite|\PHPUnit_Framework_MockObject_MockObject + */ + protected $relationCompositeMock; + + /** + * @var \Magento\Framework\Model\Resource\Db\ObjectRelationProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + protected $objectRelationProcessorMock; /** * Mock class dependencies */ public function setUp() { $this->resourceMock = $this->getMock('Magento\Framework\App\Resource', [], [], '', false); - $this->attributeMock = $this->getMock('Magento\Sales\Model\Resource\Attribute', [], [], '', false); - $this->addressHandlerMock = $this->getMock( - 'Magento\Sales\Model\Resource\Order\Handler\Address', - ['removeEmptyAddresses'], - [], - '', - false - ); - $this->stateHandlerMock = $this->getMock('Magento\Sales\Model\Resource\Order\Handler\State', [], [], '', false); - $this->salesIncrementMock = $this->getMock('Magento\Sales\Model\Increment', [], [], '', false); - $this->gridAggregatorMock = $this->getMock('Magento\Sales\Model\Resource\Order\Grid', [], [], '', false); - $this->orderMock = $this->getMock( - 'Magento\Sales\Model\Order', - [], - [], - '', - false - ); - $this->storeMock = $this->getMock('Magento\Store\Model\Store', ['__wakeup'], [], '', false); - $this->storeGroupMock = $this->getMock('Magento\Store\Model\Group', ['__wakeup'], [], '', false); - $this->websiteMock = $this->getMock('Magento\Sales\Model\Website', ['__wakeup'], [], '', false); - $this->customerMock = $this->getMock('Magento\Customer\Model\Customer', ['__wakeup'], [], '', false); - $this->orderItemCollectionMock = $this->getMock( - 'Magento\Sales\Model\Resource\Order\Item\Collection', - [], - [], - '', - false - ); - $this->orderPaymentCollectionMock = $this->getMock( - 'Magento\Sales\Model\Resource\Order\Payment\Collection', - [], - [], - '', - false - ); - $this->orderStatusHistoryCollectionMock = $this->getMock( - 'Magento\Sales\Model\Resource\Order\Status\History\Collection', - [], - [], - '', - false - ); + $this->orderMock = $this->getMock('Magento\Sales\Model\Order', [], [], '', false); + $this->storeMock = $this->getMock('Magento\Store\Model\Store', [], [], '', false); + $this->storeGroupMock = $this->getMock('Magento\Store\Model\Group', [], [], '', false); $this->adapterMock = $this->getMock( 'Magento\Framework\DB\Adapter\Pdo\Mysql', [ @@ -160,7 +95,7 @@ class OrderTest extends \PHPUnit_Framework_TestCase '', false ); - $this->salesSequenceMock = $this->getMock('Magento\SalesSequence\Sequence', [], [], '', false); + $this->salesSequenceMock = $this->getMock('Magento\SalesSequence\Model\Sequence', [], [], '', false); $this->entitySnapshotMock = $this->getMock( 'Magento\Sales\Model\Resource\EntitySnapshot', [], @@ -168,21 +103,85 @@ class OrderTest extends \PHPUnit_Framework_TestCase '', false ); + $this->relationCompositeMock = $this->getMock( + 'Magento\Sales\Model\Resource\EntityRelationComposite', + [], + [], + '', + false + ); + $this->objectRelationProcessorMock = $this->getMock( + 'Magento\Framework\Model\Resource\Db\ObjectRelationProcessor', + [], + [], + '', + false + ); $contextMock = $this->getMock('\Magento\Framework\Model\Resource\Db\Context', [], [], '', false); $contextMock->expects($this->once())->method('getResources')->willReturn($this->resourceMock); + $contextMock->expects($this->once()) + ->method('getObjectRelationProcessor') + ->willReturn($this->objectRelationProcessorMock); - $this->resource = new Order( - $contextMock, - $this->attributeMock, - $this->salesSequenceManagerMock, - $this->entitySnapshotMock, - $this->addressHandlerMock, - $this->stateHandlerMock + $objectManager = new ObjectManagerHelper($this); + $this->resource = $objectManager->getObject( + 'Magento\Sales\Model\Resource\Order', + [ + 'context' => $contextMock, + 'sequenceManager' => $this->salesSequenceManagerMock, + 'entitySnapshot' => $this->entitySnapshotMock, + 'entityRelationComposite' => $this->relationCompositeMock + ] ); } public function testSave() { + + $this->orderMock->expects($this->once()) + ->method('validateBeforeSave') + ->willReturnSelf(); + $this->orderMock->expects($this->once()) + ->method('beforeSave') + ->willReturnSelf(); + $this->orderMock->expects($this->once()) + ->method('isSaveAllowed') + ->willReturn(true); + $this->orderMock->expects($this->once()) + ->method('getEntityType') + ->willReturn('order'); + $this->orderMock->expects($this->once()) + ->method('getStore') + ->willReturn($this->storeMock); + $this->storeMock->expects($this->once()) + ->method('getGroup') + ->willReturn($this->storeGroupMock); + $this->storeGroupMock->expects($this->once()) + ->method('getDefaultStoreId') + ->willReturn(1); + $this->salesSequenceManagerMock->expects($this->once()) + ->method('getSequence') + ->with('order', 1) + ->willReturn($this->salesSequenceMock); + $this->salesSequenceMock->expects($this->once()) + ->method('getNextValue') + ->willReturn('10000001'); + $this->orderMock->expects($this->once()) + ->method('setIncrementId') + ->with('10000001') + ->willReturnSelf(); + $this->orderMock->expects($this->once()) + ->method('getIncrementId') + ->willReturn(null); + $this->orderMock->expects($this->once()) + ->method('getData') + ->willReturn(['increment_id' => '10000001']); + $this->objectRelationProcessorMock->expects($this->once()) + ->method('validateDataIntegrity') + ->with(null, ['increment_id' => '10000001']); + $this->relationCompositeMock->expects($this->once()) + ->method('processRelations') + ->with($this->orderMock); $this->resourceMock->expects($this->any()) ->method('getConnection') ->willReturn($this->adapterMock); diff --git a/app/code/Magento/Sales/composer.json b/app/code/Magento/Sales/composer.json index 5595f059c84770471bab4d730bb518089d989d93..7f07de89e05f1b012a4d782d2828f7f86dd127eb 100644 --- a/app/code/Magento/Sales/composer.json +++ b/app/code/Magento/Sales/composer.json @@ -3,35 +3,35 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-authorization": "0.74.0-beta10", - "magento/module-payment": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/module-sales-rule": "0.74.0-beta10", - "magento/module-sales-sequence": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-widget": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-gift-message": "0.74.0-beta10", - "magento/module-reports": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-wishlist": "0.74.0-beta10", - "magento/module-email": "0.74.0-beta10", - "magento/module-shipping": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-ui": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-authorization": "0.74.0-beta13", + "magento/module-payment": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/module-sales-rule": "0.74.0-beta13", + "magento/module-sales-sequence": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-widget": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-gift-message": "0.74.0-beta13", + "magento/module-reports": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-wishlist": "0.74.0-beta13", + "magento/module-email": "0.74.0-beta13", + "magento/module-shipping": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-ui": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index fee757be252e74303742af982b46ad4979950f4a..c0aec4a0857a24fdc363ad679fc38b3a44bc7408 100644 --- a/app/code/Magento/Sales/etc/di.xml +++ b/app/code/Magento/Sales/etc/di.xml @@ -220,4 +220,52 @@ <argument name="resourcePrefix" xsi:type="string">sales</argument> </arguments> </type> + <virtualType name="OrderRelationsComposite" type="Magento\Sales\Model\Resource\EntityRelationComposite"> + <arguments> + <argument name="relationProcessors" xsi:type="array"> + <item name="default" xsi:type="object">Magento\Sales\Model\Resource\Order\Relation</item> + </argument> + </arguments> + </virtualType> + <type name="Magento\Sales\Model\Resource\Order"> + <arguments> + <argument name="entityRelationComposite" xsi:type="object">OrderRelationsComposite</argument> + </arguments> + </type> + <virtualType name="InvoiceRelationsComposite" type="Magento\Sales\Model\Resource\EntityRelationComposite"> + <arguments> + <argument name="relationProcessors" xsi:type="array"> + <item name="default" xsi:type="object">Magento\Sales\Model\Resource\Order\Invoice\Relation</item> + </argument> + </arguments> + </virtualType> + <type name="Magento\Sales\Model\Resource\Order\Invoice"> + <arguments> + <argument name="entityRelationComposite" xsi:type="object">InvoiceRelationsComposite</argument> + </arguments> + </type> + <virtualType name="ShipmentRelationsComposite" type="Magento\Sales\Model\Resource\EntityRelationComposite"> + <arguments> + <argument name="relationProcessors" xsi:type="array"> + <item name="default" xsi:type="object">Magento\Sales\Model\Resource\Order\Shipment\Relation</item> + </argument> + </arguments> + </virtualType> + <type name="Magento\Sales\Model\Resource\Order\Shipment"> + <arguments> + <argument name="entityRelationComposite" xsi:type="object">ShipmentRelationsComposite</argument> + </arguments> + </type> + <virtualType name="CreditmemoRelationsComposite" type="Magento\Sales\Model\Resource\EntityRelationComposite"> + <arguments> + <argument name="relationProcessors" xsi:type="array"> + <item name="default" xsi:type="object">Magento\Sales\Model\Resource\Order\Creditmemo\Relation</item> + </argument> + </arguments> + </virtualType> + <type name="Magento\Sales\Model\Resource\Order\Creditmemo"> + <arguments> + <argument name="entityRelationComposite" xsi:type="object">CreditmemoRelationsComposite</argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Sales/etc/events.xml b/app/code/Magento/Sales/etc/events.xml index 9e38abcd68e8c2812d99b3dc4f33c20135e9e2d5..bb6e0795fc7ea190335e81abbd0f72350b71c841 100644 --- a/app/code/Magento/Sales/etc/events.xml +++ b/app/code/Magento/Sales/etc/events.xml @@ -9,16 +9,16 @@ <event name="sales_order_place_after"> <observer name="sales_vat_request_params_order_comment" instance="Magento\Sales\Model\Observer\Frontend\Quote\AddVatRequestParamsOrderComment" method="execute" /> </event> - <event name="sales_order_save_after"> + <event name="sales_order_process_relation"> <observer name="sales_grid_order_sync_insert" instance="Magento\Sales\Model\Observer\Order\IndexGrid" method="syncInsert" /> </event> - <event name="sales_order_invoice_save_after"> + <event name="sales_order_invoice_process_relation"> <observer name="sales_grid_order_invoice_sync_insert" instance="Magento\Sales\Model\Observer\Order\Invoice\IndexGrid" method="syncInsert" /> </event> - <event name="sales_order_shipment_save_after"> + <event name="sales_order_shipment_process_relation"> <observer name="sales_grid_order_shipment_sync_insert" instance="Magento\Sales\Model\Observer\Order\Shipment\IndexGrid" method="syncInsert" /> </event> - <event name="sales_order_creditmemo_save_after"> + <event name="sales_order_creditmemo_process_relation"> <observer name="sales_grid_order_creditmemo_sync_insert" instance="Magento\Sales\Model\Observer\Order\Creditmemo\IndexGrid" method="syncInsert" /> </event> <event name="sales_order_delete_after"> diff --git a/app/code/Magento/Sales/etc/service_data_attributes.xml b/app/code/Magento/Sales/etc/extension_attributes.xml similarity index 92% rename from app/code/Magento/Sales/etc/service_data_attributes.xml rename to app/code/Magento/Sales/etc/extension_attributes.xml index 1e7f320c18ed6e98b0c979d23e80e6ff48478fa4..970a003625928f218f2073cbb4262cd7d3876499 100644 --- a/app/code/Magento/Sales/etc/service_data_attributes.xml +++ b/app/code/Magento/Sales/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Sales\Api\Data\OrderInterface"> <attribute code="applied_taxes" type="Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterface[]" /> <attribute code="item_applied_taxes" type="Magento\Tax\Api\Data\OrderTaxDetailsItemInterface[]" /> diff --git a/app/code/Magento/Sales/etc/fieldset.xml b/app/code/Magento/Sales/etc/fieldset.xml index 519416dc4ca31179f491d29beb22dab760e664cc..500af715371088706b0ff208c23e7308fc5f1e7f 100644 --- a/app/code/Magento/Sales/etc/fieldset.xml +++ b/app/code/Magento/Sales/etc/fieldset.xml @@ -269,16 +269,16 @@ <field name="base_grand_total"> <aspect name="to_order" /> </field> - <field name="hidden_tax_amount"> + <field name="discount_tax_compensation_amount"> <aspect name="to_order" /> </field> - <field name="base_hidden_tax_amount"> + <field name="base_discount_tax_compensation_amount"> <aspect name="to_order" /> </field> - <field name="shipping_hidden_tax_amount"> + <field name="shipping_discount_tax_compensation_amount"> <aspect name="to_order" /> </field> - <field name="base_shipping_hidden_tax_amount"> + <field name="base_shipping_discount_tax_compensation_amount"> <aspect name="to_order" /> </field> <field name="prefix"> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/comments/view.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/comments/view.phtml index d07aa26f62841857664da6c5f09456a10d5b2672..a1e1c4b2ee36a09e902aadd08da68508e04d6c94 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/comments/view.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/comments/view.phtml @@ -63,7 +63,7 @@ <span class="note-list-customer-not-notified"><?php echo __('Not Notified') ?></span> <?php endif; ?> </span> - <div class="note-list-comment"><?php echo $block->escapeHtml($_comment->getComment(), ['b', 'br', 'strong', 'i', 'u']) ?></div> + <div class="note-list-comment"><?php echo $block->escapeHtml($_comment->getComment(), ['b', 'br', 'strong', 'i', 'u', 'a']) ?></div> </li> <?php endforeach; ?> </ul> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/items/grid.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/items/grid.phtml index 5b56da82d491cf8c5779767131a27ee8e6de4327..6096ab772d288d0529dd3cd844cb3027a62882b7 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/items/grid.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/items/grid.phtml @@ -104,8 +104,7 @@ <label class="normal admin__field-label" for="item_use_custom_price_<?php echo $_item->getId() ?>"> - <?php echo __('Custom Price') ?>* - </label> + <span><?php echo __('Custom Price') ?>*</span></label> </div> <?php endif; ?> <input id="item_custom_price_<?php echo $_item->getId() ?>" @@ -137,7 +136,8 @@ type="checkbox" /> <label for="item_use_discount_<?php echo $_item->getId() ?>" - class="normal admin__field-label"><?php echo __('Apply') ?></label> + class="normal admin__field-label"> + <span><?php echo __('Apply') ?></span></label> </div> </td> @@ -153,9 +153,9 @@ <?php if ($block->isMoveToWishlistAllowed($_item)): ?> <?php $wishlists = $block->getCustomerWishlists();?> <?php if (count($wishlists) <= 1):?> - <option value="wishlist"><?php echo __('Move to Wishlist') ?></option> + <option value="wishlist"><?php echo __('Move to Wish List') ?></option> <?php else: ?> - <optgroup label="<?php echo __('Move to Wishlist') ?>"> + <optgroup label="<?php echo __('Move to Wish List') ?>"> <?php foreach ($wishlists as $wishlist):?> <option value="wishlist_<?php echo $wishlist->getId();?>"><?php echo $block->escapeHtml($wishlist->getName());?></option> <?php endforeach;?> diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml index 70bdcbeb02068761ede066b0463ed53d07cac8fc..8fd259373f6341a3aa1090824b8166eb073d687a 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/creditmemo/create/items.phtml @@ -84,7 +84,8 @@ <div id="history_form" class="admin__fieldset-wrapper-content"> <div class="admin__field"> <label class="normal admin__field-label" - for="creditmemo_comment_text"><?php echo __('Comment Text') ?></label> + for="creditmemo_comment_text"> + <span><?php echo __('Comment Text') ?></span></label> <div class="admin__field-control"> <textarea id="creditmemo_comment_text" class="admin__control-textarea" diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml index fff76e569226d2a54dcc1bf52ad0a1a51745c9a6..0253050d8f3b0ea07bd824734a4aa44259b3c5ce 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/invoice/create/items.phtml @@ -132,7 +132,7 @@ </section> <script> -require(['jquery', 'prototype'], function($){ +require(['jquery', 'prototype'], function(jQuery){ //<![CDATA[ var submitButtons = $$('.submit-button'); @@ -143,7 +143,7 @@ var fields = $$('.qty-input'); updateButtons.each(function (elem) {elem.disabled=true;elem.addClassName('disabled');}); for(var i=0;i<fields.length;i++){ - $(fields[i]).on('keyup', checkButtonsRelation); + jQuery(fields[i]).on('keyup', checkButtonsRelation); fields[i].baseValue = fields[i].value; } diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/view/history.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/view/history.phtml index b1c4121b92fc36055dce194757c944a5486fbab3..0a681e6c628072913217cac9985b7834f011a997 100644 --- a/app/code/Magento/Sales/view/adminhtml/templates/order/view/history.phtml +++ b/app/code/Magento/Sales/view/adminhtml/templates/order/view/history.phtml @@ -86,7 +86,7 @@ <?php endif; ?> </span> <?php if ($_item->getComment()): ?> - <div class="note-list-comment"><?php echo $block->escapeHtml($_item->getComment(), ['b', 'br', 'strong', 'i', 'u']) ?></div> + <div class="note-list-comment"><?php echo $block->escapeHtml($_item->getComment(), ['b', 'br', 'strong', 'i', 'u', 'a']) ?></div> <?php endif; ?> </li> <?php endforeach; ?> 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 06ee87a09018b3bcd7ec7448ee6eba15498891dc..5479b72127223e2f0b98730a965e94a97c845f9d 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 @@ -7,10 +7,10 @@ define([ "jquery", "jquery/ui", + 'Magento_Ui/js/dialog/dialog', "mage/translate" ], function($){ "use strict"; - $.widget('mage.orderEditDialog', { options: { url: null, @@ -29,7 +29,7 @@ define([ * Show dialog */ showDialog: function() { - this.options.dialog.html(this.options.message).dialog('open'); + this.options.dialog.html(this.options.message).trigger('openDialog'); }, /** @@ -44,46 +44,9 @@ define([ * @protected */ _prepareDialog: function() { - var self = this; - - this.options.dialog = $('<div class="ui-dialog-content ui-widget-content"></div>') - .dialog({ - autoOpen: false, - title: $.mage.__('Edit Order'), - modal: true, - resizable: false, - width: '75%', - dialogClass: 'edit-order-popup', - position: { - my: 'left top', - at: 'center top', - of: 'body' - }, - open: function () { - jQuery(this).closest('.ui-dialog').addClass('ui-dialog-active'); - - var topMargin = $(this).closest('.ui-dialog').children('.ui-dialog-titlebar').outerHeight() - 20; - $(this).closest('.ui-dialog').css('margin-top', topMargin); - }, - close: function() { - jQuery(this).closest('.ui-dialog').removeClass('ui-dialog-active'); - }, - buttons: [{ - text: $.mage.__('Ok'), - 'class': 'action-primary', - click: function(){ - self.redirect(); - } - }, { - text: $.mage.__('Cancel'), - 'class': 'action-close', - click: function(){ - $(this).dialog('close'); - } - }] - }); + this.options.dialog = $('<div class="ui-dialog-content ui-widget-content"></div>').dialog(); } }); - + return $.mage.orderEditDialog; -}); \ No newline at end of file +}); 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 e2125b5a1a6b3ccd758cfc712574de53c8f28b9f..1afc292f2071b2e0b9105e8503015ae5d1f61775 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 @@ -10,11 +10,17 @@ <update handle="sales_order_item_price"/> <update handle="sales_order_guest_info_links"/> <body> + <referenceContainer name="page.main.title"> + <block class="Magento\Sales\Block\Order\Info" name="order.status" template="order/order_status.phtml" /> + <block class="Magento\Sales\Block\Order\Info" name="order.date" template="order/order_date.phtml" /> + <container name="order.actions.container" htmlTag="div" htmlClass="actions-toolbar order-actions-toolbar"> + <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"> + <block class="Magento\Sales\Block\Order\Info\Buttons\Rss" as="buttons.rss" name="sales.order.info.buttons.rss" cacheable="false"/> + </block> + </container> + </referenceContainer> <referenceContainer name="content"> - <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info"> - <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"/> - </block> - <block class="Magento\Sales\Block\Order\Creditmemo" name="sales.order.creditmemo" after="sales.order.info" cacheable="false"> + <block class="Magento\Sales\Block\Order\Creditmemo" name="sales.order.creditmemo" after="sales.order.info.links" cacheable="false"> <block class="Magento\Sales\Block\Order\Creditmemo\Items" name="creditmemo_items" template="order/creditmemo/items.phtml"> <block class="Magento\Framework\View\Element\RendererList" name="sales.order.creditmemo.renderers" as="renderer.list"/> <block class="Magento\Sales\Block\Order\Creditmemo\Totals" name="creditmemo_totals" template="order/totals.phtml"> @@ -27,9 +33,7 @@ <block class="Magento\Sales\Block\Order\Comments" name="creditmemo_comments" template="order/comments.phtml"/> </block> </block> - </referenceContainer> - <referenceContainer name="sales.order.info.buttons"> - <block class="Magento\Sales\Block\Order\Info\Buttons\Rss" as="buttons.rss" name="sales.order.info.buttons.rss" cacheable="false"/> + <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info" after="sales.order.creditmemo"/> </referenceContainer> </body> </page> 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 f5d6f7ad4d412bf63873181207fa52f416670179..20bb1d376590ac7c12e61b5b83816de53a97e8fd 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 @@ -10,11 +10,17 @@ <update handle="sales_order_item_price"/> <update handle="sales_order_guest_info_links"/> <body> + <referenceContainer name="page.main.title"> + <block class="Magento\Sales\Block\Order\Info" name="order.status" template="order/order_status.phtml" /> + <block class="Magento\Sales\Block\Order\Info" name="order.date" template="order/order_date.phtml" /> + <container name="order.actions.container" htmlTag="div" htmlClass="actions-toolbar order-actions-toolbar"> + <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"> + <block class="Magento\Sales\Block\Order\Info\Buttons\Rss" as="buttons.rss" name="sales.order.info.buttons.rss" cacheable="false"/> + </block> + </container> + </referenceContainer> <referenceContainer name="content"> - <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info"> - <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"/> - </block> - <block class="Magento\Sales\Block\Order\Invoice" name="sales.order.invoice" after="sales.order.info" cacheable="false"> + <block class="Magento\Sales\Block\Order\Invoice" name="sales.order.invoice" after="sales.order.info.links" cacheable="false"> <block class="Magento\Sales\Block\Order\Invoice\Items" name="invoice_items" template="order/invoice/items.phtml"> <block class="Magento\Framework\View\Element\RendererList" name="sales.order.invoice.renderers" as="renderer.list"/> <block class="Magento\Sales\Block\Order\Invoice\Totals" name="invoice_totals" template="order/totals.phtml"> @@ -27,9 +33,7 @@ <block class="Magento\Sales\Block\Order\Comments" name="invoice_comments" template="order/comments.phtml"/> </block> </block> - </referenceContainer> - <referenceContainer name="sales.order.info.buttons"> - <block class="Magento\Sales\Block\Order\Info\Buttons\Rss" as="buttons.rss" name="sales.order.info.buttons.rss" cacheable="false"/> + <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info" after="-"/> </referenceContainer> </body> </page> 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 1b30a34d15c6ce8779f639f7674d6fd85cfba5a7..cfdf3104f7cc65aeedceee8ac15c114e06fd8556 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 @@ -8,13 +8,17 @@ <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <update handle="sales_order_guest_info_links"/> <body> - <referenceContainer name="content"> - <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info"> - <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"/> - </block> + <referenceContainer name="page.main.title"> + <block class="Magento\Sales\Block\Order\Info" name="order.status" template="order/order_status.phtml" /> + <block class="Magento\Sales\Block\Order\Info" name="order.date" template="order/order_date.phtml" /> + <container name="order.actions.container" htmlTag="div" htmlClass="actions-toolbar order-actions-toolbar"> + <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"> + <block class="Magento\Sales\Block\Order\Info\Buttons\Rss" as="buttons.rss" name="sales.order.info.buttons.rss" cacheable="false"/> + </block> + </container> </referenceContainer> - <referenceContainer name="sales.order.info.buttons"> - <block class="Magento\Sales\Block\Order\Info\Buttons\Rss" as="buttons.rss" name="sales.order.info.buttons.rss" cacheable="false"/> + <referenceContainer name="content"> + <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info" after="sales.order.shipment"/> </referenceContainer> </body> </page> 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 fa80e2ad208caa28d327d1905781efc8038057a2..564a1f790f8c23abd53bd4bb92ad33b2072e14e1 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 @@ -10,11 +10,13 @@ <update handle="sales_order_item_price"/> <update handle="sales_order_guest_info_links"/> <body> - <referenceContainer name="page.main.title"> + <referenceContainer name="page.main.title"> <block class="Magento\Sales\Block\Order\Info" name="order.status" template="order/order_status.phtml" /> <block class="Magento\Sales\Block\Order\Info" name="order.date" template="order/order_date.phtml" /> <container name="order.actions.container" htmlTag="div" htmlClass="actions-toolbar order-actions-toolbar"> - <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"/> + <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"> + <block class="Magento\Sales\Block\Order\Info\Buttons\Rss" as="buttons.rss" name="sales.order.info.buttons.rss" cacheable="false"/> + </block> </container> </referenceContainer> <referenceContainer name="content"> @@ -30,10 +32,7 @@ </block> </block> </block> - <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info"/> - </referenceContainer> - <referenceContainer name="sales.order.info.buttons"> - <block class="Magento\Sales\Block\Order\Info\Buttons\Rss" as="buttons.rss" name="sales.order.info.buttons.rss" cacheable="false"/> + <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info" /> </referenceContainer> </body> </page> diff --git a/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Quote/Edit/Tab/Main.php b/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Quote/Edit/Tab/Main.php index 911086d9db032ca919b855b8d12fd1fa361c4bf1..8506d9693563598f14e9c5e406df6b1df8d28881 100644 --- a/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Quote/Edit/Tab/Main.php +++ b/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Quote/Edit/Tab/Main.php @@ -263,8 +263,8 @@ class Main extends Generic implements TabInterface 'date', [ 'name' => 'from_date', - 'label' => __('From Date'), - 'title' => __('From Date'), + 'label' => __('From'), + 'title' => __('From'), 'input_format' => \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT, 'date_format' => $dateFormat ] @@ -274,8 +274,8 @@ class Main extends Generic implements TabInterface 'date', [ 'name' => 'to_date', - 'label' => __('To Date'), - 'title' => __('To Date'), + 'label' => __('To'), + 'title' => __('To'), 'input_format' => \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT, 'date_format' => $dateFormat ] diff --git a/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Widget/Chooser.php b/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Widget/Chooser.php index a9de8b7661347867ac83c2bb9bc6558b84157766..b177f56ca0ce69561112476623fcae55be8ca986 100644 --- a/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Widget/Chooser.php +++ b/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Widget/Chooser.php @@ -144,7 +144,7 @@ class Chooser extends \Magento\Backend\Block\Widget\Grid\Extended $this->addColumn( 'from_date', [ - 'header' => __('Start on'), + 'header' => __('Start'), 'align' => 'left', 'width' => '120px', 'type' => 'date', @@ -155,7 +155,7 @@ class Chooser extends \Magento\Backend\Block\Widget\Grid\Extended $this->addColumn( 'to_date', [ - 'header' => __('End on'), + 'header' => __('End'), 'align' => 'left', 'width' => '120px', 'type' => 'date', diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Delete.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Delete.php index e6c5dcc4af7f394b24f98a2cc0a7bc4a6486283a..36e384e4a706a08ed7e0a92ee44f97ba8e8f9792 100644 --- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Delete.php +++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/Delete.php @@ -28,7 +28,7 @@ class Delete extends \Magento\SalesRule\Controller\Adminhtml\Promo\Quote $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { $this->messageManager->addError( - __('An error occurred while deleting the rule. Please review the log and try again.') + __('We can\'t delete the rule right now. Please review the log and try again.') ); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); $this->_redirect('sales_rule/*/edit', ['id' => $this->getRequest()->getParam('id')]); diff --git a/app/code/Magento/SalesRule/Model/Coupon/Massgenerator.php b/app/code/Magento/SalesRule/Model/Coupon/Massgenerator.php index 493d3cbfaf6f75c99978dde9fe5d7deeff5bb088..bec82aa5bce1e56a85cc95c306274882e8bdcf34 100644 --- a/app/code/Magento/SalesRule/Model/Coupon/Massgenerator.php +++ b/app/code/Magento/SalesRule/Model/Coupon/Massgenerator.php @@ -61,7 +61,7 @@ class Massgenerator extends \Magento\Framework\Model\AbstractModel implements * @param \Magento\Framework\Stdlib\DateTime\DateTime $date * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -72,7 +72,7 @@ class Massgenerator extends \Magento\Framework\Model\AbstractModel implements \Magento\Framework\Stdlib\DateTime\DateTime $date, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->salesRuleCoupon = $salesRuleCoupon; diff --git a/app/code/Magento/SalesRule/Model/Rule.php b/app/code/Magento/SalesRule/Model/Rule.php index f04d711e5a16f4a6685017ded4c22186fbe8898d..dd709002460608dacf0340541fb4754039189481 100644 --- a/app/code/Magento/SalesRule/Model/Rule.php +++ b/app/code/Magento/SalesRule/Model/Rule.php @@ -184,7 +184,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel * @param \Magento\SalesRule\Model\Resource\Coupon\Collection $couponCollection * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -200,7 +200,7 @@ class Rule extends \Magento\Rule\Model\AbstractModel \Magento\SalesRule\Model\Resource\Coupon\Collection $couponCollection, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_couponFactory = $couponFactory; diff --git a/app/code/Magento/SalesRule/Model/Validator.php b/app/code/Magento/SalesRule/Model/Validator.php index 3f36952fb21317a92df96c3fb73e28b2bd0434c8..b86faa99816ade7822fb863c1743c016699fadf1 100644 --- a/app/code/Magento/SalesRule/Model/Validator.php +++ b/app/code/Magento/SalesRule/Model/Validator.php @@ -103,7 +103,7 @@ class Validator extends \Magento\Framework\Model\AbstractModel * @param Validator\Pool $validators * @param \Magento\Framework\Message\ManagerInterface $messageManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -118,7 +118,7 @@ class Validator extends \Magento\Framework\Model\AbstractModel \Magento\SalesRule\Model\Validator\Pool $validators, \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_collectionFactory = $collectionFactory; diff --git a/app/code/Magento/SalesRule/Setup/InstallSchema.php b/app/code/Magento/SalesRule/Setup/InstallSchema.php index babe9d02c969baf8b012bb711b372f0f3eaf2013..63803b4893f9934caba02f09d69eafe4de26dbf7 100644 --- a/app/code/Magento/SalesRule/Setup/InstallSchema.php +++ b/app/code/Magento/SalesRule/Setup/InstallSchema.php @@ -52,13 +52,13 @@ class InstallSchema implements InstallSchemaInterface \Magento\Framework\DB\Ddl\Table::TYPE_DATE, null, ['nullable' => true, 'default' => null], - 'From Date' + 'From' )->addColumn( 'to_date', \Magento\Framework\DB\Ddl\Table::TYPE_DATE, null, ['nullable' => true, 'default' => null], - 'To Date' + 'To' )->addColumn( 'uses_per_customer', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/_files/quote_item_downloadable.php b/app/code/Magento/SalesRule/Test/Unit/Model/_files/quote_item_downloadable.php index 80bf622d42b89f7527c9dfbc86874cdec497406a..9cd7a0d74ab391aa9db07cb5c6622e6d83827fb4 100644 --- a/app/code/Magento/SalesRule/Test/Unit/Model/_files/quote_item_downloadable.php +++ b/app/code/Magento/SalesRule/Test/Unit/Model/_files/quote_item_downloadable.php @@ -47,8 +47,8 @@ return [ 'base_price_incl_tax' => '8.0000', 'row_total_incl_tax' => '8.0000', 'base_row_total_incl_tax' => '8.0000', - 'hidden_tax_amount' => null, - 'base_hidden_tax_amount' => null, + 'discount_tax_compensation_amount' => null, + 'base_discount_tax_compensation_amount' => null, 'gift_message_id' => null, 'weee_tax_disposition' => '0.0000', 'weee_tax_row_disposition' => '0.0000', diff --git a/app/code/Magento/SalesRule/Test/Unit/Model/_files/quote_item_simple.php b/app/code/Magento/SalesRule/Test/Unit/Model/_files/quote_item_simple.php index acf35bac2813ebd185df073bfcb5872f7bb469b1..e596b4f7dec5f94815d7568aa5666c8afad22df4 100644 --- a/app/code/Magento/SalesRule/Test/Unit/Model/_files/quote_item_simple.php +++ b/app/code/Magento/SalesRule/Test/Unit/Model/_files/quote_item_simple.php @@ -47,8 +47,8 @@ return [ 'base_price_incl_tax' => '10.8300', 'row_total_incl_tax' => '10.8300', 'base_row_total_incl_tax' => '10.8300', - 'hidden_tax_amount' => null, - 'base_hidden_tax_amount' => null, + 'discount_tax_compensation_amount' => null, + 'base_discount_tax_compensation_amount' => null, 'gift_message_id' => null, 'weee_tax_disposition' => '0.0000', 'weee_tax_row_disposition' => '0.0000', diff --git a/app/code/Magento/SalesRule/composer.json b/app/code/Magento/SalesRule/composer.json index 7e74f73963385afbd0c2f5524a03c27f3dd3597a..73ca3c6e1d876da3377b77cc31d0a0a61b398a5a 100644 --- a/app/code/Magento/SalesRule/composer.json +++ b/app/code/Magento/SalesRule/composer.json @@ -3,26 +3,26 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-rule": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-shipping": "0.74.0-beta10", - "magento/module-payment": "0.74.0-beta10", - "magento/module-reports": "0.74.0-beta10", - "magento/module-catalog-rule": "0.74.0-beta10", - "magento/module-widget": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-rule": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-shipping": "0.74.0-beta13", + "magento/module-payment": "0.74.0-beta13", + "magento/module-reports": "0.74.0-beta13", + "magento/module-catalog-rule": "0.74.0-beta13", + "magento/module-widget": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/SalesRule/etc/events.xml b/app/code/Magento/SalesRule/etc/events.xml index ed696d2cdcf8d414a46034efaddd8c7aa673ec30..08e0f690f9dda49ead109b9ea89be91cbfda8cb1 100644 --- a/app/code/Magento/SalesRule/etc/events.xml +++ b/app/code/Magento/SalesRule/etc/events.xml @@ -9,7 +9,7 @@ <event name="sales_order_place_after"> <observer name="salesrule" instance="Magento\SalesRule\Model\Observer" method="salesOrderAfterPlace" /> </event> - <event name="sales_convert_quote_to_order"> + <event name="sales_model_service_quote_submit_before"> <observer name="salesrule" instance="Magento\SalesRule\Model\Observer" method="addSalesRuleNameToOrder" /> </event> </config> 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 ab4efb027470c75d133cd2a8729e3f1af8efaeba..5fe9807df3c54f3db0116439010ea3c4f6d12a3f 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 @@ -48,7 +48,7 @@ </block> <block class="Magento\Backend\Block\Widget\Grid\Column" as="from_date"> <arguments> - <argument name="header" xsi:type="string" translate="true">Start on</argument> + <argument name="header" xsi:type="string" translate="true">Start</argument> <argument name="type" xsi:type="string">date</argument> <argument name="index" xsi:type="string">from_date</argument> <argument name="column_css_class" xsi:type="string">col-date</argument> @@ -57,7 +57,7 @@ </block> <block class="Magento\Backend\Block\Widget\Grid\Column" as="to_date"> <arguments> - <argument name="header" xsi:type="string" translate="true">End on</argument> + <argument name="header" xsi:type="string" translate="true">End</argument> <argument name="type" xsi:type="string">date</argument> <argument name="default" xsi:type="string">--</argument> <argument name="index" xsi:type="string">to_date</argument> diff --git a/app/code/Magento/SalesSequence/composer.json b/app/code/Magento/SalesSequence/composer.json index 326bf1a715a1a200411ea1f80d8a02fe9bd716b4..15ce9855deb2e50bac1d6261380f653585182cfc 100644 --- a/app/code/Magento/SalesSequence/composer.json +++ b/app/code/Magento/SalesSequence/composer.json @@ -3,11 +3,11 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Search/Helper/Data.php b/app/code/Magento/Search/Helper/Data.php index f29486cf034589a3524413d7c22a0ecbdb132e34..f6016324d5d3fd88241436ed50976a367b5abb91 100644 --- a/app/code/Magento/Search/Helper/Data.php +++ b/app/code/Magento/Search/Helper/Data.php @@ -255,15 +255,11 @@ class Data extends AbstractHelper */ public function prepareIndexdata($index, $separator = ' ') { - $_index = []; - foreach ($index as $value) { - if (!is_array($value)) { - $_index[] = $value; - } else { - $_index = array_merge($_index, $value); - } + $indexData = []; + foreach ($index as $attributeId => $value) { + $indexData[$attributeId] = is_array($value) ? implode($separator, $value) : $value; } - return join($separator, array_filter($_index)); + return $indexData; } /** diff --git a/app/code/Magento/Search/Model/Query.php b/app/code/Magento/Search/Model/Query.php index 148490a5042206df764b22af62516f82c4632b54..b9cdb8ec38db3f74669fd3b4543cf22e8e66fd70 100644 --- a/app/code/Magento/Search/Model/Query.php +++ b/app/code/Magento/Search/Model/Query.php @@ -10,7 +10,7 @@ use Magento\Search\Model\Resource\Query\CollectionFactory as QueryCollectionFact use Magento\Search\Model\SearchCollectionInterface as Collection; use Magento\Search\Model\SearchCollectionFactory as CollectionFactory; use Magento\Framework\App\Config\ScopeConfigInterface; -use Magento\Framework\Data\Collection\Db; +use Magento\Framework\Data\Collection\AbstractDb as DbCollection; use Magento\Framework\Model\AbstractModel; use Magento\Framework\Model\Resource\AbstractResource; use Magento\Framework\Registry; @@ -100,9 +100,9 @@ class Query extends AbstractModel implements QueryInterface * @param QueryCollectionFactory $queryCollectionFactory * @param CollectionFactory $searchCollectionFactory * @param StoreManagerInterface $storeManager - * @param Config $scopeConfig + * @param ScopeConfigInterface $scopeConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param Db $resourceCollection + * @param DbCollection $resourceCollection * @param array $data */ public function __construct( @@ -113,7 +113,7 @@ class Query extends AbstractModel implements QueryInterface StoreManagerInterface $storeManager, ScopeConfigInterface $scopeConfig, AbstractResource $resource = null, - Db $resourceCollection = null, + DbCollection $resourceCollection = null, array $data = [] ) { $this->_queryCollectionFactory = $queryCollectionFactory; diff --git a/app/code/Magento/Search/composer.json b/app/code/Magento/Search/composer.json index 7a92f3b6118c08bc18415a27f240f56c7c802b9a..d0eea2c18d8d8791e84e4b2b396f714ccedd2388 100644 --- a/app/code/Magento/Search/composer.json +++ b/app/code/Magento/Search/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-catalog-search": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-reports": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-catalog-search": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-reports": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Sendfriend/Block/Plugin/Catalog/Product/View.php b/app/code/Magento/SendFriend/Block/Plugin/Catalog/Product/View.php similarity index 74% rename from app/code/Magento/Sendfriend/Block/Plugin/Catalog/Product/View.php rename to app/code/Magento/SendFriend/Block/Plugin/Catalog/Product/View.php index 1b604e3b01703e1d5fdbaf5b5b4a6a81f32d76c9..01d9246dc342dbd50deadccc4a0ad498e40f9404 100644 --- a/app/code/Magento/Sendfriend/Block/Plugin/Catalog/Product/View.php +++ b/app/code/Magento/SendFriend/Block/Plugin/Catalog/Product/View.php @@ -4,20 +4,20 @@ * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Block\Plugin\Catalog\Product; +namespace Magento\SendFriend\Block\Plugin\Catalog\Product; class View { /** - * @var \Magento\Sendfriend\Model\Sendfriend + * @var \Magento\SendFriend\Model\SendFriend */ protected $_sendfriend; /** - * @param \Magento\Sendfriend\Model\Sendfriend $sendfriend + * @param \Magento\SendFriend\Model\SendFriend $sendfriend */ public function __construct( - \Magento\Sendfriend\Model\Sendfriend $sendfriend + \Magento\SendFriend\Model\SendFriend $sendfriend ) { $this->_sendfriend = $sendfriend; } diff --git a/app/code/Magento/Sendfriend/Block/Send.php b/app/code/Magento/SendFriend/Block/Send.php similarity index 92% rename from app/code/Magento/Sendfriend/Block/Send.php rename to app/code/Magento/SendFriend/Block/Send.php index ca6fe9bc76f98c7db34bb952f85516b6d9e8433a..00a9c1ba1771e93e48f4fe665870b7dbba251118 100644 --- a/app/code/Magento/Sendfriend/Block/Send.php +++ b/app/code/Magento/SendFriend/Block/Send.php @@ -3,7 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Block; +namespace Magento\SendFriend\Block; use Magento\Customer\Model\Context; @@ -15,9 +15,9 @@ use Magento\Customer\Model\Context; class Send extends \Magento\Framework\View\Element\Template { /** - * Sendfriend data + * SendFriend data * - * @var \Magento\Sendfriend\Helper\Data + * @var \Magento\SendFriend\Helper\Data */ protected $_sendfriendData = null; @@ -44,28 +44,28 @@ class Send extends \Magento\Framework\View\Element\Template protected $_customerViewHelper; /** - * @var \Magento\Sendfriend\Model\Sendfriend + * @var \Magento\SendFriend\Model\SendFriend */ protected $sendfriend; /** * @param \Magento\Framework\View\Element\Template\Context $context * @param \Magento\Customer\Model\Session $customerSession - * @param \Magento\Sendfriend\Helper\Data $sendfriendData + * @param \Magento\SendFriend\Helper\Data $sendfriendData * @param \Magento\Framework\Registry $registry * @param \Magento\Customer\Helper\View $customerViewHelper * @param \Magento\Framework\App\Http\Context $httpContext - * @param \Magento\Sendfriend\Model\Sendfriend $sendfriend + * @param \Magento\SendFriend\Model\SendFriend $sendfriend * @param array $data */ public function __construct( \Magento\Framework\View\Element\Template\Context $context, \Magento\Customer\Model\Session $customerSession, - \Magento\Sendfriend\Helper\Data $sendfriendData, + \Magento\SendFriend\Helper\Data $sendfriendData, \Magento\Framework\Registry $registry, \Magento\Customer\Helper\View $customerViewHelper, \Magento\Framework\App\Http\Context $httpContext, - \Magento\Sendfriend\Model\Sendfriend $sendfriend, + \Magento\SendFriend\Model\SendFriend $sendfriend, array $data = [] ) { $this->_customerSession = $customerSession; diff --git a/app/code/Magento/Sendfriend/Controller/Product.php b/app/code/Magento/SendFriend/Controller/Product.php similarity index 91% rename from app/code/Magento/Sendfriend/Controller/Product.php rename to app/code/Magento/SendFriend/Controller/Product.php index 9a9677d2e54c34b0345e1dd7a92108dbe92f68e5..34f2fe324b804eed01ce541bad453bd1e4bbc366 100644 --- a/app/code/Magento/Sendfriend/Controller/Product.php +++ b/app/code/Magento/SendFriend/Controller/Product.php @@ -3,7 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Controller; +namespace Magento\SendFriend\Controller; use Magento\Framework\Exception\NotFoundException; use Magento\Framework\App\RequestInterface; @@ -29,7 +29,7 @@ class Product extends \Magento\Framework\App\Action\Action protected $_formKeyValidator; /** - * @var \Magento\Sendfriend\Model\Sendfriend + * @var \Magento\SendFriend\Model\SendFriend */ protected $sendFriend; @@ -40,14 +40,14 @@ class Product extends \Magento\Framework\App\Action\Action * @param \Magento\Framework\App\Action\Context $context * @param \Magento\Framework\Registry $coreRegistry * @param \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator - * @param \Magento\Sendfriend\Model\Sendfriend $sendFriend + * @param \Magento\SendFriend\Model\SendFriend $sendFriend * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ public function __construct( \Magento\Framework\App\Action\Context $context, \Magento\Framework\Registry $coreRegistry, \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator, - \Magento\Sendfriend\Model\Sendfriend $sendFriend, + \Magento\SendFriend\Model\SendFriend $sendFriend, \Magento\Catalog\Api\ProductRepositoryInterface $productRepository ) { parent::__construct($context); @@ -67,8 +67,8 @@ class Product extends \Magento\Framework\App\Action\Action */ public function dispatch(RequestInterface $request) { - /* @var $helper \Magento\Sendfriend\Helper\Data */ - $helper = $this->_objectManager->get('Magento\Sendfriend\Helper\Data'); + /* @var $helper \Magento\SendFriend\Helper\Data */ + $helper = $this->_objectManager->get('Magento\SendFriend\Helper\Data'); /* @var $session \Magento\Customer\Model\Session */ $session = $this->_objectManager->get('Magento\Customer\Model\Session'); diff --git a/app/code/Magento/Sendfriend/Controller/Product/Send.php b/app/code/Magento/SendFriend/Controller/Product/Send.php similarity index 93% rename from app/code/Magento/Sendfriend/Controller/Product/Send.php rename to app/code/Magento/SendFriend/Controller/Product/Send.php index 77649da9ffd8dd95a2e723d249d9c6a2595b514c..56be4fe697ba69d092a2745715b43616d044ba77 100644 --- a/app/code/Magento/Sendfriend/Controller/Product/Send.php +++ b/app/code/Magento/SendFriend/Controller/Product/Send.php @@ -3,11 +3,11 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Controller\Product; +namespace Magento\SendFriend\Controller\Product; use Magento\Framework\Controller\ResultFactory; -class Send extends \Magento\Sendfriend\Controller\Product +class Send extends \Magento\SendFriend\Controller\Product { /** * Show Send to a Friend Form diff --git a/app/code/Magento/Sendfriend/Controller/Product/Sendmail.php b/app/code/Magento/SendFriend/Controller/Product/Sendmail.php similarity index 94% rename from app/code/Magento/Sendfriend/Controller/Product/Sendmail.php rename to app/code/Magento/SendFriend/Controller/Product/Sendmail.php index 995bf49d09523543b865e3063b6944864ab40cf4..404f8a020f1ad31288979d377dbefccfc30da190 100644 --- a/app/code/Magento/Sendfriend/Controller/Product/Sendmail.php +++ b/app/code/Magento/SendFriend/Controller/Product/Sendmail.php @@ -6,12 +6,12 @@ // @codingStandardsIgnoreFile -namespace Magento\Sendfriend\Controller\Product; +namespace Magento\SendFriend\Controller\Product; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Controller\ResultFactory; -class Sendmail extends \Magento\Sendfriend\Controller\Product +class Sendmail extends \Magento\SendFriend\Controller\Product { /** @var \Magento\Catalog\Api\CategoryRepositoryInterface */ protected $categoryRepository; @@ -20,7 +20,7 @@ class Sendmail extends \Magento\Sendfriend\Controller\Product * @param \Magento\Framework\App\Action\Context $context * @param \Magento\Framework\Registry $coreRegistry * @param \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator - * @param \Magento\Sendfriend\Model\Sendfriend $sendFriend + * @param \Magento\SendFriend\Model\SendFriend $sendFriend * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository * @param \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository */ @@ -28,7 +28,7 @@ class Sendmail extends \Magento\Sendfriend\Controller\Product \Magento\Framework\App\Action\Context $context, \Magento\Framework\Registry $coreRegistry, \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator, - \Magento\Sendfriend\Model\Sendfriend $sendFriend, + \Magento\SendFriend\Model\SendFriend $sendFriend, \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, \Magento\Catalog\Api\CategoryRepositoryInterface $categoryRepository ) { diff --git a/app/code/Magento/Sendfriend/Helper/Data.php b/app/code/Magento/SendFriend/Helper/Data.php similarity index 97% rename from app/code/Magento/Sendfriend/Helper/Data.php rename to app/code/Magento/SendFriend/Helper/Data.php index 28d367383b94e35450392c9590d1dc3d0fa34baf..e88bb2e9a23c2678f057f951c80ef9b1d44da5c5 100644 --- a/app/code/Magento/Sendfriend/Helper/Data.php +++ b/app/code/Magento/SendFriend/Helper/Data.php @@ -6,10 +6,10 @@ // @codingStandardsIgnoreFile -namespace Magento\Sendfriend\Helper; +namespace Magento\SendFriend\Helper; /** - * Sendfriend Data Helper + * SendFriend Data Helper * * @author Magento Core Team <core@magentocommerce.com> */ diff --git a/app/code/Magento/SendFriend/LICENSE.txt b/app/code/Magento/SendFriend/LICENSE.txt new file mode 100644 index 0000000000000000000000000000000000000000..49525fd99da9c51e6d85420266d41cb3d6b7a648 --- /dev/null +++ b/app/code/Magento/SendFriend/LICENSE.txt @@ -0,0 +1,48 @@ + +Open Software License ("OSL") v. 3.0 + +This Open Software 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 Open Software 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, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software 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 (C) 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 "Open Software License" or "OSL" 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 <insert your license name here>" 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/SendFriend/LICENSE_AFL.txt b/app/code/Magento/SendFriend/LICENSE_AFL.txt new file mode 100644 index 0000000000000000000000000000000000000000..87943b95d43a5bb8736093275afe3cb8e1d93d26 --- /dev/null +++ b/app/code/Magento/SendFriend/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 <insert your license name here>" 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/Sendfriend/Model/Resource/Sendfriend.php b/app/code/Magento/SendFriend/Model/Resource/SendFriend.php similarity index 91% rename from app/code/Magento/Sendfriend/Model/Resource/Sendfriend.php rename to app/code/Magento/SendFriend/Model/Resource/SendFriend.php index e2e98e4b7c1430506462d65e306cda1a3baf39da..f09da776a425dbf54f528772b847567adae11301 100644 --- a/app/code/Magento/Sendfriend/Model/Resource/Sendfriend.php +++ b/app/code/Magento/SendFriend/Model/Resource/SendFriend.php @@ -3,14 +3,14 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Model\Resource; +namespace Magento\SendFriend\Model\Resource; /** * SendFriend Log Resource Model * * @author Magento Core Team <core@magentocommerce.com> */ -class Sendfriend extends \Magento\Framework\Model\Resource\Db\AbstractDb +class SendFriend extends \Magento\Framework\Model\Resource\Db\AbstractDb { /** * Initialize connection and table @@ -25,7 +25,7 @@ class Sendfriend extends \Magento\Framework\Model\Resource\Db\AbstractDb /** * Retrieve Sended Emails By Ip * - * @param \Magento\Sendfriend\Model\Sendfriend $object + * @param \Magento\SendFriend\Model\SendFriend $object * @param int $ip * @param int $startTime * @param int $websiteId diff --git a/app/code/Magento/Sendfriend/Model/Resource/Sendfriend/Collection.php b/app/code/Magento/SendFriend/Model/Resource/SendFriend/Collection.php similarity index 66% rename from app/code/Magento/Sendfriend/Model/Resource/Sendfriend/Collection.php rename to app/code/Magento/SendFriend/Model/Resource/SendFriend/Collection.php index 9442be3301816d6c8f02b36cafb595d50ed4473e..95691dda11ca0ed71a21cae36cb5f1e7192f571a 100644 --- a/app/code/Magento/Sendfriend/Model/Resource/Sendfriend/Collection.php +++ b/app/code/Magento/SendFriend/Model/Resource/SendFriend/Collection.php @@ -3,10 +3,10 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Model\Resource\Sendfriend; +namespace Magento\SendFriend\Model\Resource\SendFriend; /** - * Sendfriend log resource collection + * SendFriend log resource collection * * @author Magento Core Team <core@magentocommerce.com> */ @@ -19,6 +19,6 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac */ protected function _construct() { - $this->_init('Magento\Sendfriend\Model\Sendfriend', 'Magento\Sendfriend\Model\Resource\Sendfriend'); + $this->_init('Magento\SendFriend\Model\SendFriend', 'Magento\SendFriend\Model\Resource\SendFriend'); } } diff --git a/app/code/Magento/Sendfriend/Model/Sendfriend.php b/app/code/Magento/SendFriend/Model/SendFriend.php similarity index 91% rename from app/code/Magento/Sendfriend/Model/Sendfriend.php rename to app/code/Magento/SendFriend/Model/SendFriend.php index 6b48f9dd07302cade0af21da6080a66a55b3e5bf..a2152106c837f4ed64b69758bb269a387772a15a 100644 --- a/app/code/Magento/Sendfriend/Model/Sendfriend.php +++ b/app/code/Magento/SendFriend/Model/SendFriend.php @@ -3,24 +3,24 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Model; +namespace Magento\SendFriend\Model; use Magento\Framework\Exception\LocalizedException as CoreException; /** * SendFriend Log * - * @method \Magento\Sendfriend\Model\Resource\Sendfriend _getResource() - * @method \Magento\Sendfriend\Model\Resource\Sendfriend getResource() + * @method \Magento\SendFriend\Model\Resource\SendFriend _getResource() + * @method \Magento\SendFriend\Model\Resource\SendFriend getResource() * @method int getIp() - * @method \Magento\Sendfriend\Model\Sendfriend setIp(int $value) + * @method \Magento\SendFriend\Model\SendFriend setIp(int $value) * @method int getTime() - * @method \Magento\Sendfriend\Model\Sendfriend setTime(int $value) + * @method \Magento\SendFriend\Model\SendFriend setTime(int $value) * * @author Magento Core Team <core@magentocommerce.com> * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Sendfriend extends \Magento\Framework\Model\AbstractModel +class SendFriend extends \Magento\Framework\Model\AbstractModel { /** * Recipient Names @@ -65,9 +65,9 @@ class Sendfriend extends \Magento\Framework\Model\AbstractModel protected $_lastCookieValue = []; /** - * Sendfriend data + * SendFriend data * - * @var \Magento\Sendfriend\Helper\Data + * @var \Magento\SendFriend\Helper\Data */ protected $_sendfriendData = null; @@ -114,13 +114,13 @@ class Sendfriend extends \Magento\Framework\Model\AbstractModel * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder * @param \Magento\Catalog\Helper\Image $catalogImage - * @param \Magento\Sendfriend\Helper\Data $sendfriendData + * @param \Magento\SendFriend\Helper\Data $sendfriendData * @param \Magento\Framework\Escaper $escaper * @param \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress $remoteAddress * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -130,13 +130,13 @@ class Sendfriend extends \Magento\Framework\Model\AbstractModel \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder, \Magento\Catalog\Helper\Image $catalogImage, - \Magento\Sendfriend\Helper\Data $sendfriendData, + \Magento\SendFriend\Helper\Data $sendfriendData, \Magento\Framework\Escaper $escaper, \Magento\Framework\HTTP\PhpEnvironment\RemoteAddress $remoteAddress, \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_storeManager = $storeManager; @@ -157,7 +157,7 @@ class Sendfriend extends \Magento\Framework\Model\AbstractModel */ protected function _construct() { - $this->_init('Magento\Sendfriend\Model\Resource\Sendfriend'); + $this->_init('Magento\SendFriend\Model\Resource\SendFriend'); } /** @@ -230,7 +230,7 @@ class Sendfriend extends \Magento\Framework\Model\AbstractModel $name = $this->getSender()->getName(); if (empty($name)) { - $errors[] = __('The sender name cannot be empty.'); + $errors[] = __('Please enter a sender name.'); } $email = $this->getSender()->getEmail(); @@ -240,11 +240,11 @@ class Sendfriend extends \Magento\Framework\Model\AbstractModel $message = $this->getSender()->getMessage(); if (empty($message)) { - $errors[] = __('The message cannot be empty.'); + $errors[] = __('Please enter a message.'); } if (!$this->getRecipients()->getEmails()) { - $errors[] = __('At least one recipient must be specified.'); + $errors[] = __('Please specify at least one recipient.'); } // validate recipients email addresses @@ -347,7 +347,7 @@ class Sendfriend extends \Magento\Framework\Model\AbstractModel { $product = $this->_getData('_product'); if (!$product instanceof \Magento\Catalog\Model\Product) { - throw new \Magento\Framework\Exception\LocalizedException(__('Please define a correct Product instance.')); + throw new \Magento\Framework\Exception\LocalizedException(__('Please define a correct product instance.')); } return $product; } @@ -378,7 +378,7 @@ class Sendfriend extends \Magento\Framework\Model\AbstractModel $sender = $this->_getData('_sender'); if (!$sender instanceof \Magento\Framework\Object) { throw new \Magento\Framework\Exception\LocalizedException( - __('Please define the correct Sender information.') + __('Please define the correct sender information.') ); } return $sender; @@ -437,9 +437,9 @@ class Sendfriend extends \Magento\Framework\Model\AbstractModel } switch ($this->_sendfriendData->getLimitBy()) { - case \Magento\Sendfriend\Helper\Data::CHECK_COOKIE: + case \Magento\SendFriend\Helper\Data::CHECK_COOKIE: return $this->_sentCount = $this->_sentCountByCookies(false); - case \Magento\Sendfriend\Helper\Data::CHECK_IP: + case \Magento\SendFriend\Helper\Data::CHECK_IP: return $this->_sentCount = $this->_sentCountByIp(false); default: return 0; @@ -454,9 +454,9 @@ class Sendfriend extends \Magento\Framework\Model\AbstractModel protected function _incrementSentCount() { switch ($this->_sendfriendData->getLimitBy()) { - case \Magento\Sendfriend\Helper\Data::CHECK_COOKIE: + case \Magento\SendFriend\Helper\Data::CHECK_COOKIE: return $this->_sentCount = $this->_sentCountByCookies(true); - case \Magento\Sendfriend\Helper\Data::CHECK_IP: + case \Magento\SendFriend\Helper\Data::CHECK_IP: return $this->_sentCount = $this->_sentCountByIp(true); default: return 0; diff --git a/app/code/Magento/Sendfriend/Model/Source/Checktype.php b/app/code/Magento/SendFriend/Model/Source/Checktype.php similarity index 75% rename from app/code/Magento/Sendfriend/Model/Source/Checktype.php rename to app/code/Magento/SendFriend/Model/Source/Checktype.php index 2339ae33790005b0ea92b21063caf5d47a3eabbc..3cdaa4e13bc15e85e682b7c57c32071b2b534f7f 100644 --- a/app/code/Magento/Sendfriend/Model/Source/Checktype.php +++ b/app/code/Magento/SendFriend/Model/Source/Checktype.php @@ -9,7 +9,7 @@ * * @author Magento Core Team <core@magentocommerce.com> */ -namespace Magento\Sendfriend\Model\Source; +namespace Magento\SendFriend\Model\Source; class Checktype implements \Magento\Framework\Option\ArrayInterface { @@ -21,8 +21,8 @@ class Checktype implements \Magento\Framework\Option\ArrayInterface public function toOptionArray() { return [ - ['value' => \Magento\Sendfriend\Helper\Data::CHECK_IP, 'label' => __('IP Address')], - ['value' => \Magento\Sendfriend\Helper\Data::CHECK_COOKIE, 'label' => __('Cookie (unsafe)')] + ['value' => \Magento\SendFriend\Helper\Data::CHECK_IP, 'label' => __('IP Address')], + ['value' => \Magento\SendFriend\Helper\Data::CHECK_COOKIE, 'label' => __('Cookie (unsafe)')] ]; } } diff --git a/app/code/Magento/Sendfriend/README.md b/app/code/Magento/SendFriend/README.md similarity index 64% rename from app/code/Magento/Sendfriend/README.md rename to app/code/Magento/SendFriend/README.md index 3de38fe9f9dfa452d81670ee79ddebbdb7e7af52..5d4dc6725d9fe2ff4dfb3de2be3a394ddd1bc5d0 100644 --- a/app/code/Magento/Sendfriend/README.md +++ b/app/code/Magento/SendFriend/README.md @@ -1 +1 @@ -The Magento_Sendfriend implements the functionality behind the "Email to a Friend" link on a product page, which allows to share favorite products with others by clicking the link. +The Magento_SendFriend implements the functionality behind the "Email to a Friend" link on a product page, which allows to share favorite products with others by clicking the link. diff --git a/app/code/Magento/Sendfriend/Setup/InstallSchema.php b/app/code/Magento/SendFriend/Setup/InstallSchema.php similarity index 98% rename from app/code/Magento/Sendfriend/Setup/InstallSchema.php rename to app/code/Magento/SendFriend/Setup/InstallSchema.php index ebb2442760bc22a2414d5417e5415e93714dc261..51f562b8ba901376bb2a71d76f05a5d22d86aa43 100644 --- a/app/code/Magento/Sendfriend/Setup/InstallSchema.php +++ b/app/code/Magento/SendFriend/Setup/InstallSchema.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Setup; +namespace Magento\SendFriend\Setup; use Magento\Framework\Setup\InstallSchemaInterface; use Magento\Framework\Setup\ModuleContextInterface; diff --git a/app/code/Magento/Sendfriend/Test/Unit/Block/Plugin/Catalog/Product/ViewTest.php b/app/code/Magento/SendFriend/Test/Unit/Block/Plugin/Catalog/Product/ViewTest.php similarity index 84% rename from app/code/Magento/Sendfriend/Test/Unit/Block/Plugin/Catalog/Product/ViewTest.php rename to app/code/Magento/SendFriend/Test/Unit/Block/Plugin/Catalog/Product/ViewTest.php index e4cd009f250c986301174e7200f0f89cacb9b9a5..8fedd18435c10fc470d496830d6d95dcb368be39 100644 --- a/app/code/Magento/Sendfriend/Test/Unit/Block/Plugin/Catalog/Product/ViewTest.php +++ b/app/code/Magento/SendFriend/Test/Unit/Block/Plugin/Catalog/Product/ViewTest.php @@ -4,19 +4,19 @@ * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Test\Unit\Block\Plugin\Catalog\Product; +namespace Magento\SendFriend\Test\Unit\Block\Plugin\Catalog\Product; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; class ViewTest extends \PHPUnit_Framework_TestCase { - /** @var \Magento\Sendfriend\Block\Plugin\Catalog\Product\View */ + /** @var \Magento\SendFriend\Block\Plugin\Catalog\Product\View */ protected $view; /** @var ObjectManagerHelper */ protected $objectManagerHelper; - /** @var \Magento\Sendfriend\Model\Sendfriend|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\SendFriend\Model\SendFriend|\PHPUnit_Framework_MockObject_MockObject */ protected $sendfriendModel; /** @var \Magento\Catalog\Block\Product\View|\PHPUnit_Framework_MockObject_MockObject */ @@ -25,7 +25,7 @@ class ViewTest extends \PHPUnit_Framework_TestCase protected function setUp() { $this->sendfriendModel = $this->getMock( - 'Magento\Sendfriend\Model\Sendfriend', + 'Magento\SendFriend\Model\SendFriend', ['__wakeup', 'canEmailToFriend'], [], '', @@ -35,7 +35,7 @@ class ViewTest extends \PHPUnit_Framework_TestCase $this->objectManagerHelper = new ObjectManagerHelper($this); $this->view = $this->objectManagerHelper->getObject( - 'Magento\Sendfriend\Block\Plugin\Catalog\Product\View', + 'Magento\SendFriend\Block\Plugin\Catalog\Product\View', [ 'sendfriend' => $this->sendfriendModel ] diff --git a/app/code/Magento/Sendfriend/Test/Unit/Block/SendTest.php b/app/code/Magento/SendFriend/Test/Unit/Block/SendTest.php similarity index 93% rename from app/code/Magento/Sendfriend/Test/Unit/Block/SendTest.php rename to app/code/Magento/SendFriend/Test/Unit/Block/SendTest.php index 59b2e94e8b2639fd1a0dcffa3413214a6260b8ad..68b027a8e16ae16d05694b164739c2324d7eb4c3 100644 --- a/app/code/Magento/Sendfriend/Test/Unit/Block/SendTest.php +++ b/app/code/Magento/SendFriend/Test/Unit/Block/SendTest.php @@ -4,19 +4,19 @@ * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Test\Unit\Block; +namespace Magento\SendFriend\Test\Unit\Block; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class SendTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Sendfriend\Block\Send + * @var \Magento\SendFriend\Block\Send */ protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Sendfriend\Model\Sendfriend + * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\SendFriend\Model\SendFriend */ protected $sendfriendMock; @@ -34,7 +34,7 @@ class SendTest extends \PHPUnit_Framework_TestCase { $objectManager = new ObjectManager($this); - $this->sendfriendMock = $this->getMockBuilder('Magento\Sendfriend\Model\Sendfriend') + $this->sendfriendMock = $this->getMockBuilder('Magento\SendFriend\Model\SendFriend') ->disableOriginalConstructor() ->getMock(); $this->urlBuilderMock = $this->getMockBuilder('Magento\Framework\UrlInterface') @@ -45,7 +45,7 @@ class SendTest extends \PHPUnit_Framework_TestCase ->getMockForAbstractClass(); $this->model = $objectManager->getObject( - 'Magento\Sendfriend\Block\Send', + 'Magento\SendFriend\Block\Send', [ 'sendfriend' => $this->sendfriendMock, 'urlBuilder' => $this->urlBuilderMock, diff --git a/app/code/Magento/Sendfriend/Test/Unit/Model/SendfriendTest.php b/app/code/Magento/SendFriend/Test/Unit/Model/SendFriendTest.php similarity index 84% rename from app/code/Magento/Sendfriend/Test/Unit/Model/SendfriendTest.php rename to app/code/Magento/SendFriend/Test/Unit/Model/SendFriendTest.php index 33c0b35789c7d046ebb4cb7c5fb3eff6f6eff3cd..27fc14332c2055d4adb2310b6502b9e1cf3beba0 100644 --- a/app/code/Magento/Sendfriend/Test/Unit/Model/SendfriendTest.php +++ b/app/code/Magento/SendFriend/Test/Unit/Model/SendFriendTest.php @@ -4,18 +4,18 @@ * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Test\Unit\Model; +namespace Magento\SendFriend\Test\Unit\Model; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; /** - * Test Sendfriend + * Test SendFriend * */ -class SendfriendTest extends \PHPUnit_Framework_TestCase +class SendFriendTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Sendfriend\Model\Sendfriend + * @var \Magento\SendFriend\Model\SendFriend */ protected $model; @@ -32,13 +32,13 @@ class SendfriendTest extends \PHPUnit_Framework_TestCase public function setUp() { $objectManager = new ObjectManager($this); - $this->sendfriendDataMock = $this->getMockBuilder('Magento\Sendfriend\Helper\Data') + $this->sendfriendDataMock = $this->getMockBuilder('Magento\SendFriend\Helper\Data') ->disableOriginalConstructor() ->getMock(); $this->cookieManagerMock = $this->getMock('Magento\Framework\Stdlib\CookieManagerInterface'); $this->model = $objectManager->getObject( - 'Magento\Sendfriend\Model\Sendfriend', + 'Magento\SendFriend\Model\SendFriend', [ 'sendfriendData' => $this->sendfriendDataMock, 'cookieManager' => $this->cookieManagerMock, @@ -50,7 +50,7 @@ class SendfriendTest extends \PHPUnit_Framework_TestCase { $cookieName = 'testCookieName'; $this->sendfriendDataMock->expects($this->once())->method('getLimitBy')->with()->will( - $this->returnValue(\Magento\Sendfriend\Helper\Data::CHECK_COOKIE) + $this->returnValue(\Magento\SendFriend\Helper\Data::CHECK_COOKIE) ); $this->sendfriendDataMock->expects($this->once())->method('getCookieName')->with()->will( $this->returnValue($cookieName) @@ -69,7 +69,7 @@ class SendfriendTest extends \PHPUnit_Framework_TestCase $this->cookieManagerMock->expects($this->once())->method('getCookie')->with($cookieName); $this->cookieManagerMock->expects($this->once())->method('setSensitiveCookie'); - $sendFriendClass = new \ReflectionClass('Magento\Sendfriend\Model\Sendfriend'); + $sendFriendClass = new \ReflectionClass('Magento\SendFriend\Model\SendFriend'); $method = $sendFriendClass->getMethod('_sentCountByCookies'); $method->setAccessible(true); $method->invokeArgs($this->model, [true]); diff --git a/app/code/Magento/SendFriend/composer.json b/app/code/Magento/SendFriend/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..f8e2a4f687541841f0942de6a0805271b6dac339 --- /dev/null +++ b/app/code/Magento/SendFriend/composer.json @@ -0,0 +1,27 @@ +{ + "name": "magento/module-send-friend", + "description": "N/A", + "require": { + "php": "~5.5.0|~5.6.0", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/magento-composer-installer": "*" + }, + "type": "magento2-module", + "version": "0.74.0-beta13", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "extra": { + "map": [ + [ + "*", + "Magento/SendFriend" + ] + ] + } +} diff --git a/app/code/Magento/Sendfriend/etc/adminhtml/system.xml b/app/code/Magento/SendFriend/etc/adminhtml/system.xml similarity index 97% rename from app/code/Magento/Sendfriend/etc/adminhtml/system.xml rename to app/code/Magento/SendFriend/etc/adminhtml/system.xml index 7b86d360d4e1b6a906ac441e2b2c5aa4667b6de2..c6c8e092fa9b60c1fb1ac29f881b826a944a3583 100644 --- a/app/code/Magento/Sendfriend/etc/adminhtml/system.xml +++ b/app/code/Magento/SendFriend/etc/adminhtml/system.xml @@ -35,7 +35,7 @@ </field> <field id="check_by" translate="label" type="select" sortOrder="6" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Limit Sending By</label> - <source_model>Magento\Sendfriend\Model\Source\Checktype</source_model> + <source_model>Magento\SendFriend\Model\Source\Checktype</source_model> </field> </group> </section> diff --git a/app/code/Magento/Sendfriend/etc/config.xml b/app/code/Magento/SendFriend/etc/config.xml similarity index 100% rename from app/code/Magento/Sendfriend/etc/config.xml rename to app/code/Magento/SendFriend/etc/config.xml diff --git a/app/code/Magento/Sendfriend/etc/email_templates.xml b/app/code/Magento/SendFriend/etc/email_templates.xml similarity index 95% rename from app/code/Magento/Sendfriend/etc/email_templates.xml rename to app/code/Magento/SendFriend/etc/email_templates.xml index 961545855408cd5f59da75da9837d7788faba0f6..4070d1a2fe93c5453a2e8cce864b3688e6e45611 100644 --- a/app/code/Magento/Sendfriend/etc/email_templates.xml +++ b/app/code/Magento/SendFriend/etc/email_templates.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Email/etc/email_templates.xsd"> - <template id="sendfriend_email_template" label="Send Product Link to Friend" file="product_share.html" type="html" module="Magento_Sendfriend"/> + <template id="sendfriend_email_template" label="Send Product Link to Friend" file="product_share.html" type="html" module="Magento_SendFriend"/> </config> diff --git a/app/code/Magento/Sendfriend/etc/frontend/di.xml b/app/code/Magento/SendFriend/etc/frontend/di.xml similarity index 88% rename from app/code/Magento/Sendfriend/etc/frontend/di.xml rename to app/code/Magento/SendFriend/etc/frontend/di.xml index 24d0db40cc8aaca0c74fa85d24b8eb6927962565..fa898654a5ae59e3a2ada1d261222d83d606298b 100644 --- a/app/code/Magento/Sendfriend/etc/frontend/di.xml +++ b/app/code/Magento/SendFriend/etc/frontend/di.xml @@ -7,6 +7,6 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> <type name="Magento\Catalog\Block\Product\View"> - <plugin name="catalogProductViewCanEmailToFriend" type="Magento\Sendfriend\Block\Plugin\Catalog\Product\View" /> + <plugin name="catalogProductViewCanEmailToFriend" type="Magento\SendFriend\Block\Plugin\Catalog\Product\View" /> </type> </config> diff --git a/app/code/Magento/Sendfriend/etc/frontend/page_types.xml b/app/code/Magento/SendFriend/etc/frontend/page_types.xml similarity index 100% rename from app/code/Magento/Sendfriend/etc/frontend/page_types.xml rename to app/code/Magento/SendFriend/etc/frontend/page_types.xml diff --git a/app/code/Magento/Sendfriend/etc/frontend/routes.xml b/app/code/Magento/SendFriend/etc/frontend/routes.xml similarity index 89% rename from app/code/Magento/Sendfriend/etc/frontend/routes.xml rename to app/code/Magento/SendFriend/etc/frontend/routes.xml index c939291cfddf073c7c212f86c230f89c518d75be..c483794631b23fbfdb8af789e8414877b103494d 100644 --- a/app/code/Magento/Sendfriend/etc/frontend/routes.xml +++ b/app/code/Magento/SendFriend/etc/frontend/routes.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd"> <router id="standard"> <route id="sendfriend" frontName="sendfriend"> - <module name="Magento_Sendfriend" /> + <module name="Magento_SendFriend" /> </route> </router> </config> \ No newline at end of file diff --git a/app/code/Magento/Sendfriend/etc/module.xml b/app/code/Magento/SendFriend/etc/module.xml similarity index 87% rename from app/code/Magento/Sendfriend/etc/module.xml rename to app/code/Magento/SendFriend/etc/module.xml index eedc4988739d7f74df401473958c5b8a9569032e..ed8d08f3e7dd430358ff81531ca5f7a481255776 100644 --- a/app/code/Magento/Sendfriend/etc/module.xml +++ b/app/code/Magento/SendFriend/etc/module.xml @@ -7,7 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd"> - <module name="Magento_Sendfriend" setup_version="2.0.0"> + <module name="Magento_SendFriend" setup_version="2.0.0"> <sequence> <module name="Magento_Catalog"/> </sequence> diff --git a/app/code/Magento/Sendfriend/i18n/de_DE.csv b/app/code/Magento/SendFriend/i18n/de_DE.csv similarity index 100% rename from app/code/Magento/Sendfriend/i18n/de_DE.csv rename to app/code/Magento/SendFriend/i18n/de_DE.csv diff --git a/app/code/Magento/Sendfriend/i18n/en_US.csv b/app/code/Magento/SendFriend/i18n/en_US.csv similarity index 100% rename from app/code/Magento/Sendfriend/i18n/en_US.csv rename to app/code/Magento/SendFriend/i18n/en_US.csv diff --git a/app/code/Magento/Sendfriend/i18n/es_ES.csv b/app/code/Magento/SendFriend/i18n/es_ES.csv similarity index 100% rename from app/code/Magento/Sendfriend/i18n/es_ES.csv rename to app/code/Magento/SendFriend/i18n/es_ES.csv diff --git a/app/code/Magento/Sendfriend/i18n/fr_FR.csv b/app/code/Magento/SendFriend/i18n/fr_FR.csv similarity index 100% rename from app/code/Magento/Sendfriend/i18n/fr_FR.csv rename to app/code/Magento/SendFriend/i18n/fr_FR.csv diff --git a/app/code/Magento/Sendfriend/i18n/nl_NL.csv b/app/code/Magento/SendFriend/i18n/nl_NL.csv similarity index 100% rename from app/code/Magento/Sendfriend/i18n/nl_NL.csv rename to app/code/Magento/SendFriend/i18n/nl_NL.csv diff --git a/app/code/Magento/Sendfriend/i18n/pt_BR.csv b/app/code/Magento/SendFriend/i18n/pt_BR.csv similarity index 100% rename from app/code/Magento/Sendfriend/i18n/pt_BR.csv rename to app/code/Magento/SendFriend/i18n/pt_BR.csv diff --git a/app/code/Magento/Sendfriend/i18n/zh_CN.csv b/app/code/Magento/SendFriend/i18n/zh_CN.csv similarity index 100% rename from app/code/Magento/Sendfriend/i18n/zh_CN.csv rename to app/code/Magento/SendFriend/i18n/zh_CN.csv diff --git a/app/code/Magento/Sendfriend/view/email/product_share.html b/app/code/Magento/SendFriend/view/email/product_share.html similarity index 100% rename from app/code/Magento/Sendfriend/view/email/product_share.html rename to app/code/Magento/SendFriend/view/email/product_share.html diff --git a/app/code/Magento/Sendfriend/view/frontend/layout/sendfriend_product_send.xml b/app/code/Magento/SendFriend/view/frontend/layout/sendfriend_product_send.xml similarity index 91% rename from app/code/Magento/Sendfriend/view/frontend/layout/sendfriend_product_send.xml rename to app/code/Magento/SendFriend/view/frontend/layout/sendfriend_product_send.xml index d7b3f35878a656d5c325d7273dab07e750fc3453..6923f0561d2c7b8529d58bd94dd1909b31e67976 100644 --- a/app/code/Magento/Sendfriend/view/frontend/layout/sendfriend_product_send.xml +++ b/app/code/Magento/SendFriend/view/frontend/layout/sendfriend_product_send.xml @@ -13,7 +13,7 @@ </action> </referenceBlock> <referenceContainer name="content"> - <block class="Magento\Sendfriend\Block\Send" name="sendfriend.send" template="send.phtml"/> + <block class="Magento\SendFriend\Block\Send" name="sendfriend.send" template="send.phtml"/> </referenceContainer> </body> </page> diff --git a/app/code/Magento/Sendfriend/view/frontend/templates/send.phtml b/app/code/Magento/SendFriend/view/frontend/templates/send.phtml similarity index 99% rename from app/code/Magento/Sendfriend/view/frontend/templates/send.phtml rename to app/code/Magento/SendFriend/view/frontend/templates/send.phtml index eb8e4f7cef56f25176d3c9f3e69a685daea9e41d..c4810f6c833e6a9d4d01f8d2c6322262d0fc2d14 100644 --- a/app/code/Magento/Sendfriend/view/frontend/templates/send.phtml +++ b/app/code/Magento/SendFriend/view/frontend/templates/send.phtml @@ -9,7 +9,7 @@ /** * Send to friend form * - * @var $block \Magento\Sendfriend\Block\Send + * @var $block \Magento\SendFriend\Block\Send */ ?> <script id="add-recipient-tmpl" type="text/x-magento-template"> diff --git a/app/code/Magento/Sendfriend/composer.json b/app/code/Magento/Sendfriend/composer.json deleted file mode 100644 index dfb9ff0015641b8d6be20c156d31d74395949eaf..0000000000000000000000000000000000000000 --- a/app/code/Magento/Sendfriend/composer.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "magento/module-sendfriend", - "description": "N/A", - "require": { - "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/magento-composer-installer": "*" - }, - "type": "magento2-module", - "version": "0.74.0-beta10", - "license": [ - "OSL-3.0", - "AFL-3.0" - ], - "extra": { - "map": [ - [ - "*", - "Magento/Sendfriend" - ] - ] - } -} diff --git a/app/code/Magento/Shipping/Block/Adminhtml/Order/Tracking/Invoice.php b/app/code/Magento/Shipping/Block/Adminhtml/Order/Tracking/Invoice.php index be3388ea61b99ca9fb161ba488132971e0461dd9..1733c158df98f167d9beb6d312b92faacef04f73 100644 --- a/app/code/Magento/Shipping/Block/Adminhtml/Order/Tracking/Invoice.php +++ b/app/code/Magento/Shipping/Block/Adminhtml/Order/Tracking/Invoice.php @@ -5,15 +5,14 @@ */ /** - * Shipment tracking control form - * + * Invoice tracking control form */ namespace Magento\Shipping\Block\Adminhtml\Order\Tracking; class Invoice extends \Magento\Shipping\Block\Adminhtml\Order\Tracking { /** - * Retrieve shipment model instance + * Retrieve invoice * * @return \Magento\Sales\Model\Order\Shipment */ @@ -23,9 +22,9 @@ class Invoice extends \Magento\Shipping\Block\Adminhtml\Order\Tracking } /** - * Retrieve + * Retrieve carriers * - * @return unknown + * @return array */ protected function _getCarriersInstances() { diff --git a/app/code/Magento/Shipping/Helper/Data.php b/app/code/Magento/Shipping/Helper/Data.php index 8eb59b34cc5b9f7666868e196efc8737fc8cb931..621a410a2b643035c6abdc5c43d8ead747559d3a 100644 --- a/app/code/Magento/Shipping/Helper/Data.php +++ b/app/code/Magento/Shipping/Helper/Data.php @@ -63,10 +63,13 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper protected function _getTrackingUrl($key, $model, $method = 'getId') { $urlPart = "{$key}:{$model->{$method}()}:{$model->getProtectCode()}"; - $param = ['hash' => $this->urlEncoder->encode($urlPart)]; + $params = [ + '_direct' => 'shipping/tracking/popup', + '_query' => ['hash' => $this->urlEncoder->encode($urlPart)] + ]; $storeModel = $this->_storeManager->getStore($model->getStoreId()); - return $storeModel->getUrl('shipping/tracking/popup', $param); + return $storeModel->getUrl('', $params); } /** diff --git a/app/code/Magento/Shipping/Model/Order/Track.php b/app/code/Magento/Shipping/Model/Order/Track.php index 9763f2bdb6e49035dd9b5d16b0677b635b6dd39b..e46b40c6c45729cf76717717be42de0a091bd11f 100644 --- a/app/code/Magento/Shipping/Model/Order/Track.php +++ b/app/code/Magento/Shipping/Model/Order/Track.php @@ -38,7 +38,7 @@ class Track extends \Magento\Sales\Model\Order\Shipment\Track * @param \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory * @param \Magento\Shipping\Model\CarrierFactory $carrierFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -52,7 +52,7 @@ class Track extends \Magento\Sales\Model\Order\Shipment\Track \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory, \Magento\Shipping\Model\CarrierFactory $carrierFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/Shipping/composer.json b/app/code/Magento/Shipping/composer.json index b024273bf5876516e70f4be5c76f331cc3bf5c23..1960a285405d0b1fb9159a8cbb6905f4b27b57e8 100644 --- a/app/code/Magento/Shipping/composer.json +++ b/app/code/Magento/Shipping/composer.json @@ -3,27 +3,27 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-contact": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-payment": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-contact": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-payment": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "ext-gd": "*", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-fedex": "0.74.0-beta10", - "magento/module-ups": "0.74.0-beta10" + "magento/module-fedex": "0.74.0-beta13", + "magento/module-ups": "0.74.0-beta13" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Delete.php b/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Delete.php index 90e181c12cf46dcb5df9a38a4cdb5032f3bafb74..70f12719c16cb5a2cd580b07c9915a9faa1d93b7 100644 --- a/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Delete.php +++ b/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Delete.php @@ -43,7 +43,7 @@ class Delete extends \Magento\Sitemap\Controller\Adminhtml\Sitemap } $model->delete(); // display success message - $this->messageManager->addSuccess(__('The sitemap has been deleted.')); + $this->messageManager->addSuccess(__('You deleted the sitemap.')); // go to grid $this->_redirect('adminhtml/*/'); return; diff --git a/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Generate.php b/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Generate.php index 88883b6bbecec6b2ac7bc56d9fbc795fff080b91..b5a7e40d5a04209251446b758dad4b73fd01ad43 100644 --- a/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Generate.php +++ b/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Generate.php @@ -32,7 +32,7 @@ class Generate extends \Magento\Sitemap\Controller\Adminhtml\Sitemap } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { - $this->messageManager->addException($e, __('Something went wrong generating the sitemap.')); + $this->messageManager->addException($e, __('We can\'t generate the sitemap right now.')); } } else { $this->messageManager->addError(__('We can\'t find a sitemap to generate.')); diff --git a/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Save.php b/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Save.php index da6bf182580d363bf34fa4b4e39de78127246db8..ed0bab0aec2ea260f851808fcdaee177d67d4d60 100644 --- a/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Save.php +++ b/app/code/Magento/Sitemap/Controller/Adminhtml/Sitemap/Save.php @@ -74,7 +74,7 @@ class Save extends \Magento\Sitemap\Controller\Adminhtml\Sitemap // save the data $model->save(); // display success message - $this->messageManager->addSuccess(__('The sitemap has been saved.')); + $this->messageManager->addSuccess(__('You saved the sitemap.')); // clear previously saved data from session $this->_objectManager->get('Magento\Backend\Model\Session')->setFormData(false); diff --git a/app/code/Magento/Sitemap/Model/Sitemap.php b/app/code/Magento/Sitemap/Model/Sitemap.php index ffc884eef4af30737b8b567b63bca488a9c7ad03..165f9dd20202010b667eefd25032a6b0e1f5e6e0 100644 --- a/app/code/Magento/Sitemap/Model/Sitemap.php +++ b/app/code/Magento/Sitemap/Model/Sitemap.php @@ -160,7 +160,7 @@ class Sitemap extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\App\RequestInterface $request * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -178,7 +178,7 @@ class Sitemap extends \Magento\Framework\Model\AbstractModel \Magento\Framework\App\RequestInterface $request, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_escaper = $escaper; diff --git a/app/code/Magento/Sitemap/composer.json b/app/code/Magento/Sitemap/composer.json index 61cd79f59cd6e83621d539e38a7a7d2ceb61fb05..7c7137e8db82477d6c3ded19a28dd6969b68fc42 100644 --- a/app/code/Magento/Sitemap/composer.json +++ b/app/code/Magento/Sitemap/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-cms": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-catalog-url-rewrite": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-cms": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-catalog-url-rewrite": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Store/Model/Group.php b/app/code/Magento/Store/Model/Group.php index 244011cbe86fddf93debc63765950b91856fe851..232f9b7bb65664389badaa4ff2f1a94d18185044 100644 --- a/app/code/Magento/Store/Model/Group.php +++ b/app/code/Magento/Store/Model/Group.php @@ -101,7 +101,7 @@ class Group extends \Magento\Framework\Model\AbstractModel implements \Magento\F * @param \Magento\Store\Model\Store $store * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -111,7 +111,7 @@ class Group extends \Magento\Framework\Model\AbstractModel implements \Magento\F \Magento\Store\Model\Resource\Store\CollectionFactory $storeListFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_configDataResource = $configDataResource; diff --git a/app/code/Magento/Store/Model/Resource/Website.php b/app/code/Magento/Store/Model/Resource/Website.php index 4d1c4750c44bb9d5084904f6c1a3fa4db2c994df..af8a3789b3ba9a8cf254c0c275cf3f248307f40d 100644 --- a/app/code/Magento/Store/Model/Resource/Website.php +++ b/app/code/Magento/Store/Model/Resource/Website.php @@ -46,7 +46,8 @@ class Website extends \Magento\Framework\Model\Resource\Db\AbstractDb if (!preg_match('/^[a-z]+[a-z0-9_]*$/', $object->getCode())) { throw new \Magento\Framework\Exception\LocalizedException( __( - 'Website code may only contain letters (a-z), numbers (0-9) or underscore(_), the first character must be a letter' + 'Website code may only contain letters (a-z), numbers (0-9) or underscore (_),' + . ' and the first character must be a letter.' ) ); } diff --git a/app/code/Magento/Store/Model/Store.php b/app/code/Magento/Store/Model/Store.php index 494d1c129254154208d81e6956d72027003f9dc4..38aec13e895ef256fa987399445e5f7389d5bd70 100644 --- a/app/code/Magento/Store/Model/Store.php +++ b/app/code/Magento/Store/Model/Store.php @@ -321,7 +321,7 @@ class Store extends AbstractModel implements * @param \Magento\Framework\Session\SessionManagerInterface $session * @param \Magento\Directory\Model\CurrencyFactory $currencyFactory * @param string $currencyInstalled - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param bool $isCustomEntryPoint * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -345,7 +345,7 @@ class Store extends AbstractModel implements \Magento\Framework\Session\SessionManagerInterface $session, \Magento\Directory\Model\CurrencyFactory $currencyFactory, $currencyInstalled, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, $isCustomEntryPoint = false, array $data = [] ) { @@ -434,8 +434,8 @@ class Store extends AbstractModel implements $storeCodeRule = new \Zend_Validate_Regex('/^[a-z]+[a-z0-9_]*$/'); $storeCodeRule->setMessage( __( - 'The store code may contain only letters (a-z), numbers (0-9) or underscore(_),' - . ' the first character must be a letter' + 'The store code may contain only letters (a-z), numbers (0-9) or underscore (_),' + . ' and the first character must be a letter.' ), \Zend_Validate_Regex::NOT_MATCH ); diff --git a/app/code/Magento/Store/Model/Website.php b/app/code/Magento/Store/Model/Website.php index d8cd13d963ae84379d0d31b13f1d7939c672d042..ec75da1a5b58c1e4c9c365238bd41e9fc4612289 100644 --- a/app/code/Magento/Store/Model/Website.php +++ b/app/code/Magento/Store/Model/Website.php @@ -175,7 +175,7 @@ class Website extends \Magento\Framework\Model\AbstractModel implements * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Directory\Model\CurrencyFactory $currencyFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -190,7 +190,7 @@ class Website extends \Magento\Framework\Model\AbstractModel implements \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Directory\Model\CurrencyFactory $currencyFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct($context, $registry, $resource, $resourceCollection, $data); diff --git a/app/code/Magento/Store/composer.json b/app/code/Magento/Store/composer.json index 8338ae0b224b25d8b1f0e987494555a73243d802..e8a224d7a443669cfe35054a4ebb9af15f6138fe 100644 --- a/app/code/Magento/Store/composer.json +++ b/app/code/Magento/Store/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-directory": "0.74.0-beta10", - "magento/module-ui": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-directory": "0.74.0-beta13", + "magento/module-ui": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Tax/Block/Item/Price/Renderer.php b/app/code/Magento/Tax/Block/Item/Price/Renderer.php index 9eb8842947651ca8f3d619c6de91ae949da6a83b..2fa880d4b2305a651161c133bf36d9f9165e9264 100644 --- a/app/code/Magento/Tax/Block/Item/Price/Renderer.php +++ b/app/code/Magento/Tax/Block/Item/Price/Renderer.php @@ -224,7 +224,7 @@ class Renderer extends \Magento\Framework\View\Element\Template $totalAmount = $item->getRowTotal() - $item->getDiscountAmount() + $item->getTaxAmount() - + $item->getHiddenTaxAmount(); + + $item->getDiscountTaxCompensationAmount(); return $totalAmount; } @@ -240,7 +240,7 @@ class Renderer extends \Magento\Framework\View\Element\Template $totalAmount = $item->getBaseRowTotal() - $item->getBaseDiscountAmount() + $item->getBaseTaxAmount() - + $item->getBaseHiddenTaxAmount(); + + $item->getBaseDiscountTaxCompensationAmount(); return $totalAmount; } diff --git a/app/code/Magento/Tax/Block/Sales/Order/Tax.php b/app/code/Magento/Tax/Block/Sales/Order/Tax.php index 86737961b60e2409050ec30a2da3d872958de441..6bf91735a92984a4f57b482e639eb98a26edd6df 100644 --- a/app/code/Magento/Tax/Block/Sales/Order/Tax.php +++ b/app/code/Magento/Tax/Block/Sales/Order/Tax.php @@ -143,8 +143,8 @@ class Tax extends \Magento\Framework\View\Element\Template if ($this->_source instanceof Order) { // Adjust for the discount tax compensation foreach ($this->_source->getAllItems() as $item) { - $subtotalIncl += $item->getHiddenTaxAmount(); - $baseSubtotalIncl += $item->getBaseHiddenTaxAmount(); + $subtotalIncl += $item->getDiscountTaxCompensationAmount(); + $baseSubtotalIncl += $item->getBaseDiscountTaxCompensationAmount(); } } } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxDelete.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxDelete.php index 7d5e8285ebbe6792357da00fbf158182051e69fc..5f58a4147aceb7bc992061f49bd8bc3f95e55dae 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxDelete.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxDelete.php @@ -26,7 +26,7 @@ class AjaxDelete extends \Magento\Tax\Controller\Adminhtml\Rate } catch (\Exception $e) { $responseContent = [ 'success' => false, - 'error_message' => __('An error occurred while deleting this tax rate.') + 'error_message' => __('We can\'t delete this tax rate right now.') ]; } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxSave.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxSave.php index 32ba0758fbd58b291e036ec525b06c6c3c3242c4..ab4fdf712f130a13f652ca5f37e609b997d85a87 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxSave.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/AjaxSave.php @@ -38,7 +38,7 @@ class AjaxSave extends \Magento\Tax\Controller\Adminhtml\Rate } catch (\Exception $e) { $responseContent = [ 'success' => false, - 'error_message' => __('Something went wrong saving this rate.'), + 'error_message' => __('We can\'t save this rate right now.'), 'tax_calculation_rate_id' => '', 'code' => '', ]; diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Delete.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Delete.php index 9ee9be000e87c91ed034f8158df818bd74fa1897..52890b87ae086eb997a57d9d14a2ec6c5029afe4 100755 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Delete.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Delete.php @@ -24,11 +24,11 @@ class Delete extends \Magento\Tax\Controller\Adminhtml\Rate try { $this->_taxRateRepository->deleteById($rateId); - $this->messageManager->addSuccess(__('The tax rate has been deleted.')); + $this->messageManager->addSuccess(__('You deleted the tax rate.')); return $resultRedirect->setPath("*/*/"); } catch (NoSuchEntityException $e) { $this->messageManager->addError( - __('Something went wrong deleting this rate because of an incorrect rate ID.') + __('We can\'t delete this rate because of an incorrect rate ID.') ); return $resultRedirect->setPath("tax/*/"); } diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Save.php b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Save.php index 36dbcc284eabb831c206477b1da004c886686429..442940fdfc5eab10131966b7e5814f76080cd553 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rate/Save.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rate/Save.php @@ -35,7 +35,7 @@ class Save extends \Magento\Tax\Controller\Adminhtml\Rate $taxData = $this->_taxRateConverter->populateTaxRateData($ratePost); $this->_taxRateRepository->save($taxData); - $this->messageManager->addSuccess(__('The tax rate has been saved.')); + $this->messageManager->addSuccess(__('You saved the tax rate.')); return $resultRedirect->setPath('*/*/'); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->_objectManager->get('Magento\Backend\Model\Session')->setFormData($ratePost); diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Rule/Save.php b/app/code/Magento/Tax/Controller/Adminhtml/Rule/Save.php index fdcaa2f15c127540fc9f07713b2ec3dc17da8a1d..27e75cf819b06027bbe18007d4bea1a53ed06efc 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Rule/Save.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Rule/Save.php @@ -24,7 +24,7 @@ class Save extends \Magento\Tax\Controller\Adminhtml\Rule try { $taxRule = $this->ruleService->save($taxRule); - $this->messageManager->addSuccess(__('The tax rule has been saved.')); + $this->messageManager->addSuccess(__('You saved the tax rule.')); if ($this->getRequest()->getParam('back')) { return $resultRedirect->setPath('tax/*/edit', ['rule' => $taxRule->getId()]); @@ -33,7 +33,7 @@ class Save extends \Magento\Tax\Controller\Adminhtml\Rule } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { - $this->messageManager->addError(__('Something went wrong saving this tax rule.')); + $this->messageManager->addError(__('We can\'t save this tax rule right now.')); } $this->_objectManager->get('Magento\Backend\Model\Session')->setRuleData($postData); diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxDelete.php b/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxDelete.php index 20e413ed5e78f886d9fbb4be3b8562c1249bc022..8e5e003872d7d6e345fd05739f1e3d044c3af0eb 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxDelete.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxDelete.php @@ -26,7 +26,7 @@ class AjaxDelete extends \Magento\Tax\Controller\Adminhtml\Tax } catch (\Exception $e) { $responseContent = [ 'success' => false, - 'error_message' => __('Something went wrong deleting this tax class.') + 'error_message' => __('We can\'t delete this tax class right now.') ]; } /** @var \Magento\Framework\Controller\Result\Json $resultJson */ diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxSave.php b/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxSave.php index b8f72a7fa6d439e9849df9c4c81c57c2e8655931..68527988b903bc916989bc15ef5be97c269cd597 100644 --- a/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxSave.php +++ b/app/code/Magento/Tax/Controller/Adminhtml/Tax/AjaxSave.php @@ -42,7 +42,7 @@ class AjaxSave extends \Magento\Tax\Controller\Adminhtml\Tax } catch (\Exception $e) { $responseContent = [ 'success' => false, - 'error_message' => __('Something went wrong saving this tax class.'), + 'error_message' => __('We can\'t save this tax class right now.'), 'class_id' => '', 'class_name' => '', ]; diff --git a/app/code/Magento/Tax/Helper/Data.php b/app/code/Magento/Tax/Helper/Data.php index c1f0f8d96ef4f5251231bd2d9a0386ee2249d517..56ab6d4541a1dc97038a49134b4b60efde235d18 100644 --- a/app/code/Magento/Tax/Helper/Data.php +++ b/app/code/Magento/Tax/Helper/Data.php @@ -126,7 +126,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper /** * @param \Magento\Framework\App\Helper\Context $context - * @param \Magento\Framework\Json\Helper\Data $jsonHelper + * @param \Magento\Framework\Json\Helper\Data $jsonHelper * @param \Magento\Framework\Registry $coreRegistry * @param Config $taxConfig * @param \Magento\Store\Model\StoreManagerInterface $storeManager @@ -811,4 +811,24 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper return $taxClassAmount; } + + /** + * Check whether display price is affected by different tax rates + * + * @param null|int|string|Store $store + * @return bool + */ + public function isCatalogPriceDisplayAffectedByTax($store = null) + { + if ($this->displayBothPrices($store)) { + return true; + } + + $priceInclTax = $this->priceIncludesTax($store); + if ($priceInclTax) { + return ($this->isCrossBorderTradeEnabled($store) xor $this->displayPriceIncludingTax()); + } else { + return $this->displayPriceIncludingTax(); + } + } } diff --git a/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php b/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php new file mode 100644 index 0000000000000000000000000000000000000000..0d5f9de2e47c25c3261c4322fe94226c12058b70 --- /dev/null +++ b/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php @@ -0,0 +1,111 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Tax\Model\App\Action; + +use Magento\Customer\Model\Context; +use Magento\Customer\Model\GroupManagement; + +/** + * Class ContextPlugin + */ +class ContextPlugin +{ + /** + * @var \Magento\Customer\Model\Session + */ + protected $customerSession; + + /** + * @var \Magento\Framework\App\Http\Context + */ + protected $httpContext; + + /** + * @var \Magento\Tax\Helper\Data + */ + protected $taxHelper; + + /** + * @var \Magento\Tax\Model\Calculation\Proxy + */ + protected $taxCalculation; + + /** + * Module manager + * + * @var \Magento\Framework\Module\Manager + */ + private $moduleManager; + + /** + * Cache config + * + * @var \Magento\PageCache\Model\Config + */ + private $cacheConfig; + + /** + * @param \Magento\Customer\Model\Session $customerSession + * @param \Magento\Framework\App\Http\Context $httpContext + * @param \Magento\Tax\Model\Calculation\Proxy $calculation + * @param \Magento\Tax\Helper\Data $taxHelper + * @param \Magento\Framework\Module\Manager $moduleManager + * @param \Magento\PageCache\Model\Config $cacheConfig + */ + public function __construct( + \Magento\Customer\Model\Session $customerSession, + \Magento\Framework\App\Http\Context $httpContext, + \Magento\Tax\Model\Calculation\Proxy $calculation, + \Magento\Tax\Helper\Data $taxHelper, + \Magento\Framework\Module\Manager $moduleManager, + \Magento\PageCache\Model\Config $cacheConfig + ) { + $this->customerSession = $customerSession; + $this->httpContext = $httpContext; + $this->taxCalculation = $calculation; + $this->taxHelper = $taxHelper; + $this->moduleManager = $moduleManager; + $this->cacheConfig = $cacheConfig; + } + + /** + * @param \Magento\Framework\App\Action\Action $subject + * @param callable $proceed + * @param \Magento\Framework\App\RequestInterface $request + * @return mixed + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function aroundDispatch( + \Magento\Framework\App\Action\Action $subject, + \Closure $proceed, + \Magento\Framework\App\RequestInterface $request + ) { + if (!$this->moduleManager->isEnabled('Magento_PageCache') || + !$this->cacheConfig->isEnabled() || + !$this->taxHelper->isCatalogPriceDisplayAffectedByTax()) { + return $proceed($request); + } + + $defaultBillingAddress = $this->customerSession->getDefaultTaxBillingAddress(); + $defaultShippingAddress = $this->customerSession->getDefaultTaxShippingAddress(); + $customerTaxClassId = $this->customerSession->getCustomerTaxClassId(); + + if (!empty($defaultBillingAddress) || !empty($defaultShippingAddress)) { + $taxRates = $this->taxCalculation->getTaxRates( + $defaultBillingAddress, + $defaultShippingAddress, + $customerTaxClassId + ); + $this->httpContext->setValue( + 'tax_rates', + $taxRates, + 0 + ); + } + return $proceed($request); + } +} diff --git a/app/code/Magento/Tax/Model/Calculation.php b/app/code/Magento/Tax/Model/Calculation.php old mode 100644 new mode 100755 index 611d44d15cec186cba797393380fc0a6745c8d9b..3de896077dc99e77a2ccce1d97b24b042a9414bf --- a/app/code/Magento/Tax/Model/Calculation.php +++ b/app/code/Magento/Tax/Model/Calculation.php @@ -14,6 +14,9 @@ use Magento\Customer\Api\GroupManagementInterface as CustomerGroupManagement; use Magento\Customer\Api\GroupRepositoryInterface as CustomerGroupRepository; use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository; use Magento\Customer\Api\Data\AddressInterface as CustomerAddress; +use Magento\Framework\Api\FilterBuilder; +use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Tax\Api\TaxClassRepositoryInterface; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Tax\Model\Config; @@ -165,6 +168,27 @@ class Calculation extends \Magento\Framework\Model\AbstractModel */ protected $priceCurrency; + /** + * Filter Builder + * + * @var FilterBuilder + */ + protected $filterBuilder; + + /** + * Search Criteria Builder + * + * @var SearchCriteriaBuilder + */ + protected $searchCriteriaBuilder; + + /** + * Tax Class Repository + * + * @var TaxClassRepositoryInterface + */ + protected $taxClassRepository; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -180,7 +204,10 @@ class Calculation extends \Magento\Framework\Model\AbstractModel * @param CustomerGroupRepository $customerGroupRepository * @param CustomerRepository $customerRepository * @param PriceCurrencyInterface $priceCurrency - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param SearchCriteriaBuilder $searchCriteriaBuilder + * @param FilterBuilder $filterBuilder + * @param TaxClassRepositoryInterface $taxClassRepository + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -199,7 +226,10 @@ class Calculation extends \Magento\Framework\Model\AbstractModel CustomerGroupRepository $customerGroupRepository, CustomerRepository $customerRepository, PriceCurrencyInterface $priceCurrency, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + SearchCriteriaBuilder $searchCriteriaBuilder, + FilterBuilder $filterBuilder, + TaxClassRepositoryInterface $taxClassRepository, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_scopeConfig = $scopeConfig; @@ -213,6 +243,9 @@ class Calculation extends \Magento\Framework\Model\AbstractModel $this->customerGroupRepository = $customerGroupRepository; $this->customerRepository = $customerRepository; $this->priceCurrency = $priceCurrency; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->filterBuilder = $filterBuilder; + $this->taxClassRepository = $taxClassRepository; parent::__construct($context, $registry, $resource, $resourceCollection, $data); } @@ -361,7 +394,6 @@ class Calculation extends \Magento\Framework\Model\AbstractModel } elseif (is_numeric($store)) { $key = $store . '|'; } - $key .= $request->getProductClassId() . '|' . $request->getCustomerClassId() . '|' . $request->getCountryId() . '|' @@ -647,4 +679,39 @@ class Calculation extends \Magento\Framework\Model\AbstractModel { return $this->priceCurrency->round($price); } + + /** + * @param array $billingAddress + * @param array $shippingAddress + * @param int $customerTaxClassId + * @return array + */ + public function getTaxRates($billingAddress, $shippingAddress, $customerTaxClassId) + { + $billingAddressObj = null; + $shippingAddressObj = null; + if (!empty($billingAddress)) { + $billingAddressObj = new \Magento\Framework\Object($billingAddress); + } + if (!empty($shippingAddress)) { + $shippingAddressObj = new \Magento\Framework\Object($shippingAddress); + } + $rateRequest = $this->getRateRequest($shippingAddressObj, $billingAddressObj, $customerTaxClassId); + + $searchCriteria = $this->searchCriteriaBuilder->addFilter( + [$this->filterBuilder->setField(ClassModel::KEY_TYPE) + ->setValue(\Magento\Tax\Api\TaxClassManagementInterface::TYPE_PRODUCT) + ->create()] + )->create(); + $ids = $this->taxClassRepository->getList($searchCriteria)->getItems(); + + $productRates = []; + $idKeys = array_keys($ids); + foreach ($idKeys as $idKey) { + $rateRequest->setProductClassId($idKey); + $rate = $this->getRate($rateRequest); + $productRates[$idKey] = $rate; + } + return $productRates; + } } diff --git a/app/code/Magento/Tax/Model/Calculation/Rate.php b/app/code/Magento/Tax/Model/Calculation/Rate.php index fae528a7d943f8b48b5023d3aaf2ad468a62bb98..cfdb536af25c203245c55c3793ba6cfd6c5c827a 100644 --- a/app/code/Magento/Tax/Model/Calculation/Rate.php +++ b/app/code/Magento/Tax/Model/Calculation/Rate.php @@ -73,7 +73,7 @@ class Rate extends \Magento\Framework\Model\AbstractExtensibleModel implements T * @param Rate\TitleFactory $taxTitleFactory * @param Region $directoryRegion * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -86,7 +86,7 @@ class Rate extends \Magento\Framework\Model\AbstractExtensibleModel implements T \Magento\Tax\Model\Calculation\Rate\TitleFactory $taxTitleFactory, Region $directoryRegion, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_regionFactory = $regionFactory; @@ -132,13 +132,13 @@ class Rate extends \Magento\Framework\Model\AbstractExtensibleModel implements T if ($isEmptyValues || $isWrongRange) { throw new \Magento\Framework\Exception\LocalizedException( - __('Please fill all required fields with valid information.') + __('Make sure all required information is valid.') ); } if (!is_numeric($this->getRate()) || $this->getRate() < 0) { throw new \Magento\Framework\Exception\LocalizedException( - __('Rate Percent should be a positive number.') + __('The Rate Percent should be a positive number.') ); } @@ -152,7 +152,7 @@ class Rate extends \Magento\Framework\Model\AbstractExtensibleModel implements T if (!is_numeric($zipFrom) || !is_numeric($zipTo) || $zipFrom < 0 || $zipTo < 0) { throw new \Magento\Framework\Exception\LocalizedException( - __('Zip code should not contain characters other than digits.') + __('Use digits only for the zip code.') ); } diff --git a/app/code/Magento/Tax/Model/Calculation/Rule.php b/app/code/Magento/Tax/Model/Calculation/Rule.php index dc7e0cfac6f2c4932e6c1515b277483e78e88a7c..0953adde3d24964e7c11855b2095e0189e983fdc 100644 --- a/app/code/Magento/Tax/Model/Calculation/Rule.php +++ b/app/code/Magento/Tax/Model/Calculation/Rule.php @@ -71,7 +71,7 @@ class Rule extends \Magento\Framework\Model\AbstractExtensibleModel implements T * @param \Magento\Tax\Model\Calculation $calculation * @param Rule\Validator $validator * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -84,7 +84,7 @@ class Rule extends \Magento\Framework\Model\AbstractExtensibleModel implements T \Magento\Tax\Model\Calculation $calculation, \Magento\Tax\Model\Calculation\Rule\Validator $validator, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_calculation = $calculation; diff --git a/app/code/Magento/Tax/Model/ClassModel.php b/app/code/Magento/Tax/Model/ClassModel.php index 610527d58eb625ed32510e99dabbb11d58af3bc8..69a220c6bcec6745f45e93e9986f765d819e77d1 100644 --- a/app/code/Magento/Tax/Model/ClassModel.php +++ b/app/code/Magento/Tax/Model/ClassModel.php @@ -49,7 +49,7 @@ class ClassModel extends \Magento\Framework\Model\AbstractExtensibleModel implem * @param AttributeValueFactory $customAttributeFactory * @param TaxClass\Factory $classFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -59,7 +59,7 @@ class ClassModel extends \Magento\Framework\Model\AbstractExtensibleModel implem AttributeValueFactory $customAttributeFactory, \Magento\Tax\Model\TaxClass\Factory $classFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { parent::__construct( diff --git a/app/code/Magento/Tax/Model/Config/Notification.php b/app/code/Magento/Tax/Model/Config/Notification.php index f4b395a290856cf26c36fae743ac7a3ce9797c9b..2bcf7f1ad27ecb3ae149c19e82f798dad0a476bf 100644 --- a/app/code/Magento/Tax/Model/Config/Notification.php +++ b/app/code/Magento/Tax/Model/Config/Notification.php @@ -23,7 +23,7 @@ class Notification extends \Magento\Framework\App\Config\Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Config\Model\Resource\Config $resourceConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -32,7 +32,7 @@ class Notification extends \Magento\Framework\App\Config\Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Config\Model\Resource\Config $resourceConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->resourceConfig = $resourceConfig; diff --git a/app/code/Magento/Tax/Model/Config/TaxClass.php b/app/code/Magento/Tax/Model/Config/TaxClass.php index f3472fbfdf49bc6f985ef92505a348346e8e7bbd..96846a9c909200db1f9ebd8107a9e3a938ec3ac0 100644 --- a/app/code/Magento/Tax/Model/Config/TaxClass.php +++ b/app/code/Magento/Tax/Model/Config/TaxClass.php @@ -27,7 +27,7 @@ class TaxClass extends \Magento\Framework\App\Config\Value * @param \Magento\Config\Model\Resource\Config $resourceConfig * @param \Magento\Eav\Model\Entity\AttributeFactory $attributeFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -37,7 +37,7 @@ class TaxClass extends \Magento\Framework\App\Config\Value \Magento\Config\Model\Resource\Config $resourceConfig, \Magento\Eav\Model\Entity\AttributeFactory $attributeFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->resourceConfig = $resourceConfig; diff --git a/app/code/Magento/Tax/Model/Layout/DepersonalizePlugin.php b/app/code/Magento/Tax/Model/Layout/DepersonalizePlugin.php new file mode 100644 index 0000000000000000000000000000000000000000..d9b8f5b593c7b9918e062fe95099366d7f1829c8 --- /dev/null +++ b/app/code/Magento/Tax/Model/Layout/DepersonalizePlugin.php @@ -0,0 +1,85 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Tax\Model\Layout; + +use Magento\PageCache\Model\DepersonalizeChecker; + +/** + * Class DepersonalizePlugin + */ +class DepersonalizePlugin +{ + /** + * @var DepersonalizeChecker + */ + protected $depersonalizeChecker; + + /** + * @var \Magento\Customer\Model\Session + */ + protected $customerSession; + + /** + * @var array + */ + protected $defaultTaxShippingAddress; + + /** + * @var array + */ + protected $defaultTaxBillingAddress; + + /** + * @var int + */ + protected $customerTaxClassId; + + /** + * @param DepersonalizeChecker $depersonalizeChecker + * @param \Magento\Customer\Model\Session $customerSession + */ + public function __construct( + DepersonalizeChecker $depersonalizeChecker, + \Magento\Customer\Model\Session $customerSession + ) { + $this->customerSession = $customerSession; + $this->depersonalizeChecker = $depersonalizeChecker; + } + + /** + * Before generate Xml + * + * @param \Magento\Framework\View\LayoutInterface $subject + * @return array + */ + public function beforeGenerateXml(\Magento\Framework\View\LayoutInterface $subject) + { + if ($this->depersonalizeChecker->checkIfDepersonalize($subject)) { + $this->defaultTaxBillingAddress = $this->customerSession->getDefaultTaxBillingAddress(); + $this->defaultTaxShippingAddress = $this->customerSession->getDefaultTaxShippingAddress(); + $this->customerTaxClassId = $this->customerSession->getCustomerTaxClassId(); + } + return []; + } + + /** + * After generate Xml + * + * @param \Magento\Framework\View\LayoutInterface $subject + * @param \Magento\Framework\View\LayoutInterface $result + * @return \Magento\Framework\View\LayoutInterface + */ + public function afterGenerateXml(\Magento\Framework\View\LayoutInterface $subject, $result) + { + if ($this->depersonalizeChecker->checkIfDepersonalize($subject)) { + $this->customerSession->setDefaultTaxBillingAddress($this->defaultTaxBillingAddress); + $this->customerSession->setDefaultTaxShippingAddress($this->defaultTaxShippingAddress); + $this->customerSession->setCustomerTaxClassId($this->customerTaxClassId); + } + return $result; + } +} diff --git a/app/code/Magento/Tax/Model/Observer/Session.php b/app/code/Magento/Tax/Model/Observer/Session.php new file mode 100755 index 0000000000000000000000000000000000000000..fc1b004a54b945481a1922364f12d015c758117a --- /dev/null +++ b/app/code/Magento/Tax/Model/Observer/Session.php @@ -0,0 +1,152 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + + +/** + * Customer Session Event Observer + */ +namespace Magento\Tax\Model\Observer; + +class Session +{ + /** + * @var \Magento\Customer\Model\Session + */ + protected $customerSession; + + /** + * @var \Magento\Tax\Helper\Data + */ + protected $taxHelper; + + /** + * @var \Magento\Customer\Api\GroupRepositoryInterface + */ + protected $groupRepository; + + /** + * Module manager + * + * @var \Magento\Framework\Module\Manager + */ + private $moduleManager; + + /** + * Cache config + * + * @var \Magento\PageCache\Model\Config + */ + private $cacheConfig; + + /** + * @param \Magento\Customer\Api\GroupRepositoryInterface $groupRepository + * @param \Magento\Customer\Model\Session $customerSession + * @param \Magento\Tax\Helper\Data $taxHelper + * @param \Magento\Framework\Module\Manager $moduleManager + * @param \Magento\PageCache\Model\Config $cacheConfig + */ + public function __construct( + \Magento\Customer\Api\GroupRepositoryInterface $groupRepository, + \Magento\Customer\Model\Session $customerSession, + \Magento\Tax\Helper\Data $taxHelper, + \Magento\Framework\Module\Manager $moduleManager, + \Magento\PageCache\Model\Config $cacheConfig + ) { + $this->groupRepository = $groupRepository; + $this->customerSession = $customerSession; + $this->taxHelper = $taxHelper; + $this->moduleManager = $moduleManager; + $this->cacheConfig = $cacheConfig; + } + + /** + * @param \Magento\Framework\Event\Observer $observer + * @return void + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function customerLoggedIn(\Magento\Framework\Event\Observer $observer) + { + if ($this->moduleManager->isEnabled('Magento_PageCache') && $this->cacheConfig->isEnabled() && + $this->taxHelper->isCatalogPriceDisplayAffectedByTax()) { + /** @var \Magento\Customer\Model\Data\Customer $customer */ + $customer = $observer->getData('customer'); + $customerGroupId = $customer->getGroupId(); + $customerGroup = $this->groupRepository->getById($customerGroupId); + $customerTaxClassId = $customerGroup->getTaxClassId(); + $this->customerSession->setCustomerTaxClassId($customerTaxClassId); + + /** @var \Magento\Customer\Api\Data\AddressInterface[] $addresses */ + $addresses = $customer->getAddresses(); + if (isset($addresses)) { + $defaultShippingFound = false; + $defaultBillingFound = false; + foreach ($addresses as $address) { + if ($address->isDefaultBilling()) { + $defaultBillingFound = true; + $this->customerSession->setDefaultTaxBillingAddress( + [ + 'country_id' => $address->getCountryId(), + 'region_id' => $address->getRegion() ? $address->getRegion()->getRegionId() : null, + 'postcode' => $address->getPostcode(), + ] + ); + } + if ($address->isDefaultShipping()) { + $defaultShippingFound = true; + $this->customerSession->setDefaultTaxShippingAddress( + [ + 'country_id' => $address->getCountryId(), + 'region_id' => $address->getRegion() ? $address->getRegion()->getRegionId() : null, + 'postcode' => $address->getPostcode(), + ] + ); + } + if ($defaultShippingFound && $defaultBillingFound) { + break; + } + } + } + } + } + + /** + * Address after save event handler + * + * @param \Magento\Framework\Event\Observer $observer + * @return void + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + public function afterAddressSave($observer) + { + if ($this->moduleManager->isEnabled('Magento_PageCache') && $this->cacheConfig->isEnabled() && + $this->taxHelper->isCatalogPriceDisplayAffectedByTax()) { + /** @var $customerAddress Address */ + $address = $observer->getCustomerAddress(); + + // Check if the address is either the default billing, shipping, or both + if ($address->getIsPrimaryBilling() || $address->getIsDefaultBilling()) { + $this->customerSession->setDefaultTaxBillingAddress( + [ + 'country_id' => $address->getCountryId(), + 'region_id' => $address->getRegion() ? $address->getRegionId() : null, + 'postcode' => $address->getPostcode(), + ] + ); + } + + if ($address->getIsPrimaryShipping() || $address->getIsDefaultShipping()) { + $this->customerSession->setDefaultTaxShippingAddress( + [ + 'country_id' => $address->getCountryId(), + 'region_id' => $address->getRegion() ? $address->getRegionId() : null, + 'postcode' => $address->getPostcode(), + ] + ); + } + } + } +} diff --git a/app/code/Magento/Tax/Model/Sales/Order/Tax.php b/app/code/Magento/Tax/Model/Sales/Order/Tax.php index 3b67f9222800f2f55585bff22409966003799d2e..e66460936a4b9763475c508d93788b167b4530c7 100644 --- a/app/code/Magento/Tax/Model/Sales/Order/Tax.php +++ b/app/code/Magento/Tax/Model/Sales/Order/Tax.php @@ -18,8 +18,6 @@ namespace Magento\Tax\Model\Sales\Order; * @method \Magento\Tax\Model\Sales\Order\Tax setProcess(int $value) * @method float getBaseRealAmount() * @method \Magento\Tax\Model\Sales\Order\Tax setBaseRealAmount(float $value) - * @method int getHidden() - * @method \Magento\Tax\Model\Sales\Order\Tax setHidden(int $value) * @codeCoverageIgnore */ class Tax extends \Magento\Framework\Model\AbstractExtensibleModel implements diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php index 3e7e440ff90955a66acf2d7d0415ba17c3db688d..740004bb12783f51d12235152b7f1cac85ac074e 100644 --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php @@ -469,7 +469,7 @@ class CommonTaxCollector extends AbstractTotal /** * Process product items in the quote. * Set the following aggregated values in the quote object: - * subtotal, subtotalInclTax, tax, hidden_tax, + * subtotal, subtotalInclTax, tax, discount_tax_compensation, * * @param QuoteAddress $address * @param array $itemTaxDetails @@ -484,7 +484,7 @@ class CommonTaxCollector extends AbstractTotal } $subtotal = $baseSubtotal = 0; - $hiddenTax = $baseHiddenTax = 0; + $discountTaxCompensation = $baseDiscountTaxCompensation = 0; $tax = $baseTax = 0; $subtotalInclTax = $baseSubtotalInclTax = 0; @@ -503,8 +503,8 @@ class CommonTaxCollector extends AbstractTotal } $subtotal += $taxDetail->getRowTotal(); $baseSubtotal += $baseTaxDetail->getRowTotal(); - $hiddenTax += $taxDetail->getDiscountTaxCompensationAmount(); - $baseHiddenTax += $baseTaxDetail->getDiscountTaxCompensationAmount(); + $discountTaxCompensation += $taxDetail->getDiscountTaxCompensationAmount(); + $baseDiscountTaxCompensation += $baseTaxDetail->getDiscountTaxCompensationAmount(); $tax += $taxDetail->getRowTax(); $baseTax += $baseTaxDetail->getRowTax(); $subtotalInclTax += $taxDetail->getRowTotalInclTax(); @@ -516,8 +516,8 @@ class CommonTaxCollector extends AbstractTotal $address->setBaseTotalAmount('subtotal', $baseSubtotal); $address->setTotalAmount('tax', $tax); $address->setBaseTotalAmount('tax', $baseTax); - $address->setTotalAmount('hidden_tax', $hiddenTax); - $address->setBaseTotalAmount('hidden_tax', $baseHiddenTax); + $address->setTotalAmount('discount_tax_compensation', $discountTaxCompensation); + $address->setBaseTotalAmount('discount_tax_compensation', $baseDiscountTaxCompensation); $address->setSubtotalInclTax($subtotalInclTax); $address->setBaseSubtotalInclTax($baseSubtotalInclTax); @@ -619,7 +619,7 @@ class CommonTaxCollector extends AbstractTotal $quoteItem->setRowTotalInclTax($itemTaxDetails->getRowTotalInclTax()); $quoteItem->setTaxAmount($itemTaxDetails->getRowTax()); $quoteItem->setTaxPercent($itemTaxDetails->getTaxPercent()); - $quoteItem->setHiddenTaxAmount($itemTaxDetails->getDiscountTaxCompensationAmount()); + $quoteItem->setDiscountTaxCompensationAmount($itemTaxDetails->getDiscountTaxCompensationAmount()); $quoteItem->setBasePrice($baseItemTaxDetails->getPrice()); $quoteItem->setBasePriceInclTax($baseItemTaxDetails->getPriceInclTax()); @@ -627,7 +627,7 @@ class CommonTaxCollector extends AbstractTotal $quoteItem->setBaseRowTotalInclTax($baseItemTaxDetails->getRowTotalInclTax()); $quoteItem->setBaseTaxAmount($baseItemTaxDetails->getRowTax()); $quoteItem->setTaxPercent($baseItemTaxDetails->getTaxPercent()); - $quoteItem->setBaseHiddenTaxAmount($baseItemTaxDetails->getDiscountTaxCompensationAmount()); + $quoteItem->setBaseDiscountTaxCompensationAmount($baseItemTaxDetails->getDiscountTaxCompensationAmount()); //Set discount calculation price, this may be needed by discount collector if ($this->_config->discountTax($store)) { @@ -653,8 +653,8 @@ class CommonTaxCollector extends AbstractTotal { $address->setTotalAmount('shipping', $shippingTaxDetails->getRowTotal()); $address->setBaseTotalAmount('shipping', $baseShippingTaxDetails->getRowTotal()); - $address->setTotalAmount('shipping_hidden_tax', $shippingTaxDetails->getDiscountTaxCompensationAmount()); - $address->setBaseTotalAmount('shipping_hidden_tax', $baseShippingTaxDetails->getDiscountTaxCompensationAmount()); + $address->setTotalAmount('shipping_discount_tax_compensation', $shippingTaxDetails->getDiscountTaxCompensationAmount()); + $address->setBaseTotalAmount('shipping_discount_tax_compensation', $baseShippingTaxDetails->getDiscountTaxCompensationAmount()); $address->setShippingInclTax($shippingTaxDetails->getRowTotalInclTax()); $address->setBaseShippingInclTax($baseShippingTaxDetails->getRowTotalInclTax()); diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php index 58202c2dd403f2063ffb5ed6ea8fa9f50c6bbc95..00ba67b0d113bcba4b6fd31838e37a1680cf11e2 100644 --- a/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php +++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/Tax.php @@ -39,11 +39,11 @@ class Tax extends CommonTaxCollector protected $_config; /** - * Hidden taxes array + * Discount tax compensationes array * * @var array */ - protected $_hiddenTaxes = []; + protected $_discountTaxCompensationes = []; /** * Class constructor @@ -137,10 +137,10 @@ class Tax extends CommonTaxCollector $address->setBaseTotalAmount('subtotal', 0); $address->setTotalAmount('tax', 0); $address->setBaseTotalAmount('tax', 0); - $address->setTotalAmount('hidden_tax', 0); - $address->setBaseTotalAmount('hidden_tax', 0); - $address->setTotalAmount('shipping_hidden_tax', 0); - $address->setBaseTotalAmount('shipping_hidden_tax', 0); + $address->setTotalAmount('discount_tax_compensation', 0); + $address->setBaseTotalAmount('discount_tax_compensation', 0); + $address->setTotalAmount('shipping_discount_tax_compensation', 0); + $address->setBaseTotalAmount('shipping_discount_tax_compensation', 0); $address->setSubtotalInclTax(0); $address->setBaseSubtotalInclTax(0); } diff --git a/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php b/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php new file mode 100644 index 0000000000000000000000000000000000000000..66ad1afdbcad98f745caad2d25bc55af4ab53a91 --- /dev/null +++ b/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php @@ -0,0 +1,134 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Tax\Test\Unit\App\Action; + +class ContextPluginTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Tax\Helper\Data + */ + protected $taxHelperMock; + + /** + * @var \Magento\Framework\App\Http\Context + */ + protected $httpContextMock; + + /** + * @var \Magento\Tax\Model\Calculation\Proxy + */ + protected $taxCalculationMock; + + /** + * Module manager + * + * @var \Magento\Framework\Module\Manager + */ + private $moduleManagerMock; + + /** + * Cache config + * + * @var \Magento\PageCache\Model\Config + */ + private $cacheConfigMock; + + /** + * @var \Magento\Tax\Model\App\Action\ContextPlugin + */ + protected $contextPlugin; + + protected function setUp() + { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->taxHelperMock = $this->getMockBuilder('Magento\Tax\Helper\Data') + ->disableOriginalConstructor() + ->getMock(); + + $this->httpContextMock = $this->getMockBuilder('Magento\Framework\App\Http\Context') + ->disableOriginalConstructor() + ->getMock(); + + $this->taxCalculationMock = $this->getMockBuilder('Magento\Tax\Model\Calculation\Proxy') + ->disableOriginalConstructor() + ->getMock(); + + $this->customerSessionMock = $this->getMockBuilder('Magento\Customer\Model\Session') + ->disableOriginalConstructor() + ->setMethods([ + 'getDefaultTaxBillingAddress', 'getDefaultTaxShippingAddress', 'getCustomerTaxClassId' + ]) + ->getMock(); + + $this->moduleManagerMock = $this->getMockBuilder('Magento\Framework\Module\Manager') + ->disableOriginalConstructor() + ->getMock(); + + $this->cacheConfigMock = $this->getMockBuilder('Magento\PageCache\Model\Config') + ->disableOriginalConstructor() + ->getMock(); + + $this->contextPlugin = $this->objectManager->getObject( + 'Magento\Tax\Model\App\Action\ContextPlugin', + [ + 'customerSession' => $this->customerSessionMock, + 'httpContext' => $this->httpContextMock, + 'calculation' => $this->taxCalculationMock, + 'taxHelper' => $this->taxHelperMock, + 'moduleManager' => $this->moduleManagerMock, + 'cacheConfig' => $this->cacheConfigMock + ] + ); + } + + public function testAroundDispatch() + { + $this->moduleManagerMock->expects($this->any()) + ->method('isEnabled') + ->with('Magento_PageCache') + ->willReturn(true); + + $this->cacheConfigMock->expects($this->any()) + ->method('isEnabled') + ->willReturn(true); + + $this->taxHelperMock->expects($this->any()) + ->method('isCatalogPriceDisplayAffectedByTax') + ->willReturn(true); + + $this->customerSessionMock->expects($this->once()) + ->method('getDefaultTaxBillingAddress') + ->willReturn(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]); + $this->customerSessionMock->expects($this->once()) + ->method('getDefaultTaxShippingAddress') + ->willReturn(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]); + $this->customerSessionMock->expects($this->once()) + ->method('getCustomerTaxClassId') + ->willReturn(1); + + $this->taxCalculationMock->expects($this->once()) + ->method('getTaxRates') + ->with( + ['country_id' => 1, 'region_id' => null, 'postcode' => 11111], + ['country_id' => 1, 'region_id' => null, 'postcode' => 11111], + 1 + ) + ->willReturn([]); + + $this->httpContextMock->expects($this->once()) + ->method('setValue') + ->with('tax_rates', [], 0); + + $action = $this->objectManager->getObject('Magento\Framework\App\Action\Action'); + $request = $this->getMock('\Magento\Framework\App\Request\Http', ['getActionName'], [], '', false); + $expectedResult = 'expectedResult'; + $proceed = function ($request) use ($expectedResult) { + return $expectedResult; + }; + $this->contextPlugin->aroundDispatch($action, $proceed, $request); + } +} diff --git a/app/code/Magento/Tax/Test/Unit/Block/Item/Price/RendererTest.php b/app/code/Magento/Tax/Test/Unit/Block/Item/Price/RendererTest.php index b61cf11180a88dd14f634407efc7586fd2d9986b..47fbfd4700b22475907b76d1c1ef34feaf9ef58a 100644 --- a/app/code/Magento/Tax/Test/Unit/Block/Item/Price/RendererTest.php +++ b/app/code/Magento/Tax/Test/Unit/Block/Item/Price/RendererTest.php @@ -366,14 +366,22 @@ class RendererTest extends \PHPUnit_Framework_TestCase { $rowTotal = 100; $taxAmount = 10; - $hiddenTaxAmount = 2; + $discountTaxCompensationAmount = 2; $discountAmount = 20; - $expectedValue = $rowTotal + $taxAmount + $hiddenTaxAmount - $discountAmount; + $expectedValue = $rowTotal + $taxAmount + $discountTaxCompensationAmount - $discountAmount; $itemMock = $this->getMockBuilder('\Magento\Sales\Model\Order\Item') ->disableOriginalConstructor() - ->setMethods(['getRowTotal', 'getTaxAmount', 'getHiddenTaxAmount', 'getDiscountAmount', '__wakeup']) + ->setMethods( + [ + 'getRowTotal', + 'getTaxAmount', + 'getDiscountTaxCompensationAmount', + 'getDiscountAmount', + '__wakeup' + ] + ) ->getMock(); $itemMock->expects($this->once()) @@ -385,8 +393,8 @@ class RendererTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($taxAmount)); $itemMock->expects($this->once()) - ->method('getHiddenTaxAmount') - ->will($this->returnValue($hiddenTaxAmount)); + ->method('getDiscountTaxCompensationAmount') + ->will($this->returnValue($discountTaxCompensationAmount)); $itemMock->expects($this->once()) ->method('getDiscountAmount') @@ -399,7 +407,7 @@ class RendererTest extends \PHPUnit_Framework_TestCase { $baseRowTotal = 100; $baseTaxAmount = 10; - $baseHiddenTaxAmount = 2; + $baseDiscountTaxCompensationAmount = 2; $baseDiscountAmount = 20; $expectedValue = 92; @@ -407,7 +415,13 @@ class RendererTest extends \PHPUnit_Framework_TestCase $itemMock = $this->getMockBuilder('\Magento\Sales\Model\Order\Item') ->disableOriginalConstructor() ->setMethods( - ['getBaseRowTotal', 'getBaseTaxAmount', 'getBaseHiddenTaxAmount', 'getBaseDiscountAmount', '__wakeup'] + [ + 'getBaseRowTotal', + 'getBaseTaxAmount', + 'getBaseDiscountTaxCompensationAmount', + 'getBaseDiscountAmount', + '__wakeup' + ] ) ->getMock(); @@ -420,8 +434,8 @@ class RendererTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($baseTaxAmount)); $itemMock->expects($this->once()) - ->method('getBaseHiddenTaxAmount') - ->will($this->returnValue($baseHiddenTaxAmount)); + ->method('getBaseDiscountTaxCompensationAmount') + ->will($this->returnValue($baseDiscountTaxCompensationAmount)); $itemMock->expects($this->once()) ->method('getBaseDiscountAmount') diff --git a/app/code/Magento/Tax/Test/Unit/Helper/DataTest.php b/app/code/Magento/Tax/Test/Unit/Helper/DataTest.php old mode 100644 new mode 100755 index 557dab57b787955a8778c2776f86a69f55770991..48bf55cbb1054823c512376ce072e15de4523834 --- a/app/code/Magento/Tax/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Tax/Test/Unit/Helper/DataTest.php @@ -9,7 +9,6 @@ namespace Magento\Tax\Test\Unit\Helper; use Magento\Framework\Object as MagentoObject; -use Magento\TestFramework\Event\Magento; /** * Class DataTest @@ -27,6 +26,9 @@ class DataTest extends \PHPUnit_Framework_TestCase /** @var \PHPUnit_Framework_MockObject_MockObject */ protected $priceCurrencyMock; + /** @var \PHPUnit_Framework_MockObject_MockObject */ + protected $taxConfigMock; + public function setUp() { $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); @@ -37,12 +39,16 @@ class DataTest extends \PHPUnit_Framework_TestCase $this->priceCurrencyMock = $this->getMockBuilder('Magento\Framework\Pricing\PriceCurrencyInterface') ->disableOriginalConstructor() ->getMock(); + $this->taxConfigMock = $this->getMockBuilder('Magento\Tax\Model\Config') + ->disableOriginalConstructor() + ->getMock(); $this->helper = $objectManager->getObject( 'Magento\Tax\Helper\Data', [ 'orderTaxManagement' => $this->orderTaxManagementMock, - 'priceCurrency' => $this->priceCurrencyMock + 'priceCurrency' => $this->priceCurrencyMock, + 'taxConfig' => $this->taxConfigMock ] ); } @@ -442,4 +448,61 @@ class DataTest extends \PHPUnit_Framework_TestCase return $data; } + + /** + * @param bool $expected + * @param bool $displayBothPrices + * @param bool $priceIncludesTax + * @param bool $isCrossBorderTradeEnabled + * @param bool $displayPriceIncludingTax + * @dataProvider dataProviderIsCatalogPriceDisplayAffectedByTax + */ + public function testIsCatalogPriceDisplayAffectedByTax($expected, $displayBothPrices, $priceIncludesTax, + $isCrossBorderTradeEnabled, $displayPriceIncludingTax) + { + if ($displayBothPrices == true) { + $this->taxConfigMock->expects($this->at(0)) + ->method('getPriceDisplayType') + ->willReturn(3); + } else { + $this->taxConfigMock->expects($this->at(0)) + ->method('getPriceDisplayType') + ->willReturn(2); + + $this->taxConfigMock->expects($this->any()) + ->method('priceIncludesTax') + ->willReturn($priceIncludesTax); + + $this->taxConfigMock->expects($this->any()) + ->method('crossBorderTradeEnabled') + ->willReturn($isCrossBorderTradeEnabled); + + if ($displayPriceIncludingTax == true) { + $this->taxConfigMock->expects($this->at(3)) + ->method('getPriceDisplayType') + ->willReturn(2); + } else { + $this->taxConfigMock->expects($this->at(2)) + ->method('getPriceDisplayType') + ->willReturn(1); + } + } + + $this->assertSame($expected, $this->helper->isCatalogPriceDisplayAffectedByTax(null)); + } + + /** + * @return array + */ + public function dataProviderIsCatalogPriceDisplayAffectedByTax() + { + return [ + [true , true, false, false, false], + [true , false, true, true, false], + [true , false, true, false, true], + [false , false, true, true, true], + [true , false, false, true, true], + [false , false, false, true, false] + ]; + } } diff --git a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateTest.php b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateTest.php index 49c3b4066dbd3a7a1df1f4e86865c752ace7bcbe..398f627f058ab1f3e0be98dfa53f6ff782e74726 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RateTest.php @@ -49,7 +49,10 @@ class RateTest extends \PHPUnit_Framework_TestCase 'Magento\Tax\Model\Calculation\Rate', ['resource' => $this->resourceMock] ); - $rate->setData($data)->beforeSave(); + foreach ($data as $key => $value) { + $rate->setData($key, $value); + } + $rate->beforeSave(); } /** @@ -61,16 +64,16 @@ class RateTest extends \PHPUnit_Framework_TestCase { return [ 'fill all required fields 1' => [ - 'exceptionMessage' => 'Please fill all required fields with valid information.', + 'exceptionMessage' => 'Make sure all required information is valid.', 'data' => ['zip_is_range' => true, 'zip_from' => '0111', 'zip_to' => '', 'code' => '', 'tax_country_id' => '', 'rate' => '', 'tax_postcode' => '', ], ], 'fill all required fields 2' => [ - 'exceptionMessage' => 'Please fill all required fields with valid information.', + 'exceptionMessage' => 'Make sure all required information is valid.', 'data' => ['zip_is_range' => '', 'zip_from' => '', 'zip_to' => '', 'code' => '', 'tax_country_id' => '', 'rate' => '0.2', 'tax_postcode' => '1234', ], ], 'positive number' => [ - 'exceptionMessage' => 'Rate Percent should be a positive number.', + 'exceptionMessage' => 'The Rate Percent should be a positive number.', 'data' => ['zip_is_range' => '', 'zip_from' => '', 'zip_to' => '', 'code' => 'code', 'tax_country_id' => 'US', 'rate' => '-1', 'tax_postcode' => '1234', ], ], @@ -80,7 +83,7 @@ class RateTest extends \PHPUnit_Framework_TestCase 'code' => 'code', 'tax_country_id' => 'US', 'rate' => '1.1', 'tax_postcode' => '1234', ], ], 'contain characters' => [ - 'exceptionMessage' => 'Zip code should not contain characters other than digits.', + 'exceptionMessage' => 'Use digits only for the zip code.', 'data' => ['zip_is_range' => true, 'zip_from' => 'foo', 'zip_to' => '1234', 'code' => 'code', 'tax_country_id' => 'US', 'rate' => '1.1', 'tax_postcode' => '1234', ], ], diff --git a/app/code/Magento/Tax/Test/Unit/Model/Observer/SessionTest.php b/app/code/Magento/Tax/Test/Unit/Model/Observer/SessionTest.php new file mode 100755 index 0000000000000000000000000000000000000000..8ef95ead2e386d8e95a03ff03d02a76b8350c89b --- /dev/null +++ b/app/code/Magento/Tax/Test/Unit/Model/Observer/SessionTest.php @@ -0,0 +1,197 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Tax\Test\Unit\Model\Observer; + +class SessionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\Event\Observer + */ + protected $observerMock; + + /** + * @var \Magento\Customer\Model\Session + */ + protected $customerSessionMock; + + /** + * @var \Magento\Customer\Model\Resource\GroupRepository + */ + protected $groupRepositoryMock; + + /** + * Module manager + * + * @var \Magento\Framework\Module\Manager + */ + private $moduleManagerMock; + + /** + * Cache config + * + * @var \Magento\PageCache\Model\Config + */ + private $cacheConfigMock; + + /** + * @var \Magento\Tax\Helper\Data + */ + protected $taxHelperMock; + + /** + * @var \Magento\Tax\Model\Observer\Session + */ + protected $session; + + + protected function setUp() + { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->observerMock = $this->getMockBuilder('Magento\Framework\Event\Observer') + ->disableOriginalConstructor() + ->setMethods([ + 'getCustomerAddress', 'getData' + ]) + ->getMock(); + + $this->groupRepositoryMock = $this->getMockBuilder('Magento\Customer\Model\Resource\GroupRepository') + ->disableOriginalConstructor() + ->getMock(); + + $this->customerSessionMock = $this->getMockBuilder('Magento\Customer\Model\Session') + ->disableOriginalConstructor() + ->setMethods([ + 'setCustomerTaxClassId', 'setDefaultTaxBillingAddress', 'setDefaultTaxShippingAddress' + ]) + ->getMock(); + + $this->moduleManagerMock = $this->getMockBuilder('Magento\Framework\Module\Manager') + ->disableOriginalConstructor() + ->getMock(); + + $this->cacheConfigMock = $this->getMockBuilder('Magento\PageCache\Model\Config') + ->disableOriginalConstructor() + ->getMock(); + + $this->taxHelperMock = $this->getMockBuilder('Magento\Tax\Helper\Data') + ->disableOriginalConstructor() + ->getMock(); + + $this->session = $this->objectManager->getObject( + 'Magento\Tax\Model\Observer\Session', + [ + 'groupRepository' => $this->groupRepositoryMock, + 'customerSession' => $this->customerSessionMock, + 'taxHelper' => $this->taxHelperMock, + 'moduleManager' => $this->moduleManagerMock, + 'cacheConfig' => $this->cacheConfigMock + ] + ); + } + + public function testCustomerLoggedIn() + { + $this->moduleManagerMock->expects($this->once()) + ->method('isEnabled') + ->with('Magento_PageCache') + ->willReturn(true); + + $this->cacheConfigMock->expects($this->once()) + ->method('isEnabled') + ->willReturn(true); + + $this->taxHelperMock->expects($this->any()) + ->method('isCatalogPriceDisplayAffectedByTax') + ->willReturn(true); + + $customerMock = $this->getMockBuilder('Magento\Customer\Model\Data\Customer') + ->disableOriginalConstructor() + ->getMock(); + + $this->observerMock->expects($this->once()) + ->method('getData') + ->with('customer') + ->willReturn($customerMock); + + $customerMock->expects($this->once()) + ->method('getGroupId') + ->willReturn(1); + + $customerGroupMock = $this->getMockBuilder('Magento\Customer\Model\Data\Group') + ->disableOriginalConstructor() + ->getMock(); + + $this->groupRepositoryMock->expects($this->once()) + ->method('getById') + ->with(1) + ->willReturn($customerGroupMock); + + $customerGroupMock->expects($this->once()) + ->method('getTaxClassId') + ->willReturn(1); + + $this->customerSessionMock->expects($this->once()) + ->method('setCustomerTaxClassId') + ->with(1); + + $address = $this->objectManager->getObject('Magento\Customer\Model\Data\Address'); + $address->setIsDefaultShipping(true); + $address->setIsDefaultBilling(true); + $address->setCountryId(1); + $address->setPostCode(11111); + + $addresses = [$address]; + $customerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn($addresses); + + $this->customerSessionMock->expects($this->once()) + ->method('setDefaultTaxBillingAddress') + ->with(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]); + $this->customerSessionMock->expects($this->once()) + ->method('setDefaultTaxShippingAddress') + ->with(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]); + + $this->session->customerLoggedIn($this->observerMock); + } + + public function testAfterAddressSave() + { + $this->moduleManagerMock->expects($this->once()) + ->method('isEnabled') + ->with('Magento_PageCache') + ->willReturn(true); + + $this->cacheConfigMock->expects($this->once()) + ->method('isEnabled') + ->willReturn(true); + + $this->taxHelperMock->expects($this->any()) + ->method('isCatalogPriceDisplayAffectedByTax') + ->willReturn(true); + + $address = $this->objectManager->getObject('Magento\Customer\Model\Address'); + $address->setIsDefaultShipping(true); + $address->setIsDefaultBilling(true); + $address->setIsPrimaryBilling(true); + $address->setIsPrimaryShipping(true); + $address->setCountryId(1); + $address->setData('postcode', 11111); + + $this->customerSessionMock->expects($this->once()) + ->method('setDefaultTaxBillingAddress') + ->with(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]); + $this->customerSessionMock->expects($this->once()) + ->method('setDefaultTaxShippingAddress') + ->with(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]); + + $this->observerMock->expects($this->once()) + ->method('getCustomerAddress') + ->willReturn($address); + + $this->session->afterAddressSave($this->observerMock); + } +} diff --git a/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/TaxTest.php b/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/TaxTest.php index 30b6315f2aba6b367264570cea3ec94e7f96b260..fc1f96e4364ab646286fcf1a383df13060542de0 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/TaxTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Sales/Total/Quote/TaxTest.php @@ -695,10 +695,10 @@ class TaxTest extends \PHPUnit_Framework_TestCase $address->setBaseTotalAmount('subtotal', 1); $address->setTotalAmount('tax', 1); $address->setBaseTotalAmount('tax', 1); - $address->setTotalAmount('hidden_tax', 1); - $address->setBaseTotalAmount('hidden_tax', 1); - $address->setTotalAmount('shipping_hidden_tax', 1); - $address->setBaseTotalAmount('shipping_hidden_tax', 1); + $address->setTotalAmount('discount_tax_compensation', 1); + $address->setBaseTotalAmount('discount_tax_compensation', 1); + $address->setTotalAmount('shipping_discount_tax_compensation', 1); + $address->setBaseTotalAmount('shipping_discount_tax_compensation', 1); $address->setSubtotalInclTax(1); $address->setBaseSubtotalInclTax(1); @@ -712,12 +712,12 @@ class TaxTest extends \PHPUnit_Framework_TestCase $this->assertEquals(0, $address->getTotalAmount('subtotal')); $this->assertEquals(0, $address->getTotalAmount('tax')); - $this->assertEquals(0, $address->getTotalAmount('hidden_tax')); - $this->assertEquals(0, $address->getTotalAmount('shipping_hidden_tax')); + $this->assertEquals(0, $address->getTotalAmount('discount_tax_compensation')); + $this->assertEquals(0, $address->getTotalAmount('shipping_discount_tax_compensation')); $this->assertEquals(0, $address->getBaseTotalAmount('subtotal')); $this->assertEquals(0, $address->getBaseTotalAmount('tax')); - $this->assertEquals(0, $address->getBaseTotalAmount('hidden_tax')); - $this->assertEquals(0, $address->getBaseTotalAmount('shipping_hidden_tax')); + $this->assertEquals(0, $address->getBaseTotalAmount('discount_tax_compensation')); + $this->assertEquals(0, $address->getBaseTotalAmount('shipping_discount_tax_compensation')); $this->assertEquals(0, $address->getSubtotalInclTax()); $this->assertEquals(0, $address->getBaseSubtotalInclTax()); } diff --git a/app/code/Magento/Tax/composer.json b/app/code/Magento/Tax/composer.json index 9bef9c79f3e19dd72e42ac9de6dd5e63faccd2de..3ef7c5e73fc4cd09ad9f1ff4cca1b0b5f56ed1d6 100644 --- a/app/code/Magento/Tax/composer.json +++ b/app/code/Magento/Tax/composer.json @@ -3,23 +3,24 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-config": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-shipping": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-reports": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-config": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-shipping": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-reports": "0.74.0-beta13", + "magento/module-page-cache": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Tax/etc/adminhtml/system.xml b/app/code/Magento/Tax/etc/adminhtml/system.xml index ff0eb2b5807191826faedf51d87d7539d407df19..23fc72d7d47e491e56cacb957db9b237a9487347 100644 --- a/app/code/Magento/Tax/etc/adminhtml/system.xml +++ b/app/code/Magento/Tax/etc/adminhtml/system.xml @@ -41,13 +41,13 @@ </field> <field id="price_includes_tax" translate="label comment" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Catalog Prices</label> - <comment>This sets whether catalog prices entered by admin include tax.</comment> + <comment>This sets whether catalog prices entered from Magento Admin include tax.</comment> <backend_model>Magento\Tax\Model\Config\Price\IncludePrice</backend_model> <source_model>Magento\Tax\Model\System\Config\Source\PriceType</source_model> </field> <field id="shipping_includes_tax" translate="label comment" type="select" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Shipping Prices</label> - <comment>This sets whether shipping amounts entered by admin or obtained from gateways include tax.</comment> + <comment>This sets whether shipping amounts entered from Magento Admin or obtained from gateways include tax.</comment> <backend_model>Magento\Tax\Model\Config\Price\IncludePrice</backend_model> <source_model>Magento\Tax\Model\System\Config\Source\PriceType</source_model> </field> @@ -60,7 +60,7 @@ <label>Apply Discount On Prices</label> <source_model>Magento\Tax\Model\System\Config\Source\PriceType</source_model> <backend_model>Magento\Tax\Model\Config\Notification</backend_model> - <comment>Apply discount on price including tax is calculated based on store tax, if "Apply Tax after Discount" is selected.</comment> + <comment>Apply discount on price including tax is calculated based on store tax if "Apply Tax after Discount" is selected.</comment> </field> <field id="apply_tax_on" translate="label comment" type="select" sortOrder="60" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Apply Tax On</label> @@ -69,7 +69,7 @@ <field id="cross_border_trade_enabled" translate="label comment" type="select" sortOrder="70" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Enable Cross Border Trade</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> - <comment>When catalog price includes tax, enable this setting will fix the price no matter what the customer's tax rate is.</comment> + <comment>When catalog price includes tax, enable this setting to fix the price no matter what the customer's tax rate.</comment> </field> </group> <group id="defaults" translate="label" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> diff --git a/app/code/Magento/Tax/etc/service_data_attributes.xml b/app/code/Magento/Tax/etc/extension_attributes.xml similarity index 90% rename from app/code/Magento/Tax/etc/service_data_attributes.xml rename to app/code/Magento/Tax/etc/extension_attributes.xml index 8539bcc8b88d3cdfe7dbc6bdd0b1f3446cf336bd..0302ae2fcd16a12a2f270d5f7e04fda059c52af4 100644 --- a/app/code/Magento/Tax/etc/service_data_attributes.xml +++ b/app/code/Magento/Tax/etc/extension_attributes.xml @@ -5,10 +5,8 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Quote\Api\Data\TotalsInterface"> <attribute code="tax_grandtotal_details" type="Magento\Tax\Api\Data\GrandTotalDetailsInterface[]" /> </extension_attributes> </config> - - diff --git a/app/code/Magento/Tax/etc/frontend/di.xml b/app/code/Magento/Tax/etc/frontend/di.xml index fa0d913d07cda3e55a12c73241c5183d243c654a..b58799182d93dc1bf55c5474b44f8d30e47b6960 100644 --- a/app/code/Magento/Tax/etc/frontend/di.xml +++ b/app/code/Magento/Tax/etc/frontend/di.xml @@ -31,4 +31,12 @@ </argument> </arguments> </type> + <type name="Magento\Framework\View\Layout"> + <plugin name="tax-session-depersonalize" + type="Magento\Tax\Model\Layout\DepersonalizePlugin" sortOrder="20"/> + </type> + <type name="Magento\Framework\App\Action\Action"> + <plugin name="tax-app-action-dispatchController-context-plugin" + type="Magento\Tax\Model\App\Action\ContextPlugin"/> + </type> </config> diff --git a/app/code/Magento/Tax/etc/frontend/events.xml b/app/code/Magento/Tax/etc/frontend/events.xml new file mode 100644 index 0000000000000000000000000000000000000000..499b11ccb7d150e2b05ea6158c08c05830b25105 --- /dev/null +++ b/app/code/Magento/Tax/etc/frontend/events.xml @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/Event/etc/events.xsd"> + <event name="customer_data_object_login"> + <observer name="customer_tax_logged_in" instance="Magento\Tax\Model\Observer\Session" method="customerLoggedIn" /> + </event> + <event name="customer_address_save_after"> + <observer name="customer_tax_after_address_save" instance="Magento\Tax\Model\Observer\Session" method="afterAddressSave" /> + </event> +</config> diff --git a/app/code/Magento/Tax/etc/module.xml b/app/code/Magento/Tax/etc/module.xml old mode 100644 new mode 100755 diff --git a/app/code/Magento/TaxImportExport/composer.json b/app/code/Magento/TaxImportExport/composer.json index ecd9aade49991b17043d332b0eb9ecea5560edcd..0cebf5d7d3360dba867fee97e90b3a9d2336ad91 100644 --- a/app/code/Magento/TaxImportExport/composer.json +++ b/app/code/Magento/TaxImportExport/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-tax": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-tax": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Theme/Block/Adminhtml/System/Design/Theme/Edit/Form/Element/Links.php b/app/code/Magento/Theme/Block/Adminhtml/System/Design/Theme/Edit/Form/Element/Links.php old mode 100644 new mode 100755 index 48d3bdbea7d20d3c89baaa0494d787bf960f6e00..da9535d0ae18d8e64efeb5b6cd939baac5d621ae --- a/app/code/Magento/Theme/Block/Adminhtml/System/Design/Theme/Edit/Form/Element/Links.php +++ b/app/code/Magento/Theme/Block/Adminhtml/System/Design/Theme/Edit/Form/Element/Links.php @@ -110,7 +110,9 @@ class Links extends \Magento\Framework\Data\Form\Element\AbstractElement 'onmouseup', 'onkeydown', 'onkeypress', - 'onkeyup' + 'onkeyup', + 'data-role', + 'data-action' ]; } } diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCustomCss.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCustomCss.php index 0958f0b21844a16f4da5df10355f3c5e66b65e94..8653fa797f160550c170442b1abd799464a114b6 100644 --- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCustomCss.php +++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/DownloadCustomCss.php @@ -40,7 +40,7 @@ class DownloadCustomCss extends \Magento\Theme\Controller\Adminhtml\System\Desig ); } } catch (\Exception $e) { - $this->messageManager->addException($e, __('We cannot find file')); + $this->messageManager->addException($e, __('We can\'t find file.')); $this->getResponse()->setRedirect($this->_redirect->getRefererUrl()); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Save.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Save.php index 2f5983ffbc05ce63a3486693e05222bbdf257c4d..9c19074aab15c54abdc3a8addc7d7a4c3d871e73 100644 --- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Save.php +++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/Save.php @@ -45,7 +45,7 @@ class Save extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme ); } if ($theme && !$theme->isEditable()) { - throw new \Magento\Framework\Exception\LocalizedException(__('Theme isn\'t editable.')); + throw new \Magento\Framework\Exception\LocalizedException(__('This theme is not editable.')); } $theme->addData($themeData); if (isset($themeData['preview']['delete'])) { diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadCss.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadCss.php index 60a40d294dfef7541247b0309e944e696aa157a3..c201adf38e9186767b17819517d693b61a249d8b 100644 --- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadCss.php +++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadCss.php @@ -23,7 +23,7 @@ class UploadCss extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme } catch (\Magento\Framework\Exception\LocalizedException $e) { $result = ['error' => true, 'message' => $e->getMessage()]; } catch (\Exception $e) { - $result = ['error' => true, 'message' => __('We cannot upload the CSS file.')]; + $result = ['error' => true, 'message' => __('We can\'t upload the CSS file right now.')]; $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } $this->getResponse()->representJson( diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php index 29bb491cf6b9c60e91a0ece59e1c2eac1b8a7da9..58cf189c86f0bdb5a63491384a92d9bc398370d3 100644 --- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php +++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Theme/UploadJs.php @@ -49,7 +49,7 @@ class UploadJs extends \Magento\Theme\Controller\Adminhtml\System\Design\Theme } catch (\Magento\Framework\Exception\LocalizedException $e) { $result = ['error' => true, 'message' => $e->getMessage()]; } catch (\Exception $e) { - $result = ['error' => true, 'message' => __('We cannot upload the JS file.')]; + $result = ['error' => true, 'message' => __('We can\'t upload the JS file right now.')]; $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } $this->getResponse()->representJson( diff --git a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/NewFolder.php b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/NewFolder.php index dc97c1367285f4edc8613db8808e841ba45a1ea8..639ca3f383d61c33a038c7de4b9306d362ec3e1b 100644 --- a/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/NewFolder.php +++ b/app/code/Magento/Theme/Controller/Adminhtml/System/Design/Wysiwyg/Files/NewFolder.php @@ -22,7 +22,7 @@ class NewFolder extends \Magento\Theme\Controller\Adminhtml\System\Design\Wysiwy } catch (\Magento\Framework\Exception\LocalizedException $e) { $result = ['error' => true, 'message' => $e->getMessage()]; } catch (\Exception $e) { - $result = ['error' => true, 'message' => __('Sorry, there was an unknown error.')]; + $result = ['error' => true, 'message' => __('Sorry, something went wrong.')]; $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } $this->getResponse()->representJson( diff --git a/app/code/Magento/Theme/Model/Design.php b/app/code/Magento/Theme/Model/Design.php index b82e4bc2263d2d4e716b4054eddce1a1beab3cb2..52cd618ad207c305beb3003dc6d085491b6a7d2a 100644 --- a/app/code/Magento/Theme/Model/Design.php +++ b/app/code/Magento/Theme/Model/Design.php @@ -61,7 +61,7 @@ class Design extends AbstractModel implements IdentityInterface, DesignInterface * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -70,7 +70,7 @@ class Design extends AbstractModel implements IdentityInterface, DesignInterface \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Framework\Stdlib\DateTime $dateTime, AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_localeDate = $localeDate; diff --git a/app/code/Magento/Theme/Model/Design/Backend/Exceptions.php b/app/code/Magento/Theme/Model/Design/Backend/Exceptions.php index 37a6236bc3d37fd4d2873f7ce29559ed3ebf19ef..bfe90ef91b6e484192ca76bf0f27a1c5881fc6d5 100644 --- a/app/code/Magento/Theme/Model/Design/Backend/Exceptions.php +++ b/app/code/Magento/Theme/Model/Design/Backend/Exceptions.php @@ -24,7 +24,7 @@ class Exceptions extends ArraySerialized * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\View\DesignInterface $design * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -33,7 +33,7 @@ class Exceptions extends ArraySerialized \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\View\DesignInterface $design, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_design = $design; diff --git a/app/code/Magento/Theme/Model/Design/Backend/Theme.php b/app/code/Magento/Theme/Model/Design/Backend/Theme.php index aede175c8312f075674c8fca4dceb6fe5cf8477b..9f7d2e326712f8d11c97e24aebac1625b8f88e78 100644 --- a/app/code/Magento/Theme/Model/Design/Backend/Theme.php +++ b/app/code/Magento/Theme/Model/Design/Backend/Theme.php @@ -24,7 +24,7 @@ class Theme extends Value * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\View\DesignInterface $design * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -33,7 +33,7 @@ class Theme extends Value \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\View\DesignInterface $design, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_design = $design; diff --git a/app/code/Magento/Theme/Model/Theme/File.php b/app/code/Magento/Theme/Model/Theme/File.php index 0ad82f4a51c2d6f84b5ffe7f8fb24271f36c2e91..3da6a17b0dd2e0d59ed11872a595d446b0372135 100644 --- a/app/code/Magento/Theme/Model/Theme/File.php +++ b/app/code/Magento/Theme/Model/Theme/File.php @@ -54,7 +54,7 @@ class File extends AbstractModel implements FileInterface * @param \Magento\Framework\View\Design\Theme\FlyweightFactory $themeFactory * @param \Magento\Framework\View\Design\Theme\Customization\FileServiceFactory $fileServiceFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -63,7 +63,7 @@ class File extends AbstractModel implements FileInterface \Magento\Framework\View\Design\Theme\FlyweightFactory $themeFactory, \Magento\Framework\View\Design\Theme\Customization\FileServiceFactory $fileServiceFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_themeFactory = $themeFactory; diff --git a/app/code/Magento/Theme/Model/Wysiwyg/Storage.php b/app/code/Magento/Theme/Model/Wysiwyg/Storage.php index 5eea783ab9a7d995e8e1d1402eec58f5ff84412a..8c865760540f4d3eeac391c6211788cb9c6d7b7a 100644 --- a/app/code/Magento/Theme/Model/Wysiwyg/Storage.php +++ b/app/code/Magento/Theme/Model/Wysiwyg/Storage.php @@ -118,7 +118,7 @@ class Storage $result = $uploader->save($targetPath); if (!$result) { - throw new \Magento\Framework\Exception\LocalizedException(__('We cannot upload the file.')); + throw new \Magento\Framework\Exception\LocalizedException(__('We can\'t upload the file right now.')); } $this->_createThumbnail($targetPath . '/' . $uploader->getUploadedFileName()); @@ -314,7 +314,9 @@ class Storage $pathCmp = rtrim($path, '/'); if ($rootCmp == $pathCmp) { - throw new \Magento\Framework\Exception\LocalizedException(__('We cannot delete root directory %1.', $path)); + throw new \Magento\Framework\Exception\LocalizedException( + __('We can\'t delete root directory %1 right now.', $path) + ); } return $this->mediaWriteDirectory->delete($path); diff --git a/app/code/Magento/Theme/composer.json b/app/code/Magento/Theme/composer.json index 2bc65456aad0c44122f8c1d4ed7ab7383c849308..7e2129cc460bb0145f4cf7dacf63bb226e4bb049 100644 --- a/app/code/Magento/Theme/composer.json +++ b/app/code/Magento/Theme/composer.json @@ -3,23 +3,23 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-cms": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-widget": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/module-media-storage": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-require-js": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-cms": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-widget": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/module-media-storage": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-require-js": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-translation": "0.74.0-beta10" + "magento/module-translation": "0.74.0-beta13" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Theme/etc/config.xml b/app/code/Magento/Theme/etc/config.xml index 405817f89597064bb56ed651ffb2bd5d71f4e7fb..b75fcddc364b618261e82ca9d38ef6b6158e2ec4 100644 --- a/app/code/Magento/Theme/etc/config.xml +++ b/app/code/Magento/Theme/etc/config.xml @@ -22,11 +22,8 @@ User-agent: * Disallow: /index.php/ Disallow: /*? -Disallow: /*.js$ -Disallow: /*.css$ Disallow: /checkout/ Disallow: /app/ -Disallow: /js/ Disallow: /lib/ Disallow: /*.php$ Disallow: /pkginfo/ diff --git a/app/code/Magento/Theme/view/frontend/templates/html/bugreport.phtml b/app/code/Magento/Theme/view/frontend/templates/html/bugreport.phtml index 07b90b4883e8cefee5e7aca5ebd2613a54364cfa..f81d5ae8386c690c113ed59a1ed5fef74a7ed333 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/bugreport.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/bugreport.phtml @@ -5,7 +5,7 @@ */ ?> <small class="bugs"> - <span><?php echo __('Help Us to Keep Magento Healthy') ?></span> + <span><?php echo __('Help Us Keep Magento Healthy') ?></span> <a href="http://www.magentocommerce.com/bug-tracking" target="_blank"> <?php echo __('Report All Bugs') ?> 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 1abca8a6039e43f8c53a22414e3835c2cd3a1aa9..d5e3ef7851329e5893cbf7ad15fe45fdf7cf8efb 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/footer.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/footer.phtml @@ -10,7 +10,7 @@ <div class="footer-container"> <div class="footer"> <?php echo $block->getChildHtml() ?> - <p class="bugs"><?php echo __('Help Us to Keep Magento Healthy') ?> - <a + <p class="bugs"><?php echo __('Help Us Keep Magento Healthy') ?> - <a href="http://www.magentocommerce.com/bug-tracking" target="_blank"><strong><?php echo __('Report All Bugs') ?></strong></a> <?php echo __('(ver. %1)', \Magento\Framework\AppInterface::VERSION) ?> </p> 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 2d6a562d55a8f1051a072c8c0755a1365a8ed5c7..673fb830b5a4fa6157dc60697b318c7631007647 100644 --- a/app/code/Magento/Theme/view/frontend/templates/html/notices.phtml +++ b/app/code/Magento/Theme/view/frontend/templates/html/notices.phtml @@ -18,7 +18,7 @@ <div class="content"> <p> <strong><?php echo __('JavaScript seems to be disabled in your browser.'); ?></strong> - <span><?php echo __('Enable JavaScript in your browser to get the best experience on our website!'); ?></span> + <span><?php echo __('For the best experience on our site, be sure to turn on Javascript in your browser.'); ?></span> </p> </div> </div> @@ -29,7 +29,7 @@ <div class="content"> <p> <strong><?php echo __('Local Storage seems to be disabled in your browser.'); ?></strong><br /> - <?php echo __('Enable Local Storage in your browser to get the best experience on our website!'); ?> + <?php echo __('For the best experience on our site, be sure to turn on Local Storage in your browser.'); ?> </p> </div> </div> @@ -54,7 +54,7 @@ require(['jquery'], function(jQuery){ <?php if ($block->displayDemoNotice()): ?> <div class="message global demo"> <div class="content"> - <p><?php echo __('This is demo store. All orders will not be transferred.') ?></p> + <p><?php echo __('This is demo store. No orders will be fulfilled.') ?></p> </div> </div> <?php endif; ?> diff --git a/app/code/Magento/Translation/composer.json b/app/code/Magento/Translation/composer.json index 7f04142d1fce7aab0ff51382514b523d0b2c908d..05ce2874e8b195cefb7355cb2208a5ca59b6208d 100644 --- a/app/code/Magento/Translation/composer.json +++ b/app/code/Magento/Translation/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-backend": "0.74.0-beta10", - "magento/module-developer": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-backend": "0.74.0-beta13", + "magento/module-developer": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Ui/Component/AbstractComponent.php b/app/code/Magento/Ui/Component/AbstractComponent.php index e3dd4d7d2f54c7869165190843513d18956f039a..c7af5b3f471c7c084826bc98c45a0ab6c2610cb2 100644 --- a/app/code/Magento/Ui/Component/AbstractComponent.php +++ b/app/code/Magento/Ui/Component/AbstractComponent.php @@ -232,4 +232,12 @@ abstract class AbstractComponent extends Object implements UiComponentInterface, { // } + + /** + * {@inheritdoc} + */ + public function getDataSourceData() + { + return []; + } } diff --git a/app/code/Magento/Ui/Component/Form.php b/app/code/Magento/Ui/Component/Form.php index 86f68058c08e6c076b014a8cf6a8bbab03477e08..ed0b344658a30c610169de97e9de8aaeb20d41f8 100644 --- a/app/code/Magento/Ui/Component/Form.php +++ b/app/code/Magento/Ui/Component/Form.php @@ -23,4 +23,27 @@ class Form extends AbstractComponent { return static::NAME; } + + /** + * {@inheritdoc} + */ + public function getDataSourceData() + { + $dataSource = []; + $id = $this->getContext()->getRequestParam($this->getContext()->getDataProvider()->getRequestFieldName()); + + if ($id) { + $this->getContext()->getDataProvider() + ->addFilter($this->getContext()->getDataProvider()->getPrimaryFieldName(), $id); + } + $data = $this->getContext()->getDataProvider()->getData(); + + if (isset($data[$id])) { + $dataSource = [ + 'data' => $data[$id] + ]; + } + + return $dataSource; + } } diff --git a/app/code/Magento/Ui/Component/Listing.php b/app/code/Magento/Ui/Component/Listing.php index c67ff26971b2d48838de4bf36dcfd33a94ef2645..7d7d7b692b26042a08d41295f7a24d6536fd1802 100644 --- a/app/code/Magento/Ui/Component/Listing.php +++ b/app/code/Magento/Ui/Component/Listing.php @@ -30,4 +30,15 @@ class Listing extends AbstractComponent { return static::NAME; } + + /** + * {@inheritdoc} + */ + public function getDataSourceData() + { + return [ + 'data' => $this->getContext()->getDataProvider()->getData(), + 'totalCount' => $this->getContext()->getDataProvider()->count() + ]; + } } diff --git a/app/code/Magento/Ui/Model/Bookmark.php b/app/code/Magento/Ui/Model/Bookmark.php index 60e2622b9b49e33dea54167132f9b4cdeec1bbff..2a7c7791add8834c89b281f4b476674741fa7546 100644 --- a/app/code/Magento/Ui/Model/Bookmark.php +++ b/app/code/Magento/Ui/Model/Bookmark.php @@ -5,7 +5,6 @@ */ namespace Magento\Ui\Model; -use Magento\Framework\Data\Collection\Db; use Magento\Framework\Json\Decoder; use Magento\Framework\Json\Encoder; use Magento\Framework\Model\AbstractModel; diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Content.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Content.php index 1b31288c66fd8d397a64a2ee9e766fa6008856f1..fd6426a41c6ab87cd2fbe00e076efb931ea7d4d9 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Content.php +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Content.php @@ -6,8 +6,9 @@ namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Element; use Magento\Framework\Object; -use Magento\Ui\TemplateEngine\Xhtml\Compiler; use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Element\ElementInterface; /** * Class Content @@ -17,25 +18,22 @@ class Content implements ElementInterface /** * Compiles the Element node * - * @param Compiler $compiler + * @param CompilerInterface $compiler * @param \DOMElement $node - * @param UiComponentInterface $component + * @param Object $processedObject * @param Object $context * @return void */ - public function compile( - Compiler $compiler, - \DOMElement $node, - UiComponentInterface $component, - Object $context - ) { + public function compile(CompilerInterface $compiler, \DOMElement $node, Object $processedObject, Object $context) + { $name = $node->getAttribute('name'); - $content = (string)$component->renderChildComponent($name); + /** @var UiComponentInterface $processedObject */ + $content = (string)$processedObject->renderChildComponent($name); $name .= '_' . sprintf('%x', crc32(spl_object_hash($context))); if (!empty($content)) { $compiler->setPostprocessingData($name, $content); $newNode = $node->ownerDocument->createTextNode( - Compiler::PATTERN_TAG . $name . Compiler::PATTERN_TAG + CompilerInterface::PATTERN_TAG . $name . CompilerInterface::PATTERN_TAG ); $node->parentNode->replaceChild($newNode, $node); } else { diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php deleted file mode 100644 index 9ce4c9f74583636d568a83ac45456ecdffb8222c..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Element; - -use Magento\Framework\Object; -use Magento\Ui\TemplateEngine\Xhtml\Compiler; -use Magento\Framework\View\Element\UiComponentInterface; - -/** - * Interface ElementInterface - */ -interface ElementInterface -{ - /** - * Compiles the Element node - * - * @param Compiler $compiler - * @param \DOMElement $node - * @param UiComponentInterface $component - * @param Object $context - * @return void - */ - public function compile( - Compiler $compiler, - \DOMElement $node, - UiComponentInterface $component, - Object $context - ); -} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Form.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Form.php index 513be2d1daf676ed9c433c82a2f23cbce0f3d588..8af7844c08e156508cf2c644c4085d4d8e7dc92d 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Form.php +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Form.php @@ -6,8 +6,8 @@ namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Element; use Magento\Framework\Object; -use Magento\Ui\TemplateEngine\Xhtml\Compiler; -use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Element\ElementInterface; /** * Class Form @@ -17,20 +17,16 @@ class Form implements ElementInterface /** * Compiles the Element node * - * @param Compiler $compiler + * @param CompilerInterface $compiler * @param \DOMElement $node - * @param UiComponentInterface $component + * @param Object $processedObject * @param Object $context * @return void */ - public function compile( - Compiler $compiler, - \DOMElement $node, - UiComponentInterface $component, - Object $context - ) { + public function compile(CompilerInterface $compiler, \DOMElement $node, Object $processedObject, Object $context) + { foreach ($this->getChildNodes($node) as $child) { - $compiler->compile($child, $component, $context); + $compiler->compile($child, $processedObject, $context); } } diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Render.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Render.php index 9118a5e6b6aef4cd9a00cea1e21ec38234334660..6ab676b876d2b484dcf7436b8088f082b17733cc 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Render.php +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Element/Render.php @@ -6,9 +6,10 @@ namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Element; use Magento\Framework\Object; -use Magento\Ui\TemplateEngine\Xhtml\Compiler; -use Magento\Ui\TemplateEngine\Xhtml\Result; use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\ResultInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Element\ElementInterface; /** * Class Render @@ -18,26 +19,24 @@ class Render implements ElementInterface /** * Compiles the Element node * - * @param Compiler $compiler + * @param CompilerInterface $compiler * @param \DOMElement $node - * @param UiComponentInterface $component + * @param Object $processedObject * @param Object $context * @return void + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function compile( - Compiler $compiler, - \DOMElement $node, - UiComponentInterface $component, - Object $context - ) { - $result = $component->renderChildComponent($node->getAttribute('name')); - if ($result instanceof Result) { + public function compile(CompilerInterface $compiler, \DOMElement $node, Object $processedObject, Object $context) + { + /** @var UiComponentInterface $processedObject */ + $result = $processedObject->renderChildComponent($node->getAttribute('name')); + if ($result instanceof ResultInterface) { $node->parentNode->replaceChild($result->getDocumentElement(), $node); } else if (!empty($result) && is_scalar($result)) { $newFragment = $node->ownerDocument->createDocumentFragment(); $newFragment->appendXML($result); $node->parentNode->replaceChild($newFragment, $node); - $node->parentNode->removeChild($node); } else { $node->parentNode->removeChild($node); } diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php index 2ad357022989fe9d7a4c9bd04d71d0faef71e151..bdd4e74ddd63218da303e7b9ab884814b68f2ee6 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php +++ b/app/code/Magento/Ui/TemplateEngine/Xhtml/Result.php @@ -7,11 +7,14 @@ namespace Magento\Ui\TemplateEngine\Xhtml; use Magento\Ui\Component\Layout\Generator\Structure; use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Template; +use Magento\Framework\View\TemplateEngine\Xhtml\ResultInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface; /** * Class Result */ -class Result +class Result implements ResultInterface { /** * @var Template @@ -19,7 +22,7 @@ class Result protected $template; /** - * @var Compiler + * @var CompilerInterface */ protected $compiler; @@ -37,13 +40,13 @@ class Result * Constructor * * @param Template $template - * @param Compiler $compiler + * @param CompilerInterface $compiler * @param UiComponentInterface $component * @param Structure $structure */ public function __construct( Template $template, - Compiler $compiler, + CompilerInterface $compiler, UiComponentInterface $component, Structure $structure ) { diff --git a/app/code/Magento/Ui/Test/Unit/Component/Control/ContainerTest.php b/app/code/Magento/Ui/Test/Unit/Component/Control/ContainerTest.php index 9251da5b69dffd7adee6d34dd9fff76c7babe17a..d866e39517f1060699d875493a2128bd5891e19c 100644 --- a/app/code/Magento/Ui/Test/Unit/Component/Control/ContainerTest.php +++ b/app/code/Magento/Ui/Test/Unit/Component/Control/ContainerTest.php @@ -36,7 +36,7 @@ class ContainerTest extends \PHPUnit_Framework_TestCase ->willReturn($blockButtonMock); $contextMock->expects($this->any())->method('getLayout')->willReturn($layoutMock); - $itemMock = $this->getMock('Magento\Ui\Component\Control\Item', [], [], '', false); + $itemMock = $this->getMock('Magento\Ui\Component\Control\Item', ['getId', 'getData'], [], '', false); $itemMock->expects($this->any())->method('getData')->willReturn($data); $itemMock->expects($this->any())->method('getId')->willReturn($id); diff --git a/app/code/Magento/Ui/composer.json b/app/code/Magento/Ui/composer.json index 2083a308e0e7b6bf6be377346aa369cba9150c55..edb3157e7aab2160a922d9f80b68fe3674e946ed 100644 --- a/app/code/Magento/Ui/composer.json +++ b/app/code/Magento/Ui/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-backend": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-authorization": "0.74.0-beta10", + "magento/module-backend": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-authorization": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Ui/etc/di.xml b/app/code/Magento/Ui/etc/di.xml index 6c541271294e752f2f10f300b303ef7790c3bd6b..d81fb2c0bd00a7d2681ffdcb66148924494922bd 100644 --- a/app/code/Magento/Ui/etc/di.xml +++ b/app/code/Magento/Ui/etc/di.xml @@ -18,17 +18,19 @@ <preference for="Magento\Ui\Api\BookmarkRepositoryInterface" type="Magento\Ui\Model\Resource\BookmarkRepository"/> <preference for="Magento\Ui\Api\Data\BookmarkInterface" type="Magento\Ui\Model\Bookmark"/> <preference for="Magento\Ui\Api\BookmarkManagementInterface" type="Magento\Ui\Model\BookmarkManagement"/> + <preference for="Magento\Framework\View\TemplateEngine\Xhtml\ResultInterface" type="Magento\Ui\TemplateEngine\Xhtml\Result"/> + <type name="Magento\Ui\TemplateEngine\Xhtml\Result" shared="false"/> <type name="Magento\Framework\View\Element\UiComponent\TemplateAdapter" shared="false" /> <type name="Magento\Framework\View\TemplateEngineFactory"> <arguments> <argument name="engines" xsi:type="array"> - <item name="xhtml" xsi:type="string">Magento\Ui\TemplateEngine\Xhtml</item> + <item name="xhtml" xsi:type="string">Magento\Framework\View\TemplateEngine\Xhtml</item> </argument> </arguments> </type> - <type name="Magento\Ui\TemplateEngine\Xhtml"> + <type name="Magento\Framework\View\TemplateEngine\Xhtml"> <arguments> - <argument name="compiler" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler</argument> + <argument name="compilerFactory" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\UiCompilerFactory</argument> </arguments> </type> <type name="Magento\Framework\View\Element\UiComponent\ContentType\ContentTypeFactory"> @@ -40,35 +42,40 @@ </argument> </arguments> </type> - <type name="Magento\Ui\TemplateEngine\Xhtml\Compiler\Text"> + <type name="Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Text"> <arguments> <argument name="directivePool" xsi:type="array"> - <item name="variable" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\Variable</item> - <item name="callableMethod" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\CallableMethod</item> + <item name="variable" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Directive\Variable</item> + <item name="callableMethod" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Directive\CallableMethod</item> </argument> </arguments> </type> - <type name="Magento\Ui\TemplateEngine\Xhtml\Compiler\Attribute"> + <type name="Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Attribute"> <arguments> <argument name="directivePool" xsi:type="array"> - <item name="variable" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\Variable</item> - <item name="callableMethod" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\CallableMethod</item> + <item name="variable" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Directive\Variable</item> + <item name="callableMethod" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Directive\CallableMethod</item> </argument> </arguments> </type> - <type name="Magento\Ui\TemplateEngine\Xhtml\Compiler" shared="false"> + <virtualType name="Magento\Framework\View\TemplateEngine\Xhtml\UiCompilerFactory" type="Magento\Framework\View\TemplateEngine\Xhtml\CompilerFactory"> <arguments> - <argument name="compilerText" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Text</argument> - <argument name="compilerAttribute" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Attribute</argument> - <argument name="compilerCdata" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Cdata</argument> - <argument name="compilerComment" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Comment</argument> + <argument name="instanceName" xsi:type="string">Magento\Framework\View\TemplateEngine\Xhtml\UiCompiler</argument> + </arguments> + </virtualType> + <virtualType name="Magento\Framework\View\TemplateEngine\Xhtml\UiCompiler" type="Magento\Framework\View\TemplateEngine\Xhtml\Compiler" shared="false"> + <arguments> + <argument name="compilerText" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Text</argument> + <argument name="compilerAttribute" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Attribute</argument> + <argument name="compilerCdata" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Cdata</argument> + <argument name="compilerComment" xsi:type="object">Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Comment</argument> <argument name="elementCompilers" xsi:type="array"> <item name="render" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\Render</item> - <item name="content" xsi:type="object">\Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\Content</item> + <item name="content" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\Content</item> <item name="form" xsi:type="object">Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\Form</item> </argument> </arguments> - </type> + </virtualType> <virtualType name="uiConfigurationDomMerger" type="Magento\Framework\View\Element\UiComponent\Config\DomMerger"> <arguments> <argument name="schemaFileType" xsi:type="string">etc</argument> 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 c8750c3129530719b24d7d8f3d8b4c4fc11b705e..6c6bdbfcf30067a496a874c1fd1eb24e4d4eec05 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 @@ -29,7 +29,19 @@ define([ success: function (resp) { if (!resp.error) { save.resolve(); + return true; } + + $('body').notification('clear'); + $.each(resp.messages, function(key, message) { + $('body').notification('add', { + error: resp.error, + message: message, + insertMethod: function(message) { + $('.page-main-actions').after(message); + } + }); + }); }, complete: function () { $('body').trigger('processStop'); 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 b9d2884597e2c30884226894c3d44e4f194c6918..d0b1f2fd4cfbeb505fc4044696f37e309631a774 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 @@ -21,7 +21,7 @@ define([ * Calls initListeners and pushParams methods. */ initialize: function () { - _.bindAll(this, 'onChildrenUpdate', 'onContentLoading', 'onContentLoaded'); + _.bindAll(this, 'onChildrenUpdate', 'onContentLoading'); return this._super(); }, @@ -49,8 +49,7 @@ define([ elem.on({ 'update': this.onChildrenUpdate, - 'loading': this.onContentLoading, - 'loaded': this.onContentLoaded + 'loading': this.onContentLoading }); return this; @@ -75,15 +74,8 @@ define([ /** * Callback that sets loading property to true. */ - onContentLoading: function () { - this.loading(true); - }, - - /** - * Callback that sets loading property to true. - */ - onContentLoaded: function () { - this.loading(false); + onContentLoading: function (isLoading) { + this.loading(isLoading); } }); }); 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 f40aa6ebe4134876c5f1007ab9635b8efe16b94f..8cfe842788f9a423392e2b9cdc5e551d861c358a 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 @@ -45,7 +45,7 @@ define([ elem.activate(); - this.trigger('update'); + this.bubble('update'); return this; }, @@ -151,11 +151,11 @@ define([ * Since this method is used by 'click' binding, * it requires function to invoke. */ - removeChild: function (elem) { + removeAddress: function (elem) { var confirmed = confirm(this.removeMessage); if (confirmed) { - this._removeChild(elem); + this._removeAddress(elem); } }, @@ -166,7 +166,7 @@ define([ * * @param {Object} elem - Element to remove. */ - _removeChild: function (elem) { + _removeAddress: function (elem) { var isActive = elem.active(), first; @@ -178,7 +178,7 @@ define([ first.activate(); } - this.trigger('update'); + this.bubble('update'); } }); }); 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 e8cf03cc4e1bc266f16987cf65a653842f8b432b..5b1aaccd1c8f85470c4f1c366a30b748356e9cce 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 @@ -14,10 +14,7 @@ define([ content: '', showSpinner: false, loading: false, - template: 'ui/content/content', - listens: { - loading: 'toggleLoadState' - } + template: 'ui/content/content' }, /** @@ -83,10 +80,6 @@ define([ } }, - toggleLoadState: function (value) { - this.trigger(value ? 'loading' : 'loaded'); - }, - /** * Defines if instance has 'content' property defined. * 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 71fa390a0ed5605fff9c7d9d3ab6ae99ed0f3448..84ea34f88934be1e8bc349a149482e3f297b49ee 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js @@ -30,8 +30,8 @@ define([ listens: { value: 'onUpdate', visible: 'setPreview', - '<%= provider %>:data.reset': 'reset', - '<%= provider %>:<% if (customScope !== "") { %><%= customScope %>.<% } %>data.validate': 'validate' + '${ $.provider }:data.reset': 'reset', + '${ $.provider }:${ $.customScope ? $.customScope + "." : ""}data.validate': 'validate' }, links: { 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 1467d569b9d46014491c76b71ffa0417a5f3bcb9..c0be7f0864cd6ca687508732a1becd53f3533185 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 @@ -363,13 +363,13 @@ define([ function(value) { return utils.isEmptyNoTrim(value) || /^[A-Za-z]+[A-Za-z0-9_]+$/.test(value); }, - $.mage.__('Please use only letters (a-z or A-Z), numbers (0-9) or underscore(_) in this field, first character should be a letter.') + $.mage.__('Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.') ], "validate-street": [ function(value) { return utils.isEmptyNoTrim(value) || /^[ \w]{3,}([A-Za-z]\.)?([ \w]*\#\d+)?(\r\n| )[ \w]{3,}/.test(value); }, - $.mage.__('Please use only letters (a-z or A-Z) or numbers (0-9) or spaces and # only in this field.') + $.mage.__('Please use only letters (a-z or A-Z), numbers (0-9), spaces and "#" in this field.') ], "validate-phoneStrict": [ function(value) { @@ -387,19 +387,19 @@ define([ function(value) { return utils.isEmptyNoTrim(value) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(value); }, - $.mage.__('Please enter a valid fax number. For example (123) 456-7890 or 123-456-7890.') + $.mage.__('Please enter a valid fax number (Ex: 123-456-7890).') ], "validate-email": [ function(value) { return utils.isEmptyNoTrim(value) || /^([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*@([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*\.(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]){2,})$/i.test(value); }, - $.mage.__('Please enter a valid email address. For example johndoe@domain.com.') + $.mage.__('Please enter a valid email address (Ex: johndoe@domain.com).') ], "validate-emailSender": [ function(value) { return utils.isEmptyNoTrim(value) || /^[\S ]+$/.test(value); }, - $.mage.__('Please enter a valid email address. For example johndoe@domain.com.') + $.mage.__('Please enter a valid email address (Ex: johndoe@domain.com).') ], "validate-password": [ function(value) { @@ -433,7 +433,7 @@ define([ } return true; }, - $.mage.__('Please enter 7 or more characters. Password should contain both numeric and alphabetic characters.') + $.mage.__('Please enter 7 or more characters, using both numeric and alphabetic.') ], "validate-url": [ function(value) { @@ -458,21 +458,21 @@ define([ return utils.isEmptyNoTrim(value) || /^[A-Z][A-Z0-9_\/-]*$/i.test(value); }, - $.mage.__('Please enter a valid XML-identifier. For example something_1, block5, id-4.') + $.mage.__('Please enter a valid XML-identifier (Ex: something_1, block5, id-4).') ], "validate-ssn": [ function(value) { return utils.isEmptyNoTrim(value) || /^\d{3}-?\d{2}-?\d{4}$/.test(value); }, - $.mage.__('Please enter a valid social security number. For example 123-45-6789.') + $.mage.__('Please enter a valid social security number (Ex: 123-45-6789).') ], "validate-zip-us": [ function(value) { return utils.isEmptyNoTrim(value) || /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(value); }, - $.mage.__('Please enter a valid zip code. For example 90602 or 90602-1234.') + $.mage.__('Please enter a valid zip code (Ex: 90602 or 90602-1234).') ], "validate-date-au": [ function(value) { @@ -538,7 +538,7 @@ define([ } return true; }, - $.mage.__('Please input a valid CSS-length. For example 100px or 77pt or 20em or .5ex or 50%.') + $.mage.__('Please input a valid CSS-length (Ex: 100px, 77pt, 20em, .5ex or 50%).') ], /** @description Additional methods */ "validate-number": [ @@ -639,13 +639,13 @@ define([ function(value) { return utils.isEmptyNoTrim(value) || /^[a-z]+[a-z0-9_]+$/.test(value); }, - $.mage.__('Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.') + $.mage.__('Please use only letters (a-z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.') ], "validate-alphanum": [ function(value) { return utils.isEmptyNoTrim(value) || /^[a-zA-Z0-9]+$/.test(value); }, - $.mage.__('Please use only letters (a-z or A-Z) or numbers (0-9) only in this field. No spaces or other characters are allowed.') + $.mage.__('Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.') ], "validate-date": [ function(value) { @@ -658,7 +658,7 @@ define([ function(value) { return utils.isEmptyNoTrim(value) || /^[a-z0-9][a-z0-9_\/-]+(\.[a-z0-9_-]+)?$/.test(value); }, - $.mage.__('Please enter a valid URL Key. For example "example-page", "example-page.html" or "anotherlevel/example-page".') + $.mage.__('Please enter a valid URL Key (Ex: "example-page", "example-page.html" or "anotherlevel/example-page").') ], "validate-zip-international": [ /*function(v) { 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 new file mode 100644 index 0000000000000000000000000000000000000000..1b9c0c18860a88b2faccfa8490a5c243746ce6b5 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/modal/modal.js @@ -0,0 +1,243 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + "jquery", + "underscore", + "mage/template", + "text!ui/template/modal/modal-popup.html", + "text!ui/template/modal/modal-slide.html", + "jquery/ui", + "mage/translate" +], function($, _, template, popupTpl, slideTpl){ + "use strict"; + + /** + * Modal Window Widget + */ + $.widget('mage.modal', { + options: { + type: 'popup', + title: '', + modalClass: '', + popupTpl: popupTpl, + slideTpl: slideTpl, + modalVisibleClass: '_show', + parentModalClass: '_has-modal', + innerScrollClass: '_inner-scroll', + responsive: false, + innerScroll: false, + modalBlock: '[data-role="modal"]', + modalCloseBtn: '[data-role="closeBtn"]', + modalContent: '[data-role="content"]', + modalAction: '[data-role="action"]', + appendTo: 'body', + wrapperClass: 'modals-wrapper', + overlayClass: 'modals-overlay', + responsiveClass: 'modal-slide', + modalLeftMargin: 45, + closeText: $.mage.__('Close'), + buttons: [{ + text: $.mage.__('Ok'), + class: '', + click: function(){ + this.closeModal(); + } + }] + }, + /** + * Creates modal widget. + */ + _create: function() { + this.options.transitionEvent = this.whichTransitionEvent(); + this._createWrapper(); + this._renderModal(); + this._createButtons(); + + this.modal.find(this.options.modalCloseBtn).on('click', _.bind(this.closeModal, this)); + this.element.on('openModal', _.bind(this.openModal, this)); + this.element.on('closeModal', _.bind(this.closeModal, this)); + }, + /** + * Returns element from modal node. + * @return {Object} - element. + */ + _getElem: function(elem) { + return this.modal.find(elem); + }, + /** + * Gets visible modal count. + * * @return {Number} - visible modal count. + */ + _getVisibleCount: function() { + return this.modalWrapper.find('.'+this.options.modalVisibleClass).length; + }, + /** + * Gets count of visible modal by slide type. + * * @return {Number} - visible modal count. + */ + _getVisibleSlideCount: function() { + var elems = this.modalWrapper.find('[data-type="slide"]'); + + return elems.filter('.'+this.options.modalVisibleClass).length; + }, + openModal: function() { + var that = this; + + this.options.isOpen = true; + this._createOverlay(); + this._setActive(); + this.modal.one(this.options.transitionEvent, function() { + that._trigger('opened'); + }); + this.modal.addClass(this.options.modalVisibleClass); + if ( !this.options.transitionEvent ) { + that._trigger('opened'); + } + + return this.element; + }, + closeModal: function() { + var that = this; + + this.options.isOpen = false; + this.modal.one(this.options.transitionEvent, function() { + that._close(); + }); + this.modal.removeClass(this.options.modalVisibleClass); + if ( !this.options.transitionEvent ) { + that._close(); + } + + return this.element; + }, + /** + * Helper for closeModal function. + */ + _close: function() { + var trigger = _.bind(this._trigger, this, 'closed', this.modal); + + this._destroyOverlay(); + this._unsetActive(); + _.defer(trigger, this); + }, + /** + * Set z-index and margin for modal and overlay. + */ + _setActive: function() { + var zIndex = this.modal.zIndex(); + + this.prevOverlayIndex = this.overlay.zIndex(); + this.modal.zIndex(zIndex + this._getVisibleCount()); + this.overlay.zIndex(zIndex + (this._getVisibleCount() - 1)); + if ( this._getVisibleSlideCount() ) { + this.modal.css('marginLeft', this.options.modalLeftMargin * this._getVisibleSlideCount()); + } + }, + /** + * Unset styles for modal and set z-index for previous modal. + */ + _unsetActive: function() { + this.modal.removeAttr('style'); + if ( this.overlay ) { + this.overlay.zIndex(this.prevOverlayIndex); + } + }, + /** + * Creates wrapper to hold all modals. + */ + _createWrapper: function() { + this.modalWrapper = $('.'+this.options.wrapperClass); + if ( !this.modalWrapper.length ) { + this.modalWrapper = $('<div></div>') + .addClass(this.options.wrapperClass) + .appendTo(this.options.appendTo); + } + }, + /** + * Compile template and append to wrapper. + */ + _renderModal: function() { + $(template( + this.options[this.options.type + 'Tpl'], + { + data: this.options + })).appendTo(this.modalWrapper); + this.modal = this.modalWrapper.find(this.options.modalBlock).last(); + this.element.show().appendTo(this._getElem(this.options.modalContent)); + }, + /** + * Creates buttons pane. + */ + _createButtons: function() { + var that = this; + + this.buttons = this._getElem(this.options.modalAction); + _.each(this.options.buttons, function(btn, key) { + var button = that.buttons[key]; + + $(button).on('click', _.bind(btn.click, that)); + }); + }, + /** + * Creates overlay, append it to wrapper, set previous click event on overlay. + */ + _createOverlay: function() { + var that = this, + events; + + this.overlay = $('.' + this.options.overlayClass); + if ( !this.overlay.length ) { + $(this.options.appendTo).addClass(this.options.parentModalClass); + this.overlay = $('<div></div>') + .addClass(this.options.overlayClass) + .appendTo(this.modalWrapper); + } + + events = $._data(this.overlay.get(0), 'events'); + if ( events ) { + this.prevOverlayHandler = events.click[0].handler; + } + this.overlay.unbind().on('click', function() { + that.closeModal(); + }); + }, + /** + * Destroy overlay. + */ + _destroyOverlay: function() { + var modalCount = this.modalWrapper.find('.'+this.options.modalVisibleClass).length; + + if ( !modalCount ) { + $(this.options.appendTo).removeClass(this.options.parentModalClass); + this.overlay.remove(); + this.overlay = null; + + } else { + this.overlay.unbind().on('click', this.prevOverlayHandler); + } + }, + /** + * Detects browser transition event. + */ + whichTransitionEvent: function() { + var transition, + el = document.createElement('element'), + transitions = { + 'transition': 'transitionend', + 'OTransition': 'oTransitionEnd', + 'MozTransition': 'transitionend', + 'WebkitTransition': 'webkitTransitionEnd' + }; + + for (transition in transitions){ + if ( el.style[transition] !== undefined && transitions.hasOwnProperty(transition) ) { + return transitions[transition]; + } + } + } + }); + + return $.mage.modal; +}); 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 05234c4afad7ace8a0e7261599b03eddf7c26260..60e44c80be894716ba8122e6f3d413052ecb119b 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/collection.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/components/collection.html @@ -10,7 +10,7 @@ <!-- ko foreach: { data: element.elems, as: 'element' } --> <li class="address-list-item" data-bind="css: { 'ui-state-active': element.active }, click: activate"> <div class="address-list-item-actions"> - <button class="action-delete" type="button" data-bind="click: $parent.removeChild.bind($parent, element)"> + <button class="action-delete" type="button" data-bind="click: $parent.removeAddress.bind($parent, element)"> <span data-bind="text: $parent.removeLabel"></span> </button> </div> @@ -42,4 +42,4 @@ </div> </div> <!-- /ko --> -</div> \ No newline at end of file +</div> 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 b42df55a146e9400e247e97b2751b825398a8338..ac6e00ae67b3c56b957b0edc521f49cfa9aaef1a 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 @@ -5,22 +5,22 @@ */ --> -<div - class="admin__fieldset-wrapper" - data-bind="css: {'admin__collapsible-block-wrapper': collapsible, 'opened': opened}"> - <div - class="admin__fieldset-wrapper-title" - tabindex="3" - data-bind="click: toggleOpened, keyboard: { 13: toggleOpened }"> +<div + class="admin__fieldset-wrapper" + data-bind="css: {'admin__collapsible-block-wrapper': collapsible, 'opened': opened}"> + <div + class="admin__fieldset-wrapper-title" + tabindex="3" + data-bind="click: toggleOpened, keyboard: { 13: toggleOpened }"> <strong class="title"> <span data-bind="text: label"></span> </strong> </div> <div class="admin__fieldset-wrapper-content" data-bind="visible: opened"> <fieldset class="admin__fieldset"> - <!-- ko foreach: { data: elems, as: 'element' } --> + <!-- ko foreach: { data: elems, as: 'element' } --> <!-- ko template: element.getTemplate() --><!-- /ko --> - <!-- /ko --> + <!-- /ko --> </fieldset> </div> </div> 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 new file mode 100644 index 0000000000000000000000000000000000000000..27d6bfcf6216b5a5d6ace4d652e681814b99bcaf --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/grid/cells/html.html @@ -0,0 +1,11 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<td + data-bind="visible: visible, + click: isClickable(row) ? redirect.bind($data, getClickUrl(row)) : false, + html: getLabel(row[field.index])" + data-action="grid-row-edit"></td> \ No newline at end of file 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 81ddbbd45a7bcc77ef622a906b96ffe6119d9ff8..257b4b0585d45aec84541ae338780047e16e3852 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 @@ -4,15 +4,8 @@ * See COPYING.txt for license details. */ --> - -<!-- ko if: isClickable(row) --> <td - class="_clickable" - data-bind="click: redirect.bind($data, getClickUrl(row)), - visible: visible, - html: getLabel(row[field.index])" - data-action="grid-row-edit"></td> -<!-- /ko --> -<!-- ko ifnot: isClickable(row) --> -<td data-bind="visible: visible, html: getLabel(row[field.index])"></td> -<!-- /ko --> + data-bind="visible: visible, + click: isClickable(row) ? redirect.bind($data, getClickUrl(row)) : false, + text: getLabel(row[field.index])" + data-action="grid-row-edit"></td> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html new file mode 100644 index 0000000000000000000000000000000000000000..7c45aefbb35a66ab80274fa4891f31804b246f93 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html @@ -0,0 +1,37 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<aside + class="modal-<%= data.type %> <%= data.modalClass %> + <% if(data.responsive){ %><%= data.responsiveClass %><% } %> + <% if(data.innerScroll){ %><%= data.innerScrollClass %><% } %>" + data-role="modal" + data-type="<%= data.type %>"> + <div class="modal-inner-wrap"> + <header class="modal-header"> + <h1 class="modal-title" + data-role="title"><%= data.title %></h1> + <button + class="action-close" + data-role="closeBtn" + type="button"> + <span><%= data.closeText %></span> + </button> + </header> + <div + class="modal-content" + data-role="content"></div> + <footer class="modal-footer"> + <% _.each(data.buttons, function(button) { %> + <button + class="<%= button.class %>" + type="button" + data-role="action"><span><%= button.text %></span></button> + <% }); %> + </footer> + </div> +</aside> diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-slide.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-slide.html new file mode 100644 index 0000000000000000000000000000000000000000..dbe99544b3e076a5d5fb670caad2ecdd77671437 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-slide.html @@ -0,0 +1,39 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<aside + class="modal-<%= data.type %> <%= data.modalClass %> + <% if(data.innerScroll){ %><%= data.innerScrollClass %><% } %>" + data-role="modal" + data-type="<%= data.type %>"> + <div class="modal-inner-wrap"> + <header class="modal-header"> + <h1 class="modal-title" + data-role="title"><%= data.title %></h1> + <button + class="action-close" + data-role="closeBtn" + type="button"> + <span><%= data.closeText %></span> + </button> + <div class="page-main-actions"> + <div class="page-actions"> + <div class="page-actions-buttons"> + <% _.each(data.buttons, function(button) { %> + <button + class="<%= button.class %>" + type="button" + data-role="action"><span><%= button.text %></span> + </button> + <% }); %> + </div> + </div> + </div> + </header> + <div class="modal-content" data-role="content"></div> + </div> +</aside> diff --git a/app/code/Magento/Ups/composer.json b/app/code/Magento/Ups/composer.json index 4729e5cc2fe0b60c9bf5397d0a53a61e060f19a6..29ec2510c07e79abb5e21f664e90c98db3554609 100644 --- a/app/code/Magento/Ups/composer.json +++ b/app/code/Magento/Ups/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-shipping": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-shipping": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Delete.php b/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Delete.php index 56fb10b39a515cdacb4a74594a3b027c2b57e62b..bea135dcedc2b3f78a1d388ff70e96973167da69 100644 --- a/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Delete.php +++ b/app/code/Magento/UrlRewrite/Controller/Adminhtml/Url/Rewrite/Delete.php @@ -20,7 +20,7 @@ class Delete extends \Magento\UrlRewrite\Controller\Adminhtml\Url\Rewrite $this->_getUrlRewrite()->delete(); $this->messageManager->addSuccess(__('The URL Rewrite has been deleted.')); } catch (\Exception $e) { - $this->messageManager->addException($e, __('An error occurred while deleting URL Rewrite.')); + $this->messageManager->addException($e, __('We can\'t delete URL Rewrite right now.')); $this->_redirect('adminhtml/*/edit/', ['id' => $this->_getUrlRewrite()->getId()]); return; } diff --git a/app/code/Magento/UrlRewrite/Helper/UrlRewrite.php b/app/code/Magento/UrlRewrite/Helper/UrlRewrite.php index 185241b3f27378f0b9e909f4a85bb419cd95d65d..9c55090c68aca471e6afe541374862731947fdb9 100644 --- a/app/code/Magento/UrlRewrite/Helper/UrlRewrite.php +++ b/app/code/Magento/UrlRewrite/Helper/UrlRewrite.php @@ -30,12 +30,12 @@ class UrlRewrite extends \Magento\Framework\App\Helper\AbstractHelper { if (strpos($requestPath, '//') !== false) { throw new \Exception( - __('Two and more slashes together are not permitted in request path'), + __('Do not use two or more consecutive slashes in the request path.'), self::VERR_MANYSLASHES ); } if (strpos($requestPath, '#') !== false) { - throw new \Exception(__('Anchor symbol (#) is not supported in request path'), self::VERR_ANCHOR); + throw new \Exception(__('Anchor symbol (#) is not supported in request path.'), self::VERR_ANCHOR); } return true; } @@ -76,11 +76,11 @@ class UrlRewrite extends \Magento\Framework\App\Helper\AbstractHelper switch ($e->getCode()) { case self::VERR_MANYSLASHES: throw new \Magento\Framework\Exception\LocalizedException( - __('Two and more slashes together are not permitted in url rewrite suffix') + __('Do not use two or more consecutive slashes in the url rewrite suffix.') ); case self::VERR_ANCHOR: throw new \Magento\Framework\Exception\LocalizedException( - __('Anchor symbol (#) is not supported in url rewrite suffix') + __('Anchor symbol (#) is not supported in url rewrite suffix.') ); } } diff --git a/app/code/Magento/UrlRewrite/composer.json b/app/code/Magento/UrlRewrite/composer.json index b961b2ebf0fa857ef7c0e814822b16a182a87b48..91f18fbea4728a982a17dca4cd56a0ac9f5ab88e 100644 --- a/app/code/Magento/UrlRewrite/composer.json +++ b/app/code/Magento/UrlRewrite/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-catalog-url-rewrite": "0.74.0-beta10", - "magento/module-cms": "0.74.0-beta10", - "magento/module-cms-url-rewrite": "0.74.0-beta10", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-catalog-url-rewrite": "0.74.0-beta13", + "magento/module-cms": "0.74.0-beta13", + "magento/module-cms-url-rewrite": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/User/Controller/Adminhtml/Auth/Forgotpassword.php b/app/code/Magento/User/Controller/Adminhtml/Auth/Forgotpassword.php index 046b494fdb98ab7437bdd85b75cc954bf3b3cd23..5f43bab59e6b863b06f8ddd1e0b8617ea9095d63 100644 --- a/app/code/Magento/User/Controller/Adminhtml/Auth/Forgotpassword.php +++ b/app/code/Magento/User/Controller/Adminhtml/Auth/Forgotpassword.php @@ -57,7 +57,7 @@ class Forgotpassword extends \Magento\User\Controller\Adminhtml\Auth $this->messageManager->addError(__('Please correct this email address:')); } } elseif (!empty($params)) { - $this->messageManager->addError(__('The email address is empty.')); + $this->messageManager->addError(__('Please enter an email address.')); } $this->_view->loadLayout(); $this->_view->renderLayout(); diff --git a/app/code/Magento/User/Model/User.php b/app/code/Magento/User/Model/User.php index 4b3fbc61396062d6c0d318bb0eb2554c6df1a018..9ab8a1039fcfba15ddc0e486a674098a6435878a 100644 --- a/app/code/Magento/User/Model/User.php +++ b/app/code/Magento/User/Model/User.php @@ -123,7 +123,7 @@ class User extends AbstractModel implements StorageInterface, UserInterface * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\Model\Resource\AbstractResource $resource * @param UserValidationRules $validationRules - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -140,7 +140,7 @@ class User extends AbstractModel implements StorageInterface, UserInterface \Magento\Store\Model\StoreManagerInterface $storeManager, UserValidationRules $validationRules, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_encryptor = $encryptor; @@ -484,7 +484,7 @@ class User extends AbstractModel implements StorageInterface, UserInterface throw new AuthenticationException(__('This account is inactive.')); } if (!$this->hasAssigned2Role($this->getId())) { - throw new AuthenticationException(__('Access denied.')); + throw new AuthenticationException(__('You need more permissions to access this.')); } $result = true; } diff --git a/app/code/Magento/User/Setup/UpgradeSchema.php b/app/code/Magento/User/Setup/UpgradeSchema.php new file mode 100644 index 0000000000000000000000000000000000000000..bab95673a66a016e03e2c0e8cc56db1a97fb6ab6 --- /dev/null +++ b/app/code/Magento/User/Setup/UpgradeSchema.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\User\Setup; + +use Magento\Framework\DB\Ddl\Table; +use Magento\Framework\Setup\UpgradeSchemaInterface; +use Magento\Framework\Setup\ModuleContextInterface; +use Magento\Framework\Setup\SchemaSetupInterface; + +/** + * @codeCoverageIgnore + */ +class UpgradeSchema implements UpgradeSchemaInterface +{ + /** + * {@inheritdoc} + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) + { + $installer = $setup; + $connection = $installer->getConnection(); + if (version_compare($context->getVersion(), '2.0.1') < 0) { + /** + * Modifying length of 'interface_locale' column of admin_user table. + */ + $table = $setup->getTable('admin_user'); + $connection->modifyColumn( + $table, + 'interface_locale', + [ + 'type' => Table::TYPE_TEXT, + 'length' => 16, + 'nullable' => false, + 'default' => 'en_US', + 'comment' => 'Backend interface locale', + ] + ); + } + } +} diff --git a/app/code/Magento/User/Test/Unit/Model/UserTest.php b/app/code/Magento/User/Test/Unit/Model/UserTest.php index c3c2b5fb1c7ac3145c500d9c1d1c7aff32f8e049..76facbc520bc8f469e71859c0114310462c39794 100644 --- a/app/code/Magento/User/Test/Unit/Model/UserTest.php +++ b/app/code/Magento/User/Test/Unit/Model/UserTest.php @@ -30,7 +30,7 @@ class UserTest extends \PHPUnit_Framework_TestCase /** @var \Magento\User\Model\Resource\User|\PHPUnit_Framework_MockObject_MockObject */ protected $_resourceMock; - /** @var \Magento\Framework\Data\Collection\Db|\PHPUnit_Framework_MockObject_MockObject */ + /** @var \Magento\Framework\Data\Collection\AbstractDb|\PHPUnit_Framework_MockObject_MockObject */ protected $_collectionMock; /** @var \Magento\Framework\Mail\TransportInterface|\PHPUnit_Framework_MockObject_MockObject */ @@ -69,10 +69,10 @@ class UserTest extends \PHPUnit_Framework_TestCase [] )->getMock(); $this->_collectionMock = $this->getMockBuilder( - 'Magento\Framework\Data\Collection\Db' + 'Magento\Framework\Data\Collection\AbstractDb' )->disableOriginalConstructor()->setMethods( [] - )->getMock(); + )->getMockForAbstractClass(); $coreRegistry = $this->getMockBuilder( 'Magento\Framework\Registry' )->disableOriginalConstructor()->setMethods( @@ -379,7 +379,10 @@ class UserTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue(true)); $this->_model->setIsActive(true); $this->_resourceMock->expects($this->once())->method('hasAssigned2Role')->will($this->returnValue(false)); - $this->setExpectedException('Magento\\Framework\\Exception\\AuthenticationException', 'Access denied.'); + $this->setExpectedException( + 'Magento\\Framework\\Exception\\AuthenticationException', + 'You need more permissions to access this.' + ); $this->_model->verifyIdentity($password); } } diff --git a/app/code/Magento/User/composer.json b/app/code/Magento/User/composer.json index f104204e33af9979e548288b11bca18131ba76e2..82c4b5609f4d62e0499e75a6a4f4147da21ebdf6 100644 --- a/app/code/Magento/User/composer.json +++ b/app/code/Magento/User/composer.json @@ -3,15 +3,15 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-authorization": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-integration": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-authorization": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-integration": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/User/etc/module.xml b/app/code/Magento/User/etc/module.xml index d0467cb70e860606c563d75a4deb29b59967ab6a..8bb2b470ccf553f51f260f94097338440af5a64b 100644 --- a/app/code/Magento/User/etc/module.xml +++ b/app/code/Magento/User/etc/module.xml @@ -6,7 +6,7 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd"> - <module name="Magento_User" setup_version="2.0.0"> + <module name="Magento_User" setup_version="2.0.1"> <sequence> <module name="Magento_Backend"/> </sequence> diff --git a/app/code/Magento/Usps/composer.json b/app/code/Magento/Usps/composer.json index 718aa4b4cf0f34747126e8a55ae5de514d0828fa..625a904edd642d843d9d02ec910e2616a242dd5f 100644 --- a/app/code/Magento/Usps/composer.json +++ b/app/code/Magento/Usps/composer.json @@ -3,20 +3,20 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-shipping": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/module-config": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-shipping": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/module-config": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "lib-libxml": "*", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Variable/Model/Variable.php b/app/code/Magento/Variable/Model/Variable.php index 9ab7bc8f73b90a93e063776d970d1c8b70bfde60..0a22c3fefaa1236fd9b516e3a370e94758d27d3b 100644 --- a/app/code/Magento/Variable/Model/Variable.php +++ b/app/code/Magento/Variable/Model/Variable.php @@ -38,7 +38,7 @@ class Variable extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Escaper $escaper * @param \Magento\Variable\Model\Resource\Variable $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -46,7 +46,7 @@ class Variable extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Framework\Escaper $escaper, \Magento\Variable\Model\Resource\Variable $resource, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_escaper = $escaper; @@ -69,6 +69,7 @@ class Variable extends \Magento\Framework\Model\AbstractModel * * @param integer $storeId * @return $this + * @codeCoverageIgnore */ public function setStoreId($storeId) { @@ -80,6 +81,7 @@ class Variable extends \Magento\Framework\Model\AbstractModel * Getter * * @return integer + * @codeCoverageIgnore */ public function getStoreId() { @@ -91,6 +93,7 @@ class Variable extends \Magento\Framework\Model\AbstractModel * * @param string $code * @return $this + * @codeCoverageIgnore */ public function loadByCode($code) { diff --git a/app/code/Magento/Variable/Model/Variable/Config.php b/app/code/Magento/Variable/Model/Variable/Config.php index a5c96bc10396a2ec0b4cec07a128625f969facdf..f89c73d9faeced4917b5173e22705468aed840de 100644 --- a/app/code/Magento/Variable/Model/Variable/Config.php +++ b/app/code/Magento/Variable/Model/Variable/Config.php @@ -71,6 +71,7 @@ class Config * Return url to wysiwyg plugin * * @return string + * @codeCoverageIgnore */ public function getWysiwygJsPluginSrc() { @@ -82,6 +83,7 @@ class Config * Return url of action to get variables * * @return string + * @codeCoverageIgnore */ public function getVariablesWysiwygActionUrl() { diff --git a/app/code/Magento/Variable/Test/Unit/Model/Variable/ConfigTest.php b/app/code/Magento/Variable/Test/Unit/Model/Variable/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a00c5ca54ef6a4e54cda5a1efd71068c6e6e87aa --- /dev/null +++ b/app/code/Magento/Variable/Test/Unit/Model/Variable/ConfigTest.php @@ -0,0 +1,55 @@ +<?php +/*** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Variable\Test\Unit\Model\Variable; + + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class ConfigTest extends \PHPUnit_Framework_TestCase +{ + public function testGetWysiwygPluginSettings() + { + $jsPluginSourceUrl = 'js-plugin-source'; + $actionUrl = 'action-url'; + $assetRepoMock = $this->getMockBuilder('Magento\Framework\View\Asset\Repository') + ->disableOriginalConstructor() + ->getMock(); + $urlMock = $this->getMockBuilder('Magento\Backend\Model\UrlInterface') + ->disableOriginalConstructor() + ->getMock(); + $assetRepoMock->expects($this->any()) + ->method('getUrl') + ->willReturn($jsPluginSourceUrl); + $urlMock->expects($this->any()) + ->method('getUrl') + ->willReturn($actionUrl); + + // Set up SUT + $args = [ + 'assetRepo' => $assetRepoMock, + 'url' => $urlMock + ]; + $model = (new ObjectManager($this))->getObject('Magento\Variable\Model\Variable\Config', $args); + + $customKey = 'key'; + $customVal = 'val'; + $configObject = new \Magento\Framework\Object(); + $configObject->setPlugins([[$customKey => $customVal]]); + + $variablePluginConfig = $model->getWysiwygPluginSettings($configObject)['plugins']; + $customPluginConfig = $variablePluginConfig[0]; + $addedPluginConfig = $variablePluginConfig[1]; + + // Verify custom plugin config is present + $this->assertSame($customVal, $customPluginConfig[$customKey]); + + // Verify added plugin config is present + $this->assertContains($actionUrl, $addedPluginConfig['options']['onclick']['subject']); + $this->assertContains($actionUrl, $addedPluginConfig['options']['url']); + $this->assertContains($jsPluginSourceUrl, $addedPluginConfig['src']); + } +} diff --git a/app/code/Magento/Variable/Test/Unit/Model/VariableTest.php b/app/code/Magento/Variable/Test/Unit/Model/VariableTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2bdaba7c8a06e023cdb62a2d62ebda4fc8f4b0a3 --- /dev/null +++ b/app/code/Magento/Variable/Test/Unit/Model/VariableTest.php @@ -0,0 +1,178 @@ +<?php +/*** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Variable\Test\Unit\Model; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class VariableTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Variable\Model\Variable */ + private $model; + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $escaperMock; + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $resourceMock; + + /** @var \Magento\Framework\Phrase */ + private $validationFailedPhrase; + + /** @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ + private $objectManager; + + public function setUp() + { + $this->objectManager = new ObjectManager($this); + $this->escaperMock = $this->getMockBuilder('Magento\Framework\Escaper') + ->disableOriginalConstructor() + ->getMock(); + $this->resourceMock = $this->getMockBuilder('Magento\Variable\Model\Resource\Variable') + ->disableOriginalConstructor() + ->getMock(); + $this->model = $this->objectManager->getObject( + 'Magento\Variable\Model\Variable', + [ + 'escaper' => $this->escaperMock, + 'resource' => $this->resourceMock + ] + ); + $this->validationFailedPhrase = __('Validation has failed.'); + } + + public function testGetValueHtml() + { + $type = \Magento\Variable\Model\Variable::TYPE_HTML; + $html = '<html/>'; + $this->model->setData('html_value', $html); + $this->assertSame($html, $this->model->getValue($type)); + } + + public function testGetValueEmptyHtml() + { + $type = \Magento\Variable\Model\Variable::TYPE_HTML; + $html = ''; + $plain = 'unescaped_plain_text'; + $escapedPlain = 'escaped_plain_text'; + $this->model->setData('html_value', $html); + $this->model->setData('plain_value', $plain); + $this->escaperMock->expects($this->once()) + ->method('escapeHtml') + ->with($plain) + ->willReturn($escapedPlain); + $this->assertSame($escapedPlain, $this->model->getValue($type)); + } + + public function testGetValueText() + { + $type = \Magento\Variable\Model\Variable::TYPE_TEXT; + $plain = 'plain'; + $this->model->setData('plain_value', $plain); + $this->assertSame($plain, $this->model->getValue($type)); + } + + /** + * @dataProvider validateMissingInfoDataProvider + */ + public function testValidateMissingInfo($code, $name) + { + $this->model->setCode($code)->setName($name); + $this->assertEquals($this->validationFailedPhrase, $this->model->validate()); + + } + + /** + * @dataProvider validateDataProvider + */ + public function testValidate($variableArray, $objectId, $expectedResult) + { + $code = 'variable_code'; + $this->model->setCode($code)->setName('some_name'); + $this->resourceMock->expects($this->once()) + ->method('getVariableByCode') + ->with($code) + ->willReturn($variableArray); + $this->model->setId($objectId); + $this->assertEquals($expectedResult, $this->model->validate($variableArray)); + } + + public function testGetVariablesOptionArrayNoGroup() + { + $origOptions = [ + ['value' => 'VAL', 'label' => 'LBL',] + ]; + + $transformedOptions = [ + ['value' => '{{customVar code=VAL}}', 'label' => __('%1', 'LBL')] + ]; + + $collectionMock = $this->getMockBuilder('\Magento\Variable\Model\Resource\Variable\Collection') + ->disableOriginalConstructor() + ->getMock(); + $collectionMock->expects($this->any()) + ->method('toOptionArray') + ->willReturn($origOptions); + $mockVariable = $this->getMock( + 'Magento\Variable\Model\Variable', + ['getCollection'], + $this->objectManager->getConstructArguments('Magento\Variable\Model\Variable') + ); + $mockVariable->expects($this->any()) + ->method('getCollection') + ->willReturn($collectionMock); + $this->assertEquals($transformedOptions, $mockVariable->getVariablesOptionArray()); + } + + public function testGetVariablesOptionArrayWithGroup() + { + $origOptions = [ + ['value' => 'VAL', 'label' => 'LBL',] + ]; + + $transformedOptions = [ + 'label' => __('Custom Variables'), + 'value' => [ + ['value' => '{{customVar code=VAL}}', 'label' => __('%1', 'LBL')] + ] + ]; + + $collectionMock = $this->getMockBuilder('\Magento\Variable\Model\Resource\Variable\Collection') + ->disableOriginalConstructor() + ->getMock(); + $collectionMock->expects($this->any()) + ->method('toOptionArray') + ->willReturn($origOptions); + $mockVariable = $this->getMock( + 'Magento\Variable\Model\Variable', + ['getCollection'], + $this->objectManager->getConstructArguments('Magento\Variable\Model\Variable') + ); + $mockVariable->expects($this->any()) + ->method('getCollection') + ->willReturn($collectionMock); + $this->assertEquals($transformedOptions, $mockVariable->getVariablesOptionArray(true)); + } + + public function validateDataProvider() + { + $variable = [ + 'variable_id' => 'matching_id', + ]; + return [ + 'Empty Variable' => [[], null, true], + 'IDs match' => [$variable, 'matching_id', true], + 'IDs do not match' => [$variable, 'non_matching_id', __('Variable Code must be unique.')] + ]; + } + + public function validateMissingInfoDataProvider() + { + return [ + 'Missing code' => ['', 'some-name'], + 'Missing name' => ['some-code', ''] + ]; + } +} diff --git a/app/code/Magento/Variable/composer.json b/app/code/Magento/Variable/composer.json index c73639455049ff266c4dded852265b03fb24908a..b61f8fe802c68ffa61e53966cb117e1f439a4436 100644 --- a/app/code/Magento/Variable/composer.json +++ b/app/code/Magento/Variable/composer.json @@ -3,14 +3,14 @@ "description": "N/A", "require": { "php": "~5.4.11|~5.5.0|~5.6.0", - "magento/module-backend": "0.74.0-beta10", - "magento/module-email": "0.74.0-beta10", - "magento/module-store": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-backend": "0.74.0-beta13", + "magento/module-email": "0.74.0-beta13", + "magento/module-store": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Version/composer.json b/app/code/Magento/Version/composer.json index af6036a882772de467679f79b048161ae119d631..4a3025af599865f283ba05b22341148d4412162e 100644 --- a/app/code/Magento/Version/composer.json +++ b/app/code/Magento/Version/composer.json @@ -3,11 +3,11 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Webapi/composer.json b/app/code/Magento/Webapi/composer.json index f3d9de0166e65788ecb72b8d7ac72f4fe4da86f0..94d5b769e85526178ded1e4a57d0488acccca8b6 100644 --- a/app/code/Magento/Webapi/composer.json +++ b/app/code/Magento/Webapi/composer.json @@ -3,18 +3,18 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-authorization": "0.74.0-beta10", - "magento/module-integration": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-authorization": "0.74.0-beta13", + "magento/module-integration": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-user": "0.74.0-beta10" + "magento/module-user": "0.74.0-beta13" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Weee/Block/Item/Price/Renderer.php b/app/code/Magento/Weee/Block/Item/Price/Renderer.php index 6541093aeda1153af2e589f3b301bc94a3c4b211..eb7ddf8a79b315f7680907a3a4424317c04e89ff 100644 --- a/app/code/Magento/Weee/Block/Item/Price/Renderer.php +++ b/app/code/Magento/Weee/Block/Item/Price/Renderer.php @@ -414,7 +414,7 @@ class Renderer extends \Magento\Tax\Block\Item\Price\Renderer $totalAmount = $item->getRowTotal() - $item->getDiscountAmount() + $item->getTaxAmount() - + $item->getHiddenTaxAmount() + + $item->getDiscountTaxCompensationAmount() + $this->weeeHelper->getRowWeeeTaxInclTax($item); return $totalAmount; @@ -431,7 +431,7 @@ class Renderer extends \Magento\Tax\Block\Item\Price\Renderer $totalAmount = $item->getBaseRowTotal() - $item->getBaseDiscountAmount() + $item->getBaseTaxAmount() - + $item->getBaseHiddenTaxAmount() + + $item->getBaseDiscountTaxCompensationAmount() + $this->weeeHelper->getBaseRowWeeeTaxInclTax($item); return $totalAmount; diff --git a/app/code/Magento/Weee/Model/Observer.php b/app/code/Magento/Weee/Model/Observer.php index adc961cd0357e66be67a17c16868070193ad5388..c5e0421eeeead2d413fd1b5d4041bd0fe2253ff6 100644 --- a/app/code/Magento/Weee/Model/Observer.php +++ b/app/code/Magento/Weee/Model/Observer.php @@ -54,7 +54,7 @@ class Observer extends \Magento\Framework\Model\AbstractModel * @param \Magento\Catalog\Model\Product\Type $productType * @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -68,7 +68,7 @@ class Observer extends \Magento\Framework\Model\AbstractModel \Magento\Catalog\Model\Product\Type $productType, \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_layout = $layout; diff --git a/app/code/Magento/Weee/Model/Tax.php b/app/code/Magento/Weee/Model/Tax.php index 13f1920912a2263d44b1b782cfdbaf37c12b7542..3b41cdeeb598382ab50aa542c442c0d672e0da65 100644 --- a/app/code/Magento/Weee/Model/Tax.php +++ b/app/code/Magento/Weee/Model/Tax.php @@ -97,7 +97,7 @@ class Tax extends \Magento\Framework\Model\AbstractModel * @param Resource\Tax $resource * @param Config $weeeConfig * @param PriceCurrencyInterface $priceCurrency - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -113,7 +113,7 @@ class Tax extends \Magento\Framework\Model\AbstractModel \Magento\Weee\Model\Resource\Tax $resource, \Magento\Weee\Model\Config $weeeConfig, PriceCurrencyInterface $priceCurrency, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_attributeFactory = $attributeFactory; diff --git a/app/code/Magento/Weee/Test/Unit/Block/Item/Price/RendererTest.php b/app/code/Magento/Weee/Test/Unit/Block/Item/Price/RendererTest.php index 399e1c7345d28939bb29242d6b01accca0fe665d..bf44e22e443d685bf086bb52a1a95c8a69d96d2c 100644 --- a/app/code/Magento/Weee/Test/Unit/Block/Item/Price/RendererTest.php +++ b/app/code/Magento/Weee/Test/Unit/Block/Item/Price/RendererTest.php @@ -753,7 +753,7 @@ class RendererTest extends \PHPUnit_Framework_TestCase { $rowTotal = 100; $taxAmount = 10; - $hiddenTaxAmount = 2; + $discountTaxCompensationAmount = 2; $discountAmount = 20; $weeeAmount = 5; @@ -761,7 +761,15 @@ class RendererTest extends \PHPUnit_Framework_TestCase $itemMock = $this->getMockBuilder('\Magento\Sales\Model\Order\Item') ->disableOriginalConstructor() - ->setMethods(['getRowTotal', 'getTaxAmount', 'getHiddenTaxAmount', 'getDiscountAmount', '__wakeup']) + ->setMethods( + [ + 'getRowTotal', + 'getTaxAmount', + 'getDiscountTaxCompensationAmount', + 'getDiscountAmount', + '__wakeup' + ] + ) ->getMock(); $itemMock->expects($this->once()) @@ -773,8 +781,8 @@ class RendererTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($taxAmount)); $itemMock->expects($this->once()) - ->method('getHiddenTaxAmount') - ->will($this->returnValue($hiddenTaxAmount)); + ->method('getDiscountTaxCompensationAmount') + ->will($this->returnValue($discountTaxCompensationAmount)); $itemMock->expects($this->once()) ->method('getDiscountAmount') @@ -792,16 +800,23 @@ class RendererTest extends \PHPUnit_Framework_TestCase { $baseRowTotal = 100; $baseTaxAmount = 10; - $baseHiddenTaxAmount = 2; + $baseDiscountTaxCompensationAmount = 2; $baseDiscountAmount = 20; $baseWeeeAmount = 5; - $expectedValue = $baseRowTotal + $baseTaxAmount + $baseHiddenTaxAmount - $baseDiscountAmount + $baseWeeeAmount; + $expectedValue = $baseRowTotal + $baseTaxAmount + $baseDiscountTaxCompensationAmount - + $baseDiscountAmount + $baseWeeeAmount; $itemMock = $this->getMockBuilder('\Magento\Sales\Model\Order\Item') ->disableOriginalConstructor() ->setMethods( - ['getBaseRowTotal', 'getBaseTaxAmount', 'getBaseHiddenTaxAmount', 'getBaseDiscountAmount', '__wakeup'] + [ + 'getBaseRowTotal', + 'getBaseTaxAmount', + 'getBaseDiscountTaxCompensationAmount', + 'getBaseDiscountAmount', + '__wakeup' + ] ) ->getMock(); @@ -814,8 +829,8 @@ class RendererTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($baseTaxAmount)); $itemMock->expects($this->once()) - ->method('getBaseHiddenTaxAmount') - ->will($this->returnValue($baseHiddenTaxAmount)); + ->method('getBaseDiscountTaxCompensationAmount') + ->will($this->returnValue($baseDiscountTaxCompensationAmount)); $itemMock->expects($this->once()) ->method('getBaseDiscountAmount') diff --git a/app/code/Magento/Weee/Test/Unit/Model/Total/Invoice/WeeeTest.php b/app/code/Magento/Weee/Test/Unit/Model/Total/Invoice/WeeeTest.php index d034947c48d71129a8ca1bbce59d39b69275d341..6b0c56965e84b6115bb40b7884cb11aa7bc24281 100644 --- a/app/code/Magento/Weee/Test/Unit/Model/Total/Invoice/WeeeTest.php +++ b/app/code/Magento/Weee/Test/Unit/Model/Total/Invoice/WeeeTest.php @@ -181,8 +181,8 @@ class WeeeTest extends \PHPUnit_Framework_TestCase 'data_fields' => [ 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 16.09, 'tax_invoiced' => 0, 'base_tax_amount' => 16.09, @@ -282,8 +282,8 @@ class WeeeTest extends \PHPUnit_Framework_TestCase 'data_fields' => [ 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 16.09, 'tax_invoiced' => 0, 'base_tax_amount' => 16.09, @@ -384,8 +384,8 @@ class WeeeTest extends \PHPUnit_Framework_TestCase 'data_fields' => [ 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 16.09, 'tax_invoiced' => 0, 'base_tax_amount' => 16.09, @@ -486,8 +486,8 @@ class WeeeTest extends \PHPUnit_Framework_TestCase 'data_fields' => [ 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 16.09, 'tax_invoiced' => 11.14, 'base_tax_amount' => 16.09, @@ -588,8 +588,8 @@ class WeeeTest extends \PHPUnit_Framework_TestCase 'data_fields' => [ 'shipping_tax_amount' => 1.24, 'base_shipping_tax_amount' => 1.24, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'tax_amount' => 16.09, 'tax_invoiced' => 0, 'base_tax_amount' => 16.09, diff --git a/app/code/Magento/Weee/composer.json b/app/code/Magento/Weee/composer.json index f61a9c20d89fd36ca8e52057f76834da1c30d5b3..ba0a615bab17ec2d4cd8221715dd418b87785220 100644 --- a/app/code/Magento/Weee/composer.json +++ b/app/code/Magento/Weee/composer.json @@ -3,21 +3,21 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-tax": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-directory": "0.74.0-beta10", - "magento/module-eav": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-quote": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-tax": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-directory": "0.74.0-beta13", + "magento/module-eav": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-quote": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Widget/Block/Adminhtml/Widget/Catalog/Category/Chooser.php b/app/code/Magento/Widget/Block/Adminhtml/Widget/Catalog/Category/Chooser.php new file mode 100755 index 0000000000000000000000000000000000000000..2fe2bd0646d8207729d9249cda5465a2f5cc5d83 --- /dev/null +++ b/app/code/Magento/Widget/Block/Adminhtml/Widget/Catalog/Category/Chooser.php @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Category chooser for widget's layout updates + * + * @author Magento Core Team <core@magentocommerce.com> + */ +namespace Magento\Widget\Block\Adminhtml\Widget\Catalog\Category; + +class Chooser extends \Magento\Catalog\Block\Adminhtml\Category\Widget\Chooser +{ + /** + * Get JSON of a tree node or an associative array + * + * @param \Magento\Framework\Data\Tree\Node|array $node + * @param int $level + * @return string + */ + protected function _getNodeJson($node, $level = 0) + { + $item = parent::_getNodeJson($node, $level); + $item['level'] = $node->getLevel(); + return $item; + } +} diff --git a/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance/Categories.php b/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance/Categories.php old mode 100644 new mode 100755 index dd6ee9667fa74f2591cf7828ef37fae6088d1bdc..468a5d1b7de41c0f2716804ff96380ca0999268e --- a/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance/Categories.php +++ b/app/code/Magento/Widget/Controller/Adminhtml/Widget/Instance/Categories.php @@ -8,26 +8,52 @@ namespace Magento\Widget\Controller\Adminhtml\Widget\Instance; class Categories extends \Magento\Widget\Controller\Adminhtml\Widget\Instance { + /** + * @var \Magento\Framework\View\Layout + */ + protected $layout; + + /** + * @param \Magento\Backend\App\Action\Context $context + * @param \Magento\Framework\Registry $coreRegistry + * @param \Magento\Widget\Model\Widget\InstanceFactory $widgetFactory + * @param \Psr\Log\LoggerInterface $logger + * @param \Magento\Framework\Math\Random $mathRandom + * @param \Magento\Framework\Translate\InlineInterface $translateInline + * @param \Magento\Framework\View\Layout $layout + */ + public function __construct( + \Magento\Backend\App\Action\Context $context, + \Magento\Framework\Registry $coreRegistry, + \Magento\Widget\Model\Widget\InstanceFactory $widgetFactory, + \Psr\Log\LoggerInterface $logger, + \Magento\Framework\Math\Random $mathRandom, + \Magento\Framework\Translate\InlineInterface $translateInline, + \Magento\Framework\View\Layout $layout + ) { + $this->layout = $layout; + parent::__construct($context, $coreRegistry, $widgetFactory, $logger, $mathRandom, $translateInline); + } + /** * Categories chooser Action (Ajax request) * - * @return void + * @return \Magento\Framework\Controller\Result\Raw */ public function execute() { $selected = $this->getRequest()->getParam('selected', ''); $isAnchorOnly = $this->getRequest()->getParam('is_anchor_only', 0); - $chooser = $this->_view->getLayout()->createBlock( - 'Magento\Catalog\Block\Adminhtml\Category\Widget\Chooser' - )->setUseMassaction( - true - )->setId( - $this->mathRandom->getUniqueHash('categories') - )->setIsAnchorOnly( - $isAnchorOnly - )->setSelectedCategories( - explode(',', $selected) - ); - $this->setBody($chooser->toHtml()); + + /** @var \Magento\Widget\Block\Adminhtml\Widget\Catalog\Category\Chooser $chooser */ + $chooser = $this->layout->createBlock('Magento\Widget\Block\Adminhtml\Widget\Catalog\Category\Chooser') + ->setUseMassaction(true) + ->setId($this->mathRandom->getUniqueHash('categories')) + ->setIsAnchorOnly($isAnchorOnly) + ->setSelectedCategories(explode(',', $selected)); + + /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ + $resultRaw = $this->resultFactory->create(\Magento\Framework\Controller\ResultFactory::TYPE_RAW); + return $resultRaw->setContents($chooser->toHtml()); } } diff --git a/app/code/Magento/Widget/Model/Layout/Update.php b/app/code/Magento/Widget/Model/Layout/Update.php index b8d6e965c2f8ed219890eae8cd3a52e89868c287..4e65a10c16dcd7c9005b593e109d44560c3eacb7 100644 --- a/app/code/Magento/Widget/Model/Layout/Update.php +++ b/app/code/Magento/Widget/Model/Layout/Update.php @@ -32,7 +32,7 @@ class Update extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -40,7 +40,7 @@ class Update extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Registry $registry, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_dateTime = $dateTime; diff --git a/app/code/Magento/Widget/Model/Widget/Instance.php b/app/code/Magento/Widget/Model/Widget/Instance.php index 16d357f77c670588660db9650f3ef08641747524..bc619ce9996912efb6c2ea15494b455026f8d731 100644 --- a/app/code/Magento/Widget/Model/Widget/Instance.php +++ b/app/code/Magento/Widget/Model/Widget/Instance.php @@ -121,7 +121,7 @@ class Instance extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Filesystem $filesystem * @param \Magento\Widget\Helper\Conditions $conditionsHelper * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $relatedCacheTypes * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -140,7 +140,7 @@ class Instance extends \Magento\Framework\Model\AbstractModel \Magento\Framework\Filesystem $filesystem, \Magento\Widget\Helper\Conditions $conditionsHelper, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $relatedCacheTypes = [], array $data = [] ) { diff --git a/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Catalog/Category/ChooserTest.php b/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Catalog/Category/ChooserTest.php new file mode 100755 index 0000000000000000000000000000000000000000..6f0f005c25fafaa4782affb7b87af27cc4765cbf --- /dev/null +++ b/app/code/Magento/Widget/Test/Unit/Block/Adminhtml/Widget/Catalog/Category/ChooserTest.php @@ -0,0 +1,139 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Widget\Test\Unit\Block\Adminhtml\Widget\Catalog\Category; + +class ChooserTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Catalog\Model\Resource\Category\Collection|\PHPUnit_Framework_MockObject_MockObject + */ + protected $collection; + + /** + * @var \Magento\Framework\Data\Tree\Node|\PHPUnit_Framework_MockObject_MockObject + */ + protected $childNode; + + /** + * @var \Magento\Framework\Data\Tree\Node|\PHPUnit_Framework_MockObject_MockObject + */ + protected $rootNode; + + /** + * @var \Magento\Catalog\Model\Resource\Category\Tree|\PHPUnit_Framework_MockObject_MockObject + */ + protected $categoryTree; + + /** + * @var \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject + */ + protected $store; + + /** + * @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManager; + + /** + * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $request; + + /** + * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject + */ + protected $escaper; + + /** + * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $eventManager; + + /** + * @var \Magento\Backend\Block\Template\Context|\PHPUnit_Framework_MockObject_MockObject + */ + protected $context; + + public function setUp() + { + $this->collection = $this->getMock('Magento\Catalog\Model\Resource\Category\Collection', [], [], '', false); + + $this->childNode = $this->getMock( + 'Magento\Framework\Data\Tree\Node', + ['getLevel', 'hasChildren'], + [], + '', + false + ); + $this->rootNode = $this->getMock( + 'Magento\Framework\Data\Tree\Node', + ['getLevel', 'hasChildren', 'getChildren'], + [], + '', + false + ); + $this->categoryTree = $this->getMock('Magento\Catalog\Model\Resource\Category\Tree', [], [], '', false); + $this->store = $this->getMock('Magento\Store\Model\Store', [], [], '', false); + $this->storeManager = $this->getMock('Magento\Store\Model\StoreManagerInterface', [], [], '', false); + $this->request = $this->getMock('Magento\Framework\App\RequestInterface', [], [], '', false); + $this->escaper = $this->getMock('Magento\Framework\Escaper', [], [], '', false); + $this->eventManager = $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false); + $this->context = $this->getMock('Magento\Backend\Block\Template\Context', [], [], '', false); + } + + public function testGetTreeHasLevelField() + { + $rootId = \Magento\Catalog\Model\Category::TREE_ROOT_ID; + $storeGroups = []; + $storeId = 1; + $rootLevel = 2; + $level = 3; + + $this->collection->expects($this->any())->method('addAttributeToSelect')->willReturnMap( + [ + ['url_key', false, $this->collection], + ['is_anchor', false, $this->collection] + ] + ); + + $this->childNode->expects($this->atLeastOnce())->method('getLevel')->willReturn($level); + + $this->rootNode->expects($this->atLeastOnce())->method('getLevel')->willReturn($rootLevel); + $this->rootNode->expects($this->once())->method('hasChildren')->willReturn(true); + $this->rootNode->expects($this->once())->method('getChildren')->willReturn([$this->childNode]); + + $this->categoryTree->expects($this->once())->method('load')->with(null, 3)->willReturnSelf(); + $this->categoryTree->expects($this->atLeastOnce()) + ->method('addCollectionData') + ->with($this->collection) + ->willReturnSelf(); + $this->categoryTree->expects($this->once())->method('getNodeById')->with($rootId)->willReturn($this->rootNode); + + $this->store->expects($this->atLeastOnce())->method('getId')->willReturn($storeId); + + $this->storeManager->expects($this->once())->method('getGroups')->willReturn($storeGroups); + $this->storeManager->expects($this->atLeastOnce())->method('getStore')->willReturn($this->store); + + $this->context->expects($this->once())->method('getStoreManager')->willReturn($this->storeManager); + $this->context->expects($this->once())->method('getRequest')->willReturn($this->request); + $this->context->expects($this->once())->method('getEscaper')->willReturn($this->escaper); + $this->context->expects($this->once())->method('getEventManager')->willReturn($this->eventManager); + + /** @var \Magento\Widget\Block\Adminhtml\Widget\Catalog\Category\Chooser $chooser */ + $chooser = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this)) + ->getObject( + 'Magento\Widget\Block\Adminhtml\Widget\Catalog\Category\Chooser', + [ + 'categoryTree' => $this->categoryTree, + 'context' => $this->context + ] + ); + $chooser->setData('category_collection', $this->collection); + $result = $chooser->getTree(); + $this->assertEquals($level, $result[0]['level']); + } +} diff --git a/app/code/Magento/Widget/Test/Unit/Controller/Adminhtml/Widget/Instance/CategoriesTest.php b/app/code/Magento/Widget/Test/Unit/Controller/Adminhtml/Widget/Instance/CategoriesTest.php new file mode 100755 index 0000000000000000000000000000000000000000..5a03ca570269871e81da22280dfc25da5bfbd65d --- /dev/null +++ b/app/code/Magento/Widget/Test/Unit/Controller/Adminhtml/Widget/Instance/CategoriesTest.php @@ -0,0 +1,125 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Widget\Test\Unit\Controller\Adminhtml\Widget\Instance; + +class CategoriesTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $request; + + /** + * @var \Magento\Framework\Math\Random|\PHPUnit_Framework_MockObject_MockObject + */ + protected $mathRandom; + + /** + * @var \Magento\Framework\View\Layout|\PHPUnit_Framework_MockObject_MockObject + */ + protected $chooser; + + /** + * @var string + */ + protected $blockClass = 'Magento\Widget\Block\Adminhtml\Widget\Catalog\Category\Chooser'; + + /** + * @var \Magento\Framework\View\Layout|\PHPUnit_Framework_MockObject_MockObject + */ + protected $layout; + + /** + * @var \Magento\Framework\Controller\Result\Raw|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultRaw; + + /** + * @var \Magento\Framework\Controller\ResultFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resultFactory; + + /** + * @var \Magento\Backend\App\Action\Context|\PHPUnit_Framework_MockObject_MockObject + */ + protected $context; + + /** + * @var \Magento\Widget\Controller\Adminhtml\Widget\Instance\Categories + */ + protected $controller; + + public function setUp() + { + $this->request = $this->getMock('Magento\Framework\App\RequestInterface', [], [], '', false); + $this->mathRandom = $this->getMock('Magento\Framework\Math\Random', [], [], '', false); + $this->chooser = $this->getMock( + $this->blockClass, + ['setUseMassaction', 'setId', 'setIsAnchorOnly', 'setSelectedCategories', 'toHtml'], + [], + '', + false + ); + $this->layout = $this->getMock('Magento\Framework\View\Layout', [], [], '', false); + $this->resultRaw = $this->getMock('Magento\Framework\Controller\Result\Raw', [], [], '', false); + $this->resultFactory = $this->getMock('Magento\Framework\Controller\ResultFactory', [], [], '', false); + $this->context = $this->getMock('Magento\Backend\App\Action\Context', [], [], '', false); + } + + public function testExecute() + { + $selectedCategories = '1'; + $isAnchorOnly = true; + $hash = '7e6baeca2d76ca0efc3a299986d31bdc9cd796fb'; + $content = 'block_content'; + + $this->request->expects($this->any())->method('getParam')->willReturnMap( + [ + ['selected', '', $selectedCategories], + ['is_anchor_only', 0, $isAnchorOnly] + ] + ); + + $this->mathRandom->expects($this->once())->method('getUniqueHash')->with('categories')->willReturn($hash); + + $this->chooser->expects($this->once())->method('setUseMassaction')->with()->willReturnSelf(); + $this->chooser->expects($this->once())->method('setId')->with($hash)->willReturnSelf(); + $this->chooser->expects($this->once())->method('setIsAnchorOnly')->with($isAnchorOnly)->willReturnSelf(); + $this->chooser->expects($this->once()) + ->method('setSelectedCategories') + ->with(explode(',', $selectedCategories)) + ->willReturnSelf(); + $this->chooser->expects($this->once())->method('toHtml')->willReturn($content); + + $this->layout->expects($this->once()) + ->method('createBlock') + ->with($this->blockClass) + ->willReturn($this->chooser); + + $this->resultRaw->expects($this->once())->method('setContents')->with($content)->willReturnSelf(); + + $this->resultFactory->expects($this->once()) + ->method('create') + ->with(\Magento\Framework\Controller\ResultFactory::TYPE_RAW) + ->willReturn($this->resultRaw); + + $this->context->expects($this->once())->method('getRequest')->willReturn($this->request); + $this->context->expects($this->once())->method('getResultFactory')->willReturn($this->resultFactory); + + /** @var \Magento\Widget\Controller\Adminhtml\Widget\Instance\Categories $controller */ + $this->controller = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this)) + ->getObject( + 'Magento\Widget\Controller\Adminhtml\Widget\Instance\Categories', + [ + 'context' => $this->context, + 'mathRandom' => $this->mathRandom, + 'layout' => $this->layout + ] + ); + $this->assertSame($this->resultRaw, $this->controller->execute()); + } +} diff --git a/app/code/Magento/Widget/composer.json b/app/code/Magento/Widget/composer.json index 4970a1a7c75182f80922db58ed43678ad68e715c..cfecd20e99f1b7ad876322a228f0868b448e1c05 100644 --- a/app/code/Magento/Widget/composer.json +++ b/app/code/Magento/Widget/composer.json @@ -3,17 +3,17 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-cms": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-variable": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-cms": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-variable": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Widget/view/adminhtml/templates/catalog/category/widget/tree.phtml b/app/code/Magento/Widget/view/adminhtml/templates/catalog/category/widget/tree.phtml new file mode 100755 index 0000000000000000000000000000000000000000..a0f60f63ee64e511c0993ed411f72790cb27cead --- /dev/null +++ b/app/code/Magento/Widget/view/adminhtml/templates/catalog/category/widget/tree.phtml @@ -0,0 +1,189 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +?> + +<?php $_divId = 'tree' . $block->getId() ?> +<div id="<?php echo $_divId ?>" class="tree"></div> +<!--[if IE]> +<script id="ie-deferred-loader" defer="defer" src=""></script> +<![endif]--> +<script> +require(['jquery', "prototype", "extjs/ext-tree-checkbox"], function(jQuery){ + +var tree<?php echo $block->getId() ?>; + +var useMassaction = <?php echo $block->getUseMassaction() ? 1 : 0; ?>; + +var isAnchorOnly = <?php echo $block->getIsAnchorOnly() ? 1 : 0; ?>; + +Ext.tree.TreePanel.Enhanced = function(el, config) +{ + Ext.tree.TreePanel.Enhanced.superclass.constructor.call(this, el, config); +}; + +Ext.extend(Ext.tree.TreePanel.Enhanced, Ext.tree.TreePanel, { + + loadTree : function(config, firstLoad) + { + var parameters = config['parameters']; + var data = config['data']; + + if ((typeof parameters['root_visible']) != 'undefined') { + this.rootVisible = parameters['root_visible']*1; + } + + var root = new Ext.tree.TreeNode(parameters); + + this.nodeHash = {}; + this.setRootNode(root); + + if (firstLoad) { + <?php if ($block->getNodeClickListener()): ?> + this.addListener('click', <?php echo $block->getNodeClickListener() ?>.createDelegate(this)); + <?php endif; ?> + } + + this.loader.buildCategoryTree(root, data); + this.el.dom.innerHTML = ''; + // render the tree + this.render(); + } +}); + +jQuery(function() +{ + var emptyNodeAdded = <?php echo($block->getWithEmptyNode() ? 'false' : 'true') ?>; + + var categoryLoader = new Ext.tree.TreeLoader({ + dataUrl: '<?php echo $block->getLoadTreeUrl() ?>' + }); + + categoryLoader.buildCategoryTree = function(parent, config) + { + if (!config) return null; + + + if (parent && config && config.length){ + for (var i = 0; i < config.length; i++) { + var node; + if (useMassaction && config[i].level != 1) { + config[i].uiProvider = Ext.tree.CheckboxNodeUI; + } + var _node = Object.clone(config[i]); + + // Add empty node to reset category filter + if(!emptyNodeAdded) { + var empty = Object.clone(_node); + empty.text = '<?php echo __('None') ?>'; + empty.children = []; + empty.id = 'none'; + empty.path = '1/none'; + empty.cls = 'leaf'; + parent.appendChild(new Ext.tree.TreeNode(empty)); + emptyNodeAdded = true; + } + + if (_node.children && !_node.children.length) { + delete(_node.children); + node = new Ext.tree.AsyncTreeNode(_node); + } else { + node = new Ext.tree.TreeNode(config[i]); + } + parent.appendChild(node); + node.loader = node.getOwnerTree().loader; + node.loader = node.getOwnerTree().loader; + if (_node.children) { + this.buildCategoryTree(node, _node.children); + } + } + } + }; + + categoryLoader.createNode = function(config) { + var node; + if (useMassaction && config.level != 1) { + config.uiProvider = Ext.tree.CheckboxNodeUI; + } + var _node = Object.clone(config); + if (config.children && !config.children.length) { + delete(config.children); + node = new Ext.tree.AsyncTreeNode(config); + } else { + node = new Ext.tree.TreeNode(config); + } + return node; + }; + + categoryLoader.buildHash = function(node) + { + var hash = {}; + + hash = this.toArray(node.attributes); + + if (node.childNodes.length>0 || (node.loaded==false && node.loading==false)) { + hash['children'] = new Array; + + for (var i = 0, len = node.childNodes.length; i < len; i++) { + if (!hash['children']) { + hash['children'] = new Array; + } + hash['children'].push(this.buildHash(node.childNodes[i])); + } + } + + return hash; + }; + + categoryLoader.toArray = function(attributes) { + var data = {}; + for (var key in attributes) { + var value = attributes[key]; + data[key] = value; + } + + return data; + }; + + categoryLoader.on("beforeload", function(treeLoader, node) { + $('<?php echo $_divId; ?>').fire('category:beforeLoad', {treeLoader:treeLoader}); + treeLoader.baseParams.id = node.attributes.id; + }); + + tree<?php echo $block->getId() ?> = new Ext.tree.TreePanel.Enhanced('<?php echo $_divId ?>', { + animate: false, + loader: categoryLoader, + enableDD: false, + containerScroll: true, + rootVisible: '<?php echo $block->getRoot()->getIsVisible() ?>', + useAjax: true, + currentNodeId: <?php echo (int) $block->getCategoryId() ?>, + addNodeTo: false + }); + + if (useMassaction) { + tree<?php echo $block->getId() ?>.on('check', function(node) { + $('<?php echo $_divId; ?>').fire('node:changed', {node:node}); + }, tree<?php echo $block->getId() ?>); + } + + // set the root node + var parameters = { + text: 'Psw', + draggable: false, + id: <?php echo (int) $block->getRoot()->getId() ?>, + expanded: <?php echo (int) $block->getIsWasExpanded() ?>, + category_id: <?php echo (int) $block->getCategoryId() ?> + }; + + tree<?php echo $block->getId() ?>.loadTree({parameters:parameters, data:<?php echo $block->getTreeJson() ?>},true); + +}); + +}); +</script> diff --git a/app/code/Magento/Wishlist/Block/AbstractBlock.php b/app/code/Magento/Wishlist/Block/AbstractBlock.php index 48f5f722c297e98d3f0b7db6a1d66a8c7fa5f4e9..0bdadcec99084e307b67ed953939a2f258918ba7 100644 --- a/app/code/Magento/Wishlist/Block/AbstractBlock.php +++ b/app/code/Magento/Wishlist/Block/AbstractBlock.php @@ -148,6 +148,16 @@ abstract class AbstractBlock extends \Magento\Catalog\Block\Product\AbstractProd return $this->_getHelper()->getSharedAddToCartUrl($item); } + /** + * Retrieve URL for adding All items to shopping cart from shared wishlist + * + * @return string + */ + public function getSharedAddAllToCartUrl() + { + return $this->_getHelper()->getSharedAddAllToCartUrl(); + } + /** * Retrieve params for adding Product to wishlist * diff --git a/app/code/Magento/Wishlist/Block/Adminhtml/WishlistTab.php b/app/code/Magento/Wishlist/Block/Adminhtml/WishlistTab.php index 6a6d83a1bdabef4d2d3f7d7c47b50a9c157b574a..529db935154700a6af3e725dd91ba2f8763b4fb8 100644 --- a/app/code/Magento/Wishlist/Block/Adminhtml/WishlistTab.php +++ b/app/code/Magento/Wishlist/Block/Adminhtml/WishlistTab.php @@ -56,7 +56,7 @@ class WishlistTab extends TabWrapper implements TabInterface */ public function getTabLabel() { - return __('Wishlist'); + return __('Wish List'); } /** diff --git a/app/code/Magento/Wishlist/Controller/Index/Add.php b/app/code/Magento/Wishlist/Controller/Index/Add.php index 3f307ad116dd84ad63d0befb0adde4a4919654a7..392ef5f21ab5b7c4d722e6b213914f12582fd5f0 100755 --- a/app/code/Magento/Wishlist/Controller/Index/Add.php +++ b/app/code/Magento/Wishlist/Controller/Index/Add.php @@ -115,17 +115,17 @@ class Add extends Action\Action implements IndexInterface $this->_objectManager->get('Magento\Wishlist\Helper\Data')->calculate(); $message = __( - '%1 has been added to your wishlist. Click <a href="%2">here</a> to continue shopping.', + '%1 has been added to your Wish List. Click <a href="%2">here</a> to continue shopping.', $this->_objectManager->get('Magento\Framework\Escaper')->escapeHtml($product->getName()), $this->_objectManager->get('Magento\Framework\Escaper')->escapeUrl($referer) ); $this->messageManager->addSuccess($message); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError( - __('An error occurred while adding item to wish list: %1', $e->getMessage()) + __('We can\'t add the item to Wish List right now: %1.', $e->getMessage()) ); } catch (\Exception $e) { - $this->messageManager->addError(__('An error occurred while adding item to wish list.')); + $this->messageManager->addError(__('We can\'t add the item to Wish List right now.')); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } diff --git a/app/code/Magento/Wishlist/Controller/Index/Cart.php b/app/code/Magento/Wishlist/Controller/Index/Cart.php index 5274e565c1b029777fdc7d6ec9d8753f5e7d64dc..89d070df012bada857faab47710b331c64bf2499 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Cart.php +++ b/app/code/Magento/Wishlist/Controller/Index/Cart.php @@ -184,7 +184,7 @@ class Cart extends Action\Action implements IndexInterface $this->messageManager->addNotice($e->getMessage()); $redirectUrl = $configureUrl; } catch (\Exception $e) { - $this->messageManager->addException($e, __('Cannot add item to shopping cart')); + $this->messageManager->addException($e, __('We can\'t add the item to the cart right now.')); } $this->helper->calculate(); diff --git a/app/code/Magento/Wishlist/Controller/Index/Configure.php b/app/code/Magento/Wishlist/Controller/Index/Configure.php index 37522cd4cd0dac0bf1719106db853dbba4190744..5f19495da681fcff977e1f92d1170e352c948ebb 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Configure.php +++ b/app/code/Magento/Wishlist/Controller/Index/Configure.php @@ -63,7 +63,9 @@ class Configure extends Action\Action implements IndexInterface $item = $this->_objectManager->create('Magento\Wishlist\Model\Item'); $item->loadWithOptions($id); if (!$item->getId()) { - throw new \Magento\Framework\Exception\LocalizedException(__('We can\'t load the wish list item.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('We can\'t load the Wish List item right now.') + ); } $wishlist = $this->wishlistProvider->getWishlist($item->getWishlistId()); if (!$wishlist) { @@ -101,7 +103,7 @@ class Configure extends Action\Action implements IndexInterface $resultRedirect->setPath('*'); return $resultRedirect; } catch (\Exception $e) { - $this->messageManager->addError(__('We can\'t configure the product.')); + $this->messageManager->addError(__('We can\'t configure the product right now.')); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); $resultRedirect->setPath('*'); return $resultRedirect; diff --git a/app/code/Magento/Wishlist/Controller/Index/Remove.php b/app/code/Magento/Wishlist/Controller/Index/Remove.php index 6a07bcbc9e03b6634f6c7d08fd7563e1650493ea..93cb0131b41af977b5909dbc46a4f81f9680151c 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Remove.php +++ b/app/code/Magento/Wishlist/Controller/Index/Remove.php @@ -51,10 +51,10 @@ class Remove extends Action\Action implements IndexInterface $wishlist->save(); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError( - __('An error occurred while deleting the item from wish list: %1', $e->getMessage()) + __('We can\'t delete the item from Wish List right now because of an error: %1.', $e->getMessage()) ); } catch (\Exception $e) { - $this->messageManager->addError(__('An error occurred while deleting the item from wish list.')); + $this->messageManager->addError(__('We can\'t delete the item from the Wish List right now.')); } $this->_objectManager->get('Magento\Wishlist\Helper\Data')->calculate(); diff --git a/app/code/Magento/Wishlist/Controller/Index/Send.php b/app/code/Magento/Wishlist/Controller/Index/Send.php index 591da81b0aab9f36ebcd3654bf5290fa91b11242..4e5e9fb2ffe7f985845df88428cc59793501c19f 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Send.php +++ b/app/code/Magento/Wishlist/Controller/Index/Send.php @@ -7,7 +7,10 @@ namespace Magento\Wishlist\Controller\Index; use Magento\Framework\App\Action; +use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Exception\NotFoundException; +use Magento\Framework\Session\Generic as WishlistSession; +use Magento\Store\Model\StoreManagerInterface; use Magento\Wishlist\Controller\IndexInterface; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\View\Result\Layout as ResultLayout; @@ -52,6 +55,21 @@ class Send extends Action\Action implements IndexInterface */ protected $_formKeyValidator; + /** + * @var WishlistSession + */ + protected $wishlistSession; + + /** + * @var ScopeConfigInterface + */ + protected $scopeConfig; + + /** + * @var StoreManagerInterface + */ + protected $storeManager; + /** * @param Action\Context $context * @param \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator @@ -61,6 +79,10 @@ class Send extends Action\Action implements IndexInterface * @param \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder * @param \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation * @param \Magento\Customer\Helper\View $customerHelperView + * @param WishlistSession $wishlistSession + * @param ScopeConfigInterface $scopeConfig + * @param StoreManagerInterface $storeManager + * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( Action\Context $context, @@ -70,7 +92,10 @@ class Send extends Action\Action implements IndexInterface \Magento\Wishlist\Model\Config $wishlistConfig, \Magento\Framework\Mail\Template\TransportBuilder $transportBuilder, \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation, - \Magento\Customer\Helper\View $customerHelperView + \Magento\Customer\Helper\View $customerHelperView, + WishlistSession $wishlistSession, + ScopeConfigInterface $scopeConfig, + StoreManagerInterface $storeManager ) { $this->_formKeyValidator = $formKeyValidator; $this->_customerSession = $customerSession; @@ -79,6 +104,9 @@ class Send extends Action\Action implements IndexInterface $this->_transportBuilder = $transportBuilder; $this->inlineTranslation = $inlineTranslation; $this->_customerHelperView = $customerHelperView; + $this->wishlistSession = $wishlistSession; + $this->scopeConfig = $scopeConfig; + $this->storeManager = $storeManager; parent::__construct($context); } @@ -108,7 +136,10 @@ class Send extends Action\Action implements IndexInterface $sharingLimit = $this->_wishlistConfig->getSharingEmailLimit(); $textLimit = $this->_wishlistConfig->getSharingTextLimit(); $emailsLeft = $sharingLimit - $wishlist->getShared(); - $emails = explode(',', $this->getRequest()->getPost('emails')); + + $emails = $this->getRequest()->getPost('emails'); + $emails = empty($emails) ? $emails : explode(',', $emails); + $error = false; $message = (string)$this->getRequest()->getPost('message'); if (strlen($message) > $textLimit) { @@ -116,10 +147,10 @@ class Send extends Action\Action implements IndexInterface } else { $message = nl2br(htmlspecialchars($message)); if (empty($emails)) { - $error = __('Email address can\'t be empty.'); + $error = __('Please enter an email address.'); } else { if (count($emails) > $emailsLeft) { - $error = __('This wishlist can be shared %1 more times.', $emailsLeft); + $error = __('This wish list can be shared %1 more times.', $emailsLeft); } else { foreach ($emails as $index => $email) { $email = trim($email); @@ -135,11 +166,7 @@ class Send extends Action\Action implements IndexInterface if ($error) { $this->messageManager->addError($error); - $this->_objectManager->get( - 'Magento\Wishlist\Model\Session' - )->setSharingForm( - $this->getRequest()->getPostValue() - ); + $this->wishlistSession->setSharingForm($this->getRequest()->getPostValue()); $resultRedirect->setPath('*/*/share'); return $resultRedirect; } @@ -159,18 +186,16 @@ class Send extends Action\Action implements IndexInterface $sharingCode = $wishlist->getSharingCode(); try { - $scopeConfig = $this->_objectManager->get('Magento\Framework\App\Config\ScopeConfigInterface'); - $storeManager = $this->_objectManager->get('Magento\Store\Model\StoreManagerInterface'); foreach ($emails as $email) { $transport = $this->_transportBuilder->setTemplateIdentifier( - $scopeConfig->getValue( + $this->scopeConfig->getValue( 'wishlist/email/email_template', \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) )->setTemplateOptions( [ 'area' => \Magento\Framework\App\Area::AREA_FRONTEND, - 'store' => $storeManager->getStore()->getStoreId(), + 'store' => $this->storeManager->getStore()->getStoreId(), ] )->setTemplateVars( [ @@ -178,13 +203,12 @@ class Send extends Action\Action implements IndexInterface 'customerName' => $customerName, 'salable' => $wishlist->isSalable() ? 'yes' : '', 'items' => $this->getWishlistItems($resultLayout), - 'addAllLink' => $this->_url->getUrl('*/shared/allcart', ['code' => $sharingCode]), 'viewOnSiteLink' => $this->_url->getUrl('*/shared/index', ['code' => $sharingCode]), 'message' => $message, - 'store' => $storeManager->getStore(), + 'store' => $this->storeManager->getStore(), ] )->setFrom( - $scopeConfig->getValue( + $this->scopeConfig->getValue( 'wishlist/email/email_identity', \Magento\Store\Model\ScopeInterface::SCOPE_STORE ) @@ -213,11 +237,7 @@ class Send extends Action\Action implements IndexInterface } catch (\Exception $e) { $this->inlineTranslation->resume(); $this->messageManager->addError($e->getMessage()); - $this->_objectManager->get( - 'Magento\Wishlist\Model\Session' - )->setSharingForm( - $this->getRequest()->getPostValue() - ); + $this->wishlistSession->setSharingForm($this->getRequest()->getPostValue()); $resultRedirect->setPath('*/*/share'); return $resultRedirect; } diff --git a/app/code/Magento/Wishlist/Controller/Index/Update.php b/app/code/Magento/Wishlist/Controller/Index/Update.php index ab7c5efd3d88aaf958418273106c46d66cf1b0e6..ccb46f1c44a8ce873ce7ff779ffa760e724b31e2 100644 --- a/app/code/Magento/Wishlist/Controller/Index/Update.php +++ b/app/code/Magento/Wishlist/Controller/Index/Update.php @@ -100,7 +100,7 @@ class Update extends Action\Action implements IndexInterface $item->delete(); } catch (\Exception $e) { $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); - $this->messageManager->addError(__('Can\'t delete item from wishlist')); + $this->messageManager->addError(__('We can\'t delete item from Wish List right now.')); } } diff --git a/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php b/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php index b9dee182873329586d901c6fd32ca9e18116fd95..1796edb9d2566009f835277f9f8f373857d4ac44 100644 --- a/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php +++ b/app/code/Magento/Wishlist/Controller/Index/UpdateItemOptions.php @@ -96,12 +96,12 @@ class UpdateItemOptions extends Action\Action implements IndexInterface $this->_objectManager->get('Magento\Wishlist\Helper\Data')->calculate(); - $message = __('%1 has been updated in your wish list.', $product->getName()); + $message = __('%1 has been updated in your Wish List.', $product->getName()); $this->messageManager->addSuccess($message); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { - $this->messageManager->addError(__('An error occurred while updating wish list.')); + $this->messageManager->addError(__('We can\'t update your Wish List right now.')); $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); } $resultRedirect->setPath('*/*', ['wishlist_id' => $wishlist->getId()]); diff --git a/app/code/Magento/Wishlist/Controller/Shared/Cart.php b/app/code/Magento/Wishlist/Controller/Shared/Cart.php index 5c1efa80aec9ed522b32785b837805a0c05ab120..7f697310de2425a75fd686f3d1472f5a2eee71a8 100644 --- a/app/code/Magento/Wishlist/Controller/Shared/Cart.php +++ b/app/code/Magento/Wishlist/Controller/Shared/Cart.php @@ -5,10 +5,71 @@ */ namespace Magento\Wishlist\Controller\Shared; +use Magento\Checkout\Helper\Cart as CartHelper; +use Magento\Checkout\Model\Cart as CustomerCart; +use Magento\Framework\App\Action\Context as ActionContext; use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\Escaper; +use Magento\Framework\Exception\LocalizedException; +use Magento\Wishlist\Model\Item; +use Magento\Wishlist\Model\Item\OptionFactory; +use Magento\Wishlist\Model\ItemFactory; +use Magento\Wishlist\Model\Resource\Item\Option\Collection as OptionCollection; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Cart extends \Magento\Framework\App\Action\Action { + /** + * @var CustomerCart + */ + protected $cart; + + /** + * @var OptionFactory + */ + protected $optionFactory; + + /** + * @var ItemFactory + */ + protected $itemFactory; + + /** + * @var CartHelper + */ + protected $cartHelper; + + /** + * @var Escaper + */ + protected $escaper; + + /** + * @param ActionContext $context + * @param CustomerCart $cart + * @param OptionFactory $optionFactory + * @param ItemFactory $itemFactory + * @param CartHelper $cartHelper + * @param Escaper $escaper + */ + public function __construct( + ActionContext $context, + CustomerCart $cart, + OptionFactory $optionFactory, + ItemFactory $itemFactory, + CartHelper $cartHelper, + Escaper $escaper + ) { + $this->cart = $cart; + $this->optionFactory = $optionFactory; + $this->itemFactory = $itemFactory; + $this->cartHelper = $cartHelper; + $this->escaper = $escaper; + parent::__construct($context); + } + /** * Add shared wishlist item to shopping cart * @@ -21,36 +82,41 @@ class Cart extends \Magento\Framework\App\Action\Action { $itemId = (int)$this->getRequest()->getParam('item'); - /* @var $item \Magento\Wishlist\Model\Item */ - $item = $this->_objectManager->create('Magento\Wishlist\Model\Item')->load($itemId); - - $cart = $this->_objectManager->get('Magento\Checkout\Model\Cart'); + /* @var $item Item */ + $item = $this->itemFactory->create() + ->load($itemId); $redirectUrl = $this->_redirect->getRefererUrl(); try { - $options = $this->_objectManager->create( - 'Magento\Wishlist\Model\Item\Option' - )->getCollection()->addItemFilter( - [$itemId] - ); + /** @var OptionCollection $options */ + $options = $this->optionFactory->create() + ->getCollection()->addItemFilter([$itemId]); $item->setOptions($options->getOptionsByItem($itemId)); + $item->addToCart($this->cart); + + $this->cart->save(); - $item->addToCart($cart); - $cart->save()->getQuote()->collectTotals(); + if (!$this->cart->getQuote()->getHasError()) { + $message = __( + 'You added %1 to your shopping cart.', + $this->escaper->escapeHtml($item->getProduct()->getName()) + ); + $this->messageManager->addSuccess($message); + } - if ($this->_objectManager->get('Magento\Checkout\Helper\Cart')->getShouldRedirectToCart()) { - $redirectUrl = $this->_objectManager->get('Magento\Checkout\Helper\Cart')->getCartUrl(); + if ($this->cartHelper->getShouldRedirectToCart()) { + $redirectUrl = $this->cartHelper->getCartUrl(); } - } catch (\Magento\Framework\Exception\LocalizedException $e) { - if ($e->getCode() == \Magento\Wishlist\Model\Item::EXCEPTION_CODE_NOT_SALABLE) { + } catch (LocalizedException $e) { + if ($e->getCode() == Item::EXCEPTION_CODE_NOT_SALABLE) { $this->messageManager->addError(__('This product(s) is out of stock.')); } else { $this->messageManager->addNotice($e->getMessage()); $redirectUrl = $item->getProductUrl(); } } catch (\Exception $e) { - $this->messageManager->addException($e, __('Cannot add item to shopping cart')); + $this->messageManager->addException($e, __('We can\'t add the item to the cart right now.')); } /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); diff --git a/app/code/Magento/Wishlist/Controller/WishlistProvider.php b/app/code/Magento/Wishlist/Controller/WishlistProvider.php index 117254895ca23f8e4cf1f9c4f5edd44bced00b48..7f14d136ae2ed869bda816d4be270ddf8242e449 100644 --- a/app/code/Magento/Wishlist/Controller/WishlistProvider.php +++ b/app/code/Magento/Wishlist/Controller/WishlistProvider.php @@ -81,14 +81,14 @@ class WishlistProvider implements WishlistProviderInterface if (!$wishlist->getId() || $wishlist->getCustomerId() != $customerId) { throw new \Magento\Framework\Exception\NoSuchEntityException( - __('The requested wish list doesn\'t exist.') + __('The requested Wish List doesn\'t exist.') ); } } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { $this->messageManager->addError($e->getMessage()); return false; } catch (\Exception $e) { - $this->messageManager->addException($e, __('Wish List could not be created.')); + $this->messageManager->addException($e, __('We can\'t create the Wish List right now.')); return false; } $this->wishlist = $wishlist; diff --git a/app/code/Magento/Wishlist/Helper/Data.php b/app/code/Magento/Wishlist/Helper/Data.php index 0f1ecf152c3b2efdfa345b6f00967325c4ed1e89..e0dde159b25535c372d39013880ccd82270231ba 100644 --- a/app/code/Magento/Wishlist/Helper/Data.php +++ b/app/code/Magento/Wishlist/Helper/Data.php @@ -405,6 +405,18 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper ); } + /** + * Retrieve URL for adding All items to shopping cart from shared wishlist + * + * @return string + */ + public function getSharedAddAllToCartUrl() + { + return $this->_postDataHelper->getPostData( + $this->_storeManager->getStore()->getUrl('*/*/allcart', ['_current' => true]) + ); + } + /** * @param string|\Magento\Catalog\Model\Product|\Magento\Wishlist\Model\Item $item * @return array diff --git a/app/code/Magento/Wishlist/Model/Item.php b/app/code/Magento/Wishlist/Model/Item.php index 516690383362a739e1feb53af7a2fd13570e99e7..0de3dc44c23a84a2399ccdb76cdb1cde70df6729 100644 --- a/app/code/Magento/Wishlist/Model/Item.php +++ b/app/code/Magento/Wishlist/Model/Item.php @@ -135,7 +135,7 @@ class Item extends AbstractModel implements ItemInterface * @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig * @param ProductRepositoryInterface $productRepository * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -150,7 +150,7 @@ class Item extends AbstractModel implements ItemInterface \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig, ProductRepositoryInterface $productRepository, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->productTypeConfig = $productTypeConfig; diff --git a/app/code/Magento/Wishlist/Model/ItemCarrier.php b/app/code/Magento/Wishlist/Model/ItemCarrier.php index dff865ca56ad259d224edcd57715a47f1108f127..ab9a4d500fdf5ebdc20cb98bf5975929607759da 100644 --- a/app/code/Magento/Wishlist/Model/ItemCarrier.php +++ b/app/code/Magento/Wishlist/Model/ItemCarrier.php @@ -153,7 +153,7 @@ class ItemCarrier } } catch (\Exception $e) { $this->logger->critical($e); - $messages[] = __('We cannot add this item to your shopping cart.'); + $messages[] = __('We can\'t add this item to your cart right now.'); } } @@ -213,7 +213,7 @@ class ItemCarrier try { $wishlist->save(); } catch (\Exception $e) { - $this->messageManager->addError(__('We can\'t update wish list.')); + $this->messageManager->addError(__('We can\'t update the Wish List right now.')); $redirectUrl = $indexUrl; } diff --git a/app/code/Magento/Wishlist/Model/Resource/Item/Collection/Grid.php b/app/code/Magento/Wishlist/Model/Resource/Item/Collection/Grid.php index 45eff464866a6645b1c9e55e2a50c23630ec3395..e0682867beb561323037d6f6081a511402b4dbbc 100644 --- a/app/code/Magento/Wishlist/Model/Resource/Item/Collection/Grid.php +++ b/app/code/Magento/Wishlist/Model/Resource/Item/Collection/Grid.php @@ -107,7 +107,7 @@ class Grid extends \Magento\Wishlist\Model\Resource\Item\Collection * * @param string $field * @param string $direction - * @return \Magento\Framework\Data\Collection\Db + * @return \Magento\Framework\Data\Collection\AbstractDb */ public function setOrder($field, $direction = self::SORT_ORDER_DESC) { @@ -128,7 +128,7 @@ class Grid extends \Magento\Wishlist\Model\Resource\Item\Collection * @param string|array $field * @param null|string|array $condition * @see self::_getConditionSql for $condition - * @return \Magento\Framework\Data\Collection\Db + * @return \Magento\Framework\Data\Collection\AbstractDb */ public function addFieldToFilter($field, $condition = null) { diff --git a/app/code/Magento/Wishlist/Model/Rss/Wishlist.php b/app/code/Magento/Wishlist/Model/Rss/Wishlist.php index 88f6ab4487f088b9742e0d1f9ec78a8224b3bbac..11808b1c687514ddfeb21fa6e07df3e73cd4dfee 100644 --- a/app/code/Magento/Wishlist/Model/Rss/Wishlist.php +++ b/app/code/Magento/Wishlist/Model/Rss/Wishlist.php @@ -180,8 +180,8 @@ class Wishlist implements DataProviderInterface } } else { $data = [ - 'title' => __('We cannot retrieve the wish list.'), - 'description' => __('We cannot retrieve the wish list.'), + 'title' => __('We cannot retrieve the Wish List.'), + 'description' => __('We cannot retrieve the Wish List.'), 'link' => $this->urlBuilder->getUrl(), 'charset' => 'UTF-8', ]; diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AddTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AddTest.php index 54e91fb5f079aad57ac236a3ee64c9c87f675b4b..9fdea2c67a208855db2911e63d5edf8c69291af8 100755 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AddTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/AddTest.php @@ -439,7 +439,7 @@ class AddTest extends \PHPUnit_Framework_TestCase $wishlist ->expects($this->once()) ->method('addNewItem') - ->will($this->returnValue('Can\'t add product to wishlist')); + ->will($this->returnValue('Can\'t add product to Wish List')); $wishlist ->expects($this->once()) @@ -473,7 +473,7 @@ class AddTest extends \PHPUnit_Framework_TestCase $messageManager ->expects($this->once()) ->method('addError') - ->with('An error occurred while adding item to wish list: Can\'t add product to wishlist') + ->with('We can\'t add the item to Wish List right now: Can\'t add product to Wish List.') ->will($this->returnValue(null)); $this->context @@ -694,7 +694,7 @@ class AddTest extends \PHPUnit_Framework_TestCase $messageManager ->expects($this->once()) ->method('addError') - ->with('An error occurred while adding item to wish list.') + ->with('We can\'t add the item to Wish List right now.') ->will($this->returnValue(null)); $messageManager ->expects($this->once()) diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php index 96381ac144f7ead0d860646c889ccb1bb30acb20..6b2a6b9a5959f919d05214858aa3643daef44078 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/RemoveTest.php @@ -229,7 +229,7 @@ class RemoveTest extends \PHPUnit_Framework_TestCase $this->messageManager ->expects($this->once()) ->method('addError') - ->with('An error occurred while deleting the item from wish list: Message') + ->with('We can\'t delete the item from Wish List right now because of an error: Message.') ->willReturn(true); $wishlistHelper = $this->getMock('Magento\Wishlist\Helper\Data', [], [], '', false); @@ -314,7 +314,7 @@ class RemoveTest extends \PHPUnit_Framework_TestCase $this->messageManager ->expects($this->once()) ->method('addError') - ->with('An error occurred while deleting the item from wish list.') + ->with('We can\'t delete the item from the Wish List right now.') ->willReturn(true); $wishlistHelper = $this->getMock('Magento\Wishlist\Helper\Data', [], [], '', false); diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php new file mode 100644 index 0000000000000000000000000000000000000000..55575d82b276d5b735d18147be9c1861ef068060 --- /dev/null +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/SendTest.php @@ -0,0 +1,698 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Wishlist\Test\Unit\Controller\Index; + +use Magento\Customer\Helper\View as CustomerViewHelper; +use Magento\Customer\Model\Data\Customer as CustomerData; +use Magento\Customer\Model\Session as CustomerSession; +use Magento\Framework\App\Action\Context as ActionContext; +use Magento\Framework\App\Area; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\Controller\Result\Redirect as ResultRedirect; +use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\Data\Form\FormKey\Validator as FormKeyValidator; +use Magento\Framework\Event\ManagerInterface as EventManagerInterface; +use Magento\Framework\Mail\Template\TransportBuilder; +use Magento\Framework\Mail\TransportInterface; +use Magento\Framework\Message\ManagerInterface; +use Magento\Framework\Session\Generic as WishlistSession; +use Magento\Framework\Translate\Inline\StateInterface as TranslateInlineStateInterface; +use Magento\Framework\UrlInterface; +use Magento\Framework\View\Layout; +use Magento\Framework\View\Result\Layout as ResultLayout; +use Magento\Store\Model\ScopeInterface; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Wishlist\Controller\Index\Send; +use Magento\Wishlist\Controller\WishlistProviderInterface; +use Magento\Wishlist\Model\Config as WishlistConfig; +use Magento\Wishlist\Model\Wishlist; + +/** + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class SendTest extends \PHPUnit_Framework_TestCase +{ + /** @var Send |\PHPUnit_Framework_MockObject_MockObject */ + protected $model; + + /** @var ActionContext |\PHPUnit_Framework_MockObject_MockObject */ + protected $context; + + /** @var FormKeyValidator |\PHPUnit_Framework_MockObject_MockObject */ + protected $formKeyValidator; + + /** @var CustomerSession |\PHPUnit_Framework_MockObject_MockObject */ + protected $customerSession; + + /** @var WishlistProviderInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $wishlistProvider; + + /** @var WishlistConfig |\PHPUnit_Framework_MockObject_MockObject */ + protected $wishlistConfig; + + /** @var TransportBuilder |\PHPUnit_Framework_MockObject_MockObject */ + protected $transportBuilder; + + /** @var TranslateInlineStateInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $inlineTranslation; + + /** @var CustomerViewHelper |\PHPUnit_Framework_MockObject_MockObject */ + protected $customerViewHelper; + + /** @var WishlistSession |\PHPUnit_Framework_MockObject_MockObject */ + protected $wishlistSession; + + /** @var ScopeConfigInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $scopeConfig; + + /** @var Store |\PHPUnit_Framework_MockObject_MockObject */ + protected $store; + + /** @var StoreManagerInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $storeManager; + + /** @var ResultFactory |\PHPUnit_Framework_MockObject_MockObject */ + protected $resultFactory; + + /** @var ResultRedirect |\PHPUnit_Framework_MockObject_MockObject */ + protected $resultRedirect; + + /** @var ResultLayout |\PHPUnit_Framework_MockObject_MockObject */ + protected $resultLayout; + + /** @var Layout |\PHPUnit_Framework_MockObject_MockObject */ + protected $layout; + + /** @var RequestInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $request; + + /** @var Wishlist |\PHPUnit_Framework_MockObject_MockObject */ + protected $wishlist; + + /** @var ManagerInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $messageManager; + + /** @var CustomerData |\PHPUnit_Framework_MockObject_MockObject */ + protected $customerData; + + /** @var UrlInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $url; + + /** @var TransportInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $transport; + + /** @var EventManagerInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $eventManager; + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + protected function setUp() + { + $this->resultRedirect = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultLayout = $this->getMockBuilder('Magento\Framework\View\Result\Layout') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultFactory = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultFactory->expects($this->any()) + ->method('create') + ->willReturnMap([ + [ResultFactory::TYPE_REDIRECT, [], $this->resultRedirect], + [ResultFactory::TYPE_LAYOUT, [], $this->resultLayout], + ]); + + $this->request = $this->getMockBuilder('Magento\Framework\App\RequestInterface') + ->setMethods([ + 'getPost', + 'getPostValue', + ]) + ->getMockForAbstractClass(); + + $this->messageManager = $this->getMockBuilder('Magento\Framework\Message\ManagerInterface') + ->getMockForAbstractClass(); + + $this->url = $this->getMockBuilder('Magento\Framework\UrlInterface') + ->getMockForAbstractClass(); + + $this->eventManager = $this->getMockBuilder('Magento\Framework\Event\ManagerInterface') + ->getMockForAbstractClass(); + + $this->context = $this->getMockBuilder('Magento\Framework\App\Action\Context') + ->disableOriginalConstructor() + ->getMock(); + $this->context->expects($this->any()) + ->method('getRequest') + ->willReturn($this->request); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactory); + $this->context->expects($this->any()) + ->method('getMessageManager') + ->willReturn($this->messageManager); + $this->context->expects($this->any()) + ->method('getUrl') + ->willReturn($this->url); + $this->context->expects($this->any()) + ->method('getEventManager') + ->willReturn($this->eventManager); + + $this->formKeyValidator = $this->getMockBuilder('Magento\Framework\Data\Form\FormKey\Validator') + ->disableOriginalConstructor() + ->getMock(); + + $this->customerSession = $this->getMockBuilder('Magento\Customer\Model\Session') + ->disableOriginalConstructor() + ->getMock(); + + $this->wishlistProvider = $this->getMockBuilder('Magento\Wishlist\Controller\WishlistProviderInterface') + ->getMockForAbstractClass(); + + $this->wishlistConfig = $this->getMockBuilder('Magento\Wishlist\Model\Config') + ->disableOriginalConstructor() + ->getMock(); + + $this->transportBuilder = $this->getMockBuilder('Magento\Framework\Mail\Template\TransportBuilder') + ->disableOriginalConstructor() + ->getMock(); + + $this->inlineTranslation = $this->getMockBuilder('Magento\Framework\Translate\Inline\StateInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->customerViewHelper = $this->getMockBuilder('Magento\Customer\Helper\View') + ->disableOriginalConstructor() + ->getMock(); + + $this->wishlistSession = $this->getMockBuilder('Magento\Framework\Session\Generic') + ->disableOriginalConstructor() + ->getMock(); + + $this->scopeConfig = $this->getMockBuilder('Magento\Framework\App\Config\ScopeConfigInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->store = $this->getMockBuilder('Magento\Store\Model\Store') + ->disableOriginalConstructor() + ->setMethods(['getStoreId']) + ->getMock(); + + $this->storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->storeManager->expects($this->any()) + ->method('getStore') + ->willReturn($this->store); + + $this->wishlist = $this->getMockBuilder('Magento\Wishlist\Model\Wishlist') + ->disableOriginalConstructor() + ->setMethods([ + 'getShared', + 'setShared', + 'getId', + 'getSharingCode', + 'save', + 'isSalable', + ]) + ->getMock(); + + $this->customerData = $this->getMockBuilder('Magento\Customer\Model\Data\Customer') + ->disableOriginalConstructor() + ->getMock(); + + $this->layout = $this->getMockBuilder('Magento\Framework\View\Layout') + ->disableOriginalConstructor() + ->setMethods([ + 'getBlock', + 'setWishlistId', + 'toHtml', + ]) + ->getMock(); + + $this->transport = $this->getMockBuilder('Magento\Framework\Mail\TransportInterface') + ->getMockForAbstractClass(); + + $this->model = new Send( + $this->context, + $this->formKeyValidator, + $this->customerSession, + $this->wishlistProvider, + $this->wishlistConfig, + $this->transportBuilder, + $this->inlineTranslation, + $this->customerViewHelper, + $this->wishlistSession, + $this->scopeConfig, + $this->storeManager + ); + } + + public function testExecuteNoFormKeyValidated() + { + $this->formKeyValidator->expects($this->once()) + ->method('validate') + ->with($this->request) + ->willReturn(false); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/') + ->willReturnSelf(); + + $this->assertEquals($this->resultRedirect, $this->model->execute()); + } + + /** + * @expectedException \Magento\Framework\Exception\NotFoundException + * @expectedExceptionMessage Page not found. + */ + public function testExecuteNoWishlistAvailable() + { + $this->formKeyValidator->expects($this->once()) + ->method('validate') + ->with($this->request) + ->willReturn(true); + + $this->wishlistProvider->expects($this->once()) + ->method('getWishlist') + ->willReturn(null); + + $this->model->execute(); + } + + /** + * @param string $text + * @param int $textLimit + * @param string $emails + * @param int $emailsLimit + * @param int $shared + * @param string $postValue + * @param string $errorMessage + * + * @dataProvider dataProviderExecuteWithError + */ + public function testExecuteWithError( + $text, + $textLimit, + $emails, + $emailsLimit, + $shared, + $postValue, + $errorMessage + ) { + $this->formKeyValidator->expects($this->once()) + ->method('validate') + ->with($this->request) + ->willReturn(true); + + $this->wishlist->expects($this->once()) + ->method('getShared') + ->willReturn($shared); + + $this->wishlistProvider->expects($this->once()) + ->method('getWishlist') + ->willReturn($this->wishlist); + + $this->wishlistConfig->expects($this->once()) + ->method('getSharingEmailLimit') + ->willReturn($emailsLimit); + $this->wishlistConfig->expects($this->once()) + ->method('getSharingTextLimit') + ->willReturn($textLimit); + + $this->request->expects($this->exactly(2)) + ->method('getPost') + ->willReturnMap([ + ['emails', $emails], + ['message', $text], + ]); + $this->request->expects($this->once()) + ->method('getPostValue') + ->willReturn($postValue); + + $this->messageManager->expects($this->once()) + ->method('addError') + ->with($errorMessage) + ->willReturnSelf(); + + $this->wishlistSession->expects($this->any()) + ->method('setSharingForm') + ->with($postValue) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/share') + ->willReturnSelf(); + + $this->assertEquals($this->resultRedirect, $this->model->execute()); + } + + /** + * 1. Text + * 2. Text limit + * 3. Emails + * 4. Emails limit + * 5. Shared wishlists counter + * 6. POST value + * 7. Error message (RESULT) + * + * @return array + */ + public function dataProviderExecuteWithError() + { + return [ + ['test text', 1, 'user1@example.com', 1, 0, '', 'Message length must not exceed 1 symbols'], + ['test text', 100, null, 1, 0, '', 'Please enter an email address.'], + ['test text', 100, '', 1, 0, '', 'Please enter an email address.'], + ['test text', 100, 'user1@example.com', 1, 1, '', 'This wish list can be shared 0 more times.'], + [ + 'test text', + 100, + 'u1@example.com, u2@example.com', + 3, + 2, + '', + 'This wish list can be shared 1 more times.' + ], + ['test text', 100, 'wrongEmailAddress', 1, 0, '', 'Please input a valid email address.'], + ['test text', 100, 'user1@example.com, wrongEmailAddress', 2, 0, '', 'Please input a valid email address.'], + ['test text', 100, 'wrongEmailAddress, user2@example.com', 2, 0, '', 'Please input a valid email address.'], + ]; + } + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testExecuteWithException() + { + $text = 'test text'; + $textLimit = 100; + $emails = 'user1@example.com'; + $emailsLimit = 1; + $shared = 0; + $customerName = 'user1 user1'; + $wishlistId = 1; + $rssLink = 'rss link'; + $sharingCode = 'sharing code'; + $exceptionMessage = 'test exception message'; + $postValue = ''; + + $this->formKeyValidator->expects($this->once()) + ->method('validate') + ->with($this->request) + ->willReturn(true); + + $this->wishlist->expects($this->exactly(2)) + ->method('getShared') + ->willReturn($shared); + $this->wishlist->expects($this->once()) + ->method('setShared') + ->with($shared) + ->willReturnSelf(); + $this->wishlist->expects($this->once()) + ->method('getId') + ->willReturn($wishlistId); + $this->wishlist->expects($this->once()) + ->method('getSharingCode') + ->willReturn($sharingCode); + $this->wishlist->expects($this->once()) + ->method('save') + ->willReturnSelf(); + + $this->wishlistProvider->expects($this->once()) + ->method('getWishlist') + ->willReturn($this->wishlist); + + $this->wishlistConfig->expects($this->once()) + ->method('getSharingEmailLimit') + ->willReturn($emailsLimit); + $this->wishlistConfig->expects($this->once()) + ->method('getSharingTextLimit') + ->willReturn($textLimit); + + $this->request->expects($this->exactly(2)) + ->method('getPost') + ->willReturnMap([ + ['emails', $emails], + ['message', $text], + ]); + $this->request->expects($this->exactly(2)) + ->method('getParam') + ->with('rss_url') + ->willReturn(true); + $this->request->expects($this->once()) + ->method('getPostValue') + ->willReturn($postValue); + + $this->layout->expects($this->once()) + ->method('getBlock') + ->with('wishlist.email.rss') + ->willReturnSelf(); + $this->layout->expects($this->once()) + ->method('setWishlistId') + ->with($wishlistId) + ->willReturnSelf(); + $this->layout->expects($this->once()) + ->method('toHtml') + ->willReturn($rssLink); + + $this->resultLayout->expects($this->exactly(2)) + ->method('addHandle') + ->willReturnMap([ + ['wishlist_email_rss', null], + ['wishlist_email_items', null], + ]); + $this->resultLayout->expects($this->once()) + ->method('getLayout') + ->willReturn($this->layout); + + $this->inlineTranslation->expects($this->once()) + ->method('suspend') + ->willReturnSelf(); + $this->inlineTranslation->expects($this->once()) + ->method('resume') + ->willReturnSelf(); + + $this->customerSession->expects($this->once()) + ->method('getCustomerDataObject') + ->willReturn($this->customerData); + + $this->customerViewHelper->expects($this->once()) + ->method('getCustomerName') + ->with($this->customerData) + ->willReturn($customerName); + + // Throw Exception + $this->transportBuilder->expects($this->once()) + ->method('setTemplateIdentifier') + ->willThrowException(new \Exception($exceptionMessage)); + + $this->messageManager->expects($this->once()) + ->method('addError') + ->with($exceptionMessage) + ->willReturnSelf(); + + $this->wishlistSession->expects($this->any()) + ->method('setSharingForm') + ->with($postValue) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*/share') + ->willReturnSelf(); + + $this->assertEquals($this->resultRedirect, $this->model->execute()); + } + + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testExecute() + { + $text = 'text'; + $textLimit = 100; + $emails = 'user1@example.com'; + $emailsLimit = 1; + $shared = 0; + $customerName = 'user1 user1'; + $wishlistId = 1; + $sharingCode = 'sharing code'; + $templateIdentifier = 'template identifier'; + $storeId = 1; + $viewOnSiteLink = 'view on site link'; + $from = 'user0@example.com'; + + $this->formKeyValidator->expects($this->once()) + ->method('validate') + ->with($this->request) + ->willReturn(true); + + $this->wishlist->expects($this->exactly(2)) + ->method('getShared') + ->willReturn($shared); + $this->wishlist->expects($this->once()) + ->method('setShared') + ->with(++$shared) + ->willReturnSelf(); + $this->wishlist->expects($this->exactly(2)) + ->method('getId') + ->willReturn($wishlistId); + $this->wishlist->expects($this->once()) + ->method('getSharingCode') + ->willReturn($sharingCode); + $this->wishlist->expects($this->once()) + ->method('save') + ->willReturnSelf(); + $this->wishlist->expects($this->once()) + ->method('isSalable') + ->willReturn(true); + + $this->wishlistProvider->expects($this->once()) + ->method('getWishlist') + ->willReturn($this->wishlist); + + $this->wishlistConfig->expects($this->once()) + ->method('getSharingEmailLimit') + ->willReturn($emailsLimit); + $this->wishlistConfig->expects($this->once()) + ->method('getSharingTextLimit') + ->willReturn($textLimit); + + $this->request->expects($this->exactly(2)) + ->method('getPost') + ->willReturnMap([ + ['emails', $emails], + ['message', $text], + ]); + $this->request->expects($this->exactly(2)) + ->method('getParam') + ->with('rss_url') + ->willReturn(true); + + $this->layout->expects($this->exactly(2)) + ->method('getBlock') + ->willReturnMap([ + ['wishlist.email.rss', $this->layout], + ['wishlist.email.items', $this->layout], + ]); + + $this->layout->expects($this->once()) + ->method('setWishlistId') + ->with($wishlistId) + ->willReturnSelf(); + $this->layout->expects($this->exactly(2)) + ->method('toHtml') + ->willReturn($text); + + $this->resultLayout->expects($this->exactly(2)) + ->method('addHandle') + ->willReturnMap([ + ['wishlist_email_rss', null], + ['wishlist_email_items', null], + ]); + $this->resultLayout->expects($this->exactly(2)) + ->method('getLayout') + ->willReturn($this->layout); + + $this->inlineTranslation->expects($this->once()) + ->method('suspend') + ->willReturnSelf(); + $this->inlineTranslation->expects($this->once()) + ->method('resume') + ->willReturnSelf(); + + $this->customerSession->expects($this->once()) + ->method('getCustomerDataObject') + ->willReturn($this->customerData); + + $this->customerViewHelper->expects($this->once()) + ->method('getCustomerName') + ->with($this->customerData) + ->willReturn($customerName); + + $this->scopeConfig->expects($this->exactly(2)) + ->method('getValue') + ->willReturnMap([ + ['wishlist/email/email_template', ScopeInterface::SCOPE_STORE, null, $templateIdentifier], + ['wishlist/email/email_identity', ScopeInterface::SCOPE_STORE, null, $from], + ]); + + $this->store->expects($this->once()) + ->method('getStoreId') + ->willReturn($storeId); + + $this->url->expects($this->once()) + ->method('getUrl') + ->with('*/shared/index', ['code' => $sharingCode]) + ->willReturn($viewOnSiteLink); + + $this->transportBuilder->expects($this->once()) + ->method('setTemplateIdentifier') + ->with($templateIdentifier) + ->willReturnSelf(); + $this->transportBuilder->expects($this->once()) + ->method('setTemplateOptions') + ->with([ + 'area' => Area::AREA_FRONTEND, + 'store' => $storeId, + ]) + ->willReturnSelf(); + $this->transportBuilder->expects($this->once()) + ->method('setTemplateVars') + ->with([ + 'customer' => $this->customerData, + 'customerName' => $customerName, + 'salable' => 'yes', + 'items' => $text, + 'viewOnSiteLink' => $viewOnSiteLink, + 'message' => $text . $text, + 'store' => $this->store, + ]) + ->willReturnSelf(); + $this->transportBuilder->expects($this->once()) + ->method('setFrom') + ->with($from) + ->willReturnSelf(); + $this->transportBuilder->expects($this->once()) + ->method('addTo') + ->with($emails) + ->willReturnSelf(); + $this->transportBuilder->expects($this->once()) + ->method('getTransport') + ->willReturn($this->transport); + + $this->transport->expects($this->once()) + ->method('sendMessage') + ->willReturnSelf(); + + $this->eventManager->expects($this->once()) + ->method('dispatch') + ->with('wishlist_share', ['wishlist' => $this->wishlist]) + ->willReturnSelf(); + + $this->messageManager->expects($this->once()) + ->method('addSuccess') + ->with(__('Your wish list has been shared.')) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setPath') + ->with('*/*', ['wishlist_id' => $wishlistId]) + ->willReturnSelf(); + + $this->assertEquals($this->resultRedirect, $this->model->execute()); + } +} diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php index cb1b05a9328a9203c38aa36d6c9034bfa04b1144..cb8ef4cc95396a8019e6e69de74018b3d34d2215 100755 --- a/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Index/UpdateItemOptionsTest.php @@ -395,7 +395,7 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase $this->messageManager ->expects($this->once()) ->method('addSuccess') - ->with('Test name has been updated in your wish list.', null) + ->with('Test name has been updated in your Wish List.', null) ->willThrowException(new \Magento\Framework\Exception\LocalizedException(__('error-message'))); $this->messageManager ->expects($this->once()) @@ -533,12 +533,12 @@ class UpdateItemOptionsTest extends \PHPUnit_Framework_TestCase $this->messageManager ->expects($this->once()) ->method('addSuccess') - ->with('Test name has been updated in your wish list.', null) + ->with('Test name has been updated in your Wish List.', null) ->willThrowException($exception); $this->messageManager ->expects($this->once()) ->method('addError') - ->with('An error occurred while updating wish list.', null) + ->with('We can\'t update your Wish List right now.', null) ->willReturn(true); $this->resultRedirectMock->expects($this->once()) ->method('setPath') diff --git a/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/CartTest.php b/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/CartTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cfc0d545e71ec4debbf28bd14aed08695c11bb48 --- /dev/null +++ b/app/code/Magento/Wishlist/Test/Unit/Controller/Shared/CartTest.php @@ -0,0 +1,365 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Wishlist\Test\Unit\Controller\Shared; + +use Magento\Catalog\Model\Product; +use Magento\Checkout\Helper\Cart as CartHelper; +use Magento\Checkout\Model\Cart; +use Magento\Framework\App\Action\Context as ActionContext; +use Magento\Framework\App\RequestInterface; +use Magento\Framework\App\Response\RedirectInterface; +use Magento\Framework\Controller\Result\Redirect; +use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\Escaper; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Message\ManagerInterface; +use Magento\Quote\Model\Quote; +use Magento\Wishlist\Controller\Shared\Cart as SharedCart; +use Magento\Wishlist\Model\Item; +use Magento\Wishlist\Model\Item\Option; +use Magento\Wishlist\Model\Item\OptionFactory; +use Magento\Wishlist\Model\ItemFactory; +use Magento\Wishlist\Model\Resource\Item\Option\Collection as OptionCollection; + +/** + * @SuppressWarnings(PHPMD.TooManyFields) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class CartTest extends \PHPUnit_Framework_TestCase +{ + /** @var SharedCart |\PHPUnit_Framework_MockObject_MockObject */ + protected $model; + + /** @var RequestInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $request; + + /** @var ManagerInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $messageManager; + + /** @var ActionContext |\PHPUnit_Framework_MockObject_MockObject */ + protected $context; + + /** @var Cart |\PHPUnit_Framework_MockObject_MockObject */ + protected $cart; + + /** @var CartHelper |\PHPUnit_Framework_MockObject_MockObject */ + protected $cartHelper; + + /** @var Quote | \PHPUnit_Framework_MockObject_MockObject */ + protected $quote; + + /** @var OptionCollection |\PHPUnit_Framework_MockObject_MockObject */ + protected $optionCollection; + + /** @var OptionFactory |\PHPUnit_Framework_MockObject_MockObject */ + protected $optionFactory; + + /** @var Option |\PHPUnit_Framework_MockObject_MockObject */ + protected $option; + + /** @var ItemFactory |\PHPUnit_Framework_MockObject_MockObject */ + protected $itemFactory; + + /** @var Item |\PHPUnit_Framework_MockObject_MockObject */ + protected $item; + + /** @var Escaper |\PHPUnit_Framework_MockObject_MockObject */ + protected $escaper; + + /** @var RedirectInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $redirect; + + /** @var ResultFactory |\PHPUnit_Framework_MockObject_MockObject */ + protected $resultFactory; + + /** @var Redirect |\PHPUnit_Framework_MockObject_MockObject */ + protected $resultRedirect; + + /** @var Product |\PHPUnit_Framework_MockObject_MockObject */ + protected $product; + + protected function setUp() + { + $this->request = $this->getMockBuilder('Magento\Framework\App\RequestInterface') + ->getMockForAbstractClass(); + + $this->redirect = $this->getMockBuilder('Magento\Framework\App\Response\RedirectInterface') + ->getMockForAbstractClass(); + + $this->messageManager = $this->getMockBuilder('Magento\Framework\Message\ManagerInterface') + ->getMockForAbstractClass(); + + $this->resultRedirect = $this->getMockBuilder('Magento\Framework\Controller\Result\Redirect') + ->disableOriginalConstructor() + ->getMock(); + + $this->resultFactory = $this->getMockBuilder('Magento\Framework\Controller\ResultFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->resultFactory->expects($this->once()) + ->method('create') + ->with(ResultFactory::TYPE_REDIRECT) + ->willReturn($this->resultRedirect); + + $this->context = $this->getMockBuilder('Magento\Framework\App\Action\Context') + ->disableOriginalConstructor() + ->getMock(); + $this->context->expects($this->any()) + ->method('getRequest') + ->willReturn($this->request); + $this->context->expects($this->any()) + ->method('getRedirect') + ->willReturn($this->redirect); + $this->context->expects($this->any()) + ->method('getMessageManager') + ->willReturn($this->messageManager); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($this->resultFactory); + + $this->cart = $this->getMockBuilder('Magento\Checkout\Model\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $this->cartHelper = $this->getMockBuilder('Magento\Checkout\Helper\Cart') + ->disableOriginalConstructor() + ->getMock(); + + $this->quote = $this->getMockBuilder('Magento\Quote\Model\Quote') + ->disableOriginalConstructor() + ->setMethods(['getHasError']) + ->getMock(); + + $this->optionCollection = $this->getMockBuilder('Magento\Wishlist\Model\Resource\Item\Option\Collection') + ->disableOriginalConstructor() + ->getMock(); + + $this->option = $this->getMockBuilder('Magento\Wishlist\Model\Item\Option') + ->disableOriginalConstructor() + ->getMock(); + + $this->optionFactory = $this->getMockBuilder('Magento\Wishlist\Model\Item\OptionFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->optionFactory->expects($this->once()) + ->method('create') + ->willReturn($this->option); + + $this->item = $this->getMockBuilder('Magento\Wishlist\Model\Item') + ->disableOriginalConstructor() + ->getMock(); + + $this->itemFactory = $this->getMockBuilder('Magento\Wishlist\Model\ItemFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->itemFactory->expects($this->once()) + ->method('create') + ->willReturn($this->item); + + $this->escaper = $this->getMockBuilder('Magento\Framework\Escaper') + ->disableOriginalConstructor() + ->getMock(); + + $this->product = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + + $this->model = new SharedCart( + $this->context, + $this->cart, + $this->optionFactory, + $this->itemFactory, + $this->cartHelper, + $this->escaper + ); + } + + /** + * @param int $itemId + * @param string $productName + * @param bool $hasErrors + * @param bool $redirectToCart + * @param string $refererUrl + * @param string $cartUrl + * @param string $redirectUrl + * + * @dataProvider dataProviderExecute + */ + public function testExecute( + $itemId, + $productName, + $hasErrors, + $redirectToCart, + $refererUrl, + $cartUrl, + $redirectUrl + ) { + $this->request->expects($this->once()) + ->method('getParam') + ->with('item') + ->willReturn($itemId); + + $this->redirect->expects($this->once()) + ->method('getRefererUrl') + ->willReturn($refererUrl); + + $this->option->expects($this->once()) + ->method('getCollection') + ->willReturn($this->optionCollection); + + $this->optionCollection->expects($this->once()) + ->method('addItemFilter') + ->with([$itemId]) + ->willReturnSelf(); + $this->optionCollection->expects($this->once()) + ->method('getOptionsByItem') + ->with($itemId) + ->willReturn([]); + + $this->item->expects($this->once()) + ->method('load') + ->with($itemId) + ->willReturnSelf(); + $this->item->expects($this->once()) + ->method('setOptions') + ->with([]) + ->willReturnSelf(); + $this->item->expects($this->once()) + ->method('addToCart') + ->with($this->cart) + ->willReturnSelf(); + $this->item->expects($this->any()) + ->method('getProduct') + ->willReturn($this->product); + + $this->quote->expects($this->once()) + ->method('getHasError') + ->willReturn($hasErrors); + + $this->cart->expects($this->once()) + ->method('getQuote') + ->willReturn($this->quote); + $this->cart->expects($this->once()) + ->method('save') + ->willReturnSelf(); + + $this->cartHelper->expects($this->once()) + ->method('getShouldRedirectToCart') + ->willReturn($redirectToCart); + $this->cartHelper->expects($this->any()) + ->method('getCartUrl') + ->willReturn($cartUrl); + + $this->product->expects($this->any()) + ->method('getName') + ->willReturn($productName); + + $this->escaper->expects($this->any()) + ->method('escapeHtml') + ->with($productName) + ->willReturn($productName); + + $successMessage = __('You added %1 to your shopping cart.', $productName); + $this->messageManager->expects($this->any()) + ->method('addSuccess') + ->with($successMessage) + ->willReturnSelf(); + + $this->resultRedirect->expects($this->once()) + ->method('setUrl') + ->with($redirectUrl) + ->willReturnSelf(); + + $this->assertEquals($this->resultRedirect, $this->model->execute()); + } + + /** + * 1. Wishlist Item ID + * 2. Product Name + * 3. Quote has errors + * 4. Should redirect to Cart flag + * 5. Referer URL + * 6. Shopping Cart URL + * 7. Redirect URL (RESULT) + * + * @return array + */ + public function dataProviderExecute() + { + return [ + [1, 'product_name', false, true, 'referer_url', 'cart_url', 'cart_url'], + [1, 'product_name', true, false, 'referer_url', 'cart_url', 'referer_url'], + ]; + } + + public function testExecuteLocalizedException() + { + $itemId = 1; + $refererUrl = 'referer_url'; + $productUrl = 'product_url'; + + $this->request->expects($this->once()) + ->method('getParam') + ->with('item') + ->willReturn($itemId); + + $this->item->expects($this->once()) + ->method('load') + ->with($itemId) + ->willReturnSelf(); + $this->item->expects($this->once()) + ->method('getProductUrl') + ->willReturn($productUrl); + + $this->redirect->expects($this->once()) + ->method('getRefererUrl') + ->willReturn($refererUrl); + + $this->option->expects($this->once()) + ->method('getCollection') + ->willThrowException(new LocalizedException(__('LocalizedException'))); + + $this->resultRedirect->expects($this->once()) + ->method('setUrl') + ->with($productUrl) + ->willReturnSelf(); + + $this->assertEquals($this->resultRedirect, $this->model->execute()); + } + + public function testExecuteException() + { + $itemId = 1; + $refererUrl = 'referer_url'; + + $this->request->expects($this->once()) + ->method('getParam') + ->with('item') + ->willReturn($itemId); + + $this->item->expects($this->once()) + ->method('load') + ->with($itemId) + ->willReturnSelf(); + + $this->redirect->expects($this->once()) + ->method('getRefererUrl') + ->willReturn($refererUrl); + + $this->option->expects($this->once()) + ->method('getCollection') + ->willThrowException(new \Exception('Exception')); + + $this->resultRedirect->expects($this->once()) + ->method('setUrl') + ->with($refererUrl) + ->willReturnSelf(); + + $this->assertEquals($this->resultRedirect, $this->model->execute()); + } +} diff --git a/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php b/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php index b7dd62901183f4e67928e74b3b20b4a326268fcd..afe0a833e84b3bfcf26a9f7b22ae267b9b6ca667 100644 --- a/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/Helper/DataTest.php @@ -5,32 +5,51 @@ */ namespace Magento\Wishlist\Test\Unit\Helper; +use Magento\Catalog\Model\Product; +use Magento\Framework\App\Helper\Context; +use Magento\Framework\Data\Helper\PostHelper; +use Magento\Framework\Registry; +use Magento\Framework\UrlInterface\Proxy as UrlInterface; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Wishlist\Controller\WishlistProviderInterface; +use Magento\Wishlist\Model\Item as WishlistItem; +use Magento\Wishlist\Model\Wishlist; + class DataTest extends \PHPUnit_Framework_TestCase { - /** - * @var \Magento\Wishlist\Helper\Data - */ - protected $wishlistHelper; + /** @var \Magento\Wishlist\Helper\Data */ + protected $model; - /** - * @var \Magento\Wishlist\Controller\WishlistProviderInterface - */ + /** @var WishlistProviderInterface |\PHPUnit_Framework_MockObject_MockObject */ protected $wishlistProvider; - /** - * @var \Magento\Framework\Registry - */ + /** @var Registry |\PHPUnit_Framework_MockObject_MockObject */ protected $coreRegistry; - /** - * @var string - */ - protected $url; + /** @var PostHelper |\PHPUnit_Framework_MockObject_MockObject */ + protected $postDataHelper; - /** - * @var string - */ - protected $configureUrl; + /** @var WishlistItem |\PHPUnit_Framework_MockObject_MockObject */ + protected $wishlistItem; + + /** @var Product |\PHPUnit_Framework_MockObject_MockObject */ + protected $product; + + /** @var StoreManagerInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $storeManager; + + /** @var Store |\PHPUnit_Framework_MockObject_MockObject */ + protected $store; + + /** @var UrlInterface |\PHPUnit_Framework_MockObject_MockObject */ + protected $urlBuilder; + + /** @var Wishlist |\PHPUnit_Framework_MockObject_MockObject */ + protected $wishlist; + + /** @var Context |\PHPUnit_Framework_MockObject_MockObject */ + protected $context; /** * Set up mock objects for tested class @@ -39,75 +58,91 @@ class DataTest extends \PHPUnit_Framework_TestCase */ public function setUp() { - $this->url = 'http://magento.com/wishlist/index/index/wishlist_id/1/?___store=default'; - $this->configureUrl = 'http://magento2ce/wishlist/index/configure/id/4/product_id/30/'; - $store = $this->getMock('Magento\Store\Model\Store', [], [], '', false); - $store->expects($this->any()) - ->method('getUrl') - ->with('wishlist/index/cart', ['item' => '%item%']) - ->will($this->returnValue($this->url)); + $this->store = $this->getMockBuilder('Magento\Store\Model\Store') + ->disableOriginalConstructor() + ->getMock(); - $storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface') + $this->storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface') ->disableOriginalConstructor() ->getMock(); - $storeManager->expects($this->any()) + $this->storeManager->expects($this->any()) ->method('getStore') - ->will($this->returnValue($store)); - - $urlBuilder = $this->getMock('Magento\Framework\UrlInterface\Proxy', ['getUrl'], [], '', false); - if ($this->getName() == 'testGetConfigureUrl') { - $urlBuilder->expects($this->once()) - ->method('getUrl') - ->with('wishlist/index/configure', ['id' => 4, 'product_id' => 30]) - ->will($this->returnValue($this->configureUrl)); - } else { - $urlBuilder->expects($this->any()) - ->method('getUrl') - ->with('wishlist/index/index', ['_current' => true, '_use_rewrite' => true, '_scope_to_url' => true]) - ->will($this->returnValue($this->url)); - } - - $context = $this->getMock('Magento\Framework\App\Helper\Context', [], [], '', false); - $context->expects($this->once()) + ->willReturn($this->store); + + $this->urlBuilder = $this->getMockBuilder('Magento\Framework\UrlInterface\Proxy') + ->disableOriginalConstructor() + ->setMethods(['getUrl']) + ->getMock(); + + $this->context = $this->getMockBuilder('Magento\Framework\App\Helper\Context') + ->disableOriginalConstructor() + ->getMock(); + $this->context->expects($this->once()) ->method('getUrlBuilder') - ->will($this->returnValue($urlBuilder)); + ->willReturn($this->urlBuilder); - $this->wishlistProvider = $this->getMock( - 'Magento\Wishlist\Controller\WishlistProviderInterface', - ['getWishlist'], - [], - '', - false - ); + $this->wishlistProvider = $this->getMockBuilder('Magento\Wishlist\Controller\WishlistProviderInterface') + ->disableOriginalConstructor() + ->getMock(); - $this->coreRegistry = $this->getMock( - '\Magento\Framework\Registry', - ['registry'], - [], - '', - false - ); + $this->coreRegistry = $this->getMockBuilder('Magento\Framework\Registry') + ->disableOriginalConstructor() + ->getMock(); - $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->postDataHelper = $this->getMockBuilder('Magento\Framework\Data\Helper\PostHelper') + ->disableOriginalConstructor() + ->getMock(); + + $this->wishlistItem = $this->getMockBuilder('Magento\Wishlist\Model\Item') + ->disableOriginalConstructor() + ->setMethods([ + 'getProduct', + 'getWishlistItemId', + ]) + ->getMock(); + + $this->wishlist = $this->getMockBuilder('Magento\Wishlist\Model\Wishlist') + ->disableOriginalConstructor() + ->getMock(); - $this->wishlistHelper = $objectManager->getObject( + $this->product = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + + $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->model = $objectManager->getObject( 'Magento\Wishlist\Helper\Data', [ - 'context' => $context, - 'storeManager' => $storeManager, + 'context' => $this->context, + 'storeManager' => $this->storeManager, 'wishlistProvider' => $this->wishlistProvider, - 'coreRegistry' => $this->coreRegistry + 'coreRegistry' => $this->coreRegistry, + 'postDataHelper' => $this->postDataHelper ] ); } public function testGetAddToCartUrl() { - $this->assertEquals($this->url, $this->wishlistHelper->getAddToCartUrl('%item%')); + $url = 'http://magento.com/wishlist/index/index/wishlist_id/1/?___store=default'; + + $this->store->expects($this->once()) + ->method('getUrl') + ->with('wishlist/index/cart', ['item' => '%item%']) + ->will($this->returnValue($url)); + + $this->urlBuilder->expects($this->any()) + ->method('getUrl') + ->with('wishlist/index/index', ['_current' => true, '_use_rewrite' => true, '_scope_to_url' => true]) + ->will($this->returnValue($url)); + + $this->assertEquals($url, $this->model->getAddToCartUrl('%item%')); } public function testGetConfigureUrl() { + $url = 'http://magento2ce/wishlist/index/configure/id/4/product_id/30/'; + $wishlistItem = $this->getMock( 'Magento\Wishlist\Model\Item', ['getWishlistItemId', 'getProductId'], @@ -124,26 +159,112 @@ class DataTest extends \PHPUnit_Framework_TestCase ->method('getProductId') ->will($this->returnValue(30)); - $this->assertEquals($this->configureUrl, $this->wishlistHelper->getConfigureUrl($wishlistItem)); + $this->urlBuilder->expects($this->once()) + ->method('getUrl') + ->with('wishlist/index/configure', ['id' => 4, 'product_id' => 30]) + ->will($this->returnValue($url)); + + $this->assertEquals($url, $this->model->getConfigureUrl($wishlistItem)); } public function testGetWishlist() { - $wishlist = $this->getMock('\Magento\Wishlist\Model\Wishlist', [], [], '', false); $this->wishlistProvider->expects($this->once()) ->method('getWishlist') - ->will($this->returnValue($wishlist)); + ->will($this->returnValue($this->wishlist)); - $this->assertEquals($wishlist, $this->wishlistHelper->getWishlist()); + $this->assertEquals($this->wishlist, $this->model->getWishlist()); } public function testGetWishlistWithCoreRegistry() { - $wishlist = $this->getMock('\Magento\Wishlist\Model\Wishlist', [], [], '', false); $this->coreRegistry->expects($this->any()) ->method('registry') - ->will($this->returnValue($wishlist)); + ->willReturn($this->wishlist); + + $this->assertEquals($this->wishlist, $this->model->getWishlist()); + } + + public function testGetAddToCartParams() + { + $url = 'result url'; + $storeId = 1; + $wishlistItemId = 1; + + $this->wishlistItem->expects($this->once()) + ->method('getProduct') + ->willReturn($this->product); + $this->wishlistItem->expects($this->once()) + ->method('getWishlistItemId') + ->willReturn($wishlistItemId); + + $this->product->expects($this->once()) + ->method('isVisibleInSiteVisibility') + ->willReturn(true); + $this->product->expects($this->once()) + ->method('getStoreId') + ->willReturn($storeId); + + $this->store->expects($this->once()) + ->method('getUrl') + ->with('wishlist/index/cart') + ->willReturn($url); + + $this->postDataHelper->expects($this->once()) + ->method('getPostData') + ->with($url, ['item' => $wishlistItemId]) + ->willReturn($url); + + $this->assertEquals($url, $this->model->getAddToCartParams($this->wishlistItem)); + } + + public function testGetSharedAddToCartUrl() + { + $url = 'result url'; + $storeId = 1; + $wishlistItemId = 1; + + $this->wishlistItem->expects($this->once()) + ->method('getProduct') + ->willReturn($this->product); + $this->wishlistItem->expects($this->once()) + ->method('getWishlistItemId') + ->willReturn($wishlistItemId); + + $this->product->expects($this->once()) + ->method('isVisibleInSiteVisibility') + ->willReturn(true); + $this->product->expects($this->once()) + ->method('getStoreId') + ->willReturn($storeId); + + $this->store->expects($this->once()) + ->method('getUrl') + ->with('wishlist/shared/cart') + ->willReturn($url); + + $this->postDataHelper->expects($this->once()) + ->method('getPostData') + ->with($url, ['item' => $wishlistItemId]) + ->willReturn($url); + + $this->assertEquals($url, $this->model->getSharedAddToCartUrl($this->wishlistItem)); + } + + public function testGetSharedAddAllToCartUrl() + { + $url = 'result url'; + + $this->store->expects($this->once()) + ->method('getUrl') + ->with('*/*/allcart', ['_current' => true]) + ->willReturn($url); + + $this->postDataHelper->expects($this->once()) + ->method('getPostData') + ->with($url) + ->willReturn($url); - $this->assertEquals($wishlist, $this->wishlistHelper->getWishlist()); + $this->assertEquals($url, $this->model->getSharedAddAllToCartUrl()); } } diff --git a/app/code/Magento/Wishlist/composer.json b/app/code/Magento/Wishlist/composer.json index 66ca1faad5ba8517587bacf0957e984e74a732f0..703058cbf5f90410d1631d2d9dedda1ad6c026f4 100644 --- a/app/code/Magento/Wishlist/composer.json +++ b/app/code/Magento/Wishlist/composer.json @@ -3,28 +3,28 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/module-store": "0.74.0-beta10", - "magento/module-customer": "0.74.0-beta10", - "magento/module-catalog": "0.74.0-beta10", - "magento/module-checkout": "0.74.0-beta10", - "magento/module-theme": "0.74.0-beta10", - "magento/module-catalog-inventory": "0.74.0-beta10", - "magento/module-rss": "0.74.0-beta10", - "magento/module-backend": "0.74.0-beta10", - "magento/module-sales": "0.74.0-beta10", - "magento/module-grouped-product": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", - "magento/module-ui": "0.74.0-beta10", + "magento/module-store": "0.74.0-beta13", + "magento/module-customer": "0.74.0-beta13", + "magento/module-catalog": "0.74.0-beta13", + "magento/module-checkout": "0.74.0-beta13", + "magento/module-theme": "0.74.0-beta13", + "magento/module-catalog-inventory": "0.74.0-beta13", + "magento/module-rss": "0.74.0-beta13", + "magento/module-backend": "0.74.0-beta13", + "magento/module-sales": "0.74.0-beta13", + "magento/module-grouped-product": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", + "magento/module-ui": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "suggest": { - "magento/module-configurable-product": "0.74.0-beta10", - "magento/module-downloadable": "0.74.0-beta10", - "magento/module-bundle": "0.74.0-beta10", - "magento/module-cookie": "0.74.0-beta10" + "magento/module-configurable-product": "0.74.0-beta13", + "magento/module-downloadable": "0.74.0-beta13", + "magento/module-bundle": "0.74.0-beta13", + "magento/module-cookie": "0.74.0-beta13" }, "type": "magento2-module", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/code/Magento/Wishlist/etc/adminhtml/system.xml b/app/code/Magento/Wishlist/etc/adminhtml/system.xml index f959f61b2a8fa892786fc5fb318f6fe8f7cb51c4..18f9dedd71a9326b507d8e5d6cde1f8fec946a23 100644 --- a/app/code/Magento/Wishlist/etc/adminhtml/system.xml +++ b/app/code/Magento/Wishlist/etc/adminhtml/system.xml @@ -8,7 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../Config/etc/system_file.xsd"> <system> <section id="wishlist" translate="label" type="text" sortOrder="140" showInDefault="1" showInWebsite="1" showInStore="1"> - <label>Wishlist</label> + <label>Wish List</label> <tab>customer</tab> <resource>Magento_Wishlist::config_wishlist</resource> <group id="email" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1"> @@ -49,7 +49,7 @@ </section> <section id="rss"> <group id="wishlist" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1"> - <label>Wishlist</label> + <label>Wish List</label> <field id="active" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Enable RSS</label> <source_model>Magento\Config\Model\Config\Source\Enabledisable</source_model> diff --git a/app/code/Magento/Wishlist/etc/email_templates.xml b/app/code/Magento/Wishlist/etc/email_templates.xml index 8bafbd05c983e2ace16c6444715e2bd9e9742808..6a6df6fdc6b02a2b29cf474ee1df9f6024f934be 100644 --- a/app/code/Magento/Wishlist/etc/email_templates.xml +++ b/app/code/Magento/Wishlist/etc/email_templates.xml @@ -6,5 +6,5 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Email/etc/email_templates.xsd"> - <template id="wishlist_email_email_template" label="Wishlist Sharing" file="share_notification.html" type="html" module="Magento_Wishlist"/> + <template id="wishlist_email_email_template" label="Wish List Sharing" file="share_notification.html" type="html" module="Magento_Wishlist"/> </config> diff --git a/app/code/Magento/Wishlist/etc/frontend/di.xml b/app/code/Magento/Wishlist/etc/frontend/di.xml index e5f0de7c91f3f81b3e0fe997c4e6d5b33c61cd3d..34cc5eaaa60806ef71592f7a9ebe35a5ab843321 100644 --- a/app/code/Magento/Wishlist/etc/frontend/di.xml +++ b/app/code/Magento/Wishlist/etc/frontend/di.xml @@ -30,4 +30,9 @@ </argument> </arguments> </type> + <type name="Magento\Wishlist\Controller\Index\Send"> + <arguments> + <argument name="wishlistSession" xsi:type="object">Magento\Wishlist\Model\Session</argument> + </arguments> + </type> </config> diff --git a/app/code/Magento/Wishlist/etc/frontend/page_types.xml b/app/code/Magento/Wishlist/etc/frontend/page_types.xml index 9d938ce725b41fca3bbdf872201865c8bca55131..3e6d27eb292a2d868dd7e0ffe3187b02f5b1cccd 100644 --- a/app/code/Magento/Wishlist/etc/frontend/page_types.xml +++ b/app/code/Magento/Wishlist/etc/frontend/page_types.xml @@ -9,5 +9,5 @@ <type id="wishlist_index_index" label="Customer My Account My Wish List"/> <type id="wishlist_index_share" label="Customer My Account Wish List Sharing Form"/> <type id="wishlist_shared_index" label="Customer Shared Wish List View"/> - <type id="wishlist_index_configure" label="Configure Wish list Item"/> + <type id="wishlist_index_configure" label="Configure Wish List Item"/> </page_types> diff --git a/app/code/Magento/Wishlist/etc/frontend/sections.xml b/app/code/Magento/Wishlist/etc/frontend/sections.xml index 1195050c3354551f4512ba4cc4217e9e081ce131..b20b76fb206805ba232870648aaff4a9d30fa61b 100644 --- a/app/code/Magento/Wishlist/etc/frontend/sections.xml +++ b/app/code/Magento/Wishlist/etc/frontend/sections.xml @@ -33,6 +33,9 @@ <section name="wishlist"/> <section name="cart"/> </action> + <action name="wishlist/shared/cart"> + <section name="cart"/> + </action> <action name="wishlist/index/fromcart"> <section name="cart"/> </action> diff --git a/app/code/Magento/Wishlist/view/adminhtml/templates/customer/edit/tab/wishlist.phtml b/app/code/Magento/Wishlist/view/adminhtml/templates/customer/edit/tab/wishlist.phtml index d854edd848c919af052fd58af50cb5bbca48345b..468491802413970a66fff2209c0b6ed622c9d79f 100644 --- a/app/code/Magento/Wishlist/view/adminhtml/templates/customer/edit/tab/wishlist.phtml +++ b/app/code/Magento/Wishlist/view/adminhtml/templates/customer/edit/tab/wishlist.phtml @@ -48,7 +48,7 @@ wishlistControl = { }, removeItem: function (itemId) { - if(!confirm('<?php echo __('Are you sure that you want to remove this item?') ?>')) { + if(!confirm('<?php echo __('Are you sure you want to remove this item?') ?>')) { return false; } this.reload('&delete=' + itemId); diff --git a/app/code/Magento/Wishlist/view/email/share_notification.html b/app/code/Magento/Wishlist/view/email/share_notification.html index 4132ddba07daa4b93012521dcaeb1315ba968c88..47bbf250011d4ea11ffbfcf492685817af9b02c5 100644 --- a/app/code/Magento/Wishlist/view/email/share_notification.html +++ b/app/code/Magento/Wishlist/view/email/share_notification.html @@ -4,13 +4,13 @@ * See COPYING.txt for license details. */ --> -<!--@subject Take a look at {{var customerName}}'s wishlist @--> +<!--@subject Take a look at {{var customerName}}'s Wish List @--> <!--@vars {"store url=\"\"":"Store Url", "var logo_url":"Email Logo Image Url", "var logo_alt":"Email Logo Image Alt", -"var message":"Wishlist Message", -"var items":"Wishlist Items"} +"var message":"Wish List Message", +"var items":"Wish List Items"} @--> <!--@styles body,td { color:#2f2f2f; font:11px/1.35em Verdana, Arial, Helvetica, sans-serif; } @@ -31,11 +31,11 @@ body,td { color:#2f2f2f; font:11px/1.35em Verdana, Arial, Helvetica, sans-serif; <!-- [ middle starts here] --> <tr> <td valign="top"> - <p style="font-size:12px; line-height:16px; margin:0 0 16px 0;">Hey,<br/>Take a look at my wish list from {{var store.getFrontendName()}}.</p> + <p style="font-size:12px; line-height:16px; margin:0 0 16px 0;">Hey,<br/>Take a look at my Wish List from {{var store.getFrontendName()}}.</p> <p style="font-size:12px; line-height:16px; margin:0 0 16px 0;">{{var message}}</p> {{var items}} <br/> - <p style="font-size:12px; line-height:16px; margin:0 0 8px 0;">{{depend salable}}<strong><a href="{{var addAllLink}}" style="color:#1E7EC8;">Add all items to shopping cart</a></strong> |{{/depend}} <strong><a href="{{var viewOnSiteLink}}" style="color:#1E7EC8;">View all wishlist items</a></strong></p> + <p style="font-size:12px; line-height:16px; margin:0 0 8px 0;text-align: center;"><strong><a href="{{var viewOnSiteLink}}" style="color:#1E7EC8;">View all Wish List items</a></strong></p> </td> </tr> <tr> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/email/items.phtml b/app/code/Magento/Wishlist/view/frontend/templates/email/items.phtml index 9e6ee3975d5d5c4da261ed0d04914a9d10c7bba1..88b00c1a071f5ed34bd2a3f384cc210d7cd30bda 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/email/items.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/email/items.phtml @@ -31,17 +31,12 @@ </p> <?php if ($block->hasDescription($item)): ?> <p align="center" style="font-size:12px;"><?php echo __('Comment') ?>: - <br/><?php echo $block->getEscapedDescription($item) ?></p><?php endif; ?> - <p align="center" style="font-size:12px;"> - <a href="<?php echo $block->getProductUrl($_product) ?>" style="color:#1E7EC8;"> - <?php echo __('View Product') ?> - </a> - <small>|</small> - <?php if ($_product->getIsSalable()): ?> - <a href="<?php echo $block->getAddToCartUrl($_product) ?>" style="color:#1E7EC8;"> - <strong><?php echo __('Add to Cart') ?></strong> + <br/><?php echo $block->getEscapedDescription($item) ?></p> + <?php endif; ?> + <p align="center" style="font-size:12px;"> + <a href="<?php echo $block->getProductUrl($_product) ?>" style="color:#1E7EC8;"> + <?php echo __('View Product') ?> </a> - <?php endif; ?> </p> </td> <?php if ($i % 3 != 0): ?> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml b/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml index 9a94c0a193811fa75baa0a8cc99aaa121adfbde4..0d1833ff947153a058b87c06a5204db131302c32 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/shared.phtml @@ -52,13 +52,16 @@ $imageBlock = $block->getLayout()->createBlock('Magento\Catalog\Block\Product\I <td data-th="<?php echo $block->escapeHtml(__('Add to Cart')) ?>" class="col actions" data-role="add-to-links"> <?php if ($product->isSaleable()): ?> <?php if ($isVisibleProduct): ?> - <button type="button" title="<?php echo __('Add to Cart') ?>" onclick="location.assign('<?php echo $block->getSharedItemAddToCartUrl($item) ?>')" class="action tocart"> + <button type="button" + title="<?php echo __('Add to Cart') ?>" + data-post='<?php echo $block->getSharedItemAddToCartUrl($item); ?>' + class="action tocart"> <span><?php echo __('Add to Cart') ?></span> </button> <?php endif ?> <?php endif; ?> <a href="#" data-post='<?php echo $block->getAddToWishlistParams($item); ?>' onclick="location.assign(this.href); return false;" class="action towishlist" data-action="add-to-wishlist"> - <span><?php echo __('Add to Wishlist') ?></span> + <span><?php echo __('Add to Wish List') ?></span> </a> </td> </tr> @@ -72,7 +75,7 @@ $imageBlock = $block->getLayout()->createBlock('Magento\Catalog\Block\Product\I <div class="primary"> <button type="button" title="<?php echo __('Add All to Cart') ?>" - onclick="location.assign('<?php echo $block->getUrl('*/*/allcart', ['_current' => true]) ?>')" + data-post='<?php echo $block->getSharedAddAllToCartUrl(); ?>' class="action tocart primary"> <span><?php echo __('Add All to Cart') ?></span> </button> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/sharing.phtml b/app/code/Magento/Wishlist/view/frontend/templates/sharing.phtml index 6a54b4155f5a6f6400e4389d1ae5d63ed5c4590b..2c1d8e291787d782020b04eaa8fc1b51d5a7e204 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/sharing.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/sharing.phtml @@ -31,10 +31,10 @@ </div> <?php if ($this->helper('Magento\Wishlist\Helper\Rss')->isRssAllow()): ?> <div class="field choice rss"> - <input type="checkbox" name="rss_url" id="rss_url" value="1" title="<?php echo __('Check this checkbox if you want to add a link to an rss feed to your wishlist.') ?>" class="checkbox"> + <input type="checkbox" name="rss_url" id="rss_url" value="1" title="<?php echo __('Check here to link an RSS feed to your Wish List.') ?>" class="checkbox"> <label class="label" for="rss_url"> <span> - <?php echo __('Check this checkbox if you want to add a link to an rss feed to your wishlist.') ?> + <?php echo __('Check here to link an RSS feed to your Wish List.') ?> </span> </label> </div> @@ -42,8 +42,8 @@ </fieldset> <div class="actions-toolbar"> <div class="primary"> - <button type="submit" title="<?php echo __('Share Wishlist') ?>" class="action submit primary"> - <span><?php echo __('Share Wishlist') ?></span> + <button type="submit" title="<?php echo __('Share Wish List') ?>" class="action submit primary"> + <span><?php echo __('Share Wish List') ?></span> </button> </div> <div class="secondary"> diff --git a/app/code/Magento/Wishlist/view/frontend/templates/view.phtml b/app/code/Magento/Wishlist/view/frontend/templates/view.phtml index 373ba7176df167765ebd201f99dad3b735d8d59e..1089e880f4a6fe61fc25f002f8c18224498ac8df 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/view.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/view.phtml @@ -14,7 +14,7 @@ <form class="form-wishlist-items" id="wishlist-view-form" data-mage-init='{"wishlist":{ "addToCartUrl":<?php echo $block->getItemAddToCartParams("%item%");?>, - "confirmRemoveMessage":"<?php echo __("Are you sure you want to remove this product from your wishlist?") ?>", + "confirmRemoveMessage":"<?php echo __("Are you sure you want to remove this product from your Wish List?") ?>", "addAllToCartUrl":<?php echo $block->getAddAllToCartParams(); ?>, "commentString":""}, "validation": {}}' action="<?php echo $block->getUrl('wishlist/index/update', ['wishlist_id' => $block->getWishlistInstance()->getId()]) ?>" method="post"> diff --git a/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js b/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js index ac86a43736a43727a15d7c4e9d974655ec550056..112f9406bdaf4e664e57478393a6b73409098119 100644 --- a/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js +++ b/app/code/Magento/Wishlist/view/frontend/web/js/add-to-wishlist.js @@ -83,6 +83,9 @@ define([ elementName = $(element).attr('name'), elementValue = $(element).val(); if ($(element).is('select[multiple]') && elementValue !== null) { + if (elementName.substr(elementName.length - 2) == '[]') { + elementName = elementName.substring(0, elementName.length - 2); + } $.each(elementValue, function (key, option) { data[elementName + '[' + option + ']'] = option; }); diff --git a/app/design/adminhtml/Magento/backend/Magento_AdminNotification/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_AdminNotification/web/css/source/_module.less index 4d372ba38dafb8857a4777951f7b8dbf4cab4329..09a4b451bdbd6eeb956e733719f65bce4f5bc365 100644 --- a/app/design/adminhtml/Magento/backend/Magento_AdminNotification/web/css/source/_module.less +++ b/app/design/adminhtml/Magento/backend/Magento_AdminNotification/web/css/source/_module.less @@ -15,8 +15,8 @@ // --------------------------------------------- .message-system-inner { + &:extend(.abs-clearfix all); background: @message-system__background-color; - .extend__clearfix(); .message-system-list { float: left; width: 75%; diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/layout/default.xml b/app/design/adminhtml/Magento/backend/Magento_Backend/layout/default.xml index 977f917eb142c81687bc6c48a6b1856e780d6cdd..e7b337a7ec11b7ff523b3d031405404cc07f7361 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/layout/default.xml +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/layout/default.xml @@ -13,7 +13,7 @@ <body> - <referenceContainer name="page.wrapper"> + <referenceContainer name="root"> <container name="menu.wrapper" before="-" htmlTag="div" htmlClass="menu-wrapper"/> </referenceContainer> diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less index 2fe7569f06c995e426241930d01694c5fa15c438..7301a194265965ffa0776e50028458db1651537d 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/_menu.less @@ -40,6 +40,8 @@ @submenu-column__width__l: 19.8rem; @submenu-title__color: @color-white; @submenu-link__color: @color-very-light-gray; +@submenu-link__padding-vertical: 1.25rem; +@submenu-link__active__background-color: darken(@submenu-link__focus__background-color, 5%); @submenu-link__focus__background-color: @color-black4-almost; @submenu-section-label__color: @color-gray65-almost; @submenu-heading-group__indent-bottom: 3.8rem; @@ -50,22 +52,29 @@ // --------------------------------------------- .menu-wrapper { - height: 100%; - left: 0; - position: fixed; - top: 0; + float: left; + position: relative; width: @menu__width; z-index: @menu__z-index; - &:after { + &:before { background-color: @menu__background-color; bottom: 0; content: ''; left: 0; - position: absolute; - right: 0; + position: fixed; top: 0; + width: @menu__width; z-index: @menu-wrapper__z-index; } + &._fixed { + left: 0; + position: fixed; + top: 0; + ~ .page-wrapper { + margin-left: @menu__width; + } + } + .logo { display: block; height: @menu-logo-img__height + @menu-logo__padding-top + @menu-logo__padding-bottom; @@ -117,7 +126,6 @@ // --------------------------------------------- .admin__menu { - position: relative; li { display: block; } @@ -193,19 +201,30 @@ > .submenu { background-color: @submenu__background-color; box-shadow: 0 0 3px @color-black; - left: -90rem; + left: 100%; // align all submenus with one Y axis line min-height: ~'calc(@{menu-logo__outer-size} + 2rem + 100%)'; padding: @submenu__padding-vertical 0 0; position: absolute; top: -@menu-logo__outer-size; - transition: all .5s ease; + transform: translateX(-100%); + transition-property: transform, visibility; + transition-duration: .3s; + transition-timing-function: ease-in-out; visibility: hidden; - z-index: @submenu__z-index; + z-index: @submenu__z-index - 1; + &._overlap { + overflow-y: auto; + height: 100%; + &::-webkit-scrollbar { + width: 0; + } + } } &._show { > .submenu { - left: 100%; + transform: translateX(0); visibility: visible; + z-index: @submenu__z-index; } } } @@ -219,7 +238,15 @@ &:not(.level-0) { a { display: block; - padding: 1.25rem @submenu__padding-horizontal; + padding: @submenu-link__padding-vertical @submenu__padding-horizontal; + &:hover { + background-color: @submenu-link__focus__background-color; + } + &:active { + padding-top: @submenu-link__padding-vertical + .1rem; + padding-bottom: @submenu-link__padding-vertical - .1rem; + background-color: @submenu-link__active__background-color; + } } } } @@ -230,15 +257,19 @@ } a { color: @submenu-link__color; - ._keyfocus & { - text-decoration: none; - } - &:active, + transition: background-color .1s linear; + &:hover, &:focus { box-shadow: none; - ._keyfocus & { + text-decoration: none; + } + ._keyfocus & { + &:focus { background-color: @submenu-link__focus__background-color; } + &:active { + background-color: @submenu-link__active__background-color; + } } } .parent { @@ -395,7 +426,7 @@ .admin__menu-overlay { bottom: 0; left: 0; - position: absolute; + position: fixed; right: 0; top: 0; z-index: @menu-overlay__z-index; diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_actions-bar.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_actions-bar.less index fada0a346fefbae001a76744fab17fbb07216c16..a97ca5ab66cd0bcd1c2ad47e184be91715c5061b 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_actions-bar.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_actions-bar.less @@ -20,17 +20,17 @@ @page-main-actions__background-color: @color-white-fog; @page-main-actions__border-color: @color-gray89; -@page-main-actions__padding-side: @content__indent / 2; +@page-main-actions__padding: @content__indent / 2; // .page-main-actions:not(._hidden), .page-actions._fixed { - .extend__clearfix(); + &:extend(.abs-clearfix all); background: @page-main-actions__background-color; border-bottom: 1px solid @page-main-actions__border-color; border-top: 1px solid @page-main-actions__border-color; - padding: @page-main-actions__padding-side; + padding: @page-main-actions__padding; } .page-main-actions { diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less index 433873096a7c137f6e9647ca7ef9d6342b14f66f..43a0cc5f30f0a3f9927a0eaf6f8d3c4dcaea35c3 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/main/_collapsible-blocks.less @@ -287,6 +287,15 @@ td[colspan] { padding: 0; } + .admin__control-table { + margin: 0 0 @indent__xs; + td { + padding: @control-table-cell__padding-vertical 2.5rem @control-table-cell__padding-vertical 0; + &:first-child { + padding-left: 1.5rem; + } + } + } input[type='text'], input[type='password'], select, diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_dashboard.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_dashboard.less index bb55d0e0722cdbb18b1b315f8ce82703ebeea40c..ed511e65dfcb8432013ee73f2a3271e81760763c 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_dashboard.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_dashboard.less @@ -131,8 +131,8 @@ } .dashboard-totals-list { + &:extend(.abs-clearfix all); display: table; - .extend__clearfix(); .extend__list-reset-styles(); width: 100%; } @@ -165,7 +165,7 @@ .dashboard-store-stats { .ui-tabs { - .extend__clearfix(); + &:extend(.abs-clearfix all); margin-bottom: 0; position: relative; &:before { diff --git a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_login.less b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_login.less index c6966df69c5c1bda38491371ae79002b88e4f51d..2e93e6c124f17ce361713723c553d6b078a0a1b1 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_login.less +++ b/app/design/adminhtml/Magento/backend/Magento_Backend/web/css/source/module/pages/_login.less @@ -35,6 +35,7 @@ background-color: @login-box__background-color; border: @login-box__border; box-shadow: @login-box__shadow; + float: none; margin: auto; max-width: @login-box__max-width; min-height: @login-box__min-height; diff --git a/app/design/adminhtml/Magento/backend/Magento_ConfigurableProduct/web/css/source/module.less b/app/design/adminhtml/Magento/backend/Magento_ConfigurableProduct/web/css/source/module.less index 0b67d8d1e20caa8720165790508cf50dd4ef4727..03e7bc2982c08a004a3311085732123c535acfd1 100644 --- a/app/design/adminhtml/Magento/backend/Magento_ConfigurableProduct/web/css/source/module.less +++ b/app/design/adminhtml/Magento/backend/Magento_ConfigurableProduct/web/css/source/module.less @@ -45,43 +45,63 @@ } } -#product-variations-matrix .actions-image-uploader { - .dropdown-split( +#product-variations-matrix { + .actions-image-uploader { + .dropdown-split( @_dropdown-split-list-pointer: false - ); - display: block; - width: 50px; + ); - .action.toggle { - padding: 0 2px; - border: 1px solid #b7b2a7; - background: #fff; - border-radius: 0 4px 4px 0; - border-left: none; - height: 33px; + display: block; + width: 50px; + + .action.toggle { + padding: 0 3px; + border: 1px solid #b7b2a7; + background: #fff; + border-radius: 0 1px 1px 0; + border-left: none; + height: 31px; - &.no-display { - display: none; + &.no-display { + display: none; + } + + &:after { + width: 12px; + text-indent: -5px; + } } - &:after { - width: 12px; - text-indent: -5px; + ul.dropdown { + left: 0; + margin-left: 0; + width: 100px; + + li:hover { + background: #eef8fc; + } + + a { + color: #333; + text-decoration: none; + } } } - ul.dropdown { - left: 0; - margin-left: 0; - width: 100px; + .col-name { + position: relative; + } - li:hover { - background: #eef8fc; - } + .action-choose { + margin-left: 5px; + position: absolute; + top: 17px; + } - a { - color: #333; - text-decoration: none; + .col-qty, + .col-weight { + > input { + width: 5.5rem; } } } diff --git a/app/design/adminhtml/Magento/backend/Magento_CurrencySymbol/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_CurrencySymbol/web/css/source/_module.less new file mode 100644 index 0000000000000000000000000000000000000000..ac39bbc1b8814c2caeee24c82d8b013dfafe1765 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_CurrencySymbol/web/css/source/_module.less @@ -0,0 +1,15 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +.admin__fieldset-import-service { + margin: 0 0 @indent__base; + .admin__field { + margin: 0 0 @indent__base; + } + > .action-default { + #mix-grid .return_length(@field-label-grid__column, @field-grid__columns, @mathSymbol: '+'); + margin-left: @_length; + } +} diff --git a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_items.less b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_items.less index d7e53b974b8d8534f955a8489422419c1af6a00f..960bbd1e167cd11b89636a8754b5a895d5b96484 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_items.less +++ b/app/design/adminhtml/Magento/backend/Magento_Sales/web/css/source/module/order/_items.less @@ -103,14 +103,17 @@ } } .custom-price-block { - font-size: @order-create-sidebar__font-size__xs; - margin: 0 0 @order-create-sidebar__margin__s; + .admin__control-text { &:extend(.abs-control-price); } } + .custom-price-block, .discount-price-block { font-size: @order-create-sidebar__font-size__xs; + margin: 0 0 @order-create-sidebar__margin__s; + .admin__field-label { + line-height: 1.6rem; + } } .product-configure-block { margin: @indent__s 0 0; diff --git a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-action-columns.less b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-action-columns.less index fe7365ba224c40da0087445bc1f5f37c8918ff2e..9789fc82cddf8fd3dbaa272037756ab2b15b1e4f 100644 --- a/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-action-columns.less +++ b/app/design/adminhtml/Magento/backend/Magento_Ui/web/css/source/module/data-grid/data-grid-header/_data-grid-action-columns.less @@ -60,7 +60,7 @@ } } .admin__action-dropdown-menu-content { - .extend__clearfix(); + &:extend(.abs-clearfix all); max-height: (@data-grid-action-columns-menu-items-to-scroll / @data-grid-action-columns-menu-item__column) * (@data-grid-action-columns-menu-item__height + @data-grid-action-columns-menu-item__margin-bottom) + (@data-grid-action-columns-menu-item__height / 2 + @data-grid-action-columns-menu-item__margin-bottom); overflow-y: auto; padding-top: 1.5rem; diff --git a/app/design/adminhtml/Magento/backend/composer.json b/app/design/adminhtml/Magento/backend/composer.json index a84640d0b36435508b808c673866ffe7889e35fc..58fbb8be56c6018d058fc9797820f32babab0f07 100644 --- a/app/design/adminhtml/Magento/backend/composer.json +++ b/app/design/adminhtml/Magento/backend/composer.json @@ -3,11 +3,11 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-theme", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_components.less b/app/design/adminhtml/Magento/backend/web/css/source/_components.less index 906c538fc04f7391d62733bd2768aafd188babfd..a9ee8f523cc024a0cf14676317158fd8175d58a2 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_components.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_components.less @@ -11,3 +11,5 @@ @import 'components/_calendar-temp.less'; @import 'components/_messages.less'; @import 'components/_popups.less'; +@import 'components/_modals.less'; +@import 'components/_modals_extend.less'; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_extends.less b/app/design/adminhtml/Magento/backend/web/css/source/_extends.less index 26099b295ea07cc1188b355849aa9aacec87f4d4..bb2becf9ccdac9cfe88b140b89dc300d32309ca6 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_extends.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_extends.less @@ -56,15 +56,11 @@ &:extend(.abs-visually-hidden-reset all); } -// Clearfix +// Clearfixes .abs-clearfix { .clearfix(); } -.extend__clearfix() { - &:extend(.abs-clearfix all); -} - // Clearer - clearing container using only :after element .abs-clearer { .clearer(); diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_structure.less b/app/design/adminhtml/Magento/backend/web/css/source/_structure.less index f7e0dbde07ca8958b2778f02d9811eb077738ae8..c4431841153075f491aa72e6d42e63378bfcbb6c 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_structure.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_structure.less @@ -11,6 +11,8 @@ // Variables // --------------------------------------------- +@window__min-width: 1024px; + @body__background-color: @color-white-smoke; @page-wrapper__indent-left: @menu__width; @@ -23,23 +25,31 @@ // +html { + height: 100%; +} + body { + &:extend(.abs-clearer all); background-color: @body__background-color; + min-height: 100%; + min-width: 102.4rem; } .page-wrapper { background-color: @page-wrapper__background-color; - min-width: 102.4rem; - padding-left: @page-wrapper__indent-left; + float: left; + width: ~'calc(100% - @{menu__width})'; } .page-content { - .extend__clearfix(); + &:extend(.abs-clearfix all); padding-bottom: @page-content__padding-vertical; padding-left: @page-content__padding-horizontal; padding-right: @page-content__padding-horizontal; } +// ToDo UI: should be moved to messages .notices-wrapper { margin: 0 3rem; .messages { @@ -47,6 +57,16 @@ body { } } +// Scroll bar appearing compensation +@media (min-width: @window__min-width) { + html { + width: 100vw; + } + body { + overflow-x: hidden; + } +} + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .page-layout-admin-2columns-left { .page-columns { diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_tabs.less b/app/design/adminhtml/Magento/backend/web/css/source/_tabs.less index 1728f1f08b5e655e4f61a43b9efd443f266c5c5e..2f9c78be1167153a7cb72502b61bed2be3fe7617 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_tabs.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_tabs.less @@ -10,7 +10,7 @@ // Are used in dashboard .tabs-horiz { - .extend__clearfix(); + &:extend(.abs-clearfix all); margin: 0; padding: 0; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/_typography.less b/app/design/adminhtml/Magento/backend/web/css/source/_typography.less index ef2beb554b5a79d5a0512720366d68cc6787b81b..cf7905e1c736deeedf3615cd7e7ec0e1fb319a73 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/_typography.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/_typography.less @@ -46,11 +46,6 @@ // -html, -body { - height: 100%; -} - html { font-size: 62.5%; } diff --git a/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-split.less b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-split.less index 402bd4b223727a8e437a3ce7dd66a6f09c898885..59c603217790a22e43d5f8fd245ba0a81d20831e 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-split.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/actions/_actions-split.less @@ -40,7 +40,7 @@ @_action-default__min-width: 9.3rem; @_action-toggle__width: @action__height; - .extend__clearfix(); + &:extend(.abs-clearfix all); position: relative; z-index: @actions-split__z-index; &.active, diff --git a/app/design/adminhtml/Magento/backend/web/css/source/components/_modals_extend.less b/app/design/adminhtml/Magento/backend/web/css/source/components/_modals_extend.less new file mode 100644 index 0000000000000000000000000000000000000000..6575810401fda06e5810e56f658fbabeea170ac8 --- /dev/null +++ b/app/design/adminhtml/Magento/backend/web/css/source/components/_modals_extend.less @@ -0,0 +1,87 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Components -> Modals +// _____________________________________________ + +// +// Variables +// --------------------------------------------- + +@modal-title__color: @text__color; + +@modal-popup-title__font-size: 2.4rem; + +@modal-slide-title__font-size: 2.1rem; + +@modal-action-close__color: @color-brownie-vanilla; +@modal-action-close__font-size: 2rem; +@modal-action-close__active__font-size: 1.8rem; +@modal-action-close__hover__color: darken(@color-brownie-vanilla, 10%); + +// + +.modal-popup, +.modal-slide { + .action-close { + color: @modal-action-close__color; + position: absolute; + right: 0; + top: 0; + &:active { + transform: none; + &:before { + font-size: @modal-action-close__active__font-size; + } + } + &:hover { + &:before { + color: @modal-action-close__hover__color; + } + } + &:before { + font-size: @modal-action-close__font-size; + } + } +} + +.modal-popup { + .modal-title { + font-size: @modal-popup-title__font-size; + margin-right: @modal-popup-title__font-size + @modal-popup__padding + 1rem; + } + .action-close { + padding: @modal-popup__padding; + &:active { + padding-top: @modal-popup__padding + (@modal-action-close__font-size - @modal-action-close__active__font-size) / 2; + padding-right: @modal-popup__padding + (@modal-action-close__font-size - @modal-action-close__active__font-size) / 2; + } + } +} + +.modal-slide { + .modal-title { + font-size: @modal-slide-title__font-size; + margin-right: @modal-slide-title__font-size + @modal-slide__padding + 1rem; + } + .action-close { + padding: @modal-slide-header__padding-vertical @modal-slide__padding; + &:active { + padding-top: @modal-slide-header__padding-vertical + (@modal-action-close__font-size - @modal-action-close__active__font-size) / 2; + padding-right: @modal-slide__padding + (@modal-action-close__font-size - @modal-action-close__active__font-size) / 2; + } + } + .page-main-actions { + margin-top: @modal-slide-header__padding-vertical; + margin-bottom: @modal-slide-header__padding-vertical - @page-main-actions__padding; + } +} + +.modal-title { + font-weight: @font-weight__regular; + margin-bottom: 0; + min-height: 1em; +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less index 9bece984eb4ef5d04f24aadb1ed0c7278f5e3a8d..fcdae3d29f0a5d535b8b349abf1f1c1246122e83 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_fields.less @@ -31,6 +31,10 @@ @field-error-message__border-color: @color-apricot; @field-error-message__color: @color-very-dark-gray2; +@field-grid__columns: 9; +@field-control-grid__column: 4; +@field-label-grid__column: 3; + // // Form Fields // _____________________________________________ @@ -54,11 +58,11 @@ &:extend(.abs-field-rows all); } > .admin__field-control { - #mix-grid .column(4,9); + #mix-grid .column(@field-control-grid__column, @field-grid__columns); } > .admin__field-label { - #mix-grid .column(3,9); + #mix-grid .column(@field-label-grid__column, @field-grid__columns); } } } @@ -164,7 +168,7 @@ &[data-config-scope] { &:before { - #mix-grid .return_length(7,9); + #mix-grid .return_length(7, @field-grid__columns); color: @field-scope__color; content: attr(data-config-scope); display: inline-block; @@ -175,7 +179,7 @@ position: absolute; & { - #mix-grid .return_length(2,9); + #mix-grid .return_length(2, @field-grid__columns); width: @_length; } } @@ -267,7 +271,7 @@ & > .admin__field:first-child { position: static; & > .admin__field-label { - #mix-grid .column(3, 9); + #mix-grid .column(@field-label-grid__column, @field-grid__columns); cursor: pointer; left: 0; opacity: 0; diff --git a/app/design/adminhtml/Magento/backend/web/css/source/forms/_temp.less b/app/design/adminhtml/Magento/backend/web/css/source/forms/_temp.less index 2ba9ee7f8678f1eccc7b162b1be56a23f68b3359..92274b9c27f450901876e75cb849c93b572c5861 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/forms/_temp.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/forms/_temp.less @@ -19,9 +19,9 @@ .extend__clearer(); margin-left: ~'-@{temp_gutter}'; } - .return_length(@_columns-min, @_total: @temp_columns) { + .return_length(@_columns-min, @_total: @temp_columns, @mathSymbol: '-') { @_part: @_columns-min/@_total; - @_length: ~'calc( (100%) * @{_part} - @{temp_gutter} )'; + @_length: ~'calc( (100%) * @{_part} @{mathSymbol} @{temp_gutter} )'; } .width(@_columns-min, @_total: @temp_columns) { #mix-grid .return_length(@_columns-min, @_total); @@ -517,3 +517,10 @@ label.mage-error { padding-right: 1.8rem; } } + +.product-configure-popup { + .time-picker { + display: block; + margin-top: 1rem; + } +} diff --git a/app/design/adminhtml/Magento/backend/web/css/source/variables/_structure.less b/app/design/adminhtml/Magento/backend/web/css/source/variables/_structure.less index 521d53cbe3e4cbce844ca3fdaeab6139473e643e..04ed06bee4107f9d1aa22ed0aba1e5ea7a27996a 100644 --- a/app/design/adminhtml/Magento/backend/web/css/source/variables/_structure.less +++ b/app/design/adminhtml/Magento/backend/web/css/source/variables/_structure.less @@ -22,17 +22,6 @@ // Z axis // --------------------------------------------- -@z-index-1: 100; -@z-index-2: 200; -@z-index-3: 300; -@z-index-4: 400; -@z-index-5: 500; -@z-index-6: 600; -@z-index-7: 700; -@z-index-8: 800; -@z-index-9: 900; -@z-index-10: 1000; - // z-index 2 @actions-split__z-index: @z-index-2; @action-multiselect__z-index: @z-index-2; @@ -52,9 +41,6 @@ // z-index 7 @menu__z-index: @z-index-7; -// z-index 8 -@overlay__z-index: @z-index-8; - // Base z-index for page wrapper to prevent inner page element overlap with pop-ups @page-wrapper__z-index__base: 1; @@ -65,8 +51,3 @@ @content__indent: @indent__l; @menu__width: 8.8rem; - -@component__shadow-size__base: 5px; -@component__box-shadow__base: 1px 1px @component__shadow-size__base rgba(0, 0, 0, .5); - -@component-modal__opacity: .98; diff --git a/app/design/adminhtml/Magento/backend/web/css/styles-old.less b/app/design/adminhtml/Magento/backend/web/css/styles-old.less index e95925876fca2a1fa9bb037239d168c733833174..dbce802f7266dd4610e2d66492bf554cea335af9 100644 --- a/app/design/adminhtml/Magento/backend/web/css/styles-old.less +++ b/app/design/adminhtml/Magento/backend/web/css/styles-old.less @@ -345,10 +345,6 @@ input.no-display, .data-table .action-locked.active, .data-table .action-locked[disabled], #product-variations-matrix .action-choose, - #product-variations-matrix .action-choose:hover, - #product-variations-matrix .action-choose:active, - #product-variations-matrix .action-choose.active, - #product-variations-matrix .action-choose[disabled], .action-manage-images, .action-manage-images:hover, .action-manage-images:active, @@ -406,7 +402,6 @@ input.no-display, .data-table .action-.delete[disabled], .data-table .action-delete[disabled], .data-table .action-locked[disabled], - #product-variations-matrix .action-choose[disabled], .image-panel .action-close[disabled], .image-panel-controls .action-remove[disabled], .suggest-expandable .action-show-all[disabled], diff --git a/app/design/adminhtml/Magento/backend/web/js/theme.js b/app/design/adminhtml/Magento/backend/web/js/theme.js index 56921a21e7f2d83eb9cf13e5c446f86b55640c60..c3d695cb9e5821c4fbf780bf445d29e7ceee6fe3 100644 --- a/app/design/adminhtml/Magento/backend/web/js/theme.js +++ b/app/design/adminhtml/Magento/backend/web/js/theme.js @@ -3,9 +3,145 @@ * See COPYING.txt for license details. */ +define('globalNavigationScroll', [ + 'jquery' +], function ($) { + 'use strict'; + + var win = $(window), + subMenuClass = '.submenu', + overlapClassName = '_overlap', + fixedClassName = '_fixed', + menu = $('.menu-wrapper'), + content = $('.page-wrapper'), + menuItems = $('#nav').children('li'), + subMenus = menuItems.children(subMenuClass), + winHeight, + menuHeight = menu.height(), + menuHeightRest = 0, + menuScrollMax = 0, + submenuHeight = 0, + contentHeight, + winTop = 0, + winTopLast = 0, + scrollStep = 0, + nextTop = 0; + + /** + * Check if menu is fixed + * @returns {boolean} + */ + function isMenuFixed() { + return (menuHeight < contentHeight) && (contentHeight > winHeight); + } + + /** + * Check if class exist than add or do nothing + * @param {jQuery} el + * @param $class string + */ + function checkAddClass(el, $class) { + if (!el.hasClass($class)) { + el.addClass($class); + } + } + + /** + * Check if class exist than remove or do nothing + * @param {jQuery} el + * @param $class string + */ + function checkRemoveClass(el, $class) { + if (el.hasClass($class)) { + el.removeClass($class); + } + } + + /** + * Calculate and apply menu position + */ + function positionMenu() { + + // Spotting positions and heights + winHeight = win.height(); + contentHeight = content.height(); + winTop = win.scrollTop(); + scrollStep = winTop - winTopLast; + menuHeightRest = menuHeight - winTop; // is a visible menu height + + if (isMenuFixed()) { // fixed menu cases + + checkAddClass(menu, fixedClassName); + + if (menuHeight > winHeight) { // smart scroll cases + + if (winTop > winTopLast) { // scroll down + + menuScrollMax = menuHeight - winHeight; + + nextTop < (menuScrollMax - scrollStep) ? + nextTop += scrollStep : nextTop = menuScrollMax; + + menu.css('top', -nextTop); + + } else if (winTop < winTopLast) { // scroll up + + nextTop > -scrollStep ? + nextTop += scrollStep : nextTop = 0; + + menu.css('top', -nextTop); + + } + + } + + } else { // static menu cases + checkRemoveClass(menu, fixedClassName); + } + + // Save previous window scrollTop + winTopLast = winTop; + + } + + positionMenu(); // page start calculation + + // Change position on scroll + win.on('scroll', function () { + positionMenu(); + }); + + win.on('resize', function () { + + winHeight = win.height(); + + // Reset position if fixed and out of smart scroll + if ((menuHeight < contentHeight) && (menuHeight <= winHeight)) { + menu.removeAttr('style'); + // Remove overlap classes from submenus and clear overlap adding event + subMenus.removeClass(overlapClassName); + menuItems.off(); + } + + }); + + // Add event to menuItems to check submenu overlap + menuItems.on('click', function () { + + var submenu = $(this).children(subMenuClass); + submenuHeight = submenu.height(); + + if (isMenuFixed() && (submenuHeight > winHeight)) { + checkAddClass(submenu, overlapClassName); + } + }); + +}); + define('globalNavigation', [ 'jquery', - 'jquery/ui' + 'jquery/ui', + 'globalNavigationScroll' ], function ($) { 'use strict'; diff --git a/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_module.less index d6dd6315b31c51f33ca02547e80b87f793ce49d7..97f0f32bad1cd22fa24b77aee31dda53f625fafc 100644 --- a/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Sales/web/css/source/_module.less @@ -4,8 +4,8 @@ // */ // -// Common -//-------------------------------------- +// Common +// --------------------------------------------- & when (@media-common = true) { @@ -95,6 +95,7 @@ } .account, +[class^="sales-guest-"], .sales-guest-view { .page-title-wrapper { .page-title { @@ -188,8 +189,10 @@ } // -// Guest order view page -//-------------------------------------- +// Guest order view page +// --------------------------------------------- + +[class^="sales-guest-"], .sales-guest-view { .column.main { .block:not(.widget) { @@ -201,8 +204,9 @@ } // -// Mobile -//-------------------------------------- +// Mobile +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { .account { .order-details-items { @@ -232,8 +236,9 @@ } // -// Desktop -//-------------------------------------- +// Desktop +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .table-order-items { .subtotal, @@ -269,8 +274,10 @@ } // - // Guest order view page - //-------------------------------------- + // Guest order view page + // --------------------------------------------- + + [class^="sales-guest-"], .sales-guest-view { .column.main { .block:not(.widget) { diff --git a/app/design/frontend/Magento/blank/composer.json b/app/design/frontend/Magento/blank/composer.json index 3c301e591a8fb223501875962ef75af9da3e117a..ed12dd50070e3732d4d1dad3ae1035b8452d9dc4 100644 --- a/app/design/frontend/Magento/blank/composer.json +++ b/app/design/frontend/Magento/blank/composer.json @@ -3,11 +3,11 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-theme", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/design/frontend/Magento/blank/web/css/print.less b/app/design/frontend/Magento/blank/web/css/print.less index 8b82b43ad6a3291e3b955958454b95318299051f..0e2e9e7fed8fc30f3ee6adbba00ae989c4f81f03 100644 --- a/app/design/frontend/Magento/blank/web/css/print.less +++ b/app/design/frontend/Magento/blank/web/css/print.less @@ -77,6 +77,9 @@ h3 { page-break-after: avoid; } + .nav-toggle { + display: none !important; + } .sidebar, .nav-sections, .header.content > *[class], diff --git a/app/design/frontend/Magento/blank/web/css/source/_tables.less b/app/design/frontend/Magento/blank/web/css/source/_tables.less index 66b56eb77b4f10bd73a62510f35eae6c07f66bc0..aef5ae55b1f4eb0bf2ac239465d23a2de5503fbc 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_tables.less +++ b/app/design/frontend/Magento/blank/web/css/source/_tables.less @@ -23,11 +23,13 @@ table { @_table_border-width: @table__border-width ); tfoot { - > tr:first-child { - th, - td { - border-top: @table__border-width @table__border-style @table__border-color; - padding-top: @indent__base; + > tr { + &:first-child { + th, + td { + border-top: @table__border-width @table__border-style @table__border-color; + padding-top: @indent__base; + } } } .mark { @@ -85,6 +87,19 @@ table { width: 30%; } } + &.additional-attributes { + tbody { + th { + &:extend(.abs-no-display-s all); + } + td { + &:last-child { + border: none; + padding: 0 0 @indent__xs; + } + } + } + } } } } diff --git a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less index 110feac0776b802714610b4d3a008f7211027b03..76a5fa1fd4d87b96459a3fa4ce1b85b2bb5dc2ce 100644 --- a/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Catalog/web/css/source/_module.less @@ -524,13 +524,6 @@ .additional-attributes-wrapper { &:extend(.abs-no-border-top all); } - .additional-attributes { - tbody { - th { - &:extend(.abs-no-display-s all); - } - } - } } } diff --git a/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less index a38d28d2443c18e53258eec7ee2343a946cd48c1..b1984fc64e9003144e1579bf2d854f6ba659013e 100644 --- a/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less @@ -8,8 +8,8 @@ @account-table-action-delete: @color-red12; // -// Common -//-------------------------------------- +// Common +// --------------------------------------------- & when (@media-common = true) { @@ -77,7 +77,7 @@ } } -// My account +// My account .account { .page-title-wrapper { .page-title { @@ -107,8 +107,24 @@ margin-bottom: 0; } } + .legend { + &:extend(.abs-account-title all); + } +} + +.account, +[class^="sales-guest-"], +.sales-guest-view { + .column.main { + .order-details-items { + .table-wrapper { + .data.table { + &:extend(.abs-table-striped all); + } + } + } + } .data.table { - &:extend(.abs-table-striped all); .col.actions { .action { &:extend(.abs-account-actions all); @@ -118,12 +134,9 @@ } } } - .legend { - &:extend(.abs-account-title all); - } } -// Checkout address (create shipping address) +// Checkout address (create shipping address) .field.street { .field.additional { .label { @@ -133,8 +146,9 @@ } // -// Blocks & Widgets -//-------------------------------------- +// Blocks & Widgets +// --------------------------------------------- + .block { &:extend(.abs-margin-for-blocks-and-widgets all); .column.main & { @@ -181,8 +195,9 @@ } // -// Desktop -//-------------------------------------- +// Desktop +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .login-container { &:extend(.abs-add-clearfix-desktop all); @@ -217,7 +232,7 @@ min-width: 600px; } - // My account + // My account .account.page-layout-2columns-left { .sidebar-main, .sidebar-additional { @@ -299,8 +314,9 @@ } // -// Mobile @screen__s -//-------------------------------------- +// Mobile @screen__s +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { .account { .column.main, @@ -314,8 +330,9 @@ } // -// Mobile @screen__m -//-------------------------------------- +// Mobile @screen__m +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { .login-container { .fieldset { diff --git a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less index 3c172bdb6a4281905a01ef1912d31663a9e3a42b..0d1b84affd292387856a20422cdc6789f53900f9 100644 --- a/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Sales/web/css/source/_module.less @@ -4,8 +4,8 @@ // */ // -// Common -//-------------------------------------- +// Common +// --------------------------------------------- & when (@media-common = true) { @@ -268,7 +268,9 @@ } .account, -.sales-guest-view { +[class^="sales-guest-"], +.sales-guest-view, +.magento-rma-guest-returns { &:extend(.abs-title-orders all); } @@ -305,8 +307,10 @@ } // -// Guest order view page -//-------------------------------------- +// Guest order view page +// --------------------------------------------- + +[class^="sales-guest-"], .sales-guest-view { .column.main { .block:not(.widget) { @@ -315,11 +319,24 @@ } } +.magento-rma-guest-returns { + .column.main { + .order-details-items { + .table-wrapper { + .data.table { + &:extend(.abs-table-striped all); + } + } + } + } +} + } // -// Mobile -//-------------------------------------- +// Mobile +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { .table-wrapper { &.orders-recent { @@ -352,6 +369,7 @@ } } .account, + [class^="sales-guest-"], .sales-guest-view { &:extend(.abs-title-orders-mobile all); } @@ -412,8 +430,9 @@ } // -// Desktop -//-------------------------------------- +// Desktop +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) { .order-details-items { .order-title { @@ -427,9 +446,6 @@ } } -// -// Desktop -//-------------------------------------- .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .table-wrapper.orders-recent { &:extend(.abs-account-table-margin-desktop all); @@ -459,6 +475,7 @@ } .account, + [class^="sales-guest-"], .sales-guest-view { &:extend(.abs-title-orders-desktop all); .column.main .block.block-order-details-view { diff --git a/app/design/frontend/Magento/luma/composer.json b/app/design/frontend/Magento/luma/composer.json index 0d81261558ced2f07df8f16b8601d14e4e6c13af..84cbda7b1c907d6bc7262137162476f6a1d94ca3 100644 --- a/app/design/frontend/Magento/luma/composer.json +++ b/app/design/frontend/Magento/luma/composer.json @@ -3,12 +3,12 @@ "description": "N/A", "require": { "php": "~5.5.0|~5.6.0", - "magento/theme-frontend-blank": "0.74.0-beta10", - "magento/framework": "0.74.0-beta10", + "magento/theme-frontend-blank": "0.74.0-beta13", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-theme", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/app/design/frontend/Magento/luma/i18n/en_US.csv b/app/design/frontend/Magento/luma/i18n/en_US.csv index 57c395ca05625be8715af0e7c2b7e8318bbb3ac8..c407d6608c877cd7d8efd758671e14fe2ed2cc34 100644 --- a/app/design/frontend/Magento/luma/i18n/en_US.csv +++ b/app/design/frontend/Magento/luma/i18n/en_US.csv @@ -1,4 +1,4 @@ -"Add to Wishlist", "Wishlist" +"Add to Wish List", "Wish List" "Add to Compare", "Compare" "Your Checkout Progress", "Checkout Progress" "Card Verification Number", "CVV" diff --git a/app/design/frontend/Magento/luma/web/css/source/_tables.less b/app/design/frontend/Magento/luma/web/css/source/_tables.less index 14f31d64bd27a0e5067ffe4f5e7fba658d859c40..9074d5aa2e1f9a19fe79d3636ce18f15365ae2dd 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_tables.less +++ b/app/design/frontend/Magento/luma/web/css/source/_tables.less @@ -20,11 +20,13 @@ table { .table { tfoot { .css(background, @sidebar__background-color); - > tr:first-child { - th, - td { - border-top: @table__border-width @table__border-style @table__border-color; - padding-top: @indent__base; + > tr { + &:first-child { + th, + td { + border-top: @table__border-width @table__border-style @table__border-color; + padding-top: @indent__base; + } } } th, @@ -95,6 +97,19 @@ table { } } } + &.additional-attributes { + tbody { + th { + &:extend(.abs-no-display-s all); + } + td { + &:last-child { + border: none; + padding: 0 0 @indent__xs; + } + } + } + } } } } diff --git a/app/etc/di.xml b/app/etc/di.xml old mode 100755 new mode 100644 index 00eb93bd1cc5f8a874e46d711caba22f2fc95feb..bf956a4b271b6fb22be26b6d668267db074349e8 --- a/app/etc/di.xml +++ b/app/etc/di.xml @@ -12,6 +12,7 @@ <preference for="Magento\Framework\Search\Adapter\Mysql\Filter\PreprocessorInterface" type="Magento\Framework\Search\Adapter\Mysql\Filter\Preprocessor" /> <preference for="Magento\Framework\Search\Adapter\Mysql\Field\ResolverInterface" type="Magento\Framework\Search\Adapter\Mysql\Field\Resolver" /> <preference for="Magento\Framework\Search\Request\Aggregation\StatusInterface" type="Magento\Framework\Search\Request\Aggregation\Status" /> + <preference for="Magento\Framework\Search\Adapter\Mysql\Field\FieldInterface" type="Magento\Framework\Search\Adapter\Mysql\Field\Field"/> <preference for="Magento\Framework\App\RequestInterface" type="Magento\Framework\App\Request\Http" /> <preference for="Magento\Framework\App\Request\PathInfoProcessorInterface" type="Magento\Store\App\Request\PathInfoProcessor" /> <preference for="Magento\Framework\App\ResponseInterface" type="Magento\Framework\App\Response\Http" /> @@ -44,6 +45,7 @@ <preference for="Magento\Framework\Config\CacheInterface" type="Magento\Framework\App\Cache\Type\Config" /> <preference for="Magento\Framework\Config\ValidationStateInterface" type="Magento\Framework\App\Arguments\ValidationState" /> <preference for="Magento\Framework\Module\ModuleListInterface" type="Magento\Framework\Module\ModuleList" /> + <preference for="Magento\Framework\Module\ModuleRegistryInterface" type="Magento\Framework\Module\Registrar" /> <preference for="Magento\Framework\Event\ConfigInterface" type="Magento\Framework\Event\Config" /> <preference for="Magento\Framework\Event\InvokerInterface" type="Magento\Framework\Event\Invoker\InvokerDefault" /> <preference for="Magento\Framework\Interception\PluginListInterface" type="Magento\Framework\Interception\PluginList\PluginList" /> @@ -131,7 +133,7 @@ <preference for="Magento\Framework\Api\Data\ImageContentInterface" type="Magento\Framework\Api\ImageContent" /> <preference for="Magento\Framework\Api\ImageContentValidatorInterface" type="Magento\Framework\Api\ImageContentValidator" /> <preference for="Magento\Framework\Api\ImageProcessorInterface" type="Magento\Framework\Api\ImageProcessor" /> - + <preference for="Magento\Framework\Code\Reader\ClassReaderInterface" type="Magento\Framework\Code\Reader\ClassReader" /> <type name="Magento\Framework\Model\Resource\Db\TransactionManager" shared="false" /> <type name="Magento\Framework\Logger\Handler\Base"> <arguments> @@ -634,8 +636,14 @@ <item name="factory" xsi:type="string">\Magento\Framework\ObjectManager\Code\Generator\Factory</item> <item name="proxy" xsi:type="string">\Magento\Framework\ObjectManager\Code\Generator\Proxy</item> <item name="interceptor" xsi:type="string">\Magento\Framework\Interception\Code\Generator\Interceptor</item> - <item name="decorator" xsi:type="string">\Magento\Framework\Interception\Code\Generator\Decorator</item> <item name="logger" xsi:type="string">\Magento\Framework\ObjectManager\Profiler\Code\Generator\Logger</item> + <item name="mapper" xsi:type="string">\Magento\Framework\Api\Code\Generator\Mapper</item> + <item name="persistor" xsi:type="string">\Magento\Framework\ObjectManager\Code\Generator\Persistor</item> + <item name="repository" xsi:type="string">\Magento\Framework\ObjectManager\Code\Generator\Repository</item> + <item name="convertor" xsi:type="string">\Magento\Framework\ObjectManager\Code\Generator\Converter</item> + <item name="searchResults" xsi:type="string">\Magento\Framework\Api\Code\Generator\SearchResults</item> + <item name="extensionInterface" xsi:type="string">\Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator</item> + <item name="extension" xsi:type="string">\Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator</item> </argument> </arguments> </type> @@ -1075,6 +1083,11 @@ <argument name="overriddenBaseFiles" xsi:type="object">lessFileOverriddenBase</argument> </arguments> </type> + <type name="Magento\Framework\Module\ModuleList\Loader"> + <arguments> + <argument name="filesystemDriver" xsi:type="object">Magento\Framework\Filesystem\Driver\File</argument> + </arguments> + </type> <type name="Magento\Framework\Module\Setup\MigrationData"> <arguments> <argument name="data" xsi:type="array"> diff --git a/app/i18n/magento/de_de/composer.json b/app/i18n/magento/de_de/composer.json index 483e918c3b1fa2997947326a1ceec68fcb68555b..8792a746870334173328153bee80077157349745 100644 --- a/app/i18n/magento/de_de/composer.json +++ b/app/i18n/magento/de_de/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-de_de", "description": "German (Germany) language", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/en_us/composer.json b/app/i18n/magento/en_us/composer.json index f25a545ee602e2cbd566d5c6b628fc10af9642be..12f592f50bc7f6772183dc3e44a42ecb65fbfb05 100644 --- a/app/i18n/magento/en_us/composer.json +++ b/app/i18n/magento/en_us/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-en_us", "description": "English (United States) language", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/es_es/composer.json b/app/i18n/magento/es_es/composer.json index 49be1b919d4ff218b06ceb7722a380e86a4734d2..eec09e8483fbe8846f06947d7d8fef60d284d0d0 100644 --- a/app/i18n/magento/es_es/composer.json +++ b/app/i18n/magento/es_es/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-es_es", "description": "Spanish (Spain) language", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/fr_fr/composer.json b/app/i18n/magento/fr_fr/composer.json index ad7c84d5542f1aae6202163a2b08a59cbbfa706b..7ff13b7e8f3aa58340613fe97806ecfcc1b174aa 100644 --- a/app/i18n/magento/fr_fr/composer.json +++ b/app/i18n/magento/fr_fr/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-fr_fr", "description": "French (France) language", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/nl_nl/composer.json b/app/i18n/magento/nl_nl/composer.json index a9ce8307e5d3f759431e86f7813b2e19666724d2..af92cc0e22f2de55041a7b8d0f6973cfa7244e09 100644 --- a/app/i18n/magento/nl_nl/composer.json +++ b/app/i18n/magento/nl_nl/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-nl_nl", "description": "Dutch (Netherlands) language", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/pt_br/composer.json b/app/i18n/magento/pt_br/composer.json index aaf84ee0cc1ebbfddfdc1fa634a495415c122656..ea475dfb76206af0453c1d37586d71107d2ea7bb 100644 --- a/app/i18n/magento/pt_br/composer.json +++ b/app/i18n/magento/pt_br/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-pt_br", "description": "Portuguese (Brazil) language", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/app/i18n/magento/zh_cn/composer.json b/app/i18n/magento/zh_cn/composer.json index ffe3b6cb5744fbce0ec841297f2a2e989532fa3b..fe43b44fcdc7f9e7a3f2b31fa64b08e5bee94b3b 100644 --- a/app/i18n/magento/zh_cn/composer.json +++ b/app/i18n/magento/zh_cn/composer.json @@ -1,13 +1,13 @@ { "name": "magento/language-zh_cn", "description": "Chinese (China) language", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" ], "require": { - "magento/framework": "0.74.0-beta10", + "magento/framework": "0.74.0-beta13", "magento/magento-composer-installer": "*" }, "type": "magento2-language", diff --git a/bin/magento b/bin/magento index 728379e2a2bcf518088c4d9f99cc0fcea7f9e159..38a7c73544e1ac42419f66b00172cf676ec29b2e 100755 --- a/bin/magento +++ b/bin/magento @@ -5,10 +5,16 @@ * See COPYING.txt for license details. */ +use Magento\Framework\AppInterface; + try { require __DIR__ . '/../app/bootstrap.php'; if (PHP_SAPI == 'cli') { - $application = new Magento\Framework\Console\Cli('Magento CLI'); + // For Cli we are using our customized error handler + $handler = new \Magento\Framework\App\ErrorHandler(); + set_error_handler([$handler, 'handler']); + + $application = new Magento\Framework\Console\Cli('Magento CLI', AppInterface::VERSION); $application->run(); } diff --git a/composer.json b/composer.json index eed43c95b4cca8b4533d6997ff2cdc6460ebf404..1879c7e9d60a5286dc36cb420766b99cd5c9b492 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "magento/magento2ce", "description": "Magento 2 (Community Edition)", "type": "project", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" @@ -30,8 +30,8 @@ "zendframework/zend-serializer": "2.4.0", "zendframework/zend-log": "2.4.0", "zendframework/zend-http": "2.4.0", - "magento/zendframework1": "1.12.10", - "composer/composer": "1.0.0-alpha9", + "magento/zendframework1": "1.12.13", + "composer/composer": "1.0.0-alpha10", "monolog/monolog": "1.11.0", "oyejorge/less.php": "1.7.0.3", "tubalmartin/cssmin": "2.4.8-p4", @@ -54,6 +54,7 @@ "ext-curl": "*", "ext-iconv": "*", "ext-intl": "*", + "ext-xsl": "*", "sjparkinson/static-review": "~4.1", "fabpot/php-cs-fixer": "~1.2", "lusitanian/oauth": "~0.3" @@ -64,6 +65,7 @@ "magento/module-backend": "self.version", "magento/module-backup": "self.version", "magento/module-bundle": "self.version", + "magento/module-bundle-import-export": "self.version", "magento/module-cache-invalidate": "self.version", "magento/module-captcha": "self.version", "magento/module-catalog": "self.version", @@ -126,7 +128,7 @@ "magento/module-sales-rule": "self.version", "magento/module-sales-sequence": "self.version", "magento/module-search": "self.version", - "magento/module-sendfriend": "self.version", + "magento/module-send-friend": "self.version", "magento/module-shipping": "self.version", "magento/module-sitemap": "self.version", "magento/module-store": "self.version", diff --git a/composer.lock b/composer.lock index dcf8c4b429aaced526af1abe94f793350d73e18b..2436cff71f1c366b3f281cc5a8c44a59a25762f5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,32 +4,32 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "83f0bf6faf27d24da65818858b1c9a67", + "hash": "55186e4b1650ca5f2ad865799800f636", "packages": [ { "name": "composer/composer", - "version": "1.0.0-alpha9", + "version": "1.0.0-alpha10", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "eb1ce550ca51134ee619ad3e37f5a0b7e980dd24" + "reference": "775f6cd5c633facf2e7b99611fdcaa900b58ddb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/eb1ce550ca51134ee619ad3e37f5a0b7e980dd24", - "reference": "eb1ce550ca51134ee619ad3e37f5a0b7e980dd24", + "url": "https://api.github.com/repos/composer/composer/zipball/775f6cd5c633facf2e7b99611fdcaa900b58ddb7", + "reference": "775f6cd5c633facf2e7b99611fdcaa900b58ddb7", "shasum": "" }, "require": { - "justinrainbow/json-schema": "~1.1", + "justinrainbow/json-schema": "~1.4", "php": ">=5.3.2", "seld/jsonlint": "~1.0", - "symfony/console": "~2.3", + "symfony/console": "~2.5", "symfony/finder": "~2.2", "symfony/process": "~2.1" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.5" }, "suggest": { "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", @@ -49,7 +49,7 @@ "Composer": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -72,7 +72,7 @@ "dependency", "package" ], - "time": "2014-12-07 17:15:20" + "time": "2015-04-14 21:18:51" }, { "name": "justinrainbow/json-schema", @@ -110,7 +110,7 @@ "JsonSchema": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -178,7 +178,7 @@ "MagentoHackathon\\Composer\\Magento": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "OSL-3.0" ], @@ -218,16 +218,16 @@ }, { "name": "magento/zendframework1", - "version": "1.12.10", + "version": "1.12.13", "source": { "type": "git", "url": "https://github.com/magento/zf1.git", - "reference": "d1e5cd8c9f83229bcdd9bb485c3ce25259c77884" + "reference": "07ce4e9fba448f4aa48acbb1605c68897dac595f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/magento/zf1/zipball/d1e5cd8c9f83229bcdd9bb485c3ce25259c77884", - "reference": "d1e5cd8c9f83229bcdd9bb485c3ce25259c77884", + "url": "https://api.github.com/repos/magento/zf1/zipball/07ce4e9fba448f4aa48acbb1605c68897dac595f", + "reference": "07ce4e9fba448f4aa48acbb1605c68897dac595f", "shasum": "" }, "require": { @@ -248,7 +248,7 @@ "Zend_": "library/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "include-path": [ "library/" ], @@ -261,7 +261,7 @@ "ZF1", "framework" ], - "time": "2015-02-06 17:25:45" + "time": "2015-06-02 08:04:41" }, { "name": "monolog/monolog", @@ -315,7 +315,7 @@ "Monolog\\": "src/Monolog" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -364,7 +364,7 @@ "lessc.inc.php" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "Apache-2.0" ], @@ -414,7 +414,7 @@ "Psr\\Log\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -458,7 +458,7 @@ "Seld\\JsonLint\\": "src/Seld/JsonLint/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -480,21 +480,20 @@ }, { "name": "symfony/console", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Console", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272" + "reference": "564398bc1f33faf92fc2ec86859983d30eb81806" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/ebc5679854aa24ed7d65062e9e3ab0b18a917272", - "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272", + "url": "https://api.github.com/repos/symfony/Console/zipball/564398bc1f33faf92fc2ec86859983d30eb81806", + "reference": "564398bc1f33faf92fc2ec86859983d30eb81806", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "psr/log": "~1.0", @@ -510,15 +509,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Console\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -534,25 +533,24 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-06-10 15:30:22" }, { "name": "symfony/finder", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Finder", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Finder.git", - "reference": "704c64c8b12c8882640d5c0330a8414b1e06dc99" + "reference": "c13a40d638aeede1e8400f8c956c7f9246c05f75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Finder/zipball/704c64c8b12c8882640d5c0330a8414b1e06dc99", - "reference": "704c64c8b12c8882640d5c0330a8414b1e06dc99", + "url": "https://api.github.com/repos/symfony/Finder/zipball/c13a40d638aeede1e8400f8c956c7f9246c05f75", + "reference": "c13a40d638aeede1e8400f8c956c7f9246c05f75", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -560,15 +558,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Finder\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -584,25 +582,24 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-06-04 20:11:48" }, { "name": "symfony/process", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Process", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Process.git", - "reference": "9f3c4baaf840ed849e1b1f7bfd5ae246e8509562" + "reference": "552d8efdc80980cbcca50b28d626ac8e36e3cdd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/9f3c4baaf840ed849e1b1f7bfd5ae246e8509562", - "reference": "9f3c4baaf840ed849e1b1f7bfd5ae246e8509562", + "url": "https://api.github.com/repos/symfony/Process/zipball/552d8efdc80980cbcca50b28d626ac8e36e3cdd1", + "reference": "552d8efdc80980cbcca50b28d626ac8e36e3cdd1", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -610,15 +607,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Process\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -634,7 +631,7 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-06-08 09:37:21" }, { "name": "tubalmartin/cssmin", @@ -659,7 +656,7 @@ "cssmin.php" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -686,12 +683,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-code.git", - "reference": "cfd5951ff4348e4430850560416c7ddb755f95d3" + "reference": "0ed94f842ba60cdc900c46a61bdbd7ac95a3e140" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-code/zipball/0ed94f842ba60cdc900c46a61bdbd7ac95a3e140", - "reference": "cfd5951ff4348e4430850560416c7ddb755f95d3", + "reference": "0ed94f842ba60cdc900c46a61bdbd7ac95a3e140", "shasum": "" }, "require": { @@ -700,6 +697,9 @@ }, "require-dev": { "doctrine/common": ">=2.1", + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-stdlib": "self.version" }, "suggest": { @@ -715,20 +715,20 @@ }, "autoload": { "psr-4": { - "Zend\\Code\\": "" + "Zend\\Code\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides facilities to generate arbitrary code using an object oriented interface", - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-code", "keywords": [ "code", "zf2" ], - "time": "2015-04-01 17:59:08" + "time": "2015-03-31 15:39:14" }, { "name": "zendframework/zend-config", @@ -736,12 +736,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-config.git", - "reference": "8682fe4e2923b383bb6472fc84b5796a07589163" + "reference": "95f3a4b3fa85d49e6f060183122de4596fa6d29d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-config/zipball/95f3a4b3fa85d49e6f060183122de4596fa6d29d", - "reference": "8682fe4e2923b383bb6472fc84b5796a07589163", + "reference": "95f3a4b3fa85d49e6f060183122de4596fa6d29d", "shasum": "" }, "require": { @@ -749,6 +749,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-filter": "self.version", "zendframework/zend-i18n": "self.version", "zendframework/zend-json": "self.version", @@ -769,20 +772,20 @@ }, "autoload": { "psr-4": { - "Zend\\Config\\": "" + "Zend\\Config\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides a nested object property based user interface for accessing this configuration data within application code", - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-config", "keywords": [ "config", "zf2" ], - "time": "2015-04-01 17:59:31" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-console", @@ -790,18 +793,23 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-console.git", - "reference": "94ab6663b07e19f20b3319ecf317bd72b6a72dca" + "reference": "54823d9ba6f8ce39046384ee5a043b5b3d5f56d7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-console/zipball/54823d9ba6f8ce39046384ee5a043b5b3d5f56d7", - "reference": "94ab6663b07e19f20b3319ecf317bd72b6a72dca", + "reference": "54823d9ba6f8ce39046384ee5a043b5b3d5f56d7", "shasum": "" }, "require": { "php": ">=5.3.23", "zendframework/zend-stdlib": "self.version" }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master" + }, "suggest": { "zendframework/zend-filter": "To support DefaultRouteMatcher usage", "zendframework/zend-validator": "To support DefaultRouteMatcher usage" @@ -815,19 +823,19 @@ }, "autoload": { "psr-4": { - "Zend\\Console\\": "" + "Zend\\Console\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-console", "keywords": [ "console", "zf2" ], - "time": "2015-04-01 17:59:48" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-di", @@ -835,12 +843,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-di.git", - "reference": "0811f2a67ad0b50dfb8d602ed67cde0b82249190" + "reference": "b9f8de081adecf71a003a569e9ba76c0a4c00bf2" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-di/zipball/b9f8de081adecf71a003a569e9ba76c0a4c00bf2", - "reference": "0811f2a67ad0b50dfb8d602ed67cde0b82249190", + "reference": "b9f8de081adecf71a003a569e9ba76c0a4c00bf2", "shasum": "" }, "require": { @@ -849,6 +857,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-servicemanager": "self.version" }, "suggest": { @@ -863,19 +874,19 @@ }, "autoload": { "psr-4": { - "Zend\\Di\\": "" + "Zend\\Di\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-di", "keywords": [ "di", "zf2" ], - "time": "2015-04-01 18:01:30" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-escaper", @@ -883,17 +894,22 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-escaper.git", - "reference": "65b3328627362b0be1d5e9067bc846511d1fbc96" + "reference": "15e5769e4fcdb4bf07ebd76500810e7070e23a97" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-escaper/zipball/15e5769e4fcdb4bf07ebd76500810e7070e23a97", - "reference": "65b3328627362b0be1d5e9067bc846511d1fbc96", + "reference": "15e5769e4fcdb4bf07ebd76500810e7070e23a97", "shasum": "" }, "require": { "php": ">=5.3.23" }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master" + }, "type": "library", "extra": { "branch-alias": { @@ -903,19 +919,19 @@ }, "autoload": { "psr-4": { - "Zend\\Escaper\\": "" + "Zend\\Escaper\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-escaper", "keywords": [ "escaper", "zf2" ], - "time": "2015-04-01 18:02:07" + "time": "2015-03-23 18:29:14" }, { "name": "zendframework/zend-eventmanager", @@ -923,18 +939,23 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-eventmanager.git", - "reference": "38df5b567d4ff4d22144745c503ba0502d0d5695" + "reference": "58d21c95c7005a527262fd536499195f104e83f9" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/58d21c95c7005a527262fd536499195f104e83f9", - "reference": "38df5b567d4ff4d22144745c503ba0502d0d5695", + "reference": "58d21c95c7005a527262fd536499195f104e83f9", "shasum": "" }, "require": { "php": ">=5.3.23", "zendframework/zend-stdlib": "self.version" }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master" + }, "type": "library", "extra": { "branch-alias": { @@ -944,19 +965,19 @@ }, "autoload": { "psr-4": { - "Zend\\EventManager\\": "" + "Zend\\EventManager\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-event-manager", "keywords": [ "eventmanager", "zf2" ], - "time": "2015-04-01 18:05:26" + "time": "2015-03-23 18:29:14" }, { "name": "zendframework/zend-filter", @@ -964,12 +985,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-filter.git", - "reference": "b13741a88553351fc52472de529b57b580b8f6f1" + "reference": "6d8aed2da81b62a04747346c4370562cdbe34595" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-filter/zipball/6d8aed2da81b62a04747346c4370562cdbe34595", - "reference": "b13741a88553351fc52472de529b57b580b8f6f1", + "reference": "6d8aed2da81b62a04747346c4370562cdbe34595", "shasum": "" }, "require": { @@ -977,6 +998,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-crypt": "self.version", "zendframework/zend-servicemanager": "self.version", "zendframework/zend-uri": "self.version" @@ -996,20 +1020,20 @@ }, "autoload": { "psr-4": { - "Zend\\Filter\\": "" + "Zend\\Filter\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides a set of commonly needed data filters", - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-filter", "keywords": [ "filter", "zf2" ], - "time": "2015-04-01 18:09:25" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-form", @@ -1017,12 +1041,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-form.git", - "reference": "09f5bd46ffbf783df22281898e2175b291bd43a3" + "reference": "bca0db55718355d25c2c10fdd41a83561f1c94b3" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-form/zipball/bca0db55718355d25c2c10fdd41a83561f1c94b3", - "reference": "09f5bd46ffbf783df22281898e2175b291bd43a3", + "reference": "bca0db55718355d25c2c10fdd41a83561f1c94b3", "shasum": "" }, "require": { @@ -1031,6 +1055,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-captcha": "self.version", "zendframework/zend-code": "self.version", "zendframework/zend-eventmanager": "self.version", @@ -1061,19 +1088,19 @@ }, "autoload": { "psr-4": { - "Zend\\Form\\": "" + "Zend\\Form\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-form", "keywords": [ "form", "zf2" ], - "time": "2015-04-01 18:09:25" + "time": "2015-03-28 20:29:18" }, { "name": "zendframework/zend-http", @@ -1081,12 +1108,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-http.git", - "reference": "ee6220609845b32d1b2873c9ac694aef56d508f5" + "reference": "9c6047a0bdb3094d3ea07a215ff929cc47de4deb" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-http/zipball/9c6047a0bdb3094d3ea07a215ff929cc47de4deb", - "reference": "ee6220609845b32d1b2873c9ac694aef56d508f5", + "reference": "9c6047a0bdb3094d3ea07a215ff929cc47de4deb", "shasum": "" }, "require": { @@ -1096,6 +1123,11 @@ "zendframework/zend-uri": "self.version", "zendframework/zend-validator": "self.version" }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master" + }, "type": "library", "extra": { "branch-alias": { @@ -1105,20 +1137,20 @@ }, "autoload": { "psr-4": { - "Zend\\Http\\": "" + "Zend\\Http\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests", - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-http", "keywords": [ "http", "zf2" ], - "time": "2015-04-01 18:09:25" + "time": "2015-03-27 15:46:30" }, { "name": "zendframework/zend-i18n", @@ -1126,12 +1158,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-i18n.git", - "reference": "33051775d9a8c341fe3b77d1f3daa0e921e2f4bd" + "reference": "9aebc5287373a802540d75fe5508417f866c2e52" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-i18n/zipball/9aebc5287373a802540d75fe5508417f866c2e52", - "reference": "33051775d9a8c341fe3b77d1f3daa0e921e2f4bd", + "reference": "9aebc5287373a802540d75fe5508417f866c2e52", "shasum": "" }, "require": { @@ -1139,6 +1171,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-cache": "self.version", "zendframework/zend-config": "self.version", "zendframework/zend-eventmanager": "self.version", @@ -1167,19 +1202,19 @@ }, "autoload": { "psr-4": { - "Zend\\I18n\\": "" + "Zend\\I18n\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-i18n", "keywords": [ "i18n", "zf2" ], - "time": "2015-04-01 18:09:26" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-inputfilter", @@ -1187,12 +1222,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-inputfilter.git", - "reference": "16856fec61f285e41e5492235220a4dec06ab90f" + "reference": "4b1398f3635fae3cc5e873c5bb067274f3d10a93" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-inputfilter/zipball/4b1398f3635fae3cc5e873c5bb067274f3d10a93", - "reference": "16856fec61f285e41e5492235220a4dec06ab90f", + "reference": "4b1398f3635fae3cc5e873c5bb067274f3d10a93", "shasum": "" }, "require": { @@ -1202,6 +1237,9 @@ "zendframework/zend-validator": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-servicemanager": "self.version" }, "suggest": { @@ -1216,19 +1254,19 @@ }, "autoload": { "psr-4": { - "Zend\\InputFilter\\": "" + "Zend\\InputFilter\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-input-filter", "keywords": [ "inputfilter", "zf2" ], - "time": "2015-04-01 18:09:26" + "time": "2015-03-23 18:29:14" }, { "name": "zendframework/zend-json", @@ -1236,12 +1274,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-json.git", - "reference": "76aeb27e4baf39799e5ca3cf6f2fdd6748ee930c" + "reference": "2d845e151c1b9a237cf1899ac31e17fb10bd1e3f" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-json/zipball/2d845e151c1b9a237cf1899ac31e17fb10bd1e3f", - "reference": "76aeb27e4baf39799e5ca3cf6f2fdd6748ee930c", + "reference": "2d845e151c1b9a237cf1899ac31e17fb10bd1e3f", "shasum": "" }, "require": { @@ -1249,6 +1287,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-http": "self.version", "zendframework/zend-server": "self.version" }, @@ -1266,20 +1307,20 @@ }, "autoload": { "psr-4": { - "Zend\\Json\\": "" + "Zend\\Json\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP", - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-json", "keywords": [ "json", "zf2" ], - "time": "2015-04-01 18:09:26" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-loader", @@ -1287,17 +1328,22 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-loader.git", - "reference": "6868b8a0c346f17fb97724c3a63aa2cbf6b94865" + "reference": "65de2c7a56f8eee633c6bf1cfab73e45648880d4" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-loader/zipball/65de2c7a56f8eee633c6bf1cfab73e45648880d4", - "reference": "6868b8a0c346f17fb97724c3a63aa2cbf6b94865", + "reference": "65de2c7a56f8eee633c6bf1cfab73e45648880d4", "shasum": "" }, "require": { "php": ">=5.3.23" }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master" + }, "type": "library", "extra": { "branch-alias": { @@ -1307,19 +1353,19 @@ }, "autoload": { "psr-4": { - "Zend\\Loader\\": "" + "Zend\\Loader\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-loader", "keywords": [ "loader", "zf2" ], - "time": "2015-04-01 18:09:26" + "time": "2015-03-23 18:29:14" }, { "name": "zendframework/zend-log", @@ -1327,12 +1373,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-log.git", - "reference": "2d5d20fd45470506bdaff727c46dc25fe953146e" + "reference": "002e3c810cad7e31e51c9895e9e3cb6fbd312cdd" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-log/zipball/002e3c810cad7e31e51c9895e9e3cb6fbd312cdd", - "reference": "2d5d20fd45470506bdaff727c46dc25fe953146e", + "reference": "002e3c810cad7e31e51c9895e9e3cb6fbd312cdd", "shasum": "" }, "require": { @@ -1341,6 +1387,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-console": "self.version", "zendframework/zend-db": "self.version", "zendframework/zend-escaper": "self.version", @@ -1364,21 +1413,21 @@ }, "autoload": { "psr-4": { - "Zend\\Log\\": "" + "Zend\\Log\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "component for general purpose logging", - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-log", "keywords": [ "log", "logging", "zf2" ], - "time": "2015-04-01 18:09:26" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-math", @@ -1386,17 +1435,22 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-math.git", - "reference": "634123f83ca90b6613f132d0d100e6b5e9890a29" + "reference": "f41fe4acfd809c14f2a802d1aa45dec8fcd2cc73" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-math/zipball/f41fe4acfd809c14f2a802d1aa45dec8fcd2cc73", - "reference": "634123f83ca90b6613f132d0d100e6b5e9890a29", + "reference": "f41fe4acfd809c14f2a802d1aa45dec8fcd2cc73", "shasum": "" }, "require": { "php": ">=5.3.23" }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master" + }, "suggest": { "ext-bcmath": "If using the bcmath functionality", "ext-gmp": "If using the gmp functionality", @@ -1412,19 +1466,19 @@ }, "autoload": { "psr-4": { - "Zend\\Math\\": "" + "Zend\\Math\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-math", "keywords": [ "math", "zf2" ], - "time": "2015-04-01 18:09:27" + "time": "2015-03-23 18:29:14" }, { "name": "zendframework/zend-modulemanager", @@ -1432,12 +1486,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-modulemanager.git", - "reference": "cbe16b0eafe734a062ed0182381e64b9c953dccf" + "reference": "af7ae3cd29a1efb73cc66ae1081e606039d5c20f" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-modulemanager/zipball/af7ae3cd29a1efb73cc66ae1081e606039d5c20f", - "reference": "cbe16b0eafe734a062ed0182381e64b9c953dccf", + "reference": "af7ae3cd29a1efb73cc66ae1081e606039d5c20f", "shasum": "" }, "require": { @@ -1446,6 +1500,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-config": "self.version", "zendframework/zend-console": "self.version", "zendframework/zend-loader": "self.version", @@ -1467,19 +1524,19 @@ }, "autoload": { "psr-4": { - "Zend\\ModuleManager\\": "" + "Zend\\ModuleManager\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-module-manager", "keywords": [ "modulemanager", "zf2" ], - "time": "2015-04-01 18:09:27" + "time": "2015-03-23 18:29:14" }, { "name": "zendframework/zend-mvc", @@ -1487,12 +1544,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-mvc.git", - "reference": "bfff0f5f9e4d925ee13b8c159c9d6ae7e0db5412" + "reference": "0b4a4a829b30be510a3f215c4ff00c703ee8b431" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-mvc/zipball/0b4a4a829b30be510a3f215c4ff00c703ee8b431", - "reference": "bfff0f5f9e4d925ee13b8c159c9d6ae7e0db5412", + "reference": "0b4a4a829b30be510a3f215c4ff00c703ee8b431", "shasum": "" }, "require": { @@ -1503,6 +1560,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-authentication": "self.version", "zendframework/zend-console": "self.version", "zendframework/zend-di": "self.version", @@ -1551,19 +1611,19 @@ }, "autoload": { "psr-4": { - "Zend\\Mvc\\": "" + "Zend\\Mvc\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-mvc", "keywords": [ "mvc", "zf2" ], - "time": "2015-04-01 18:09:27" + "time": "2015-03-26 18:55:14" }, { "name": "zendframework/zend-serializer", @@ -1571,12 +1631,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-serializer.git", - "reference": "a46960854d6326f0036d98c9abc7a79e36e25928" + "reference": "3c531789a9882a5deb721356a7bd2642b65d4b09" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/3c531789a9882a5deb721356a7bd2642b65d4b09", - "reference": "a46960854d6326f0036d98c9abc7a79e36e25928", + "reference": "3c531789a9882a5deb721356a7bd2642b65d4b09", "shasum": "" }, "require": { @@ -1586,6 +1646,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-servicemanager": "self.version" }, "suggest": { @@ -1600,20 +1663,20 @@ }, "autoload": { "psr-4": { - "Zend\\Serializer\\": "" + "Zend\\Serializer\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides an adapter based interface to simply generate storable representation of PHP types by different facilities, and recover", - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-serializer", "keywords": [ "serializer", "zf2" ], - "time": "2015-04-01 18:09:28" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-server", @@ -1621,12 +1684,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-server.git", - "reference": "fc73c34490908ba143af3c57c7e166b40c4b9f8e" + "reference": "d11ff0bd529d202022823d4accf5983cbd50fc49" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-server/zipball/d11ff0bd529d202022823d4accf5983cbd50fc49", - "reference": "fc73c34490908ba143af3c57c7e166b40c4b9f8e", + "reference": "d11ff0bd529d202022823d4accf5983cbd50fc49", "shasum": "" }, "require": { @@ -1634,6 +1697,11 @@ "zendframework/zend-code": "self.version", "zendframework/zend-stdlib": "self.version" }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master" + }, "type": "library", "extra": { "branch-alias": { @@ -1643,19 +1711,19 @@ }, "autoload": { "psr-4": { - "Zend\\Server\\": "" + "Zend\\Server\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-server", "keywords": [ "server", "zf2" ], - "time": "2015-04-01 18:09:28" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-servicemanager", @@ -1663,18 +1731,21 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-servicemanager.git", - "reference": "d3c27c708a148a30608f313a5b7a61a531bd9cb9" + "reference": "57cf99fa5ac08c05a135a8d0d676c52a5e450083" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/57cf99fa5ac08c05a135a8d0d676c52a5e450083", - "reference": "d3c27c708a148a30608f313a5b7a61a531bd9cb9", + "reference": "57cf99fa5ac08c05a135a8d0d676c52a5e450083", "shasum": "" }, "require": { "php": ">=5.3.23" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-di": "self.version" }, "suggest": { @@ -1690,19 +1761,19 @@ }, "autoload": { "psr-4": { - "Zend\\ServiceManager\\": "" + "Zend\\ServiceManager\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-service-manager", "keywords": [ "servicemanager", "zf2" ], - "time": "2015-04-01 18:09:28" + "time": "2015-03-23 18:29:14" }, { "name": "zendframework/zend-soap", @@ -1710,12 +1781,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-soap.git", - "reference": "e42b900798ea95a9063fa4922da976d8b3a8ab6f" + "reference": "a599463aba97ce247faf3fb443e3c7858b46449b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-soap/zipball/a599463aba97ce247faf3fb443e3c7858b46449b", - "reference": "e42b900798ea95a9063fa4922da976d8b3a8ab6f", + "reference": "a599463aba97ce247faf3fb443e3c7858b46449b", "shasum": "" }, "require": { @@ -1725,6 +1796,9 @@ "zendframework/zend-uri": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-http": "self.version" }, "suggest": { @@ -1739,19 +1813,19 @@ }, "autoload": { "psr-4": { - "Zend\\Soap\\": "" + "Zend\\Soap\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-soap", "keywords": [ "soap", "zf2" ], - "time": "2015-04-01 18:09:29" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-stdlib", @@ -1759,18 +1833,21 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-stdlib.git", - "reference": "eab586f4c18af3fa63c977611939f1f4a3cf1030" + "reference": "cf05c5ba75606e47ffee91cedc72778da46f74c3" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/cf05c5ba75606e47ffee91cedc72778da46f74c3", - "reference": "eab586f4c18af3fa63c977611939f1f4a3cf1030", + "reference": "cf05c5ba75606e47ffee91cedc72778da46f74c3", "shasum": "" }, "require": { "php": ">=5.3.23" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-eventmanager": "self.version", "zendframework/zend-filter": "self.version", "zendframework/zend-serializer": "self.version", @@ -1791,19 +1868,19 @@ }, "autoload": { "psr-4": { - "Zend\\Stdlib\\": "" + "Zend\\Stdlib\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-stdlib", "keywords": [ "stdlib", "zf2" ], - "time": "2015-04-01 18:09:29" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-text", @@ -1811,12 +1888,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-text.git", - "reference": "35f519e20e575a331c2ee554e5a555a59ce4b9e2" + "reference": "d962ea25647b20527f3ca34ae225bbc885dabfc7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-text/zipball/d962ea25647b20527f3ca34ae225bbc885dabfc7", - "reference": "35f519e20e575a331c2ee554e5a555a59ce4b9e2", + "reference": "d962ea25647b20527f3ca34ae225bbc885dabfc7", "shasum": "" }, "require": { @@ -1824,6 +1901,11 @@ "zendframework/zend-servicemanager": "self.version", "zendframework/zend-stdlib": "self.version" }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master" + }, "type": "library", "extra": { "branch-alias": { @@ -1833,19 +1915,19 @@ }, "autoload": { "psr-4": { - "Zend\\Text\\": "" + "Zend\\Text\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-text", "keywords": [ "text", "zf2" ], - "time": "2015-04-01 18:09:29" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-uri", @@ -1853,12 +1935,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-uri.git", - "reference": "53f5b162b293f80de8b951eece8e08be83c4fe16" + "reference": "bd9e625639415376f6a82551c73328448d7bc7d1" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-uri/zipball/bd9e625639415376f6a82551c73328448d7bc7d1", - "reference": "53f5b162b293f80de8b951eece8e08be83c4fe16", + "reference": "bd9e625639415376f6a82551c73328448d7bc7d1", "shasum": "" }, "require": { @@ -1866,6 +1948,11 @@ "zendframework/zend-escaper": "self.version", "zendframework/zend-validator": "self.version" }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master" + }, "type": "library", "extra": { "branch-alias": { @@ -1875,20 +1962,20 @@ }, "autoload": { "psr-4": { - "Zend\\Uri\\": "" + "Zend\\Uri\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "a component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)", - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-uri", "keywords": [ "uri", "zf2" ], - "time": "2015-04-01 18:09:29" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-validator", @@ -1896,12 +1983,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-validator.git", - "reference": "eb678d20256f120a72ca27276bbb2875841701ab" + "reference": "45fac2545a0f2eb66d71cb7966feee481e7c475f" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-validator/zipball/45fac2545a0f2eb66d71cb7966feee481e7c475f", - "reference": "eb678d20256f120a72ca27276bbb2875841701ab", + "reference": "45fac2545a0f2eb66d71cb7966feee481e7c475f", "shasum": "" }, "require": { @@ -1909,6 +1996,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-db": "self.version", "zendframework/zend-filter": "self.version", "zendframework/zend-i18n": "self.version", @@ -1936,20 +2026,20 @@ }, "autoload": { "psr-4": { - "Zend\\Validator\\": "" + "Zend\\Validator\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides a set of commonly needed validators", - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-validator", "keywords": [ "validator", "zf2" ], - "time": "2015-04-01 18:09:30" + "time": "2015-03-25 20:55:48" }, { "name": "zendframework/zend-view", @@ -1957,12 +2047,12 @@ "source": { "type": "git", "url": "https://github.com/zendframework/zend-view.git", - "reference": "e119b4b5f082af58a96eb206e782b62c193227bf" + "reference": "37beb1ad46e530f627b4b6c3716efd728e976ba9" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-view/zipball/37beb1ad46e530f627b4b6c3716efd728e976ba9", - "reference": "e119b4b5f082af58a96eb206e782b62c193227bf", + "reference": "37beb1ad46e530f627b4b6c3716efd728e976ba9", "shasum": "" }, "require": { @@ -1972,6 +2062,9 @@ "zendframework/zend-stdlib": "self.version" }, "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "dev-master", "zendframework/zend-authentication": "self.version", "zendframework/zend-escaper": "self.version", "zendframework/zend-feed": "self.version", @@ -2010,20 +2103,20 @@ }, "autoload": { "psr-4": { - "Zend\\View\\": "" + "Zend\\View\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "provides a system of helpers, output filters, and variable escaping", - "homepage": "https://github.com/zendframework/zf2", + "homepage": "https://github.com/zendframework/zend-view", "keywords": [ "view", "zf2" ], - "time": "2015-04-01 18:09:30" + "time": "2015-03-25 20:55:48" } ], "packages-dev": [ @@ -2062,7 +2155,7 @@ "Doctrine\\Instantiator\\": "src" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -2083,16 +2176,16 @@ }, { "name": "fabpot/php-cs-fixer", - "version": "v1.8", + "version": "v1.8.1", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "93c723fe0c50ed54292006e7249a4c1173cf5847" + "reference": "c1e28e95a978e967dade5469a4bf88162faa67bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/93c723fe0c50ed54292006e7249a4c1173cf5847", - "reference": "93c723fe0c50ed54292006e7249a4c1173cf5847", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/c1e28e95a978e967dade5469a4bf88162faa67bf", + "reference": "c1e28e95a978e967dade5469a4bf88162faa67bf", "shasum": "" }, "require": { @@ -2118,7 +2211,7 @@ "Symfony\\CS\\": "Symfony/CS/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -2133,7 +2226,7 @@ } ], "description": "A tool to automatically fix PHP code style", - "time": "2015-05-04 17:06:20" + "time": "2015-05-29 06:10:12" }, { "name": "league/climate", @@ -2162,7 +2255,7 @@ "League\\CLImate\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -2223,7 +2316,7 @@ "OAuth\\Unit": "tests" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -2278,7 +2371,7 @@ "PDepend\\": "src/main/php/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2287,20 +2380,20 @@ }, { "name": "phpmd/phpmd", - "version": "2.2.2", + "version": "2.2.3", "source": { "type": "git", "url": "https://github.com/phpmd/phpmd.git", - "reference": "7dc4a6b5c07b119ab5da7960b56303fa6855eb84" + "reference": "5eeb5a4d39c8304910b33ae49f8813905346cc35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpmd/phpmd/zipball/7dc4a6b5c07b119ab5da7960b56303fa6855eb84", - "reference": "7dc4a6b5c07b119ab5da7960b56303fa6855eb84", + "url": "https://api.github.com/repos/phpmd/phpmd/zipball/5eeb5a4d39c8304910b33ae49f8813905346cc35", + "reference": "5eeb5a4d39c8304910b33ae49f8813905346cc35", "shasum": "" }, "require": { - "pdepend/pdepend": "2.0.*", + "pdepend/pdepend": "~2.0", "php": ">=5.3.0", "symfony/config": ">=2.4", "symfony/dependency-injection": ">=2.4", @@ -2319,7 +2412,7 @@ "PHPMD\\": "src/main/php" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2345,20 +2438,20 @@ "phpmd", "pmd" ], - "time": "2015-03-26 07:47:05" + "time": "2015-05-27 18:16:57" }, { "name": "phpunit/php-code-coverage", - "version": "2.0.16", + "version": "2.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c" + "reference": "be2286cb8c7e1773eded49d9719219e6f74f9e3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/934fd03eb6840508231a7f73eb8940cf32c3b66c", - "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/be2286cb8c7e1773eded49d9719219e6f74f9e3e", + "reference": "be2286cb8c7e1773eded49d9719219e6f74f9e3e", "shasum": "" }, "require": { @@ -2381,7 +2474,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { @@ -2389,7 +2482,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2407,7 +2500,7 @@ "testing", "xunit" ], - "time": "2015-04-11 04:35:00" + "time": "2015-06-09 13:05:42" }, { "name": "phpunit/php-file-iterator", @@ -2432,7 +2525,7 @@ "File/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "include-path": [ "" ], @@ -2477,7 +2570,7 @@ "Text/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "include-path": [ "" ], @@ -2521,7 +2614,7 @@ "PHP/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "include-path": [ "" ], @@ -2544,16 +2637,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "1.4.1", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "eab81d02569310739373308137284e0158424330" + "reference": "db63be1159c81df649cd0260e30249a586d4129e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330", - "reference": "eab81d02569310739373308137284e0158424330", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/db63be1159c81df649cd0260e30249a586d4129e", + "reference": "db63be1159c81df649cd0260e30249a586d4129e", "shasum": "" }, "require": { @@ -2574,7 +2667,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2589,7 +2682,7 @@ "keywords": [ "tokenizer" ], - "time": "2015-04-08 04:46:07" + "time": "2015-06-12 07:34:24" }, { "name": "phpunit/phpunit", @@ -2641,7 +2734,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "include-path": [ "", "../../symfony/yaml/" @@ -2667,16 +2760,16 @@ }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.1", + "version": "2.3.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c" + "reference": "92408bb1968a81b3217a6fdf6c1a198da83caa35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/92408bb1968a81b3217a6fdf6c1a198da83caa35", + "reference": "92408bb1968a81b3217a6fdf6c1a198da83caa35", "shasum": "" }, "require": { @@ -2701,7 +2794,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2718,7 +2811,7 @@ "mock", "xunit" ], - "time": "2015-04-02 05:36:41" + "time": "2015-06-11 15:55:48" }, { "name": "sebastian/comparator", @@ -2753,7 +2846,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2815,7 +2908,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2867,7 +2960,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2918,7 +3011,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2983,7 +3076,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3025,7 +3118,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3079,7 +3172,7 @@ "StaticReview\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -3150,7 +3243,7 @@ "CodeSniffer/Standards/Zend/Sniffs/" ] }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3170,21 +3263,20 @@ }, { "name": "symfony/config", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Config", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Config.git", - "reference": "b6fddb4aa2daaa2b06f0040071ac131b4a1ecf25" + "reference": "58ded81f1f582a87c528ef3dae9a859f78b5f374" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Config/zipball/b6fddb4aa2daaa2b06f0040071ac131b4a1ecf25", - "reference": "b6fddb4aa2daaa2b06f0040071ac131b4a1ecf25", + "url": "https://api.github.com/repos/symfony/Config/zipball/58ded81f1f582a87c528ef3dae9a859f78b5f374", + "reference": "58ded81f1f582a87c528ef3dae9a859f78b5f374", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.9", "symfony/filesystem": "~2.3" }, "require-dev": { @@ -3193,15 +3285,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Config\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -3217,25 +3309,24 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-06-11 14:06:56" }, { "name": "symfony/dependency-injection", - "version": "v2.6.7", - "target-dir": "Symfony/Component/DependencyInjection", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/DependencyInjection.git", - "reference": "b575c160af001d3525ee733085bcc4ec7c8e1b51" + "reference": "1a409e52a38ec891de0a7a61a191d1c62080b69d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/b575c160af001d3525ee733085bcc4ec7c8e1b51", - "reference": "b575c160af001d3525ee733085bcc4ec7c8e1b51", + "url": "https://api.github.com/repos/symfony/DependencyInjection/zipball/1a409e52a38ec891de0a7a61a191d1c62080b69d", + "reference": "1a409e52a38ec891de0a7a61a191d1c62080b69d", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "conflict": { "symfony/expression-language": "<2.6" @@ -3254,15 +3345,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\DependencyInjection\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -3278,25 +3369,24 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-06-11 19:13:11" }, { "name": "symfony/event-dispatcher", - "version": "v2.6.7", - "target-dir": "Symfony/Component/EventDispatcher", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02" + "reference": "be3c5ff8d503c46768aeb78ce6333051aa6f26d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/672593bc4b0043a0acf91903bb75a1c82d8f2e02", - "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02", + "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/be3c5ff8d503c46768aeb78ce6333051aa6f26d9", + "reference": "be3c5ff8d503c46768aeb78ce6333051aa6f26d9", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "psr/log": "~1.0", @@ -3313,15 +3403,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -3337,25 +3427,24 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-06-08 09:37:21" }, { "name": "symfony/filesystem", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Filesystem", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Filesystem.git", - "reference": "f73904bd2dae525c42ea1f0340c7c98480ecacde" + "reference": "a0d43eb3e17d4f4c6990289805a488a0482a07f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/f73904bd2dae525c42ea1f0340c7c98480ecacde", - "reference": "f73904bd2dae525c42ea1f0340c7c98480ecacde", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/a0d43eb3e17d4f4c6990289805a488a0482a07f3", + "reference": "a0d43eb3e17d4f4c6990289805a488a0482a07f3", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -3363,15 +3452,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Filesystem\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -3387,25 +3476,24 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2015-05-08 00:09:07" + "time": "2015-06-08 09:37:21" }, { "name": "symfony/stopwatch", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Stopwatch", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Stopwatch.git", - "reference": "b470f87c69837cb71115f1fa720388bb19b63635" + "reference": "c653f1985f6c2b7dbffd04d48b9c0a96aaef814b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/b470f87c69837cb71115f1fa720388bb19b63635", - "reference": "b470f87c69837cb71115f1fa720388bb19b63635", + "url": "https://api.github.com/repos/symfony/Stopwatch/zipball/c653f1985f6c2b7dbffd04d48b9c0a96aaef814b", + "reference": "c653f1985f6c2b7dbffd04d48b9c0a96aaef814b", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -3413,15 +3501,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Stopwatch\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -3437,25 +3525,24 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-06-04 20:11:48" }, { "name": "symfony/yaml", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Yaml", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2" + "reference": "9808e75c609a14f6db02f70fccf4ca4aab53c160" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/9808e75c609a14f6db02f70fccf4ca4aab53c160", + "reference": "9808e75c609a14f6db02f70fccf4ca4aab53c160", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "symfony/phpunit-bridge": "~2.7" @@ -3463,15 +3550,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Yaml\\": "" } }, - "notification-url": "https://packagist.org/downloads/", + "notification-url": "http://packagist.org/downloads/", "license": [ "MIT" ], @@ -3487,7 +3574,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2015-06-10 15:30:22" } ], "aliases": [], @@ -3512,6 +3599,7 @@ "ext-hash": "*", "ext-curl": "*", "ext-iconv": "*", - "ext-intl": "*" + "ext-intl": "*", + "ext-xsl": "*" } } diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModule1/etc/di.xml index 61cdfb19a09e0b1b59a27663d261969600e6340e..2a25820907ce76892f606fbbbca53fcf7c19292a 100644 --- a/dev/tests/api-functional/_files/Magento/TestModule1/etc/di.xml +++ b/dev/tests/api-functional/_files/Magento/TestModule1/etc/di.xml @@ -9,7 +9,7 @@ <preference for="Magento\TestModule1\Service\V1\AllSoapAndRestInterface" type="Magento\TestModule1\Service\V1\AllSoapAndRest" /> <preference for="Magento\TestModule1\Service\V2\AllSoapAndRestInterface" type="Magento\TestModule1\Service\V2\AllSoapAndRest" /> - <virtualType name="Magento\TestModule1\Service\Config\TestModule1MetadataConfig" type="Magento\Framework\Api\Config\MetadataConfig"> + <virtualType name="Magento\TestModule1\Service\Config\TestModule1MetadataConfig" type="Magento\Framework\Api\ExtensionAttribute\Config\MetadataConfig"> <arguments> <argument name="attributeMetadataBuilder" xsi:type="object">Magento\TestModuleMSC\Model\Data\Eav\AttributeMetadataBuilder</argument> <argument name="dataObjectClassName" xsi:type="string">Magento\TestModule1\Service\V1\Entity\Item</argument> diff --git a/dev/tests/api-functional/_files/Magento/TestModule1/etc/service_data_attributes.xml b/dev/tests/api-functional/_files/Magento/TestModule1/etc/extension_attributes.xml similarity index 94% rename from dev/tests/api-functional/_files/Magento/TestModule1/etc/service_data_attributes.xml rename to dev/tests/api-functional/_files/Magento/TestModule1/etc/extension_attributes.xml index fa96514a063b6112004e7a6073a2cc131a87f44c..befcd3199564e3753dbf4394d2e4824b87812a32 100644 --- a/dev/tests/api-functional/_files/Magento/TestModule1/etc/service_data_attributes.xml +++ b/dev/tests/api-functional/_files/Magento/TestModule1/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\TestModule1\Service\V1\Entity\Item"> <attribute code="custom_attribute_data_object" type="Magento\TestModuleMSC\Model\Data\CustomAttributeDataObject" /> <attribute code="custom_attribute_string" type="string" /> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/di.xml b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/di.xml index a9c4adca72a7d373bbb5a768be48672d99c85f76..0dc0390e215b99647a2a3efb4c8129c00f0ba9a4 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/di.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/di.xml @@ -13,7 +13,7 @@ <preference for="Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectInterface" type="Magento\TestModuleMSC\Model\Data\CustomAttributeDataObject" /> <preference for="Magento\TestModuleMSC\Api\Data\CustomAttributeNestedDataObjectInterface" type="Magento\TestModuleMSC\Model\Data\CustomAttributeNestedDataObject" /> - <virtualType name="Magento\TestModuleMSC\Service\Config\TestModuleMSCMetadataConfig" type="Magento\Framework\Api\Config\MetadataConfig"> + <virtualType name="Magento\TestModuleMSC\Service\Config\TestModuleMSCMetadataConfig" type="Magento\Framework\Api\ExtensionAttribute\Config\MetadataConfig"> <arguments> <argument name="attributeMetadataBuilder" xsi:type="object">Magento\TestModuleMSC\Model\Data\Eav\AttributeMetadataBuilder</argument> <argument name="dataObjectClassName" xsi:type="string">Magento\TestModuleMSC\Model\Data\Item</argument> diff --git a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/service_data_attributes.xml b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/extension_attributes.xml similarity index 94% rename from dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/service_data_attributes.xml rename to dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/extension_attributes.xml index f11e639ccd2753296d65071cf32f3e5fb47e0e7d..7682e3bed03be597c899c14b919d65ce572e29ce 100644 --- a/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/service_data_attributes.xml +++ b/dev/tests/api-functional/_files/Magento/TestModuleMSC/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\TestModuleMSC\Api\Data\ItemInterface"> <attribute code="custom_attribute_data_object" type="Magento\TestModuleMSC\Api\Data\CustomAttributeDataObjectInterface" /> <attribute code="custom_attribute_string" type="string" /> diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/OauthHelper.php b/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/OauthHelper.php index d59fc83193eb2de24b3d056d62dfb9fea3b9fb05..5df4d8e02d792ff09dab05802e7a471cfc135da5 100644 --- a/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/OauthHelper.php +++ b/dev/tests/api-functional/framework/Magento/TestFramework/Authentication/OauthHelper.php @@ -189,7 +189,7 @@ class OauthHelper $integration->setStatus(\Magento\Integration\Model\Integration::STATUS_ACTIVE)->save(); /** Magento cache must be cleared to activate just created ACL role. */ - $varPath = realpath('../../../var'); + $varPath = realpath(BP . '/var'); if (!$varPath) { throw new LogicException("Magento cache cannot be cleared after new ACL role creation."); } else { diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetManagementTest.php index a1a2c4de266fa35c1fe9e037c5e2e7c70014d28c..12fceed6d9d7b672ab6ef1609b16f82eee79368b 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetManagementTest.php @@ -156,7 +156,7 @@ class AttributeSetManagementTest extends WebapiAbstract $entityTypeCode = 'catalog_product'; $entityType = $this->getEntityTypeByCode($entityTypeCode); $attributeSetName = 'Default'; - $expectedMessage = 'An attribute set with the "Default" name already exists.'; + $expectedMessage = 'An attribute set named "Default" already exists.'; $arguments = [ 'attributeSet' => [ diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkManagementInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkManagementInterfaceTest.php index 5592363a2a8e2d9ed3e1e82b91c6e902c8aab5a2..3aa38f8cdb53f505a5f2b7b530b176c47fac6a69 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkManagementInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkManagementInterfaceTest.php @@ -95,13 +95,13 @@ class ProductLinkManagementInterfaceTest extends WebapiAbstract 'linked_product_type' => 'virtual', 'linked_product_sku' => 'virtual-product', 'position' => 100, - 'product_sku' => 'simple', + 'sku' => 'simple', 'link_type' => 'related', ]; $serviceInfo = [ 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . $productSku . '/links/' . $linkType, + 'resourcePath' => self::RESOURCE_PATH . $productSku . '/links', 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, ], 'soap' => [ diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkRepositoryInterfaceTest.php index 30d9d54a86d48363882113e4ee024ec5e6dff2d9..dce4213d2a937409d546d2e9af44bd9393fd5fa8 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductLinkRepositoryInterfaceTest.php @@ -71,7 +71,7 @@ class ProductLinkRepositoryInterfaceTest extends WebapiAbstract $serviceInfo = [ 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . $productSku . '/links/' . $linkType, + 'resourcePath' => self::RESOURCE_PATH . $productSku . '/links', 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, ], 'soap' => [ @@ -85,7 +85,7 @@ class ProductLinkRepositoryInterfaceTest extends WebapiAbstract $serviceInfo, [ 'entity' => [ - 'product_sku' => 'simple_with_cross', + 'sku' => 'simple_with_cross', 'link_type' => 'related', 'linked_product_sku' => 'simple', 'linked_product_type' => 'simple', diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php index 5472f12af1b2b237450577f60a0f166ef1e6f6aa..f3fe09d67ba43860c90979c321ab4f59182d473f 100644 --- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php @@ -140,7 +140,7 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract $this->saveProduct($productData); - $productLinkData = ["product_sku" => "product_simple_with_related_500", "link_type" => "related", + $productLinkData = ["sku" => "product_simple_with_related_500", "link_type" => "related", "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", "position" => 0, "extension_attributes" => []]; $productWithRelatedData = [ @@ -164,7 +164,7 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract $this->assertEquals($productLinkData, $links[0]); // update link information - $productLinkData = ["product_sku" => "product_simple_with_related_500", "link_type" => "upsell", + $productLinkData = ["sku" => "product_simple_with_related_500", "link_type" => "upsell", "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", "position" => 0, "extension_attributes" => []]; $productWithUpsellData = [ diff --git a/dev/tests/api-functional/testsuite/Magento/Cms/Api/BlockRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Cms/Api/BlockRepositoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7d6aa8b83d90156e37dbd442bbfdc141fa2c02bb --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Cms/Api/BlockRepositoryTest.php @@ -0,0 +1,251 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cms\Api; + +use Magento\Cms\Api\Data\BlockInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\WebapiAbstract; + +/** + * Tests for cms block service. + */ +class BlockRepositoryTest extends WebapiAbstract +{ + const SERVICE_NAME = 'cmsBlockRepositoryV1'; + const SERVICE_VERSION = 'V1'; + const RESOURCE_PATH = '/V1/cmsBlock'; + + /** + * @var \Magento\Cms\Api\Data\BlockInterfaceFactory + */ + protected $blockFactory; + + /** + * @var \Magento\Cms\Api\BlockRepositoryInterface + */ + protected $blockRepository; + + /** + * @var \Magento\Framework\Api\DataObjectHelper + */ + protected $dataObjectHelper; + + /** + * @var \Magento\Framework\Reflection\DataObjectProcessor + */ + protected $dataObjectProcessor; + + /** + * @var \Magento\Cms\Api\Data\BlockInterface|null + */ + protected $currentBlock; + + /** + * Execute per test initialization. + */ + public function setUp() + { + $this->blockFactory = Bootstrap::getObjectManager()->create('Magento\Cms\Api\Data\BlockInterfaceFactory'); + $this->blockRepository = Bootstrap::getObjectManager()->create('Magento\Cms\Api\BlockRepositoryInterface'); + $this->dataObjectHelper = Bootstrap::getObjectManager()->create('Magento\Framework\Api\DataObjectHelper'); + $this->dataObjectProcessor = Bootstrap::getObjectManager() + ->create('Magento\Framework\Reflection\DataObjectProcessor'); + } + + /** + * Clear temporary data + */ + public function tearDown() + { + if ($this->currentBlock) { + $this->blockRepository->delete($this->currentBlock); + $this->currentBlock = null; + } + } + + /** + * Test get \Magento\Cms\Api\Data\BlockInterface + */ + public function testGet() + { + $blockTitle = 'Block title'; + $blockIdentifier = 'block-title'; + /** @var \Magento\Cms\Api\Data\BlockInterface $blockDataObject */ + $blockDataObject = $this->blockFactory->create(); + $blockDataObject->setTitle($blockTitle) + ->setIdentifier($blockIdentifier); + $this->currentBlock = $this->blockRepository->save($blockDataObject); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $this->currentBlock->getId(), + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'GetById', + ], + ]; + + $block = $this->_webApiCall($serviceInfo, [BlockInterface::BLOCK_ID => $this->currentBlock->getId()]); + $this->assertNotNull($block['id']); + + $blockData = $this->blockRepository->getById($block['id']); + $this->assertEquals($blockData->getTitle(), $blockTitle); + $this->assertEquals($blockData->getIdentifier(), $blockIdentifier); + } + + /** + * Test create \Magento\Cms\Api\Data\BlockInterface + */ + public function testCreate() + { + $blockTitle = 'Block title'; + $blockIdentifier = 'block-title'; + /** @var \Magento\Cms\Api\Data\BlockInterface $blockDataObject */ + $blockDataObject = $this->blockFactory->create(); + $blockDataObject->setTitle($blockTitle) + ->setIdentifier($blockIdentifier); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + + $requestData = ['block' => [ + BlockInterface::IDENTIFIER => $blockDataObject->getIdentifier(), + BlockInterface::TITLE => $blockDataObject->getTitle(), + ], + ]; + $block = $this->_webApiCall($serviceInfo, $requestData); + $this->assertNotNull($block['id']); + + $this->currentBlock = $this->blockRepository->getById($block['id']); + $this->assertEquals($this->currentBlock->getTitle(), $blockTitle); + $this->assertEquals($this->currentBlock->getIdentifier(), $blockIdentifier); + } + + /** + * Test update \Magento\Cms\Api\Data\BlockInterface + */ + public function testUpdate() + { + $blockTitle = 'Block title'; + $newBlockTitle = 'New Block title'; + $blockIdentifier = 'block-title'; + /** @var \Magento\Cms\Api\Data\BlockInterface $blockDataObject */ + $blockDataObject = $this->blockFactory->create(); + $blockDataObject->setTitle($blockTitle) + ->setIdentifier($blockIdentifier); + $this->currentBlock = $this->blockRepository->save($blockDataObject); + $this->dataObjectHelper->populateWithArray( + $this->currentBlock, + [BlockInterface::TITLE => $newBlockTitle], + 'Magento\Cms\Api\Data\BlockInterface' + ); + $blockData = $this->dataObjectProcessor->buildOutputDataArray( + $this->currentBlock, + 'Magento\Cms\Api\Data\BlockInterface' + ); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + + $block = $this->_webApiCall($serviceInfo, ['block' => $blockData]); + $this->assertNotNull($block['id']); + + $blockData = $this->blockRepository->getById($block['id']); + $this->assertEquals($blockData->getTitle(), $newBlockTitle); + } + + /** + * Test delete \Magento\Cms\Api\Data\BlockInterface + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + */ + public function testDelete() + { + $blockTitle = 'Block title'; + $blockIdentifier = 'block-title'; + /** @var \Magento\Cms\Api\Data\BlockInterface $blockDataObject */ + $blockDataObject = $this->blockFactory->create(); + $blockDataObject->setTitle($blockTitle) + ->setIdentifier($blockIdentifier); + $this->currentBlock = $this->blockRepository->save($blockDataObject); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $this->currentBlock->getId(), + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'DeleteById', + ], + ]; + + $this->_webApiCall($serviceInfo, [BlockInterface::BLOCK_ID => $this->currentBlock->getId()]); + $this->blockRepository->getById($this->currentBlock['id']); + } + + /** + * Test search \Magento\Cms\Api\Data\BlockInterface + */ + public function testSearch() + { + $blockTitle = 'Block title'; + $blockIdentifier = 'block-title'; + /** @var \Magento\Cms\Api\Data\BlockInterface $blockDataObject */ + $blockDataObject = $this->blockFactory->create(); + $blockDataObject->setTitle($blockTitle) + ->setIdentifier($blockIdentifier); + $this->currentBlock = $this->blockRepository->save($blockDataObject); + + $filterBuilder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder'); + $searchCriteriaBuilder = Bootstrap::getObjectManager() + ->create('Magento\Framework\Api\SearchCriteriaBuilder'); + $filter = $filterBuilder + ->setField(BlockInterface::IDENTIFIER) + ->setValue($blockIdentifier) + ->create(); + $searchCriteriaBuilder->addFilter([$filter]); + + $searchData = $searchCriteriaBuilder->create()->__toArray(); + $requestData = ['searchCriteria' => $searchData]; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . "/search" . '?' . http_build_query($requestData), + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'GetList', + ], + ]; + + $searchResult = $this->_webApiCall($serviceInfo, $requestData); + $this->assertEquals(1, $searchResult['total_count']); + $this->assertEquals($searchResult['items'][0][BlockInterface::IDENTIFIER], $blockIdentifier); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/Cms/Api/PageRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Cms/Api/PageRepositoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4997e463488220fc809e078e98eda7bb3053a90b --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/Cms/Api/PageRepositoryTest.php @@ -0,0 +1,251 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cms\Api; + +use Magento\Cms\Api\Data\PageInterface; +use Magento\TestFramework\Helper\Bootstrap; +use Magento\TestFramework\TestCase\WebapiAbstract; + +/** + * Tests for cms page service. + */ +class PageRepositoryTest extends WebapiAbstract +{ + const SERVICE_NAME = 'cmsPageRepositoryV1'; + const SERVICE_VERSION = 'V1'; + const RESOURCE_PATH = '/V1/cmsPage'; + + /** + * @var \Magento\Cms\Api\Data\PageInterfaceFactory + */ + protected $pageFactory; + + /** + * @var \Magento\Cms\Api\PageRepositoryInterface + */ + protected $pageRepository; + + /** + * @var \Magento\Framework\Api\DataObjectHelper + */ + protected $dataObjectHelper; + + /** + * @var \Magento\Framework\Reflection\DataObjectProcessor + */ + protected $dataObjectProcessor; + + /** + * @var \Magento\Cms\Api\Data\PageInterface|null + */ + protected $currentPage; + + /** + * Execute per test initialization. + */ + public function setUp() + { + $this->pageFactory = Bootstrap::getObjectManager()->create('Magento\Cms\Api\Data\PageInterfaceFactory'); + $this->pageRepository = Bootstrap::getObjectManager()->create('Magento\Cms\Api\PageRepositoryInterface'); + $this->dataObjectHelper = Bootstrap::getObjectManager()->create('Magento\Framework\Api\DataObjectHelper'); + $this->dataObjectProcessor = Bootstrap::getObjectManager() + ->create('Magento\Framework\Reflection\DataObjectProcessor'); + } + + /** + * Clear temporary data + */ + public function tearDown() + { + if ($this->currentPage) { + $this->pageRepository->delete($this->currentPage); + $this->currentPage = null; + } + } + + /** + * Test get \Magento\Cms\Api\Data\PageInterface + */ + public function testGet() + { + $pageTitle = 'Page title'; + $pageIdentifier = 'page-title' . uniqid(); + /** @var \Magento\Cms\Api\Data\PageInterface $pageDataObject */ + $pageDataObject = $this->pageFactory->create(); + $pageDataObject->setTitle($pageTitle) + ->setIdentifier($pageIdentifier); + $this->currentPage = $this->pageRepository->save($pageDataObject); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $this->currentPage->getId(), + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'GetById', + ], + ]; + + $page = $this->_webApiCall($serviceInfo, [PageInterface::PAGE_ID => $this->currentPage->getId()]); + $this->assertNotNull($page['id']); + + $pageData = $this->pageRepository->getById($page['id']); + $this->assertEquals($pageData->getTitle(), $pageTitle); + $this->assertEquals($pageData->getIdentifier(), $pageIdentifier); + } + + /** + * Test create \Magento\Cms\Api\Data\PageInterface + */ + public function testCreate() + { + $pageTitle = 'Page title'; + $pageIdentifier = 'page-title' . uniqid(); + /** @var \Magento\Cms\Api\Data\PageInterface $pageDataObject */ + $pageDataObject = $this->pageFactory->create(); + $pageDataObject->setTitle($pageTitle) + ->setIdentifier($pageIdentifier); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + + $requestData = ['page' => [ + PageInterface::IDENTIFIER => $pageDataObject->getIdentifier(), + PageInterface::TITLE => $pageDataObject->getTitle(), + ], + ]; + $page = $this->_webApiCall($serviceInfo, $requestData); + $this->assertNotNull($page['id']); + + $this->currentPage = $this->pageRepository->getById($page['id']); + $this->assertEquals($this->currentPage->getTitle(), $pageTitle); + $this->assertEquals($this->currentPage->getIdentifier(), $pageIdentifier); + } + + /** + * Test update \Magento\Cms\Api\Data\PageInterface + */ + public function testUpdate() + { + $pageTitle = 'Page title'; + $newPageTitle = 'New Page title'; + $pageIdentifier = 'page-title' . uniqid(); + /** @var \Magento\Cms\Api\Data\PageInterface $pageDataObject */ + $pageDataObject = $this->pageFactory->create(); + $pageDataObject->setTitle($pageTitle) + ->setIdentifier($pageIdentifier); + $this->currentPage = $this->pageRepository->save($pageDataObject); + $this->dataObjectHelper->populateWithArray( + $this->currentPage, + [PageInterface::TITLE => $newPageTitle], + 'Magento\Cms\Api\Data\PageInterface' + ); + $pageData = $this->dataObjectProcessor->buildOutputDataArray( + $this->currentPage, + 'Magento\Cms\Api\Data\PageInterface' + ); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'Save', + ], + ]; + + $page = $this->_webApiCall($serviceInfo, ['page' => $pageData]); + $this->assertNotNull($page['id']); + + $pageData = $this->pageRepository->getById($page['id']); + $this->assertEquals($pageData->getTitle(), $newPageTitle); + } + + /** + * Test delete \Magento\Cms\Api\Data\PageInterface + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + */ + public function testDelete() + { + $pageTitle = 'Page title'; + $pageIdentifier = 'page-title' . uniqid(); + /** @var \Magento\Cms\Api\Data\PageInterface $pageDataObject */ + $pageDataObject = $this->pageFactory->create(); + $pageDataObject->setTitle($pageTitle) + ->setIdentifier($pageIdentifier); + $this->currentPage = $this->pageRepository->save($pageDataObject); + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . '/' . $this->currentPage->getId(), + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'DeleteById', + ], + ]; + + $this->_webApiCall($serviceInfo, [PageInterface::PAGE_ID => $this->currentPage->getId()]); + $this->pageRepository->getById($this->currentPage['id']); + } + + /** + * Test search \Magento\Cms\Api\Data\PageInterface + */ + public function testSearch() + { + $pageTitle = 'Page title'; + $pageIdentifier = 'page-title' . uniqid(); + /** @var \Magento\Cms\Api\Data\PageInterface $pageDataObject */ + $pageDataObject = $this->pageFactory->create(); + $pageDataObject->setTitle($pageTitle) + ->setIdentifier($pageIdentifier); + $this->currentPage = $this->pageRepository->save($pageDataObject); + + $filterBuilder = Bootstrap::getObjectManager()->create('Magento\Framework\Api\FilterBuilder'); + $searchCriteriaBuilder = Bootstrap::getObjectManager() + ->create('Magento\Framework\Api\SearchCriteriaBuilder'); + $filter = $filterBuilder + ->setField(PageInterface::IDENTIFIER) + ->setValue($pageIdentifier) + ->create(); + $searchCriteriaBuilder->addFilter([$filter]); + + $searchData = $searchCriteriaBuilder->create()->__toArray(); + $requestData = ['searchCriteria' => $searchData]; + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => self::RESOURCE_PATH . "/search" . '?' . http_build_query($requestData), + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => self::SERVICE_NAME, + 'serviceVersion' => self::SERVICE_VERSION, + 'operation' => self::SERVICE_NAME . 'GetList', + ], + ]; + + $searchResult = $this->_webApiCall($serviceInfo, $requestData); + $this->assertEquals(1, $searchResult['total_count']); + $this->assertEquals($searchResult['items'][0][PageInterface::IDENTIFIER], $pageIdentifier); + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ProductRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ProductRepositoryTest.php index b9a2c658dfa3bd771656523fa6a3669ec2eaf411..3e2debd2aa20a1db5fe89fd4dec8d0e255077f55 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ProductRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/ProductRepositoryTest.php @@ -160,9 +160,6 @@ class ProductRepositoryTest extends WebapiAbstract */ public function testDeleteConfigurableProductOption() { - $productId1 = 10; - $productId2 = 20; - $response = $this->createConfigurableProduct(); //delete existing option $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options'] = []; @@ -182,9 +179,9 @@ class ProductRepositoryTest extends WebapiAbstract ); $resultConfigurableProductLinks = $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]["configurable_product_links"]; - $this->assertEquals(2, count($resultConfigurableProductLinks)); + $this->assertEquals(0, count($resultConfigurableProductLinks)); - $this->assertEquals([$productId1, $productId2], $resultConfigurableProductLinks); + $this->assertEquals([], $resultConfigurableProductLinks); } /** @@ -211,6 +208,7 @@ class ProductRepositoryTest extends WebapiAbstract 'value_index' => $option['values'][0]['value_index'], ], ], + 'product_id' => $response['id'], ]; $response[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]['configurable_product_options'][0] = $updatedOption; diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php index e1cbe53152c37507113646f77d570094bbe782f3..d77ab4ee6de5d8ffb9351345ebf8686b11cc5c2b 100644 --- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AccountManagementTest.php @@ -535,8 +535,8 @@ class AccountManagementTest extends WebapiAbstract $requestData = ['customer' => $customerData]; $validationResponse = $this->_webApiCall($serviceInfo, $requestData); $this->assertFalse($validationResponse['valid']); - $this->assertEquals('The first name cannot be empty.', $validationResponse['messages'][0]); - $this->assertEquals('The last name cannot be empty.', $validationResponse['messages'][1]); + $this->assertEquals('Please enter a first name.', $validationResponse['messages'][0]); + $this->assertEquals('Please enter a last name.', $validationResponse['messages'][1]); } public function testIsReadonly() diff --git a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressMetadataTest.php b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressMetadataTest.php index 95a2a8e2b795c4f6a8137a898d04315450e41e19..22b3c02f692894363ff87734eb8864791f45d854 100644 --- a/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressMetadataTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Customer/Api/AddressMetadataTest.php @@ -76,7 +76,7 @@ class AddressMetadataTest extends WebapiAbstract AttributeMetadata::NOTE => '', AttributeMetadata::SYSTEM => true, AttributeMetadata::USER_DEFINED => false, - AttributeMetadata::BACKEND_TYPE => 'varchar', + AttributeMetadata::BACKEND_TYPE => 'static', AttributeMetadata::SORT_ORDER => 110 ], ] diff --git a/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetManagementTest.php index 668242a5986fb1cf37fb33c4cd0c10854b93e78e..04038f70f22f333a40839ea320d2f9c046671f2c 100644 --- a/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Eav/Api/AttributeSetManagementTest.php @@ -169,7 +169,7 @@ class AttributeSetManagementTest extends WebapiAbstract $entityTypeCode = 'catalog_product'; $entityType = $this->getEntityTypeByCode($entityTypeCode); $attributeSetName = 'Default'; - $expectedMessage = 'An attribute set with the "Default" name already exists.'; + $expectedMessage = 'An attribute set named "Default" already exists.'; $arguments = [ 'entityTypeCode' => $entityTypeCode, diff --git a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkManagementTest.php b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkManagementTest.php index 10e6d6f41ed029f84d9aab099da6cf27c462a736..88160057b07004339713b92e36d1fc93be910cae 100644 --- a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkManagementTest.php @@ -36,14 +36,14 @@ class ProductLinkManagementTest extends \Magento\TestFramework\TestCase\WebapiAb $expected = [ [ - 'product_sku' => 'grouped-product', + 'sku' => 'grouped-product', 'link_type' => 'associated', 'linked_product_sku' => 'simple-1', 'linked_product_type' => 'simple', 'position' => 1, ], [ - 'product_sku' => 'grouped-product', + 'sku' => 'grouped-product', 'link_type' => 'associated', 'linked_product_sku' => 'virtual-product', 'linked_product_type' => 'virtual', diff --git a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkRepositoryTest.php index 69b1ef5073b6169102748462104bade23fc22017..6d1786b32c21d081422c85ef4ae5f844a3fcdb35 100644 --- a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductLinkRepositoryTest.php @@ -32,7 +32,7 @@ class ProductLinkRepositoryTest extends \Magento\TestFramework\TestCase\WebapiAb $productSku = 'grouped-product'; $linkType = 'associated'; $productData = [ - 'product_sku' => $productSku, + 'sku' => $productSku, 'link_type' => $linkType, 'linked_product_type' => 'simple', 'linked_product_sku' => 'simple', @@ -44,7 +44,7 @@ class ProductLinkRepositoryTest extends \Magento\TestFramework\TestCase\WebapiAb $serviceInfo = [ 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . $productSku . '/links/' . $linkType, + 'resourcePath' => self::RESOURCE_PATH . $productSku . '/links', 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, ], 'soap' => [ diff --git a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductRepositoryInterfaceTest.php b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductRepositoryInterfaceTest.php index c8ab24527c633a12fd46442a9528570a4586e458..8adffb82f70547d69249fde8e57dcfcce1643a13 100644 --- a/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductRepositoryInterfaceTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GroupedProduct/Api/ProductRepositoryInterfaceTest.php @@ -131,7 +131,7 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract $this->saveProduct($productData); // Create a group product - $productLinkData = ["product_sku" => "group_product_500", "link_type" => "associated", + $productLinkData = ["sku" => "group_product_500", "link_type" => "associated", "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", "position" => 0, "extension_attributes" => ["qty" => 1]]; $productWithGroupData = [ @@ -153,10 +153,10 @@ class ProductRepositoryInterfaceTest extends WebapiAbstract $this->assertEquals($productLinkData, $links[0]); // update link information for Group Product - $productLinkData1 = ["product_sku" => "group_product_500", "link_type" => "associated", + $productLinkData1 = ["sku" => "group_product_500", "link_type" => "associated", "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", "position" => 0, "extension_attributes" => ["qty" => 4]]; - $productLinkData2 = ["product_sku" => "group_product_500", "link_type" => "upsell", + $productLinkData2 = ["sku" => "group_product_500", "link_type" => "upsell", "linked_product_sku" => "product_simple_500", "linked_product_type" => "simple", "position" => 0, "extension_attributes" => []]; $productWithGroupData = [ diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCreateTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCreateTest.php index 1f3e32bcd3441fdde3cc3e07918bf2000b3a2746..4e14024dcf104ff1f0a34b9a19501bdd065ef35a 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCreateTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCreateTest.php @@ -67,9 +67,9 @@ class CreditmemoCreateTest extends WebapiAbstract 'base_currency_code' => null, 'base_discount_amount' => null, 'base_grand_total' => null, - 'base_hidden_tax_amount' => null, + 'base_discount_tax_compensation_amount' => null, 'base_shipping_amount' => null, - 'base_shipping_hidden_tax_amnt' => null, + 'base_shipping_discount_tax_compensation_amnt' => null, 'base_shipping_incl_tax' => null, 'base_shipping_tax_amount' => null, 'base_subtotal' => null, @@ -86,14 +86,14 @@ class CreditmemoCreateTest extends WebapiAbstract 'entity_id' => null, 'global_currency_code' => null, 'grand_total' => null, - 'hidden_tax_amount' => null, + 'discount_tax_compensation_amount' => null, 'increment_id' => null, 'invoice_id' => null, 'order_currency_code' => null, 'order_id' => $order->getId(), 'shipping_address_id' => null, 'shipping_amount' => null, - 'shipping_hidden_tax_amount' => null, + 'shipping_discount_tax_compensation_amount' => null, 'shipping_incl_tax' => null, 'shipping_tax_amount' => null, 'state' => null, diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCreateTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCreateTest.php index 3237b600d6194811759404a099936f0d4b9e1f87..d9aefceb45c888964689cf0d089c18dc6d9ce87b 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCreateTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/InvoiceCreateTest.php @@ -52,9 +52,9 @@ class InvoiceCreateTest extends WebapiAbstract 'base_currency_code' => null, 'base_discount_amount' => null, 'base_grand_total' => null, - 'base_hidden_tax_amount' => null, + 'base_discount_tax_compensation_amount' => null, 'base_shipping_amount' => null, - 'base_shipping_hidden_tax_amnt' => null, + 'base_shipping_discount_tax_compensation_amnt' => null, 'base_shipping_incl_tax' => null, 'base_shipping_tax_amount' => null, 'base_subtotal' => null, @@ -72,13 +72,13 @@ class InvoiceCreateTest extends WebapiAbstract 'entity_id' => null, 'global_currency_code' => null, 'grand_total' => null, - 'hidden_tax_amount' => null, + 'discount_tax_compensation_amount' => null, 'increment_id' => null, 'is_used_for_refund' => null, 'order_currency_code' => null, 'shipping_address_id' => null, 'shipping_amount' => null, - 'shipping_hidden_tax_amount' => null, + 'shipping_discount_tax_compensation_amount' => null, 'shipping_incl_tax' => null, 'shipping_tax_amount' => null, 'state' => null, @@ -99,7 +99,7 @@ class InvoiceCreateTest extends WebapiAbstract 'additionalData' => null, 'baseCost' => null, 'baseDiscountAmount' => null, - 'baseHiddenTaxAmount' => null, + 'baseDiscountTaxCompensationAmount' => null, 'basePrice' => null, 'basePriceInclTax' => null, 'baseRowTotal' => null, @@ -107,7 +107,7 @@ class InvoiceCreateTest extends WebapiAbstract 'baseTaxAmount' => null, 'description' => null, 'discountAmount' => null, - 'hiddenTaxAmount' => null, + 'discountTaxCompensationAmount' => null, 'name' => null, 'entity_id' => null, 'parentId' => null, diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/JquerytreeElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/JquerytreeElement.php index e08b8a6adff03f71182cb7366445c3509970713e..5f43bba871275e176c534f2d53018ef7c655274d 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Client/Element/JquerytreeElement.php +++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/JquerytreeElement.php @@ -7,154 +7,138 @@ namespace Magento\Mtf\Client\Element; use Magento\Mtf\Client\ElementInterface; +use Magento\Mtf\Client\Locator; /** - * Class JquerytreeElement - * Typified element class for JqueryTree elements + * Typified element class for JqueryTree elements. */ class JquerytreeElement extends Tree { /** - * Css class for finding tree nodes. + * Root element. * * @var string */ - protected $nodeCssClass = ' > ul'; + protected $rootElement = '//div[contains(@class, "tree x-tree jstree")]'; /** - * Css class for detecting tree nodes. + * Pattern for level node. * * @var string */ - protected $nodeSelector = 'li[data-id]'; + protected $level = '/ul/li[contains(@class, "jstree")]'; /** - * Css class for detecting tree nodes. + * Pattern for child element node. * * @var string */ - protected $checkedNodeSelector = 'li.jstree-checked[data-id]'; + protected $pattern = '/ul/li[contains(@class, "jstree") and a[text() = "%s"]]'; /** - * Css class for fetching node's name. + * Pattern for child open node. * * @var string */ - protected $nodeName = 'a'; + protected $openNode = '//li[contains(@class, "jstree-open") and a[text() = "%s"]]'; /** - * Array, which holds all selected elements paths. + * Pattern for child closed node. * - * @var array + * @var string */ - protected $checkedNodesPaths = []; + protected $closedNode = '//li[contains(@class, "jstree-closed") and a[text() = "%s"]]'; /** - * Returns structure of the jquerytree element. + * Selector for parent element. * - * @return array + * @var string */ - public function getStructure() - { - return $this->_getNodeContent($this, 'div[class*=jstree] > ul'); - } + protected $parentElement = './../../../a'; /** - * Recursive walks tree + * Selector for input. * - * @param ElementInterface $node - * @param string $parentCssClass - * @return array + * @var string */ - protected function _getNodeContent(ElementInterface $node, $parentCssClass) - { - $counter = 1; - $nextNodeSelector = $parentCssClass . " > " . $this->nodeSelector . ":nth-of-type($counter)"; - $nodeArray = []; - //Get list of all children nodes to work with - $newNode = $node->find($nextNodeSelector); - while ($newNode->isVisible()) { - $nextCheckedNodeSelector = $parentCssClass . " > " . $this->checkedNodeSelector . ":nth-of-type($counter)"; - $nodesNames = $newNode->find($this->nodeName); - $text = ltrim($nodesNames->getText()); - $childNodeSelector = $nextNodeSelector . $this->nodeCssClass; - $nodesContents = $newNode->find($childNodeSelector); - $subNodes = null; - if ($nodesContents->isVisible()) { - $subNodes = $this->_getNodeContent($nodesContents, $childNodeSelector); - } - $nodeArray[] = [ - 'name' => $text, - 'isChecked' => $node->find($nextCheckedNodeSelector)->isVisible() ? true : false, - 'element' => $newNode, - 'subnodes' => $subNodes, - ]; - ++$counter; - $nextNodeSelector = $parentCssClass . " > " . $this->nodeSelector . ":nth-of-type($counter)"; - $newNode = $node->find($nextNodeSelector); - } - return $nodeArray; - } + protected $input = '/a/ins[@class="jstree-checkbox"]'; + + /** + * Selected checkboxes. + * + * @var string + */ + protected $selectedLabels = '//li[contains(@class, "jstree-checked")]/a'; + + /** + * Selected checkboxes by level. + * + * @var string + */ + protected $selectedLabelsByLevel = '/ul/li[contains(@class, "jstree-checked")]/a'; /** - * Retrieve array of checked nodes from structure array. + * Display children. * - * @param array $structure - * @return array|null + * @param string $element + * @return void */ - protected function getCheckedNodes($structure) + protected function displayChildren($element) { - $pathArray = []; - if ($structure['isChecked'] == true) { - array_push($pathArray, $structure['name']); - if (is_array($structure['subnodes'])) { - foreach ($structure['subnodes'] as $node) { - array_push($pathArray, $this->getCheckedNodes($node)); - } - } - return $pathArray; + $element = $this->find(sprintf($this->openNode, $element), Locator::SELECTOR_XPATH); + if ($element->isVisible()) { + return; + } + $plusButton = $this->find(sprintf($this->closedNode, $element) . $this->input, Locator::SELECTOR_XPATH); + if ($plusButton->isVisible()) { + $plusButton->click(); + $this->waitLoadChildren($element); } - return null; } /** - * Method for recursive walk array of checked elements. - * If element haven't subnodes, adds element's path to $checkedNodesPaths + * Get element label. * - * @param array $pathArray - * @param string $rootPath + * @param ElementInterface $element * @return string */ - protected function getPathFromArray($pathArray, $rootPath = '') + protected function getElementLabel(ElementInterface $element) { - $path = ''; - $rootPath = $rootPath == '' ? $pathArray[0] : $rootPath . '/' . $pathArray[0]; - if (count($pathArray) > 1) { - for ($counter = 1; $counter < count($pathArray); $counter++) { - $path .= $this->getPathFromArray($pathArray[$counter], $rootPath); - } - } else { - $path = $rootPath; - $this->checkedNodesPaths[] = $path; - } - return $path; + return trim($element->getText()); } /** - * Returns array of paths of all selected elements. + * Get structure. * + * @param int|null $level * @return array */ - public function getValue() + public function getStructure($level = null) { - $pathsArray = []; - $structure = $this->getStructure(); - foreach ($structure as $structureChunk) { - $pathsArray[] = $this->getCheckedNodes($structureChunk); - } - foreach ($pathsArray as $pathArray) { - $this->getPathFromArray($pathArray); + $nodesSelector = $this->getNodesSelector($level); + $nodes = $this->getElements($nodesSelector, Locator::SELECTOR_XPATH); + + return $this->prepareValues($nodes); + } + + /** + * Get nodes selector. + * + * @param int|null $level + * @return string + */ + protected function getNodesSelector($level) + { + $selector = $this->rootElement; + if ($level !== null) { + for ($i = 1; $i < $level; $i++) { + $selector .= $this->level; + } + $selector .= $this->selectedLabelsByLevel; + } else { + $selector .= $this->selectedLabels; } - return array_filter($this->checkedNodesPaths); + + return $selector; } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/MultiselectlistElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/MultiselectlistElement.php index d5d4539e1b4e0c022f7d89d495118da02b31cf42..baa29cf35066d834536de1dba51f4eb2f5bd4faa 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Client/Element/MultiselectlistElement.php +++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/MultiselectlistElement.php @@ -27,6 +27,13 @@ class MultiselectlistElement extends MultiselectElement */ protected $optionCheckedElement = './/*[contains(@class, "mselect-checked")]/following-sibling::span'; + /** + * Option locator by value. + * + * @var string + */ + protected $optionByValue = './/*[contains(@class,"mselect-list-item")]/label[contains(normalize-space(.), %s)]'; + /** * Select options by values in multiple select list * @@ -107,4 +114,16 @@ class MultiselectlistElement extends MultiselectElement return $optionsValue; } + + /** + * Check whether value is visible in the list. + * + * @param string $value + * @return bool + */ + public function isValueVisible($value) + { + $option = $this->find(sprintf($this->optionByValue, $this->escapeQuotes($value)), Locator::SELECTOR_XPATH); + return $option->isVisible(); + } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php index c45d902c1bd33858055fea1ae1976a0e8d62b25a..7c5dad046efce8e907aa120edfc757968e57f94b 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php +++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/SuggestElement.php @@ -6,11 +6,9 @@ namespace Magento\Mtf\Client\Element; -use Magento\Framework\Webapi\Exception; use Magento\Mtf\Client\Locator; /** - * Class SuggestElement * General class for suggest elements. */ class SuggestElement extends SimpleElement @@ -21,35 +19,35 @@ class SuggestElement extends SimpleElement const BACKSPACE = "\xEE\x80\x83"; /** - * Selector suggest input + * Selector suggest input. * * @var string */ protected $suggest = '.mage-suggest-inner > .search'; /** - * Selector search result + * Selector search result. * * @var string */ protected $searchResult = '.mage-suggest-dropdown'; /** - * Selector item of search result + * Selector item of search result. * * @var string */ protected $resultItem = './/ul/li/a[text()="%s"]'; /** - * Suggest state loader + * Suggest state loader. * * @var string */ protected $suggestStateLoader = '.mage-suggest-state-loading'; /** - * Set value + * Set value. * * @param string $value * @return void @@ -64,10 +62,7 @@ class SuggestElement extends SimpleElement return; } foreach (str_split($value) as $symbol) { - $input = $this->find($this->suggest); - $input->click(); - $input->keys([$symbol]); - $this->waitResult(); + $this->keys([$symbol]); $searchedItem = $this->find(sprintf($this->resultItem, $value), Locator::SELECTOR_XPATH); if ($searchedItem->isVisible()) { try { @@ -81,6 +76,20 @@ class SuggestElement extends SimpleElement } } + /** + * Send keys. + * + * @param array $keys + * @return void + */ + public function keys(array $keys) + { + $input = $this->find($this->suggest); + $input->click(); + $input->keys($keys); + $this->waitResult(); + } + /** * Clear value of element. * @@ -95,7 +104,7 @@ class SuggestElement extends SimpleElement } /** - * Wait for search result is visible + * Wait for search result is visible. * * @return void */ @@ -112,7 +121,7 @@ class SuggestElement extends SimpleElement } /** - * Get value + * Get value. * * @return string */ @@ -124,21 +133,25 @@ class SuggestElement extends SimpleElement } /** - * Checking exist value in search result + * Checking exist value in search result. * * @param string $value * @return bool */ public function isExistValueInSearchResult($value) { - $searchResult = $this->find($this->searchResult); - - $this->find($this->suggest)->setValue($value); - $this->waitResult(); - if (!$searchResult->isVisible()) { - return false; + $needle = $this->find($this->searchResult)->find(sprintf($this->resultItem, $value), Locator::SELECTOR_XPATH); + $keys = str_split($value); + $this->keys($keys); + if ($needle->isVisible()) { + try { + return true; + } catch (\Exception $e) { + // In parallel run on windows change the focus is lost on element + // that causes disappearing of attribute suggest list. + } } - return $searchResult->find(sprintf($this->resultItem, $value), Locator::SELECTOR_XPATH)->isVisible(); + return false; } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/Tree.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/Tree.php index 00c3d41ffe2bca015596392b0b6a30616fc1da9a..3f53152af2ce1be9b9d2536b94b8e3a40d69276f 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Client/Element/Tree.php +++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/Tree.php @@ -7,58 +7,72 @@ namespace Magento\Mtf\Client\Element; use Magento\Mtf\Client\ElementInterface; +use Magento\Mtf\Client\Locator; /** - * Class Tree * General class for tree elements. Holds general implementation of methods, which overrides in child classes. */ abstract class Tree extends SimpleElement { /** - * Css class for finding tree nodes + * Selected checkboxes. * * @var string */ - protected $nodeCssClass; + protected $selectedLabels; /** - * Css class for detecting tree nodes + * Pattern for child element node. * * @var string */ - protected $nodeSelector; + protected $pattern; /** - * Css class for fetching node's name + * Selector for child loader. * * @var string */ - protected $nodeName; + protected $childLoader = 'ul'; /** - * @return mixed + * Selector for input. + * + * @var string */ - abstract public function getStructure(); + protected $input; /** - * Drag and drop element to(between) another element(s) + * Selector for parent element. * - * @param ElementInterface $target - * @throws \Exception - * @SuppressWarnings(PHPMD.UnusedFormalParameter) + * @var string */ - public function dragAndDrop(ElementInterface $target) - { - throw new \Exception('Not applicable for this class of elements (TreeElement)'); - } + protected $parentElement; /** - * getValue method is not accessible in this class. - * Throws exception if used. + * Display children. + * + * @param string $element + * @return void + */ + abstract protected function displayChildren($element); + + /** + * Get element label. * + * @param ElementInterface $element + * @return string + */ + abstract protected function getElementLabel(ElementInterface $element); + + /** + * Drag and drop element to(between) another element(s). + * + * @param ElementInterface $target * @throws \Exception + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ - public function getValue() + public function dragAndDrop(ElementInterface $target) { throw new \Exception('Not applicable for this class of elements (TreeElement)'); } @@ -77,87 +91,110 @@ abstract class Tree extends SimpleElement } /** - * Click a tree element by its path (Node names) in tree + * Click a tree element by its path (Node names) in tree. * * @param string $path - * @throws \InvalidArgumentException */ public function setValue($path) { - $pathChunkCounter = 0; - $pathArray = explode('/', $path); - $pathArrayLength = count($pathArray); - $structureChunk = $this->getStructure(); //Set the root of a structure as a first structure chunk - foreach ($pathArray as $pathChunk) { - $structureChunk = $this->deep($pathChunk, $structureChunk); - $structureChunk = ($pathChunkCounter == $pathArrayLength - 1) ? - $structureChunk['element'] : $structureChunk['subnodes']; - ++$pathChunkCounter; - } - if ($structureChunk) { - /** @var ElementInterface $needleElement */ - $needleElement = $structureChunk->find($this->nodeName); - $needleElement->click(); - } else { - throw new \InvalidArgumentException('The path specified for tree is invalid'); + $this->eventManager->dispatchEvent(['set_value'], [(string)$this->getAbsoluteSelector()]); + $elementSelector = $this->prepareElementSelector($path); + $elements = $this->getElements('.' . $elementSelector . $this->input, Locator::SELECTOR_XPATH); + foreach ($elements as $element) { + $element->click(); } } /** - * Internal function for deeping in hierarchy of the tree structure - * Return the nested array if it exists or object of class Element if this is the final part of structure + * Get the value. * - * @param string $pathChunk - * @param array $structureChunk - * @return array|ElementInterface|false + * @return array */ - protected function deep($pathChunk, $structureChunk) + public function getValue() { - if (is_array($structureChunk)) { - foreach ($structureChunk as $structureNode) { - $pattern = '/' . $pathChunk . '\s\([\d]+\)|' . $pathChunk . '/'; - if (isset($structureNode) && preg_match($pattern, $structureNode['name'])) { - return $structureNode; - } - } - } + $this->eventManager->dispatchEvent(['get_value'], [(string)$this->getAbsoluteSelector()]); + $checkboxes = $this->getElements($this->selectedLabels, Locator::SELECTOR_XPATH); - return false; + return $this->prepareValues($checkboxes); } /** - * Recursive walks tree + * Prepare values for checked checkboxes. * - * @param ElementInterface $node - * @param string $parentCssClass + * @param ElementInterface[] $checkboxes * @return array */ - protected function _getNodeContent(ElementInterface $node, $parentCssClass) + protected function prepareValues(array $checkboxes) + { + $values = []; + foreach ($checkboxes as $checkbox) { + $fullPath = $this->getFullPath($checkbox); + $values[] = implode('/', array_reverse($fullPath)); + } + + return $values; + } + + /** + * Prepare element selector. + * + * @param string $path + * @return string + */ + protected function prepareElementSelector($path) { - $nodeArray = []; - $nodeList = []; - $counter = 1; - $newNode = $node->find($parentCssClass . ' > ' . $this->nodeSelector . ':nth-of-type(' . $counter . ')'); - //Get list of all children nodes to work with - while ($newNode->isVisible()) { - $nodeList[] = $newNode; - ++$counter; - $newNode = $node->find($parentCssClass . ' > ' . $this->nodeSelector . ':nth-of-type(' . $counter . ')'); + $pathArray = explode('/', $path); + $elementSelector = ''; + foreach ($pathArray as $itemElement) { + $this->displayChildren($itemElement); + $elementSelector .= sprintf($this->pattern, $itemElement); } - //Write to array values of current node - foreach ($nodeList as $currentNode) { - /** @var ElementInterface $currentNode */ - $nodesNames = $currentNode->find($this->nodeName); - $nodesContents = $currentNode->find($this->nodeCssClass); - $text = ltrim($nodesNames->getText()); - $nodeArray[] = [ - 'name' => $text, - 'element' => $currentNode, - 'subnodes' => $nodesContents->isVisible() ? - $this->_getNodeContent($nodesContents, $this->nodeCssClass) : null, - ]; + + return $elementSelector; + } + + /** + * Check visible element. + * + * @param string $path + * @return bool + */ + public function isElementVisible($path) + { + $elementSelector = $this->prepareElementSelector($path); + return $this->find($elementSelector, Locator::SELECTOR_XPATH)->isVisible(); + } + + /** + * Waiter for load children. + * + * @param ElementInterface $element + * @return void + */ + protected function waitLoadChildren(ElementInterface $element) + { + $selector = $this->childLoader; + $this->waitUntil( + function () use ($element, $selector) { + return $element->find($selector)->isVisible() ? true : null; + } + ); + } + + /** + * Get full path for element. + * + * @param ElementInterface $element + * @return string[] + */ + protected function getFullPath(ElementInterface $element) + { + $fullPath[] = $this->getElementLabel($element); + $parentElement = $element->find($this->parentElement, Locator::SELECTOR_XPATH); + if ($parentElement->isVisible()) { + $fullPath = array_merge($fullPath, $this->getFullPath($parentElement)); } - return $nodeArray; + return $fullPath; } } diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/TreeElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/TreeElement.php index 09995686b04c96c3dd4378b3ec3bb93eb2d23780..d49000f3268ca2292f8e97035768344cda5e19a6 100644 --- a/dev/tests/functional/lib/Magento/Mtf/Client/Element/TreeElement.php +++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/TreeElement.php @@ -6,40 +6,103 @@ namespace Magento\Mtf\Client\Element; +use Magento\Mtf\Client\ElementInterface; +use Magento\Mtf\Client\Locator; + /** - * Class TreeElement - * Typified element class for Tree elements + * Typified element class for Tree elements. */ class TreeElement extends Tree { /** - * Css class for finding tree nodes + * All selected checkboxes. + * + * @var string + */ + protected $selectedCheckboxes = '//input[@checked=""]'; + + /** + * Selector for plus image. + * + * @var string + */ + protected $imagePlus = './div/img[contains(@class, "-plus")]'; + + /** + * Selector for input. + * + * @var string + */ + protected $input = '/div/a/span'; + + /** + * Selector for parent element. + * + * @var string + */ + protected $parentElement = './../../../../../div/a/span'; + + /** + * Selected checkboxes. * * @var string */ - protected $nodeCssClass = '.x-tree-node > .x-tree-node-ct'; + protected $selectedLabels = '//input[@checked=""]/../a/span'; /** - * Css class for detecting tree nodes + * Pattern for child element node. * * @var string */ - protected $nodeSelector = '.x-tree-node'; + protected $pattern = '//li[@class="x-tree-node" and div/a/span[contains(text(),"%s")]]'; /** - * Css class for fetching node's name + * Regular pattern mask for node label. * * @var string */ - protected $nodeName = 'div > a'; + protected $regPatternLabel = '`(.+) \(.*`'; /** - * Get structure of the tree element + * Clear data for element. * - * @return array + * @return void */ - public function getStructure() + public function clear() { - return $this->_getNodeContent($this, '.x-tree-root-node'); + $checkboxes = $this->getElements($this->selectedCheckboxes, Locator::SELECTOR_XPATH, 'checkbox'); + foreach ($checkboxes as $checkbox) { + $checkbox->setValue('No'); + } + } + + /** + * Display children. + * + * @param string $element + * @return void + */ + protected function displayChildren($element) + { + $element = $this->find(sprintf($this->pattern, $element), Locator::SELECTOR_XPATH); + $plusButton = $element->find($this->imagePlus, Locator::SELECTOR_XPATH); + if ($plusButton->isVisible()) { + $plusButton->click(); + $this->waitLoadChildren($element); + } + } + + /** + * Get element label. + * + * @param ElementInterface $element + * @return string + */ + protected function getElementLabel(ElementInterface $element) + { + $value = $element->getText(); + preg_match($this->regPatternLabel, $value, $matches); + + return trim($matches[1]); } } diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Menu.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Menu.php index efc576650288fa3d288416494047832226fb9d09..7b8b2651a08b14f09741f9f7a9d8ad5ab8d2a4c9 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Menu.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Menu.php @@ -26,7 +26,7 @@ class Menu extends Block * * @var string */ - protected $subMenu = './/li[@role="menu-item" and a[span="%s"]]/div[@class="submenu"]'; + protected $subMenu = './/li[@role="menu-item" and a[span="%s"]]/div[contains(@class, "submenu")]'; /** * Submenu item selector. diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php index 32e4652e88d005d24688a98b8b68ef9843a417b4..7fe5ba759627fa0343c77f45496b949662522bca 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/Block/Widget/Grid.php @@ -104,13 +104,6 @@ abstract class Grid extends Block */ protected $templateBlock = './ancestor::body'; - /** - * Selector of element to wait for. If set by child will wait for element after action - * - * @var string - */ - protected $waitForSelector; - /** * Locator type of waitForSelector * @@ -144,7 +137,7 @@ abstract class Grid extends Block * * @var string */ - protected $rowTemplate = 'td[contains(text(),normalize-space("%s"))]'; + protected $rowTemplate = 'td[contains(.,normalize-space("%s"))]'; /** * Secondary part of row locator template for getRow() method with strict option @@ -249,7 +242,6 @@ abstract class Grid extends Block $rowItem = $this->_rootElement->find($this->rowItem, Locator::SELECTOR_CSS); if ($rowItem->isVisible()) { $rowItem->find($this->editLink, Locator::SELECTOR_CSS)->click(); - $this->waitForElement(); } else { throw new \Exception('Searched item was not found.'); } @@ -273,20 +265,6 @@ abstract class Grid extends Block $this->getTemplateBlock()->waitLoader(); } - /** - * Method that waits for the configured selector using class attributes. - */ - protected function waitForElement() - { - if (!empty($this->waitForSelector)) { - if ($this->waitForSelectorVisible) { - $this->getTemplateBlock()->waitForElementVisible($this->waitForSelector, $this->waitForSelectorType); - } else { - $this->getTemplateBlock()->waitForElementNotVisible($this->waitForSelector, $this->waitForSelectorType); - } - } - } - /** * Search for item and select it * diff --git a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/NavigateMenuTest.php b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/NavigateMenuTest.php index 5ddeae663986fb131b8da386365384173c9dc35a..b8d486de23c5b4006f491a3f1fad1532a2a0f928 100644 --- a/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/NavigateMenuTest.php +++ b/dev/tests/functional/tests/app/Magento/Backend/Test/TestCase/NavigateMenuTest.php @@ -21,7 +21,7 @@ class NavigateMenuTest extends Injectable { /* tags */ const MVP = 'no'; - const DOMAIN = 'CS, MX, PS'; + const DOMAIN = 'PS'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Product/Composite/Configure.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Product/Composite/Configure.php index 59d90eddd8a9f42b20c1a9de1e60bc55bab76f9a..d3fb156148f56bcf1c4aed8aaf403cc44f3e2b65 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Product/Composite/Configure.php +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Product/Composite/Configure.php @@ -19,7 +19,7 @@ class Configure extends \Magento\Catalog\Test\Block\Adminhtml\Product\Composite\ * * @var string */ - protected $option = '//div[@class="composite-bundle"]//label[.="%option_name%"]//following-sibling::*//%selector%'; + protected $option = '//label[contains(.,"%option_name%")]//following-sibling::*//%selector%'; /** * Fill options for the product diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php index 802a2d53e6bc04359dc92f2a39edbf4ba20b5d2a..35662e78d52a2ec3cd3470175cc803071664b0f1 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php @@ -11,53 +11,52 @@ use Magento\Mtf\Block\Block; use Magento\Mtf\Client\Locator; use Magento\Mtf\Fixture\FixtureInterface; use Magento\Mtf\Fixture\InjectableFixture; -use Magento\Mtf\Client\Element\TreeElement; +use Magento\Backend\Test\Block\Template; /** - * Class Tree - * Categories tree block + * Categories tree block. */ class Tree extends Block { /** - * 'Add Subcategory' button + * 'Add Subcategory' button. * * @var string */ protected $addSubcategory = '#add_subcategory_button'; /** - * 'Add Root Category' button + * 'Add Root Category' button. * * @var string */ protected $addRootCategory = '#add_root_category_button'; /** - * 'Expand All' link + * 'Expand All' link. * * @var string */ protected $expandAll = 'a[onclick*=expandTree]'; /** - * Backend abstract block + * Backend abstract block. * * @var string */ protected $templateBlock = './ancestor::body'; /** - * Category tree + * Category tree. * * @var string */ protected $treeElement = '.tree-holder'; /** - * Get backend abstract block + * Get backend abstract block. * - * @return \Magento\Backend\Test\Block\Template + * @return Template */ protected function getTemplateBlock() { @@ -68,7 +67,7 @@ class Tree extends Block } /** - * Press 'Add Subcategory' button + * Press 'Add Subcategory' button. * * @return void */ @@ -79,7 +78,7 @@ class Tree extends Block } /** - * Press 'Add Root Category' button + * Press 'Add Root Category' button. * * @return void */ @@ -90,7 +89,7 @@ class Tree extends Block } /** - * Select Default category + * Select Default category. * * @param FixtureInterface $category * @param bool $fullPath @@ -102,6 +101,9 @@ class Tree extends Block if (!$fullPath) { array_pop($parentPath); } + if (empty($parentPath)) { + return; + } $path = implode('/', $parentPath); $this->expandAllCategories(); @@ -110,7 +112,7 @@ class Tree extends Block } /** - * Prepare category path + * Prepare category path. * * @param Category $category * @return array @@ -129,28 +131,7 @@ class Tree extends Block } /** - * Find category name in array - * - * @param array $structure - * @param array $category - * @return bool - */ - protected function inTree(array $structure, array &$category) - { - $element = array_shift($category); - foreach ($structure as $item) { - $result = strpos($item['name'], $element); - if ($result !== false && !empty($item['subnodes'])) { - return $this->inTree($item['subnodes'], $category); - } elseif ($result !== false && empty($category)) { - return true; - } - } - return false; - } - - /** - * Check category in category tree + * Check category in category tree. * * @param Category $category * @return bool @@ -158,24 +139,13 @@ class Tree extends Block public function isCategoryVisible(Category $category) { $categoryPath = $this->prepareFullCategoryPath($category); - /** @var TreeElement $treeElement */ - $treeElement = $this->_rootElement->find($this->treeElement, Locator::SELECTOR_CSS, 'tree'); - $structure = $treeElement->getStructure(); - $result = false; - $element = array_shift($categoryPath); - foreach ($structure as $item) { - $searchResult = strpos($item['name'], $element); - if ($searchResult !== false && !empty($item['subnodes'])) { - $result = $this->inTree($item['subnodes'], $categoryPath); - } elseif ($searchResult !== false && empty($categoryPath)) { - $result = true; - } - } - return $result; + $categoryPath = implode('/', $categoryPath); + return $this->_rootElement->find($this->treeElement, Locator::SELECTOR_CSS, 'tree') + ->isElementVisible($categoryPath); } /** - * Expand all categories tree + * Expand all categories tree. * * @return void */ diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Composite/Configure.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Composite/Configure.php index 4308b05b35bc7602516325b0a27f538f37565831..0b85e719aa1577e1f0467519ee92276e24ae5456 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Composite/Configure.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Composite/Configure.php @@ -103,7 +103,7 @@ class Configure extends AbstractConfigureBlock { $context = $this->_rootElement; $selector = $this->configureForm; - return $this->browser->waitUntil( + $this->browser->waitUntil( function () use ($context, $selector) { return $context->find($selector)->isVisible() ? true : null; } @@ -119,7 +119,7 @@ class Configure extends AbstractConfigureBlock { $context = $this->_rootElement; $selector = $this->configureForm; - return $this->browser->waitUntil( + $this->browser->waitUntil( function () use ($context, $selector) { return $context->find($selector)->isVisible() ? null : true; } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/AdvancedInventory.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/AdvancedInventory.php new file mode 100644 index 0000000000000000000000000000000000000000..56c418fcf5effc4553b83230e0584d3c4061aacf --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/AdvancedInventory.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab; + +use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\ProductTab; +use Magento\Mtf\Client\Element\SimpleElement; +use Magento\Mtf\Client\Locator; + +/** + * Advanced inventory tab. + */ +class AdvancedInventory extends ProductTab +{ + /** + * Styled field block selector. + * + * @var string + */ + protected $styledFieldBlock = './/*[@id="table_cataloginventory"]/div[@style][1]'; + + /** + * Fill data to fields on tab. + * + * @param array $fields + * @param SimpleElement|null $element + * @return $this + */ + public function fillFormTab(array $fields, SimpleElement $element = null) + { + $this->waitInit(); + return parent::fillFormTab($fields, $element); + } + + /** + * Get data of tab. + * + * @param array|null $fields + * @param SimpleElement|null $element + * @return array + */ + public function getDataFormTab($fields = null, SimpleElement $element = null) + { + $this->waitInit(); + return parent::getDataFormTab($fields, $element); + } + + /** + * Wait until init tab. + * + * @return void + */ + public function waitInit() + { + $context = $this->_rootElement; + $selector = $this->styledFieldBlock; + + $context->waitUntil( + function () use ($context, $selector) { + $elements = $context->getElements($selector, Locator::SELECTOR_XPATH); + return count($elements) > 0 ? true : null; + } + ); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Attributes/Search.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Attributes/Search.php index 408d81f180988082640513b174fab943989efa4e..9812d5bcd0120c19cf6ef142056b824b2e3e30ee 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Attributes/Search.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Attributes/Search.php @@ -15,6 +15,13 @@ use Magento\Mtf\Client\Locator; */ class Search extends SuggestElement { + /** + * Selector for top page. + * + * @var string + */ + protected $topPage = './ancestor::body//header[contains(@class, "page-header")]/div[1]'; + /** * Attributes locator. * @@ -73,11 +80,28 @@ class Search extends SuggestElement */ public function isExistAttributeInSearchResult($productAttribute) { + $this->find($this->topPage, Locator::SELECTOR_XPATH)->click(); $this->find($this->actionToggle)->click(); - $this->find($this->suggest)->setValue($productAttribute->getFrontendLabel()); + + return $this->isExistValueInSearchResult($productAttribute->getFrontendLabel()); + } + + /** + * Send keys. + * + * @param array $keys + * @return void + */ + public function keys(array $keys) + { + $input = $this->find($this->suggest); + if (!$input->isVisible()) { + $this->find($this->actionToggle)->click(); + } + $input->click(); + $input->keys($keys); + $input->click(); $this->waitResult(); - $attributeSelector = sprintf($this->searchArrtibute, $productAttribute->getFrontendLabel()); - return $this->find($this->searchResult)->find($attributeSelector, Locator::SELECTOR_XPATH)->isVisible(); } /** @@ -87,12 +111,9 @@ class Search extends SuggestElement */ public function waitResult() { - $browser = $this; - $selector = $this->searchResult; - $browser->waitUntil( - function () use ($browser, $selector) { - $element = $browser->find($selector); - return $element->isVisible() ? true : null; + $this->waitUntil( + function () { + return $this->find($this->searchResult)->isVisible() ? true : null; } ); } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Crosssell/Grid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Crosssell/Grid.php index 395b7d273efd2ffd3d5d9654d33362f5bc7bb496..8a148a80ee809d78f777d0862c2dd5c4cd6c59b6 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Crosssell/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/Crosssell/Grid.php @@ -6,13 +6,10 @@ namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Crosssell; -use Magento\Backend\Test\Block\Widget\Grid as GridInterface; - /** - * Class Grid - * Cross sell products grid + * Cross sell products grid. */ -class Grid extends GridInterface +class Grid extends \Magento\Backend\Test\Block\Widget\Grid { /** * Grid fields map diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/NewCategoryIds.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/NewCategoryIds.php index 21ab6bf91c168c6470600e060b5e98108b5e2319..c1baad740ef47f6564c703afddebd6d11d772b35 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/NewCategoryIds.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Tab/ProductDetails/NewCategoryIds.php @@ -40,7 +40,7 @@ class NewCategoryIds extends Form * * @var string */ - protected $createCategoryButton = '[data-action="save"]'; + protected $createCategoryButton = '[data-role="action"][type="button"]'; /** * Add new category to product. diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php index d8febacc644781c8d3e0000ce4ce3cbaff009a86..ee3a7bc511f008fcbf453db174e2353b9206e800 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php @@ -18,6 +18,7 @@ use Magento\Mtf\Client\Locator; use Magento\Mtf\Fixture\FixtureInterface; use Magento\Mtf\Fixture\InjectableFixture; use Magento\Catalog\Test\Fixture\Category; +use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Attributes\Search; /** * Product form on backend product page. @@ -247,12 +248,23 @@ class ProductForm extends FormTabs * @return bool */ public function checkAttributeInSearchAttributeForm(CatalogProductAttribute $productAttribute) + { + $this->waitPageToLoad(); + return $this->getAttributesSearchForm()->isExistAttributeInSearchResult($productAttribute); + } + + /** + * Get attributes search form. + * + * @return Search + */ + protected function getAttributesSearchForm() { return $this->_rootElement->find( $this->attributeSearch, Locator::SELECTOR_CSS, 'Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\Attributes\Search' - )->isExistAttributeInSearchResult($productAttribute); + ); } /** @@ -338,7 +350,6 @@ class ProductForm extends FormTabs */ public function getAttributeForm() { - /** @var AttributeForm $attributeForm */ return $this->blockFactory->create( 'Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\AttributeForm', ['element' => $this->browser->find('body')] diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml index 3ea93f0ab859baa7e39f824f0b91d8c971928dc0..d88f2728f04b0837febe3c9cd96965d98bdec566 100755 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml @@ -90,7 +90,7 @@ </fields> </advanced-pricing> <advanced-inventory> - <class>\Magento\Backend\Test\Block\Widget\Tab</class> + <class>\Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Tab\AdvancedInventory</class> <selector>#product_info_tabs_advanced-inventory</selector> <strategy>css selector</strategy> <wrapper>product[stock_data]</wrapper> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeOptionsOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeOptionsOnProductForm.php index b14e5ac6e201000ef0206d5f86fc27220961008b..60f0df41ed6bb3691ce512d632457720494b3e85 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeOptionsOnProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeOptionsOnProductForm.php @@ -14,6 +14,8 @@ use Magento\Mtf\Constraint\AbstractConstraint; class AssertAttributeOptionsOnProductForm extends AbstractConstraint { /** + * Assert all product attribute options on product creation form. + * * @return void */ public function processAssert() diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSearchableByLabel.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSearchableByLabel.php index 23d7946f161db6a01dc838a5719b4ce6b5db83a2..fc84ae52d8a084bfdfc65444dc50cd52a2f7ca49 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSearchableByLabel.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAttributeSearchableByLabel.php @@ -14,6 +14,8 @@ use Magento\Mtf\Constraint\AbstractConstraint; class AssertAttributeSearchableByLabel extends AbstractConstraint { /** + * Assert that product attribute is searchable on Frontend. + * * @return void */ public function processAssert() diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryAbsenceOnBackend.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryAbsenceOnBackend.php index 2fceef709b88b6e834f84ef9db4a3b682af68b90..38f027b0454511619104f3b702ea105ca7e6c80e 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryAbsenceOnBackend.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCategoryAbsenceOnBackend.php @@ -11,13 +11,12 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogCategoryIndex; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertCategoryAbsenceOnBackend - * Assert that not displayed category in backend catalog category tree + * Assert that not displayed category in backend catalog category tree. */ class AssertCategoryAbsenceOnBackend extends AbstractConstraint { /** - * Assert that not displayed category in backend catalog category tree + * Assert that not displayed category in backend catalog category tree. * * @param CatalogCategoryIndex $catalogCategoryIndex * @param Category $category @@ -33,7 +32,7 @@ class AssertCategoryAbsenceOnBackend extends AbstractConstraint } /** - * Returns a string representation of the object + * Returns a string representation of the object. * * @return string */ diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php index f9b830d3a0349904fb9f600e7d724e207294e193..4052a470a60642250dcefe83cae20bef9696df43 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php @@ -12,13 +12,12 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertAbsenceInAddAttributeSearch - * Checks that product attribute cannot be added to product template on Product Page via Add Attribute control + * Checks that product attribute cannot be added to product template on Product Page via Add Attribute control. */ class AssertProductAttributeAbsenceInSearchOnProductForm extends AbstractConstraint { /** - * Assert that deleted attribute can't be added to product template on Product Page via Add Attribute control + * Assert that deleted attribute can't be added to product template on Product Page via Add Attribute control. * * @param CatalogProductAttribute $productAttribute * @param CatalogProductIndex $productGrid @@ -39,7 +38,7 @@ class AssertProductAttributeAbsenceInSearchOnProductForm extends AbstractConstra } /** - * Text absent Product Attribute in Attribute Search form + * Text absent Product Attribute in Attribute Search form. * * @return string */ diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php index ca35c959794d9775f823ca133adcea15e930da1b..f812fcdcf2617a925569123cba71e145b0dd4646 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php @@ -27,13 +27,20 @@ class AssertProductAttributeIsUnique extends AbstractConstraint */ const UNIQUE_MESSAGE = 'The value of attribute "%s" must be unique'; + /** + * Fixture factory. + * + * @var FixtureFactory + */ + protected $fixtureFactory; + /** * Check whether the attribute is unique. * * @param CatalogProductIndex $catalogProductIndex * @param CatalogProductEdit $catalogProductEdit * @param CatalogProductAttribute $attribute - * @param CatalogProductSimple $product, + * @param CatalogProductSimple $product , * @param FixtureFactory $fixtureFactory * @throws \Exception * @return void @@ -45,7 +52,47 @@ class AssertProductAttributeIsUnique extends AbstractConstraint CatalogProductSimple $product, FixtureFactory $fixtureFactory ) { - $simpleProduct = $fixtureFactory->createByCode( + $this->fixtureFactory = $fixtureFactory; + $simpleProduct = $this->createSimpleProductFixture($product, $attribute); + $catalogProductIndex->open()->getGridPageActionBlock()->addProduct('simple'); + $productForm = $catalogProductEdit->getProductForm(); + $productForm->fill($simpleProduct); + $catalogProductEdit->getFormPageActions()->save(); + $failedAttributes = $productForm->getRequireNoticeAttributes($simpleProduct); + $attributeLabel = $attribute->getFrontendLabel(); + $actualMessage = $this->getActualMessage($failedAttributes, $attributeLabel); + + \PHPUnit_Framework_Assert::assertEquals( + sprintf(self::UNIQUE_MESSAGE, $attributeLabel), + $actualMessage, + 'JS error notice on product edit page is not equal to expected.' + ); + } + + /** + * Get actual message. + * + * @param array $errors + * @param string $attributeLabel + * @return mixed + */ + protected function getActualMessage(array $errors, $attributeLabel) + { + return isset($errors['product-details'][$attributeLabel]) + ? $errors['product-details'][$attributeLabel] + : null; + } + + /** + * Create simple product fixture. + * + * @param CatalogProductSimple $product + * @param CatalogProductAttribute $attribute + * @return CatalogProductSimple + */ + protected function createSimpleProductFixture(CatalogProductSimple $product, CatalogProductAttribute $attribute) + { + return $this->fixtureFactory->createByCode( 'catalogProductSimple', [ 'dataSet' => 'product_with_category_with_anchor', @@ -57,20 +104,6 @@ class AssertProductAttributeIsUnique extends AbstractConstraint ], ] ); - $catalogProductIndex->open()->getGridPageActionBlock()->addProduct('simple'); - $productForm = $catalogProductEdit->getProductForm(); - $productForm->fill($simpleProduct); - $catalogProductEdit->getFormPageActions()->save(); - $failedAttributes = $productForm->getRequireNoticeAttributes($simpleProduct); - $actualMessage = isset($failedAttributes['product-details'][$attribute->getFrontendLabel()]) - ? $failedAttributes['product-details'][$attribute->getFrontendLabel()] - : null; - - \PHPUnit_Framework_Assert::assertEquals( - sprintf(self::UNIQUE_MESSAGE, $attribute->getFrontendLabel()), - $actualMessage, - 'JS error notice on product edit page is not equal to expected.' - ); } /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUsedPromoRules.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUsedPromoRules.php index f7ff0b4382e0ba7e73a2ab44ecc29557100596f5..a26a88439a0f53feeb7cbc1f62c78ab359e6e9f2 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUsedPromoRules.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUsedPromoRules.php @@ -14,6 +14,8 @@ use Magento\Mtf\Constraint\AbstractConstraint; class AssertProductAttributeIsUsedPromoRules extends AbstractConstraint { /** + * Assert that product attribute can be used on promo rules conditions. + * * @return void */ public function processAssert() diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/DeleteCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/DeleteCategoryEntityTest.xml index 7c83200156588aa0b2cbca44e7eb1af91ff18e95..6e1a9b50d3b46e4140241fcfc9e4a4086f16c726 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/DeleteCategoryEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/DeleteCategoryEntityTest.xml @@ -6,18 +6,18 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> - <testCase name="Magento\Catalog\Test\TestCase\Category\DeleteCategoryEntityTest"> - <variation name="DeleteCategoryEntityTestVariation1"> - <data name="category/dataSet" xsi:type="string">root_category</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySuccessDeleteMessage"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryAbsenceOnBackend"/> - </variation> - <variation name="DeleteCategoryEntityTestVariation2"> - <data name="category/dataSet" xsi:type="string">root_subcategory</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySuccessDeleteMessage"/> - <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteCategoryNotInGrid"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryAbsenceOnBackend"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryAbsenceOnFrontend"/> - </variation> - </testCase> + <testCase name="Magento\Catalog\Test\TestCase\Category\DeleteCategoryEntityTest"> + <variation name="DeleteCategoryEntityTestVariation1"> + <data name="category/dataSet" xsi:type="string">root_category</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySuccessDeleteMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryAbsenceOnBackend" /> + </variation> + <variation name="DeleteCategoryEntityTestVariation2"> + <data name="category/dataSet" xsi:type="string">root_subcategory</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySuccessDeleteMessage" /> + <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteCategoryNotInGrid" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryAbsenceOnBackend" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryAbsenceOnFrontend" /> + </variation> + </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/UpdateCategoryEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/UpdateCategoryEntityTest.xml index 44ea89b8918c994f0b6cdbcf5eacab22e57ba1ef..ed7e2cdbd4394824e95cbcb4328d220255f6f2d5 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/UpdateCategoryEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Category/UpdateCategoryEntityTest.xml @@ -6,59 +6,45 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> - <testCase name="Magento\Catalog\Test\TestCase\Category\UpdateCategoryEntityTest"> - <variation name="UpdateCategoryEntityTestVariation1"> - <data name="category/data/parent_id/dataSet" xsi:type="string">default_category</data> - <data name="category/data/name" xsi:type="string">Name%isolation%</data> - <data name="category/data/is_active" xsi:type="string">Yes</data> - <data name="category/data/url_key" xsi:type="string">UrlKey%isolation%</data> - <data name="category/data/description" xsi:type="string">-</data> - <data name="category/data/meta_title" xsi:type="string">-</data> - <data name="category/data/include_in_menu" xsi:type="string">Yes</data> - <data name="category/data/available_product_listing_config" xsi:type="string">Yes</data> - <data name="category/data/available_sort_by/sort_2" xsi:type="string">-</data> - <data name="category/data/available_sort_by/sort_1" xsi:type="string">-</data> - <data name="category/data/default_product_listing_config" xsi:type="string">No</data> - <data name="category/data/default_sort_by" xsi:type="string">Name</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm"/> - <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteCategoryInGrid"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryRedirect"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryPage"/> - </variation> - <variation name="UpdateCategoryEntityTestVariation2"> - <data name="category/data/parent_id/dataSet" xsi:type="string">default_category</data> - <data name="category/data/name" xsi:type="string">Name%isolation%</data> - <data name="category/data/is_active" xsi:type="string">Yes</data> - <data name="category/data/url_key" xsi:type="string">UrlKey%isolation%</data> - <data name="category/data/description" xsi:type="string">Category Description</data> - <data name="category/data/meta_title" xsi:type="string">Category Title</data> - <data name="category/data/include_in_menu" xsi:type="string">Yes</data> - <data name="category/data/available_product_listing_config" xsi:type="string">No</data> - <data name="category/data/available_sort_by/sort_2" xsi:type="string">Position</data> - <data name="category/data/available_sort_by/sort_1" xsi:type="string">Price</data> - <data name="category/data/default_product_listing_config" xsi:type="string">Yes</data> - <data name="category/data/default_sort_by" xsi:type="string">-</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm"/> - <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteCategoryInGrid"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryPage"/> - </variation> - <variation name="UpdateCategoryEntityTestVariation3"> - <data name="category/data/parent_id/dataSet" xsi:type="string">default_category</data> - <data name="category/data/name" xsi:type="string">Name%isolation%</data> - <data name="category/data/is_active" xsi:type="string">No</data> - <data name="category/data/url_key" xsi:type="string">-</data> - <data name="category/data/description" xsi:type="string">-</data> - <data name="category/data/meta_title" xsi:type="string">-</data> - <data name="category/data/include_in_menu" xsi:type="string">-</data> - <data name="category/data/available_product_listing_config" xsi:type="string">-</data> - <data name="category/data/available_sort_by/sort_2" xsi:type="string">-</data> - <data name="category/data/available_sort_by/sort_1" xsi:type="string">-</data> - <data name="category/data/default_product_listing_config" xsi:type="string">-</data> - <data name="category/data/default_sort_by" xsi:type="string">-</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm"/> - </variation> - </testCase> + <testCase name="Magento\Catalog\Test\TestCase\Category\UpdateCategoryEntityTest"> + <variation name="UpdateCategoryEntityTestVariation1"> + <data name="category/data/parent_id/dataSet" xsi:type="string">default_category</data> + <data name="category/data/name" xsi:type="string">Name%isolation%</data> + <data name="category/data/is_active" xsi:type="string">Yes</data> + <data name="category/data/url_key" xsi:type="string">UrlKey%isolation%</data> + <data name="category/data/include_in_menu" xsi:type="string">Yes</data> + <data name="category/data/available_product_listing_config" xsi:type="string">Yes</data> + <data name="category/data/default_product_listing_config" xsi:type="string">No</data> + <data name="category/data/default_sort_by" xsi:type="string">Name</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm" /> + <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteCategoryInGrid" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryRedirect" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryPage" /> + </variation> + <variation name="UpdateCategoryEntityTestVariation2"> + <data name="category/data/parent_id/dataSet" xsi:type="string">default_category</data> + <data name="category/data/name" xsi:type="string">Name%isolation%</data> + <data name="category/data/is_active" xsi:type="string">Yes</data> + <data name="category/data/url_key" xsi:type="string">UrlKey%isolation%</data> + <data name="category/data/description" xsi:type="string">Category Description</data> + <data name="category/data/meta_title" xsi:type="string">Category Title</data> + <data name="category/data/include_in_menu" xsi:type="string">Yes</data> + <data name="category/data/available_product_listing_config" xsi:type="string">No</data> + <data name="category/data/available_sort_by/sort_2" xsi:type="string">Position</data> + <data name="category/data/available_sort_by/sort_1" xsi:type="string">Price</data> + <data name="category/data/default_product_listing_config" xsi:type="string">Yes</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm" /> + <constraint name="Magento\UrlRewrite\Test\Constraint\AssertUrlRewriteCategoryInGrid" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryPage" /> + </variation> + <variation name="UpdateCategoryEntityTestVariation3"> + <data name="category/data/parent_id/dataSet" xsi:type="string">default_category</data> + <data name="category/data/name" xsi:type="string">Name%isolation%</data> + <data name="category/data/is_active" xsi:type="string">No</data> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategorySaveMessage" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertCategoryForm" /> + </variation> + </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml index 6bb452fe6914937f8757c249d68de9594c2454d0..e84f0409dada6c372eead7ef608a6adb8544f588 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml @@ -456,7 +456,7 @@ <data name="product/data/price/value" xsi:type="string">10</data> <data name="product/data/stock_data/manage_stock" xsi:type="string">Yes</data> <data name="product/data/stock_data/qty" xsi:type="string">1</data> - <data name="tag" xsi:type="string">test_type:acceptance_test, stable:no</data> + <data name="tag" xsi:type="string">test_type:acceptance_test</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductInCategory" /> </variation> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/NavigateUpSellProductsTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/NavigateUpSellProductsTest.php index b5d12d96c0d2b60fdd9629c9ef2a4a489c6f74a6..57d87b3147d82451f71b8324a310cae4db658327 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/NavigateUpSellProductsTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/NavigateUpSellProductsTest.php @@ -18,7 +18,7 @@ use Magento\Mtf\Fixture\InjectableFixture; * Steps: * 1. Navigate through up-sell products. * - * @ZephirId MAGETWO-12391 + * @ZephyrId MAGETWO-12391 * @group Up-sells_(MX) */ class NavigateUpSellProductsTest extends AbstractProductPromotedProductsTest diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.php index ae3394249f9324d1361b5cdfd508fd2c963cdd2b..396d177f80c0fdec006ff9e52afe5dd3b57f3b8f 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.php @@ -10,8 +10,6 @@ use Magento\Mtf\Fixture\FixtureFactory; use Magento\Mtf\TestCase\Scenario; /** - * Test Flow: - * * Preconditions: * 1. Create Product. * @@ -34,7 +32,6 @@ class CreateProductAttributeEntityFromProductPageTest extends Scenario /* tags */ const MVP = 'yes'; const DOMAIN = 'MX'; - const TO_MAINTAIN = 'yes'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.xml index 2a0d3215e00f39556df7101785673ee781987133..0236f7716289ef6a0ca0ec1fec079770c68f1462 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityFromProductPageTest.xml @@ -14,25 +14,23 @@ <data name="attribute/data/attribute_code" xsi:type="string">attr_text_%isolation%</data> <data name="attribute/data/is_global" xsi:type="string">Global</data> <data name="attribute/data/default_value_text" xsi:type="string"><b><i>default_value_text%isolation%</i></b></data> - <data name="attribute/data/default_value_textarea" xsi:type="string">-</data> <data name="attribute/data/is_unique" xsi:type="string">Yes</data> <data name="attribute/data/is_searchable" xsi:type="string">Yes</data> <data name="attribute/data/is_visible_in_advanced_search" xsi:type="string">Yes</data> <data name="attribute/data/is_comparable" xsi:type="string">Yes</data> - <data name="attribute/data/is_filterable_in_search" xsi:type="string">-</data> <data name="attribute/data/is_html_allowed_on_front" xsi:type="string">Yes</data> <data name="attribute/data/is_visible_on_front" xsi:type="string">Yes</data> <data name="attribute/data/used_for_sort_by" xsi:type="string">Yes</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeInGrid"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeForm"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeDisplayingOnSearchForm"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsGlobal"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeDisplayingOnFrontend"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeDisplayingOnSearchForm"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsComparable"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsHtmlAllowed"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsUsedInSortOnFrontend"/> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeInGrid" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeForm" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertAddedProductAttributeOnProductForm" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeDisplayingOnSearchForm" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsGlobal" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeDisplayingOnFrontend" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeDisplayingOnSearchForm" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsComparable" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsHtmlAllowed" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsUsedInSortOnFrontend" /> </variation> <variation name="CreateProductAttributeEntityFromProductPageTestVariation2"> <data name="attribute/data/frontend_label" xsi:type="string">Dropdown_Admin_%isolation%</data> @@ -41,12 +39,11 @@ <data name="attribute/data/is_required" xsi:type="string">No</data> <data name="attribute/data/attribute_code" xsi:type="string">attr_dropdown_%isolation%</data> <data name="attribute/data/is_global" xsi:type="string">Global</data> - <data name="attribute/data/is_unique" xsi:type="string">-</data> <data name="attribute/data/is_filterable" xsi:type="string">Filterable (with results)</data> <data name="attribute/data/is_filterable_in_search" xsi:type="string">Yes</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsFilterable"/> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsFilterableInSearch"/> - <constraint name="Magento\ConfigurableProduct\Test\Constraint\AssertProductAttributeIsConfigurable"/> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsFilterable" /> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsFilterableInSearch" /> + <constraint name="Magento\ConfigurableProduct\Test\Constraint\AssertProductAttributeIsConfigurable" /> </variation> <variation name="CreateProductAttributeEntityFromProductPageTestVariation3"> <data name="attribute/data/frontend_label" xsi:type="string">Text_Field_Admin_%isolation%</data> @@ -54,10 +51,7 @@ <data name="attribute/data/is_required" xsi:type="string">Yes</data> <data name="attribute/data/attribute_code" xsi:type="string">attr_text_%isolation%</data> <data name="attribute/data/default_value_text" xsi:type="string">default_value_text%isolation%</data> - <data name="attribute/data/default_value_textarea" xsi:type="string">-</data> - <data name="attribute/data/manage_frontend_label" xsi:type="string">-</data> - <data name="attribute/data/is_visible_in_advanced_search" xsi:type="string">-</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsRequired"/> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsRequired" /> </variation> <variation name="CreateProductAttributeEntityFromProductPageTestVariation4"> <data name="attribute/data/frontend_label" xsi:type="string">Text_Field_Admin_%isolation%</data> @@ -66,7 +60,7 @@ <data name="attribute/data/attribute_code" xsi:type="string">attr_text_%isolation%</data> <data name="attribute/data/default_value_text" xsi:type="string">default_value_text%isolation%</data> <data name="attribute/data/is_unique" xsi:type="string">Yes</data> - <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsUnique"/> + <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeIsUnique" /> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml index 0d8c49414fb80ba6fd05ed3c27f40f16fe79731f..cd482fba45140d4a24631d09b5add85bf5144294 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/CreateProductAttributeEntityTest.xml @@ -8,7 +8,6 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../vendor/magento/mtf/etc/variations.xsd"> <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\CreateProductAttributeEntityTest"> <variation name="CreateProductAttributeEntityTestVariation1"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="productTemplate/dataSet" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Text_Field_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Text Field</data> @@ -104,7 +103,6 @@ <constraint name="Magento\Catalog\Test\Constraint\AssertAttributeOptionsOnProductForm" /> </variation> <variation name="CreateProductAttributeEntityTestVariation6"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="productTemplate/dataSet" xsi:type="string">custom_attribute_set</data> <data name="productAttribute/data/frontend_label" xsi:type="string">Dropdown_Admin_%isolation%</data> <data name="productAttribute/data/frontend_input" xsi:type="string">Dropdown</data> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.php index d037ce350d9bd8485be0c71e8021be587aaf5720..b2803209bad71d700debd46f25397569d8f22cb5 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.php @@ -12,17 +12,16 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductAttributeNew; use Magento\Mtf\TestCase\Injectable; /** - * Test Creation for UpdateProductAttributeEntity - * * Preconditions: - * 1. Attribute is created + * 1. Attribute is created. + * * Test Flow: * 1. Log in as default admin user. - * 2. Go to Stores > Attributes > Product - * 3. Search product attribute in grid by given data - * 4. Click on the required product attribute - * 5. Click on the "Delete Attribute" button - * 6. Perform all assertions + * 2. Go to Stores > Attributes > Product. + * 3. Search product attribute in grid by given data. + * 4. Click on the required product attribute. + * 5. Click on the "Delete Attribute" button. + * 6. Perform all assertions. * * @group Product_Attributes_(MX) * @ZephyrId MAGETWO-24998 @@ -32,11 +31,10 @@ class DeleteProductAttributeEntityTest extends Injectable /* tags */ const MVP = 'yes'; const DOMAIN = 'MX'; - const STABLE = 'no'; /* end tags */ /** - * Run DeleteProductAttributeEntity test + * Run DeleteProductAttributeEntity test. * * @param CatalogProductAttribute $attribute * @param CatalogProductAttributeIndex $attributeIndex @@ -51,12 +49,9 @@ class DeleteProductAttributeEntityTest extends Injectable //Precondition $attribute->persist(); - $filter = [ - 'frontend_label' => $attribute->getFrontendLabel(), - ]; //Steps $attributeIndex->open(); - $attributeIndex->getGrid()->searchAndOpen($filter); + $attributeIndex->getGrid()->searchAndOpen(['frontend_label' => $attribute->getFrontendLabel()]); $attributeNew->getPageActions()->delete(); } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml index 9c1369bf8e710dd2ae17e039eb657392d6958381..fcd45cbf6b0fa3248290f18f3e2fbe1e369c0427 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/ProductAttribute/DeleteProductAttributeEntityTest.xml @@ -9,7 +9,6 @@ <testCase name="Magento\Catalog\Test\TestCase\ProductAttribute\DeleteProductAttributeEntityTest"> <variation name="DeleteProductAttributeEntityTestVariation1"> <data name="attribute/dataSet" xsi:type="string">attribute_type_text_field</data> - <data name="isRequired" xsi:type="string">Yes</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeSuccessDeleteMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeAbsenceInGrid" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeAbsenceInSearchOnProductForm" /> @@ -17,7 +16,6 @@ </variation> <variation name="DeleteProductAttributeEntityTestVariation2"> <data name="attribute/dataSet" xsi:type="string">attribute_type_dropdown</data> - <data name="isRequired" xsi:type="string">No</data> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeSuccessDeleteMessage" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeAbsenceInGrid" /> <constraint name="Magento\Catalog\Test\Constraint\AssertProductAttributeAbsenceInSearchOnProductForm" /> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml index 03b98fec16ca5f434e972fa72235802de695bec3..4e02d8c777cdae0624fb21d771f32920a66a3c69 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml @@ -6,22 +6,22 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/TestCase/etc/testcase.xsd"> - <scenario name="CreateProductAttributeEntityFromProductPageTest" firstStep="openProductOnBackend"> - <step name="openProductOnBackend" module="Magento_Catalog" next="addNewAttributeFromProductPage"/> - <step name="addNewAttributeFromProductPage" module="Magento_Catalog" next="fillAttributeFormOnProductPage"> - <item name="tabName" value="product-details"/> - </step> - <step name="fillAttributeFormOnProductPage" module="Magento_Catalog" next="saveAttributeOnProductPage"/> - <step name="saveAttributeOnProductPage" module="Magento_Catalog" next="setDefaultAttributeValue"/> - <step name="setDefaultAttributeValue" module="Magento_Catalog" next="saveProduct"/> - <step name="saveProduct" module="Magento_Catalog"/> - </scenario> - <scenario name="CreateProductAttributeEntityTest" firstStep="createProductTemplate"> - <step name="createProductTemplate" module="Magento_Catalog" next="openProductAttributesPage"/> - <step name="openProductAttributesPage" module="Magento_Catalog" next="addNewAttribute"/> - <step name="addNewAttribute" module="Magento_Catalog" next="fillAttributeForm"/> - <step name="fillAttributeForm" module="Magento_Catalog" next="saveAttribute"/> - <step name="saveAttribute" module="Magento_Catalog" next="addAttributeToProductTemplate"/> - <step name="addAttributeToProductTemplate" module="Magento_Catalog"/> - </scenario> + <scenario name="CreateProductAttributeEntityFromProductPageTest" firstStep="openProductOnBackend"> + <step name="openProductOnBackend" module="Magento_Catalog" next="addNewAttributeFromProductPage"/> + <step name="addNewAttributeFromProductPage" module="Magento_Catalog" next="fillAttributeFormOnProductPage"> + <item name="tabName" value="product-details"/> + </step> + <step name="fillAttributeFormOnProductPage" module="Magento_Catalog" next="saveAttributeOnProductPage"/> + <step name="saveAttributeOnProductPage" module="Magento_Catalog" next="setDefaultAttributeValue"/> + <step name="setDefaultAttributeValue" module="Magento_Catalog" next="saveProduct"/> + <step name="saveProduct" module="Magento_Catalog"/> + </scenario> + <scenario name="CreateProductAttributeEntityTest" firstStep="createProductTemplate"> + <step name="createProductTemplate" module="Magento_Catalog" next="openProductAttributesPage"/> + <step name="openProductAttributesPage" module="Magento_Catalog" next="addNewAttribute"/> + <step name="addNewAttribute" module="Magento_Catalog" next="fillAttributeForm"/> + <step name="fillAttributeForm" module="Magento_Catalog" next="saveAttribute"/> + <step name="saveAttribute" module="Magento_Catalog" next="addAttributeToProductTemplate"/> + <step name="addAttributeToProductTemplate" module="Magento_Catalog"/> + </scenario> </config> diff --git a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogRuleTest.php b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogRuleTest.php index 5944e457a3549973457e82da91ced553de34ad55..e09819c8e64a3b3c7bb80492d06814673d925e89 100644 --- a/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogRuleTest.php +++ b/dev/tests/functional/tests/app/Magento/CatalogRule/Test/TestCase/CreateCatalogRuleTest.php @@ -23,7 +23,7 @@ use Magento\Customer\Test\Fixture\CustomerGroup; * 8. Clear cache. * 9. Perform all assertions. * - * @ticketId MAGETWO-23036 + * @ZephyrId MAGETWO-23036 */ class CreateCatalogRuleTest extends AbstractCatalogRuleEntityTest { diff --git a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Multishipping/MultishippingAgreementReview.php b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Multishipping/MultishippingAgreementReview.php index cbc6a610b231ae9d1f9d85efdd8ec6e445bc6ae4..f49d6f3939a1b67aef1561f3d0153854ea59b804 100644 --- a/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Multishipping/MultishippingAgreementReview.php +++ b/dev/tests/functional/tests/app/Magento/CheckoutAgreements/Test/Block/Multishipping/MultishippingAgreementReview.php @@ -3,14 +3,70 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\CheckoutAgreements\Test\Block\Multishipping; -use Magento\CheckoutAgreements\Test\Block\Onepage\AgreementReview; +use \Magento\Multishipping\Test\Block\Checkout\Overview; +use Magento\CheckoutAgreements\Test\Fixture\CheckoutAgreement; +use Magento\Mtf\Client\Locator; /** - * Multiple addresses checkout order review block. + * Class MultishippingAgreementReview + * Multiple page checkout order review block */ -class MultishippingAgreementReview extends AgreementReview +class MultishippingAgreementReview extends Overview { - // + /** + * Notification agreements locator + * + * @var string + */ + protected $notification = 'div.mage-error'; + + /** + * Agreement locator + * + * @var string + */ + protected $agreement = './/div[contains(@id, "checkout-review-submit")]//label[.="%s"]'; + + /** + * Agreement checkbox locator + * + * @var string + */ + protected $agreementCheckbox = 'input[name^=agreement]'; + + /** + * Get notification massage + * + * @return string + */ + public function getNotificationMassage() + { + return $this->_rootElement->find($this->notification)->getText(); + } + + /** + * Set agreement + * + * @param string $value + * @return void + */ + public function setAgreement($value) + { + $this->_rootElement->find($this->agreementCheckbox, Locator::SELECTOR_CSS, 'checkbox')->setValue($value); + } + + /** + * Check agreement + * + * @param CheckoutAgreement $agreement + * @return bool + */ + public function checkAgreement(CheckoutAgreement $agreement) + { + return $this->_rootElement + ->find(sprintf($this->agreement, $agreement->getCheckboxText()), Locator::SELECTOR_XPATH)->isVisible(); + } } diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Grid.php b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Grid.php index e2e0547c443093b53517719cb27c73e3e6fa9cda..4188aef15cd0565a483f3a08e31fdaf7156cd429 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Grid.php +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Block/Adminhtml/Page/Grid.php @@ -81,9 +81,29 @@ class Grid extends DataGrid $rowItem = $this->_rootElement->find($this->rowItem); if ($rowItem->isVisible()) { $rowItem->find($this->previewCmsPage)->click(); - $this->waitForElement(); } else { throw new \Exception('Searched item was not found.'); } } + + /** + * Wait loader. + * + * @return void + */ + protected function waitLoader() + { + try { + $browser = $this->browser; + $selector = $this->loader; + $browser->waitUntil( + function () use ($browser, $selector) { + return $browser->find($selector)->isVisible() == true ? true : null; + } + ); + } catch (\Exception $e) { + } + + parent::waitLoader(); + } } diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsBlock.xml b/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsBlock.xml index 5d1a718ff1178b9a4737c8bbcc3df08f9e79accf..746165d67c89a7210ccc56a3e065f581fff90a75 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsBlock.xml +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/Fixture/CmsBlock.xml @@ -7,7 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd"> <fixture name="cmsBlock" module="Magento_Cms" type="flat" entity_type="cms_block" collection="Magento\Cms\Model\Resource\Block\Grid\Collection" identifier="identifier" - handler_interface="Magento\Cms\Test\Handler\CmsBlock\CmsBlockInterface" class="Magento\Cms\Test\Fixture\CmsBlock"> + handler_interface="Magento\Cms\Test\Handler\CmsBlock\CmsBlockInterface" repository_class="Magento\Cms\Test\Repository\CmsBlock" class="Magento\Cms\Test\Fixture\CmsBlock"> <dataset name="default"> <field name="title" xsi:type="string">block_%isolation%</field> <field name="identifier" xsi:type="string">identifier_%isolation%</field> diff --git a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/CreateCmsPageEntityTest.php b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/CreateCmsPageEntityTest.php index ef198391835920bc6da6304783938d70a4bb1eaa..60e0ea23b8526546d7ef2dca4f1d92a7c870c99b 100644 --- a/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/CreateCmsPageEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Cms/Test/TestCase/CreateCmsPageEntityTest.php @@ -30,7 +30,6 @@ class CreateCmsPageEntityTest extends Injectable const DOMAIN = 'PS'; const TEST_TYPE = 'acceptance_test'; const TO_MAINTAIN = 'yes'; - const STABLE = 'no'; /* end tags */ /** @@ -71,6 +70,8 @@ class CreateCmsPageEntityTest extends Injectable // Steps $this->cmsIndex->open(); $this->cmsIndex->getPageActionsBlock()->addNew(); + //TODO: remove cms page new refresh after resolve issue with static js files publication (MAGETWO-37898) + $this->cmsPageNew->open(); $this->cmsPageNew->getPageForm()->fill($cms); $this->cmsPageNew->getPageMainActions()->save(); } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute/AttributeSelector.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute/AttributeSelector.php index 7fac90081181236c028ba2a8af2c5c103a820fa9..d3c32d608a143ce63212eef08da97c7df4372a93 100755 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute/AttributeSelector.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Super/Config/Attribute/AttributeSelector.php @@ -10,13 +10,29 @@ use Magento\Mtf\Client\Element\SuggestElement; use Magento\Catalog\Test\Fixture\CatalogProductAttribute; /** - * Class AttributeSelector - * Form Attribute Search on Product page + * Form Attribute Search on Product page. */ class AttributeSelector extends SuggestElement { /** - * Checking exist configurable attribute in search result + * Wait for search result is visible. + * + * @return void + */ + public function waitResult() + { + $browser = $this; + $selector = $this->searchResult; + $browser->waitUntil( + function () use ($browser, $selector) { + $element = $browser->find($selector); + return $element->isVisible() ? true : null; + } + ); + } + + /** + * Checking exist configurable attribute in search result. * * @param CatalogProductAttribute $productAttribute * @return bool diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php index 9c1d9b988ed215b235da978bd414f59422be0d52..e088a33cf703d48927bed5a0bcb4ca8597713438 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php @@ -20,7 +20,6 @@ class AssertProductAttributeIsConfigurable extends AbstractConstraint /** * Assert check whether the attribute is used to create a configurable products. * - * @param CatalogProductAttribute $productAttribute * @param CatalogProductAttribute $attribute * @param CatalogProductIndex $productGrid * @param CatalogProductNew $newProductPage @@ -28,20 +27,17 @@ class AssertProductAttributeIsConfigurable extends AbstractConstraint public function processAssert( CatalogProductAttribute $attribute, CatalogProductIndex $productGrid, - CatalogProductNew $newProductPage, - CatalogProductAttribute $productAttribute = null + CatalogProductNew $newProductPage ) { - $attributeSearch = $productAttribute === null ? $attribute : $productAttribute; $productGrid->open(); $productGrid->getGridPageActionBlock()->addProduct('configurable'); $productBlockForm = $newProductPage->getProductForm(); $productBlockForm->openTab('variations'); - /** @var TabVariation $tabVariation */ $tabVariation = $productBlockForm->getTab('variations'); $configurableAttributeSelector = $tabVariation->getAttributeBlock()->getAttributeSelector(); \PHPUnit_Framework_Assert::assertTrue( - $configurableAttributeSelector->isExistAttributeInSearchResult($attributeSearch), + $configurableAttributeSelector->isExistAttributeInSearchResult($attribute), "Product attribute is absent on the product page." ); } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/di.xml index 543f1f6f41768afc03868bc78364c119a0413a8c..fa0df04101e3a2fb4f430bdf917855473588a473 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/di.xml @@ -6,24 +6,24 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> - <type name="Magento\ConfigurableProduct\Test\Constraint\AssertConfigurableProductDuplicateForm"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\ConfigurableProduct\Test\Constraint\AssertChildProductIsNotDisplayedSeparately"> - <arguments> - <argument name="severity" xsi:type="string">middle</argument> - </arguments> - </type> - <type name="Magento\ConfigurableProduct\Test\Constraint\AssertConfigurableProductPage"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\ConfigurableProduct\Test\Constraint\AssertProductAttributeIsConfigurable"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> + <type name="Magento\ConfigurableProduct\Test\Constraint\AssertConfigurableProductDuplicateForm"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\ConfigurableProduct\Test\Constraint\AssertChildProductIsNotDisplayedSeparately"> + <arguments> + <argument name="severity" xsi:type="string">middle</argument> + </arguments> + </type> + <type name="Magento\ConfigurableProduct\Test\Constraint\AssertConfigurableProductPage"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\ConfigurableProduct\Test\Constraint\AssertProductAttributeIsConfigurable"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> </config> diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php index fb1030c3143f16e5496bd47354f74826ed2c457c..a13c263aeab7fe4db7e475dc11ee6f668fbfe4a8 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/Handler/Customer/Curl.php @@ -98,7 +98,7 @@ class Curl extends AbstractCurl implements CustomerInterface $response = $curl->read(); $curl->close(); // After caching My Account page we cannot check by success message - if (!strpos($response, 'customer/account/logout')) { + if (!strpos($response, 'block-dashboard-info')) { throw new \Exception("Customer entity creating by curl handler was not successful! Response: $response"); } diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest.php index d5e4eb857f2d3803b3e9829df79c8111f7010f05..3cd1876a43225f763729773bb7df430b872236d3 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerBackendEntityTest.php @@ -21,7 +21,7 @@ use Magento\Customer\Test\Page\Adminhtml\CustomerIndexNew; * 5. Click "Save Customer" button. * 6. Perform all assertions. * - * @ticketId MAGETWO-23424 + * @ZephyrId MAGETWO-23424 */ class CreateCustomerBackendEntityTest extends Injectable { diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerAddressTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerAddressTest.php index c9dc9642b47e76b0bbd70200ca0f945b54f6a240..31174f91a34960e195e469f1c6e3e795b7a41c98 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerAddressTest.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerAddressTest.php @@ -60,7 +60,6 @@ class DeleteCustomerAddressTest extends Injectable */ public function test(Customer $customer) { - $this->markTestIncomplete('Bug: MAGETWO-34634'); // Precondition: $customer->persist(); $addressToDelete = $customer->getDataFieldConfig('address')['source']->getAddresses()[1]; diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.php index 1e2eebf2720782e74cc943280e3ce918d330846d..11dd9feb3fc865fa51d957511cf089f2df2aa599 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerBackendEntityTest.php @@ -23,7 +23,7 @@ use Magento\Mtf\TestCase\Injectable; * 5. Click 'Save' button * 6. Perform all assertions * - * @ticketId MAGETWO-23881 + * @ZephyrId MAGETWO-23881 */ class UpdateCustomerBackendEntityTest extends Injectable { diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestStep/LogoutCustomerOnFrontendStep.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestStep/LogoutCustomerOnFrontendStep.php index 21a17180e7e0fac2b637abca11a85cc7f9d2ba8a..5a441a09bccec36068cb2efc51e23a0497296756 100644 --- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestStep/LogoutCustomerOnFrontendStep.php +++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestStep/LogoutCustomerOnFrontendStep.php @@ -52,19 +52,12 @@ class LogoutCustomerOnFrontendStep implements TestStepInterface */ public function run() { - /* @TODO: MAGETWO-37391 - * $this->cmsIndex->open(); - * $this->cmsIndex->getCmsPageBlock()->waitPageInit(); - * if ($this->cmsIndex->getLinksBlock()->isLinkVisible("Log Out")) { - * $this->cmsIndex->getLinksBlock()->openLink("Log Out"); - * $this->cmsIndex->getCmsPageBlock()->waitUntilTextIsVisible('Home Page'); - * $this->cmsIndex->getCmsPageBlock()->waitPageInit(); - * } - */ - $this->customerAccountLogout->open(); - if (self::LOGOUT_PAGE_TITLE == $this->cmsIndex->getCmsPageBlock()->getPageTitle()) { + $this->cmsIndex->open(); + $this->cmsIndex->getCmsPageBlock()->waitPageInit(); + if ($this->cmsIndex->getLinksBlock()->isLinkVisible("Log Out")) { + $this->cmsIndex->getLinksBlock()->openLink("Log Out"); $this->cmsIndex->getCmsPageBlock()->waitUntilTextIsVisible('Home Page'); + $this->cmsIndex->getCmsPageBlock()->waitPageInit(); } - $this->cmsIndex->getCmsPageBlock()->waitPageInit(); } } diff --git a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedProductInCustomerWishlistOnBackendGrid.php b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedProductInCustomerWishlistOnBackendGrid.php index b9b255d09090a209b23333e307addd2081a79af8..988851b55506bda689b84c2eab65ae4e6079653a 100644 --- a/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedProductInCustomerWishlistOnBackendGrid.php +++ b/dev/tests/functional/tests/app/Magento/GroupedProduct/Test/Constraint/AssertGroupedProductInCustomerWishlistOnBackendGrid.php @@ -26,7 +26,7 @@ class AssertGroupedProductInCustomerWishlistOnBackendGrid extends AssertProductI { $options = $this->prepareOptions($product); - return ['product_name' => $product->getName(), 'qty_from' => 1, 'qty_to' => 1, 'options' => $options]; + return ['product_name' => $product->getName(), 'options' => $options]; } /** diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/Edit/IntegrationForm.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/Edit/IntegrationForm.php index 2d2daa83b7be69994149e5cb37ab085fa3f90aa4..875cf0fefabefcef82b3fd9cb916ca6c6ed36b80 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/Edit/IntegrationForm.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/Edit/IntegrationForm.php @@ -9,7 +9,6 @@ namespace Magento\Integration\Test\Block\Adminhtml\Integration\Edit; use Magento\Backend\Test\Block\Widget\FormTabs; /** - * Class IntegrationForm * Integration form block. */ class IntegrationForm extends FormTabs diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/ResourcesPopup.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/ResourcesPopup.php index 53baa08c1e2811116c08e4bc6f98c62f370494e7..9c25994a869647e89195d2c271c6adb4839318b7 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/ResourcesPopup.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Block/Adminhtml/Integration/IntegrationGrid/ResourcesPopup.php @@ -11,9 +11,9 @@ use Magento\Mtf\Block\Form; use Magento\Mtf\Block\Mapper; use Magento\Mtf\Client\BrowserInterface; use Magento\Mtf\Client\Element\SimpleElement; +use Magento\Mtf\Client\Locator; /** - * Class ResourcesPopup * Integration resources popup container. */ class ResourcesPopup extends Form @@ -39,6 +39,13 @@ class ResourcesPopup extends Form */ protected $content = '#integrations-activate-permissions-content'; + /** + * Css selector for tree element. + * + * @var string + */ + protected $tree = '[data-role="tree-resources-container"]'; + /** * @constructor * @param SimpleElement $element @@ -91,4 +98,15 @@ class ResourcesPopup extends Form { $this->_rootElement->find($this->reauthorizeButtonSelector)->click(); } + + /** + * Get tree structure for selected nodes. + * + * @param int|null $level + * @return array + */ + public function getStructure($level = null) + { + return $this->_rootElement->find($this->tree, Locator::SELECTOR_CSS, 'jquerytree')->getStructure($level); + } } diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationForm.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationForm.php index 2e949b489436315e8c8f459b4ea5213eda7febed..5877e316a5a60b218c83933098a246802f4d36f3 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationForm.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationForm.php @@ -12,13 +12,12 @@ use Magento\Integration\Test\Page\Adminhtml\IntegrationNew; use Magento\Mtf\Constraint\AbstractAssertForm; /** - * Class AssertIntegrationForm - * Assert that integration form filled correctly + * Assert that integration form filled correctly. */ class AssertIntegrationForm extends AbstractAssertForm { /** - * Skipped fields while verifying + * Skipped fields while verifying. * * @var array */ @@ -27,20 +26,37 @@ class AssertIntegrationForm extends AbstractAssertForm ]; /** - * Assert that integration form filled correctly + * Pattern for error message. + * + * @var string + */ + protected $errorMessagePattern = "Data in '%s' field not equal.\nExpected: %s\nActual: %s"; + + /** + * Flag for strict verify resources data. + * + * @var bool + */ + protected $strictResourcesVerify; + + /** + * Assert that integration form filled correctly. * * @param IntegrationIndex $integrationIndexPage * @param IntegrationNew $integrationNewPage * @param Integration $integration * @param Integration|null $initialIntegration + * @param bool $strictResourcesVerify [optional] * @return void */ public function processAssert( IntegrationIndex $integrationIndexPage, IntegrationNew $integrationNewPage, Integration $integration, - Integration $initialIntegration = null + Integration $initialIntegration = null, + $strictResourcesVerify = false ) { + $this->strictResourcesVerify = $strictResourcesVerify; $data = ($initialIntegration === null) ? $integration->getData() : array_merge($initialIntegration->getData(), $integration->getData()); @@ -60,44 +76,25 @@ class AssertIntegrationForm extends AbstractAssertForm } /** - * Verifying that form is filled correctly + * Verifying that form is filled correctly. * * @param array $formData * @param array $fixtureData - * @return array $errorMessages - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @return array */ protected function verifyForm(array $formData, array $fixtureData) { - $issetResources = []; $errorMessages = []; - $errorMessage = "Data in '%s' field not equal.\nExpected: %s\nActual: %s"; - foreach ($fixtureData as $key => $value) { if (in_array($key, $this->skippedFields)) { continue; - } - if ($key === 'resources') { - $fixtureData[$key] = is_array($fixtureData[$key]) ? $fixtureData[$key] : [$fixtureData[$key]]; - foreach ($fixtureData[$key] as $fixtureResource) { - foreach ($formData[$key] as $formResource) { - if (preg_match('|^' . preg_quote($fixtureResource) . '|', $formResource)) { - $issetResources[] = $formResource; - } - } - } - $diff = array_diff($formData[$key], $issetResources); - if (!empty($diff)) { - $errorMessages[] = sprintf( - $errorMessage, - $key, - implode(",\n", $fixtureData[$key]), - implode(",\n", $formData[$key]) - ); - } + } elseif ($key === 'resources') { + $errorMessages = array_merge( + $errorMessages, + $this->checkResources($formData[$key], $fixtureData[$key]) + ); } elseif ($value !== $formData[$key]) { - $errorMessages[] = sprintf($errorMessage, $key, $value, $formData[$key]); + $errorMessages[] = $this->getErrorMessage($value, $formData[$key], $key); } } @@ -105,7 +102,72 @@ class AssertIntegrationForm extends AbstractAssertForm } /** - * Returns a string representation of successful assertion + * Check resources errors. + * + * @param array $formData + * @param array|string $fixtureData + * @return array + */ + protected function checkResources(array $formData, $fixtureData) + { + $errorMessages = []; + $diff = $this->getResourcesDifferentData($formData, $fixtureData); + if (array_filter($diff)) { + $errorMessages[] = $this->getErrorMessage($fixtureData, $formData, 'resources'); + } + + return $errorMessages; + } + + /** + * Get different data between form and fixture data. + * + * @param array $formData + * @param array|string $fixtureData + * @return array + */ + protected function getResourcesDifferentData(array $formData, $fixtureData) + { + $fixtureData = is_array($fixtureData) ? $fixtureData : [$fixtureData]; + return $this->strictResourcesVerify + ? array_diff($formData, $fixtureData) + : $this->notStrictVerification($formData, $fixtureData); + } + + /** + * Not strict verify resources data. + * + * @param array $formData + * @param array $fixtureData + * @return array + */ + protected function notStrictVerification(array $formData, array $fixtureData) + { + $diff = []; + foreach ($fixtureData as $itemData) { + $diff[] = in_array($itemData, $formData) ? null : true; + } + + return $diff; + } + + /** + * Get error message. + * + * @param mixed $fixtureData + * @param mixed $formData + * @param mixed $field + * @return string + */ + protected function getErrorMessage($fixtureData, $formData, $field) + { + $fixtureData = is_array($fixtureData) ? $this->arrayToString($fixtureData) : $fixtureData; + $formData = is_array($formData) ? $this->arrayToString($formData) : $formData; + return sprintf($this->errorMessagePattern, $field, $fixtureData, $formData); + } + + /** + * Returns a string representation of successful assertion. * * @return string */ diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationResourcesPopup.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationResourcesPopup.php index 90f5f099fb3ea14f6948afb009be3efb9fb4a76c..77a018862ef999c0ad941bb2831f3d60ae76fc24 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationResourcesPopup.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationResourcesPopup.php @@ -11,26 +11,26 @@ use Magento\Integration\Test\Page\Adminhtml\IntegrationIndex; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertIntegrationResourcesPopup - * Assert that pop-up with resources are shown after starting activation + * Assert that pop-up with resources are shown after starting activation. */ class AssertIntegrationResourcesPopup extends AbstractConstraint { /** * Assert that pop-up with resources, that were specified for integration are shown - * after starting activation of integration + * after starting activation of integration. * * @param IntegrationIndex $integrationIndex * @param Integration $integration + * @param int|null $resourceDepth * @return void */ - public function processAssert(IntegrationIndex $integrationIndex, Integration $integration) + public function processAssert(IntegrationIndex $integrationIndex, Integration $integration, $resourceDepth = null) { $fixtureResources = is_array($integration->getResources()) ? $integration->getResources() : [$integration->getResources()]; - $formResources = $integrationIndex->getIntegrationGrid()->getResourcesPopup()->getData(); - $result = $this->verifyResources($formResources['resources'], $fixtureResources); + $formResources = $integrationIndex->getIntegrationGrid()->getResourcesPopup()->getStructure($resourceDepth); + $result = $this->verifyResources($formResources, $fixtureResources); \PHPUnit_Framework_Assert::assertEmpty( $result, "Integration resources is not correct.\nLog:\n" . $result @@ -39,7 +39,7 @@ class AssertIntegrationResourcesPopup extends AbstractConstraint } /** - * Verify that resources are correct + * Verify that resources are correct. * * @param array $formResources * @param array $fixtureResources @@ -70,7 +70,7 @@ class AssertIntegrationResourcesPopup extends AbstractConstraint } /** - * Returns a string representation of successful assertion + * Returns a string representation of successful assertion. * * @return string */ diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationTokensPopup.php b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationTokensPopup.php index 79af964f4ecff561e3e7a75144bffdffc880c8d5..8e4ecc80dcf28c9480e1018cab7b32020356db9f 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationTokensPopup.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/Constraint/AssertIntegrationTokensPopup.php @@ -10,7 +10,6 @@ use Magento\Integration\Test\Page\Adminhtml\IntegrationIndex; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertIntegrationTokensPopup * Assert that pop-up with tokens is shown after clicking on "Allow" button on Resources popup. */ class AssertIntegrationTokensPopup extends AbstractConstraint @@ -20,7 +19,7 @@ class AssertIntegrationTokensPopup extends AbstractConstraint /* end tags */ /** - * Fields to be checked + * Fields to be checked. * * @var array */ @@ -65,7 +64,7 @@ class AssertIntegrationTokensPopup extends AbstractConstraint } /** - * Returns a string representation of successful assertion + * Returns a string representation of successful assertion. * * @return string */ diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ActivateIntegrationEntityTest.php b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ActivateIntegrationEntityTest.php index caf67686a3604ff01447238c7ed9fab3a68e3b60..3e298c97a8a1c9cb450cb8ca6d10892ef7e2ef35 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ActivateIntegrationEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ActivateIntegrationEntityTest.php @@ -11,15 +11,12 @@ use Magento\Integration\Test\Page\Adminhtml\IntegrationIndex; use Magento\Mtf\TestCase\Injectable; /** - * Test Creation for Activate Integration Entity - * - * Test Flow: * Preconditions: - * 1. Integration is created + * 1. Integration is created. * * Steps: * 1. Log in to backend as admin user. - * 2. Navigate to System > Extensions > Integrations + * 2. Navigate to System > Extensions > Integrations. * 3. Click on the "Activate" link near required integration. * 4. Perform all assertions. * @@ -34,14 +31,14 @@ class ActivateIntegrationEntityTest extends Injectable /* end tags */ /** - * Integration grid page + * Integration grid page. * * @var IntegrationIndex */ protected $integrationIndexPage; /** - * Injection data + * Injection data. * * @param IntegrationIndex $integrationIndex * @return void @@ -52,7 +49,7 @@ class ActivateIntegrationEntityTest extends Injectable } /** - * Activate Integration Entity Test + * Activate Integration Entity Test. * * @param Integration $integration * @return void diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ActivateIntegrationEntityTest.xml b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ActivateIntegrationEntityTest.xml index d12ebb768f9e832bf296bacc687148f72db8d2ee..b77b66906a0c89cae9dd9e43e2e2c8ac94d626d8 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ActivateIntegrationEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ActivateIntegrationEntityTest.xml @@ -6,12 +6,13 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> - <testCase name="Magento\Integration\Test\TestCase\ActivateIntegrationEntityTest"> - <variation name="ActivateIntegrationEntityTestVariation1"> - <data name="integration/dataSet" xsi:type="string">default_with_all_resources</data> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationResourcesPopup"/> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationTokensPopup"/> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationSuccessActivationMessage"/> - </variation> - </testCase> + <testCase name="Magento\Integration\Test\TestCase\ActivateIntegrationEntityTest"> + <variation name="ActivateIntegrationEntityTestVariation1"> + <data name="integration/dataSet" xsi:type="string">default_with_all_resources</data> + <data name="resourceDepth" xsi:type="number">1</data> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationResourcesPopup"/> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationTokensPopup"/> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationSuccessActivationMessage"/> + </variation> + </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/CreateIntegrationEntityTest.php b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/CreateIntegrationEntityTest.php index 2056ea6a9c7bb1e957ae4e3d5cab0bd14271a2d1..b57e65919f29f589e3c11e43f56310958d2994ab 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/CreateIntegrationEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/CreateIntegrationEntityTest.php @@ -12,12 +12,9 @@ use Magento\Integration\Test\Page\Adminhtml\IntegrationNew; use Magento\Mtf\TestCase\Injectable; /** - * Test Creation for Create Integration Entity - * - * Test Flow: * Steps: * 1. Log in to backend as admin user. - * 2. Navigate to System > Extensions > Integrations + * 2. Navigate to System > Extensions > Integrations. * 3. Start to create new Integration. * 4. Fill in all data according to data set. * 5. Click "Save" button. @@ -34,21 +31,21 @@ class CreateIntegrationEntityTest extends Injectable /* end tags */ /** - * Integration grid page + * Integration grid page. * * @var IntegrationIndex */ protected $integrationIndexPage; /** - * Integration new page + * Integration new page. * * @var IntegrationNew */ protected $integrationNewPage; /** - * Injection data + * Injection data. * * @param IntegrationIndex $integrationIndex * @param IntegrationNew $integrationNew @@ -61,7 +58,7 @@ class CreateIntegrationEntityTest extends Injectable } /** - * Create Integration Entity test + * Create Integration Entity test. * * @param Integration $integration * @return void diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/CreateIntegrationEntityTest.xml b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/CreateIntegrationEntityTest.xml index 3e90685115e0ae4c2ffeee24e9d8676e54b7ccdb..de7d90dc329c35d2f6ed30551eb1a8b25d8bc70c 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/CreateIntegrationEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/CreateIntegrationEntityTest.xml @@ -6,39 +6,32 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> - <testCase name="Magento\Integration\Test\TestCase\CreateIntegrationEntityTest"> - <variation name="CreateIntegrationEntityTestVariation1"> - <data name="integration/data/name" xsi:type="string">Integration%isolation%</data> - <data name="integration/data/email" xsi:type="string">test@example.com</data> - <data name="integration/data/endpoint" xsi:type="string">https://endpoint.com</data> - <data name="integration/data/identity_link_url" xsi:type="string">https://testlink.com</data> - <data name="integration/data/resource_access" xsi:type="string">All</data> - <data name="integration/data/resources" xsi:type="string">-</data> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationSuccessSaveMessage"/> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationForm"/> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationInGrid"/> - </variation> - <variation name="CreateIntegrationEntityTestVariation2"> - <data name="integration/data/name" xsi:type="string">Integration%isolation%</data> - <data name="integration/data/email" xsi:type="string">-</data> - <data name="integration/data/endpoint" xsi:type="string">-</data> - <data name="integration/data/identity_link_url" xsi:type="string">-</data> - <data name="integration/data/resource_access" xsi:type="string">Custom</data> - <data name="integration/data/resources" xsi:type="string">Sales</data> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationSuccessSaveMessage"/> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationForm"/> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationInGrid"/> - </variation> - <variation name="CreateIntegrationEntityTestVariation3"> - <data name="integration/data/name" xsi:type="string">Integration%isolation%</data> - <data name="integration/data/email" xsi:type="string">-</data> - <data name="integration/data/endpoint" xsi:type="string">-</data> - <data name="integration/data/identity_link_url" xsi:type="string">-</data> - <data name="integration/data/resource_access" xsi:type="string">All</data> - <data name="integration/data/resources" xsi:type="string">-</data> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationSuccessSaveMessage"/> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationForm"/> - <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationInGrid"/> - </variation> - </testCase> + <testCase name="Magento\Integration\Test\TestCase\CreateIntegrationEntityTest"> + <variation name="CreateIntegrationEntityTestVariation1"> + <data name="integration/data/name" xsi:type="string">Integration%isolation%</data> + <data name="integration/data/email" xsi:type="string">test@example.com</data> + <data name="integration/data/endpoint" xsi:type="string">https://endpoint.com</data> + <data name="integration/data/identity_link_url" xsi:type="string">https://testlink.com</data> + <data name="integration/data/resource_access" xsi:type="string">All</data> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationSuccessSaveMessage" /> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationForm" /> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationInGrid" /> + </variation> + <variation name="CreateIntegrationEntityTestVariation2"> + <data name="integration/data/name" xsi:type="string">Integration%isolation%</data> + <data name="integration/data/resource_access" xsi:type="string">Custom</data> + <data name="integration/data/resources" xsi:type="string">Sales/Operations/Invoices</data> + <data name="strictResourcesVerify" xsi:type="boolean">false</data> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationSuccessSaveMessage" /> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationForm" /> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationInGrid" /> + </variation> + <variation name="CreateIntegrationEntityTestVariation3"> + <data name="integration/data/name" xsi:type="string">Integration%isolation%</data> + <data name="integration/data/resource_access" xsi:type="string">All</data> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationSuccessSaveMessage" /> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationForm" /> + <constraint name="Magento\Integration\Test\Constraint\AssertIntegrationInGrid" /> + </variation> + </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/DeleteIntegrationEntityTest.php b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/DeleteIntegrationEntityTest.php index d1cbf03eaecd41730831dad4dcd4df1f56b947d0..fc8f6fc2a2ddf7e8e93562ee829f05a7cd5c9024 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/DeleteIntegrationEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/DeleteIntegrationEntityTest.php @@ -11,16 +11,13 @@ use Magento\Integration\Test\Page\Adminhtml\IntegrationIndex; use Magento\Mtf\TestCase\Injectable; /** - * Test Creation for Delete Integration Entity - * - * Test Flow: * Preconditions: - * 1. Integration is created + * 1. Integration is created. * * Steps: * 1. Log in to backend as admin user. - * 2. Navigate to System > Extensions > Integrations - * 3. Click on the "Remove" icon for required integration + * 2. Navigate to System > Extensions > Integrations. + * 3. Click on the "Remove" icon for required integration. * 4. Click "Delete" button. * 5. Perform all assertions. * @@ -35,14 +32,14 @@ class DeleteIntegrationEntityTest extends Injectable /* end tags */ /** - * Integration grid page + * Integration grid page. * * @var IntegrationIndex */ protected $integrationIndexPage; /** - * Injection data + * Injection data. * * @param IntegrationIndex $integrationIndex * @return void @@ -53,7 +50,7 @@ class DeleteIntegrationEntityTest extends Injectable } /** - * Delete Integration Entity test + * Delete Integration Entity test. * * @param Integration $integration * @return void diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ReAuthorizeTokensIntegrationEntityTest.php b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ReAuthorizeTokensIntegrationEntityTest.php index 9c5d0e9b3d71542b571be08db84fb80012f6fcfb..897798003ff40b069d25ab6320646a2ee219ee2c 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ReAuthorizeTokensIntegrationEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/ReAuthorizeTokensIntegrationEntityTest.php @@ -12,20 +12,16 @@ use Magento\Mtf\Fixture\FixtureFactory; use Magento\Mtf\TestCase\Injectable; /** - * Test Creation for Reauthorize tokens for the Integration Entity. - * - * Test Flow: - * * Preconditions: - * 1. Create Integration - * 2. Activate Integration + * 1. Create Integration. + * 2. Activate Integration. * * Steps: - * 1. Go to Integration page on backend - * 2. Click on the "Reauthorize" link on the Integration grid + * 1. Go to Integration page on backend. + * 2. Click on the "Reauthorize" link on the Integration grid. * 3. Click on the "Reauthorize" button. - * 4. Click Done - * 5. Perform assertions + * 4. Click Done. + * 5. Perform assertions. * * @group Integrations_(PS) * @ZephyrId MAGETWO-29648 diff --git a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/UpdateIntegrationEntityTest.php b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/UpdateIntegrationEntityTest.php index 987c3c68b52dbcc4d35cd230a4dac4f9b6e6dd92..e7b32f956126e6e471975d0d64bacee012de840d 100644 --- a/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/UpdateIntegrationEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Integration/Test/TestCase/UpdateIntegrationEntityTest.php @@ -12,15 +12,12 @@ use Magento\Integration\Test\Page\Adminhtml\IntegrationNew; use Magento\Mtf\TestCase\Injectable; /** - * Test Creation for Update Integration Entity - * - * Test Flow: * Preconditions: - * 1. Integration is created + * 1. Integration is created. * * Steps: * 1. Log in to backend as admin user. - * 2. Navigate to System > Extensions > Integrations + * 2. Navigate to System > Extensions > Integrations. * 3. Select an integration in the grid. * 4. Edit test value(s) according to dataset. * 5. Click "Save" button. @@ -37,21 +34,21 @@ class UpdateIntegrationEntityTest extends Injectable /* end tags */ /** - * Integration grid page + * Integration grid page. * * @var IntegrationIndex */ protected $integrationIndexPage; /** - * Integration edit page + * Integration edit page. * * @var IntegrationNew */ protected $integrationNewPage; /** - * Injection data + * Injection data. * * @param IntegrationIndex $integrationIndex * @param IntegrationNew $integrationNew @@ -64,7 +61,7 @@ class UpdateIntegrationEntityTest extends Injectable } /** - * Update Integration Entity test + * Update Integration Entity test. * * @param Integration $initialIntegration * @param Integration $integration diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable.xml index 4f26f0a213fffc903b7e364b16f3b79f286ea36f..e5e9d7d6f475e3953fa063dc2ef4d0bebcb0241e 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Fixture/OrderInjectable.xml @@ -414,28 +414,28 @@ <field name="customer_gender" is_required=""> <default_value xsi:type="null" /> </field> - <field name="hidden_tax_amount" is_required=""> + <field name="discount_tax_compensation_amount" is_required=""> <default_value xsi:type="null" /> </field> - <field name="base_hidden_tax_amount" is_required=""> + <field name="base_discount_tax_compensation_amount" is_required=""> <default_value xsi:type="null" /> </field> - <field name="shipping_hidden_tax_amount" is_required=""> + <field name="shipping_discount_tax_compensation_amount" is_required=""> <default_value xsi:type="null" /> </field> - <field name="base_shipping_hidden_tax_amnt" is_required=""> + <field name="base_shipping_discount_tax_compensation_amnt" is_required=""> <default_value xsi:type="null" /> </field> - <field name="hidden_tax_invoiced" is_required=""> + <field name="discount_tax_compensation_invoiced" is_required=""> <default_value xsi:type="null" /> </field> - <field name="base_hidden_tax_invoiced" is_required=""> + <field name="base_discount_tax_compensation_invoiced" is_required=""> <default_value xsi:type="null" /> </field> - <field name="hidden_tax_refunded" is_required=""> + <field name="discount_tax_compensation_refunded" is_required=""> <default_value xsi:type="null" /> </field> - <field name="base_hidden_tax_refunded" is_required=""> + <field name="base_discount_tax_compensation_refunded" is_required=""> <default_value xsi:type="null" /> </field> <field name="shipping_incl_tax" is_required=""> diff --git a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessDeleteMessage.php index 9c0a3ad593a5adb4a3dae1ce0c28cf838d50aecf..0209c3f0a7659e98be796329a23705070ff61edb 100644 --- a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessDeleteMessage.php @@ -14,7 +14,7 @@ use Magento\Mtf\Constraint\AbstractConstraint; */ class AssertSitemapSuccessDeleteMessage extends AbstractConstraint { - const SUCCESS_DELETE_MESSAGE = 'The sitemap has been deleted.'; + const SUCCESS_DELETE_MESSAGE = 'You deleted the sitemap.'; /** * Assert that success message is displayed after sitemap delete diff --git a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveAndGenerateMessages.php b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveAndGenerateMessages.php index 3c388b8c1710c81bfe4c28b113e4c7888a7a9ea7..a2924af474a21b2c040fb8a41097d821fdcb04e9 100644 --- a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveAndGenerateMessages.php +++ b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveAndGenerateMessages.php @@ -17,7 +17,7 @@ class AssertSitemapSuccessSaveAndGenerateMessages extends AbstractConstraint { const SUCCESS_GENERATE_MESSAGE = 'The sitemap "%s" has been generated.'; - const SUCCESS_SAVE_MESSAGE = 'The sitemap has been saved.'; + const SUCCESS_SAVE_MESSAGE = 'You saved the sitemap.'; /** * Assert that success messages is displayed after sitemap generate diff --git a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveMessage.php index 5900e0217fbdef73a8360a6672c68f418210883d..e0e4efc80694dfa9901040e5b5ffec1610424782 100644 --- a/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sitemap/Test/Constraint/AssertSitemapSuccessSaveMessage.php @@ -14,7 +14,7 @@ use Magento\Mtf\Constraint\AbstractConstraint; */ class AssertSitemapSuccessSaveMessage extends AbstractConstraint { - const SUCCESS_MESSAGE = 'The sitemap has been saved.'; + const SUCCESS_MESSAGE = 'You saved the sitemap.'; /** * Assert that success message is displayed after sitemap save diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php index 9477d5377db9b512e54ef8bc209942f0aee9384b..e6f58b5aef94f8795cc791ce3b1c387ab5b5b92d 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Block/Adminhtml/Rule/Edit/Form.php @@ -262,11 +262,26 @@ class Form extends FormInterface } /** - * Getting all options in Tax Rate multi select list. + * Click 'Add New' button. * - * @return array + * @param SimpleElement $element + * @return void */ - public function getAllTaxRates() + protected function clickAddNewButton(SimpleElement $element) + { + $addNewButton = $this->addNewButton; + $element->waitUntil( + function () use ($element, $addNewButton) { + return $element->find($addNewButton)->isVisible() ? true : null; + } + ); + $element->find($this->addNewButton)->click(); + } + + /** + * Wait until tax rate element appears. + */ + protected function waitForTaxRates() { $browser = $this->browser; $taxRateMultiSelectList = $this->taxRateMultiSelectList; @@ -276,6 +291,16 @@ class Form extends FormInterface return $element->isVisible() ? true : null; } ); + } + + /** + * Getting all options in Tax Rate multi select list. + * + * @return array + */ + public function getAllTaxRates() + { + $this->waitForTaxRates(); /** @var \Magento\Mtf\Client\Element\MultiselectlistElement $taxRates */ $taxRates = $this->_rootElement->find($this->taxRateBlock, Locator::SELECTOR_CSS, 'multiselectlist'); @@ -283,19 +308,15 @@ class Form extends FormInterface } /** - * Click 'Add New' button. + * Check whether tax rate is visible in the list. * - * @param SimpleElement $element - * @return void + * @param string $value + * @return bool */ - protected function clickAddNewButton(SimpleElement $element) + public function isTaxRateAvailable($value) { - $addNewButton = $this->addNewButton; - $element->waitUntil( - function () use ($element, $addNewButton) { - return $element->find($addNewButton)->isVisible() ? true : null; - } - ); - $element->find($this->addNewButton)->click(); + /** @var \Magento\Mtf\Client\Element\MultiselectlistElement $taxRate */ + $taxRate = $this->_rootElement->find($this->taxRateBlock, Locator::SELECTOR_CSS, 'multiselectlist'); + return $taxRate->isValueVisible($value); } } diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateInTaxRule.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateInTaxRule.php index 96f386dbf5918c54bf77c39b3a19dbb2c6891d80..b9b5f5d5e7038519e2a5522509e429add1152ae3 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateInTaxRule.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateInTaxRule.php @@ -6,26 +6,43 @@ namespace Magento\Tax\Test\Constraint; +use Magento\Tax\Test\Fixture\TaxRate; use Magento\Mtf\Constraint\AbstractConstraint; +use Magento\Tax\Test\Page\Adminhtml\TaxRuleNew; +use Magento\Tax\Test\Page\Adminhtml\TaxRuleIndex; /** - * Class AssertTaxRateInTaxRule + * Assert that required tax rate is present in tax rule. */ class AssertTaxRateInTaxRule extends AbstractConstraint { /** + * Assert that required tax rate is present in "Tax Rule Information" on tax rule creation page. + * + * @param TaxRuleIndex $taxRuleIndex + * @param TaxRuleNew $taxRuleNew + * @param TaxRate $taxRate * @return void */ - public function processAssert() + public function processAssert(TaxRuleIndex $taxRuleIndex, TaxRuleNew $taxRuleNew, TaxRate $taxRate) { - // + $taxRateCode = $taxRate->getCode(); + $taxRuleIndex->open(); + $taxRuleIndex->getGridPageActions()->addNew(); + + \PHPUnit_Framework_Assert::assertTrue( + $taxRuleNew->getTaxRuleForm()->isTaxRateAvailable($taxRateCode), + "$taxRateCode is not present in Tax Rates multiselect on tax rule creation page." + ); } /** + * Returns string representation of object. + * * @return string */ public function toString() { - // + return "Required tax rate is present on Tax Rule page."; } } diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateIsInCorrectRange.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateIsInCorrectRange.php deleted file mode 100644 index cbb72df8b8514127eecbe68e42fc2ebf18151d44..0000000000000000000000000000000000000000 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateIsInCorrectRange.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Tax\Test\Constraint; - -use Magento\Mtf\Constraint\AbstractConstraint; - -/** - * Class AssertTaxRateIsInCorrectRange - */ -class AssertTaxRateIsInCorrectRange extends AbstractConstraint -{ - /** - * @return void - */ - public function processAssert() - { - // - } - - /** - * @return string - */ - public function toString() - { - // - } -} diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessDeleteMessage.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessDeleteMessage.php index dcfd8a35229ac00ad79cfe0162b028308a8ac5a0..f956e5c82b97bd87c08c3fec8f158fd995dfb9cb 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessDeleteMessage.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessDeleteMessage.php @@ -14,7 +14,7 @@ use Magento\Mtf\Constraint\AbstractConstraint; */ class AssertTaxRateSuccessDeleteMessage extends AbstractConstraint { - const SUCCESS_DELETE_MESSAGE = 'The tax rate has been deleted.'; + const SUCCESS_DELETE_MESSAGE = 'You deleted the tax rate.'; /** * Assert that success delete message is displayed after tax rate deleted diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessSaveMessage.php index 3c473195455b9afb50a73b21545fac1f81579f42..165e9a7aeb65f2be2fd5a9a13903e6e793fae7ee 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRateSuccessSaveMessage.php @@ -14,7 +14,7 @@ use Magento\Mtf\Constraint\AbstractConstraint; */ class AssertTaxRateSuccessSaveMessage extends AbstractConstraint { - const SUCCESS_MESSAGE = 'The tax rate has been saved.'; + const SUCCESS_MESSAGE = 'You saved the tax rate.'; /** * Assert that success message is displayed after tax rate saved diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessSaveMessage.php b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessSaveMessage.php index 1507e373dc21f00f56ebf5db4dbbc5b923237fc0..73e32f4f8b151902bef7d3702bc9462b25080852 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessSaveMessage.php +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/Constraint/AssertTaxRuleSuccessSaveMessage.php @@ -18,7 +18,7 @@ class AssertTaxRuleSuccessSaveMessage extends AbstractConstraint const SEVERITY = 'low'; /* end tags */ - const SUCCESS_MESSAGE = 'The tax rule has been saved.'; + const SUCCESS_MESSAGE = 'You saved the tax rule.'; /** * Assert that success message is displayed after tax rule saved diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/CreateTaxRateEntityTest.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/CreateTaxRateEntityTest.xml index 7f3623a24026445a73f7daec9ef2c73fe131f259..bee3fb886b6f598dd767fe1706a967247ea05736 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/CreateTaxRateEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/CreateTaxRateEntityTest.xml @@ -6,68 +6,74 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> - <testCase name="Magento\Tax\Test\TestCase\CreateTaxRateEntityTest"> - <variation name="CreateTaxRateEntityTestVariation1"> - <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> - <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> - <data name="taxRate/data/zip_from" xsi:type="string">-</data> - <data name="taxRate/data/zip_to" xsi:type="string">-</data> - <data name="taxRate/data/tax_postcode" xsi:type="string">*</data> - <data name="taxRate/data/tax_country_id" xsi:type="string">Australia</data> - <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> - <data name="taxRate/data/rate" xsi:type="string">20</data> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInTaxRule"/> - </variation> - <variation name="CreateTaxRateEntityTestVariation2"> - <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> - <data name="taxRate/data/zip_is_range" xsi:type="string">Yes</data> - <data name="taxRate/data/zip_from" xsi:type="string">90001</data> - <data name="taxRate/data/zip_to" xsi:type="string">96162</data> - <data name="taxRate/data/tax_postcode" xsi:type="string">-</data> - <data name="taxRate/data/tax_country_id" xsi:type="string">United States</data> - <data name="taxRate/data/tax_region_id" xsi:type="string">California</data> - <data name="taxRate/data/rate" xsi:type="string">15.5</data> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInTaxRule"/> - </variation> - <variation name="CreateTaxRateEntityTestVariation3"> - <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> - <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> - <data name="taxRate/data/zip_from" xsi:type="string">-</data> - <data name="taxRate/data/zip_to" xsi:type="string">-</data> - <data name="taxRate/data/tax_postcode" xsi:type="string">180</data> - <data name="taxRate/data/tax_country_id" xsi:type="string">Canada</data> - <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> - <data name="taxRate/data/rate" xsi:type="string">25</data> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInTaxRule"/> - </variation> - <variation name="CreateTaxRateEntityTestVariation4"> - <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> - <data name="taxRate/data/zip_is_range" xsi:type="string">Yes</data> - <data name="taxRate/data/zip_to" xsi:type="string">7800935</data> - <data name="taxRate/data/tax_postcode" xsi:type="string">-</data> - <data name="taxRate/data/tax_country_id" xsi:type="string">United Kingdom</data> - <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateIsInCorrectRange"/> - </variation> - <variation name="CreateTaxRateEntityTestVariation5"> - <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> - <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> - <data name="taxRate/data/zip_from" xsi:type="string">-</data> - <data name="taxRate/data/zip_to" xsi:type="string">-</data> - <data name="taxRate/data/tax_postcode" xsi:type="string">*</data> - <data name="taxRate/data/tax_country_id" xsi:type="string">France</data> - <data name="taxRate/data/tax_region_id" xsi:type="string">Val-d'Oise</data> - <data name="taxRate/data/rate" xsi:type="string">999</data> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateIsInCorrectRange"/> - </variation> - </testCase> + <testCase name="Magento\Tax\Test\TestCase\CreateTaxRateEntityTest"> + <variation name="CreateTaxRateEntityTestVariation1"> + <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> + <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> + <data name="taxRate/data/zip_from" xsi:type="string">-</data> + <data name="taxRate/data/zip_to" xsi:type="string">-</data> + <data name="taxRate/data/tax_postcode" xsi:type="string">*</data> + <data name="taxRate/data/tax_country_id" xsi:type="string">Australia</data> + <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> + <data name="taxRate/data/rate" xsi:type="string">20</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInTaxRule" /> + </variation> + <variation name="CreateTaxRateEntityTestVariation2"> + <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> + <data name="taxRate/data/zip_is_range" xsi:type="string">Yes</data> + <data name="taxRate/data/zip_from" xsi:type="string">90001</data> + <data name="taxRate/data/zip_to" xsi:type="string">96162</data> + <data name="taxRate/data/tax_postcode" xsi:type="string">-</data> + <data name="taxRate/data/tax_country_id" xsi:type="string">United States</data> + <data name="taxRate/data/tax_region_id" xsi:type="string">California</data> + <data name="taxRate/data/rate" xsi:type="string">15.5</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInTaxRule" /> + </variation> + <variation name="CreateTaxRateEntityTestVariation3"> + <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> + <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> + <data name="taxRate/data/zip_from" xsi:type="string">-</data> + <data name="taxRate/data/zip_to" xsi:type="string">-</data> + <data name="taxRate/data/tax_postcode" xsi:type="string">180</data> + <data name="taxRate/data/tax_country_id" xsi:type="string">Canada</data> + <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> + <data name="taxRate/data/rate" xsi:type="string">25</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInTaxRule" /> + </variation> + <variation name="CreateTaxRateEntityTestVariation4"> + <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> + <data name="taxRate/data/zip_is_range" xsi:type="string">Yes</data> + <data name="taxRate/data/zip_from" xsi:type="string">1</data> + <data name="taxRate/data/zip_to" xsi:type="string">7800935</data> + <data name="taxRate/data/tax_postcode" xsi:type="string">-</data> + <data name="taxRate/data/tax_country_id" xsi:type="string">United Kingdom</data> + <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> + <data name="taxRate/data/rate" xsi:type="string">7.75</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInTaxRule" /> + </variation> + <variation name="CreateTaxRateEntityTestVariation5"> + <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> + <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> + <data name="taxRate/data/zip_from" xsi:type="string">-</data> + <data name="taxRate/data/zip_to" xsi:type="string">-</data> + <data name="taxRate/data/tax_postcode" xsi:type="string">*</data> + <data name="taxRate/data/tax_country_id" xsi:type="string">France</data> + <data name="taxRate/data/tax_region_id" xsi:type="string">Val-d'Oise</data> + <data name="taxRate/data/rate" xsi:type="string">999</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInTaxRule" /> + </variation> + </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/UpdateTaxRateEntityTest.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/UpdateTaxRateEntityTest.xml index 007307f625682ab5a7188cfd209de76f0c71dc1b..5f3a3e5fba76bad0aa9afb2fa85624cddb1e4beb 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/UpdateTaxRateEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/TestCase/UpdateTaxRateEntityTest.xml @@ -6,84 +6,89 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd"> - <testCase name="Magento\Tax\Test\TestCase\UpdateTaxRateEntityTest"> - <variation name="UpdateTaxRateEntityTestVariation1"> - <data name="initialTaxRate/dataSet" xsi:type="string">default</data> - <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> - <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> - <data name="taxRate/data/zip_from" xsi:type="string">-</data> - <data name="taxRate/data/zip_to" xsi:type="string">-</data> - <data name="taxRate/data/tax_postcode" xsi:type="string">90001</data> - <data name="taxRate/data/tax_country_id" xsi:type="string">United States</data> - <data name="taxRate/data/tax_region_id" xsi:type="string">California</data> - <data name="taxRate/data/rate" xsi:type="string">100</data> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm"/> - </variation> - <variation name="UpdateTaxRateEntityTestVariation2"> - <data name="initialTaxRate/dataSet" xsi:type="string">default</data> - <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> - <data name="taxRate/data/zip_is_range" xsi:type="string">Yes</data> - <data name="taxRate/data/zip_from" xsi:type="string">90001</data> - <data name="taxRate/data/zip_to" xsi:type="string">96162</data> - <data name="taxRate/data/tax_postcode" xsi:type="string">-</data> - <data name="taxRate/data/tax_country_id" xsi:type="string">United States</data> - <data name="taxRate/data/tax_region_id" xsi:type="string">California</data> - <data name="taxRate/data/rate" xsi:type="string">15.05</data> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm"/> - </variation> - <variation name="UpdateTaxRateEntityTestVariation3"> - <data name="initialTaxRate/dataSet" xsi:type="string">default</data> - <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> - <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> - <data name="taxRate/data/zip_from" xsi:type="string">-</data> - <data name="taxRate/data/zip_to" xsi:type="string">-</data> - <data name="taxRate/data/tax_postcode" xsi:type="string">*</data> - <data name="taxRate/data/tax_country_id" xsi:type="string">United Kingdom</data> - <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> - <data name="taxRate/data/rate" xsi:type="string">777</data> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateIsInCorrectRange"/> - </variation> - <variation name="UpdateTaxRateEntityTestVariation4"> - <data name="initialTaxRate/dataSet" xsi:type="string">withZipRange</data> - <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> - <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> - <data name="taxRate/data/zip_from" xsi:type="string">-</data> - <data name="taxRate/data/zip_to" xsi:type="string">-</data> - <data name="taxRate/data/tax_postcode" xsi:type="string">180</data> - <data name="taxRate/data/tax_country_id" xsi:type="string">Canada</data> - <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> - <data name="taxRate/data/rate" xsi:type="string">25</data> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm"/> - </variation> - <variation name="UpdateTaxRateEntityTestVariation5"> - <data name="initialTaxRate/dataSet" xsi:type="string">withZipRange</data> - <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> - <data name="taxRate/data/zip_is_range" xsi:type="string">Yes</data> - <data name="taxRate/data/zip_to" xsi:type="string">7800935</data> - <data name="taxRate/data/tax_postcode" xsi:type="string">-</data> - <data name="taxRate/data/tax_country_id" xsi:type="string">United Kingdom</data> - <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateIsInCorrectRange"/> - </variation> - <variation name="UpdateTaxRateEntityTestVariation6"> - <data name="initialTaxRate/dataSet" xsi:type="string">withZipRange</data> - <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> - <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> - <data name="taxRate/data/zip_from" xsi:type="string">-</data> - <data name="taxRate/data/zip_to" xsi:type="string">-</data> - <data name="taxRate/data/tax_postcode" xsi:type="string">*</data> - <data name="taxRate/data/tax_country_id" xsi:type="string">France</data> - <data name="taxRate/data/tax_region_id" xsi:type="string">Val-d'Oise</data> - <data name="taxRate/data/rate" xsi:type="string">0.1</data> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid"/> - <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm"/> - </variation> - </testCase> + <testCase name="Magento\Tax\Test\TestCase\UpdateTaxRateEntityTest"> + <variation name="UpdateTaxRateEntityTestVariation1"> + <data name="initialTaxRate/dataSet" xsi:type="string">default</data> + <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> + <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> + <data name="taxRate/data/zip_from" xsi:type="string">-</data> + <data name="taxRate/data/zip_to" xsi:type="string">-</data> + <data name="taxRate/data/tax_postcode" xsi:type="string">90001</data> + <data name="taxRate/data/tax_country_id" xsi:type="string">United States</data> + <data name="taxRate/data/tax_region_id" xsi:type="string">California</data> + <data name="taxRate/data/rate" xsi:type="string">100</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm" /> + </variation> + <variation name="UpdateTaxRateEntityTestVariation2"> + <data name="initialTaxRate/dataSet" xsi:type="string">default</data> + <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> + <data name="taxRate/data/zip_is_range" xsi:type="string">Yes</data> + <data name="taxRate/data/zip_from" xsi:type="string">90001</data> + <data name="taxRate/data/zip_to" xsi:type="string">96162</data> + <data name="taxRate/data/tax_postcode" xsi:type="string">-</data> + <data name="taxRate/data/tax_country_id" xsi:type="string">United States</data> + <data name="taxRate/data/tax_region_id" xsi:type="string">California</data> + <data name="taxRate/data/rate" xsi:type="string">15.05</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm" /> + </variation> + <variation name="UpdateTaxRateEntityTestVariation3"> + <data name="initialTaxRate/dataSet" xsi:type="string">default</data> + <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> + <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> + <data name="taxRate/data/zip_from" xsi:type="string">-</data> + <data name="taxRate/data/zip_to" xsi:type="string">-</data> + <data name="taxRate/data/tax_postcode" xsi:type="string">*</data> + <data name="taxRate/data/tax_country_id" xsi:type="string">United Kingdom</data> + <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> + <data name="taxRate/data/rate" xsi:type="string">777</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm" /> + </variation> + <variation name="UpdateTaxRateEntityTestVariation4"> + <data name="initialTaxRate/dataSet" xsi:type="string">withZipRange</data> + <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> + <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> + <data name="taxRate/data/zip_from" xsi:type="string">-</data> + <data name="taxRate/data/zip_to" xsi:type="string">-</data> + <data name="taxRate/data/tax_postcode" xsi:type="string">180</data> + <data name="taxRate/data/tax_country_id" xsi:type="string">Canada</data> + <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> + <data name="taxRate/data/rate" xsi:type="string">25</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm" /> + </variation> + <variation name="UpdateTaxRateEntityTestVariation5"> + <data name="initialTaxRate/dataSet" xsi:type="string">withZipRange</data> + <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> + <data name="taxRate/data/zip_is_range" xsi:type="string">Yes</data> + <data name="taxRate/data/zip_from" xsi:type="string">1</data> + <data name="taxRate/data/zip_to" xsi:type="string">7800935</data> + <data name="taxRate/data/tax_postcode" xsi:type="string">-</data> + <data name="taxRate/data/tax_country_id" xsi:type="string">United Kingdom</data> + <data name="taxRate/data/tax_region_id" xsi:type="string">*</data> + <data name="taxRate/data/rate" xsi:type="string">12.99</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm" /> + </variation> + <variation name="UpdateTaxRateEntityTestVariation6"> + <data name="initialTaxRate/dataSet" xsi:type="string">withZipRange</data> + <data name="taxRate/data/code" xsi:type="string">TaxIdentifier%isolation%</data> + <data name="taxRate/data/zip_is_range" xsi:type="string">No</data> + <data name="taxRate/data/zip_from" xsi:type="string">-</data> + <data name="taxRate/data/zip_to" xsi:type="string">-</data> + <data name="taxRate/data/tax_postcode" xsi:type="string">*</data> + <data name="taxRate/data/tax_country_id" xsi:type="string">France</data> + <data name="taxRate/data/tax_region_id" xsi:type="string">Val-d'Oise</data> + <data name="taxRate/data/rate" xsi:type="string">0.1</data> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid" /> + <constraint name="Magento\Tax\Test\Constraint\AssertTaxRateForm" /> + </variation> + </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Tax/Test/etc/di.xml b/dev/tests/functional/tests/app/Magento/Tax/Test/etc/di.xml index 62c39459f0d5b0e02862e5fff673bf421276b738..00eb021110e48ef82bffbac63bb7ced5555e3a59 100644 --- a/dev/tests/functional/tests/app/Magento/Tax/Test/etc/di.xml +++ b/dev/tests/functional/tests/app/Magento/Tax/Test/etc/di.xml @@ -6,74 +6,79 @@ */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"> - <type name="Magento\Tax\Test\Constraint\AssertTaxRuleInGrid"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxRuleForm"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxRateForm"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxRuleIsApplied"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxWithCrossBorderApplied"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxRuleIsNotApplied"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxWithCrossBorderNotApplied"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxRuleSuccessDeleteMessage"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxRuleNotInGrid"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessDeleteMessage"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxRateNotInGrid"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> - <type name="Magento\Tax\Test\Constraint\AssertTaxRateNotInTaxRule"> - <arguments> - <argument name="severity" xsi:type="string">high</argument> - </arguments> - </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRuleInGrid"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRuleForm"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessSaveMessage"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRateInGrid"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRateForm"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRuleIsApplied"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxWithCrossBorderApplied"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRuleIsNotApplied"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxWithCrossBorderNotApplied"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRuleSuccessDeleteMessage"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRuleNotInGrid"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRateSuccessDeleteMessage"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRateNotInGrid"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRateNotInTaxRule"> + <arguments> + <argument name="severity" xsi:type="string">high</argument> + </arguments> + </type> + <type name="Magento\Tax\Test\Constraint\AssertTaxRateInTaxRule"> + <arguments> + <argument name="severity" xsi:type="string">middle</argument> + </arguments> + </type> </config> diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php index f4bdb4bb6f62e19d7b79dd810cf5a9571cc0db47..552f31dfb63bc8bc64cfab6a1c7147dd939b62dc 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/DataGrid.php @@ -114,10 +114,10 @@ class DataGrid extends Grid */ public function searchAndOpen(array $filter) { + $this->waitLoader(); $rowItem = $this->getRow($filter); if ($rowItem->isVisible()) { $rowItem->find($this->editLink)->click(); - $this->waitForElement(); } else { throw new \Exception('Searched item was not found.'); } diff --git a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserWrongCredentialsMessage.php b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginMessage.php similarity index 76% rename from dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserWrongCredentialsMessage.php rename to dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginMessage.php index c78a7553ba9e40afa040fb7acc2fc174eba1f9fd..e01aa9a9cd0cdfe0af16c3c74c6f32cfdbe8f669 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserWrongCredentialsMessage.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/Constraint/AssertUserFailedLoginMessage.php @@ -11,11 +11,11 @@ use Magento\User\Test\Fixture\User; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertUserWrongCredentialsMessage + * Class AssertUserFailedLoginMessage */ -class AssertUserWrongCredentialsMessage extends AbstractConstraint +class AssertUserFailedLoginMessage extends AbstractConstraint { - const INVALID_CREDENTIALS_MESSAGE = 'Please correct the user name or password.'; + const FAILED_LOGIN_MESSAGE = 'You did not sign in correctly or your account is temporarily disabled.'; /** * Verify incorrect credentials message while login to admin @@ -33,9 +33,9 @@ class AssertUserWrongCredentialsMessage extends AbstractConstraint $adminAuth->getLoginBlock()->submit(); \PHPUnit_Framework_Assert::assertEquals( - self::INVALID_CREDENTIALS_MESSAGE, + self::FAILED_LOGIN_MESSAGE, $adminAuth->getMessagesBlock()->getErrorMessages(), - 'Message "' . self::INVALID_CREDENTIALS_MESSAGE . '" is not visible.' + 'Message "' . self::FAILED_LOGIN_MESSAGE . '" is not visible.' ); } diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.xml b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.xml index c71d32fb5b91f118f3c8067ff82d467861638f4b..98c6794f0dfe3b4934290320024399493b1188ab 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserEntityTest.xml @@ -37,7 +37,7 @@ <constraint name="Magento\User\Test\Constraint\AssertUserSuccessSaveMessage"/> <constraint name="Magento\User\Test\Constraint\AssertUserInGrid"/> <constraint name="Magento\User\Test\Constraint\AssertUserSuccessLogOut"/> - <constraint name="Magento\User\Test\Constraint\AssertUserWrongCredentialsMessage"/> + <constraint name="Magento\User\Test\Constraint\AssertUserFailedLoginMessage"/> </variation> <variation name="CreateAdminUserEntityTestVariation3"> <data name="user/data/firstname" xsi:type="string">FirstName%isolation%</data> @@ -76,7 +76,7 @@ <constraint name="Magento\User\Test\Constraint\AssertUserSuccessSaveMessage"/> <constraint name="Magento\User\Test\Constraint\AssertUserInGrid"/> <constraint name="Magento\User\Test\Constraint\AssertUserSuccessLogOut"/> - <constraint name="Magento\User\Test\Constraint\AssertUserWrongCredentialsMessage"/> + <constraint name="Magento\User\Test\Constraint\AssertUserFailedLoginMessage"/> </variation> <variation name="CreateAdminUserEntityTestVariation6"> <data name="user/data/username" xsi:type="string">AdminUser%isolation%</data> diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserRoleEntityTest.php b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserRoleEntityTest.php index f37fc9ab0694a145c81bf435685bd68e24475b64..21d5a4bbb6e5a3e61ef0c30a307f550536fb6e69 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserRoleEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserRoleEntityTest.php @@ -12,8 +12,6 @@ use Magento\User\Test\Page\Adminhtml\UserRoleIndex; use Magento\Mtf\TestCase\Injectable; /** - * Test Creation for CreateAdminUserRolesEntity - * * Test Flow: * 1. Log in as default admin user * 2. Go to System>Permissions>User Roles @@ -33,25 +31,27 @@ class CreateAdminUserRoleEntityTest extends Injectable /* end tags */ /** + * UserRoleIndex page. + * * @var UserRoleIndex */ protected $userRoleIndex; /** + * UserRoleEditRole page. + * * @var UserRoleEditRole */ protected $userRoleEditRole; /** - * Setup data for test + * Setup data for test. * * @param UserRoleIndex $userRoleIndex * @param UserRoleEditRole $userRoleEditRole */ - public function __inject( - UserRoleIndex $userRoleIndex, - UserRoleEditRole $userRoleEditRole - ) { + public function __inject(UserRoleIndex $userRoleIndex, UserRoleEditRole $userRoleEditRole) + { $this->userRoleIndex = $userRoleIndex; $this->userRoleEditRole = $userRoleEditRole; } diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserRoleEntityTest.xml b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserRoleEntityTest.xml index aa70d5ad8bf4ec8fd910a5d90782edc20ee6aa5b..dcbed28377e90ded318fd6027cbcbed4de9a34fa 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserRoleEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/CreateAdminUserRoleEntityTest.xml @@ -11,14 +11,14 @@ <data name="role/data/rolename" xsi:type="string">AdminRole%isolation%</data> <data name="role/data/resource_access" xsi:type="string">Custom</data> <data name="role/data/roles_resources" xsi:type="string">Sales</data> - <constraint name="Magento\User\Test\Constraint\AssertRoleSuccessSaveMessage"/> - <constraint name="Magento\User\Test\Constraint\AssertRoleInGrid"/> + <constraint name="Magento\User\Test\Constraint\AssertRoleSuccessSaveMessage" /> + <constraint name="Magento\User\Test\Constraint\AssertRoleInGrid" /> </variation> <variation name="CreateAdminUserRoleEntityTestVariation2"> <data name="role/data/rolename" xsi:type="string">AdminRole%isolation%</data> <data name="role/data/resource_access" xsi:type="string">All</data> - <constraint name="Magento\User\Test\Constraint\AssertRoleSuccessSaveMessage"/> - <constraint name="Magento\User\Test\Constraint\AssertRoleInGrid"/> + <constraint name="Magento\User\Test\Constraint\AssertRoleSuccessSaveMessage" /> + <constraint name="Magento\User\Test\Constraint\AssertRoleInGrid" /> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.xml b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.xml index e64b21124c8b1db49907f7571c2ce2242f2aa157..a96e809038e1bfad5fee61066835313c576af266 100644 --- a/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/User/Test/TestCase/UpdateAdminUserRoleEntityTest.xml @@ -10,9 +10,6 @@ <variation name="UpdateAdminUserRoleEntityTestVariation1"> <data name="user/dataSet" xsi:type="string">custom_admin_with_default_role</data> <data name="role/data/rolename" xsi:type="string">NewAdminRole%isolation%</data> - <data name="role/data/resource_access" xsi:type="string">-</data> - <data name="role/data/roles_resources" xsi:type="string">-</data> - <data name="role/data/in_role_users/dataSet" xsi:type="string">-</data> <constraint name="Magento\User\Test\Constraint\AssertRoleSuccessSaveMessage"/> <constraint name="Magento\User\Test\Constraint\AssertRoleInGrid"/> <constraint name="Magento\User\Test\Constraint\AssertUserSuccessLogOut"/> @@ -20,7 +17,6 @@ </variation> <variation name="UpdateAdminUserRoleEntityTestVariation2"> <data name="user/dataSet" xsi:type="string">default</data> - <data name="role/data/rolename" xsi:type="string">-</data> <data name="role/data/resource_access" xsi:type="string">Custom</data> <data name="role/data/roles_resources" xsi:type="string">Sales</data> <data name="role/data/in_role_users/dataSet" xsi:type="string">custom_admin</data> diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertAddProductToWishlistSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertAddProductToWishlistSuccessMessage.php index 0e616a4d881dd06a42562fefb1601286b0ff56be..ead94063b609e1b9b3f162859196441aded573db 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertAddProductToWishlistSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertAddProductToWishlistSuccessMessage.php @@ -23,7 +23,7 @@ class AssertAddProductToWishlistSuccessMessage extends AbstractConstraint /** * Success add message */ - const SUCCESS_MESSAGE = "%s has been added to your wishlist. Click here to continue shopping."; + const SUCCESS_MESSAGE = "%s has been added to your Wish List. Click here to continue shopping."; /** * Assert that success message appears on My Wish List page after adding product to wishlist. @@ -48,6 +48,6 @@ class AssertAddProductToWishlistSuccessMessage extends AbstractConstraint */ public function toString() { - return 'Success message appears on My Wish List page after adding product to wishlist.'; + return 'Success message appears on My Wish List page after adding product to Wish List.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertMoveProductToWishlistSuccessMessage.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertMoveProductToWishlistSuccessMessage.php index 139ffe1a02c9fba57f5da164d16ef0395207c34f..29ef84e8349a6a0f2a998a011db4a6a95a525c40 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertMoveProductToWishlistSuccessMessage.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertMoveProductToWishlistSuccessMessage.php @@ -44,6 +44,6 @@ class AssertMoveProductToWishlistSuccessMessage extends AbstractConstraint */ public function toString() { - return 'Success message appears on Checkout Cart page after moving product to wishlist.'; + return 'Success message appears on Checkout Cart page after moving product to Wish List.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductInCustomerWishlistOnBackendGrid.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductInCustomerWishlistOnBackendGrid.php index 80ead47f4e3d3a60813d59163f5688382f746d67..31a5ef3052a5610ca9b966b915079512338199e6 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductInCustomerWishlistOnBackendGrid.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductInCustomerWishlistOnBackendGrid.php @@ -31,7 +31,7 @@ class AssertProductInCustomerWishlistOnBackendGrid extends AbstractConstraint /** @var Grid $wishlistGrid */ $wishlistGrid = $customerIndexEdit->getCustomerForm()->getTab('wishlist')->getSearchGridBlock(); \PHPUnit_Framework_Assert::assertTrue( - $wishlistGrid->isRowVisible($filter, true, false), + $wishlistGrid->isRowVisible($filter), 'Product ' . $product->getName() . ' is absent in grid with configure option.' ); } @@ -85,6 +85,6 @@ class AssertProductInCustomerWishlistOnBackendGrid extends AbstractConstraint */ public function toString() { - return "Product is visible in customer wishlist on backend."; + return "Product is visible in Customer Wish List on Backend."; } } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductIsPresentInCustomerBackendWishlist.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductIsPresentInCustomerBackendWishlist.php index 615b571ccb378401aa353a2b7c6bbb13b20385e7..f6d591fe1cb399e2c1fd3df273c749edfde16cd3 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductIsPresentInCustomerBackendWishlist.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductIsPresentInCustomerBackendWishlist.php @@ -41,7 +41,7 @@ class AssertProductIsPresentInCustomerBackendWishlist extends AbstractConstraint $wishlistGrid = $customerIndexEdit->getCustomerForm()->getTab('wishlist')->getSearchGridBlock(); \PHPUnit_Framework_Assert::assertTrue( - $wishlistGrid->isRowVisible(['product_name' => $product->getName()], true, false), + $wishlistGrid->isRowVisible(['product_name' => $product->getName()]), $product->getName() . " is not visible in customer wishlist on backend." ); } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductIsPresentInWishlist.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductIsPresentInWishlist.php index 1b6b77bef669dd0296bdcd945cad5a63b1e0b044..ff6e4eab6a449de16b1feb2df89ea5054a3fc7bd 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductIsPresentInWishlist.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductIsPresentInWishlist.php @@ -37,7 +37,7 @@ class AssertProductIsPresentInWishlist extends AbstractConstraint \PHPUnit_Framework_Assert::assertTrue( $wishlistIndex->getWishlistBlock()->getProductItemsBlock()->getItemProduct($product)->isVisible(), - $product->getName() . ' is not visible on wishlist page.' + $product->getName() . ' is not visible on Wish List page.' ); } @@ -48,6 +48,6 @@ class AssertProductIsPresentInWishlist extends AbstractConstraint */ public function toString() { - return 'Product is present in default wishlist.'; + return 'Product is present in default Wish List.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductsIsAbsentInWishlist.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductsIsAbsentInWishlist.php index caa27aff310a8854d696b7af5da1146fad85d57c..a8323a590010d82cbe114ed434343c529fd96cbd 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductsIsAbsentInWishlist.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertProductsIsAbsentInWishlist.php @@ -42,7 +42,7 @@ class AssertProductsIsAbsentInWishlist extends AbstractConstraint foreach ($products as $itemProduct) { \PHPUnit_Framework_Assert::assertFalse( $itemBlock->getItemProduct($itemProduct)->isVisible(), - 'Product \'' . $itemProduct->getName() . '\' is present in Wishlist on Frontend.' + 'Product \'' . $itemProduct->getName() . '\' is present in Wish List on Frontend.' ); } } @@ -54,6 +54,6 @@ class AssertProductsIsAbsentInWishlist extends AbstractConstraint */ public function toString() { - return 'Product is absent in Wishlist on Frontend.'; + return 'Product is absent in Wish List on Frontend.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistIsEmpty.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistIsEmpty.php index dbaa793d77aee552e7b7ba3b0ccae015b3c1fa82..ef7bad115d1b603903514943d68997ef45c651f1 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistIsEmpty.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistIsEmpty.php @@ -29,7 +29,7 @@ class AssertWishlistIsEmpty extends AbstractConstraint $cmsIndex->getLinksBlock()->openLink("My Wish List"); \PHPUnit_Framework_Assert::assertTrue( $wishlistIndex->getWishlistBlock()->isEmptyBlockVisible(), - 'Wish list is not empty.' + 'Wish List is not empty.' ); } @@ -40,6 +40,6 @@ class AssertWishlistIsEmpty extends AbstractConstraint */ public function toString() { - return 'Wish list is empty.'; + return 'Wish List is empty.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistShareMessage.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistShareMessage.php index 302e994568ddd2ab57a7f2a8c0eb7505cd4c19b3..7013691e59cbf853b1fe18f596ea5375c3576638 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistShareMessage.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/Constraint/AssertWishlistShareMessage.php @@ -46,6 +46,6 @@ class AssertWishlistShareMessage extends AbstractConstraint */ public function toString() { - return 'Wishlist success share message is present.'; + return 'Wish List success share message is present.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.php index 72e9ed8848e64bea6c6e7fcd3adbaf8f8d465140..f64c8da3fa6d472013efd3c52dbc5cfc92edcd02 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.php @@ -29,7 +29,6 @@ class AddProductToWishlistEntityTest extends AbstractWishlistTest /* tags */ const MVP = 'no'; const DOMAIN = 'CS'; - const STABLE = 'no'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml index 7a8124b775f9ab3bc75758b5eae67d9170f9bd0b..8b9d67b714f3501297779fa769c268c7702ed5fe 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductToWishlistEntityTest.xml @@ -14,7 +14,6 @@ <constraint name="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInCustomerBackendWishlist" /> </variation> <variation name="AddProductToWishlistEntityTestVariation2"> - <data name="tag" xsi:type="string">to_maintain:yes</data> <data name="product" xsi:type="string">catalogProductVirtual::default</data> <constraint name="Magento\Wishlist\Test\Constraint\AssertAddProductToWishlistSuccessMessage" /> <constraint name="Magento\Wishlist\Test\Constraint\AssertProductIsPresentInWishlist" /> diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductsToCartFromCustomerWishlistOnFrontendTest.xml b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductsToCartFromCustomerWishlistOnFrontendTest.xml index d88f6d3054641ffa76b70d4b5593bcd59f3aede1..6c3f3a5e70ac89f82d9c25c06da422416580eb9d 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductsToCartFromCustomerWishlistOnFrontendTest.xml +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/AddProductsToCartFromCustomerWishlistOnFrontendTest.xml @@ -20,7 +20,6 @@ <constraint name="Magento\Wishlist\Test\Constraint\AssertProductsIsAbsentInWishlist" /> </variation> <variation name="AddProductsToCartFromCustomerWishlistOnFrontendTestVariation3"> - <data name="issue" xsi:type="string">Bug: MAGETWO-36215</data> <data name="products" xsi:type="string">catalogProductSimple::default,catalogProductVirtual::product_50_dollar,catalogProductSimple::default,catalogProductVirtual::product_50_dollar</data> <data name="qty" xsi:type="string">-</data> <constraint name="Magento\Checkout\Test\Constraint\AssertProductQtyInShoppingCart" /> diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ConfigureProductInCustomerWishlistOnFrontendTest.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ConfigureProductInCustomerWishlistOnFrontendTest.php index f5d83130ce39ad2b866645cd38602e95d81bcb33..451c3deb582f05249b0fdc99748901c176df27ea 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ConfigureProductInCustomerWishlistOnFrontendTest.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ConfigureProductInCustomerWishlistOnFrontendTest.php @@ -30,7 +30,6 @@ class ConfigureProductInCustomerWishlistOnFrontendTest extends AbstractWishlistT /* tags */ const MVP = 'no'; const DOMAIN = 'CS'; - const TO_MAINTAIN = 'yes'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/DeleteProductFromCustomerWishlistOnBackendTest.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/DeleteProductFromCustomerWishlistOnBackendTest.php index f8673a5334d74cea99b32b815120b4141b11ae0b..ed9d3a17868fe4ad4bb48e91db1bb684f37ab3da 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/DeleteProductFromCustomerWishlistOnBackendTest.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/DeleteProductFromCustomerWishlistOnBackendTest.php @@ -35,7 +35,6 @@ class DeleteProductFromCustomerWishlistOnBackendTest extends AbstractWishlistTes /* tags */ const MVP = 'no'; const DOMAIN = 'CS'; - const TO_MAINTAIN = 'yes'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/MoveProductFromShoppingCartToWishlistTest.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/MoveProductFromShoppingCartToWishlistTest.php index 2bbe614e06bae4d88630c8aebb1e96cd470c2085..d325e868b4e703ba7bfb19e1e5816da24c5bdb07 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/MoveProductFromShoppingCartToWishlistTest.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/MoveProductFromShoppingCartToWishlistTest.php @@ -29,7 +29,6 @@ class MoveProductFromShoppingCartToWishlistTest extends AbstractWishlistTest /* tags */ const MVP = 'no'; const DOMAIN = 'CS'; - const STABLE = 'no'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.php index 2b96619bcae14f8186d73bd61782a213238bd33e..d57c5147d2bdb2de972d9113771e9cee55d67a34 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ShareWishlistEntityTest.php @@ -7,13 +7,10 @@ namespace Magento\Wishlist\Test\TestCase; use Magento\Catalog\Test\Fixture\CatalogProductSimple; -use Magento\Catalog\Test\Page\Product\CatalogProductView; use Magento\Cms\Test\Page\CmsIndex; use Magento\Customer\Test\Fixture\Customer; -use Magento\Customer\Test\Page\CustomerAccountIndex; use Magento\Wishlist\Test\Page\WishlistIndex; use Magento\Wishlist\Test\Page\WishlistShare; -use Magento\Mtf\Client\BrowserInterface; use Magento\Mtf\TestCase\Injectable; /** @@ -31,13 +28,14 @@ use Magento\Mtf\TestCase\Injectable; * * @group Wishlist_(CS) * @ZephyrId MAGETWO-23394 + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ShareWishlistEntityTest extends Injectable { /* tags */ const MVP = 'no'; const DOMAIN = 'CS'; - const TO_MAINTAIN = 'yes'; /* end tags */ /** @@ -47,20 +45,6 @@ class ShareWishlistEntityTest extends Injectable */ protected $cmsIndex; - /** - * Customer account index page. - * - * @var CustomerAccountIndex - */ - protected $customerAccountIndex; - - /** - * Product view page. - * - * @var CatalogProductView - */ - protected $catalogProductView; - /** * Wishlist index page. * @@ -82,10 +66,8 @@ class ShareWishlistEntityTest extends Injectable * @param CatalogProductSimple $product * @return array */ - public function __prepare( - Customer $customer, - CatalogProductSimple $product - ) { + public function __prepare(Customer $customer, CatalogProductSimple $product) + { $customer->persist(); $product->persist(); @@ -99,22 +81,16 @@ class ShareWishlistEntityTest extends Injectable * Inject pages. * * @param CmsIndex $cmsIndex - * @param CustomerAccountIndex $customerAccountIndex - * @param CatalogProductView $catalogProductView * @param WishlistIndex $wishlistIndex * @param WishlistShare $wishlistShare * @return void */ public function __inject( CmsIndex $cmsIndex, - CustomerAccountIndex $customerAccountIndex, - CatalogProductView $catalogProductView, WishlistIndex $wishlistIndex, WishlistShare $wishlistShare ) { $this->cmsIndex = $cmsIndex; - $this->customerAccountIndex = $customerAccountIndex; - $this->catalogProductView = $catalogProductView; $this->wishlistIndex = $wishlistIndex; $this->wishlistShare = $wishlistShare; } @@ -122,40 +98,29 @@ class ShareWishlistEntityTest extends Injectable /** * Share wish list. * - * @param BrowserInterface $browser * @param Customer $customer * @param CatalogProductSimple $product * @param array $sharingInfo * @return void */ public function test( - BrowserInterface $browser, Customer $customer, CatalogProductSimple $product, array $sharingInfo ) { //Steps - $this->loginCustomer($customer); - $browser->open($_ENV['app_frontend_url'] . $product->getUrlKey() . '.html'); - $this->catalogProductView->getViewBlock()->clickAddToWishlist(); + $this->objectManager->create( + 'Magento\Customer\Test\TestStep\LoginCustomerOnFrontendStep', + ['customer' => $customer] + )->run(); + $this->objectManager->create( + 'Magento\Wishlist\Test\TestStep\AddProductsToWishlistStep', + ['products' => [$product]] + )->run(); $this->wishlistIndex->getMessagesBlock()->waitSuccessMessage(); $this->wishlistIndex->getWishlistBlock()->clickShareWishList(); $this->cmsIndex->getCmsPageBlock()->waitPageInit(); $this->wishlistShare->getSharingInfoForm()->fillForm($sharingInfo); $this->wishlistShare->getSharingInfoForm()->shareWishlist(); } - - /** - * Login customer. - * - * @param Customer $customer - * @return void - */ - protected function loginCustomer(Customer $customer) - { - $this->objectManager->create( - 'Magento\Customer\Test\TestStep\LoginCustomerOnFrontendStep', - ['customer' => $customer] - )->run(); - } } diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ViewProductInCustomerWishlistOnBackendTest.php b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ViewProductInCustomerWishlistOnBackendTest.php index 862a0fe4b34b92aaed8a8ec3976ae8ec13137657..0c2913116d0e28b0488f56f3d20f113e4ec6308f 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ViewProductInCustomerWishlistOnBackendTest.php +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ViewProductInCustomerWishlistOnBackendTest.php @@ -33,7 +33,6 @@ class ViewProductInCustomerWishlistOnBackendTest extends AbstractWishlistTest /* tags */ const MVP = 'no'; const DOMAIN = 'CS'; - const TO_MAINTAIN = 'yes'; /* end tags */ /** diff --git a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ViewProductInCustomerWishlistOnBackendTest.xml b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ViewProductInCustomerWishlistOnBackendTest.xml index ad4882298675403e262138326141123456e124c2..144d6a838c0d95af8bdf774035b671604bbfa1c6 100644 --- a/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ViewProductInCustomerWishlistOnBackendTest.xml +++ b/dev/tests/functional/tests/app/Magento/Wishlist/Test/TestCase/ViewProductInCustomerWishlistOnBackendTest.xml @@ -20,7 +20,6 @@ <constraint name="Magento\Bundle\Test\Constraint\AssertBundleProductInCustomerWishlistOnBackendGrid" /> </variation> <variation name="ViewProductInCustomerWishlistOnBackendTestVariation4"> - <data name="issue" xsi:type="string">Bug: MAGETWO-34633</data> <data name="product" xsi:type="string">downloadableProduct::with_two_separately_links</data> <constraint name="Magento\Downloadable\Test\Constraint\AssertDownloadableProductInCustomerWishlistOnBackendGrid" /> </variation> diff --git a/dev/tests/integration/IntegationTestsForTravis.sh b/dev/tests/integration/IntegationTestsForTravis.sh new file mode 100644 index 0000000000000000000000000000000000000000..cb4ce14e04a50f62c7b0c33c485b1265ad6911b7 --- /dev/null +++ b/dev/tests/integration/IntegationTestsForTravis.sh @@ -0,0 +1,44 @@ +#!usr/bin/bash + +# Copyright © 2015 Magento. All rights reserved. +# See COPYING.txt for license details. + +# Get number of files in directory +NUMBER_OF_SUITES=$1 +FOLDERSIZE=$(find ./testsuite/Magento/ -maxdepth 1 -type d|wc -l) +FOLDERSIZE=$((FOLDERSIZE/NUMBER_OF_SUITES)) + +# Get folders +FOLDERS=$(ls "./testsuite/Magento") + +# Create n testsuites +i=0 +for i in `seq 1 $NUMBER_OF_SUITES` +do + cp phpunit.xml.dist phpunit.xml.travis$i +done + +# Replace Memory Usage Tests in all except testsuite 1 +for i in `seq 2 $NUMBER_OF_SUITES` +do + perl -i -0pe 's/(<!-- Memory)(.*?)(<\/testsuite>)//ims' phpunit.xml.travis$i +done + +# Create list of folders on which tests are to be run +i=0 +j=1 +for FOLDER in $FOLDERS +do + FILE[j]+="\n<directory suffix=\"Test.php\">testsuite\/Magento\/${FOLDER}<\/directory>" + i=$((i+1)) + if [ "$i" -eq "$FOLDERSIZE" ] && [ "$j" -lt "$NUMBER_OF_SUITES" ]; then + j=$((j+1)) + i=0 + fi +done + +# Finally replacing in config files. +for i in `seq 1 $NUMBER_OF_SUITES` +do + perl -pi -e "s/<directory suffix=\"Test.php\">testsuite<\/directory>/${FILE[i]}/g" phpunit.xml.travis$i +done \ No newline at end of file diff --git a/dev/tests/integration/framework/Magento/TestFramework/Api/Config/Reader/FileResolver.php b/dev/tests/integration/framework/Magento/TestFramework/Api/Config/Reader/FileResolver.php new file mode 100644 index 0000000000000000000000000000000000000000..3b450d4b5f0faff53fa0c42ed22e238faf24ab9b --- /dev/null +++ b/dev/tests/integration/framework/Magento/TestFramework/Api/Config/Reader/FileResolver.php @@ -0,0 +1,88 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\TestFramework\Api\Config\Reader; + +/** + * Config file resolver for extension_attributes.xml files, which reads configs defined in tests. + * + * It is necessary because these configs are used during extension classes generation. And thus it is impossible + * to add customizations to the configs in concrete test, because respective extension class is already generated + * and loaded by the PHP. It is impossible to reload definition of the class, which is already loaded. + */ +class FileResolver extends \Magento\Framework\App\Config\FileResolver +{ + /** + * {@inheritdoc} + */ + public function get($filename, $scope) + { + return $this->merge(parent::get($filename, $scope), $this->getIntegrationTestConfigFiles()); + } + + /** + * Merge arrays or \Magento\Framework\Config\FileIterator into an array + * + * @param mixed $array1 + * @param mixed $array2,... + * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + protected function merge($array1, $array2) + { + $arguments = func_get_args(); + $arraysToMerge = []; + foreach ($arguments as $argument) { + $arraysToMerge[] = is_array($argument) ? $argument : $this->convertToArray($argument); + } + return call_user_func_array('array_merge', $arraysToMerge); + } + + /** + * Return a list of test config files + * + * Looks for config files located at + * dev/tests/integration/testsuite/Magento/*\/etc/extension_attributes.xml + * dev/tests/integration/testsuite/Magento/Framework/*\/etc/extension_attributes.xml + * + * @return array + */ + protected function getIntegrationTestConfigFiles() + { + $filePatterns = [ + 'dev/tests/integration/testsuite/Magento/*/etc/extension_attributes.xml', + 'dev/tests/integration/testsuite/Magento/Framework/*/etc/extension_attributes.xml' + ]; + + $filesArray = []; + foreach ($filePatterns as $pattern) { + foreach (glob(BP . '/' . $pattern) as $file) { + $content = file_get_contents($file); + if ($content) { + $filesArray[$file] = $content; + } + } + } + return $filesArray; + } + + /** + * Convert an argument to an array + * + * If it's not FileIterator instance, then empty array will be returned + * + * @param mixed $argument + * @return array + */ + protected function convertToArray($argument) + { + $resultArray = []; + if ($argument instanceof \Magento\Framework\Config\FileIterator) { + $resultArray = $argument->toArray(); + } + return $resultArray; + } +} diff --git a/dev/tests/integration/framework/Magento/TestFramework/Application.php b/dev/tests/integration/framework/Magento/TestFramework/Application.php index 7c652997b1fb3ebf0fda11b2eaafe24658f5e785..dc457df4db0f0f9fdcd5c7cb13f1ff6f6afe4e6f 100644 --- a/dev/tests/integration/framework/Magento/TestFramework/Application.php +++ b/dev/tests/integration/framework/Magento/TestFramework/Application.php @@ -331,6 +331,11 @@ class Application 'Magento\Framework\Mail\Template\TransportBuilder' => 'Magento\TestFramework\Mail\Template\TransportBuilderMock', ], + 'Magento\Framework\Api\ExtensionAttribute\Config\Reader' => [ + 'arguments' => [ + 'fileResolver' => ['instance' => 'Magento\TestFramework\Api\Config\Reader\FileResolver'], + ], + ], ] ); diff --git a/dev/tests/integration/framework/bootstrap.php b/dev/tests/integration/framework/bootstrap.php index 32fabb2269a4453e5762790ea11c61d0a0c60ae0..2f607671fe7736eac1da2fb0f704f2b52b8eb5fc 100644 --- a/dev/tests/integration/framework/bootstrap.php +++ b/dev/tests/integration/framework/bootstrap.php @@ -14,9 +14,12 @@ if (file_exists($updateAppBootstrap)) { } $testsBaseDir = dirname(__DIR__); -$testsTmpDir = "{$testsBaseDir}/tmp"; $magentoBaseDir = realpath("{$testsBaseDir}/../../../"); +if (!defined('TESTS_TEMP_DIR')) { + define('TESTS_TEMP_DIR', $testsBaseDir . '/tmp'); +} + try { /* Bootstrap the application */ $settings = new \Magento\TestFramework\Bootstrap\Settings($testsBaseDir, get_defined_constants()); @@ -41,7 +44,7 @@ try { $globalConfigFile .= '.dist'; } $sandboxUniqueId = md5(sha1_file($installConfigFile)); - $installDir = "{$testsTmpDir}/sandbox-{$settings->get('TESTS_PARALLEL_THREAD', 0)}-{$sandboxUniqueId}"; + $installDir = TESTS_TEMP_DIR . "/sandbox-{$settings->get('TESTS_PARALLEL_THREAD', 0)}-{$sandboxUniqueId}"; $application = new \Magento\TestFramework\Application( $shell, $installDir, @@ -75,7 +78,7 @@ try { \Magento\Framework\App\Utility\Files::setInstance(new Magento\Framework\App\Utility\Files($magentoBaseDir)); /* Unset declared global variables to release the PHPUnit from maintaining their values between tests */ - unset($testsBaseDir, $testsTmpDir, $magentoBaseDir, $logWriter, $settings, $shell, $application, $bootstrap); + unset($testsBaseDir, $magentoBaseDir, $logWriter, $settings, $shell, $application, $bootstrap); } catch (\Exception $e) { echo $e . PHP_EOL; exit(1); diff --git a/dev/tests/integration/phpunit.xml.dist b/dev/tests/integration/phpunit.xml.dist index bd6cbffb247d64f6617eef5fc9c8ebaebb753b7e..ef8df73676a75e506083b4c7d0bac1a94f2acbb2 100644 --- a/dev/tests/integration/phpunit.xml.dist +++ b/dev/tests/integration/phpunit.xml.dist @@ -29,6 +29,13 @@ <directory suffix=".php">../../../app/code/Magento</directory> <directory suffix=".php">../../../lib/internal/Magento</directory> <directory suffix=".php">../../../update/app/code</directory> + <exclude> + <directory>../../../app/code/*/*/Test</directory> + <directory>../../../lib/internal/*/*/Test</directory> + <directory>../../../lib/internal/*/*/*/Test</directory> + <directory>../../../setup/src/*/*/Test</directory> + <directory>../../../update/app/code/*/*/Test</directory> + </exclude> </whitelist> </filter> <!-- PHP INI settings and constants definition --> diff --git a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/AuthTest.php b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/AuthTest.php index 277ddde0a3d394ffb4d0dde65a644e5e73dab3ee..6d0b535d0c615357944904d508aa28f24df61d55 100644 --- a/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/AuthTest.php +++ b/dev/tests/integration/testsuite/Magento/Backend/Controller/Adminhtml/AuthTest.php @@ -186,7 +186,10 @@ class AuthTest extends \Magento\TestFramework\TestCase\AbstractController { $this->getRequest()->setPostValue($params); $this->dispatch('backend/admin/auth/login'); - $this->assertContains('Please correct the user name or password.', $this->getResponse()->getBody()); + $this->assertContains( + 'You did not sign in correctly or your account is temporarily disabled.', + $this->getResponse()->getBody() + ); } public function incorrectLoginDataProvider() diff --git a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php index 465cfc2f42ea744fb59d3e2cde3b1d71ea8ab42f..6021353adea102f0f96cd03ce3df58ef383c2d79 100644 --- a/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php +++ b/dev/tests/integration/testsuite/Magento/Bundle/Model/Product/TypeTest.php @@ -56,7 +56,7 @@ class TypeTest extends \PHPUnit_Framework_TestCase { $this->indexer->reindexAll(); - $select = $this->adapter->select()->from($this->resource->getTableName('catalogsearch_fulltext')) + $select = $this->adapter->select()->from($this->resource->getTableName('catalogsearch_fulltext_index_default')) ->where('`data_index` LIKE ?', '%' . 'Bundle Product Items' . '%'); $result = $this->adapter->fetchAll($select); diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/etc/service_data_attributes.xml b/dev/tests/integration/testsuite/Magento/Catalog/_files/etc/extension_attributes.xml similarity index 96% rename from dev/tests/integration/testsuite/Magento/Catalog/_files/etc/service_data_attributes.xml rename to dev/tests/integration/testsuite/Magento/Catalog/_files/etc/extension_attributes.xml index 93cf7bfb484a6de773ab318549385ad2436f2fa4..eb77caf25a42e1734cecebec596ff8150ed36e6a 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/etc/service_data_attributes.xml +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> </extension_attributes> <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractTest.php index 90f43ff42ae496d6bbea21f740ed08843a4be7b1..72f5bc6f82d8f18eec21d07e8523ae5569dcc8d1 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractTest.php @@ -46,7 +46,7 @@ class AbstractTest extends \PHPUnit_Framework_TestCase { return [ 'Updating existing product with attributes that do not have default values' => [ - ['sku' => 'simple_product_1', 'price' => 55, '_attribute_set' => 'Default', '_type' => 'simple'], + ['sku' => 'simple_product_1', 'price' => 55, '_attribute_set' => 'Default', 'product_type' => 'simple'], false, ['price' => 55], ], @@ -55,8 +55,8 @@ class AbstractTest extends \PHPUnit_Framework_TestCase 'sku' => 'simple_product_2', 'price' => 65, '_attribute_set' => 'Default', - '_type' => 'simple', - 'visibility' => 1, + 'product_type' => 'simple', + 'visibility' => 'not visible individually', 'tax_class_id' => '', ], false, @@ -65,11 +65,11 @@ class AbstractTest extends \PHPUnit_Framework_TestCase 'Adding new product with attributes that do not have default values' => [ [ 'sku' => 'simple_product_3', - '_store' => '', + 'store_view_code' => '', '_attribute_set' => 'Default', - '_type' => 'simple', - '_category' => '_root_category', - '_product_websites' => 'base', + 'product_type' => 'simple', + 'categories' => '_root_category', + 'website_code' => '', 'name' => 'Simple Product 3', 'price' => 150, 'status' => 1, @@ -77,7 +77,7 @@ class AbstractTest extends \PHPUnit_Framework_TestCase 'weight' => 1, 'description' => 'a', 'short_description' => 'a', - 'visibility' => 1, + 'visibility' => 'not visible individually', ], true, [ @@ -96,11 +96,11 @@ class AbstractTest extends \PHPUnit_Framework_TestCase 'Adding new product with attributes that have default values' => [ [ 'sku' => 'simple_product_4', - '_store' => '', + 'store_view_code' => '', '_attribute_set' => 'Default', - '_type' => 'simple', - '_category' => '_root_category', - '_product_websites' => 'base', + 'product_type' => 'simple', + 'categories' => '_root_category', + 'website_code' => 'base', 'name' => 'Simple Product 4', 'price' => 100, 'status' => 1, @@ -108,7 +108,7 @@ class AbstractTest extends \PHPUnit_Framework_TestCase 'weight' => 1, 'description' => 'a', 'short_description' => 'a', - 'visibility' => 2, + 'visibility' => 'catalog', 'msrp_display_actual_price_type' => 'In Cart', ], true, @@ -146,17 +146,17 @@ class AbstractTest extends \PHPUnit_Framework_TestCase [ [ 'sku' => 'simple1', - '_store' => '', + 'store_view_code' => '', '_attribute_set' => 'Default', - '_type' => 'simple', + 'product_type' => 'simple', 'name' => 'Simple 01', 'price' => 10, ], [ 'sku' => 'simple1', - '_store' => '', + 'store_view_code' => '', '_attribute_set' => 'Default', - '_type' => 'simple', + 'product_type' => 'simple', 'name' => 'Simple 01', 'price' => 10 ], @@ -164,17 +164,17 @@ class AbstractTest extends \PHPUnit_Framework_TestCase [ [ 'sku' => '', - '_store' => 'German', + 'store_view_code' => 'German', '_attribute_set' => 'Default', - '_type' => '', + 'product_type' => '', 'name' => 'Simple 01 German', 'price' => '', ], [ 'sku' => '', - '_store' => 'German', + 'store_view_code' => 'German', '_attribute_set' => 'Default', - '_type' => '', + 'product_type' => '', 'name' => 'Simple 01 German' ] ] diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index d3e665a753e5b1e401de8675209dbd64650b49d8..5dc83110bba57763362bbe0053a873650f905e7e 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -115,7 +115,7 @@ class ProductTest extends \PHPUnit_Framework_TestCase $directory ); $this->_model->setParameters( - ['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE, 'entity' => 'catalog_product'] + ['behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, 'entity' => 'catalog_product'] )->setSource( $source )->isDataValid(); @@ -443,10 +443,12 @@ class ProductTest extends \PHPUnit_Framework_TestCase foreach ($options->getItems() as $option) { $lastOptionKey = $option->getType() . '|' . $option->getTitle(); $actualOptionId++; - $actualOptions[$actualOptionId] = $lastOptionKey; - $actualData[$actualOptionId] = $this->_getOptionData($option); - if ($optionValues = $this->_getOptionValues($option)) { - $actualValues[$actualOptionId] = $optionValues; + if (!in_array($lastOptionKey, $actualOptions)) { + $actualOptions[$actualOptionId] = $lastOptionKey; + $actualData[$actualOptionId] = $this->_getOptionData($option); + if ($optionValues = $this->_getOptionValues($option)) { + $actualValues[$actualOptionId] = $optionValues; + } } } return [ @@ -516,16 +518,6 @@ class ProductTest extends \PHPUnit_Framework_TestCase '$behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND, '$importFile' => 'product_with_custom_options_new.csv', '$sku' => 'simple_new', - ], - 'Replace behavior with existing product' => [ - '$behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE, - '$importFile' => 'product_with_custom_options.csv', - '$sku' => 'simple', - ], - 'Replace behavior with new product' => [ - '$behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE, - '$importFile' => 'product_with_custom_options_new.csv', - '$sku' => 'simple_new', ] ]; } @@ -769,7 +761,6 @@ class ProductTest extends \PHPUnit_Framework_TestCase $errors = $this->_model->getErrorMessages(); $expectedErrors = [ "Please correct the value for 'multiselect_attribute'." => [2], - "Orphan rows that will be skipped due default row errors" => [3,4], ]; foreach ($expectedErrors as $message => $invalidRows) { $this->assertArrayHasKey($message, $errors); @@ -816,7 +807,6 @@ class ProductTest extends \PHPUnit_Framework_TestCase $id = $simpleProduct->getIdBySku('Configurable 03-option_0'); $simpleProduct->load($id); $this->assertEquals('Option Label', $simpleProduct->getAttributeText('attribute_with_option')); - $this->assertEquals([2, 4], $simpleProduct->getAvailableInCategories()); } /** diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_to_import_invalid_weight.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_to_import_invalid_weight.csv index 02b5c012bee1e9a4bb05bd9e677cb4b7a6f3b0bd..85c56f1cf7ae16ed2e7bf390bea515e867727fd6 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_to_import_invalid_weight.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_to_import_invalid_weight.csv @@ -1,4 +1,4 @@ -sku,_store,name,price,_type,_attribute_set,weight +sku,store_view_code,name,price,product_type,attribute_set_code,weight simple1,,"simple 1",10,simple,Default,2 simple2,,"simple 2",20,simple,Default,-5 simple3,,"simple 3",30,simple,Default,0 diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options.csv index cce02f6edfc2174746ef825b424c3d85d44a2bce..17106cdac132c22cbfe8c2e0472df7b9ebc09867 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options.csv @@ -1,13 +1,2 @@ -"sku","_store","_attribute_set","_type","_category","_root_category","_product_websites","color","cost","country_of_manufacture","created_at","custom_design","custom_design_from","custom_design_to","custom_layout_update","description","gallery","gift_message_available","has_options","image","image_label","manufacturer","media_gallery","meta_description","meta_keyword","meta_title","minimal_price","msrp","msrp_display_actual_price_type","msrp_enabled","name","news_from_date","news_to_date","options_container","page_layout","price","required_options","short_description","small_image","small_image_label","special_from_date","special_price","special_to_date","status","tax_class_id","thumbnail","thumbnail_label","updated_at","url_key","url_path","visibility","weight","qty","min_qty","use_config_min_qty","is_qty_decimal","backorders","use_config_backorders","min_sale_qty","use_config_min_sale_qty","max_sale_qty","use_config_max_sale_qty","is_in_stock","notify_stock_qty","use_config_notify_stock_qty","manage_stock","use_config_manage_stock","use_config_qty_increments","qty_increments","use_config_enable_qty_inc","enable_qty_increments","is_decimal_divided","_related_sku","_related_position","_crosssell_sku","_crosssell_position","_upsell_sku","_upsell_position","_associated_sku","_associated_default_qty","_associated_position","_tier_price_website","_tier_price_customer_group","_tier_price_qty","_tier_price_price","_group_price_website","_group_price_customer_group","_group_price_price","_media_attribute_id","_media_image","_media_label","_media_position","_media_is_disabled","_custom_option_store","_custom_option_type","_custom_option_title","_custom_option_is_required","_custom_option_price","_custom_option_sku","_custom_option_max_characters","_custom_option_sort_order","_custom_option_row_title","_custom_option_row_price","_custom_option_row_sku","_custom_option_row_sort" -"simple",,"Default","simple",,,"base",,,,,,,,,,,,1,,,,,,,,,,,,"New Product",,,"Block after Info Column",,"10.0000",1,,,,,,,1,,,,"2012-07-13 12:04:17","new-product","new-product.html",4,,"100.0000","0.0000",1,0,0,1,"1.0000",1,"0.0000",1,1,,1,0,1,1,"0.0000",1,0,0,,,,,,,,,,,,,,,,,,,,,,,"field","Test Field",1,"1.0000","1-text",100,0,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,default,,"Test Field",,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"date_time","Test Date and Time",1,"2.0000","2-date",,0,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,default,,"Test Date and Time",,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"drop_down","New Select",1,,,,0,"Option 1","3.0000","3-1-select",0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"Option 2","3.0000","3-2-select",0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"default",,,,,,,,"Option 1",,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"default",,,,,,,,"Option 2",,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"radio","New Radio",1,,,,0,"Option 1","3.0000","4-1-radio",0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"Option 2","3.0000","4-2-radio",0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"default",,,,,,,,"Option 1",,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"default",,,,,,,,"Option 2",,, +sku,website_code,store_view_code,attribute_set_code,product_type,name,description,short_description,weight,product_online,visibility,product_websites,categories,price,special_price,special_price_from_date,special_price_to_date,tax_class_name,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,additional_images,additional_image_labels,configurable_variation_labels,configurable_variations,bundle_price_type,bundle_sku_type,bundle_weight_type,bundle_values,downloadble_samples,downloadble_links,associated_skus,related_skus,crosssell_skus,upsell_skus,custom_options,additional_attributes,manage_stock,is_in_stock,qty,out_of_stock_qty,is_qty_decimal,allow_backorders,min_cart_qty,max_cart_qty,notify_on_stock_below,qty_increments,enable_qty_increments,is_decimal_divided,new_from_date,new_to_date,gift_message_available,created_at,updated_at,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_price,msrp_display_actual_price_type,map_enabled +simple,base,,Default,simple,New Product,,,9,1,"Catalog, Search",base,,10,,,,Taxable Goods,new-product,,,,,,,,,,,,,,,,,,,,,,,,"name=Test Field Title,type=field,required=1;sku=1-text,price=0,price_type=fixed|name=Test Date and Time Title,type=date_time,required=1,price=2,option_title=custom option 1,sku=2-date|name=Test Select,type=drop_down,required=1,price=3,option_title=Option 1,sku=3-1-select|name=Test Select,type=drop_down,required=1,price=3,option_title=Option 2,sku=3-2-select|name=Test Radio,type=radio,required=1,price=3,option_title=Option 1,sku=4-1-radio|name=Test Radio,type=radio,required=1,price=3,option_title=Option 2,sku=4-2-radio",,1,1,999,0,0,0,1,10000,1,1,0,0,,,,,,,,,,,Block after Info Column,,, diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_new.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_new.csv index 20d46670371e621af5b8c337510fd277117bb5d0..5211dd576ae6a16a71cd9f3e03a8b9b6b000db78 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_new.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/product_with_custom_options_new.csv @@ -1,13 +1,2 @@ -"sku","_store","_attribute_set","_type","_category","_root_category","_product_websites","color","cost","country_of_manufacture","created_at","custom_design","custom_design_from","custom_design_to","custom_layout_update","description","gallery","gift_message_available","has_options","image","image_label","manufacturer","media_gallery","meta_description","meta_keyword","meta_title","minimal_price","msrp","msrp_display_actual_price_type","msrp_enabled","name","news_from_date","news_to_date","options_container","page_layout","price","required_options","short_description","small_image","small_image_label","special_from_date","special_price","special_to_date","status","tax_class_id","thumbnail","thumbnail_label","updated_at","url_key","url_path","visibility","weight","qty","min_qty","use_config_min_qty","is_qty_decimal","backorders","use_config_backorders","min_sale_qty","use_config_min_sale_qty","max_sale_qty","use_config_max_sale_qty","is_in_stock","notify_stock_qty","use_config_notify_stock_qty","manage_stock","use_config_manage_stock","use_config_qty_increments","qty_increments","use_config_enable_qty_inc","enable_qty_increments","is_decimal_divided","_related_sku","_related_position","_crosssell_sku","_crosssell_position","_upsell_sku","_upsell_position","_associated_sku","_associated_default_qty","_associated_position","_tier_price_website","_tier_price_customer_group","_tier_price_qty","_tier_price_price","_group_price_website","_group_price_customer_group","_group_price_price","_media_attribute_id","_media_image","_media_label","_media_position","_media_is_disabled","_custom_option_store","_custom_option_type","_custom_option_title","_custom_option_is_required","_custom_option_price","_custom_option_sku","_custom_option_max_characters","_custom_option_sort_order","_custom_option_row_title","_custom_option_row_price","_custom_option_row_sku","_custom_option_row_sort" -"simple_new",,"Default","simple",,,"base",,,,,,,,,,,,1,,,,,,,,,,,,"New Product",,,"Block after Info Column",,"10.0000",1,,,,,,,1,,,,"2012-07-13 12:04:17","new-product","new-product.html",4,,"100.0000","0.0000",1,0,0,1,"1.0000",1,"0.0000",1,1,,1,0,1,1,"0.0000",1,0,0,,,,,,,,,,,,,,,,,,,,,,,"field","Test Field",1,"1.0000","1-text",100,0,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,default,,"Test Field",,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"date_time","Test Date and Time",1,"2.0000","2-date",,0,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,default,,"Test Date and Time",,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"drop_down","New Select",1,,,,0,"Option 1","3.0000","3-1-select",0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"Option 2","3.0000","3-2-select",0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"default",,,,,,,,"Option 1",,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"default",,,,,,,,"Option 2",,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"radio","New Radio",1,,,,0,"Option 1","3.0000","4-1-radio",0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"Option 2","3.0000","4-2-radio",0 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"default",,,,,,,,"Option 1",,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"default",,,,,,,,"Option 2",,, +sku,store_view_code,attribute_set_code,product_type,categories,product_websites,color,cost,country_of_manufacture,created_at,custom_design,custom_design_from,custom_design_to,custom_layout_update,description,gallery,gift_message_available,has_options,image,image_label,manufacturer,media_gallery,meta_description,meta_keyword,meta_title,minimal_price,msrp,msrp_display_actual_price_type,msrp_enabled,name,news_from_date,news_to_date,options_container,page_layout,price,required_options,short_description,small_image,small_image_label,special_from_date,special_price,special_to_date,product_online,tax_class_name,thumbnail,thumbnail_label,updated_at,url_key,url_path,visibility,weight,qty,min_qty,use_config_min_qty,is_qty_decimal,backorders,use_config_backorders,min_sale_qty,use_config_min_sale_qty,max_sale_qty,use_config_max_sale_qty,is_in_stock,notify_stock_qty,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,_related_sku,_related_position,_crosssell_sku,_crosssell_position,_upsell_sku,_upsell_position,_associated_sku,_associated_default_qty,_associated_position,_tier_price_website,_tier_price_customer_group,_tier_price_qty,_tier_price_price,_group_price_website,_group_price_customer_group,_group_price_price,_media_attribute_id,_media_image,_media_label,_media_position,_media_is_disabled,custom_options +simple_new,,Default,simple,,,base,,,,,,,,,,,1,,,,,,,,,,,,New Product,,,Block after Info Column,,10,1,,,,,,,1,Taxable Goods,,,2012-07-13 12:04:17,new-product,new-product.html,"Catalog, Search",,100,0,1,0,0,1,1,1,0,1,1,,1,0,1,1,0,1,0,0,,,,,,,,,,,,,,,,,,,,,,"name=Test Field Title,type=field,required=1;sku=1-text,price=0,price_type=fixed|name=Test Date and Time Title,type=date_time,required=1,price=2,option_title=custom option 1,sku=2-date|name=New Select,type=drop_down,required=1,price=3,option_title=Option 1,sku=3-1-select|name=New Select,type=drop_down,required=1,price=3,option_title=Option 2,sku=3-2-select|name=New Radio,type=radio,required=1,price=3,option_title=Option 1,sku=4-1-radio|name=New Radio,type=radio,required=1,price=3,option_title=Option 2,sku=4-2-radio" diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_multiple_stores.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_multiple_stores.csv index 1dc4a16f7412d24e94eb5058f3f6736304b5555e..10299936a27ea2d3283e4d9b49ca93c9ea8be71f 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_multiple_stores.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_multiple_stores.csv @@ -1,6 +1,5 @@ -sku,_store,_attribute_set,_type,_category,_root_category,_product_websites,test_configurable,cost,country_of_manufacture,created_at,custom_design,custom_design_from,custom_design_to,custom_layout_update,description,gallery,gift_message_available,gift_wrapping_available,gift_wrapping_price,has_options,image,image_label,is_returnable,manufacturer,meta_description,meta_keyword,meta_title,minimal_price,msrp,msrp_display_actual_price_type,msrp_enabled,name,news_from_date,news_to_date,options_container,page_layout,price,quantity_and_stock_status,related_tgtr_position_behavior,related_tgtr_position_limit,required_options,short_description,attribute_with_option,small_image,small_image_label,special_from_date,special_price,special_to_date,status,tax_class_id,thumbnail,thumbnail_label,updated_at,upsell_tgtr_position_behavior,upsell_tgtr_position_limit,url_key,url_path,visibility,weight,qty,min_qty,use_config_min_qty,is_qty_decimal,backorders,use_config_backorders,min_sale_qty,use_config_min_sale_qty,max_sale_qty,use_config_max_sale_qty,is_in_stock,notify_stock_qty,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,_related_sku,_related_position,_crosssell_sku,_crosssell_position,_upsell_sku,_upsell_position,_associated_sku,_associated_default_qty,_associated_position,_tier_price_website,_tier_price_customer_group,_tier_price_qty,_tier_price_price,_group_price_website,_group_price_customer_group,_group_price_price,_media_attribute_id,_media_image,_media_label,_media_position,_media_is_disabled,_super_products_sku,_super_attribute_code,_super_attribute_option,_super_attribute_price_corr -"Configurable 03-option_0",,Default,virtual,"Category 1/Category 1.1","Default Category",base,Option 1,,,"2014-06-13 07:34:02",,,,,,,,,,0,,,"Use config",,"Configurable 03 ","Configurable 03","Configurable 03",,,"Use config","Use config","Configurable 03-option_0",,,"Block after Info Column",,10.0000,"In Stock",,,0,,,,,,,,1,2,,,"2014-06-13 07:35:59",,,configurable-03-option_0,configurable-03-option_0.html,1,,99999.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,1,1,1,0.0000,1,0,0,,,,,,,,,,,,,,,,,,,,,,,,, -,fixturestore,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"Option Label",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -"Configurable 03-option_1",,Default,virtual,"Category 1/Category 1.1","Default Category",base,Option 2,,,"2014-06-13 07:34:05",,,,,,,,,,0,,,"Use config",,"Configurable 03 ","Configurable 03","Configurable 03",,,"Use config","Use config","Configurable 03-option_1",,,"Block after Info Column",,10.0000,"In Stock",,,0,,,,,,,,1,2,,,"2014-06-13 07:34:05",,,configurable-03-option_1,configurable-03-option_1.html,1,,99999.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,1,1,1,0.0000,1,0,0,,,,,,,,,,,,,,,,,,,,,,,,, -"Configurable 03",,Default,configurable,"Category 1/Category 1.1","Default Category",base,,,,"2014-06-13 07:34:07",,,,,,,,,,1,,,"Use config",,"Configurable 03 ","Configurable 03","Configurable 03",,,"Use config","Use config","Configurable 03",,,"Block after Info Column",,10.0000,"In Stock",,,1,,,,,,,,1,2,,,"2014-06-13 07:36:32",,,configurable-03,configurable-03.html,4,,0.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,1,1,1,0.0000,1,0,0,,,,,,,,,,,,,,,,,,,,,,"Configurable 03-option_0",test_configurable,Option 1,1.0000 -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"Configurable 03-option_1",test_configurable,Option 2,2.0000 +sku,store_view_code,attribute_set_code,product_type,categories,product_websites,test_configurable,cost,country_of_manufacture,created_at,custom_design,custom_design_from,custom_design_to,custom_layout_update,description,gallery,gift_message_available,gift_wrapping_available,gift_wrapping_price,has_options,image,image_label,is_returnable,manufacturer,meta_description,meta_keyword,meta_title,minimal_price,msrp,msrp_display_actual_price_type,msrp_enabled,name,news_from_date,news_to_date,options_container,page_layout,price,quantity_and_stock_status,related_tgtr_position_behavior,related_tgtr_position_limit,required_options,short_description,attribute_with_option,small_image,small_image_label,special_from_date,special_price,special_to_date,product_online,tax_class_name,thumbnail,thumbnail_label,updated_at,upsell_tgtr_position_behavior,upsell_tgtr_position_limit,url_key,visibility,weight,qty,min_qty,use_config_min_qty,is_qty_decimal,backorders,use_config_backorders,min_sale_qty,use_config_min_sale_qty,max_sale_qty,use_config_max_sale_qty,is_in_stock,notify_stock_qty,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,_related_sku,_related_position,_crosssell_sku,_crosssell_position,_upsell_sku,_upsell_position,configurable_variations,configurable_variation_prices,configurable_variation_labels +Configurable 03-option_0,,Default,virtual,Default Category/Category 1/Category 1.1,base,Option 1,,,2014-06-13 07:34:02,,,,,,,,,,0,,,Use config,,Configurable 03 ,Configurable 03,Configurable 03,,,Use config,Use config,Configurable 03-option_0,,,Block after Info Column,,10,In Stock,,,0,,Option Label,,,,,,1,Taxable Goods,,,2014-06-13 07:35:59,,,configurable-03-option11,Search,,99999,0,1,0,0,1,1,1,0,1,1,,1,1,1,1,0,1,0,0,,,,,,,,, +Configurable 03-option_0,fixturestore,Default,virtual,Default Category/Category 1/Category 1.1,base,Option 1,,,2014-06-13 07:34:02,,,,,,,,,,,,,,,,,,,,,,Configurable 03-option_0,,,Block after Info Column,,10,,,,0,,Option Label,,,,,,,,,,,,,,Search,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Configurable 03-option_1,,Default,virtual,Default Category/Category 1/Category 1.1,base,Option 2,,,2014-06-13 07:34:05,,,,,,,,,,0,,,Use config,,Configurable 03 ,Configurable 03,Configurable 03,,,Use config,Use config,Configurable 03-option_1,,,Block after Info Column,,10,In Stock,,,0,,,,,,,,1,Taxable Goods,,,2014-06-13 07:34:05,,,configurable-03-option12,Search,,99999,0,1,0,0,1,1,1,0,1,1,,1,1,1,1,0,1,0,0,,,,,,,,, +Configurable 03,,Default,configurable,Default Category/Category 1/Category 1.1,base,,,,2014-06-13 07:34:07,,,,,,,,,,1,,,Use config,,Configurable 03 ,Configurable 03,Configurable 03,,,Use config,Use config,Configurable 03,,,Block after Info Column,,10,In Stock,,,1,,,,,,,,1,Taxable Goods,,,2014-06-13 07:36:32,,,Configurable-03-11,"Catalog, Search",,0,0,1,0,0,1,1,1,0,1,1,,1,1,1,1,0,1,0,0,,,,,,,"sku=Configurable 03-option_0,test_configurable=Option 1,display=1|sku=Configurable 03-option_1,test_configurable=Option 2,display=1","name=test_configurable,value=Option 1,price=1|name=test_configurable,value=Option 2,price=2", diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import.csv index 3f355c98e215216e5eea1dd7df8d463369e2f3e2..d8d879193d82e4526a46ee09b9226a5885bd2e45 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import.csv @@ -1,5 +1,5 @@ -sku,_store,name,price +sku,store_view_code,name,price simple1,,"simple 1",25 -,German,"simple 1 German", +simple1,German,"simple 1 German", simple2,,"simple 2",34 simple3,,"simple 3",58 diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_invalid_attribute_set.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_invalid_attribute_set.csv index 3f852c2b90c60551c6f2760016a2c29e9a8f5285..ae16f0735a163d9138cf7124cd5b88d9e078bed6 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_invalid_attribute_set.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_invalid_attribute_set.csv @@ -1,4 +1,4 @@ -sku,price,name,_type,_attribute_set,_upsell_sku,description +sku,price,name,product_type,_attribute_set,_upsell_sku,description simple1,25,"Simple Product",simple,Default,,description simple2,NULL,"Simple Product2",invalid attribute set,Default,,HiThere simple3,58,"Simple Product 3",simple,Default,simple2,description diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_qty.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_qty.csv index 1cc313c8429188c845763d38ac0ac0dfcaef1b0a..7872a16727763867dcf4d28723dd26a5d970f6c3 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_qty.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_to_import_with_qty.csv @@ -1,2 +1,2 @@ -sku,_store,name,price,qty,_type,_attribute_set,manage_stock +sku,store_view_code,name,price,qty,product_type,attribute_set_code,manage_stock simple1,,"simple 1",25,0.0000,simple,Default,1 diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_with_invalid_multiselect_values.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_with_invalid_multiselect_values.csv index 6aee29b2c1e5f66810f79a22f688ba0f66a5dc4d..b6da8449c9ccd80e53d52aab642c3e7f51fb5184 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_with_invalid_multiselect_values.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/products_with_invalid_multiselect_values.csv @@ -1,5 +1,3 @@ -sku,_store,_type,name,price,multiselect_attribute +sku,store_view_code,product_type,name,price,multiselect_attribute simple_ms_1,,simple,"With Multiselect 1",10,Option 1 -simple_ms_2,,simple,"With Multiselect 2",10,Option 5 -,,,,Option 2 -,,,,Option 3 +simple_ms_2,,simple,"With Multiselect 2",10,"Option 5,Option 2,Option 3" diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php index acf4ba7ebf5013ba0d801b28cb9283f1f535b63c..e55c777ef575588c077f2179c9f65dcaa46f5fdb 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AddressTest.php @@ -174,7 +174,7 @@ class AddressTest extends \Magento\TestFramework\TestCase\AbstractController $this->assertRedirect($this->stringContains('customer/address/index')); $this->assertSessionMessages( - $this->equalTo(['An error occurred while deleting the address.']), + $this->equalTo(['We can\'t delete the address right now.']), \Magento\Framework\Message\MessageInterface::TYPE_ERROR ); } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php index a52fef8b40a434b0f81df94a0d15bd88bc9b57c9..6eae4325406634be36b7e25ecc58000e3636243a 100755 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/Adminhtml/IndexTest.php @@ -981,7 +981,7 @@ class IndexTest extends \Magento\Backend\Utility\Controller $this->dispatch('backend/customer/index/validate'); $body = $this->getResponse()->getBody(); - $this->assertContains('{"error":1,"html_message":', $body); + $this->assertContains('{"error":true,"messages":', $body); $this->assertContains('Please correct this email address: \"*\".', $body); $this->assertContains('\"First Name\" is a required value.', $body); $this->assertContains('\"Last Name\" is a required value.', $body); diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AddressMetadataTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AddressMetadataTest.php index 1b9ad064466529226a1751f4a7c359931f6a1abd..09d7485a1dff22f059ea830e00648b50c443766b 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/AddressMetadataTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AddressMetadataTest.php @@ -18,7 +18,7 @@ class AddressMetadataTest extends \PHPUnit_Framework_TestCase $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $objectManager->configure( [ - 'Magento\Framework\Api\Config\Reader' => [ + 'Magento\Framework\Api\ExtensionAttribute\Config\Reader' => [ 'arguments' => [ 'fileResolver' => ['instance' => 'Magento\Customer\Model\FileResolverStub'], ], @@ -94,7 +94,7 @@ class AddressMetadataTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('Magento\Customer\Model\Data\AttributeMetadata', $attributeMetadata); $this->assertEquals('company', $attributeMetadata->getAttributeCode(), 'Attribute code is invalid'); $this->assertNotEmpty($attributeMetadata->getValidationRules(), 'Validation rules are not set'); - $this->assertEquals('varchar', $attributeMetadata->getBackendType(), 'Backend type is invalid'); + $this->assertEquals('static', $attributeMetadata->getBackendType(), 'Backend type is invalid'); $this->assertEquals('Company', $attributeMetadata->getFrontendLabel(), 'Frontend label is invalid'); } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php index 9ff582dc40c3c7c42afbedda308bc39d09b4db78..a0263163223c892c4bf1814f8805b286b4ff8629 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/CustomerMetadataTest.php @@ -28,7 +28,7 @@ class CustomerMetadataTest extends \PHPUnit_Framework_TestCase $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $objectManager->configure( [ - 'Magento\Framework\Api\Config\Reader' => [ + 'Magento\Framework\Api\ExtensionAttribute\Config\Reader' => [ 'arguments' => [ 'fileResolver' => ['instance' => 'Magento\Customer\Model\FileResolverStub'], ], diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/FileResolverStub.php b/dev/tests/integration/testsuite/Magento/Customer/Model/FileResolverStub.php index 9ee9ed911f7c092aac6034ed441e5c96f2e46aa2..7a288246a4881030b04b0664c13a2ed2875e2e9e 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/FileResolverStub.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/FileResolverStub.php @@ -21,7 +21,7 @@ class FileResolverStub implements \Magento\Framework\Config\FileResolverInterfac 'path' => realpath(__DIR__ . '/../_files/etc'), ] ); - $paths = ['service_data_attributes.xml']; + $paths = ['extension_attributes.xml']; return new \Magento\Framework\Config\FileIterator($readDirectory, $paths); } } diff --git a/dev/tests/integration/testsuite/Magento/Customer/_files/etc/service_data_attributes.xml b/dev/tests/integration/testsuite/Magento/Customer/_files/etc/extension_attributes.xml similarity index 96% rename from dev/tests/integration/testsuite/Magento/Customer/_files/etc/service_data_attributes.xml rename to dev/tests/integration/testsuite/Magento/Customer/_files/etc/extension_attributes.xml index a7ae041eda7683ce99dd168befc50c2ae5a46f3c..507e8fe20afc2d073bc459946acb829093699e78 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/_files/etc/service_data_attributes.xml +++ b/dev/tests/integration/testsuite/Magento/Customer/_files/etc/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> </extension_attributes> <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> diff --git a/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/AddressTest.php b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/AddressTest.php index 7811a44b6e3cb1ec6a469ded720f159d08f97848..df6a03e4fbc7093db9a83bb445b663329ba13a97 100644 --- a/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/AddressTest.php +++ b/dev/tests/integration/testsuite/Magento/CustomerImportExport/Model/Import/AddressTest.php @@ -246,7 +246,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase $addressId = $objectManager->get('Magento\ImportExport\Model\Resource\Helper') ->getNextAutoincrement($tableName); - $entityData = [ + $newEntityData = [ 'entity_id' => $addressId, 'parent_id' => $customerId, 'created_at' => (new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT), @@ -256,7 +256,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase // invoke _saveAddressEntities $saveAddressEntities = new \ReflectionMethod($this->_testClassName, '_saveAddressEntities'); $saveAddressEntities->setAccessible(true); - $saveAddressEntities->invoke($entityAdapter, $entityData); + $saveAddressEntities->invoke($entityAdapter, $newEntityData, []); return [$customerId, $addressId]; } @@ -268,6 +268,7 @@ class AddressTest extends \PHPUnit_Framework_TestCase */ public function testSaveAddressAttributes() { + $this->markTestSkipped("to test _saveAddressAttributes attribute need to add custom address attribute"); // get attributes list $attributesReflection = new \ReflectionProperty($this->_testClassName, '_attributes'); $attributesReflection->setAccessible(true); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/ReaderTest.php b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/Config/ReaderTest.php similarity index 77% rename from dev/tests/integration/testsuite/Magento/Framework/Api/Config/ReaderTest.php rename to dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/Config/ReaderTest.php index 07fceddb6424b3bc01d7e4448833cb92a709d6c9..e5fb4c8794a8e72807094e03c1676c598eb5cc8a 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/ReaderTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/Config/ReaderTest.php @@ -3,15 +3,15 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Framework\Api\Config; +namespace Magento\Framework\Api\ExtensionAttribute\Config; /** - * Tests for \Magento\Framework\Api\Config\Reader + * Tests for \Magento\Framework\Api\ExtensionAttribute\Config\Reader */ class ReaderTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\Api\Config\Reader + * @var \Magento\Framework\Api\ExtensionAttribute\Config\Reader */ protected $_model; @@ -31,12 +31,12 @@ class ReaderTest extends \PHPUnit_Framework_TestCase protected $_validationState; /** - * @var \Magento\Framework\Api\Config\SchemaLocator + * @var \Magento\Framework\Api\ExtensionAttribute\Config\SchemaLocator */ protected $_schemaLocator; /** - * @var \Magento\Framework\Api\Config\Converter + * @var \Magento\Framework\Api\ExtensionAttribute\Config\Converter */ protected $_converter; @@ -56,17 +56,17 @@ class ReaderTest extends \PHPUnit_Framework_TestCase ->method('get') ->will($this->returnValue($this->_fileList)); - $this->_converter = new \Magento\Framework\Api\Config\Converter(); + $this->_converter = new \Magento\Framework\Api\ExtensionAttribute\Config\Converter(); $this->_validationState = new \Magento\Framework\App\Arguments\ValidationState( \Magento\Framework\App\State::MODE_DEFAULT ); - $this->_schemaLocator = new \Magento\Framework\Api\Config\SchemaLocator(); + $this->_schemaLocator = new \Magento\Framework\Api\ExtensionAttribute\Config\SchemaLocator(); } public function testMerge() { - $model = new \Magento\Framework\Api\Config\Reader( + $model = new \Magento\Framework\Api\ExtensionAttribute\Config\Reader( $this->_fileResolverMock, $this->_converter, $this->_schemaLocator, @@ -79,20 +79,24 @@ class ReaderTest extends \PHPUnit_Framework_TestCase 'stock_item' => [ "type" => "Magento\CatalogInventory\Api\Data\StockItem", "resourceRefs" => [], + "join" => null, ], ], 'Magento\Customer\Api\Data\CustomerInterface' => [ 'custom_1' => [ "type" => "Magento\Customer\Api\Data\CustomerCustom", "resourceRefs" => [], + "join" => null, ], 'custom_2' => [ "type" => "Magento\CustomerExtra\Api\Data\CustomerCustom22", "resourceRefs" => [], + "join" => null, ], 'custom_3' => [ "type" => "Magento\Customer\Api\Data\CustomerCustom3", "resourceRefs" => [], + "join" => null, ], ], ]; diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_one.xml b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/Config/_files/config_one.xml similarity index 86% rename from dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_one.xml rename to dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/Config/_files/config_one.xml index 82aa641d5e8bd9040d9fa26689d95a09b74e19f3..3be36f43ab35694ce758d2d9461e194d0e355daf 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_one.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/Config/_files/config_one.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> </extension_attributes> <extension_attributes for="Magento\Catalog\Api\Data\Product"> diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_two.xml b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/Config/_files/config_two.xml similarity index 79% rename from dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_two.xml rename to dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/Config/_files/config_two.xml index 5596f61e572f4b076a1d850b38002b6a448a7297..f85a1a4d69efbe616970388f6e8de8f2e305fcd3 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Api/Config/_files/config_two.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/Config/_files/config_two.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Customer\Api\Data\CustomerInterface"> <attribute code="custom_2" type="Magento\CustomerExtra\Api\Data\CustomerCustom22" /> <attribute code="custom_3" type="Magento\Customer\Api\Data\CustomerCustom3" /> diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttributesFactoryTest.php b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttributesFactoryTest.php index 2c6ddf42f67cbbfc9edb55330c4ae09f387807ae..674fc1432f0ef7e6d0eb0ee177f9ac9e25f5e87c 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttributesFactoryTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttributesFactoryTest.php @@ -5,18 +5,71 @@ */ namespace Magento\Framework\Api; +use Magento\Framework\Api\ExtensionAttribute\Config\Converter; +use Magento\Framework\Api\ExtensionAttribute\Config\Reader; +use Magento\Framework\Api\ExtensionAttribute\JoinData; +use Magento\Framework\Api\ExtensionAttribute\JoinDataFactory; +use Magento\Framework\Reflection\TypeProcessor; +use Magento\Framework\App\Resource; + class ExtensionAttributesFactoryTest extends \PHPUnit_Framework_TestCase { /** @var \Magento\Framework\Api\ExtensionAttributesFactory */ private $factory; + /** + * @var Reader|\PHPUnit_Framework_MockObject_MockObject + */ + private $config; + + /** + * @var JoinDataFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $extensionAttributeJoinDataFactory; + + /** + * @var TypeProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + private $typeProcessor; + + /** + * @var AppResource|\PHPUnit_Framework_MockObject_MockObject + */ + private $appResource; + protected function setUp() { + $this->config = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\Config') + ->disableOriginalConstructor() + ->getMock(); + $this->extensionAttributeJoinDataFactory = $this + ->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\JoinDataFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->extensionAttributeJoinDataFactory = $this + ->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\JoinDataFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->typeProcessor = $this->getMockBuilder('Magento\Framework\Reflection\TypeProcessor') + ->disableOriginalConstructor() + ->getMock(); + $autoloadWrapper = \Magento\Framework\Autoload\AutoloaderRegistry::getAutoloader(); $autoloadWrapper->addPsr4('Magento\\Wonderland\\', realpath(__DIR__ . '/_files/Magento/Wonderland')); /** @var \Magento\Framework\ObjectManagerInterface */ $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - $this->factory = new ExtensionAttributesFactory($objectManager); + + $this->appResource = $objectManager->get('Magento\Framework\App\Resource'); + + $this->factory = $objectManager->create( + 'Magento\Framework\Api\ExtensionAttributesFactory', + [ + 'objectManager' => $objectManager, + 'config' => $this->config, + 'extensionAttributeJoinDataFactory' => $this->extensionAttributeJoinDataFactory, + 'typeProcessor' => $this->typeProcessor + ] + ); } /** @@ -50,4 +103,248 @@ class ExtensionAttributesFactoryTest extends \PHPUnit_Framework_TestCase $this->factory->create('Magento\Wonderland\Model\Data\FakeRegion') ); } + + /** + * Test the processing of the join config for a particular type + */ + public function testProcess() + { + $this->config->expects($this->once()) + ->method('get') + ->will($this->returnValue($this->getConfig())); + + $collection = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->setMethods(['joinExtensionAttribute']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + + $extensionAttributeJoinData = new JoinData(); + $this->extensionAttributeJoinDataFactory + ->expects($this->once()) + ->method('create') + ->willReturn($extensionAttributeJoinData); + + $collection->expects($this->once())->method('joinExtensionAttribute')->with($extensionAttributeJoinData); + + $this->factory->process($collection, 'Magento\Catalog\Api\Data\ProductInterface'); + $expectedTableName = 'reviews'; + $this->assertEquals($expectedTableName, $extensionAttributeJoinData->getReferenceTable()); + $this->assertEquals('extension_attribute_review_id', $extensionAttributeJoinData->getReferenceTableAlias()); + $this->assertEquals('product_id', $extensionAttributeJoinData->getReferenceField()); + $this->assertEquals('id', $extensionAttributeJoinData->getJoinField()); + $this->assertEquals(['review_id'], $extensionAttributeJoinData->getSelectFields()); + } + + private function getConfig() + { + return [ + 'Magento\Catalog\Api\Data\ProductInterface' => [ + 'review_id' => [ + Converter::DATA_TYPE => 'string', + Converter::RESOURCE_PERMISSIONS => [], + Converter::JOIN_DIRECTIVE => [ + Converter::JOIN_REFERENCE_TABLE => "reviews", + Converter::JOIN_REFERENCE_FIELD => "product_id", + Converter::JOIN_SELECT_FIELDS => [ + [ + Converter::JOIN_SELECT_FIELD => "review_id", + ], + ], + Converter::JOIN_JOIN_ON_FIELD => "id", + ], + ], + ], + 'Magento\Customer\Api\Data\CustomerInterface' => [ + 'library_card_id' => [ + Converter::DATA_TYPE => 'string', + Converter::RESOURCE_PERMISSIONS => [], + Converter::JOIN_DIRECTIVE => [ + Converter::JOIN_REFERENCE_TABLE => "library_account", + Converter::JOIN_SELECT_FIELDS => [ + [ + Converter::JOIN_SELECT_FIELD => "library_card_id", + ], + ], + Converter::JOIN_JOIN_ON_FIELD => "customer_id", + ], + ], + 'reviews' => [ + Converter::DATA_TYPE => 'Magento\Reviews\Api\Data\Reviews[]', + Converter::RESOURCE_PERMISSIONS => [], + Converter::JOIN_DIRECTIVE => [ + Converter::JOIN_REFERENCE_TABLE => "reviews", + Converter::JOIN_SELECT_FIELDS => [ + [ + Converter::JOIN_SELECT_FIELD => "comment", + ], + [ + Converter::JOIN_SELECT_FIELD => "rating", + ], + ], + Converter::JOIN_JOIN_ON_FIELD => "customer_id", + ], + ], + ], + ]; + } + + public function testProcessSqlSelectVerification() + { + /** @var \Magento\Framework\ObjectManagerInterface */ + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + /** @var \Magento\Framework\Api\ExtensionAttribute\Config $config */ + $config = $objectManager->get('Magento\Framework\Api\ExtensionAttribute\Config'); + $config->reset(); + + $extensionConfigFileResolverMock = $this->getMockBuilder('Magento\Framework\Config\FileResolverInterface') + ->disableOriginalConstructor() + ->getMock(); + $extensionConfigFilePath = __DIR__ . '/_files/extension_attributes.xml'; + $extensionConfigFileContent = file_get_contents($extensionConfigFilePath); + $extensionConfigFileResolverMock->expects($this->any()) + ->method('get') + ->willReturn([$extensionConfigFilePath => $extensionConfigFileContent]); + $configReader = $objectManager->create( + 'Magento\Framework\Api\ExtensionAttribute\Config\Reader', + ['fileResolver' => $extensionConfigFileResolverMock] + ); + /** @var \Magento\Framework\Api\ExtensionAttribute\Config $config */ + $config = $objectManager->create( + 'Magento\Framework\Api\ExtensionAttribute\Config', + ['reader' => $configReader] + ); + /** @var \Magento\Framework\Api\ExtensionAttributesFactory $extensionAttributesFactory */ + $extensionAttributesFactory = $objectManager->create( + 'Magento\Framework\Api\ExtensionAttributesFactory', + ['config' => $config] + ); + $productClassName = 'Magento\Catalog\Model\Product'; + /** @var \Magento\Catalog\Model\Resource\Product\Collection $collection */ + $collection = $objectManager->create('Magento\Catalog\Model\Resource\Product\Collection'); + + $extensionAttributesFactory->process($collection, $productClassName); + $config->reset(); + + $catalogProductEntity = $this->appResource->getTableName('catalog_product_entity'); + $catalogInventoryStockItem = $this->appResource->getTableName('cataloginventory_stock_item'); + $reviews = $this->appResource->getTableName('reviews'); + $expectedSql = <<<EXPECTED_SQL +SELECT `e`.*, + `extension_attribute_stock_item`.`qty` AS `extension_attribute_stock_item_qty`, + `extension_attribute_reviews`.`comment` AS `extension_attribute_reviews_comment`, + `extension_attribute_reviews`.`rating` AS `extension_attribute_reviews_rating`, + `extension_attribute_reviews`.`date` AS `extension_attribute_reviews_date` FROM `$catalogProductEntity` AS `e` + LEFT JOIN `$catalogInventoryStockItem` AS `extension_attribute_stock_item` ON e.id = extension_attribute_stock_item.id + LEFT JOIN `$reviews` AS `extension_attribute_reviews` ON e.id = extension_attribute_reviews.product_id +EXPECTED_SQL; + $resultSql = $collection->getSelectSql(true); + $formattedResultSql = str_replace(',', ",\n ", $resultSql); + $this->assertEquals($expectedSql, $formattedResultSql); + } + + /** + * @magentoDataFixture Magento/Catalog/_files/products.php + */ + public function testGetListWithExtensionAttributesAbstractModel() + { + $firstProductId = 1; + $firstProductQty = 11; + $secondProductId = 2; + $secondProductQty = 22; + /** @var \Magento\Framework\ObjectManagerInterface */ + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ + $productRepository = $objectManager->create('Magento\Catalog\Api\ProductRepositoryInterface'); + /** @var \Magento\CatalogInventory\Api\StockItemRepositoryInterface $stockItemRepository */ + $stockItemRepository = $objectManager->get('Magento\CatalogInventory\Api\StockItemRepositoryInterface'); + + /** Prepare stock items */ + $firstStockItem = $productRepository->getById($firstProductId)->getExtensionAttributes()->getStockItem(); + $firstStockItem->setQty($firstProductQty); + $stockItemRepository->save($firstStockItem); + $this->assertEquals( + $firstProductQty, + $productRepository->getById($firstProductId)->getExtensionAttributes()->getStockItem()->getQty(), + 'Precondition failed.' + ); + $secondStockItem = $productRepository->getById($secondProductId)->getExtensionAttributes()->getStockItem(); + $secondStockItem->setQty($secondProductQty); + $stockItemRepository->save($secondStockItem); + $this->assertEquals( + $secondProductQty, + $productRepository->getById($secondProductId)->getExtensionAttributes()->getStockItem()->getQty(), + 'Precondition failed.' + ); + + /** @var \Magento\Framework\Api\Search\FilterGroup $searchCriteriaGroup */ + $searchCriteriaGroup = $objectManager->create('Magento\Framework\Api\Search\FilterGroup'); + /** @var \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria */ + $searchCriteria = $objectManager->create('Magento\Framework\Api\SearchCriteriaInterface'); + $searchCriteria->setFilterGroups([$searchCriteriaGroup]); + $products = $productRepository->getList($searchCriteria)->getItems(); + + /** Ensure that simple extension attributes were populated correctly */ + $this->assertEquals( + $firstProductQty, + $products[$firstProductId]->getExtensionAttributes()->getTestStockItemQty() + ); + $this->assertEquals( + $secondProductQty, + $products[$secondProductId]->getExtensionAttributes()->getTestStockItemQty() + ); + + /** Check population of complex extension attributes */ + $this->assertEquals( + $firstProductQty, + $products[$firstProductId]->getExtensionAttributes()->getTestStockItem()->getQty() + ); + $this->assertNotEmpty($products[$firstProductId]->getExtensionAttributes()->getTestStockItem()->getItemId()); + + $this->assertArrayNotHasKey( + 'extension_attribute_test_stock_item_qty_qty', + $products[$firstProductId]->getData(), + "Selected extension field should be unset after it is added to extension attributes object." + ); + } + + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + * @magentoDataFixture Magento/Customer/_files/customer_group.php + */ + public function testGetListWithExtensionAttributesAbstractObject() + { + $customerId = 1; + $customerGroupName = 'General'; + $taxClassId = 3; + /** @var \Magento\Framework\ObjectManagerInterface */ + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + + /** @var \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository */ + $customerRepository = $objectManager->get('Magento\Customer\Api\CustomerRepositoryInterface'); + /** @var \Magento\Framework\Api\Search\FilterGroup $searchCriteriaGroup */ + $searchCriteriaGroup = $objectManager->create('Magento\Framework\Api\Search\FilterGroup'); + /** @var \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria */ + $searchCriteria = $objectManager->create('Magento\Framework\Api\SearchCriteriaInterface'); + $searchCriteria->setFilterGroups([$searchCriteriaGroup]); + $customers = $customerRepository->getList($searchCriteria)->getItems(); + + /** Ensure that simple extension attributes were populated correctly */ + $customer = $customers[0]; + $this->assertEquals($customerId, $customer->getId(), 'Precondition failed'); + $this->assertEquals($customerGroupName, $customer->getExtensionAttributes()->getTestGroupCode()); + + /** Check population of complex extension attributes */ + $this->assertEquals($taxClassId, $customer->getExtensionAttributes()->getTestGroup()->getTaxClassId()); + $this->assertEquals($customerGroupName, $customer->getExtensionAttributes()->getTestGroup()->getCode()); + } + + public function testCreateWithLogicException() + { + $this->setExpectedException( + 'LogicException', + "Class 'Magento\\Framework\\Api\\ExtensionAttributesFactoryTest' must implement an interface, " + . "which extends from 'Magento\\Framework\\Api\\ExtensibleDataInterface'" + ); + $this->factory->create(get_class($this)); + } } diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/_files/extension_attributes.xml b/dev/tests/integration/testsuite/Magento/Framework/Api/_files/extension_attributes.xml new file mode 100644 index 0000000000000000000000000000000000000000..4b47d317898abda10226f72f7dac4a04004a6ad3 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/_files/extension_attributes.xml @@ -0,0 +1,36 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> + <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> + <attribute code="stock_item" type="Magento\CatalogInventory\Api\Data\StockItemInterface"> + <resources> + <resource ref="Magento_CatalogInventory::cataloginventory"/> + </resources> + <join reference_table="cataloginventory_stock_item" + join_on_field="id" + reference_field="id" + > + <select_field>qty</select_field> + </join> + </attribute> + <attribute code="reviews" type="Magento\Reviews\Api\Data\Reviews[]"> + <join reference_table="reviews" + reference_field="product_id" + join_on_field="id" + > + <select_field>comment</select_field> + <select_field>rating</select_field> + <select_field>date</select_field> + </join> + </attribute> + </extension_attributes> + <extension_attributes for="Magento\Catalog\Api\Data\ProductLinkInterface"> + <attribute code="qty" type="float"/> + </extension_attributes> +</config> diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/etc/extension_attributes.xml b/dev/tests/integration/testsuite/Magento/Framework/Api/etc/extension_attributes.xml new file mode 100644 index 0000000000000000000000000000000000000000..68bc09b6590be6fd3617d210af26a150151363d6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/etc/extension_attributes.xml @@ -0,0 +1,54 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> + <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> + <attribute code="test_stock_item" type="Magento\CatalogInventory\Api\Data\StockItemInterface"> + <resources> + <resource ref="Magento_CatalogInventory::cataloginventory"/> + </resources> + <join reference_table="cataloginventory_stock_item" + join_on_field="entity_id" + reference_field="product_id" + > + <select_field>qty</select_field> + <select_field>item_id</select_field> + </join> + </attribute> + <attribute code="test_stock_item_qty" type="string"> + <resources> + <resource ref="Magento_CatalogInventory::cataloginventory"/> + </resources> + <join reference_table="cataloginventory_stock_item" + join_on_field="entity_id" + reference_field="product_id" + > + <select_field>qty</select_field> + </join> + </attribute> + </extension_attributes> + <extension_attributes for="Magento\Customer\Api\Data\CustomerInterface"> + <attribute code="test_group_code" type="string"> + <join reference_table="customer_group" + join_on_field="group_id" + reference_field="customer_group_id" + > + <select_field>customer_group_code</select_field> + </join> + </attribute> + <attribute code="test_group" type="Magento\Customer\Api\Data\GroupInterface"> + <join reference_table="customer_group" + join_on_field="group_id" + reference_field="customer_group_id" + > + <select_field>tax_class_id</select_field> + <select_field setter_name="setCode">customer_group_code</select_field> + </join> + </attribute> + </extension_attributes> +</config> diff --git a/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceInterceptor.php.sample b/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceInterceptor.php.sample index a7a5a35de142c8b58124bceb50b8f6ddbd13045f..6cc973c0c676610e97b4fe1cdc3461a212483559 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceInterceptor.php.sample +++ b/dev/tests/integration/testsuite/Magento/Framework/Code/_expected/SourceClassWithNamespaceInterceptor.php.sample @@ -5,35 +5,9 @@ namespace Magento\Framework\Code\GeneratorTest\SourceClassWithNamespace; * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -class Interceptor extends \Magento\Framework\Code\GeneratorTest\SourceClassWithNamespace +class Interceptor extends \Magento\Framework\Code\GeneratorTest\SourceClassWithNamespace implements \Magento\Framework\Interception\InterceptorInterface { - /** - * Object Manager instance - * - * @var \Magento\Framework\ObjectManagerInterface - */ - protected $pluginLocator = null; - - /** - * List of plugins - * - * @var \Magento\Framework\Interception\PluginListInterface - */ - protected $pluginList = null; - - /** - * Invocation chain - * - * @var \Magento\Framework\Interception\ChainInterface - */ - protected $chain = null; - - /** - * Subject type name - * - * @var string - */ - protected $subjectType = null; + use \Magento\Framework\Interception\Interceptor; public function __construct($param1 = '', $param2 = '\\', $param3 = '\'') { @@ -41,81 +15,6 @@ class Interceptor extends \Magento\Framework\Code\GeneratorTest\SourceClassWithN parent::__construct($param1, $param2, $param3); } - public function ___init() - { - $this->pluginLocator = \Magento\Framework\App\ObjectManager::getInstance(); - $this->pluginList = $this->pluginLocator->get('Magento\Framework\Interception\PluginListInterface'); - $this->chain = $this->pluginLocator->get('Magento\Framework\Interception\ChainInterface'); - $this->subjectType = get_parent_class($this); - if (method_exists($this->subjectType, '___init')) { - parent::___init(); - } - } - - public function ___callParent($method, array $arguments) - { - return call_user_func_array(array('parent', $method), $arguments); - } - - public function __sleep() - { - if (method_exists(get_parent_class($this), '__sleep')) { - return array_diff(parent::__sleep(), array('pluginLocator', 'pluginList', 'chain', 'subjectType')); - } else { - return array_keys(get_class_vars(get_parent_class($this))); - } - } - - public function __wakeup() - { - if (method_exists(get_parent_class($this), '__wakeup')) { - parent::__wakeup(); - } - $this->___init(); - } - - protected function ___callPlugins($method, array $arguments, array $pluginInfo) - { - $capMethod = ucfirst($method); - $result = null; - if (isset($pluginInfo[\Magento\Framework\Interception\DefinitionInterface::LISTENER_BEFORE])) { - // Call 'before' listeners - foreach ($pluginInfo[\Magento\Framework\Interception\DefinitionInterface::LISTENER_BEFORE] as $code) { - $beforeResult = call_user_func_array( - array($this->pluginList->getPlugin($this->subjectType, $code), 'before'. $capMethod), array_merge(array($this), $arguments) - ); - if ($beforeResult) { - $arguments = $beforeResult; - } - } - } - if (isset($pluginInfo[\Magento\Framework\Interception\DefinitionInterface::LISTENER_AROUND])) { - // Call 'around' listener - $chain = $this->chain; - $type = $this->subjectType; - $subject = $this; - $code = $pluginInfo[\Magento\Framework\Interception\DefinitionInterface::LISTENER_AROUND]; - $next = function () use ($chain, $type, $method, $subject, $code) { - return $chain->invokeNext($type, $method, $subject, func_get_args(), $code); - }; - $result = call_user_func_array( - array($this->pluginList->getPlugin($this->subjectType, $code), 'around' . $capMethod), - array_merge(array($this, $next), $arguments) - ); - } else { - // Call original method - $result = call_user_func_array(array('parent', $method), $arguments); - } - if (isset($pluginInfo[\Magento\Framework\Interception\DefinitionInterface::LISTENER_AFTER])) { - // Call 'after' listeners - foreach ($pluginInfo[\Magento\Framework\Interception\DefinitionInterface::LISTENER_AFTER] as $code) { - $result = $this->pluginList->getPlugin($this->subjectType, $code) - ->{'after' . $capMethod}($this, $result); - } - } - return $result; - } - /** * {@inheritdoc} */ diff --git a/dev/tests/integration/testsuite/Magento/Framework/Object/CopyTest.php b/dev/tests/integration/testsuite/Magento/Framework/Object/CopyTest.php index 76f0334d773c175a741542ec35b96f0e20f2eb1a..274be468175ccbd8d8aa299668c553d0e3c46892 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Object/CopyTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Object/CopyTest.php @@ -26,8 +26,6 @@ class CopyTest extends \PHPUnit_Framework_TestCase $source = new \Magento\Framework\Object($data); $target = new \Magento\Framework\Object(); $expectedTarget = new \Magento\Framework\Object($data); - $expectedTarget->setDataChanges(true); - // hack for assertion $this->assertNull($this->_service->copyFieldsetToTarget($fieldset, $aspect, 'invalid_source', [])); $this->assertNull($this->_service->copyFieldsetToTarget($fieldset, $aspect, [], 'invalid_target')); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/Builder/Query/MatchTest.php b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/Builder/Query/MatchTest.php index 07db7b9e7893eb0364bedc8b9a24ff651fe3a3df..f3c867a6986a47b9539f6f4162280a709c0db177 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/Builder/Query/MatchTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/Builder/Query/MatchTest.php @@ -7,6 +7,7 @@ namespace Magento\Framework\Search\Adapter\Mysql\Builder\Query; use Magento\Framework\App\Resource\Config; use Magento\Framework\Search\Request\Query\Bool; +use Magento\Framework\Search\Adapter\Mysql\ScoreBuilder; use Magento\TestFramework\Helper\Bootstrap; class MatchTest extends \PHPUnit_Framework_TestCase @@ -28,8 +29,8 @@ class MatchTest extends \PHPUnit_Framework_TestCase */ public function testBuildQuery($conditionType, $expectedSuffix) { - $expectedScoreCondition = "(MATCH (data_index) AGAINST ('{$expectedSuffix}someValue*' " . - "IN BOOLEAN MODE) * 3.14) AS global_score"; + $conditionPattern = "(MATCH (data_index) AGAINST ('%ssomeValue*' IN BOOLEAN MODE) * %s) AS score"; + $expectedScoreCondition = sprintf($conditionPattern, $expectedSuffix, ScoreBuilder::WEIGHT_FIELD); $expectedSql = "SELECT `someTable`.* FROM `someTable` WHERE (MATCH (data_index) " . "AGAINST ('{$expectedSuffix}someValue*' IN BOOLEAN MODE))"; diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php b/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php index ef66092a66cf4e9e86638ae6cf2982afb76a5e74..86be1ce1a2843149f0a743534762da0db237501a 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/View/LayoutDirectivesTest.php @@ -119,11 +119,11 @@ class LayoutDirectivesTest extends \PHPUnit_Framework_TestCase { $layout = $this->_getLayoutModel('arguments_object_type.xml'); $this->assertInstanceOf( - 'Magento\Framework\Data\Collection\Db', + 'Magento\Framework\Data\Collection', $layout->getBlock('block_with_object_args')->getOne() ); $this->assertInstanceOf( - 'Magento\Framework\Data\Collection\Db', + 'Magento\Framework\Data\Collection', $layout->getBlock('block_with_object_args')->getTwo() ); $this->assertEquals(3, $layout->getBlock('block_with_object_args')->getThree()); diff --git a/dev/tests/integration/testsuite/Magento/Framework/View/_files/layout_directives_test/arguments_object_type.xml b/dev/tests/integration/testsuite/Magento/Framework/View/_files/layout_directives_test/arguments_object_type.xml index e304d6443d0385197649bb3d0d3e653ba188586c..c27321edacda146f6428e8c4ac3c1aca2dc668b5 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/View/_files/layout_directives_test/arguments_object_type.xml +++ b/dev/tests/integration/testsuite/Magento/Framework/View/_files/layout_directives_test/arguments_object_type.xml @@ -8,15 +8,15 @@ <layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_layout.xsd"> <block class="Magento\Framework\View\Element\Text" name="block_with_object_args"> <arguments> - <argument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="one" xsi:type="object">Magento\Framework\Data\Collection\Db</argument> - <argument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="two" xsi:type="object">Magento\Framework\Data\Collection\Db</argument> - <argument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="three" xsi:type="object">Magento\Framework\Data\Collection\Db</argument> - <argument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="four" xsi:type="object">Magento\Framework\Data\Collection\Db</argument> + <argument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="one" xsi:type="object">Magento\Framework\Data\Collection</argument> + <argument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="two" xsi:type="object">Magento\Framework\Data\Collection</argument> + <argument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="three" xsi:type="object">Magento\Framework\Data\Collection</argument> + <argument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="four" xsi:type="object">Magento\Framework\Data\Collection</argument> </arguments> </block> <referenceBlock name="block_with_object_args"> <arguments> - <argument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="two" xsi:type="object">Magento\Framework\Data\Collection\Db</argument> + <argument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="two" xsi:type="object">Magento\Framework\Data\Collection</argument> <argument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="three" xsi:type="string">3</argument> </arguments> </referenceBlock> diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/HttpFactoryMock.php b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/HttpFactoryMock.php index ab162c5011bfe2295d3232977c67a5eeaa1b67b7..d557cc6977eee926df29eb42dfdd3d6a5987c312 100644 --- a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/HttpFactoryMock.php +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/HttpFactoryMock.php @@ -11,6 +11,6 @@ class HttpFactoryMock extends FileTransferFactory { public function create(array $options = []) { - return new \Magento\Framework\Validator\NotEmpty(); + return new \Magento\Framework\Validator\NotEmpty($options); } } diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/ValidateTest.php b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/ValidateTest.php index cc698e42cfe54320722b5f96f33c03a86dec2e13..4667222256a4fdc04c359ae01442b72bb0374acd 100644 --- a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/ValidateTest.php +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/ValidateTest.php @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ namespace Magento\ImportExport\Controller\Adminhtml\Import; + use Magento\Framework\Filesystem\DirectoryList; /** @@ -26,6 +27,7 @@ class ValidateTest extends \Magento\Backend\Utility\Controller $this->getRequest()->setPostValue('form_key', $formKey->getFormKey()); $this->getRequest()->setPostValue('entity', 'catalog_product'); $this->getRequest()->setPostValue('behavior', 'replace'); + $this->getRequest()->setPostValue('_import_field_separator', ','); $name = 'catalog_product.csv'; diff --git a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/_files/catalog_product.csv b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/_files/catalog_product.csv index 84e87317ec5bba48bd856541f9a7494b78472197..76a3e1128efd93009f7409c99c8dfc7d67cb45fd 100644 --- a/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/_files/catalog_product.csv +++ b/dev/tests/integration/testsuite/Magento/ImportExport/Controller/Adminhtml/Import/_files/catalog_product.csv @@ -1,3 +1,3 @@ -sku,_store,_attribute_set,_type,_category,_root_category,_product_websites,color,cost,country_of_manufacture,created_at,custom_design,custom_design_from,custom_design_to,custom_layout_update,description,gallery,gift_message_available,gift_wrapping_available,gift_wrapping_price,has_options,image,image_label,is_returnable,manufacturer,meta_description,meta_keyword,meta_title,minimal_price,msrp,msrp_display_actual_price_type,name,news_from_date,news_to_date,options_container,page_layout,price,quantity_and_stock_status,related_tgtr_position_behavior,related_tgtr_position_limit,required_options,short_description,small_image,small_image_label,special_from_date,special_price,special_to_date,status,tax_class_id,thumbnail,thumbnail_label,updated_at,upsell_tgtr_position_behavior,upsell_tgtr_position_limit,url_key,url_path,visibility,weight,qty,min_qty,use_config_min_qty,is_qty_decimal,backorders,use_config_backorders,min_sale_qty,use_config_min_sale_qty,max_sale_qty,use_config_max_sale_qty,is_in_stock,notify_stock_qty,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,_related_sku,_related_position,_crosssell_sku,_crosssell_position,_upsell_sku,_upsell_position,_tier_price_website,_tier_price_customer_group,_tier_price_qty,_tier_price_price,_group_price_website,_group_price_customer_group,_group_price_price,_media_attribute_id,_media_image,_media_label,_media_position,_media_is_disabled,_associated_sku,_associated_default_qty,_associated_position -"simple product 1",,Default,simple,,,base,,,,"2014-12-25 19:52:47",,,,,,,,,,0,,,"Use config",,"simple product 1 ","simple product 1","simple product 1",,,,"simple product 1",,,"Block after Info Column",,100.0000,"In Stock",,,0,,,,,,,1,2,,,"2014-12-25 19:52:47",,,simple-product-1,,4,,123.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,1,0,1,0.0000,1,0,0,1,,,,,,,,,,,,,,,,,,,,, -"simple product 2",,Default,simple,,,base,,,,"2014-12-25 19:53:14",,,,,,,,,,0,,,"Use config",,"simple product 2 ","simple product 2","simple product 2",,,,"simple product 2",,,"Block after Info Column",,200.0000,"In Stock",,,0,,,,,,,1,2,,,"2014-12-25 19:53:14",,,simple-product-2,,4,,234.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,1,0,1,0.0000,1,0,0,1,,,,,,,,,,,,,,,,,,,,, +sku,_store,_attribute_set,product_type,categories,_product_websites,color,cost,country_of_manufacture,created_at,custom_design,custom_design_from,custom_design_to,custom_layout_update,description,gallery,gift_message_available,gift_wrapping_available,gift_wrapping_price,has_options,image,image_label,is_returnable,manufacturer,meta_description,meta_keyword,meta_title,minimal_price,msrp,msrp_display_actual_price_type,name,news_from_date,news_to_date,options_container,page_layout,price,quantity_and_stock_status,related_tgtr_position_behavior,related_tgtr_position_limit,required_options,short_description,small_image,small_image_label,special_from_date,special_price,special_to_date,status,tax_class_id,thumbnail,thumbnail_label,updated_at,upsell_tgtr_position_behavior,upsell_tgtr_position_limit,url_key,url_path,visibility,weight,qty,min_qty,use_config_min_qty,is_qty_decimal,backorders,use_config_backorders,min_sale_qty,use_config_min_sale_qty,max_sale_qty,use_config_max_sale_qty,is_in_stock,notify_stock_qty,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,_related_sku,_related_position,_crosssell_sku,_crosssell_position,_upsell_sku,_upsell_position,_tier_price_website,_tier_price_customer_group,_tier_price_qty,_tier_price_price,_group_price_website,_group_price_customer_group,_group_price_price,_media_attribute_id,_media_image,_media_label,_media_position,_media_is_disabled,_associated_sku,_associated_default_qty,_associated_position +"simple product 1",,Default,simple,,base,,,,"2014-12-25 19:52:47",,,,,,,,,,0,,,"Use config",,"simple product 1 ","simple product 1","simple product 1",,,,"simple product 1",,,"Block after Info Column",,100.0000,"In Stock",,,0,,,,,,,1,2,,,"2014-12-25 19:52:47",,,simple-product-1,,"catalog, search",,123.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,1,0,1,0.0000,1,0,0,1,,,,,,,,,,,,,,,,,,,,, +"simple product 2",,Default,simple,,base,,,,"2014-12-25 19:53:14",,,,,,,,,,0,,,"Use config",,"simple product 2 ","simple product 2","simple product 2",,,,"simple product 2",,,"Block after Info Column",,200.0000,"In Stock",,,0,,,,,,,1,2,,,"2014-12-25 19:53:14",,,simple-product-2,,"catalog, search",,234.0000,0.0000,1,0,0,1,1.0000,1,0.0000,1,1,,1,1,0,1,0.0000,1,0,0,1,,,,,,,,,,,,,,,,,,,,, diff --git a/dev/tests/integration/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php b/dev/tests/integration/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php index f7cf66f678e7791569ebcf8c4342ca85f0063bf0..fc49f27cb91c7455a62a39f8fe6d6c0b056c4aa6 100644 --- a/dev/tests/integration/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php +++ b/dev/tests/integration/testsuite/Magento/Integration/Model/AdminTokenServiceTest.php @@ -73,7 +73,7 @@ class AdminTokenServiceTest extends \PHPUnit_Framework_TestCase /** * @expectedException \Magento\Framework\Exception\AuthenticationException - * @expectedExceptionMessage Please correct the user name or password. + * @expectedExceptionMessage You did not sign in correctly or your account is temporarily disabled. */ public function testCreateAdminAccessTokenInvalidCustomer() { diff --git a/dev/tests/integration/testsuite/Magento/Integration/Model/Resource/IntegrationTest.php b/dev/tests/integration/testsuite/Magento/Integration/Model/Resource/IntegrationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1ddce9d8b615802902e9afeaf939c2536542874f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Integration/Model/Resource/IntegrationTest.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Integration\Model\Resource; + +/** + * Integration test for \Magento\Integration\Model\Resource\Integration + */ +class IntegrationTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Integration\Model\Integration + */ + protected $integration; + + /** + * @var \Magento\Integration\Model\Oauth\Consumer + */ + protected $consumer; + + protected function setUp() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + $this->consumer = $objectManager->create('Magento\Integration\Model\Oauth\Consumer'); + $this->consumer->setData( + [ + 'key' => md5(uniqid()), + 'secret' => md5(uniqid()), + 'callback_url' => 'http://example.com/callback', + 'rejected_callback_url' => 'http://example.com/rejectedCallback' + ] + )->save(); + $this->integration = $objectManager->create('Magento\Integration\Model\Integration'); + $this->integration->setName('Test Integration') + ->setConsumerId($this->consumer->getId()) + ->setStatus(\Magento\Integration\Model\Integration::STATUS_ACTIVE) + ->save(); + } + + public function testLoadActiveIntegrationByConsumerId() + { + $integration = $this->integration->getResource()->selectActiveIntegrationByConsumerId($this->consumer->getId()); + $this->assertEquals($this->integration->getId(), $integration['integration_id']); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php new file mode 100644 index 0000000000000000000000000000000000000000..68635c4369b3c313ebe6c2ef561242bb4763b06a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteManagementTest.php @@ -0,0 +1,44 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Quote\Model; + +use Magento\Catalog\Model\Product\Type; +use Magento\TestFramework\Helper\Bootstrap; + +class QuoteManagementTest extends \PHPUnit_Framework_TestCase +{ + /** + * Create order with product that has child items + * + * @magentoDataFixture Magento/Sales/_files/quote_with_bundle.php + */ + public function testSubmit() + { + /** + * Preconditions: + * Load quote with Bundle product that has at least to child products + */ + $objectManager = Bootstrap::getObjectManager(); + /** @var \Magento\Quote\Model\Quote $quote */ + $quote = $objectManager->create('\Magento\Quote\Model\Quote'); + $quote->load('test01', 'reserved_order_id'); + + /** Execute SUT */ + /** @var \Magento\Quote\Model\QuoteManagement $model */ + $model = $objectManager->create('\Magento\Quote\Model\QuoteManagement'); + $order = $model->submit($quote); + + /** Check if SUT caused expected effects */ + $orderItems = $order->getItems(); + $this->assertCount(3, $orderItems); + foreach ($orderItems as $orderItem) { + if ($orderItem->getProductType() == Type::TYPE_SIMPLE) { + $this->assertNotEmpty($orderItem->getParentItem(), 'Parent is not set for child product'); + $this->assertNotEmpty($orderItem->getParentItemId(), 'Parent is not set for child product'); + } + } + } +} diff --git a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php index 92fc68dbe396734fa7d87b5803f7ecbb8c830e1c..c3cb9184d214ab5cdd403e493b4ea9eab8a8ad72 100644 --- a/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php +++ b/dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php @@ -16,6 +16,7 @@ class QuoteTest extends \PHPUnit_Framework_TestCase ->create('Magento\Framework\Api\ExtensibleDataObjectConverter') ->toFlatArray($entity); } + /** * @magentoDataFixture Magento/Catalog/_files/product_virtual.php * @magentoDataFixture Magento/Sales/_files/quote.php @@ -277,6 +278,44 @@ class QuoteTest extends \PHPUnit_Framework_TestCase } } + /** + * @magentoDataFixture Magento/Catalog/_files/product_simple_duplicated.php + */ + public function testAddProductUpdateItem() + { + /** @var \Magento\Quote\Model\Quote $quote */ + $quote = Bootstrap::getObjectManager()->create('Magento\Quote\Model\Quote'); + $quote->load('test01', 'reserved_order_id'); + + $productStockQty = 100; + /** @var \Magento\Catalog\Model\Product $product */ + $product = Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product'); + $product->load(2); + $quote->addProduct($product, 50); + $quote->setTotalsCollectedFlag(false)->collectTotals(); + $this->assertEquals(50, $quote->getItemsQty()); + $quote->addProduct($product, 50); + $quote->setTotalsCollectedFlag(false)->collectTotals(); + $this->assertEquals(100, $quote->getItemsQty()); + $params = [ + 'related_product' => '', + 'product' => $product->getId(), + 'qty' => 1, + 'id' => 0 + ]; + $updateParams = new \Magento\Framework\Object($params); + $quote->updateItem($updateParams['id'], $updateParams); + $quote->setTotalsCollectedFlag(false)->collectTotals(); + $this->assertEquals(1, $quote->getItemsQty()); + + $this->setExpectedException( + '\Magento\Framework\Exception\LocalizedException', + 'We don\'t have as many "Simple Product" as you requested.' + ); + $updateParams['qty'] = $productStockQty + 1; + $quote->updateItem($updateParams['id'], $updateParams); + } + /** * Prepare quote for testing assignCustomerWithAddressChange method. * diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/AdminOrder/CreateTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/AdminOrder/CreateTest.php index ab65efa40a0ec16a5e87507b90e0cde8139b8377..028610784b91e0530aead51d9bbb0be94b0c93a3 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/AdminOrder/CreateTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/AdminOrder/CreateTest.php @@ -154,9 +154,9 @@ class CreateTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf( 'Magento\Wishlist\Model\Wishlist', $wishlist, - 'New wishlist is expected to be created if existing customer does not have one yet.' + 'New Wish List is expected to be created if existing Customer does not have one yet.' ); - $this->assertEquals(0, $wishlist->getItemsCount(), 'New wishlist must be empty just after creation.'); + $this->assertEquals(0, $wishlist->getItemsCount(), 'New Wish List must be empty just after creation.'); /** Add new item to wishlist and try to get it using getCustomerWishlist once again */ $wishlist->addNewItem($productIdFromFixture)->save(); @@ -164,7 +164,7 @@ class CreateTest extends \PHPUnit_Framework_TestCase $this->assertEquals( 1, $updatedWishlist->getItemsCount(), - 'Wishlist must contain a product which was added to it earlier.' + 'Wish List must contain a Product which was added to it earlier.' ); /** Try to load wishlist from cache in the class after it is deleted from DB */ @@ -172,12 +172,12 @@ class CreateTest extends \PHPUnit_Framework_TestCase $this->assertSame( $updatedWishlist, $this->_model->getCustomerWishlist(false), - 'Wishlist cached in class variable is expected to be returned.' + 'Wish List cached in class variable is expected to be returned.' ); $this->assertNotSame( $updatedWishlist, $this->_model->getCustomerWishlist(true), - 'New wishlist is expected to be created when cache is forced to be refreshed.' + 'New Wish List is expected to be created when cache is forced to be refreshed.' ); } @@ -550,7 +550,7 @@ class CreateTest extends \PHPUnit_Framework_TestCase ); $this->assertEquals( 'Simple Product', - $this->_model->getQuote()->getAllItems()[0]->getData('name'), + $this->_model->getQuote()->getItemByProduct($product)->getData('name'), 'Precondition failed: Quote items data is invalid in create order model' ); $this->assertEquals( diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_bundle.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_bundle.php new file mode 100644 index 0000000000000000000000000000000000000000..f80113ad1119427ff2d5002b914b2f121b1fe503 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_bundle.php @@ -0,0 +1,164 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +\Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('frontend'); +$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +/** Create simple and bundle products for quote*/ +$simpleProducts[] = $objectManager->create('Magento\Catalog\Model\Product') + ->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setId(1) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Simple Product 1') + ->setSku('simple-1') + ->setPrice(10) + ->setDescription('Description with <b>html tag</b>') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setCategoryIds([2]) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->save(); + +$simpleProducts[] = $objectManager->create('Magento\Catalog\Model\Product') + ->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE) + ->setId(2) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Simple Product 2') + ->setSku('simple-2') + ->setPrice(10) + ->setDescription('Description with <b>html tag</b>') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setCategoryIds([2]) + ->setStockData(['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]) + ->save(); + +$product = $objectManager->create('Magento\Catalog\Model\Product'); +$product + ->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) + ->setId(3) + ->setAttributeSetId(4) + ->setWebsiteIds([1]) + ->setName('Bundle Product') + ->setSku('bundle-product') + ->setDescription('Description with <b>html tag</b>') + ->setShortDescription('Bundle') + ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) + ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) + ->setStockData( + [ + 'use_config_manage_stock' => 0, + 'manage_stock' => 0, + 'use_config_enable_qty_increments' => 1, + 'use_config_qty_increments' => 1, + 'is_in_stock' => 0, + ] + ) + ->setBundleOptionsData( + [ + [ + 'title' => 'Bundle Product Items', + 'default_title' => 'Bundle Product Items', + 'type' => 'checkbox', + 'required' => 1, + 'delete' => '', + 'position' => 0, + 'option_id' => '', + ], + ] + ) + ->setBundleSelectionsData( + [ + [ + [ + 'product_id' => $simpleProducts[0]->getId(), + 'selection_qty' => 1, + 'selection_can_change_qty' => 1, + 'delete' => '', + 'position' => 0, + 'selection_price_type' => 0, + 'selection_price_value' => 0.0, + 'option_id' => '', + 'selection_id' => '', + 'is_default' => 1, + ], + [ + 'product_id' => $simpleProducts[1]->getId(), + 'selection_qty' => 1, + 'selection_can_change_qty' => 1, + 'delete' => '', + 'position' => 0, + 'selection_price_type' => 0, + 'selection_price_value' => 0.0, + 'option_id' => '', + 'selection_id' => '', + 'is_default' => 1, + ] + ], + ] + ) + ->setCanSaveBundleSelections(true) + ->setAffectBundleProductSelections(true) + ->save(); + +//Load options +$typeInstance = $product->getTypeInstance(); +$typeInstance->setStoreFilter($product->getStoreId(), $product); +$optionCollection = $typeInstance->getOptionsCollection($product); +$selectionCollection = $typeInstance->getSelectionsCollection($typeInstance->getOptionsIds($product), $product); + +$bundleOptions = []; +$bundleOptionsQty = []; +/** @var $option \Magento\Bundle\Model\Option */ +foreach ($optionCollection as $option) { + /** @var $selection \Magento\Bundle\Model\Selection */ + foreach ($selectionCollection as $selection) { + $bundleOptions[$option->getId()][] = $selection->getSelectionId(); + $bundleOptionsQty[$option->getId()][] = 1; + } +} + +$buyRequest = new \Magento\Framework\Object( + ['qty' => 1, 'bundle_option' => $bundleOptions, 'bundle_option_qty' => $bundleOptionsQty] +); +$product->setSkipCheckRequiredOption(true); + +$addressData = include __DIR__ . '/address_data.php'; +$billingAddress = $objectManager->create('Magento\Quote\Model\Quote\Address', ['data' => $addressData]); +$billingAddress->setAddressType('billing'); + +/** @var Magento\Quote\Model\Quote\Address $shippingAddress */ +$shippingAddress = clone $billingAddress; +$shippingAddress->setId(null)->setAddressType('shipping'); + +/** @var \Magento\Quote\Model\Quote $quote */ +$quote = $objectManager->create('Magento\Quote\Model\Quote'); +$quote + ->setCustomerIsGuest(true) + ->setStoreId($objectManager->get('Magento\Store\Model\StoreManagerInterface')->getStore()->getId()) + ->setReservedOrderId('test01') + ->setBillingAddress($billingAddress) + ->setShippingAddress($shippingAddress) + ->setCustomerEmail('test@test.magento.com') + ->addProduct($product, $buyRequest); + +/** @var $rate \Magento\Quote\Model\Quote\Address\Rate */ +$rate = $objectManager->create('Magento\Quote\Model\Quote\Address\Rate'); +$rate + ->setCode('freeshipping_freeshipping') + ->getPrice(1); + +$quote->getShippingAddress()->setShippingMethod('freeshipping_freeshipping'); +$quote->getShippingAddress()->addShippingRate($rate); +$quote->getPayment()->setMethod('checkmo'); +$quote->collectTotals(); +$quote->save(); + +/** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */ +$quoteIdMask = $objectManager->create('Magento\Quote\Model\QuoteIdMaskFactory')->create(); +$quoteIdMask->setQuoteId($quote->getId()); +$quoteIdMask->setDataChanges(true); +$quoteIdMask->save(); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_bundle_rollback.php b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_bundle_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..8808f9c1efe204fbaa33d9f5bf44e2992f188983 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/quote_with_bundle_rollback.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** @var \Magento\Framework\Registry $registry */ +$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry'); +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', true); + +/** @var $quote \Magento\Quote\Model\Quote */ +$quote = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Quote\Model\Quote'); +$quote->load('test01', 'reserved_order_id'); +if ($quote->getId()) { + $quote->delete(); +} + +/** @var $product \Magento\Catalog\Model\Product */ +$productIds = [1, 2, 3]; +$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product'); +foreach ($productIds as $productId) { + $product->load($productId); + if ($product->getId()) { + $product->delete(); + } +} + +$registry->unregister('isSecureArea'); +$registry->register('isSecureArea', false); diff --git a/dev/tests/integration/testsuite/Magento/Sendfriend/Block/SendTest.php b/dev/tests/integration/testsuite/Magento/SendFriend/Block/SendTest.php similarity index 87% rename from dev/tests/integration/testsuite/Magento/Sendfriend/Block/SendTest.php rename to dev/tests/integration/testsuite/Magento/SendFriend/Block/SendTest.php index 141b8c5cfeefd8a73db8c717a51f8d960d6c8b48..b7c45b1c6bd0b66fb5941abc148edaec83625c5d 100644 --- a/dev/tests/integration/testsuite/Magento/Sendfriend/Block/SendTest.php +++ b/dev/tests/integration/testsuite/Magento/SendFriend/Block/SendTest.php @@ -3,28 +3,28 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Sendfriend\Block; +namespace Magento\SendFriend\Block; use Magento\TestFramework\Helper\Bootstrap; class SendTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Sendfriend\Block\Send + * @var \Magento\SendFriend\Block\Send */ protected $_block; protected function setUp() { - $this->_block = Bootstrap::getObjectManager()->create('Magento\Sendfriend\Block\Send'); + $this->_block = Bootstrap::getObjectManager()->create('Magento\SendFriend\Block\Send'); } /** * @param string $field * @param string $value * @dataProvider formDataProvider - * @covers \Magento\Sendfriend\Block\Send::getUserName - * @covers \Magento\Sendfriend\Block\Send::getEmail + * @covers \Magento\SendFriend\Block\Send::getUserName + * @covers \Magento\SendFriend\Block\Send::getEmail */ public function testGetCustomerFieldFromFormData($field, $value) { @@ -48,8 +48,8 @@ class SendTest extends \PHPUnit_Framework_TestCase * @param string $field * @param string $value * @dataProvider customerSessionDataProvider - * @covers \Magento\Sendfriend\Block\Send::getUserName - * @covers \Magento\Sendfriend\Block\Send::getEmail + * @covers \Magento\SendFriend\Block\Send::getUserName + * @covers \Magento\SendFriend\Block\Send::getEmail * @magentoDataFixture Magento/Customer/_files/customer.php */ public function testGetCustomerFieldFromSession($field, $value) diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowFrameworkCommandTest.php b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowFrameworkCommandTest.php index 7a986a3c7ee0ef6b1f83cb0eda77002ae027ea4c..afb10f97cbeb448353694e1fac36f46d40ffc340 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowFrameworkCommandTest.php +++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowFrameworkCommandTest.php @@ -40,10 +40,15 @@ class DependenciesShowFrameworkCommandTest extends \PHPUnit_Framework_TestCase ['--directory' => __DIR__ . '/_files/root', '--output' => __DIR__ . '/_files/output/framework.csv'] ); $this->assertEquals('Report successfully processed.' . PHP_EOL, $this->commandTester->getDisplay()); - $this->assertFileEquals( - __DIR__ . '/_files/expected/framework.csv', - __DIR__ . '/_files/output/framework.csv' + $fileContents = file_get_contents(__DIR__ . '/_files/output/framework.csv'); + $this->assertContains( + '"Dependencies of framework:","Total number"' . PHP_EOL . '"","2"' . PHP_EOL, + $fileContents ); + $this->assertContains('"Dependencies for each module:",""' . PHP_EOL, $fileContents); + $this->assertContains('"Magento\A","1"' . PHP_EOL . '" -- Magento\Framework","1"' . PHP_EOL, $fileContents); + $this->assertContains('"Magento\B","1"' . PHP_EOL . '" -- Magento\Framework","1"' . PHP_EOL, $fileContents); + } public function testExecuteInvalidDirectory() diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowModulesCircularCommandTest.php b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowModulesCircularCommandTest.php index 9fc5e9dbecdae680e4d7eda3a13929d6886d2558..44121115fd7f03ea122ae9aa95662e4169dbd437 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowModulesCircularCommandTest.php +++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowModulesCircularCommandTest.php @@ -38,9 +38,19 @@ class DependenciesShowModulesCircularCommandTest extends \PHPUnit_Framework_Test ['--directory' => __DIR__ . '/_files/root', '--output' => __DIR__ . '/_files/output/circular.csv'] ); $this->assertEquals('Report successfully processed.' . PHP_EOL, $this->commandTester->getDisplay()); - $this->assertFileEquals( - __DIR__ . '/_files/expected/circular.csv', - __DIR__ . '/_files/output/circular.csv' + $fileContents = file_get_contents(__DIR__ . '/_files/output/circular.csv'); + $this->assertContains( + '"Circular dependencies:","Total number of chains"' . PHP_EOL . '"","2"' . PHP_EOL, + $fileContents + ); + $this->assertContains('"Circular dependencies for each module:",""' . PHP_EOL, $fileContents); + $this->assertContains( + '"magento/module-a","1"' . PHP_EOL . '"magento/module-a->magento/module-b->magento/module-a"' . PHP_EOL, + $fileContents + ); + $this->assertContains( + '"magento/module-b","1"' . PHP_EOL . '"magento/module-b->magento/module-a->magento/module-b"' . PHP_EOL, + $fileContents ); } diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowModulesCommandTest.php b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowModulesCommandTest.php index 6d0c16225cd5cb7395672f8361baf7e9f9ab5c73..580e888ee653d76822f704aaea68e47058865370 100644 --- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowModulesCommandTest.php +++ b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowModulesCommandTest.php @@ -38,9 +38,19 @@ class DependenciesShowModulesCommandTest extends \PHPUnit_Framework_TestCase ['--directory' => __DIR__ . '/_files/root', '--output' => __DIR__ . '/_files/output/modules.csv'] ); $this->assertEquals('Report successfully processed.' . PHP_EOL, $this->commandTester->getDisplay()); - $this->assertFileEquals( - __DIR__ . '/_files/expected/modules.csv', - __DIR__ . '/_files/output/modules.csv' + $fileContents = file_get_contents(__DIR__ . '/_files/output/modules.csv'); + $this->assertContains( + '"","All","Hard","Soft"' . PHP_EOL . '"Total number of dependencies","2","2","0"' . PHP_EOL, + $fileContents + ); + $this->assertContains('"Dependencies for each module:","All","Hard","Soft"'. PHP_EOL, $fileContents); + $this->assertContains( + '"magento/module-a","1","1","0"' . PHP_EOL . '" -- magento/module-b","","1","0"' . PHP_EOL, + $fileContents + ); + $this->assertContains( + '"magento/module-b","1","1","0"' . PHP_EOL . '" -- magento/module-a","","1","0"' . PHP_EOL, + $fileContents ); } diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expected/circular.csv b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expected/circular.csv deleted file mode 100644 index 6d00c9f4815548d8bbd880ebb06aebd44ccffe6d..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expected/circular.csv +++ /dev/null @@ -1,9 +0,0 @@ -"Circular dependencies:","Total number of chains" -"","2" - -"Circular dependencies for each module:","" -"magento/module-a","1" -"magento/module-a->magento/module-b->magento/module-a" - -"magento/module-b","1" -"magento/module-b->magento/module-a->magento/module-b" diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expected/framework.csv b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expected/framework.csv deleted file mode 100644 index b6abb23cd683f2651f147138297602b2c51da494..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expected/framework.csv +++ /dev/null @@ -1,9 +0,0 @@ -"Dependencies of framework:","Total number" -"","2" - -"Dependencies for each module:","" -"Magento\A","1" -" -- Magento\Framework","1" - -"Magento\B","1" -" -- Magento\Framework","1" diff --git a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expected/modules.csv b/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expected/modules.csv deleted file mode 100644 index 41deca9466eca3a56292a26c5f28bc4121afafc1..0000000000000000000000000000000000000000 --- a/dev/tests/integration/testsuite/Magento/Setup/Console/Command/_files/expected/modules.csv +++ /dev/null @@ -1,9 +0,0 @@ -"","All","Hard","Soft" -"Total number of dependencies","2","2","0" - -"Dependencies for each module:","All","Hard","Soft" -"magento/module-a","1","1","0" -" -- magento/module-b","","1","0" - -"magento/module-b","1","1","0" -" -- magento/module-a","","1","0" diff --git a/dev/tests/integration/testsuite/Magento/Shipping/Helper/DataTest.php b/dev/tests/integration/testsuite/Magento/Shipping/Helper/DataTest.php index 98edf563710e99efc0341060d85127d9e46294fb..482f4580c5b96795fa65cb14238a0b72c1345258 100644 --- a/dev/tests/integration/testsuite/Magento/Shipping/Helper/DataTest.php +++ b/dev/tests/integration/testsuite/Magento/Shipping/Helper/DataTest.php @@ -97,21 +97,21 @@ class DataTest extends \PHPUnit_Framework_TestCase 'setId', 42, 'abc', - 'http://localhost/index.php/shipping/tracking/popup/hash/b3JkZXJfaWQ6NDI6YWJj/', + 'http://localhost/index.php/shipping/tracking/popup?hash=b3JkZXJfaWQ6NDI6YWJj', ], [ 'Magento\Sales\Model\Order\Shipment', 'setId', 42, 'abc', - 'http://localhost/index.php/shipping/tracking/popup/hash/c2hpcF9pZDo0MjphYmM,/' + 'http://localhost/index.php/shipping/tracking/popup?hash=c2hpcF9pZDo0MjphYmM%2C' ], [ 'Magento\Sales\Model\Order\Shipment\Track', 'setEntityId', 42, 'abc', - 'http://localhost/index.php/shipping/tracking/popup/hash/dHJhY2tfaWQ6NDI6YWJj/' + 'http://localhost/index.php/shipping/tracking/popup?hash=dHJhY2tfaWQ6NDI6YWJj' ] ]; } diff --git a/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php b/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php index ab5c6cd2ba0d57b05bd90e250dd4550a254010e1..f91ac38ec5effe8a65f465a36f0d99ae0a27df30 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php +++ b/dev/tests/integration/testsuite/Magento/Tax/Controller/Adminhtml/RateTest.php @@ -109,7 +109,7 @@ class RateTest extends \Magento\Backend\Utility\Controller { $expectedData = [ 'success' => false, - 'error_message' => 'Please fill all required fields with valid information.', + 'error_message' => 'Make sure all required information is valid.', ]; return [ [ diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_after_discount.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_after_discount.php index 8f6344fa04658eae9688793495d1b909f7db6567..8939c66ae72a2785ff0faa24164979e78fa76b62 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_after_discount.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_after_discount.php @@ -67,10 +67,10 @@ $taxCalculationData['excluding_tax_apply_tax_after_discount'] = [ 'base_shipping_tax_amount' => 0.75, 'discount_amount' => -10, 'base_discount_amount' => -10, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 22.75, 'base_grand_total' => 22.75, 'applied_taxes' => [ @@ -116,8 +116,8 @@ $taxCalculationData['excluding_tax_apply_tax_after_discount'] = [ 'discount_amount' => 10, 'base_discount_amount' => 10, 'discount_percent' => 50, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_after_discount_discount_tax.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_after_discount_discount_tax.php index 9553492ec8fb02f8c22a2f0f5783f5535949e1dc..572a9e778b0827b2a38bb826aa6903917f92fe93 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_after_discount_discount_tax.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_after_discount_discount_tax.php @@ -68,10 +68,10 @@ $taxCalculationData['excluding_tax_apply_tax_after_discount_discount_tax'] = [ 'base_shipping_tax_amount' => 0.75, 'discount_amount' => -12, 'base_discount_amount' => -12, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 20.35, 'base_grand_total' => 20.35, 'applied_taxes' => [ @@ -117,8 +117,8 @@ $taxCalculationData['excluding_tax_apply_tax_after_discount_discount_tax'] = [ 'discount_amount' => 12, 'base_discount_amount' => 12, 'discount_percent' => 50, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_before_discount.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_before_discount.php index 1da4eda698d94caeb7f38a2e4ffe71a08ed35911..ab6b80c0e752cc99bb82b0a69976597a93a88e34 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_before_discount.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_apply_tax_before_discount.php @@ -56,10 +56,10 @@ $taxCalculationData['excluding_tax_apply_tax_before_discount'] = [ 'base_shipping_tax_amount' => 2, 'discount_amount' => -10, 'base_discount_amount' => -10, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 26, 'base_grand_total' => 26, ], @@ -79,8 +79,8 @@ $taxCalculationData['excluding_tax_apply_tax_before_discount'] = [ 'discount_amount' => 10, 'base_discount_amount' => 10, 'discount_percent' => 50, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_row.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_row.php index b1854d2d8c16722f628e0148234b599e1e3ddbd6..ea6d1ca2063acdd93bf2aaf98bf87ad4c4885e27 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_row.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_row.php @@ -60,10 +60,10 @@ $taxCalculationData['excluding_tax__multi_item_row'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 22.74, 'base_grand_total' => 22.74, ], @@ -83,8 +83,8 @@ $taxCalculationData['excluding_tax__multi_item_row'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], 'simple2' => [ 'row_total' => 11, @@ -101,8 +101,8 @@ $taxCalculationData['excluding_tax__multi_item_row'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_total.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_total.php index e5f486018853c2482c7a5a9b3e3ece13a07a8356..763e9ca8ac426af8f07aa6aa0e3349553f044088 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_total.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_total.php @@ -60,10 +60,10 @@ $taxCalculationData['excluding_tax__multi_item_total'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 22.73, 'base_grand_total' => 22.73, ], @@ -83,8 +83,8 @@ $taxCalculationData['excluding_tax__multi_item_total'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], 'simple2' => [ 'row_total' => 11, @@ -101,8 +101,8 @@ $taxCalculationData['excluding_tax__multi_item_total'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_unit.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_unit.php index 427f4f48bdf51af39390851819559c45e9db799a..59df16b832812397f58c557671b27a6809da6539 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_unit.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_multi_item_unit.php @@ -60,10 +60,10 @@ $taxCalculationData['excluding_tax__multi_item_unit'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 22.74, 'base_grand_total' => 22.74, ], @@ -83,8 +83,8 @@ $taxCalculationData['excluding_tax__multi_item_unit'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], 'simple2' => [ 'row_total' => 11, @@ -101,8 +101,8 @@ $taxCalculationData['excluding_tax__multi_item_unit'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_row.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_row.php index 643f1b8e7fb9c80a6001b3b1a7b8d4a19318179d..2b79af679e58794baab32cc357fdcb365eb63c7c 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_row.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_row.php @@ -53,10 +53,10 @@ $taxCalculationData['excluding_tax_row'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 21.65, 'base_grand_total' => 21.65, ], @@ -76,8 +76,8 @@ $taxCalculationData['excluding_tax_row'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_total.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_total.php index 9c3456a6dde5730cab8691d16eba9216e87fa0dc..02e4849979dee787640898fb558bedf252f691f8 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_total.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_total.php @@ -53,10 +53,10 @@ $taxCalculationData['excluding_tax_total'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 21.65, 'base_grand_total' => 21.65, ], @@ -76,8 +76,8 @@ $taxCalculationData['excluding_tax_total'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_unit.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_unit.php index a7b711c72488ecf39e2e0a9603968a178bb0d8d9..581ca9af4d738e7657135770da451d6692a4c64a 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_unit.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/excluding_tax_unit.php @@ -53,10 +53,10 @@ $taxCalculationData['excluding_tax_unit'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 21.66, 'base_grand_total' => 21.66, ], @@ -76,8 +76,8 @@ $taxCalculationData['excluding_tax_unit'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_disabled.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_disabled.php index 8eef71d40735695de958cf7937a7bcde7489f54a..b7abef6f91fe5d6da4da00a7a0bd8e8ea3cb9833 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_disabled.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_disabled.php @@ -56,10 +56,10 @@ $taxCalculationData['including_tax_cross_border_trade_disabled'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 21.80, 'base_grand_total' => 21.80, ], @@ -79,8 +79,8 @@ $taxCalculationData['including_tax_cross_border_trade_disabled'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_enabled.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_enabled.php index cc5d8e055aa73b02faab08f1c1798eae26c491d7..e5baa6f5459e4702c16a67527bf6268afa12f46a 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_enabled.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_cross_border_trade_enabled.php @@ -56,10 +56,10 @@ $taxCalculationData['including_tax_cross_border_trade_enabled'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 19.98, 'base_grand_total' => 19.98, ], @@ -79,8 +79,8 @@ $taxCalculationData['including_tax_cross_border_trade_enabled'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_row.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_row.php index 2764b8fc7b26a9ef54cc18e75929645740ff0299..2551ea91df20236a3bbb9b30600a522ea62ea2aa 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_row.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_row.php @@ -55,10 +55,10 @@ $taxCalculationData['including_tax_row'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 19.98, 'base_grand_total' => 19.98, ], @@ -78,8 +78,8 @@ $taxCalculationData['including_tax_row'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_total.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_total.php index 0ad007e15cfa0b52864c4d1211746a743859c6fa..6fb00ca444842cf951712a96e80238c8257652c8 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_total.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_total.php @@ -55,10 +55,10 @@ $taxCalculationData['including_tax_total'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 19.98, 'base_grand_total' => 19.98, ], @@ -78,8 +78,8 @@ $taxCalculationData['including_tax_total'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_unit.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_unit.php index 905dd784d38dae5f8228dcb7226964e6b863fe10..03f582a753543e7eb7375f5d87f327f093fc4dd1 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_unit.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/including_tax_unit.php @@ -55,10 +55,10 @@ $taxCalculationData['including_tax_unit'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 19.98, 'base_grand_total' => 19.98, ], @@ -78,8 +78,8 @@ $taxCalculationData['including_tax_unit'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_no.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_no.php index d0d2e425830b1beffe42f8c0b1d8e498794b23f6..712b4365ab6ff4878c651b3a8da317260f21fc84 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_no.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_no.php @@ -75,10 +75,10 @@ $taxCalculationData['multi_tax_rule_total_calculate_subtotal_no'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 11.34, 'base_grand_total' => 11.34, 'applied_taxes' => [ @@ -124,8 +124,8 @@ $taxCalculationData['multi_tax_rule_total_calculate_subtotal_no'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_yes.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_yes.php index 8959d95ba7359ea62b0690b9a6528f5fae8b667f..3ddef5c5162d44ebc1e30378582dc25b1443e8d0 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_yes.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_total_calculate_subtotal_yes.php @@ -75,10 +75,10 @@ $taxCalculationData['multi_tax_rule_total_calculate_subtotal_yes'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 11.3, 'base_grand_total' => 11.3, 'applied_taxes' => [ @@ -124,8 +124,8 @@ $taxCalculationData['multi_tax_rule_total_calculate_subtotal_yes'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_row.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_row.php index 9580e894c69b16f27c771b7533df60053669ac1e..75dbde5089d1ebafe9ebe1a96671dd3869ae521c 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_row.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_row.php @@ -80,10 +80,10 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_row'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 23.36, 'base_grand_total' => 23.36, 'applied_taxes' => [ @@ -129,8 +129,8 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_row'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'applied_taxes' => [ [ 'amount' => 0.9, @@ -181,8 +181,8 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_row'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'applied_taxes' => [ [ 'amount' => 0.94, diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_total.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_total.php index baf75c132d84b8415da6fb310b9928a2a1d2ccc2..20a6ef1043ce886fa261702fec232b8f5ee89349 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_total.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_two_row_calculate_subtotal_yes_total.php @@ -80,10 +80,10 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_total'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 23.38, 'base_grand_total' => 23.38, 'applied_taxes' => [ @@ -129,8 +129,8 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_total'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'applied_taxes' => [ [ 'amount' => 0.9, @@ -181,8 +181,8 @@ $taxCalculationData['multi_tax_rule_two_row_calculate_subtotal_yes_total'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, 'applied_taxes' => [ [ 'amount' => 0.95, diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_no.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_no.php index dbf42d2c57f3127dbed372982342f9c9bbdb0cc6..f37949436180365734d05fdab72e52d9d64dad17 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_no.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_no.php @@ -75,10 +75,10 @@ $taxCalculationData['multi_tax_rule_unit_calculate_subtotal_no'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 11.4, 'base_grand_total' => 11.4, 'applied_taxes' => [ @@ -124,8 +124,8 @@ $taxCalculationData['multi_tax_rule_unit_calculate_subtotal_no'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_yes.php b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_yes.php index 40cc7ccce6e41e2d98aaf2f9f752a78c1c2e33f4..d13be92ad56afeda56e3e483ca6e87e3294bfe18 100644 --- a/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_yes.php +++ b/dev/tests/integration/testsuite/Magento/Tax/_files/scenarios/multi_tax_rule_unit_calculate_subtotal_yes.php @@ -75,10 +75,10 @@ $taxCalculationData['multi_tax_rule_unit_calculate_subtotal_yes'] = [ 'base_shipping_tax_amount' => 0, 'discount_amount' => 0, 'base_discount_amount' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, - 'shipping_hidden_tax_amount' => 0, - 'base_shipping_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, 'grand_total' => 11.4, 'base_grand_total' => 11.4, 'applied_taxes' => [ @@ -124,8 +124,8 @@ $taxCalculationData['multi_tax_rule_unit_calculate_subtotal_yes'] = [ 'discount_amount' => 0, 'base_discount_amount' => 0, 'discount_percent' => 0, - 'hidden_tax_amount' => 0, - 'base_hidden_tax_amount' => 0, + 'discount_tax_compensation_amount' => 0, + 'base_discount_tax_compensation_amount' => 0, ], ], ], diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dialog/dialog.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dialog/dialog.test.js new file mode 100644 index 0000000000000000000000000000000000000000..be1e6dfa867088f6174526b3d41c6fade7276b8a --- /dev/null +++ b/dev/tests/js/jasmine/tests/app/code/Magento/Ui/base/js/dialog/dialog.test.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'Magento_Ui/js/dialog/dialog' +], function ($) { + 'use strict'; + + describe('ui/js/dialog/dialog', function () { + var element = $('<div>some element</div>'), + dialog = element.dialog({}).data('mage-dialog'); + + it('Check for dialog definition', function () { + expect(dialog).toBeDefined(); + }); + it('Show/hide function check', function () { + expect(element.trigger('openDialog')).toBe(element); + expect(element.trigger('closeDialog')).toBe(element); + }); + it('Check for transition support', function () { + expect(dialog.whichTransitionEvent()).toBe('webkitTransitionEnd'); + }); + }); +}); \ No newline at end of file diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Core/Model/Fieldset/_files/fieldset.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Core/Model/Fieldset/_files/fieldset.xml index f6b412aa67c33d3e29d45368951034a2294d5602..16dc7a030a78901741a5e96dd97497e829289bb5 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Core/Model/Fieldset/_files/fieldset.xml +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Core/Model/Fieldset/_files/fieldset.xml @@ -269,16 +269,16 @@ <field name="base_grand_total"> <aspect name="to_order" /> </field> - <field name="hidden_tax_amount"> + <field name="discount_tax_compensation_amount"> <aspect name="to_order" /> </field> - <field name="base_hidden_tax_amount"> + <field name="base_discount_tax_compensation_amount"> <aspect name="to_order" /> </field> - <field name="shipping_hidden_tax_amount"> + <field name="shipping_discount_tax_compensation_amount"> <aspect name="to_order" /> </field> - <field name="base_shipping_hidden_tax_amount"> + <field name="base_shipping_discount_tax_compensation_amount"> <aspect name="to_order" /> </field> <field name="prefix"> @@ -473,10 +473,10 @@ <field name="store_id"> <aspect name="to_order_item" /> </field> - <field name="hidden_tax_amount"> + <field name="discount_tax_compensation_amount"> <aspect name="to_order_item" /> </field> - <field name="base_hidden_tax_amount"> + <field name="base_discount_tax_compensation_amount"> <aspect name="to_order_item" /> </field> <field name="free_shipping"> diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Core/Model/Fieldset/_files/invalid_fieldset.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Core/Model/Fieldset/_files/invalid_fieldset.xml index 8fba3db47c123f3e93fdc853c66a37323dae2c0d..a9a306b7183f922a97bfce3e90db36494f74848e 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Core/Model/Fieldset/_files/invalid_fieldset.xml +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Core/Model/Fieldset/_files/invalid_fieldset.xml @@ -269,18 +269,18 @@ <base_grand_total> <to_order>*</to_order> </base_grand_total> - <hidden_tax_amount> + <discount_tax_compensation_amount> <to_order>*</to_order> - </hidden_tax_amount> - <base_hidden_tax_amount> + </discount_tax_compensation_amount> + <base_discount_tax_compensation_amount> <to_order>*</to_order> - </base_hidden_tax_amount> - <shipping_hidden_tax_amount> + </base_discount_tax_compensation_amount> + <shipping_discount_tax_compensation_amount> <to_order>*</to_order> - </shipping_hidden_tax_amount> - <base_shipping_hidden_tax_amount> + </shipping_discount_tax_compensation_amount> + <base_shipping_discount_tax_compensation_amount> <to_order>*</to_order> - </base_shipping_hidden_tax_amount> + </base_shipping_discount_tax_compensation_amount> <prefix> <to_order_address>*</to_order_address> <to_customer_address>*</to_customer_address> @@ -473,12 +473,12 @@ <store_id> <to_order_item>*</to_order_item> </store_id> - <hidden_tax_amount> + <discount_tax_compensation_amount> <to_order_item>*</to_order_item> - </hidden_tax_amount> - <base_hidden_tax_amount> + </discount_tax_compensation_amount> + <base_discount_tax_compensation_amount> <to_order_item>*</to_order_item> - </base_hidden_tax_amount> + </base_discount_tax_compensation_amount> <free_shipping> <to_order_item>*</to_order_item> </free_shipping> diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/invalid_partial.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/invalid_partial.xml index 0010ef47c1ade472bc60e09b5eae240abca66bed..78d6ffb916f429b64c599160dcfc85586833b50b 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/invalid_partial.xml +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/invalid_partial.xml @@ -17,7 +17,7 @@ <queryReference clause="not" ref="fulltext_search_query"/> </query> <query xsi:type="matchQuery" value="$fulltext_search_query$" name="fulltext_search_query" boost="5"> - <match field="title" boost="2"/> + <match field="title"/> <match field="description"/> </query> <query xsi:type="filteredQuery" name="promoted_documents_boost"> diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/valid.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/valid.xml index e1bf879b160aeae196888ab51b38fb8a4a5b3a29..62fd4c97098b254e88b537aacd489232198610a3 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/valid.xml +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/valid.xml @@ -18,7 +18,7 @@ </query> <query xsi:type="matchQuery" name="fulltext_search_query" value="$fulltext_search_query$" boost="5"> - <match field="title" boost="2"/> + <match field="title"/> <match field="description"/> </query> @@ -73,7 +73,7 @@ <queryReference clause="not" ref="fulltext_search_query_c_2"/> </query> <query xsi:type="matchQuery" value="$fulltext_search$" name="fulltext_search_query_c_2" boost="5"> - <match field="title" boost="2"/> + <match field="title"/> <match field="description"/> </query> </queries> diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/valid_partial.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/valid_partial.xml index 2c300737ef2e42d37d06cb193407d8996f7fd8b8..55b05fa416e0cfd40e3d9c941c4bf4a3644d6a80 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/valid_partial.xml +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Search/_files/valid_partial.xml @@ -18,7 +18,7 @@ </query> <query xsi:type="matchQuery" value="$fulltext_search_query$" name="fulltext_search_query" boost="5"> - <match field="title" boost="2" /> + <match field="title" /> <match field="description" /> </query> diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/ConfigTest.php b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2df8d4f97e04ab0d4695526929f60d4b5f298deb --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/ConfigTest.php @@ -0,0 +1,105 @@ +<?php +/** + * Test indexer.xsd and xml files. + * + * Find "indexer.xml" files in code tree and validate them. Also verify schema fails on an invalid xml and + * passes on a valid xml. + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Test\Integrity\Magento\Indexer; + +class ConfigTest extends \Magento\TestFramework\Integrity\AbstractConfig +{ + /** + * Returns the name of the XSD file to be used to validate the XML + * + * @return string + */ + protected function _getXsd() + { + return '/app/code/Magento/Indexer/etc/indexer.xsd'; + } + + /** + * The location of a single valid complete xml file + * + * @return string + */ + protected function _getKnownValidXml() + { + return __DIR__ . '/_files/valid_indexer.xml'; + } + + /** + * The location of a single known invalid complete xml file + * + * @return string + */ + protected function _getKnownInvalidXml() + { + return __DIR__ . '/_files/invalid_indexer.xml'; + } + + /** + * The location of a single known valid partial xml file + * + * @return string + */ + protected function _getKnownValidPartialXml() + { + return null; + } + + /** + * Returns the name of the XSD file to be used to validate partial XML + * + * @return string + */ + protected function _getFileXsd() + { + return ''; + } + + /** + * The location of a single known invalid partial xml file + * + * @return string + */ + protected function _getKnownInvalidPartialXml() + { + return null; + } + + /** + * Returns the name of the xml files to validate + * + * @return string + */ + protected function _getXmlName() + { + return 'indexer.xml'; + } + + public function testSchemaUsingInvalidXml($expectedErrors = null) + { + // @codingStandardsIgnoreStart + $expectedErrors = [ + "Element 'indexer': Duplicate key-sequence ['catalogsearch_fulltext'] in unique identity-constraint 'uniqueViewId'.", + "Element 'indexer': Duplicate key-sequence ['indexer_0', 'catalogsearch_fulltext'] in unique identity-constraint 'uniqueIndexertId'.", + "Element 'fields': Missing child element(s). Expected is ( field ).", + "Element 'fields', attribute 'handler': [facet 'pattern'] The value 'field_handler' is not accepted by the pattern '[a-zA-Z\\\\]+'.", + "Element 'fields', attribute 'handler': 'field_handler' is not a valid value of the atomic type 'classType'.", + "Element 'field': Duplicate key-sequence ['visibility'] in unique identity-constraint 'uniqueField'.", + "Element 'field', attribute 'origin': [facet 'pattern'] The value 'table_name_field_name' is not accepted by the pattern '[a-zA-Z0-9_]+\\.[a-zA-Z0-9_]+'.", + "Element 'field', attribute 'origin': 'table_name_field_name' is not a valid value of the atomic type 'originType'.", + "Element 'field': The attribute 'dataType' is required but missing.", + "Element 'field', attribute '{http://www.w3.org/2001/XMLSchema-instance}type': The QName value 'any' of the xsi:type attribute does not resolve to a type definition.", + "Element 'field', attribute 'dataType': [facet 'enumeration'] The value 'string' is not an element of the set {'int', 'float', 'varchar'}.", + "Element 'field', attribute 'dataType': 'string' is not a valid value of the atomic type 'dataType'." + ]; + // @codingStandardsIgnoreEnd + parent::testSchemaUsingInvalidXml($expectedErrors); + } +} diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/invalid_indexer.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/invalid_indexer.xml new file mode 100644 index 0000000000000000000000000000000000000000..deccb217533f0f112802d13ec61130c3091c3d5a --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/invalid_indexer.xml @@ -0,0 +1,80 @@ +<?xml version="1.0"?> +<!-- +/** + * This file contains errors that will fail schema validation. + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../app/code/Magento/Indexer/etc/indexer.xsd"> + <indexer id="indexer_0" view_id="catalogsearch_fulltext" class="NotAClass"> + <title translate="true">Test Indexer Declaration</title> + <description translate="true">Invalid class attribute value</description> + </indexer> + <indexer id="indexer_0" view_id="catalogsearch_fulltext" class="Magento\CatalogSearch\Model\Indexer\Fulltext"> + <title translate="true">Test Indexer Declaration</title> + <description translate="true">Duplicate indexer id</description> + </indexer> + <indexer id="indexer_10" view_id="catalogsearch_fulltext_10" class="Magento\CatalogSearch\Model\Indexer\Fulltext"> + <title translate="true">Test Indexer Declaration</title> + <description translate="true">Duplicate 'view_id' in indexer declaration</description> + </indexer> + <indexer id="indexer_11" view_id="catalogsearch_fulltext_11" class="Magento\CatalogSearch\Model\Indexer\Fulltext"> + <title translate="true">Test Indexer Declaration</title> + <description translate="true">Empty fields</description> + <fields handler="Magento\Framework\Search\Index\Fields\Handler"/> + </indexer> + <indexer id="indexer_1" view_id="catalogsearch_fulltext_1" class="Magento\CatalogSearch\Model\Indexer\Fulltext"> + <title translate="true">Test Indexer Declaration</title> + <description translate="true">Invalid handler attribute value</description> + <fields handler="field_handler"> + <field name="visibility" origin="table_name.field_name" handler="Magento\Framework\Search\Index\Field\Handler\Class" xsi:type="filter" dataType="int" /> + </fields> + </indexer> + <indexer id="indexer_2" view_id="catalogsearch_fulltext_2" class="Magento\CatalogSearch\Model\Indexer\Fulltext"> + <title translate="true">Test Indexer Declaration</title> + <description translate="true">Duplicate field declaration</description> + <fields handler="Magento\Framework\Search\Index\Fields\Handler"> + <field name="visibility" origin="table_name.field_name" handler="Magento\Framework\Search\Index\Field\Handler\Class" xsi:type="filter" dataType="int" /> + <field name="visibility" origin="table_name.field_name" handler="Magento\Framework\Search\Index\Field\Handler\Class" xsi:type="both"> + <filter class="Magento\Framework\Search\Index\Filter\StopWordsFilter"/> + </field> + </fields> + </indexer> + <indexer id="indexer_3" view_id="catalogsearch_fulltext_3" class="Magento\CatalogSearch\Model\Indexer\Fulltext"> + <title translate="true">Test Indexer Declaration</title> + <description translate="true">Invalid origin attribute value</description> + <fields handler="Magento\Framework\Search\Index\Fields\Handler"> + <field name="visibility" origin="table_name_field_name" handler="Magento\Framework\Search\Index\Field\Handler\Class" xsi:type="both"/> + </fields> + </indexer> + <indexer id="indexer_4" view_id="catalogsearch_fulltext_4" class="Magento\CatalogSearch\Model\Indexer\Fulltext"> + <title translate="true">Test Indexer Declaration</title> + <description translate="true">Invalid field handler attribute value</description> + <fields handler="Magento\Framework\Search\Index\Fields\Handler"> + <field name="visibility" origin="table_name.field_name" handler="handler" xsi:type="filter" dataType="int"/> + </fields> + </indexer> + <indexer id="indexer_5" view_id="catalogsearch_fulltext_5" class="Magento\CatalogSearch\Model\Indexer\Fulltext"> + <title translate="true">Test Indexer Declaration</title> + <description translate="true">Invalid field type</description> + <fields handler="Magento\Framework\Search\Index\Fields\Handler"> + <field name="visibility" origin="table_name.field_name" handler="Magento\Framework\Search\Index\Field\Handler\Class" xsi:type="any"/> + </fields> + </indexer> + <indexer id="indexer_6" view_id="catalogsearch_fulltext_6" class="Magento\CatalogSearch\Model\Indexer\Fulltext"> + <title translate="true">Test Indexer Declaration</title> + <description translate="true">No dataType attribute for 'filter' type field</description> + <fields handler="Magento\Framework\Search\Index\Fields\Handler"> + <field name="visibility" origin="table_name.field_name" handler="Magento\Framework\Search\Index\Field\Handler\Class" xsi:type="filter"/> + </fields> + </indexer> + <indexer id="indexer_12" view_id="catalogsearch_fulltext_12" class="Magento\CatalogSearch\Model\Indexer\Fulltext"> + <title translate="true">Test Indexer Declaration</title> + <description translate="true">Invalid field dataType attribute value</description> + <fields handler="Magento\Framework\Search\Index\Fields\Handler"> + <field name="visibility" origin="table_name.field_name" handler="handler" xsi:type="filter" dataType="string"/> + </fields> + </indexer> +</config> diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/valid_indexer.xml b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/valid_indexer.xml new file mode 100644 index 0000000000000000000000000000000000000000..da0d383ffa547554aeaf3bcc14ba287861212bea --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Indexer/_files/valid_indexer.xml @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../app/code/Magento/Indexer/etc/indexer.xsd"> + <indexer id="indexer_1" view_id="catalogsearch_fulltext" class="Magento\CatalogSearch\Model\Indexer\Fulltext"> + <title translate="true">Test Indexer Declaration 1</title> + <description translate="true">Test Indexer Declaration 1</description> + <fields handler="Magento\Framework\Search\Index\Fields\Handler"> + <field name="title" origin="table_name.field_name" handler="Magento\Framework\Search\Index\Field\Handler\Class" xsi:type="both"> + <filter class="Magento\Framework\Search\Index\Filter\StopWordsFilter"/> + </field> + <field name="description" origin="table_name.field_name" handler="Magento\Framework\Search\Index\Field\Handler\Class" xsi:type="match"> + <filter class="Magento\Framework\Search\Index\Filter\LowercaseFilter"/> + </field> + <field name="visibility" origin="table_name.field_name" handler="Magento\Framework\Search\Index\Field\Handler\Class" xsi:type="filter" dataType="int" /> + </fields> + </indexer> +</config> diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/blacklist/obsolete_mage.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/blacklist/obsolete_mage.php index 6654e41160a637b121caa7b61c8a41d5bffe56db..3c8f1fbd1ac0429c8a6e28b2e200d8fe68ce12b1 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/blacklist/obsolete_mage.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/blacklist/obsolete_mage.php @@ -12,5 +12,6 @@ return [ 'downloader/app/Magento/Downloader/Model/Session.php', 'downloader/lib/Magento/Framework/Backup/Db.php', 'downloader/lib/Magento/Framework/Backup/Snapshot.php', - 'dev/tests/static/testsuite/Magento/Test/Integrity/ClassesTest.php' + 'dev/tests/static/testsuite/Magento/Test/Integrity/ClassesTest.php', + 'app/code/Magento/CatalogImportExport/Model/Import/Product/Validator/Category.php' ]; diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php old mode 100644 new mode 100755 index cfa0609a658460f9ab13834027dda6e6aa8ff948..638d18c04958565b8638e3bf97df343a8e58cb9d --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php @@ -2025,6 +2025,18 @@ return [ 'Magento\Core\Model\Layout\Argument\UpdaterInterface', 'Magento\Framework\View\Layout\Argument\UpdaterInterface', ], + [ + 'Magento\Framework\Api\Config\Converter', + 'Magento\Framework\Api\ExtensionAttribute\Config\Converter', + ], + [ + 'Magento\Framework\Api\Config\Reader', + 'Magento\Framework\Api\ExtensionAttribute\Config\Reader', + ], + [ + 'Magento\Framework\Api\Config\SchemaLocator', + 'Magento\Framework\Api\ExtensionAttribute\Config\SchemaLocator', + ], ['Magento\Core\Model\Layout\Filter\Acl', 'Magento\Backend\Model\Layout\Filter\Acl'], [ 'Magento\Framework\View\Layout\Argument\HandlerInterface', @@ -2082,6 +2094,7 @@ return [ ['Magento\Core\Model\Context', 'Magento\Framework\Model\Context'], ['Magento\Core\Model\Registry', 'Magento\Framework\Registry'], ['Magento\Framework\Code\Plugin\InvocationChain'], + ['Magento\Framework\Data\Collection\Db', 'Magento\Framework\Data\Collection\AbstractDb'], ['Magento\Catalog\Helper\Product\Flat'], ['Magento\Catalog\Helper\Flat\AbstractFlat'], ['Magento\Core\App\Action\Plugin\Install', 'Magento\Framework\App\Bootstrap'], @@ -3643,4 +3656,5 @@ return [ ['Magento\Centinel\Test\TestCase\CentinelPaymentsInvalidCcTest'], ['Magento\Centinel\Test\TestCase\CentinelPaymentsValidCcTest'], ['Magento\Centinel\CreateOrderTest'], + ['Magento\Payment\Model\Checks\PaymentMethodChecksInterface', 'Magento\Payment\Model\MethodInterface'] ]; diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php index 2ed697e91c893bf4e0c8c00c295925333bee0698..9d673b85440767476a42f3067945af15b318772a 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php @@ -768,6 +768,9 @@ return [ ['postDispatchMyAccountSave'], ['postDispatchSystemImportExportRun'], ['prepareAttributesForSave', 'Magento\CatalogImportExport\Model\Import\Product'], + ['getAffectedEntityIds', 'Magento\CatalogImportExport\Model\Import\Product'], + ['getCategoryWithRoot', 'Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor'], + ['getCategory', 'Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor'], ['prepareGoogleOptimizerScripts'], ['prepareRedirect', 'Magento\Core\Controller\Varien\Exception'], ['preparePriceAlertData', 'Magento\ProductAlert\Block\Product\View'], @@ -950,7 +953,7 @@ return [ ['_getGridHtml', 'Magento\User\Block\Role\Tab\Users', 'getGridHtml'], ['_getSelectedRoles', 'Magento\User\Block\User\Edit\Tab\Roles', 'getSelectedRoles'], ['_prepareSelect', 'Magento\Framework\Model\Resource\Db\Collection\AbstractCollection'], - ['_prepareSelect', 'Magento\Framework\Data\Collection\Db'], + ['_prepareSelect', 'Magento\Framework\Data\Collection\AbstractDb'], ['_createOrderFromAddress', 'Magento\Checkout\Model\Type\AbstractType'], ['_addLoadAttributesSelectFields', 'Magento\Catalog\Model\Resource\AbstractResource'], ['attributeSelectFields', 'Magento\Catalog\Model\Resource\Helper'], @@ -1583,7 +1586,7 @@ return [ ['_compareSortOrder', 'Magento\Sales\Model\Config\Ordered'], [ '_toOptionHashOptimized', - 'Magento\Framework\Data\Collection\Db', + 'Magento\Framework\Data\Collection\AbstractDb', 'Magento\Tax\Model\Resource\Calculation\Rate\Collection::toOptionHashOptimized', ], ['getSwitchCurrencyUrl', 'Magento\Directory\Block\Currency'], @@ -1679,6 +1682,7 @@ return [ ['getVisibleOnFrontStates', 'Magento\Sales\Model\Order\Config', 'getVisibleOnFrontStatuses'], ['getInvisibleOnFrontStates', 'Magento\Sales\Model\Order\Config', 'getInvisibleOnFrontStatuses'], ['_authorize', 'Magento\Sales\Model\Order\Payment'], + ['registerPaymentReviewAction', 'Magento\Sales\Model\Order\Payment'], ['_shouldBeConverted', 'Magento\Sales\Model\Resource\AbstractResource'], ['_beforeSave', 'Magento\Sales\Model\Resource\AbstractResource'], ['_afterSave', 'Magento\Sales\Model\Resource\AbstractResource'], @@ -2232,4 +2236,13 @@ return [ ['Magento\Catalog\Model\Product\Attribute\Backend\Startdate', 'Magento\Catalog\Model\Attribute\Backend\Startdate'], ['_getStoreTimezoneUtcOffset', 'Magento\Reports\Model\Resource\Report\AbstractReport'], ['_dateToUtc', 'Magento\Reports\Model\Resource\Report\AbstractReport'], + ['getDataSetDefault', 'Magento\Framework\Object'], + ['isDeleted', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], + ['hasDataChanges', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], + ['setIdFieldName', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], + ['getIdFieldName', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], + ['setOrigData', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], + ['getOrigData', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], + ['dataHasChangedFor', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], + ['setDataChanges', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], ]; diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php index b5f328e8bed28f5be002c3267a573a045351528a..cfb1078156bf214d798499c6e2bc9962702d8608 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_properties.php @@ -411,4 +411,8 @@ return [ ['_emulatedLocales', 'Magento\Framework\Locale\Resolver', 'emulatedLocales'], ['_collectionAttributes', 'Magento\Eav\Model\Config'], ['_attributeFactory', '\Magento\Customer\Model\Customer'], + ['_hasDataChanges', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], + ['_origData', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], + ['_idFieldName', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], + ['_isDeleted', 'Magento\Framework\Object', 'Moved to Magento\Framework\Model\AbstractModel'], ]; diff --git a/dev/tests/unit/phpunit.xml.dist b/dev/tests/unit/phpunit.xml.dist index 80c46fdb992251e2a617faee95ad3b67d47952dd..3e564d8323f875a000b48a90f77e2bdc5bbc846d 100644 --- a/dev/tests/unit/phpunit.xml.dist +++ b/dev/tests/unit/phpunit.xml.dist @@ -17,7 +17,7 @@ <directory suffix="Test.php">../../../lib/internal/*/*/Test/Unit</directory> <directory suffix="Test.php">../../../lib/internal/*/*/*/Test/Unit</directory> <directory suffix="Test.php">../../../setup/src/*/*/Test/Unit</directory> - <directory suffix="Test.php">../../../update/dev/tests/unit/testsuite</directory> + <directory suffix="Test.php">../../../update/app/code/*/*/Test/Unit</directory> </testsuite> <php> <ini name="date.timezone" value="America/Los_Angeles"/> @@ -34,6 +34,7 @@ <directory>../../../lib/internal/*/*/Test</directory> <directory>../../../lib/internal/*/*/*/Test</directory> <directory>../../../setup/src/*/*/Test</directory> + <directory>../../../update/app/code/*/*/Test</directory> </exclude> </whitelist> </filter> diff --git a/dev/tools/grunt/configs/replace.js b/dev/tools/grunt/configs/replace.js new file mode 100644 index 0000000000000000000000000000000000000000..8865cf72cdbfdd896f42ad092b3c56bd6e0b43ba --- /dev/null +++ b/dev/tools/grunt/configs/replace.js @@ -0,0 +1,55 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +'use strict'; + +var nlWin = '\r\n', + nlUnix = '\n'; + +function findCopyright(lang, nlSys) { + var copyrightText = { + firstLine: 'Copyright © 2015 Magento. All rights reserved.', + secondLine: 'See COPYING.txt for license details.' + }; + switch (lang) { + case 'less': + return new RegExp( + '// /\\*\\*' + nlSys + '// \\* ' + + copyrightText.firstLine + + '' + nlSys + '// \\* ' + + copyrightText.secondLine + + '' + nlSys + '// \\*/' + nlSys + nlSys + ); + break; + default: + return; + } +} + +module.exports = { + documentation: { + options: { + patterns: [ + { + match: findCopyright('less', nlWin), + replacement: '' + }, + { + match: findCopyright('less', nlUnix), + replacement: '' + } + ] + }, + files: [{ + expand: true, + flatten: true, + src: [ + '<%= path.doc %>/source/**/*.less' + ], + dest: '<%= path.doc %>/source/' + }] + } + +}; diff --git a/dev/tools/grunt/configs/usebanner.js b/dev/tools/grunt/configs/usebanner.js index fb952f050c2b906907decaec2cdf19783960ba1c..614ecb8d1d5985602f4d9c206d11703d7c1c4d2d 100644 --- a/dev/tools/grunt/configs/usebanner.js +++ b/dev/tools/grunt/configs/usebanner.js @@ -5,22 +5,26 @@ 'use strict'; -var banner = { - firstLine: 'Copyright © 2015 Magento. All rights reserved.', - secondLine: 'See COPYING.txt for license details.', - - css: function () { - return '/**\n * ' + this.firstLine + '\n * ' + this.secondLine + '\n */\n'; - }, - - less: function () { - return '// /**\n// * ' + this.firstLine + '\n// * ' + this.secondLine + '\n// */\n'; - }, - - html: function () { - return '<!--\n/**\n * ' + this.firstLine + '\n * ' + this.secondLine + '\n */\n-->\n'; +function printCopyright(lang) { + var copyrightText = { + firstLine: 'Copyright © 2015 Magento. All rights reserved.', + secondLine: 'See COPYING.txt for license details.' + }, + nlWin = '\r\n'; + switch (lang) { + case 'css': + return '/**' + nlWin + ' * ' + copyrightText.firstLine + nlWin + ' * ' + copyrightText.secondLine + nlWin + ' */' + nlWin; + break; + case 'less': + return '// /**' + nlWin + '// * ' + copyrightText.firstLine + nlWin + '// * ' + copyrightText.secondLine + nlWin + '// */' + nlWin; + break; + case 'html': + return '<!--' + nlWin + '/**' + nlWin + ' * ' + copyrightText.firstLine + nlWin + ' * ' + copyrightText.secondLine + nlWin + ' */' + nlWin + '-->' + nlWin; + break; + default: + return; } -}; +} module.exports = { options: { @@ -29,7 +33,7 @@ module.exports = { }, setup: { options: { - banner: banner.css() + banner: printCopyright('css') }, files: { src: '<%= path.css.setup %>/*.css' @@ -37,7 +41,7 @@ module.exports = { }, documentationCss: { options: { - banner: banner.css() + banner: printCopyright('css') }, files: { src: '<%= path.doc %>/**/*.css' @@ -45,7 +49,7 @@ module.exports = { }, documentationLess: { options: { - banner: banner.less() + banner: printCopyright('less') }, files: { src: '<%= path.doc %>/**/*.less' @@ -53,7 +57,7 @@ module.exports = { }, documentationHtml: { options: { - banner: banner.html() + banner: printCopyright('html') }, files: { src: '<%= path.doc %>/**/*.html' diff --git a/dev/tools/performance-toolkit/fixtures/orders.php b/dev/tools/performance-toolkit/fixtures/orders.php new file mode 100644 index 0000000000000000000000000000000000000000..e2aa2c832e0fb6390dda692fce7b5b831329b047 --- /dev/null +++ b/dev/tools/performance-toolkit/fixtures/orders.php @@ -0,0 +1,314 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Class OrdersFixture + */ +class OrdersFixture extends \Magento\ToolkitFramework\Fixture +{ + /** + * @var int + */ + protected $priority = 135; + + /** + * {@inheritdoc} + */ + public function execute() + { + $ordersCount = \Magento\ToolkitFramework\Config::getInstance()->getValue('orders', 0); + if ($ordersCount < 1) { + return; + } + $this->application->resetObjectManager(); + + $writeAdapter = $this->getConnection('write'); + + $quoteTableName = $this->getTableName( + 'quote', + 'Magento\Quote\Model\Resource\Quote' + ); + $quoteAddressTableName = $this->getTableName( + 'quote_address', + 'Magento\Quote\Model\Resource\Quote\Address' + ); + $quoteItemTableName = $this->getTableName( + 'quote_item', + 'Magento\Quote\Model\Resource\Quote\Item' + ); + $quoteItemOptionTableName = $this->getTableName( + 'quote_item_option', + 'Magento\Quote\Model\Resource\Quote\Item\Option' + ); + $quotePaymentTableName = $this->getTableName( + 'quote_payment', + 'Magento\Quote\Model\Resource\Quote\Payment' + ); + $quoteAddressRateTableName = $this->getTableName( + 'quote_shipping_rate', + 'Magento\Quote\Model\Resource\Quote\Address\Rate' + ); + $reportEventTableName = $this->getTableName( + 'report_event', + 'Magento\Reports\Model\Resource\Event' + ); + $salesOrderTableName = $this->getTableName( + 'sales_order', + 'Magento\Sales\Model\Resource\Order' + ); + $salesOrderAddressTableName = $this->getTableName( + 'sales_order_address', + 'Magento\Sales\Model\Resource\Order' + ); + $salesOrderGridTableName = $this->getTableName( + 'sales_order_grid', + 'Magento\Sales\Model\Resource\Order\Grid' + ); + $salesOrderItemTableName = $this->getTableName( + 'sales_order_item', + 'Magento\Sales\Model\Resource\Order\Item' + ); + $salesOrderPaymentTableName = $this->getTableName( + 'sales_order_payment', + 'Magento\Sales\Model\Resource\Order\Payment' + ); + $salesOrderStatusHistoryTableName = $this->getTableName( + 'sales_order_status_history', + 'Magento\Sales\Model\Resource\Order\Status\History' + ); + $eavEntityStoreTableName = $this->getTableName( + 'eav_entity_store', + '\Magento\Eav\Model\Resource\Entity\Store' + ); + /** @var \Magento\Store\Model\StoreManager $storeManager */ + $storeManager = $this->application->getObjectManager()->create('Magento\Store\Model\StoreManager'); + /** @var $category \Magento\Catalog\Model\Category */ + $category = $this->application->getObjectManager()->get('Magento\Catalog\Model\Category'); + /** @var $product \Magento\Catalog\Model\Product */ + $product = $this->application->getObjectManager()->get('Magento\Catalog\Model\Product'); + + $result = []; + $stores = $storeManager->getStores(); + foreach ($stores as $store) { + $storeId = $store->getStoreId(); + $websiteId = $store->getWebsite()->getId(); + $websiteName = $store->getWebsite()->getName(); + $groupName = $store->getGroup()->getName(); + $storeName = $store->getName(); + $storeRootCategory = $store->getRootCategoryId(); + $category->load($storeRootCategory); + $categoryResource = $category->getResource(); + //Get all categories + $resultsCategories = $categoryResource->getAllChildren($category); + foreach ($resultsCategories as $resultsCategory) { + $category->load($resultsCategory); + $structure = explode('/', $category->getPath()); + $pathSize = count($structure); + if ($pathSize > 1) { + $path = []; + for ($i = 1; $i < $pathSize; $i++) { + $path[] = $category->load($structure[$i])->getName(); + } + array_shift($path); + $resultsCategoryName = implode('/', $path); + } else { + $resultsCategoryName = $category->getName(); + } + //Not use root categories + if (trim($resultsCategoryName) != '') { + /** @var $productCategory \Magento\Catalog\Model\Category */ + $productCategory = $this->application->getObjectManager()->get('Magento\Catalog\Model\Category'); + + /** @var $simpleProductCollection \Magento\Catalog\Model\Resource\Product\Collection */ + $simpleProductCollection = $this->application->getObjectManager()->create( + 'Magento\Catalog\Model\Resource\Product\Collection' + ); + + $simpleProductCollection->addStoreFilter($storeId); + $simpleProductCollection->addWebsiteFilter($websiteId); + $simpleProductCollection->addCategoryFilter($productCategory->load($resultsCategory)); + $simpleProductCollection->getSelect()->where(" type_id = 'simple' "); + $simpleIds = $simpleProductCollection->getAllIds(2); + $simpleProductsResult = []; + foreach ($simpleIds as $key => $simpleId) { + $simpleProduct = $product->load($simpleId); + $simpleProductsResult[$key]['simpleProductId'] = $simpleId; + $simpleProductsResult[$key]['simpleProductSku'] = $simpleProduct->getSku(); + $simpleProductsResult[$key]['simpleProductName'] = $simpleProduct->getName(); + } + + $result[] = [ + $storeId, + $websiteName. '\n'. $groupName . '\n' . $storeName, + $simpleProductsResult + ]; + } + } + } + + $productStoreId = function ($index) use ($result) { + return $result[$index % count($result)][0]; + }; + $productStoreName = function ($index) use ($result) { + return $result[$index % count($result)][1]; + }; + + $simpleProductId[0] = function ($index) use ($result) { + return $result[$index % count($result)][2][0]['simpleProductId']; + }; + $simpleProductId[1] = function ($index) use ($result) { + return $result[$index % count($result)][2][1]['simpleProductId']; + }; + $simpleProductSku[0] = function ($index) use ($result) { + return $result[$index % count($result)][2][0]['simpleProductSku']; + }; + $simpleProductSku[1] = function ($index) use ($result) { + return $result[$index % count($result)][2][1]['simpleProductSku']; + }; + $simpleProductName[0] = function ($index) use ($result) { + return $result[$index % count($result)][2][0]['simpleProductName']; + }; + $simpleProductName[1] = function ($index) use ($result) { + return $result[$index % count($result)][2][1]['simpleProductName']; + }; + + $entityId = 1; + while ($entityId <= $ordersCount) { + $queries = ""; + + $orderNumber = 100000000 * $productStoreId($entityId) + $entityId; + $email = 'order_' . $entityId . '@example.com'; + $firstName = 'First Name'; + $lastName = 'Last Name'; + $company = 'Company'; + $address = 'Address'; + $city = 'City'; + $state = 'Alabama'; + $country = 'US'; + $zip = '11111'; + $phone = '911'; + $time = date("Y-m-d h:i:s"); + + $simpleProductIdLen[0] = strlen($simpleProductId[0]($entityId)); + $simpleProductIdLen[1] = strlen($simpleProductId[1]($entityId)); + + $queries .= "INSERT INTO `{$eavEntityStoreTableName}` (`entity_store_id`, `entity_type_id`, `store_id`, `increment_prefix`, `increment_last_id`) VALUES ({$productStoreId($entityId)}, 5, {$productStoreId($entityId)}, '{$productStoreId($entityId)}', '{$orderNumber}') ON DUPLICATE KEY UPDATE `increment_last_id`='{$orderNumber}';"; + + $quoteId = $entityId; + $queries .= "INSERT INTO `{$quoteTableName}` (`entity_id`, `store_id`, `created_at`, `updated_at`, `converted_at`, `is_active`, `is_virtual`, `is_multi_shipping`, `items_count`, `items_qty`, `orig_order_id`, `store_to_base_rate`, `store_to_quote_rate`, `base_currency_code`, `store_currency_code`, `quote_currency_code`, `grand_total`, `base_grand_total`, `checkout_method`, `customer_id`, `customer_tax_class_id`, `customer_group_id`, `customer_email`, `customer_prefix`, `customer_firstname`, `customer_middlename`, `customer_lastname`, `customer_suffix`, `customer_dob`, `customer_note`, `customer_note_notify`, `customer_is_guest`, `remote_ip`, `applied_rule_ids`, `reserved_order_id`, `password_hash`, `coupon_code`, `global_currency_code`, `base_to_global_rate`, `base_to_quote_rate`, `customer_taxvat`, `customer_gender`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `is_changed`, `trigger_recollect`, `ext_shipping_info`, `is_persistent`, `gift_message_id`) VALUES ({$quoteId}, {$productStoreId($entityId)}, '{$time}', '1970-01-01 03:00:00', NULL, 0, 0, 0, 2, 2.0000, 0, 0.0000, 0.0000, 'USD', 'USD', 'USD', 25.3000, 25.3000, 'guest', NULL, 3, 0, '{$email}', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, '127.0.0.1', '1', NULL, NULL, NULL, 'USD', 1.0000, 1.0000, NULL, NULL, 17.0000, 17.0000, 15.3000, 15.3000, 1, 0, NULL, 0, NULL);"; + + $quoteAddressId[0] = $entityId * 2 - 1; + $quoteAddressId[1] = $entityId * 2; + $queries .= "INSERT INTO `{$quoteAddressTableName}` (`address_id`, `quote_id`, `created_at`, `updated_at`, `customer_id`, `save_in_address_book`, `customer_address_id`, `address_type`, `email`, `prefix`, `firstname`, `middlename`, `lastname`, `suffix`, `company`, `street`, `city`, `region`, `region_id`, `postcode`, `country_id`, `telephone`, `fax`, `same_as_billing`, `collect_shipping_rates`, `shipping_method`, `shipping_description`, `weight`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `tax_amount`, `base_tax_amount`, `shipping_amount`, `base_shipping_amount`, `shipping_tax_amount`, `base_shipping_tax_amount`, `discount_amount`, `base_discount_amount`, `grand_total`, `base_grand_total`, `customer_notes`, `applied_taxes`, `discount_description`, `shipping_discount_amount`, `base_shipping_discount_amount`, `subtotal_incl_tax`, `base_subtotal_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `shipping_discount_tax_compensation_amount`, `base_shipping_discount_tax_compensation_amnt`, `shipping_incl_tax`, `base_shipping_incl_tax`, `free_shipping`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`, `gift_message_id`) VALUES ({$quoteAddressId[0]}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', NULL, 1, NULL, 'billing', '{$email}', NULL, '{$firstName}', NULL, '{$lastName}', NULL, '{$company}', '{$address}', '{$city}', '{$state}', 1, '{$zip}', '{$country}', '{$phone}', NULL, 0, 0, NULL, NULL, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, NULL, NULL, 0.0000, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, 0.0000, NULL, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries .= "INSERT INTO `{$quoteAddressTableName}` (`address_id`, `quote_id`, `created_at`, `updated_at`, `customer_id`, `save_in_address_book`, `customer_address_id`, `address_type`, `email`, `prefix`, `firstname`, `middlename`, `lastname`, `suffix`, `company`, `street`, `city`, `region`, `region_id`, `postcode`, `country_id`, `telephone`, `fax`, `same_as_billing`, `collect_shipping_rates`, `shipping_method`, `shipping_description`, `weight`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `tax_amount`, `base_tax_amount`, `shipping_amount`, `base_shipping_amount`, `shipping_tax_amount`, `base_shipping_tax_amount`, `discount_amount`, `base_discount_amount`, `grand_total`, `base_grand_total`, `customer_notes`, `applied_taxes`, `discount_description`, `shipping_discount_amount`, `base_shipping_discount_amount`, `subtotal_incl_tax`, `base_subtotal_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `shipping_discount_tax_compensation_amount`, `base_shipping_discount_tax_compensation_amnt`, `shipping_incl_tax`, `base_shipping_incl_tax`, `free_shipping`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`, `gift_message_id`) VALUES ({$quoteAddressId[1]}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', NULL, 0, NULL, 'shipping', '{$email}', NULL, '{$firstName}', NULL, '{$lastName}', NULL, '{$company}', '{$address}', '{$city}', '{$state}', 1, '{$zip}', '{$country}', '{$phone}', NULL, 1, 0, 'flatrate_flatrate', 'Flat Rate - Fixed', 2.0000, 17.0000, 17.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 10.0000, 0.0000, 0.0000, -1.7000, -1.7000, 25.3000, 25.3000, NULL, 'a:0:{}', NULL, 0.0000, 0.0000, 17.0000, NULL, 0.0000, 0.0000, 0.0000, NULL, 10.0000, 10.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL);"; + + $quoteItemId[0] = $entityId * 4 - 3; + $quoteItemId[1] = $entityId * 4 - 2; + $quoteItemId[2] = $entityId * 4 - 1; + $quoteItemId[3] = $entityId * 4; + $queries .= "INSERT INTO `{$quoteItemTableName}` (`item_id`, `quote_id`, `created_at`, `updated_at`, `product_id`, `store_id`, `parent_item_id`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `weight`, `qty`, `price`, `base_price`, `custom_price`, `discount_percent`, `discount_amount`, `base_discount_amount`, `tax_percent`, `tax_amount`, `base_tax_amount`, `row_total`, `base_row_total`, `row_total_with_discount`, `row_weight`, `product_type`, `base_tax_before_discount`, `tax_before_discount`, `original_custom_price`, `redirect_url`, `base_cost`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `free_shipping`, `gift_message_id`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$quoteItemId[0]}, {$quoteId}, '1970-01-01 03:00:00', '1970-01-01 03:00:00', {$simpleProductId[0]($entityId)}, {$productStoreId($entityId)}, NULL, 0, '{$simpleProductSku[0]($entityId)}', '{$simpleProductName[0]($entityId)}', NULL, '1', NULL, 0, 0, 1.0000, 1.0000, 8.5000, 8.5000, NULL, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 1.0000, 'simple', NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries .= "INSERT INTO `{$quoteItemTableName}` (`item_id`, `quote_id`, `created_at`, `updated_at`, `product_id`, `store_id`, `parent_item_id`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `weight`, `qty`, `price`, `base_price`, `custom_price`, `discount_percent`, `discount_amount`, `base_discount_amount`, `tax_percent`, `tax_amount`, `base_tax_amount`, `row_total`, `base_row_total`, `row_total_with_discount`, `row_weight`, `product_type`, `base_tax_before_discount`, `tax_before_discount`, `original_custom_price`, `redirect_url`, `base_cost`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `free_shipping`, `gift_message_id`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$quoteItemId[1]}, {$quoteId}, '1970-01-01 03:00:00', '1970-01-01 03:00:00', {$simpleProductId[1]($entityId)}, {$productStoreId($entityId)}, NULL, 0, '{$simpleProductSku[1]($entityId)}', '{$simpleProductName[1]($entityId)}', NULL, '1', NULL, 0, 0, 1.0000, 1.0000, 8.5000, 8.5000, NULL, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 1.0000, 'simple', NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + + $quoteItemOptionId[0] = $entityId * 8 - 7; + $quoteItemOptionId[1] = $entityId * 8 - 6; + $quoteItemOptionId[2] = $entityId * 8 - 5; + $quoteItemOptionId[3] = $entityId * 8 - 4; + $quoteItemOptionId[4] = $entityId * 8 - 3; + $quoteItemOptionId[5] = $entityId * 8 - 2; + $quoteItemOptionId[6] = $entityId * 8 - 1; + $quoteItemOptionId[7] = $entityId * 8; + $queries .= "INSERT INTO `{$quoteItemOptionTableName}` (`option_id`, `item_id`, `product_id`, `code`, `value`) VALUES ({$quoteItemOptionId[0]}, {$quoteItemId[0]}, {$simpleProductId[0]($entityId)}, 'info_buyRequest', 'a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[0]}:\"{$simpleProductId[0]($entityId)}\";s:3:\"qty\";i:1;}');"; + $queries .= "INSERT INTO `{$quoteItemOptionTableName}` (`option_id`, `item_id`, `product_id`, `code`, `value`) VALUES ({$quoteItemOptionId[1]}, {$quoteItemId[1]}, {$simpleProductId[1]($entityId)}, 'info_buyRequest', 'a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[1]}:\"{$simpleProductId[1]($entityId)}\";s:3:\"qty\";i:1;}');"; + + $quotePaymentId = $quoteId; + $queries .= "INSERT INTO `{$quotePaymentTableName}` (`payment_id`, `quote_id`, `created_at`, `updated_at`, `method`, `cc_type`, `cc_number_enc`, `cc_last_4`, `cc_cid_enc`, `cc_owner`, `cc_exp_month`, `cc_exp_year`, `cc_ss_owner`, `cc_ss_start_month`, `cc_ss_start_year`, `po_number`, `additional_data`, `cc_ss_issue`, `additional_information`) VALUES ({$quotePaymentId}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', 'checkmo', NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, NULL, NULL, NULL, NULL);"; + + $quoteShippingRateId = $quoteAddressId[1]; + $queries .= "INSERT INTO `{$quoteAddressRateTableName}` (`rate_id`, `address_id`, `created_at`, `updated_at`, `carrier`, `carrier_title`, `code`, `method`, `method_description`, `price`, `error_message`, `method_title`) VALUES ({$quoteShippingRateId}, {$quoteAddressId[1]}, '{$time}', '1970-01-01 03:00:00', 'flatrate', 'Flat Rate', 'flatrate_flatrate', 'flatrate', NULL, 10.0000, NULL, 'Fixed');"; + + $reportEventId[0] = $quoteItemId[0]; + $reportEventId[1] = $quoteItemId[1]; + $reportEventId[2] = $quoteItemId[2]; + $reportEventId[3] = $quoteItemId[3]; + $queries .= "INSERT INTO `{$reportEventTableName}` (`event_id`, `logged_at`, `event_type_id`, `object_id`, `subject_id`, `subtype`, `store_id`) VALUES ({$reportEventId[0]}, '{$time}', 4, {$simpleProductId[0]($entityId)}, 2, 1, {$productStoreId($entityId)});"; + $queries .= "INSERT INTO `{$reportEventTableName}` (`event_id`, `logged_at`, `event_type_id`, `object_id`, `subject_id`, `subtype`, `store_id`) VALUES ({$reportEventId[1]}, '{$time}', 4, {$simpleProductId[1]($entityId)}, 2, 1, {$productStoreId($entityId)});"; + + $salesOrderId = $quoteId; + $queries .= "INSERT INTO `{$salesOrderTableName}` (`entity_id`, `state`, `status`, `coupon_code`, `protect_code`, `shipping_description`, `is_virtual`, `store_id`, `customer_id`, `base_discount_amount`, `base_discount_canceled`, `base_discount_invoiced`, `base_discount_refunded`, `base_grand_total`, `base_shipping_amount`, `base_shipping_canceled`, `base_shipping_invoiced`, `base_shipping_refunded`, `base_shipping_tax_amount`, `base_shipping_tax_refunded`, `base_subtotal`, `base_subtotal_canceled`, `base_subtotal_invoiced`, `base_subtotal_refunded`, `base_tax_amount`, `base_tax_canceled`, `base_tax_invoiced`, `base_tax_refunded`, `base_to_global_rate`, `base_to_order_rate`, `base_total_canceled`, `base_total_invoiced`, `base_total_invoiced_cost`, `base_total_offline_refunded`, `base_total_online_refunded`, `base_total_paid`, `base_total_qty_ordered`, `base_total_refunded`, `discount_amount`, `discount_canceled`, `discount_invoiced`, `discount_refunded`, `grand_total`, `shipping_amount`, `shipping_canceled`, `shipping_invoiced`, `shipping_refunded`, `shipping_tax_amount`, `shipping_tax_refunded`, `store_to_base_rate`, `store_to_order_rate`, `subtotal`, `subtotal_canceled`, `subtotal_invoiced`, `subtotal_refunded`, `tax_amount`, `tax_canceled`, `tax_invoiced`, `tax_refunded`, `total_canceled`, `total_invoiced`, `total_offline_refunded`, `total_online_refunded`, `total_paid`, `total_qty_ordered`, `total_refunded`, `can_ship_partially`, `can_ship_partially_item`, `customer_is_guest`, `customer_note_notify`, `billing_address_id`, `customer_group_id`, `edit_increment`, `email_sent`, `send_email`, `forced_shipment_with_invoice`, `payment_auth_expiration`, `quote_address_id`, `quote_id`, `shipping_address_id`, `adjustment_negative`, `adjustment_positive`, `base_adjustment_negative`, `base_adjustment_positive`, `base_shipping_discount_amount`, `base_subtotal_incl_tax`, `base_total_due`, `payment_authorization_amount`, `shipping_discount_amount`, `subtotal_incl_tax`, `total_due`, `weight`, `customer_dob`, `increment_id`, `applied_rule_ids`, `base_currency_code`, `customer_email`, `customer_firstname`, `customer_lastname`, `customer_middlename`, `customer_prefix`, `customer_suffix`, `customer_taxvat`, `discount_description`, `ext_customer_id`, `ext_order_id`, `global_currency_code`, `hold_before_state`, `hold_before_status`, `order_currency_code`, `original_increment_id`, `relation_child_id`, `relation_child_real_id`, `relation_parent_id`, `relation_parent_real_id`, `remote_ip`, `shipping_method`, `store_currency_code`, `store_name`, `x_forwarded_for`, `customer_note`, `created_at`, `updated_at`, `total_item_count`, `customer_gender`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `shipping_discount_tax_compensation_amount`, `base_shipping_discount_tax_compensation_amnt`, `discount_tax_compensation_invoiced`, `base_discount_tax_compensation_invoiced`, `discount_tax_compensation_refunded`, `base_discount_tax_compensation_refunded`, `shipping_incl_tax`, `base_shipping_incl_tax`, `coupon_rule_name`, `gift_message_id`) VALUES ({$salesOrderId}, 'new', 'pending', NULL, '272ecb', 'Flat Rate - Fixed', 0, {$productStoreId($entityId)}, NULL, -1.7000, NULL, NULL, NULL, 25.3000, 10.0000, NULL, NULL, NULL, 0.0000, NULL, 17.0000, NULL, NULL, NULL, 0.0000, NULL, NULL, NULL, 1.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1.7000, NULL, NULL, NULL, 25.3000, 10.0000, NULL, NULL, NULL, 0.0000, NULL, 0.0000, 0.0000, 17.0000, NULL, NULL, NULL, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2.0000, NULL, NULL, NULL, 1, 1, 2, 0, NULL, 1, 1, NULL, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, NULL, 17.0000, 25.3000, NULL, NULL, 17.0000, 25.3000, 2.0000, NULL, {$orderNumber}, '1', 'USD', '{$email}', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'USD', NULL, NULL, 'USD', NULL, NULL, NULL, NULL, NULL, '127.0.0.1', 'flatrate_flatrate', 'USD', '{$productStoreName($entityId)}', NULL, NULL, '{$time}', '{$time}', 2, NULL, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, 10.0000, 10.0000, NULL, NULL);"; + + $salesOrderAddressId[0] = $quoteAddressId[0]; + $salesOrderAddressId[1] = $quoteAddressId[1]; + $queries .= "INSERT INTO `{$salesOrderAddressTableName}` (`entity_id`, `parent_id`, `customer_address_id`, `quote_address_id`, `region_id`, `customer_id`, `fax`, `region`, `postcode`, `lastname`, `street`, `city`, `email`, `telephone`, `country_id`, `firstname`, `address_type`, `prefix`, `middlename`, `suffix`, `company`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`) VALUES ({$salesOrderAddressId[0]}, {$salesOrderId}, NULL, NULL, 1, NULL, NULL, '{$state}', '{$zip}', '{$lastName}', '{$address}', '{$city}', '{$email}', '{$phone}', '{$country}', '{$firstName}', 'shipping', NULL, NULL, NULL, '{$company}', NULL, NULL, NULL, NULL, NULL);"; + $queries .= "INSERT INTO `{$salesOrderAddressTableName}` (`entity_id`, `parent_id`, `customer_address_id`, `quote_address_id`, `region_id`, `customer_id`, `fax`, `region`, `postcode`, `lastname`, `street`, `city`, `email`, `telephone`, `country_id`, `firstname`, `address_type`, `prefix`, `middlename`, `suffix`, `company`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`) VALUES ({$salesOrderAddressId[1]}, {$salesOrderId}, NULL, NULL, 1, NULL, NULL, '{$state}', '{$zip}', '{$lastName}', '{$address}', '{$city}', '{$email}', '{$phone}', '{$country}', '{$firstName}', 'billing', NULL, NULL, NULL, '{$company}', NULL, NULL, NULL, NULL, NULL);"; + + $salesOrderGridId = $salesOrderId; + $queries .= "INSERT INTO `{$salesOrderGridTableName}` (`entity_id`, `status`, `store_id`, `store_name`, `customer_id`, `base_grand_total`, `base_total_paid`, `grand_total`, `total_paid`, `increment_id`, `base_currency_code`, `order_currency_code`, `shipping_name`, `billing_name`, `created_at`, `updated_at`) VALUES ({$salesOrderGridId}, 'pending', {$productStoreId($entityId)}, '{$productStoreName($entityId)}', NULL, 25.3000, NULL, 25.3000, NULL, {$orderNumber}, 'USD', 'USD', '', '', '{$time}', NULL);"; + + $salesOrderItemId[0] = $quoteItemId[0]; + $salesOrderItemId[1] = $quoteItemId[1]; + $salesOrderItemId[2] = $quoteItemId[2]; + $salesOrderItemId[3] = $quoteItemId[3]; + $queries .= "INSERT INTO `{$salesOrderItemTableName}` (`item_id`, `order_id`, `parent_item_id`, `quote_item_id`, `store_id`, `created_at`, `updated_at`, `product_id`, `product_type`, `product_options`, `weight`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `qty_backordered`, `qty_canceled`, `qty_invoiced`, `qty_ordered`, `qty_refunded`, `qty_shipped`, `base_cost`, `price`, `base_price`, `original_price`, `base_original_price`, `tax_percent`, `tax_amount`, `base_tax_amount`, `tax_invoiced`, `base_tax_invoiced`, `discount_percent`, `discount_amount`, `base_discount_amount`, `discount_invoiced`, `base_discount_invoiced`, `amount_refunded`, `base_amount_refunded`, `row_total`, `base_row_total`, `row_invoiced`, `base_row_invoiced`, `row_weight`, `base_tax_before_discount`, `tax_before_discount`, `ext_order_item_id`, `locked_do_invoice`, `locked_do_ship`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `discount_tax_compensation_invoiced`, `base_discount_tax_compensation_invoiced`, `discount_tax_compensation_refunded`, `base_discount_tax_compensation_refunded`, `tax_canceled`, `discount_tax_compensation_canceled`, `tax_refunded`, `base_tax_refunded`, `discount_refunded`, `base_discount_refunded`, `free_shipping`, `gift_message_id`, `gift_message_available`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$salesOrderItemId[0]}, {$salesOrderId}, NULL, {$quoteItemId[0]}, {$productStoreId($entityId)}, '{$time}', '0000-00-00 00:00:00', {$simpleProductId[0]($entityId)}, 'simple', 'a:1:{s:15:\"info_buyRequest\";a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[0]}:\"{$simpleProductId[0]($entityId)}\";s:3:\"qty\";i:1;}}', 1.0000, 0, '{$simpleProductSku[0]($entityId)}', '{$simpleProductName[0]($entityId)}', NULL, '1', NULL, 0, 0, NULL, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, NULL, 8.5000, 8.5000, 10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 0.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries .= "INSERT INTO `{$salesOrderItemTableName}` (`item_id`, `order_id`, `parent_item_id`, `quote_item_id`, `store_id`, `created_at`, `updated_at`, `product_id`, `product_type`, `product_options`, `weight`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `qty_backordered`, `qty_canceled`, `qty_invoiced`, `qty_ordered`, `qty_refunded`, `qty_shipped`, `base_cost`, `price`, `base_price`, `original_price`, `base_original_price`, `tax_percent`, `tax_amount`, `base_tax_amount`, `tax_invoiced`, `base_tax_invoiced`, `discount_percent`, `discount_amount`, `base_discount_amount`, `discount_invoiced`, `base_discount_invoiced`, `amount_refunded`, `base_amount_refunded`, `row_total`, `base_row_total`, `row_invoiced`, `base_row_invoiced`, `row_weight`, `base_tax_before_discount`, `tax_before_discount`, `ext_order_item_id`, `locked_do_invoice`, `locked_do_ship`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `discount_tax_compensation_invoiced`, `base_discount_tax_compensation_invoiced`, `discount_tax_compensation_refunded`, `base_discount_tax_compensation_refunded`, `tax_canceled`, `discount_tax_compensation_canceled`, `tax_refunded`, `base_tax_refunded`, `discount_refunded`, `base_discount_refunded`, `free_shipping`, `gift_message_id`, `gift_message_available`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$salesOrderItemId[1]}, {$salesOrderId}, NULL, {$quoteItemId[1]}, {$productStoreId($entityId)}, '{$time}', '0000-00-00 00:00:00', {$simpleProductId[1]($entityId)}, 'simple', 'a:1:{s:15:\"info_buyRequest\";a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[1]}:\"{$simpleProductId[1]($entityId)}\";s:3:\"qty\";i:1;}}', 1.0000, 0, '{$simpleProductSku[1]($entityId)}', '{$simpleProductName[1]($entityId)}', NULL, '1', NULL, 0, 0, NULL, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, NULL, 8.5000, 8.5000, 10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 0.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + + $salesOrderPaymentId = $salesOrderId; + $queries .= "INSERT INTO `{$salesOrderPaymentTableName}` (`entity_id`, `parent_id`, `base_shipping_captured`, `shipping_captured`, `amount_refunded`, `base_amount_paid`, `amount_canceled`, `base_amount_authorized`, `base_amount_paid_online`, `base_amount_refunded_online`, `base_shipping_amount`, `shipping_amount`, `amount_paid`, `amount_authorized`, `base_amount_ordered`, `base_shipping_refunded`, `shipping_refunded`, `base_amount_refunded`, `amount_ordered`, `base_amount_canceled`, `quote_payment_id`, `additional_data`, `cc_exp_month`, `cc_ss_start_year`, `echeck_bank_name`, `method`, `cc_debug_request_body`, `cc_secure_verify`, `protection_eligibility`, `cc_approval`, `cc_last_4`, `cc_status_description`, `echeck_type`, `cc_debug_response_serialized`, `cc_ss_start_month`, `echeck_account_type`, `last_trans_id`, `cc_cid_status`, `cc_owner`, `cc_type`, `po_number`, `cc_exp_year`, `cc_status`, `echeck_routing_number`, `account_status`, `anet_trans_method`, `cc_debug_response_body`, `cc_ss_issue`, `echeck_account_name`, `cc_avs_status`, `cc_number_enc`, `cc_trans_id`, `address_status`, `additional_information`) VALUES ({$salesOrderPaymentId}, {$salesOrderId}, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 10.0000, 10.0000, NULL, NULL, 25.3000, NULL, NULL, NULL, 25.3000, NULL, NULL, NULL, NULL, '0', NULL, 'checkmo', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '0', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'a:1:{s:53:\"a:1:{s:12:\"method_title\";s:19:\"Check / Money order\";}\";N;}');"; + + $salesOrderStatusHistoryId = $salesOrderId; + $queries .= "INSERT INTO `{$salesOrderStatusHistoryTableName}` (`entity_id`, `parent_id`, `is_customer_notified`, `is_visible_on_front`, `comment`, `status`, `created_at`, `entity_name`) VALUES ({$salesOrderStatusHistoryId}, {$salesOrderId}, 1, 0, NULL, 'pending', '{$time}', 'order');"; + + $writeAdapter->multiQuery($queries); + + $entityId++; + } + } + + /** + * {@inheritdoc} + */ + public function getActionTitle() + { + return 'Generating orders'; + } + + /** + * {@inheritdoc} + */ + public function introduceParamLabels() + { + return [ + 'orders' => 'Orders' + ]; + } + + /** + * Get real table name for db table, validated by db adapter + * + * @param string $tableName + * @param string $resourceName + * @return string + */ + public function getTableName($tableName, $resourceName) + { + $resource = $this->application->getObjectManager()->get($resourceName); + return $this->getConnection('write')->getTableName($resource->getTable($tableName)); + } + + /** + * Retrieve connection to resource specified by $resourceName + * + * @param string $resourceName + * @return \Magento\Framework\DB\Adapter\AdapterInterface|false + */ + public function getConnection($resourceName) + { + return $this->application->getObjectManager()->get( + 'Magento\Framework\App\Resource' + )->getConnection($resourceName); + } +} + +return new OrdersFixture($this); diff --git a/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesGenerator.php b/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesGenerator.php index aa91250b41fb3ce83f95c8d3df94e144c79a9bfb..c700cc21b55b4c014041f01600fcc8d268719198 100644 --- a/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesGenerator.php +++ b/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesGenerator.php @@ -8,7 +8,7 @@ namespace Magento\Framework\Api\Code\Generator; use Magento\Framework\Code\Generator\DefinedClasses; use Magento\Framework\Code\Generator\Io; use Magento\Framework\Api\SimpleDataObjectConverter; -use Magento\Framework\Api\Config\Converter; +use Magento\Framework\Api\ExtensionAttribute\Config\Converter; /** * Code generator for data object extensions. @@ -20,9 +20,9 @@ class ExtensionAttributesGenerator extends \Magento\Framework\Code\Generator\Ent const EXTENSION_SUFFIX = 'Extension'; /** - * @var \Magento\Framework\Api\Config\Reader + * @var \Magento\Framework\Api\ExtensionAttribute\Config */ - protected $configReader; + protected $config; /** * @var array @@ -32,7 +32,7 @@ class ExtensionAttributesGenerator extends \Magento\Framework\Code\Generator\Ent /** * Initialize dependencies. * - * @param \Magento\Framework\Api\Config\Reader $configReader + * @param \Magento\Framework\Api\ExtensionAttribute\Config $config * @param string|null $sourceClassName * @param string|null $resultClassName * @param Io $ioObject @@ -40,7 +40,7 @@ class ExtensionAttributesGenerator extends \Magento\Framework\Code\Generator\Ent * @param DefinedClasses $definedClasses */ public function __construct( - \Magento\Framework\Api\Config\Reader $configReader, + \Magento\Framework\Api\ExtensionAttribute\Config $config, $sourceClassName = null, $resultClassName = null, Io $ioObject = null, @@ -48,7 +48,7 @@ class ExtensionAttributesGenerator extends \Magento\Framework\Code\Generator\Ent DefinedClasses $definedClasses = null ) { $sourceClassName .= 'Interface'; - $this->configReader = $configReader; + $this->config = $config; parent::__construct( $sourceClassName, $resultClassName, @@ -148,7 +148,7 @@ class ExtensionAttributesGenerator extends \Magento\Framework\Code\Generator\Ent protected function getCustomAttributes() { if (!isset($this->allCustomAttributes)) { - $this->allCustomAttributes = $this->configReader->read(); + $this->allCustomAttributes = $this->config->get(); } $dataInterface = ltrim($this->getSourceClassName(), '\\'); if (isset($this->allCustomAttributes[$dataInterface])) { diff --git a/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesInterfaceGenerator.php b/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesInterfaceGenerator.php index 59b6f225bb6c1d84acdfb20d96880980712b1bd2..468aff6e133696b0583b6ed951b8cb40e170cb64 100644 --- a/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesInterfaceGenerator.php +++ b/lib/internal/Magento/Framework/Api/Code/Generator/ExtensionAttributesInterfaceGenerator.php @@ -20,7 +20,7 @@ class ExtensionAttributesInterfaceGenerator extends \Magento\Framework\Api\Code\ /** * Initialize dependencies. * - * @param \Magento\Framework\Api\Config\Reader $configReader + * @param \Magento\Framework\Api\ExtensionAttribute\Config $config * @param string|null $sourceClassName * @param string|null $resultClassName * @param Io $ioObject @@ -28,7 +28,7 @@ class ExtensionAttributesInterfaceGenerator extends \Magento\Framework\Api\Code\ * @param DefinedClasses $definedClasses */ public function __construct( - \Magento\Framework\Api\Config\Reader $configReader, + \Magento\Framework\Api\ExtensionAttribute\Config $config, $sourceClassName = null, $resultClassName = null, Io $ioObject = null, @@ -39,7 +39,7 @@ class ExtensionAttributesInterfaceGenerator extends \Magento\Framework\Api\Code\ $classGenerator = new \Magento\Framework\Code\Generator\InterfaceGenerator(); } parent::__construct( - $configReader, + $config, $sourceClassName, $resultClassName, $ioObject, diff --git a/lib/internal/Magento/Framework/Api/DataObjectHelper.php b/lib/internal/Magento/Framework/Api/DataObjectHelper.php index 698a6d83922851fc8cd50c98e6b8516d71b87ea7..80e8587315bd552b5982000250003b6734719741 100644 --- a/lib/internal/Magento/Framework/Api/DataObjectHelper.php +++ b/lib/internal/Magento/Framework/Api/DataObjectHelper.php @@ -69,6 +69,9 @@ class DataObjectHelper */ public function populateWithArray($dataObject, array $data, $interfaceName) { + if ($dataObject instanceof ExtensibleDataInterface) { + $data = $this->extensionFactory->extractExtensionAttributes(get_class($dataObject), $data); + } $this->_setDataValues($dataObject, $data, $interfaceName); return $this; } @@ -115,10 +118,8 @@ class DataObjectHelper $getterMethodName = 'get' . $camelCaseKey; $this->setComplexValue($dataObject, $getterMethodName, $methodName, $value, $interfaceName); } - } else { - if ($dataObject instanceof ExtensibleDataInterface) { - $dataObject->setCustomAttribute($key, $value); - } + } elseif ($dataObject instanceof CustomAttributesDataInterface) { + $dataObject->setCustomAttribute($key, $value); } } diff --git a/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..94f36b513e2703fcf6a4b83bc8c307dab70f72db --- /dev/null +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Api\ExtensionAttribute; + +use Magento\Framework\Config\CacheInterface; +use Magento\Framework\Api\ExtensionAttribute\Config\Reader; + +/** + * Extension attributes config + */ +class Config extends \Magento\Framework\Config\Data +{ + const CACHE_ID = 'extension_attributes_config'; + + /** + * Initialize reader and cache. + * + * @param Reader $reader + * @param CacheInterface $cache + */ + public function __construct( + Reader $reader, + CacheInterface $cache + ) { + parent::__construct($reader, $cache, self::CACHE_ID); + } +} diff --git a/lib/internal/Magento/Framework/Api/Config/Converter.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/Converter.php similarity index 50% rename from lib/internal/Magento/Framework/Api/Config/Converter.php rename to lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/Converter.php index 68914a98b5c77ab1bc452c90fc26dfbee64797d8..f4e9df7cd643a67eccf4893097bb70b257fd2ef2 100644 --- a/lib/internal/Magento/Framework/Api/Config/Converter.php +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/Converter.php @@ -3,12 +3,19 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Framework\Api\Config; +namespace Magento\Framework\Api\ExtensionAttribute\Config; class Converter implements \Magento\Framework\Config\ConverterInterface { const RESOURCE_PERMISSIONS = "resourceRefs"; const DATA_TYPE = "type"; + const JOIN_DIRECTIVE = "join"; + const JOIN_REFERENCE_TABLE = "join_reference_table"; + const JOIN_REFERENCE_FIELD = "join_reference_field"; + const JOIN_SELECT_FIELDS = "join_select_fields"; + const JOIN_SELECT_FIELD = "select_field"; + const JOIN_SELECT_FIELD_SETTER = "setter_name"; + const JOIN_JOIN_ON_FIELD= "join_join_on_field"; /** * Convert dom node tree to array @@ -47,9 +54,13 @@ class Converter implements \Magento\Framework\Config\ConverterInterface } } + $joinElement = $attribute->getElementsByTagName('join')->item(0); + $join = $this->processJoinElement($joinElement, $attribute); + $typeConfig[$code] = [ self::DATA_TYPE => $codeType, self::RESOURCE_PERMISSIONS => $resourceRefs, + self::JOIN_DIRECTIVE => $join, ]; } @@ -57,4 +68,35 @@ class Converter implements \Magento\Framework\Config\ConverterInterface } return $output; } + + /** + * Process the join element configuration + * + * @param \DOMElement $joinElement + * @param \DOMElement $attribute + * @return array + */ + private function processJoinElement($joinElement, $attribute) + { + $join = null; + if ($joinElement && $joinElement->nodeType === XML_ELEMENT_NODE) { + $joinAttributes = $joinElement->attributes; + $join = [ + self::JOIN_REFERENCE_TABLE => $joinAttributes->getNamedItem('reference_table')->nodeValue, + self::JOIN_JOIN_ON_FIELD => $joinAttributes->getNamedItem('join_on_field')->nodeValue, + self::JOIN_REFERENCE_FIELD => $joinAttributes->getNamedItem('reference_field')->nodeValue, + ]; + $selectElements = $attribute->getElementsByTagName('select_field'); + foreach ($selectElements as $selectElement) { + $selectField = $selectElement->nodeValue; + $setterName = $selectElement->getAttribute('setter_name'); + $join[self::JOIN_SELECT_FIELDS][] = [ + self::JOIN_SELECT_FIELD => $selectField, + self::JOIN_SELECT_FIELD_SETTER => $setterName + ]; + } + } + + return $join; + } } diff --git a/lib/internal/Magento/Framework/Api/Config/Reader.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/Reader.php similarity index 74% rename from lib/internal/Magento/Framework/Api/Config/Reader.php rename to lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/Reader.php index 6bc97c71c11563cfb46efeaaedf2ecd03fd3bf83..f1158d6acb89584fa6684b5083c815014e701072 100644 --- a/lib/internal/Magento/Framework/Api/Config/Reader.php +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/Reader.php @@ -3,7 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Framework\Api\Config; +namespace Magento\Framework\Api\ExtensionAttribute\Config; class Reader extends \Magento\Framework\Config\Reader\Filesystem { @@ -19,8 +19,8 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem /** * @param \Magento\Framework\Config\FileResolverInterface $fileResolver - * @param \Magento\Framework\Api\Config\Converter $converter - * @param \Magento\Framework\Api\Config\SchemaLocator $schemaLocator + * @param \Magento\Framework\Api\ExtensionAttribute\Config\Converter $converter + * @param \Magento\Framework\Api\ExtensionAttribute\Config\SchemaLocator $schemaLocator * @param \Magento\Framework\Config\ValidationStateInterface $validationState * @param string $fileName * @param array $idAttributes @@ -29,10 +29,10 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem */ public function __construct( \Magento\Framework\Config\FileResolverInterface $fileResolver, - \Magento\Framework\Api\Config\Converter $converter, - \Magento\Framework\Api\Config\SchemaLocator $schemaLocator, + \Magento\Framework\Api\ExtensionAttribute\Config\Converter $converter, + \Magento\Framework\Api\ExtensionAttribute\Config\SchemaLocator $schemaLocator, \Magento\Framework\Config\ValidationStateInterface $validationState, - $fileName = 'service_data_attributes.xml', + $fileName = 'extension_attributes.xml', $idAttributes = [], $domDocumentClass = 'Magento\Framework\Config\Dom', $defaultScope = 'global' diff --git a/lib/internal/Magento/Framework/Api/Config/SchemaLocator.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/SchemaLocator.php similarity index 81% rename from lib/internal/Magento/Framework/Api/Config/SchemaLocator.php rename to lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/SchemaLocator.php index 1e8334c643def347b9392eba52d624b5fdaab556..a6fa7a9d8798f2b132923e9b862f4356aa94376b 100644 --- a/lib/internal/Magento/Framework/Api/Config/SchemaLocator.php +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/Config/SchemaLocator.php @@ -5,7 +5,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Framework\Api\Config; +namespace Magento\Framework\Api\ExtensionAttribute\Config; class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface { @@ -16,7 +16,7 @@ class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface */ public function getSchema() { - return realpath(__DIR__ . '/../etc/service_data_attributes.xsd'); + return realpath(__DIR__ . '/../../etc/extension_attributes.xsd'); } /** diff --git a/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinData.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinData.php new file mode 100644 index 0000000000000000000000000000000000000000..6457c79d1e145c216ebed6b183d23536e0ea1011 --- /dev/null +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinData.php @@ -0,0 +1,150 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Api\ExtensionAttribute; + +/** + * Data holder for extension attribute joins. + * + * @codeCoverageIgnore + */ +class JoinData +{ + /** + * @var string + */ + private $referenceTable; + + /** + * @var string + */ + private $referenceTableAlias; + + /** + * @var string + */ + private $referenceField; + + /** + * @var string + */ + private $joinField; + + /** + * @var string[] + */ + private $selectFields; + + /** + * Get reference table name. + * + * @return string + */ + public function getReferenceTable() + { + return $this->referenceTable; + } + + /** + * Set reference table name. + * + * @param string $referenceTable + * @return $this + */ + public function setReferenceTable($referenceTable) + { + $this->referenceTable = $referenceTable; + return $this; + } + + /** + * Get reference table alias. + * + * @return string + */ + public function getReferenceTableAlias() + { + return $this->referenceTableAlias; + } + + /** + * Set reference table alias. + * + * @param string $referenceTableAlias + * @return $this + */ + public function setReferenceTableAlias($referenceTableAlias) + { + $this->referenceTableAlias = $referenceTableAlias; + return $this; + } + + /** + * Get reference field. + * + * @return string + */ + public function getReferenceField() + { + return $this->referenceField; + } + + /** + * Set reference field. + * + * @param string $referenceField + * @return $this + */ + public function setReferenceField($referenceField) + { + $this->referenceField = $referenceField; + return $this; + } + + /** + * Get join field. + * + * @return string + */ + public function getJoinField() + { + return $this->joinField; + } + + /** + * Set join field. + * + * @param string $joinField + * @return $this + */ + public function setJoinField($joinField) + { + $this->joinField = $joinField; + return $this; + } + + /** + * Get select fields. + * + * @return string[] + */ + public function getSelectFields() + { + return $this->selectFields; + } + + /** + * Set select field. + * + * @param string[] $selectFields + * @return $this + */ + public function setSelectFields(array $selectFields) + { + $this->selectFields = $selectFields; + return $this; + } +} diff --git a/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinDataFactory.php b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinDataFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..a34c41363a2a28664764a04922cc06e2cdf52164 --- /dev/null +++ b/lib/internal/Magento/Framework/Api/ExtensionAttribute/JoinDataFactory.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Api\ExtensionAttribute; + +/** + * Factory class for @see + * \Magento\Framework\Api\ExtensionAttribute\JoinData + */ +class JoinDataFactory +{ + /** + * Object Manager instance + * + * @var \Magento\Framework\ObjectManagerInterface + */ + protected $_objectManager = null; + + /** + * Instance name to create + * + * @var string + */ + protected $_instanceName = null; + + /** + * Factory constructor + * + * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param string $instanceName + */ + public function __construct( + \Magento\Framework\ObjectManagerInterface $objectManager, + $instanceName = '\\Magento\\Framework\\Api\\ExtensionAttribute\\JoinData' + ) { + $this->_objectManager = $objectManager; + $this->_instanceName = $instanceName; + } + + /** + * Create class instance with specified parameters + * + * @param array $data + * @return \Magento\Framework\Api\ExtensionAttribute\JoinData + */ + public function create(array $data = []) + { + return $this->_objectManager->create($this->_instanceName, $data); + } +} diff --git a/lib/internal/Magento/Framework/Api/ExtensionAttributesFactory.php b/lib/internal/Magento/Framework/Api/ExtensionAttributesFactory.php index e50b83d11c7a95758ed9d8f07a4231419018e43a..499477cfc17b9f112d78b18eadad834e74d5dfa7 100644 --- a/lib/internal/Magento/Framework/Api/ExtensionAttributesFactory.php +++ b/lib/internal/Magento/Framework/Api/ExtensionAttributesFactory.php @@ -6,26 +6,68 @@ namespace Magento\Framework\Api; +use Magento\Framework\Api\ExtensionAttribute\Config; +use Magento\Framework\Api\ExtensionAttribute\Config\Converter; +use Magento\Framework\Data\Collection\AbstractDb as DbCollection; +use Magento\Framework\Api\ExtensionAttribute\JoinData; +use Magento\Framework\Api\ExtensionAttribute\JoinDataFactory; +use Magento\Framework\Reflection\TypeProcessor; +use Magento\Framework\Api\ExtensibleDataInterface; + /** * Factory class for instantiation of extension attributes objects. */ class ExtensionAttributesFactory { + const EXTENSIBLE_INTERFACE_NAME = 'Magento\Framework\Api\ExtensibleDataInterface'; + /** * Object Manager instance * * @var \Magento\Framework\ObjectManagerInterface */ - protected $_objectManager = null; + protected $objectManager; + + /** + * @var Config + */ + private $config; + + /** + * @var JoinDataFactory + */ + private $extensionAttributeJoinDataFactory; + + /** + * @var TypeProcessor + */ + private $typeProcessor; + + /** + * Map is used for performance optimization. + * + * @var array + */ + private $classInterfaceMap = []; /** * Factory constructor * * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param Config $config + * @param JoinDataFactory $extensionAttributeJoinDataFactory + * @param TypeProcessor $typeProcessor */ - public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager) - { - $this->_objectManager = $objectManager; + public function __construct( + \Magento\Framework\ObjectManagerInterface $objectManager, + Config $config, + JoinDataFactory $extensionAttributeJoinDataFactory, + TypeProcessor $typeProcessor + ) { + $this->objectManager = $objectManager; + $this->config = $config; + $this->extensionAttributeJoinDataFactory = $extensionAttributeJoinDataFactory; + $this->typeProcessor = $typeProcessor; } /** @@ -37,30 +79,13 @@ class ExtensionAttributesFactory */ public function create($extensibleClassName, $data = []) { - $modelReflection = new \ReflectionClass($extensibleClassName); - - $implementsExtensibleInterface = false; - $extensibleInterfaceName = 'Magento\Framework\Api\ExtensibleDataInterface'; - foreach ($modelReflection->getInterfaces() as $interfaceReflection) { - if ($interfaceReflection->isSubclassOf($extensibleInterfaceName) - && $interfaceReflection->hasMethod('getExtensionAttributes') - ) { - $implementsExtensibleInterface = true; - break; - } - } - if (!$implementsExtensibleInterface) { - throw new \LogicException( - "Class '{$extensibleClassName}' must implement an interface, " - . "which extends from 'Magento\\Framework\\Api\\ExtensibleDataInterface'" - ); - } + $interfaceReflection = new \ReflectionClass($this->getExtensibleInterfaceName($extensibleClassName)); $methodReflection = $interfaceReflection->getMethod('getExtensionAttributes'); - if ($methodReflection->getDeclaringClass() == $extensibleInterfaceName) { + if ($methodReflection->getDeclaringClass() == self::EXTENSIBLE_INTERFACE_NAME) { throw new \LogicException( "Method 'getExtensionAttributes' must be overridden in the interfaces " - . "which extend 'Magento\\Framework\\Api\\ExtensibleDataInterface'. " + . "which extend '" . self::EXTENSIBLE_INTERFACE_NAME . "'. " . "Concrete return type should be specified." ); } @@ -75,13 +100,209 @@ class ExtensionAttributesFactory if (!preg_match($pattern, $methodDocBlock)) { throw new \LogicException( "Method 'getExtensionAttributes' must be overridden in the interfaces " - . "which extend 'Magento\\Framework\\Api\\ExtensibleDataInterface'. " + . "which extend '" . self::EXTENSIBLE_INTERFACE_NAME . "'. " . "Concrete return type must be specified. Please fix :" . $interfaceName ); } $extensionFactoryName = $extensionClassName . 'Factory'; - $extensionFactory = $this->_objectManager->create($extensionFactoryName); + $extensionFactory = $this->objectManager->create($extensionFactoryName); return $extensionFactory->create($data); } + + /** + * Processes join instructions to add to the collection for a data interface. + * + * @param DbCollection $collection + * @param string $extensibleEntityClass + * @return void + */ + public function process(DbCollection $collection, $extensibleEntityClass) + { + $joinDirectives = $this->getJoinDirectivesForType($extensibleEntityClass); + foreach ($joinDirectives as $attributeCode => $directive) { + /** @var JoinData $joinData */ + $joinData = $this->extensionAttributeJoinDataFactory->create(); + $joinData->setReferenceTable($directive[Converter::JOIN_REFERENCE_TABLE]) + ->setReferenceTableAlias('extension_attribute_' . $attributeCode) + ->setReferenceField($directive[Converter::JOIN_REFERENCE_FIELD]) + ->setJoinField($directive[Converter::JOIN_JOIN_ON_FIELD]); + $selectFieldsMapper = function ($selectFieldData) { + return $selectFieldData[Converter::JOIN_SELECT_FIELD]; + }; + $joinData->setSelectFields(array_map($selectFieldsMapper, $directive[Converter::JOIN_SELECT_FIELDS])); + $collection->joinExtensionAttribute($joinData, [$this, 'extractExtensionAttributes']); + } + } + + /** + * Extract extension attributes into separate extension object. + * + * @param string $extensibleEntityClass + * @param array $data + * @return array + * @throws \LogicException + */ + public function extractExtensionAttributes($extensibleEntityClass, array $data) + { + if (!$this->isExtensibleAttributesImplemented($extensibleEntityClass)) { + /* do nothing as there are no extension attributes */ + return $data; + } + + $joinDirectives = $this->getJoinDirectivesForType($extensibleEntityClass); + $extensionData = []; + foreach ($joinDirectives as $attributeCode => $directive) { + $this->populateAttributeCodeWithDirective( + $attributeCode, + $directive, + $data, + $extensionData, + $extensibleEntityClass + ); + } + if (!empty($extensionData)) { + $extensionAttributes = $this->create($extensibleEntityClass, $extensionData); + $data[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY] = $extensionAttributes; + } + return $data; + } + + /** + * Populate a specific attribute code with join directive instructions. + * + * @param string $attributeCode + * @param array $directive + * @param array &$data + * @param array &$extensionData + * @param string $extensibleEntityClass + * @return void + */ + private function populateAttributeCodeWithDirective( + $attributeCode, + $directive, + &$data, + &$extensionData, + $extensibleEntityClass + ) { + $attributeType = $directive[Converter::DATA_TYPE]; + $selectFields = $directive[Converter::JOIN_SELECT_FIELDS]; + foreach ($selectFields as $selectField) { + $selectFieldAlias = 'extension_attribute_' . $attributeCode + . '_' . $selectField[Converter::JOIN_SELECT_FIELD]; + if (isset($data[$selectFieldAlias])) { + if ($this->typeProcessor->isArrayType($attributeType)) { + throw new \LogicException( + sprintf( + 'Join directives cannot be processed for attribute (%s) of extensible entity (%s),' + . ' which has an Array type (%s).', + $attributeCode, + $this->getExtensibleInterfaceName($extensibleEntityClass), + $attributeType + ) + ); + } elseif ($this->typeProcessor->isTypeSimple($attributeType)) { + $extensionData['data'][$attributeCode] = $data[$selectFieldAlias]; + unset($data[$selectFieldAlias]); + break; + } else { + if (!isset($extensionData['data'][$attributeCode])) { + $extensionData['data'][$attributeCode] = $this->objectManager->create($attributeType); + } + $setterName = $selectField[Converter::JOIN_SELECT_FIELD_SETTER] + ? $selectField[Converter::JOIN_SELECT_FIELD_SETTER] + :'set' . ucfirst( + SimpleDataObjectConverter::snakeCaseToCamelCase( + $selectField[Converter::JOIN_SELECT_FIELD] + ) + ); + $extensionData['data'][$attributeCode]->$setterName($data[$selectFieldAlias]); + unset($data[$selectFieldAlias]); + } + } + } + } + + /** + * Returns the internal join directive config for a given type. + * + * Array returned has all of the \Magento\Framework\Api\ExtensionAttribute\Config\Converter JOIN* fields set. + * + * @param string $extensibleEntityClass + * @return array + */ + private function getJoinDirectivesForType($extensibleEntityClass) + { + $extensibleInterfaceName = $this->getExtensibleInterfaceName($extensibleEntityClass); + $extensibleInterfaceName = ltrim($extensibleInterfaceName, '\\'); + $config = $this->config->get(); + if (!isset($config[$extensibleInterfaceName])) { + return []; + } + + $typeAttributesConfig = $config[$extensibleInterfaceName]; + $joinDirectives = []; + foreach ($typeAttributesConfig as $attributeCode => $attributeConfig) { + if (isset($attributeConfig[Converter::JOIN_DIRECTIVE])) { + $joinDirectives[$attributeCode] = $attributeConfig[Converter::JOIN_DIRECTIVE]; + $joinDirectives[$attributeCode][Converter::DATA_TYPE] = $attributeConfig[Converter::DATA_TYPE]; + } + } + + return $joinDirectives; + } + + /** + * Identify concrete extensible interface name based on the class name. + * + * @param string $extensibleClassName + * @return string + */ + private function getExtensibleInterfaceName($extensibleClassName) + { + $exceptionMessage = "Class '{$extensibleClassName}' must implement an interface, " + . "which extends from '" . self::EXTENSIBLE_INTERFACE_NAME . "'"; + $notExtensibleClassFlag = ''; + if (isset($this->classInterfaceMap[$extensibleClassName])) { + if ($notExtensibleClassFlag === $this->classInterfaceMap[$extensibleClassName]) { + throw new \LogicException($exceptionMessage); + } else { + return $this->classInterfaceMap[$extensibleClassName]; + } + } + $modelReflection = new \ReflectionClass($extensibleClassName); + if ($modelReflection->isInterface() + && $modelReflection->isSubClassOf(self::EXTENSIBLE_INTERFACE_NAME) + && $modelReflection->hasMethod('getExtensionAttributes') + ) { + $this->classInterfaceMap[$extensibleClassName] = $extensibleClassName; + return $this->classInterfaceMap[$extensibleClassName]; + } + foreach ($modelReflection->getInterfaces() as $interfaceReflection) { + if ($interfaceReflection->isSubclassOf(self::EXTENSIBLE_INTERFACE_NAME) + && $interfaceReflection->hasMethod('getExtensionAttributes') + ) { + $this->classInterfaceMap[$extensibleClassName] = $interfaceReflection->getName(); + return $this->classInterfaceMap[$extensibleClassName]; + } + } + $this->classInterfaceMap[$extensibleClassName] = $notExtensibleClassFlag; + throw new \LogicException($exceptionMessage); + } + + /** + * Determine if the type is an actual extensible data interface. + * + * @param string $typeName + * @return bool + */ + private function isExtensibleAttributesImplemented($typeName) + { + try { + $this->getExtensibleInterfaceName($typeName); + return true; + } catch (\LogicException $e) { + return false; + } + } } diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesGeneratorTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesGeneratorTest.php index efdeb4ae914348fa51302891271d018b06c70067..057ca793d7b78ba25341fb99bc05133316ba980d 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesGeneratorTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesGeneratorTest.php @@ -6,14 +6,14 @@ // @codingStandardsIgnoreFile namespace Magento\Framework\Api\Test\Unit\Code\Generator; -use Magento\Framework\Api\Config\Converter; +use Magento\Framework\Api\ExtensionAttribute\Config\Converter; class ExtensionAttributesGeneratorTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\Api\Config\Reader|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Api\ExtensionAttribute\Config|\PHPUnit_Framework_MockObject_MockObject */ - protected $configReaderMock; + protected $configMock; /** * @var \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator|\PHPUnit_Framework_MockObject_MockObject @@ -22,7 +22,7 @@ class ExtensionAttributesGeneratorTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->configReaderMock = $this->getMockBuilder('Magento\Framework\Api\Config\Reader') + $this->configMock = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\Config') ->disableOriginalConstructor() ->getMock(); @@ -30,7 +30,7 @@ class ExtensionAttributesGeneratorTest extends \PHPUnit_Framework_TestCase $this->model = $objectManager->getObject( 'Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator', [ - 'configReader' => $this->configReaderMock, + 'config' => $this->configMock, 'sourceClassName' => '\Magento\Catalog\Api\Data\Product', 'resultClassName' => '\Magento\Catalog\Api\Data\ProductExtension', 'classGenerator' => null @@ -41,8 +41,8 @@ class ExtensionAttributesGeneratorTest extends \PHPUnit_Framework_TestCase public function testGenerate() { - $this->configReaderMock->expects($this->any()) - ->method('read') + $this->configMock->expects($this->any()) + ->method('get') ->willReturn( [ 'Magento\Catalog\Api\Data\ProductInterface' => [ @@ -70,8 +70,8 @@ class ExtensionAttributesGeneratorTest extends \PHPUnit_Framework_TestCase public function testGenerateEmptyExtension() { - $this->configReaderMock->expects($this->any()) - ->method('read') + $this->configMock->expects($this->any()) + ->method('get') ->willReturn(['Magento\Catalog\Api\Data\Product' => ['should_not_include' => 'string']]); $expectedResult = file_get_contents(__DIR__ . '/_files/SampleEmptyExtension.txt'); $this->validateGeneratedCode($expectedResult); @@ -116,6 +116,8 @@ class ExtensionAttributesGeneratorTest extends \PHPUnit_Framework_TestCase $reflectionMethod = $reflectionObject->getMethod('_generateCode'); $reflectionMethod->setAccessible(true); $generatedCode = $reflectionMethod->invoke($this->model); + $expectedResult = preg_replace('/\s+/', ' ', $expectedResult); + $generatedCode = preg_replace('/\s+/', ' ', $generatedCode); $this->assertEquals($expectedResult, $generatedCode); } } diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesInterfaceGeneratorTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesInterfaceGeneratorTest.php index 33d4ecf9e7906c2abd4bfe15ef429c539405b059..ed8bb4a90403990a18e31ebc721bc3ae3ba296fb 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesInterfaceGeneratorTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/Code/Generator/ExtensionAttributesInterfaceGeneratorTest.php @@ -6,18 +6,18 @@ // @codingStandardsIgnoreFile namespace Magento\Framework\Api\Test\Unit\Code\Generator; -use Magento\Framework\Api\Config\Converter; +use Magento\Framework\Api\ExtensionAttribute\Config\Converter; class ExtensionAttributesInterfaceGeneratorTest extends \PHPUnit_Framework_TestCase { public function testGenerate() { $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $configReaderMock = $this->getMockBuilder('Magento\Framework\Api\Config\Reader') + $configMock = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\Config') ->disableOriginalConstructor() ->getMock(); - $configReaderMock->expects($this->any()) - ->method('read') + $configMock->expects($this->any()) + ->method('get') ->willReturn( [ 'Magento\Catalog\Api\Data\ProductInterface' => [ @@ -43,7 +43,7 @@ class ExtensionAttributesInterfaceGeneratorTest extends \PHPUnit_Framework_TestC $model = $objectManager->getObject( 'Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator', [ - 'configReader' => $configReaderMock, + 'config' => $configMock, 'sourceClassName' => '\Magento\Catalog\Api\Data\Product', 'resultClassName' => '\Magento\Catalog\Api\Data\ProductExtensionInterface', 'classGenerator' => null diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Config/ConverterTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/Config/ConverterTest.php deleted file mode 100644 index d4629213b20be2d7bbca2ff16bacf0b36de608e5..0000000000000000000000000000000000000000 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Config/ConverterTest.php +++ /dev/null @@ -1,90 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Framework\Api\Test\Unit\Config; - -use Magento\Framework\Api\Config\Converter; - -class ConverterTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \Magento\Framework\Api\Config\Converter - */ - protected $_converter; - - /** - * Initialize parameters - */ - protected function setUp() - { - $this->_converter = new \Magento\Framework\Api\Config\Converter(); - } - - /** - * Test invalid data - */ - public function testInvalidData() - { - $result = $this->_converter->convert(['invalid data']); - $this->assertEmpty($result); - } - - /** - * Test empty data - */ - public function testConvertNoElements() - { - $result = $this->_converter->convert(new \DOMDocument()); - $this->assertEmpty($result); - } - - /** - * Test converting valid data object config - */ - public function testConvert() - { - $expected = [ - 'Magento\Tax\Api\Data\TaxRateInterface' => [ - ], - 'Magento\Catalog\Api\Data\ProductInterface' => [ - 'stock_item' => [ - Converter::DATA_TYPE => 'Magento\CatalogInventory\Api\Data\StockItemInterface', - Converter::RESOURCE_PERMISSIONS => [], - ], - ], - 'Magento\Customer\Api\Data\CustomerInterface' => [ - 'custom_1' => [ - Converter::DATA_TYPE => 'Magento\Customer\Api\Data\CustomerCustom', - Converter::RESOURCE_PERMISSIONS => [], - ], - 'custom_2' => [ - Converter::DATA_TYPE => 'Magento\CustomerExtra\Api\Data\CustomerCustom2', - Converter::RESOURCE_PERMISSIONS => [], - ], - ], - 'Magento\Customer\Api\Data\CustomerInterface2' => [ - 'custom_with_permission' => [ - Converter::DATA_TYPE => 'Magento\Customer\Api\Data\CustomerCustom', - Converter::RESOURCE_PERMISSIONS => [ - 'Magento_Customer::manage', - ], - ], - 'custom_with_multiple_permissions' => [ - Converter::DATA_TYPE => 'Magento\CustomerExtra\Api\Data\CustomerCustom2', - Converter::RESOURCE_PERMISSIONS => [ - 'Magento_Customer::manage', - 'Magento_Customer::manage2', - ], - ], - ], - ]; - - $xmlFile = __DIR__ . '/_files/service_data_attributes.xml'; - $dom = new \DOMDocument(); - $dom->loadXML(file_get_contents($xmlFile)); - $result = $this->_converter->convert($dom); - $this->assertEquals($expected, $result); - } -} diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php index 65c7cb906d1f2f15b8f251145633cdb6e85848c5..079ebbaec7832fa40b5cb260a32fecae1524a774 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/DataObjectHelperTest.php @@ -43,6 +43,11 @@ class DataObjectHelperTest extends \PHPUnit_Framework_TestCase */ protected $attributeValueFactoryMock; + /** + * @var \Magento\Framework\Api\ExtensionAttributesFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $extensionFactoryMock; + /** * @var \Magento\Framework\Reflection\MethodsMap|\PHPUnit_Framework_MockObject_MockObject */ @@ -52,25 +57,33 @@ class DataObjectHelperTest extends \PHPUnit_Framework_TestCase { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->objectFactoryMock = $this->getMockBuilder('\Magento\Framework\Api\ObjectFactory') + $this->objectFactoryMock = $this->getMockBuilder('Magento\Framework\Api\ObjectFactory') + ->disableOriginalConstructor() + ->getMock(); + $this->objectProcessorMock = $this->getMockBuilder('Magento\Framework\Reflection\DataObjectProcessor') ->disableOriginalConstructor() ->getMock(); - $this->objectProcessorMock = $this->getMockBuilder('\Magento\Framework\Reflection\DataObjectProcessor') + $this->methodsMapProcessor = $this->getMockBuilder('Magento\Framework\Reflection\MethodsMap') ->disableOriginalConstructor() ->getMock(); - $this->methodsMapProcessor = $this->getMockBuilder('\Magento\Framework\Reflection\MethodsMap') + $this->attributeValueFactoryMock = $this->getMockBuilder('Magento\Framework\Api\AttributeValueFactory') ->disableOriginalConstructor() ->getMock(); - $this->attributeValueFactoryMock = $this->getMockBuilder('\Magento\Framework\Api\AttributeValueFactory') + $this->extensionFactoryMock = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttributesFactory') + ->setMethods(['extractExtensionAttributes']) ->disableOriginalConstructor() ->getMock(); - $this->typeProcessor = $this->objectManager->getObject('\Magento\Framework\Reflection\TypeProcessor'); + $this->extensionFactoryMock->expects($this->any()) + ->method('extractExtensionAttributes') + ->willReturnArgument(1); + $this->typeProcessor = $this->objectManager->getObject('Magento\Framework\Reflection\TypeProcessor'); $this->dataObjectHelper = $this->objectManager->getObject( 'Magento\Framework\Api\DataObjectHelper', [ 'objectFactory' => $this->objectFactoryMock, 'typeProcessor' => $this->typeProcessor, 'objectProcessor' => $this->objectProcessorMock, + 'extensionFactory' => $this->extensionFactoryMock, 'methodsMapProcessor' => $this->methodsMapProcessor, ] ); diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/ConverterTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/ConverterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..46b46456c828ace6fa6183ceb0aad5bb76991704 --- /dev/null +++ b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/ConverterTest.php @@ -0,0 +1,146 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Api\Test\Unit\ExtensionAttribute\Config; + +use Magento\Framework\Api\ExtensionAttribute\Config\Converter; + +class ConverterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\Api\ExtensionAttribute\Config\Converter + */ + protected $_converter; + + /** + * Initialize parameters + */ + protected function setUp() + { + $this->_converter = new \Magento\Framework\Api\ExtensionAttribute\Config\Converter(); + } + + /** + * Test invalid data + */ + public function testInvalidData() + { + $result = $this->_converter->convert(['invalid data']); + $this->assertEmpty($result); + } + + /** + * Test empty data + */ + public function testConvertNoElements() + { + $result = $this->_converter->convert(new \DOMDocument()); + $this->assertEmpty($result); + } + + /** + * Test converting valid data object config + */ + public function testConvert() + { + $expected = [ + 'Magento\Tax\Api\Data\TaxRateInterface' => [ + ], + 'Magento\Catalog\Api\Data\ProductInterface' => [ + 'stock_item' => [ + Converter::DATA_TYPE => 'Magento\CatalogInventory\Api\Data\StockItemInterface', + Converter::RESOURCE_PERMISSIONS => [], + Converter::JOIN_DIRECTIVE => null, + ], + ], + 'Magento\Customer\Api\Data\CustomerInterface' => [ + 'custom_1' => [ + Converter::DATA_TYPE => 'Magento\Customer\Api\Data\CustomerCustom', + Converter::RESOURCE_PERMISSIONS => [], + Converter::JOIN_DIRECTIVE => null, + ], + 'custom_2' => [ + Converter::DATA_TYPE => 'Magento\CustomerExtra\Api\Data\CustomerCustom2', + Converter::RESOURCE_PERMISSIONS => [], + Converter::JOIN_DIRECTIVE => null, + ], + ], + 'Magento\Customer\Api\Data\CustomerInterface2' => [ + 'custom_with_permission' => [ + Converter::DATA_TYPE => 'Magento\Customer\Api\Data\CustomerCustom', + Converter::RESOURCE_PERMISSIONS => [ + 'Magento_Customer::manage', + ], + Converter::JOIN_DIRECTIVE => null, + ], + 'custom_with_multiple_permissions' => [ + Converter::DATA_TYPE => 'Magento\CustomerExtra\Api\Data\CustomerCustom2', + Converter::RESOURCE_PERMISSIONS => [ + 'Magento_Customer::manage', + 'Magento_Customer::manage2', + ], + Converter::JOIN_DIRECTIVE => null, + ], + ], + ]; + + $xmlFile = __DIR__ . '/_files/extension_attributes.xml'; + $dom = new \DOMDocument(); + $dom->loadXML(file_get_contents($xmlFile)); + $result = $this->_converter->convert($dom); + $this->assertEquals($expected, $result); + } + + /** + * Test converting valid data object config + */ + public function testConvertWithJoinDirectives() + { + $expected = [ + 'Magento\Customer\Api\Data\CustomerInterface' => [ + 'library_card_id' => [ + Converter::DATA_TYPE => 'string', + Converter::RESOURCE_PERMISSIONS => [], + Converter::JOIN_DIRECTIVE => [ + Converter::JOIN_REFERENCE_TABLE => "library_account", + Converter::JOIN_SELECT_FIELDS => [ + [ + Converter::JOIN_SELECT_FIELD => "library_card_id", + Converter::JOIN_SELECT_FIELD_SETTER => "" + ] + ], + Converter::JOIN_JOIN_ON_FIELD => "id", + Converter::JOIN_REFERENCE_FIELD => "customer_id", + ], + ], + 'reviews' => [ + Converter::DATA_TYPE => 'Magento\Reviews\Api\Data\Reviews[]', + Converter::RESOURCE_PERMISSIONS => [], + Converter::JOIN_DIRECTIVE => [ + Converter::JOIN_REFERENCE_TABLE => "reviews", + Converter::JOIN_SELECT_FIELDS => [ + [ + Converter::JOIN_SELECT_FIELD => "comment", + Converter::JOIN_SELECT_FIELD_SETTER => "" + ], + [ + Converter::JOIN_SELECT_FIELD => "rating", + Converter::JOIN_SELECT_FIELD_SETTER => "" + ] + ], + Converter::JOIN_JOIN_ON_FIELD => "customer_id", + Converter::JOIN_REFERENCE_FIELD => "customer_id", + ], + ], + ], + ]; + + $xmlFile = __DIR__ . '/_files/extension_attributes_with_join_directives.xml'; + $dom = new \DOMDocument(); + $dom->loadXML(file_get_contents($xmlFile)); + $result = $this->_converter->convert($dom); + $this->assertEquals($expected, $result); + } +} diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Config/ReaderTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/ReaderTest.php similarity index 60% rename from lib/internal/Magento/Framework/Api/Test/Unit/Config/ReaderTest.php rename to lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/ReaderTest.php index 5887985e9e0cab9ec0699b839407e7454b333fd5..6392a7327db8066413ea7e5e658c29174212430b 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Config/ReaderTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/ReaderTest.php @@ -3,12 +3,12 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Framework\Api\Test\Unit\Config; +namespace Magento\Framework\Api\Test\Unit\ExtensionAttribute\Config; class ReaderTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\Api\Config\Reader + * @var \Magento\Framework\Api\ExtensionAttribute\Config\Reader */ protected $_reader; @@ -20,16 +20,21 @@ class ReaderTest extends \PHPUnit_Framework_TestCase $fileResolver = $this->getMockBuilder('Magento\Framework\App\Config\FileResolver') ->disableOriginalConstructor() ->getMock(); - $converter = $this->getMockBuilder('Magento\Framework\Api\Config\Converter') + $converter = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\Config\Converter') ->disableOriginalConstructor() ->getMock(); - $schema = $this->getMockBuilder('Magento\Framework\Api\Config\SchemaLocator') + $schema = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\Config\SchemaLocator') ->disableOriginalConstructor() ->getMock(); $validator = $this->getMockBuilder('\Magento\Framework\Config\ValidationStateInterface') ->disableOriginalConstructor() ->getMock(); - $this->_reader = new \Magento\Framework\Api\Config\Reader($fileResolver, $converter, $schema, $validator); + $this->_reader = new \Magento\Framework\Api\ExtensionAttribute\Config\Reader( + $fileResolver, + $converter, + $schema, + $validator + ); } /** @@ -37,6 +42,6 @@ class ReaderTest extends \PHPUnit_Framework_TestCase */ public function testInstanceof() { - $this->assertInstanceOf('Magento\Framework\Api\Config\Reader', $this->_reader); + $this->assertInstanceOf('Magento\Framework\Api\ExtensionAttribute\Config\Reader', $this->_reader); } } diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Config/SchemaLocatorTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/SchemaLocatorTest.php similarity index 63% rename from lib/internal/Magento/Framework/Api/Test/Unit/Config/SchemaLocatorTest.php rename to lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/SchemaLocatorTest.php index f05583db0490194e949261bce0a2c176932dbdb5..d3cf12de695450e9a5b5e053e7c01e093df76d8f 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Config/SchemaLocatorTest.php +++ b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/SchemaLocatorTest.php @@ -3,26 +3,26 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Framework\Api\Test\Unit\Config; +namespace Magento\Framework\Api\Test\Unit\ExtensionAttribute\Config; /** - * Test for \Magento\Framework\Api\Config\SchemaLocator + * Test for \Magento\Framework\Api\ExtensionAttribute\Config\SchemaLocator */ class SchemaLocatorTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\Api\Config\SchemaLocator + * @var \Magento\Framework\Api\ExtensionAttribute\Config\SchemaLocator */ protected $_model; protected function setUp() { - $this->_model = new \Magento\Framework\Api\Config\SchemaLocator(); + $this->_model = new \Magento\Framework\Api\ExtensionAttribute\Config\SchemaLocator(); } public function testGetSchema() { - $expected = str_replace('\\', '/', BP . '/lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd'); + $expected = str_replace('\\', '/', BP . '/lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd'); $actual = str_replace('\\', '/', $this->_model->getSchema()); $this->assertEquals($expected, $actual); } @@ -30,7 +30,7 @@ class SchemaLocatorTest extends \PHPUnit_Framework_TestCase public function testGetPerFileSchema() { $actual = str_replace('\\', '/', $this->_model->getPerFileSchema()); - $expected = str_replace('\\', '/', BP . '/lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd'); + $expected = str_replace('\\', '/', BP . '/lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd'); $this->assertEquals($expected, $actual); } } diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/XsdTest.php b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/XsdTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c599760f5934ff67f679db1186f44d205ee46b34 --- /dev/null +++ b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/XsdTest.php @@ -0,0 +1,150 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Api\Test\Unit\ExtensionAttribute\Config; + +class XsdTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var string + */ + protected $_schemaFile; + + protected function setUp() + { + $this->_schemaFile = BP . '/lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd'; + } + + /** + * @param string $fixtureXml + * @param array $expectedErrors + * @dataProvider exemplarXmlDataProvider + */ + public function testExemplarXml($fixtureXml, array $expectedErrors) + { + $messageFormat = '%message%'; + $dom = new \Magento\Framework\Config\Dom($fixtureXml, [], null, null, $messageFormat); + $actualResult = $dom->validate($this->_schemaFile, $actualErrors); + $this->assertEquals($expectedErrors, $actualErrors, "Validation errors does not match."); + $this->assertEquals(empty($expectedErrors), $actualResult, "Validation result is invalid."); + } + + /** + * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function exemplarXmlDataProvider() + { + return [ + /** Valid configurations */ + 'valid with empty extension attributes' => [ + '<config> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + </extension_attributes> + </config>', + [], + ], + 'valid with one attribute code' => [ + '<config> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + <attribute code="stock_item" type="Magento\CatalogInventory\Api\Data\StockItemInterface" /> + </extension_attributes> + </config>', + [], + ], + 'valid with multiple attribute codes' => [ + '<config> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + <attribute code="custom_1" type="Magento\Customer\Api\Data\CustomerCustom" /> + <attribute code="custom_2" type="Magento\CustomerExtra\Api\Data\CustomerCustom2" /> + </extension_attributes> + </config>', + [], + ], + 'valid with multiple attribute codes with permissions' => [ + '<config> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + <attribute code="custom_1" type="Magento\Customer\Api\Data\CustomerCustom"> + <resources> + <resource ref="Magento_Customer::manage"/> + </resources> + </attribute> + <attribute code="custom_2" type="Magento\CustomerExtra\Api\Data\CustomerCustom2"> + <resources> + <resource ref="Magento_Customer::manage"/> + <resource ref="Magento_Catalog::other"/> + </resources> + </attribute> + </extension_attributes> + </config>', + [], + ], + 'valid with attribute code with join' => [ + '<config> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + <attribute code="custom_1" type="Magento\Customer\Api\Data\CustomerCustom"> + <join reference_table="library_account" + reference_field="customer_id" + join_on_field="id" + > + <select_field>library_card_id</select_field> + </join> + </attribute> + </extension_attributes> + </config>', + [], + ], + 'valid with attribute code with permissions and join' => [ + '<config> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + <attribute code="custom_1" type="Magento\Customer\Api\Data\CustomerCustom"> + <resources> + <resource ref="Magento_Customer::manage"/> + </resources> + <join reference_table="library_account" + reference_field="customer_id" + join_on_field="id" + > + <select_field>library_card_id</select_field> + </join> + </attribute> + </extension_attributes> + </config>', + [], + ], + /** Invalid configurations */ + 'invalid missing extension_attributes' => [ + '<config/>', + ["Element 'config': Missing child element(s). Expected is ( extension_attributes )."], + ], + 'invalid with attribute code with resources without single resource' => [ + '<config> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + <attribute code="custom_1" type="Magento\Customer\Api\Data\CustomerCustom"> + <resources> + </resources> + </attribute> + </extension_attributes> + </config>', + ["Element 'resources': Missing child element(s). Expected is ( resource )."], + ], + 'invalid with attribute code without join attributes' => [ + '<config> + <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> + <attribute code="custom_1" type="Magento\Customer\Api\Data\CustomerCustom"> + <join/> + </attribute> + </extension_attributes> + </config>', + [ + "Element 'join': The attribute 'reference_table' is required but missing.", + "Element 'join': The attribute 'join_on_field' is required but missing.", + "Element 'join': The attribute 'reference_field' is required but missing.", + "Element 'join': Missing child element(s). Expected is ( select_field ).", + ], + ], + ]; + } +} diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/Config/_files/service_data_attributes.xml b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/_files/extension_attributes.xml similarity index 91% rename from lib/internal/Magento/Framework/Api/Test/Unit/Config/_files/service_data_attributes.xml rename to lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/_files/extension_attributes.xml index 4f6a9838bfcdb6bd9dbfa20b18ffcfde80bd625d..20272619db1fb78a9cb4d212d4c57316a78e13f9 100644 --- a/lib/internal/Magento/Framework/Api/Test/Unit/Config/_files/service_data_attributes.xml +++ b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/_files/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Tax\Api\Data\TaxRateInterface"> </extension_attributes> <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> diff --git a/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/_files/extension_attributes_with_join_directives.xml b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/_files/extension_attributes_with_join_directives.xml new file mode 100644 index 0000000000000000000000000000000000000000..bdf8f3920bb19091f5b49bf991c500027247b108 --- /dev/null +++ b/lib/internal/Magento/Framework/Api/Test/Unit/ExtensionAttribute/Config/_files/extension_attributes_with_join_directives.xml @@ -0,0 +1,28 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> + <extension_attributes for="Magento\Customer\Api\Data\CustomerInterface"> + <attribute code="library_card_id" type="string"> + <join reference_table="library_account" + reference_field="customer_id" + join_on_field="id" + > + <select_field>library_card_id</select_field> + </join> + </attribute> + <attribute code="reviews" type="Magento\Reviews\Api\Data\Reviews[]"> + <join reference_table="reviews" + reference_field="customer_id" + join_on_field="customer_id" + > + <select_field>comment</select_field> + <select_field>rating</select_field> + </join> + </attribute> + </extension_attributes> +</config> diff --git a/lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd b/lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd similarity index 70% rename from lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd rename to lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd index 24590e3d758c79afeef7ce85c8cb9f6547e6f524..6bccd9b1643b0c515e4c16bdbd8eb200f9c568dc 100644 --- a/lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd +++ b/lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd @@ -22,6 +22,7 @@ <xs:complexType name="attributeType"> <xs:sequence> <xs:element name="resources" type="resourcesType" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="join" type="joinType" minOccurs="0" maxOccurs="1"/> </xs:sequence> <xs:attribute type="xs:string" name="code" use="required"/> <xs:attribute type="xs:string" name="type" use="required"/> @@ -37,6 +38,21 @@ <xs:element name="resource" type="resourceType" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> + <xs:complexType name="selectFieldType"> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:string" name="setter_name" use="optional"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + <xs:complexType name="joinType"> + <xs:sequence> + <xs:element type="selectFieldType" name="select_field" maxOccurs="unbounded" minOccurs="1"/> + </xs:sequence> + <xs:attribute type="xs:string" name="reference_table" use="required"/> + <xs:attribute type="xs:string" name="join_on_field" use="required"/> + <xs:attribute type="xs:string" name="reference_field" use="required"/> + </xs:complexType> <xs:complexType name="resourceType"> <xs:attribute name="ref" use="required"> <xs:simpleType> diff --git a/lib/internal/Magento/Framework/App/Config/Value.php b/lib/internal/Magento/Framework/App/Config/Value.php index 92ee527a9c48eb77a35f527c2c471c2507d1b546..3794adae384f4a5e101d2aab75f64ecc6e355c66 100644 --- a/lib/internal/Magento/Framework/App/Config/Value.php +++ b/lib/internal/Magento/Framework/App/Config/Value.php @@ -47,7 +47,7 @@ class Value extends \Magento\Framework\Model\AbstractModel implements \Magento\F * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\App\Config\ScopeConfigInterface $config * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -55,7 +55,7 @@ class Value extends \Magento\Framework\Model\AbstractModel implements \Magento\F \Magento\Framework\Registry $registry, \Magento\Framework\App\Config\ScopeConfigInterface $config, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_config = $config; diff --git a/lib/internal/Magento/Framework/App/ErrorHandler.php b/lib/internal/Magento/Framework/App/ErrorHandler.php index 46a7120cf5159b1ee6b18bf775e8d4d7afa820ec..59119102e6955a742beb3398588d305b663b7ab8 100644 --- a/lib/internal/Magento/Framework/App/ErrorHandler.php +++ b/lib/internal/Magento/Framework/App/ErrorHandler.php @@ -50,6 +50,14 @@ class ErrorHandler // there's no way to distinguish between caught system exceptions and warnings return false; } + + if (strpos($errorStr, 'Automatically populating $HTTP_RAW_POST_DATA is deprecated') !== false) { + // this warning should be suppressed as it is a known bug in php 5.6.0 https://bugs.php.net/bug.php?id=66763 + // and workaround suggested here (http://php.net/manual/en/ini.core.php#ini.always-populate-raw-post-data) + // is not compatible with HHVM + return false; + } + $errorNo = $errorNo & error_reporting(); if ($errorNo == 0) { return false; diff --git a/lib/internal/Magento/Framework/AppInterface.php b/lib/internal/Magento/Framework/AppInterface.php index 0322b76feb62aba21ec7c59f1968ded0265c2efe..b0b03dfcb471f368da7964d27b52ab16cae7f171 100644 --- a/lib/internal/Magento/Framework/AppInterface.php +++ b/lib/internal/Magento/Framework/AppInterface.php @@ -17,7 +17,7 @@ interface AppInterface /** * Magento version */ - const VERSION = '0.74.0-beta10'; + const VERSION = '0.74.0-beta13'; /** * Launch application diff --git a/lib/internal/Magento/Framework/Archive/Test/Unit/ZipTest.php b/lib/internal/Magento/Framework/Archive/Test/Unit/ZipTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bd25de5b31a9379f066602f02f7d42559fb10f25 --- /dev/null +++ b/lib/internal/Magento/Framework/Archive/Test/Unit/ZipTest.php @@ -0,0 +1,56 @@ +<?php + +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Archive\Test\Unit; + +use Composer\Composer; + +class ZipTest extends \PHPUnit_Framework_TestCase +{ + + /** + * @var \Magento\Framework\Archive\Zip|\PHPUnit_Framework_MockObject_MockObject + */ + protected $zip; + + public function setUp() + { + $this->zip = $this->getMockBuilder('\Magento\Framework\Archive\Zip') + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * Check constructor if no exceptions is thrown. + */ + public function testConstructorNoExceptions() + { + try { + $reflectedClass = new \ReflectionClass('\Magento\Framework\Archive\Zip'); + $constructor = $reflectedClass->getConstructor(); + $constructor->invoke($this->zip, []); + } catch (\Exception $e) { + $this->fail('Failed asserting that no exceptions is thrown'); + } + } + + /** + * @depends testConstructorNoExceptions + */ + public function testPack() + { + $this->markTestSkipped('Method pack contains dependency on \ZipArchive object'); + } + + /** + * @depends testConstructorNoExceptions + */ + public function testUnpack() + { + $this->markTestSkipped('Method unpack contains dependency on \ZipArchive object'); + } +} diff --git a/lib/internal/Magento/Framework/Archive/Zip.php b/lib/internal/Magento/Framework/Archive/Zip.php new file mode 100644 index 0000000000000000000000000000000000000000..d6ba5c970cfa54070da93a1ac492426f6b7f31b8 --- /dev/null +++ b/lib/internal/Magento/Framework/Archive/Zip.php @@ -0,0 +1,64 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Class to work with zip archives + * + * @author Magento Core Team <core@magentocommerce.com> + */ +namespace Magento\Framework\Archive; + +class Zip extends AbstractArchive implements ArchiveInterface +{ + /** + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function __construct() + { + $type = 'Zip'; + if (!class_exists('\ZipArchive')) { + throw new \Magento\Framework\Exception\LocalizedException( + new \Magento\Framework\Phrase('\'%1\' file extension is not supported', $type) + ); + } + } + + /** + * Pack file. + * + * @param string $source + * @param string $destination + * + * @return string + */ + public function pack($source, $destination) + { + $zip = new \ZipArchive(); + $zip->open($destination, \ZipArchive::CREATE); + $zip->addFile($source); + $zip->close(); + return $destination; + } + + /** + * Unpack file. + * + * @param string $source + * @param string $destination + * + * @return string + */ + public function unpack($source, $destination) + { + $zip = new \ZipArchive(); + $zip->open($source); + $filename = $zip->getNameIndex(0); + $zip->extractTo(dirname($destination), $filename); + rename(dirname($destination).'/'.$filename, $destination); + $zip->close(); + return $destination; + } +} diff --git a/lib/internal/Magento/Framework/Code/Generator/CodeGeneratorInterface.php b/lib/internal/Magento/Framework/Code/Generator/CodeGeneratorInterface.php index a994681409bf1532a8349c031f287e5e17f5bf6c..fd93ed6457ffd09f905356aac455e6bb0f54fa24 100644 --- a/lib/internal/Magento/Framework/Code/Generator/CodeGeneratorInterface.php +++ b/lib/internal/Magento/Framework/Code/Generator/CodeGeneratorInterface.php @@ -54,4 +54,12 @@ interface CodeGeneratorInterface extends \Zend\Code\Generator\GeneratorInterface * @return $this */ public function setImplementedInterfaces(array $interfaces); + + /** + * Add a trait to the class. + * + * @param string $trait + * @return $this + */ + public function addTrait($trait); } diff --git a/lib/internal/Magento/Framework/Data/Collection/Db.php b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php similarity index 87% rename from lib/internal/Magento/Framework/Data/Collection/Db.php rename to lib/internal/Magento/Framework/Data/Collection/AbstractDb.php index 563a654811edc9222580dfd46caa0c229cab96a0..e745a916a8092b6302250c7c86f6eda9601da9a1 100755 --- a/lib/internal/Magento/Framework/Data/Collection/Db.php +++ b/lib/internal/Magento/Framework/Data/Collection/AbstractDb.php @@ -8,13 +8,14 @@ namespace Magento\Framework\Data\Collection; use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Select; +use Magento\Framework\Api\ExtensionAttribute\JoinData; use Psr\Log\LoggerInterface as Logger; /** * Base items collection class * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Db extends \Magento\Framework\Data\Collection +abstract class AbstractDb extends \Magento\Framework\Data\Collection { /** * DB connection @@ -85,6 +86,13 @@ class Db extends \Magento\Framework\Data\Collection */ private $_fetchStrategy; + /** + * Flag which determines if extension attributes were joined before the collection was loaded. + * + * @var callable|null + */ + protected $extensionAttributesExtractorCallback; + /** * @param EntityFactoryInterface $entityFactory * @param Logger $logger @@ -105,6 +113,13 @@ class Db extends \Magento\Framework\Data\Collection $this->_logger = $logger; } + /** + * Get resource instance. + * + * @return \Magento\Framework\Model\Resource\Db\AbstractDb + */ + abstract public function getResource(); + /** * Add variable to bind list * @@ -573,7 +588,7 @@ class Db extends \Magento\Framework\Data\Collection * Returns a collection item that corresponds to the fetched row * and moves the internal data pointer ahead * - * @return \Magento\Framework\Object|bool + * @return \Magento\Framework\Model\AbstractModel|bool */ public function fetchItem() { @@ -728,6 +743,7 @@ class Db extends \Magento\Framework\Data\Collection $this->_setIsLoaded(false); $this->_items = []; $this->_data = null; + $this->extensionAttributesExtractorCallback = null; return $this; } @@ -739,7 +755,16 @@ class Db extends \Magento\Framework\Data\Collection */ protected function _fetchAll(\Zend_Db_Select $select) { - return $this->_fetchStrategy->fetchAll($select, $this->_bindParams); + $data = $this->_fetchStrategy->fetchAll($select, $this->_bindParams); + if ($this->extensionAttributesExtractorCallback && is_callable($this->extensionAttributesExtractorCallback)) { + foreach ($data as $key => $dataItem) { + $data[$key] = call_user_func_array( + $this->extensionAttributesExtractorCallback, + [$this->_itemObjectClass, $dataItem] + ); + } + } + return $data; } /** @@ -783,4 +808,49 @@ class Db extends \Magento\Framework\Data\Collection { // no implementation, should be overridden in children classes } + + /** + * Join extension attribute. + * + * @param \Magento\Framework\Api\ExtensionAttribute\JoinData $join + * @param callable $extensionAttributesExtractorCallback + * @return $this + */ + public function joinExtensionAttribute($join, $extensionAttributesExtractorCallback) + { + $selectFrom = $this->getSelect()->getPart(\Zend_Db_Select::FROM); + $joinRequired = !isset($selectFrom[$join->getReferenceTableAlias()]); + if ($joinRequired) { + $this->getSelect()->joinLeft( + [$join->getReferenceTableAlias() => $this->getResource()->getTable($join->getReferenceTable())], + $this->getMainTableAlias() . '.' . $join->getJoinField() + . ' = ' . $join->getReferenceTableAlias() . '.' . $join->getReferenceField(), + [] + ); + } + $columns = []; + foreach ($join->getSelectFields() as $selectField) { + $fieldAlias = $join->getReferenceTableAlias() . '_' . $selectField; + $columns[$fieldAlias] = $join->getReferenceTableAlias() . '.' . $selectField; + } + $this->getSelect()->columns($columns); + $this->extensionAttributesExtractorCallback = $extensionAttributesExtractorCallback; + return $this; + } + + /** + * Identify main table alias or its name if alias is not defined. + * + * @return string + * @throws \LogicException + */ + private function getMainTableAlias() + { + foreach ($this->getSelect()->getPart(\Zend_Db_Select::FROM) as $tableAlias => $tableMetadata) { + if ($tableMetadata['joinType'] == 'from') { + return $tableAlias; + } + } + throw new \LogicException("Main table cannot be identified."); + } } diff --git a/lib/internal/Magento/Framework/Data/Form/AbstractForm.php b/lib/internal/Magento/Framework/Data/Form/AbstractForm.php index 97cd209a00fa1828a742d2b3ff8ca9b4b52146f9..b60e4fcb622ed5e53df96de5f2664c863211566e 100644 --- a/lib/internal/Magento/Framework/Data/Form/AbstractForm.php +++ b/lib/internal/Magento/Framework/Data/Form/AbstractForm.php @@ -43,6 +43,11 @@ class AbstractForm extends \Magento\Framework\Object */ protected $_factoryCollection; + /** + * @var array + */ + protected $customAttributes = []; + /** * @param Factory $factoryElement * @param CollectionFactory $factoryCollection @@ -203,6 +208,7 @@ class AbstractForm extends \Magento\Framework\Object * * @param array $arrAttributes * @return array + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function convertToArray(array $arrAttributes = []) { @@ -214,4 +220,49 @@ class AbstractForm extends \Magento\Framework\Object } return $res; } + + /** + * Add custom attribute + * + * @param string $key + * @param mixed $value + * @return $this + */ + public function addCustomAttribute($key, $value) + { + $this->customAttributes[$key] = $value; + return $this; + } + + /** + * Convert data into string with defined keys and values + * + * @param array $keys + * @param string $valueSeparator + * @param string $fieldSeparator + * @param string $quote + * @return string + */ + public function serialize($keys = [], $valueSeparator = '=', $fieldSeparator = ' ', $quote = '"') + { + $data = []; + if (empty($keys)) { + $keys = array_keys($this->_data); + } + + $customAttributes = array_filter($this->customAttributes); + $keys = array_merge($keys, array_keys(array_diff($this->customAttributes, $customAttributes))); + + foreach ($this->_data as $key => $value) { + if (in_array($key, $keys)) { + $data[] = $key . $valueSeparator . $quote . $value . $quote; + } + } + + foreach ($customAttributes as $key => $value) { + $data[] = $key . $valueSeparator . $quote . $value . $quote; + } + + return implode($fieldSeparator, $data); + } } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/AbstractElement.php b/lib/internal/Magento/Framework/Data/Form/Element/AbstractElement.php old mode 100644 new mode 100755 index 9240d89da1fc95fe50ea0fb83cfa34c1660728a6..af8eb41ae628399e7bb63b73ed56384c0d3213d7 --- a/lib/internal/Magento/Framework/Data/Form/Element/AbstractElement.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/AbstractElement.php @@ -239,7 +239,9 @@ abstract class AbstractElement extends AbstractForm 'readonly', 'tabindex', 'placeholder', - 'data-form-part' + 'data-form-part', + 'data-role', + 'data-action' ]; } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Checkbox.php b/lib/internal/Magento/Framework/Data/Form/Element/Checkbox.php old mode 100644 new mode 100755 index 7f079c6e1b514093f27447a60278a9537f867688..15736c2fe871079b61307a7466ac23e5e3da3c33 --- a/lib/internal/Magento/Framework/Data/Form/Element/Checkbox.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Checkbox.php @@ -46,7 +46,9 @@ class Checkbox extends AbstractElement 'onchange', 'disabled', 'tabindex', - 'data-form-part' + 'data-form-part', + 'data-role', + 'data-action' ]; } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Checkboxes.php b/lib/internal/Magento/Framework/Data/Form/Element/Checkboxes.php old mode 100644 new mode 100755 index 8daf0329f0bd3671e937932eb2985fac03e3053f..1eb259438a5b2c39b1a9d82fc544ebc4fe828a52 --- a/lib/internal/Magento/Framework/Data/Form/Element/Checkboxes.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Checkboxes.php @@ -38,7 +38,18 @@ class Checkboxes extends AbstractElement */ public function getHtmlAttributes() { - return ['type', 'name', 'class', 'style', 'checked', 'onclick', 'onchange', 'disabled']; + return [ + 'type', + 'name', + 'class', + 'style', + 'checked', + 'onclick', + 'onchange', + 'disabled', + 'data-role', + 'data-action' + ]; } /** diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Editor.php b/lib/internal/Magento/Framework/Data/Form/Element/Editor.php index 281f46c402bb6528d4452d26b2bc0ca5d85f9be5..7ddcc639e8eb7a9f09177ff914f2e09fce362f0c 100644 --- a/lib/internal/Magento/Framework/Data/Form/Element/Editor.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Editor.php @@ -40,6 +40,20 @@ class Editor extends Textarea } } + /** + * @return array + */ + protected function getButtonTranslations() + { + $buttonTranslations = [ + 'Insert Image...' => $this->translate('Insert Image...'), + 'Insert Media...' => $this->translate('Insert Media...'), + 'Insert File...' => $this->translate('Insert File...'), + ]; + + return $buttonTranslations; + } + /** * @return string * @SuppressWarnings(PHPMD.ExcessiveMethodLength) @@ -71,12 +85,6 @@ class Editor extends Textarea </script>'; if ($this->isEnabled()) { - $translatedString = [ - 'Insert Image...' => $this->translate('Insert Image...'), - 'Insert Media...' => $this->translate('Insert Media...'), - 'Insert File...' => $this->translate('Insert File...'), - ]; - $jsSetupObject = 'wysiwyg' . $this->getHtmlId(); $forceLoad = ''; @@ -119,7 +127,7 @@ class Editor extends Textarea "\n" . '(function($) {$.mage.translate.add(' . \Zend_Json::encode( - $translatedString + $this->getButtonTranslations() ) . ')})(jQuery);' . "\n" . @@ -161,6 +169,17 @@ class Editor extends Textarea // Display only buttons to additional features if ($this->getConfig('widget_window_url')) { $html = $this->_getButtonsHtml() . $js . parent::getElementHtml(); + if ($this->getConfig('add_widgets')) { + $html .= '<script type="text/javascript"> + //<![CDATA[ + require(["jquery", "mage/translate", "mage/adminhtml/wysiwyg/widget"], function(jQuery){ + (function($) { + $.mage.translate.add(' . \Zend_Json::encode($this->getButtonTranslations()) . ') + })(jQuery); + }); + //]]> + </script>'; + } $html = $this->_wrapIntoContainer($html); return $html; } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Link.php b/lib/internal/Magento/Framework/Data/Form/Element/Link.php old mode 100644 new mode 100755 index 9adf13d287fa0e5aa0618aab220c7bfdf0da2ee8..ec4dcc7ff7693ca3c39960f72e1f4c1606b9dbd9 --- a/lib/internal/Magento/Framework/Data/Form/Element/Link.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Link.php @@ -80,7 +80,9 @@ class Link extends AbstractElement 'onmouseup', 'onkeydown', 'onkeypress', - 'onkeyup' + 'onkeyup', + 'data-role', + 'data-action' ]; } } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Multiline.php b/lib/internal/Magento/Framework/Data/Form/Element/Multiline.php old mode 100644 new mode 100755 index 641d6ec936c0da8b1b760b503d515d40ab708378..f1ee6936104faba54e467a670c1e6e15077d8e49 --- a/lib/internal/Magento/Framework/Data/Form/Element/Multiline.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Multiline.php @@ -46,7 +46,9 @@ class Multiline extends AbstractElement 'onchange', 'disabled', 'maxlength', - 'data-form-part' + 'data-form-part', + 'data-role', + 'data-action' ]; } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Multiselect.php b/lib/internal/Magento/Framework/Data/Form/Element/Multiselect.php old mode 100644 new mode 100755 index fb17c96af2ad10ee2cc72b5bf4afa2fa082e1760..ac3306bb69bc9d903ca977c0d5a128eb9c123c5c --- a/lib/internal/Magento/Framework/Data/Form/Element/Multiselect.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Multiselect.php @@ -105,7 +105,9 @@ class Multiselect extends AbstractElement 'disabled', 'size', 'tabindex', - 'data-form-part' + 'data-form-part', + 'data-role', + 'data-action' ]; } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Obscure.php b/lib/internal/Magento/Framework/Data/Form/Element/Obscure.php old mode 100644 new mode 100755 index 88690b5f38533f4da1281e50d2a4d88e0bf095cf..0230031512d46b9630bcadde073caa5ae92a399b --- a/lib/internal/Magento/Framework/Data/Form/Element/Obscure.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Obscure.php @@ -52,7 +52,9 @@ class Obscure extends \Magento\Framework\Data\Form\Element\Password 'readonly', 'maxlength', 'tabindex', - 'data-form-part' + 'data-form-part', + 'data-role', + 'data-action' ]; } } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Select.php b/lib/internal/Magento/Framework/Data/Form/Element/Select.php old mode 100644 new mode 100755 index 6e80fe5cd177e510a746498e68a62c0ed418d51a..c3d71171be3a04ec7c973fc6c2ccee6e2a12c5b2 --- a/lib/internal/Magento/Framework/Data/Form/Element/Select.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Select.php @@ -152,7 +152,9 @@ class Select extends AbstractElement 'disabled', 'readonly', 'tabindex', - 'data-form-part' + 'data-form-part', + 'data-role', + 'data-action' ]; } } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Text.php b/lib/internal/Magento/Framework/Data/Form/Element/Text.php old mode 100644 new mode 100755 index e29188cf6ba01de64fa016e2a677c935f0c728bc..9c1b8c17262aec37a535f934de3f031b6c6d73a3 --- a/lib/internal/Magento/Framework/Data/Form/Element/Text.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Text.php @@ -63,7 +63,9 @@ class Text extends AbstractElement 'maxlength', 'tabindex', 'placeholder', - 'data-form-part' + 'data-form-part', + 'data-role', + 'data-action' ]; } } diff --git a/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php b/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php old mode 100644 new mode 100755 index 26826e2515fc1386ff4fdf7e29d3243a4b0620c6..9fb3041882565a706fa79b15eee2b1893222f815 --- a/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php +++ b/lib/internal/Magento/Framework/Data/Form/Element/Textarea.php @@ -67,7 +67,9 @@ class Textarea extends AbstractElement 'disabled', 'onkeyup', 'tabindex', - 'data-form-part' + 'data-form-part', + 'data-role', + 'data-action' ]; } diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/Collection/DbCollection.php b/lib/internal/Magento/Framework/Data/Test/Unit/Collection/DbCollection.php new file mode 100644 index 0000000000000000000000000000000000000000..180a1858a7be91a6e3359cb9af65c73e5e7940e3 --- /dev/null +++ b/lib/internal/Magento/Framework/Data/Test/Unit/Collection/DbCollection.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Data\Test\Unit\Collection; + +/** + * Concrete implementation of abstract collection, created for abstract collection testing purposes. + */ +class DbCollection extends \Magento\Framework\Data\Collection\AbstractDb +{ + /** + * @var \Magento\Framework\Model\Resource\Db\AbstractDb + */ + private $resource; + + /** + * Set DB resource for testing purposes. + * + * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource + * @return $this + */ + public function setResource(\Magento\Framework\Model\Resource\Db\AbstractDb $resource) + { + $this->resource = $resource; + return $this; + } + + /** + * Get resource instance. + * + * @return \Magento\Framework\Model\Resource\Db\AbstractDb + */ + public function getResource() + { + return $this->resource; + } +} diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/Collection/DbTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/Collection/DbTest.php index 666655aefd385fe6cddaff1f7c172e69c042a9d5..f10c0c0d84243a3fa3d244c4fd1be404e98b033c 100755 --- a/lib/internal/Magento/Framework/Data/Test/Unit/Collection/DbTest.php +++ b/lib/internal/Magento/Framework/Data/Test/Unit/Collection/DbTest.php @@ -11,7 +11,7 @@ namespace Magento\Framework\Data\Test\Unit\Collection; class DbTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Framework\Data\Collection\Db + * @var \Magento\Framework\Data\Collection\AbstractDb */ protected $collection; @@ -39,7 +39,7 @@ class DbTest extends \PHPUnit_Framework_TestCase 'Magento\Framework\Data\Collection\EntityFactory', ['create'], [], '', false ); $this->loggerMock = $this->getMock('Psr\Log\LoggerInterface'); - $this->collection = new \Magento\Framework\Data\Collection\Db( + $this->collection = new \Magento\Framework\Data\Test\Unit\Collection\DbCollection( $this->entityFactoryMock, $this->loggerMock, $this->fetchStrategyMock @@ -258,7 +258,7 @@ class DbTest extends \PHPUnit_Framework_TestCase * Test that after cloning collection $this->_select in initial and cloned collections * do not reference the same object * - * @covers \Magento\Framework\Data\Collection\Db::__clone + * @covers \Magento\Framework\Data\Collection\AbstractDb::__clone */ public function testClone() { diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php index 6ca63330b2e472f80862cd0c2e9f55f2a2d0e411..db79898c29e85cbd2c5ee9fd1c179f92289fbedb 100644 --- a/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php +++ b/lib/internal/Magento/Framework/Data/Test/Unit/CollectionTest.php @@ -103,8 +103,8 @@ class CollectionTest extends \PHPUnit_Framework_TestCase public function testPossibleFlowWithItem() { - $firstItemMock = $this->getMock('Magento\Framework\Object', [], [], '', false); - $secondItemMock = $this->getMock('Magento\Framework\Object', [], [], '', false); + $firstItemMock = $this->getMock('Magento\Framework\Object', ['getId', 'getData', 'toArray'], [], '', false); + $secondItemMock = $this->getMock('Magento\Framework\Object', ['getId', 'getData', 'toArray'], [], '', false); $requiredFields = ['required_field_one', 'required_field_two']; $arrItems = [ 'totalRecords' => 1, diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/Form/AbstractFormTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/Form/AbstractFormTest.php index dd2aeb5f53f09c6332f780986648558db6a2448c..e1234b96f87e541405e8324031688d714e31ee9c 100644 --- a/lib/internal/Magento/Framework/Data/Test/Unit/Form/AbstractFormTest.php +++ b/lib/internal/Magento/Framework/Data/Test/Unit/Form/AbstractFormTest.php @@ -127,4 +127,94 @@ class AbstractFormTest extends \PHPUnit_Framework_TestCase $this->allElementsMock->expects($this->once())->method('add')->with($this->elementMock, false); $this->abstractForm->addColumn('hidden', $config); } + + public function testAddCustomAttribute() + { + $this->assertEquals( + $this->abstractForm, + $this->abstractForm->addCustomAttribute('attribute_key1', 'attribute_value1') + ); + + $form = clone $this->abstractForm; + $this->assertNotEquals( + $form, + $this->abstractForm->addCustomAttribute('attribute_key2', 'attribute_value2') + ); + } + + /** + * @param array $keys + * @param array $data + * @param array $customAttributes + * @param string $result + * @dataProvider dataProviderSerialize + */ + public function testSerialize( + $keys, + $data, + $customAttributes, + $result + ) { + foreach ($data as $key => $value) { + $this->abstractForm->setData($key, $value); + } + + foreach ($customAttributes as $key => $value) { + $this->abstractForm->addCustomAttribute($key, $value); + } + + $this->assertEquals($result, $this->abstractForm->serialize($keys)); + } + + /** + * 1. Keys + * 2. Data + * 3. Custom Attributes + * 4. Result + * + * @return array + */ + public function dataProviderSerialize() + { + return [ + [[], [], [], ''], + [['key1'], [], [], ''], + [['key1'], ['key1' => 'value'], [], 'key1="value"'], + [['key1', 'key2'], ['key1' => 'value'], [], 'key1="value"'], + [['key1', 'key2'], ['key1' => 'value', 'key3' => 'value3'], [], 'key1="value"'], + [['key1', 'key2'], ['key1' => 'value', 'key3' => 'value3'], ['custom1' => ''], 'key1="value"'], + [ + [ + 'key1', + 'key2', + ], + [ + 'key1' => 'value', + 'key3' => 'value3', + ], + [ + 'custom1' => 'custom_value1', + ], + 'key1="value" custom1="custom_value1"' + ], + [ + [ + 'key1', + 'key2', + ], + [ + 'key1' => 'value', + 'key3' => 'value3', + ], + [ + 'custom1' => 'custom_value1', + 'custom2' => '', + 'custom3' => 0, + 'custom4' => false, + 'custom5' => null, + ], + 'key1="value" custom1="custom_value1"' + ], + ]; + } } diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/AbstractElementTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/AbstractElementTest.php old mode 100644 new mode 100755 index eb351e549c09a7545dd54289aed7167b2d020aa4..736c72b7826897c2e72ff7cea00b243a6347c7e5 --- a/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/AbstractElementTest.php +++ b/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/AbstractElementTest.php @@ -205,6 +205,8 @@ class AbstractElementTest extends \PHPUnit_Framework_TestCase 'tabindex', 'placeholder', 'data-form-part', + 'data-role', + 'data-action' ]; $this->assertEquals($htmlAttributes, $this->_model->getHtmlAttributes()); } diff --git a/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/EditorTest.php b/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/EditorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b88de63daefae6cacf4b5538b887a14e3de2e98e --- /dev/null +++ b/lib/internal/Magento/Framework/Data/Test/Unit/Form/Element/EditorTest.php @@ -0,0 +1,184 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Tests for \Magento\Framework\Data\Form\Element\Editor + */ +namespace Magento\Framework\Data\Test\Unit\Form\Element; + +use Magento\Framework\Data\Form\Element\Editor; + +class EditorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var Editor + */ + protected $model; + + /** + * @var \Magento\Framework\Data\Form\Element\Factory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $factoryMock; + + /** + * @var \Magento\Framework\Data\Form\Element\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + protected $collectionFactoryMock; + + /** + * @var \Magento\Framework\Escaper|\PHPUnit_Framework_MockObject_MockObject + */ + protected $escaperMock; + + /** + * @var \Magento\Framework\Object|\PHPUnit_Framework_MockObject_MockObject + */ + protected $formMock; + + /** + * @var \Magento\Framework\Object|\PHPUnit_Framework_MockObject_MockObject + */ + protected $configMock; + + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + protected $objectManager; + + protected function setUp() + { + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->factoryMock = $this->getMock('\Magento\Framework\Data\Form\Element\Factory', [], [], '', false); + $this->collectionFactoryMock = $this->getMock( + '\Magento\Framework\Data\Form\Element\CollectionFactory', + [], + [], + '', + false + ); + $this->escaperMock = $this->getMock('\Magento\Framework\Escaper', [], [], '', false); + $this->configMock = $this->getMock('\Magento\Framework\Object', ['getData'], [], '', false); + + $this->model = $this->objectManager->getObject( + 'Magento\Framework\Data\Form\Element\Editor', + [ + 'factoryElement' => $this->factoryMock, + 'factoryCollection' => $this->collectionFactoryMock, + 'escaper' => $this->escaperMock, + 'data' => ['config' => $this->configMock] + ] + ); + + $this->formMock = $this->getMock( + 'Magento\Framework\Data\Form', + ['getHtmlIdPrefix', 'getHtmlIdSuffix'], + [], + '', + false, + false + ); + $this->model->setForm($this->formMock); + } + + public function testConstruct() + { + $this->assertEquals('textarea', $this->model->getType()); + $this->assertEquals('textarea', $this->model->getExtType()); + $this->assertEquals(Editor::DEFAULT_ROWS, $this->model->getRows()); + $this->assertEquals(Editor::DEFAULT_COLS, $this->model->getCols()); + + $this->configMock->expects($this->once())->method('getData')->with('enabled')->willReturn(true); + + $model = $this->objectManager->getObject( + 'Magento\Framework\Data\Form\Element\Editor', + [ + 'factoryElement' => $this->factoryMock, + 'factoryCollection' => $this->collectionFactoryMock, + 'escaper' => $this->escaperMock, + 'data' => ['config' => $this->configMock] + ] + ); + + $this->assertEquals('wysiwyg', $model->getType()); + $this->assertEquals('wysiwyg', $model->getExtType()); + } + + public function testGetElementHtml() + { + $html = $this->model->getElementHtml(); + $this->assertContains('</textarea>', $html); + $this->assertContains('rows="2"', $html); + $this->assertContains('cols="15"', $html); + $this->assertRegExp('/class=\".*textarea.*\"/i', $html); + $this->assertNotRegExp('/.*mage\/adminhtml\/wysiwyg\/widget.*/i', $html); + + $this->configMock->expects($this->any())->method('getData') + ->willReturnMap( + [ + ['enabled', null, true], + ['hidden', null, null] + ] + ); + $html = $this->model->getElementHtml(); + $this->assertRegExp('/.*mage\/adminhtml\/wysiwyg\/widget.*/i', $html); + + $this->configMock->expects($this->any())->method('getData') + ->willReturnMap( + [ + ['enabled', null, null], + ['widget_window_url', null, 'localhost'], + ['add_widgets', null, true], + ['hidden', null, null] + ] + ); + $html = $this->model->getElementHtml(); + $this->assertRegExp('/.*mage\/adminhtml\/wysiwyg\/widget.*/i', $html); + } + + public function testIsEnabled() + { + $this->assertEmpty($this->model->isEnabled()); + + $this->model->setData('wysiwyg', true); + $this->assertTrue($this->model->isEnabled()); + + $this->model->unsetData('wysiwyg'); + $this->configMock->expects($this->once())->method('getData')->with('enabled')->willReturn(true); + $this->assertTrue($this->model->isEnabled()); + } + + public function testIsHidden() + { + $this->assertEmpty($this->model->isHidden()); + + $this->configMock->expects($this->once())->method('getData')->with('hidden')->willReturn(true); + $this->assertTrue($this->model->isHidden()); + } + + public function testTranslate() + { + $this->assertEquals('Insert Image...', $this->model->translate('Insert Image...')); + } + + public function testGetConfig() + { + $config = $this->getMock('\Magento\Framework\Object', ['getData'], [], '', false); + $this->assertEquals($config, $this->model->getConfig()); + + $this->configMock->expects($this->once())->method('getData')->with('test')->willReturn('test'); + $this->assertEquals('test', $this->model->getConfig('test')); + } + + /** + * Test protected `getTranslatedString` method via public `getElementHtml` method + */ + public function testGetTranslatedString() + { + $this->configMock->expects($this->any())->method('getData')->withConsecutive(['enabled'])->willReturn(true); + $html = $this->model->getElementHtml(); + $this->assertRegExp('/.*"Insert Image...":"Insert Image...".*/i', $html); + } +} diff --git a/lib/internal/Magento/Framework/Filesystem/Driver/File.php b/lib/internal/Magento/Framework/Filesystem/Driver/File.php index 167027a7d8589c03c49d64ac0f7b74258dfffd2d..90ab906eebaf21911459edf9825cb9fd935da2de 100644 --- a/lib/internal/Magento/Framework/Filesystem/Driver/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Driver/File.php @@ -645,10 +645,16 @@ class File implements DriverInterface public function filePutCsv($resource, array $data, $delimiter = ',', $enclosure = '"') { /** - * Security enhancement for CSV data processing by Excel-like applications. - * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1054702 - */ + * Security enhancement for CSV data processing by Excel-like applications. + * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1054702 + * + * @var $value string|\Magento\Framework\Phrase + */ foreach ($data as $key => $value) { + + if (!is_string($value)) { + $value = (string)$value; + } if (isset($value[0]) && $value[0] === '=') { $data[$key] = ' ' . $value; } diff --git a/lib/internal/Magento/Framework/Filesystem/Io/File.php b/lib/internal/Magento/Framework/Filesystem/Io/File.php index 352cdb3b5643f015d82dee141d3074b0db09d734..4f754db62250ed5e675d63ca025999e428383018 100644 --- a/lib/internal/Magento/Framework/Filesystem/Io/File.php +++ b/lib/internal/Magento/Framework/Filesystem/Io/File.php @@ -180,8 +180,13 @@ class File extends AbstractIo /** * Security enhancement for CSV data processing by Excel-like applications. * @see https://bugzilla.mozilla.org/show_bug.cgi?id=1054702 + * + * @var $value string|\Magento\Framework\Phrase */ foreach ($row as $key => $value) { + if (!is_string($value)) { + $value = (string)$value; + } if (isset($value[0]) && $value[0] === '=') { $row[$key] = ' ' . $value; } diff --git a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php index 426bcc02e1e73eb8d7c37cd77a7513d5b1523800..1d3a7bd7e093e677d61daf66471ca58737f716dc 100644 --- a/lib/internal/Magento/Framework/Image/Adapter/Gd2.php +++ b/lib/internal/Magento/Framework/Image/Adapter/Gd2.php @@ -34,6 +34,16 @@ class Gd2 extends \Magento\Framework\Image\Adapter\AbstractAdapter */ protected $_resized = false; + /** + * For properties reset, e.g. mimeType caching. + * + * @return void + */ + protected function _reset() + { + $this->_fileMimeType = null; + $this->_fileType = null; + } /** * Open image for processing * @@ -44,6 +54,7 @@ class Gd2 extends \Magento\Framework\Image\Adapter\AbstractAdapter public function open($filename) { $this->_fileName = $filename; + $this->_reset(); $this->getMimeType(); $this->_getFileAttributes(); if ($this->_isMemoryLimitReached()) { diff --git a/lib/internal/Magento/Framework/Image/Test/Unit/Adapter/Gd2Test.php b/lib/internal/Magento/Framework/Image/Test/Unit/Adapter/Gd2Test.php index 76b1e5ab0e9eacb4bef2c10c22d9f02c13288eef..6961cf172274a26b9033db4d494918efa5baa40a 100644 --- a/lib/internal/Magento/Framework/Image/Test/Unit/Adapter/Gd2Test.php +++ b/lib/internal/Magento/Framework/Image/Test/Unit/Adapter/Gd2Test.php @@ -103,4 +103,39 @@ class Gd2Test extends \PHPUnit_Framework_TestCase 'no_limit' => [$bigFile, false, '-1'], ]; } + + /** + * Test if open() method resets cached fileType + * + */ + public function testOpenDifferentTypes() + { + self::$imageData = [ + 0 => 480, + 1 => 320, + 2 => 2, + 3 => 'width="480" height="320"', + 'bits' => 8, + 'channels' => 3, + 'mime' => 'image/jpeg', + ]; + + $this->adapter->open('file'); + $type1 = $this->adapter->getImageType(); + + self::$imageData = [ + 0 => 480, + 1 => 320, + 2 => 3, + 3 => 'width="480" height="320"', + 'bits' => 8, + 'channels' => 3, + 'mime' => 'image/png', + ]; + + $this->adapter->open('file'); + $type2 = $this->adapter->getImageType(); + + $this->assertNotEquals($type1, $type2); + } } diff --git a/lib/internal/Magento/Framework/Interception/Chain/Chain.php b/lib/internal/Magento/Framework/Interception/Chain/Chain.php index b6aa297461209424ca939b384a7f2d7cb10f0e32..5788e7e18a566811d08b807f41d63ed459feb065 100644 --- a/lib/internal/Magento/Framework/Interception/Chain/Chain.php +++ b/lib/internal/Magento/Framework/Interception/Chain/Chain.php @@ -6,7 +6,7 @@ */ namespace Magento\Framework\Interception\Chain; -use Magento\Framework\Code\GeneratorTest\SourceClassWithNamespace\Interceptor; +use Magento\Framework\Interception\InterceptorInterface; use Magento\Framework\Interception\DefinitionInterface; use Magento\Framework\Interception\PluginListInterface; @@ -31,12 +31,17 @@ class Chain implements \Magento\Framework\Interception\ChainInterface * @param string $type * @param string $method * @param string $previousPluginCode - * @param Interceptor $subject + * @param InterceptorInterface $subject * @param array $arguments * @return mixed|void */ - public function invokeNext($type, $method, $subject, array $arguments, $previousPluginCode = null) - { + public function invokeNext( + $type, + $method, + InterceptorInterface $subject, + array $arguments, + $previousPluginCode = null + ) { $pluginInfo = $this->pluginList->getNext($type, $method, $previousPluginCode); $capMethod = ucfirst($method); $result = null; diff --git a/lib/internal/Magento/Framework/Interception/ChainInterface.php b/lib/internal/Magento/Framework/Interception/ChainInterface.php index de9ccfed0c470726803691cfa08aba412ac1f31d..6d47bb223fba72756eaa02bba5819fdad6914c03 100644 --- a/lib/internal/Magento/Framework/Interception/ChainInterface.php +++ b/lib/internal/Magento/Framework/Interception/ChainInterface.php @@ -11,10 +11,16 @@ interface ChainInterface /** * @param string $type * @param string $method - * @param string $subject + * @param InterceptorInterface $subject * @param array $arguments * @param string $previousPluginCode * @return mixed */ - public function invokeNext($type, $method, $subject, array $arguments, $previousPluginCode = null); + public function invokeNext( + $type, + $method, + InterceptorInterface $subject, + array $arguments, + $previousPluginCode = null + ); } diff --git a/lib/internal/Magento/Framework/Interception/Code/Generator/Interceptor.php b/lib/internal/Magento/Framework/Interception/Code/Generator/Interceptor.php index 679e3fde28927a1beb1894fef5140d721a9c3b87..b8a2e1597d3077cadbb793e9d32a8f39fe86a814 100644 --- a/lib/internal/Magento/Framework/Interception/Code/Generator/Interceptor.php +++ b/lib/internal/Magento/Framework/Interception/Code/Generator/Interceptor.php @@ -31,49 +31,7 @@ class Interceptor extends \Magento\Framework\Code\Generator\EntityAbstract */ protected function _getClassProperties() { - return [ - [ - 'name' => 'pluginLocator', - 'visibility' => 'protected', - 'docblock' => [ - 'shortDescription' => 'Object Manager instance', - 'tags' => [[ - 'name' => 'var', - 'description' => '\Magento\Framework\ObjectManagerInterface', - ]], - ], - ], - [ - 'name' => 'pluginList', - 'visibility' => 'protected', - 'docblock' => [ - 'shortDescription' => 'List of plugins', - 'tags' => [[ - 'name' => 'var', - 'description' => '\Magento\Framework\Interception\PluginListInterface', - ]], - ] - ], - [ - 'name' => 'chain', - 'visibility' => 'protected', - 'docblock' => [ - 'shortDescription' => 'Invocation chain', - 'tags' => [[ - 'name' => 'var', - 'description' => '\Magento\Framework\Interception\ChainInterface', - ]], - ] - ], - [ - 'name' => 'subjectType', - 'visibility' => 'protected', - 'docblock' => [ - 'shortDescription' => 'Subject type name', - 'tags' => [['name' => 'var', 'description' => 'string']], - ] - ] - ]; + return []; } /** @@ -113,92 +71,6 @@ class Interceptor extends \Magento\Framework\Code\Generator\EntityAbstract { $methods = [$this->_getDefaultConstructorDefinition()]; - $methods[] = [ - 'name' => '___init', - 'body' => "\$this->pluginLocator = \\Magento\\Framework\\App\\ObjectManager::getInstance();\n" . - "\$this->pluginList = \$this->pluginLocator->get('Magento\\Framework\\Interception\\PluginListInterface');\n" . - "\$this->chain = \$this->pluginLocator->get('Magento\\Framework\\Interception\\ChainInterface');\n" . - "\$this->subjectType = get_parent_class(\$this);\n" . - "if (method_exists(\$this->subjectType, '___init')) {\n" . - " parent::___init();\n" . - "}\n", - ]; - - $methods[] = [ - 'name' => '___callParent', - 'parameters' => [ - ['name' => 'method', 'type' => 'string'], - ['name' => 'arguments', 'type' => 'array'], - ], - 'body' => 'return call_user_func_array(array(\'parent\', $method), $arguments);', - ]; - - $methods[] = [ - 'name' => '__sleep', - 'body' => "if (method_exists(get_parent_class(\$this), '__sleep')) {\n" . - " return array_diff(parent::__sleep(), array('pluginLocator', 'pluginList', 'chain', 'subjectType'));" . - "\n} else {\n" . - " return array_keys(get_class_vars(get_parent_class(\$this)));\n" . - "}\n", - ]; - - $methods[] = [ - 'name' => '__wakeup', - 'body' => "if (method_exists(get_parent_class(\$this), '__wakeup')) {\n" - . " parent::__wakeup();\n" - . "}\n" - . "\$this->___init();\n", - ]; - - $methods[] = [ - 'name' => '___callPlugins', - 'visibility' => 'protected', - 'parameters' => [ - ['name' => 'method', 'type' => 'string'], - ['name' => 'arguments', 'type' => 'array'], - ['name' => 'pluginInfo', 'type' => 'array'], - ], - 'body' => "\$capMethod = ucfirst(\$method);\n" . - "\$result = null;\n" . - "if (isset(\$pluginInfo[\\Magento\\Framework\\Interception\\DefinitionInterface::LISTENER_BEFORE])) {\n" . - " // Call 'before' listeners\n" . - " foreach (\$pluginInfo[\\Magento\\Framework\\Interception\\DefinitionInterface::LISTENER_BEFORE] as \$code) {\n" . - " \$beforeResult = call_user_func_array(\n" . - " array(\$this->pluginList->getPlugin(\$this->subjectType, \$code), 'before'" . - ". \$capMethod), array_merge(array(\$this), \$arguments)\n" . - " );\n" . - " if (\$beforeResult) {\n" . - " \$arguments = \$beforeResult;\n" . - " }\n" . - " }\n" . - "}\n" . - "if (isset(\$pluginInfo[\\Magento\\Framework\\Interception\\DefinitionInterface::LISTENER_AROUND])) {\n" . - " // Call 'around' listener\n" . - " \$chain = \$this->chain;\n" . - " \$type = \$this->subjectType;\n" . - " \$subject = \$this;\n" . - " \$code = \$pluginInfo[\\Magento\\Framework\\Interception\\DefinitionInterface::LISTENER_AROUND];\n" . - " \$next = function () use (\$chain, \$type, \$method, \$subject, \$code) {\n" . - " return \$chain->invokeNext(\$type, \$method, \$subject, func_get_args(), \$code);\n" . - " };\n" . - " \$result = call_user_func_array(\n" . - " array(\$this->pluginList->getPlugin(\$this->subjectType, \$code), 'around' . \$capMethod),\n" . - " array_merge(array(\$this, \$next), \$arguments)\n" . - " );\n" . - "} else {\n" . - " // Call original method\n" . - " \$result = call_user_func_array(array('parent', \$method), \$arguments);\n" . - "}\n" . - "if (isset(\$pluginInfo[\\Magento\\Framework\\Interception\\DefinitionInterface::LISTENER_AFTER])) {\n" . - " // Call 'after' listeners\n" . - " foreach (\$pluginInfo[\\Magento\\Framework\\Interception\\DefinitionInterface::LISTENER_AFTER] as \$code) {\n" . - " \$result = \$this->pluginList->getPlugin(\$this->subjectType, \$code)\n" . - " ->{'after' . \$capMethod}(\$this, \$result);\n" . - " }\n" . - "}\n" . - "return \$result;\n", - ]; - $reflectionClass = new \ReflectionClass($this->getSourceClassName()); $publicMethods = $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC); foreach ($publicMethods as $method) { @@ -283,11 +155,15 @@ class Interceptor extends \Magento\Framework\Code\Generator\EntityAbstract $typeName = $this->getSourceClassName(); $reflection = new \ReflectionClass($typeName); + $interfaces = []; if ($reflection->isInterface()) { - $this->_classGenerator->setImplementedInterfaces([$typeName]); + $interfaces[] = $typeName; } else { $this->_classGenerator->setExtendedClass($typeName); } + $this->_classGenerator->addTrait('\Magento\Framework\Interception\Interceptor'); + $interfaces[] = '\Magento\Framework\Interception\InterceptorInterface'; + $this->_classGenerator->setImplementedInterfaces($interfaces); return parent::_generateCode(); } diff --git a/lib/internal/Magento/Framework/Interception/Interceptor.php b/lib/internal/Magento/Framework/Interception/Interceptor.php new file mode 100644 index 0000000000000000000000000000000000000000..1fcf8e4134812d81e65fbc3844cb3b63b4331e31 --- /dev/null +++ b/lib/internal/Magento/Framework/Interception/Interceptor.php @@ -0,0 +1,155 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Interception; + +use Magento\Framework\App\ObjectManager; + +/** + * Interceptor trait that contains the common logic for all interceptor classes. + * + * A trait is used because our interceptor classes need to extend the class that they are intercepting. + * + * Any class using this trait is required to implement \Magento\Framework\Interception\InterceptorInterface + * + * @see \Magento\Framework\Interception\InterceptorInterface + */ +trait Interceptor +{ + /** + * Object Manager instance + * + * @var \Magento\Framework\ObjectManagerInterface + */ + protected $pluginLocator = null; + + /** + * List of plugins + * + * @var \Magento\Framework\Interception\PluginListInterface + */ + protected $pluginList = null; + + /** + * Invocation chain + * + * @var \Magento\Framework\Interception\ChainInterface + */ + protected $chain = null; + + /** + * Subject type name + * + * @var string + */ + protected $subjectType = null; + + /** + * Initialize the Interceptor + * + * @return void + */ + public function ___init() + { + $this->pluginLocator = ObjectManager::getInstance(); + $this->pluginList = $this->pluginLocator->get('Magento\Framework\Interception\PluginListInterface'); + $this->chain = $this->pluginLocator->get('Magento\Framework\Interception\ChainInterface'); + $this->subjectType = get_parent_class($this); + if (method_exists($this->subjectType, '___init')) { + parent::___init(); + } + } + + /** + * Calls parent class method + * + * @param string $method + * @param array $arguments + * @return mixed + */ + public function ___callParent($method, array $arguments) + { + return call_user_func_array(['parent', $method], $arguments); + } + + /** + * Calls parent class sleep if defined, otherwise provides own implementation + * + * @return array + */ + public function __sleep() + { + if (method_exists(get_parent_class($this), '__sleep')) { + return array_diff(parent::__sleep(), ['pluginLocator', 'pluginList', 'chain', 'subjectType']); + } else { + return array_keys(get_class_vars(get_parent_class($this))); + } + } + + /** + * Causes Interceptor to be initialized + * + * @return void + */ + public function __wakeup() + { + if (method_exists(get_parent_class($this), '__wakeup')) { + parent::__wakeup(); + } + $this->___init(); + } + + /** + * Calls plugins for a given method. + * + * @param string $method + * @param array $arguments + * @param array $pluginInfo + * @return mixed|null + */ + protected function ___callPlugins($method, array $arguments, array $pluginInfo) + { + $capMethod = ucfirst($method); + $result = null; + if (isset($pluginInfo[DefinitionInterface::LISTENER_BEFORE])) { + // Call 'before' listeners + foreach ($pluginInfo[DefinitionInterface::LISTENER_BEFORE] as $code) { + $beforeResult = call_user_func_array( + [$this->pluginList->getPlugin($this->subjectType, $code), 'before'. $capMethod], + array_merge([$this], $arguments) + ); + if ($beforeResult) { + $arguments = $beforeResult; + } + } + } + if (isset($pluginInfo[DefinitionInterface::LISTENER_AROUND])) { + // Call 'around' listener + $chain = $this->chain; + $type = $this->subjectType; + /** @var \Magento\Framework\Interception\InterceptorInterface $subject */ + $subject = $this; + $code = $pluginInfo[DefinitionInterface::LISTENER_AROUND]; + $next = function () use ($chain, $type, $method, $subject, $code) { + return $chain->invokeNext($type, $method, $subject, func_get_args(), $code); + }; + $result = call_user_func_array( + [$this->pluginList->getPlugin($this->subjectType, $code), 'around' . $capMethod], + array_merge([$this, $next], $arguments) + ); + } else { + // Call original method + $result = call_user_func_array(['parent', $method], $arguments); + } + if (isset($pluginInfo[DefinitionInterface::LISTENER_AFTER])) { + // Call 'after' listeners + foreach ($pluginInfo[DefinitionInterface::LISTENER_AFTER] as $code) { + $result = $this->pluginList->getPlugin($this->subjectType, $code) + ->{'after' . $capMethod}($this, $result); + } + } + return $result; + } +} diff --git a/lib/internal/Magento/Framework/Interception/InterceptorInterface.php b/lib/internal/Magento/Framework/Interception/InterceptorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..6a5960676d2f864629d817fbbabd55ca840b4c34 --- /dev/null +++ b/lib/internal/Magento/Framework/Interception/InterceptorInterface.php @@ -0,0 +1,24 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Interception; + +/** + * Interface for any class that is intercepting another Magento class. + * + * This interface exposes the parent method of the interception class, which allows the caller to bypass + * the interception logic. + */ +interface InterceptorInterface +{ + /** + * Calls parent class method + * + * @param string $method + * @param array $arguments + * @return mixed + */ + public function ___callParent($method, array $arguments); +} diff --git a/lib/internal/Magento/Framework/Interception/Test/Unit/Chain/ChainTest.php b/lib/internal/Magento/Framework/Interception/Test/Unit/Chain/ChainTest.php index 11451bb0b805488dfb7557cfd7fe8d66f0c748c9..3a83920456e57976ceba02c0909eb1242a20ca94 100644 --- a/lib/internal/Magento/Framework/Interception/Test/Unit/Chain/ChainTest.php +++ b/lib/internal/Magento/Framework/Interception/Test/Unit/Chain/ChainTest.php @@ -33,13 +33,13 @@ class ChainTest extends \PHPUnit_Framework_TestCase $type = 'type'; $method = 'method'; - $subjectMock = $this->getMock('SubjectClass', ['___callParent']); + $subjectMock = $this->getMock('Magento\Framework\Interception\InterceptorInterface'); $pluginMock = $this->getMock('PluginClass', ['beforeMethod']); $pluginMock->expects($this->once()) ->method('beforeMethod') ->with($subjectMock, 1, 2) - ->will($this->returnValue('beforeMethodResult')); + ->will($this->returnValue(['beforeMethodResult'])); $this->_pluginListMock->expects($this->once()) ->method('getNext') @@ -57,7 +57,7 @@ class ChainTest extends \PHPUnit_Framework_TestCase $subjectMock->expects($this->once()) ->method('___callParent') - ->with('method', 'beforeMethodResult') + ->with('method', ['beforeMethodResult']) ->will($this->returnValue('subjectMethodResult')); $this->assertEquals('subjectMethodResult', $this->_model->invokeNext($type, $method, $subjectMock, [1, 2])); @@ -71,7 +71,7 @@ class ChainTest extends \PHPUnit_Framework_TestCase $type = 'type'; $method = 'method'; - $subjectMock = $this->getMock('SubjectClass'); + $subjectMock = $this->getMock('Magento\Framework\Interception\InterceptorInterface'); $pluginMock = $this->getMock('PluginClass', ['aroundMethod']); $pluginMock->expects($this->once()) @@ -102,7 +102,7 @@ class ChainTest extends \PHPUnit_Framework_TestCase $type = 'type'; $method = 'method'; - $subjectMock = $this->getMock('SubjectClass', ['___callParent']); + $subjectMock = $this->getMock('Magento\Framework\Interception\InterceptorInterface'); $pluginMock = $this->getMock('PluginClass', ['afterMethod']); $pluginMock->expects($this->once()) diff --git a/lib/internal/Magento/Framework/Interception/Test/Unit/Code/Generator/InterceptorTest.php b/lib/internal/Magento/Framework/Interception/Test/Unit/Code/Generator/InterceptorTest.php index 91b7b2ebb4ce643bf7d9f63a184973fe7d5c588f..78f5759d9fa77707de1e1c1bb1cf39b5c4596fdc 100644 --- a/lib/internal/Magento/Framework/Interception/Test/Unit/Code/Generator/InterceptorTest.php +++ b/lib/internal/Magento/Framework/Interception/Test/Unit/Code/Generator/InterceptorTest.php @@ -11,12 +11,12 @@ namespace Magento\Framework\Interception\Test\Unit\Code\Generator; class InterceptorTest extends \PHPUnit_Framework_TestCase { /** - * @var \PHPUnit_Framework_MockObject + * @var \PHPUnit_Framework_MockObject_MockObject */ protected $ioObjectMock; /** - * @var \PHPUnit_Framework_MockObject + * @var \PHPUnit_Framework_MockObject_MockObject */ protected $classGeneratorMock; @@ -46,13 +46,13 @@ class InterceptorTest extends \PHPUnit_Framework_TestCase ); $this->classGeneratorMock->expects($this->once())->method('setName') - ->will($this->returnValue($this->classGeneratorMock)); + ->willReturnSelf(); $this->classGeneratorMock->expects($this->once())->method('addProperties') - ->will($this->returnValue($this->classGeneratorMock)); + ->willReturnSelf(); $this->classGeneratorMock->expects($this->once())->method('addMethods') - ->will($this->returnValue($this->classGeneratorMock)); + ->willReturnSelf(); $this->classGeneratorMock->expects($this->once())->method('setClassDocBlock') - ->will($this->returnValue($this->classGeneratorMock)); + ->willReturnSelf(); $this->classGeneratorMock->expects($this->once())->method('generate') ->will($this->returnValue('source code example')); $model->expects($this->once())->method('_validateData')->will($this->returnValue(true)); diff --git a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php index 7b70fa5d35e61e3174d0b008a275f2afd8880d3c..4e0efcdcd0d9bb49ca19661abe806453b65b30a5 100644 --- a/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractExtensibleModel.php @@ -49,7 +49,7 @@ abstract class AbstractExtensibleModel extends AbstractModel implements * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( @@ -58,7 +58,7 @@ abstract class AbstractExtensibleModel extends AbstractModel implements \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, AttributeValueFactory $customAttributeFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->extensionAttributesFactory = $extensionFactory; diff --git a/lib/internal/Magento/Framework/Model/AbstractModel.php b/lib/internal/Magento/Framework/Model/AbstractModel.php index fcd03252a4160d16805909a3bc45492f896f2e85..76729e191161dbd9e09a5a8e873957f86116a448 100644 --- a/lib/internal/Magento/Framework/Model/AbstractModel.php +++ b/lib/internal/Magento/Framework/Model/AbstractModel.php @@ -33,6 +33,33 @@ abstract class AbstractModel extends \Magento\Framework\Object */ protected $_eventObject = 'object'; + /** + * Name of object id field + * + * @var string + */ + protected $_idFieldName = 'id'; + + /** + * Data changes flag (true after setData|unsetData call) + * @var $_hasDataChange bool + */ + protected $_hasDataChanges = false; + + /** + * Original data that was loaded + * + * @var array + */ + protected $_origData; + + /** + * Object delete flag + * + * @var bool + */ + protected $_isDeleted = false; + /** * Resource model instance * @@ -138,14 +165,14 @@ abstract class AbstractModel extends \Magento\Framework\Object * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Model\Resource\AbstractResource $resource - * @param \Magento\Framework\Data\Collection\Db $resourceCollection + * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data */ public function __construct( \Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, \Magento\Framework\Model\Resource\AbstractResource $resource = null, - \Magento\Framework\Data\Collection\Db $resourceCollection = null, + \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->_registry = $registry; @@ -215,6 +242,191 @@ abstract class AbstractModel extends \Magento\Framework\Object } } + /** + * Id field name setter + * + * @param string $name + * @return $this + */ + public function setIdFieldName($name) + { + $this->_idFieldName = $name; + return $this; + } + + /** + * Id field name getter + * + * @return string + */ + public function getIdFieldName() + { + return $this->_idFieldName; + } + + + /** + * Identifier getter + * + * @return mixed + */ + public function getId() + { + return $this->_getData($this->_idFieldName); + } + + /** + * Identifier setter + * + * @param mixed $value + * @return $this + */ + public function setId($value) + { + $this->setData($this->_idFieldName, $value); + return $this; + } + + /** + * Set _isDeleted flag value (if $isDeleted parameter is defined) and return current flag value + * + * @param boolean $isDeleted + * @return bool + */ + public function isDeleted($isDeleted = null) + { + $result = $this->_isDeleted; + if ($isDeleted !== null) { + $this->_isDeleted = $isDeleted; + } + return $result; + } + + /** + * Check if initial object data was changed. + * + * Initial data is coming to object constructor. + * Flag value should be set up to true after any external data changes + * + * @return bool + */ + public function hasDataChanges() + { + return $this->_hasDataChanges; + } + + /** + * Overwrite data in the object. + * + * The $key parameter can be string or array. + * If $key is string, the attribute value will be overwritten by $value + * + * If $key is an array, it will overwrite all the data in the object. + * + * @param string|array $key + * @param mixed $value + * @return $this + */ + public function setData($key, $value = null) + { + if ($key === (array)$key) { + if ($this->_data !== $key) { + $this->_hasDataChanges = true; + } + $this->_data = $key; + } else { + if (!array_key_exists($key, $this->_data) || $this->_data[$key] !== $value) { + $this->_hasDataChanges = true; + } + $this->_data[$key] = $value; + } + return $this; + } + + /** + * Unset data from the object. + * + * @param null|string|array $key + * @return $this + */ + public function unsetData($key = null) + { + if ($key === null) { + $this->setData([]); + } elseif (is_string($key)) { + if (isset($this->_data[$key]) || array_key_exists($key, $this->_data)) { + $this->_hasDataChanges = true; + unset($this->_data[$key]); + } + } elseif ($key === (array)$key) { + foreach ($key as $element) { + $this->unsetData($element); + } + } + return $this; + } + + /** + * Clears data changes status + * + * @param bool $value + * @return $this + */ + public function setDataChanges($value) + { + $this->_hasDataChanges = (bool)$value; + return $this; + } + + /** + * Get object original data + * + * @param string $key + * @return mixed + */ + public function getOrigData($key = null) + { + if ($key === null) { + return $this->_origData; + } + if (isset($this->_origData[$key])) { + return $this->_origData[$key]; + } + return null; + } + + /** + * Initialize object original data + * + * @FIXME changing original data can't be available as public interface + * + * @param string $key + * @param mixed $data + * @return $this + */ + public function setOrigData($key = null, $data = null) + { + if ($key === null) { + $this->_origData = $this->_data; + } else { + $this->_origData[$key] = $data; + } + return $this; + } + + /** + * Compare object data with original data + * + * @param string $field + * @return bool + */ + public function dataHasChangedFor($field) + { + $newData = $this->getData($field); + $origData = $this->getOrigData($field); + return $newData != $origData; + } + /** * Set resource names * diff --git a/lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php b/lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php index 725b39484dcc648022a2c854d34cf3700f53c2a7..6676bd40c5b8052ae3a06a6ca553cbe25626fa77 100644 --- a/lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php +++ b/lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php @@ -12,7 +12,7 @@ namespace Magento\Framework\Model\Resource\Db\Collection; * Abstract Resource Collection * @SuppressWarnings(PHPMD.NumberOfChildren) */ -abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Db +abstract class AbstractCollection extends \Magento\Framework\Data\Collection\AbstractDb { /** * Model name @@ -569,7 +569,7 @@ abstract class AbstractCollection extends \Magento\Framework\Data\Collection\Db parent::_afterLoad(); foreach ($this->_items as $item) { $item->setOrigData(); - if ($this->_resetItemsDataChanged) { + if ($this->_resetItemsDataChanged && ($item instanceof \Magento\Framework\Model\AbstractModel)) { $item->setDataChanges(false); } } diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/AbstractExtensibleModelTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/AbstractExtensibleModelTest.php index f6065b38af8fc4f4d7c448a113cd8187a55fa740..8cead443a6b3f3b9e68fb4cb6b6929c5ef89d51c 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/AbstractExtensibleModelTest.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/AbstractExtensibleModelTest.php @@ -34,7 +34,7 @@ class AbstractExtensibleModelTest extends \PHPUnit_Framework_TestCase protected $resourceMock; /** - * @var \Magento\Framework\Data\Collection\Db|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Data\Collection\AbstractDb|\PHPUnit_Framework_MockObject_MockObject */ protected $resourceCollectionMock; @@ -87,13 +87,9 @@ class AbstractExtensibleModelTest extends \PHPUnit_Framework_TestCase '', false ); - $this->resourceCollectionMock = $this->getMock( - 'Magento\Framework\Data\Collection\Db', - [], - [], - '', - false - ); + $this->resourceCollectionMock = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $this->metadataServiceMock = $this->getMockBuilder('Magento\Framework\Api\MetadataServiceInterface')->getMock(); $this->metadataServiceMock ->expects($this->any()) @@ -106,8 +102,12 @@ class AbstractExtensibleModelTest extends \PHPUnit_Framework_TestCase ] ); $extensionAttributesFactory = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttributesFactory') + ->setMethods(['extractExtensionAttributes']) ->disableOriginalConstructor() ->getMock(); + $extensionAttributesFactory->expects($this->any()) + ->method('extractExtensionAttributes') + ->willReturnArgument(1); $this->attributeValueFactoryMock = $this->getMockBuilder('Magento\Framework\Api\AttributeValueFactory') ->disableOriginalConstructor() ->getMock(); @@ -204,7 +204,9 @@ class AbstractExtensibleModelTest extends \PHPUnit_Framework_TestCase 'invalid' => true, ]; $modelData = ['key1' => 'value1', 'key2' => 222]; - $this->model->setData($modelData); + foreach ($modelData as $key => $value) { + $this->model->setData($key, $value); + } $this->addCustomAttributesToModel($attributesAsArray, $this->model); $this->assertEquals( $modelData, diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/AbstractModelTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/AbstractModelTest.php index 71df4ee8ed9475b92e10972758dc62b3b5926bb3..0b692b8c0332df44d6bf4652924614af80046a9f 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/AbstractModelTest.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/AbstractModelTest.php @@ -30,7 +30,7 @@ class AbstractModelTest extends \PHPUnit_Framework_TestCase protected $resourceMock; /** - * @var \Magento\Framework\Data\Collection\Db|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Data\Collection\AbstractDb|\PHPUnit_Framework_MockObject_MockObject */ protected $resourceCollectionMock; @@ -77,13 +77,9 @@ class AbstractModelTest extends \PHPUnit_Framework_TestCase '', false ); - $this->resourceCollectionMock = $this->getMock( - 'Magento\Framework\Data\Collection\Db', - [], - [], - '', - false - ); + $this->resourceCollectionMock = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $this->model = $this->getMockForAbstractClass( 'Magento\Framework\Model\AbstractModel', [$this->contextMock, $this->registryMock, $this->resourceMock, $this->resourceCollectionMock] @@ -126,4 +122,78 @@ class AbstractModelTest extends \PHPUnit_Framework_TestCase $this->model->afterDelete(); $this->assertEmpty($this->model->getStoredData()); } + + /** + * Tests \Magento\Framework\Object->isDeleted() + */ + public function testIsDeleted() + { + $this->assertFalse($this->model->isDeleted()); + $this->model->isDeleted(); + $this->assertFalse($this->model->isDeleted()); + $this->model->isDeleted(true); + $this->assertTrue($this->model->isDeleted()); + } + + /** + * Tests \Magento\Framework\Object->hasDataChanges() + */ + public function testHasDataChanges() + { + $this->assertFalse($this->model->hasDataChanges()); + $this->model->setData('key', 'value'); + $this->assertTrue($this->model->hasDataChanges(), 'Data changed'); + + $this->model->setDataChanges(false); + $this->model->setData('key', 'value'); + $this->assertFalse($this->model->hasDataChanges(), 'Data not changed'); + + $this->model->setData(['key' => 'value']); + $this->assertFalse($this->model->hasDataChanges(), 'Data not changed (array)'); + + $this->model->unsetData(); + $this->assertTrue($this->model->hasDataChanges(), 'Unset data'); + } + + /** + * Tests \Magento\Framework\Object->getId() + */ + public function testSetGetId() + { + $this->model->setId('test'); + $this->assertEquals('test', $this->model->getId()); + } + + public function testSetGetIdFieldName() + { + $name = 'entity_id_custom'; + $this->model->setIdFieldName($name); + $this->assertEquals($name, $this->model->getIdFieldName()); + } + + /** + * Tests \Magento\Framework\Object->setOrigData() + */ + public function testOrigData() + { + $data = ['key1' => 'value1', 'key2' => 'value2']; + $this->model->setData($data); + $this->model->setOrigData(); + $this->model->setData('key1', 'test'); + $this->assertTrue($this->model->dataHasChangedFor('key1')); + $this->assertEquals($data, $this->model->getOrigData()); + + $this->model->setOrigData('key1', 'test'); + $this->assertEquals('test', $this->model->getOrigData('key1')); + } + + /** + * Tests \Magento\Framework\Object->setDataChanges() + */ + public function testSetDataChanges() + { + $this->assertFalse($this->model->hasDataChanges()); + $this->model->setDataChanges(true); + $this->assertTrue($this->model->hasDataChanges()); + } } diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/AbstractDbTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/AbstractDbTest.php index 6745f6d62c7412089519d0bd6569d0ef29624cbd..6f94faf2bd170abdec47d9749dfab647e224cc39 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/AbstractDbTest.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/AbstractDbTest.php @@ -452,7 +452,9 @@ class AbstractDbTest extends \PHPUnit_Framework_TestCase $resourceMock->expects($this->any()) ->method('_getWriteAdapter') ->will($this->returnValue($adapterMock)); - $resourceCollectionMock = $this->getMock('Magento\Framework\Data\Collection\Db', [], [], '', false); + $resourceCollectionMock = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $abstractModelMock = $this->getMockForAbstractClass( 'Magento\Framework\Model\AbstractModel', [$context, $registryMock, $resourceMock, $resourceCollectionMock] diff --git a/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/Collection/AbstractCollectionTest.php b/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/Collection/AbstractCollectionTest.php index 9d4540a26e896351957dd9bf08dd49454dfd842e..99858753a86249e4f50e547e84b0e77b80994ccc 100644 --- a/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/Collection/AbstractCollectionTest.php +++ b/lib/internal/Magento/Framework/Model/Test/Unit/Resource/Db/Collection/AbstractCollectionTest.php @@ -49,6 +49,11 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase /** @var \Magento\Framework\App\ObjectManager|\PHPUnit_Framework_MockObject_MockObject */ protected $objectManagerMock; + /** + * @var \Magento\Framework\App\ObjectManager + */ + protected $objectManagerBackup; + protected function setUp() { $this->entityFactoryMock = $this->getMock('Magento\Framework\Data\Collection\EntityFactoryInterface'); @@ -75,6 +80,13 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($this->selectMock)); $this->objectManagerMock = $this->getMock('Magento\Framework\App\ObjectManager', [], [], '', false); + + try { + $this->objectManagerBackup = \Magento\Framework\App\ObjectManager::getInstance(); + } catch (\RuntimeException $e) { + $this->objectManagerBackup = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER) + ->create($_SERVER); + } \Magento\Framework\App\ObjectManager::setInstance($this->objectManagerMock); $this->objectManagerHelper = new ObjectManagerHelper($this); @@ -84,9 +96,7 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase protected function tearDown() { parent::tearDown(); - $magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER); - $objectManager = $magentoObjectManagerFactory->create($_SERVER); - \Magento\Framework\App\ObjectManager::setInstance($objectManager); + \Magento\Framework\App\ObjectManager::setInstance($this->objectManagerBackup); } protected function getUut() @@ -378,7 +388,9 @@ class AbstractCollectionTest extends \PHPUnit_Framework_TestCase public function testResetItemsDataChanged() { for ($i = 0; $i < 3; $i++) { - $this->uut->addItem((new MagentoObject())->setDataChanges(true)); + /** @var \Magento\Framework\Model\AbstractModel $item */ + $item = $this->getMockForAbstractClass('Magento\Framework\Model\AbstractModel', [], '', false); + $this->uut->addItem($item->setDataChanges(true)); } $this->assertTrue($this->uut->resetItemsDataChanged() instanceof Uut); diff --git a/lib/internal/Magento/Framework/Module/Dir.php b/lib/internal/Magento/Framework/Module/Dir.php index 749e443fe7c104603c471df2f790711bb9867dd8..376303356d93e236580d78afcbe24865f6218c65 100644 --- a/lib/internal/Magento/Framework/Module/Dir.php +++ b/lib/internal/Magento/Framework/Module/Dir.php @@ -10,9 +10,20 @@ namespace Magento\Framework\Module; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; use Magento\Framework\Filesystem\Directory\ReadInterface; +use Magento\Framework\Stdlib\String as StringHelper; +use Magento\Framework\Module\ModuleRegistryInterface; class Dir { + /**#@+ + * Directories within modules + */ + const MODULE_ETC_DIR = 'etc'; + const MODULE_I18N_DIR = 'i18n'; + const MODULE_VIEW_DIR = 'view'; + const MODULE_CONTROLLER_DIR = 'Controller'; + /**#@-*/ + /** * Modules root directory * @@ -25,14 +36,26 @@ class Dir */ protected $_string; + /** + * Module registry + * + * @var ModuleRegistryInterface + */ + private $moduleRegistry; + /** * @param Filesystem $filesystem - * @param \Magento\Framework\Stdlib\String $string + * @param StringHelper $string + * @param ModuleRegistryInterface $moduleRegistry */ - public function __construct(Filesystem $filesystem, \Magento\Framework\Stdlib\String $string) - { + public function __construct( + Filesystem $filesystem, + StringHelper $string, + ModuleRegistryInterface $moduleRegistry + ) { $this->_modulesDirectory = $filesystem->getDirectoryRead(DirectoryList::MODULES); $this->_string = $string; + $this->moduleRegistry = $moduleRegistry; } /** @@ -45,16 +68,23 @@ class Dir */ public function getDir($moduleName, $type = '') { - $path = $this->_string->upperCaseWords($moduleName, '_', '/'); + if (null === $path = $this->moduleRegistry->getModulePath($moduleName)) { + $relativePath = $this->_string->upperCaseWords($moduleName, '_', '/'); + $path = $this->_modulesDirectory->getAbsolutePath($relativePath); + } + if ($type) { - if (!in_array($type, ['etc', 'i18n', 'view', 'Controller'])) { + if (!in_array($type, [ + self::MODULE_ETC_DIR, + self::MODULE_I18N_DIR, + self::MODULE_VIEW_DIR, + self::MODULE_CONTROLLER_DIR + ])) { throw new \InvalidArgumentException("Directory type '{$type}' is not recognized."); } $path .= '/' . $type; } - $result = $this->_modulesDirectory->getAbsolutePath($path); - - return $result; + return $path; } } diff --git a/lib/internal/Magento/Framework/Module/ModuleList/Loader.php b/lib/internal/Magento/Framework/Module/ModuleList/Loader.php index 08660d98bb6ebeabb6085bf9689db4cb18189dad..b452c389205c5778517c5e27249b341259148d19 100644 --- a/lib/internal/Magento/Framework/Module/ModuleList/Loader.php +++ b/lib/internal/Magento/Framework/Module/ModuleList/Loader.php @@ -10,6 +10,8 @@ use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; use Magento\Framework\Module\Declaration\Converter\Dom; use Magento\Framework\Xml\Parser; +use Magento\Framework\Module\ModuleRegistryInterface; +use Magento\Framework\Filesystem\DriverInterface; /** * Loader of module list information from the filesystem @@ -37,19 +39,42 @@ class Loader */ private $parser; + /** + * Module registry + * + * @var ModuleRegistryInterface + */ + private $moduleRegistry; + + /** + * Filesystem driver to allow reading of module.xml files which live outside of app/code + * + * @var DriverInterface + */ + private $filesystemDriver; + /** * Constructor * * @param Filesystem $filesystem * @param Dom $converter * @param Parser $parser + * @param ModuleRegistryInterface $moduleRegistry + * @param DriverInterface $filesystemDriver */ - public function __construct(Filesystem $filesystem, Dom $converter, Parser $parser) - { + public function __construct( + Filesystem $filesystem, + Dom $converter, + Parser $parser, + ModuleRegistryInterface $moduleRegistry, + DriverInterface $filesystemDriver + ) { $this->filesystem = $filesystem; $this->converter = $converter; $this->parser = $parser; $this->parser->initErrorHandler(); + $this->moduleRegistry = $moduleRegistry; + $this->filesystemDriver = $filesystemDriver; } /** @@ -61,10 +86,7 @@ class Loader public function load() { $result = []; - $dir = $this->filesystem->getDirectoryRead(DirectoryList::MODULES); - foreach ($dir->search('*/*/etc/module.xml') as $file) { - $contents = $dir->readFile($file); - + foreach ($this->getModuleConfigs() as list($file, $contents)) { try { $this->parser->loadXML($contents); } catch (\Magento\Framework\Exception\LocalizedException $e) { @@ -84,6 +106,31 @@ class Loader return $this->sortBySequence($result); } + /** + * Returns module config data and a path to the module.xml file. + * + * Example of data returned by generator: + * <code> + * [ 'vendor/module/etc/module.xml', '<xml>contents</xml>' ] + * </code> + * + * @return \Traversable + * + * @author Josh Di Fabio <joshdifabio@gmail.com> + */ + private function getModuleConfigs() + { + $modulesDir = $this->filesystem->getDirectoryRead(DirectoryList::MODULES); + foreach ($modulesDir->search('*/*/etc/module.xml') as $filePath) { + yield [$filePath, $modulesDir->readFile($filePath)]; + } + + foreach ($this->moduleRegistry->getModulePaths() as $modulePath) { + $filePath = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, "$modulePath/etc/module.xml"); + yield [$filePath, $this->filesystemDriver->fileGetContents($filePath)]; + } + } + /** * Sort the list of modules using "sequence" key in meta-information * diff --git a/lib/internal/Magento/Framework/Module/ModuleRegistryInterface.php b/lib/internal/Magento/Framework/Module/ModuleRegistryInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..331bd80cab338d7c90b71cab0ecdf337df05d0f6 --- /dev/null +++ b/lib/internal/Magento/Framework/Module/ModuleRegistryInterface.php @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Module; + +/** + * @author Josh Di Fabio <joshdifabio@gmail.com> + */ +interface ModuleRegistryInterface +{ + /** + * Get list of registered Magento module paths + * + * Returns an array where key is fully-qualified module name and value is absolute path to module + * + * @return array + */ + public function getModulePaths(); + + /** + * Get path of a module if it is already registered + * + * @param string $moduleName + * @return null|string + */ + public function getModulePath($moduleName); +} diff --git a/lib/internal/Magento/Framework/Module/Registrar.php b/lib/internal/Magento/Framework/Module/Registrar.php new file mode 100644 index 0000000000000000000000000000000000000000..d5144de92a6c0f1404ace0187044098f9000b55e --- /dev/null +++ b/lib/internal/Magento/Framework/Module/Registrar.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Module; + +/** + * Provides ability to statically register modules which do not reside in the modules directory. Not all modules + * will be registered by default. + * + * @author Josh Di Fabio <joshdifabio@gmail.com> + */ +class Registrar implements ModuleRegistryInterface +{ + /** + * Paths to modules + * + * @var string[] + */ + private static $modulePaths = []; + + /** + * Sets the location of a module. Necessary for modules which do not reside in modules directory + * + * @param string $moduleName Fully-qualified module name + * @param string $path Absolute file path to the module + * @return void + */ + public static function registerModule($moduleName, $path) + { + self::$modulePaths[$moduleName] = $path; + } + + /** + * {@inheritdoc} + */ + public function getModulePaths() + { + return self::$modulePaths; + } + + /** + * {@inheritdoc} + */ + public function getModulePath($moduleName) + { + return isset(self::$modulePaths[$moduleName]) ? self::$modulePaths[$moduleName] : null; + } +} diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/DirTest.php b/lib/internal/Magento/Framework/Module/Test/Unit/DirTest.php index 8b25ec2523c0715a45b083ad097bfac4cffbe646..616aae5a11007dc3aefca3b823f072ade88d04f2 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/DirTest.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/DirTest.php @@ -27,6 +27,11 @@ class DirTest extends \PHPUnit_Framework_TestCase */ protected $directoryMock; + /** + * @var \Magento\Framework\Module\ModuleRegistryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $moduleRegistryMock; + protected function setUp() { $this->filesystemMock = $this->getMock('Magento\Framework\Filesystem', [], [], '', false, false); @@ -39,8 +44,14 @@ class DirTest extends \PHPUnit_Framework_TestCase false ); $this->_stringMock = $this->getMock('Magento\Framework\Stdlib\String', [], [], '', false, false); - - $this->_stringMock->expects($this->once())->method('upperCaseWords')->will($this->returnValue('Test/Module')); + $this->moduleRegistryMock = $this->getMock( + 'Magento\Framework\Module\ModuleRegistryInterface', + [], + [], + '', + false, + false + ); $this->filesystemMock->expects( $this->once() @@ -50,11 +61,27 @@ class DirTest extends \PHPUnit_Framework_TestCase $this->returnValue($this->directoryMock) ); - $this->_model = new \Magento\Framework\Module\Dir($this->filesystemMock, $this->_stringMock); + $this->_model = new \Magento\Framework\Module\Dir( + $this->filesystemMock, + $this->_stringMock, + $this->moduleRegistryMock + ); } public function testGetDirModuleRoot() { + $this->moduleRegistryMock->expects( + $this->once() + )->method( + 'getModulePath' + )->with( + 'Test_Module' + )->will( + $this->returnValue(null) + ); + + $this->_stringMock->expects($this->once())->method('upperCaseWords')->will($this->returnValue('Test/Module')); + $this->directoryMock->expects( $this->once() )->method( @@ -64,20 +91,39 @@ class DirTest extends \PHPUnit_Framework_TestCase )->will( $this->returnValue('/Test/Module') ); + $this->assertEquals('/Test/Module', $this->_model->getDir('Test_Module')); } + public function testGetDirModuleRootFromResolver() + { + $this->moduleRegistryMock->expects( + $this->once() + )->method( + 'getModulePath' + )->with( + 'Test_Module2' + )->will( + $this->returnValue('/path/to/module') + ); + + $this->assertEquals('/path/to/module', $this->_model->getDir('Test_Module2')); + } + public function testGetDirModuleSubDir() { + $this->_stringMock->expects($this->once())->method('upperCaseWords')->will($this->returnValue('Test/Module')); + $this->directoryMock->expects( $this->once() )->method( 'getAbsolutePath' )->with( - 'Test/Module/etc' + 'Test/Module' )->will( - $this->returnValue('/Test/Module/etc') + $this->returnValue('/Test/Module') ); + $this->assertEquals('/Test/Module/etc', $this->_model->getDir('Test_Module', 'etc')); } @@ -87,6 +133,8 @@ class DirTest extends \PHPUnit_Framework_TestCase */ public function testGetDirModuleSubDirUnknown() { + $this->_stringMock->expects($this->once())->method('upperCaseWords')->will($this->returnValue('Test/Module')); + $this->_model->getDir('Test_Module', 'unknown'); } } diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/ModuleList/LoaderTest.php b/lib/internal/Magento/Framework/Module/Test/Unit/ModuleList/LoaderTest.php index 5185851d78bb567a5e8d0d39e174ad0d7e086b31..5cb38c5be6838311f3847a10f0138942facc00a9 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/ModuleList/LoaderTest.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/ModuleList/LoaderTest.php @@ -35,11 +35,26 @@ class LoaderTest extends \PHPUnit_Framework_TestCase */ private $converter; - /* + /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $parser; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $registry; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $driver; + + /** + * @var \Magento\Framework\Module\ModuleList\Loader + */ + private $loader; + protected function setUp() { $this->filesystem = $this->getMock('Magento\Framework\Filesystem', [], [], '', false); @@ -50,34 +65,45 @@ class LoaderTest extends \PHPUnit_Framework_TestCase ->willReturn($this->dir); $this->converter = $this->getMock('Magento\Framework\Module\Declaration\Converter\Dom', [], [], '', false); $this->parser = $this->getMock('Magento\Framework\Xml\Parser', [], [], '', false); + $this->parser->expects($this->once())->method('initErrorHandler'); + $this->registry = $this->getMock('Magento\Framework\Module\ModuleRegistryInterface', [], [], '', false, false); + $this->driver = $this->getMock('Magento\Framework\Filesystem\DriverInterface', [], [], '', false, false); + $this->loader = new Loader($this->filesystem, $this->converter, $this->parser, $this->registry, $this->driver); } public function testLoad() { - $fixture = [ + $fixtures = [ 'a' => ['name' => 'a', 'sequence' => []], // a is on its own - 'b' => ['name' => 'b', 'sequence' => ['c']], // b is after c - 'c' => ['name' => 'c', 'sequence' => ['a']], // c is after a - // so expected sequence is a -> c -> b + 'b' => ['name' => 'b', 'sequence' => ['d']], // b is after d + 'c' => ['name' => 'c', 'sequence' => ['e']], // c is after e + 'd' => ['name' => 'd', 'sequence' => ['c']], // d is after c + 'e' => ['name' => 'e', 'sequence' => ['a']], // e is after a + // so expected sequence is a -> e -> c -> d -> b ]; $this->dir->expects($this->once())->method('search')->willReturn(['a', 'b', 'c']); + $this->registry->expects($this->once())->method('getModulePaths')->willReturn(['/path/to/d', '/path/to/e']); $this->dir->expects($this->exactly(3))->method('readFile')->will($this->returnValueMap([ ['a', null, null, self::$sampleXml], ['b', null, null, self::$sampleXml], ['c', null, null, self::$sampleXml], ])); - $this->converter->expects($this->at(0))->method('convert')->willReturn(['a' => $fixture['a']]); - $this->converter->expects($this->at(1))->method('convert')->willReturn(['b' => $fixture['b']]); - $this->converter->expects($this->at(2))->method('convert')->willReturn(['c' => $fixture['c']]); - $this->parser->expects($this->once())->method('initErrorHandler'); - $this->parser->expects($this->atLeastOnce())->method('loadXML'); + $this->driver->expects($this->exactly(2))->method('fileGetContents')->will($this->returnValueMap([ + ['/path/to/d/etc/module.xml', null, null, self::$sampleXml], + ['/path/to/e/etc/module.xml', null, null, self::$sampleXml], + ])); + $index = 0; + foreach ($fixtures as $name => $fixture) { + $this->converter->expects($this->at($index++))->method('convert')->willReturn([$name => $fixture]); + } + $this->parser->expects($this->atLeastOnce())->method('loadXML') + ->with(self::$sampleXml); $this->parser->expects($this->atLeastOnce())->method('getDom'); - $object = new Loader($this->filesystem, $this->converter, $this->parser); - $result = $object->load(); - $this->assertSame(['a', 'c', 'b'], array_keys($result)); - $this->assertSame($fixture['a'], $result['a']); - $this->assertSame($fixture['b'], $result['b']); - $this->assertSame($fixture['c'], $result['c']); + $result = $this->loader->load(); + $this->assertSame(['a', 'e', 'c', 'd', 'b'], array_keys($result)); + foreach ($fixtures as $name => $fixture) { + $this->assertSame($fixture, $result[$name]); + } } /** @@ -97,7 +123,7 @@ class LoaderTest extends \PHPUnit_Framework_TestCase ])); $this->converter->expects($this->at(0))->method('convert')->willReturn(['a' => $fixture['a']]); $this->converter->expects($this->at(1))->method('convert')->willReturn(['b' => $fixture['b']]); - $object = new Loader($this->filesystem, $this->converter, $this->parser); - $object->load(); + $this->registry->expects($this->once())->method('getModulePaths')->willReturn([]); + $this->loader->load(); } } diff --git a/lib/internal/Magento/Framework/Mview/View.php b/lib/internal/Magento/Framework/Mview/View.php index 47b43916febc51d04a94035a3dbb9b68992fff04..1aaf01056687a5093c48c59f68d4e26913cc1d8c 100644 --- a/lib/internal/Magento/Framework/Mview/View.php +++ b/lib/internal/Magento/Framework/Mview/View.php @@ -67,6 +67,50 @@ class View extends \Magento\Framework\Object implements ViewInterface parent::__construct($data); } + /** + * Return ID + * + * @return string + */ + public function getId() + { + return $this->getData($this->_idFieldName); + } + + /** + * Set ID + * + * @param string $id + * @return $this + */ + public function setId($id) + { + $this->setData($this->_idFieldName, $id); + return $this; + } + + /** + * Id field name setter + * + * @param string $name + * @return $this + */ + public function setIdFieldName($name) + { + $this->_idFieldName = $name; + return $this; + } + + /** + * Id field name getter + * + * @return string + */ + public function getIdFieldName() + { + return $this->_idFieldName; + } + /** * Return view action class * diff --git a/lib/internal/Magento/Framework/Object.php b/lib/internal/Magento/Framework/Object.php index 81be913e5543c7dc3f664bfbfd570175a50bf534..8ad8f30f6241d9270730eb37934dbf18d9e247e6 100644 --- a/lib/internal/Magento/Framework/Object.php +++ b/lib/internal/Magento/Framework/Object.php @@ -20,26 +20,6 @@ class Object implements \ArrayAccess */ protected $_data = []; - /** - * Data changes flag (true after setData|unsetData call) - * @var $_hasDataChange bool - */ - protected $_hasDataChanges = false; - - /** - * Original data that was loaded - * - * @var array - */ - protected $_origData; - - /** - * Name of object id field - * - * @var string - */ - protected $_idFieldName = 'id'; - /** * Setter/Getter underscore transformation cache * @@ -47,13 +27,6 @@ class Object implements \ArrayAccess */ protected static $_underscoreCache = []; - /** - * Object delete flag - * - * @var bool - */ - protected $_isDeleted = false; - /** * Constructor * @@ -67,78 +40,6 @@ class Object implements \ArrayAccess $this->_data = $data; } - /** - * Set _isDeleted flag value (if $isDeleted parameter is defined) and return current flag value - * - * @param boolean $isDeleted - * @return bool - */ - public function isDeleted($isDeleted = null) - { - $result = $this->_isDeleted; - if ($isDeleted !== null) { - $this->_isDeleted = $isDeleted; - } - return $result; - } - - /** - * Check if initial object data was changed. - * - * Initial data is coming to object constructor. - * Flag value should be set up to true after any external data changes - * - * @return bool - */ - public function hasDataChanges() - { - return $this->_hasDataChanges; - } - - /** - * Id field name setter - * - * @param string $name - * @return $this - */ - public function setIdFieldName($name) - { - $this->_idFieldName = $name; - return $this; - } - - /** - * Id field name getter - * - * @return string - */ - public function getIdFieldName() - { - return $this->_idFieldName; - } - - /** - * Identifier getter - * - * @return mixed - */ - public function getId() - { - return $this->_getData($this->_idFieldName); - } - - /** - * Identifier setter - * - * @param mixed $value - * @return $this - */ - public function setId($value) - { - $this->setData($this->_idFieldName, $value); - return $this; - } - /** * Add data to the object. * @@ -170,14 +71,8 @@ class Object implements \ArrayAccess public function setData($key, $value = null) { if ($key === (array)$key) { - if ($this->_data !== $key) { - $this->_hasDataChanges = true; - } $this->_data = $key; } else { - if (!array_key_exists($key, $this->_data) || $this->_data[$key] !== $value) { - $this->_hasDataChanges = true; - } $this->_data[$key] = $value; } return $this; @@ -195,7 +90,6 @@ class Object implements \ArrayAccess $this->setData([]); } elseif (is_string($key)) { if (isset($this->_data[$key]) || array_key_exists($key, $this->_data)) { - $this->_hasDataChanges = true; unset($this->_data[$key]); } } elseif ($key === (array)$key) { @@ -327,21 +221,6 @@ class Object implements \ArrayAccess return $this->{$method}($args); } - /** - * Fast get data or set default if value is not available - * - * @param string $key - * @param mixed $default - * @return mixed - */ - public function getDataSetDefault($key, $default) - { - if (!array_key_exists($key, $this->_data)) { - $this->_data[$key] = $default; - } - return $this->_data[$key]; - } - /** * If $key is empty, checks whether there's any data in the object * Otherwise checks if the specified attribute is set. @@ -578,67 +457,6 @@ class Object implements \ArrayAccess return $res; } - /** - * Initialize object original data - * - * @FIXME changing original data can't be available as public interface - * - * @param string $key - * @param mixed $data - * @return $this - */ - public function setOrigData($key = null, $data = null) - { - if ($key === null) { - $this->_origData = $this->_data; - } else { - $this->_origData[$key] = $data; - } - return $this; - } - - /** - * Get object original data - * - * @param string $key - * @return mixed - */ - public function getOrigData($key = null) - { - if ($key === null) { - return $this->_origData; - } - if (isset($this->_origData[$key])) { - return $this->_origData[$key]; - } - return null; - } - - /** - * Compare object data with original data - * - * @param string $field - * @return bool - */ - public function dataHasChangedFor($field) - { - $newData = $this->getData($field); - $origData = $this->getOrigData($field); - return $newData != $origData; - } - - /** - * Clears data changes status - * - * @param bool $value - * @return $this - */ - public function setDataChanges($value) - { - $this->_hasDataChanges = (bool)$value; - return $this; - } - /** * Present object data as string in debug mode * diff --git a/lib/internal/Magento/Framework/ObjectManager/TMap.php b/lib/internal/Magento/Framework/ObjectManager/TMap.php new file mode 100644 index 0000000000000000000000000000000000000000..759ed739d624497ce65ee5e2678b4d9cbe3c99a0 --- /dev/null +++ b/lib/internal/Magento/Framework/ObjectManager/TMap.php @@ -0,0 +1,206 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\ObjectManager; + +use Magento\Framework\Code\Reader\ClassReaderInterface; +use Magento\Framework\ObjectManagerInterface; + +/** + * Class TMap + * @internal + */ +class TMap implements \IteratorAggregate, \Countable, \ArrayAccess +{ + /** + * @var string + */ + private $type; + + /** + * @var array + */ + private $array = []; + + /** + * @var array + */ + private $objectsArray = []; + + /** + * @var int + */ + private $counter = 0; + + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var ConfigInterface + */ + private $configInterface; + + /** + * @var ClassReaderInterface + */ + private $classReaderInterface; + + + /** + * @param string $type + * @param ObjectManagerInterface $objectManager + * @param ConfigInterface $configInterface + * @param ClassReaderInterface $classReaderInterface + * @param array $array + */ + public function __construct( + $type, + ObjectManagerInterface $objectManager, + ConfigInterface $configInterface, + ClassReaderInterface $classReaderInterface, + array $array = [] + ) { + if (!class_exists($this->type) && !interface_exists($type)) { + throw new \InvalidArgumentException(sprintf('Unknown type %s', $type)); + } + + $this->type = $type; + + $this->objectManager = $objectManager; + $this->configInterface = $configInterface; + $this->classReaderInterface = $classReaderInterface; + + array_walk( + $array, + function ($item, $index) { + $this->assertValidTypeLazy($item, $index); + } + ); + + $this->array = $array; + $this->counter = count($array); + } + + /** + * Asserts that item type is collection defined type + * + * @param string $instanceName + * @param string|int|null $index + * @return void + * @throws \InvalidArgumentException + */ + private function assertValidTypeLazy($instanceName, $index = null) + { + $realType = $this->configInterface->getInstanceType( + $this->configInterface->getPreference($instanceName) + ); + + if (!in_array($this->type, $this->classReaderInterface->getParents($realType), true)) { + $this->throwTypeException($realType, $index); + } + } + + /** + * Throws exception according type mismatch + * + * @param string $inputType + * @param string $index + * @return void + * @throws \InvalidArgumentException + */ + private function throwTypeException($inputType, $index) + { + $message = 'Type mismatch. Expected type: %s. Actual: %s, Code: %s'; + + throw new \InvalidArgumentException( + sprintf($message, $this->type, $inputType, $index) + ); + } + + /** + * Returns object for requested index + * + * @param string|int $index + * @return object + */ + private function initObject($index) + { + if (isset($this->objectsArray[$index])) { + return $this->objectsArray[$index]; + } + + return $this->objectsArray[$index] = $this->objectManager->create($this->array[$index]); + } + + /** + * {inheritdoc} + */ + public function getIterator() + { + if (array_keys($this->array) != array_keys($this->objectsArray)) { + foreach (array_keys($this->array) as $index) { + $this->initObject($index); + } + } + + return new \ArrayIterator($this->objectsArray); + } + + /** + * {inheritdoc} + */ + public function offsetExists($offset) + { + return array_key_exists($offset, $this->array); + } + + /** + * {inheritdoc} + */ + public function offsetGet($offset) + { + return isset($this->array[$offset]) ? $this->initObject($offset) : null; + } + + /** + * {inheritdoc} + */ + public function offsetSet($offset, $value) + { + $this->assertValidTypeLazy($value, $offset); + if ($offset === null) { + $this->array[] = $value; + } else { + $this->array[$offset] = $value; + } + + $this->counter++; + } + + /** + * {inheritdoc} + */ + public function offsetUnset($offset) + { + if ($this->counter && isset($this->array[$offset])) { + $this->counter--; + unset($this->array[$offset]); + + if (isset($this->objectsArray[$offset])) { + unset($this->objectsArray[$offset]); + } + } + } + + /** + * {inheritdoc} + */ + public function count() + { + return $this->counter; + } +} diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/TMapTest.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/TMapTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6ce188335d8c6aa1f9e8dba25addacfb2d116847 --- /dev/null +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/TMapTest.php @@ -0,0 +1,173 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\ObjectManager\Test\Unit; + +use Magento\Framework\ObjectManager\TMap; + +require_once __DIR__ . '/_files/TMap/TClass.php'; +require_once __DIR__ . '/_files/TMap/TInterface.php'; + +class TMapTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Framework\ObjectManagerInterface | \PHPUnit_Framework_MockObject_MockObject + */ + private $om; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\ObjectManager\ConfigInterface + */ + private $omConfig; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\Framework\Code\Reader\ClassReaderInterface + */ + private $cReader; + + public function setUp() + { + $this->om = $this->getMockBuilder('Magento\Framework\ObjectManagerInterface') + ->getMockForAbstractClass(); + + $this->omConfig = $this->getMockBuilder('Magento\Framework\ObjectManager\ConfigInterface') + ->getMockForAbstractClass(); + + $this->cReader = $this->getMockBuilder('Magento\Framework\Code\Reader\ClassReaderInterface') + ->getMockForAbstractClass(); + } + + public function testConstructor() + { + $tMap = $this->getSimpleInitialized(3); + static::assertEquals(3, $tMap->count()); + } + + public function testRead() + { + $tMap = $this->getSimpleInitialized(3); + $this->om->expects(static::exactly(3)) + ->method('create') + ->willReturnMap( + [ + ['TClass', [], new \TClass()], + ['TInterface', [], new \TClass()], + ['TClassVirtual', [], new \TClass()] + ] + ); + + foreach ($tMap as $instance) { + static::assertInstanceOf('\TInterface', $instance); + } + } + + /** + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + public function testRemove() + { + $tMap = $this->getSimpleInitialized(3); + + static::assertEquals(3, $tMap->count()); + foreach ($tMap as $key => $instance) { + unset($tMap[$key]); + } + static::assertEquals(0, $tMap->count()); + } + + /** + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + public function testEdit() + { + $expectedKeysOrder = [ + 'item', + 4, + 'item2', + 5 + ]; + $tMap = $this->getSimpleInitialized(6); + + unset($tMap[0], $tMap[3]); + + $tMap[] = 'TClassVirtual'; + $tMap['item2'] = 'TClass'; + $tMap[] = 'TInterface'; + + $this->om->expects(static::exactly(4)) + ->method('create') + ->willReturnMap( + [ + ['TClass', [], new \TClass()], + ['TInterface', [], new \TClass()], + ['TClassVirtual', [], new \TClass()] + ] + ); + + $i = 0; + foreach ($tMap as $key => $item) { + static::assertEquals($expectedKeysOrder[$i], $key); + $i++; + } + + static::assertEquals(4, $tMap->count()); + } + + /** + * Returns simple initialized tMap + * + * @param int $exactlyCalls + * @return TMap + */ + private function getSimpleInitialized($exactlyCalls = 3) + { + /** + [ + 0 => ['TClass', 'TClass', 'TClass'], + 'item' => ['TClassVirtual', 'TClassVirtual', 'TClass'], + 3 => ['TInterface', 'TClassVirtual', 'TClass'] + ]; + */ + $testClasses = [ + 0 => 'TClass', + 'item' => 'TClassVirtual', + 3 => 'TInterface' + ]; + + $this->omConfig->expects(static::exactly($exactlyCalls)) + ->method('getPreference') + ->willReturnMap( + [ + ['TClass', 'TClass'], + ['TClassVirtual', 'TClassVirtual'], + ['TInterface', 'TClassVirtual'] + ] + ); + $this->omConfig->expects(static::exactly($exactlyCalls)) + ->method('getInstanceType') + ->willReturnMap( + [ + ['TClass', 'TClass'], + ['TClassVirtual', 'TClass'] + ] + ); + + $this->cReader->expects(static::exactly($exactlyCalls)) + ->method('getParents') + ->willReturnMap( + [ + ['TClass', ['TInterface']] + ] + ); + + return new TMap( + 'TInterface', + $this->om, + $this->omConfig, + $this->cReader, + $testClasses + ); + } +} diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/TMap/TClass.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/TMap/TClass.php new file mode 100644 index 0000000000000000000000000000000000000000..551a689c376660626b30e924ffde3dc73a03143a --- /dev/null +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/TMap/TClass.php @@ -0,0 +1,14 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace { + + require_once __DIR__ . '/TInterface.php'; + + class TClass implements TInterface + { + + } +} diff --git a/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/TMap/TInterface.php b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/TMap/TInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..5d20869f47c62fae098317adf6dbc5de41fe5a2e --- /dev/null +++ b/lib/internal/Magento/Framework/ObjectManager/Test/Unit/_files/TMap/TInterface.php @@ -0,0 +1,13 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace { + + interface TInterface + { + + } +} diff --git a/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php b/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php index 6824dca09e58c813d114dba3f3c720dad27a710d..dc8d3ae715051e8f36d99111322a259f61a80c77 100644 --- a/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php +++ b/lib/internal/Magento/Framework/Reflection/AttributeTypeResolver.php @@ -7,14 +7,14 @@ namespace Magento\Framework\Reflection; use Magento\Framework\Api\AttributeTypeResolverInterface; -use Magento\Framework\Api\Config\Reader; +use Magento\Framework\Api\ExtensionAttribute\Config; class AttributeTypeResolver implements AttributeTypeResolverInterface { /** - * @var Reader + * @var Config */ - protected $configReader; + protected $config; /** * @var TypeProcessor @@ -23,11 +23,11 @@ class AttributeTypeResolver implements AttributeTypeResolverInterface /** * @param TypeProcessor $typeProcessor - * @param Reader $configReader + * @param Config $config */ - public function __construct(TypeProcessor $typeProcessor, Reader $configReader) + public function __construct(TypeProcessor $typeProcessor, Config $config) { - $this->configReader = $configReader; + $this->config = $config; $this->typeProcessor = $typeProcessor; } @@ -39,7 +39,7 @@ class AttributeTypeResolver implements AttributeTypeResolverInterface if (!is_object($value)) { throw new \InvalidArgumentException('Provided value is not object type'); } - $data = $this->configReader->read(); + $data = $this->config->get(); $context = trim($context, '\\'); $config = isset($data[$context]) ? $data[$context] : []; $output = get_class($value); diff --git a/lib/internal/Magento/Framework/Reflection/ExtensionAttributesProcessor.php b/lib/internal/Magento/Framework/Reflection/ExtensionAttributesProcessor.php index c2d2d69c758f8b4676da91027080fb5736d5c880..aa4180b8155551166409aacb989cbd5ede812b69 100644 --- a/lib/internal/Magento/Framework/Reflection/ExtensionAttributesProcessor.php +++ b/lib/internal/Magento/Framework/Reflection/ExtensionAttributesProcessor.php @@ -6,17 +6,18 @@ namespace Magento\Framework\Reflection; -use Magento\Framework\Api\Config\Reader as ExtensionAttributesConfigReader; -use Magento\Framework\Api\Config\Converter; +use Magento\Framework\Api\ExtensionAttribute\Config; +use Magento\Framework\Api\ExtensionAttribute\Config\Converter; use Magento\Framework\AuthorizationInterface; use Magento\Framework\Phrase; -use Magento\Framework\Api\SimpleDataObjectConverter; use Magento\Framework\Api\ExtensionAttributesInterface; use Magento\Framework\Reflection\MethodsMap; use Zend\Code\Reflection\MethodReflection; /** * Processes extension attributes and produces an array for the data. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ExtensionAttributesProcessor { @@ -36,9 +37,9 @@ class ExtensionAttributesProcessor private $authorization; /** - * @var ExtensionAttributesConfigReader + * @var Config */ - private $configReader; + private $config; /** * @var bool @@ -61,7 +62,7 @@ class ExtensionAttributesProcessor * @param TypeCaster $typeCaster * @param FieldNamer $fieldNamer * @param AuthorizationInterface $authorization - * @param ExtensionAttributesConfigReader $configReader + * @param Config $config * @param bool $isPermissionChecked */ public function __construct( @@ -70,7 +71,7 @@ class ExtensionAttributesProcessor TypeCaster $typeCaster, FieldNamer $fieldNamer, AuthorizationInterface $authorization, - ExtensionAttributesConfigReader $configReader, + Config $config, $isPermissionChecked = false ) { $this->dataObjectProcessor = $dataObjectProcessor; @@ -78,7 +79,7 @@ class ExtensionAttributesProcessor $this->typeCaster = $typeCaster; $this->fieldNamer = $fieldNamer; $this->authorization = $authorization; - $this->configReader = $configReader; + $this->config = $config; $this->isPermissionChecked = $isPermissionChecked; } @@ -173,8 +174,7 @@ class ExtensionAttributesProcessor */ private function getPermissionsForTypeAndMethod($typeName, $attributeCode) { - // TODO: Move function to the Config and hope this is cached - $attributes = $this->configReader->read(); + $attributes = $this->config->get(); if (isset($attributes[$typeName]) && isset($attributes[$typeName][$attributeCode])) { $attributeMetadata = $attributes[$typeName][$attributeCode]; $permissions = []; diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php index 68902f3851380d368c88ca8e2357bada00a2de7d..755b4b666896a6dca8872eae60b93eea9acd5c9c 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/AttributeTypeResolverTest.php @@ -16,23 +16,23 @@ class AttributeTypeResolverTest extends \PHPUnit_Framework_TestCase protected $model; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Reflection\TypeProcessor|\PHPUnit_Framework_MockObject_MockObject */ protected $typeProcessor; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Framework\Api\ExtensionAttribute\Config|\PHPUnit_Framework_MockObject_MockObject */ - protected $reader; + protected $configMock; /** * Set up helper. */ protected function setUp() { - $this->typeProcessor = $this->getMock('\Magento\Framework\Reflection\TypeProcessor', [], [], '', false); - $this->reader = $this->getMock('\Magento\Framework\Api\Config\Reader', [], [], '', false); - $this->model = new AttributeTypeResolver($this->typeProcessor, $this->reader); + $this->typeProcessor = $this->getMock('Magento\Framework\Reflection\TypeProcessor', [], [], '', false); + $this->configMock = $this->getMock('Magento\Framework\Api\ExtensionAttribute\Config', [], [], '', false); + $this->model = new AttributeTypeResolver($this->typeProcessor, $this->configMock); } /** @@ -53,7 +53,7 @@ class AttributeTypeResolverTest extends \PHPUnit_Framework_TestCase $value = new \stdClass(); $context = 'Some\Class'; - $this->reader->expects($this->once())->method('read')->willReturn([]); + $this->configMock->expects($this->once())->method('get')->willReturn([]); $this->assertEquals('stdClass', $this->model->resolveObjectType($code, $value, $context)); } @@ -75,7 +75,7 @@ class AttributeTypeResolverTest extends \PHPUnit_Framework_TestCase ->with('\Magento\Framework\Object') ->willReturn('\Magento\Framework\Object'); - $this->reader->expects($this->once())->method('read')->willReturn($config); + $this->configMock->expects($this->once())->method('get')->willReturn($config); $this->assertEquals('\Magento\Framework\Object', $this->model->resolveObjectType($code, $value, $context)); } @@ -101,7 +101,7 @@ class AttributeTypeResolverTest extends \PHPUnit_Framework_TestCase ->with('\Some\Class') ->willReturn('\Some\Class'); - $this->reader->expects($this->once())->method('read')->willReturn($config); + $this->configMock->expects($this->once())->method('get')->willReturn($config); $this->model->resolveObjectType($code, $value, $context); } } diff --git a/lib/internal/Magento/Framework/Reflection/Test/Unit/ExtensionAttributesProcessorTest.php b/lib/internal/Magento/Framework/Reflection/Test/Unit/ExtensionAttributesProcessorTest.php index 8da0c1f734f710da1c69d28c9e9f4ac02999db86..381cb9c62b641dc34462f0912f742e154ceb0c23 100644 --- a/lib/internal/Magento/Framework/Reflection/Test/Unit/ExtensionAttributesProcessorTest.php +++ b/lib/internal/Magento/Framework/Reflection/Test/Unit/ExtensionAttributesProcessorTest.php @@ -6,8 +6,7 @@ namespace Magento\Framework\Reflection\Test\Unit; -use Magento\Framework\Api\Config\Converter; -use Magento\Framework\Api\Config\Reader; +use Magento\Framework\Api\ExtensionAttribute\Config\Converter; use Magento\Framework\AuthorizationInterface; use Magento\Framework\Reflection\DataObjectProcessor; use Magento\Framework\Reflection\ExtensionAttributesProcessor; @@ -46,9 +45,9 @@ class ExtensionAttributesProcessorTest extends \PHPUnit_Framework_TestCase private $typeCasterMock; /** - * @var Reader + * @var \Magento\Framework\Api\ExtensionAttribute\Config */ - private $configReaderMock; + private $configMock; /** * @var AuthorizationInterface @@ -73,7 +72,7 @@ class ExtensionAttributesProcessorTest extends \PHPUnit_Framework_TestCase $this->fieldNamerMock = $this->getMockBuilder('Magento\Framework\Reflection\FieldNamer') ->disableOriginalConstructor() ->getMock(); - $this->configReaderMock = $this->getMockBuilder('Magento\Framework\Api\Config\Reader') + $this->configMock = $this->getMockBuilder('Magento\Framework\Api\ExtensionAttribute\Config') ->disableOriginalConstructor() ->getMock(); $this->authorizationMock = $this->getMockBuilder('Magento\Framework\AuthorizationInterface') @@ -88,7 +87,7 @@ class ExtensionAttributesProcessorTest extends \PHPUnit_Framework_TestCase 'typeCaster' => $this->typeCasterMock, 'fieldNamer' => $this->fieldNamerMock, 'authorization' => $this->authorizationMock, - 'configReader' => $this->configReaderMock, + 'config' => $this->configMock, 'isPermissionChecked' => true, ] ); @@ -120,8 +119,8 @@ class ExtensionAttributesProcessorTest extends \PHPUnit_Framework_TestCase ->with($methodName) ->will($this->returnValue($attributeName)); $permissionName = 'Magento_Permission'; - $this->configReaderMock->expects($this->once()) - ->method('read') + $this->configMock->expects($this->once()) + ->method('get') ->will($this->returnValue([ $dataObjectType => [ $attributeName => [ Converter::RESOURCE_PERMISSIONS => [ $permissionName ] ] diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Aggregation/Builder.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Aggregation/Builder.php index 12e5c515ca4134700023cd254cb964fae9e81587..1258f2eb118ee3b7d903bdcc46f1e624a5acb196 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Aggregation/Builder.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Aggregation/Builder.php @@ -35,7 +35,7 @@ class Builder /** * @param Resource $resource * @param DataProviderContainer $dataProviderContainer - * @param Builder\Container $aggregationContainer + * @param AggregationContainer $aggregationContainer * @param EntityMetadata $entityMetadata */ public function __construct( diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/Field.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/Field.php new file mode 100644 index 0000000000000000000000000000000000000000..ba5e20d2e7582dd9673c7c761e3aaa1f28faad4f --- /dev/null +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/Field.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Search\Adapter\Mysql\Field; + +class Field implements FieldInterface +{ + /** + * @var string + */ + private $column; + /** + * @var int|null + */ + private $attributeId; + /** + * @var int + */ + private $type; + + /** + * @param string $column + * @param int|null $attributeId + * @param int $type + */ + public function __construct($column, $attributeId = null, $type = self::TYPE_FULLTEXT) + { + $this->column = $column; + $this->attributeId = $attributeId; + $this->type = $type; + } + + /** + * @return string + */ + public function getColumn() + { + return $this->column; + } + + /** + * @return int|null + */ + public function getAttributeId() + { + return $this->attributeId; + } + + /** + * @return int + */ + public function getType() + { + return $this->type; + } +} diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/FieldFactory.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/FieldFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..ae17d20679d822300269b35a17240cf0458109c1 --- /dev/null +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/FieldFactory.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Search\Adapter\Mysql\Field; + + +class FieldFactory +{ + /** + * Object Manager instance + * + * @var \Magento\Framework\ObjectManagerInterface + */ + protected $_objectManager = null; + + /** + * Instance name to create + * + * @var string + */ + protected $_instanceName = null; + + /** + * Factory constructor + * + * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param string $instanceName + */ + public function __construct( + \Magento\Framework\ObjectManagerInterface $objectManager, + $instanceName = 'Magento\Framework\Search\Adapter\Mysql\Field\FieldInterface' + ) { + $this->_objectManager = $objectManager; + $this->_instanceName = $instanceName; + } + + /** + * Create class instance with specified parameters + * + * @param array $data + * @return \Magento\Framework\Search\Adapter\Mysql\Field\FieldInterface + */ + public function create(array $data = []) + { + return $this->_objectManager->create($this->_instanceName, $data); + } +} diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/FieldInterface.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/FieldInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c70f02c44459db753d4763a1dc1d00da6b2c0d26 --- /dev/null +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/FieldInterface.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Search\Adapter\Mysql\Field; + + +interface FieldInterface +{ + const TYPE_FLAT = 1; + const TYPE_FULLTEXT = 2; + + /** + * Get type of index + * @return int + */ + public function getType(); + + /** + * Get ID of attribute + * @return int + */ + public function getAttributeId(); + + /** + * Get field name + * @return string + */ + public function getColumn(); +} diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/Resolver.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/Resolver.php index e2cf380fefa49a50ff01bd1fcd9f5a4192c4721c..363159b209cbc6722ac630571a4cb782108cc58f 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/Resolver.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/Resolver.php @@ -7,11 +7,29 @@ namespace Magento\Framework\Search\Adapter\Mysql\Field; class Resolver implements ResolverInterface { + /** + * @var FieldFactory + */ + private $fieldFactory; + + /** + * @param FieldFactory $fieldFactory + */ + public function __construct(FieldFactory $fieldFactory) + { + $this->fieldFactory = $fieldFactory; + } + /** * {@inheritdoc} */ - public function resolve($fields) + public function resolve(array $fields) { - return $fields; + $resolvedFields = []; + foreach ($fields as $field) { + $resolvedFields[] = $this->fieldFactory->create(['column' => $field]); + } + + return $resolvedFields; } } diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/ResolverInterface.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/ResolverInterface.php index 7138ae1e483be612044e5e07a82371884880f9e9..ad04eb81ebccb650cee3dc196549e2d8a1c44280 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/ResolverInterface.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Field/ResolverInterface.php @@ -10,8 +10,8 @@ interface ResolverInterface /** * Resolve field * - * @param string|array $fields - * @return string|array + * @param array $fields + * @return FieldInterface[] */ - public function resolve($fields); + public function resolve(array $fields); } diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Builder.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Builder.php index 19cf05923aa1e323c2eaddfee17102990a108358..9b55177403ae5072547a3e40a38472a3be246879 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Builder.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Builder.php @@ -11,6 +11,7 @@ use Magento\Framework\Search\Adapter\Mysql\Filter\Builder\FilterInterface; use Magento\Framework\Search\Adapter\Mysql\Filter\Builder\Range; use Magento\Framework\Search\Adapter\Mysql\Filter\Builder\Term; use Magento\Framework\Search\Adapter\Mysql\Filter\Builder\Wildcard; +use Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer; use Magento\Framework\Search\Request\FilterInterface as RequestFilterInterface; use Magento\Framework\Search\Request\Query\Bool; @@ -57,27 +58,28 @@ class Builder implements BuilderInterface /** * {@inheritdoc} */ - public function build(RequestFilterInterface $filter, $conditionType) + public function build(RequestFilterInterface $filter, $conditionType, QueryContainer $queryContainer) { - return $this->processFilter($filter, $this->isNegation($conditionType)); + return $this->processFilter($filter, $this->isNegation($conditionType), $queryContainer); } /** * @param RequestFilterInterface $filter * @param bool $isNegation + * @param QueryContainer $queryContainer * @return string */ - private function processFilter(RequestFilterInterface $filter, $isNegation) + private function processFilter(RequestFilterInterface $filter, $isNegation, QueryContainer $queryContainer) { if ($filter->getType() == RequestFilterInterface::TYPE_BOOL) { - $query = $this->processBoolFilter($filter, $isNegation); + $query = $this->processBoolFilter($filter, $isNegation, $queryContainer); $query = $this->conditionManager->wrapBrackets($query); } else { if (!isset($this->filters[$filter->getType()])) { throw new \InvalidArgumentException('Unknown filter type ' . $filter->getType()); } $query = $this->filters[$filter->getType()]->buildFilter($filter, $isNegation); - $query = $this->preprocessor->process($filter, $isNegation, $query); + $query = $this->preprocessor->process($filter, $isNegation, $query, $queryContainer); } return $query; @@ -86,16 +88,18 @@ class Builder implements BuilderInterface /** * @param RequestFilterInterface|\Magento\Framework\Search\Request\Filter\Bool $filter * @param bool $isNegation + * @param QueryContainer $queryContainer * @return string */ - private function processBoolFilter(RequestFilterInterface $filter, $isNegation) + private function processBoolFilter(RequestFilterInterface $filter, $isNegation, QueryContainer $queryContainer) { - $must = $this->buildFilters($filter->getMust(), Select::SQL_AND, $isNegation); - $should = $this->buildFilters($filter->getShould(), Select::SQL_OR, $isNegation); + $must = $this->buildFilters($filter->getMust(), Select::SQL_AND, $isNegation, $queryContainer); + $should = $this->buildFilters($filter->getShould(), Select::SQL_OR, $isNegation, $queryContainer); $mustNot = $this->buildFilters( $filter->getMustNot(), Select::SQL_AND, - !$isNegation + !$isNegation, + $queryContainer ); $queries = [ @@ -111,13 +115,14 @@ class Builder implements BuilderInterface * @param \Magento\Framework\Search\Request\FilterInterface[] $filters * @param string $unionOperator * @param bool $isNegation + * @param QueryContainer $queryContainer * @return string */ - private function buildFilters(array $filters, $unionOperator, $isNegation) + private function buildFilters(array $filters, $unionOperator, $isNegation, QueryContainer $queryContainer) { $queries = []; foreach ($filters as $filter) { - $queries[] = $this->processFilter($filter, $isNegation); + $queries[] = $this->processFilter($filter, $isNegation, $queryContainer); } return $this->conditionManager->combineQueries($queries, $unionOperator); } diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/BuilderInterface.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/BuilderInterface.php index ed3c7b6b05909686b0a3c1a1a04dbbbe15ae1f42..ee0d5b83d8dd133e1a5008dc2c53e8414b53dba9 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/BuilderInterface.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/BuilderInterface.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Search\Adapter\Mysql\Filter; +use Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer; use Magento\Framework\Search\Request\FilterInterface as RequestFilterInterface; interface BuilderInterface @@ -12,7 +13,8 @@ interface BuilderInterface /** * @param RequestFilterInterface $filter * @param string $conditionType + * @param QueryContainer $queryContainer * @return string */ - public function build(RequestFilterInterface $filter, $conditionType); + public function build(RequestFilterInterface $filter, $conditionType, QueryContainer $queryContainer); } diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Preprocessor.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Preprocessor.php index cfdb0f03020719e5b54718ce515c9d9c17241ab4..51bf992250d7fab5dce6da9c26cea65404ed3625 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Preprocessor.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/Preprocessor.php @@ -6,6 +6,7 @@ namespace Magento\Framework\Search\Adapter\Mysql\Filter; use Magento\Framework\Search\Adapter\Mysql\ConditionManager; +use Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer; use Magento\Framework\Search\Request\FilterInterface; class Preprocessor implements PreprocessorInterface @@ -26,7 +27,7 @@ class Preprocessor implements PreprocessorInterface /** * {@inheritdoc} */ - public function process(FilterInterface $filter, $isNegation, $query) + public function process(FilterInterface $filter, $isNegation, $query, QueryContainer $queryContainer) { return $query; } diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/PreprocessorInterface.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/PreprocessorInterface.php index 8734185ca5bddccba8141a3ce198cde1f3dd7511..b11a69eaf6f3bedeb5831c67cf38f371cd7e6b60 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/PreprocessorInterface.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Filter/PreprocessorInterface.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Search\Adapter\Mysql\Filter; +use Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer; use Magento\Framework\Search\Request\FilterInterface; interface PreprocessorInterface @@ -13,7 +14,8 @@ interface PreprocessorInterface * @param FilterInterface $filter * @param bool $isNegation * @param string $query + * @param QueryContainer $queryContainer * @return string */ - public function process(FilterInterface $filter, $isNegation, $query); + public function process(FilterInterface $filter, $isNegation, $query, QueryContainer $queryContainer); } diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Mapper.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Mapper.php index 2f8579a79e2dc678bba7880661b7d764bf6faba5..e8992a0e6c53226c5f880273e994debcacd3b867 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Mapper.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Mapper.php @@ -5,9 +5,12 @@ */ namespace Magento\Framework\Search\Adapter\Mysql; +use Magento\Framework\App\Resource; use Magento\Framework\DB\Select; use Magento\Framework\Search\Adapter\Mysql\Filter\Builder; -use Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match as MatchQueryBuilder; +use Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer; +use Magento\Framework\Search\Adapter\Mysql\Query\QueryContainerFactory; +use Magento\Framework\Search\EntityMetadata; use Magento\Framework\Search\Request\Query\Bool as BoolQuery; use Magento\Framework\Search\Request\Query\Filter as FilterQuery; use Magento\Framework\Search\Request\Query\Match as MatchQuery; @@ -20,16 +23,12 @@ use Magento\Framework\Search\RequestInterface; */ class Mapper { + const SQL_ENTITIES_LIMIT = 10000; /** * @var ScoreBuilder */ private $scoreBuilderFactory; - /** - * @var \Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match - */ - private $matchQueryBuilder; - /** * @var Filter\Builder */ @@ -46,32 +45,53 @@ class Mapper private $conditionManager; /** - * @var array + * @var IndexBuilderInterface[] */ private $indexProviders; + /** + * @var Resource + */ + private $resource; + + /** + * @var EntityMetadata + */ + private $entityMetadata; + + /** + * @var QueryContainerFactory + */ + private $queryContainerFactory; + /** * @param ScoreBuilderFactory $scoreBuilderFactory - * @param MatchQueryBuilder $matchQueryBuilder * @param Builder $filterBuilder * @param Dimensions $dimensionsBuilder * @param ConditionManager $conditionManager - * @param \Magento\Framework\Search\Adapter\Mysql\IndexBuilderInterface[] $indexProviders + * @param Resource|Resource $resource + * @param EntityMetadata $entityMetadata + * @param QueryContainerFactory $queryContainerFactory + * @param IndexBuilderInterface[] $indexProviders */ public function __construct( ScoreBuilderFactory $scoreBuilderFactory, - MatchQueryBuilder $matchQueryBuilder, Builder $filterBuilder, Dimensions $dimensionsBuilder, ConditionManager $conditionManager, + Resource $resource, + EntityMetadata $entityMetadata, + QueryContainerFactory $queryContainerFactory, array $indexProviders ) { $this->scoreBuilderFactory = $scoreBuilderFactory; - $this->matchQueryBuilder = $matchQueryBuilder; $this->filterBuilder = $filterBuilder; $this->dimensionsBuilder = $dimensionsBuilder; $this->conditionManager = $conditionManager; + $this->resource = $resource; + $this->entityMetadata = $entityMetadata; $this->indexProviders = $indexProviders; + $this->queryContainerFactory = $queryContainerFactory; } /** @@ -86,22 +106,89 @@ class Mapper if (!isset($this->indexProviders[$request->getIndex()])) { throw new \Exception('Index provider not configured'); } - $select = $this->indexProviders[$request->getIndex()]->build($request); + $indexBuilder = $this->indexProviders[$request->getIndex()]; + + $queryContainer = $this->queryContainerFactory->create( + [ + 'indexBuilder' => $indexBuilder, + 'request' => $request + ] + ); + $select = $indexBuilder->build($request); /** @var ScoreBuilder $scoreBuilder */ $scoreBuilder = $this->scoreBuilderFactory->create(); $select = $this->processQuery( $scoreBuilder, $request->getQuery(), $select, - BoolQuery::QUERY_CONDITION_MUST + BoolQuery::QUERY_CONDITION_MUST, + $queryContainer ); $select = $this->processDimensions($request, $select); $select->columns($scoreBuilder->build()); - $select->order($scoreBuilder->getScoreAlias() . ' ' . Select::SQL_DESC); + $select->limit(self::SQL_ENTITIES_LIMIT); + + $filtersCount = $queryContainer->getFiltersCount(); + if ($filtersCount > 1) { + $select->group('entity_id'); + $select->having('COUNT(DISTINCT search_index.attribute_id) = ' . $filtersCount); + } + + $select = $this->createAroundSelect($select, $scoreBuilder); + $select->limit($request->getSize()); + + $matchQueries = $queryContainer->getDerivedQueries(); + + if ($matchQueries) { + $subSelect = $select; + $select = $this->resource->getConnection(Resource::DEFAULT_READ_RESOURCE)->select(); + $tables = array_merge($queryContainer->getDerivedQueryNames(), ['main_select.relevance']); + $relevance = implode('.relevance + ', $tables); + $select + ->from( + ['main_select' => $subSelect], + [ + $this->entityMetadata->getEntityId() => 'entity_id', + 'relevance' => sprintf('(%s)', $relevance), + ] + ); + + foreach ($matchQueries as $matchName => $matchSelect) { + $select->join( + [$matchName => $this->createAroundSelect($matchSelect, $scoreBuilder)], + $matchName . '.entity_id = main_select.entity_id', + [] + ); + } + } + + $select->order('relevance ' . Select::SQL_DESC); return $select; } + /** + * @param Select $select + * @param ScoreBuilder $scoreBuilder + * @return Select + */ + private function createAroundSelect( + Select $select, + ScoreBuilder $scoreBuilder + ) { + $parentSelect = $this->resource->getConnection(Resource::DEFAULT_READ_RESOURCE)->select(); + $parentSelect + ->from( + ['main_select' => $select], + [ + $this->entityMetadata->getEntityId() => 'entity_id', + 'relevance' => sprintf('MAX(%s)', $scoreBuilder->getScoreAlias()) + ] + ) + ->group($this->entityMetadata->getEntityId()); + return $parentSelect; + } + /** * Process query * @@ -109,6 +196,7 @@ class Mapper * @param RequestQueryInterface $query * @param Select $select * @param string $conditionType + * @param QueryContainer $queryContainer * @return Select * @throws \InvalidArgumentException */ @@ -116,13 +204,13 @@ class Mapper ScoreBuilder $scoreBuilder, RequestQueryInterface $query, Select $select, - $conditionType + $conditionType, + QueryContainer $queryContainer ) { switch ($query->getType()) { case RequestQueryInterface::TYPE_MATCH: /** @var MatchQuery $query */ - $select = $this->matchQueryBuilder->build( - $scoreBuilder, + $select = $queryContainer->addMatchQuery( $select, $query, $conditionType @@ -130,11 +218,11 @@ class Mapper break; case RequestQueryInterface::TYPE_BOOL: /** @var BoolQuery $query */ - $select = $this->processBoolQuery($scoreBuilder, $query, $select); + $select = $this->processBoolQuery($scoreBuilder, $query, $select, $queryContainer); break; case RequestQueryInterface::TYPE_FILTER: /** @var FilterQuery $query */ - $select = $this->processFilterQuery($scoreBuilder, $query, $select, $conditionType); + $select = $this->processFilterQuery($scoreBuilder, $query, $select, $conditionType, $queryContainer); break; default: throw new \InvalidArgumentException(sprintf('Unknown query type \'%s\'', $query->getType())); @@ -148,31 +236,39 @@ class Mapper * @param ScoreBuilder $scoreBuilder * @param BoolQuery $query * @param Select $select + * @param QueryContainer $queryContainer * @return Select */ - private function processBoolQuery(ScoreBuilder $scoreBuilder, BoolQuery $query, Select $select) - { + private function processBoolQuery( + ScoreBuilder $scoreBuilder, + BoolQuery $query, + Select $select, + QueryContainer $queryContainer + ) { $scoreBuilder->startQuery(); $select = $this->processBoolQueryCondition( $scoreBuilder, $query->getMust(), $select, - BoolQuery::QUERY_CONDITION_MUST + BoolQuery::QUERY_CONDITION_MUST, + $queryContainer ); $select = $this->processBoolQueryCondition( $scoreBuilder, $query->getShould(), $select, - BoolQuery::QUERY_CONDITION_SHOULD + BoolQuery::QUERY_CONDITION_SHOULD, + $queryContainer ); $select = $this->processBoolQueryCondition( $scoreBuilder, $query->getMustNot(), $select, - BoolQuery::QUERY_CONDITION_NOT + BoolQuery::QUERY_CONDITION_NOT, + $queryContainer ); $scoreBuilder->endQuery($query->getBoost()); @@ -187,16 +283,23 @@ class Mapper * @param RequestQueryInterface[] $subQueryList * @param Select $select * @param string $conditionType + * @param QueryContainer $queryContainer * @return Select */ private function processBoolQueryCondition( ScoreBuilder $scoreBuilder, array $subQueryList, Select $select, - $conditionType + $conditionType, + QueryContainer $queryContainer ) { foreach ($subQueryList as $subQuery) { - $select = $this->processQuery($scoreBuilder, $subQuery, $select, $conditionType); + $select = $this->processQuery($scoreBuilder, $subQuery, $select, $conditionType, $queryContainer); + } + $filters = $queryContainer->getFilters(); + if ($filters) { + $select->where('(' . implode(' OR ', $filters) . ')'); + $queryContainer->clearFilters(); } return $select; } @@ -208,19 +311,33 @@ class Mapper * @param FilterQuery $query * @param Select $select * @param string $conditionType + * @param QueryContainer $queryContainer * @return Select */ - private function processFilterQuery(ScoreBuilder $scoreBuilder, FilterQuery $query, Select $select, $conditionType) - { + private function processFilterQuery( + ScoreBuilder $scoreBuilder, + FilterQuery $query, + Select $select, + $conditionType, + QueryContainer $queryContainer + ) { $scoreBuilder->startQuery(); switch ($query->getReferenceType()) { case FilterQuery::REFERENCE_QUERY: - $select = $this->processQuery($scoreBuilder, $query->getReference(), $select, $conditionType); + $select = $this->processQuery( + $scoreBuilder, + $query->getReference(), + $select, + $conditionType, + $queryContainer + ); $scoreBuilder->endQuery($query->getBoost()); break; case FilterQuery::REFERENCE_FILTER: - $filterCondition = $this->filterBuilder->build($query->getReference(), $conditionType); - $select->where($filterCondition); + $filterCondition = $this->filterBuilder->build($query->getReference(), $conditionType, $queryContainer); + if ($filterCondition) { + $select->where($filterCondition); + } break; } $scoreBuilder->endQuery($query->getBoost()); diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php index b024b8e42ba1b85aecdda6d845ac287c26bf0530..7e1c52ec089cae7fe160c4ee85383c6de6ff2277 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/Builder/Match.php @@ -7,6 +7,7 @@ namespace Magento\Framework\Search\Adapter\Mysql\Query\Builder; use Magento\Framework\DB\Helper\Mysql\Fulltext; use Magento\Framework\DB\Select; +use Magento\Framework\Search\Adapter\Mysql\Field\FieldInterface; use Magento\Framework\Search\Adapter\Mysql\Field\ResolverInterface; use Magento\Framework\Search\Adapter\Mysql\ScoreBuilder; use Magento\Framework\Search\Request\Query\Bool; @@ -62,18 +63,28 @@ class Match implements QueryInterface } $resolvedFieldList = $this->resolver->resolve($fieldList); - $queryBoost = $query->getBoost(); - $scoreBuilder->addCondition( - $this->fulltextHelper->getMatchQuery($resolvedFieldList, $queryValue, Fulltext::FULLTEXT_MODE_BOOLEAN), - $queryBoost !== null ? $queryBoost : 1 - ); - $select = $this->fulltextHelper->match( - $select, - $resolvedFieldList, + $fieldIds = []; + $columns = []; + foreach ($resolvedFieldList as $field) { + if ($field->getType() === FieldInterface::TYPE_FULLTEXT && $field->getAttributeId()) { + $fieldIds[] = $field->getAttributeId(); + } + $column = $field->getColumn(); + $columns[$column] = $column; + } + + $matchQuery = $this->fulltextHelper->getMatchQuery( + $columns, $queryValue, - true, Fulltext::FULLTEXT_MODE_BOOLEAN ); + $scoreBuilder->addCondition($matchQuery); + + if ($fieldIds) { + $matchQuery = sprintf('(%s AND search_index.attribute_id IN (%s))', $matchQuery, implode(',', $fieldIds)); + } + + $select->where($matchQuery); return $select; } diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/QueryContainer.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/QueryContainer.php new file mode 100644 index 0000000000000000000000000000000000000000..32ec278580297b78407f13691a18345e3fbf9d82 --- /dev/null +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/QueryContainer.php @@ -0,0 +1,174 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Search\Adapter\Mysql\Query; + +use Magento\Framework\DB\Select; +use Magento\Framework\Search\Adapter\Mysql\IndexBuilderInterface; +use Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match; +use Magento\Framework\Search\Adapter\Mysql\ScoreBuilder; +use Magento\Framework\Search\Adapter\Mysql\ScoreBuilderFactory; +use Magento\Framework\Search\Request\QueryInterface as RequestQueryInterface; +use Magento\Framework\Search\RequestInterface; + +class QueryContainer +{ + const DERIVED_QUERY_PREFIX = 'derived_'; + /** + * @var array [[$select, $scoreBuilder], [$select, $scoreBuilder]] + */ + private $queries = []; + /** + * @var ScoreBuilderFactory + */ + private $scoreBuilderFactory; + /** + * @var Match + */ + private $matchBuilder; + /** + * @var IndexBuilderInterface + */ + private $indexBuilder; + /** + * @var RequestInterface + */ + private $request; + + /** + * @var string[] + */ + private $filters = []; + + /** + * @var int + */ + private $filtersCount = 0; + + /** + * @param ScoreBuilderFactory $scoreBuilderFactory + * @param Match $matchBuilder + * @param IndexBuilderInterface $indexBuilder + * @param RequestInterface $request + */ + public function __construct( + ScoreBuilderFactory $scoreBuilderFactory, + Match $matchBuilder, + IndexBuilderInterface $indexBuilder, + RequestInterface $request + ) { + $this->scoreBuilderFactory = $scoreBuilderFactory; + $this->matchBuilder = $matchBuilder; + $this->indexBuilder = $indexBuilder; + $this->request = $request; + } + + /** + * @param Select $select + * @param RequestQueryInterface $query + * @param string $conditionType + * @return Select + */ + public function addMatchQuery( + Select $select, + RequestQueryInterface $query, + $conditionType + ) { + $subSelect = $this->createSelect(); + $subScoreBuilder = $this->scoreBuilderFactory->create(); + $this->buildMatchQuery($subScoreBuilder, $subSelect, $query, $conditionType); + $subSelect->columns($subScoreBuilder->build()); + $subSelect->limit($this->request->getSize()); + $this->addDerivedQuery($subSelect); + + return $select; + } + + /** + * @param string $filter + * @return void + */ + public function addFilter($filter) + { + $this->filters[] = '(' . $filter . ')'; + $this->filtersCount++; + } + + /** + * @return void + */ + public function clearFilters() + { + $this->filters = []; + } + + /** + * @return string[] + */ + public function getFilters() + { + return $this->filters; + } + + /** + * @return int + */ + public function getFiltersCount() + { + return $this->filtersCount; + } + + /** + * @return Select[] + */ + public function getDerivedQueries() + { + return $this->queries; + } + + /** + * @return array + */ + public function getDerivedQueryNames() + { + return array_keys($this->getDerivedQueries()); + } + + /** + * @param Select $select + * @return void + */ + private function addDerivedQuery(Select $select) + { + $name = self::DERIVED_QUERY_PREFIX . count($this->queries); + $this->queries[$name] = $select; + } + + /** + * @return Select + */ + private function createSelect() + { + return $this->indexBuilder->build($this->request); + } + + /** + * @param ScoreBuilder $scoreBuilder + * @param Select $select + * @param RequestQueryInterface $query + * @param string $conditionType + * @return Select + */ + private function buildMatchQuery( + ScoreBuilder $scoreBuilder, + Select $select, + RequestQueryInterface $query, + $conditionType + ) { + $select = $this->matchBuilder->build($scoreBuilder, $select, $query, $conditionType); + return $select; + } +} diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/QueryContainerFactory.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/QueryContainerFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..15591bab26cbfbc7a480d7f42d6b5d2fd8a7cab4 --- /dev/null +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/Query/QueryContainerFactory.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Search\Adapter\Mysql\Query; + +/** + * MatchContainer Factory + */ +class QueryContainerFactory +{ + /** + * Object Manager instance + * + * @var \Magento\Framework\ObjectManagerInterface + */ + protected $_objectManager = null; + + /** + * Instance name to create + * + * @var string + */ + protected $_instanceName = null; + + /** + * Factory constructor + * + * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param string $instanceName + */ + public function __construct( + \Magento\Framework\ObjectManagerInterface $objectManager, + $instanceName = 'Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer' + ) { + $this->_objectManager = $objectManager; + $this->_instanceName = $instanceName; + } + + /** + * Create class instance with specified parameters + * + * @param array $data + * @return \Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer + */ + public function create(array $data = []) + { + return $this->_objectManager->create($this->_instanceName, $data); + } +} diff --git a/lib/internal/Magento/Framework/Search/Adapter/Mysql/ScoreBuilder.php b/lib/internal/Magento/Framework/Search/Adapter/Mysql/ScoreBuilder.php index 2b2e41808855b14fdfa3fad307e40ff0ee2317d3..19c8f261d99470083abab1582a4b1c9e5f705eae 100644 --- a/lib/internal/Magento/Framework/Search/Adapter/Mysql/ScoreBuilder.php +++ b/lib/internal/Magento/Framework/Search/Adapter/Mysql/ScoreBuilder.php @@ -15,6 +15,11 @@ class ScoreBuilder */ private $scoreCondition = ''; + /** + * @var string + */ + const WEIGHT_FIELD = 'search_weight'; + /** * Get column alias for global score query in sql * @@ -22,7 +27,7 @@ class ScoreBuilder */ public function getScoreAlias() { - return 'global_score'; + return 'score'; } /** @@ -69,13 +74,12 @@ class ScoreBuilder * Add Condition for score calculation * * @param string $score - * @param float $boost * @return void */ - public function addCondition($score, $boost) + public function addCondition($score) { $this->addPlus(); - $this->scoreCondition .= "{$score} * {$boost}"; + $this->scoreCondition .= "{$score} * " . self::WEIGHT_FIELD; } /** diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Filter/BuilderTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Filter/BuilderTest.php index b915ac500a5e9f578fd51bfd5c46a5a9607f9ed2..8c1cc50ded322f937aa30b739fcc75f9ee53bd50 100644 --- a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Filter/BuilderTest.php +++ b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Filter/BuilderTest.php @@ -161,7 +161,10 @@ class BuilderTest extends \PHPUnit_Framework_TestCase */ public function testBuildFilter($filter, $conditionType, $expectedResult) { - $actualResult = $this->builder->build($filter, $conditionType); + $queryContainer = $this->getMockBuilder('\Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer') + ->disableOriginalConstructor() + ->getMock(); + $actualResult = $this->builder->build($filter, $conditionType, $queryContainer); $this->assertEquals($expectedResult, $actualResult); } @@ -412,6 +415,9 @@ class BuilderTest extends \PHPUnit_Framework_TestCase $filter->expects($this->any()) ->method('getType') ->will($this->returnValue('unknownType')); - $this->builder->build($filter, RequestBoolQuery::QUERY_CONDITION_MUST); + $queryContainer = $this->getMockBuilder('\Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer') + ->disableOriginalConstructor() + ->getMock(); + $this->builder->build($filter, RequestBoolQuery::QUERY_CONDITION_MUST, $queryContainer); } } diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/MapperTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/MapperTest.php index 4a918ed2d016e678b4348c11a552a298b282fe59..05e063694dbd7e6aa631a40c4554c9f153eebfb9 100644 --- a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/MapperTest.php +++ b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/MapperTest.php @@ -54,7 +54,7 @@ class MapperTest extends \PHPUnit_Framework_TestCase /** * @var \Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match|MockObject */ - private $matchQueryBuilder; + private $queryContainer; /** * @var \Magento\Framework\Search\Adapter\Mysql\Filter\Builder|MockObject @@ -76,9 +76,12 @@ class MapperTest extends \PHPUnit_Framework_TestCase $helper = new ObjectManager($this); $this->select = $this->getMockBuilder('Magento\Framework\DB\Select') - ->setMethods([]) + ->setMethods(['group', 'limit', 'where', 'columns', 'from']) ->disableOriginalConstructor() ->getMock(); + $this->select->expects($this->any()) + ->method('from') + ->willReturnSelf(); $connectionAdapter = $this->getMockBuilder('Magento\Framework\DB\Adapter\AdapterInterface') ->setMethods(['select']) @@ -110,14 +113,26 @@ class MapperTest extends \PHPUnit_Framework_TestCase ->getMock(); $this->request = $this->getMockBuilder('Magento\Framework\Search\RequestInterface') - ->setMethods(['getQuery', 'getDimensions', 'getIndex']) + ->setMethods(['getQuery', 'getDimensions', 'getIndex', 'getSize']) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $this->matchQueryBuilder = $this->getMockBuilder('Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match') - ->setMethods(['build']) + $this->queryContainer = $this->getMockBuilder('Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer') + ->setMethods(['addMatchQuery']) + ->disableOriginalConstructor() + ->getMock(); + $this->queryContainer->expects($this->any()) + ->method('addMatchQuery') + ->willReturnArgument(0); + $queryContainerFactory = $this->getMockBuilder( + 'Magento\Framework\Search\Adapter\Mysql\Query\QueryContainerFactory' + ) + ->setMethods(['create']) ->disableOriginalConstructor() ->getMock(); + $queryContainerFactory->expects($this->any()) + ->method('create') + ->willReturn($this->queryContainer); $this->filter = $this->getMockBuilder('Magento\Framework\Search\Request\FilterInterface') ->disableOriginalConstructor() @@ -133,7 +148,7 @@ class MapperTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->setMethods(['build']) ->getMockForAbstractClass(); - $indexBuilder->expects($this->once()) + $indexBuilder->expects($this->any()) ->method('build') ->will($this->returnValue($this->select)); @@ -147,7 +162,7 @@ class MapperTest extends \PHPUnit_Framework_TestCase [ 'resource' => $this->resource, 'scoreBuilderFactory' => $this->scoreBuilderFactory, - 'matchQueryBuilder' => $this->matchQueryBuilder, + 'queryContainerFactory' => $queryContainerFactory, 'filterBuilder' => $this->filterBuilder, 'dimensionsBuilder' => $this->dimensionsBuilder, 'indexProviders' => [$index => $indexBuilder] @@ -164,13 +179,12 @@ class MapperTest extends \PHPUnit_Framework_TestCase ->will( $this->returnValue([$this->createDimension()]) ); - $this->dimensionsBuilder->expects($this->once()) + $this->dimensionsBuilder->expects($this->any()) ->method('build') ->will($this->returnValue('a = b')); - $this->matchQueryBuilder->expects($this->once())->method('build') + $this->queryContainer->expects($this->any())->method('addMatchQuery') ->with( - $this->equalTo($this->scoreBuilder), $this->equalTo($this->select), $this->equalTo($query), $this->equalTo(Bool::QUERY_CONDITION_MUST) @@ -217,9 +231,6 @@ class MapperTest extends \PHPUnit_Framework_TestCase $query = $this->createBoolQuery(); $this->request->expects($this->once())->method('getQuery')->will($this->returnValue($query)); - $this->matchQueryBuilder->expects($this->exactly(4))->method('build') - ->will($this->returnValue($this->select)); - $matchQuery = $this->createMatchQuery(); $filterMatchQuery = $this->createFilterQuery(); $filterMatchQuery->expects($this->once())->method('getReferenceType') diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Builder/Query/MatchTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Query/Builder/MatchTest.php similarity index 74% rename from lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Builder/Query/MatchTest.php rename to lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Query/Builder/MatchTest.php index dc2a157d0127f08bf9946435843410997e1b150d..6e8bfe5d8aa504f5204c4bb8e35183b4ac686517 100644 --- a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Builder/Query/MatchTest.php +++ b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Query/Builder/MatchTest.php @@ -3,9 +3,8 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Framework\Search\Test\Unit\Adapter\Mysql\Builder\Query; +namespace Magento\Framework\Search\Test\Unit\Adapter\Mysql\Query\Builder; -use Magento\Framework\DB\Helper\Mysql\Fulltext; use Magento\Framework\DB\Select; use Magento\Framework\Search\Request\Query\Bool; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; @@ -58,37 +57,44 @@ class MatchTest extends \PHPUnit_Framework_TestCase public function testBuildQuery() { - $boost = 3.14; - /** @var Select|\PHPUnit_Framework_MockObject_MockObject $select */ $select = $this->getMockBuilder('Magento\Framework\DB\Select') - ->setMethods(['getMatchQuery', 'match']) + ->setMethods(['getMatchQuery', 'match', 'where']) ->disableOriginalConstructor() ->getMock(); $this->fulltextHelper->expects($this->once()) ->method('getMatchQuery') - ->with($this->equalTo(['some_field']), $this->equalTo('-some_value*')) + ->with($this->equalTo(['some_field' => 'some_field']), $this->equalTo('-some_value*')) ->will($this->returnValue('matchedQuery')); - $this->fulltextHelper->expects($this->once()) - ->method('match') - ->withConsecutive([$select, ['some_field'], '-some_value*', true, Fulltext::FULLTEXT_MODE_BOOLEAN]) - ->willReturn($select); + $select->expects($this->once()) + ->method('where') + ->with('matchedQuery') + ->willReturnSelf(); $this->resolver->expects($this->once()) ->method('resolve') - ->willReturnArgument(0); + ->willReturnCallback(function ($fieldList) { + $resolvedFields = []; + foreach ($fieldList as $column) { + $field = $this->getMockBuilder('\Magento\Framework\Search\Adapter\Mysql\Field\FieldInterface') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $field->expects($this->any()) + ->method('getColumn') + ->willReturn($column); + $resolvedFields[] = $field; + } + return $resolvedFields; + }); /** @var \Magento\Framework\Search\Request\Query\Match|\PHPUnit_Framework_MockObject_MockObject $query */ $query = $this->getMockBuilder('Magento\Framework\Search\Request\Query\Match') - ->setMethods(['getMatches', 'getValue', 'getBoost']) + ->setMethods(['getMatches', 'getValue']) ->disableOriginalConstructor() ->getMock(); $query->expects($this->once()) ->method('getValue') ->willReturn('some_value '); - $query->expects($this->once()) - ->method('getBoost') - ->willReturn($boost); $query->expects($this->once()) ->method('getMatches') ->willReturn([['field' => 'some_field']]); diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Query/QueryContainerTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Query/QueryContainerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a1ef558e3dc68fbe011050c3e015d66c3690d4aa --- /dev/null +++ b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/Query/QueryContainerTest.php @@ -0,0 +1,126 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\Search\Test\Unit\Adapter\Mysql\Query; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer; +use Magento\Framework\Search\Request\Query\Bool; + +class QueryContainerTest extends \PHPUnit_Framework_TestCase +{ + /** @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject */ + private $select; + + /** @var \Magento\Framework\Search\Adapter\Mysql\ScoreBuilder|\PHPUnit_Framework_MockObject_MockObject */ + private $scoreBuilder; + + /** @var \Magento\Framework\Search\Adapter\Mysql\ScoreBuilderFactory|\PHPUnit_Framework_MockObject_MockObject */ + private $scoreBuilderFactory; + + /** @var \Magento\Framework\Search\Request\QueryInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $query; + + /** @var \Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match|\PHPUnit_Framework_MockObject_MockObject */ + private $matchBuilder; + + /** @var \Magento\Framework\Search\Adapter\Mysql\IndexBuilderInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $indexBuilder; + + /** @var \Magento\Framework\Search\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ + private $request; + + /** @var \Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer */ + private $queryContainer; + + protected function setUp() + { + $helper = new ObjectManager($this); + + $this->select = $this->getMockBuilder('Magento\Framework\DB\Select') + ->disableOriginalConstructor() + ->getMock(); + + $this->scoreBuilder = $this->getMockBuilder('Magento\Framework\Search\Adapter\Mysql\ScoreBuilder') + ->disableOriginalConstructor() + ->getMock(); + $this->scoreBuilderFactory = $this->getMockBuilder('Magento\Framework\Search\Adapter\Mysql\ScoreBuilderFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $this->scoreBuilderFactory->expects($this->any())->method('create')->willReturn($this->scoreBuilder); + + $this->query = $this->getMockBuilder('Magento\Framework\Search\Request\QueryInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->matchBuilder = $this->getMockBuilder('Magento\Framework\Search\Adapter\Mysql\Query\Builder\Match') + ->setMethods(['build']) + ->disableOriginalConstructor() + ->getMock(); + $this->matchBuilder->expects($this->any())->method('build')->willReturnArgument(1); + + $this->indexBuilder = $this->getMockBuilder('Magento\Framework\Search\Adapter\Mysql\IndexBuilderInterface') + ->setMethods(['build']) + ->disableOriginalConstructor() + ->getMock(); + + $this->request = $this->getMockBuilder('\Magento\Framework\Search\RequestInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->queryContainer = $helper->getObject( + 'Magento\Framework\Search\Adapter\Mysql\Query\QueryContainer', + [ + 'scoreBuilderFactory' => $this->scoreBuilderFactory, + 'matchBuilder' => $this->matchBuilder, + 'indexBuilder' => $this->indexBuilder, + 'request' => $this->request + ] + ); + } + + public function testBuild() + { + + $this->scoreBuilder->expects($this->once())->method('build')->willReturn('score condition'); + $subSelect = $this->getMockBuilder('Magento\Framework\DB\Select') + ->disableOriginalConstructor() + ->getMock(); + $this->indexBuilder->expects($this->once())->method('build')->willReturn($subSelect); + $subSelect->expects($this->once())->method('columns')->with('score condition'); + $this->request->expects($this->once())->method('getSize')->willReturn(1000); + $subSelect->expects($this->once())->method('limit')->with(1000); + + $result = $this->queryContainer->addMatchQuery($this->select, $this->query, Bool::QUERY_CONDITION_MUST); + $this->assertEquals($this->select, $result); + } + + public function testGetDerivedQueryNames() + { + $this->testBuild(); + $expected = [QueryContainer::DERIVED_QUERY_PREFIX . '0']; + $this->assertEquals($expected, $this->queryContainer->getDerivedQueryNames()); + } + + public function testGetDerivedQueries() + { + $this->testBuild(); + $queries = $this->queryContainer->getDerivedQueries(); + $this->assertCount(1, $queries); + $this->assertEquals($this->select, reset($queries)); + } + + public function testFilters() + { + $this->assertEmpty($this->queryContainer->getFilters()); + $this->queryContainer->addFilter('filter'); + $this->assertCount(1, $this->queryContainer->getFilters()); + $this->assertEquals(1, $this->queryContainer->getFiltersCount()); + $this->queryContainer->clearFilters(); + $this->assertCount(0, $this->queryContainer->getFilters()); + $this->assertEquals(1, $this->queryContainer->getFiltersCount()); + } +} diff --git a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/ScoreBuilderTest.php b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/ScoreBuilderTest.php index daa11aa0e0dd29f08e592c0e2d45369795dbe205..c9f895042d657130c0a60bbcbbf1b0f002ce0d34 100644 --- a/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/ScoreBuilderTest.php +++ b/lib/internal/Magento/Framework/Search/Test/Unit/Adapter/Mysql/ScoreBuilderTest.php @@ -5,6 +5,7 @@ */ namespace Magento\Framework\Search\Test\Unit\Adapter\Mysql; +use Magento\Framework\Search\Adapter\Mysql\ScoreBuilder; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class ScoreBuilderTest extends \PHPUnit_Framework_TestCase @@ -16,24 +17,24 @@ class ScoreBuilderTest extends \PHPUnit_Framework_TestCase $builder->startQuery(); // start one query - $builder->addCondition('someCondition1', 1.1); + $builder->addCondition('someCondition1'); $builder->startQuery(); // start two query - $builder->addCondition('someCondition2', 1.2); - $builder->addCondition('someCondition3', 1.3); + $builder->addCondition('someCondition2'); + $builder->addCondition('someCondition3'); $builder->startQuery(); // start three query - $builder->addCondition('someCondition4', 1.4); - $builder->addCondition('someCondition5', 1.5); + $builder->addCondition('someCondition4'); + $builder->addCondition('someCondition5'); $builder->endQuery(10.1); // end three query $builder->startQuery(); // start four query - $builder->addCondition('someCondition6', 1.6); - $builder->addCondition('someCondition7', 1.7); + $builder->addCondition('someCondition6'); + $builder->addCondition('someCondition7'); $builder->endQuery(10.2); // end four query $builder->endQuery(10.3); // start two query @@ -44,10 +45,10 @@ class ScoreBuilderTest extends \PHPUnit_Framework_TestCase $result = $builder->build(); - $expected = '((someCondition1 * 1.1 + (someCondition2 * 1.2 + someCondition3 * 1.3 + ' . - '(someCondition4 * 1.4 + someCondition5 * 1.5) * 10.1 + (someCondition6 * 1.6 + ' . - 'someCondition7 * 1.7) * 10.2) * 10.3) * 10.4 + (0)) AS global_score'; - + $expected = '((someCondition1 * %1$s + (someCondition2 * %1$s + someCondition3 * %1$s + ' . + '(someCondition4 * %1$s + someCondition5 * %1$s) * 10.1 + (someCondition6 * %1$s + ' . + 'someCondition7 * %1$s) * 10.2) * 10.3) * 10.4 + (0)) AS ' . $builder->getScoreAlias(); + $expected = sprintf($expected, ScoreBuilder::WEIGHT_FIELD); $this->assertEquals($expected, $result); } } diff --git a/lib/internal/Magento/Framework/Search/etc/requests.xsd b/lib/internal/Magento/Framework/Search/etc/requests.xsd index b15f296d90d613663c796cddcf850af15c6f9209..e7fdeaaa43e87912a035f6345cb9fc1d513aba84 100644 --- a/lib/internal/Magento/Framework/Search/etc/requests.xsd +++ b/lib/internal/Magento/Framework/Search/etc/requests.xsd @@ -225,7 +225,6 @@ <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute type="xs:string" name="field" use="required" /> - <xs:attribute type="xs:byte" name="boost" use="optional" /> </xs:extension> </xs:simpleContent> </xs:complexType> diff --git a/lib/internal/Magento/Framework/Stdlib/Test/Unit/ArrayUtilsTest.php b/lib/internal/Magento/Framework/Stdlib/Test/Unit/ArrayUtilsTest.php index 08e3373ef96857b05e9c7470bd7f79524b575751..70f895792c70a34787df370826207d6c908a906e 100644 --- a/lib/internal/Magento/Framework/Stdlib/Test/Unit/ArrayUtilsTest.php +++ b/lib/internal/Magento/Framework/Stdlib/Test/Unit/ArrayUtilsTest.php @@ -72,9 +72,6 @@ class ArrayUtilsTest extends \PHPUnit_Framework_TestCase new \Magento\Framework\Object($decorated[1]), new \Magento\Framework\Object($decorated[2]), ]; - foreach ($decoratedVo as $obj) { - $obj->setDataChanges(true); // hack for assertion - } $this->assertEquals($decoratedVo, $this->_arrayUtils->decorateArray($sample, '')); } } diff --git a/lib/internal/Magento/Framework/Test/Unit/FlagTest.php b/lib/internal/Magento/Framework/Test/Unit/FlagTest.php index d3dba9f57bda97eb4b4ae7aaa5d93cc43bab1fad..bb97be1fde8888544023b8ab45e7d4eb4fa55532 100644 --- a/lib/internal/Magento/Framework/Test/Unit/FlagTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/FlagTest.php @@ -61,7 +61,9 @@ class FlagTest extends \PHPUnit_Framework_TestCase ->method('addCommitCallback') ->will($this->returnSelf()); - $resourceCollection = $this->getMock('Magento\Framework\Data\Collection\Db', [], [], '', false, false); + $resourceCollection = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $this->flag = new \Magento\Framework\Flag( $context, diff --git a/lib/internal/Magento/Framework/Test/Unit/ObjectTest.php b/lib/internal/Magento/Framework/Test/Unit/ObjectTest.php index 66edf78695dfb5e65b9e4516ad23f296e7d26745..e276bd54407fd520be750c90814e6f74bd725c6a 100644 --- a/lib/internal/Magento/Framework/Test/Unit/ObjectTest.php +++ b/lib/internal/Magento/Framework/Test/Unit/ObjectTest.php @@ -49,59 +49,6 @@ class ObjectTest extends \PHPUnit_Framework_TestCase $this->assertEquals($data, $object->getData()); } - /** - * Tests \Magento\Framework\Object->isDeleted() - */ - public function testIsDeleted() - { - $this->assertFalse($this->_object->isDeleted()); - $this->_object->isDeleted(); - $this->assertFalse($this->_object->isDeleted()); - $this->_object->isDeleted(true); - $this->assertTrue($this->_object->isDeleted()); - } - - /** - * Tests \Magento\Framework\Object->hasDataChanges() - */ - public function testHasDataChanges() - { - $this->assertFalse($this->_object->hasDataChanges()); - $this->_object->setData('key', 'value'); - $this->assertTrue($this->_object->hasDataChanges(), 'Data changed'); - - $object = new \Magento\Framework\Object(['key' => 'value']); - $object->setData('key', 'value'); - $this->assertFalse($object->hasDataChanges(), 'Data not changed'); - - $object->setData(['key' => 'value']); - $this->assertFalse($object->hasDataChanges(), 'Data not changed (array)'); - - $object = new \Magento\Framework\Object(); - $object->unsetData(); - $this->assertFalse($object->hasDataChanges(), 'Unset data'); - - $object = new \Magento\Framework\Object(['key' => null]); - $object->setData('key', null); - $this->assertFalse($object->hasDataChanges(), 'Null data'); - } - - /** - * Tests \Magento\Framework\Object->getId() - */ - public function testSetGetId() - { - $this->_object->setId('test'); - $this->assertEquals('test', $this->_object->getId()); - } - - public function testSetGetIdFieldName() - { - $name = 'entity_id_custom'; - $this->_object->setIdFieldName($name); - $this->assertEquals($name, $this->_object->getIdFieldName()); - } - /** * Tests \Magento\Framework\Object->addData() */ @@ -165,14 +112,14 @@ class ObjectTest extends \PHPUnit_Framework_TestCase 'key1' => 'value1', 'key2' => [ 'subkey2.1' => 'value2.1', - 'subkey2.2' => 'multiline -string', + 'subkey2.2' => 'multiline'. PHP_EOL .'string', 'subkey2.3' => new \Magento\Framework\Object(['test_key' => 'test_value']), ], 'key3' => 5, ]; - $this->_object->setData($data); - + foreach ($data as $key => $value) { + $this->_object->setData($key, $value); + } $this->assertEquals($data, $this->_object->getData()); $this->assertEquals('value1', $this->_object->getData('key1')); $this->assertEquals('value2.1', $this->_object->getData('key2/subkey2.1')); @@ -184,17 +131,18 @@ string', public function testGetDataByPath() { - $this->_object->setData( - [ - 'key1' => 'value1', - 'key2' => [ - 'subkey2.1' => 'value2.1', - 'subkey2.2' => 'multiline + $data = [ + 'key1' => 'value1', + 'key2' => [ + 'subkey2.1' => 'value2.1', + 'subkey2.2' => 'multiline string', - 'subkey2.3' => new \Magento\Framework\Object(['test_key' => 'test_value']), - ], - ] - ); + 'subkey2.3' => new \Magento\Framework\Object(['test_key' => 'test_value']), + ], + ]; + foreach ($data as $key => $value) { + $this->_object->setData($key, $value); + } $this->assertEquals('value1', $this->_object->getDataByPath('key1')); $this->assertEquals('value2.1', $this->_object->getDataByPath('key2/subkey2.1')); $this->assertEquals('test_value', $this->_object->getDataByPath('key2/subkey2.3/test_key')); @@ -204,7 +152,7 @@ string', public function testGetDataByKey() { - $this->_object->setData(['key' => 'value']); + $this->_object->setData('key', 'value'); $this->assertEquals('value', $this->_object->getDataByKey('key')); $this->assertNull($this->_object->getDataByKey('empty')); } @@ -222,17 +170,6 @@ string', $mock->getDataUsingMethod('test_data'); } - /** - * Tests \Magento\Framework\Object->getDataSetDefault() - */ - public function testGetDataSetDefault() - { - $this->_object->setData(['key1' => 'value1', 'key2' => null]); - $this->assertEquals('value1', $this->_object->getDataSetDefault('key1', 'default')); - $this->assertEquals(null, $this->_object->getDataSetDefault('key2', 'default')); - $this->assertEquals('default', $this->_object->getDataSetDefault('key3', 'default')); - } - /** * Tests \Magento\Framework\Object->hasData() */ @@ -251,7 +188,8 @@ string', { $this->assertEquals([], $this->_object->toArray()); $this->assertEquals(['key' => null], $this->_object->toArray(['key'])); - $this->_object->setData(['key1' => 'value1', 'key2' => 'value2']); + $this->_object->setData('key1', 'value1'); + $this->_object->setData('key2', 'value2'); $this->assertEquals(['key1' => 'value1'], $this->_object->toArray(['key1'])); $this->assertEquals(['key2' => 'value2'], $this->_object->convertToArray(['key2'])); } @@ -261,7 +199,8 @@ string', */ public function testToXml() { - $this->_object->setData(['key1' => 'value1', 'key2' => 'value2']); + $this->_object->setData('key1', 'value1'); + $this->_object->setData('key2', 'value2'); $xml = '<item> <key1><![CDATA[value1]]></key1> <key2><![CDATA[value2]]></key2> @@ -309,7 +248,8 @@ string', */ public function testToJson() { - $this->_object->setData(['key1' => 'value1', 'key2' => 'value2']); + $this->_object->setData('key1', 'value1'); + $this->_object->setData('key2', 'value2'); $this->assertEquals('{"key1":"value1","key2":"value2"}', $this->_object->toJson()); $this->assertEquals('{"key1":"value1"}', $this->_object->toJson(['key1'])); $this->assertEquals('{"key1":"value1","key":null}', $this->_object->convertToJson(['key1', 'key'])); @@ -320,7 +260,8 @@ string', */ public function testToString() { - $this->_object->setData(['key1' => 'value1', 'key2' => 'value2']); + $this->_object->setData('key1', 'value1'); + $this->_object->setData('key2', 'value2'); $this->assertEquals('value1, value2', $this->_object->toString()); $this->assertEquals('test value1 with value2', $this->_object->toString('test {{key1}} with {{key2}}')); } @@ -332,7 +273,7 @@ string', */ public function testCall() { - $this->_object->setData(['key' => 'value']); + $this->_object->setData('key', 'value'); $this->_object->setTest('test'); $this->assertEquals('test', $this->_object->getData('test')); @@ -372,7 +313,8 @@ string', */ public function testSerialize() { - $this->_object->setData(['key1' => 'value1', 'key2' => 'value2']); + $this->_object->setData('key1', 'value1'); + $this->_object->setData('key2', 'value2'); $this->assertEquals('key1="value1" key2="value2"', $this->_object->serialize()); $this->assertEquals( 'key1:\'value1\'_key2:\'value2\'', @@ -380,40 +322,15 @@ string', ); } - /** - * Tests \Magento\Framework\Object->setOrigData() - */ - public function testOrigData() - { - $data = ['key1' => 'value1', 'key2' => 'value2']; - $this->_object->setData($data); - $this->_object->setOrigData(); - $this->_object->setData('key1', 'test'); - $this->assertTrue($this->_object->dataHasChangedFor('key1')); - $this->assertEquals($data, $this->_object->getOrigData()); - - $this->_object->setOrigData('key1', 'test'); - $this->assertEquals('test', $this->_object->getOrigData('key1')); - } - - /** - * Tests \Magento\Framework\Object->setDataChanges() - */ - public function testSetDataChanges() - { - $this->assertFalse($this->_object->hasDataChanges()); - $this->_object->setDataChanges(true); - $this->assertTrue($this->_object->hasDataChanges()); - } - /** * Tests \Magento\Framework\Object->debug() */ public function testDebug() { $data = ['key1' => 'value1', 'key2' => ['test'], 'key3' => $this->_object]; - $this->_object->setData($data); - + foreach ($data as $key => $value) { + $this->_object->setData($key, $value); + } $debug = $data; unset($debug['key3']); $debug['key3 (Magento\Framework\Object)'] = '*** RECURSION ***'; diff --git a/lib/internal/Magento/Framework/Validator/Entity/Properties.php b/lib/internal/Magento/Framework/Validator/Entity/Properties.php index 6c96fe8bac14afc2f40dc5f5a943b1c73d41ef13..59e0044b56b2910df880a6bbf893154387dd2994 100644 --- a/lib/internal/Magento/Framework/Validator/Entity/Properties.php +++ b/lib/internal/Magento/Framework/Validator/Entity/Properties.php @@ -8,6 +8,7 @@ namespace Magento\Framework\Validator\Entity; use Magento\Framework\Object; +use Magento\Framework\Model\AbstractModel; class Properties extends \Magento\Framework\Validator\AbstractValidator { @@ -28,19 +29,19 @@ class Properties extends \Magento\Framework\Validator\AbstractValidator } /** - * Successful if $value is \Magento\Framework\Object an all condition are fulfilled. + * Successful if $value is \Magento\Framework\Model\AbstractModel an all condition are fulfilled. * * If read-only properties are set than $value mustn't have changes in them. * - * @param Object $value + * @param AbstractModel $value * @return bool * @throws \InvalidArgumentException when $value is not instanceof \Magento\Framework\Object */ public function isValid($value) { $this->_clearMessages(); - if (!$value instanceof Object) { - throw new \InvalidArgumentException('Instance of \Magento\Framework\Object is expected.'); + if (!$value instanceof AbstractModel) { + throw new \InvalidArgumentException('Instance of \Magento\Framework\Model\AbstractModel is expected.'); } if ($this->_readOnlyProperties) { if (!$value->hasDataChanges()) { diff --git a/lib/internal/Magento/Framework/Validator/Test/Unit/Entity/PropertiesTest.php b/lib/internal/Magento/Framework/Validator/Test/Unit/Entity/PropertiesTest.php index 2b3ac221d6cb9df0015ed3a03c967e580fe71265..62bc492e123ba407c133533cd167057d3a6c39bb 100644 --- a/lib/internal/Magento/Framework/Validator/Test/Unit/Entity/PropertiesTest.php +++ b/lib/internal/Magento/Framework/Validator/Test/Unit/Entity/PropertiesTest.php @@ -18,7 +18,13 @@ class PropertiesTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->_object = $this->getMock('Magento\Framework\Object', ['hasDataChanges', 'getData', 'getOrigData']); + $this->_object = $this->getMock( + 'Magento\Framework\Model\AbstractModel', + ['hasDataChanges', 'getData', 'getOrigData'], + [], + '', + false + ); } protected function tearDown() @@ -30,7 +36,7 @@ class PropertiesTest extends \PHPUnit_Framework_TestCase * Testing \Magento\Framework\Validator\Entity\Properties::isValid on invalid argument passed * * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Instance of \Magento\Framework\Object is expected. + * @expectedExceptionMessage Instance of \Magento\Framework\Model\AbstractModel is expected. */ public function testIsValidException() { diff --git a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php index c4b3167ac45ca9b2f8ec4dca4d31947f6157e04a..0e9f2b4040579479779363073c74fe73c327ef5f 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponent/Context.php @@ -206,25 +206,8 @@ class Context implements ContextInterface */ public function getDataSourceData(UiComponentInterface $component) { - $dataSource = []; - $id = $this->getRequestParam($this->getDataProvider()->getRequestFieldName()); - if ($id) { // case form - $this->getDataProvider()->addFilter($this->getDataProvider()->getPrimaryFieldName(), $id); - $data = $this->getDataProvider()->getData(); - if (isset($data[$id])) { - $dataSource = [ - 'data' => $data[$id] - ]; - } - } else { // case listing - $dataSource = [ - 'data' => $this->getDataProvider()->getData(), - 'totalCount' => $this->getDataProvider()->count() - ]; - } - + $dataSource = $component->getDataSourceData(); $this->prepareDataSource($dataSource, $component); - $dataProviderConfig = $this->getDataProvider()->getConfigData(); return [ $this->getDataProvider()->getName() => [ diff --git a/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php b/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php index 0735eff2a4c4dd6590b6ef998d426a4b43bc499e..ac3ad58af7677390be42e5a4dd0b5e615ae1fe72 100644 --- a/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php +++ b/lib/internal/Magento/Framework/View/Element/UiComponentInterface.php @@ -116,4 +116,11 @@ interface UiComponentInterface extends BlockInterface * @return void */ public function prepareDataSource(array & $dataSource); + + /** + * Get Data Source data + * + * @return array + */ + public function getDataSourceData(); } diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml.php similarity index 80% rename from app/code/Magento/Ui/TemplateEngine/Xhtml.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml.php index e4a7765e90f79c0e2ad0223177707d0ed528c18c..bf3a5da2a35197e99a34f97c34050526163a1d1e 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml.php @@ -3,16 +3,15 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine; +namespace Magento\Framework\View\TemplateEngine; -use Magento\Ui\TemplateEngine\Xhtml\Result; -use Magento\Ui\TemplateEngine\Xhtml\Template; -use Magento\Ui\TemplateEngine\Xhtml\Compiler; -use Magento\Ui\TemplateEngine\Xhtml\ResultFactory; use Magento\Framework\View\Element\BlockInterface; use Magento\Framework\View\TemplateEngineInterface; -use Magento\Ui\TemplateEngine\Xhtml\CompilerFactory; -use Magento\Ui\TemplateEngine\Xhtml\TemplateFactory; +use Magento\Framework\View\TemplateEngine\Xhtml\Template; +use Magento\Framework\View\TemplateEngine\Xhtml\ResultFactory; +use Magento\Framework\View\TemplateEngine\Xhtml\ResultInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\CompilerFactory; +use Magento\Framework\View\TemplateEngine\Xhtml\TemplateFactory; use Magento\Framework\View\Element\UiComponent\Config\Provider\Template as TemplateProvider; /** @@ -20,8 +19,6 @@ use Magento\Framework\View\Element\UiComponent\Config\Provider\Template as Templ */ class Xhtml implements TemplateEngineInterface { - const INSTANCE_NAME = 'Magento\Ui\Content\Template\Type\Xhtml\Template'; - /** * @var TemplateProvider */ @@ -68,10 +65,11 @@ class Xhtml implements TemplateEngineInterface * Render the named template in the context of a particular block and with * the data provided in $vars. * - * @param \Magento\Framework\View\Element\BlockInterface $block + * @param BlockInterface $block * @param string $templateFile * @param array $dictionary - * @return Result + * @return ResultInterface + * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function render(BlockInterface $block, $templateFile, array $dictionary = []) @@ -79,7 +77,6 @@ class Xhtml implements TemplateEngineInterface /** @var Template $template */ $template = $this->templateFactory->create(['content' => $this->templateProvider->getTemplate($templateFile)]); - /** @var Result $result */ $result = $this->resultFactory->create( [ 'template' => $template, diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler.php similarity index 75% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler.php index 68830d2a6574ffa1cd1bc82579cff98f56ea7a90..609c924dc3f5b454e3c4b56fcddc8b2f6ad1a793 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler.php @@ -3,23 +3,20 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml; +namespace Magento\Framework\View\TemplateEngine\Xhtml; use Magento\Framework\Object; -use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Ui\TemplateEngine\Xhtml\Compiler\TextInterface; -use Magento\Ui\TemplateEngine\Xhtml\Compiler\CdataInterface; -use Magento\Ui\TemplateEngine\Xhtml\Compiler\CommentInterface; -use Magento\Ui\TemplateEngine\Xhtml\Compiler\AttributeInterface; -use Magento\Ui\TemplateEngine\Xhtml\Compiler\Element\ElementInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\TextInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\CdataInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\CommentInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\AttributeInterface; +use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Element\ElementInterface; /** * Class Compiler */ -class Compiler +class Compiler implements CompilerInterface { - const PATTERN_TAG = '|@|'; - /** * @var TextInterface */ @@ -79,50 +76,51 @@ class Compiler * The compilation of the template and filling in the data * * @param \DOMNode $node - * @param UiComponentInterface $component + * @param Object $processedObject * @param Object $context * @return void */ - public function compile(\DOMNode $node, UiComponentInterface $component, Object $context) + public function compile(\DOMNode $node, Object $processedObject, Object $context) { switch ($node->nodeType) { case XML_TEXT_NODE: - $this->compilerText->compile($node, $component); + $this->compilerText->compile($node, $processedObject); break; case XML_CDATA_SECTION_NODE: - $this->compilerCdata->compile($node, $component); + $this->compilerCdata->compile($node, $processedObject); break; case XML_COMMENT_NODE: - $this->compilerComment->compile($node, $component); + $this->compilerComment->compile($node, $processedObject); break; default: /** @var \DomElement $node */ if ($node->hasAttributes()) { foreach ($node->attributes as $attribute) { - $this->compilerAttribute->compile($attribute, $component); + $this->compilerAttribute->compile($attribute, $processedObject); } } $compiler = $this->getElementCompiler($node->nodeName); if (null !== $compiler) { - $compiler->compile($this, $node, $component, $context); + $compiler->compile($this, $node, $processedObject, $context); } else if ($node->hasChildNodes()) { foreach ($this->getChildNodes($node) as $child) { - $this->compile($child, $component, $context); + $this->compile($child, $processedObject, $context); } } } } /** - * Run postprocessing contents template + * Run postprocessing contents * * @param string $content * @return string */ public function postprocessing($content) { + $patternTag = preg_quote(CompilerInterface::PATTERN_TAG); return preg_replace_callback( - '#' . preg_quote(static::PATTERN_TAG) . '(.+?)' . preg_quote(static::PATTERN_TAG) . '#', + '#' . $patternTag . '(.+?)' . $patternTag . '#', function ($match) { return isset($this->data[$match[1]]) ? $this->data[$match[1]] : ''; }, diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Attribute.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Attribute.php similarity index 64% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Attribute.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Attribute.php index f1ab640960831615310268cc4d99e6dc39fcd415..2e19d778dff790ee7c5def4e8b519a581bd346c4 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Attribute.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Attribute.php @@ -3,10 +3,10 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler; -use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\DirectiveInterface; +use Magento\Framework\Object; +use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Directive\DirectiveInterface; /** * Class Attribute @@ -32,16 +32,16 @@ class Attribute implements AttributeInterface * Compiles the Element node * * @param \DOMAttr $node - * @param UiComponentInterface $component + * @param Object $processedObject * @return void */ - public function compile(\DOMAttr $node, UiComponentInterface $component) + public function compile(\DOMAttr $node, Object $processedObject) { foreach ($this->directivePool as $directive) { $node->value = preg_replace_callback( $directive->getPattern(), - function ($match) use ($directive, $component) { - return $directive->execute($match, $component); + function ($match) use ($directive, $processedObject) { + return $directive->execute($match, $processedObject); }, $node->value ); diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/AttributeInterface.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/AttributeInterface.php similarity index 55% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/AttributeInterface.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/AttributeInterface.php index 274d43bcde56dd2f793d0b5a2fd01abae047c9f6..e21ddea348c6d9cbf4e8a8e42a103c8c1a67f178 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/AttributeInterface.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/AttributeInterface.php @@ -3,9 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler; -use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Object; /** * Interface AttributeInterface @@ -16,8 +16,8 @@ interface AttributeInterface * Compiles the Element node * * @param \DOMAttr $node - * @param UiComponentInterface $component + * @param Object $processedObject * @return void */ - public function compile(\DOMAttr $node, UiComponentInterface $component); + public function compile(\DOMAttr $node, Object $processedObject); } diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Cdata.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Cdata.php similarity index 56% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Cdata.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Cdata.php index 785a86eb5c2b36a46691383b702b7dd1c39a556b..4d965b1d50a5eaddc2f01b4d3fe9b2f0fae4cd38 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Cdata.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Cdata.php @@ -3,9 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler; -use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Object; /** * Class Cdata @@ -16,10 +16,10 @@ class Cdata implements CdataInterface * Compiles the CData Section node * * @param \DOMCdataSection $node - * @param UiComponentInterface $component + * @param Object $processedObject * @return void */ - public function compile(\DOMCdataSection $node, UiComponentInterface $component) + public function compile(\DOMCdataSection $node, Object $processedObject) { // } diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CdataInterface.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/CdataInterface.php similarity index 54% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CdataInterface.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/CdataInterface.php index d37d9460fc2f8a49cbef9689a53776918e3fa2d4..621303fecb56564419106b1d741fcd251ec55ba6 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CdataInterface.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/CdataInterface.php @@ -3,9 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler; -use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Object; /** * Interface CdataInterface @@ -16,8 +16,8 @@ interface CdataInterface * Compiles the CData Section node * * @param \DOMCdataSection $node - * @param UiComponentInterface $component + * @param Object $processedObject * @return void */ - public function compile(\DOMCdataSection $node, UiComponentInterface $component); + public function compile(\DOMCdataSection $node, Object $processedObject); } diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Comment.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Comment.php similarity index 56% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Comment.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Comment.php index 2ad634611ab74b0d762947a1ac54b8695bd37768..1f14b7315c072f4805e4790764319b388ad814eb 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Comment.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Comment.php @@ -3,9 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler; -use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Object; /** * Class Comment @@ -16,10 +16,10 @@ class Comment implements CommentInterface * Compiles the Comment node * * @param \DOMComment $node - * @param UiComponentInterface $component + * @param Object $processedObject * @return void */ - public function compile(\DOMComment $node, UiComponentInterface $component) + public function compile(\DOMComment $node, Object $processedObject) { // } diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CommentInterface.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/CommentInterface.php similarity index 54% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CommentInterface.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/CommentInterface.php index 19a2d6569c977a056e22cd69322475616f736acb..464e5fb062f96ad1ff331553dc1f1ef6d3e9eea7 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/CommentInterface.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/CommentInterface.php @@ -3,9 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler; -use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Object; /** * Interface CommentInterface @@ -16,8 +16,8 @@ interface CommentInterface * Compiles the Comment node * * @param \DOMComment $node - * @param UiComponentInterface $component + * @param Object $processedObject * @return void */ - public function compile(\DOMComment $node, UiComponentInterface $component); + public function compile(\DOMComment $node, Object $processedObject); } diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/CallableMethod.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Directive/CallableMethod.php similarity index 78% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/CallableMethod.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Directive/CallableMethod.php index ef14461f3610f8b3fc914a646b58ba62a73f2122..105ffafd7f541014d7844a6b53d4d4aade023c4f 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/CallableMethod.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Directive/CallableMethod.php @@ -3,9 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive; +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Directive; -use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Object; /** * Class CallableMethod @@ -16,12 +16,12 @@ class CallableMethod implements DirectiveInterface * Execute directive * * @param array $directive - * @param UiComponentInterface $component + * @param Object $processedObject * @return string */ - public function execute($directive, UiComponentInterface $component) + public function execute($directive, Object $processedObject) { - $object = $component; + $object = $processedObject; $result = ''; foreach (explode('.', $directive[1]) as $method) { $methodName = substr($method, 0, strpos($method, '(')); diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php similarity index 62% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php index b367a6b84f7b3edb47869b967a88e66dd84a6cf1..6687801ba0f6817e9b45dc38199fd7056db3b9ef 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Directive/DirectiveInterface.php @@ -3,9 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive; +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Directive; -use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Object; /** * Interface DirectiveInterface @@ -16,10 +16,10 @@ interface DirectiveInterface * Execute directive * * @param array $directive - * @param UiComponentInterface $component + * @param Object $processedObject * @return string */ - public function execute($directive, UiComponentInterface $component); + public function execute($directive, Object $processedObject); /** * Get regexp search pattern diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/Variable.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Directive/Variable.php similarity index 61% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/Variable.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Directive/Variable.php index b903855c821912ed3ec9d19eb1feb575c0e8c017..ef3a8bfa5df6d0588a63b4b65ea343b927b9d9d3 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Directive/Variable.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Directive/Variable.php @@ -3,9 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive; +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Directive; -use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Object; /** * Class Variable @@ -16,12 +16,12 @@ class Variable implements DirectiveInterface * Execute directive * * @param array $directive - * @param UiComponentInterface $component + * @param Object $processedObject * @return string */ - public function execute($directive, UiComponentInterface $component) + public function execute($directive, Object $processedObject) { - return $component->getData($directive[1]); + return $processedObject->getData($directive[1]); } /** diff --git a/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..eec42c573ff077f3f63dd7bfbe4cf1314b56ed27 --- /dev/null +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Element/ElementInterface.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Element; + +use Magento\Framework\Object; +use Magento\Framework\View\TemplateEngine\Xhtml\CompilerInterface; + +/** + * Interface ElementInterface + */ +interface ElementInterface +{ + /** + * Compiles the Element node + * + * @param CompilerInterface $compiler + * @param \DOMElement $node + * @param Object $processedObject + * @param Object $context + * @return void + */ + public function compile(CompilerInterface $compiler, \DOMElement $node, Object $processedObject, Object $context); +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Text.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Text.php similarity index 68% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Text.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Text.php index 5bdfe50622c2a5b13000b10e9848265fc46e847f..3d6b9750107155b1d6c1ad8b8998130d68b3c3be 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/Text.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/Text.php @@ -3,10 +3,10 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler; -use Magento\Framework\View\Element\UiComponentInterface; -use Magento\Ui\TemplateEngine\Xhtml\Compiler\Directive\DirectiveInterface; +use Magento\Framework\Object; +use Magento\Framework\View\TemplateEngine\Xhtml\Compiler\Directive\DirectiveInterface; /** * Class Text @@ -32,17 +32,17 @@ class Text implements TextInterface * Compiles the Element node * * @param \DOMText $node - * @param UiComponentInterface $component + * @param Object $processedObject * @return void */ - public function compile(\DOMText $node, UiComponentInterface $component) + public function compile(\DOMText $node, Object $processedObject) { $result = ''; foreach ($this->directivePool as $directive) { $result = preg_replace_callback( $directive->getPattern(), - function ($match) use ($directive, $component) { - return $directive->execute($match, $component); + function ($match) use ($directive, $processedObject) { + return $directive->execute($match, $processedObject); }, $node->textContent ); diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/TextInterface.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/TextInterface.php similarity index 54% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/TextInterface.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/TextInterface.php index 1f1ffc41586164cbf0da8b960007b0c27c998476..19170aa95bdf0096c42e6c06215e199d631f9781 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Compiler/TextInterface.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Compiler/TextInterface.php @@ -3,9 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml\Compiler; +namespace Magento\Framework\View\TemplateEngine\Xhtml\Compiler; -use Magento\Framework\View\Element\UiComponentInterface; +use Magento\Framework\Object; /** * Interface TextInterface @@ -16,8 +16,8 @@ interface TextInterface * Compiles the Element node * * @param \DOMText $node - * @param UiComponentInterface $component + * @param Object $processedObject * @return void */ - public function compile(\DOMText $node, UiComponentInterface $component); + public function compile(\DOMText $node, Object $processedObject); } diff --git a/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/CompilerFactory.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/CompilerFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..f6082689d4798fe29fa1126e485961529486bbe1 --- /dev/null +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/CompilerFactory.php @@ -0,0 +1,60 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\TemplateEngine\Xhtml; + +use Magento\Framework\Phrase; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Exception\LocalizedException; + +/** + * Class CompilerFactory + */ +class CompilerFactory +{ + /** + * Object manager + * + * @var ObjectManagerInterface + */ + protected $objectManager; + + /** + * Instance name + * + * @var string + */ + protected $instanceName; + + /** + * Constructor + * + * @param ObjectManagerInterface $objectManager + * @param string $instanceName + */ + public function __construct(ObjectManagerInterface $objectManager, $instanceName) + { + $this->objectManager = $objectManager; + $this->instanceName = $instanceName; + } + + /** + * Create result + * + * @param array $arguments + * @return CompilerInterface + * @throws LocalizedException + */ + public function create(array $arguments = []) + { + $object = $this->objectManager->create($this->instanceName, $arguments); + + if (!($object instanceof CompilerInterface)) { + throw new LocalizedException(new Phrase('This class must implement the "CompilerInterface"')); + } + + return $object; + } +} diff --git a/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/CompilerInterface.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/CompilerInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..6bbaead257446326c0d55fb263a43a15ba5498d9 --- /dev/null +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/CompilerInterface.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\TemplateEngine\Xhtml; + +use Magento\Framework\Object; + +/** + * Interface CompilerInterface + */ +interface CompilerInterface +{ + const PATTERN_TAG = '|@|'; + + /** + * The compilation of the template and filling in the data + * + * @param \DOMNode $node + * @param Object $dataObject + * @param Object $context + * @return void + */ + public function compile(\DOMNode $node, Object $dataObject, Object $context); + + /** + * Run postprocessing contents + * + * @param string $content + * @return string + */ + public function postprocessing($content); + + /** + * Set postprocessing data + * + * @param string $key + * @param string $content + * @return void + */ + public function setPostprocessingData($key, $content); +} diff --git a/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/ResultFactory.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/ResultFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..35c510c9f60972fbce230c515235a5de88ee9ba6 --- /dev/null +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/ResultFactory.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\TemplateEngine\Xhtml; + +use Magento\Framework\Phrase; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\ObjectManagerInterface; + +/** + * Class ResultFactory + */ +class ResultFactory +{ + /** + * Object manager + * + * @var ObjectManagerInterface + */ + protected $objectManager; + + /** + * Instance name + * + * @var string + */ + protected $instanceName; + + /** + * Constructor + * + * @param ObjectManagerInterface $objectManager + * @param string $instanceName + */ + public function __construct( + ObjectManagerInterface $objectManager, + $instanceName = 'Magento\Framework\View\TemplateEngine\Xhtml\ResultInterface' + ) { + $this->objectManager = $objectManager; + $this->instanceName = $instanceName; + } + + /** + * Create result + * + * @param array $arguments + * @return ResultInterface + * @throws LocalizedException + */ + public function create(array $arguments = []) + { + $object = $this->objectManager->create($this->instanceName, $arguments); + + if (!($object instanceof ResultInterface)) { + throw new LocalizedException(new Phrase('This class must implement the "ResultInterface"')); + } + + return $object; + } +} diff --git a/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/ResultInterface.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/ResultInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..f9548561f7ae155a6cdfd72f7092ed9879ff72d6 --- /dev/null +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/ResultInterface.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\TemplateEngine\Xhtml; + +/** + * Interface ResultInterface + */ +interface ResultInterface +{ + /** + * Get result document root element \DOMElement + * + * @return \DOMElement + */ + public function getDocumentElement(); + + /** + * Append layout configuration + * + * @return void + */ + public function appendLayoutConfiguration(); + + /** + * Returns the string representation + * + * @return string + */ + public function __toString(); +} diff --git a/app/code/Magento/Ui/TemplateEngine/Xhtml/Template.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Template.php similarity index 96% rename from app/code/Magento/Ui/TemplateEngine/Xhtml/Template.php rename to lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Template.php index 52cc35f0cf461c943598ba3206fdebe6ea26b824..2ce37749a3d945eb59f9e6fa51f2f6d055e246ed 100644 --- a/app/code/Magento/Ui/TemplateEngine/Xhtml/Template.php +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/Template.php @@ -3,7 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Ui\TemplateEngine\Xhtml; +namespace Magento\Framework\View\TemplateEngine\Xhtml; /** * Class Template diff --git a/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/TemplateFactory.php b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/TemplateFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..615ff39d2825bd09652424238be761d87620764b --- /dev/null +++ b/lib/internal/Magento/Framework/View/TemplateEngine/Xhtml/TemplateFactory.php @@ -0,0 +1,62 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Framework\View\TemplateEngine\Xhtml; + +use Magento\Framework\Phrase; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Exception\LocalizedException; + +/** + * Class TemplateFactory + */ +class TemplateFactory +{ + /** + * Object manager + * + * @var ObjectManagerInterface + */ + protected $objectManager; + + /** + * Instance name + * + * @var string + */ + protected $instanceName; + + /** + * Constructor + * + * @param ObjectManagerInterface $objectManager + * @param string $instanceName + */ + public function __construct( + ObjectManagerInterface $objectManager, + $instanceName = 'Magento\Framework\View\TemplateEngine\Xhtml\Template' + ) { + $this->objectManager = $objectManager; + $this->instanceName = $instanceName; + } + + /** + * Create result + * + * @param array $arguments + * @return Template + * @throws LocalizedException + */ + public function create(array $arguments = []) + { + $object = $this->objectManager->create($this->instanceName, $arguments); + + if (!($object instanceof Template)) { + throw new LocalizedException(new Phrase('This class must inherit from a class "Template"')); + } + + return $object; + } +} diff --git a/lib/internal/Magento/Framework/composer.json b/lib/internal/Magento/Framework/composer.json index 95533010a155bfa87aaea0f02b561a458f62a72c..1307d01001635ca7553aabcd9dcd94884d01801c 100644 --- a/lib/internal/Magento/Framework/composer.json +++ b/lib/internal/Magento/Framework/composer.json @@ -2,7 +2,7 @@ "name": "magento/framework", "description": "N/A", "type": "magento2-library", - "version": "0.74.0-beta10", + "version": "0.74.0-beta13", "license": [ "OSL-3.0", "AFL-3.0" @@ -18,6 +18,7 @@ "ext-iconv": "*", "ext-gd": "*", "lib-libxml": "*", + "ext-xsl": "*", "magento/magento-composer-installer": "*" }, "suggest": { diff --git a/lib/web/css/docs/actions-toolbar.html b/lib/web/css/docs/actions-toolbar.html index 45405f0d0fd6684c02ea12f23405039700e11854..361cd94d46f6a49a05f405a0e3fed840c0c728c7 100644 --- a/lib/web/css/docs/actions-toolbar.html +++ b/lib/web/css/docs/actions-toolbar.html @@ -1,10 +1,10 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> - +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + <!DOCTYPE html><html><head><title>actions-toolbar | Magento UI Library </title><meta charset="utf-8"><style>*{-moz-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;border:0}body{padding:60px 0 40px;background-color:hsl(207,10%,90%);color:hsl(207,5%,30%)}.container{max-width:1300px;margin:0 auto;padding:0 20px}.section{position:relative;margin-bottom:20px}.docs{position:relative;z-index:2;width:68%;min-height:200px;background-color:hsl(207,0%,100%);background-clip:padding-box;border:1px solid hsla(207,5%,5%,.1);border-radius:5px;box-shadow:0 0 3px hsla(207,5%,5%,.1)}.code{position:absolute;top:5px;bottom:5px;right:0;z-index:1;width:33%;padding:10px 10px 10px 20px;border-radius:0 5px 5px 0;border:1px solid hsla(207,20%,10%,.1);background-color:hsla(207,20%,95%,.9);background-clip:padding-box;opacity:.5;-webkit-transition:opacity .4s;-moz-transition:opacity .4s;-o-transition:opacity .4s;transition:opacity .4s}.code:hover{opacity:1}.preview{background:hsl(207,0%,100%);border-top:1px solid hsl(207,30%,95%);position:relative;z-index:1}.preview-code+.preview{margin-top:0;border-top:0}.preview iframe{display:block;width:100%;height:100%;overflow:hidden}.preview-code{position:relative;z-index:2;display:block;width:100%;color:hsl(207,9%,37%);max-height:200px;padding:10px 20px;overflow-y:auto;background:hsl(207,30%,95%);border:1px solid hsl(207,30%,85%);border-left:0;border-right;box-shadow:inset 0 1px 2px hsla(207,30%,10%,.1);line-height:1.1!important;resize:none}.preview-code:focus{outline:0;background:hsl(207,30%,97%);box-shadow:inset 0 1px 2px hsla(207,30%,10%,.1),0 0 5px hsla(207,75%,75%,.9)}.preview-code:last-child{border-bottom:0;border-radius:0 0 5px 5px}.resizeable{padding:15px;overflow:auto;background:hsl(207,0%,100%);box-shadow:0 0 2px hsla(207,10%,20%,.2);resize:both}.preview-code,pre{white-space:pre-wrap;word-wrap:break-word;overflow-y:auto}.code pre{height:100%;margin-top:0}.bar{position:fixed;left:0;right:0;z-index:1010;min-height:40px;line-height:40px;background-image:-webkit-linear-gradient(hsla(207,10%,35%,.97),hsla(207,5%,25%,.92));background-image:-moz-linear-gradient(hsla(207,10%,35%,.97),hsla(207,5%,25%,.92));background-image:-o-linear-gradient(hsla(207,10%,35%,.97),hsla(207,5%,25%,.92));background-image:linear-gradient(hsla(207,10%,35%,.97),hsla(207,5%,25%,.92))}.bar.top{top:0;box-shadow:0 1px 2px hsla(207,5%,0%,.2)}.bar.bottom{bottom:0;box-shadow:0 -1px 2px hsla(207,5%,0%,.2)}.bar ul{margin:0!important}.bar li{display:block;list-style:none}.bar .icon path{fill:hsla(27,10%,75%,.75)}.docs .icon path{fill:hsla(207,10%,75%,.5)}.docs .permalink:hover .icon path{fill:hsl(207,10%,75%)}.bar button{color:hsla(27,10%,75%,.75)}.bar button:hover .icon path,.bar button.is-active .icon path{fill:hsl(27,10%,85%)}.bar button:hover,.bar button.is-active{color:hsl(27,10%,85%)}.bar .icon{vertical-align:middle;display:inline-block}.bar,.bar a,.bar a:visited{color:hsl(27,10%,85%);text-shadow:1px 1px 0 hsla(27,5%,0%,.5)}.bar a:hover,.bar a.is-active{color:hsl(27,10%,95%);text-shadow:1px 1px 0 hsla(27,5%,0%,1);text-decoration:none}.brand{float:left;margin-right:20px;font-weight:700;font-size:16px;text-decoration:none}.brand,a.brand,a.brand:visited{color:hsl(27,5%,5%);text-shadow:1px 1px 0 hsla(27,5%,100%,.2)}.brand:hover,a.brand:hover{color:hsl(27,5%,0%);text-shadow:1px 1px 0 hsla(27,5%,100%,.3);text-decoration:none}.menu{font-size:12px}.menu>li{float:left;position:relative}.menu a{display:block;margin-right:15px}.dropdown-toggle{position:relative;padding-right:15px}.dropdown-toggle:after{display:block;position:absolute;right:0;top:18px;content:'';border:4px solid;border-left-color:transparent;border-right-color:transparent;border-bottom-color:transparent}.nav-results,.dropdown{position:absolute;z-index:1020;top:32px;left:-16px;width:175px;max-height:500px;padding:10px 0;overflow-y:auto;word-wrap:break-word;font-size:11px;line-height:20px;background-color:hsla(207,10%,25%,.97);border:1px solid hsla(207,5%,70%,.3);border-radius:3px;box-shadow:0 0 3px hsla(207,5%,0%,.2)}.toc-list{width:200px}.nav-results{right:0;width:200px;left:auto;padding:5px 0}.nav-results-filename{display:block;font-size:10px;opacity:.75}.nav-results a{display:block;line-height:15px;padding:5px 10px}.nav-results li:not([hidden])~li a{border-top:1px solid hsla(27,10%,90%,.1)}.dropdown a{padding:0 15px}.dropdown li:hover{background-color:hsl(207,10%,22%)}.nav{float:right;position:relative}.nav input[type="search"]{padding:2px 4px;color:#fff;width:150px;border:1px solid hsla(207,5%,0%,.3);background:hsla(207,12%,40%,.9);box-shadow:inset 1px 1px 3px hsla(207,5%,0%,.05),1px 1px 0 hsla(207,5%,100%,.05);border-radius:10px;-webkit-appearance:textfield}.nav input[type="search"]:focus{outline:0;background:hsla(207,7%,45%,.9)}.settings{text-align:center}.bar button{display:inline-block;vertical-align:middle;padding:0 5px;margin:0 3px;background:transparent}.bar button:first-child{margin-left:0}.settings .auto{line-height:32px;font-size:11px;font-weight:700;letter-spacing:-1px;text-shadow:none;text-transform:uppercase}body{font-family:sans-serif;font-size:14px;line-height:1.618}.docs pre,p,ol,ul,dl,figure,blockquote,table{margin-left:20px;margin-right:20px}.preview,.docs pre,p,ol,ul,dl,figure,blockquote,table{margin-top:10px}ul ul,ol ol,ul ol,ol ul,blockquote p:last-child{margin-top:0}ul,ol{padding-left:1.5em}p:last-child,ol:last-child,ul:last-child,dl:last-child{margin-bottom:20px}hr,h1,h2,h3,h4,h5,h6{margin:1em 20px .5em}h1:first-of-type{margin-top:20px}h1,h2,h3,h4,h5,h6{line-height:1.2;color:hsl(207,10%,50%)}h1 a,h1 a:hover,h1 a:visited{color:inherit;text-decoration:inherit}h1{font-size:3.052em;font-weight:400;color:hsl(207,10%,45%)}h2{font-size:1.953em}h3{font-size:1.536em}h1,h2,h3{letter-spacing:-.025em}h4{font-size:1.25em}h5{font-size:1em;text-transform:uppercase}h6{font-size:1em}.permalink{position:absolute;top:15px;right:15px}a{color:hsl(207,90%,50%);text-decoration:none}a:hover{color:hsl(207,95%,40%);text-decoration:underline}a:visited{color:hsl(207,100%,35%)}.preview-code,pre,code,var{font-style:normal;font-family:"Ubuntu Mono","Andale Mono","DejaVu Sans Mono","Monaco","Bitstream Vera Sans Mono","Consolas","Lucida Console",monospace;font-size:12px}.docs pre,code,var{padding:.1em 3px;background:hsla(207,5%,0%,.025);border:1px solid hsla(207,5%,0%,.05);border-radius:3px}.code pre{line-height:1.1!important}pre code{padding:0;background:transparent;border:0}.cf:before,.cf:after{content:'';display:table}.cf:after{clear:both}[unselectable="on"]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}[hidden]{display:none!important}small{font-size:85%;opacity:.9}.docs .vars_list{width:100%}.docs .vars_list th,.docs .vars_list td{width:33%}.docs pre th{text-align:left}.docs pre table{border-collapse:collapse;margin:0}.docs th,.docs td{border:0;padding:9px 10px 9px 0;vertical-align:top}.docs tr th:last-child,.docs tr td:last-child{padding-right:0}.docs pre th{font-weight:400}.docs pre th.vars_head{border-bottom:1px solid #e5e5e5;color:#707070;white-space:nowrap}.docs pre th.vars_section{border-bottom:1px solid #e5e5e5;color:#333;font-size:18px;padding-top:30px}.vars_value{color:#338bb8}.docs li p{margin:0 0 20px}.dropdown a{text-transform:capitalize}#default-button #default-button-big+.preview+.preview-code{display:block}#actions-toolbar-alignment .preview-code,#reverse-primary-and-secondary-blocks .preview-code,#actions-toolbar-indents-customizations .preview-code,#actionstoolbarclearfloats-mixin .preview-code,#responsive-actions-toolbar .preview-code,#button-with-gradient-background .preview-code,#primary-button .preview-code,#button-as-an-icon .preview-code,#button-with-an-icon-on-the-left-or-right-side-of-the-text .preview-code,#button-with-fixed-width .preview-code,#button-as-a-link .preview-code,#link-as-a-button .preview-code,#buttonstyled-breadcrumbs-with-gradient-background-border-and-no-separating-symbol .preview-code,#breadcrumbs-with-solid-background .preview-code,#pagination-without-label-with-solid-background .preview-code,#pagination-with-label-and-text-previousnext-links .preview-code,#pagination-with-label-and-gradient-background-on-links .preview-code,#fixed-height-popup .preview-code,#fixed-content-height-popup .preview-code,#margins-for-header-content-and-footer-block-in-popup .preview-code,#popup-titles-with-styled-as-theme-headings .preview-code,#popup-action-toolbar .preview-code,#popup-close-button-without-an-icon .preview-code,#modify-icon-of-popup-close-button .preview-code,#modify-overlay-styles .preview-code,#rating-summary-multiple-ratings .preview-code,#rating-summary-hide-label .preview-code,#rating-summary-icons-symbol .preview-code,#rating-summary-icons-color .preview-code,#rating-summary-set-number-of-icons .preview-code,#rating-summary .preview-code,#rating-with-vote-icon-symbol .preview-code,#rating-with-vote-setup-icons-colors .preview-code,#rating-with-vote-setup-number-of-icons .preview-code,#tabs-with-content-top-border .preview-code,#accordion-mixin-variables .preview-code,#tabs-base .preview-code,#accordion-base .preview-code,#warning-message .preview-code,#error-message .preview-code,#success-message .preview-code,#notice-message .preview-code,#message-with-inner-icon .preview-code,#message-with-lateral-icon .preview-code,#custom-message-style .preview-code,#modify-dropdown-list-styles .preview-code,#dropdown-with-icon-customization .preview-code,#split-button-button-styling .preview-code,#split-button-icon-customization .preview-code,#split-button-dropdown-list-customization .preview-code,#table-cells-resize .preview-code,#table-caption .preview-code,#table-typography .preview-code,#table-background-customization .preview-code,#table-borders-customization .preview-code,#table-without-borders .preview-code,#table-with-horizontal-borders .preview-code,#table-with-vertical-borders .preview-code,#striped-table .preview-code,#responsive-table-technics-1 .preview-code,#responsive-table-technics-2 .preview-code,#fontsize-mixin .preview-code,#word-breaking-mixin .preview-code,#word-breaking-mixin .preview-code,#text-overflow-mixin .preview-code,#text-hide .preview-code,#hyphens .preview-code,#font-style-and-color .preview-code,#reset-list-styles .preview-code,#inlineblock-list-item-styling .preview-code,#link-styling-mixin .preview-code,#heading-styling-mixin .preview-code,#icon-with-image-or-sprite .preview-code,#change-the-size-of-font-icon .preview-code,#sprite-and-font-icons-for-blank-theme .preview-code,#icon-position-for-an-icon-with-image-or-sprite .preview-code{display:none}article[id$="-variables"] .docs,#resets .docs,#ratings .docs,#tabs-and-accordions .docs,#messages .docs,#dropdown-and-split-buttons-mixins .docs,#font-face-mixin .docs,#layout .docs,#forms-mixins .docs,#including-magento-ui-library-to-your-theme .docs,#global-forms-elements-customization .docs,#mobile-off-canvas-navigation .docs,#desktop-navigation .docs,#layout-width .docs{width:100%}article[id$="-variables"] .code{display:none}article[id$="-variables"] .docs pre{background:#fff;border:0;margin-top:0}</style><script type="text/preview">(function(){"use strict";var a=function(a){return Array.prototype.slice.call(a)},b=document.getElementsByTagName("body")[0],c=["link","visited","hover","active","focus","target","enabled","disabled","checked"],d=new RegExp(":(("+c.join(")|(")+"))","gi"),e=a(document.styleSheets).map(function(b){return a(b.cssRules).filter(function(a){return a.selectorText&&a.selectorText.match(d)}).map(function(a){return a.cssText.replace(d,".\\3A $1")}).join("")}).join("");if(e.length){var f=document.createElement("style");f.innerText=e;var g=document.getElementsByTagName("style")[0];g.parentNode.insertBefore(f,g)}var h=function(){var a=window.getComputedStyle(b,null);return function(){if(b.childElementCount===0)return b.offsetHeight;var c=b.getElementsByTagName("*"),d=[];for(var e=0,f=c.length;e<f;e++)d.push(c[e].offsetTop+c[e].offsetHeight+parseInt(window.getComputedStyle(c[e],null).getPropertyValue("margin-bottom")));var g=Math.max.apply(Math,d);return g+=parseInt(a.getPropertyValue("padding-bottom"),10),Math.max(g,b.offsetHeight)}}(),i={getHeight:function(){window.parent.postMessage({height:h()},"*")}};window.addEventListener("message",function(a){if(a.data==null)return;typeof a.data=="string"&&i[a.data]()},!1)})()</script><style type="text/preview">.actions-toolbar:before,.actions-toolbar:after{content:"";display:table}.actions-toolbar:after{clear:both}.actions-toolbar .primary{float:left}.actions-toolbar .secondary{float:right}.actions-toolbar .primary,.actions-toolbar .secondary{display:inline-block}.actions-toolbar .primary a.action,.actions-toolbar .secondary a.action{display:inline-block}.actions-toolbar .primary .action{margin:0 5px 0 0}.actions-toolbar .secondary a.action{margin-top:6px}.example-actions-toolbar-1:before,.example-actions-toolbar-1:after{content:"";display:table}.example-actions-toolbar-1:after{clear:both}.example-actions-toolbar-1 .primary{float:left}.example-actions-toolbar-1 .secondary{float:right}.example-actions-toolbar-1 .primary,.example-actions-toolbar-1 .secondary{display:inline-block}.example-actions-toolbar-1 .primary a.action,.example-actions-toolbar-1 .secondary a.action{display:inline-block}.example-actions-toolbar-1 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-1 .secondary a.action{margin-top:6px}.example-actions-toolbar-1:before,.example-actions-toolbar-1:after{content:"";display:table}.example-actions-toolbar-1:after{clear:both}.example-actions-toolbar-1 .primary{float:left}.example-actions-toolbar-1 .secondary{float:right}.example-actions-toolbar-1 .primary,.example-actions-toolbar-1 .secondary{display:inline-block}.example-actions-toolbar-1 .primary a.action,.example-actions-toolbar-1 .secondary a.action{display:inline-block}.example-actions-toolbar-1 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-1 .secondary a.action{margin-top:6px}.example-actions-toolbar-2:before,.example-actions-toolbar-2:after{content:"";display:table}.example-actions-toolbar-2:after{clear:both}.example-actions-toolbar-2 .primary{float:left}.example-actions-toolbar-2 .secondary{float:right}.example-actions-toolbar-2 .primary,.example-actions-toolbar-2 .secondary{display:inline-block}.example-actions-toolbar-2 .primary a.action,.example-actions-toolbar-2 .secondary a.action{display:inline-block}.example-actions-toolbar-2 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-2 .secondary a.action{margin-top:6px}.example-actions-toolbar-3{text-align:left}.example-actions-toolbar-3:before,.example-actions-toolbar-3:after{content:"";display:table}.example-actions-toolbar-3:after{clear:both}.example-actions-toolbar-3 .primary{float:left}.example-actions-toolbar-3 .primary,.example-actions-toolbar-3 .secondary{display:inline-block}.example-actions-toolbar-3 .primary a.action,.example-actions-toolbar-3 .secondary a.action{display:inline-block}.example-actions-toolbar-3 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-3 .secondary a.action{margin-top:6px}.example-actions-toolbar-4{text-align:right}.example-actions-toolbar-4:before,.example-actions-toolbar-4:after{content:"";display:table}.example-actions-toolbar-4:after{clear:both}.example-actions-toolbar-4 .secondary{float:right}.example-actions-toolbar-4 .primary,.example-actions-toolbar-4 .secondary{display:inline-block}.example-actions-toolbar-4 .primary a.action,.example-actions-toolbar-4 .secondary a.action{display:inline-block}.example-actions-toolbar-4 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-4 .secondary a.action{margin-top:6px}.example-actions-toolbar-5{text-align:center}.example-actions-toolbar-5:before,.example-actions-toolbar-5:after{content:"";display:table}.example-actions-toolbar-5:after{clear:both}.example-actions-toolbar-5 .primary,.example-actions-toolbar-5 .secondary{vertical-align:top}.example-actions-toolbar-5 .primary,.example-actions-toolbar-5 .secondary{display:inline-block}.example-actions-toolbar-5 .primary a.action,.example-actions-toolbar-5 .secondary a.action{display:inline-block}.example-actions-toolbar-5 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-5 .secondary a.action{margin-top:6px}.example-actions-toolbar-6:before,.example-actions-toolbar-6:after{content:"";display:table}.example-actions-toolbar-6:after{clear:both}.example-actions-toolbar-6 .primary{float:right}.example-actions-toolbar-6 .secondary{float:left}.example-actions-toolbar-6 .primary,.example-actions-toolbar-6 .secondary{display:inline-block}.example-actions-toolbar-6 .primary a.action,.example-actions-toolbar-6 .secondary a.action{display:inline-block}.example-actions-toolbar-6 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-6 .secondary a.action{margin-top:6px}.example-actions-toolbar-7{text-align:left}.example-actions-toolbar-7:before,.example-actions-toolbar-7:after{content:"";display:table}.example-actions-toolbar-7:after{clear:both}.example-actions-toolbar-7 .secondary{float:left}.example-actions-toolbar-7 .primary,.example-actions-toolbar-7 .secondary{display:inline-block}.example-actions-toolbar-7 .primary a.action,.example-actions-toolbar-7 .secondary a.action{display:inline-block}.example-actions-toolbar-7 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-7 .secondary a.action{margin-top:6px}.example-actions-toolbar-8{text-align:right}.example-actions-toolbar-8:before,.example-actions-toolbar-8:after{content:"";display:table}.example-actions-toolbar-8:after{clear:both}.example-actions-toolbar-8 .primary{float:right}.example-actions-toolbar-8 .primary,.example-actions-toolbar-8 .secondary{display:inline-block}.example-actions-toolbar-8 .primary a.action,.example-actions-toolbar-8 .secondary a.action{display:inline-block}.example-actions-toolbar-8 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-8 .secondary a.action{margin-top:6px}.example-actions-toolbar-9{margin:10px;padding:10px}.example-actions-toolbar-9:before,.example-actions-toolbar-9:after{content:"";display:table}.example-actions-toolbar-9:after{clear:both}.example-actions-toolbar-9 .primary{float:left}.example-actions-toolbar-9 .secondary{float:right}.example-actions-toolbar-9 .primary,.example-actions-toolbar-9 .secondary{display:inline-block}.example-actions-toolbar-9 .primary a.action,.example-actions-toolbar-9 .secondary a.action{display:inline-block}.example-actions-toolbar-9 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-9 .secondary a.action{margin-top:6px}.example-actions-toolbar-10{text-align:left}.example-actions-toolbar-10:before,.example-actions-toolbar-10:after{content:"";display:table}.example-actions-toolbar-10:after{clear:both}.example-actions-toolbar-10 .primary{float:left}.example-actions-toolbar-10 .primary,.example-actions-toolbar-10 .secondary{display:inline-block}.example-actions-toolbar-10 .primary a.action,.example-actions-toolbar-10 .secondary a.action{display:inline-block}.example-actions-toolbar-10 .primary .action{margin:0 50px 0 0}.example-actions-toolbar-10 .secondary a.action{margin-top:6px}.example-actions-toolbar-11{text-align:left}.example-actions-toolbar-11:before,.example-actions-toolbar-11:after{content:"";display:table}.example-actions-toolbar-11:after{clear:both}.example-actions-toolbar-11 .primary{float:left}.example-actions-toolbar-11 .primary,.example-actions-toolbar-11 .secondary{display:inline-block}.example-actions-toolbar-11 .primary a.action,.example-actions-toolbar-11 .secondary a.action{display:inline-block}.example-actions-toolbar-11 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-11 .secondary .action{margin:0 50px 0 0}.example-actions-toolbar-11 .secondary a.action{margin-top:6px}.example-actions-toolbar-12:before,.example-actions-toolbar-12:after{content:"";display:table}.example-actions-toolbar-12:after{clear:both}.example-actions-toolbar-12 .primary{float:left}.example-actions-toolbar-12 .secondary{float:right}.example-actions-toolbar-12 .primary,.example-actions-toolbar-12 .secondary{display:inline-block}.example-actions-toolbar-12 .primary a.action,.example-actions-toolbar-12 .secondary a.action{display:inline-block}.example-actions-toolbar-12 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-12 .secondary a.action{margin-top:6px}.example-actions-toolbar-12:before,.example-actions-toolbar-12:after{content:"";display:table}.example-actions-toolbar-12:after{clear:both}.example-actions-toolbar-12 .primary{float:left}.example-actions-toolbar-12 .secondary{float:right}.example-actions-toolbar-12 .primary,.example-actions-toolbar-12 .secondary{display:inline-block}.example-actions-toolbar-12 .primary a.action,.example-actions-toolbar-12 .secondary a.action{display:inline-block}.example-actions-toolbar-12 .primary .action{margin:0 5px 0 0}.example-actions-toolbar-12 .secondary a.action{margin-top:6px}@media only screen and (max-width: 768px){.example-actions-toolbar-12 .primary,.example-actions-toolbar-12 .secondary{ display:block;float:none}}.example-breadcrumbs-1{margin:0 0 20px}.example-breadcrumbs-1 .items{font-size:1.2rem;color:#a3a3a3;margin:0;padding:0;list-style:none none}.example-breadcrumbs-1 .items>li{display:inline-block;vertical-align:top}.example-breadcrumbs-1 .item{margin:0}.example-breadcrumbs-1 a{color:#333;text-decoration:none}.example-breadcrumbs-1 a:visited{color:#333;text-decoration:none}.example-breadcrumbs-1 a:hover{color:#333;text-decoration:underline}.example-breadcrumbs-1 a:active{color:#333;text-decoration:none}.example-breadcrumbs-1 strong{font-weight:400}.example-breadcrumbs-1 .item:not(:last-child){display:inline-block;text-decoration:none}.example-breadcrumbs-1 .item:not(:last-child):after{font-family:'icons-blank-theme';content:'\e608';font-size:24px;line-height:18px;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-breadcrumbs-2{margin:0 0 20px}.example-breadcrumbs-2 .items{font-size:1.2rem;color:#1979c3;margin:0;padding:0;list-style:none none}.example-breadcrumbs-2 .items>li{display:inline-block;vertical-align:top}.example-breadcrumbs-2 .item{margin:0}.example-breadcrumbs-2 a{background-color:#ccc;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top, #f4f4f4 0, #ccc 100%);background-image:linear-gradient(to bottom, #f4f4f4 0, #ccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f4f4f4', endColorstr='#cccccc', GradientType=0);border:1px solid #ccc;display:inline-block;padding:3px 5px;color:#333;text-decoration:none}.example-breadcrumbs-2 a:visited{background-color:false;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top,false 0,false 100%);background-image:linear-gradient(to bottom,false 0,false 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='false', endColorstr='false', GradientType=0);color:#333;text-decoration:none}.example-breadcrumbs-2 a:hover{background-color:#f4f4f4;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top, #ccc 0, #f4f4f4 100%);background-image:linear-gradient(to bottom, #ccc 0, #f4f4f4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#f4f4f4', GradientType=0);color:#333;text-decoration:none}.example-breadcrumbs-2 a:active{background-color:false;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top,false 0,false 100%);background-image:linear-gradient(to bottom,false 0,false 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='false', endColorstr='false', GradientType=0);color:#333;text-decoration:none}.example-breadcrumbs-2 strong{background-color:#ff5501;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top, #f7b32e 0, #ff5501 100%);background-image:linear-gradient(to bottom, #f7b32e 0, #ff5501 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7b32e', endColorstr='#ff5501', GradientType=0);border:1px solid #d04b0a;display:inline-block;padding:3px 5px;font-weight:400}.example-breadcrumbs-2 .item:not(:last-child){display:inline-block;text-decoration:none}.example-breadcrumbs-2 .item:not(:last-child):after{font-family:'icons-blank-theme';content:'\e608';font-size:24px;line-height:18px;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-breadcrumbs-3{margin:0 0 20px}.example-breadcrumbs-3 .items{font-size:1.2rem;color:#333;margin:0;padding:0;list-style:none none}.example-breadcrumbs-3 .items>li{display:inline-block;vertical-align:top}.example-breadcrumbs-3 .item{margin:0}.example-breadcrumbs-3 a{background:#f4f4f4;display:inline-block;padding:3px 5px;color:#333;text-decoration:none}.example-breadcrumbs-3 a:visited{color:#333;text-decoration:none}.example-breadcrumbs-3 a:hover{background:#ccc;color:#333;text-decoration:none}.example-breadcrumbs-3 a:active{color:#333;text-decoration:none}.example-breadcrumbs-3 strong{background:#e7e7e7;display:inline-block;padding:3px 5px;font-weight:400}.example-breadcrumbs-3 .item:not(:last-child){display:inline-block;text-decoration:none}.example-breadcrumbs-3 .item:not(:last-child):after{font-family:'icons-blank-theme';content:'\e608';font-size:24px;line-height:18px;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-breadcrumbs-3 .item a{position:relative;margin:0 11px 0 0}.example-breadcrumbs-3 .item a:after{border:12px solid transparent;height:0;width:0;border-left-color:#f4f4f4;content:"";position:absolute;display:block;top:0;right:-23px}.example-breadcrumbs-3 .item a:hover:after{border-color:transparent transparent transparent #ccc}button{background-image:none;background:#f2f2f2;padding:7px 15px;color:#333;border:1px solid #cdcdcd;cursor:pointer;display:inline-block;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;line-height:1.6rem;box-sizing:border-box;margin:3px;vertical-align:middle;border-radius:3px}button:focus,button:active{background:#e2e2e2;border:1px solid #cdcdcd;color:#333}button:hover{background:#e2e2e2;border:1px solid #cdcdcd;color:#555}button.disabled,button[disabled],fieldset[disabled] button{cursor:default;pointer-events:none;opacity:.5}button:active,button:focus{box-shadow:inset 0 2px 1px rgba(0,0,0,.12)}.example-button-1.example-button-2{line-height:2.2rem;padding:14px 17px;font-size:1.8rem}.example-button-1.example-button-3{line-height:1.2rem;padding:5px 8px;font-size:1.1rem;border-radius:0;color:#000}.example-button-1.example-button-3:hover,.example-button-1.example-button-3.active{color:#000}.example-button-10{background:#f2f2f2;padding:7px 15px;color:#333;border:1px solid #cdcdcd;cursor:pointer;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;line-height:1.6rem;box-sizing:border-box;margin:3px;vertical-align:middle;display:inline-block;background-image:none;background:0;border:0;margin:0;padding:0;-moz-box-sizing:content-box;box-shadow:none;text-shadow:none;text-decoration:none;line-height:inherit;font-weight:400}.example-button-10>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-button-10:before{font-family:'icons-blank-theme';content:'\e611';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-button-10:hover:before{color:inherit}.example-button-10:active:before{color:inherit}.example-button-10:focus,.example-button-10:active{background:#e2e2e2;border:1px solid #cdcdcd;color:#333}.example-button-10:hover{background:#e2e2e2;border:1px solid #cdcdcd;color:#555}.example-button-10.disabled,.example-button-10[disabled],fieldset[disabled] .example-button-10{cursor:default;pointer-events:none;opacity:.5}.example-button-10:focus,.example-button-10:active{background:0;border:0}.example-button-10:hover{background:0;border:0}.example-button-10.disabled,.example-button-10[disabled],fieldset[disabled] .example-button-10{cursor:not-allowed;pointer-events:none;opacity:.5}.example-button-11{background-image:none;background:#f2f2f2;padding:7px 15px;color:#333;border:1px solid #cdcdcd;cursor:pointer;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;line-height:1.6rem;box-sizing:border-box;margin:3px;vertical-align:middle;display:inline-block;text-decoration:none}.example-button-11:before{font-family:'icons-blank-theme';content:'\e611';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-button-11:hover:before{color:inherit}.example-button-11:active:before{color:inherit}.example-button-11:focus,.example-button-11:active{background:#e2e2e2;border:1px solid #cdcdcd;color:#333}.example-button-11:hover{background:#e2e2e2;border:1px solid #cdcdcd;color:#555}.example-button-11.disabled,.example-button-11[disabled],fieldset[disabled] .example-button-11{cursor:default;pointer-events:none;opacity:.5}.example-button-12{background-image:none;background:#f2f2f2;padding:7px 15px;color:#333;border:1px solid #cdcdcd;cursor:pointer;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;line-height:1.6rem;box-sizing:border-box;margin:3px;vertical-align:middle;display:inline-block;text-decoration:none}.example-button-12:after{font-family:'icons-blank-theme';content:'\e611';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-button-12:hover:after{color:inherit}.example-button-12:active:after{color:inherit}.example-button-12:focus,.example-button-12:active{background:#e2e2e2;border:1px solid #cdcdcd;color:#333}.example-button-12:hover{background:#e2e2e2;border:1px solid #cdcdcd;color:#555}.example-button-12.disabled,.example-button-12[disabled],fieldset[disabled] .example-button-12{cursor:default;pointer-events:none;opacity:.5}.example-button-13{background-image:none;background:#f2f2f2;padding:7px 15px;width:100px;color:#333;border:1px solid #cdcdcd;cursor:pointer;display:inline-block;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;line-height:1.6rem;box-sizing:border-box;margin:3px;vertical-align:middle}.example-button-13:focus,.example-button-13:active{background:#e2e2e2;border:1px solid #cdcdcd;color:#333}.example-button-13:hover{background:#e2e2e2;border:1px solid #cdcdcd;color:#555}.example-button-13.disabled,.example-button-13[disabled],fieldset[disabled] .example-button-13{cursor:default;pointer-events:none;opacity:.5}.example-button-4{background-image:none;background:#1979c3;padding:7px 15px;color:#fff;border:1px solid #1979c3;cursor:pointer;display:inline-block;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;box-sizing:border-box;margin:3px;vertical-align:middle}.example-button-4:focus,.example-button-4:active{background:#006bb4;border:1px solid #006bb4;color:#fff}.example-button-4:hover{background:#006bb4;border:1px solid #006bb4;color:#fff}.example-button-4.disabled,.example-button-4[disabled],fieldset[disabled] .example-button-4{cursor:default;pointer-events:none;opacity:.5}.example-button-4:active{box-shadow:inset 0 3px 1px rgba(0,0,0,.29)}.example-button-4.example-button-5{line-height:2.2rem;padding:7px 35px;font-size:1.8rem}.example-button-4.example-button-6{line-height:1.2rem;padding:5px 8px;font-size:1.1rem;color:#fff}.example-button-4.example-button-6:hover,.example-button-4.example-button-6.active{color:#fff}.example-button-7{background-image:none;background:#f2f2f2;background-color:#006bb4;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top, #1979c3 0, #006bb4 100%);background-image:linear-gradient(to bottom, #1979c3 0, #006bb4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#1979c3', endColorstr='#006bb4', GradientType=0);padding:7px 15px;color:#fff;border:1px solid #1979c3;cursor:pointer;display:inline-block;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;line-height:1.6rem;box-sizing:border-box;margin:3px;vertical-align:middle;border-radius:3px}.example-button-7:focus,.example-button-7:active{background:#e2e2e2;background-color:#006bb4;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top, #006bb4 0, #006bb4 100%);background-image:linear-gradient(to bottom, #006bb4 0, #006bb4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#006bb4', endColorstr='#006bb4', GradientType=0);border:1px solid #006bb4;color:#fff}.example-button-7:hover{background:#e2e2e2;background-color:#1979c3;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top, #006bb4 0, #1979c3 100%);background-image:linear-gradient(to bottom, #006bb4 0, #1979c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#006bb4', endColorstr='#1979c3', GradientType=0);border:1px solid #006bb4;color:#fff}.example-button-7.disabled,.example-button-7[disabled],fieldset[disabled] .example-button-7{cursor:default;pointer-events:none;opacity:.5}.example-button-7:active{box-shadow:inset 0 3px 1px rgba(0,0,0,.29)}.example-button-8{background:0;border:0;display:inline;line-height:1.42857143;margin:0;padding:0;color:#1979c3;text-decoration:none;font-weight:400}.example-button-8:visited{color:#1979c3;text-decoration:none}.example-button-8:hover{color:#006bb4;text-decoration:underline}.example-button-8:active{color:#ff5501;text-decoration:underline}.example-button-8:hover{color:#006bb4}.example-button-8:hover,.example-button-8:active,.example-button-8:focus{background:0;border:0}.example-button-8.disabled,.example-button-8[disabled],fieldset[disabled] .example-button-8{color:#1979c3;text-decoration:underline;cursor:default;pointer-events:none;opacity:.5}.example-button-8:active{box-shadow:none}.example-button-9{text-decoration:none;background-image:none;background:#f2f2f2;padding:7px 15px;color:#333;border:1px solid #cdcdcd;cursor:pointer;display:inline-block;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;line-height:1.6rem;box-sizing:border-box;margin:0;vertical-align:middle;margin:3px;border-radius:3px;font-weight:700}.example-button-9:hover,.example-button-9:active,.example-button-9:focus{text-decoration:none}.example-button-9:focus,.example-button-9:active{background:#e2e2e2;border:1px solid #cdcdcd;color:#333}.example-button-9:hover{background:#e2e2e2;border:1px solid #cdcdcd;color:#555}.example-button-9.disabled,.example-button-9[disabled],fieldset[disabled] .example-button-9{cursor:default;pointer-events:none;opacity:.5}.example-button-9:active{box-shadow:inset 0 3px 1px rgba(0,0,0,.29)}.example-button-14{background-image:none;background:0;border:0;margin:0;padding:0;-moz-box-sizing:content-box;box-shadow:none;text-shadow:none;text-decoration:none;line-height:inherit;font-weight:400}.example-button-14:focus,.example-button-14:active{background:0;border:0}.example-button-14:hover{background:0;border:0}.example-button-14.disabled,.example-button-14[disabled],fieldset[disabled] .example-button-14{cursor:not-allowed;pointer-events:none;opacity:.5}.example-button-15{background-image:none;background:#1979c3;padding:7px 15px;color:#fff;border:1px solid #1979c3;cursor:pointer;display:inline-block;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;box-sizing:border-box;vertical-align:middle;background:#f2f2f2;color:#333;border:1px solid #cdcdcd}.example-button-15:focus,.example-button-15:active{background:#006bb4;border:1px solid #006bb4;color:#fff}.example-button-15:hover{background:#006bb4;border:1px solid #006bb4;color:#fff}.example-button-15.disabled,.example-button-15[disabled],fieldset[disabled] .example-button-15{cursor:default;pointer-events:none;opacity:.5}.example-button-15:focus,.example-button-15:active{background:#e2e2e2;color:#333;border:1px solid #cdcdcd}.example-button-15:hover{background:#e2e2e2;color:#555;border:1px solid #cdcdcd}.example-button-17{line-height:2.2rem;padding:14px 17px;font-size:1.8rem;font-size:1.4rem;line-height:1.6rem;padding:7px 15px}.example-button-18{font-size:1rem;line-height:1.2rem;padding:4px 10px}.example-dropdown-1{display:inline-block;position:relative}.example-dropdown-1:before,.example-dropdown-1:after{content:"";display:table}.example-dropdown-1:after{clear:both}.example-dropdown-1 .action.toggle{cursor:pointer;display:inline-block;text-decoration:none}.example-dropdown-1 .action.toggle:after{font-family:'icons-blank-theme';content:'\e607';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-1 .action.toggle:hover:after{color:inherit}.example-dropdown-1 .action.toggle:active:after{color:inherit}.example-dropdown-1 .action.toggle.active{display:inline-block;text-decoration:none}.example-dropdown-1 .action.toggle.active:after{font-family:'icons-blank-theme';content:'\e618';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-1 .action.toggle.active:hover:after{color:inherit}.example-dropdown-1 .action.toggle.active:active:after{color:inherit}.example-dropdown-1 ul.dropdown{margin:0;padding:0;list-style:none none;box-sizing:border-box;background:#fff;border:1px solid #bbb;position:absolute;z-index:100;top:100%;min-width:100%;margin-top:4px;display:none;box-shadow:0 3px 3px rgba(0,0,0,.15)}.example-dropdown-1 ul.dropdown li{margin:0;padding:3px 5px}.example-dropdown-1 ul.dropdown li:hover{background:#e8e8e8;cursor:pointer}.example-dropdown-1 ul.dropdown:before,.example-dropdown-1 ul.dropdown:after{content:"";position:absolute;display:block;width:0;height:0;border-bottom-style:solid}.example-dropdown-1 ul.dropdown:before{z-index:99;border:solid 6px;border-color:transparent transparent #fff transparent}.example-dropdown-1 ul.dropdown:after{z-index:98;border:solid 7px;border-color:transparent transparent #bbb transparent}.example-dropdown-1 ul.dropdown:before{top:-12px;left:10px}.example-dropdown-1 ul.dropdown:after{top:-14px;left:9px}.example-dropdown-1.active{overflow:visible}.example-dropdown-1.active ul.dropdown{display:block}.example-dropdown-2{display:inline-block;position:relative}.example-dropdown-2:before,.example-dropdown-2:after{content:"";display:table}.example-dropdown-2:after{clear:both}.example-dropdown-2 .action.toggle{cursor:pointer;display:inline-block;text-decoration:none}.example-dropdown-2 .action.toggle:after{font-family:'icons-blank-theme';content:'\e607';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-2 .action.toggle:hover:after{color:inherit}.example-dropdown-2 .action.toggle:active:after{color:inherit}.example-dropdown-2 .action.toggle.active{display:inline-block;text-decoration:none}.example-dropdown-2 .action.toggle.active:after{font-family:'icons-blank-theme';content:'\e618';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-2 .action.toggle.active:hover:after{color:inherit}.example-dropdown-2 .action.toggle.active:active:after{color:inherit}.example-dropdown-2 ul.dropdown{margin:0;padding:0;list-style:none none;box-sizing:border-box;background:#fff;border:1px solid #bbb;position:absolute;z-index:100;top:100%;min-width:100%;margin-top:4px;display:none;box-shadow:0 3px 3px rgba(0,0,0,.15)}.example-dropdown-2 ul.dropdown li{margin:0;padding:3px 5px}.example-dropdown-2 ul.dropdown li:hover{background:#e8e8e8;cursor:pointer}.example-dropdown-2 ul.dropdown:before,.example-dropdown-2 ul.dropdown:after{content:"";position:absolute;display:block;width:0;height:0;border-bottom-style:solid}.example-dropdown-2 ul.dropdown:before{z-index:99;border:solid 6px;border-color:transparent transparent #fff transparent}.example-dropdown-2 ul.dropdown:after{z-index:98;border:solid 7px;border-color:transparent transparent #bbb transparent}.example-dropdown-2 ul.dropdown:before{top:-12px;left:10px}.example-dropdown-2 ul.dropdown:after{top:-14px;left:9px}.example-dropdown-2.active{overflow:visible}.example-dropdown-2.active ul.dropdown{display:block}.example-dropdown-3{display:inline-block;position:relative}.example-dropdown-3:before,.example-dropdown-3:after{content:"";display:table}.example-dropdown-3:after{clear:both}.example-dropdown-3 .action.toggle{cursor:pointer;display:inline-block;text-decoration:none}.example-dropdown-3 .action.toggle:before{font-family:'icons-blank-theme';content:'\e61c';font-size:22px;line-height:1;color:red;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-3 .action.toggle:hover:before{color:red}.example-dropdown-3 .action.toggle:active:before{color:inherit}.example-dropdown-3 .action.toggle.active{display:inline-block;text-decoration:none}.example-dropdown-3 .action.toggle.active:before{font-family:'icons-blank-theme';content:'\e60f';font-size:22px;line-height:1;color:red;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-3 .action.toggle.active:hover:before{color:red}.example-dropdown-3 .action.toggle.active:active:before{color:inherit}.example-dropdown-3 ul.dropdown{margin:0;padding:0;list-style:none none;box-sizing:border-box;background:#fff;border:1px solid #bbb;position:absolute;z-index:100;top:100%;min-width:100%;margin-top:4px;display:none;box-shadow:0 3px 3px rgba(0,0,0,.15)}.example-dropdown-3 ul.dropdown li{margin:0;padding:3px 5px}.example-dropdown-3 ul.dropdown li:hover{background:#e8e8e8;cursor:pointer}.example-dropdown-3 ul.dropdown:before,.example-dropdown-3 ul.dropdown:after{content:"";position:absolute;display:block;width:0;height:0;border-bottom-style:solid}.example-dropdown-3 ul.dropdown:before{z-index:99;border:solid 6px;border-color:transparent transparent #fff transparent}.example-dropdown-3 ul.dropdown:after{z-index:98;border:solid 7px;border-color:transparent transparent #bbb transparent}.example-dropdown-3 ul.dropdown:before{top:-12px;left:10px}.example-dropdown-3 ul.dropdown:after{top:-14px;left:9px}.example-dropdown-3.active{overflow:visible}.example-dropdown-3.active ul.dropdown{display:block}.example-dropdown-5{display:inline-block;position:relative}.example-dropdown-5:before,.example-dropdown-5:after{content:"";display:table}.example-dropdown-5:after{clear:both}.example-dropdown-5 .action.toggle{cursor:pointer;display:inline-block;text-decoration:none}.example-dropdown-5 .action.toggle:after{font-family:'icons-blank-theme';content:'\e607';font-size:22px;line-height:1;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-5 .action.toggle:hover:after{color:inherit}.example-dropdown-5 .action.toggle:active:after{color:inherit}.example-dropdown-5 .action.toggle.active{display:inline-block;text-decoration:none}.example-dropdown-5 .action.toggle.active:after{font-family:'icons-blank-theme';content:'\e618';font-size:22px;line-height:1;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-5 .action.toggle.active:hover:after{color:inherit}.example-dropdown-5 .action.toggle.active:active:after{color:inherit}.example-dropdown-5 ul.dropdown{margin:0;padding:0;list-style:none none;box-sizing:border-box;background:#eef1f3;border:2px solid #ced1d4;position:absolute;z-index:100;top:100%;min-width:100%;margin-top:4px;display:none}.example-dropdown-5 ul.dropdown li{margin:0;padding:10px;border-top:2px solid #e8eaed}.example-dropdown-5 ul.dropdown li:first-child{border:0}.example-dropdown-5 ul.dropdown li:hover{background:#d8e3e3;cursor:pointer}.example-dropdown-5.active{overflow:visible}.example-dropdown-5.active ul.dropdown{display:block}.example-dropdown-6{display:inline-block;position:relative}.example-dropdown-6:before,.example-dropdown-6:after{content:"";display:table}.example-dropdown-6:after{clear:both}.example-dropdown-6 .action.split{float:left;margin:0}.example-dropdown-6 .action.toggle{float:right;margin:0}.example-dropdown-6 button.action.split{border-top-right-radius:0;border-bottom-right-radius:0}.example-dropdown-6 button+.action.toggle{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.example-dropdown-6 .action.toggle{padding:4px 5px;display:inline-block;text-decoration:none}.example-dropdown-6 .action.toggle>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-6 .action.toggle:after{font-family:'icons-blank-theme';content:'\e607';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-6 .action.toggle:hover:after{color:inherit}.example-dropdown-6 .action.toggle:active:after{color:inherit}.example-dropdown-6 .action.toggle.active{display:inline-block;text-decoration:none}.example-dropdown-6 .action.toggle.active>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-6 .action.toggle.active:after{font-family:'icons-blank-theme';content:'\e618';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-6 .action.toggle.active:hover:after{color:inherit}.example-dropdown-6 .action.toggle.active:active:after{color:inherit}.example-dropdown-6 ul.dropdown{margin:0;padding:0;list-style:none none;box-sizing:border-box;background:#fff;border:1px solid #bbb;position:absolute;z-index:100;top:100%;min-width:100%;margin-top:4px;display:none;box-shadow:0 3px 3px rgba(0,0,0,.15)}.example-dropdown-6 ul.dropdown li{margin:0;padding:3px 5px}.example-dropdown-6 ul.dropdown li:hover{background:#e8e8e8;cursor:pointer}.example-dropdown-6 ul.dropdown:before,.example-dropdown-6 ul.dropdown:after{content:"";position:absolute;display:block;width:0;height:0;border-bottom-style:solid}.example-dropdown-6 ul.dropdown:before{z-index:99;border:solid 6px;border-color:transparent transparent #fff transparent}.example-dropdown-6 ul.dropdown:after{z-index:98;border:solid 7px;border-color:transparent transparent #bbb transparent}.example-dropdown-6 ul.dropdown:before{top:-12px;right:10px}.example-dropdown-6 ul.dropdown:after{top:-14px;right:9px}.example-dropdown-6.active{overflow:visible}.example-dropdown-6.active ul.dropdown{display:block}.split.example-dropdown-7{display:inline-block;position:relative}.split.example-dropdown-7:before,.split.example-dropdown-7:after{content:"";display:table}.split.example-dropdown-7:after{clear:both}.split.example-dropdown-7 .action.split{float:left;margin:0}.split.example-dropdown-7 .action.toggle{float:right;margin:0}.split.example-dropdown-7 .action.toggle{padding:4px 5px;display:inline-block;text-decoration:none}.split.example-dropdown-7 .action.toggle>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.split.example-dropdown-7 .action.toggle:after{font-family:'icons-blank-theme';content:'\e607';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.split.example-dropdown-7 .action.toggle:hover:after{color:inherit}.split.example-dropdown-7 .action.toggle:active:after{color:inherit}.split.example-dropdown-7 .action.toggle.active{display:inline-block;text-decoration:none}.split.example-dropdown-7 .action.toggle.active>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.split.example-dropdown-7 .action.toggle.active:after{font-family:'icons-blank-theme';content:'\e618';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.split.example-dropdown-7 .action.toggle.active:hover:after{color:inherit}.split.example-dropdown-7 .action.toggle.active:active:after{color:inherit}.split.example-dropdown-7 ul.dropdown{margin:0;padding:0;list-style:none none;box-sizing:border-box;background:#fff;border:1px solid #bbb;position:absolute;z-index:100;top:100%;min-width:100%;margin-top:4px;display:none;box-shadow:0 3px 3px rgba(0,0,0,.15)}.split.example-dropdown-7 ul.dropdown li{margin:0;padding:3px 5px}.split.example-dropdown-7 ul.dropdown li:hover{background:#e8e8e8;cursor:pointer}.split.example-dropdown-7 ul.dropdown:before,.split.example-dropdown-7 ul.dropdown:after{content:"";position:absolute;display:block;width:0;height:0;border-bottom-style:solid}.split.example-dropdown-7 ul.dropdown:before{z-index:99;border:solid 6px;border-color:transparent transparent #fff transparent}.split.example-dropdown-7 ul.dropdown:after{z-index:98;border:solid 7px;border-color:transparent transparent #bbb transparent}.split.example-dropdown-7 ul.dropdown:before{top:-12px;right:10px}.split.example-dropdown-7 ul.dropdown:after{top:-14px;right:9px}.split.example-dropdown-7.active{overflow:visible}.split.example-dropdown-7.active ul.dropdown{display:block}.example-dropdown-8{display:inline-block;position:relative}.example-dropdown-8:before,.example-dropdown-8:after{content:"";display:table}.example-dropdown-8:after{clear:both}.example-dropdown-8 .action.split{float:left;margin:0}.example-dropdown-8 .action.toggle{float:right;margin:0}.example-dropdown-8 button.action.split{border-top-right-radius:0;border-bottom-right-radius:0}.example-dropdown-8 button+.action.toggle{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.example-dropdown-8 .action.toggle{padding:4px 5px;display:inline-block;text-decoration:none}.example-dropdown-8 .action.toggle>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-8 .action.toggle:after{font-family:'icons-blank-theme';content:'\e607';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-8 .action.toggle:hover:after{color:inherit}.example-dropdown-8 .action.toggle:active:after{color:inherit}.example-dropdown-8 .action.toggle.active{display:inline-block;text-decoration:none}.example-dropdown-8 .action.toggle.active>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-8 .action.toggle.active:after{font-family:'icons-blank-theme';content:'\e618';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-8 .action.toggle.active:hover:after{color:inherit}.example-dropdown-8 .action.toggle.active:active:after{color:inherit}.example-dropdown-8 ul.dropdown{margin:0;padding:0;list-style:none none;box-sizing:border-box;background:#fff;border:1px solid #bbb;position:absolute;z-index:100;top:100%;min-width:100%;margin-top:4px;display:none;box-shadow:0 3px 3px rgba(0,0,0,.15)}.example-dropdown-8 ul.dropdown li{margin:0;padding:3px 5px}.example-dropdown-8 ul.dropdown li:hover{background:#e8e8e8;cursor:pointer}.example-dropdown-8 ul.dropdown:before,.example-dropdown-8 ul.dropdown:after{content:"";position:absolute;display:block;width:0;height:0;border-bottom-style:solid}.example-dropdown-8 ul.dropdown:before{z-index:99;border:solid 6px;border-color:transparent transparent #fff transparent}.example-dropdown-8 ul.dropdown:after{z-index:98;border:solid 7px;border-color:transparent transparent #bbb transparent}.example-dropdown-8 ul.dropdown:before{top:-12px;right:10px}.example-dropdown-8 ul.dropdown:after{top:-14px;right:9px}.example-dropdown-8.active{overflow:visible}.example-dropdown-8.active ul.dropdown{display:block}.example-dropdown-9{display:inline-block;position:relative}.example-dropdown-9 .action.split,.example-dropdown-9 .action.toggle{line-height:2.2rem;padding:14px 17px;font-size:1.8rem}.example-dropdown-9:before,.example-dropdown-9:after{content:"";display:table}.example-dropdown-9:after{clear:both}.example-dropdown-9 .action.split{float:left;margin:0}.example-dropdown-9 .action.toggle{float:right;margin:0}.example-dropdown-9 button.action.split{border-top-right-radius:0;border-bottom-right-radius:0}.example-dropdown-9 button+.action.toggle{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.example-dropdown-9 .action.toggle{padding:4px 5px;display:inline-block;text-decoration:none}.example-dropdown-9 .action.toggle>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-9 .action.toggle:after{font-family:'icons-blank-theme';content:'\e607';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-9 .action.toggle:hover:after{color:inherit}.example-dropdown-9 .action.toggle:active:after{color:inherit}.example-dropdown-9 .action.toggle.active{display:inline-block;text-decoration:none}.example-dropdown-9 .action.toggle.active>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-9 .action.toggle.active:after{font-family:'icons-blank-theme';content:'\e618';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-9 .action.toggle.active:hover:after{color:inherit}.example-dropdown-9 .action.toggle.active:active:after{color:inherit}.example-dropdown-9 ul.dropdown{margin:0;padding:0;list-style:none none;box-sizing:border-box;background:#fff;border:1px solid #bbb;position:absolute;z-index:100;top:100%;min-width:100%;margin-top:4px;display:none;box-shadow:0 3px 3px rgba(0,0,0,.15)}.example-dropdown-9 ul.dropdown li{margin:0;padding:3px 5px}.example-dropdown-9 ul.dropdown li:hover{background:#e8e8e8;cursor:pointer}.example-dropdown-9 ul.dropdown:before,.example-dropdown-9 ul.dropdown:after{content:"";position:absolute;display:block;width:0;height:0;border-bottom-style:solid}.example-dropdown-9 ul.dropdown:before{z-index:99;border:solid 6px;border-color:transparent transparent #fff transparent}.example-dropdown-9 ul.dropdown:after{z-index:98;border:solid 7px;border-color:transparent transparent #bbb transparent}.example-dropdown-9 ul.dropdown:before{top:-12px;right:10px}.example-dropdown-9 ul.dropdown:after{top:-14px;right:9px}.example-dropdown-9.active{overflow:visible}.example-dropdown-9.active ul.dropdown{display:block}.example-dropdown-10{display:inline-block;position:relative}.example-dropdown-10 .action.split,.example-dropdown-10 .action.toggle{line-height:1.2rem;padding:5px 8px;font-size:1.1rem}.example-dropdown-10:before,.example-dropdown-10:after{content:"";display:table}.example-dropdown-10:after{clear:both}.example-dropdown-10 .action.split{float:left;margin:0}.example-dropdown-10 .action.toggle{float:right;margin:0}.example-dropdown-10 button.action.split{border-top-right-radius:0;border-bottom-right-radius:0}.example-dropdown-10 button+.action.toggle{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.example-dropdown-10 .action.toggle{padding:4px 5px;display:inline-block;text-decoration:none}.example-dropdown-10 .action.toggle>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-10 .action.toggle:after{font-family:'icons-blank-theme';content:'\e607';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-10 .action.toggle:hover:after{color:inherit}.example-dropdown-10 .action.toggle:active:after{color:inherit}.example-dropdown-10 .action.toggle.active{display:inline-block;text-decoration:none}.example-dropdown-10 .action.toggle.active>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-10 .action.toggle.active:after{font-family:'icons-blank-theme';content:'\e618';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-10 .action.toggle.active:hover:after{color:inherit}.example-dropdown-10 .action.toggle.active:active:after{color:inherit}.example-dropdown-10 ul.dropdown{margin:0;padding:0;list-style:none none;box-sizing:border-box;background:#fff;border:1px solid #bbb;position:absolute;z-index:100;top:100%;min-width:100%;margin-top:4px;display:none;box-shadow:0 3px 3px rgba(0,0,0,.15)}.example-dropdown-10 ul.dropdown li{margin:0;padding:3px 5px}.example-dropdown-10 ul.dropdown li:hover{background:#e8e8e8;cursor:pointer}.example-dropdown-10 ul.dropdown:before,.example-dropdown-10 ul.dropdown:after{content:"";position:absolute;display:block;width:0;height:0;border-bottom-style:solid}.example-dropdown-10 ul.dropdown:before{z-index:99;border:solid 6px;border-color:transparent transparent #fff transparent}.example-dropdown-10 ul.dropdown:after{z-index:98;border:solid 7px;border-color:transparent transparent #bbb transparent}.example-dropdown-10 ul.dropdown:before{top:-12px;right:10px}.example-dropdown-10 ul.dropdown:after{top:-14px;right:9px}.example-dropdown-10.active{overflow:visible}.example-dropdown-10.active ul.dropdown{display:block}.example-dropdown-11{display:inline-block;position:relative}.example-dropdown-11:before,.example-dropdown-11:after{content:"";display:table}.example-dropdown-11:after{clear:both}.example-dropdown-11 .action.split{float:right;margin:0}.example-dropdown-11 .action.toggle{float:left;margin:0}.example-dropdown-11 button.action.split{border-top-left-radius:0;border-bottom-left-radius:0}.example-dropdown-11 button+.action.toggle{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.example-dropdown-11 .action.toggle{padding:4px 5px;display:inline-block;text-decoration:none}.example-dropdown-11 .action.toggle>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-11 .action.toggle:before{font-family:'icons-blank-theme';content:'\e61c';font-size:22px;line-height:22px;color:red;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-11 .action.toggle:hover:before{color:red}.example-dropdown-11 .action.toggle:active:before{color:inherit}.example-dropdown-11 .action.toggle.active{display:inline-block;text-decoration:none}.example-dropdown-11 .action.toggle.active>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-11 .action.toggle.active:before{font-family:'icons-blank-theme';content:'\e60f';font-size:22px;line-height:22px;color:red;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-11 .action.toggle.active:hover:before{color:red}.example-dropdown-11 .action.toggle.active:active:before{color:inherit}.example-dropdown-11 ul.dropdown{margin:0;padding:0;list-style:none none;box-sizing:border-box;background:#fff;border:1px solid #bbb;position:absolute;z-index:100;top:100%;min-width:100%;margin-top:4px;display:none;box-shadow:0 3px 3px rgba(0,0,0,.15)}.example-dropdown-11 ul.dropdown li{margin:0;padding:3px 5px}.example-dropdown-11 ul.dropdown li:hover{background:#e8e8e8;cursor:pointer}.example-dropdown-11 ul.dropdown:before,.example-dropdown-11 ul.dropdown:after{content:"";position:absolute;display:block;width:0;height:0;border-bottom-style:solid}.example-dropdown-11 ul.dropdown:before{z-index:99;border:solid 6px;border-color:transparent transparent #fff transparent}.example-dropdown-11 ul.dropdown:after{z-index:98;border:solid 7px;border-color:transparent transparent #bbb transparent}.example-dropdown-11 ul.dropdown:before{top:-12px;right:10px}.example-dropdown-11 ul.dropdown:after{top:-14px;right:9px}.example-dropdown-11.active{overflow:visible}.example-dropdown-11.active ul.dropdown{display:block}.example-dropdown-12{display:inline-block;position:relative}.example-dropdown-12:before,.example-dropdown-12:after{content:"";display:table}.example-dropdown-12:after{clear:both}.example-dropdown-12 .action.split{float:left;margin:0}.example-dropdown-12 .action.toggle{float:right;margin:0}.example-dropdown-12 button.action.split{border-top-right-radius:0;border-bottom-right-radius:0}.example-dropdown-12 button+.action.toggle{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.example-dropdown-12 .action.toggle{padding:4px 5px;display:inline-block;text-decoration:none}.example-dropdown-12 .action.toggle>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-12 .action.toggle:after{font-family:'icons-blank-theme';content:'\e607';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-12 .action.toggle:hover:after{color:inherit}.example-dropdown-12 .action.toggle:active:after{color:inherit}.example-dropdown-12 .action.toggle.active{display:inline-block;text-decoration:none}.example-dropdown-12 .action.toggle.active>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-dropdown-12 .action.toggle.active:after{font-family:'icons-blank-theme';content:'\e618';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.example-dropdown-12 .action.toggle.active:hover:after{color:inherit}.example-dropdown-12 .action.toggle.active:active:after{color:inherit}.example-dropdown-12 ul.dropdown{margin:0;padding:0;list-style:none none;box-sizing:border-box;background:#eef1f3;border:2px solid #ced1d4;position:absolute;z-index:100;top:100%;min-width:100%;margin-top:4px;display:none}.example-dropdown-12 ul.dropdown li{margin:0;padding:10px;border-top:2px solid #e8eaed}.example-dropdown-12 ul.dropdown li:first-child{border:0}.example-dropdown-12 ul.dropdown li:hover{background:#d8e3e3;cursor:pointer}.example-dropdown-12.active{overflow:visible}.example-dropdown-12.active ul.dropdown{display:block}.example-form-1 .example-form-1-fieldset{padding:0;margin:0 0 40px;border:0;letter-spacing:-.31em}.example-form-1 .example-form-1-fieldset>*{letter-spacing:normal}.example-form-1 .example-form-1-fieldset>.legend{margin:0 0 25px;padding:0;font-size:2rem;line-height:1.2;box-sizing:border-box;float:left}.example-form-1 .example-form-1-fieldset>.legend+br{display:block;visibility:hidden;height:0;overflow:hidden;clear:both}.example-form-1 .example-form-1-fieldset:after{content:attr(data-hasrequired);display:block;font-size:1.2rem;color:#e02b27;margin:10px 0 0;letter-spacing:normal;word-spacing:normal}.example-form-1 .example-form-1-fieldset>.field{margin:0 0 20px}.example-form-1 .example-form-1-fieldset>.field>.label{display:inline-block;margin:0 0 5px}.example-form-1 .example-form-1-fieldset>.field:last-child{margin-bottom:0}.example-form-1 .example-form-1-fieldset>.field>.label{font-weight:700}.example-form-1 .example-form-1-fieldset>.field>.label+br{display:none}.example-form-1 .example-form-1-fieldset>.field .choice input{vertical-align:top}.example-form-1 .example-form-1-fieldset>.field .fields.group:before,.example-form-1 .example-form-1-fieldset>.field .fields.group:after{content:"";display:table}.example-form-1 .example-form-1-fieldset>.field .fields.group:after{clear:both}.example-form-1 .example-form-1-fieldset>.field .fields.group .field{box-sizing:border-box;float:left}.example-form-1 .example-form-1-fieldset>.field .fields.group.group-2 .field{width:50%!important}.example-form-1 .example-form-1-fieldset>.field .fields.group.group-3 .field{width:33.3%!important}.example-form-1 .example-form-1-fieldset>.field .fields.group.group-4 .field{width:25%!important}.example-form-1 .example-form-1-fieldset>.field .fields.group.group-5 .field{width:20%!important}.example-form-1 .example-form-1-fieldset>.field .addon{display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-flex-wrap:nowrap;flex-wrap:nowrap;padding:0;width:100%}.example-form-1 .example-form-1-fieldset>.field .addon textarea,.example-form-1 .example-form-1-fieldset>.field .addon select,.example-form-1 .example-form-1-fieldset>.field .addon input{-ms-flex-order:2;-webkit-order:2;order:2;-webkit-flex-basis:100%;flex-basis:100%;box-shadow:none;display:inline-block;margin:0;width:auto}.example-form-1 .example-form-1-fieldset>.field .addon .addbefore,.example-form-1 .example-form-1-fieldset>.field .addon .addafter{-ms-flex-order:3;-webkit-order:3;order:3;display:inline-block;box-sizing:border-box;background:#fff;border:1px solid #c2c2c2;border-radius:1px;height:32px;width:100%;padding:0 9px;font-size:14px;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.428571429;background-clip:padding-box;vertical-align:baseline;width:auto;white-space:nowrap;vertical-align:middle}.example-form-1 .example-form-1-fieldset>.field .addon .addbefore:disabled,.example-form-1 .example-form-1-fieldset>.field .addon .addafter:disabled{opacity:.5}.example-form-1 .example-form-1-fieldset>.field .addon .addbefore::-moz-placeholder,.example-form-1 .example-form-1-fieldset>.field .addon .addafter::-moz-placeholder{color:#c2c2c2}.example-form-1 .example-form-1-fieldset>.field .addon .addbefore::-webkit-input-placeholder,.example-form-1 .example-form-1-fieldset>.field .addon .addafter::-webkit-input-placeholder{color:#c2c2c2}.example-form-1 .example-form-1-fieldset>.field .addon .addbefore:-ms-input-placeholder,.example-form-1 .example-form-1-fieldset>.field .addon .addafter:-ms-input-placeholder{color:#c2c2c2}.example-form-1 .example-form-1-fieldset>.field .addon .addbefore{float:left;-ms-flex-order:1;-webkit-order:1;order:1}.example-form-1 .example-form-1-fieldset>.field .additional{margin-top:10px}.example-form-1 .example-form-1-fieldset>.field.required>.label:after{content:'*';font-size:1.2rem;color:#e02b27;margin:0 0 0 5px}.example-form-1 .example-form-1-fieldset>.field .note{font-size:1.2rem;margin:3px 0 0;padding:0;display:inline-block;text-decoration:none}.example-form-1 .example-form-1-fieldset>.field .note:before{font-family:'icons-blank-theme';content:'\e618';font-size:24px;line-height:12px;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;text-align:center}.example-form-2 .example-form-2-fieldset{padding:0;margin:0 0 40px;border:0;letter-spacing:-.31em}.example-form-2 .example-form-2-fieldset>*{letter-spacing:normal}.example-form-2 .example-form-2-fieldset>.legend{margin:0 0 25px;padding:0;font-size:2rem;line-height:1.2;box-sizing:border-box;float:left}.example-form-2 .example-form-2-fieldset>.legend+br{display:block;visibility:hidden;height:0;overflow:hidden;clear:both}.example-form-2 .example-form-2-fieldset>.field{margin:0 0 20px;box-sizing:border-box;display:inline-block;padding:0 12px 0 0;width:50%;vertical-align:top}.example-form-2 .example-form-2-fieldset>.field>.label{display:inline-block;margin:0 0 5px}.example-form-2 .example-form-2-fieldset>.field:last-child{margin-bottom:0}.example-form-2 .example-form-2-fieldset>.field+.fieldset{clear:both}.example-form-2 .example-form-2-fieldset>.field>.label{font-weight:700}.example-form-2 .example-form-2-fieldset>.field>.label+br{display:none}.example-form-2 .example-form-2-fieldset>.field .choice input{vertical-align:top}.example-form-2 .example-form-2-fieldset>.field .fields.group:before,.example-form-2 .example-form-2-fieldset>.field .fields.group:after{content:"";display:table}.example-form-2 .example-form-2-fieldset>.field .fields.group:after{clear:both}.example-form-2 .example-form-2-fieldset>.field .fields.group .field{box-sizing:border-box;float:left}.example-form-2 .example-form-2-fieldset>.field .fields.group.group-2 .field{width:50%!important}.example-form-2 .example-form-2-fieldset>.field .fields.group.group-3 .field{width:33.3%!important}.example-form-2 .example-form-2-fieldset>.field .fields.group.group-4 .field{width:25%!important}.example-form-2 .example-form-2-fieldset>.field .fields.group.group-5 .field{width:20%!important}.example-form-2 .example-form-2-fieldset>.field .addon{display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-flex-wrap:nowrap;flex-wrap:nowrap;padding:0;width:100%}.example-form-2 .example-form-2-fieldset>.field .addon textarea,.example-form-2 .example-form-2-fieldset>.field .addon select,.example-form-2 .example-form-2-fieldset>.field .addon input{-ms-flex-order:2;-webkit-order:2;order:2;-webkit-flex-basis:100%;flex-basis:100%;box-shadow:none;display:inline-block;margin:0;width:auto}.example-form-2 .example-form-2-fieldset>.field .addon .addbefore,.example-form-2 .example-form-2-fieldset>.field .addon .addafter{-ms-flex-order:3;-webkit-order:3;order:3;display:inline-block;box-sizing:border-box;background:#fff;border:1px solid #c2c2c2;border-radius:1px;height:32px;width:100%;padding:0 9px;font-size:14px;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.428571429;background-clip:padding-box;vertical-align:baseline;width:auto;white-space:nowrap;vertical-align:middle}.example-form-2 .example-form-2-fieldset>.field .addon .addbefore:disabled,.example-form-2 .example-form-2-fieldset>.field .addon .addafter:disabled{opacity:.5}.example-form-2 .example-form-2-fieldset>.field .addon .addbefore::-moz-placeholder,.example-form-2 .example-form-2-fieldset>.field .addon .addafter::-moz-placeholder{color:#c2c2c2}.example-form-2 .example-form-2-fieldset>.field .addon .addbefore::-webkit-input-placeholder,.example-form-2 .example-form-2-fieldset>.field .addon .addafter::-webkit-input-placeholder{color:#c2c2c2}.example-form-2 .example-form-2-fieldset>.field .addon .addbefore:-ms-input-placeholder,.example-form-2 .example-form-2-fieldset>.field .addon .addafter:-ms-input-placeholder{color:#c2c2c2}.example-form-2 .example-form-2-fieldset>.field .addon .addbefore{float:left;-ms-flex-order:1;-webkit-order:1;order:1}.example-form-2 .example-form-2-fieldset>.field .additional{margin-top:10px}.example-form-2 .example-form-2-fieldset>.field.required>.label:after{content:'*';font-size:1.2rem;color:#e02b27;margin:0 0 0 5px}.example-form-2 .example-form-2-fieldset>.field .note{font-size:1.2rem;margin:3px 0 0;padding:0;display:inline-block;text-decoration:none}.example-form-2 .example-form-2-fieldset>.field .note:before{font-family:'icons-blank-theme';content:'\e618';font-size:24px;line-height:12px;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;text-align:center}input[type="text"],input[type="password"],input[type="url"],input[type="tel"],input[type="search"],input[type="number"],input[type="datetime"],input[type="email"]{box-sizing:border-box;background:#fff;border:1px solid #c2c2c2;border-radius:1px;height:32px;width:100%;padding:0 9px;font-size:14px;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.428571429;background-clip:padding-box;vertical-align:baseline;margin-bottom:20px}input[type="text"]:disabled,input[type="password"]:disabled,input[type="url"]:disabled,input[type="tel"]:disabled,input[type="search"]:disabled,input[type="number"]:disabled,input[type="datetime"]:disabled,input[type="email"]:disabled{opacity:.5}input[type="text"]::-moz-placeholder,input[type="password"]::-moz-placeholder,input[type="url"]::-moz-placeholder,input[type="tel"]::-moz-placeholder,input[type="search"]::-moz-placeholder,input[type="number"]::-moz-placeholder,input[type="datetime"]::-moz-placeholder,input[type="email"]::-moz-placeholder{color:#c2c2c2}input[type="text"]::-webkit-input-placeholder,input[type="password"]::-webkit-input-placeholder,input[type="url"]::-webkit-input-placeholder,input[type="tel"]::-webkit-input-placeholder,input[type="search"]::-webkit-input-placeholder,input[type="number"]::-webkit-input-placeholder,input[type="datetime"]::-webkit-input-placeholder,input[type="email"]::-webkit-input-placeholder{color:#c2c2c2}input[type="text"]:-ms-input-placeholder,input[type="password"]:-ms-input-placeholder,input[type="url"]:-ms-input-placeholder,input[type="tel"]:-ms-input-placeholder,input[type="search"]:-ms-input-placeholder,input[type="number"]:-ms-input-placeholder,input[type="datetime"]:-ms-input-placeholder,input[type="email"]:-ms-input-placeholder{color:#c2c2c2}select{box-sizing:border-box;background:#fff;border:1px solid #c2c2c2;border-radius:1px;height:32px;width:100%;padding:5px 10px 4px;font-size:14px;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.428571429;background-clip:padding-box;vertical-align:baseline;margin-bottom:20px}select:disabled{opacity:.5}select[multiple="multiple"]{height:auto;margin-bottom:20px}textarea{box-sizing:border-box;background:#fff;border:1px solid #c2c2c2;border-radius:1px;height:auto;width:100%;padding:10px;margin:0;font-size:14px;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.428571429;background-clip:padding-box;vertical-align:baseline;resize:vertical}textarea:disabled{opacity:.5}textarea::-moz-placeholder{color:#c2c2c2}textarea::-webkit-input-placeholder{color:#c2c2c2}textarea:-ms-input-placeholder{color:#c2c2c2}input[type="checkbox"]{margin:2px 5px 0 0}input[type="checkbox"]:disabled{opacity:.5}input[type="radio"]{margin:2px 5px 0 0}input[type="radio"]:disabled{opacity:.5}input.text-example-1,select.select-example-1,textarea.textarea-example-1{background:#fdf0d5;border-color:#fc0;color:#b30000}input.text-example-1:focus,select.select-example-1:focus,textarea.textarea-example-1:focus{border-color:#cff;color:#060}input.text-example-1:disabled,select.select-example-1:disabled,textarea.textarea-example-1:disabled{color:#fcc}input.text-example-1::-moz-placeholder,textarea.textarea-example-1::-moz-placeholder{color:#ccc}input.text-example-1::-webkit-input-placeholder,textarea.textarea-example-1::-webkit-input-placeholder{color:#ccc}input.text-example-1:-ms-input-placeholder,textarea.textarea-example-1:-ms-input-placeholder{color:#ccc}.number-example{-moz-appearance:textfield}.number-example::-webkit-inner-spin-button,.number-example::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.search-example{-webkit-appearance:none}.search-example::-webkit-search-cancel-button,.search-example::-webkit-search-decoration,.search-example::-webkit-search-results-button,.search-example::-webkit-search-results-decoration{-webkit-appearance:none}input,textarea,select{font-size:1.2rem;color:#e02b27}.example-icon-1{display:inline-block}.example-icon-1:before{content:'';display:inline-block;width:26px;height:26px;line-height:26px;vertical-align:middle;background:url('/pub/static/frontend/Magento/blank/en_US/images/blank-theme-icons.png') no-repeat 0 0}.example-icon-2{display:inline-block}.example-icon-2:after{content:'';display:inline-block;width:26px;height:26px;line-height:26px;vertical-align:middle;background:url('/pub/static/frontend/Magento/blank/en_US/images/blank-theme-icons.png') no-repeat -26px 0}.example-icon-3{display:inline-block}.example-icon-3>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-icon-3:before{content:'';display:inline-block;width:26px;height:26px;line-height:26px;vertical-align:middle;background:url('/pub/static/frontend/Magento/blank/en_US/images/blank-theme-icons.png') no-repeat -156px -52px}.example-icon-4{display:inline-block;text-decoration:none}.example-icon-4:before{font-family:'icons-blank-theme';content:'\e606';font-size:24px;line-height:inherit;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;text-align:center}.example-icon-5{display:inline-block;text-decoration:none}.example-icon-5:after{font-family:'icons-blank-theme';content:'\e605';font-size:24px;line-height:inherit;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;text-align:center}.example-icon-6{display:inline-block;text-decoration:none}.example-icon-6>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-icon-6:before{font-family:'icons-blank-theme';content:'\e61b';font-size:24px;line-height:inherit;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;text-align:center}.example-icon-7{display:inline-block}.example-icon-7:before{content:'';display:inline-block;width:26px;height:26px;line-height:26px;vertical-align:middle;background:url('/pub/static/frontend/Magento/blank/en_US/images/blank-theme-icons.png') no-repeat 0 0}.example-icon-8{display:inline-block}.example-icon-8:before{content:'';display:inline-block;width:26px;height:26px;line-height:26px;vertical-align:middle;background:url('/pub/static/frontend/Magento/blank/en_US/images/blank-theme-icons.png') no-repeat 0 0}.example-icon-8:before{background-position:-182px 0}.example-icon-9{display:inline-block}.example-icon-9:after{content:'';display:inline-block;width:26px;height:26px;line-height:26px;vertical-align:middle;background:url('/pub/static/frontend/Magento/blank/en_US/images/blank-theme-icons.png') no-repeat 0 0}.example-icon-9:after{background-position:-52px -26px}.example-icon-10{display:inline-block}.example-icon-10:before{content:'';display:inline-block;width:26px;height:26px;line-height:26px;vertical-align:middle;background:url('/pub/static/frontend/Magento/blank/en_US/images/blank-theme-icons.png') no-repeat 0 0}.example-icon-10:before{background-position:-104px 0}.example-icon-11{display:inline-block}.example-icon-11:before{content:'';display:inline-block;width:26px;height:26px;line-height:26px;vertical-align:middle;background:url('/pub/static/frontend/Magento/blank/en_US/images/blank-theme-icons.png') no-repeat 0 0}.example-icon-11:before{width:30px;height:30px}.example-icon-11:after{width:30px;height:30px}.example-icon-11:before{background-color:#f1f1f1}.example-icon-12{display:inline-block;text-decoration:none}.example-icon-12:before{font-family:'icons-blank-theme';content:'\e612';font-size:28px;line-height:inherit;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;text-align:center}.example-icon-13{display:inline-block;text-decoration:none}.example-icon-13:before{font-family:'icons-blank-theme';content:'\e612';font-size:inherit;line-height:inherit;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;text-align:center}.example-icon-13:before{font-size:26px;line-height:inherit}.example-icon-14{display:inline-block;text-decoration:none}.example-icon-14:before{font-family:'icons-blank-theme';content:'\e61d';font-size:26px;line-height:inherit;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;text-align:center}.example-icon-14>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.icons-image-list{list-style:none;padding:0}.icons-image-list li{float:left;width:33%}.icons-image-list li>span{display:inline-block}.icons-image-list li>span:before{content:'';display:inline-block;width:26px;height:26px;line-height:26px;vertical-align:middle;background:url('/pub/static/frontend/Magento/blank/en_US/images/blank-theme-icons.png') no-repeat 0 0}.icons-image-list li .icon-search:before{background-position:0 0}.icons-image-list li .icon-cart:before{background-position:-26px 0}.icons-image-list li .icon-arrow-down:before{background-position:-52px 0}.icons-image-list li .icon-arrow-up:before{background-position:-78px 0}.icons-image-list li .icon-grid:before{background-position:-104px 0}.icons-image-list li .icon-list:before{background-position:-130px 0}.icons-image-list li .icon-remove:before{background-position:-156px 0}.icons-image-list li .icon-star:before{background-position:-182px 0}.icons-image-list li .icon-pointer-down:before{background-position:-208px 0}.icons-image-list li .icon-pointer-up:before{background-position:-234px 0}.icons-image-list li .icon-pointer-left:before{background-position:-260px 0}.icons-image-list li .icon-pointer-right:before{background-position:-286px 0}.icons-image-list li .icon-compare-empty:before{background-position:0 -26px}.icons-image-list li .icon-compare-full:before{background-position:-26px -26px}.icons-image-list li .icon-wishlist-empty:before{background-position:-52px -26px}.icons-image-list li .icon-wishlist-full:before{background-position:-78px -26px}.icons-image-list li .icon-update:before{background-position:-104px -26px}.icons-image-list li .icon-collapse:before{background-position:-130px -26px}.icons-image-list li .icon-expand:before{background-position:-156px -26px}.icons-image-list li .icon-menu:before{background-position:-182px -26px}.icons-image-list li .icon-prev:before{background-position:-208px -26px}.icons-image-list li .icon-next:before{background-position:-234px -26px}.icons-image-list li .icon-settings:before{background-position:-260px -26px}.icons-image-list li .icon-info:before{background-position:-286px -26px}.icons-image-list li .icon-checkmark:before{background-position:0 -52px}.icons-image-list li .icon-calendar:before{background-position:-26px -52px}.icons-image-list li .icon-comment:before{background-position:-52px -52px}.icons-image-list li .icon-comment-reflected:before{background-position:-78px -52px}.icons-image-list li .icon-envelope:before{background-position:-104px -52px}.icons-image-list li .icon-warning:before{background-position:-130px -52px}.icons-image-list li .icon-trash:before{background-position:-156px -52px}.icons-image-list li .icon-flag:before{background-position:-182px -52px}.icons-image-list li .icon-location:before{background-position:-208px -52px}.icons-image-list li .icon-up:before{background-position:-234px -52px}.icons-image-list li .icon-down:before{background-position:-260px -52px}.icons-font-list{list-style:none;padding:0}.icons-font-list li{float:left;width:25%;margin-bottom:35px;text-align:center}.icons-font-list li>span{display:inline-block;text-decoration:none}.icons-font-list li>span:before{font-family:'icons-blank-theme';font-size:34px;line-height:inherit;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;text-align:center}.icons-font-list li>span:before{content:attr(data-icon);margin:0 auto;display:block}.loader{position:fixed;top:0;right:0;bottom:0;left:0;background-color:rgba(255,255,255,.5);z-index:9999}.loader:before{border-radius:5px;background:transparent url('/pub/static/frontend/Magento/blank/en_US/images/loader-2.gif') no-repeat 50% 50%;box-sizing:border-box;content:'';position:absolute;top:0;right:0;left:0;bottom:0;margin:auto;width:160px;height:160px}.loading{position:relative}.loading:before{content:'';position:absolute;left:0;top:0;right:0;bottom:0;background:rgba(255,255,255,.5) url('/pub/static/frontend/Magento/blank/en_US/images/loader-2.gif') no-repeat 50% 50%}.example-message-info{display:block;margin:0 0 10px;padding:10px 20px;font-size:1.3rem;line-height:1.2em;background:#fdf0d5;color:#6f4400}.example-message-info a{color:#1979c3}.example-message-info a:hover{color:#006bb4}.example-message-info a:active{color:#006bb4}.example-message-warning{display:block;margin:0 0 10px;padding:10px 20px;font-size:1.3rem;line-height:1.2em;background:#fdf0d5;color:#6f4400}.example-message-warning a{color:#1979c3}.example-message-warning a:hover{color:#006bb4}.example-message-warning a:active{color:#006bb4}.example-message-error{display:block;margin:0 0 10px;padding:10px 20px;font-size:1.3rem;line-height:1.2em;background:#fae5e5;color:#e02b27}.example-message-error a{color:#1979c3}.example-message-error a:hover{color:#006bb4}.example-message-error a:active{color:#006bb4}.example-message-success{display:block;margin:0 0 10px;padding:10px 20px;font-size:1.3rem;line-height:1.2em;background:#e5efe5;color:#006400}.example-message-success a{color:#1979c3}.example-message-success a:hover{color:#006bb4}.example-message-success a:active{color:#006bb4}.example-message-notice{display:block;margin:0 0 10px;padding:10px 20px;font-size:1.3rem;line-height:1.2em;background:#fdf0d5;color:#6f4400}.example-message-notice a{color:#1979c3}.example-message-notice a:hover{color:#006bb4}.example-message-notice a:active{color:#006bb4}.example-message-1{display:block;margin:0 0 10px;padding:10px 20px;font-size:1.3rem;line-height:1.2em;background:#fdf0d5;color:#6f4400;position:relative;padding-left:40px}.example-message-1 a{color:#1979c3}.example-message-1 a:hover{color:#006bb4}.example-message-1 a:active{color:#006bb4}.example-message-1>:first-child:before{font-family:'icons-blank-theme';content:'\e602';font-size:28px;line-height:28px;color:#c07600;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;margin:-14px 0 0;position:absolute;top:18px;left:0;text-align:center;width:40px}.example-message-2{display:block;margin:0 0 10px;padding:10px 20px;font-size:1.3rem;line-height:1.2em;background:#fae5e5;color:#e02b27;position:relative;padding-right:40px}.example-message-2 a{color:#1979c3}.example-message-2 a:hover{color:#006bb4}.example-message-2 a:active{color:#006bb4}.example-message-2:before{content:'';position:absolute;width:30px;text-align:center;top:0;height:100%;display:block;padding:0;background:#b30000}.example-message-2>:first-child:before{content:'';position:absolute;overflow:hidden;top:50%;margin-top:-5px}.example-message-2>:first-child:after{font-family:'icons-blank-theme';content:'\e602';font-size:28px;line-height:28px;color:#fff;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;margin:-14px 0 0;position:absolute;top:18px;left:0;text-align:center;width:30px}.example-message-2:before{right:0}.example-message-2>:first-child:before{border:5px solid transparent;height:0;width:0;border-right-color:#b30000;right:30px}.example-message-2>:first-child:after{right:0}.example-message-3{display:block;margin:0 0 10px;padding:10px 20px;font-size:1.3rem;line-height:1.2em;background:#e5efe5;color:#006400;position:relative;padding-left:40px}.example-message-3 a{color:#1979c3}.example-message-3 a:hover{color:#006bb4}.example-message-3 a:active{color:#006bb4}.example-message-3:before{content:'';position:absolute;width:30px;text-align:center;top:0;height:100%;display:block;padding:0;background:#006400}.example-message-3>:first-child:before{content:'';position:absolute;overflow:hidden;top:50%;margin-top:-5px}.example-message-3>:first-child:after{font-family:'icons-blank-theme';content:'\e610';font-size:28px;line-height:28px;color:#fff;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;margin:-14px 0 0;position:absolute;top:18px;left:0;text-align:center;width:30px}.example-message-3:before{left:0}.example-message-3>:first-child:before{border:5px solid transparent;height:0;width:0;border-left-color:#006400;left:30px}.example-message-3>:first-child:after{left:0}.example-message-4{display:block;margin:0 0 10px;padding:10px 20px;font-size:1.3rem;line-height:1.2em;background:#fc0;border-color:#ffa500;color:#000;position:relative;padding-left:40px;border-width:4px;border-radius:10px}.example-message-4 a{color:#00f}.example-message-4 a:hover{color:#009}.example-message-4 a:active{color:#006}.example-message-4:before{content:'';position:absolute;width:30px;text-align:center;top:0;height:100%;display:block;padding:0;background:#green}.example-message-4>:first-child:before{content:'';position:absolute;overflow:hidden;top:50%;margin-top:-5px}.example-message-4>:first-child:after{font-family:'icons-blank-theme';content:'\e606';font-size:28px;line-height:28px;color:#000;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;margin:-14px 0 0;position:absolute;top:15px;left:0;text-align:center;width:30px}.example-message-4:before{left:0}.example-message-4>:first-child:before{border:5px solid transparent;height:0;width:0;border-left-color:#green;left:30px}.example-message-4>:first-child:after{left:0}header.header{background-color:rgba(255,0,0,.2)}.column.main{background-color:rgba(255,255,0,.2)}.column.left{background-color:rgba(0,255,255,.2)}.column.right{background-color:rgba(0,0,255,.2)}footer.footer{background-color:rgba(0,0,0,.2)}.columns{box-sizing:border-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap}.columns:after{content:" ";display:block;height:0;clear:both;overflow:hidden;visibility:hidden}.columns>.column{padding-bottom:40px}@media (min-width: 600px){.page-layout-1column .column.main{ width:100%;-ms-flex-order:2;-webkit-order:2;order:2}.page-layout-3columns .column.main{width:66.66666667%;display:inline-block;-ms-flex-order:2;-webkit-order:2;order:2}.page-layout-2columns-left .column.main{width:83.33333333%;float:right;-ms-flex-order:2;-webkit-order:2;order:2}.page-layout-2columns-right .column.main{width:83.33333333%;float:left;-ms-flex-order:1;-webkit-order:1;order:1}.page-layout-3columns .column.left{width:16.66666667%;float:left;-ms-flex-order:1;-webkit-order:1;order:1}.page-layout-2columns-left .column.left{width:16.66666667%;float:left;-ms-flex-order:1;-webkit-order:1;order:1}.page-layout-2columns-right .column.left{width:16.66666667%;float:left;-ms-flex-order:1;-webkit-order:1;order:1}.page-layout-3columns .column.right{width:16.66666667%;float:right;-ms-flex-order:3;-webkit-order:3;order:3}.page-layout-2columns-left .column.right{width:16.66666667%;float:right;-ms-flex-order:2;-webkit-order:2;order:2}.page-layout-2columns-right .column.right{width:16.66666667%;float:right;-ms-flex-order:2;-webkit-order:2;order:2}}.layout-example-3 .column.main{width:60%;display:inline-block;-ms-flex-order:2;-webkit-order:2;order:2}.layout-example-3 .column.left{width:20%;float:left;-ms-flex-order:1;-webkit-order:1;order:1}.layout-example-3 .column.right{width:20%;float:right;-ms-flex-order:3;-webkit-order:3;order:3}.layout-example-3-1 .column.main{width:60%;float:left;-ms-flex-order:1;-webkit-order:1;order:1}.layout-example-3-1 .column.left{width:20%;display:inline-block;-ms-flex-order:2;-webkit-order:2;order:2}.layout-example-3-1 .column.right{width:20%;float:right;-ms-flex-order:3;-webkit-order:3;order:3}.pages>.label{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.pages .items{font-size:0;line-height:0;letter-spacing:-1px;white-space:nowrap;margin:0;padding:0;list-style:none none;display:inline-block;font-weight:700}.pages .item{font-size:1.2rem;font-size:12px;line-height:32px;letter-spacing:normal;margin:0 2px 0 0;display:inline-block}.pages .item .label{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.pages a.page{color:#1979c3;display:inline-block;padding:0 4px;text-decoration:none}.pages a.page:visited{color:#1979c3}.pages a.page:hover{color:#006bb4;text-decoration:none}.pages a.page:active{color:#ff5501}.pages strong.page{font-size:1.2rem;font-size:12px;line-height:32px;letter-spacing:normal;color:#333;display:inline-block;font-weight:700;padding:0 4px}.pages .action{border:1px solid #d1d1d1;color:#7d7d7d;display:inline-block;padding:0;text-decoration:none}.pages .action:visited{color:#7d7d7d}.pages .action:hover{color:#7d7d7d;text-decoration:none}.pages .action:active{color:#7d7d7d}.pages .action.next{display:inline-block;text-decoration:none}.pages .action.next:visited:before{color:#7d7d7d}.pages .action.next:active:before{color:#7d7d7d}.pages .action.next>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.pages .action.next:before{font-family:'icons-blank-theme';content:'\e608';font-size:46px;line-height:inherit;color:#7d7d7d;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0 0 0 -6px}.pages .action.next:hover:before{color:#7d7d7d}.pages .action.next:active:before{color:#7d7d7d}.pages .action.previous{display:inline-block;text-decoration:none}.pages .action.previous:visited:before{color:#7d7d7d}.pages .action.previous:active:before{color:#7d7d7d}.pages .action.previous>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.pages .action.previous:before{font-family:'icons-blank-theme';content:'\e617';font-size:46px;line-height:inherit;color:#7d7d7d;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0 0 0 -6px}.pages .action.previous:hover:before{color:#7d7d7d}.pages .action.previous:active:before{color:#7d7d7d}.example-pages-1>.label{display:inline-block;font-weight:700;font-size:1.2rem;font-size:12px;line-height:32px;letter-spacing:normal}.example-pages-1>.label:after{content:':'}.example-pages-1 .items{font-size:0;line-height:0;letter-spacing:-1px;white-space:nowrap;margin:0;padding:0;list-style:none none;display:inline-block;font-weight:700}.example-pages-1 .item{font-size:1.2rem;font-size:12px;line-height:32px;letter-spacing:normal;margin:0 3px;display:inline-block}.example-pages-1 .item .label{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-pages-1 a.page{background-color:#ccc;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top, #f4f4f4 0, #ccc 100%);background-image:linear-gradient(to bottom, #f4f4f4 0, #ccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f4f4f4', endColorstr='#cccccc', GradientType=0);border:1px solid #b3b3b3;color:#333;display:inline-block;padding:0 4px;text-decoration:none}.example-pages-1 a.page:visited{background-color:false;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top,false 0,false 100%);background-image:linear-gradient(to bottom,false 0,false 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='false', endColorstr='false', GradientType=0);color:#1979c3}.example-pages-1 a.page:hover{background-color:#f4f4f4;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top, #ccc 0, #f4f4f4 100%);background-image:linear-gradient(to bottom, #ccc 0, #f4f4f4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#f4f4f4', GradientType=0);border:1px solid #999;color:#333;text-decoration:none}.example-pages-1 a.page:active{background-color:false;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top,false 0,false 100%);background-image:linear-gradient(to bottom,false 0,false 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='false', endColorstr='false', GradientType=0);color:#ff5501}.example-pages-1 strong.page{background:#1979c3;border:1px solid #135d96;font-size:1.2rem;font-size:12px;line-height:32px;letter-spacing:normal;color:#f7b32e;display:inline-block;font-weight:700;padding:0 4px}.example-pages-1 .action{border:1px solid #d1d1d1;color:#7d7d7d;display:inline-block;padding:0;text-decoration:none}.example-pages-1 .action:visited{color:#7d7d7d}.example-pages-1 .action:hover{color:#ff5501;text-decoration:none}.example-pages-1 .action:active{color:#7d7d7d}.example-pages-1 .action.next{display:inline-block;text-decoration:none}.example-pages-1 .action.next:visited:before{color:#7d7d7d}.example-pages-1 .action.next:active:before{color:#7d7d7d}.example-pages-1 .action.next>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-pages-1 .action.next:before{font-family:'icons-blank-theme';content:'\e608';font-size:30px;line-height:inherit;color:#7d7d7d;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0 0 0 -6px}.example-pages-1 .action.next:hover:before{color:#ff5501}.example-pages-1 .action.next:active:before{color:#7d7d7d}.example-pages-1 .action.previous{display:inline-block;text-decoration:none}.example-pages-1 .action.previous:visited:before{color:#7d7d7d}.example-pages-1 .action.previous:active:before{color:#7d7d7d}.example-pages-1 .action.previous>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-pages-1 .action.previous:before{font-family:'icons-blank-theme';content:'\e617';font-size:30px;line-height:inherit;color:#7d7d7d;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0 0 0 -6px}.example-pages-1 .action.previous:hover:before{color:#ff5501}.example-pages-1 .action.previous:active:before{color:#7d7d7d}.example-pages-2>.label{display:inline-block;font-weight:700;font-size:1.2rem;font-size:12px;line-height:32px;letter-spacing:normal}.example-pages-2>.label:after{content:':'}.example-pages-2 .items{font-size:0;line-height:0;letter-spacing:-1px;white-space:nowrap;margin:0;padding:0;list-style:none none;display:inline-block;font-weight:700}.example-pages-2 .item{font-size:1.2rem;font-size:12px;line-height:32px;letter-spacing:normal;margin:0 2px 0 0;display:inline-block}.example-pages-2 .item .label{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-pages-2 a.page{color:#1979c3;display:inline-block;padding:0 4px;text-decoration:none}.example-pages-2 a.page:visited{color:#1979c3}.example-pages-2 a.page:hover{color:#006bb4;text-decoration:none}.example-pages-2 a.page:active{color:#ff5501}.example-pages-2 strong.page{font-size:1.2rem;font-size:12px;line-height:32px;letter-spacing:normal;color:#333;display:inline-block;font-weight:700;padding:0 4px}.example-pages-2 .action{border:1px solid #d1d1d1;color:#7d7d7d;display:inline-block;padding:0;text-decoration:none}.example-pages-2 .action:visited{color:#7d7d7d}.example-pages-2 .action:hover{color:#7d7d7d;text-decoration:none}.example-pages-2 .action:active{color:#7d7d7d}.example-pages-3>.label{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-pages-3 .items{font-size:0;line-height:0;letter-spacing:-1px;white-space:nowrap;margin:0;padding:0;list-style:none none;display:inline-block;font-weight:700}.example-pages-3 .item{font-size:1.2rem;font-size:12px;line-height:32px;letter-spacing:normal;margin:0 2px 0 0;display:inline-block}.example-pages-3 .item .label{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-pages-3 a.page{background:#1979c3;color:#fff;display:inline-block;padding:0 4px;text-decoration:none}.example-pages-3 a.page:visited{background:#1979c3;color:#fff}.example-pages-3 a.page:hover{background:#006bb4;color:#fff;text-decoration:none}.example-pages-3 a.page:active{background:#ff5501;color:#fff}.example-pages-3 strong.page{background:#1979c3;font-size:1.2rem;font-size:12px;line-height:32px;letter-spacing:normal;color:#fff;display:inline-block;font-weight:700;padding:0 4px}.example-pages-3 .action{background:#1979c3;border:1px solid #d1d1d1;color:#fff;display:inline-block;padding:0;text-decoration:none}.example-pages-3 .action:visited{background:#1979c3;color:#7d7d7d}.example-pages-3 .action:hover{background:#006bb4;color:#fff;text-decoration:none}.example-pages-3 .action:active{background:#ff5501;color:#fff}.example-pages-3 .action.next{display:inline-block;text-decoration:none}.example-pages-3 .action.next:visited:before{color:#7d7d7d}.example-pages-3 .action.next:active:before{color:#fff}.example-pages-3 .action.next>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-pages-3 .action.next:before{font-family:'icons-blank-theme';content:'\e608';font-size:46px;line-height:inherit;color:#fff;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0 0 0 -6px}.example-pages-3 .action.next:hover:before{color:#fff}.example-pages-3 .action.next:active:before{color:#fff}.example-pages-3 .action.previous{display:inline-block;text-decoration:none}.example-pages-3 .action.previous:visited:before{color:#7d7d7d}.example-pages-3 .action.previous:active:before{color:#fff}.example-pages-3 .action.previous>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-pages-3 .action.previous:before{font-family:'icons-blank-theme';content:'\e617';font-size:46px;line-height:inherit;color:#fff;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0 0 0 -6px}.example-pages-3 .action.previous:hover:before{color:#fff}.example-pages-3 .action.previous:active:before{color:#fff}.window.popup.popup-example{background:#fff;border:1px solid #aeaeae;padding:22px;width:auto;box-shadow:0 3px 3px rgba(0,0,0,.15);top:0;right:0;bottom:0;left:0;display:none;opacity:0;position:fixed;z-index:1001;transition:opacity .3s linear}.window.popup.popup-example .popup-header{margin:0 0 25px;padding-right:22px}.window.popup.popup-example .popup-header .title{font-size:1.8rem;font-weight:300;line-height:1.1;margin-top:1.5rem;margin-bottom:1rem}.window.popup.popup-example .popup-actions .action.close{position:absolute;display:inline-block;background-image:none;background:0;border:0;margin:0;padding:0;-moz-box-sizing:content-box;box-shadow:none;text-shadow:none;text-decoration:none;line-height:inherit;font-weight:400;top:10px;right:10px}.window.popup.popup-example .popup-actions .action.close>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.window.popup.popup-example .popup-actions .action.close:before{font-family:'icons-blank-theme';content:'\e616';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.window.popup.popup-example .popup-actions .action.close:hover:before{color:inherit}.window.popup.popup-example .popup-actions .action.close:active:before{color:inherit}.window.popup.popup-example .popup-actions .action.close:focus,.window.popup.popup-example .popup-actions .action.close:active{background:0;border:0}.window.popup.popup-example .popup-actions .action.close:hover{background:0;border:0}.window.popup.popup-example .popup-actions .action.close.disabled,.window.popup.popup-example .popup-actions .action.close[disabled],fieldset[disabled] .window.popup.popup-example .popup-actions .action.close{cursor:not-allowed;pointer-events:none;opacity:.5}.window.popup.popup-example.active{opacity:1}.window.popup.popup-example-1{background:#fff;border:1px solid #aeaeae;padding:22px;width:auto;box-shadow:0 3px 3px rgba(0,0,0,.15);top:0;right:0;bottom:0;left:0;display:none;opacity:0;position:fixed;z-index:1001;transition:opacity .3s linear}.window.popup.popup-example-1 .popup-header{margin:0 0 25px;padding-right:22px}.window.popup.popup-example-1 .popup-header .title{font-size:1.8rem;font-weight:300;line-height:1.1;margin-top:1.5rem;margin-bottom:1rem}.window.popup.popup-example-1 .popup-actions .action.close{position:absolute;display:inline-block;background-image:none;background:0;border:0;margin:0;padding:0;-moz-box-sizing:content-box;box-shadow:none;text-shadow:none;text-decoration:none;line-height:inherit;font-weight:400;top:10px;right:10px}.window.popup.popup-example-1 .popup-actions .action.close>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.window.popup.popup-example-1 .popup-actions .action.close:before{font-family:'icons-blank-theme';content:'\e616';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.window.popup.popup-example-1 .popup-actions .action.close:hover:before{color:inherit}.window.popup.popup-example-1 .popup-actions .action.close:active:before{color:inherit}.window.popup.popup-example-1 .popup-actions .action.close:focus,.window.popup.popup-example-1 .popup-actions .action.close:active{background:0;border:0}.window.popup.popup-example-1 .popup-actions .action.close:hover{background:0;border:0}.window.popup.popup-example-1 .popup-actions .action.close.disabled,.window.popup.popup-example-1 .popup-actions .action.close[disabled],fieldset[disabled] .window.popup.popup-example-1 .popup-actions .action.close{cursor:not-allowed;pointer-events:none;opacity:.5}.window.popup.popup-example-1.active{opacity:1}.window.overlay{transition:opacity .15s linear;position:fixed;top:0;right:0;bottom:0;left:0;background:#000;z-index:1000;opacity:0}.window.overlay.active{opacity:.5;filter:alpha(opacity=50)}.window.popup.popup-example-2{background:#fff;border:1px solid #aeaeae;padding:22px;width:auto;overflow-y:auto;max-height:200px;box-shadow:0 3px 3px rgba(0,0,0,.15);top:0;right:0;bottom:0;left:0;display:none;opacity:0;position:fixed;z-index:1001;transition:opacity .3s linear}.window.popup.popup-example-2 .popup-header{margin:0 0 25px;padding-right:22px}.window.popup.popup-example-2 .popup-header .title{font-size:1.8rem;font-weight:300;line-height:1.1;margin-top:1.5rem;margin-bottom:1rem}.window.popup.popup-example-2 .popup-actions .action.close{position:absolute;display:inline-block;background-image:none;background:0;border:0;margin:0;padding:0;-moz-box-sizing:content-box;box-shadow:none;text-shadow:none;text-decoration:none;line-height:inherit;font-weight:400;top:10px;right:10px}.window.popup.popup-example-2 .popup-actions .action.close>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.window.popup.popup-example-2 .popup-actions .action.close:before{font-family:'icons-blank-theme';content:'\e616';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.window.popup.popup-example-2 .popup-actions .action.close:hover:before{color:inherit}.window.popup.popup-example-2 .popup-actions .action.close:active:before{color:inherit}.window.popup.popup-example-2 .popup-actions .action.close:focus,.window.popup.popup-example-2 .popup-actions .action.close:active{background:0;border:0}.window.popup.popup-example-2 .popup-actions .action.close:hover{background:0;border:0}.window.popup.popup-example-2 .popup-actions .action.close.disabled,.window.popup.popup-example-2 .popup-actions .action.close[disabled],fieldset[disabled] .window.popup.popup-example-2 .popup-actions .action.close{cursor:not-allowed;pointer-events:none;opacity:.5}.window.popup.popup-example-2.active{opacity:1}.window.popup.popup-example-3{background:#fff;border:1px solid #aeaeae;padding:22px;width:auto;box-shadow:0 3px 3px rgba(0,0,0,.15);top:0;right:0;bottom:0;left:0;display:none;opacity:0;position:fixed;z-index:1001;transition:opacity .3s linear}.window.popup.popup-example-3 .popup-header{margin:0 0 25px;padding-right:22px}.window.popup.popup-example-3 .popup-header .title{font-size:1.8rem;font-weight:300;line-height:1.1;margin-top:1.5rem;margin-bottom:1rem}.window.popup.popup-example-3 .popup-content{overflow-y:auto;max-height:200px}.window.popup.popup-example-3 .popup-actions .action.close{position:absolute;display:inline-block;background-image:none;background:0;border:0;margin:0;padding:0;-moz-box-sizing:content-box;box-shadow:none;text-shadow:none;text-decoration:none;line-height:inherit;font-weight:400;top:10px;right:10px}.window.popup.popup-example-3 .popup-actions .action.close>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.window.popup.popup-example-3 .popup-actions .action.close:before{font-family:'icons-blank-theme';content:'\e616';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.window.popup.popup-example-3 .popup-actions .action.close:hover:before{color:inherit}.window.popup.popup-example-3 .popup-actions .action.close:active:before{color:inherit}.window.popup.popup-example-3 .popup-actions .action.close:focus,.window.popup.popup-example-3 .popup-actions .action.close:active{background:0;border:0}.window.popup.popup-example-3 .popup-actions .action.close:hover{background:0;border:0}.window.popup.popup-example-3 .popup-actions .action.close.disabled,.window.popup.popup-example-3 .popup-actions .action.close[disabled],fieldset[disabled] .window.popup.popup-example-3 .popup-actions .action.close{cursor:not-allowed;pointer-events:none;opacity:.5}.window.popup.popup-example-3.active{opacity:1}.window.popup.popup-example-4{background:#fff;border:1px solid #aeaeae;padding:22px;width:auto;box-shadow:0 3px 3px rgba(0,0,0,.15);top:0;right:0;bottom:0;left:0;display:none;opacity:0;position:fixed;z-index:1001;transition:opacity .3s linear}.window.popup.popup-example-4 .popup-header{margin:0 0 25px;padding-right:22px}.window.popup.popup-example-4 .popup-header .title{font-size:1.8rem;font-weight:300;line-height:1.1;margin-top:1.5rem;margin-bottom:1rem}.window.popup.popup-example-4 .popup-content{margin:0 0 20px}.window.popup.popup-example-4 .popup-footer{margin:0 20px}.window.popup.popup-example-4 .popup-actions .action.close{position:absolute;display:inline-block;background-image:none;background:0;border:0;margin:0;padding:0;-moz-box-sizing:content-box;box-shadow:none;text-shadow:none;text-decoration:none;line-height:inherit;font-weight:400;top:10px;right:10px}.window.popup.popup-example-4 .popup-actions .action.close>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.window.popup.popup-example-4 .popup-actions .action.close:before{font-family:'icons-blank-theme';content:'\e616';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.window.popup.popup-example-4 .popup-actions .action.close:hover:before{color:inherit}.window.popup.popup-example-4 .popup-actions .action.close:active:before{color:inherit}.window.popup.popup-example-4 .popup-actions .action.close:focus,.window.popup.popup-example-4 .popup-actions .action.close:active{background:0;border:0}.window.popup.popup-example-4 .popup-actions .action.close:hover{background:0;border:0}.window.popup.popup-example-4 .popup-actions .action.close.disabled,.window.popup.popup-example-4 .popup-actions .action.close[disabled],fieldset[disabled] .window.popup.popup-example-4 .popup-actions .action.close{cursor:not-allowed;pointer-events:none;opacity:.5}.window.popup.popup-example-4.active{opacity:1}.window.popup.popup-example-5{background:#fff;border:1px solid #aeaeae;padding:22px;width:auto;box-shadow:0 3px 3px rgba(0,0,0,.15);top:0;right:0;bottom:0;left:0;display:none;opacity:0;position:fixed;z-index:1001;transition:opacity .3s linear}.window.popup.popup-example-5 .popup-header{margin:0 0 25px;padding-right:22px}.window.popup.popup-example-5 .popup-header .title{font-size:2.6rem;font-weight:300;line-height:1.1;margin-top:0rem;margin-bottom:2rem}.window.popup.popup-example-5 .popup-actions .action.close{position:absolute;display:inline-block;background-image:none;background:0;border:0;margin:0;padding:0;-moz-box-sizing:content-box;box-shadow:none;text-shadow:none;text-decoration:none;line-height:inherit;font-weight:400;top:10px;right:10px}.window.popup.popup-example-5 .popup-actions .action.close>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.window.popup.popup-example-5 .popup-actions .action.close:before{font-family:'icons-blank-theme';content:'\e616';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.window.popup.popup-example-5 .popup-actions .action.close:hover:before{color:inherit}.window.popup.popup-example-5 .popup-actions .action.close:active:before{color:inherit}.window.popup.popup-example-5 .popup-actions .action.close:focus,.window.popup.popup-example-5 .popup-actions .action.close:active{background:0;border:0}.window.popup.popup-example-5 .popup-actions .action.close:hover{background:0;border:0}.window.popup.popup-example-5 .popup-actions .action.close.disabled,.window.popup.popup-example-5 .popup-actions .action.close[disabled],fieldset[disabled] .window.popup.popup-example-5 .popup-actions .action.close{cursor:not-allowed;pointer-events:none;opacity:.5}.window.popup.popup-example-5.active{opacity:1}.window.popup.popup-example-6{background:#fff;border:1px solid #aeaeae;padding:22px;width:auto;box-shadow:0 3px 3px rgba(0,0,0,.15);top:0;right:0;bottom:0;left:0;display:none;opacity:0;position:fixed;z-index:1001;transition:opacity .3s linear}.window.popup.popup-example-6 .popup-footer .actions.toolbar{text-align:left}.window.popup.popup-example-6 .popup-footer .actions.toolbar:before,.window.popup.popup-example-6 .popup-footer .actions.toolbar:after{content:"";display:table}.window.popup.popup-example-6 .popup-footer .actions.toolbar:after{clear:both}.window.popup.popup-example-6 .popup-footer .actions.toolbar .secondary{float:left}.window.popup.popup-example-6 .popup-footer .actions.toolbar .primary,.window.popup.popup-example-6 .popup-footer .actions.toolbar .secondary{display:inline-block}.window.popup.popup-example-6 .popup-footer .actions.toolbar .primary a.action,.window.popup.popup-example-6 .popup-footer .actions.toolbar .secondary a.action{display:inline-block}.window.popup.popup-example-6 .popup-footer .actions.toolbar .primary .action{margin:0 5px 0 0}.window.popup.popup-example-6 .popup-footer .actions.toolbar .secondary a.action{margin-top:6px}.window.popup.popup-example-6 .popup-header{margin:0 0 25px;padding-right:22px}.window.popup.popup-example-6 .popup-header .title{font-size:1.8rem;font-weight:300;line-height:1.1;margin-top:1.5rem;margin-bottom:1rem}.window.popup.popup-example-6 .popup-actions .action.close{position:absolute;display:inline-block;background-image:none;background:0;border:0;margin:0;padding:0;-moz-box-sizing:content-box;box-shadow:none;text-shadow:none;text-decoration:none;line-height:inherit;font-weight:400;top:10px;right:10px}.window.popup.popup-example-6 .popup-actions .action.close>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.window.popup.popup-example-6 .popup-actions .action.close:before{font-family:'icons-blank-theme';content:'\e616';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.window.popup.popup-example-6 .popup-actions .action.close:hover:before{color:inherit}.window.popup.popup-example-6 .popup-actions .action.close:active:before{color:inherit}.window.popup.popup-example-6 .popup-actions .action.close:focus,.window.popup.popup-example-6 .popup-actions .action.close:active{background:0;border:0}.window.popup.popup-example-6 .popup-actions .action.close:hover{background:0;border:0}.window.popup.popup-example-6 .popup-actions .action.close.disabled,.window.popup.popup-example-6 .popup-actions .action.close[disabled],fieldset[disabled] .window.popup.popup-example-6 .popup-actions .action.close{cursor:not-allowed;pointer-events:none;opacity:.5}.window.popup.popup-example-6.active{opacity:1}.window.popup.popup-example-7{background:#fff;border:1px solid #aeaeae;padding:22px;width:auto;box-shadow:0 3px 3px rgba(0,0,0,.15);top:0;right:0;bottom:0;left:0;display:none;opacity:0;position:fixed;z-index:1001;transition:opacity .3s linear}.window.popup.popup-example-7 .popup-header{margin:0 0 25px;padding-right:22px}.window.popup.popup-example-7 .popup-header .title{font-size:1.8rem;font-weight:300;line-height:1.1;margin-top:1.5rem;margin-bottom:1rem}.window.popup.popup-example-7 .popup-actions .action.close{position:absolute;top:10px;right:10px}.window.popup.popup-example-7.active{opacity:1}.window.popup.popup-example-8{background:#fff;border:1px solid #aeaeae;padding:22px;width:auto;box-shadow:0 3px 3px rgba(0,0,0,.15);top:0;right:0;bottom:0;left:0;display:none;opacity:0;position:fixed;z-index:1001;transition:opacity .3s linear}.window.popup.popup-example-8 .popup-header{margin:0 0 25px;padding-right:30px}.window.popup.popup-example-8 .popup-header .title{font-size:1.8rem;font-weight:300;line-height:1.1;margin-top:1.5rem;margin-bottom:1rem}.window.popup.popup-example-8 .popup-actions .action.close{position:absolute;display:inline-block;background-image:none;background:0;border:0;margin:0;padding:0;-moz-box-sizing:content-box;box-shadow:none;text-shadow:none;text-decoration:none;line-height:inherit;font-weight:400;top:10px;right:10px}.window.popup.popup-example-8 .popup-actions .action.close:before{font-family:'icons-blank-theme';content:'\e613';font-size:30px;line-height:22px;color:red;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:middle;text-align:center;margin:0}.window.popup.popup-example-8 .popup-actions .action.close:hover:before{color:#090}.window.popup.popup-example-8 .popup-actions .action.close:active:before{color:#00f}.window.popup.popup-example-8 .popup-actions .action.close:focus,.window.popup.popup-example-8 .popup-actions .action.close:active{background:0;border:0}.window.popup.popup-example-8 .popup-actions .action.close:hover{background:0;border:0}.window.popup.popup-example-8 .popup-actions .action.close.disabled,.window.popup.popup-example-8 .popup-actions .action.close[disabled],fieldset[disabled] .window.popup.popup-example-8 .popup-actions .action.close{cursor:not-allowed;pointer-events:none;opacity:.5}.window.popup.popup-example-8.active{opacity:1}.window.popup.popup-example-9{background:#fff;border:1px solid #aeaeae;padding:22px;width:auto;box-shadow:0 3px 3px rgba(0,0,0,.15);top:0;right:0;bottom:0;left:0;display:none;opacity:0;position:fixed;z-index:1001;transition:opacity .3s linear}.window.popup.popup-example-9 .popup-header{margin:0 0 25px;padding-right:22px}.window.popup.popup-example-9 .popup-header .title{font-size:1.8rem;font-weight:300;line-height:1.1;margin-top:1.5rem;margin-bottom:1rem}.window.popup.popup-example-9 .popup-actions .action.close{position:absolute;display:inline-block;background-image:none;background:0;border:0;margin:0;padding:0;-moz-box-sizing:content-box;box-shadow:none;text-shadow:none;text-decoration:none;line-height:inherit;font-weight:400;top:10px;right:10px}.window.popup.popup-example-9 .popup-actions .action.close>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.window.popup.popup-example-9 .popup-actions .action.close:before{font-family:'icons-blank-theme';content:'\e616';font-size:22px;line-height:22px;color:inherit;overflow:hidden;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;display:inline-block;vertical-align:top;text-align:center;margin:0}.window.popup.popup-example-9 .popup-actions .action.close:hover:before{color:inherit}.window.popup.popup-example-9 .popup-actions .action.close:active:before{color:inherit}.window.popup.popup-example-9 .popup-actions .action.close:focus,.window.popup.popup-example-9 .popup-actions .action.close:active{background:0;border:0}.window.popup.popup-example-9 .popup-actions .action.close:hover{background:0;border:0}.window.popup.popup-example-9 .popup-actions .action.close.disabled,.window.popup.popup-example-9 .popup-actions .action.close[disabled],fieldset[disabled] .window.popup.popup-example-9 .popup-actions .action.close{cursor:not-allowed;pointer-events:none;opacity:.5}.window.popup.popup-example-9.active{opacity:1}.window.overlay.example-overlay-1.active{transition:opacity .15s linear;position:fixed;top:0;right:0;bottom:0;left:0;background:#0f5293;z-index:1000;opacity:0}.window.overlay.example-overlay-1.active.active{opacity:.8;filter:alpha(opacity=80)}.example-ratings-1{overflow:hidden}.example-ratings-1:before{color:#c7c7c7;font-family:'icons-blank-theme';font-style:normal;font-size:28px;line-height:28px;letter-spacing:-10px;height:28px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;vertical-align:top;content:'\e605' '\e605' '\e605' '\e605' '\e605';position:absolute;z-index:1;display:block}.example-ratings-1 input[type="radio"]{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-ratings-1 input[type="radio"]:focus+label:before,.example-ratings-1 input[type="radio"]:checked+label:before{opacity:1}.example-ratings-1 label{position:absolute;display:block;cursor:pointer}.example-ratings-1 label span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-ratings-1 label:before{color:#ff5601;font-family:'icons-blank-theme';font-style:normal;font-size:28px;line-height:28px;letter-spacing:-10px;height:28px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;vertical-align:top;opacity:0}.example-ratings-1 label:hover:before{opacity:1}.example-ratings-1 label:hover~label:before{opacity:0}.example-ratings-1 .rating-5{z-index:2}.example-ratings-1 .rating-5:before{content:'\e605' '\e605' '\e605' '\e605' '\e605'}.example-ratings-1 .rating-4{z-index:3}.example-ratings-1 .rating-4:before{content:'\e605' '\e605' '\e605' '\e605'}.example-ratings-1 .rating-3{z-index:4}.example-ratings-1 .rating-3:before{content:'\e605' '\e605' '\e605'}.example-ratings-1 .rating-2{z-index:5}.example-ratings-1 .rating-2:before{content:'\e605' '\e605'}.example-ratings-1 .rating-1{z-index:6}.example-ratings-1 .rating-1:before{content:'\e605'}.example-ratings-2{overflow:hidden}.example-ratings-2:before{color:#c7c7c7;font-family:'icons-blank-theme';font-style:normal;font-size:28px;line-height:28px;letter-spacing:-10px;height:28px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;vertical-align:top;content:'\e605' '\e605' '\e605' '\e605' '\e605' '\e605' '\e605' '\e605';position:absolute;z-index:1;display:block}.example-ratings-2 input[type="radio"]{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-ratings-2 input[type="radio"]:focus+label:before,.example-ratings-2 input[type="radio"]:checked+label:before{opacity:1}.example-ratings-2 label{position:absolute;display:block;cursor:pointer}.example-ratings-2 label span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-ratings-2 label:before{color:#ff5601;font-family:'icons-blank-theme';font-style:normal;font-size:28px;line-height:28px;letter-spacing:-10px;height:28px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;vertical-align:top;opacity:0}.example-ratings-2 label:hover:before{opacity:1}.example-ratings-2 label:hover~label:before{opacity:0}.example-ratings-2 .rating-8{z-index:2}.example-ratings-2 .rating-8:before{content:'\e605' '\e605' '\e605' '\e605' '\e605' '\e605' '\e605' '\e605'}.example-ratings-2 .rating-7{z-index:3}.example-ratings-2 .rating-7:before{content:'\e605' '\e605' '\e605' '\e605' '\e605' '\e605' '\e605'}.example-ratings-2 .rating-6{z-index:4}.example-ratings-2 .rating-6:before{content:'\e605' '\e605' '\e605' '\e605' '\e605' '\e605'}.example-ratings-2 .rating-5{z-index:5}.example-ratings-2 .rating-5:before{content:'\e605' '\e605' '\e605' '\e605' '\e605'}.example-ratings-2 .rating-4{z-index:6}.example-ratings-2 .rating-4:before{content:'\e605' '\e605' '\e605' '\e605'}.example-ratings-2 .rating-3{z-index:7}.example-ratings-2 .rating-3:before{content:'\e605' '\e605' '\e605'}.example-ratings-2 .rating-2{z-index:8}.example-ratings-2 .rating-2:before{content:'\e605' '\e605'}.example-ratings-2 .rating-1{z-index:9}.example-ratings-2 .rating-1:before{content:'\e605'}.example-ratings-3{overflow:hidden}.example-ratings-3:before{color:#aff5e3;font-family:'icons-blank-theme';font-style:normal;font-size:28px;line-height:28px;letter-spacing:-10px;height:28px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;vertical-align:top;content:'\e605' '\e605' '\e605' '\e605' '\e605';position:absolute;z-index:1;display:block}.example-ratings-3 input[type="radio"]{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-ratings-3 input[type="radio"]:focus+label:before,.example-ratings-3 input[type="radio"]:checked+label:before{opacity:1}.example-ratings-3 label{position:absolute;display:block;cursor:pointer}.example-ratings-3 label span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-ratings-3 label:before{color:#0a6767;font-family:'icons-blank-theme';font-style:normal;font-size:28px;line-height:28px;letter-spacing:-10px;height:28px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;vertical-align:top;opacity:0}.example-ratings-3 label:hover:before{opacity:1}.example-ratings-3 label:hover~label:before{opacity:0}.example-ratings-3 .rating-5{z-index:2}.example-ratings-3 .rating-5:before{content:'\e605' '\e605' '\e605' '\e605' '\e605'}.example-ratings-3 .rating-4{z-index:3}.example-ratings-3 .rating-4:before{content:'\e605' '\e605' '\e605' '\e605'}.example-ratings-3 .rating-3{z-index:4}.example-ratings-3 .rating-3:before{content:'\e605' '\e605' '\e605'}.example-ratings-3 .rating-2{z-index:5}.example-ratings-3 .rating-2:before{content:'\e605' '\e605'}.example-ratings-3 .rating-1{z-index:6}.example-ratings-3 .rating-1:before{content:'\e605'}.example-ratings-4{overflow:hidden}.example-ratings-4:before{color:#c7c7c7;font-family:'icons-blank-theme';font-style:normal;font-size:28px;line-height:28px;letter-spacing:-10px;height:28px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;vertical-align:top;content:'\e600' '\e600' '\e600' '\e600' '\e600';position:absolute;z-index:1;display:block}.example-ratings-4 input[type="radio"]{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-ratings-4 input[type="radio"]:focus+label:before,.example-ratings-4 input[type="radio"]:checked+label:before{opacity:1}.example-ratings-4 label{position:absolute;display:block;cursor:pointer}.example-ratings-4 label span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-ratings-4 label:before{color:#ff5601;font-family:'icons-blank-theme';font-style:normal;font-size:28px;line-height:28px;letter-spacing:-10px;height:28px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;vertical-align:top;opacity:0}.example-ratings-4 label:hover:before{opacity:1}.example-ratings-4 label:hover~label:before{opacity:0}.example-ratings-4 .rating-5{z-index:2}.example-ratings-4 .rating-5:before{content:'\e600' '\e600' '\e600' '\e600' '\e600'}.example-ratings-4 .rating-4{z-index:3}.example-ratings-4 .rating-4:before{content:'\e600' '\e600' '\e600' '\e600'}.example-ratings-4 .rating-3{z-index:4}.example-ratings-4 .rating-3:before{content:'\e600' '\e600' '\e600'}.example-ratings-4 .rating-2{z-index:5}.example-ratings-4 .rating-2:before{content:'\e600' '\e600'}.example-ratings-4 .rating-1{z-index:6}.example-ratings-4 .rating-1:before{content:'\e600'}.exapmle-ratings-5 .control.rating.vote{overflow:hidden}.exapmle-ratings-5 .control.rating.vote:before{color:#c7c7c7;font-family:'icons-blank-theme';font-style:normal;font-size:28px;line-height:28px;letter-spacing:-10px;height:28px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;vertical-align:top;content:'\e605' '\e605' '\e605' '\e605' '\e605';position:absolute;z-index:1;display:block}.exapmle-ratings-5 .control.rating.vote input[type="radio"]{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.exapmle-ratings-5 .control.rating.vote input[type="radio"]:focus+label:before,.exapmle-ratings-5 .control.rating.vote input[type="radio"]:checked+label:before{opacity:1}.exapmle-ratings-5 .control.rating.vote label{position:absolute;display:block;cursor:pointer}.exapmle-ratings-5 .control.rating.vote label span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.exapmle-ratings-5 .control.rating.vote label:before{color:#ff5601;font-family:'icons-blank-theme';font-style:normal;font-size:28px;line-height:28px;letter-spacing:-10px;height:28px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased;vertical-align:top;opacity:0}.exapmle-ratings-5 .control.rating.vote label:hover:before{opacity:1}.exapmle-ratings-5 .control.rating.vote label:hover~label:before{opacity:0}.exapmle-ratings-5 .control.rating.vote .rating-5{z-index:2}.exapmle-ratings-5 .control.rating.vote .rating-5:before{content:'\e605' '\e605' '\e605' '\e605' '\e605'}.exapmle-ratings-5 .control.rating.vote .rating-4{z-index:3}.exapmle-ratings-5 .control.rating.vote .rating-4:before{content:'\e605' '\e605' '\e605' '\e605'}.exapmle-ratings-5 .control.rating.vote .rating-3{z-index:4}.exapmle-ratings-5 .control.rating.vote .rating-3:before{content:'\e605' '\e605' '\e605'}.exapmle-ratings-5 .control.rating.vote .rating-2{z-index:5}.exapmle-ratings-5 .control.rating.vote .rating-2:before{content:'\e605' '\e605'}.exapmle-ratings-5 .control.rating.vote .rating-1{z-index:6}.exapmle-ratings-5 .control.rating.vote .rating-1:before{content:'\e605'}.example-rating-summary-1{white-space:nowrap;overflow:hidden}.example-rating-summary-1 .rating-result{width:100px;display:inline-block;vertical-align:middle;position:relative}.example-rating-summary-1 .rating-result:before{position:absolute;top:0;left:0;width:100%;z-index:1;color:#c7c7c7;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-1 .rating-result>span{display:block;overflow:hidden}.example-rating-summary-1 .rating-result>span:before{position:relative;z-index:2;color:#ff5601;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-1 .rating-result>span span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-rating-summary-2{white-space:nowrap;overflow:hidden}.example-rating-summary-2 .rating-result{width:154px;display:inline-block;vertical-align:middle;position:relative}.example-rating-summary-2 .rating-result:before{position:absolute;top:0;left:0;width:100%;z-index:1;color:#c7c7c7;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-2 .rating-result>span{display:block;overflow:hidden}.example-rating-summary-2 .rating-result>span:before{position:relative;z-index:2;color:#ff5601;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-2 .rating-result>span span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-rating-summary-3{white-space:nowrap;overflow:hidden}.example-rating-summary-3 .rating-result{width:100px;display:inline-block;vertical-align:middle;position:relative}.example-rating-summary-3 .rating-result:before{position:absolute;top:0;left:0;width:100%;z-index:1;color:#aff5e3;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-3 .rating-result>span{display:block;overflow:hidden}.example-rating-summary-3 .rating-result>span:before{position:relative;z-index:2;color:#0a6767;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-3 .rating-result>span span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-rating-summary-4{white-space:nowrap;overflow:hidden}.example-rating-summary-4 .rating-result{width:100px;display:inline-block;vertical-align:middle;position:relative}.example-rating-summary-4 .rating-result:before{position:absolute;top:0;left:0;width:100%;z-index:1;color:#c7c7c7;display:block;font-family:'icons-blank-theme';content:'\e600' '\e600' '\e600' '\e600' '\e600';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-4 .rating-result>span{display:block;overflow:hidden}.example-rating-summary-4 .rating-result>span:before{position:relative;z-index:2;color:#ff5601;display:block;font-family:'icons-blank-theme';content:'\e600' '\e600' '\e600' '\e600' '\e600';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-4 .rating-result>span span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-rating-summary-5{white-space:nowrap;overflow:hidden}.example-rating-summary-5 .label{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-rating-summary-5 .rating-result{width:100px;display:inline-block;vertical-align:middle;position:relative}.example-rating-summary-5 .rating-result:before{position:absolute;top:0;left:0;width:100%;z-index:1;color:#c7c7c7;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-5 .rating-result>span{display:block;overflow:hidden}.example-rating-summary-5 .rating-result>span:before{position:relative;z-index:2;color:#ff5601;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-5 .rating-result>span span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-rating-summary-6 .rating-summary{white-space:nowrap;overflow:hidden}.example-rating-summary-6 .rating-summary .rating-result{width:100px;display:inline-block;vertical-align:middle;position:relative}.example-rating-summary-6 .rating-summary .rating-result:before{position:absolute;top:0;left:0;width:100%;z-index:1;color:#c7c7c7;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-6 .rating-summary .rating-result>span{display:block;overflow:hidden}.example-rating-summary-6 .rating-summary .rating-result>span:before{position:relative;z-index:2;color:#ff5601;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-6 .rating-summary .rating-result>span span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-rating-summary-7{white-space:nowrap;overflow:hidden}.example-rating-summary-7 .rating-result{width:100px;display:inline-block;vertical-align:middle;position:relative}.example-rating-summary-7 .rating-result:before{position:absolute;top:0;left:0;width:100%;z-index:1;color:#c7c7c7;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-7 .rating-result>span{display:block;overflow:hidden}.example-rating-summary-7 .rating-result>span:before{position:relative;z-index:2;color:#ff5601;display:block;font-family:'icons-blank-theme';content:'\e605' '\e605' '\e605' '\e605' '\e605';font-style:normal;font-size:28px;height:28px;line-height:28px;letter-spacing:-10px;speak:none;font-weight:400;-webkit-font-smoothing:antialiased}.example-rating-summary-7 .rating-result>span span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-rating-summary-7 .label{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-responsive-block{padding:10px}.example-sections-1{position:relative;z-index:1}.example-sections-1:before,.example-sections-1:after{content:"";display:table}.example-sections-1:after{clear:both}.example-sections-1>.item.title{float:left;width:auto}.example-sections-1>.item.title>.switch{display:block;height:20px;position:relative;z-index:2}.example-sections-1>.item.content{box-sizing:border-box;float:right;margin-top:20px;margin-left:-100%;width:100%}.example-sections-1>.item.content:before,.example-sections-1>.item.content:after{content:"";display:table}.example-sections-1>.item.content:after{clear:both}.example-sections-1>.item.content.active{display:block}.example-sections-1>.item.title{margin:0 5px 0 0}.example-sections-1>.item.title>.switch{font-size:1.4rem;font-weight:600;line-height:20px;color:#7d7d7d;text-decoration:none;background:#f0f0f0;border:1px solid #d1d1d1;border-bottom:0;height:20px;padding:5px 20px 5px 20px}.example-sections-1>.item.title>.switch:visited{color:#7d7d7d;text-decoration:none}.example-sections-1>.item.title>.switch:hover{color:#7d7d7d;text-decoration:none}.example-sections-1>.item.title>.switch:active{color:#333;text-decoration:none}.example-sections-1>.item.title:not(.disabled)>.switch:focus,.example-sections-1>.item.title:not(.disabled)>.switch:hover{background:#fcfcfc}.example-sections-1>.item.title:not(.disabled)>.switch:active,.example-sections-1>.item.title.active>.switch,.example-sections-1>.item.title.active>.switch:focus,.example-sections-1>.item.title.active>.switch:hover{background:#fff;color:#333}.example-sections-1>.item.title.active>.switch,.example-sections-1>.item.title.active>.switch:focus,.example-sections-1>.item.title.active>.switch:hover{padding-bottom:6px}.example-sections-1>.item.content{background:#fff;margin-top:31px;padding:20px 20px 20px 20px;border:1px solid #d1d1d1}.example-sections-2{position:relative;z-index:1}.example-sections-2:before,.example-sections-2:after{content:"";display:table}.example-sections-2:after{clear:both}.example-sections-2>.item.title{float:left;width:auto}.example-sections-2>.item.title>.switch{display:block;height:20px;position:relative;z-index:2}.example-sections-2>.item.content{box-sizing:border-box;float:right;margin-top:20px;margin-left:-100%;width:100%}.example-sections-2>.item.content:before,.example-sections-2>.item.content:after{content:"";display:table}.example-sections-2>.item.content:after{clear:both}.example-sections-2>.item.content.active{display:block}.example-sections-2>.item.title{margin:0 5px 0 0}.example-sections-2>.item.title>.switch{font-size:1.4rem;font-weight:600;line-height:20px;color:#7d7d7d;text-decoration:none;background:#f0f0f0;border:1px solid #d1d1d1;border-bottom:0;height:20px;padding:5px 20px 5px 20px}.example-sections-2>.item.title>.switch:visited{color:#7d7d7d;text-decoration:none}.example-sections-2>.item.title>.switch:hover{color:#7d7d7d;text-decoration:none}.example-sections-2>.item.title>.switch:active{color:#333;text-decoration:none}.example-sections-2>.item.title:not(.disabled)>.switch:focus,.example-sections-2>.item.title:not(.disabled)>.switch:hover{background:#fcfcfc}.example-sections-2>.item.title:not(.disabled)>.switch:active,.example-sections-2>.item.title.active>.switch,.example-sections-2>.item.title.active>.switch:focus,.example-sections-2>.item.title.active>.switch:hover{background:#fff;color:#333}.example-sections-2>.item.title.active>.switch,.example-sections-2>.item.title.active>.switch:focus,.example-sections-2>.item.title.active>.switch:hover{padding-bottom:6px}.example-sections-2>.item.content{background:#fff;margin-top:31px;padding:20px 20px 20px 20px;border:0;border-top:1px solid #d1d1d1}.example-sections-3{margin:0;padding:0}.example-sections-3>.item.title{box-sizing:border-box;float:none;width:100%}.example-sections-3>.item.title>.switch{display:block}.example-sections-3>.item.content{box-sizing:border-box;float:none;margin:0;display:block}.example-sections-3>.item.content:before,.example-sections-3>.item.content:after{content:"";display:table}.example-sections-3>.item.content:after{clear:both}.example-sections-3>.item.content.active{display:block}.example-sections-3>.item.title{margin:0 0 5px}.example-sections-3>.item.title>.switch{background:#f0f0f0;border-top:1px solid #d1d1d1;border-right:1px solid #d1d1d1;border-bottom:1px solid #d1d1d1;border-left:1px solid #d1d1d1;height:40px;padding:5px 20px 5px 20px;font-size:1.8rem;font-weight:600;line-height:40px;color:#7d7d7d;text-decoration:none}.example-sections-3>.item.title>.switch:visited{color:#7d7d7d;text-decoration:none}.example-sections-3>.item.title>.switch:hover{color:#7d7d7d;text-decoration:none}.example-sections-3>.item.title>.switch:active{color:#333;text-decoration:none}.example-sections-3>.item.title:not(.disabled)>.switch:focus,.example-sections-3>.item.title:not(.disabled)>.switch:hover{background:#fcfcfc}.example-sections-3>.item.title:not(.disabled)>.switch:active,.example-sections-3>.item.title.active>.switch,.example-sections-3>.item.title.active>.switch:focus,.example-sections-3>.item.title.active>.switch:hover{background:#fff;padding-bottom:5px}.example-sections-3>.item.content{background:#fff;border:1px solid #d1d1d1;margin:0 0 5px;padding:20px 20px 20px 20px}@media only screen and (max-width: 99999px){.example-sections-4{ position:relative;z-index:1}.example-sections-4:before,.example-sections-4:after{content:"";display:table}.example-sections-4:after{clear:both}.example-sections-4>.item.title{float:left;width:auto}.example-sections-4>.item.title>.switch{display:block;height:20px;position:relative;z-index:2}.example-sections-4>.item.content{box-sizing:border-box;float:right;margin-top:20px;margin-left:-100%;width:100%}.example-sections-4>.item.content:before,.example-sections-4>.item.content:after{content:"";display:table}.example-sections-4>.item.content:after{clear:both}.example-sections-4>.item.content.active{display:block}.example-sections-4>.item.title{margin:0 5px 0 0}.example-sections-4>.item.title>.switch{font-size:1.4rem;font-weight:600;line-height:20px;color:#7d7d7d;text-decoration:none;background:#f0f0f0;border:1px solid #d1d1d1;border-bottom:0;height:20px;padding:5px 20px 5px 20px}.example-sections-4>.item.title>.switch:visited{color:#7d7d7d;text-decoration:none}.example-sections-4>.item.title>.switch:hover{color:#7d7d7d;text-decoration:none}.example-sections-4>.item.title>.switch:active{color:#333;text-decoration:none}.example-sections-4>.item.title:not(.disabled)>.switch:focus,.example-sections-4>.item.title:not(.disabled)>.switch:hover{background:#fcfcfc}.example-sections-4>.item.title:not(.disabled)>.switch:active,.example-sections-4>.item.title.active>.switch,.example-sections-4>.item.title.active>.switch:focus,.example-sections-4>.item.title.active>.switch:hover{background:#fff;color:#333}.example-sections-4>.item.title.active>.switch,.example-sections-4>.item.title.active>.switch:focus,.example-sections-4>.item.title.active>.switch:hover{padding-bottom:6px}.example-sections-4>.item.content{background:#fff;margin-top:31px;padding:20px 20px 20px 20px;border:1px solid #d1d1d1}}@media only screen and (max-width: 768px){.example-sections-4{ margin:0;padding:0}.example-sections-4>.item.title{box-sizing:border-box;float:none;width:100%}.example-sections-4>.item.title>.switch{display:block}.example-sections-4>.item.content{box-sizing:border-box;float:none;margin:0;display:block}.example-sections-4>.item.content:before,.example-sections-4>.item.content:after{content:"";display:table}.example-sections-4>.item.content:after{clear:both}.example-sections-4>.item.content.active{display:block}.example-sections-4>.item.title{margin:0 0 5px}.example-sections-4>.item.title>.switch{background:#f0f0f0;border-top:1px solid #d1d1d1;border-right:1px solid #d1d1d1;border-bottom:1px solid #d1d1d1;border-left:1px solid #d1d1d1;height:40px;padding:5px 20px 5px 20px;font-size:1.8rem;font-weight:600;line-height:40px;color:#7d7d7d;text-decoration:none}.example-sections-4>.item.title>.switch:visited{color:#7d7d7d;text-decoration:none}.example-sections-4>.item.title>.switch:hover{color:#7d7d7d;text-decoration:none}.example-sections-4>.item.title>.switch:active{color:#333;text-decoration:none}.example-sections-4>.item.title:not(.disabled)>.switch:focus,.example-sections-4>.item.title:not(.disabled)>.switch:hover{background:#fcfcfc}.example-sections-4>.item.title:not(.disabled)>.switch:active,.example-sections-4>.item.title.active>.switch,.example-sections-4>.item.title.active>.switch:focus,.example-sections-4>.item.title.active>.switch:hover{background:#fff;padding-bottom:5px}.example-sections-4>.item.content{background:#fff;border:1px solid #d1d1d1;margin:0 0 5px;padding:20px 20px 20px 20px}}.example-sections-5{position:relative;z-index:1}.example-sections-5:before,.example-sections-5:after{content:"";display:table}.example-sections-5:after{clear:both}.example-sections-5>.item.title{float:left;width:auto}.example-sections-5>.item.title>.switch{display:block;height:20px;position:relative;z-index:2}.example-sections-5>.item.content{box-sizing:border-box;float:right;margin-top:20px;margin-left:-100%;width:100%}.example-sections-5>.item.content:before,.example-sections-5>.item.content:after{content:"";display:table}.example-sections-5>.item.content:after{clear:both}.example-sections-5>.item.content.active{display:block}.example-sections-6{margin:0;padding:0}.example-sections-6>.item.title{box-sizing:border-box;float:none;width:100%}.example-sections-6>.item.title>.switch{display:block}.example-sections-6>.item.content{box-sizing:border-box;float:none;margin:0;display:block}.example-sections-6>.item.content:before,.example-sections-6>.item.content:after{content:"";display:table}.example-sections-6>.item.content:after{clear:both}.example-sections-6>.item.content.active{display:block}.example-table-1{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%}.example-table-1 th{text-align:left}.example-table-1>tbody>tr>th,.example-table-1>tfoot>tr>th,.example-table-1>tbody>tr>td,.example-table-1>tfoot>tr>td{vertical-align:top}.example-table-1>thead>tr>th,.example-table-1>thead>tr>td{vertical-align:bottom}.example-table-1>thead>tr>th,.example-table-1>tbody>tr>th,.example-table-1>tfoot>tr>th,.example-table-1>thead>tr>td,.example-table-1>tbody>tr>td,.example-table-1>tfoot>tr>td{padding:8px 10px}.example-table-2>thead>tr>th,.example-table-2>tbody>tr>th,.example-table-2>tfoot>tr>th{color:#111;font-weight:700}.example-table-3{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%}.example-table-3 th{text-align:left}.example-table-3>tbody>tr>th,.example-table-3>tfoot>tr>th,.example-table-3>tbody>tr>td,.example-table-3>tfoot>tr>td{vertical-align:top}.example-table-3>thead>tr>th,.example-table-3>thead>tr>td{vertical-align:bottom}.example-table-3>thead>tr>th,.example-table-3>tbody>tr>th,.example-table-3>tfoot>tr>th,.example-table-3>thead>tr>td,.example-table-3>tbody>tr>td,.example-table-3>tfoot>tr>td{padding:8px 10px}.example-table-3>caption{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-table-4{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%}.example-table-4 th{text-align:left}.example-table-4>tbody>tr>th,.example-table-4>tfoot>tr>th,.example-table-4>tbody>tr>td,.example-table-4>tfoot>tr>td{vertical-align:top}.example-table-4>thead>tr>th,.example-table-4>thead>tr>td{vertical-align:bottom}.example-table-4>thead>tr>th,.example-table-4>tbody>tr>th,.example-table-4>tfoot>tr>th,.example-table-4>thead>tr>td,.example-table-4>tbody>tr>td,.example-table-4>tfoot>tr>td{padding:8px 10px}.example-table-4>thead>tr>td,.example-table-4>tbody>tr>td,.example-table-4>tfoot>tr>td{padding:15px 25px 5px 0}.example-table-4>thead>tr>th,.example-table-4>tbody>tr>th,.example-table-4>tfoot>tr>th{padding:15px 25px 10px 0}.example-table-5{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%;background:#fff}.example-table-5 th{text-align:left}.example-table-5>tbody>tr>th,.example-table-5>tfoot>tr>th,.example-table-5>tbody>tr>td,.example-table-5>tfoot>tr>td{vertical-align:top}.example-table-5>thead>tr>th,.example-table-5>thead>tr>td{vertical-align:bottom}.example-table-5>thead>tr>th,.example-table-5>tbody>tr>th,.example-table-5>tfoot>tr>th,.example-table-5>thead>tr>td,.example-table-5>tbody>tr>td,.example-table-5>tfoot>tr>td{padding:8px 10px}.example-table-5>thead{background:#ccf}.example-table-5>tfoot{background:#cff}.example-table-5>tbody>tr>td{background:#fcc}.example-table-5>tbody>tr>th{background:#ffc}.example-table-6{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%;border:1px solid #d1d1d1}.example-table-6 th{text-align:left}.example-table-6>tbody>tr>th,.example-table-6>tfoot>tr>th,.example-table-6>tbody>tr>td,.example-table-6>tfoot>tr>td{vertical-align:top}.example-table-6>thead>tr>th,.example-table-6>thead>tr>td{vertical-align:bottom}.example-table-6>thead>tr>th,.example-table-6>tbody>tr>th,.example-table-6>tfoot>tr>th,.example-table-6>thead>tr>td,.example-table-6>tbody>tr>td,.example-table-6>tfoot>tr>td{padding:8px 10px}.example-table-6>thead>tr>th,.example-table-6>tbody>tr>th,.example-table-6>tfoot>tr>th,.example-table-6>thead>tr>td,.example-table-6>tbody>tr>td,.example-table-6>tfoot>tr>td{border:1px solid #d1d1d1}.example-table-7{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%}.example-table-7 th{text-align:left}.example-table-7>tbody>tr>th,.example-table-7>tfoot>tr>th,.example-table-7>tbody>tr>td,.example-table-7>tfoot>tr>td{vertical-align:top}.example-table-7>thead>tr>th,.example-table-7>thead>tr>td{vertical-align:bottom}.example-table-7>thead>tr>th,.example-table-7>tbody>tr>th,.example-table-7>tfoot>tr>th,.example-table-7>thead>tr>td,.example-table-7>tbody>tr>td,.example-table-7>tfoot>tr>td{padding:8px 10px}.example-table-7>thead>tr>th,.example-table-7>tbody>tr>th,.example-table-7>tfoot>tr>th,.example-table-7>thead>tr>td,.example-table-7>tbody>tr>td,.example-table-7>tfoot>tr>td{border-top:1px solid #d1d1d1}.example-table-7>caption+thead>tr:first-child>th,.example-table-7>colgroup+thead>tr:first-child>th,.example-table-7>thead:first-child>tr:first-child>th,.example-table-7>caption+thead>tr:first-child>td,.example-table-7>colgroup+thead>tr:first-child>td,.example-table-7>thead:first-child>tr:first-child>td{border-top:0}.example-table-7>tbody+tbody{border-top:1px solid #d1d1d1}.example-table-8{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%}.example-table-8 th{text-align:left}.example-table-8>tbody>tr>th,.example-table-8>tfoot>tr>th,.example-table-8>tbody>tr>td,.example-table-8>tfoot>tr>td{vertical-align:top}.example-table-8>thead>tr>th,.example-table-8>thead>tr>td{vertical-align:bottom}.example-table-8>thead>tr>th,.example-table-8>tbody>tr>th,.example-table-8>tfoot>tr>th,.example-table-8>thead>tr>td,.example-table-8>tbody>tr>td,.example-table-8>tfoot>tr>td{padding:8px 10px}.example-table-8>thead>tr>th,.example-table-8>tbody>tr>th,.example-table-8>tfoot>tr>th,.example-table-8>thead>tr>td,.example-table-8>tbody>tr>td,.example-table-8>tfoot>tr>td{border-left:1px solid #d1d1d1}.example-table-8>thead>tr>th:first-child,.example-table-8>tbody>tr>th:first-child,.example-table-8>tfoot>tr>th:first-child,.example-table-8>thead>tr>td:first-child,.example-table-8>tbody>tr>td:first-child,.example-table-8>tfoot>tr>td:first-child{border-left:0}.example-table-9{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%;border:0}.example-table-9 th{text-align:left}.example-table-9>tbody>tr>th,.example-table-9>tfoot>tr>th,.example-table-9>tbody>tr>td,.example-table-9>tfoot>tr>td{vertical-align:top}.example-table-9>thead>tr>th,.example-table-9>thead>tr>td{vertical-align:bottom}.example-table-9>thead>tr>th,.example-table-9>tbody>tr>th,.example-table-9>tfoot>tr>th,.example-table-9>thead>tr>td,.example-table-9>tbody>tr>td,.example-table-9>tfoot>tr>td{padding:8px 10px}.example-table-9>thead>tr>th,.example-table-9>tbody>tr>th,.example-table-9>tfoot>tr>th,.example-table-9>thead>tr>td,.example-table-9>tbody>tr>td,.example-table-9>tfoot>tr>td{border:0}.example-table-9>thead>tr>th,.example-table-9>thead>tr>td{border-bottom:1px solid #d1d1d1}.example-table-10{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%;border:0}.example-table-10 th{text-align:left}.example-table-10>tbody>tr>th,.example-table-10>tfoot>tr>th,.example-table-10>tbody>tr>td,.example-table-10>tfoot>tr>td{vertical-align:top}.example-table-10>thead>tr>th,.example-table-10>thead>tr>td{vertical-align:bottom}.example-table-10>thead>tr>th,.example-table-10>tbody>tr>th,.example-table-10>tfoot>tr>th,.example-table-10>thead>tr>td,.example-table-10>tbody>tr>td,.example-table-10>tfoot>tr>td{padding:8px 10px}.example-table-10>thead>tr>th,.example-table-10>tbody>tr>th,.example-table-10>tfoot>tr>th,.example-table-10>thead>tr>td,.example-table-10>tbody>tr>td,.example-table-10>tfoot>tr>td{border:0}.example-table-11{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%}.example-table-11 th{text-align:left}.example-table-11>tbody>tr>th,.example-table-11>tfoot>tr>th,.example-table-11>tbody>tr>td,.example-table-11>tfoot>tr>td{vertical-align:top}.example-table-11>thead>tr>th,.example-table-11>thead>tr>td{vertical-align:bottom}.example-table-11>thead>tr>th,.example-table-11>tbody>tr>th,.example-table-11>tfoot>tr>th,.example-table-11>thead>tr>td,.example-table-11>tbody>tr>td,.example-table-11>tfoot>tr>td{padding:8px 10px}.example-table-11>tbody>tr:nth-child(even)>td,.example-table-11>tbody>tr:nth-child(even)>th{background:#ffc;color:#000}.example-table-12{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%}.example-table-12 th{text-align:left}.example-table-12>tbody>tr>th,.example-table-12>tfoot>tr>th,.example-table-12>tbody>tr>td,.example-table-12>tfoot>tr>td{vertical-align:top}.example-table-12>thead>tr>th,.example-table-12>thead>tr>td{vertical-align:bottom}.example-table-12>thead>tr>th,.example-table-12>tbody>tr>th,.example-table-12>tfoot>tr>th,.example-table-12>thead>tr>td,.example-table-12>tbody>tr>td,.example-table-12>tfoot>tr>td{padding:8px 10px}.example-table-12>tbody>tr:nth-child(even):hover>td,.example-table-12>tbody>tr:nth-child(even):hover>th{background:#f0f0f0}.example-table-12>tbody>tr:nth-child(odd):hover>td,.example-table-12>tbody>tr:nth-child(odd):hover>th{background:#f0f0f0}.example-table-13{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%;border:1px solid #d1d1d1}.example-table-13 th{text-align:left}.example-table-13>tbody>tr>th,.example-table-13>tfoot>tr>th,.example-table-13>tbody>tr>td,.example-table-13>tfoot>tr>td{vertical-align:top}.example-table-13>thead>tr>th,.example-table-13>thead>tr>td{vertical-align:bottom}.example-table-13>thead>tr>th,.example-table-13>tbody>tr>th,.example-table-13>tfoot>tr>th,.example-table-13>thead>tr>td,.example-table-13>tbody>tr>td,.example-table-13>tfoot>tr>td{padding:8px 10px}.example-table-13>thead>tr>th,.example-table-13>tbody>tr>th,.example-table-13>tfoot>tr>th,.example-table-13>thead>tr>td,.example-table-13>tbody>tr>td,.example-table-13>tfoot>tr>td{border:1px solid #d1d1d1}.example-table-13>tbody>tr:nth-child(odd)>td,.example-table-13>tbody>tr:nth-child(odd)>th{background:#fff}.example-table-13>tbody>tr:nth-child(even):hover>td,.example-table-13>tbody>tr:nth-child(even):hover>th{background:#f0f0f0}.example-table-13>tbody>tr:nth-child(odd):hover>td,.example-table-13>tbody>tr:nth-child(odd):hover>th{background:#f0f0f0}@media only screen and (max-width: 768px){.example-table-14{ width:100%;overflow-y:hidden;overflow-x:auto;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}}.example-table-15{border-collapse:collapse;border-spacing:0;max-width:100%;width:100%;border:1px solid #d1d1d1}.example-table-15 th{text-align:left}.example-table-15>tbody>tr>th,.example-table-15>tfoot>tr>th,.example-table-15>tbody>tr>td,.example-table-15>tfoot>tr>td{vertical-align:top}.example-table-15>thead>tr>th,.example-table-15>thead>tr>td{vertical-align:bottom}.example-table-15>thead>tr>th,.example-table-15>tbody>tr>th,.example-table-15>tfoot>tr>th,.example-table-15>thead>tr>td,.example-table-15>tbody>tr>td,.example-table-15>tfoot>tr>td{padding:8px 10px}.example-table-15>thead>tr>th,.example-table-15>tbody>tr>th,.example-table-15>tfoot>tr>th,.example-table-15>thead>tr>td,.example-table-15>tbody>tr>td,.example-table-15>tfoot>tr>td{border:1px solid #d1d1d1}.example-table-15>tbody>tr:nth-child(odd)>td,.example-table-15>tbody>tr:nth-child(odd)>th{background:#fff}.example-table-15>tbody>tr:nth-child(even):hover>td,.example-table-15>tbody>tr:nth-child(even):hover>th{background:#f0f0f0}.example-table-15>tbody>tr:nth-child(odd):hover>td,.example-table-15>tbody>tr:nth-child(odd):hover>th{background:#f0f0f0}@media only screen and (max-width: 768px){.example-table-15{ border:0;display:block;background:#cff}.example-table-15>tbody>tr:nth-child(odd)>td,.example-table-15>tbody>tr:nth-child(odd)>th{background:#cff}.example-table-15>tbody>tr:nth-child(even):hover>td,.example-table-15>tbody>tr:nth-child(even):hover>th{background:#cff}.example-table-15>tbody>tr:nth-child(odd):hover>td,.example-table-15>tbody>tr:nth-child(odd):hover>th{background:#cff}.example-table-15>thead>tr>th{display:none}.example-table-15>tbody{display:block}.example-table-15>tbody>tr{display:block}.example-table-15>tbody>tr td,.example-table-15>tbody>tr th{border-bottom:0;display:block;padding:5px 0}.example-table-15>tbody>tr td:before,.example-table-15>tbody>tr th:before{content:attr(data-th) ":";display:inline-block;padding-right:10px;color:#111;font-weight:700}.example-table-15>tbody>tr td{background:#cff}.example-table-15>tbody>tr>th{background-color:#ffc!important}}.example-tooltip-bottom{position:relative}.example-tooltip-bottom .tooltip-content{z-index:100;background:#fff;min-width:210px;max-width:360px;padding:12px 16px;display:none;position:absolute;text-align:left;color:#333;line-height:1.4;border:1px solid #bbb;top:100%;left:0;margin-top:5px}.example-tooltip-bottom .tooltip-content:after,.example-tooltip-bottom .tooltip-content:before{border:solid transparent;content:'';height:0;width:0;position:absolute}.example-tooltip-bottom .tooltip-content:after{border-color:transparent;border-width:5px}.example-tooltip-bottom .tooltip-content:before{border-color:transparent;border-width:6px}.example-tooltip-bottom .tooltip-content:after,.example-tooltip-bottom .tooltip-content:before{bottom:100%}.example-tooltip-bottom .tooltip-content:after{border-bottom-color:#fff;margin-left:-5px;left:15px}.example-tooltip-bottom .tooltip-content:before{border-bottom-color:#bbb;margin-left:-6px;left:15px}.example-tooltip-bottom .tooltip-toggle{cursor:help}.example-tooltip-bottom .tooltip-toggle:hover+.tooltip-content,.example-tooltip-bottom .tooltip-toggle:focus+.tooltip-content,.example-tooltip-bottom:hover .tooltip-content{display:block}.example-tooltip-left{position:relative}.example-tooltip-left .tooltip-content{z-index:100;background:#fff;min-width:210px;max-width:360px;padding:12px 16px;display:none;position:absolute;text-align:left;color:#333;line-height:1.4;border:1px solid #bbb;right:100%;top:0;margin-right:5px}.example-tooltip-left .tooltip-content:after,.example-tooltip-left .tooltip-content:before{border:solid transparent;content:'';height:0;width:0;position:absolute}.example-tooltip-left .tooltip-content:after{border-color:transparent;border-width:5px}.example-tooltip-left .tooltip-content:before{border-color:transparent;border-width:6px}.example-tooltip-left .tooltip-content:after,.example-tooltip-left .tooltip-content:before{left:100%}.example-tooltip-left .tooltip-content:after{border-left-color:#fff;margin-top:-5px;top:15px}.example-tooltip-left .tooltip-content:before{border-left-color:#bbb;margin-top:-6px;top:15px}.example-tooltip-left .tooltip-toggle{cursor:help}.example-tooltip-left .tooltip-toggle:hover+.tooltip-content,.example-tooltip-left .tooltip-toggle:focus+.tooltip-content,.example-tooltip-left:hover .tooltip-content{display:block}.example-tooltip-right{position:relative}.example-tooltip-right .tooltip-content{z-index:100;background:#fff;min-width:210px;max-width:360px;padding:12px 16px;display:none;position:absolute;text-align:left;color:#333;line-height:1.4;border:1px solid #bbb;left:100%;top:0;margin-left:5px}.example-tooltip-right .tooltip-content:after,.example-tooltip-right .tooltip-content:before{border:solid transparent;content:'';height:0;width:0;position:absolute}.example-tooltip-right .tooltip-content:after{border-color:transparent;border-width:5px}.example-tooltip-right .tooltip-content:before{border-color:transparent;border-width:6px}.example-tooltip-right .tooltip-content:after,.example-tooltip-right .tooltip-content:before{right:100%}.example-tooltip-right .tooltip-content:after{border-right-color:#fff;margin-top:-5px;top:15px}.example-tooltip-right .tooltip-content:before{border-right-color:#bbb;margin-top:-6px;top:15px}.example-tooltip-right .tooltip-toggle{cursor:help}.example-tooltip-right .tooltip-toggle:hover+.tooltip-content,.example-tooltip-right .tooltip-toggle:focus+.tooltip-content,.example-tooltip-right:hover .tooltip-content{display:block}.example-tooltip-top{position:relative}.example-tooltip-top .tooltip-content{z-index:100;background:#fff;min-width:210px;max-width:360px;padding:12px 16px;display:none;position:absolute;text-align:left;color:#333;line-height:1.4;border:1px solid #bbb;bottom:100%;left:0;margin-bottom:5px}.example-tooltip-top .tooltip-content:after,.example-tooltip-top .tooltip-content:before{border:solid transparent;content:'';height:0;width:0;position:absolute}.example-tooltip-top .tooltip-content:after{border-color:transparent;border-width:5px}.example-tooltip-top .tooltip-content:before{border-color:transparent;border-width:6px}.example-tooltip-top .tooltip-content:after,.example-tooltip-top .tooltip-content:before{top:100%}.example-tooltip-top .tooltip-content:after{border-top-color:#fff;margin-left:-5px;left:15px}.example-tooltip-top .tooltip-content:before{border-top-color:#bbb;margin-left:-6px;left:15px}.example-tooltip-top .tooltip-toggle{cursor:help}.example-tooltip-top .tooltip-toggle:hover+.tooltip-content,.example-tooltip-top .tooltip-toggle:focus+.tooltip-content,.example-tooltip-top:hover .tooltip-content{display:block}html{font-size:62.5%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;font-size-adjust:100%}body{font-size:1.4rem;color:#333;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-weight:400;font-style:normal;line-height:1.42857143}p{margin-top:0rem;margin-bottom:1rem}abbr[title]{cursor:help;border-bottom:1px dotted #d1d1d1}b,strong{font-weight:700}em,i{font-style:italic}mark{background:#f0f0f0;color:#000}small,.small{font-size:12px}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #d1d1d1}sub,sup{font-size:71.42857143%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dfn{font-style:italic}h1{font-size:2.6rem;font-weight:300;line-height:1.1;margin-top:0rem;margin-bottom:2rem}h2{font-size:2.6rem;font-weight:300;line-height:1.1;margin-top:2.5rem;margin-bottom:2rem}h3{font-size:1.8rem;font-weight:300;line-height:1.1;margin-top:1.5rem;margin-bottom:1rem}h4{font-size:1.4rem;font-weight:700;line-height:1.1;margin-top:2rem;margin-bottom:2rem}h5{font-size:1.2rem;font-weight:700;line-height:1.1;margin-top:2rem;margin-bottom:2rem}h6{font-size:1rem;font-weight:700;line-height:1.1;margin-top:2rem;margin-bottom:2rem}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small{font-size:71.42857143%;color:#333;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-weight:400;font-style:normal;line-height:1}a,.alink{color:#1979c3;text-decoration:none}a:visited,.alink:visited{color:#1979c3;text-decoration:none}a:hover,.alink:hover{color:#006bb4;text-decoration:underline}a:active,.alink:active{color:#ff5501;text-decoration:underline}ul,ol{margin-top:0rem;margin-bottom:2.5rem}ul>li,ol>li{margin-top:0rem;margin-bottom:1rem}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}dl{margin-top:0;margin-bottom:20px}dt{font-weight:700;margin-top:0;margin-bottom:5px}dd{margin-top:0;margin-bottom:10px;margin-left:0}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,'Courier New',monospace}code{background:#f0f0f0;color:#111;font-size:1.2rem;padding:2px 4px;white-space:nowrap}kbd{background:#f0f0f0;color:#111;font-size:1.2rem;padding:2px 4px}pre{background:#f0f0f0;border:1px solid #d1d1d1;color:#111;display:block;font-size:1.2rem;margin:0 0 10px;line-height:1.42857143;padding:10px;word-break:break-all;word-wrap:break-word}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}blockquote{border-left:0 solid #d1d1d1;margin:0 0 20px 40px;padding:0;font-size:1.4rem;color:#333;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-weight:400;font-style:italic;line-height:1.42857143}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{color:#333;display:block;font-size:1rem;line-height:1.42857143}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}blockquote cite{font-style:normal}blockquote:before,blockquote:after{content:""}q{quotes:none}q:before,q:after{content:'';content:none}cite{font-style:normal}.example-line-height{line-height:3rem}.example-word-wrap{word-break:break-all;word-break:break-word;word-wrap:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;background:#ccc;width:120px}.example-text-overflow{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:#ccc;width:120px}.example-text-hide{background-color:transparent;border:0;font:0/0 a;color:transparent;text-shadow:none}.example-hyphens{word-wrap:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto}.example-hyphens-none{word-wrap:break-word;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}.example-typography{color:#fc0;font-family:Menlo,Monaco,Consolas,'Courier New',monospace;font-weight:500;font-style:italic;line-height:1.2}.example-list-reset-styles{margin:0;padding:0;list-style:none none}.example-list-inline{margin:0;padding:0;list-style:none none}.example-list-inline>li{display:inline-block;vertical-align:top}.example-link-default{color:#1979c3;text-decoration:none}.example-link-default:visited{color:#1979c3;text-decoration:none}.example-link-default:hover{color:#006bb4;text-decoration:underline}.example-link-default:active{color:#ff5501;text-decoration:underline}.example-link{color:#008000;text-decoration:none}.example-link:visited{color:#1979c3;text-decoration:none}.example-link:hover{color:#ffa500;text-decoration:none}.example-link:active{color:#ff5501;text-decoration:underline}.example-heading{font-size:2.6rem;font-weight:300;line-height:1.1;margin-top:0rem;margin-bottom:2rem}.example-heading-2{font-size:2.6rem;font-weight:300;line-height:1.1;margin-top:2.5rem;margin-bottom:2rem}html{font-size:62.5%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;font-size-adjust:100%}body{font-size:1.4rem;color:#333;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-weight:400;font-style:normal;line-height:1.42857143}p{margin-top:0rem;margin-bottom:1rem}abbr[title]{cursor:help;border-bottom:1px dotted #d1d1d1}b,strong{font-weight:700}em,i{font-style:italic}mark{background:#f0f0f0;color:#000}small,.small{font-size:12px}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #d1d1d1}sub,sup{font-size:71.42857143%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dfn{font-style:italic}h1{font-size:2.6rem;font-weight:300;line-height:1.1;margin-top:0rem;margin-bottom:2rem}h2{font-size:2.6rem;font-weight:300;line-height:1.1;margin-top:2.5rem;margin-bottom:2rem}h3{font-size:1.8rem;font-weight:300;line-height:1.1;margin-top:1.5rem;margin-bottom:1rem}h4{font-size:1.4rem;font-weight:700;line-height:1.1;margin-top:2rem;margin-bottom:2rem}h5{font-size:1.2rem;font-weight:700;line-height:1.1;margin-top:2rem;margin-bottom:2rem}h6{font-size:1rem;font-weight:700;line-height:1.1;margin-top:2rem;margin-bottom:2rem}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small{font-size:71.42857143%;color:#333;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-weight:400;font-style:normal;line-height:1}a,.alink{color:#1979c3;text-decoration:none}a:visited,.alink:visited{color:#1979c3;text-decoration:none}a:hover,.alink:hover{color:#006bb4;text-decoration:underline}a:active,.alink:active{color:#ff5501;text-decoration:underline}ul,ol{margin-top:0rem;margin-bottom:2.5rem}ul>li,ol>li{margin-top:0rem;margin-bottom:1rem}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}dl{margin-top:0;margin-bottom:20px}dt{font-weight:700;margin-top:0;margin-bottom:5px}dd{margin-top:0;margin-bottom:10px;margin-left:0}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,'Courier New',monospace}code{background:#f0f0f0;color:#111;font-size:1.2rem;padding:2px 4px;white-space:nowrap}kbd{background:#f0f0f0;color:#111;font-size:1.2rem;padding:2px 4px}pre{background:#f0f0f0;border:1px solid #d1d1d1;color:#111;display:block;font-size:1.2rem;margin:0 0 10px;line-height:1.42857143;padding:10px;word-break:break-all;word-wrap:break-word}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}blockquote{border-left:0 solid #d1d1d1;margin:0 0 20px 40px;padding:0;font-size:1.4rem;color:#333;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-weight:400;font-style:italic;line-height:1.42857143}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{color:#333;display:block;font-size:1rem;line-height:1.42857143}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}blockquote cite{font-style:normal}blockquote:before,blockquote:after{content:""}q{quotes:none}q:before,q:after{content:'';content:none}cite{font-style:normal}.example-clearfix-container-1{border:1px solid red}.example-clearfix-container-2{border:1px solid #0f0}.example-clearfix-container-2:before,.example-clearfix-container-2:after{content:"";display:table}.example-clearfix-container-2:after{clear:both}.example-clearfix-item.left{float:left}.example-clearfix-item.right{float:right}.example-visibility-hidden{height:0;visibility:hidden}.example-visually-hidden-1{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-visually-hidden-2{background:#fdf0d5;padding:5px;border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.example-visually-hidden-2{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.example-css-container{padding:20px;background:#e8e8e8}.example-rotate{background:red;position:absolute;height:20px;width:40px;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.example-placeholder::-webkit-input-placeholder{color:#808080;font-weight:700}.example-placeholder:-moz-placeholder{color:#808080;font-weight:700}.example-placeholder::-moz-placeholder{color:#808080;font-weight:700}.example-placeholder:-ms-input-placeholder{color:#808080;font-weight:700}.example-background-gradient-1{background-color:#ccf;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top, #cff 0, #ccf 100%);background-image:linear-gradient(to bottom, #cff 0, #ccf 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ccffff', endColorstr='#ccccff', GradientType=0)}.example-background-gradient-2{background-color:#ccf;background-repeat:repeat-x;background-image:-webkit-linear-gradient(left,color-stop( #cff 0),color-stop( #ccf 100%));background-image:linear-gradient(to right, #cff 0, #ccf 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ccffff', endColorstr='#ccccff', GradientType=1)}.example-background-gradient-3-wrapper{background:#ffc;padding:10px}.example-background-gradient-3{background-color:rgba(255,255,255,0);background-repeat:repeat-x;background-image:-webkit-linear-gradient(left,color-stop(rgba(255,255,255,0) 0),color-stop( #ccf 100%));background-image:linear-gradient(to right,rgba(255,255,255,0) 0, #ccf 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='rgba(255, 255, 255, 0)',endColorstr='#ccccff',GradientType=1)}body{padding:15px;background-image:none}</style></head><body><nav class="bar top cf"><div class="container"><a href="index.html" class="brand">Magento UI Library</a><ul class="menu"><li><a href="#" data-toggle="dropdown-1" unselectable="on" class="dropdown-toggle">files</a><ul id="dropdown-1" hidden class="dropdown"><li><a href="actions-toolbar.html">actions-toolbar</a></li><li><a href="breadcrumbs.html">breadcrumbs</a></li><li><a href="buttons.html">buttons</a></li><li><a href="docs.html">docs</a></li><li><a href="dropdowns.html">dropdowns</a></li><li><a href="forms.html">forms</a></li><li><a href="icons.html">icons</a></li><li><a href="layout.html">layout</a></li><li><a href="lib.html">lib</a></li><li><a href="loaders.html">loaders</a></li><li><a href="messages.html">messages</a></li><li><a href="pages.html">pages</a></li><li><a href="popups.html">popups</a></li><li><a href="rating.html">rating</a></li><li><a href="resets.html">resets</a></li><li><a href="responsive.html">responsive</a></li><li><a href="sections.html">sections</a></li><li><a href="tables.html">tables</a></li><li><a href="tooltips.html">tooltips</a></li><li><a href="typography.html">typography</a></li><li><a href="utilities.html">utilities</a></li><li><a href="variables.html">variables</a></li></ul></li></ul><div class="nav"><button title="Table of Contents" data-toggle="nav-toc"><svg viewBox="0 0 512 512" height="22" width="22" class="icon"><path d="M108.9,403.1V462H50v-58.9H108.9z M108.9,285.4H50v58.9h58.9V285.4zM108.9,50H50v58.9h58.9V50z M108.9,167.7H50v58.9h58.9V167.7z M167.7,344.3H462v-58.9H167.7V344.3zM167.7,50v58.9H462V50H167.7z M167.7,462H462v-58.9H167.7V462z M167.7,226.6H462v-58.9H167.7V226.6z"></path></svg></button><input type="search" placeholder="Search" class="search"></div></div></nav><section class="container"><article id="actions-toolbar" class="section"><div class="docs"><a href="#actions-toolbar" class="permalink"><svg viewBox="0 0 512 512" height="32" width="32" class="icon"><path d="M156.2,199.7c7.5-7.5,15.9-13.8,24.8-18.7c49.6-27.3,113.1-12.8,145,35.5l-38.5,38.5c-11.1-25.2-38.5-39.6-65.8-33.5c-10.3,2.3-20.1,7.4-28,15.4l-73.9,73.9c-22.4,22.4-22.4,58.9,0,81.4c22.4,22.4,58.9,22.4,81.4,0l22.8-22.8c20.7,8.2,42.9,11.5,64.9,9.9l-50.3,50.3c-43.1,43.1-113,43.1-156.1,0c-43.1-43.1-43.1-113-0-156.1L156.2,199.7z M273.6,82.3l-50.3,50.3c21.9-1.6,44.2,1.6,64.9,9.9l22.8-22.8c22.4-22.4,58.9-22.4,81.4,0c22.4,22.4,22.4,58.9,0,81.4l-73.9,73.9c-22.5,22.5-59.1,22.3-81.4,0c-5.2-5.2-9.7-11.7-12.5-18l-38.5,38.5c4,6.1,8.3,11.5,13.7,16.9c13.9,13.9,31.7,24.3,52.1,29.3c26.5,6.4,54.8,2.8,79.2-10.6c8.9-4.9,17.3-11.1,24.8-18.7l73.9-73.9c43.1-43.1,43.1-113,0-156.1C386.6,39.2,316.7,39.2,273.6,82.3z"></path></svg></a><h1 id="actions-toolbar">Actions toolbar</h1> <p> Actions toolbar is a set of actions on a page, form and so on that includes primary and/or secondary actions. @@ -29,15 +29,16 @@ </button> </div> </div></textarea> -</div><div class="code"><pre><code> -.actions-toolbar { - .actions-toolbar(); -} - -.example-actions-toolbar-1 { - .actions-toolbar(); -} - </code></pre></div></article><article id="actions-toolbar-mixin-variables" class="section"><div class="docs"><a href="#actions-toolbar-mixin-variables" class="permalink"><svg viewBox="0 0 512 512" height="32" width="32" class="icon"><path d="M156.2,199.7c7.5-7.5,15.9-13.8,24.8-18.7c49.6-27.3,113.1-12.8,145,35.5l-38.5,38.5c-11.1-25.2-38.5-39.6-65.8-33.5c-10.3,2.3-20.1,7.4-28,15.4l-73.9,73.9c-22.4,22.4-22.4,58.9,0,81.4c22.4,22.4,58.9,22.4,81.4,0l22.8-22.8c20.7,8.2,42.9,11.5,64.9,9.9l-50.3,50.3c-43.1,43.1-113,43.1-156.1,0c-43.1-43.1-43.1-113-0-156.1L156.2,199.7z M273.6,82.3l-50.3,50.3c21.9-1.6,44.2,1.6,64.9,9.9l22.8-22.8c22.4-22.4,58.9-22.4,81.4,0c22.4,22.4,22.4,58.9,0,81.4l-73.9,73.9c-22.5,22.5-59.1,22.3-81.4,0c-5.2-5.2-9.7-11.7-12.5-18l-38.5,38.5c4,6.1,8.3,11.5,13.7,16.9c13.9,13.9,31.7,24.3,52.1,29.3c26.5,6.4,54.8,2.8,79.2-10.6c8.9-4.9,17.3-11.1,24.8-18.7l73.9-73.9c43.1-43.1,43.1-113,0-156.1C386.6,39.2,316.7,39.2,273.6,82.3z"></path></svg></a><h1 id="actions-toolbar-mixin-variables">Actions toolbar mixin variables</h1> +</div><div class="code"><pre><code> +.actions-toolbar { + .actions-toolbar(); +} + +.example-actions-toolbar-1 { + .actions-toolbar(); +} + +</code></pre></div></article><article id="actions-toolbar-mixin-variables" class="section"><div class="docs"><a href="#actions-toolbar-mixin-variables" class="permalink"><svg viewBox="0 0 512 512" height="32" width="32" class="icon"><path d="M156.2,199.7c7.5-7.5,15.9-13.8,24.8-18.7c49.6-27.3,113.1-12.8,145,35.5l-38.5,38.5c-11.1-25.2-38.5-39.6-65.8-33.5c-10.3,2.3-20.1,7.4-28,15.4l-73.9,73.9c-22.4,22.4-22.4,58.9,0,81.4c22.4,22.4,58.9,22.4,81.4,0l22.8-22.8c20.7,8.2,42.9,11.5,64.9,9.9l-50.3,50.3c-43.1,43.1-113,43.1-156.1,0c-43.1-43.1-43.1-113-0-156.1L156.2,199.7z M273.6,82.3l-50.3,50.3c21.9-1.6,44.2,1.6,64.9,9.9l22.8-22.8c22.4-22.4,58.9-22.4,81.4,0c22.4,22.4,22.4,58.9,0,81.4l-73.9,73.9c-22.5,22.5-59.1,22.3-81.4,0c-5.2-5.2-9.7-11.7-12.5-18l-38.5,38.5c4,6.1,8.3,11.5,13.7,16.9c13.9,13.9,31.7,24.3,52.1,29.3c26.5,6.4,54.8,2.8,79.2-10.6c8.9-4.9,17.3-11.1,24.8-18.7l73.9-73.9c43.1-43.1,43.1-113,0-156.1C386.6,39.2,316.7,39.2,273.6,82.3z"></path></svg></a><h1 id="actions-toolbar-mixin-variables">Actions toolbar mixin variables</h1> <pre> <table> <tr> @@ -148,31 +149,32 @@ <a class="action back" href="#"><span>Back</span></a> </div> </div></textarea> -</div><div class="code"><pre><code> -.example-actions-toolbar-2 { - .actions-toolbar( - @_actions-toolbar-actions-position: justify - ); -} - -.example-actions-toolbar-3 { - .actions-toolbar( - @_actions-toolbar-actions-position: left - ); -} - -.example-actions-toolbar-4 { - .actions-toolbar( - @_actions-toolbar-actions-position: right - ); -} - -.example-actions-toolbar-5 { - .actions-toolbar( - @_actions-toolbar-actions-position: center - ); -} - </code></pre></div></article><article id="reverse-primary-and-secondary-blocks" class="section"><div class="docs"><a href="#reverse-primary-and-secondary-blocks" class="permalink"><svg viewBox="0 0 512 512" height="32" width="32" class="icon"><path d="M156.2,199.7c7.5-7.5,15.9-13.8,24.8-18.7c49.6-27.3,113.1-12.8,145,35.5l-38.5,38.5c-11.1-25.2-38.5-39.6-65.8-33.5c-10.3,2.3-20.1,7.4-28,15.4l-73.9,73.9c-22.4,22.4-22.4,58.9,0,81.4c22.4,22.4,58.9,22.4,81.4,0l22.8-22.8c20.7,8.2,42.9,11.5,64.9,9.9l-50.3,50.3c-43.1,43.1-113,43.1-156.1,0c-43.1-43.1-43.1-113-0-156.1L156.2,199.7z M273.6,82.3l-50.3,50.3c21.9-1.6,44.2,1.6,64.9,9.9l22.8-22.8c22.4-22.4,58.9-22.4,81.4,0c22.4,22.4,22.4,58.9,0,81.4l-73.9,73.9c-22.5,22.5-59.1,22.3-81.4,0c-5.2-5.2-9.7-11.7-12.5-18l-38.5,38.5c4,6.1,8.3,11.5,13.7,16.9c13.9,13.9,31.7,24.3,52.1,29.3c26.5,6.4,54.8,2.8,79.2-10.6c8.9-4.9,17.3-11.1,24.8-18.7l73.9-73.9c43.1-43.1,43.1-113,0-156.1C386.6,39.2,316.7,39.2,273.6,82.3z"></path></svg></a><h1 id="reverse-primary-and-secondary-blocks">Reverse primary and secondary blocks</h1> +</div><div class="code"><pre><code> +.example-actions-toolbar-2 { + .actions-toolbar( + @_actions-toolbar-actions-position: justify + ); +} + +.example-actions-toolbar-3 { + .actions-toolbar( + @_actions-toolbar-actions-position: left + ); +} + +.example-actions-toolbar-4 { + .actions-toolbar( + @_actions-toolbar-actions-position: right + ); +} + +.example-actions-toolbar-5 { + .actions-toolbar( + @_actions-toolbar-actions-position: center + ); +} + +</code></pre></div></article><article id="reverse-primary-and-secondary-blocks" class="section"><div class="docs"><a href="#reverse-primary-and-secondary-blocks" class="permalink"><svg viewBox="0 0 512 512" height="32" width="32" class="icon"><path d="M156.2,199.7c7.5-7.5,15.9-13.8,24.8-18.7c49.6-27.3,113.1-12.8,145,35.5l-38.5,38.5c-11.1-25.2-38.5-39.6-65.8-33.5c-10.3,2.3-20.1,7.4-28,15.4l-73.9,73.9c-22.4,22.4-22.4,58.9,0,81.4c22.4,22.4,58.9,22.4,81.4,0l22.8-22.8c20.7,8.2,42.9,11.5,64.9,9.9l-50.3,50.3c-43.1,43.1-113,43.1-156.1,0c-43.1-43.1-43.1-113-0-156.1L156.2,199.7z M273.6,82.3l-50.3,50.3c21.9-1.6,44.2,1.6,64.9,9.9l22.8-22.8c22.4-22.4,58.9-22.4,81.4,0c22.4,22.4,22.4,58.9,0,81.4l-73.9,73.9c-22.5,22.5-59.1,22.3-81.4,0c-5.2-5.2-9.7-11.7-12.5-18l-38.5,38.5c4,6.1,8.3,11.5,13.7,16.9c13.9,13.9,31.7,24.3,52.1,29.3c26.5,6.4,54.8,2.8,79.2-10.6c8.9-4.9,17.3-11.1,24.8-18.7l73.9-73.9c43.1-43.1,43.1-113,0-156.1C386.6,39.2,316.7,39.2,273.6,82.3z"></path></svg></a><h1 id="reverse-primary-and-secondary-blocks">Reverse primary and secondary blocks</h1> <p> <code>@_actions-toolbar-actions-reverse</code> variable controls reversing of primary and secondary blocks.</p> <p> If it is set to <code>false</code>, the order of blocks in action toolbar is <strong>default</strong>.</p> <p> If it is set to <code>true</code>, the order of blocks in action toolbar is <strong>reversed</strong>.</p> @@ -207,28 +209,29 @@ <a class="action back" href="#"><span>Back</span></a> </div> </div></textarea> -</div><div class="code"><pre><code> -.example-actions-toolbar-6 { - .actions-toolbar( - @_actions-toolbar-actions-position: justify, - @_actions-toolbar-actions-reverse: true - ); -} - -.example-actions-toolbar-7 { - .actions-toolbar( - @_actions-toolbar-actions-position: left, - @_actions-toolbar-actions-reverse: true - ); -} - -.example-actions-toolbar-8 { - .actions-toolbar( - @_actions-toolbar-actions-position: right, - @_actions-toolbar-actions-reverse: true - ); -} - </code></pre></div></article><article id="actions-toolbar-indents-customizations" class="section"><div class="docs"><a href="#actions-toolbar-indents-customizations" class="permalink"><svg viewBox="0 0 512 512" height="32" width="32" class="icon"><path d="M156.2,199.7c7.5-7.5,15.9-13.8,24.8-18.7c49.6-27.3,113.1-12.8,145,35.5l-38.5,38.5c-11.1-25.2-38.5-39.6-65.8-33.5c-10.3,2.3-20.1,7.4-28,15.4l-73.9,73.9c-22.4,22.4-22.4,58.9,0,81.4c22.4,22.4,58.9,22.4,81.4,0l22.8-22.8c20.7,8.2,42.9,11.5,64.9,9.9l-50.3,50.3c-43.1,43.1-113,43.1-156.1,0c-43.1-43.1-43.1-113-0-156.1L156.2,199.7z M273.6,82.3l-50.3,50.3c21.9-1.6,44.2,1.6,64.9,9.9l22.8-22.8c22.4-22.4,58.9-22.4,81.4,0c22.4,22.4,22.4,58.9,0,81.4l-73.9,73.9c-22.5,22.5-59.1,22.3-81.4,0c-5.2-5.2-9.7-11.7-12.5-18l-38.5,38.5c4,6.1,8.3,11.5,13.7,16.9c13.9,13.9,31.7,24.3,52.1,29.3c26.5,6.4,54.8,2.8,79.2-10.6c8.9-4.9,17.3-11.1,24.8-18.7l73.9-73.9c43.1-43.1,43.1-113,0-156.1C386.6,39.2,316.7,39.2,273.6,82.3z"></path></svg></a><h1 id="actions-toolbar-indents-customizations">Actions toolbar indents customizations</h1> +</div><div class="code"><pre><code> +.example-actions-toolbar-6 { + .actions-toolbar( + @_actions-toolbar-actions-position: justify, + @_actions-toolbar-actions-reverse: true + ); +} + +.example-actions-toolbar-7 { + .actions-toolbar( + @_actions-toolbar-actions-position: left, + @_actions-toolbar-actions-reverse: true + ); +} + +.example-actions-toolbar-8 { + .actions-toolbar( + @_actions-toolbar-actions-position: right, + @_actions-toolbar-actions-reverse: true + ); +} + +</code></pre></div></article><article id="actions-toolbar-indents-customizations" class="section"><div class="docs"><a href="#actions-toolbar-indents-customizations" class="permalink"><svg viewBox="0 0 512 512" height="32" width="32" class="icon"><path d="M156.2,199.7c7.5-7.5,15.9-13.8,24.8-18.7c49.6-27.3,113.1-12.8,145,35.5l-38.5,38.5c-11.1-25.2-38.5-39.6-65.8-33.5c-10.3,2.3-20.1,7.4-28,15.4l-73.9,73.9c-22.4,22.4-22.4,58.9,0,81.4c22.4,22.4,58.9,22.4,81.4,0l22.8-22.8c20.7,8.2,42.9,11.5,64.9,9.9l-50.3,50.3c-43.1,43.1-113,43.1-156.1,0c-43.1-43.1-43.1-113-0-156.1L156.2,199.7z M273.6,82.3l-50.3,50.3c21.9-1.6,44.2,1.6,64.9,9.9l22.8-22.8c22.4-22.4,58.9-22.4,81.4,0c22.4,22.4,22.4,58.9,0,81.4l-73.9,73.9c-22.5,22.5-59.1,22.3-81.4,0c-5.2-5.2-9.7-11.7-12.5-18l-38.5,38.5c4,6.1,8.3,11.5,13.7,16.9c13.9,13.9,31.7,24.3,52.1,29.3c26.5,6.4,54.8,2.8,79.2-10.6c8.9-4.9,17.3-11.1,24.8-18.7l73.9-73.9c43.1-43.1,43.1-113,0-156.1C386.6,39.2,316.7,39.2,273.6,82.3z"></path></svg></a><h1 id="actions-toolbar-indents-customizations">Actions toolbar indents customizations</h1> <p> <code>@_actions-toolbar-margin</code> variable controls margins of the actions toolbar wrapper.</p> <p> <code>@_actions-toolbar-padding</code> variable controls paddings of the actions toolbar wrapper.</p> <textarea class="preview-code" spellcheck="false"> <div class="example-actions-toolbar-9"> @@ -245,7 +248,7 @@ <button type="submit" class="action submit2" title="Submit2"><span>Submit2</span></button> </div> <div class="secondary"> - <a href="#" class="action towishlist"><span>Add to Wishlist</span></a> + <a href="#" class="action towishlist"><span>Add to Wish List</span></a> <a href="#" class="action tocompare"><span>Add to Compare</span></a> </div> </div></textarea><p> <code>@_actions-toolbar-secondary-actions-margin</code> variable controls margins of the secondary action elements.</p> @@ -255,48 +258,50 @@ <button type="submit" class="action submit2" title="Submit2"><span>Submit2</span></button> </div> <div class="secondary"> - <a href="#" class="action towishlist"><span>Add to Wishlist</span></a> + <a href="#" class="action towishlist"><span>Add to Wish List</span></a> <a href="#" class="action tocompare"><span>Add to Compare</span></a> </div> </div></textarea> -</div><div class="code"><pre><code> -.example-actions-toolbar-9 { - .actions-toolbar( - @_actions-toolbar-margin: 10px, - @_actions-toolbar-padding: 10px - ); -} - -.example-actions-toolbar-10 { - .actions-toolbar( - @_actions-toolbar-actions-position: left, - @_actions-toolbar-primary-actions-margin: 0 50px 0 0 - ); -} - -.example-actions-toolbar-11 { - .actions-toolbar( - @_actions-toolbar-actions-position: left, - @_actions-toolbar-secondary-actions-margin: 0 50px 0 0 - ); -} - </code></pre></div></article><article id="responsive-actions-toolbar" class="section"><div class="docs"><a href="#responsive-actions-toolbar" class="permalink"><svg viewBox="0 0 512 512" height="32" width="32" class="icon"><path d="M156.2,199.7c7.5-7.5,15.9-13.8,24.8-18.7c49.6-27.3,113.1-12.8,145,35.5l-38.5,38.5c-11.1-25.2-38.5-39.6-65.8-33.5c-10.3,2.3-20.1,7.4-28,15.4l-73.9,73.9c-22.4,22.4-22.4,58.9,0,81.4c22.4,22.4,58.9,22.4,81.4,0l22.8-22.8c20.7,8.2,42.9,11.5,64.9,9.9l-50.3,50.3c-43.1,43.1-113,43.1-156.1,0c-43.1-43.1-43.1-113-0-156.1L156.2,199.7z M273.6,82.3l-50.3,50.3c21.9-1.6,44.2,1.6,64.9,9.9l22.8-22.8c22.4-22.4,58.9-22.4,81.4,0c22.4,22.4,22.4,58.9,0,81.4l-73.9,73.9c-22.5,22.5-59.1,22.3-81.4,0c-5.2-5.2-9.7-11.7-12.5-18l-38.5,38.5c4,6.1,8.3,11.5,13.7,16.9c13.9,13.9,31.7,24.3,52.1,29.3c26.5,6.4,54.8,2.8,79.2-10.6c8.9-4.9,17.3-11.1,24.8-18.7l73.9-73.9c43.1-43.1,43.1-113,0-156.1C386.6,39.2,316.7,39.2,273.6,82.3z"></path></svg></a><h1 id="responsive-actions-toolbar">Responsive actions toolbar</h1> +</div><div class="code"><pre><code> +.example-actions-toolbar-9 { + .actions-toolbar( + @_actions-toolbar-margin: 10px, + @_actions-toolbar-padding: 10px + ); +} + +.example-actions-toolbar-10 { + .actions-toolbar( + @_actions-toolbar-actions-position: left, + @_actions-toolbar-primary-actions-margin: 0 50px 0 0 + ); +} + +.example-actions-toolbar-11 { + .actions-toolbar( + @_actions-toolbar-actions-position: left, + @_actions-toolbar-secondary-actions-margin: 0 50px 0 0 + ); +} + +</code></pre></div></article><article id="responsive-actions-toolbar" class="section"><div class="docs"><a href="#responsive-actions-toolbar" class="permalink"><svg viewBox="0 0 512 512" height="32" width="32" class="icon"><path d="M156.2,199.7c7.5-7.5,15.9-13.8,24.8-18.7c49.6-27.3,113.1-12.8,145,35.5l-38.5,38.5c-11.1-25.2-38.5-39.6-65.8-33.5c-10.3,2.3-20.1,7.4-28,15.4l-73.9,73.9c-22.4,22.4-22.4,58.9,0,81.4c22.4,22.4,58.9,22.4,81.4,0l22.8-22.8c20.7,8.2,42.9,11.5,64.9,9.9l-50.3,50.3c-43.1,43.1-113,43.1-156.1,0c-43.1-43.1-43.1-113-0-156.1L156.2,199.7z M273.6,82.3l-50.3,50.3c21.9-1.6,44.2,1.6,64.9,9.9l22.8-22.8c22.4-22.4,58.9-22.4,81.4,0c22.4,22.4,22.4,58.9,0,81.4l-73.9,73.9c-22.5,22.5-59.1,22.3-81.4,0c-5.2-5.2-9.7-11.7-12.5-18l-38.5,38.5c4,6.1,8.3,11.5,13.7,16.9c13.9,13.9,31.7,24.3,52.1,29.3c26.5,6.4,54.8,2.8,79.2-10.6c8.9-4.9,17.3-11.1,24.8-18.7l73.9-73.9c43.1-43.1,43.1-113,0-156.1C386.6,39.2,316.7,39.2,273.6,82.3z"></path></svg></a><h1 id="responsive-actions-toolbar">Responsive actions toolbar</h1> <p> To set up responsive action toolbar, all floats of its elements should be cleared. To do this <code> .actions-toolbar-clear-floats()</code> mixin is used.</p> <textarea class="preview-code" spellcheck="false"> <div class="example-actions-toolbar-12"> <div class="primary"> <button type="submit" class="action submit" title="Submit"><span>Submit</span></button> </div> <div class="secondary"> - <a href="#" class="action towishlist"><span>Add to Wishlist</span></a> + <a href="#" class="action towishlist"><span>Add to Wish List</span></a> </div> </div></textarea> -</div><div class="code"><pre><code> -.example-actions-toolbar-12 { - .actions-toolbar(); -} - -@media only screen and (max-width: @screen__m) { - .example-actions-toolbar-12 { - .actions-toolbar-clear-floats(); - } -} </code></pre></div></article></section><div class="bar bottom"><div hidden class="settings container"><!-- Icons from http://iconmonstr.com--><button title="Desktop (1280)" data-width='1280'><svg viewBox="0 0 412 386" height="24" width="26" class="icon"><path d="m147.6,343.9c-4.5,15.9-26.2,37.6-42.1,42.1h201c-15.3,-4-38.1,-26.8-42.1,-42.1H147.6zM387,0.5H25c-13.8,0-25,11.2-25,25V294c0,13.8 11.2,25 25,25h362c13.8,0 25,-11.2 25,-25V25.5C412,11.7 400.8,0.5 387,0.5zM369.9,238.2H42.1L42.1,42.6 369.9,42.6V238.2z"></path></svg></button><button title="Laptop (1024)" data-width='1024'><svg viewBox="0 0 384 312" height="23" width="28" class="icon"><path d="m349.2,20.5c0,-11-9,-20-20,-20H53.6c-11,0-20,9-20,20v194H349.2v-194zm-27,167H60.6V27.5H322.2v160zm28,42H32.6L2.6,282.1c-3.5,6.2-3.5,13.8 0.1,19.9 3.6,6.2 10.2,9.9 17.3,9.9H363.1c7.1,0 13.7,-3.8 17.3,-10 3.6,-6.2 3.6,-13.8 0,-20l-30.2,-52.5zm-196.9,54 8,-23.5h60.5l8,23.5h-76.5z"></path></svg></button><button title="Tablet (768)" data-width='768'><svg viewBox="0 0 317 412" height="24" width="18" class="icon"><path d="M 316.5,380 V 32 c 0,-17.7 -14.3,-32 -32,-32 H 32 C 14.3,0 0,14.3 0,32 v 348 c 0,17.7 14.3,32 32,32 h 252.5 c 17.7,0 32,-14.3 32,-32 z M 40,367 V 45 H 276.5 V 367 H 40 z m 109.8,22.7 c 0,-4.7 3.8,-8.5 8.5,-8.5 4.7,0 8.5,3.8 8.5,8.5 0,4.7 -3.8,8.5 -8.5,8.5 -4.7,0 -8.5,-3.8 -8.5,-8.5 z"></path></svg></button><button title="Smart phone (320)" data-width='320'><svg viewBox="0 0 224 412" height="24" width="13" class="icon"><path d="M 190.7,0 H 33 C 14.8,0 0,14.8 0,33 v 346 c 0,18.2 14.8,33 33,33 h 157.7 c 18.2,0 33,-14.8 33,-33 V 33 c 0,-18.2 -14.8,-33 -33,-33 z M 94.3,30.2 h 37 c 2.2,0 4,1.8 4,4 0,2.2 -1.8,4 -4,4 h -37 c -2.2,0 -4,-1.8 -4,-4 0,-2.2 1.8,-4 4,-4 z m 18.5,362.8 c -8.8,0 -16,-7.2 -16,-16 0,-8.8 7.2,-16 16,-16 8.8,0 16,7.2 16,16 0,8.8 -7.2,16 -16,16 z M 198.6,343.8 H 25.1 V 68.2 h 173.5 v 275.5 z"></path></svg></button><button title="Feature phone (240)" data-width='240'><svg viewBox="0 0 201 412" height="24" width="12" class="icon"><path d="M 165.5,0.2 V 45 H 25 c -13.8,0 -25,11.2 -25,25 V 387 c 0,13.8 11.2,25 25,25 h 150.5 c 13.8,0 25,-11.2 25,-25 V 0.2 h -35 z M 65.2,366.5 H 34.2 v -24.5 h 31 v 24.5 z m 0,-44.3 H 34.2 v -24.5 h 31 v 24.5 z m 50.5,44.3 H 84.7 v -24.5 h 31 v 24.5 z m 0,-44.3 H 84.7 v -24.5 h 31 v 24.5 z m 50.5,44.3 h -31 v -24.5 h 31 v 24.5 z m 0,-44.3 h -31 v -24.5 h 31 v 24.5 z m 0,-59.3 h -132 V 95.4 h 132 V 262.9 z"></path></svg></button><button title="Auto (100%)" data-width="auto" class="auto is-active">Auto</button></div></div><script>(function(){var a=[{title:"actions-toolbar",filename:"actions-toolbar",url:"actions-toolbar.html"},{title:"Actions toolbar",filename:"actions-toolbar",url:"actions-toolbar.html#actions-toolbar"},{title:"Actions toolbar mixin variables",filename:"actions-toolbar",url:"actions-toolbar.html#actions-toolbar-mixin-variables"},{title:"Actions toolbar alignment",filename:"actions-toolbar",url:"actions-toolbar.html#actions-toolbar-alignment"},{title:"Reverse primary and secondary blocks",filename:"actions-toolbar",url:"actions-toolbar.html#reverse-primary-and-secondary-blocks"},{title:"Actions toolbar indents customizations",filename:"actions-toolbar",url:"actions-toolbar.html#actions-toolbar-indents-customizations"},{title:"Responsive actions toolbar",filename:"actions-toolbar",url:"actions-toolbar.html#responsive-actions-toolbar"},{title:"breadcrumbs",filename:"breadcrumbs",url:"breadcrumbs.html"},{title:"Breadcrumbs",filename:"breadcrumbs",url:"breadcrumbs.html#breadcrumbs"},{title:"Breadcrumbs variables",filename:"breadcrumbs",url:"breadcrumbs.html#breadcrumbs-variables"},{title:"Button-styled breadcrumbs with gradient background, border, and no separating symbol",filename:"breadcrumbs",url:"breadcrumbs.html#buttonstyled-breadcrumbs-with-gradient-background-border-and-no-separating-symbol"},{title:"Breadcrumbs with solid background",filename:"breadcrumbs",url:"breadcrumbs.html#breadcrumbs-with-solid-background"},{title:"buttons",filename:"buttons",url:"buttons.html"},{title:"Default button",filename:"buttons",url:"buttons.html#default-button"},{title:"Button variables",filename:"buttons",url:"buttons.html#button-variables"},{title:"Button as an icon",filename:"buttons",url:"buttons.html#button-as-an-icon"},{title:"Button with an icon on the left or right side of the text",filename:"buttons",url:"buttons.html#button-with-an-icon-on-the-left-or-right-side-of-the-text"},{title:"Button with fixed width",filename:"buttons",url:"buttons.html#button-with-fixed-width"},{title:"Primary button",filename:"buttons",url:"buttons.html#primary-button"},{title:"Primary button variables",filename:"buttons",url:"buttons.html#primary-button-variables"},{title:"Button with gradient background",filename:"buttons",url:"buttons.html#button-with-gradient-background"},{title:"Button as a link",filename:"buttons",url:"buttons.html#button-as-a-link"},{title:"Link as a button",filename:"buttons",url:"buttons.html#link-as-a-button"},{title:"Button reset",filename:"buttons",url:"buttons.html#button-reset"},{title:"Button revert secondary color",filename:"buttons",url:"buttons.html#button-revert-secondary-color"},{title:"Button revert secondary color variables",filename:"buttons",url:"buttons.html#button-revert-secondary-color-variables"},{title:"Button revert secondary size",filename:"buttons",url:"buttons.html#button-revert-secondary-size"},{title:"Button revert secondary size variables",filename:"buttons",url:"buttons.html#button-revert-secondary-size-variables"},{title:"docs",filename:"docs",url:"docs.html"},{title:"Documentation",filename:"docs",url:"docs.html#documentation"},{title:"dropdowns",filename:"dropdowns",url:"dropdowns.html"},{title:"Drop-down and split buttons mixins",filename:"dropdowns",url:"dropdowns.html#dropdown-and-split-buttons-mixins"},{title:"Drop-down",filename:"dropdowns",url:"dropdowns.html#dropdown"},{title:"Drop-down variables",filename:"dropdowns",url:"dropdowns.html#dropdown-variables"},{title:"Drop-down with icon customization",filename:"dropdowns",url:"dropdowns.html#dropdown-with-icon-customization"},{title:"Modify dropdown list styles",filename:"dropdowns",url:"dropdowns.html#modify-dropdown-list-styles"},{title:"Split button",filename:"dropdowns",url:"dropdowns.html#split-button"},{title:"Split button variables",filename:"dropdowns",url:"dropdowns.html#split-button-variables"},{title:"Split button - button styling",filename:"dropdowns",url:"dropdowns.html#split-button-button-styling"},{title:"Split button icon customization",filename:"dropdowns",url:"dropdowns.html#split-button-icon-customization"},{title:"Split button drop-down list customization",filename:"dropdowns",url:"dropdowns.html#split-button-dropdown-list-customization"},{title:"forms",filename:"forms",url:"forms.html"},{title:"Forms mixins",filename:"forms",url:"forms.html#forms-mixins"},{title:"Global forms elements customization",filename:"forms",url:"forms.html#global-forms-elements-customization"},{title:"Fieldsets & fields customization",filename:"forms",url:"forms.html#fieldsets-fields-customization"},{title:"Fieldset and legend customization variables",filename:"forms",url:"forms.html#fieldset-and-legend-customization-variables"},{title:"Fields customization variables",filename:"forms",url:"forms.html#fields-customization-variables"},{title:"Required fields message customization variables",filename:"forms",url:"forms.html#required-fields-message-customization-variables"},{title:"Form element inputs customization",filename:"forms",url:"forms.html#form-element-inputs-customization"},{title:"Form element inputs customization variables",filename:"forms",url:"forms.html#form-element-inputs-customization-variables"},{title:"Form element choice",filename:"forms",url:"forms.html#form-element-choice"},{title:"Form element choice variables",filename:"forms",url:"forms.html#form-element-choice-variables"},{title:"Custom color",filename:"forms",url:"forms.html#custom-color"},{title:"Input number - input-text view",filename:"forms",url:"forms.html#input-number-inputtext-view"},{title:"Input search - input-text view",filename:"forms",url:"forms.html#input-search-inputtext-view"},{title:"Form validation",filename:"forms",url:"forms.html#form-validation"},{title:"Form validation variables// <pre>",filename:"forms",url:"forms.html#form-validation-variables-pre"},{title:"icons",filename:"icons",url:"icons.html"},{title:"Icons",filename:"icons",url:"icons.html#icons"},{title:"Icon with image or sprite",filename:"icons",url:"icons.html#icon-with-image-or-sprite"},{title:"Icon with image or sprite variables",filename:"icons",url:"icons.html#icon-with-image-or-sprite-variables"},{title:"Icon position for an icon with image or sprite",filename:"icons",url:"icons.html#icon-position-for-an-icon-with-image-or-sprite"},{title:"Position for icon with image or sprite mixin variables",filename:"icons",url:"icons.html#position-for-icon-with-image-or-sprite-mixin-variables"},{title:"Icon sprite position (with grid)",filename:"icons",url:"icons.html#icon-sprite-position-with-grid"},{title:"Icon sprite position variables",filename:"icons",url:"icons.html#icon-sprite-position-variables"},{title:"Image/sprite icon size",filename:"icons",url:"icons.html#imagesprite-icon-size"},{title:"Image/sprite icon size variables",filename:"icons",url:"icons.html#imagesprite-icon-size-variables"},{title:"Font icon",filename:"icons",url:"icons.html#font-icon"},{title:"Font icon variables",filename:"icons",url:"icons.html#font-icon-variables"},{title:"Change the size of font icon",filename:"icons",url:"icons.html#change-the-size-of-font-icon"},{title:"Change the size of font icon variables",filename:"icons",url:"icons.html#change-the-size-of-font-icon-variables"},{title:"Hide icon text",filename:"icons",url:"icons.html#hide-icon-text"},{title:"Sprite and font icons for Blank theme",filename:"icons",url:"icons.html#sprite-and-font-icons-for-blank-theme"},{title:"layout",filename:"layout",url:"layout.html"},{title:"Layout",filename:"layout",url:"layout.html#layout"},{title:"Layout global variables",filename:"layout",url:"layout.html#layout-global-variables"},{title:"Page layouts",filename:"layout",url:"layout.html#page-layouts"},{title:"Layout column",filename:"layout",url:"layout.html#layout-column"},{title:"Layout column variables",filename:"layout",url:"layout.html#layout-column-variables"},{title:"Layout width",filename:"layout",url:"layout.html#layout-width"},{title:"Layout width variables",filename:"layout",url:"layout.html#layout-width-variables"},{title:"lib",filename:"lib",url:"lib.html"},{title:"Including Magento UI library to your theme",filename:"lib",url:"lib.html#including-magento-ui-library-to-your-theme"},{title:"loaders",filename:"loaders",url:"loaders.html"},{title:"Loaders",filename:"loaders",url:"loaders.html#loaders"},{title:"Default loader variables",filename:"loaders",url:"loaders.html#default-loader-variables"},{title:"Loading",filename:"loaders",url:"loaders.html#loading"},{title:"Loading default variables",filename:"loaders",url:"loaders.html#loading-default-variables"},{title:"messages",filename:"messages",url:"messages.html"},{title:"Messages",filename:"messages",url:"messages.html#messages"},{title:"Information message",filename:"messages",url:"messages.html#information-message"},{title:"Warning message",filename:"messages",url:"messages.html#warning-message"},{title:"Error message",filename:"messages",url:"messages.html#error-message"},{title:"Success message",filename:"messages",url:"messages.html#success-message"},{title:"Notice message",filename:"messages",url:"messages.html#notice-message"},{title:"Message with inner icon",filename:"messages",url:"messages.html#message-with-inner-icon"},{title:"Message with lateral icon",filename:"messages",url:"messages.html#message-with-lateral-icon"},{title:"Custom message style",filename:"messages",url:"messages.html#custom-message-style"},{title:"Messages global variables",filename:"messages",url:"messages.html#messages-global-variables"},{title:"pages",filename:"pages",url:"pages.html"},{title:"Pagination HTML markup",filename:"pages",url:"pages.html#pagination-html-markup"},{title:"Pagination variables",filename:"pages",url:"pages.html#pagination-variables"},{title:"Pagination with label and gradient background on links",filename:"pages",url:"pages.html#pagination-with-label-and-gradient-background-on-links"},{title:'Pagination with "previous"..."next" text links and label',filename:"pages",url:"pages.html#pagination-with-previousnext-text-links-and-label"},{title:"Pagination without label, with solid background",filename:"pages",url:"pages.html#pagination-without-label-with-solid-background"},{title:"popups",filename:"popups",url:"popups.html"},{title:"Popups",filename:"popups",url:"popups.html#popups"},{title:"Popup variables",filename:"popups",url:"popups.html#popup-variables"},{title:"Window overlay mixin variables",filename:"popups",url:"popups.html#window-overlay-mixin-variables"},{title:"Fixed height popup",filename:"popups",url:"popups.html#fixed-height-popup"},{title:"Fixed content height popup",filename:"popups",url:"popups.html#fixed-content-height-popup"},{title:"Margins for header, content and footer block in popup",filename:"popups",url:"popups.html#margins-for-header-content-and-footer-block-in-popup"},{title:"Popup titles styled as theme headings",filename:"popups",url:"popups.html#popup-titles-styled-as-theme-headings"},{title:"Popup action toolbar",filename:"popups",url:"popups.html#popup-action-toolbar"},{title:"Popup Close button without an icon",filename:"popups",url:"popups.html#popup-close-button-without-an-icon"},{title:"Modify the icon of popup Close button",filename:"popups",url:"popups.html#modify-the-icon-of-popup-close-button"},{title:"Modify overlay styles",filename:"popups",url:"popups.html#modify-overlay-styles"},{title:"rating",filename:"rating",url:"rating.html"},{title:"Ratings",filename:"rating",url:"rating.html#ratings"},{title:"Global rating variables",filename:"rating",url:"rating.html#global-rating-variables"},{title:"Rating with vote",filename:"rating",url:"rating.html#rating-with-vote"},{title:"Rating with vote icons number customization",filename:"rating",url:"rating.html#rating-with-vote-icons-number-customization"},{title:"Rating with vote icons colors customization",filename:"rating",url:"rating.html#rating-with-vote-icons-colors-customization"},{title:"Rating with vote icons symbol customization",filename:"rating",url:"rating.html#rating-with-vote-icons-symbol-customization"},{title:"Accessible rating with vote",filename:"rating",url:"rating.html#accessible-rating-with-vote"},{title:"Rating summary",filename:"rating",url:"rating.html#rating-summary"},{title:"Rating summary icons number customization",filename:"rating",url:"rating.html#rating-summary-icons-number-customization"},{title:"Rating summary icons color customization",filename:"rating",url:"rating.html#rating-summary-icons-color-customization"},{title:"Rating summary icons symbol customization",filename:"rating",url:"rating.html#rating-summary-icons-symbol-customization"},{title:"Rating summary hide label",filename:"rating",url:"rating.html#rating-summary-hide-label"},{title:"Rating summary multiple ratings",filename:"rating",url:"rating.html#rating-summary-multiple-ratings"},{title:"Rating hide label mixin",filename:"rating",url:"rating.html#rating-hide-label-mixin"},{title:"resets",filename:"resets",url:"resets.html"},{title:"Resets",filename:"resets",url:"resets.html#resets"},{title:"responsive",filename:"responsive",url:"responsive.html"},{title:"Responsive",filename:"responsive",url:"responsive.html#responsive"},{title:"Responsive mixins usage",filename:"responsive",url:"responsive.html#responsive-mixins-usage"},{title:"Media query style groups separation variables",filename:"responsive",url:"responsive.html#media-query-style-groups-separation-variables"},{title:"Responsive breakpoints",filename:"responsive",url:"responsive.html#responsive-breakpoints"},{title:"sections",filename:"sections",url:"sections.html"},{title:"Tabs and accordions",filename:"sections",url:"sections.html#tabs-and-accordions"},{title:"Tabs",filename:"sections",url:"sections.html#tabs"},{title:"Tabs mixin variables",filename:"sections",url:"sections.html#tabs-mixin-variables"},{title:"Tabs with content top border",filename:"sections",url:"sections.html#tabs-with-content-top-border"},{title:"Accordion",filename:"sections",url:"sections.html#accordion"},{title:"Accordion mixin variables",filename:"sections",url:"sections.html#accordion-mixin-variables"},{title:"Responsive tabs",filename:"sections",url:"sections.html#responsive-tabs"},{title:"Tabs Base",filename:"sections",url:"sections.html#tabs-base"},{title:"Accordion Base",filename:"sections",url:"sections.html#accordion-base"},{title:"tables",filename:"tables",url:"tables.html"},{title:"Tables",filename:"tables",url:"tables.html#tables"},{title:"Table mixin variables",filename:"tables",url:"tables.html#table-mixin-variables"},{title:"Table typography",filename:"tables",url:"tables.html#table-typography"},{title:"Table typography mixin variables",filename:"tables",url:"tables.html#table-typography-mixin-variables"},{title:"Table caption",filename:"tables",url:"tables.html#table-caption"},{title:"Table caption mixin variables",filename:"tables",url:"tables.html#table-caption-mixin-variables"},{title:"Table cells resize",filename:"tables",url:"tables.html#table-cells-resize"},{title:"Table cells resize variables",filename:"tables",url:"tables.html#table-cells-resize-variables"},{title:"Table background customization",filename:"tables",url:"tables.html#table-background-customization"},{title:"Table background mixin variables",filename:"tables",url:"tables.html#table-background-mixin-variables"},{title:"Table borders customization",filename:"tables",url:"tables.html#table-borders-customization"},{title:"Table borders mixin variables",filename:"tables",url:"tables.html#table-borders-mixin-variables"},{title:"Table with horizontal borders",filename:"tables",url:"tables.html#table-with-horizontal-borders"},{title:"Table with vertical borders",filename:"tables",url:"tables.html#table-with-vertical-borders"},{title:"Table with light borders",filename:"tables",url:"tables.html#table-with-light-borders"},{title:"Table without borders",filename:"tables",url:"tables.html#table-without-borders"},{title:"Striped table",filename:"tables",url:"tables.html#striped-table"},{title:"Striped table mixin variables",filename:"tables",url:"tables.html#striped-table-mixin-variables"},{title:"Table with rows hover",filename:"tables",url:"tables.html#table-with-rows-hover"},{title:"Table with rows hover mixin variables",filename:"tables",url:"tables.html#table-with-rows-hover-mixin-variables"},{title:"Responsive table technics #1",filename:"tables",url:"tables.html#responsive-table-technics-1"},{title:"Responsive table technics #2",filename:"tables",url:"tables.html#responsive-table-technics-2"},{title:"Responsive table technics #2 mixin variables",filename:"tables",url:"tables.html#responsive-table-technics-2-mixin-variables"},{title:"tooltips",filename:"tooltips",url:"tooltips.html"},{title:"Tooltips",filename:"tooltips",url:"tooltips.html#tooltips"},{title:"Tooltips variables",filename:"tooltips",url:"tooltips.html#tooltips-variables"},{title:"typography",filename:"typography",url:"typography.html"},{title:"Typogrphy",filename:"typography",url:"typography.html#typogrphy"},{title:"Typography variables",filename:"typography",url:"typography.html#typography-variables"},{title:"Font-size mixin",filename:"typography",url:"typography.html#fontsize-mixin"},{title:"Line-height mixin",filename:"typography",url:"typography.html#lineheight-mixin"},{title:"Word breaking mixin",filename:"typography",url:"typography.html#word-breaking-mixin"},{title:"Font face mixin",filename:"typography",url:"typography.html#font-face-mixin"},{title:"Text overflow mixin",filename:"typography",url:"typography.html#text-overflow-mixin"},{title:"Text hide",filename:"typography",url:"typography.html#text-hide"},{title:"Hyphens",filename:"typography",url:"typography.html#hyphens"},{title:"Font style and color",filename:"typography",url:"typography.html#font-style-and-color"},{title:"Font style mixin variables",filename:"typography",url:"typography.html#font-style-mixin-variables"},{title:"Reset list styles",filename:"typography",url:"typography.html#reset-list-styles"},{title:"Reset list styles variables",filename:"typography",url:"typography.html#reset-list-styles-variables"},{title:"Inline-block list item styling",filename:"typography",url:"typography.html#inlineblock-list-item-styling"},{title:"Link styling mixin",filename:"typography",url:"typography.html#link-styling-mixin"},{title:"Link styling mixin variables",filename:"typography",url:"typography.html#link-styling-mixin-variables"},{title:"Heading styling mixin",filename:"typography",url:"typography.html#heading-styling-mixin"},{title:"Base typography mixins",filename:"typography",url:"typography.html#base-typography-mixins"},{title:"Headings typography mixin",filename:"typography",url:"typography.html#headings-typography-mixin"},{title:"Typography links mixin",filename:"typography",url:"typography.html#typography-links-mixin"},{title:"Typography lists mixin",filename:"typography",url:"typography.html#typography-lists-mixin"},{title:"Typography code elements mixin",filename:"typography",url:"typography.html#typography-code-elements-mixin"},{title:"Typography blockquote",filename:"typography",url:"typography.html#typography-blockquote"},{title:"utilities",filename:"utilities",url:"utilities.html"},{title:"Utilities",filename:"utilities",url:"utilities.html#utilities"},{title:".clearfix()",filename:"utilities",url:"utilities.html#clearfix"},{title:".visibility-hidden()",filename:"utilities",url:"utilities.html#visibilityhidden"},{title:".visually-hidden()",filename:"utilities",url:"utilities.html#visuallyhidden"},{title:".visually-hidden-reset()",filename:"utilities",url:"utilities.html#visuallyhiddenreset"},{title:".css()",filename:"utilities",url:"utilities.html#css"},{title:".css() variables",filename:"utilities",url:"utilities.html#css-variables"},{title:".rotate()",filename:"utilities",url:"utilities.html#rotate"},{title:".rotate() variables",filename:"utilities",url:"utilities.html#rotate-variables"},{title:".input-placeholder()",filename:"utilities",url:"utilities.html#inputplaceholder"},{title:".input-placeholder() variables",filename:"utilities",url:"utilities.html#inputplaceholder-variables"},{title:".background-gradient()",filename:"utilities",url:"utilities.html#backgroundgradient"},{title:".background-gradient() variables",filename:"utilities",url:"utilities.html#backgroundgradient-variables"},{title:"variables",filename:"variables",url:"variables.html"},{title:"List of Global Variables",filename:"variables",url:"variables.html#list-of-global-variables"},{title:"Table with rows hover mixin variables",filename:"variables",url:"variables.html#table-with-rows-hover-mixin-variables"}];(function(){"use strict";var b=function(a,b){return Array.prototype.indexOf.call(a,b)!==-1},c=function(a,b){return Array.prototype.filter.call(a,b)},d=function(a,b){return Array.prototype.forEach.call(a,b)},e=document.getElementsByTagName("body")[0];e.addEventListener("click",function(a){var b=a.target;b.tagName.toLowerCase()==="svg"&&(b=b.parentNode);var c=!1;b.dataset.toggle!=null&&(a.preventDefault(),b.classList.contains("is-active")||(c=!0)),d(e.querySelectorAll("[data-toggle]"),function(a){a.classList.remove("is-active"),document.getElementById(a.dataset.toggle).hidden=!0}),c&&(b.classList.add("is-active"),document.getElementById(b.dataset.toggle).hidden=!1)}),function(){var f=e.getElementsByClassName("nav")[0];if(!f)return;var g=document.createElement("ul");g.className="nav-results",g.id="nav-search",g.hidden=!0,d(a,function(a){var b,c,d;b=document.createElement("li"),b._title=a.title.toLowerCase(),b.hidden=!0,b.appendChild(c=document.createElement("a")),c.href=a.url,c.innerHTML=a.title,c.appendChild(d=document.createElement("span")),d.innerHTML=a.filename,d.className="nav-results-filename",g.appendChild(b)}),f.appendChild(g);var h=g.children,i=function(a){d(h,function(a){a.hidden=!0});var b=this.value.toLowerCase(),e=[];b!==""&&(e=c(h,function(a){return a._title.indexOf(b)!==-1})),e.length>0?(d(e,function(a){a.hidden=!1}),g.hidden=!1):g.hidden=!0},j=f.querySelector('input[type="search"]');j.addEventListener("keyup",i),j.addEventListener("focus",i),e.addEventListener("click",function(a){if(a.target.classList&&a.target.classList.contains("search"))return;g.hidden=!0}),g.addEventListener("click",function(a){j.value=""});var k=document.createElement("ul");k.id="nav-toc",k.hidden=!0,k.className="nav-results toc-list",c(e.getElementsByTagName("*"),function(a){return b(["h1","h2","h3"],a.tagName.toLowerCase())}).map(function(a){var b=document.createElement("li"),c=document.createElement("a"),d=a.tagName.toLowerCase()[1];c.classList.add("level-"+d),b.appendChild(c),c.href="#"+a.id,c.innerHTML=a.innerHTML,k.appendChild(b)}),f.appendChild(k)}()})(),function(){"use strict";if(location.hash==="#__preview__"||location.protocol==="data:")return;var a=function(a,b){return Array.prototype.forEach.call(a,b)},b=function(a,b){var e=Array.prototype.slice.call(arguments,2);return d(a,function(a){return(c(b)?b||a:a[b]).apply(a,e)})},c=function(a){return Object.prototype.toString.call(a)==="[object Function]"},d=function(a,b){return Array.prototype.map.call(a,b)},e=function(a,b){return d(a,function(a){return a[b]})},f=function(a){var b={},c=a.split(";");for(var d=0;c.length>d;d++){var e=c[d].trim().split("=");b[e[0]]=e[1]}return b},g=function(a,c){return b(e(a,"classList"),"remove",c)},h=function(a,b){a.contentDocument.defaultView.postMessage(b,"*")},i=document.getElementsByTagName("head")[0],j=document.getElementsByTagName("body")[0],k=e(i.querySelectorAll('style[type="text/preview"]'),"innerHTML").join(""),l=e(i.querySelectorAll('script[type="text/preview"]'),"innerHTML").join(""),m=location.href.split("#")[0]+"#__preview__",n=document.createElement("iframe");n.src="data:text/html,",j.appendChild(n),n.addEventListener("load",function(){var b={sameOriginDataUri:!0};try{this.contentDocument,this.contentDocument||(b.sameOriginDataUri=!1)}catch(c){b.sameOriginDataUri=!1}this.parentNode.removeChild(this),a(j.getElementsByTagName("textarea"),function(a,c){o(a,b,c),q(),p(a)})});var o=function(a,b,c){var d,e,f;d=document.createElement("div"),d.appendChild(e=document.createElement("div")),d.className="preview",e.appendChild(f=document.createElement("iframe")),e.className="resizeable",f.setAttribute("scrolling","no"),f.name="iframe"+c++,f.addEventListener("load",function(){var c,d,e,f,g,i,j;j=this.contentDocument;if(!b.sameOriginDataUri&&this.src!==m)return;this.src===m&&(c=j.createElement("html"),c.appendChild(j.createElement("head")),c.appendChild(d=j.createElement("body")),d.innerHTML=a.textContent,j.replaceChild(c,j.documentElement)),g=j.createElement("head"),g.appendChild(f=j.createElement("style")),g.appendChild(e=j.createElement("script")),e.textContent=l,f.textContent=k,i=j.getElementsByTagName("head")[0],i.parentNode.replaceChild(g,i),h(this,"getHeight")});var g;b.sameOriginDataUri?g="data:text/html;charset=utf-8,"+encodeURIComponent("<!doctype html><html><head></head></body>"+a.textContent):g=m,f.setAttribute("src",g);var i=function(){f.contentDocument.body.innerHTML=this.value,h(f,"getHeight")};a.addEventListener("keypress",i),a.addEventListener("keyup",i),a.parentNode.insertBefore(d,a)},p=function(a){var b=document.createElement("div");b.className="preview-code",b.style.position="absolute",b.style.left="-9999px",j.appendChild(b);var c=parseInt(window.getComputedStyle(a).getPropertyValue("max-height"),10),d=function(a){b.textContent=this.value+"\n";var d=b.offsetHeight+2;d>=c?this.style.overflow="auto":this.style.overflow="hidden",this.style.height=b.offsetHeight+2+"px"};a.addEventListener("keypress",d),a.addEventListener("keyup",d),d.call(a)},q=function(){var b=j.getElementsByClassName("settings")[0],c=j.getElementsByClassName("resizeable"),d=30,e=function(b){document.cookie="preview-width="+b,a(c,function(a){b==="auto"&&(b=a.parentNode.offsetWidth),a.style.width=b+"px",h(a.getElementsByTagName("iframe")[0],"getHeight")})},i=f(document.cookie)["preview-width"];if(i){e(i),g(b.getElementsByClassName("is-active"),"is-active");var k=b.querySelector('button[data-width="'+i+'"]');k&&k.classList.add("is-active")}window.addEventListener("message",function(a){if(a.data==null||!a.source)return;var b=a.data,c=document.getElementsByName(a.source.name)[0];b.height!=null&&c&&(c.parentNode.style.height=b.height+d+"px")},!1),b&&c.length>0&&(b.hidden=!1,b.addEventListener("click",function(a){var c=a.target.tagName.toLowerCase(),d;if(c==="button")d=a.target;else{if(c!=="svg")return;d=a.target.parentNode}a.preventDefault(),g(b.getElementsByClassName("is-active"),"is-active"),d.classList.add("is-active");var f=d.dataset.width;e(f)}))}}()})()</script></body></html><!-- Generated with StyleDocco (http://jacobrask.github.com/styledocco). --> +</div><div class="code"><pre><code> +.example-actions-toolbar-12 { + .actions-toolbar(); +} + +@media only screen and (max-width: @screen__m) { + .example-actions-toolbar-12 { + .actions-toolbar-clear-floats(); + } +} +</code></pre></div></article></section><div class="bar bottom"><div hidden class="settings container"><!-- Icons from http://iconmonstr.com--><button title="Desktop (1280)" data-width='1280'><svg viewBox="0 0 412 386" height="24" width="26" class="icon"><path d="m147.6,343.9c-4.5,15.9-26.2,37.6-42.1,42.1h201c-15.3,-4-38.1,-26.8-42.1,-42.1H147.6zM387,0.5H25c-13.8,0-25,11.2-25,25V294c0,13.8 11.2,25 25,25h362c13.8,0 25,-11.2 25,-25V25.5C412,11.7 400.8,0.5 387,0.5zM369.9,238.2H42.1L42.1,42.6 369.9,42.6V238.2z"></path></svg></button><button title="Laptop (1024)" data-width='1024'><svg viewBox="0 0 384 312" height="23" width="28" class="icon"><path d="m349.2,20.5c0,-11-9,-20-20,-20H53.6c-11,0-20,9-20,20v194H349.2v-194zm-27,167H60.6V27.5H322.2v160zm28,42H32.6L2.6,282.1c-3.5,6.2-3.5,13.8 0.1,19.9 3.6,6.2 10.2,9.9 17.3,9.9H363.1c7.1,0 13.7,-3.8 17.3,-10 3.6,-6.2 3.6,-13.8 0,-20l-30.2,-52.5zm-196.9,54 8,-23.5h60.5l8,23.5h-76.5z"></path></svg></button><button title="Tablet (768)" data-width='768'><svg viewBox="0 0 317 412" height="24" width="18" class="icon"><path d="M 316.5,380 V 32 c 0,-17.7 -14.3,-32 -32,-32 H 32 C 14.3,0 0,14.3 0,32 v 348 c 0,17.7 14.3,32 32,32 h 252.5 c 17.7,0 32,-14.3 32,-32 z M 40,367 V 45 H 276.5 V 367 H 40 z m 109.8,22.7 c 0,-4.7 3.8,-8.5 8.5,-8.5 4.7,0 8.5,3.8 8.5,8.5 0,4.7 -3.8,8.5 -8.5,8.5 -4.7,0 -8.5,-3.8 -8.5,-8.5 z"></path></svg></button><button title="Smart phone (320)" data-width='320'><svg viewBox="0 0 224 412" height="24" width="13" class="icon"><path d="M 190.7,0 H 33 C 14.8,0 0,14.8 0,33 v 346 c 0,18.2 14.8,33 33,33 h 157.7 c 18.2,0 33,-14.8 33,-33 V 33 c 0,-18.2 -14.8,-33 -33,-33 z M 94.3,30.2 h 37 c 2.2,0 4,1.8 4,4 0,2.2 -1.8,4 -4,4 h -37 c -2.2,0 -4,-1.8 -4,-4 0,-2.2 1.8,-4 4,-4 z m 18.5,362.8 c -8.8,0 -16,-7.2 -16,-16 0,-8.8 7.2,-16 16,-16 8.8,0 16,7.2 16,16 0,8.8 -7.2,16 -16,16 z M 198.6,343.8 H 25.1 V 68.2 h 173.5 v 275.5 z"></path></svg></button><button title="Feature phone (240)" data-width='240'><svg viewBox="0 0 201 412" height="24" width="12" class="icon"><path d="M 165.5,0.2 V 45 H 25 c -13.8,0 -25,11.2 -25,25 V 387 c 0,13.8 11.2,25 25,25 h 150.5 c 13.8,0 25,-11.2 25,-25 V 0.2 h -35 z M 65.2,366.5 H 34.2 v -24.5 h 31 v 24.5 z m 0,-44.3 H 34.2 v -24.5 h 31 v 24.5 z m 50.5,44.3 H 84.7 v -24.5 h 31 v 24.5 z m 0,-44.3 H 84.7 v -24.5 h 31 v 24.5 z m 50.5,44.3 h -31 v -24.5 h 31 v 24.5 z m 0,-44.3 h -31 v -24.5 h 31 v 24.5 z m 0,-59.3 h -132 V 95.4 h 132 V 262.9 z"></path></svg></button><button title="Auto (100%)" data-width="auto" class="auto is-active">Auto</button></div></div><script>(function(){var a=[{title:"actions-toolbar",filename:"actions-toolbar",url:"actions-toolbar.html"},{title:"Actions toolbar",filename:"actions-toolbar",url:"actions-toolbar.html#actions-toolbar"},{title:"Actions toolbar mixin variables",filename:"actions-toolbar",url:"actions-toolbar.html#actions-toolbar-mixin-variables"},{title:"Actions toolbar alignment",filename:"actions-toolbar",url:"actions-toolbar.html#actions-toolbar-alignment"},{title:"Reverse primary and secondary blocks",filename:"actions-toolbar",url:"actions-toolbar.html#reverse-primary-and-secondary-blocks"},{title:"Actions toolbar indents customizations",filename:"actions-toolbar",url:"actions-toolbar.html#actions-toolbar-indents-customizations"},{title:"Responsive actions toolbar",filename:"actions-toolbar",url:"actions-toolbar.html#responsive-actions-toolbar"},{title:"breadcrumbs",filename:"breadcrumbs",url:"breadcrumbs.html"},{title:"Breadcrumbs",filename:"breadcrumbs",url:"breadcrumbs.html#breadcrumbs"},{title:"Breadcrumbs variables",filename:"breadcrumbs",url:"breadcrumbs.html#breadcrumbs-variables"},{title:"Button-styled breadcrumbs with gradient background, border, and no separating symbol",filename:"breadcrumbs",url:"breadcrumbs.html#buttonstyled-breadcrumbs-with-gradient-background-border-and-no-separating-symbol"},{title:"Breadcrumbs with solid background",filename:"breadcrumbs",url:"breadcrumbs.html#breadcrumbs-with-solid-background"},{title:"buttons",filename:"buttons",url:"buttons.html"},{title:"Default button",filename:"buttons",url:"buttons.html#default-button"},{title:"Button variables",filename:"buttons",url:"buttons.html#button-variables"},{title:"Button as an icon",filename:"buttons",url:"buttons.html#button-as-an-icon"},{title:"Button with an icon on the left or right side of the text",filename:"buttons",url:"buttons.html#button-with-an-icon-on-the-left-or-right-side-of-the-text"},{title:"Button with fixed width",filename:"buttons",url:"buttons.html#button-with-fixed-width"},{title:"Primary button",filename:"buttons",url:"buttons.html#primary-button"},{title:"Primary button variables",filename:"buttons",url:"buttons.html#primary-button-variables"},{title:"Button with gradient background",filename:"buttons",url:"buttons.html#button-with-gradient-background"},{title:"Button as a link",filename:"buttons",url:"buttons.html#button-as-a-link"},{title:"Link as a button",filename:"buttons",url:"buttons.html#link-as-a-button"},{title:"Button reset",filename:"buttons",url:"buttons.html#button-reset"},{title:"Button revert secondary color",filename:"buttons",url:"buttons.html#button-revert-secondary-color"},{title:"Button revert secondary color variables",filename:"buttons",url:"buttons.html#button-revert-secondary-color-variables"},{title:"Button revert secondary size",filename:"buttons",url:"buttons.html#button-revert-secondary-size"},{title:"Button revert secondary size variables",filename:"buttons",url:"buttons.html#button-revert-secondary-size-variables"},{title:"docs",filename:"docs",url:"docs.html"},{title:"Documentation",filename:"docs",url:"docs.html#documentation"},{title:"dropdowns",filename:"dropdowns",url:"dropdowns.html"},{title:"Drop-down and split buttons mixins",filename:"dropdowns",url:"dropdowns.html#dropdown-and-split-buttons-mixins"},{title:"Drop-down",filename:"dropdowns",url:"dropdowns.html#dropdown"},{title:"Drop-down variables",filename:"dropdowns",url:"dropdowns.html#dropdown-variables"},{title:"Drop-down with icon customization",filename:"dropdowns",url:"dropdowns.html#dropdown-with-icon-customization"},{title:"Modify dropdown list styles",filename:"dropdowns",url:"dropdowns.html#modify-dropdown-list-styles"},{title:"Split button",filename:"dropdowns",url:"dropdowns.html#split-button"},{title:"Split button variables",filename:"dropdowns",url:"dropdowns.html#split-button-variables"},{title:"Split button - button styling",filename:"dropdowns",url:"dropdowns.html#split-button-button-styling"},{title:"Split button icon customization",filename:"dropdowns",url:"dropdowns.html#split-button-icon-customization"},{title:"Split button drop-down list customization",filename:"dropdowns",url:"dropdowns.html#split-button-dropdown-list-customization"},{title:"forms",filename:"forms",url:"forms.html"},{title:"Forms mixins",filename:"forms",url:"forms.html#forms-mixins"},{title:"Global forms elements customization",filename:"forms",url:"forms.html#global-forms-elements-customization"},{title:"Fieldsets & fields customization",filename:"forms",url:"forms.html#fieldsets-fields-customization"},{title:"Fieldset and legend customization variables",filename:"forms",url:"forms.html#fieldset-and-legend-customization-variables"},{title:"Fields customization variables",filename:"forms",url:"forms.html#fields-customization-variables"},{title:"Required fields message customization variables",filename:"forms",url:"forms.html#required-fields-message-customization-variables"},{title:"Form element inputs customization",filename:"forms",url:"forms.html#form-element-inputs-customization"},{title:"Form element inputs customization variables",filename:"forms",url:"forms.html#form-element-inputs-customization-variables"},{title:"Form element choice",filename:"forms",url:"forms.html#form-element-choice"},{title:"Form element choice variables",filename:"forms",url:"forms.html#form-element-choice-variables"},{title:"Custom color",filename:"forms",url:"forms.html#custom-color"},{title:"Input number - input-text view",filename:"forms",url:"forms.html#input-number-inputtext-view"},{title:"Input search - input-text view",filename:"forms",url:"forms.html#input-search-inputtext-view"},{title:"Form validation",filename:"forms",url:"forms.html#form-validation"},{title:"Form validation variables// <pre>",filename:"forms",url:"forms.html#form-validation-variables-pre"},{title:"icons",filename:"icons",url:"icons.html"},{title:"Icons",filename:"icons",url:"icons.html#icons"},{title:"Icon with image or sprite",filename:"icons",url:"icons.html#icon-with-image-or-sprite"},{title:"Icon with image or sprite variables",filename:"icons",url:"icons.html#icon-with-image-or-sprite-variables"},{title:"Icon position for an icon with image or sprite",filename:"icons",url:"icons.html#icon-position-for-an-icon-with-image-or-sprite"},{title:"Position for icon with image or sprite mixin variables",filename:"icons",url:"icons.html#position-for-icon-with-image-or-sprite-mixin-variables"},{title:"Icon sprite position (with grid)",filename:"icons",url:"icons.html#icon-sprite-position-with-grid"},{title:"Icon sprite position variables",filename:"icons",url:"icons.html#icon-sprite-position-variables"},{title:"Image/sprite icon size",filename:"icons",url:"icons.html#imagesprite-icon-size"},{title:"Image/sprite icon size variables",filename:"icons",url:"icons.html#imagesprite-icon-size-variables"},{title:"Font icon",filename:"icons",url:"icons.html#font-icon"},{title:"Font icon variables",filename:"icons",url:"icons.html#font-icon-variables"},{title:"Change the size of font icon",filename:"icons",url:"icons.html#change-the-size-of-font-icon"},{title:"Change the size of font icon variables",filename:"icons",url:"icons.html#change-the-size-of-font-icon-variables"},{title:"Hide icon text",filename:"icons",url:"icons.html#hide-icon-text"},{title:"Sprite and font icons for Blank theme",filename:"icons",url:"icons.html#sprite-and-font-icons-for-blank-theme"},{title:"layout",filename:"layout",url:"layout.html"},{title:"Layout",filename:"layout",url:"layout.html#layout"},{title:"Layout global variables",filename:"layout",url:"layout.html#layout-global-variables"},{title:"Page layouts",filename:"layout",url:"layout.html#page-layouts"},{title:"Layout column",filename:"layout",url:"layout.html#layout-column"},{title:"Layout column variables",filename:"layout",url:"layout.html#layout-column-variables"},{title:"Layout width",filename:"layout",url:"layout.html#layout-width"},{title:"Layout width variables",filename:"layout",url:"layout.html#layout-width-variables"},{title:"lib",filename:"lib",url:"lib.html"},{title:"Including Magento UI library to your theme",filename:"lib",url:"lib.html#including-magento-ui-library-to-your-theme"},{title:"loaders",filename:"loaders",url:"loaders.html"},{title:"Loaders",filename:"loaders",url:"loaders.html#loaders"},{title:"Default loader variables",filename:"loaders",url:"loaders.html#default-loader-variables"},{title:"Loading",filename:"loaders",url:"loaders.html#loading"},{title:"Loading default variables",filename:"loaders",url:"loaders.html#loading-default-variables"},{title:"messages",filename:"messages",url:"messages.html"},{title:"Messages",filename:"messages",url:"messages.html#messages"},{title:"Information message",filename:"messages",url:"messages.html#information-message"},{title:"Warning message",filename:"messages",url:"messages.html#warning-message"},{title:"Error message",filename:"messages",url:"messages.html#error-message"},{title:"Success message",filename:"messages",url:"messages.html#success-message"},{title:"Notice message",filename:"messages",url:"messages.html#notice-message"},{title:"Message with inner icon",filename:"messages",url:"messages.html#message-with-inner-icon"},{title:"Message with lateral icon",filename:"messages",url:"messages.html#message-with-lateral-icon"},{title:"Custom message style",filename:"messages",url:"messages.html#custom-message-style"},{title:"Messages global variables",filename:"messages",url:"messages.html#messages-global-variables"},{title:"pages",filename:"pages",url:"pages.html"},{title:"Pagination HTML markup",filename:"pages",url:"pages.html#pagination-html-markup"},{title:"Pagination variables",filename:"pages",url:"pages.html#pagination-variables"},{title:"Pagination with label and gradient background on links",filename:"pages",url:"pages.html#pagination-with-label-and-gradient-background-on-links"},{title:'Pagination with "previous"..."next" text links and label',filename:"pages",url:"pages.html#pagination-with-previousnext-text-links-and-label"},{title:"Pagination without label, with solid background",filename:"pages",url:"pages.html#pagination-without-label-with-solid-background"},{title:"popups",filename:"popups",url:"popups.html"},{title:"Popups",filename:"popups",url:"popups.html#popups"},{title:"Popup variables",filename:"popups",url:"popups.html#popup-variables"},{title:"Window overlay mixin variables",filename:"popups",url:"popups.html#window-overlay-mixin-variables"},{title:"Fixed height popup",filename:"popups",url:"popups.html#fixed-height-popup"},{title:"Fixed content height popup",filename:"popups",url:"popups.html#fixed-content-height-popup"},{title:"Margins for header, content and footer block in popup",filename:"popups",url:"popups.html#margins-for-header-content-and-footer-block-in-popup"},{title:"Popup titles styled as theme headings",filename:"popups",url:"popups.html#popup-titles-styled-as-theme-headings"},{title:"Popup action toolbar",filename:"popups",url:"popups.html#popup-action-toolbar"},{title:"Popup Close button without an icon",filename:"popups",url:"popups.html#popup-close-button-without-an-icon"},{title:"Modify the icon of popup Close button",filename:"popups",url:"popups.html#modify-the-icon-of-popup-close-button"},{title:"Modify overlay styles",filename:"popups",url:"popups.html#modify-overlay-styles"},{title:"rating",filename:"rating",url:"rating.html"},{title:"Ratings",filename:"rating",url:"rating.html#ratings"},{title:"Global rating variables",filename:"rating",url:"rating.html#global-rating-variables"},{title:"Rating with vote",filename:"rating",url:"rating.html#rating-with-vote"},{title:"Rating with vote icons number customization",filename:"rating",url:"rating.html#rating-with-vote-icons-number-customization"},{title:"Rating with vote icons colors customization",filename:"rating",url:"rating.html#rating-with-vote-icons-colors-customization"},{title:"Rating with vote icons symbol customization",filename:"rating",url:"rating.html#rating-with-vote-icons-symbol-customization"},{title:"Accessible rating with vote",filename:"rating",url:"rating.html#accessible-rating-with-vote"},{title:"Rating summary",filename:"rating",url:"rating.html#rating-summary"},{title:"Rating summary icons number customization",filename:"rating",url:"rating.html#rating-summary-icons-number-customization"},{title:"Rating summary icons color customization",filename:"rating",url:"rating.html#rating-summary-icons-color-customization"},{title:"Rating summary icons symbol customization",filename:"rating",url:"rating.html#rating-summary-icons-symbol-customization"},{title:"Rating summary hide label",filename:"rating",url:"rating.html#rating-summary-hide-label"},{title:"Rating summary multiple ratings",filename:"rating",url:"rating.html#rating-summary-multiple-ratings"},{title:"Rating hide label mixin",filename:"rating",url:"rating.html#rating-hide-label-mixin"},{title:"resets",filename:"resets",url:"resets.html"},{title:"Resets",filename:"resets",url:"resets.html#resets"},{title:"responsive",filename:"responsive",url:"responsive.html"},{title:"Responsive",filename:"responsive",url:"responsive.html#responsive"},{title:"Responsive mixins usage",filename:"responsive",url:"responsive.html#responsive-mixins-usage"},{title:"Media query style groups separation variables",filename:"responsive",url:"responsive.html#media-query-style-groups-separation-variables"},{title:"Responsive breakpoints",filename:"responsive",url:"responsive.html#responsive-breakpoints"},{title:"sections",filename:"sections",url:"sections.html"},{title:"Tabs and accordions",filename:"sections",url:"sections.html#tabs-and-accordions"},{title:"Tabs",filename:"sections",url:"sections.html#tabs"},{title:"Tabs mixin variables",filename:"sections",url:"sections.html#tabs-mixin-variables"},{title:"Tabs with content top border",filename:"sections",url:"sections.html#tabs-with-content-top-border"},{title:"Accordion",filename:"sections",url:"sections.html#accordion"},{title:"Accordion mixin variables",filename:"sections",url:"sections.html#accordion-mixin-variables"},{title:"Responsive tabs",filename:"sections",url:"sections.html#responsive-tabs"},{title:"Tabs Base",filename:"sections",url:"sections.html#tabs-base"},{title:"Accordion Base",filename:"sections",url:"sections.html#accordion-base"},{title:"tables",filename:"tables",url:"tables.html"},{title:"Tables",filename:"tables",url:"tables.html#tables"},{title:"Table mixin variables",filename:"tables",url:"tables.html#table-mixin-variables"},{title:"Table typography",filename:"tables",url:"tables.html#table-typography"},{title:"Table typography mixin variables",filename:"tables",url:"tables.html#table-typography-mixin-variables"},{title:"Table caption",filename:"tables",url:"tables.html#table-caption"},{title:"Table caption mixin variables",filename:"tables",url:"tables.html#table-caption-mixin-variables"},{title:"Table cells resize",filename:"tables",url:"tables.html#table-cells-resize"},{title:"Table cells resize variables",filename:"tables",url:"tables.html#table-cells-resize-variables"},{title:"Table background customization",filename:"tables",url:"tables.html#table-background-customization"},{title:"Table background mixin variables",filename:"tables",url:"tables.html#table-background-mixin-variables"},{title:"Table borders customization",filename:"tables",url:"tables.html#table-borders-customization"},{title:"Table borders mixin variables",filename:"tables",url:"tables.html#table-borders-mixin-variables"},{title:"Table with horizontal borders",filename:"tables",url:"tables.html#table-with-horizontal-borders"},{title:"Table with vertical borders",filename:"tables",url:"tables.html#table-with-vertical-borders"},{title:"Table with light borders",filename:"tables",url:"tables.html#table-with-light-borders"},{title:"Table without borders",filename:"tables",url:"tables.html#table-without-borders"},{title:"Striped table",filename:"tables",url:"tables.html#striped-table"},{title:"Striped table mixin variables",filename:"tables",url:"tables.html#striped-table-mixin-variables"},{title:"Table with rows hover",filename:"tables",url:"tables.html#table-with-rows-hover"},{title:"Table with rows hover mixin variables",filename:"tables",url:"tables.html#table-with-rows-hover-mixin-variables"},{title:"Responsive table technics #1",filename:"tables",url:"tables.html#responsive-table-technics-1"},{title:"Responsive table technics #2",filename:"tables",url:"tables.html#responsive-table-technics-2"},{title:"Responsive table technics #2 mixin variables",filename:"tables",url:"tables.html#responsive-table-technics-2-mixin-variables"},{title:"tooltips",filename:"tooltips",url:"tooltips.html"},{title:"Tooltips",filename:"tooltips",url:"tooltips.html#tooltips"},{title:"Tooltips variables",filename:"tooltips",url:"tooltips.html#tooltips-variables"},{title:"typography",filename:"typography",url:"typography.html"},{title:"Typogrphy",filename:"typography",url:"typography.html#typogrphy"},{title:"Typography variables",filename:"typography",url:"typography.html#typography-variables"},{title:"Font-size mixin",filename:"typography",url:"typography.html#fontsize-mixin"},{title:"Line-height mixin",filename:"typography",url:"typography.html#lineheight-mixin"},{title:"Word breaking mixin",filename:"typography",url:"typography.html#word-breaking-mixin"},{title:"Font face mixin",filename:"typography",url:"typography.html#font-face-mixin"},{title:"Text overflow mixin",filename:"typography",url:"typography.html#text-overflow-mixin"},{title:"Text hide",filename:"typography",url:"typography.html#text-hide"},{title:"Hyphens",filename:"typography",url:"typography.html#hyphens"},{title:"Font style and color",filename:"typography",url:"typography.html#font-style-and-color"},{title:"Font style mixin variables",filename:"typography",url:"typography.html#font-style-mixin-variables"},{title:"Reset list styles",filename:"typography",url:"typography.html#reset-list-styles"},{title:"Reset list styles variables",filename:"typography",url:"typography.html#reset-list-styles-variables"},{title:"Inline-block list item styling",filename:"typography",url:"typography.html#inlineblock-list-item-styling"},{title:"Link styling mixin",filename:"typography",url:"typography.html#link-styling-mixin"},{title:"Link styling mixin variables",filename:"typography",url:"typography.html#link-styling-mixin-variables"},{title:"Heading styling mixin",filename:"typography",url:"typography.html#heading-styling-mixin"},{title:"Base typography mixins",filename:"typography",url:"typography.html#base-typography-mixins"},{title:"Headings typography mixin",filename:"typography",url:"typography.html#headings-typography-mixin"},{title:"Typography links mixin",filename:"typography",url:"typography.html#typography-links-mixin"},{title:"Typography lists mixin",filename:"typography",url:"typography.html#typography-lists-mixin"},{title:"Typography code elements mixin",filename:"typography",url:"typography.html#typography-code-elements-mixin"},{title:"Typography blockquote",filename:"typography",url:"typography.html#typography-blockquote"},{title:"utilities",filename:"utilities",url:"utilities.html"},{title:"Utilities",filename:"utilities",url:"utilities.html#utilities"},{title:".clearfix()",filename:"utilities",url:"utilities.html#clearfix"},{title:".visibility-hidden()",filename:"utilities",url:"utilities.html#visibilityhidden"},{title:".visually-hidden()",filename:"utilities",url:"utilities.html#visuallyhidden"},{title:".visually-hidden-reset()",filename:"utilities",url:"utilities.html#visuallyhiddenreset"},{title:".css()",filename:"utilities",url:"utilities.html#css"},{title:".css() variables",filename:"utilities",url:"utilities.html#css-variables"},{title:".rotate()",filename:"utilities",url:"utilities.html#rotate"},{title:".rotate() variables",filename:"utilities",url:"utilities.html#rotate-variables"},{title:".input-placeholder()",filename:"utilities",url:"utilities.html#inputplaceholder"},{title:".input-placeholder() variables",filename:"utilities",url:"utilities.html#inputplaceholder-variables"},{title:".background-gradient()",filename:"utilities",url:"utilities.html#backgroundgradient"},{title:".background-gradient() variables",filename:"utilities",url:"utilities.html#backgroundgradient-variables"},{title:"variables",filename:"variables",url:"variables.html"},{title:"List of Global Variables",filename:"variables",url:"variables.html#list-of-global-variables"},{title:"Table with rows hover mixin variables",filename:"variables",url:"variables.html#table-with-rows-hover-mixin-variables"}];(function(){"use strict";var b=function(a,b){return Array.prototype.indexOf.call(a,b)!==-1},c=function(a,b){return Array.prototype.filter.call(a,b)},d=function(a,b){return Array.prototype.forEach.call(a,b)},e=document.getElementsByTagName("body")[0];e.addEventListener("click",function(a){var b=a.target;b.tagName.toLowerCase()==="svg"&&(b=b.parentNode);var c=!1;b.dataset.toggle!=null&&(a.preventDefault(),b.classList.contains("is-active")||(c=!0)),d(e.querySelectorAll("[data-toggle]"),function(a){a.classList.remove("is-active"),document.getElementById(a.dataset.toggle).hidden=!0}),c&&(b.classList.add("is-active"),document.getElementById(b.dataset.toggle).hidden=!1)}),function(){var f=e.getElementsByClassName("nav")[0];if(!f)return;var g=document.createElement("ul");g.className="nav-results",g.id="nav-search",g.hidden=!0,d(a,function(a){var b,c,d;b=document.createElement("li"),b._title=a.title.toLowerCase(),b.hidden=!0,b.appendChild(c=document.createElement("a")),c.href=a.url,c.innerHTML=a.title,c.appendChild(d=document.createElement("span")),d.innerHTML=a.filename,d.className="nav-results-filename",g.appendChild(b)}),f.appendChild(g);var h=g.children,i=function(a){d(h,function(a){a.hidden=!0});var b=this.value.toLowerCase(),e=[];b!==""&&(e=c(h,function(a){return a._title.indexOf(b)!==-1})),e.length>0?(d(e,function(a){a.hidden=!1}),g.hidden=!1):g.hidden=!0},j=f.querySelector('input[type="search"]');j.addEventListener("keyup",i),j.addEventListener("focus",i),e.addEventListener("click",function(a){if(a.target.classList&&a.target.classList.contains("search"))return;g.hidden=!0}),g.addEventListener("click",function(a){j.value=""});var k=document.createElement("ul");k.id="nav-toc",k.hidden=!0,k.className="nav-results toc-list",c(e.getElementsByTagName("*"),function(a){return b(["h1","h2","h3"],a.tagName.toLowerCase())}).map(function(a){var b=document.createElement("li"),c=document.createElement("a"),d=a.tagName.toLowerCase()[1];c.classList.add("level-"+d),b.appendChild(c),c.href="#"+a.id,c.innerHTML=a.innerHTML,k.appendChild(b)}),f.appendChild(k)}()})(),function(){"use strict";if(location.hash==="#__preview__"||location.protocol==="data:")return;var a=function(a,b){return Array.prototype.forEach.call(a,b)},b=function(a,b){var e=Array.prototype.slice.call(arguments,2);return d(a,function(a){return(c(b)?b||a:a[b]).apply(a,e)})},c=function(a){return Object.prototype.toString.call(a)==="[object Function]"},d=function(a,b){return Array.prototype.map.call(a,b)},e=function(a,b){return d(a,function(a){return a[b]})},f=function(a){var b={},c=a.split(";");for(var d=0;c.length>d;d++){var e=c[d].trim().split("=");b[e[0]]=e[1]}return b},g=function(a,c){return b(e(a,"classList"),"remove",c)},h=function(a,b){a.contentDocument.defaultView.postMessage(b,"*")},i=document.getElementsByTagName("head")[0],j=document.getElementsByTagName("body")[0],k=e(i.querySelectorAll('style[type="text/preview"]'),"innerHTML").join(""),l=e(i.querySelectorAll('script[type="text/preview"]'),"innerHTML").join(""),m=location.href.split("#")[0]+"#__preview__",n=document.createElement("iframe");n.src="data:text/html,",j.appendChild(n),n.addEventListener("load",function(){var b={sameOriginDataUri:!0};try{this.contentDocument,this.contentDocument||(b.sameOriginDataUri=!1)}catch(c){b.sameOriginDataUri=!1}this.parentNode.removeChild(this),a(j.getElementsByTagName("textarea"),function(a,c){o(a,b,c),q(),p(a)})});var o=function(a,b,c){var d,e,f;d=document.createElement("div"),d.appendChild(e=document.createElement("div")),d.className="preview",e.appendChild(f=document.createElement("iframe")),e.className="resizeable",f.setAttribute("scrolling","no"),f.name="iframe"+c++,f.addEventListener("load",function(){var c,d,e,f,g,i,j;j=this.contentDocument;if(!b.sameOriginDataUri&&this.src!==m)return;this.src===m&&(c=j.createElement("html"),c.appendChild(j.createElement("head")),c.appendChild(d=j.createElement("body")),d.innerHTML=a.textContent,j.replaceChild(c,j.documentElement)),g=j.createElement("head"),g.appendChild(f=j.createElement("style")),g.appendChild(e=j.createElement("script")),e.textContent=l,f.textContent=k,i=j.getElementsByTagName("head")[0],i.parentNode.replaceChild(g,i),h(this,"getHeight")});var g;b.sameOriginDataUri?g="data:text/html;charset=utf-8,"+encodeURIComponent("<!doctype html><html><head></head></body>"+a.textContent):g=m,f.setAttribute("src",g);var i=function(){f.contentDocument.body.innerHTML=this.value,h(f,"getHeight")};a.addEventListener("keypress",i),a.addEventListener("keyup",i),a.parentNode.insertBefore(d,a)},p=function(a){var b=document.createElement("div");b.className="preview-code",b.style.position="absolute",b.style.left="-9999px",j.appendChild(b);var c=parseInt(window.getComputedStyle(a).getPropertyValue("max-height"),10),d=function(a){b.textContent=this.value+"\n";var d=b.offsetHeight+2;d>=c?this.style.overflow="auto":this.style.overflow="hidden",this.style.height=b.offsetHeight+2+"px"};a.addEventListener("keypress",d),a.addEventListener("keyup",d),d.call(a)},q=function(){var b=j.getElementsByClassName("settings")[0],c=j.getElementsByClassName("resizeable"),d=30,e=function(b){document.cookie="preview-width="+b,a(c,function(a){b==="auto"&&(b=a.parentNode.offsetWidth),a.style.width=b+"px",h(a.getElementsByTagName("iframe")[0],"getHeight")})},i=f(document.cookie)["preview-width"];if(i){e(i),g(b.getElementsByClassName("is-active"),"is-active");var k=b.querySelector('button[data-width="'+i+'"]');k&&k.classList.add("is-active")}window.addEventListener("message",function(a){if(a.data==null||!a.source)return;var b=a.data,c=document.getElementsByName(a.source.name)[0];b.height!=null&&c&&(c.parentNode.style.height=b.height+d+"px")},!1),b&&c.length>0&&(b.hidden=!1,b.addEventListener("click",function(a){var c=a.target.tagName.toLowerCase(),d;if(c==="button")d=a.target;else{if(c!=="svg")return;d=a.target.parentNode}a.preventDefault(),g(b.getElementsByClassName("is-active"),"is-active"),d.classList.add("is-active");var f=d.dataset.width;e(f)}))}}()})()</script></body></html><!-- Generated with StyleDocco (http://jacobrask.github.com/styledocco). --> diff --git a/lib/web/css/docs/source/actions-toolbar.less b/lib/web/css/docs/source/actions-toolbar.less index 7af58eb3403fe68211d22bf70eeedc3fa55a4e82..ea3bcbdea371f7a724c7b1ed489f78e80c3e4094 100644 --- a/lib/web/css/docs/source/actions-toolbar.less +++ b/lib/web/css/docs/source/actions-toolbar.less @@ -308,7 +308,7 @@ // <button type="submit" class="action submit2" title="Submit2"><span>Submit2</span></button> // </div> // <div class="secondary"> -// <a href="#" class="action towishlist"><span>Add to Wishlist</span></a> +// <a href="#" class="action towishlist"><span>Add to Wish List</span></a> // <a href="#" class="action tocompare"><span>Add to Compare</span></a> // </div> // </div> @@ -323,7 +323,7 @@ // <button type="submit" class="action submit2" title="Submit2"><span>Submit2</span></button> // </div> // <div class="secondary"> -// <a href="#" class="action towishlist"><span>Add to Wishlist</span></a> +// <a href="#" class="action towishlist"><span>Add to Wish List</span></a> // <a href="#" class="action tocompare"><span>Add to Compare</span></a> // </div> // </div> @@ -360,7 +360,7 @@ // <button type="submit" class="action submit" title="Submit"><span>Submit</span></button> // </div> // <div class="secondary"> -// <a href="#" class="action towishlist"><span>Add to Wishlist</span></a> +// <a href="#" class="action towishlist"><span>Add to Wish List</span></a> // </div> // </div> // ``` diff --git a/lib/web/css/source/components/_modals.less b/lib/web/css/source/components/_modals.less new file mode 100644 index 0000000000000000000000000000000000000000..c7776d6684e7e5880247625d2032f0cd4b33fc02 --- /dev/null +++ b/lib/web/css/source/components/_modals.less @@ -0,0 +1,201 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Lib -> Components -> Modals +// _____________________________________________ + +// +// Variables +// --------------------------------------------- + +@import '../../source/_variables.less'; + +@modal__background-color: @color-white; +@modal__box-shadow: 0 0 12px 2px rgba(0, 0, 0, .35); + +@modal-popup__indent-vertical: 5rem; +@modal-popup__padding: 3rem; +@modal-popup__width: 75%; +@modal-popup__z-index: @modal__z-index; + +@modal-slide__first__indent-left: 14.8rem; +@modal-slide__indent-left: 4.5rem; +@modal-slide__padding: 2.6rem; +@modal-slide__z-index: @modal__z-index; + +@modal-slide-header__padding-vertical: 2.1rem; + +// +// Utilities +// --------------------------------------------- + +.abs-modal() { + bottom: 0; + left: 0; + min-width: 0; + position: fixed; + right: 0; + top: 0; + visibility: hidden; + pointer-events: none; + &._show { + visibility: visible; + .modal-inner-wrap { + transform: translate(0, 0); + } + } + .modal-inner-wrap { + background-color: @modal__background-color; + box-shadow: @modal__box-shadow; + opacity: 1; + pointer-events: auto; + } +} + +.abs-modal-slide() { + left: @modal-slide__first__indent-left; + z-index: @modal-slide__z-index; + &._show { + .modal-inner-wrap { + transform: translateX(0); + } + } + .modal-inner-wrap { + height: 100%; + overflow-y: auto; + position: static; + transform: translateX(100%); + transition-duration: .3s; + transition-timing-function: ease-in-out; + transition-property: transform, visibility; + width: auto; + } +} + +.abs-modal-popup() { + left: 0; + overflow-y: auto; + z-index: @modal-popup__z-index; + &._show { + .modal-inner-wrap { + transform: translateY(0); + } + } + .modal-inner-wrap { + .vendor-prefix-display(flex); + .vendor-prefix-flex-direction(column); + height: auto; + margin: @modal-popup__indent-vertical (100% - @modal-popup__width) / 2; + position: absolute; + transform: translateY(-200%); + transition-duration: .2s; + transition-timing-function: ease; + transition-property: transform, visibility; + width: @modal-popup__width; + } +} + +// + +._has-modal { + height: 100vh; + overflow: hidden; + width: 100vw; +} + +// Modals overlay + +.modals-overlay { + &:extend(.ui-widget-overlay all); + z-index: @overlay__z-index; +} + +.modal-slide, +.modal-popup { + .abs-modal(); +} + +.modal-slide { + .abs-modal-slide(); + &._inner-scroll { + .modal-inner-wrap { + .vendor-prefix-display(flex); + .vendor-prefix-flex-direction(column); + overflow-y: visible; + } + .modal-header, + .modal-footer { + .vendor-prefix-flex-grow(0); + .vendor-prefix-flex-shrink(0); + } + .modal-content { + overflow-y: auto; + } + .modal-footer { + margin-top: auto; + } + } + .modal-header, + .modal-content, + .modal-footer { + padding: 0 @modal-slide__padding @modal-slide__padding; + } + .modal-header { + padding-top: @modal-slide-header__padding-vertical; + padding-bottom: @modal-slide-header__padding-vertical; + } +} + +.modal-popup { + .abs-modal-popup(); + // If applied, switching outer popup scroll to inner + &._inner-scroll { + overflow-y: visible; + .modal-inner-wrap { + max-height: 90%; + } + .modal-content { + overflow-y: auto; + } + } + .modal-header, + .modal-content, + .modal-footer { + padding-left: @modal-popup__padding; + padding-right: @modal-popup__padding; + } + .modal-header, + .modal-footer { + .vendor-prefix-flex-grow(0); + .vendor-prefix-flex-shrink(0); + } + .modal-header { + padding-top: @modal-popup__padding; + padding-bottom: @modal-popup__padding; + } + .modal-footer { + margin-top: auto; + padding-top: @modal-popup__padding; + padding-bottom: @modal-popup__padding; + } +} + +// +// Mobile +// --------------------------------------------- + +// Mobile transform to modal-slide +@media (max-width: @screen__m) { + .modal-popup { + &.modal-slide { + .abs-modal-slide(); + .modal-inner-wrap { + margin: 0; + max-height: none; + } + } + } +} diff --git a/lib/web/css/source/lib/_variables.less b/lib/web/css/source/lib/_variables.less index 812c1f86a30bb01981e2a7393c54db63b69a9e4a..c40c9a7cb0ce35df69f44b025d99d9afb4ec979d 100644 --- a/lib/web/css/source/lib/_variables.less +++ b/lib/web/css/source/lib/_variables.less @@ -28,3 +28,6 @@ @import 'variables/_actions-toolbar.less'; @import 'variables/_breadcrumbs.less'; @import 'variables/_popups.less'; +@import 'variables/_structure.less'; + +@import 'variables/_components.less'; diff --git a/lib/web/css/source/lib/variables/_components.less b/lib/web/css/source/lib/variables/_components.less new file mode 100644 index 0000000000000000000000000000000000000000..0a4a0d9d688ce28dbd51cb24bef4bffad9d6f432 --- /dev/null +++ b/lib/web/css/source/lib/variables/_components.less @@ -0,0 +1,13 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Lib -> Components -> Variables +// _____________________________________________ + +@component__box-shadow__base: 1px 1px @component__shadow-size__base rgba(0, 0, 0, .5); +@component__shadow-size__base: 5px; + +@component-modal__opacity: .98; diff --git a/lib/web/css/source/lib/variables/_structure.less b/lib/web/css/source/lib/variables/_structure.less new file mode 100644 index 0000000000000000000000000000000000000000..b29e0b2d2f65f19b0236fe0140caabef5d2f1a0f --- /dev/null +++ b/lib/web/css/source/lib/variables/_structure.less @@ -0,0 +1,29 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Structure +// _____________________________________________ + +// +// Z axis +// --------------------------------------------- + +@z-index-1: 100; +@z-index-2: 200; +@z-index-3: 300; +@z-index-4: 400; +@z-index-5: 500; +@z-index-6: 600; +@z-index-7: 700; +@z-index-8: 800; +@z-index-9: 900; +@z-index-10: 1000; + +// z-index 8 +@overlay__z-index: @modal__z-index - 1; + +// z-index 9 +@modal__z-index: @z-index-9; diff --git a/lib/web/legacy-build.min.js b/lib/web/legacy-build.min.js index 0312112dca5d41449fbc5685310ead5593c7353e..e6c723156294c1337da171abb4a71eafff53bc38 100644 --- a/lib/web/legacy-build.min.js +++ b/lib/web/legacy-build.min.js @@ -5,4 +5,4 @@ var Prototype={Version:"1.7",Browser:(function(){var d=navigator.userAgent;var b * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ -(function(){var w=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,p=0,g=Object.prototype.toString,u=false,o=true;[0,0].sort(function(){o=false;return 0});var d=function(L,B,I,D){I=I||[];var e=B=B||document;if(B.nodeType!==1&&B.nodeType!==9){return[]}if(!L||typeof L!=="string"){return I}var J=[],K,G,P,O,H,A,z=true,E=v(B),N=L;while((w.exec(""),K=w.exec(N))!==null){N=K[3];J.push(K[1]);if(K[2]){A=K[3];break}}if(J.length>1&&q.exec(L)){if(J.length===2&&h.relative[J[0]]){G=l(J[0]+J[1],B)}else{G=h.relative[J[0]]?[B]:d(J.shift(),B);while(J.length){L=J.shift();if(h.relative[L]){L+=J.shift()}G=l(L,G)}}}else{if(!D&&J.length>1&&B.nodeType===9&&!E&&h.match.ID.test(J[0])&&!h.match.ID.test(J[J.length-1])){var Q=d.find(J.shift(),B,E);B=Q.expr?d.filter(Q.expr,Q.set)[0]:Q.set[0]}if(B){var Q=D?{expr:J.pop(),set:b(D)}:d.find(J.pop(),J.length===1&&(J[0]==="~"||J[0]==="+")&&B.parentNode?B.parentNode:B,E);G=Q.expr?d.filter(Q.expr,Q.set):Q.set;if(J.length>0){P=b(G)}else{z=false}while(J.length){var C=J.pop(),F=C;if(!h.relative[C]){C=""}else{F=J.pop()}if(F==null){F=B}h.relative[C](P,F,E)}}else{P=J=[]}}if(!P){P=G}if(!P){throw"Syntax error, unrecognized expression: "+(C||L)}if(g.call(P)==="[object Array]"){if(!z){I.push.apply(I,P)}else{if(B&&B.nodeType===1){for(var M=0;P[M]!=null;M++){if(P[M]&&(P[M]===true||P[M].nodeType===1&&n(B,P[M]))){I.push(G[M])}}}else{for(var M=0;P[M]!=null;M++){if(P[M]&&P[M].nodeType===1){I.push(G[M])}}}}}else{b(P,I)}if(A){d(A,e,I,D);d.uniqueSort(I)}return I};d.uniqueSort=function(z){if(f){u=o;z.sort(f);if(u){for(var e=1;e<z.length;e++){if(z[e]===z[e-1]){z.splice(e--,1)}}}}return z};d.matches=function(e,z){return d(e,null,null,z)};d.find=function(F,e,G){var E,C;if(!F){return[]}for(var B=0,A=h.order.length;B<A;B++){var D=h.order[B],C;if((C=h.leftMatch[D].exec(F))){var z=C[1];C.splice(1,1);if(z.substr(z.length-1)!=="\\"){C[1]=(C[1]||"").replace(/\\/g,"");E=h.find[D](C,e,G);if(E!=null){F=F.replace(h.match[D],"");break}}}}if(!E){E=e.getElementsByTagName("*")}return{set:E,expr:F}};d.filter=function(I,H,L,B){var A=I,N=[],F=H,D,e,E=H&&H[0]&&v(H[0]);while(I&&H.length){for(var G in h.filter){if((D=h.match[G].exec(I))!=null){var z=h.filter[G],M,K;e=false;if(F==N){N=[]}if(h.preFilter[G]){D=h.preFilter[G](D,F,L,N,B,E);if(!D){e=M=true}else{if(D===true){continue}}}if(D){for(var C=0;(K=F[C])!=null;C++){if(K){M=z(K,D,C,F);var J=B^!!M;if(L&&M!=null){if(J){e=true}else{F[C]=false}}else{if(J){N.push(K);e=true}}}}}if(M!==undefined){if(!L){F=N}I=I.replace(h.match[G],"");if(!e){return[]}break}}}if(I==A){if(e==null){throw"Syntax error, unrecognized expression: "+I}else{break}}A=I}return F};var h=d.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(e){return e.getAttribute("href")}},relative:{"+":function(F,e,E){var C=typeof e==="string",G=C&&!/\W/.test(e),D=C&&!G;if(G&&!E){e=e.toUpperCase()}for(var B=0,A=F.length,z;B<A;B++){if((z=F[B])){while((z=z.previousSibling)&&z.nodeType!==1){}F[B]=D||z&&z.nodeName===e?z||false:z===e}}if(D){d.filter(e,F,true)}},">":function(E,z,F){var C=typeof z==="string";if(C&&!/\W/.test(z)){z=F?z:z.toUpperCase();for(var A=0,e=E.length;A<e;A++){var D=E[A];if(D){var B=D.parentNode;E[A]=B.nodeName===z?B:false}}}else{for(var A=0,e=E.length;A<e;A++){var D=E[A];if(D){E[A]=C?D.parentNode:D.parentNode===z}}if(C){d.filter(z,E,true)}}},"":function(B,z,D){var A=p++,e=y;if(!/\W/.test(z)){var C=z=D?z:z.toUpperCase();e=t}e("parentNode",z,A,B,C,D)},"~":function(B,z,D){var A=p++,e=y;if(typeof z==="string"&&!/\W/.test(z)){var C=z=D?z:z.toUpperCase();e=t}e("previousSibling",z,A,B,C,D)}},find:{ID:function(z,A,B){if(typeof A.getElementById!=="undefined"&&!B){var e=A.getElementById(z[1]);return e?[e]:[]}},NAME:function(A,D,E){if(typeof D.getElementsByName!=="undefined"){var z=[],C=D.getElementsByName(A[1]);for(var B=0,e=C.length;B<e;B++){if(C[B].getAttribute("name")===A[1]){z.push(C[B])}}return z.length===0?null:z}},TAG:function(e,z){return z.getElementsByTagName(e[1])}},preFilter:{CLASS:function(B,z,A,e,E,F){B=" "+B[1].replace(/\\/g,"")+" ";if(F){return B}for(var C=0,D;(D=z[C])!=null;C++){if(D){if(E^(D.className&&(" "+D.className+" ").indexOf(B)>=0)){if(!A){e.push(D)}}else{if(A){z[C]=false}}}}return false},ID:function(e){return e[1].replace(/\\/g,"")},TAG:function(z,e){for(var A=0;e[A]===false;A++){}return e[A]&&v(e[A])?z[1]:z[1].toUpperCase()},CHILD:function(e){if(e[1]=="nth"){var z=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(e[2]=="even"&&"2n"||e[2]=="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(z[1]+(z[2]||1))-0;e[3]=z[3]-0}e[0]=p++;return e},ATTR:function(C,z,A,e,D,E){var B=C[1].replace(/\\/g,"");if(!E&&h.attrMap[B]){C[1]=h.attrMap[B]}if(C[2]==="~="){C[4]=" "+C[4]+" "}return C},PSEUDO:function(C,z,A,e,D){if(C[1]==="not"){if((w.exec(C[3])||"").length>1||/^\w/.test(C[3])){C[3]=d(C[3],null,null,z)}else{var B=d.filter(C[3],z,A,true^D);if(!A){e.push.apply(e,B)}return false}}else{if(h.match.POS.test(C[0])||h.match.CHILD.test(C[0])){return true}}return C},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){e.parentNode.selectedIndex;return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(A,z,e){return !!d(e[3],A).length},header:function(e){return/h\d/i.test(e.nodeName)},text:function(e){return"text"===e.type},radio:function(e){return"radio"===e.type},checkbox:function(e){return"checkbox"===e.type},file:function(e){return"file"===e.type},password:function(e){return"password"===e.type},submit:function(e){return"submit"===e.type},image:function(e){return"image"===e.type},reset:function(e){return"reset"===e.type},button:function(e){return"button"===e.type||e.nodeName.toUpperCase()==="BUTTON"},input:function(e){return/input|select|textarea|button/i.test(e.nodeName)}},setFilters:{first:function(z,e){return e===0},last:function(A,z,e,B){return z===B.length-1},even:function(z,e){return e%2===0},odd:function(z,e){return e%2===1},lt:function(A,z,e){return z<e[3]-0},gt:function(A,z,e){return z>e[3]-0},nth:function(A,z,e){return e[3]-0==z},eq:function(A,z,e){return e[3]-0==z}},filter:{PSEUDO:function(E,A,B,F){var z=A[1],C=h.filters[z];if(C){return C(E,B,A,F)}else{if(z==="contains"){return(E.textContent||E.innerText||"").indexOf(A[3])>=0}else{if(z==="not"){var D=A[3];for(var B=0,e=D.length;B<e;B++){if(D[B]===E){return false}}return true}}}},CHILD:function(e,B){var E=B[1],z=e;switch(E){case"only":case"first":while((z=z.previousSibling)){if(z.nodeType===1){return false}}if(E=="first"){return true}z=e;case"last":while((z=z.nextSibling)){if(z.nodeType===1){return false}}return true;case"nth":var A=B[2],H=B[3];if(A==1&&H==0){return true}var D=B[0],G=e.parentNode;if(G&&(G.sizcache!==D||!e.nodeIndex)){var C=0;for(z=G.firstChild;z;z=z.nextSibling){if(z.nodeType===1){z.nodeIndex=++C}}G.sizcache=D}var F=e.nodeIndex-H;if(A==0){return F==0}else{return(F%A==0&&F/A>=0)}}},ID:function(z,e){return z.nodeType===1&&z.getAttribute("id")===e},TAG:function(z,e){return(e==="*"&&z.nodeType===1)||z.nodeName===e},CLASS:function(z,e){return(" "+(z.className||z.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(D,B){var A=B[1],e=h.attrHandle[A]?h.attrHandle[A](D):D[A]!=null?D[A]:D.getAttribute(A),E=e+"",C=B[2],z=B[4];return e==null?C==="!=":C==="="?E===z:C==="*="?E.indexOf(z)>=0:C==="~="?(" "+E+" ").indexOf(z)>=0:!z?E&&e!==false:C==="!="?E!=z:C==="^="?E.indexOf(z)===0:C==="$="?E.substr(E.length-z.length)===z:C==="|="?E===z||E.substr(0,z.length+1)===z+"-":false},POS:function(C,z,A,D){var e=z[2],B=h.setFilters[e];if(B){return B(C,A,z,D)}}}};var q=h.match.POS;for(var s in h.match){h.match[s]=new RegExp(h.match[s].source+/(?![^\[]*\])(?![^\(]*\))/.source);h.leftMatch[s]=new RegExp(/(^(?:.|\r|\n)*?)/.source+h.match[s].source)}var b=function(z,e){z=Array.prototype.slice.call(z,0);if(e){e.push.apply(e,z);return e}return z};try{Array.prototype.slice.call(document.documentElement.childNodes,0)}catch(r){b=function(C,B){var z=B||[];if(g.call(C)==="[object Array]"){Array.prototype.push.apply(z,C)}else{if(typeof C.length==="number"){for(var A=0,e=C.length;A<e;A++){z.push(C[A])}}else{for(var A=0;C[A];A++){z.push(C[A])}}}return z}}var f;if(document.documentElement.compareDocumentPosition){f=function(z,e){if(!z.compareDocumentPosition||!e.compareDocumentPosition){if(z==e){u=true}return 0}var A=z.compareDocumentPosition(e)&4?-1:z===e?0:1;if(A===0){u=true}return A}}else{if("sourceIndex" in document.documentElement){f=function(z,e){if(!z.sourceIndex||!e.sourceIndex){if(z==e){u=true}return 0}var A=z.sourceIndex-e.sourceIndex;if(A===0){u=true}return A}}else{if(document.createRange){f=function(B,z){if(!B.ownerDocument||!z.ownerDocument){if(B==z){u=true}return 0}var A=B.ownerDocument.createRange(),e=z.ownerDocument.createRange();A.setStart(B,0);A.setEnd(B,0);e.setStart(z,0);e.setEnd(z,0);var C=A.compareBoundaryPoints(Range.START_TO_END,e);if(C===0){u=true}return C}}}}(function(){var z=document.createElement("div"),A="script"+(new Date).getTime();z.innerHTML="<a name='"+A+"'/>";var e=document.documentElement;e.insertBefore(z,e.firstChild);if(!!document.getElementById(A)){h.find.ID=function(C,D,E){if(typeof D.getElementById!=="undefined"&&!E){var B=D.getElementById(C[1]);return B?B.id===C[1]||typeof B.getAttributeNode!=="undefined"&&B.getAttributeNode("id").nodeValue===C[1]?[B]:undefined:[]}};h.filter.ID=function(D,B){var C=typeof D.getAttributeNode!=="undefined"&&D.getAttributeNode("id");return D.nodeType===1&&C&&C.nodeValue===B}}e.removeChild(z);e=z=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){h.find.TAG=function(z,D){var C=D.getElementsByTagName(z[1]);if(z[1]==="*"){var B=[];for(var A=0;C[A];A++){if(C[A].nodeType===1){B.push(C[A])}}C=B}return C}}e.innerHTML="<a href='#'></a>";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){h.attrHandle.href=function(z){return z.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=d,A=document.createElement("div");A.innerHTML="<p class='TEST'></p>";if(A.querySelectorAll&&A.querySelectorAll(".TEST").length===0){return}d=function(E,D,B,C){D=D||document;if(!C&&D.nodeType===9&&!v(D)){try{return b(D.querySelectorAll(E),B)}catch(F){}}return e(E,D,B,C)};for(var z in e){d[z]=e[z]}A=null})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var e=document.createElement("div");e.innerHTML="<div class='test e'></div><div class='test'></div>";if(e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}h.order.splice(1,0,"CLASS");h.find.CLASS=function(z,A,B){if(typeof A.getElementsByClassName!=="undefined"&&!B){return A.getElementsByClassName(z[1])}};e=null})()}function t(z,E,D,I,F,H){var G=z=="previousSibling"&&!H;for(var B=0,A=I.length;B<A;B++){var e=I[B];if(e){if(G&&e.nodeType===1){e.sizcache=D;e.sizset=B}e=e[z];var C=false;while(e){if(e.sizcache===D){C=I[e.sizset];break}if(e.nodeType===1&&!H){e.sizcache=D;e.sizset=B}if(e.nodeName===E){C=e;break}e=e[z]}I[B]=C}}}function y(z,E,D,I,F,H){var G=z=="previousSibling"&&!H;for(var B=0,A=I.length;B<A;B++){var e=I[B];if(e){if(G&&e.nodeType===1){e.sizcache=D;e.sizset=B}e=e[z];var C=false;while(e){if(e.sizcache===D){C=I[e.sizset];break}if(e.nodeType===1){if(!H){e.sizcache=D;e.sizset=B}if(typeof E!=="string"){if(e===E){C=true;break}}else{if(d.filter(E,[e]).length>0){C=e;break}}}e=e[z]}I[B]=C}}}var n=document.compareDocumentPosition?function(z,e){return z.compareDocumentPosition(e)&16}:function(z,e){return z!==e&&(z.contains?z.contains(e):true)};var v=function(e){return e.nodeType===9&&e.documentElement.nodeName!=="HTML"||!!e.ownerDocument&&e.ownerDocument.documentElement.nodeName!=="HTML"};var l=function(e,F){var B=[],C="",D,A=F.nodeType?[F]:F;while((D=h.match.PSEUDO.exec(e))){C+=D[0];e=e.replace(h.match.PSEUDO,"")}e=h.relative[e]?e+"*":e;for(var E=0,z=A.length;E<z;E++){d(e,A[E],B)}return d.filter(C,B)};window.Sizzle=d})();(function(e){var f=Prototype.Selector.extendElements;function b(g,h){return f(e(g,h||document))}function d(h,g){return e.matches(g,[h]).length==1}Prototype.Selector.engine=e;Prototype.Selector.select=b;Prototype.Selector.match=d})(Sizzle);window.Sizzle=Prototype._original_property;delete Prototype._original_property;var Form={reset:function(b){b=$(b);b.reset();return b},serializeElements:function(n,f){if(typeof f!="object"){f={hash:!!f}}else{if(Object.isUndefined(f.hash)){f.hash=true}}var g,l,b=false,h=f.submit,d,e;if(f.hash){e={};d=function(o,p,q){if(p in o){if(!Object.isArray(o[p])){o[p]=[o[p]]}o[p].push(q)}else{o[p]=q}return o}}else{e="";d=function(o,p,q){return o+(o?"&":"")+encodeURIComponent(p)+"="+encodeURIComponent(q)}}return n.inject(e,function(o,p){if(!p.disabled&&p.name){g=p.name;l=$(p).getValue();if(l!=null&&p.type!="file"&&(p.type!="submit"||(!b&&h!==false&&(!h||g==h)&&(b=true)))){o=d(o,g,l)}}return o})}};Form.Methods={serialize:function(d,b){return Form.serializeElements(Form.getElements(d),b)},getElements:function(g){var h=$(g).getElementsByTagName("*"),f,b=[],e=Form.Element.Serializers;for(var d=0;f=h[d];d++){b.push(f)}return b.inject([],function(l,n){if(e[n.tagName.toLowerCase()]){l.push(Element.extend(n))}return l})},getInputs:function(l,e,f){l=$(l);var b=l.getElementsByTagName("input");if(!e&&!f){return $A(b).map(Element.extend)}for(var g=0,n=[],h=b.length;g<h;g++){var d=b[g];if((e&&d.type!=e)||(f&&d.name!=f)){continue}n.push(Element.extend(d))}return n},disable:function(b){b=$(b);Form.getElements(b).invoke("disable");return b},enable:function(b){b=$(b);Form.getElements(b).invoke("enable");return b},findFirstElement:function(d){var e=$(d).getElements().findAll(function(f){return"hidden"!=f.type&&!f.disabled});var b=e.findAll(function(f){return f.hasAttribute("tabIndex")&&f.tabIndex>=0}).sortBy(function(f){return f.tabIndex}).first();return b?b:e.find(function(f){return/^(?:input|select|textarea)$/i.test(f.tagName)})},focusFirstElement:function(d){d=$(d);var b=d.findFirstElement();if(b){b.activate()}return d},request:function(d,b){d=$(d),b=Object.clone(b||{});var f=b.parameters,e=d.readAttribute("action")||"";if(e.blank()){e=window.location.href}b.parameters=d.serialize(true);if(f){if(Object.isString(f)){f=f.toQueryParams()}Object.extend(b.parameters,f)}if(d.hasAttribute("method")&&!b.method){b.method=d.method}return new Ajax.Request(e,b)}};Form.Element={focus:function(b){$(b).focus();return b},select:function(b){$(b).select();return b}};Form.Element.Methods={serialize:function(b){b=$(b);if(!b.disabled&&b.name){var d=b.getValue();if(d!=undefined){var e={};e[b.name]=d;return Object.toQueryString(e)}}return""},getValue:function(b){b=$(b);var d=b.tagName.toLowerCase();return Form.Element.Serializers[d](b)},setValue:function(b,d){b=$(b);var e=b.tagName.toLowerCase();Form.Element.Serializers[e](b,d);return b},clear:function(b){$(b).value="";return b},present:function(b){return $(b).value!=""},activate:function(b){b=$(b);try{b.focus();if(b.select&&(b.tagName.toLowerCase()!="input"||!(/^(?:button|reset|submit)$/i.test(b.type)))){b.select()}}catch(d){}return b},disable:function(b){b=$(b);b.disabled=true;return b},enable:function(b){b=$(b);b.disabled=false;return b}};var Field=Form.Element;var $F=Form.Element.Methods.getValue;Form.Element.Serializers=(function(){function d(n,o){switch(n.type.toLowerCase()){case"checkbox":case"radio":return h(n,o);default:return g(n,o)}}function h(n,o){if(Object.isUndefined(o)){return n.checked?n.value:null}else{n.checked=!!o}}function g(n,o){if(Object.isUndefined(o)){return n.value}else{n.value=o}}function b(p,s){if(Object.isUndefined(s)){return(p.type==="select-one"?e:f)(p)}var o,q,t=!Object.isArray(s);for(var n=0,r=p.length;n<r;n++){o=p.options[n];q=this.optionValue(o);if(t){if(q==s){o.selected=true;return}}else{o.selected=s.include(q)}}}function e(o){var n=o.selectedIndex;return n>=0?l(o.options[n]):null}function f(q){var n,r=q.length;if(!r){return null}for(var p=0,n=[];p<r;p++){var o=q.options[p];if(o.selected){n.push(l(o))}}return n}function l(n){return Element.hasAttribute(n,"value")?n.value:n.text}return{input:d,inputSelector:h,textarea:g,select:b,selectOne:e,selectMany:f,optionValue:l,button:g}})();Abstract.TimedObserver=Class.create(PeriodicalExecuter,{initialize:function($super,b,d,e){$super(e,d);this.element=$(b);this.lastValue=this.getValue()},execute:function(){var b=this.getValue();if(Object.isString(this.lastValue)&&Object.isString(b)?this.lastValue!=b:String(this.lastValue)!=String(b)){this.callback(this.element,b);this.lastValue=b}}});Form.Element.Observer=Class.create(Abstract.TimedObserver,{getValue:function(){return Form.Element.getValue(this.element)}});Form.Observer=Class.create(Abstract.TimedObserver,{getValue:function(){return Form.serialize(this.element)}});Abstract.EventObserver=Class.create({initialize:function(b,d){this.element=$(b);this.callback=d;this.lastValue=this.getValue();if(this.element.tagName.toLowerCase()=="form"){this.registerFormCallbacks()}else{this.registerCallback(this.element)}},onElementEvent:function(){var b=this.getValue();if(this.lastValue!=b){this.callback(this.element,b);this.lastValue=b}},registerFormCallbacks:function(){Form.getElements(this.element).each(this.registerCallback,this)},registerCallback:function(b){if(b.type){switch(b.type.toLowerCase()){case"checkbox":case"radio":Event.observe(b,"click",this.onElementEvent.bind(this));break;default:Event.observe(b,"change",this.onElementEvent.bind(this));break}}}});Form.Element.EventObserver=Class.create(Abstract.EventObserver,{getValue:function(){return Form.Element.getValue(this.element)}});Form.EventObserver=Class.create(Abstract.EventObserver,{getValue:function(){return Form.serialize(this.element)}});(function(){var J={KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,KEY_HOME:36,KEY_END:35,KEY_PAGEUP:33,KEY_PAGEDOWN:34,KEY_INSERT:45,cache:{}};var h=document.documentElement;var K="onmouseenter" in h&&"onmouseleave" in h;var b=function(L){return false};if(window.attachEvent){if(window.addEventListener){b=function(L){return !(L instanceof window.Event)}}else{b=function(L){return true}}}var y;function H(M,L){return M.which?(M.which===L+1):(M.button===L)}var u={0:1,1:4,2:2};function F(M,L){return M.button===u[L]}function I(M,L){switch(L){case 0:return M.which==1&&!M.metaKey;case 1:return M.which==2||(M.which==1&&M.metaKey);case 2:return M.which==3;default:return false}}if(window.attachEvent){if(!window.addEventListener){y=F}else{y=function(M,L){return b(M)?F(M,L):H(M,L)}}}else{if(Prototype.Browser.WebKit){y=I}else{y=H}}function C(L){return y(L,0)}function A(L){return y(L,1)}function t(L){return y(L,2)}function f(N){N=J.extend(N);var M=N.target,L=N.type,O=N.currentTarget;if(O&&O.tagName){if(L==="load"||L==="error"||(L==="click"&&O.tagName.toLowerCase()==="input"&&O.type==="radio")){M=O}}if(M.nodeType==Node.TEXT_NODE){M=M.parentNode}return Element.extend(M)}function v(M,N){var L=J.element(M);if(!N){return L}while(L){if(Object.isElement(L)&&Prototype.Selector.match(L,N)){return Element.extend(L)}L=L.parentNode}}function z(L){return{x:e(L),y:d(L)}}function e(N){var M=document.documentElement,L=document.body||{scrollLeft:0};return N.pageX||(N.clientX+(M.scrollLeft||L.scrollLeft)-(M.clientLeft||0))}function d(N){var M=document.documentElement,L=document.body||{scrollTop:0};return N.pageY||(N.clientY+(M.scrollTop||L.scrollTop)-(M.clientTop||0))}function w(L){J.extend(L);L.preventDefault();L.stopPropagation();L.stopped=true}J.Methods={isLeftClick:C,isMiddleClick:A,isRightClick:t,element:f,findElement:v,pointer:z,pointerX:e,pointerY:d,stop:w};var E=Object.keys(J.Methods).inject({},function(L,M){L[M]=J.Methods[M].methodize();return L});if(window.attachEvent){function o(M){var L;switch(M.type){case"mouseover":case"mouseenter":L=M.fromElement;break;case"mouseout":case"mouseleave":L=M.toElement;break;default:return null}return Element.extend(L)}var B={stopPropagation:function(){this.cancelBubble=true},preventDefault:function(){this.returnValue=false},inspect:function(){return"[object Event]"}};J.extend=function(M,L){if(!M){return false}if(!b(M)){return M}if(M._extendedByPrototype){return M}M._extendedByPrototype=Prototype.emptyFunction;var N=J.pointer(M);Object.extend(M,{target:M.srcElement||L,relatedTarget:o(M),pageX:N.x,pageY:N.y});Object.extend(M,E);Object.extend(M,B);return M}}else{J.extend=Prototype.K}if(window.addEventListener){J.prototype=window.Event.prototype||document.createEvent("HTMLEvents").__proto__;Object.extend(J.prototype,E)}function s(P,O,Q){var N=Element.retrieve(P,"prototype_event_registry");if(Object.isUndefined(N)){g.push(P);N=Element.retrieve(P,"prototype_event_registry",$H())}var L=N.get(O);if(Object.isUndefined(L)){L=[];N.set(O,L)}if(L.pluck("handler").include(Q)){return false}var M;if(O.include(":")){M=function(R){if(Object.isUndefined(R.eventName)){return false}if(R.eventName!==O){return false}J.extend(R,P);Q.call(P,R)}}else{if(!K&&(O==="mouseenter"||O==="mouseleave")){if(O==="mouseenter"||O==="mouseleave"){M=function(S){J.extend(S,P);var R=S.relatedTarget;while(R&&R!==P){try{R=R.parentNode}catch(T){R=P}}if(R===P){return}Q.call(P,S)}}}else{M=function(R){J.extend(R,P);Q.call(P,R)}}}M.handler=Q;L.push(M);return M}function n(){for(var L=0,M=g.length;L<M;L++){J.stopObserving(g[L]);g[L]=null}}var g=[];if(Prototype.Browser.IE){window.attachEvent("onunload",n)}if(Prototype.Browser.WebKit){window.addEventListener("unload",Prototype.emptyFunction,false)}var r=Prototype.K,l={mouseenter:"mouseover",mouseleave:"mouseout"};if(!K){r=function(L){return(l[L]||L)}}function D(O,N,P){O=$(O);var M=s(O,N,P);if(!M){return O}if(N.include(":")){if(O.addEventListener){O.addEventListener("dataavailable",M,false)}else{O.attachEvent("ondataavailable",M);O.attachEvent("onlosecapture",M)}}else{var L=r(N);if(O.addEventListener){O.addEventListener(L,M,false)}else{O.attachEvent("on"+L,M)}}return O}function q(R,O,S){R=$(R);var N=Element.retrieve(R,"prototype_event_registry");if(!N){return R}if(!O){N.each(function(U){var T=U.key;q(R,T)});return R}var P=N.get(O);if(!P){return R}if(!S){P.each(function(T){q(R,O,T.handler)});return R}var Q=P.length,M;while(Q--){if(P[Q].handler===S){M=P[Q];break}}if(!M){return R}if(O.include(":")){if(R.removeEventListener){R.removeEventListener("dataavailable",M,false)}else{R.detachEvent("ondataavailable",M);R.detachEvent("onlosecapture",M)}}else{var L=r(O);if(R.removeEventListener){R.removeEventListener(L,M,false)}else{R.detachEvent("on"+L,M)}}N.set(O,P.without(M));return R}function G(O,N,M,L){O=$(O);if(Object.isUndefined(L)){L=true}if(O==document&&document.createEvent&&!O.dispatchEvent){O=document.documentElement}var P;if(document.createEvent){P=document.createEvent("HTMLEvents");P.initEvent("dataavailable",L,true)}else{P=document.createEventObject();P.eventType=L?"ondataavailable":"onlosecapture"}P.eventName=N;P.memo=M||{};if(document.createEvent){O.dispatchEvent(P)}else{O.fireEvent(P.eventType,P)}return J.extend(P)}J.Handler=Class.create({initialize:function(N,M,L,O){this.element=$(N);this.eventName=M;this.selector=L;this.callback=O;this.handler=this.handleEvent.bind(this)},start:function(){J.observe(this.element,this.eventName,this.handler);return this},stop:function(){J.stopObserving(this.element,this.eventName,this.handler);return this},handleEvent:function(M){var L=J.findElement(M,this.selector);if(L){this.callback.call(this.element,M,L)}}});function p(N,M,L,O){N=$(N);if(Object.isFunction(L)&&Object.isUndefined(O)){O=L,L=null}return new J.Handler(N,M,L,O).start()}Object.extend(J,J.Methods);Object.extend(J,{fire:G,observe:D,stopObserving:q,on:p});Element.addMethods({fire:G,observe:D,stopObserving:q,on:p});Object.extend(document,{fire:G.methodize(),observe:D.methodize(),stopObserving:q.methodize(),on:p.methodize(),loaded:false});if(window.Event){Object.extend(window.Event,J)}else{window.Event=J}})();(function(){var e;function b(){if(document.loaded){return}if(e){window.clearTimeout(e)}document.loaded=true;document.fire("dom:loaded")}function d(){if(document.readyState==="complete"){document.stopObserving("readystatechange",d);b()}}if(document.addEventListener){document.addEventListener("DOMContentLoaded",b,false)}else{document.observe("readystatechange",d);if(window==top){var e=window.setInterval(function(){try{document.documentElement.doScroll("left")}catch(f){return}window.clearInterval(e);b()},5)}}Event.observe(window,"load",b)})();Element.addMethods();Hash.toQueryString=Object.toQueryString;var Toggle={display:Element.toggle};Element.Methods.childOf=Element.Methods.descendantOf;var Insertion={Before:function(b,d){return Element.insert(b,{before:d})},Top:function(b,d){return Element.insert(b,{top:d})},Bottom:function(b,d){return Element.insert(b,{bottom:d})},After:function(b,d){return Element.insert(b,{after:d})}};var $continue=new Error('"throw $continue" is deprecated, use "return" instead');var Position={includeScrollOffsets:false,prepare:function(){this.deltaX=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;this.deltaY=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0},within:function(d,b,e){if(this.includeScrollOffsets){return this.withinIncludingScrolloffsets(d,b,e)}this.xcomp=b;this.ycomp=e;this.offset=Element.cumulativeOffset(d);return(e>=this.offset[1]&&e<this.offset[1]+d.offsetHeight&&b>=this.offset[0]&&b<this.offset[0]+d.offsetWidth)},withinIncludingScrolloffsets:function(d,b,f){var e=Element.cumulativeScrollOffset(d);this.xcomp=b+e[0]-this.deltaX;this.ycomp=f+e[1]-this.deltaY;this.offset=Element.cumulativeOffset(d);return(this.ycomp>=this.offset[1]&&this.ycomp<this.offset[1]+d.offsetHeight&&this.xcomp>=this.offset[0]&&this.xcomp<this.offset[0]+d.offsetWidth)},overlap:function(d,b){if(!d){return 0}if(d=="vertical"){return((this.offset[1]+b.offsetHeight)-this.ycomp)/b.offsetHeight}if(d=="horizontal"){return((this.offset[0]+b.offsetWidth)-this.xcomp)/b.offsetWidth}},cumulativeOffset:Element.Methods.cumulativeOffset,positionedOffset:Element.Methods.positionedOffset,absolutize:function(b){Position.prepare();return Element.absolutize(b)},relativize:function(b){Position.prepare();return Element.relativize(b)},realOffset:Element.Methods.cumulativeScrollOffset,offsetParent:Element.Methods.getOffsetParent,page:Element.Methods.viewportOffset,clone:function(d,e,b){b=b||{};return Element.clonePosition(e,d,b)}};if(!document.getElementsByClassName){document.getElementsByClassName=function(d){function b(e){return e.blank()?null:"[contains(concat(' ', @class, ' '), ' "+e+" ')]"}d.getElementsByClassName=Prototype.BrowserFeatures.XPath?function(e,g){g=g.toString().strip();var f=/\s/.test(g)?$w(g).map(b).join(""):b(g);return f?document._getElementsByXPath(".//*"+f,e):[]}:function(g,h){h=h.toString().strip();var l=[],n=(/\s/.test(h)?$w(h):null);if(!n&&!h){return l}var e=$(g).getElementsByTagName("*");h=" "+h+" ";for(var f=0,p,o;p=e[f];f++){if(p.className&&(o=" "+p.className+" ")&&(o.include(h)||(n&&n.all(function(q){return !q.toString().blank()&&o.include(" "+q+" ")})))){l.push(Element.extend(p))}}return l};return function(f,e){return $(e||document.body).getElementsByClassName(f)}}(Element.Methods)}Element.ClassNames=Class.create();Element.ClassNames.prototype={initialize:function(b){this.element=$(b)},_each:function(b){this.element.className.split(/\s+/).select(function(d){return d.length>0})._each(b)},set:function(b){this.element.className=b},add:function(b){if(this.include(b)){return}this.set($A(this).concat(b).join(" "))},remove:function(b){if(!this.include(b)){return}this.set($A(this).without(b).join(" "))},toString:function(){return $A(this).join(" ")}};Object.extend(Element.ClassNames.prototype,Enumerable);(function(){window.Selector=Class.create({initialize:function(b){this.expression=b.strip()},findElements:function(b){return Prototype.Selector.select(this.expression,b)},match:function(b){return Prototype.Selector.match(b,this.expression)},toString:function(){return this.expression},inspect:function(){return"#<Selector: "+this.expression+">"}});Object.extend(Selector,{matchElements:function(h,l){var b=Prototype.Selector.match,f=[];for(var e=0,g=h.length;e<g;e++){var d=h[e];if(b(d,l)){f.push(Element.extend(d))}}return f},findElement:function(h,l,d){d=d||0;var b=0,f;for(var e=0,g=h.length;e<g;e++){f=h[e];if(Prototype.Selector.match(f,l)&&d===b++){return Element.extend(f)}}},findChildElements:function(d,e){var b=e.toArray().join(", ");return Prototype.Selector.select(b,d||document)}})})();var Window=Class.create();Window.keepMultiModalWindow=false;Window.hasEffectLib=(typeof Effect!="undefined");Window.resizeEffectDuration=0.4;Window.prototype={initialize:function(){var e;var d=0;if(arguments.length>0){if(typeof arguments[0]=="string"){e=arguments[0];d=1}else{e=arguments[0]?arguments[0].id:null}}if(!e){e="window_"+new Date().getTime()}if($(e)){alert("Window "+e+" is already registered in the DOM! Make sure you use setDestroyOnClose() or destroyOnClose: true in the constructor")}this.options=Object.extend({className:"dialog",windowClassName:null,blurClassName:null,minWidth:100,minHeight:20,resizable:true,closable:true,minimizable:true,maximizable:true,draggable:true,userData:null,showEffect:(Window.hasEffectLib?Effect.Appear:Element.show),hideEffect:(Window.hasEffectLib?Effect.Fade:Element.hide),showEffectOptions:{},hideEffectOptions:{},effectOptions:null,parent:document.body,title:" ",url:null,onload:Prototype.emptyFunction,width:200,height:300,opacity:1,recenterAuto:true,wiredDrag:false,closeOnEsc:true,closeCallback:null,destroyOnClose:false,gridX:1,gridY:1},arguments[d]||{});if(this.options.blurClassName){this.options.focusClassName=this.options.className}if(typeof this.options.top=="undefined"&&typeof this.options.bottom=="undefined"){this.options.top=this._round(Math.random()*500,this.options.gridY)}if(typeof this.options.left=="undefined"&&typeof this.options.right=="undefined"){this.options.left=this._round(Math.random()*500,this.options.gridX)}if(this.options.effectOptions){Object.extend(this.options.hideEffectOptions,this.options.effectOptions);Object.extend(this.options.showEffectOptions,this.options.effectOptions);if(this.options.showEffect==Element.Appear){this.options.showEffectOptions.to=this.options.opacity}}if(Window.hasEffectLib){if(this.options.showEffect==Effect.Appear){this.options.showEffectOptions.to=this.options.opacity}if(this.options.hideEffect==Effect.Fade){this.options.hideEffectOptions.from=this.options.opacity}}if(this.options.hideEffect==Element.hide){this.options.hideEffect=function(){Element.hide(this.element);if(this.options.destroyOnClose){this.destroy()}}.bind(this)}if(this.options.parent!=document.body){this.options.parent=$(this.options.parent)}this.element=this._createWindow(e);this.element.win=this;this.eventMouseDown=this._initDrag.bindAsEventListener(this);this.eventMouseUp=this._endDrag.bindAsEventListener(this);this.eventMouseMove=this._updateDrag.bindAsEventListener(this);this.eventOnLoad=this._getWindowBorderSize.bindAsEventListener(this);this.eventMouseDownContent=this.toFront.bindAsEventListener(this);this.eventResize=this._recenter.bindAsEventListener(this);this.eventKeyUp=this._keyUp.bindAsEventListener(this);this.topbar=$(this.element.id+"_top");this.bottombar=$(this.element.id+"_bottom");this.content=$(this.element.id+"_content");Event.observe(this.topbar,"mousedown",this.eventMouseDown);Event.observe(this.bottombar,"mousedown",this.eventMouseDown);Event.observe(this.content,"mousedown",this.eventMouseDownContent);Event.observe(window,"load",this.eventOnLoad);Event.observe(window,"resize",this.eventResize);Event.observe(window,"scroll",this.eventResize);Event.observe(document,"keyup",this.eventKeyUp);Event.observe(this.options.parent,"scroll",this.eventResize);if(this.options.draggable){var b=this;[this.topbar,this.topbar.up().previous(),this.topbar.up().next()].each(function(f){f.observe("mousedown",b.eventMouseDown);f.addClassName("top_draggable")});[this.bottombar.up(),this.bottombar.up().previous(),this.bottombar.up().next()].each(function(f){f.observe("mousedown",b.eventMouseDown);f.addClassName("bottom_draggable")})}if(this.options.resizable){this.sizer=$(this.element.id+"_sizer");Event.observe(this.sizer,"mousedown",this.eventMouseDown)}this.useLeft=null;this.useTop=null;if(typeof this.options.left!="undefined"){this.element.setStyle({left:parseFloat(this.options.left)+"px"});this.useLeft=true}else{this.element.setStyle({right:parseFloat(this.options.right)+"px"});this.useLeft=false}if(typeof this.options.top!="undefined"){this.element.setStyle({top:parseFloat(this.options.top)+"px"});this.useTop=true}else{this.element.setStyle({bottom:parseFloat(this.options.bottom)+"px"});this.useTop=false}this.storedLocation=null;this.setOpacity(this.options.opacity);if(this.options.zIndex){this.setZIndex(this.options.zIndex)}else{this.setZIndex(this.getMaxZIndex())}if(this.options.destroyOnClose){this.setDestroyOnClose(true)}this._getWindowBorderSize();this.width=this.options.width;this.height=this.options.height;this.visible=false;this.constraint=false;this.constraintPad={top:0,left:0,bottom:0,right:0};if(this.width&&this.height){this.setSize(this.options.width,this.options.height)}this.setTitle(this.options.title);Windows.register(this)},getMaxZIndex:function(){var b=0,d;var g=document.body.childNodes;for(d=0;d<g.length;d++){var e=g[d];var f=e.nodeType==1?parseInt(e.style.zIndex,10)||0:0;if(f<10000){b=Math.max(b,f)}}return b+10},destroy:function(){this._notify("onDestroy");Event.stopObserving(this.topbar,"mousedown",this.eventMouseDown);Event.stopObserving(this.bottombar,"mousedown",this.eventMouseDown);Event.stopObserving(this.content,"mousedown",this.eventMouseDownContent);Event.stopObserving(window,"load",this.eventOnLoad);Event.stopObserving(window,"resize",this.eventResize);Event.stopObserving(window,"scroll",this.eventResize);Event.stopObserving(this.content,"load",this.options.onload);Event.stopObserving(document,"keyup",this.eventKeyUp);if(this._oldParent){var e=this.getContent();var b=null;for(var d=0;d<e.childNodes.length;d++){b=e.childNodes[d];if(b.nodeType==1){break}b=null}if(b){this._oldParent.appendChild(b)}this._oldParent=null}if(this.sizer){Event.stopObserving(this.sizer,"mousedown",this.eventMouseDown)}if(this.options.url){this.content.src=null}if(this.iefix){Element.remove(this.iefix)}Element.remove(this.element);Windows.unregister(this)},setCloseCallback:function(b){this.options.closeCallback=b},getContent:function(){return this.content},setContent:function(n,l,e){var b=$(n);if(null==b){throw"Unable to find element '"+n+"' in DOM"}this._oldParent=b.parentNode;var h=null;var g=null;if(l){h=Element.getDimensions(b)}if(e){g=Position.cumulativeOffset(b)}var f=this.getContent();this.setHTMLContent("");f=this.getContent();f.appendChild(b);b.show();if(l){this.setSize(h.width,h.height)}if(e){this.setLocation(g[1]-this.heightN,g[0]-this.widthW)}},setHTMLContent:function(b){if(this.options.url){this.content.src=null;this.options.url=null;var d='<div id="'+this.getId()+'_content" class="'+this.options.className+'_content"> </div>';$(this.getId()+"_table_content").innerHTML=d;this.content=$(this.element.id+"_content")}this.getContent().innerHTML=b},setAjaxContent:function(d,b,f,e){this.showFunction=f?"showCenter":"show";this.showModal=e||false;b=b||{};this.setHTMLContent("");this.onComplete=b.onComplete;if(!this._onCompleteHandler){this._onCompleteHandler=this._setAjaxContent.bind(this)}b.onComplete=this._onCompleteHandler;new Ajax.Request(d,b);b.onComplete=this.onComplete},_setAjaxContent:function(b){Element.update(this.getContent(),b.responseText);if(this.onComplete){this.onComplete(b)}this.onComplete=null;this[this.showFunction](this.showModal)},setURL:function(b){if(this.options.url){this.content.src=null}this.options.url=b;var d="<iframe frameborder='0' name='"+this.getId()+"_content' id='"+this.getId()+"_content' src='"+b+"' width='"+this.width+"' height='"+this.height+"'> </iframe>";$(this.getId()+"_table_content").innerHTML=d;this.content=$(this.element.id+"_content")},getURL:function(){return this.options.url?this.options.url:null},refresh:function(){if(this.options.url){$(this.element.getAttribute("id")+"_content").src=this.options.url}},setCookie:function(d,e,t,g,b){d=d||this.element.id;this.cookie=[d,e,t,g,b];var r=WindowUtilities.getCookie(d);if(r){var s=r.split(",");var p=s[0].split(":");var o=s[1].split(":");var q=parseFloat(s[2]),l=parseFloat(s[3]);var n=s[4];var f=s[5];this.setSize(q,l);if(n=="true"){this.doMinimize=true}else{if(f=="true"){this.doMaximize=true}}this.useLeft=p[0]=="l";this.useTop=o[0]=="t";this.element.setStyle(this.useLeft?{left:p[1]}:{right:p[1]});this.element.setStyle(this.useTop?{top:o[1]}:{bottom:o[1]})}},getId:function(){return this.element.id},setDestroyOnClose:function(){this.options.destroyOnClose=true},setConstraint:function(b,d){this.constraint=b;this.constraintPad=Object.extend(this.constraintPad,d||{});if(this.useTop&&this.useLeft){this.setLocation(parseFloat(this.element.style.top),parseFloat(this.element.style.left))}},_initDrag:function(d){if(Event.element(d)==this.sizer&&this.isMinimized()){return}if(Event.element(d)!=this.sizer&&this.isMaximized()){return}if(Prototype.Browser.IE&&this.heightN==0){this._getWindowBorderSize()}this.pointer=[this._round(Event.pointerX(d),this.options.gridX),this._round(Event.pointerY(d),this.options.gridY)];if(this.options.wiredDrag){this.currentDrag=this._createWiredElement()}else{this.currentDrag=this.element}if(Event.element(d)==this.sizer){this.doResize=true;this.widthOrg=this.width;this.heightOrg=this.height;this.bottomOrg=parseFloat(this.element.getStyle("bottom"));this.rightOrg=parseFloat(this.element.getStyle("right"));this._notify("onStartResize")}else{this.doResize=false;var b=$(this.getId()+"_close");if(b&&Position.within(b,this.pointer[0],this.pointer[1])){this.currentDrag=null;return}this.toFront();if(!this.options.draggable){return}this._notify("onStartMove")}Event.observe(document,"mouseup",this.eventMouseUp,false);Event.observe(document,"mousemove",this.eventMouseMove,false);WindowUtilities.disableScreen("__invisible__","__invisible__",this.overlayOpacity);document.body.ondrag=function(){return false};document.body.onselectstart=function(){return false};this.currentDrag.show();Event.stop(d)},_round:function(d,b){return b==1?d:d=Math.floor(d/b)*b},_updateDrag:function(d){var b=[this._round(Event.pointerX(d),this.options.gridX),this._round(Event.pointerY(d),this.options.gridY)];var q=b[0]-this.pointer[0];var p=b[1]-this.pointer[1];if(this.doResize){var o=this.widthOrg+q;var f=this.heightOrg+p;q=this.width-this.widthOrg;p=this.height-this.heightOrg;if(this.useLeft){o=this._updateWidthConstraint(o)}else{this.currentDrag.setStyle({right:(this.rightOrg-q)+"px"})}if(this.useTop){f=this._updateHeightConstraint(f)}else{this.currentDrag.setStyle({bottom:(this.bottomOrg-p)+"px"})}this.setSize(o,f);this._notify("onResize")}else{this.pointer=b;if(this.useLeft){var e=parseFloat(this.currentDrag.getStyle("left"))+q;var n=this._updateLeftConstraint(e);this.pointer[0]+=n-e;this.currentDrag.setStyle({left:n+"px"})}else{this.currentDrag.setStyle({right:parseFloat(this.currentDrag.getStyle("right"))-q+"px"})}if(this.useTop){var l=parseFloat(this.currentDrag.getStyle("top"))+p;var g=this._updateTopConstraint(l);this.pointer[1]+=g-l;this.currentDrag.setStyle({top:g+"px"})}else{this.currentDrag.setStyle({bottom:parseFloat(this.currentDrag.getStyle("bottom"))-p+"px"})}this._notify("onMove")}if(this.iefix){this._fixIEOverlapping()}this._removeStoreLocation();Event.stop(d)},_endDrag:function(b){WindowUtilities.enableScreen("__invisible__");if(this.doResize){this._notify("onEndResize")}else{this._notify("onEndMove")}Event.stopObserving(document,"mouseup",this.eventMouseUp,false);Event.stopObserving(document,"mousemove",this.eventMouseMove,false);Event.stop(b);this._hideWiredElement();this._saveCookie();document.body.ondrag=null;document.body.onselectstart=null},_updateLeftConstraint:function(d){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowWidth:this.options.parent.getDimensions().width;if(d<this.constraintPad.left){d=this.constraintPad.left}if(d+this.width+this.widthE+this.widthW>b-this.constraintPad.right){d=b-this.constraintPad.right-this.width-this.widthE-this.widthW}}return d},_updateTopConstraint:function(e){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowHeight:this.options.parent.getDimensions().height;var d=this.height+this.heightN+this.heightS;if(e<this.constraintPad.top){e=this.constraintPad.top}if(e+d>b-this.constraintPad.bottom){e=b-this.constraintPad.bottom-d}}return e},_updateWidthConstraint:function(b){if(this.constraint&&this.useLeft&&this.useTop){var d=this.options.parent==document.body?WindowUtilities.getPageSize().windowWidth:this.options.parent.getDimensions().width;var e=parseFloat(this.element.getStyle("left"));if(e+b+this.widthE+this.widthW>d-this.constraintPad.right){b=d-this.constraintPad.right-e-this.widthE-this.widthW}}return b},_updateHeightConstraint:function(d){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowHeight:this.options.parent.getDimensions().height;var e=parseFloat(this.element.getStyle("top"));if(e+d+this.heightN+this.heightS>b-this.constraintPad.bottom){d=b-this.constraintPad.bottom-e-this.heightN-this.heightS}}return d},_createWindow:function(b){var h=this.options.className;var f=document.createElement("div");f.setAttribute("id",b);f.className="dialog";if(this.options.windowClassName){f.className+=" "+this.options.windowClassName}var g;if(this.options.url){g='<iframe frameborder="0" name="'+b+'_content" id="'+b+'_content" src="'+this.options.url+'"> </iframe>'}else{g='<div id="'+b+'_content" class="'+h+'_content"> </div>'}var l=this.options.closable?"<div class='"+h+"_close' id='"+b+"_close' onclick='Windows.close(\""+b+"\", event)'> </div>":"";var n=this.options.minimizable?"<div class='"+h+"_minimize' id='"+b+"_minimize' onclick='Windows.minimize(\""+b+"\", event)'> </div>":"";var o=this.options.maximizable?"<div class='"+h+"_maximize' id='"+b+"_maximize' onclick='Windows.maximize(\""+b+"\", event)'> </div>":"";var e=this.options.resizable?"class='"+h+"_sizer' id='"+b+"_sizer'":"class='"+h+"_se'";var d="../themes/default/blank.gif";f.innerHTML=l+n+o+" <a href='#' id='"+b+"_focus_anchor'><!-- --></a> <table id='"+b+"_row1' class=\"top table_window\"> <tr> <td class='"+h+"_nw'></td> <td class='"+h+"_n'><div id='"+b+"_top' class='"+h+"_title title_window'>"+this.options.title+"</div></td> <td class='"+h+"_ne'></td> </tr> </table> <table id='"+b+"_row2' class=\"mid table_window\"> <tr> <td class='"+h+"_w'></td> <td id='"+b+"_table_content' class='"+h+"_content' valign='top'>"+g+"</td> <td class='"+h+"_e'></td> </tr> </table> <table id='"+b+"_row3' class=\"bot table_window\"> <tr> <td class='"+h+"_sw'></td> <td class='"+h+"_s'><div id='"+b+"_bottom' class='status_bar'><span style='float:left; width:1px; height:1px'></span></div></td> <td "+e+"></td> </tr> </table> ";Element.hide(f);this.options.parent.insertBefore(f,this.options.parent.firstChild);Event.observe($(b+"_content"),"load",this.options.onload);return f},changeClassName:function(b){var d=this.options.className;var e=this.getId();$A(["_close","_minimize","_maximize","_sizer","_content"]).each(function(f){this._toggleClassName($(e+f),d+f,b+f)}.bind(this));this._toggleClassName($(e+"_top"),d+"_title",b+"_title");$$("#"+e+" td").each(function(f){f.className=f.className.sub(d,b)});this.options.className=b},_toggleClassName:function(e,d,b){if(e){e.removeClassName(d);e.addClassName(b)}},setLocation:function(f,d){f=this._updateTopConstraint(f);d=this._updateLeftConstraint(d);var b=this.currentDrag||this.element;b.setStyle({top:f+"px"});b.setStyle({left:d+"px"});this.useLeft=true;this.useTop=true},getLocation:function(){var b={};if(this.useTop){b=Object.extend(b,{top:this.element.getStyle("top")})}else{b=Object.extend(b,{bottom:this.element.getStyle("bottom")})}if(this.useLeft){b=Object.extend(b,{left:this.element.getStyle("left")})}else{b=Object.extend(b,{right:this.element.getStyle("right")})}return b},getSize:function(){return{width:this.width,height:this.height}},setSize:function(f,d,b){f=parseFloat(f);d=parseFloat(d);if(!this.minimized&&f<this.options.minWidth){f=this.options.minWidth}if(!this.minimized&&d<this.options.minHeight){d=this.options.minHeight}if(this.options.maxHeight&&d>this.options.maxHeight){d=this.options.maxHeight}if(this.options.maxWidth&&f>this.options.maxWidth){f=this.options.maxWidth}if(this.useTop&&this.useLeft&&Window.hasEffectLib&&Effect.ResizeWindow&&b){new Effect.ResizeWindow(this,null,null,f,d,{duration:Window.resizeEffectDuration})}else{this.width=f;this.height=d;var h=this.currentDrag?this.currentDrag:this.element;h.setStyle({width:f+this.widthW+this.widthE+"px"});h.setStyle({height:d+this.heightN+this.heightS+"px"});if(!this.currentDrag||this.currentDrag==this.element){var g=$(this.element.id+"_content");g.setStyle({height:d+"px"});g.setStyle({width:f+"px"})}}},updateHeight:function(){this.setSize(this.width,this.content.scrollHeight,true)},updateWidth:function(){this.setSize(this.content.scrollWidth,this.height,true)},toFront:function(){if(this.element.style.zIndex<Windows.maxZIndex){this.setZIndex(Windows.maxZIndex+1)}if(this.iefix){this._fixIEOverlapping()}},getBounds:function(d){if(!this.width||!this.height||!this.visible){this.computeBounds()}var b=this.width;var e=this.height;if(!d){b+=this.widthW+this.widthE;e+=this.heightN+this.heightS}var f=Object.extend(this.getLocation(),{width:b+"px",height:e+"px"});return f},computeBounds:function(){if(!this.width||!this.height){var b=WindowUtilities._computeSize(this.content.innerHTML,this.content.id,this.width,this.height,0,this.options.className);if(this.height){this.width=b+5}else{this.height=b+5}}this.setSize(this.width,this.height);if(this.centered){this._center(this.centerTop,this.centerLeft)}},show:function(d){this.visible=true;if(d){if(typeof this.overlayOpacity=="undefined"){var b=this;setTimeout(function(){b.show(d)},10);return}Windows.addModalWindow(this);this.modal=true;this.setZIndex(Windows.maxZIndex+1);Windows.unsetOverflow(this)}else{if(!this.element.style.zIndex){this.setZIndex(Windows.maxZIndex+1)}}if(this.oldStyle){this.getContent().setStyle({overflow:this.oldStyle})}this.computeBounds();this._notify("onBeforeShow");if(this.options.showEffect!=Element.show&&this.options.showEffectOptions){this.options.showEffect(this.element,this.options.showEffectOptions)}else{this.options.showEffect(this.element)}this._checkIEOverlapping();WindowUtilities.focusedWindow=this;this._notify("onShow");$(this.element.id+"_focus_anchor").focus()},showCenter:function(b,e,d){this.centered=true;this.centerTop=e;this.centerLeft=d;this.show(b)},isVisible:function(){return this.visible},_center:function(e,d){var f=WindowUtilities.getWindowScroll(this.options.parent);var b=WindowUtilities.getPageSize(this.options.parent);if(typeof e=="undefined"){e=(b.windowHeight-(this.height+this.heightN+this.heightS))/2}e+=f.top;if(typeof d=="undefined"){d=(b.windowWidth-(this.width+this.widthW+this.widthE))/2}d+=f.left;this.setLocation(e,d);this.toFront()},_recenter:function(d){if(this.centered){var b=WindowUtilities.getPageSize(this.options.parent);var e=WindowUtilities.getWindowScroll(this.options.parent);if(this.pageSize&&this.pageSize.windowWidth==b.windowWidth&&this.pageSize.windowHeight==b.windowHeight&&this.windowScroll.left==e.left&&this.windowScroll.top==e.top){return}this.pageSize=b;this.windowScroll=e;if($("overlay_modal")){$("overlay_modal").setStyle({height:(b.pageHeight+"px")})}if(this.options.recenterAuto){this._center(this.centerTop,this.centerLeft)}}},hide:function(){this.visible=false;if(this.modal){Windows.removeModalWindow(this);Windows.resetOverflow()}this.oldStyle=this.getContent().getStyle("overflow")||"auto";this.getContent().setStyle({overflow:"hidden"});this.options.hideEffect(this.element,this.options.hideEffectOptions);if(this.iefix){this.iefix.hide()}if(!this.doNotNotifyHide){this._notify("onHide")}},close:function(){if(this.visible){if(this.options.closeCallback&&!this.options.closeCallback(this)){return}if(this.options.destroyOnClose){var b=this.destroy.bind(this);if(this.options.hideEffectOptions.afterFinish){var d=this.options.hideEffectOptions.afterFinish;this.options.hideEffectOptions.afterFinish=function(){d();b()}}else{this.options.hideEffectOptions.afterFinish=function(){b()}}}Windows.updateFocusedWindow();this.doNotNotifyHide=true;this.hide();this.doNotNotifyHide=false;this._notify("onClose")}},minimize:function(){if(this.resizing){return}var b=$(this.getId()+"_row2");if(!this.minimized){this.minimized=true;var f=b.getDimensions().height;this.r2Height=f;var e=this.element.getHeight()-f;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,null,null,null,this.height-f,{duration:Window.resizeEffectDuration})}else{this.height-=f;this.element.setStyle({height:e+"px"});b.hide()}if(!this.useTop){var d=parseFloat(this.element.getStyle("bottom"));this.element.setStyle({bottom:(d+f)+"px"})}}else{this.minimized=false;var f=this.r2Height;this.r2Height=null;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,null,null,null,this.height+f,{duration:Window.resizeEffectDuration})}else{var e=this.element.getHeight()+f;this.height+=f;this.element.setStyle({height:e+"px"});b.show()}if(!this.useTop){var d=parseFloat(this.element.getStyle("bottom"));this.element.setStyle({bottom:(d-f)+"px"})}this.toFront()}this._notify("onMinimize");this._saveCookie()},maximize:function(){if(this.isMinimized()||this.resizing){return}if(Prototype.Browser.IE&&this.heightN==0){this._getWindowBorderSize()}if(this.storedLocation!=null){this._restoreLocation();if(this.iefix){this.iefix.hide()}}else{this._storeLocation();Windows.unsetOverflow(this);var l=WindowUtilities.getWindowScroll(this.options.parent);var d=WindowUtilities.getPageSize(this.options.parent);var h=l.left;var g=l.top;if(this.options.parent!=document.body){l={top:0,left:0,bottom:0,right:0};var f=this.options.parent.getDimensions();d.windowWidth=f.width;d.windowHeight=f.height;g=0;h=0}if(this.constraint){d.windowWidth-=Math.max(0,this.constraintPad.left)+Math.max(0,this.constraintPad.right);d.windowHeight-=Math.max(0,this.constraintPad.top)+Math.max(0,this.constraintPad.bottom);h+=Math.max(0,this.constraintPad.left);g+=Math.max(0,this.constraintPad.top)}var e=d.windowWidth-this.widthW-this.widthE;var b=d.windowHeight-this.heightN-this.heightS;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,g,h,e,b,{duration:Window.resizeEffectDuration})}else{this.setSize(e,b);this.element.setStyle(this.useLeft?{left:h}:{right:h});this.element.setStyle(this.useTop?{top:g}:{bottom:g})}this.toFront();if(this.iefix){this._fixIEOverlapping()}}this._notify("onMaximize");this._saveCookie()},isMinimized:function(){return this.minimized},isMaximized:function(){return(this.storedLocation!=null)},setOpacity:function(b){if(Element.setOpacity){Element.setOpacity(this.element,b)}},setZIndex:function(b){this.element.setStyle({zIndex:b});Windows.updateZindex(b,this)},setTitle:function(b){if(!b||b==""){b=" "}Element.update(this.element.id+"_top",b)},getTitle:function(){return $(this.element.id+"_top").innerHTML},setStatusBar:function(d){var b=$(this.getId()+"_bottom");if(typeof(d)=="object"){if(this.bottombar.firstChild){this.bottombar.replaceChild(d,this.bottombar.firstChild)}else{this.bottombar.appendChild(d)}}else{this.bottombar.innerHTML=d}},_checkIEOverlapping:function(){if(!this.iefix&&(navigator.appVersion.indexOf("MSIE")>0)&&(navigator.userAgent.indexOf("Opera")<0)&&(this.element.getStyle("position")=="absolute")){new Insertion.After(this.element.id,'<iframe id="'+this.element.id+'_iefix" style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" src="javascript:false;" frameborder="0" scrolling="no"></iframe>');this.iefix=$(this.element.id+"_iefix")}if(this.iefix){setTimeout(this._fixIEOverlapping.bind(this),50)}},_fixIEOverlapping:function(){Position.clone(this.element,this.iefix);this.iefix.style.zIndex=this.element.style.zIndex-1;this.iefix.show()},_keyUp:function(b){if(27==b.keyCode&&this.options.closeOnEsc){this.close()}},_getWindowBorderSize:function(d){var e=this._createHiddenDiv(this.options.className+"_n");this.heightN=Element.getDimensions(e).height;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_s");this.heightS=Element.getDimensions(e).height;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_e");this.widthE=Element.getDimensions(e).width;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_w");this.widthW=Element.getDimensions(e).width;e.parentNode.removeChild(e);var e=document.createElement("div");e.className="overlay_"+this.options.className;document.body.appendChild(e);var b=this;setTimeout(function(){b.overlayOpacity=($(e).getStyle("opacity"));e.parentNode.removeChild(e)},10);if(Prototype.Browser.IE){this.heightS=$(this.getId()+"_row3").getDimensions().height;this.heightN=$(this.getId()+"_row1").getDimensions().height}if(Prototype.Browser.WebKit&&Prototype.Browser.WebKitVersion<420){this.setSize(this.width,this.height)}if(this.doMaximize){this.maximize()}if(this.doMinimize){this.minimize()}},_createHiddenDiv:function(d){var b=document.body;var e=document.createElement("div");e.setAttribute("id",this.element.id+"_tmp");e.className=d;e.style.display="none";e.innerHTML="";b.insertBefore(e,b.firstChild);return e},_storeLocation:function(){if(this.storedLocation==null){this.storedLocation={useTop:this.useTop,useLeft:this.useLeft,top:this.element.getStyle("top"),bottom:this.element.getStyle("bottom"),left:this.element.getStyle("left"),right:this.element.getStyle("right"),width:this.width,height:this.height}}},_restoreLocation:function(){if(this.storedLocation!=null){this.useLeft=this.storedLocation.useLeft;this.useTop=this.storedLocation.useTop;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,this.storedLocation.top,this.storedLocation.left,this.storedLocation.width,this.storedLocation.height,{duration:Window.resizeEffectDuration})}else{this.element.setStyle(this.useLeft?{left:this.storedLocation.left}:{right:this.storedLocation.right});this.element.setStyle(this.useTop?{top:this.storedLocation.top}:{bottom:this.storedLocation.bottom});this.setSize(this.storedLocation.width,this.storedLocation.height)}Windows.resetOverflow();this._removeStoreLocation()}},_removeStoreLocation:function(){this.storedLocation=null},_saveCookie:function(){if(this.cookie){var b="";if(this.useLeft){b+="l:"+(this.storedLocation?this.storedLocation.left:this.element.getStyle("left"))}else{b+="r:"+(this.storedLocation?this.storedLocation.right:this.element.getStyle("right"))}if(this.useTop){b+=",t:"+(this.storedLocation?this.storedLocation.top:this.element.getStyle("top"))}else{b+=",b:"+(this.storedLocation?this.storedLocation.bottom:this.element.getStyle("bottom"))}b+=","+(this.storedLocation?this.storedLocation.width:this.width);b+=","+(this.storedLocation?this.storedLocation.height:this.height);b+=","+this.isMinimized();b+=","+this.isMaximized();WindowUtilities.setCookie(b,this.cookie)}},_createWiredElement:function(){if(!this.wiredElement){if(Prototype.Browser.IE){this._getWindowBorderSize()}var d=document.createElement("div");d.className="wired_frame "+this.options.className+"_wired_frame";d.style.position="absolute";this.options.parent.insertBefore(d,this.options.parent.firstChild);this.wiredElement=$(d)}if(this.useLeft){this.wiredElement.setStyle({left:this.element.getStyle("left")})}else{this.wiredElement.setStyle({right:this.element.getStyle("right")})}if(this.useTop){this.wiredElement.setStyle({top:this.element.getStyle("top")})}else{this.wiredElement.setStyle({bottom:this.element.getStyle("bottom")})}var b=this.element.getDimensions();this.wiredElement.setStyle({width:b.width+"px",height:b.height+"px"});this.wiredElement.setStyle({zIndex:Windows.maxZIndex+30});return this.wiredElement},_hideWiredElement:function(){if(!this.wiredElement||!this.currentDrag){return}if(this.currentDrag==this.element){this.currentDrag=null}else{if(this.useLeft){this.element.setStyle({left:this.currentDrag.getStyle("left")})}else{this.element.setStyle({right:this.currentDrag.getStyle("right")})}if(this.useTop){this.element.setStyle({top:this.currentDrag.getStyle("top")})}else{this.element.setStyle({bottom:this.currentDrag.getStyle("bottom")})}this.currentDrag.hide();this.currentDrag=null;if(this.doResize){this.setSize(this.width,this.height)}}},_notify:function(b){if(this.options[b]){this.options[b](this)}else{Windows.notify(b,this)}}};var Windows={windows:[],modalWindows:[],observers:[],focusedWindow:null,maxZIndex:0,overlayShowEffectOptions:{duration:0.5},overlayHideEffectOptions:{duration:0.5},addObserver:function(b){this.removeObserver(b);this.observers.push(b)},removeObserver:function(b){this.observers=this.observers.reject(function(d){return d==b})},notify:function(b,d){this.observers.each(function(e){if(e[b]){e[b](b,d)}})},getWindow:function(b){return this.windows.detect(function(e){return e.getId()==b})},getFocusedWindow:function(){return this.focusedWindow},updateFocusedWindow:function(){this.focusedWindow=this.windows.length>=2?this.windows[this.windows.length-2]:null},register:function(b){this.windows.push(b)},addModalWindow:function(b){if(this.modalWindows.length==0){WindowUtilities.disableScreen(b.options.className,"overlay_modal",b.overlayOpacity,b.getId(),b.options.parent)}else{if(Window.keepMultiModalWindow){$("overlay_modal").style.zIndex=Windows.maxZIndex+1;Windows.maxZIndex+=1;WindowUtilities._hideSelect(this.modalWindows.last().getId())}else{this.modalWindows.last().element.hide()}WindowUtilities._showSelect(b.getId())}this.modalWindows.push(b)},removeModalWindow:function(b){this.modalWindows.pop();if(this.modalWindows.length==0){WindowUtilities.enableScreen()}else{if(Window.keepMultiModalWindow){this.modalWindows.last().toFront();WindowUtilities._showSelect(this.modalWindows.last().getId())}else{this.modalWindows.last().element.show()}}},register:function(b){this.windows.push(b)},unregister:function(b){this.windows=this.windows.reject(function(e){return e==b})},closeAll:function(){this.windows.each(function(b){Windows.close(b.getId())})},closeAllModalWindows:function(){WindowUtilities.enableScreen();this.modalWindows.each(function(b){if(b){b.close()}})},minimize:function(e,b){var d=this.getWindow(e);if(d&&d.visible){d.minimize()}Event.stop(b)},maximize:function(e,b){var d=this.getWindow(e);if(d&&d.visible){d.maximize()}Event.stop(b)},close:function(e,b){var d=this.getWindow(e);if(d){d.close()}if(b){Event.stop(b)}},blur:function(d){var b=this.getWindow(d);if(!b){return}if(b.options.blurClassName){b.changeClassName(b.options.blurClassName)}if(this.focusedWindow==b){this.focusedWindow=null}b._notify("onBlur")},focus:function(d){var b=this.getWindow(d);if(!b){return}if(this.focusedWindow){this.blur(this.focusedWindow.getId())}if(b.options.focusClassName){b.changeClassName(b.options.focusClassName)}this.focusedWindow=b;b._notify("onFocus")},unsetOverflow:function(b){this.windows.each(function(e){e.oldOverflow=e.getContent().getStyle("overflow")||"auto";e.getContent().setStyle({overflow:"hidden"})});if(b&&b.oldOverflow){b.getContent().setStyle({overflow:b.oldOverflow})}},resetOverflow:function(){this.windows.each(function(b){if(b.oldOverflow){b.getContent().setStyle({overflow:b.oldOverflow})}})},updateZindex:function(b,d){if(b>this.maxZIndex){this.maxZIndex=b;if(this.focusedWindow){this.blur(this.focusedWindow.getId())}}this.focusedWindow=d;if(this.focusedWindow){this.focus(this.focusedWindow.getId())}}};var Dialog={dialogId:null,onCompleteFunc:null,callFunc:null,parameters:null,confirm:function(f,e){if(f&&typeof f!="string"){Dialog._runAjaxRequest(f,e,Dialog.confirm);return}f=f||"";e=e||{};var h=e.okLabel?e.okLabel:"Ok";var b=e.cancelLabel?e.cancelLabel:"Cancel";e=Object.extend(e,e.windowParameters||{});e.windowParameters=e.windowParameters||{};e.className=e.className||"alert";var d="class ='"+(e.buttonClass?e.buttonClass+" ":"")+" ok_button'";var g="class ='"+(e.buttonClass?e.buttonClass+" ":"")+" cancel_button'";var f=" <div class='"+e.className+"_message'>"+f+"</div> <div class='"+e.className+"_buttons'> <button type='button' title='"+h+"' onclick='Dialog.okCallback()' "+d+"><span><span><span>"+h+"</span></span></span></button> <button type='button' title='"+b+"' onclick='Dialog.cancelCallback()' "+g+"><span><span><span>"+b+"</span></span></span></button> </div> ";return this._openDialog(f,e)},alert:function(e,d){if(e&&typeof e!="string"){Dialog._runAjaxRequest(e,d,Dialog.alert);return}e=e||"";d=d||{};var f=d.okLabel?d.okLabel:"Ok";d=Object.extend(d,d.windowParameters||{});d.windowParameters=d.windowParameters||{};d.className=d.className||"alert";var b="class ='"+(d.buttonClass?d.buttonClass+" ":"")+" ok_button'";var e=" <div class='"+d.className+"_message'>"+e+"</div> <div class='"+d.className+"_buttons'> <button type='button' title='"+f+"' onclick='Dialog.okCallback()' "+b+"><span><span><span>"+f+"</span></span></span></button> </div>";return this._openDialog(e,d)},info:function(d,b){if(d&&typeof d!="string"){Dialog._runAjaxRequest(d,b,Dialog.info);return}d=d||"";b=b||{};b=Object.extend(b,b.windowParameters||{});b.windowParameters=b.windowParameters||{};b.className=b.className||"alert";var d="<div id='modal_dialog_message' class='"+b.className+"_message'>"+d+"</div>";if(b.showProgress){d+="<div id='modal_dialog_progress' class='"+b.className+"_progress'> </div>"}b.ok=null;b.cancel=null;return this._openDialog(d,b)},setInfoMessage:function(b){$("modal_dialog_message").update(b)},closeInfo:function(){Windows.close(this.dialogId)},_openDialog:function(g,f){var e=f.className;if(!f.height&&!f.width){f.width=WindowUtilities.getPageSize(f.options.parent||document.body).pageWidth/2}if(f.id){this.dialogId=f.id}else{var d=new Date();this.dialogId="modal_dialog_"+d.getTime();f.id=this.dialogId}if(!f.height||!f.width){var b=WindowUtilities._computeSize(g,this.dialogId,f.width,f.height,5,e);if(f.height){f.width=b+5}else{f.height=b+5}}f.effectOptions=f.effectOptions;f.resizable=f.resizable||false;f.minimizable=f.minimizable||false;f.maximizable=f.maximizable||false;f.draggable=f.draggable||false;f.closable=f.closable||false;var h=new Window(f);h.getContent().innerHTML=g;h.showCenter(true,f.top,f.left);h.setDestroyOnClose();h.cancelCallback=f.onCancel||f.cancel;h.okCallback=f.onOk||f.ok;return h},_getAjaxContent:function(b){Dialog.callFunc(b.responseText,Dialog.parameters)},_runAjaxRequest:function(e,d,b){if(e.options==null){e.options={}}Dialog.onCompleteFunc=e.options.onComplete;Dialog.parameters=d;Dialog.callFunc=b;e.options.onComplete=Dialog._getAjaxContent;new Ajax.Request(e.url,e.options)},okCallback:function(){var b=Windows.focusedWindow;if(!b.okCallback||b.okCallback(b)){$$("#"+b.getId()+" input").each(function(d){d.onclick=null});b.close()}},cancelCallback:function(){var b=Windows.focusedWindow;$$("#"+b.getId()+" input").each(function(d){d.onclick=null});b.close();if(b.cancelCallback){b.cancelCallback(b)}}};if(Prototype.Browser.WebKit){var array=navigator.userAgent.match(new RegExp(/AppleWebKit\/([\d\.\+]*)/));Prototype.Browser.WebKitVersion=parseFloat(array[1])}var WindowUtilities={getWindowScroll:function(parent){var T,L,W,H;parent=parent||document.body;if(parent!=document.body){T=parent.scrollTop;L=parent.scrollLeft;W=parent.scrollWidth;H=parent.scrollHeight}else{var w=window;with(w.document){if(w.document.documentElement&&documentElement.scrollTop){T=documentElement.scrollTop;L=documentElement.scrollLeft}else{if(w.document.body){T=body.scrollTop;L=body.scrollLeft}}if(w.innerWidth){W=w.innerWidth;H=w.innerHeight}else{if(w.document.documentElement&&documentElement.clientWidth){W=documentElement.clientWidth;H=documentElement.clientHeight}else{W=body.offsetWidth;H=body.offsetHeight}}}}return{top:T,left:L,width:W,height:H}},getPageSize:function(f){f=f||document.body;var e,l;var g,d;if(f!=document.body){e=f.getWidth();l=f.getHeight();d=f.scrollWidth;g=f.scrollHeight}else{var h,b;if(window.innerHeight&&window.scrollMaxY){h=document.body.scrollWidth;b=window.innerHeight+window.scrollMaxY}else{if(document.body.scrollHeight>document.body.offsetHeight){h=document.body.scrollWidth;b=document.body.scrollHeight}else{h=document.body.offsetWidth;b=document.body.offsetHeight}}if(self.innerHeight){e=document.documentElement.clientWidth;l=self.innerHeight}else{if(document.documentElement&&document.documentElement.clientHeight){e=document.documentElement.clientWidth;l=document.documentElement.clientHeight}else{if(document.body){e=document.body.clientWidth;l=document.body.clientHeight}}}if(b<l){g=l}else{g=b}if(h<e){d=e}else{d=h}}return{pageWidth:d,pageHeight:g,windowWidth:e,windowHeight:l}},disableScreen:function(e,b,f,g,d){WindowUtilities.initLightbox(b,e,function(){this._disableScreen(e,b,f,g)}.bind(this),d||document.body)},_disableScreen:function(e,d,g,h){var f=$(d);var b=WindowUtilities.getPageSize(f.parentNode);if(h&&Prototype.Browser.IE){WindowUtilities._hideSelect();WindowUtilities._showSelect(h)}f.style.height=(b.pageHeight+"px");f.style.display="none";if(d=="overlay_modal"&&Window.hasEffectLib&&Windows.overlayShowEffectOptions){f.overlayOpacity=g;new Effect.Appear(f,Object.extend({from:0,to:g},Windows.overlayShowEffectOptions))}else{f.style.display="block"}},enableScreen:function(d){d=d||"overlay_modal";var b=$(d);if(b){if(d=="overlay_modal"&&Window.hasEffectLib&&Windows.overlayHideEffectOptions){new Effect.Fade(b,Object.extend({from:b.overlayOpacity,to:0},Windows.overlayHideEffectOptions))}else{b.style.display="none";b.parentNode.removeChild(b)}if(d!="__invisible__"){WindowUtilities._showSelect()}}},_hideSelect:function(b){if(Prototype.Browser.IE){b=b==null?"":"#"+b+" ";$$(b+"select").each(function(d){if(!WindowUtilities.isDefined(d.oldVisibility)){d.oldVisibility=d.style.visibility?d.style.visibility:"visible";d.style.visibility="hidden"}})}},_showSelect:function(b){if(Prototype.Browser.IE){b=b==null?"":"#"+b+" ";$$(b+"select").each(function(d){if(WindowUtilities.isDefined(d.oldVisibility)){try{d.style.visibility=d.oldVisibility}catch(f){d.style.visibility="visible"}d.oldVisibility=null}else{if(d.style.visibility){d.style.visibility="visible"}}})}},isDefined:function(b){return typeof(b)!="undefined"&&b!=null},initLightbox:function(g,e,b,d){if($(g)){Element.setStyle(g,{zIndex:Windows.maxZIndex+1});Windows.maxZIndex++;b()}else{var f=document.createElement("div");f.setAttribute("id",g);f.className="overlay_"+e;f.style.display="none";f.style.position="absolute";f.style.top="0";f.style.left="0";f.style.zIndex=Windows.maxZIndex+1;Windows.maxZIndex++;f.style.width="100%";d.insertBefore(f,d.firstChild);if(Prototype.Browser.WebKit&&g=="overlay_modal"){setTimeout(function(){b()},10)}else{b()}}},setCookie:function(d,b){document.cookie=b[0]+"="+escape(d)+((b[1])?"; expires="+b[1].toGMTString():"")+((b[2])?"; path="+b[2]:"")+((b[3])?"; domain="+b[3]:"")+((b[4])?"; secure":"")},getCookie:function(e){var d=document.cookie;var g=e+"=";var f=d.indexOf("; "+g);if(f==-1){f=d.indexOf(g);if(f!=0){return null}}else{f+=2}var b=document.cookie.indexOf(";",f);if(b==-1){b=d.length}return unescape(d.substring(f+g.length,b))},_computeSize:function(g,b,d,l,f,h){var o=document.body;var e=document.createElement("div");e.setAttribute("id",b);e.className=h+"_content";if(l){e.style.height=l+"px"}else{e.style.width=d+"px"}e.style.position="absolute";e.style.top="0";e.style.left="0";e.style.display="none";e.innerHTML=g;o.insertBefore(e,o.firstChild);var n;if(l){n=$(e).getDimensions().width+f}else{n=$(e).getDimensions().height+f}o.removeChild(e);return n}};var Builder={NODEMAP:{AREA:"map",CAPTION:"table",COL:"table",COLGROUP:"table",LEGEND:"fieldset",OPTGROUP:"select",OPTION:"select",PARAM:"object",TBODY:"table",TD:"table",TFOOT:"table",TH:"table",THEAD:"table",TR:"table"},node:function(b){b=b.toUpperCase();var l=this.NODEMAP[b]||"div";var d=document.createElement(l);try{d.innerHTML="<"+b+"></"+b+">"}catch(h){}var g=d.firstChild||null;if(g&&(g.tagName.toUpperCase()!=b)){g=g.getElementsByTagName(b)[0]}if(!g){g=document.createElement(b)}if(!g){return}if(arguments[1]){if(this._isStringOrNumber(arguments[1])||(arguments[1] instanceof Array)||arguments[1].tagName){this._children(g,arguments[1])}else{var f=this._attributes(arguments[1]);if(f.length){try{d.innerHTML="<"+b+" "+f+"></"+b+">"}catch(h){}g=d.firstChild||null;if(!g){g=document.createElement(b);for(attr in arguments[1]){g[attr=="class"?"className":attr]=arguments[1][attr]}}if(g.tagName.toUpperCase()!=b){g=d.getElementsByTagName(b)[0]}}}}if(arguments[2]){this._children(g,arguments[2])}return $(g)},_text:function(b){return document.createTextNode(b)},ATTR_MAP:{className:"class",htmlFor:"for"},_attributes:function(b){var d=[];for(attribute in b){d.push((attribute in this.ATTR_MAP?this.ATTR_MAP[attribute]:attribute)+'="'+b[attribute].toString().escapeHTML().gsub(/"/,""")+'"')}return d.join(" ")},_children:function(d,b){if(b.tagName){d.appendChild(b);return}if(typeof b=="object"){b.flatten().each(function(f){if(typeof f=="object"){d.appendChild(f)}else{if(Builder._isStringOrNumber(f)){d.appendChild(Builder._text(f))}}})}else{if(Builder._isStringOrNumber(b)){d.appendChild(Builder._text(b))}}},_isStringOrNumber:function(b){return(typeof b=="string"||typeof b=="number")},build:function(d){var b=this.node("div");$(b).update(d.strip());return b.down()},dump:function(d){if(typeof d!="object"&&typeof d!="function"){d=window}var b=("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);b.each(function(e){d[e]=function(){return Builder.node.apply(Builder,[e].concat($A(arguments)))}})}};String.prototype.parseColor=function(){var b="#";if(this.slice(0,4)=="rgb("){var e=this.slice(4,this.length-1).split(",");var d=0;do{b+=parseInt(e[d]).toColorPart()}while(++d<3)}else{if(this.slice(0,1)=="#"){if(this.length==4){for(var d=1;d<4;d++){b+=(this.charAt(d)+this.charAt(d)).toLowerCase()}}if(this.length==7){b=this.toLowerCase()}}}return(b.length==7?b:(arguments[0]||this))};Element.collectTextNodes=function(b){return $A($(b).childNodes).collect(function(d){return(d.nodeType==3?d.nodeValue:(d.hasChildNodes()?Element.collectTextNodes(d):""))}).flatten().join("")};Element.collectTextNodesIgnoreClass=function(b,d){return $A($(b).childNodes).collect(function(e){return(e.nodeType==3?e.nodeValue:((e.hasChildNodes()&&!Element.hasClassName(e,d))?Element.collectTextNodesIgnoreClass(e,d):""))}).flatten().join("")};Element.setContentZoom=function(b,d){b=$(b);b.setStyle({fontSize:(d/100)+"em"});if(Prototype.Browser.WebKit){window.scrollBy(0,0)}return b};Element.getInlineOpacity=function(b){return $(b).style.opacity||""};Element.forceRerendering=function(b){try{b=$(b);var f=document.createTextNode(" ");b.appendChild(f);b.removeChild(f)}catch(d){}};var Effect={_elementDoesNotExistError:{name:"ElementDoesNotExistError",message:"The specified DOM element does not exist, but is required for this effect to operate"},Transitions:{linear:Prototype.K,sinoidal:function(b){return(-Math.cos(b*Math.PI)/2)+0.5},reverse:function(b){return 1-b},flicker:function(b){var b=((-Math.cos(b*Math.PI)/4)+0.75)+Math.random()/4;return b>1?1:b},wobble:function(b){return(-Math.cos(b*Math.PI*(9*b))/2)+0.5},pulse:function(d,b){return(-Math.cos((d*((b||5)-0.5)*2)*Math.PI)/2)+0.5},spring:function(b){return 1-(Math.cos(b*4.5*Math.PI)*Math.exp(-b*6))},none:function(b){return 0},full:function(b){return 1}},DefaultOptions:{duration:1,fps:100,sync:false,from:0,to:1,delay:0,queue:"parallel"},tagifyText:function(b){var d="position:relative";if(Prototype.Browser.IE){d+=";zoom:1"}b=$(b);$A(b.childNodes).each(function(e){if(e.nodeType==3){e.nodeValue.toArray().each(function(f){b.insertBefore(new Element("span",{style:d}).update(f==" "?String.fromCharCode(160):f),e)});Element.remove(e)}})},multiple:function(d,e){var g;if(((typeof d=="object")||Object.isFunction(d))&&(d.length)){g=d}else{g=$(d).childNodes}var b=Object.extend({speed:0.1,delay:0},arguments[2]||{});var f=b.delay;$A(g).each(function(l,h){new e(l,Object.extend(b,{delay:h*b.speed+f}))})},PAIRS:{slide:["SlideDown","SlideUp"],blind:["BlindDown","BlindUp"],appear:["Appear","Fade"]},toggle:function(d,e){d=$(d);e=(e||"appear").toLowerCase();var b=Object.extend({queue:{position:"end",scope:(d.id||"global"),limit:1}},arguments[2]||{});Effect[d.visible()?Effect.PAIRS[e][1]:Effect.PAIRS[e][0]](d,b)}};Effect.DefaultOptions.transition=Effect.Transitions.sinoidal;Effect.ScopedQueue=Class.create(Enumerable,{initialize:function(){this.effects=[];this.interval=null},_each:function(b){this.effects._each(b)},add:function(d){var e=new Date().getTime();var b=Object.isString(d.options.queue)?d.options.queue:d.options.queue.position;switch(b){case"front":this.effects.findAll(function(f){return f.state=="idle"}).each(function(f){f.startOn+=d.finishOn;f.finishOn+=d.finishOn});break;case"with-last":e=this.effects.pluck("startOn").max()||e;break;case"end":e=this.effects.pluck("finishOn").max()||e;break}d.startOn+=e;d.finishOn+=e;if(!d.options.queue.limit||(this.effects.length<d.options.queue.limit)){this.effects.push(d)}if(!this.interval){this.interval=setInterval(this.loop.bind(this),15)}},remove:function(b){this.effects=this.effects.reject(function(d){return d==b});if(this.effects.length==0){clearInterval(this.interval);this.interval=null}},loop:function(){var e=new Date().getTime();for(var d=0,b=this.effects.length;d<b;d++){this.effects[d]&&this.effects[d].loop(e)}}});Effect.Queues={instances:$H(),get:function(b){if(!Object.isString(b)){return b}return this.instances.get(b)||this.instances.set(b,new Effect.ScopedQueue())}};Effect.Queue=Effect.Queues.get("global");Effect.Base=Class.create({position:null,start:function(b){function d(f,e){return((f[e+"Internal"]?"this.options."+e+"Internal(this);":"")+(f[e]?"this.options."+e+"(this);":""))}if(b&&b.transition===false){b.transition=Effect.Transitions.linear}this.options=Object.extend(Object.extend({},Effect.DefaultOptions),b||{});this.currentFrame=0;this.state="idle";this.startOn=this.options.delay*1000;this.finishOn=this.startOn+(this.options.duration*1000);this.fromToDelta=this.options.to-this.options.from;this.totalTime=this.finishOn-this.startOn;this.totalFrames=this.options.fps*this.options.duration;this.render=(function(){function e(g,f){if(g.options[f+"Internal"]){g.options[f+"Internal"](g)}if(g.options[f]){g.options[f](g)}}return function(f){if(this.state==="idle"){this.state="running";e(this,"beforeSetup");if(this.setup){this.setup()}e(this,"afterSetup")}if(this.state==="running"){f=(this.options.transition(f)*this.fromToDelta)+this.options.from;this.position=f;e(this,"beforeUpdate");if(this.update){this.update(f)}e(this,"afterUpdate")}}})();this.event("beforeStart");if(!this.options.sync){Effect.Queues.get(Object.isString(this.options.queue)?"global":this.options.queue.scope).add(this)}},loop:function(e){if(e>=this.startOn){if(e>=this.finishOn){this.render(1);this.cancel();this.event("beforeFinish");if(this.finish){this.finish()}this.event("afterFinish");return}var d=(e-this.startOn)/this.totalTime,b=(d*this.totalFrames).round();if(b>this.currentFrame){this.render(d);this.currentFrame=b}}},cancel:function(){if(!this.options.sync){Effect.Queues.get(Object.isString(this.options.queue)?"global":this.options.queue.scope).remove(this)}this.state="finished"},event:function(b){if(this.options[b+"Internal"]){this.options[b+"Internal"](this)}if(this.options[b]){this.options[b](this)}},inspect:function(){var b=$H();for(property in this){if(!Object.isFunction(this[property])){b.set(property,this[property])}}return"#<Effect:"+b.inspect()+",options:"+$H(this.options).inspect()+">"}});Effect.Parallel=Class.create(Effect.Base,{initialize:function(b){this.effects=b||[];this.start(arguments[1])},update:function(b){this.effects.invoke("render",b)},finish:function(b){this.effects.each(function(d){d.render(1);d.cancel();d.event("beforeFinish");if(d.finish){d.finish(b)}d.event("afterFinish")})}});Effect.Tween=Class.create(Effect.Base,{initialize:function(e,h,g){e=Object.isString(e)?$(e):e;var d=$A(arguments),f=d.last(),b=d.length==5?d[3]:null;this.method=Object.isFunction(f)?f.bind(e):Object.isFunction(e[f])?e[f].bind(e):function(l){e[f]=l};this.start(Object.extend({from:h,to:g},b||{}))},update:function(b){this.method(b)}});Effect.Event=Class.create(Effect.Base,{initialize:function(){this.start(Object.extend({duration:0},arguments[0]||{}))},update:Prototype.emptyFunction});Effect.Opacity=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}if(Prototype.Browser.IE&&(!this.element.currentStyle.hasLayout)){this.element.setStyle({zoom:1})}var b=Object.extend({from:this.element.getOpacity()||0,to:1},arguments[1]||{});this.start(b)},update:function(b){this.element.setOpacity(b)}});Effect.Move=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({x:0,y:0,mode:"relative"},arguments[1]||{});this.start(b)},setup:function(){this.element.makePositioned();this.originalLeft=parseFloat(this.element.getStyle("left")||"0");this.originalTop=parseFloat(this.element.getStyle("top")||"0");if(this.options.mode=="absolute"){this.options.x=this.options.x-this.originalLeft;this.options.y=this.options.y-this.originalTop}},update:function(b){this.element.setStyle({left:(this.options.x*b+this.originalLeft).round()+"px",top:(this.options.y*b+this.originalTop).round()+"px"})}});Effect.MoveBy=function(d,b,e){return new Effect.Move(d,Object.extend({x:e,y:b},arguments[3]||{}))};Effect.Scale=Class.create(Effect.Base,{initialize:function(d,e){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:"box",scaleFrom:100,scaleTo:e},arguments[2]||{});this.start(b)},setup:function(){this.restoreAfterFinish=this.options.restoreAfterFinish||false;this.elementPositioning=this.element.getStyle("position");this.originalStyle={};["top","left","width","height","fontSize"].each(function(d){this.originalStyle[d]=this.element.style[d]}.bind(this));this.originalTop=this.element.offsetTop;this.originalLeft=this.element.offsetLeft;var b=this.element.getStyle("font-size")||"100%";["em","px","%","pt"].each(function(d){if(b.indexOf(d)>0){this.fontSize=parseFloat(b);this.fontSizeType=d}}.bind(this));this.factor=(this.options.scaleTo-this.options.scaleFrom)/100;this.dims=null;if(this.options.scaleMode=="box"){this.dims=[this.element.offsetHeight,this.element.offsetWidth]}if(/^content/.test(this.options.scaleMode)){this.dims=[this.element.scrollHeight,this.element.scrollWidth]}if(!this.dims){this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth]}},update:function(b){var d=(this.options.scaleFrom/100)+(this.factor*b);if(this.options.scaleContent&&this.fontSize){this.element.setStyle({fontSize:this.fontSize*d+this.fontSizeType})}this.setDimensions(this.dims[0]*d,this.dims[1]*d)},finish:function(b){if(this.restoreAfterFinish){this.element.setStyle(this.originalStyle)}},setDimensions:function(b,g){var h={};if(this.options.scaleX){h.width=g.round()+"px"}if(this.options.scaleY){h.height=b.round()+"px"}if(this.options.scaleFromCenter){var f=(b-this.dims[0])/2;var e=(g-this.dims[1])/2;if(this.elementPositioning=="absolute"){if(this.options.scaleY){h.top=this.originalTop-f+"px"}if(this.options.scaleX){h.left=this.originalLeft-e+"px"}}else{if(this.options.scaleY){h.top=-f+"px"}if(this.options.scaleX){h.left=-e+"px"}}}this.element.setStyle(h)}});Effect.Highlight=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({startcolor:"#ffff99"},arguments[1]||{});this.start(b)},setup:function(){if(this.element.getStyle("display")=="none"){this.cancel();return}this.oldStyle={};if(!this.options.keepBackgroundImage){this.oldStyle.backgroundImage=this.element.getStyle("background-image");this.element.setStyle({backgroundImage:"none"})}if(!this.options.endcolor){this.options.endcolor=this.element.getStyle("background-color").parseColor("#ffffff")}if(!this.options.restorecolor){this.options.restorecolor=this.element.getStyle("background-color")}this._base=$R(0,2).map(function(b){return parseInt(this.options.startcolor.slice(b*2+1,b*2+3),16)}.bind(this));this._delta=$R(0,2).map(function(b){return parseInt(this.options.endcolor.slice(b*2+1,b*2+3),16)-this._base[b]}.bind(this))},update:function(b){this.element.setStyle({backgroundColor:$R(0,2).inject("#",function(d,e,f){return d+((this._base[f]+(this._delta[f]*b)).round().toColorPart())}.bind(this))})},finish:function(){this.element.setStyle(Object.extend(this.oldStyle,{backgroundColor:this.options.restorecolor}))}});Effect.ScrollTo=function(e){var d=arguments[1]||{},b=document.viewport.getScrollOffsets(),f=$(e).cumulativeOffset();if(d.offset){f[1]+=d.offset}return new Effect.Tween(null,b.top,f[1],d,function(g){scrollTo(b.left,g.round())})};Effect.Fade=function(e){e=$(e);var b=e.getInlineOpacity();var d=Object.extend({from:e.getOpacity()||1,to:0,afterFinishInternal:function(f){if(f.options.to!=0){return}f.element.hide().setStyle({opacity:b})}},arguments[1]||{});return new Effect.Opacity(e,d)};Effect.Appear=function(d){d=$(d);var b=Object.extend({from:(d.getStyle("display")=="none"?0:d.getOpacity()||0),to:1,afterFinishInternal:function(e){e.element.forceRerendering()},beforeSetup:function(e){e.element.setOpacity(e.options.from).show()}},arguments[1]||{});return new Effect.Opacity(d,b)};Effect.Puff=function(d){d=$(d);var b={opacity:d.getInlineOpacity(),position:d.getStyle("position"),top:d.style.top,left:d.style.left,width:d.style.width,height:d.style.height};return new Effect.Parallel([new Effect.Scale(d,200,{sync:true,scaleFromCenter:true,scaleContent:true,restoreAfterFinish:true}),new Effect.Opacity(d,{sync:true,to:0})],Object.extend({duration:1,beforeSetupInternal:function(e){Position.absolutize(e.effects[0].element)},afterFinishInternal:function(e){e.effects[0].element.hide().setStyle(b)}},arguments[1]||{}))};Effect.BlindUp=function(b){b=$(b);b.makeClipping();return new Effect.Scale(b,0,Object.extend({scaleContent:false,scaleX:false,restoreAfterFinish:true,afterFinishInternal:function(d){d.element.hide().undoClipping()}},arguments[1]||{}))};Effect.BlindDown=function(d){d=$(d);var b=d.getDimensions();return new Effect.Scale(d,100,Object.extend({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:b.height,originalWidth:b.width},restoreAfterFinish:true,afterSetup:function(e){e.element.makeClipping().setStyle({height:"0px"}).show()},afterFinishInternal:function(e){e.element.undoClipping()}},arguments[1]||{}))};Effect.SwitchOff=function(d){d=$(d);var b=d.getInlineOpacity();return new Effect.Appear(d,Object.extend({duration:0.4,from:0,transition:Effect.Transitions.flicker,afterFinishInternal:function(e){new Effect.Scale(e.element,1,{duration:0.3,scaleFromCenter:true,scaleX:false,scaleContent:false,restoreAfterFinish:true,beforeSetup:function(f){f.element.makePositioned().makeClipping()},afterFinishInternal:function(f){f.element.hide().undoClipping().undoPositioned().setStyle({opacity:b})}})}},arguments[1]||{}))};Effect.DropOut=function(d){d=$(d);var b={top:d.getStyle("top"),left:d.getStyle("left"),opacity:d.getInlineOpacity()};return new Effect.Parallel([new Effect.Move(d,{x:0,y:100,sync:true}),new Effect.Opacity(d,{sync:true,to:0})],Object.extend({duration:0.5,beforeSetup:function(e){e.effects[0].element.makePositioned()},afterFinishInternal:function(e){e.effects[0].element.hide().undoPositioned().setStyle(b)}},arguments[1]||{}))};Effect.Shake=function(f){f=$(f);var d=Object.extend({distance:20,duration:0.5},arguments[1]||{});var g=parseFloat(d.distance);var e=parseFloat(d.duration)/10;var b={top:f.getStyle("top"),left:f.getStyle("left")};return new Effect.Move(f,{x:g,y:0,duration:e,afterFinishInternal:function(h){new Effect.Move(h.element,{x:-g*2,y:0,duration:e*2,afterFinishInternal:function(l){new Effect.Move(l.element,{x:g*2,y:0,duration:e*2,afterFinishInternal:function(n){new Effect.Move(n.element,{x:-g*2,y:0,duration:e*2,afterFinishInternal:function(o){new Effect.Move(o.element,{x:g*2,y:0,duration:e*2,afterFinishInternal:function(p){new Effect.Move(p.element,{x:-g,y:0,duration:e,afterFinishInternal:function(q){q.element.undoPositioned().setStyle(b)}})}})}})}})}})}})};Effect.SlideDown=function(e){e=$(e).cleanWhitespace();var b=e.down().getStyle("bottom");var d=e.getDimensions();return new Effect.Scale(e,100,Object.extend({scaleContent:false,scaleX:false,scaleFrom:window.opera?0:1,scaleMode:{originalHeight:d.height,originalWidth:d.width},restoreAfterFinish:true,afterSetup:function(f){f.element.makePositioned();f.element.down().makePositioned();if(window.opera){f.element.setStyle({top:""})}f.element.makeClipping().setStyle({height:"0px"}).show()},afterUpdateInternal:function(f){f.element.down().setStyle({bottom:(f.dims[0]-f.element.clientHeight)+"px"})},afterFinishInternal:function(f){f.element.undoClipping().undoPositioned();f.element.down().undoPositioned().setStyle({bottom:b})}},arguments[1]||{}))};Effect.SlideUp=function(e){e=$(e).cleanWhitespace();var b=e.down().getStyle("bottom");var d=e.getDimensions();return new Effect.Scale(e,window.opera?0:1,Object.extend({scaleContent:false,scaleX:false,scaleMode:"box",scaleFrom:100,scaleMode:{originalHeight:d.height,originalWidth:d.width},restoreAfterFinish:true,afterSetup:function(f){f.element.makePositioned();f.element.down().makePositioned();if(window.opera){f.element.setStyle({top:""})}f.element.makeClipping().show()},afterUpdateInternal:function(f){f.element.down().setStyle({bottom:(f.dims[0]-f.element.clientHeight)+"px"})},afterFinishInternal:function(f){f.element.hide().undoClipping().undoPositioned();f.element.down().undoPositioned().setStyle({bottom:b})}},arguments[1]||{}))};Effect.Squish=function(b){return new Effect.Scale(b,window.opera?1:0,{restoreAfterFinish:true,beforeSetup:function(d){d.element.makeClipping()},afterFinishInternal:function(d){d.element.hide().undoClipping()}})};Effect.Grow=function(e){e=$(e);var d=Object.extend({direction:"center",moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.full},arguments[1]||{});var b={top:e.style.top,left:e.style.left,height:e.style.height,width:e.style.width,opacity:e.getInlineOpacity()};var l=e.getDimensions();var n,h;var g,f;switch(d.direction){case"top-left":n=h=g=f=0;break;case"top-right":n=l.width;h=f=0;g=-l.width;break;case"bottom-left":n=g=0;h=l.height;f=-l.height;break;case"bottom-right":n=l.width;h=l.height;g=-l.width;f=-l.height;break;case"center":n=l.width/2;h=l.height/2;g=-l.width/2;f=-l.height/2;break}return new Effect.Move(e,{x:n,y:h,duration:0.01,beforeSetup:function(o){o.element.hide().makeClipping().makePositioned()},afterFinishInternal:function(o){new Effect.Parallel([new Effect.Opacity(o.element,{sync:true,to:1,from:0,transition:d.opacityTransition}),new Effect.Move(o.element,{x:g,y:f,sync:true,transition:d.moveTransition}),new Effect.Scale(o.element,100,{scaleMode:{originalHeight:l.height,originalWidth:l.width},sync:true,scaleFrom:window.opera?1:0,transition:d.scaleTransition,restoreAfterFinish:true})],Object.extend({beforeSetup:function(p){p.effects[0].element.setStyle({height:"0px"}).show()},afterFinishInternal:function(p){p.effects[0].element.undoClipping().undoPositioned().setStyle(b)}},d))}})};Effect.Shrink=function(e){e=$(e);var d=Object.extend({direction:"center",moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.none},arguments[1]||{});var b={top:e.style.top,left:e.style.left,height:e.style.height,width:e.style.width,opacity:e.getInlineOpacity()};var h=e.getDimensions();var g,f;switch(d.direction){case"top-left":g=f=0;break;case"top-right":g=h.width;f=0;break;case"bottom-left":g=0;f=h.height;break;case"bottom-right":g=h.width;f=h.height;break;case"center":g=h.width/2;f=h.height/2;break}return new Effect.Parallel([new Effect.Opacity(e,{sync:true,to:0,from:1,transition:d.opacityTransition}),new Effect.Scale(e,window.opera?1:0,{sync:true,transition:d.scaleTransition,restoreAfterFinish:true}),new Effect.Move(e,{x:g,y:f,sync:true,transition:d.moveTransition})],Object.extend({beforeStartInternal:function(l){l.effects[0].element.makePositioned().makeClipping()},afterFinishInternal:function(l){l.effects[0].element.hide().undoClipping().undoPositioned().setStyle(b)}},d))};Effect.Pulsate=function(e){e=$(e);var d=arguments[1]||{},b=e.getInlineOpacity(),g=d.transition||Effect.Transitions.linear,f=function(h){return 1-g((-Math.cos((h*(d.pulses||5)*2)*Math.PI)/2)+0.5)};return new Effect.Opacity(e,Object.extend(Object.extend({duration:2,from:0,afterFinishInternal:function(h){h.element.setStyle({opacity:b})}},d),{transition:f}))};Effect.Fold=function(d){d=$(d);var b={top:d.style.top,left:d.style.left,width:d.style.width,height:d.style.height};d.makeClipping();return new Effect.Scale(d,5,Object.extend({scaleContent:false,scaleX:false,afterFinishInternal:function(e){new Effect.Scale(d,1,{scaleContent:false,scaleY:false,afterFinishInternal:function(f){f.element.hide().undoClipping().setStyle(b)}})}},arguments[1]||{}))};Effect.Morph=Class.create(Effect.Base,{initialize:function(e){this.element=$(e);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({style:{}},arguments[1]||{});if(!Object.isString(b.style)){this.style=$H(b.style)}else{if(b.style.include(":")){this.style=b.style.parseStyle()}else{this.element.addClassName(b.style);this.style=$H(this.element.getStyles());this.element.removeClassName(b.style);var d=this.element.getStyles();this.style=this.style.reject(function(f){return f.value==d[f.key]});b.afterFinishInternal=function(f){f.element.addClassName(f.options.style);f.transforms.each(function(g){f.element.style[g.style]=""})}}}this.start(b)},setup:function(){function b(d){if(!d||["rgba(0, 0, 0, 0)","transparent"].include(d)){d="#ffffff"}d=d.parseColor();return $R(0,2).map(function(e){return parseInt(d.slice(e*2+1,e*2+3),16)})}this.transforms=this.style.map(function(l){var h=l[0],g=l[1],f=null;if(g.parseColor("#zzzzzz")!="#zzzzzz"){g=g.parseColor();f="color"}else{if(h=="opacity"){g=parseFloat(g);if(Prototype.Browser.IE&&(!this.element.currentStyle.hasLayout)){this.element.setStyle({zoom:1})}}else{if(Element.CSS_LENGTH.test(g)){var e=g.match(/^([\+\-]?[0-9\.]+)(.*)$/);g=parseFloat(e[1]);f=(e.length==3)?e[2]:null}}}var d=this.element.getStyle(h);return{style:h.camelize(),originalValue:f=="color"?b(d):parseFloat(d||0),targetValue:f=="color"?b(g):g,unit:f}}.bind(this)).reject(function(d){return((d.originalValue==d.targetValue)||(d.unit!="color"&&(isNaN(d.originalValue)||isNaN(d.targetValue))))})},update:function(b){var f={},d,e=this.transforms.length;while(e--){f[(d=this.transforms[e]).style]=d.unit=="color"?"#"+(Math.round(d.originalValue[0]+(d.targetValue[0]-d.originalValue[0])*b)).toColorPart()+(Math.round(d.originalValue[1]+(d.targetValue[1]-d.originalValue[1])*b)).toColorPart()+(Math.round(d.originalValue[2]+(d.targetValue[2]-d.originalValue[2])*b)).toColorPart():(d.originalValue+(d.targetValue-d.originalValue)*b).toFixed(3)+(d.unit===null?"":d.unit)}this.element.setStyle(f,true)}});Effect.Transform=Class.create({initialize:function(b){this.tracks=[];this.options=arguments[1]||{};this.addTracks(b)},addTracks:function(b){b.each(function(d){d=$H(d);var e=d.values().first();this.tracks.push($H({ids:d.keys().first(),effect:Effect.Morph,options:{style:e}}))}.bind(this));return this},play:function(){return new Effect.Parallel(this.tracks.map(function(b){var f=b.get("ids"),e=b.get("effect"),d=b.get("options");var g=[$(f)||$$(f)].flatten();return g.map(function(h){return new e(h,Object.extend({sync:true},d))})}).flatten(),this.options)}});Element.CSS_PROPERTIES=$w("backgroundColor backgroundPosition borderBottomColor borderBottomStyle borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth borderRightColor borderRightStyle borderRightWidth borderSpacing borderTopColor borderTopStyle borderTopWidth bottom clip color fontSize fontWeight height left letterSpacing lineHeight marginBottom marginLeft marginRight marginTop markerOffset maxHeight maxWidth minHeight minWidth opacity outlineColor outlineOffset outlineWidth paddingBottom paddingLeft paddingRight paddingTop right textIndent top width wordSpacing zIndex");Element.CSS_LENGTH=/^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;String.__parseStyleElement=document.createElement("div");String.prototype.parseStyle=function(){var d,b=$H();if(Prototype.Browser.WebKit){d=new Element("div",{style:this}).style}else{String.__parseStyleElement.innerHTML='<div style="'+this+'"></div>';d=String.__parseStyleElement.childNodes[0].style}Element.CSS_PROPERTIES.each(function(e){if(d[e]){b.set(e,d[e])}});if(Prototype.Browser.IE&&this.include("opacity")){b.set("opacity",this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1])}return b};if(document.defaultView&&document.defaultView.getComputedStyle){Element.getStyles=function(d){var b=document.defaultView.getComputedStyle($(d),null);return Element.CSS_PROPERTIES.inject({},function(e,f){e[f]=b[f];return e})}}else{Element.getStyles=function(d){d=$(d);var b=d.currentStyle,e;e=Element.CSS_PROPERTIES.inject({},function(f,g){f[g]=b[g];return f});if(!e.opacity){e.opacity=d.getOpacity()}return e}}Effect.Methods={morph:function(b,d){b=$(b);new Effect.Morph(b,Object.extend({style:d},arguments[2]||{}));return b},visualEffect:function(e,g,d){e=$(e);var f=g.dasherize().camelize(),b=f.charAt(0).toUpperCase()+f.substring(1);new Effect[b](e,d);return e},highlight:function(d,b){d=$(d);new Effect.Highlight(d,b);return d}};$w("fade appear grow shrink fold blindUp blindDown slideUp slideDown pulsate shake puff squish switchOff dropOut").each(function(b){Effect.Methods[b]=function(e,d){e=$(e);Effect[b.charAt(0).toUpperCase()+b.substring(1)](e,d);return e}});$w("getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles").each(function(b){Effect.Methods[b]=Element[b]});Element.addMethods(Effect.Methods);function validateCreditCard(e){var d="0123456789";var b="";for(i=0;i<e.length;i++){x=e.charAt(i);if(d.indexOf(x,0)!=-1){b+=x}}j=b.length/2;k=Math.floor(j);m=Math.ceil(j)-k;c=0;for(i=0;i<k;i++){a=b.charAt(i*2+m)*2;c+=a>9?Math.floor(a/10+a%10):a}for(i=0;i<k+m;i++){c+=b.charAt(i*2+1-m)*1}return(c%10==0)}var Validator=Class.create();Validator.prototype={initialize:function(e,d,f,b){if(typeof f=="function"){this.options=$H(b);this._test=f}else{this.options=$H(f);this._test=function(){return true}}this.error=d||"Validation failed.";this.className=e},test:function(b,d){return(this._test(b,d)&&this.options.all(function(e){return Validator.methods[e.key]?Validator.methods[e.key](b,d,e.value):true}))}};Validator.methods={pattern:function(b,e,d){return Validation.get("IsEmpty").test(b)||d.test(b)},minLength:function(b,e,d){return b.length>=d},maxLength:function(b,e,d){return b.length<=d},min:function(b,e,d){return b>=parseFloat(d)},max:function(b,e,d){return b<=parseFloat(d)},notOneOf:function(b,e,d){return $A(d).all(function(f){return b!=f})},oneOf:function(b,e,d){return $A(d).any(function(f){return b==f})},is:function(b,e,d){return b==d},isNot:function(b,e,d){return b!=d},equalToField:function(b,e,d){return b==$F(d)},notEqualToField:function(b,e,d){return b!=$F(d)},include:function(b,e,d){return $A(d).all(function(f){return Validation.get(f).test(b,e)})}};var Validation=Class.create();Validation.defaultOptions={onSubmit:true,stopOnFirst:false,immediate:false,focusOnError:true,useTitles:false,addClassNameToContainer:false,containerClassName:".input-box",onFormValidate:function(b,d){},onElementValidate:function(b,d){}};Validation.prototype={initialize:function(d,b){this.form=$(d);if(!this.form){return}this.options=Object.extend({onSubmit:Validation.defaultOptions.onSubmit,stopOnFirst:Validation.defaultOptions.stopOnFirst,immediate:Validation.defaultOptions.immediate,focusOnError:Validation.defaultOptions.focusOnError,useTitles:Validation.defaultOptions.useTitles,onFormValidate:Validation.defaultOptions.onFormValidate,onElementValidate:Validation.defaultOptions.onElementValidate},b||{});if(this.options.onSubmit){Event.observe(this.form,"submit",this.onSubmit.bind(this),false)}if(this.options.immediate){Form.getElements(this.form).each(function(e){if(e.tagName.toLowerCase()=="select"){Event.observe(e,"blur",this.onChange.bindAsEventListener(this))}if(e.type.toLowerCase()=="radio"||e.type.toLowerCase()=="checkbox"){Event.observe(e,"click",this.onChange.bindAsEventListener(this))}else{Event.observe(e,"change",this.onChange.bindAsEventListener(this))}},this)}},onChange:function(b){Validation.isOnChange=true;Validation.validate(Event.element(b),{useTitle:this.options.useTitles,onElementValidate:this.options.onElementValidate});Validation.isOnChange=false},onSubmit:function(b){if(!this.validate()){Event.stop(b)}},validate:function(){var b=false;var d=this.options.useTitles;var g=this.options.onElementValidate;try{if(this.options.stopOnFirst){b=Form.getElements(this.form).all(function(e){if(e.hasClassName("local-validation")&&!this.isElementInForm(e,this.form)){return true}return Validation.validate(e,{useTitle:d,onElementValidate:g})},this)}else{b=Form.getElements(this.form).collect(function(e){if(e.hasClassName("local-validation")&&!this.isElementInForm(e,this.form)){return true}if(e.hasClassName("validation-disabled")){return true}return Validation.validate(e,{useTitle:d,onElementValidate:g})},this).all()}}catch(f){}if(!b&&this.options.focusOnError){try{Form.getElements(this.form).findAll(function(e){return $(e).hasClassName("validation-failed")}).first().focus()}catch(f){}}this.options.onFormValidate(b,this.form);return b},reset:function(){Form.getElements(this.form).each(Validation.reset)},isElementInForm:function(e,d){var b=e.up("form");if(b==d){return true}return false}};Object.extend(Validation,{validate:function(e,b){b=Object.extend({useTitle:false,onElementValidate:function(f,g){}},b||{});e=$(e);var d=$w(e.className);return result=d.all(function(f){var g=Validation.test(f,e,b.useTitle);b.onElementValidate(g,e);return g})},insertAdvice:function(f,d){var b=$(f).up(".field-row");if(b){Element.insert(b,{after:d})}else{if(f.up("td.value")){f.up("td.value").insert({bottom:d})}else{if(f.advaiceContainer&&$(f.advaiceContainer)){$(f.advaiceContainer).update(d)}else{switch(f.type.toLowerCase()){case"checkbox":case"radio":var e=f.parentNode;if(e){Element.insert(e,{bottom:d})}else{Element.insert(f,{after:d})}break;default:Element.insert(f,{after:d})}}}}},showAdvice:function(e,d,b){if(!e.advices){e.advices=new Hash()}else{e.advices.each(function(f){if(!d||f.value.id!=d.id){this.hideAdvice(e,f.value)}}.bind(this))}e.advices.set(b,d);if(typeof Effect=="undefined"){d.style.display="block"}else{if(!d._adviceAbsolutize){new Effect.Appear(d,{duration:1})}else{Position.absolutize(d);d.show();d.setStyle({top:d._adviceTop,left:d._adviceLeft,width:d._adviceWidth,"z-index":1000});d.addClassName("advice-absolute")}}},hideAdvice:function(d,b){if(b!=null){new Effect.Fade(b,{duration:1,afterFinishInternal:function(){b.hide()}})}},updateCallback:function(elm,status){if(typeof elm.callbackFunction!="undefined"){eval(elm.callbackFunction+"('"+elm.id+"','"+status+"')")}},ajaxError:function(g,f){var e="validate-ajax";var d=Validation.getAdvice(e,g);if(d==null){d=this.createAdvice(e,g,false,f)}this.showAdvice(g,d,"validate-ajax");this.updateCallback(g,"failed");g.addClassName("validation-failed");g.addClassName("validate-ajax");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=g.up(Validation.defaultOptions.containerClassName);if(b&&this.allowContainerClassName(g)){b.removeClassName("validation-passed");b.addClassName("validation-error")}}},allowContainerClassName:function(b){if(b.type=="radio"||b.type=="checkbox"){return b.hasClassName("change-container-classname")}return true},test:function(g,o,l){var d=Validation.get(g);var n="__advice"+g.camelize();try{if(Validation.isVisible(o)&&!d.test($F(o),o)){var f=Validation.getAdvice(g,o);if(f==null){f=this.createAdvice(g,o,l)}this.showAdvice(o,f,g);this.updateCallback(o,"failed");o[n]=1;if(!o.advaiceContainer){o.removeClassName("validation-passed");o.addClassName("validation-failed")}if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=o.up(Validation.defaultOptions.containerClassName);if(b&&this.allowContainerClassName(o)){b.removeClassName("validation-passed");b.addClassName("validation-error")}}return false}else{var f=Validation.getAdvice(g,o);this.hideAdvice(o,f);this.updateCallback(o,"passed");o[n]="";o.removeClassName("validation-failed");o.addClassName("validation-passed");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=o.up(Validation.defaultOptions.containerClassName);if(b&&!b.down(".validation-failed")&&this.allowContainerClassName(o)){if(!Validation.get("IsEmpty").test(o.value)||!this.isVisible(o)){b.addClassName("validation-passed")}else{b.removeClassName("validation-passed")}b.removeClassName("validation-error")}}return true}}catch(h){throw (h)}},isVisible:function(b){while(b.tagName!="BODY"){if(!$(b).visible()){return false}b=b.parentNode}return true},getAdvice:function(b,d){return $("advice-"+b+"-"+Validation.getElmID(d))||$("advice-"+Validation.getElmID(d))},createAdvice:function(e,n,l,d){var b=Validation.get(e);var h=l?((n&&n.title)?n.title:b.error):b.error;if(d){h=d}if(jQuery.mage.__){h=jQuery.mage.__(h)}advice='<div class="validation-advice" id="advice-'+e+"-"+Validation.getElmID(n)+'" style="display:none">'+h+"</div>";Validation.insertAdvice(n,advice);advice=Validation.getAdvice(e,n);if($(n).hasClassName("absolute-advice")){var g=$(n).getDimensions();var f=Position.cumulativeOffset(n);advice._adviceTop=(f[1]+g.height)+"px";advice._adviceLeft=(f[0])+"px";advice._adviceWidth=(g.width)+"px";advice._adviceAbsolutize=true}return advice},getElmID:function(b){return b.id?b.id:b.name},reset:function(d){d=$(d);var b=$w(d.className);b.each(function(g){var h="__advice"+g.camelize();if(d[h]){var f=Validation.getAdvice(g,d);if(f){f.hide()}d[h]=""}d.removeClassName("validation-failed");d.removeClassName("validation-passed");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var e=d.up(Validation.defaultOptions.containerClassName);if(e){e.removeClassName("validation-passed");e.removeClassName("validation-error")}}})},add:function(f,e,g,d){var b={};b[f]=new Validator(f,e,g,d);Object.extend(Validation.methods,b)},addAllThese:function(b){var d={};$A(b).each(function(e){d[e[0]]=new Validator(e[0],e[1],e[2],(e.length>3?e[3]:{}))});Object.extend(Validation.methods,d)},get:function(b){return Validation.methods[b]?Validation.methods[b]:Validation.methods._LikeNoIDIEverSaw_},methods:{_LikeNoIDIEverSaw_:new Validator("_LikeNoIDIEverSaw_","",{})}});Validation.add("IsEmpty","",function(b){return(b==""||(b==null)||(b.length==0)||/^\s+$/.test(b))});Validation.addAllThese([["validate-no-html-tags","HTML tags are not allowed",function(b){return !/<(\/)?\w+/.test(b)}],["validate-select","Please select an option.",function(b){return((b!="none")&&(b!=null)&&(b.length!=0))}],["required-entry","This is a required field.",function(b){return !Validation.get("IsEmpty").test(b)}],["validate-number","Please enter a valid number in this field.",function(b){return Validation.get("IsEmpty").test(b)||(!isNaN(parseNumber(b))&&/^\s*-?\d*(\.\d*)?\s*$/.test(b))}],["validate-number-range","The value is not within the specified range.",function(e,g){if(Validation.get("IsEmpty").test(e)){return true}var f=parseNumber(e);if(isNaN(f)){return false}var d=/^number-range-(-?[\d.,]+)?-(-?[\d.,]+)?$/,b=true;$w(g.className).each(function(l){var h=d.exec(l);if(h){b=b&&(h[1]==null||h[1]==""||f>=parseNumber(h[1]))&&(h[2]==null||h[2]==""||f<=parseNumber(h[2]))}});return b}],["validate-digits","Please use numbers only in this field. Please avoid spaces or other characters such as dots or commas.",function(b){return Validation.get("IsEmpty").test(b)||!/[^\d]/.test(b)}],["validate-digits-range","The value is not within the specified range.",function(e,g){if(Validation.get("IsEmpty").test(e)){return true}var f=parseNumber(e);if(isNaN(f)){return false}var d=/^digits-range-(-?\d+)?-(-?\d+)?$/,b=true;$w(g.className).each(function(l){var h=d.exec(l);if(h){b=b&&(h[1]==null||h[1]==""||f>=parseNumber(h[1]))&&(h[2]==null||h[2]==""||f<=parseNumber(h[2]))}});return b}],["validate-range","The value is not within the specified range.",function(f,l){var g,h;if(Validation.get("IsEmpty").test(f)){return true}else{if(Validation.get("validate-digits").test(f)){g=h=parseNumber(f)}else{var e=/^(-?\d+)?-(-?\d+)?$/.exec(f);if(e){g=parseNumber(e[1]);h=parseNumber(e[2]);if(g>h){return false}}else{return false}}}var d=/^range-(-?\d+)?-(-?\d+)?$/,b=true;$w(l.className).each(function(n){var q=d.exec(n);if(q){var p=parseNumber(q[1]);var o=parseNumber(q[2]);b=b&&(isNaN(p)||g>=p)&&(isNaN(o)||h<=o)}});return b}],["validate-alpha","Please use letters only (a-z or A-Z) in this field.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z]+$/.test(b)}],["validate-code","Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-z]+[a-z0-9_]+$/.test(b)}],["validate-alphanum","Please use only letters (a-z or A-Z) or numbers (0-9) only in this field. No spaces or other characters are allowed.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z0-9]+$/.test(b)}],["validate-alphanum-with-spaces","Please use only letters (a-z or A-Z), numbers (0-9) or spaces only in this field.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z0-9 ]+$/.test(b)}],["validate-street","Please use only letters (a-z or A-Z) or numbers (0-9) or spaces and # only in this field.",function(b){return Validation.get("IsEmpty").test(b)||/^[ \w]{3,}([A-Za-z]\.)?([ \w]*\#\d+)?(\r\n| )[ \w]{3,}/.test(b)}],["validate-phoneStrict","Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.",function(b){return Validation.get("IsEmpty").test(b)||/^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(b)}],["validate-phoneLax","Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.",function(b){return Validation.get("IsEmpty").test(b)||/^((\d[-. ]?)?((\(\d{3}\))|\d{3}))?[-. ]?\d{3}[-. ]?\d{4}$/.test(b)}],["validate-fax","Please enter a valid fax number. For example (123) 456-7890 or 123-456-7890.",function(b){return Validation.get("IsEmpty").test(b)||/^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(b)}],["validate-date","Please enter a valid date.",function(b){var d=new Date(b);return Validation.get("IsEmpty").test(b)||!isNaN(d)}],["validate-date-range","The From Date value should be less than or equal to the To Date value.",function(e,h){var d=/\bdate-range-(\w+)-(\w+)\b/.exec(h.className);if(!d||d[2]=="to"||Validation.get("IsEmpty").test(e)){return true}var f=new Date().getFullYear()+"";var b=function(l){l=l.split(/[.\/]/);if(l[2]&&l[2].length<4){l[2]=f.substr(0,l[2].length)+l[2]}return new Date(l.join("/")).getTime()};var g=Element.select(h.form,".validate-date-range.date-range-"+d[1]+"-to");return !g.length||Validation.get("IsEmpty").test(g[0].value)||b(e)<=b(g[0].value)}],["validate-email","Please enter a valid email address. For example johndoe@domain.com.",function(b){return Validation.get("IsEmpty").test(b)||/^([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*@([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*\.(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]){2,})$/i.test(b)}],["validate-emailSender","Please use only visible characters and spaces.",function(b){return Validation.get("IsEmpty").test(b)||/^[\S ]+$/.test(b)}],["validate-password","Please enter 6 or more characters. Leading or trailing spaces will be ignored.",function(b){var d=b.strip();return !(d.length>0&&d.length<6)}],["validate-admin-password","Please enter 7 or more characters. Password should contain both numeric and alphabetic characters.",function(b){var d=b.strip();if(0==d.length){return true}if(!(/[a-z]/i.test(b))||!(/[0-9]/.test(b))){return false}return !(d.length<7)}],["validate-cpassword","Please make sure your passwords match.",function(b){var d=$("confirmation")?$("confirmation"):$$(".validate-cpassword")[0];var g=false;if($("password")){g=$("password")}var h=$$(".validate-password");for(var e=0;e<h.size();e++){var f=h[e];if(f.up("form").id==d.up("form").id){g=f}}if($$(".validate-admin-password").size()){g=$$(".validate-admin-password")[0]}return(g.value==d.value)}],["validate-both-passwords","Please make sure your passwords match.",function(e,d){var b=$(d.form[d.name=="password"?"confirmation":"password"]),f=d.value==b.value;if(f&&b.hasClassName("validation-failed")){Validation.test(this.className,b)}return b.value==""||f}],["validate-url","Please enter a valid URL. Protocol is required (http://, https:// or ftp://)",function(b){b=(b||"").replace(/^\s+/,"").replace(/\s+$/,"");return Validation.get("IsEmpty").test(b)||/^(http|https|ftp):\/\/(([A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))(\.[A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))*)(:(\d+))?(\/[A-Z0-9~](([A-Z0-9_~-]|\.)*[A-Z0-9~]|))*\/?(.*)?$/i.test(b)}],["validate-clean-url","Please enter a valid URL. For example http://www.example.com or www.example.com",function(b){return Validation.get("IsEmpty").test(b)||/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(b)||/^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(b)}],["validate-identifier",'Please enter a valid URL Key. For example "example-page", "example-page.html" or "anotherlevel/example-page".',function(b){return Validation.get("IsEmpty").test(b)||/^[a-z0-9][a-z0-9_\/-]+(\.[a-z0-9_-]+)?$/.test(b)}],["validate-xml-identifier","Please enter a valid XML-identifier. For example something_1, block5, id-4.",function(b){return Validation.get("IsEmpty").test(b)||/^[A-Z][A-Z0-9_\/-]*$/i.test(b)}],["validate-ssn","Please enter a valid social security number. For example 123-45-6789.",function(b){return Validation.get("IsEmpty").test(b)||/^\d{3}-?\d{2}-?\d{4}$/.test(b)}],["validate-zip-us","Please enter a valid zip code. For example 90602 or 90602-1234.",function(b){return Validation.get("IsEmpty").test(b)||/(^\d{5}$)|(^\d{5}-\d{4}$)/.test(b)}],["validate-zip-international","Please enter a valid zip code.",function(b){return true}],["validate-date-au","Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.",function(b){if(Validation.get("IsEmpty").test(b)){return true}var e=/^(\d{2})\/(\d{2})\/(\d{4})$/;if(!e.test(b)){return false}var f=new Date(b.replace(e,"$2/$1/$3"));return(parseInt(RegExp.$2,10)==(1+f.getMonth()))&&(parseInt(RegExp.$1,10)==f.getDate())&&(parseInt(RegExp.$3,10)==f.getFullYear())}],["validate-currency-dollar","Please enter a valid $ amount. For example $100.00.",function(b){return Validation.get("IsEmpty").test(b)||/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(b)}],["validate-one-required","Please select one of the above options.",function(b,f){var e=f.parentNode;var d=e.getElementsByTagName("INPUT");return $A(d).any(function(g){return $F(g)})}],["validate-one-required-by-name","Please select one of the options.",function(d,g){var b=$$('input[name="'+g.name.replace(/([\\"])/g,"\\$1")+'"]');var e=1;for(var f=0;f<b.length;f++){if((b[f].type=="checkbox"||b[f].type=="radio")&&b[f].checked==true){e=0}if(Validation.isOnChange&&(b[f].type=="checkbox"||b[f].type=="radio")){Validation.reset(b[f])}}if(e==0){return true}else{return false}}],["validate-not-negative-number","Please enter a number 0 or greater in this field.",function(b){if(Validation.get("IsEmpty").test(b)){return true}b=parseNumber(b);return !isNaN(b)&&b>=0}],["validate-zero-or-greater","Please enter a number 0 or greater in this field.",function(b){return Validation.get("validate-not-negative-number").test(b)}],["validate-greater-than-zero","Please enter a number greater than 0 in this field.",function(b){if(Validation.get("IsEmpty").test(b)){return true}b=parseNumber(b);return !isNaN(b)&&b>0}],["validate-state","Please select State/Province.",function(b){return(b!=0||b=="")}],["validate-new-password","Please enter 6 or more characters. Leading or trailing spaces will be ignored.",function(b){if(!Validation.get("validate-password").test(b)){return false}if(Validation.get("IsEmpty").test(b)&&b!=""){return false}return true}],["validate-cc-number","Please enter a valid credit card number.",function(b,e){var d=$(e.id.substr(0,e.id.indexOf("_cc_number"))+"_cc_type");if(d&&typeof Validation.creditCartTypes.get(d.value)!="undefined"&&Validation.creditCartTypes.get(d.value)[2]==false){if(!Validation.get("IsEmpty").test(b)&&Validation.get("validate-digits").test(b)){return true}else{return false}}return validateCreditCard(b)}],["validate-cc-type","Credit card number does not match credit card type.",function(d,g){g.value=removeDelimiters(g.value);d=removeDelimiters(d);var f=$(g.id.substr(0,g.id.indexOf("_cc_number"))+"_cc_type");if(!f){return true}var e=f.value;if(typeof Validation.creditCartTypes.get(e)=="undefined"){return false}if(Validation.creditCartTypes.get(e)[0]==false){return true}var b="";Validation.creditCartTypes.each(function(h){if(h.value[0]&&d.match(h.value[0])){b=h.key;throw $break}});if(b!=e){return false}if(f.hasClassName("validation-failed")&&Validation.isOnChange){Validation.validate(f)}return true}],["validate-cc-type-select","Card type does not match credit card number.",function(d,e){var b=$(e.id.substr(0,e.id.indexOf("_cc_type"))+"_cc_number");if(Validation.isOnChange&&Validation.get("IsEmpty").test(b.value)){return true}if(Validation.get("validate-cc-type").test(b.value,b)){Validation.validate(b)}return Validation.get("validate-cc-type").test(b.value,b)}],["validate-cc-exp","Incorrect credit card expiration date.",function(b,l){var h=b;var g=$(l.id.substr(0,l.id.indexOf("_expiration"))+"_expiration_yr").value;var f=new Date();var e=f.getMonth()+1;var d=f.getFullYear();if(h<e&&g==d){return false}return true}],["validate-cc-cvn","Please enter a valid credit card verification number.",function(b,g){var f=$(g.id.substr(0,g.id.indexOf("_cc_cid"))+"_cc_type");if(!f){return true}var d=f.value;if(typeof Validation.creditCartTypes.get(d)=="undefined"){return false}var e=Validation.creditCartTypes.get(d)[1];if(b.match(e)){return true}return false}],["validate-ajax","",function(b,d){return true}],["validate-data","Please use only letters (a-z or A-Z), numbers (0-9) or underscore(_) in this field, first character should be a letter.",function(b){if(b!=""&&b){return/^[A-Za-z]+[A-Za-z0-9_]+$/.test(b)}return true}],["validate-css-length","Please input a valid CSS-length. For example 100px or 77pt or 20em or .5ex or 50%.",function(b){if(b!=""&&b){return/^[0-9\.]+(px|pt|em|ex|%)?$/.test(b)&&(!(/\..*\./.test(b)))&&!(/\.$/.test(b))}return true}],["validate-length","Text length does not satisfy specified text range.",function(d,g){var e=new RegExp(/^maximum-length-[0-9]+$/);var f=new RegExp(/^minimum-length-[0-9]+$/);var b=true;$w(g.className).each(function(l,h){if(l.match(e)&&b){var n=l.split("-")[2];b=(d.length<=n)}if(l.match(f)&&b&&!Validation.get("IsEmpty").test(d)){var n=l.split("-")[2];b=(d.length>=n)}});return b}],["validate-percents","Please enter a number lower than 100.",{max:100}],["required-file","Please select a file",function(d,e){var b=!Validation.get("IsEmpty").test(d);if(b===false){ovId=e.id+"_value";if($(ovId)){b=!Validation.get("IsEmpty").test($(ovId).value)}}return b}],["validate-cc-ukss","Please enter issue number or start date for switch/solo card type.",function(o,g){var b;if(g.id.match(/(.)+_cc_issue$/)){b=g.id.indexOf("_cc_issue")}else{if(g.id.match(/(.)+_start_month$/)){b=g.id.indexOf("_start_month")}else{b=g.id.indexOf("_start_year")}}var f=g.id.substr(0,b);var d=$(f+"_cc_type");if(!d){return true}var n=d.value;if(["SS","SM","SO"].indexOf(n)==-1){return true}$(f+"_cc_issue").advaiceContainer=$(f+"_start_month").advaiceContainer=$(f+"_start_year").advaiceContainer=$(f+"_cc_type_ss_div").down(".adv-container");var h=$(f+"_cc_issue").value;var l=$(f+"_start_month").value;var p=$(f+"_start_year").value;var e=(l&&p)?true:false;if(!e&&!h){return false}return true}]]);function removeDelimiters(b){b=b.replace(/\s/g,"");b=b.replace(/\-/g,"");return b}function parseNumber(b){if(typeof b!="string"){return parseFloat(b)}var e=b.indexOf(".");var d=b.indexOf(",");if(e!=-1&&d!=-1){if(d>e){b=b.replace(".","").replace(",",".")}else{b=b.replace(",","")}}else{if(d!=-1){b=b.replace(",",".")}}return parseFloat(b)}Validation.creditCartTypes=$H({SO:[new RegExp("^(6334[5-9]([0-9]{11}|[0-9]{13,14}))|(6767([0-9]{12}|[0-9]{14,15}))$"),new RegExp("^([0-9]{3}|[0-9]{4})?$"),true],SM:[new RegExp("(^(5[0678])[0-9]{11,18}$)|(^(6[^05])[0-9]{11,18}$)|(^(601)[^1][0-9]{9,16}$)|(^(6011)[0-9]{9,11}$)|(^(6011)[0-9]{13,16}$)|(^(65)[0-9]{11,13}$)|(^(65)[0-9]{15,18}$)|(^(49030)[2-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49033)[5-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49110)[1-2]([0-9]{10}$|[0-9]{12,13}$))|(^(49117)[4-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49118)[0-2]([0-9]{10}$|[0-9]{12,13}$))|(^(4936)([0-9]{12}$|[0-9]{14,15}$))"),new RegExp("^([0-9]{3}|[0-9]{4})?$"),true],VI:[new RegExp("^4[0-9]{12}([0-9]{3})?$"),new RegExp("^[0-9]{3}$"),true],MC:[new RegExp("^5[1-5][0-9]{14}$"),new RegExp("^[0-9]{3}$"),true],AE:[new RegExp("^3[47][0-9]{13}$"),new RegExp("^[0-9]{4}$"),true],DI:[new RegExp("^6(011|4[4-9][0-9]|5[0-9]{2})[0-9]{12}$"),new RegExp("^[0-9]{3}$"),true],JCB:[new RegExp("^(3[0-9]{15}|(2131|1800)[0-9]{11})$"),new RegExp("^[0-9]{3,4}$"),true],OT:[false,new RegExp("^([0-9]{3}|[0-9]{4})?$"),false]});function popWin(d,e,b){var e=window.open(d,e,b);e.focus()}function setLocation(b){window.location.href=b}function setPLocation(d,b){if(b){window.opener.focus()}window.opener.location.href=d}function setLanguageCode(e,f){var b=window.location.href;var h="",g;if(g=b.match(/\#(.*)$/)){b=b.replace(/\#(.*)$/,"");h=g[0]}if(b.match(/[?]/)){var d=/([?&]store=)[a-z0-9_]*/;if(b.match(d)){b=b.replace(d,"$1"+e)}else{b+="&store="+e}var d=/([?&]from_store=)[a-z0-9_]*/;if(b.match(d)){b=b.replace(d,"")}}else{b+="?store="+e}if(typeof(f)!="undefined"){b+="&from_store="+f}b+=h;setLocation(b)}function decorateGeneric(h,e){var l=["odd","even","first","last"];var d={};var g=h.length;if(g){if(typeof(e)=="undefined"){e=l}if(!e.length){return}for(var b in l){d[l[b]]=false}for(var b in e){d[e[b]]=true}if(d.first){Element.addClassName(h[0],"first")}if(d.last){Element.addClassName(h[g-1],"last")}for(var f=0;f<g;f++){if((f+1)%2==0){if(d.even){Element.addClassName(h[f],"even")}}else{if(d.odd){Element.addClassName(h[f],"odd")}}}}}function decorateTable(h,e){var h=$(h);if(h){var b={tbody:false,"tbody tr":["odd","even","first","last"],"thead tr":["first","last"],"tfoot tr":["first","last"],"tr td":["last"]};if(typeof(e)!="undefined"){for(var d in e){b[d]=e[d]}}if(b.tbody){decorateGeneric(h.select("tbody"),b.tbody)}if(b["tbody tr"]){decorateGeneric(h.select("tbody tr"),b["tbody tr"])}if(b["thead tr"]){decorateGeneric(h.select("thead tr"),b["thead tr"])}if(b["tfoot tr"]){decorateGeneric(h.select("tfoot tr"),b["tfoot tr"])}if(b["tr td"]){var g=h.select("tr");if(g.length){for(var f=0;f<g.length;f++){decorateGeneric(g[f].getElementsByTagName("TD"),b["tr td"])}}}}}function decorateList(e,d){if($(e)){if(typeof(d)=="undefined"){var b=$(e).select("li")}else{var b=$(e).childElements()}decorateGeneric(b,["odd","even","last"])}}function decorateDataList(b){b=$(b);if(b){decorateGeneric(b.select("dt"),["odd","even","last"]);decorateGeneric(b.select("dd"),["odd","even","last"])}}function parseSidUrl(f,e){var d=f.indexOf("/?SID=");var b="";e=(e!=undefined)?e:"";if(d>-1){b="?"+f.substring(d+2);f=f.substring(0,d+1)}return f+e+b}function formatCurrency(n,q,g){var l=isNaN(q.precision=Math.abs(q.precision))?2:q.precision;var v=isNaN(q.requiredPrecision=Math.abs(q.requiredPrecision))?2:q.requiredPrecision;l=v;var t=isNaN(q.integerRequired=Math.abs(q.integerRequired))?1:q.integerRequired;var p=q.decimalSymbol==undefined?",":q.decimalSymbol;var e=q.groupSymbol==undefined?".":q.groupSymbol;var d=q.groupLength==undefined?3:q.groupLength;var u="";if(g==undefined||g==true){u=n<0?"-":(g?"+":"")}else{if(g==false){u=""}}var h=parseInt(n=Math.abs(+n||0).toFixed(l))+"";var f=(h.length<t)?(t-h.length):0;while(f){h="0"+h;f--}j=(j=h.length)>d?j%d:0;re=new RegExp("(\\d{"+d+"})(?=\\d)","g");var b=(j?h.substr(0,j)+e:"")+h.substr(j).replace(re,"$1"+e)+(l?p+Math.abs(n-h).toFixed(l).replace(/-/,0).slice(2):"");var o="";if(q.pattern.indexOf("{sign}")==-1){o=u+q.pattern}else{o=q.pattern.replace("{sign}",u)}return o.replace("%s",b).replace(/^\s\s*/,"").replace(/\s\s*$/,"")}function expandDetails(d,b){if(Element.hasClassName(d,"show-details")){$$(b).each(function(e){e.hide()});Element.removeClassName(d,"show-details")}else{$$(b).each(function(e){e.show()});Element.addClassName(d,"show-details")}}var isIE=navigator.appVersion.match(/MSIE/)=="MSIE";if(!window.Varien){var Varien=new Object()}Varien.showLoading=function(){var b=$("loading-process");b&&b.show()};Varien.hideLoading=function(){var b=$("loading-process");b&&b.hide()};Varien.GlobalHandlers={onCreate:function(){Varien.showLoading()},onComplete:function(){if(Ajax.activeRequestCount==0){Varien.hideLoading()}}};Ajax.Responders.register(Varien.GlobalHandlers);Varien.searchForm=Class.create();Varien.searchForm.prototype={initialize:function(d,e,b){this.form=$(d);this.field=$(e);this.emptyText=b;Event.observe(this.form,"submit",this.submit.bind(this));Event.observe(this.field,"focus",this.focus.bind(this));Event.observe(this.field,"blur",this.blur.bind(this));this.blur()},submit:function(b){if(this.field.value==this.emptyText||this.field.value==""){Event.stop(b);return false}return true},focus:function(b){if(this.field.value==this.emptyText){this.field.value=""}},blur:function(b){if(this.field.value==""){this.field.value=this.emptyText}}};Varien.DateElement=Class.create();Varien.DateElement.prototype={initialize:function(b,d,f,e){if(b=="id"){this.day=$(d+"day");this.month=$(d+"month");this.year=$(d+"year");this.full=$(d+"full");this.advice=$(d+"date-advice")}else{if(b=="container"){this.day=d.day;this.month=d.month;this.year=d.year;this.full=d.full;this.advice=d.advice}else{return}}this.required=f;this.format=e;this.day.addClassName("validate-custom");this.day.validate=this.validate.bind(this);this.month.addClassName("validate-custom");this.month.validate=this.validate.bind(this);this.year.addClassName("validate-custom");this.year.validate=this.validate.bind(this);this.setDateRange(false,false);this.year.setAttribute("autocomplete","off");this.advice.hide()},validate:function(){var l=false,o=parseInt(this.day.value,10)||0,f=parseInt(this.month.value,10)||0,h=parseInt(this.year.value,10)||0;if(this.day.value.strip().empty()&&this.month.value.strip().empty()&&this.year.value.strip().empty()){if(this.required){l="This date is a required value."}else{this.full.value=""}}else{if(!o||!f||!h){l="Please enter a valid full date."}else{var d=new Date,n=0,e=null;d.setYear(h);d.setMonth(f-1);d.setDate(32);n=32-d.getDate();if(!n||n>31){n=31}if(o<1||o>n){e="day";l="Please enter a valid day (1-%1)."}else{if(f<1||f>12){e="month";l="Please enter a valid month (1-12)."}else{if(o%10==o){this.day.value="0"+o}if(f%10==f){this.month.value="0"+f}this.full.value=this.format.replace(/%[mb]/i,this.month.value).replace(/%[de]/i,this.day.value).replace(/%y/i,this.year.value);var b=this.month.value+"/"+this.day.value+"/"+this.year.value;var g=new Date(b);if(isNaN(g)){l="Please enter a valid date."}else{this.setFullDate(g)}}}var p=false;if(!l&&!this.validateData()){e=this.validateDataErrorType;p=this.validateDataErrorText;l=p}}}if(l!==false){if(jQuery.mage.__){l=jQuery.mage.__(l)}if(!p){this.advice.innerHTML=l.replace("%1",n)}else{this.advice.innerHTML=this.errorTextModifier(l)}this.advice.show();return false}this.day.removeClassName("validation-failed");this.month.removeClassName("validation-failed");this.year.removeClassName("validation-failed");this.advice.hide();return true},validateData:function(){var d=this.fullDate.getFullYear();var b=new Date;this.curyear=b.getFullYear();return(d>=1900&&d<=this.curyear)},validateDataErrorType:"year",validateDataErrorText:"Please enter a valid year (1900-%1).",errorTextModifier:function(b){return b.replace("%1",this.curyear)},setDateRange:function(b,d){this.minDate=b;this.maxDate=d},setFullDate:function(b){this.fullDate=b}};Varien.DOB=Class.create();Varien.DOB.prototype={initialize:function(b,g,f){var e=$$(b)[0];var d={};d.day=Element.select(e,".dob-day input")[0];d.month=Element.select(e,".dob-month input")[0];d.year=Element.select(e,".dob-year input")[0];d.full=Element.select(e,".dob-full input")[0];d.advice=Element.select(e,".validation-advice")[0];new Varien.DateElement("container",d,g,f)}};Varien.dateRangeDate=Class.create();Varien.dateRangeDate.prototype=Object.extend(new Varien.DateElement(),{validateData:function(){var b=true;if(this.minDate||this.maxValue){if(this.minDate){this.minDate=new Date(this.minDate);this.minDate.setHours(0);if(isNaN(this.minDate)){this.minDate=new Date("1/1/1900")}b=b&&(this.fullDate>=this.minDate)}if(this.maxDate){this.maxDate=new Date(this.maxDate);this.minDate.setHours(0);if(isNaN(this.maxDate)){this.maxDate=new Date()}b=b&&(this.fullDate<=this.maxDate)}if(this.maxDate&&this.minDate){this.validateDataErrorText="Please enter a valid date between %s and %s"}else{if(this.maxDate){this.validateDataErrorText="Please enter a valid date less than or equal to %s"}else{if(this.minDate){this.validateDataErrorText="Please enter a valid date equal to or greater than %s"}else{this.validateDataErrorText=""}}}}return b},validateDataErrorText:"Date should be between %s and %s",errorTextModifier:function(b){if(this.minDate){b=b.sub("%s",this.dateFormat(this.minDate))}if(this.maxDate){b=b.sub("%s",this.dateFormat(this.maxDate))}return b},dateFormat:function(b){return(b.getMonth()+1)+"/"+b.getDate()+"/"+b.getFullYear()}});Varien.FileElement=Class.create();Varien.FileElement.prototype={initialize:function(b){this.fileElement=$(b);this.hiddenElement=$(b+"_value");this.fileElement.observe("change",this.selectFile.bind(this))},selectFile:function(b){this.hiddenElement.value=this.fileElement.getValue()}};Validation.addAllThese([["validate-custom"," ",function(b,d){return d.validate()}]]);Element.addMethods({getInnerText:function(b){b=$(b);if(b.innerText&&!Prototype.Browser.Opera){return b.innerText}return b.innerHTML.stripScripts().unescapeHTML().replace(/[\n\r\s]+/g," ").strip()}});function fireEvent(d,e){if(document.createEvent){var b=document.createEvent("HTMLEvents");b.initEvent(e,true,true);return d.dispatchEvent(b)}else{var b=document.createEventObject();return d.fireEvent("on"+e,b)}}function modulo(b,f){var e=f/10000;var d=b%f;if(Math.abs(d-f)<e||Math.abs(d)<e){d=0}return d}if((typeof Range!="undefined")&&!Range.prototype.createContextualFragment){Range.prototype.createContextualFragment=function(b){var e=document.createDocumentFragment(),d=document.createElement("div");e.appendChild(d);d.outerHTML=b;return e}}var byteConvert=function(b){if(isNaN(b)){return""}var d=["bytes","KB","MB","GB","TB","PB","EB","ZB","YB"];var f=Math.floor(Math.log(b)/Math.log(2));if(f<1){f=0}var e=Math.floor(f/10);b=b/Math.pow(2,10*e);if(b.toString().length>b.toFixed(2).toString().length){b=b.toFixed(2)}return b+" "+d[e]};var SessionError=Class.create();SessionError.prototype={initialize:function(b){this.errorText=b},toString:function(){return"Session Error:"+this.errorText}};Ajax.Request.addMethods({initialize:function($super,d,b){$super(b);this.transport=Ajax.getTransport();if(!d.match(new RegExp("[?&]isAjax=true",""))){d=d.match(new RegExp("\\?","g"))?d+"&isAjax=true":d+"?isAjax=true"}if(Object.isString(this.options.parameters)&&this.options.parameters.indexOf("form_key=")==-1){this.options.parameters+="&"+Object.toQueryString({form_key:FORM_KEY})}else{if(!this.options.parameters){this.options.parameters={form_key:FORM_KEY}}if(!this.options.parameters.form_key){this.options.parameters.form_key=FORM_KEY}}this.request(d)},respondToReadyState:function(b){var g=Ajax.Request.Events[b],d=new Ajax.Response(this);if(g=="Complete"){try{this._complete=true;if(d.responseText.isJSON()){var f=d.responseText.evalJSON();if(f.ajaxExpired&&f.ajaxRedirect){window.location.replace(f.ajaxRedirect);throw new SessionError("session expired")}}(this.options["on"+d.status]||this.options["on"+(this.success()?"Success":"Failure")]||Prototype.emptyFunction)(d,d.headerJSON)}catch(h){this.dispatchException(h);if(h instanceof SessionError){return}}var l=d.getHeader("Content-type");if(this.options.evalJS=="force"||(this.options.evalJS&&this.isSameOrigin()&&l&&l.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))){this.evalResponse()}}try{(this.options["on"+g]||Prototype.emptyFunction)(d,d.headerJSON);Ajax.Responders.dispatch("on"+g,this,d,d.headerJSON)}catch(h){this.dispatchException(h)}if(g=="Complete"){this.transport.onreadystatechange=Prototype.emptyFunction}}});Ajax.Updater.respondToReadyState=Ajax.Request.respondToReadyState;var varienLoader=new Class.create();varienLoader.prototype={initialize:function(b){this.callback=false;this.cache=$H();this.caching=b||false;this.url=false},getCache:function(b){if(this.cache.get(b)){return this.cache.get(b)}return false},load:function(b,d,f){this.url=b;this.callback=f;if(this.caching){var e=this.getCache(b);if(e){this.processResult(e);return}}if(typeof(d.updaterId)!="undefined"){new varienUpdater(d.updaterId,b,{evalScripts:true,onComplete:this.processResult.bind(this),onFailure:this._processFailure.bind(this)})}else{new Ajax.Request(b,{method:"post",parameters:d||{},onComplete:this.processResult.bind(this),onFailure:this._processFailure.bind(this)})}},_processFailure:function(b){location.href=BASE_URL},processResult:function(b){if(this.caching){this.cache.set(this.url,b)}if(this.callback){this.callback(b.responseText)}}};if(!window.varienLoaderHandler){var varienLoaderHandler=new Object()}varienLoaderHandler.handler={onCreate:function(b){if(b.options.loaderArea===false){return}jQuery("body").trigger("processStart")},onException:function(b){jQuery("body").trigger("processStop")},onComplete:function(b){jQuery("body").trigger("processStop")}};function setLoaderPosition(){var e=$("loading_mask_loader");if(e&&Prototype.Browser.IE){var d=e.getDimensions();var f=document.viewport.getDimensions();var b=document.viewport.getScrollOffsets();e.style.left=Math.floor(f.width/2+b.left-d.width/2)+"px";e.style.top=Math.floor(f.height/2+b.top-d.height/2)+"px";e.style.position="absolute"}}function toggleSelectsUnderBlock(f,b){if(Prototype.Browser.IE){var e=document.getElementsByTagName("select");for(var d=0;d<e.length;d++){if(b){if(e[d].needShowOnSuccess){e[d].needShowOnSuccess=false;e[d].style.visibility=""}}else{if(Element.visible(e[d])){e[d].style.visibility="hidden";e[d].needShowOnSuccess=true}}}}}Ajax.Responders.register(varienLoaderHandler.handler);var varienUpdater=Class.create(Ajax.Updater,{updateContent:function($super,b){if(b.isJSON()){var d=b.evalJSON();if(d.ajaxExpired&&d.ajaxRedirect){window.location.replace(d.ajaxRedirect)}}else{$super(b)}}});function setLocation(b){window.location.href=b}function confirmSetLocation(d,b){if(confirm(d)){setLocation(b)}return false}function deleteConfirm(d,b){confirmSetLocation(d,b)}function setElementDisable(d,b){if($(d)){$(d).disabled=b}}function toggleParentVis(b){b=$(b).parentNode;if(b.style.display=="none"){b.style.display=""}else{b.style.display="none"}}function toggleFieldsetVis(d){id=d;d=$(d);if(d.style.display=="none"){d.style.display=""}else{d.style.display="none"}d=d.parentNode.childElements();for(var b=0;b<d.length;b++){if(d[b].id!=undefined&&d[b].id==id&&d[(b-1)].classNames()=="entry-edit-head"){if(d[b-1].style.display=="none"){d[b-1].style.display=""}else{d[b-1].style.display="none"}}}}function toggleVis(b){b=$(b);if(b.style.display=="none"){b.style.display=""}else{b.style.display="none"}}function imagePreview(b){if($(b)){var d=window.open("","preview","width=400,height=400,resizable=1,scrollbars=1");d.document.open();d.document.write('<body style="padding:0;margin:0"><img src="'+$(b).src+'" id="image_preview"/></body>');d.document.close();Event.observe(d,"load",function(){var e=d.document.getElementById("image_preview");d.resizeTo(e.width+40,e.height+80)})}}function checkByProductPriceType(b){if(b.id=="price_type"){this.productPriceType=b.value;return false}else{if(b.id=="price"&&this.productPriceType==0){return false}return true}}Event.observe(window,"load",function(){if($("price_default")&&$("price_default").checked){$("price").disabled="disabled"}});function toggleSeveralValueElements(f,e,b,d){if(e&&f){if(Object.prototype.toString.call(e)!="[object Array]"){e=[e]}e.each(function(g){toggleValueElements(f,g,b,d)})}}function toggleValueElements(l,d,f,h){if(d&&l){var n=[l];if(typeof f!="undefined"){if(Object.prototype.toString.call(f)!="[object Array]"){f=[f]}for(var g=0;g<f.length;g++){n.push(f[g])}}var e=Element.select(d,["select","input","textarea","button","img"]).filter(function(o){return(o.readAttribute("type")!="hidden")});var b=(h!=undefined?h:l.checked);e.each(function(p){if(checkByProductPriceType(p)){var o=n.length;while(o--&&p!=n[o]){}if(o!=-1){return}p.disabled=b;if(b){p.addClassName("disabled")}else{p.removeClassName("disabled")}if(p.nodeName.toLowerCase()=="img"){b?p.hide():p.show()}}})}}function submitAndReloadArea(e,d){if($(e)){var b=$(e).select("input","select","textarea");var f=Form.serializeElements(b,true);d=d+(d.match(new RegExp("\\?"))?"&isAjax=true":"?isAjax=true");new Ajax.Request(d,{parameters:$H(f),loaderArea:e,onSuccess:function(l){try{if(l.responseText.isJSON()){var g=l.responseText.evalJSON();if(g.error){alert(g.message)}if(g.ajaxExpired&&g.ajaxRedirect){setLocation(g.ajaxRedirect)}}else{$(e).update(l.responseText)}}catch(h){$(e).update(l.responseText)}}})}}function syncOnchangeValue(d,e){var b={baseElem:d,distElem:e};Event.observe(d,"change",function(){if($(this.baseElem)&&$(this.distElem)){$(this.distElem).value=$(this.baseElem).value}}.bind(b))}function updateElementAtCursor(e,f,g){if(g==undefined){g=window.self}if(document.selection){e.focus();sel=g.document.selection.createRange();sel.text=f}else{if(e.selectionStart||e.selectionStart=="0"){var d=e.selectionStart;var b=e.selectionEnd;e.value=e.value.substring(0,d)+f+e.value.substring(b,e.value.length)}else{e.value+=f}}}function firebugEnabled(){if(window.console&&window.console.firebug){return true}return false}function disableElement(b){b.disabled=true;b.addClassName("disabled")}function enableElement(b){b.disabled=false;b.removeClassName("disabled")}function disableElements(b){$$("."+b).each(disableElement)}function enableElements(b){$$("."+b).each(enableElement)}var Cookie={all:function(){var d=document.cookie.split(";");var b={};d.each(function(f,e){var g=f.strip().split("=");b[unescape(g[0])]=unescape(g[1])});return b},read:function(d){var b=this.all();if(b[d]){return b[d]}return null},write:function(h,f,g){var b="";if(g){var e=new Date();e.setTime(e.getTime()+(g*1000));b="; expires="+e.toGMTString()}var d="/"+BASE_URL.split("/").slice(3).join("/");document.cookie=escape(h)+"="+escape(f)+b+"; path="+d},clear:function(b){this.write(b,"",-1)}};var Fieldset={cookiePrefix:"fh-",applyCollapse:function(b){if($(b+"-state")){collapsed=$(b+"-state").value==1?0:1}else{collapsed=$(b+"-head").collapsed}if(collapsed==1||collapsed===undefined){$(b+"-head").removeClassName("open");if($(b+"-head").up(".section-config")){$(b+"-head").up(".section-config").removeClassName("active")}$(b).hide()}else{$(b+"-head").addClassName("open");if($(b+"-head").up(".section-config")){$(b+"-head").up(".section-config").addClassName("active")}$(b).show()}},toggleCollapse:function(b,d){if($(b+"-state")){collapsed=$(b+"-state").value==1?0:1}else{collapsed=$(b+"-head").collapsed}if(collapsed==1||collapsed===undefined){if($(b+"-state")){$(b+"-state").value=1}$(b+"-head").collapsed=0}else{if($(b+"-state")){$(b+"-state").value=0}$(b+"-head").collapsed=1}this.applyCollapse(b);if(typeof d!="undefined"){this.saveState(d,{container:b,value:$(b+"-state").value})}},addToPrefix:function(b){this.cookiePrefix+=b+"-"},saveState:function(b,d){new Ajax.Request(b,{method:"get",parameters:Object.toQueryString(d),loaderArea:false})}};var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var b="";var p,n,h,o,l,g,f;var d=0;if(typeof window.btoa==="function"){return window.btoa(e)}e=Base64._utf8_encode(e);while(d<e.length){p=e.charCodeAt(d++);n=e.charCodeAt(d++);h=e.charCodeAt(d++);o=p>>2;l=((p&3)<<4)|(n>>4);g=((n&15)<<2)|(h>>6);f=h&63;if(isNaN(n)){g=f=64}else{if(isNaN(h)){f=64}}b=b+this._keyStr.charAt(o)+this._keyStr.charAt(l)+this._keyStr.charAt(g)+this._keyStr.charAt(f)}return b},decode:function(e){var b="";var p,n,h;var o,l,g,f;var d=0;if(typeof window.atob==="function"){return window.atob(e)}e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(d<e.length){o=this._keyStr.indexOf(e.charAt(d++));l=this._keyStr.indexOf(e.charAt(d++));g=this._keyStr.indexOf(e.charAt(d++));f=this._keyStr.indexOf(e.charAt(d++));p=(o<<2)|(l>>4);n=((l&15)<<4)|(g>>2);h=((g&3)<<6)|f;b=b+String.fromCharCode(p);if(g!=64){b=b+String.fromCharCode(n)}if(f!=64){b=b+String.fromCharCode(h)}}b=Base64._utf8_decode(b);return b},mageEncode:function(b){return this.encode(b).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,",")},mageDecode:function(b){b=b.replace(/\-/g,"+").replace(/_/g,"/").replace(/,/g,"=");return this.decode(b)},idEncode:function(b){return this.encode(b).replace(/\+/g,":").replace(/\//g,"_").replace(/=/g,"-")},idDecode:function(b){b=b.replace(/\-/g,"=").replace(/_/g,"/").replace(/\:/g,"+");return this.decode(b)},_utf8_encode:function(d){d=d.replace(/\r\n/g,"\n");var b="";for(var f=0;f<d.length;f++){var e=d.charCodeAt(f);if(e<128){b+=String.fromCharCode(e)}else{if((e>127)&&(e<2048)){b+=String.fromCharCode((e>>6)|192);b+=String.fromCharCode((e&63)|128)}else{b+=String.fromCharCode((e>>12)|224);b+=String.fromCharCode(((e>>6)&63)|128);b+=String.fromCharCode((e&63)|128)}}}return b},_utf8_decode:function(b){var d="";var e=0;var f=c1=c2=0;while(e<b.length){f=b.charCodeAt(e);if(f<128){d+=String.fromCharCode(f);e++}else{if((f>191)&&(f<224)){c2=b.charCodeAt(e+1);d+=String.fromCharCode(((f&31)<<6)|(c2&63));e+=2}else{c2=b.charCodeAt(e+1);c3=b.charCodeAt(e+2);d+=String.fromCharCode(((f&15)<<12)|((c2&63)<<6)|(c3&63));e+=3}}}return d}};function sortNumeric(d,b){return d-b}(function(){var globals=["Prototype","Abstract","Try","Class","PeriodicalExecuter","Template","$break","Enumerable","$A","$w","$H","Hash","$R","ObjectRange","Ajax","$","Form","Field","$F","Toggle","Insertion","$continue","Position","Windows","Dialog","array","WindowUtilities","Builder","Effect","validateCreditCard","Validator","Validation","removeDelimiters","parseNumber","popWin","setLocation","setPLocation","setLanguageCode","decorateGeneric","decorateTable","decorateList","decorateDataList","parseSidUrl","formatCurrency","expandDetails","isIE","Varien","fireEvent","modulo","byteConvert","SessionError","varienLoader","varienLoaderHandler","setLoaderPosition","toggleSelectsUnderBlock","varienUpdater","confirmSetLocation","deleteConfirm","setElementDisable","toggleParentVis","toggleFieldsetVis","toggleVis","imagePreview","checkByProductPriceType","toggleSeveralValueElements","toggleValueElements","submitAndReloadArea","syncOnchangeValue","updateElementAtCursor","firebugEnabled","disableElement","enableElement","disableElements","enableElements","Cookie","Fieldset","Base64","sortNumeric","Element","$$","Sizzle","Selector","Window"];globals.forEach(function(prop){window[prop]=eval(prop)})})(); \ No newline at end of file +(function(){var w=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,p=0,g=Object.prototype.toString,u=false,o=true;[0,0].sort(function(){o=false;return 0});var d=function(L,B,I,D){I=I||[];var e=B=B||document;if(B.nodeType!==1&&B.nodeType!==9){return[]}if(!L||typeof L!=="string"){return I}var J=[],K,G,P,O,H,A,z=true,E=v(B),N=L;while((w.exec(""),K=w.exec(N))!==null){N=K[3];J.push(K[1]);if(K[2]){A=K[3];break}}if(J.length>1&&q.exec(L)){if(J.length===2&&h.relative[J[0]]){G=l(J[0]+J[1],B)}else{G=h.relative[J[0]]?[B]:d(J.shift(),B);while(J.length){L=J.shift();if(h.relative[L]){L+=J.shift()}G=l(L,G)}}}else{if(!D&&J.length>1&&B.nodeType===9&&!E&&h.match.ID.test(J[0])&&!h.match.ID.test(J[J.length-1])){var Q=d.find(J.shift(),B,E);B=Q.expr?d.filter(Q.expr,Q.set)[0]:Q.set[0]}if(B){var Q=D?{expr:J.pop(),set:b(D)}:d.find(J.pop(),J.length===1&&(J[0]==="~"||J[0]==="+")&&B.parentNode?B.parentNode:B,E);G=Q.expr?d.filter(Q.expr,Q.set):Q.set;if(J.length>0){P=b(G)}else{z=false}while(J.length){var C=J.pop(),F=C;if(!h.relative[C]){C=""}else{F=J.pop()}if(F==null){F=B}h.relative[C](P,F,E)}}else{P=J=[]}}if(!P){P=G}if(!P){throw"Syntax error, unrecognized expression: "+(C||L)}if(g.call(P)==="[object Array]"){if(!z){I.push.apply(I,P)}else{if(B&&B.nodeType===1){for(var M=0;P[M]!=null;M++){if(P[M]&&(P[M]===true||P[M].nodeType===1&&n(B,P[M]))){I.push(G[M])}}}else{for(var M=0;P[M]!=null;M++){if(P[M]&&P[M].nodeType===1){I.push(G[M])}}}}}else{b(P,I)}if(A){d(A,e,I,D);d.uniqueSort(I)}return I};d.uniqueSort=function(z){if(f){u=o;z.sort(f);if(u){for(var e=1;e<z.length;e++){if(z[e]===z[e-1]){z.splice(e--,1)}}}}return z};d.matches=function(e,z){return d(e,null,null,z)};d.find=function(F,e,G){var E,C;if(!F){return[]}for(var B=0,A=h.order.length;B<A;B++){var D=h.order[B],C;if((C=h.leftMatch[D].exec(F))){var z=C[1];C.splice(1,1);if(z.substr(z.length-1)!=="\\"){C[1]=(C[1]||"").replace(/\\/g,"");E=h.find[D](C,e,G);if(E!=null){F=F.replace(h.match[D],"");break}}}}if(!E){E=e.getElementsByTagName("*")}return{set:E,expr:F}};d.filter=function(I,H,L,B){var A=I,N=[],F=H,D,e,E=H&&H[0]&&v(H[0]);while(I&&H.length){for(var G in h.filter){if((D=h.match[G].exec(I))!=null){var z=h.filter[G],M,K;e=false;if(F==N){N=[]}if(h.preFilter[G]){D=h.preFilter[G](D,F,L,N,B,E);if(!D){e=M=true}else{if(D===true){continue}}}if(D){for(var C=0;(K=F[C])!=null;C++){if(K){M=z(K,D,C,F);var J=B^!!M;if(L&&M!=null){if(J){e=true}else{F[C]=false}}else{if(J){N.push(K);e=true}}}}}if(M!==undefined){if(!L){F=N}I=I.replace(h.match[G],"");if(!e){return[]}break}}}if(I==A){if(e==null){throw"Syntax error, unrecognized expression: "+I}else{break}}A=I}return F};var h=d.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(e){return e.getAttribute("href")}},relative:{"+":function(F,e,E){var C=typeof e==="string",G=C&&!/\W/.test(e),D=C&&!G;if(G&&!E){e=e.toUpperCase()}for(var B=0,A=F.length,z;B<A;B++){if((z=F[B])){while((z=z.previousSibling)&&z.nodeType!==1){}F[B]=D||z&&z.nodeName===e?z||false:z===e}}if(D){d.filter(e,F,true)}},">":function(E,z,F){var C=typeof z==="string";if(C&&!/\W/.test(z)){z=F?z:z.toUpperCase();for(var A=0,e=E.length;A<e;A++){var D=E[A];if(D){var B=D.parentNode;E[A]=B.nodeName===z?B:false}}}else{for(var A=0,e=E.length;A<e;A++){var D=E[A];if(D){E[A]=C?D.parentNode:D.parentNode===z}}if(C){d.filter(z,E,true)}}},"":function(B,z,D){var A=p++,e=y;if(!/\W/.test(z)){var C=z=D?z:z.toUpperCase();e=t}e("parentNode",z,A,B,C,D)},"~":function(B,z,D){var A=p++,e=y;if(typeof z==="string"&&!/\W/.test(z)){var C=z=D?z:z.toUpperCase();e=t}e("previousSibling",z,A,B,C,D)}},find:{ID:function(z,A,B){if(typeof A.getElementById!=="undefined"&&!B){var e=A.getElementById(z[1]);return e?[e]:[]}},NAME:function(A,D,E){if(typeof D.getElementsByName!=="undefined"){var z=[],C=D.getElementsByName(A[1]);for(var B=0,e=C.length;B<e;B++){if(C[B].getAttribute("name")===A[1]){z.push(C[B])}}return z.length===0?null:z}},TAG:function(e,z){return z.getElementsByTagName(e[1])}},preFilter:{CLASS:function(B,z,A,e,E,F){B=" "+B[1].replace(/\\/g,"")+" ";if(F){return B}for(var C=0,D;(D=z[C])!=null;C++){if(D){if(E^(D.className&&(" "+D.className+" ").indexOf(B)>=0)){if(!A){e.push(D)}}else{if(A){z[C]=false}}}}return false},ID:function(e){return e[1].replace(/\\/g,"")},TAG:function(z,e){for(var A=0;e[A]===false;A++){}return e[A]&&v(e[A])?z[1]:z[1].toUpperCase()},CHILD:function(e){if(e[1]=="nth"){var z=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(e[2]=="even"&&"2n"||e[2]=="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(z[1]+(z[2]||1))-0;e[3]=z[3]-0}e[0]=p++;return e},ATTR:function(C,z,A,e,D,E){var B=C[1].replace(/\\/g,"");if(!E&&h.attrMap[B]){C[1]=h.attrMap[B]}if(C[2]==="~="){C[4]=" "+C[4]+" "}return C},PSEUDO:function(C,z,A,e,D){if(C[1]==="not"){if((w.exec(C[3])||"").length>1||/^\w/.test(C[3])){C[3]=d(C[3],null,null,z)}else{var B=d.filter(C[3],z,A,true^D);if(!A){e.push.apply(e,B)}return false}}else{if(h.match.POS.test(C[0])||h.match.CHILD.test(C[0])){return true}}return C},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){e.parentNode.selectedIndex;return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(A,z,e){return !!d(e[3],A).length},header:function(e){return/h\d/i.test(e.nodeName)},text:function(e){return"text"===e.type},radio:function(e){return"radio"===e.type},checkbox:function(e){return"checkbox"===e.type},file:function(e){return"file"===e.type},password:function(e){return"password"===e.type},submit:function(e){return"submit"===e.type},image:function(e){return"image"===e.type},reset:function(e){return"reset"===e.type},button:function(e){return"button"===e.type||e.nodeName.toUpperCase()==="BUTTON"},input:function(e){return/input|select|textarea|button/i.test(e.nodeName)}},setFilters:{first:function(z,e){return e===0},last:function(A,z,e,B){return z===B.length-1},even:function(z,e){return e%2===0},odd:function(z,e){return e%2===1},lt:function(A,z,e){return z<e[3]-0},gt:function(A,z,e){return z>e[3]-0},nth:function(A,z,e){return e[3]-0==z},eq:function(A,z,e){return e[3]-0==z}},filter:{PSEUDO:function(E,A,B,F){var z=A[1],C=h.filters[z];if(C){return C(E,B,A,F)}else{if(z==="contains"){return(E.textContent||E.innerText||"").indexOf(A[3])>=0}else{if(z==="not"){var D=A[3];for(var B=0,e=D.length;B<e;B++){if(D[B]===E){return false}}return true}}}},CHILD:function(e,B){var E=B[1],z=e;switch(E){case"only":case"first":while((z=z.previousSibling)){if(z.nodeType===1){return false}}if(E=="first"){return true}z=e;case"last":while((z=z.nextSibling)){if(z.nodeType===1){return false}}return true;case"nth":var A=B[2],H=B[3];if(A==1&&H==0){return true}var D=B[0],G=e.parentNode;if(G&&(G.sizcache!==D||!e.nodeIndex)){var C=0;for(z=G.firstChild;z;z=z.nextSibling){if(z.nodeType===1){z.nodeIndex=++C}}G.sizcache=D}var F=e.nodeIndex-H;if(A==0){return F==0}else{return(F%A==0&&F/A>=0)}}},ID:function(z,e){return z.nodeType===1&&z.getAttribute("id")===e},TAG:function(z,e){return(e==="*"&&z.nodeType===1)||z.nodeName===e},CLASS:function(z,e){return(" "+(z.className||z.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(D,B){var A=B[1],e=h.attrHandle[A]?h.attrHandle[A](D):D[A]!=null?D[A]:D.getAttribute(A),E=e+"",C=B[2],z=B[4];return e==null?C==="!=":C==="="?E===z:C==="*="?E.indexOf(z)>=0:C==="~="?(" "+E+" ").indexOf(z)>=0:!z?E&&e!==false:C==="!="?E!=z:C==="^="?E.indexOf(z)===0:C==="$="?E.substr(E.length-z.length)===z:C==="|="?E===z||E.substr(0,z.length+1)===z+"-":false},POS:function(C,z,A,D){var e=z[2],B=h.setFilters[e];if(B){return B(C,A,z,D)}}}};var q=h.match.POS;for(var s in h.match){h.match[s]=new RegExp(h.match[s].source+/(?![^\[]*\])(?![^\(]*\))/.source);h.leftMatch[s]=new RegExp(/(^(?:.|\r|\n)*?)/.source+h.match[s].source)}var b=function(z,e){z=Array.prototype.slice.call(z,0);if(e){e.push.apply(e,z);return e}return z};try{Array.prototype.slice.call(document.documentElement.childNodes,0)}catch(r){b=function(C,B){var z=B||[];if(g.call(C)==="[object Array]"){Array.prototype.push.apply(z,C)}else{if(typeof C.length==="number"){for(var A=0,e=C.length;A<e;A++){z.push(C[A])}}else{for(var A=0;C[A];A++){z.push(C[A])}}}return z}}var f;if(document.documentElement.compareDocumentPosition){f=function(z,e){if(!z.compareDocumentPosition||!e.compareDocumentPosition){if(z==e){u=true}return 0}var A=z.compareDocumentPosition(e)&4?-1:z===e?0:1;if(A===0){u=true}return A}}else{if("sourceIndex" in document.documentElement){f=function(z,e){if(!z.sourceIndex||!e.sourceIndex){if(z==e){u=true}return 0}var A=z.sourceIndex-e.sourceIndex;if(A===0){u=true}return A}}else{if(document.createRange){f=function(B,z){if(!B.ownerDocument||!z.ownerDocument){if(B==z){u=true}return 0}var A=B.ownerDocument.createRange(),e=z.ownerDocument.createRange();A.setStart(B,0);A.setEnd(B,0);e.setStart(z,0);e.setEnd(z,0);var C=A.compareBoundaryPoints(Range.START_TO_END,e);if(C===0){u=true}return C}}}}(function(){var z=document.createElement("div"),A="script"+(new Date).getTime();z.innerHTML="<a name='"+A+"'/>";var e=document.documentElement;e.insertBefore(z,e.firstChild);if(!!document.getElementById(A)){h.find.ID=function(C,D,E){if(typeof D.getElementById!=="undefined"&&!E){var B=D.getElementById(C[1]);return B?B.id===C[1]||typeof B.getAttributeNode!=="undefined"&&B.getAttributeNode("id").nodeValue===C[1]?[B]:undefined:[]}};h.filter.ID=function(D,B){var C=typeof D.getAttributeNode!=="undefined"&&D.getAttributeNode("id");return D.nodeType===1&&C&&C.nodeValue===B}}e.removeChild(z);e=z=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){h.find.TAG=function(z,D){var C=D.getElementsByTagName(z[1]);if(z[1]==="*"){var B=[];for(var A=0;C[A];A++){if(C[A].nodeType===1){B.push(C[A])}}C=B}return C}}e.innerHTML="<a href='#'></a>";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){h.attrHandle.href=function(z){return z.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=d,A=document.createElement("div");A.innerHTML="<p class='TEST'></p>";if(A.querySelectorAll&&A.querySelectorAll(".TEST").length===0){return}d=function(E,D,B,C){D=D||document;if(!C&&D.nodeType===9&&!v(D)){try{return b(D.querySelectorAll(E),B)}catch(F){}}return e(E,D,B,C)};for(var z in e){d[z]=e[z]}A=null})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var e=document.createElement("div");e.innerHTML="<div class='test e'></div><div class='test'></div>";if(e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}h.order.splice(1,0,"CLASS");h.find.CLASS=function(z,A,B){if(typeof A.getElementsByClassName!=="undefined"&&!B){return A.getElementsByClassName(z[1])}};e=null})()}function t(z,E,D,I,F,H){var G=z=="previousSibling"&&!H;for(var B=0,A=I.length;B<A;B++){var e=I[B];if(e){if(G&&e.nodeType===1){e.sizcache=D;e.sizset=B}e=e[z];var C=false;while(e){if(e.sizcache===D){C=I[e.sizset];break}if(e.nodeType===1&&!H){e.sizcache=D;e.sizset=B}if(e.nodeName===E){C=e;break}e=e[z]}I[B]=C}}}function y(z,E,D,I,F,H){var G=z=="previousSibling"&&!H;for(var B=0,A=I.length;B<A;B++){var e=I[B];if(e){if(G&&e.nodeType===1){e.sizcache=D;e.sizset=B}e=e[z];var C=false;while(e){if(e.sizcache===D){C=I[e.sizset];break}if(e.nodeType===1){if(!H){e.sizcache=D;e.sizset=B}if(typeof E!=="string"){if(e===E){C=true;break}}else{if(d.filter(E,[e]).length>0){C=e;break}}}e=e[z]}I[B]=C}}}var n=document.compareDocumentPosition?function(z,e){return z.compareDocumentPosition(e)&16}:function(z,e){return z!==e&&(z.contains?z.contains(e):true)};var v=function(e){return e.nodeType===9&&e.documentElement.nodeName!=="HTML"||!!e.ownerDocument&&e.ownerDocument.documentElement.nodeName!=="HTML"};var l=function(e,F){var B=[],C="",D,A=F.nodeType?[F]:F;while((D=h.match.PSEUDO.exec(e))){C+=D[0];e=e.replace(h.match.PSEUDO,"")}e=h.relative[e]?e+"*":e;for(var E=0,z=A.length;E<z;E++){d(e,A[E],B)}return d.filter(C,B)};window.Sizzle=d})();(function(e){var f=Prototype.Selector.extendElements;function b(g,h){return f(e(g,h||document))}function d(h,g){return e.matches(g,[h]).length==1}Prototype.Selector.engine=e;Prototype.Selector.select=b;Prototype.Selector.match=d})(Sizzle);window.Sizzle=Prototype._original_property;delete Prototype._original_property;var Form={reset:function(b){b=$(b);b.reset();return b},serializeElements:function(n,f){if(typeof f!="object"){f={hash:!!f}}else{if(Object.isUndefined(f.hash)){f.hash=true}}var g,l,b=false,h=f.submit,d,e;if(f.hash){e={};d=function(o,p,q){if(p in o){if(!Object.isArray(o[p])){o[p]=[o[p]]}o[p].push(q)}else{o[p]=q}return o}}else{e="";d=function(o,p,q){return o+(o?"&":"")+encodeURIComponent(p)+"="+encodeURIComponent(q)}}return n.inject(e,function(o,p){if(!p.disabled&&p.name){g=p.name;l=$(p).getValue();if(l!=null&&p.type!="file"&&(p.type!="submit"||(!b&&h!==false&&(!h||g==h)&&(b=true)))){o=d(o,g,l)}}return o})}};Form.Methods={serialize:function(d,b){return Form.serializeElements(Form.getElements(d),b)},getElements:function(g){var h=$(g).getElementsByTagName("*"),f,b=[],e=Form.Element.Serializers;for(var d=0;f=h[d];d++){b.push(f)}return b.inject([],function(l,n){if(e[n.tagName.toLowerCase()]){l.push(Element.extend(n))}return l})},getInputs:function(l,e,f){l=$(l);var b=l.getElementsByTagName("input");if(!e&&!f){return $A(b).map(Element.extend)}for(var g=0,n=[],h=b.length;g<h;g++){var d=b[g];if((e&&d.type!=e)||(f&&d.name!=f)){continue}n.push(Element.extend(d))}return n},disable:function(b){b=$(b);Form.getElements(b).invoke("disable");return b},enable:function(b){b=$(b);Form.getElements(b).invoke("enable");return b},findFirstElement:function(d){var e=$(d).getElements().findAll(function(f){return"hidden"!=f.type&&!f.disabled});var b=e.findAll(function(f){return f.hasAttribute("tabIndex")&&f.tabIndex>=0}).sortBy(function(f){return f.tabIndex}).first();return b?b:e.find(function(f){return/^(?:input|select|textarea)$/i.test(f.tagName)})},focusFirstElement:function(d){d=$(d);var b=d.findFirstElement();if(b){b.activate()}return d},request:function(d,b){d=$(d),b=Object.clone(b||{});var f=b.parameters,e=d.readAttribute("action")||"";if(e.blank()){e=window.location.href}b.parameters=d.serialize(true);if(f){if(Object.isString(f)){f=f.toQueryParams()}Object.extend(b.parameters,f)}if(d.hasAttribute("method")&&!b.method){b.method=d.method}return new Ajax.Request(e,b)}};Form.Element={focus:function(b){$(b).focus();return b},select:function(b){$(b).select();return b}};Form.Element.Methods={serialize:function(b){b=$(b);if(!b.disabled&&b.name){var d=b.getValue();if(d!=undefined){var e={};e[b.name]=d;return Object.toQueryString(e)}}return""},getValue:function(b){b=$(b);var d=b.tagName.toLowerCase();return Form.Element.Serializers[d](b)},setValue:function(b,d){b=$(b);var e=b.tagName.toLowerCase();Form.Element.Serializers[e](b,d);return b},clear:function(b){$(b).value="";return b},present:function(b){return $(b).value!=""},activate:function(b){b=$(b);try{b.focus();if(b.select&&(b.tagName.toLowerCase()!="input"||!(/^(?:button|reset|submit)$/i.test(b.type)))){b.select()}}catch(d){}return b},disable:function(b){b=$(b);b.disabled=true;return b},enable:function(b){b=$(b);b.disabled=false;return b}};var Field=Form.Element;var $F=Form.Element.Methods.getValue;Form.Element.Serializers=(function(){function d(n,o){switch(n.type.toLowerCase()){case"checkbox":case"radio":return h(n,o);default:return g(n,o)}}function h(n,o){if(Object.isUndefined(o)){return n.checked?n.value:null}else{n.checked=!!o}}function g(n,o){if(Object.isUndefined(o)){return n.value}else{n.value=o}}function b(p,s){if(Object.isUndefined(s)){return(p.type==="select-one"?e:f)(p)}var o,q,t=!Object.isArray(s);for(var n=0,r=p.length;n<r;n++){o=p.options[n];q=this.optionValue(o);if(t){if(q==s){o.selected=true;return}}else{o.selected=s.include(q)}}}function e(o){var n=o.selectedIndex;return n>=0?l(o.options[n]):null}function f(q){var n,r=q.length;if(!r){return null}for(var p=0,n=[];p<r;p++){var o=q.options[p];if(o.selected){n.push(l(o))}}return n}function l(n){return Element.hasAttribute(n,"value")?n.value:n.text}return{input:d,inputSelector:h,textarea:g,select:b,selectOne:e,selectMany:f,optionValue:l,button:g}})();Abstract.TimedObserver=Class.create(PeriodicalExecuter,{initialize:function($super,b,d,e){$super(e,d);this.element=$(b);this.lastValue=this.getValue()},execute:function(){var b=this.getValue();if(Object.isString(this.lastValue)&&Object.isString(b)?this.lastValue!=b:String(this.lastValue)!=String(b)){this.callback(this.element,b);this.lastValue=b}}});Form.Element.Observer=Class.create(Abstract.TimedObserver,{getValue:function(){return Form.Element.getValue(this.element)}});Form.Observer=Class.create(Abstract.TimedObserver,{getValue:function(){return Form.serialize(this.element)}});Abstract.EventObserver=Class.create({initialize:function(b,d){this.element=$(b);this.callback=d;this.lastValue=this.getValue();if(this.element.tagName.toLowerCase()=="form"){this.registerFormCallbacks()}else{this.registerCallback(this.element)}},onElementEvent:function(){var b=this.getValue();if(this.lastValue!=b){this.callback(this.element,b);this.lastValue=b}},registerFormCallbacks:function(){Form.getElements(this.element).each(this.registerCallback,this)},registerCallback:function(b){if(b.type){switch(b.type.toLowerCase()){case"checkbox":case"radio":Event.observe(b,"click",this.onElementEvent.bind(this));break;default:Event.observe(b,"change",this.onElementEvent.bind(this));break}}}});Form.Element.EventObserver=Class.create(Abstract.EventObserver,{getValue:function(){return Form.Element.getValue(this.element)}});Form.EventObserver=Class.create(Abstract.EventObserver,{getValue:function(){return Form.serialize(this.element)}});(function(){var J={KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,KEY_HOME:36,KEY_END:35,KEY_PAGEUP:33,KEY_PAGEDOWN:34,KEY_INSERT:45,cache:{}};var h=document.documentElement;var K="onmouseenter" in h&&"onmouseleave" in h;var b=function(L){return false};if(window.attachEvent){if(window.addEventListener){b=function(L){return !(L instanceof window.Event)}}else{b=function(L){return true}}}var y;function H(M,L){return M.which?(M.which===L+1):(M.button===L)}var u={0:1,1:4,2:2};function F(M,L){return M.button===u[L]}function I(M,L){switch(L){case 0:return M.which==1&&!M.metaKey;case 1:return M.which==2||(M.which==1&&M.metaKey);case 2:return M.which==3;default:return false}}if(window.attachEvent){if(!window.addEventListener){y=F}else{y=function(M,L){return b(M)?F(M,L):H(M,L)}}}else{if(Prototype.Browser.WebKit){y=I}else{y=H}}function C(L){return y(L,0)}function A(L){return y(L,1)}function t(L){return y(L,2)}function f(N){N=J.extend(N);var M=N.target,L=N.type,O=N.currentTarget;if(O&&O.tagName){if(L==="load"||L==="error"||(L==="click"&&O.tagName.toLowerCase()==="input"&&O.type==="radio")){M=O}}if(M.nodeType==Node.TEXT_NODE){M=M.parentNode}return Element.extend(M)}function v(M,N){var L=J.element(M);if(!N){return L}while(L){if(Object.isElement(L)&&Prototype.Selector.match(L,N)){return Element.extend(L)}L=L.parentNode}}function z(L){return{x:e(L),y:d(L)}}function e(N){var M=document.documentElement,L=document.body||{scrollLeft:0};return N.pageX||(N.clientX+(M.scrollLeft||L.scrollLeft)-(M.clientLeft||0))}function d(N){var M=document.documentElement,L=document.body||{scrollTop:0};return N.pageY||(N.clientY+(M.scrollTop||L.scrollTop)-(M.clientTop||0))}function w(L){J.extend(L);L.preventDefault();L.stopPropagation();L.stopped=true}J.Methods={isLeftClick:C,isMiddleClick:A,isRightClick:t,element:f,findElement:v,pointer:z,pointerX:e,pointerY:d,stop:w};var E=Object.keys(J.Methods).inject({},function(L,M){L[M]=J.Methods[M].methodize();return L});if(window.attachEvent){function o(M){var L;switch(M.type){case"mouseover":case"mouseenter":L=M.fromElement;break;case"mouseout":case"mouseleave":L=M.toElement;break;default:return null}return Element.extend(L)}var B={stopPropagation:function(){this.cancelBubble=true},preventDefault:function(){this.returnValue=false},inspect:function(){return"[object Event]"}};J.extend=function(M,L){if(!M){return false}if(!b(M)){return M}if(M._extendedByPrototype){return M}M._extendedByPrototype=Prototype.emptyFunction;var N=J.pointer(M);Object.extend(M,{target:M.srcElement||L,relatedTarget:o(M),pageX:N.x,pageY:N.y});Object.extend(M,E);Object.extend(M,B);return M}}else{J.extend=Prototype.K}if(window.addEventListener){J.prototype=window.Event.prototype||document.createEvent("HTMLEvents").__proto__;Object.extend(J.prototype,E)}function s(P,O,Q){var N=Element.retrieve(P,"prototype_event_registry");if(Object.isUndefined(N)){g.push(P);N=Element.retrieve(P,"prototype_event_registry",$H())}var L=N.get(O);if(Object.isUndefined(L)){L=[];N.set(O,L)}if(L.pluck("handler").include(Q)){return false}var M;if(O.include(":")){M=function(R){if(Object.isUndefined(R.eventName)){return false}if(R.eventName!==O){return false}J.extend(R,P);Q.call(P,R)}}else{if(!K&&(O==="mouseenter"||O==="mouseleave")){if(O==="mouseenter"||O==="mouseleave"){M=function(S){J.extend(S,P);var R=S.relatedTarget;while(R&&R!==P){try{R=R.parentNode}catch(T){R=P}}if(R===P){return}Q.call(P,S)}}}else{M=function(R){J.extend(R,P);Q.call(P,R)}}}M.handler=Q;L.push(M);return M}function n(){for(var L=0,M=g.length;L<M;L++){J.stopObserving(g[L]);g[L]=null}}var g=[];if(Prototype.Browser.IE){window.attachEvent("onunload",n)}if(Prototype.Browser.WebKit){window.addEventListener("unload",Prototype.emptyFunction,false)}var r=Prototype.K,l={mouseenter:"mouseover",mouseleave:"mouseout"};if(!K){r=function(L){return(l[L]||L)}}function D(O,N,P){O=$(O);var M=s(O,N,P);if(!M){return O}if(N.include(":")){if(O.addEventListener){O.addEventListener("dataavailable",M,false)}else{O.attachEvent("ondataavailable",M);O.attachEvent("onlosecapture",M)}}else{var L=r(N);if(O.addEventListener){O.addEventListener(L,M,false)}else{O.attachEvent("on"+L,M)}}return O}function q(R,O,S){R=$(R);var N=Element.retrieve(R,"prototype_event_registry");if(!N){return R}if(!O){N.each(function(U){var T=U.key;q(R,T)});return R}var P=N.get(O);if(!P){return R}if(!S){P.each(function(T){q(R,O,T.handler)});return R}var Q=P.length,M;while(Q--){if(P[Q].handler===S){M=P[Q];break}}if(!M){return R}if(O.include(":")){if(R.removeEventListener){R.removeEventListener("dataavailable",M,false)}else{R.detachEvent("ondataavailable",M);R.detachEvent("onlosecapture",M)}}else{var L=r(O);if(R.removeEventListener){R.removeEventListener(L,M,false)}else{R.detachEvent("on"+L,M)}}N.set(O,P.without(M));return R}function G(O,N,M,L){O=$(O);if(Object.isUndefined(L)){L=true}if(O==document&&document.createEvent&&!O.dispatchEvent){O=document.documentElement}var P;if(document.createEvent){P=document.createEvent("HTMLEvents");P.initEvent("dataavailable",L,true)}else{P=document.createEventObject();P.eventType=L?"ondataavailable":"onlosecapture"}P.eventName=N;P.memo=M||{};if(document.createEvent){O.dispatchEvent(P)}else{O.fireEvent(P.eventType,P)}return J.extend(P)}J.Handler=Class.create({initialize:function(N,M,L,O){this.element=$(N);this.eventName=M;this.selector=L;this.callback=O;this.handler=this.handleEvent.bind(this)},start:function(){J.observe(this.element,this.eventName,this.handler);return this},stop:function(){J.stopObserving(this.element,this.eventName,this.handler);return this},handleEvent:function(M){var L=J.findElement(M,this.selector);if(L){this.callback.call(this.element,M,L)}}});function p(N,M,L,O){N=$(N);if(Object.isFunction(L)&&Object.isUndefined(O)){O=L,L=null}return new J.Handler(N,M,L,O).start()}Object.extend(J,J.Methods);Object.extend(J,{fire:G,observe:D,stopObserving:q,on:p});Element.addMethods({fire:G,observe:D,stopObserving:q,on:p});Object.extend(document,{fire:G.methodize(),observe:D.methodize(),stopObserving:q.methodize(),on:p.methodize(),loaded:false});if(window.Event){Object.extend(window.Event,J)}else{window.Event=J}})();(function(){var e;function b(){if(document.loaded){return}if(e){window.clearTimeout(e)}document.loaded=true;document.fire("dom:loaded")}function d(){if(document.readyState==="complete"){document.stopObserving("readystatechange",d);b()}}if(document.addEventListener){document.addEventListener("DOMContentLoaded",b,false)}else{document.observe("readystatechange",d);if(window==top){var e=window.setInterval(function(){try{document.documentElement.doScroll("left")}catch(f){return}window.clearInterval(e);b()},5)}}Event.observe(window,"load",b)})();Element.addMethods();Hash.toQueryString=Object.toQueryString;var Toggle={display:Element.toggle};Element.Methods.childOf=Element.Methods.descendantOf;var Insertion={Before:function(b,d){return Element.insert(b,{before:d})},Top:function(b,d){return Element.insert(b,{top:d})},Bottom:function(b,d){return Element.insert(b,{bottom:d})},After:function(b,d){return Element.insert(b,{after:d})}};var $continue=new Error('"throw $continue" is deprecated, use "return" instead');var Position={includeScrollOffsets:false,prepare:function(){this.deltaX=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;this.deltaY=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0},within:function(d,b,e){if(this.includeScrollOffsets){return this.withinIncludingScrolloffsets(d,b,e)}this.xcomp=b;this.ycomp=e;this.offset=Element.cumulativeOffset(d);return(e>=this.offset[1]&&e<this.offset[1]+d.offsetHeight&&b>=this.offset[0]&&b<this.offset[0]+d.offsetWidth)},withinIncludingScrolloffsets:function(d,b,f){var e=Element.cumulativeScrollOffset(d);this.xcomp=b+e[0]-this.deltaX;this.ycomp=f+e[1]-this.deltaY;this.offset=Element.cumulativeOffset(d);return(this.ycomp>=this.offset[1]&&this.ycomp<this.offset[1]+d.offsetHeight&&this.xcomp>=this.offset[0]&&this.xcomp<this.offset[0]+d.offsetWidth)},overlap:function(d,b){if(!d){return 0}if(d=="vertical"){return((this.offset[1]+b.offsetHeight)-this.ycomp)/b.offsetHeight}if(d=="horizontal"){return((this.offset[0]+b.offsetWidth)-this.xcomp)/b.offsetWidth}},cumulativeOffset:Element.Methods.cumulativeOffset,positionedOffset:Element.Methods.positionedOffset,absolutize:function(b){Position.prepare();return Element.absolutize(b)},relativize:function(b){Position.prepare();return Element.relativize(b)},realOffset:Element.Methods.cumulativeScrollOffset,offsetParent:Element.Methods.getOffsetParent,page:Element.Methods.viewportOffset,clone:function(d,e,b){b=b||{};return Element.clonePosition(e,d,b)}};if(!document.getElementsByClassName){document.getElementsByClassName=function(d){function b(e){return e.blank()?null:"[contains(concat(' ', @class, ' '), ' "+e+" ')]"}d.getElementsByClassName=Prototype.BrowserFeatures.XPath?function(e,g){g=g.toString().strip();var f=/\s/.test(g)?$w(g).map(b).join(""):b(g);return f?document._getElementsByXPath(".//*"+f,e):[]}:function(g,h){h=h.toString().strip();var l=[],n=(/\s/.test(h)?$w(h):null);if(!n&&!h){return l}var e=$(g).getElementsByTagName("*");h=" "+h+" ";for(var f=0,p,o;p=e[f];f++){if(p.className&&(o=" "+p.className+" ")&&(o.include(h)||(n&&n.all(function(q){return !q.toString().blank()&&o.include(" "+q+" ")})))){l.push(Element.extend(p))}}return l};return function(f,e){return $(e||document.body).getElementsByClassName(f)}}(Element.Methods)}Element.ClassNames=Class.create();Element.ClassNames.prototype={initialize:function(b){this.element=$(b)},_each:function(b){this.element.className.split(/\s+/).select(function(d){return d.length>0})._each(b)},set:function(b){this.element.className=b},add:function(b){if(this.include(b)){return}this.set($A(this).concat(b).join(" "))},remove:function(b){if(!this.include(b)){return}this.set($A(this).without(b).join(" "))},toString:function(){return $A(this).join(" ")}};Object.extend(Element.ClassNames.prototype,Enumerable);(function(){window.Selector=Class.create({initialize:function(b){this.expression=b.strip()},findElements:function(b){return Prototype.Selector.select(this.expression,b)},match:function(b){return Prototype.Selector.match(b,this.expression)},toString:function(){return this.expression},inspect:function(){return"#<Selector: "+this.expression+">"}});Object.extend(Selector,{matchElements:function(h,l){var b=Prototype.Selector.match,f=[];for(var e=0,g=h.length;e<g;e++){var d=h[e];if(b(d,l)){f.push(Element.extend(d))}}return f},findElement:function(h,l,d){d=d||0;var b=0,f;for(var e=0,g=h.length;e<g;e++){f=h[e];if(Prototype.Selector.match(f,l)&&d===b++){return Element.extend(f)}}},findChildElements:function(d,e){var b=e.toArray().join(", ");return Prototype.Selector.select(b,d||document)}})})();var Window=Class.create();Window.keepMultiModalWindow=false;Window.hasEffectLib=(typeof Effect!="undefined");Window.resizeEffectDuration=0.4;Window.prototype={initialize:function(){var e;var d=0;if(arguments.length>0){if(typeof arguments[0]=="string"){e=arguments[0];d=1}else{e=arguments[0]?arguments[0].id:null}}if(!e){e="window_"+new Date().getTime()}if($(e)){alert("Window "+e+" is already registered in the DOM! Make sure you use setDestroyOnClose() or destroyOnClose: true in the constructor")}this.options=Object.extend({className:"dialog",windowClassName:null,blurClassName:null,minWidth:100,minHeight:20,resizable:true,closable:true,minimizable:true,maximizable:true,draggable:true,userData:null,showEffect:(Window.hasEffectLib?Effect.Appear:Element.show),hideEffect:(Window.hasEffectLib?Effect.Fade:Element.hide),showEffectOptions:{},hideEffectOptions:{},effectOptions:null,parent:document.body,title:" ",url:null,onload:Prototype.emptyFunction,width:200,height:300,opacity:1,recenterAuto:true,wiredDrag:false,closeOnEsc:true,closeCallback:null,destroyOnClose:false,gridX:1,gridY:1},arguments[d]||{});if(this.options.blurClassName){this.options.focusClassName=this.options.className}if(typeof this.options.top=="undefined"&&typeof this.options.bottom=="undefined"){this.options.top=this._round(Math.random()*500,this.options.gridY)}if(typeof this.options.left=="undefined"&&typeof this.options.right=="undefined"){this.options.left=this._round(Math.random()*500,this.options.gridX)}if(this.options.effectOptions){Object.extend(this.options.hideEffectOptions,this.options.effectOptions);Object.extend(this.options.showEffectOptions,this.options.effectOptions);if(this.options.showEffect==Element.Appear){this.options.showEffectOptions.to=this.options.opacity}}if(Window.hasEffectLib){if(this.options.showEffect==Effect.Appear){this.options.showEffectOptions.to=this.options.opacity}if(this.options.hideEffect==Effect.Fade){this.options.hideEffectOptions.from=this.options.opacity}}if(this.options.hideEffect==Element.hide){this.options.hideEffect=function(){Element.hide(this.element);if(this.options.destroyOnClose){this.destroy()}}.bind(this)}if(this.options.parent!=document.body){this.options.parent=$(this.options.parent)}this.element=this._createWindow(e);this.element.win=this;this.eventMouseDown=this._initDrag.bindAsEventListener(this);this.eventMouseUp=this._endDrag.bindAsEventListener(this);this.eventMouseMove=this._updateDrag.bindAsEventListener(this);this.eventOnLoad=this._getWindowBorderSize.bindAsEventListener(this);this.eventMouseDownContent=this.toFront.bindAsEventListener(this);this.eventResize=this._recenter.bindAsEventListener(this);this.eventKeyUp=this._keyUp.bindAsEventListener(this);this.topbar=$(this.element.id+"_top");this.bottombar=$(this.element.id+"_bottom");this.content=$(this.element.id+"_content");Event.observe(this.topbar,"mousedown",this.eventMouseDown);Event.observe(this.bottombar,"mousedown",this.eventMouseDown);Event.observe(this.content,"mousedown",this.eventMouseDownContent);Event.observe(window,"load",this.eventOnLoad);Event.observe(window,"resize",this.eventResize);Event.observe(window,"scroll",this.eventResize);Event.observe(document,"keyup",this.eventKeyUp);Event.observe(this.options.parent,"scroll",this.eventResize);if(this.options.draggable){var b=this;[this.topbar,this.topbar.up().previous(),this.topbar.up().next()].each(function(f){f.observe("mousedown",b.eventMouseDown);f.addClassName("top_draggable")});[this.bottombar.up(),this.bottombar.up().previous(),this.bottombar.up().next()].each(function(f){f.observe("mousedown",b.eventMouseDown);f.addClassName("bottom_draggable")})}if(this.options.resizable){this.sizer=$(this.element.id+"_sizer");Event.observe(this.sizer,"mousedown",this.eventMouseDown)}this.useLeft=null;this.useTop=null;if(typeof this.options.left!="undefined"){this.element.setStyle({left:parseFloat(this.options.left)+"px"});this.useLeft=true}else{this.element.setStyle({right:parseFloat(this.options.right)+"px"});this.useLeft=false}if(typeof this.options.top!="undefined"){this.element.setStyle({top:parseFloat(this.options.top)+"px"});this.useTop=true}else{this.element.setStyle({bottom:parseFloat(this.options.bottom)+"px"});this.useTop=false}this.storedLocation=null;this.setOpacity(this.options.opacity);if(this.options.zIndex){this.setZIndex(this.options.zIndex)}else{this.setZIndex(this.getMaxZIndex())}if(this.options.destroyOnClose){this.setDestroyOnClose(true)}this._getWindowBorderSize();this.width=this.options.width;this.height=this.options.height;this.visible=false;this.constraint=false;this.constraintPad={top:0,left:0,bottom:0,right:0};if(this.width&&this.height){this.setSize(this.options.width,this.options.height)}this.setTitle(this.options.title);Windows.register(this)},getMaxZIndex:function(){var b=0,d;var g=document.body.childNodes;for(d=0;d<g.length;d++){var e=g[d];var f=e.nodeType==1?parseInt(e.style.zIndex,10)||0:0;if(f<10000){b=Math.max(b,f)}}return b+10},destroy:function(){this._notify("onDestroy");Event.stopObserving(this.topbar,"mousedown",this.eventMouseDown);Event.stopObserving(this.bottombar,"mousedown",this.eventMouseDown);Event.stopObserving(this.content,"mousedown",this.eventMouseDownContent);Event.stopObserving(window,"load",this.eventOnLoad);Event.stopObserving(window,"resize",this.eventResize);Event.stopObserving(window,"scroll",this.eventResize);Event.stopObserving(this.content,"load",this.options.onload);Event.stopObserving(document,"keyup",this.eventKeyUp);if(this._oldParent){var e=this.getContent();var b=null;for(var d=0;d<e.childNodes.length;d++){b=e.childNodes[d];if(b.nodeType==1){break}b=null}if(b){this._oldParent.appendChild(b)}this._oldParent=null}if(this.sizer){Event.stopObserving(this.sizer,"mousedown",this.eventMouseDown)}if(this.options.url){this.content.src=null}if(this.iefix){Element.remove(this.iefix)}Element.remove(this.element);Windows.unregister(this)},setCloseCallback:function(b){this.options.closeCallback=b},getContent:function(){return this.content},setContent:function(n,l,e){var b=$(n);if(null==b){throw"Unable to find element '"+n+"' in DOM"}this._oldParent=b.parentNode;var h=null;var g=null;if(l){h=Element.getDimensions(b)}if(e){g=Position.cumulativeOffset(b)}var f=this.getContent();this.setHTMLContent("");f=this.getContent();f.appendChild(b);b.show();if(l){this.setSize(h.width,h.height)}if(e){this.setLocation(g[1]-this.heightN,g[0]-this.widthW)}},setHTMLContent:function(b){if(this.options.url){this.content.src=null;this.options.url=null;var d='<div id="'+this.getId()+'_content" class="'+this.options.className+'_content"> </div>';$(this.getId()+"_table_content").innerHTML=d;this.content=$(this.element.id+"_content")}this.getContent().innerHTML=b},setAjaxContent:function(d,b,f,e){this.showFunction=f?"showCenter":"show";this.showModal=e||false;b=b||{};this.setHTMLContent("");this.onComplete=b.onComplete;if(!this._onCompleteHandler){this._onCompleteHandler=this._setAjaxContent.bind(this)}b.onComplete=this._onCompleteHandler;new Ajax.Request(d,b);b.onComplete=this.onComplete},_setAjaxContent:function(b){Element.update(this.getContent(),b.responseText);if(this.onComplete){this.onComplete(b)}this.onComplete=null;this[this.showFunction](this.showModal)},setURL:function(b){if(this.options.url){this.content.src=null}this.options.url=b;var d="<iframe frameborder='0' name='"+this.getId()+"_content' id='"+this.getId()+"_content' src='"+b+"' width='"+this.width+"' height='"+this.height+"'> </iframe>";$(this.getId()+"_table_content").innerHTML=d;this.content=$(this.element.id+"_content")},getURL:function(){return this.options.url?this.options.url:null},refresh:function(){if(this.options.url){$(this.element.getAttribute("id")+"_content").src=this.options.url}},setCookie:function(d,e,t,g,b){d=d||this.element.id;this.cookie=[d,e,t,g,b];var r=WindowUtilities.getCookie(d);if(r){var s=r.split(",");var p=s[0].split(":");var o=s[1].split(":");var q=parseFloat(s[2]),l=parseFloat(s[3]);var n=s[4];var f=s[5];this.setSize(q,l);if(n=="true"){this.doMinimize=true}else{if(f=="true"){this.doMaximize=true}}this.useLeft=p[0]=="l";this.useTop=o[0]=="t";this.element.setStyle(this.useLeft?{left:p[1]}:{right:p[1]});this.element.setStyle(this.useTop?{top:o[1]}:{bottom:o[1]})}},getId:function(){return this.element.id},setDestroyOnClose:function(){this.options.destroyOnClose=true},setConstraint:function(b,d){this.constraint=b;this.constraintPad=Object.extend(this.constraintPad,d||{});if(this.useTop&&this.useLeft){this.setLocation(parseFloat(this.element.style.top),parseFloat(this.element.style.left))}},_initDrag:function(d){if(Event.element(d)==this.sizer&&this.isMinimized()){return}if(Event.element(d)!=this.sizer&&this.isMaximized()){return}if(Prototype.Browser.IE&&this.heightN==0){this._getWindowBorderSize()}this.pointer=[this._round(Event.pointerX(d),this.options.gridX),this._round(Event.pointerY(d),this.options.gridY)];if(this.options.wiredDrag){this.currentDrag=this._createWiredElement()}else{this.currentDrag=this.element}if(Event.element(d)==this.sizer){this.doResize=true;this.widthOrg=this.width;this.heightOrg=this.height;this.bottomOrg=parseFloat(this.element.getStyle("bottom"));this.rightOrg=parseFloat(this.element.getStyle("right"));this._notify("onStartResize")}else{this.doResize=false;var b=$(this.getId()+"_close");if(b&&Position.within(b,this.pointer[0],this.pointer[1])){this.currentDrag=null;return}this.toFront();if(!this.options.draggable){return}this._notify("onStartMove")}Event.observe(document,"mouseup",this.eventMouseUp,false);Event.observe(document,"mousemove",this.eventMouseMove,false);WindowUtilities.disableScreen("__invisible__","__invisible__",this.overlayOpacity);document.body.ondrag=function(){return false};document.body.onselectstart=function(){return false};this.currentDrag.show();Event.stop(d)},_round:function(d,b){return b==1?d:d=Math.floor(d/b)*b},_updateDrag:function(d){var b=[this._round(Event.pointerX(d),this.options.gridX),this._round(Event.pointerY(d),this.options.gridY)];var q=b[0]-this.pointer[0];var p=b[1]-this.pointer[1];if(this.doResize){var o=this.widthOrg+q;var f=this.heightOrg+p;q=this.width-this.widthOrg;p=this.height-this.heightOrg;if(this.useLeft){o=this._updateWidthConstraint(o)}else{this.currentDrag.setStyle({right:(this.rightOrg-q)+"px"})}if(this.useTop){f=this._updateHeightConstraint(f)}else{this.currentDrag.setStyle({bottom:(this.bottomOrg-p)+"px"})}this.setSize(o,f);this._notify("onResize")}else{this.pointer=b;if(this.useLeft){var e=parseFloat(this.currentDrag.getStyle("left"))+q;var n=this._updateLeftConstraint(e);this.pointer[0]+=n-e;this.currentDrag.setStyle({left:n+"px"})}else{this.currentDrag.setStyle({right:parseFloat(this.currentDrag.getStyle("right"))-q+"px"})}if(this.useTop){var l=parseFloat(this.currentDrag.getStyle("top"))+p;var g=this._updateTopConstraint(l);this.pointer[1]+=g-l;this.currentDrag.setStyle({top:g+"px"})}else{this.currentDrag.setStyle({bottom:parseFloat(this.currentDrag.getStyle("bottom"))-p+"px"})}this._notify("onMove")}if(this.iefix){this._fixIEOverlapping()}this._removeStoreLocation();Event.stop(d)},_endDrag:function(b){WindowUtilities.enableScreen("__invisible__");if(this.doResize){this._notify("onEndResize")}else{this._notify("onEndMove")}Event.stopObserving(document,"mouseup",this.eventMouseUp,false);Event.stopObserving(document,"mousemove",this.eventMouseMove,false);Event.stop(b);this._hideWiredElement();this._saveCookie();document.body.ondrag=null;document.body.onselectstart=null},_updateLeftConstraint:function(d){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowWidth:this.options.parent.getDimensions().width;if(d<this.constraintPad.left){d=this.constraintPad.left}if(d+this.width+this.widthE+this.widthW>b-this.constraintPad.right){d=b-this.constraintPad.right-this.width-this.widthE-this.widthW}}return d},_updateTopConstraint:function(e){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowHeight:this.options.parent.getDimensions().height;var d=this.height+this.heightN+this.heightS;if(e<this.constraintPad.top){e=this.constraintPad.top}if(e+d>b-this.constraintPad.bottom){e=b-this.constraintPad.bottom-d}}return e},_updateWidthConstraint:function(b){if(this.constraint&&this.useLeft&&this.useTop){var d=this.options.parent==document.body?WindowUtilities.getPageSize().windowWidth:this.options.parent.getDimensions().width;var e=parseFloat(this.element.getStyle("left"));if(e+b+this.widthE+this.widthW>d-this.constraintPad.right){b=d-this.constraintPad.right-e-this.widthE-this.widthW}}return b},_updateHeightConstraint:function(d){if(this.constraint&&this.useLeft&&this.useTop){var b=this.options.parent==document.body?WindowUtilities.getPageSize().windowHeight:this.options.parent.getDimensions().height;var e=parseFloat(this.element.getStyle("top"));if(e+d+this.heightN+this.heightS>b-this.constraintPad.bottom){d=b-this.constraintPad.bottom-e-this.heightN-this.heightS}}return d},_createWindow:function(b){var h=this.options.className;var f=document.createElement("div");f.setAttribute("id",b);f.className="dialog";if(this.options.windowClassName){f.className+=" "+this.options.windowClassName}var g;if(this.options.url){g='<iframe frameborder="0" name="'+b+'_content" id="'+b+'_content" src="'+this.options.url+'"> </iframe>'}else{g='<div id="'+b+'_content" class="'+h+'_content"> </div>'}var l=this.options.closable?"<div class='"+h+"_close' id='"+b+"_close' onclick='Windows.close(\""+b+"\", event)'> </div>":"";var n=this.options.minimizable?"<div class='"+h+"_minimize' id='"+b+"_minimize' onclick='Windows.minimize(\""+b+"\", event)'> </div>":"";var o=this.options.maximizable?"<div class='"+h+"_maximize' id='"+b+"_maximize' onclick='Windows.maximize(\""+b+"\", event)'> </div>":"";var e=this.options.resizable?"class='"+h+"_sizer' id='"+b+"_sizer'":"class='"+h+"_se'";var d="../themes/default/blank.gif";f.innerHTML=l+n+o+" <a href='#' id='"+b+"_focus_anchor'><!-- --></a> <table id='"+b+"_row1' class=\"top table_window\"> <tr> <td class='"+h+"_nw'></td> <td class='"+h+"_n'><div id='"+b+"_top' class='"+h+"_title title_window'>"+this.options.title+"</div></td> <td class='"+h+"_ne'></td> </tr> </table> <table id='"+b+"_row2' class=\"mid table_window\"> <tr> <td class='"+h+"_w'></td> <td id='"+b+"_table_content' class='"+h+"_content' valign='top'>"+g+"</td> <td class='"+h+"_e'></td> </tr> </table> <table id='"+b+"_row3' class=\"bot table_window\"> <tr> <td class='"+h+"_sw'></td> <td class='"+h+"_s'><div id='"+b+"_bottom' class='status_bar'><span style='float:left; width:1px; height:1px'></span></div></td> <td "+e+"></td> </tr> </table> ";Element.hide(f);this.options.parent.insertBefore(f,this.options.parent.firstChild);Event.observe($(b+"_content"),"load",this.options.onload);return f},changeClassName:function(b){var d=this.options.className;var e=this.getId();$A(["_close","_minimize","_maximize","_sizer","_content"]).each(function(f){this._toggleClassName($(e+f),d+f,b+f)}.bind(this));this._toggleClassName($(e+"_top"),d+"_title",b+"_title");$$("#"+e+" td").each(function(f){f.className=f.className.sub(d,b)});this.options.className=b},_toggleClassName:function(e,d,b){if(e){e.removeClassName(d);e.addClassName(b)}},setLocation:function(f,d){f=this._updateTopConstraint(f);d=this._updateLeftConstraint(d);var b=this.currentDrag||this.element;b.setStyle({top:f+"px"});b.setStyle({left:d+"px"});this.useLeft=true;this.useTop=true},getLocation:function(){var b={};if(this.useTop){b=Object.extend(b,{top:this.element.getStyle("top")})}else{b=Object.extend(b,{bottom:this.element.getStyle("bottom")})}if(this.useLeft){b=Object.extend(b,{left:this.element.getStyle("left")})}else{b=Object.extend(b,{right:this.element.getStyle("right")})}return b},getSize:function(){return{width:this.width,height:this.height}},setSize:function(f,d,b){f=parseFloat(f);d=parseFloat(d);if(!this.minimized&&f<this.options.minWidth){f=this.options.minWidth}if(!this.minimized&&d<this.options.minHeight){d=this.options.minHeight}if(this.options.maxHeight&&d>this.options.maxHeight){d=this.options.maxHeight}if(this.options.maxWidth&&f>this.options.maxWidth){f=this.options.maxWidth}if(this.useTop&&this.useLeft&&Window.hasEffectLib&&Effect.ResizeWindow&&b){new Effect.ResizeWindow(this,null,null,f,d,{duration:Window.resizeEffectDuration})}else{this.width=f;this.height=d;var h=this.currentDrag?this.currentDrag:this.element;h.setStyle({width:f+this.widthW+this.widthE+"px"});h.setStyle({height:d+this.heightN+this.heightS+"px"});if(!this.currentDrag||this.currentDrag==this.element){var g=$(this.element.id+"_content");g.setStyle({height:d+"px"});g.setStyle({width:f+"px"})}}},updateHeight:function(){this.setSize(this.width,this.content.scrollHeight,true)},updateWidth:function(){this.setSize(this.content.scrollWidth,this.height,true)},toFront:function(){if(this.element.style.zIndex<Windows.maxZIndex){this.setZIndex(Windows.maxZIndex+1)}if(this.iefix){this._fixIEOverlapping()}},getBounds:function(d){if(!this.width||!this.height||!this.visible){this.computeBounds()}var b=this.width;var e=this.height;if(!d){b+=this.widthW+this.widthE;e+=this.heightN+this.heightS}var f=Object.extend(this.getLocation(),{width:b+"px",height:e+"px"});return f},computeBounds:function(){if(!this.width||!this.height){var b=WindowUtilities._computeSize(this.content.innerHTML,this.content.id,this.width,this.height,0,this.options.className);if(this.height){this.width=b+5}else{this.height=b+5}}this.setSize(this.width,this.height);if(this.centered){this._center(this.centerTop,this.centerLeft)}},show:function(d){this.visible=true;if(d){if(typeof this.overlayOpacity=="undefined"){var b=this;setTimeout(function(){b.show(d)},10);return}Windows.addModalWindow(this);this.modal=true;this.setZIndex(Windows.maxZIndex+1);Windows.unsetOverflow(this)}else{if(!this.element.style.zIndex){this.setZIndex(Windows.maxZIndex+1)}}if(this.oldStyle){this.getContent().setStyle({overflow:this.oldStyle})}this.computeBounds();this._notify("onBeforeShow");if(this.options.showEffect!=Element.show&&this.options.showEffectOptions){this.options.showEffect(this.element,this.options.showEffectOptions)}else{this.options.showEffect(this.element)}this._checkIEOverlapping();WindowUtilities.focusedWindow=this;this._notify("onShow");$(this.element.id+"_focus_anchor").focus()},showCenter:function(b,e,d){this.centered=true;this.centerTop=e;this.centerLeft=d;this.show(b)},isVisible:function(){return this.visible},_center:function(e,d){var f=WindowUtilities.getWindowScroll(this.options.parent);var b=WindowUtilities.getPageSize(this.options.parent);if(typeof e=="undefined"){e=(b.windowHeight-(this.height+this.heightN+this.heightS))/2}e+=f.top;if(typeof d=="undefined"){d=(b.windowWidth-(this.width+this.widthW+this.widthE))/2}d+=f.left;this.setLocation(e,d);this.toFront()},_recenter:function(d){if(this.centered){var b=WindowUtilities.getPageSize(this.options.parent);var e=WindowUtilities.getWindowScroll(this.options.parent);if(this.pageSize&&this.pageSize.windowWidth==b.windowWidth&&this.pageSize.windowHeight==b.windowHeight&&this.windowScroll.left==e.left&&this.windowScroll.top==e.top){return}this.pageSize=b;this.windowScroll=e;if($("overlay_modal")){$("overlay_modal").setStyle({height:(b.pageHeight+"px")})}if(this.options.recenterAuto){this._center(this.centerTop,this.centerLeft)}}},hide:function(){this.visible=false;if(this.modal){Windows.removeModalWindow(this);Windows.resetOverflow()}this.oldStyle=this.getContent().getStyle("overflow")||"auto";this.getContent().setStyle({overflow:"hidden"});this.options.hideEffect(this.element,this.options.hideEffectOptions);if(this.iefix){this.iefix.hide()}if(!this.doNotNotifyHide){this._notify("onHide")}},close:function(){if(this.visible){if(this.options.closeCallback&&!this.options.closeCallback(this)){return}if(this.options.destroyOnClose){var b=this.destroy.bind(this);if(this.options.hideEffectOptions.afterFinish){var d=this.options.hideEffectOptions.afterFinish;this.options.hideEffectOptions.afterFinish=function(){d();b()}}else{this.options.hideEffectOptions.afterFinish=function(){b()}}}Windows.updateFocusedWindow();this.doNotNotifyHide=true;this.hide();this.doNotNotifyHide=false;this._notify("onClose")}},minimize:function(){if(this.resizing){return}var b=$(this.getId()+"_row2");if(!this.minimized){this.minimized=true;var f=b.getDimensions().height;this.r2Height=f;var e=this.element.getHeight()-f;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,null,null,null,this.height-f,{duration:Window.resizeEffectDuration})}else{this.height-=f;this.element.setStyle({height:e+"px"});b.hide()}if(!this.useTop){var d=parseFloat(this.element.getStyle("bottom"));this.element.setStyle({bottom:(d+f)+"px"})}}else{this.minimized=false;var f=this.r2Height;this.r2Height=null;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,null,null,null,this.height+f,{duration:Window.resizeEffectDuration})}else{var e=this.element.getHeight()+f;this.height+=f;this.element.setStyle({height:e+"px"});b.show()}if(!this.useTop){var d=parseFloat(this.element.getStyle("bottom"));this.element.setStyle({bottom:(d-f)+"px"})}this.toFront()}this._notify("onMinimize");this._saveCookie()},maximize:function(){if(this.isMinimized()||this.resizing){return}if(Prototype.Browser.IE&&this.heightN==0){this._getWindowBorderSize()}if(this.storedLocation!=null){this._restoreLocation();if(this.iefix){this.iefix.hide()}}else{this._storeLocation();Windows.unsetOverflow(this);var l=WindowUtilities.getWindowScroll(this.options.parent);var d=WindowUtilities.getPageSize(this.options.parent);var h=l.left;var g=l.top;if(this.options.parent!=document.body){l={top:0,left:0,bottom:0,right:0};var f=this.options.parent.getDimensions();d.windowWidth=f.width;d.windowHeight=f.height;g=0;h=0}if(this.constraint){d.windowWidth-=Math.max(0,this.constraintPad.left)+Math.max(0,this.constraintPad.right);d.windowHeight-=Math.max(0,this.constraintPad.top)+Math.max(0,this.constraintPad.bottom);h+=Math.max(0,this.constraintPad.left);g+=Math.max(0,this.constraintPad.top)}var e=d.windowWidth-this.widthW-this.widthE;var b=d.windowHeight-this.heightN-this.heightS;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,g,h,e,b,{duration:Window.resizeEffectDuration})}else{this.setSize(e,b);this.element.setStyle(this.useLeft?{left:h}:{right:h});this.element.setStyle(this.useTop?{top:g}:{bottom:g})}this.toFront();if(this.iefix){this._fixIEOverlapping()}}this._notify("onMaximize");this._saveCookie()},isMinimized:function(){return this.minimized},isMaximized:function(){return(this.storedLocation!=null)},setOpacity:function(b){if(Element.setOpacity){Element.setOpacity(this.element,b)}},setZIndex:function(b){this.element.setStyle({zIndex:b});Windows.updateZindex(b,this)},setTitle:function(b){if(!b||b==""){b=" "}Element.update(this.element.id+"_top",b)},getTitle:function(){return $(this.element.id+"_top").innerHTML},setStatusBar:function(d){var b=$(this.getId()+"_bottom");if(typeof(d)=="object"){if(this.bottombar.firstChild){this.bottombar.replaceChild(d,this.bottombar.firstChild)}else{this.bottombar.appendChild(d)}}else{this.bottombar.innerHTML=d}},_checkIEOverlapping:function(){if(!this.iefix&&(navigator.appVersion.indexOf("MSIE")>0)&&(navigator.userAgent.indexOf("Opera")<0)&&(this.element.getStyle("position")=="absolute")){new Insertion.After(this.element.id,'<iframe id="'+this.element.id+'_iefix" style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" src="javascript:false;" frameborder="0" scrolling="no"></iframe>');this.iefix=$(this.element.id+"_iefix")}if(this.iefix){setTimeout(this._fixIEOverlapping.bind(this),50)}},_fixIEOverlapping:function(){Position.clone(this.element,this.iefix);this.iefix.style.zIndex=this.element.style.zIndex-1;this.iefix.show()},_keyUp:function(b){if(27==b.keyCode&&this.options.closeOnEsc){this.close()}},_getWindowBorderSize:function(d){var e=this._createHiddenDiv(this.options.className+"_n");this.heightN=Element.getDimensions(e).height;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_s");this.heightS=Element.getDimensions(e).height;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_e");this.widthE=Element.getDimensions(e).width;e.parentNode.removeChild(e);var e=this._createHiddenDiv(this.options.className+"_w");this.widthW=Element.getDimensions(e).width;e.parentNode.removeChild(e);var e=document.createElement("div");e.className="overlay_"+this.options.className;document.body.appendChild(e);var b=this;setTimeout(function(){b.overlayOpacity=($(e).getStyle("opacity"));e.parentNode.removeChild(e)},10);if(Prototype.Browser.IE){this.heightS=$(this.getId()+"_row3").getDimensions().height;this.heightN=$(this.getId()+"_row1").getDimensions().height}if(Prototype.Browser.WebKit&&Prototype.Browser.WebKitVersion<420){this.setSize(this.width,this.height)}if(this.doMaximize){this.maximize()}if(this.doMinimize){this.minimize()}},_createHiddenDiv:function(d){var b=document.body;var e=document.createElement("div");e.setAttribute("id",this.element.id+"_tmp");e.className=d;e.style.display="none";e.innerHTML="";b.insertBefore(e,b.firstChild);return e},_storeLocation:function(){if(this.storedLocation==null){this.storedLocation={useTop:this.useTop,useLeft:this.useLeft,top:this.element.getStyle("top"),bottom:this.element.getStyle("bottom"),left:this.element.getStyle("left"),right:this.element.getStyle("right"),width:this.width,height:this.height}}},_restoreLocation:function(){if(this.storedLocation!=null){this.useLeft=this.storedLocation.useLeft;this.useTop=this.storedLocation.useTop;if(this.useLeft&&this.useTop&&Window.hasEffectLib&&Effect.ResizeWindow){new Effect.ResizeWindow(this,this.storedLocation.top,this.storedLocation.left,this.storedLocation.width,this.storedLocation.height,{duration:Window.resizeEffectDuration})}else{this.element.setStyle(this.useLeft?{left:this.storedLocation.left}:{right:this.storedLocation.right});this.element.setStyle(this.useTop?{top:this.storedLocation.top}:{bottom:this.storedLocation.bottom});this.setSize(this.storedLocation.width,this.storedLocation.height)}Windows.resetOverflow();this._removeStoreLocation()}},_removeStoreLocation:function(){this.storedLocation=null},_saveCookie:function(){if(this.cookie){var b="";if(this.useLeft){b+="l:"+(this.storedLocation?this.storedLocation.left:this.element.getStyle("left"))}else{b+="r:"+(this.storedLocation?this.storedLocation.right:this.element.getStyle("right"))}if(this.useTop){b+=",t:"+(this.storedLocation?this.storedLocation.top:this.element.getStyle("top"))}else{b+=",b:"+(this.storedLocation?this.storedLocation.bottom:this.element.getStyle("bottom"))}b+=","+(this.storedLocation?this.storedLocation.width:this.width);b+=","+(this.storedLocation?this.storedLocation.height:this.height);b+=","+this.isMinimized();b+=","+this.isMaximized();WindowUtilities.setCookie(b,this.cookie)}},_createWiredElement:function(){if(!this.wiredElement){if(Prototype.Browser.IE){this._getWindowBorderSize()}var d=document.createElement("div");d.className="wired_frame "+this.options.className+"_wired_frame";d.style.position="absolute";this.options.parent.insertBefore(d,this.options.parent.firstChild);this.wiredElement=$(d)}if(this.useLeft){this.wiredElement.setStyle({left:this.element.getStyle("left")})}else{this.wiredElement.setStyle({right:this.element.getStyle("right")})}if(this.useTop){this.wiredElement.setStyle({top:this.element.getStyle("top")})}else{this.wiredElement.setStyle({bottom:this.element.getStyle("bottom")})}var b=this.element.getDimensions();this.wiredElement.setStyle({width:b.width+"px",height:b.height+"px"});this.wiredElement.setStyle({zIndex:Windows.maxZIndex+30});return this.wiredElement},_hideWiredElement:function(){if(!this.wiredElement||!this.currentDrag){return}if(this.currentDrag==this.element){this.currentDrag=null}else{if(this.useLeft){this.element.setStyle({left:this.currentDrag.getStyle("left")})}else{this.element.setStyle({right:this.currentDrag.getStyle("right")})}if(this.useTop){this.element.setStyle({top:this.currentDrag.getStyle("top")})}else{this.element.setStyle({bottom:this.currentDrag.getStyle("bottom")})}this.currentDrag.hide();this.currentDrag=null;if(this.doResize){this.setSize(this.width,this.height)}}},_notify:function(b){if(this.options[b]){this.options[b](this)}else{Windows.notify(b,this)}}};var Windows={windows:[],modalWindows:[],observers:[],focusedWindow:null,maxZIndex:0,overlayShowEffectOptions:{duration:0.5},overlayHideEffectOptions:{duration:0.5},addObserver:function(b){this.removeObserver(b);this.observers.push(b)},removeObserver:function(b){this.observers=this.observers.reject(function(d){return d==b})},notify:function(b,d){this.observers.each(function(e){if(e[b]){e[b](b,d)}})},getWindow:function(b){return this.windows.detect(function(e){return e.getId()==b})},getFocusedWindow:function(){return this.focusedWindow},updateFocusedWindow:function(){this.focusedWindow=this.windows.length>=2?this.windows[this.windows.length-2]:null},register:function(b){this.windows.push(b)},addModalWindow:function(b){if(this.modalWindows.length==0){WindowUtilities.disableScreen(b.options.className,"overlay_modal",b.overlayOpacity,b.getId(),b.options.parent)}else{if(Window.keepMultiModalWindow){$("overlay_modal").style.zIndex=Windows.maxZIndex+1;Windows.maxZIndex+=1;WindowUtilities._hideSelect(this.modalWindows.last().getId())}else{this.modalWindows.last().element.hide()}WindowUtilities._showSelect(b.getId())}this.modalWindows.push(b)},removeModalWindow:function(b){this.modalWindows.pop();if(this.modalWindows.length==0){WindowUtilities.enableScreen()}else{if(Window.keepMultiModalWindow){this.modalWindows.last().toFront();WindowUtilities._showSelect(this.modalWindows.last().getId())}else{this.modalWindows.last().element.show()}}},register:function(b){this.windows.push(b)},unregister:function(b){this.windows=this.windows.reject(function(e){return e==b})},closeAll:function(){this.windows.each(function(b){Windows.close(b.getId())})},closeAllModalWindows:function(){WindowUtilities.enableScreen();this.modalWindows.each(function(b){if(b){b.close()}})},minimize:function(e,b){var d=this.getWindow(e);if(d&&d.visible){d.minimize()}Event.stop(b)},maximize:function(e,b){var d=this.getWindow(e);if(d&&d.visible){d.maximize()}Event.stop(b)},close:function(e,b){var d=this.getWindow(e);if(d){d.close()}if(b){Event.stop(b)}},blur:function(d){var b=this.getWindow(d);if(!b){return}if(b.options.blurClassName){b.changeClassName(b.options.blurClassName)}if(this.focusedWindow==b){this.focusedWindow=null}b._notify("onBlur")},focus:function(d){var b=this.getWindow(d);if(!b){return}if(this.focusedWindow){this.blur(this.focusedWindow.getId())}if(b.options.focusClassName){b.changeClassName(b.options.focusClassName)}this.focusedWindow=b;b._notify("onFocus")},unsetOverflow:function(b){this.windows.each(function(e){e.oldOverflow=e.getContent().getStyle("overflow")||"auto";e.getContent().setStyle({overflow:"hidden"})});if(b&&b.oldOverflow){b.getContent().setStyle({overflow:b.oldOverflow})}},resetOverflow:function(){this.windows.each(function(b){if(b.oldOverflow){b.getContent().setStyle({overflow:b.oldOverflow})}})},updateZindex:function(b,d){if(b>this.maxZIndex){this.maxZIndex=b;if(this.focusedWindow){this.blur(this.focusedWindow.getId())}}this.focusedWindow=d;if(this.focusedWindow){this.focus(this.focusedWindow.getId())}}};var Dialog={dialogId:null,onCompleteFunc:null,callFunc:null,parameters:null,confirm:function(f,e){if(f&&typeof f!="string"){Dialog._runAjaxRequest(f,e,Dialog.confirm);return}f=f||"";e=e||{};var h=e.okLabel?e.okLabel:"Ok";var b=e.cancelLabel?e.cancelLabel:"Cancel";e=Object.extend(e,e.windowParameters||{});e.windowParameters=e.windowParameters||{};e.className=e.className||"alert";var d="class ='"+(e.buttonClass?e.buttonClass+" ":"")+" ok_button'";var g="class ='"+(e.buttonClass?e.buttonClass+" ":"")+" cancel_button'";var f=" <div class='"+e.className+"_message'>"+f+"</div> <div class='"+e.className+"_buttons'> <button type='button' title='"+h+"' onclick='Dialog.okCallback()' "+d+"><span><span><span>"+h+"</span></span></span></button> <button type='button' title='"+b+"' onclick='Dialog.cancelCallback()' "+g+"><span><span><span>"+b+"</span></span></span></button> </div> ";return this._openDialog(f,e)},alert:function(e,d){if(e&&typeof e!="string"){Dialog._runAjaxRequest(e,d,Dialog.alert);return}e=e||"";d=d||{};var f=d.okLabel?d.okLabel:"Ok";d=Object.extend(d,d.windowParameters||{});d.windowParameters=d.windowParameters||{};d.className=d.className||"alert";var b="class ='"+(d.buttonClass?d.buttonClass+" ":"")+" ok_button'";var e=" <div class='"+d.className+"_message'>"+e+"</div> <div class='"+d.className+"_buttons'> <button type='button' title='"+f+"' onclick='Dialog.okCallback()' "+b+"><span><span><span>"+f+"</span></span></span></button> </div>";return this._openDialog(e,d)},info:function(d,b){if(d&&typeof d!="string"){Dialog._runAjaxRequest(d,b,Dialog.info);return}d=d||"";b=b||{};b=Object.extend(b,b.windowParameters||{});b.windowParameters=b.windowParameters||{};b.className=b.className||"alert";var d="<div id='modal_dialog_message' class='"+b.className+"_message'>"+d+"</div>";if(b.showProgress){d+="<div id='modal_dialog_progress' class='"+b.className+"_progress'> </div>"}b.ok=null;b.cancel=null;return this._openDialog(d,b)},setInfoMessage:function(b){$("modal_dialog_message").update(b)},closeInfo:function(){Windows.close(this.dialogId)},_openDialog:function(g,f){var e=f.className;if(!f.height&&!f.width){f.width=WindowUtilities.getPageSize(f.options.parent||document.body).pageWidth/2}if(f.id){this.dialogId=f.id}else{var d=new Date();this.dialogId="modal_dialog_"+d.getTime();f.id=this.dialogId}if(!f.height||!f.width){var b=WindowUtilities._computeSize(g,this.dialogId,f.width,f.height,5,e);if(f.height){f.width=b+5}else{f.height=b+5}}f.effectOptions=f.effectOptions;f.resizable=f.resizable||false;f.minimizable=f.minimizable||false;f.maximizable=f.maximizable||false;f.draggable=f.draggable||false;f.closable=f.closable||false;var h=new Window(f);h.getContent().innerHTML=g;h.showCenter(true,f.top,f.left);h.setDestroyOnClose();h.cancelCallback=f.onCancel||f.cancel;h.okCallback=f.onOk||f.ok;return h},_getAjaxContent:function(b){Dialog.callFunc(b.responseText,Dialog.parameters)},_runAjaxRequest:function(e,d,b){if(e.options==null){e.options={}}Dialog.onCompleteFunc=e.options.onComplete;Dialog.parameters=d;Dialog.callFunc=b;e.options.onComplete=Dialog._getAjaxContent;new Ajax.Request(e.url,e.options)},okCallback:function(){var b=Windows.focusedWindow;if(!b.okCallback||b.okCallback(b)){$$("#"+b.getId()+" input").each(function(d){d.onclick=null});b.close()}},cancelCallback:function(){var b=Windows.focusedWindow;$$("#"+b.getId()+" input").each(function(d){d.onclick=null});b.close();if(b.cancelCallback){b.cancelCallback(b)}}};if(Prototype.Browser.WebKit){var array=navigator.userAgent.match(new RegExp(/AppleWebKit\/([\d\.\+]*)/));Prototype.Browser.WebKitVersion=parseFloat(array[1])}var WindowUtilities={getWindowScroll:function(parent){var T,L,W,H;parent=parent||document.body;if(parent!=document.body){T=parent.scrollTop;L=parent.scrollLeft;W=parent.scrollWidth;H=parent.scrollHeight}else{var w=window;with(w.document){if(w.document.documentElement&&documentElement.scrollTop){T=documentElement.scrollTop;L=documentElement.scrollLeft}else{if(w.document.body){T=body.scrollTop;L=body.scrollLeft}}if(w.innerWidth){W=w.innerWidth;H=w.innerHeight}else{if(w.document.documentElement&&documentElement.clientWidth){W=documentElement.clientWidth;H=documentElement.clientHeight}else{W=body.offsetWidth;H=body.offsetHeight}}}}return{top:T,left:L,width:W,height:H}},getPageSize:function(f){f=f||document.body;var e,l;var g,d;if(f!=document.body){e=f.getWidth();l=f.getHeight();d=f.scrollWidth;g=f.scrollHeight}else{var h,b;if(window.innerHeight&&window.scrollMaxY){h=document.body.scrollWidth;b=window.innerHeight+window.scrollMaxY}else{if(document.body.scrollHeight>document.body.offsetHeight){h=document.body.scrollWidth;b=document.body.scrollHeight}else{h=document.body.offsetWidth;b=document.body.offsetHeight}}if(self.innerHeight){e=document.documentElement.clientWidth;l=self.innerHeight}else{if(document.documentElement&&document.documentElement.clientHeight){e=document.documentElement.clientWidth;l=document.documentElement.clientHeight}else{if(document.body){e=document.body.clientWidth;l=document.body.clientHeight}}}if(b<l){g=l}else{g=b}if(h<e){d=e}else{d=h}}return{pageWidth:d,pageHeight:g,windowWidth:e,windowHeight:l}},disableScreen:function(e,b,f,g,d){WindowUtilities.initLightbox(b,e,function(){this._disableScreen(e,b,f,g)}.bind(this),d||document.body)},_disableScreen:function(e,d,g,h){var f=$(d);var b=WindowUtilities.getPageSize(f.parentNode);if(h&&Prototype.Browser.IE){WindowUtilities._hideSelect();WindowUtilities._showSelect(h)}f.style.height=(b.pageHeight+"px");f.style.display="none";if(d=="overlay_modal"&&Window.hasEffectLib&&Windows.overlayShowEffectOptions){f.overlayOpacity=g;new Effect.Appear(f,Object.extend({from:0,to:g},Windows.overlayShowEffectOptions))}else{f.style.display="block"}},enableScreen:function(d){d=d||"overlay_modal";var b=$(d);if(b){if(d=="overlay_modal"&&Window.hasEffectLib&&Windows.overlayHideEffectOptions){new Effect.Fade(b,Object.extend({from:b.overlayOpacity,to:0},Windows.overlayHideEffectOptions))}else{b.style.display="none";b.parentNode.removeChild(b)}if(d!="__invisible__"){WindowUtilities._showSelect()}}},_hideSelect:function(b){if(Prototype.Browser.IE){b=b==null?"":"#"+b+" ";$$(b+"select").each(function(d){if(!WindowUtilities.isDefined(d.oldVisibility)){d.oldVisibility=d.style.visibility?d.style.visibility:"visible";d.style.visibility="hidden"}})}},_showSelect:function(b){if(Prototype.Browser.IE){b=b==null?"":"#"+b+" ";$$(b+"select").each(function(d){if(WindowUtilities.isDefined(d.oldVisibility)){try{d.style.visibility=d.oldVisibility}catch(f){d.style.visibility="visible"}d.oldVisibility=null}else{if(d.style.visibility){d.style.visibility="visible"}}})}},isDefined:function(b){return typeof(b)!="undefined"&&b!=null},initLightbox:function(g,e,b,d){if($(g)){Element.setStyle(g,{zIndex:Windows.maxZIndex+1});Windows.maxZIndex++;b()}else{var f=document.createElement("div");f.setAttribute("id",g);f.className="overlay_"+e;f.style.display="none";f.style.position="absolute";f.style.top="0";f.style.left="0";f.style.zIndex=Windows.maxZIndex+1;Windows.maxZIndex++;f.style.width="100%";d.insertBefore(f,d.firstChild);if(Prototype.Browser.WebKit&&g=="overlay_modal"){setTimeout(function(){b()},10)}else{b()}}},setCookie:function(d,b){document.cookie=b[0]+"="+escape(d)+((b[1])?"; expires="+b[1].toGMTString():"")+((b[2])?"; path="+b[2]:"")+((b[3])?"; domain="+b[3]:"")+((b[4])?"; secure":"")},getCookie:function(e){var d=document.cookie;var g=e+"=";var f=d.indexOf("; "+g);if(f==-1){f=d.indexOf(g);if(f!=0){return null}}else{f+=2}var b=document.cookie.indexOf(";",f);if(b==-1){b=d.length}return unescape(d.substring(f+g.length,b))},_computeSize:function(g,b,d,l,f,h){var o=document.body;var e=document.createElement("div");e.setAttribute("id",b);e.className=h+"_content";if(l){e.style.height=l+"px"}else{e.style.width=d+"px"}e.style.position="absolute";e.style.top="0";e.style.left="0";e.style.display="none";e.innerHTML=g;o.insertBefore(e,o.firstChild);var n;if(l){n=$(e).getDimensions().width+f}else{n=$(e).getDimensions().height+f}o.removeChild(e);return n}};var Builder={NODEMAP:{AREA:"map",CAPTION:"table",COL:"table",COLGROUP:"table",LEGEND:"fieldset",OPTGROUP:"select",OPTION:"select",PARAM:"object",TBODY:"table",TD:"table",TFOOT:"table",TH:"table",THEAD:"table",TR:"table"},node:function(b){b=b.toUpperCase();var l=this.NODEMAP[b]||"div";var d=document.createElement(l);try{d.innerHTML="<"+b+"></"+b+">"}catch(h){}var g=d.firstChild||null;if(g&&(g.tagName.toUpperCase()!=b)){g=g.getElementsByTagName(b)[0]}if(!g){g=document.createElement(b)}if(!g){return}if(arguments[1]){if(this._isStringOrNumber(arguments[1])||(arguments[1] instanceof Array)||arguments[1].tagName){this._children(g,arguments[1])}else{var f=this._attributes(arguments[1]);if(f.length){try{d.innerHTML="<"+b+" "+f+"></"+b+">"}catch(h){}g=d.firstChild||null;if(!g){g=document.createElement(b);for(attr in arguments[1]){g[attr=="class"?"className":attr]=arguments[1][attr]}}if(g.tagName.toUpperCase()!=b){g=d.getElementsByTagName(b)[0]}}}}if(arguments[2]){this._children(g,arguments[2])}return $(g)},_text:function(b){return document.createTextNode(b)},ATTR_MAP:{className:"class",htmlFor:"for"},_attributes:function(b){var d=[];for(attribute in b){d.push((attribute in this.ATTR_MAP?this.ATTR_MAP[attribute]:attribute)+'="'+b[attribute].toString().escapeHTML().gsub(/"/,""")+'"')}return d.join(" ")},_children:function(d,b){if(b.tagName){d.appendChild(b);return}if(typeof b=="object"){b.flatten().each(function(f){if(typeof f=="object"){d.appendChild(f)}else{if(Builder._isStringOrNumber(f)){d.appendChild(Builder._text(f))}}})}else{if(Builder._isStringOrNumber(b)){d.appendChild(Builder._text(b))}}},_isStringOrNumber:function(b){return(typeof b=="string"||typeof b=="number")},build:function(d){var b=this.node("div");$(b).update(d.strip());return b.down()},dump:function(d){if(typeof d!="object"&&typeof d!="function"){d=window}var b=("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);b.each(function(e){d[e]=function(){return Builder.node.apply(Builder,[e].concat($A(arguments)))}})}};String.prototype.parseColor=function(){var b="#";if(this.slice(0,4)=="rgb("){var e=this.slice(4,this.length-1).split(",");var d=0;do{b+=parseInt(e[d]).toColorPart()}while(++d<3)}else{if(this.slice(0,1)=="#"){if(this.length==4){for(var d=1;d<4;d++){b+=(this.charAt(d)+this.charAt(d)).toLowerCase()}}if(this.length==7){b=this.toLowerCase()}}}return(b.length==7?b:(arguments[0]||this))};Element.collectTextNodes=function(b){return $A($(b).childNodes).collect(function(d){return(d.nodeType==3?d.nodeValue:(d.hasChildNodes()?Element.collectTextNodes(d):""))}).flatten().join("")};Element.collectTextNodesIgnoreClass=function(b,d){return $A($(b).childNodes).collect(function(e){return(e.nodeType==3?e.nodeValue:((e.hasChildNodes()&&!Element.hasClassName(e,d))?Element.collectTextNodesIgnoreClass(e,d):""))}).flatten().join("")};Element.setContentZoom=function(b,d){b=$(b);b.setStyle({fontSize:(d/100)+"em"});if(Prototype.Browser.WebKit){window.scrollBy(0,0)}return b};Element.getInlineOpacity=function(b){return $(b).style.opacity||""};Element.forceRerendering=function(b){try{b=$(b);var f=document.createTextNode(" ");b.appendChild(f);b.removeChild(f)}catch(d){}};var Effect={_elementDoesNotExistError:{name:"ElementDoesNotExistError",message:"The specified DOM element does not exist, but is required for this effect to operate"},Transitions:{linear:Prototype.K,sinoidal:function(b){return(-Math.cos(b*Math.PI)/2)+0.5},reverse:function(b){return 1-b},flicker:function(b){var b=((-Math.cos(b*Math.PI)/4)+0.75)+Math.random()/4;return b>1?1:b},wobble:function(b){return(-Math.cos(b*Math.PI*(9*b))/2)+0.5},pulse:function(d,b){return(-Math.cos((d*((b||5)-0.5)*2)*Math.PI)/2)+0.5},spring:function(b){return 1-(Math.cos(b*4.5*Math.PI)*Math.exp(-b*6))},none:function(b){return 0},full:function(b){return 1}},DefaultOptions:{duration:1,fps:100,sync:false,from:0,to:1,delay:0,queue:"parallel"},tagifyText:function(b){var d="position:relative";if(Prototype.Browser.IE){d+=";zoom:1"}b=$(b);$A(b.childNodes).each(function(e){if(e.nodeType==3){e.nodeValue.toArray().each(function(f){b.insertBefore(new Element("span",{style:d}).update(f==" "?String.fromCharCode(160):f),e)});Element.remove(e)}})},multiple:function(d,e){var g;if(((typeof d=="object")||Object.isFunction(d))&&(d.length)){g=d}else{g=$(d).childNodes}var b=Object.extend({speed:0.1,delay:0},arguments[2]||{});var f=b.delay;$A(g).each(function(l,h){new e(l,Object.extend(b,{delay:h*b.speed+f}))})},PAIRS:{slide:["SlideDown","SlideUp"],blind:["BlindDown","BlindUp"],appear:["Appear","Fade"]},toggle:function(d,e){d=$(d);e=(e||"appear").toLowerCase();var b=Object.extend({queue:{position:"end",scope:(d.id||"global"),limit:1}},arguments[2]||{});Effect[d.visible()?Effect.PAIRS[e][1]:Effect.PAIRS[e][0]](d,b)}};Effect.DefaultOptions.transition=Effect.Transitions.sinoidal;Effect.ScopedQueue=Class.create(Enumerable,{initialize:function(){this.effects=[];this.interval=null},_each:function(b){this.effects._each(b)},add:function(d){var e=new Date().getTime();var b=Object.isString(d.options.queue)?d.options.queue:d.options.queue.position;switch(b){case"front":this.effects.findAll(function(f){return f.state=="idle"}).each(function(f){f.startOn+=d.finishOn;f.finishOn+=d.finishOn});break;case"with-last":e=this.effects.pluck("startOn").max()||e;break;case"end":e=this.effects.pluck("finishOn").max()||e;break}d.startOn+=e;d.finishOn+=e;if(!d.options.queue.limit||(this.effects.length<d.options.queue.limit)){this.effects.push(d)}if(!this.interval){this.interval=setInterval(this.loop.bind(this),15)}},remove:function(b){this.effects=this.effects.reject(function(d){return d==b});if(this.effects.length==0){clearInterval(this.interval);this.interval=null}},loop:function(){var e=new Date().getTime();for(var d=0,b=this.effects.length;d<b;d++){this.effects[d]&&this.effects[d].loop(e)}}});Effect.Queues={instances:$H(),get:function(b){if(!Object.isString(b)){return b}return this.instances.get(b)||this.instances.set(b,new Effect.ScopedQueue())}};Effect.Queue=Effect.Queues.get("global");Effect.Base=Class.create({position:null,start:function(b){function d(f,e){return((f[e+"Internal"]?"this.options."+e+"Internal(this);":"")+(f[e]?"this.options."+e+"(this);":""))}if(b&&b.transition===false){b.transition=Effect.Transitions.linear}this.options=Object.extend(Object.extend({},Effect.DefaultOptions),b||{});this.currentFrame=0;this.state="idle";this.startOn=this.options.delay*1000;this.finishOn=this.startOn+(this.options.duration*1000);this.fromToDelta=this.options.to-this.options.from;this.totalTime=this.finishOn-this.startOn;this.totalFrames=this.options.fps*this.options.duration;this.render=(function(){function e(g,f){if(g.options[f+"Internal"]){g.options[f+"Internal"](g)}if(g.options[f]){g.options[f](g)}}return function(f){if(this.state==="idle"){this.state="running";e(this,"beforeSetup");if(this.setup){this.setup()}e(this,"afterSetup")}if(this.state==="running"){f=(this.options.transition(f)*this.fromToDelta)+this.options.from;this.position=f;e(this,"beforeUpdate");if(this.update){this.update(f)}e(this,"afterUpdate")}}})();this.event("beforeStart");if(!this.options.sync){Effect.Queues.get(Object.isString(this.options.queue)?"global":this.options.queue.scope).add(this)}},loop:function(e){if(e>=this.startOn){if(e>=this.finishOn){this.render(1);this.cancel();this.event("beforeFinish");if(this.finish){this.finish()}this.event("afterFinish");return}var d=(e-this.startOn)/this.totalTime,b=(d*this.totalFrames).round();if(b>this.currentFrame){this.render(d);this.currentFrame=b}}},cancel:function(){if(!this.options.sync){Effect.Queues.get(Object.isString(this.options.queue)?"global":this.options.queue.scope).remove(this)}this.state="finished"},event:function(b){if(this.options[b+"Internal"]){this.options[b+"Internal"](this)}if(this.options[b]){this.options[b](this)}},inspect:function(){var b=$H();for(property in this){if(!Object.isFunction(this[property])){b.set(property,this[property])}}return"#<Effect:"+b.inspect()+",options:"+$H(this.options).inspect()+">"}});Effect.Parallel=Class.create(Effect.Base,{initialize:function(b){this.effects=b||[];this.start(arguments[1])},update:function(b){this.effects.invoke("render",b)},finish:function(b){this.effects.each(function(d){d.render(1);d.cancel();d.event("beforeFinish");if(d.finish){d.finish(b)}d.event("afterFinish")})}});Effect.Tween=Class.create(Effect.Base,{initialize:function(e,h,g){e=Object.isString(e)?$(e):e;var d=$A(arguments),f=d.last(),b=d.length==5?d[3]:null;this.method=Object.isFunction(f)?f.bind(e):Object.isFunction(e[f])?e[f].bind(e):function(l){e[f]=l};this.start(Object.extend({from:h,to:g},b||{}))},update:function(b){this.method(b)}});Effect.Event=Class.create(Effect.Base,{initialize:function(){this.start(Object.extend({duration:0},arguments[0]||{}))},update:Prototype.emptyFunction});Effect.Opacity=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}if(Prototype.Browser.IE&&(!this.element.currentStyle.hasLayout)){this.element.setStyle({zoom:1})}var b=Object.extend({from:this.element.getOpacity()||0,to:1},arguments[1]||{});this.start(b)},update:function(b){this.element.setOpacity(b)}});Effect.Move=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({x:0,y:0,mode:"relative"},arguments[1]||{});this.start(b)},setup:function(){this.element.makePositioned();this.originalLeft=parseFloat(this.element.getStyle("left")||"0");this.originalTop=parseFloat(this.element.getStyle("top")||"0");if(this.options.mode=="absolute"){this.options.x=this.options.x-this.originalLeft;this.options.y=this.options.y-this.originalTop}},update:function(b){this.element.setStyle({left:(this.options.x*b+this.originalLeft).round()+"px",top:(this.options.y*b+this.originalTop).round()+"px"})}});Effect.MoveBy=function(d,b,e){return new Effect.Move(d,Object.extend({x:e,y:b},arguments[3]||{}))};Effect.Scale=Class.create(Effect.Base,{initialize:function(d,e){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:"box",scaleFrom:100,scaleTo:e},arguments[2]||{});this.start(b)},setup:function(){this.restoreAfterFinish=this.options.restoreAfterFinish||false;this.elementPositioning=this.element.getStyle("position");this.originalStyle={};["top","left","width","height","fontSize"].each(function(d){this.originalStyle[d]=this.element.style[d]}.bind(this));this.originalTop=this.element.offsetTop;this.originalLeft=this.element.offsetLeft;var b=this.element.getStyle("font-size")||"100%";["em","px","%","pt"].each(function(d){if(b.indexOf(d)>0){this.fontSize=parseFloat(b);this.fontSizeType=d}}.bind(this));this.factor=(this.options.scaleTo-this.options.scaleFrom)/100;this.dims=null;if(this.options.scaleMode=="box"){this.dims=[this.element.offsetHeight,this.element.offsetWidth]}if(/^content/.test(this.options.scaleMode)){this.dims=[this.element.scrollHeight,this.element.scrollWidth]}if(!this.dims){this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth]}},update:function(b){var d=(this.options.scaleFrom/100)+(this.factor*b);if(this.options.scaleContent&&this.fontSize){this.element.setStyle({fontSize:this.fontSize*d+this.fontSizeType})}this.setDimensions(this.dims[0]*d,this.dims[1]*d)},finish:function(b){if(this.restoreAfterFinish){this.element.setStyle(this.originalStyle)}},setDimensions:function(b,g){var h={};if(this.options.scaleX){h.width=g.round()+"px"}if(this.options.scaleY){h.height=b.round()+"px"}if(this.options.scaleFromCenter){var f=(b-this.dims[0])/2;var e=(g-this.dims[1])/2;if(this.elementPositioning=="absolute"){if(this.options.scaleY){h.top=this.originalTop-f+"px"}if(this.options.scaleX){h.left=this.originalLeft-e+"px"}}else{if(this.options.scaleY){h.top=-f+"px"}if(this.options.scaleX){h.left=-e+"px"}}}this.element.setStyle(h)}});Effect.Highlight=Class.create(Effect.Base,{initialize:function(d){this.element=$(d);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({startcolor:"#ffff99"},arguments[1]||{});this.start(b)},setup:function(){if(this.element.getStyle("display")=="none"){this.cancel();return}this.oldStyle={};if(!this.options.keepBackgroundImage){this.oldStyle.backgroundImage=this.element.getStyle("background-image");this.element.setStyle({backgroundImage:"none"})}if(!this.options.endcolor){this.options.endcolor=this.element.getStyle("background-color").parseColor("#ffffff")}if(!this.options.restorecolor){this.options.restorecolor=this.element.getStyle("background-color")}this._base=$R(0,2).map(function(b){return parseInt(this.options.startcolor.slice(b*2+1,b*2+3),16)}.bind(this));this._delta=$R(0,2).map(function(b){return parseInt(this.options.endcolor.slice(b*2+1,b*2+3),16)-this._base[b]}.bind(this))},update:function(b){this.element.setStyle({backgroundColor:$R(0,2).inject("#",function(d,e,f){return d+((this._base[f]+(this._delta[f]*b)).round().toColorPart())}.bind(this))})},finish:function(){this.element.setStyle(Object.extend(this.oldStyle,{backgroundColor:this.options.restorecolor}))}});Effect.ScrollTo=function(e){var d=arguments[1]||{},b=document.viewport.getScrollOffsets(),f=$(e).cumulativeOffset();if(d.offset){f[1]+=d.offset}return new Effect.Tween(null,b.top,f[1],d,function(g){scrollTo(b.left,g.round())})};Effect.Fade=function(e){e=$(e);var b=e.getInlineOpacity();var d=Object.extend({from:e.getOpacity()||1,to:0,afterFinishInternal:function(f){if(f.options.to!=0){return}f.element.hide().setStyle({opacity:b})}},arguments[1]||{});return new Effect.Opacity(e,d)};Effect.Appear=function(d){d=$(d);var b=Object.extend({from:(d.getStyle("display")=="none"?0:d.getOpacity()||0),to:1,afterFinishInternal:function(e){e.element.forceRerendering()},beforeSetup:function(e){e.element.setOpacity(e.options.from).show()}},arguments[1]||{});return new Effect.Opacity(d,b)};Effect.Puff=function(d){d=$(d);var b={opacity:d.getInlineOpacity(),position:d.getStyle("position"),top:d.style.top,left:d.style.left,width:d.style.width,height:d.style.height};return new Effect.Parallel([new Effect.Scale(d,200,{sync:true,scaleFromCenter:true,scaleContent:true,restoreAfterFinish:true}),new Effect.Opacity(d,{sync:true,to:0})],Object.extend({duration:1,beforeSetupInternal:function(e){Position.absolutize(e.effects[0].element)},afterFinishInternal:function(e){e.effects[0].element.hide().setStyle(b)}},arguments[1]||{}))};Effect.BlindUp=function(b){b=$(b);b.makeClipping();return new Effect.Scale(b,0,Object.extend({scaleContent:false,scaleX:false,restoreAfterFinish:true,afterFinishInternal:function(d){d.element.hide().undoClipping()}},arguments[1]||{}))};Effect.BlindDown=function(d){d=$(d);var b=d.getDimensions();return new Effect.Scale(d,100,Object.extend({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:b.height,originalWidth:b.width},restoreAfterFinish:true,afterSetup:function(e){e.element.makeClipping().setStyle({height:"0px"}).show()},afterFinishInternal:function(e){e.element.undoClipping()}},arguments[1]||{}))};Effect.SwitchOff=function(d){d=$(d);var b=d.getInlineOpacity();return new Effect.Appear(d,Object.extend({duration:0.4,from:0,transition:Effect.Transitions.flicker,afterFinishInternal:function(e){new Effect.Scale(e.element,1,{duration:0.3,scaleFromCenter:true,scaleX:false,scaleContent:false,restoreAfterFinish:true,beforeSetup:function(f){f.element.makePositioned().makeClipping()},afterFinishInternal:function(f){f.element.hide().undoClipping().undoPositioned().setStyle({opacity:b})}})}},arguments[1]||{}))};Effect.DropOut=function(d){d=$(d);var b={top:d.getStyle("top"),left:d.getStyle("left"),opacity:d.getInlineOpacity()};return new Effect.Parallel([new Effect.Move(d,{x:0,y:100,sync:true}),new Effect.Opacity(d,{sync:true,to:0})],Object.extend({duration:0.5,beforeSetup:function(e){e.effects[0].element.makePositioned()},afterFinishInternal:function(e){e.effects[0].element.hide().undoPositioned().setStyle(b)}},arguments[1]||{}))};Effect.Shake=function(f){f=$(f);var d=Object.extend({distance:20,duration:0.5},arguments[1]||{});var g=parseFloat(d.distance);var e=parseFloat(d.duration)/10;var b={top:f.getStyle("top"),left:f.getStyle("left")};return new Effect.Move(f,{x:g,y:0,duration:e,afterFinishInternal:function(h){new Effect.Move(h.element,{x:-g*2,y:0,duration:e*2,afterFinishInternal:function(l){new Effect.Move(l.element,{x:g*2,y:0,duration:e*2,afterFinishInternal:function(n){new Effect.Move(n.element,{x:-g*2,y:0,duration:e*2,afterFinishInternal:function(o){new Effect.Move(o.element,{x:g*2,y:0,duration:e*2,afterFinishInternal:function(p){new Effect.Move(p.element,{x:-g,y:0,duration:e,afterFinishInternal:function(q){q.element.undoPositioned().setStyle(b)}})}})}})}})}})}})};Effect.SlideDown=function(e){e=$(e).cleanWhitespace();var b=e.down().getStyle("bottom");var d=e.getDimensions();return new Effect.Scale(e,100,Object.extend({scaleContent:false,scaleX:false,scaleFrom:window.opera?0:1,scaleMode:{originalHeight:d.height,originalWidth:d.width},restoreAfterFinish:true,afterSetup:function(f){f.element.makePositioned();f.element.down().makePositioned();if(window.opera){f.element.setStyle({top:""})}f.element.makeClipping().setStyle({height:"0px"}).show()},afterUpdateInternal:function(f){f.element.down().setStyle({bottom:(f.dims[0]-f.element.clientHeight)+"px"})},afterFinishInternal:function(f){f.element.undoClipping().undoPositioned();f.element.down().undoPositioned().setStyle({bottom:b})}},arguments[1]||{}))};Effect.SlideUp=function(e){e=$(e).cleanWhitespace();var b=e.down().getStyle("bottom");var d=e.getDimensions();return new Effect.Scale(e,window.opera?0:1,Object.extend({scaleContent:false,scaleX:false,scaleMode:"box",scaleFrom:100,scaleMode:{originalHeight:d.height,originalWidth:d.width},restoreAfterFinish:true,afterSetup:function(f){f.element.makePositioned();f.element.down().makePositioned();if(window.opera){f.element.setStyle({top:""})}f.element.makeClipping().show()},afterUpdateInternal:function(f){f.element.down().setStyle({bottom:(f.dims[0]-f.element.clientHeight)+"px"})},afterFinishInternal:function(f){f.element.hide().undoClipping().undoPositioned();f.element.down().undoPositioned().setStyle({bottom:b})}},arguments[1]||{}))};Effect.Squish=function(b){return new Effect.Scale(b,window.opera?1:0,{restoreAfterFinish:true,beforeSetup:function(d){d.element.makeClipping()},afterFinishInternal:function(d){d.element.hide().undoClipping()}})};Effect.Grow=function(e){e=$(e);var d=Object.extend({direction:"center",moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.full},arguments[1]||{});var b={top:e.style.top,left:e.style.left,height:e.style.height,width:e.style.width,opacity:e.getInlineOpacity()};var l=e.getDimensions();var n,h;var g,f;switch(d.direction){case"top-left":n=h=g=f=0;break;case"top-right":n=l.width;h=f=0;g=-l.width;break;case"bottom-left":n=g=0;h=l.height;f=-l.height;break;case"bottom-right":n=l.width;h=l.height;g=-l.width;f=-l.height;break;case"center":n=l.width/2;h=l.height/2;g=-l.width/2;f=-l.height/2;break}return new Effect.Move(e,{x:n,y:h,duration:0.01,beforeSetup:function(o){o.element.hide().makeClipping().makePositioned()},afterFinishInternal:function(o){new Effect.Parallel([new Effect.Opacity(o.element,{sync:true,to:1,from:0,transition:d.opacityTransition}),new Effect.Move(o.element,{x:g,y:f,sync:true,transition:d.moveTransition}),new Effect.Scale(o.element,100,{scaleMode:{originalHeight:l.height,originalWidth:l.width},sync:true,scaleFrom:window.opera?1:0,transition:d.scaleTransition,restoreAfterFinish:true})],Object.extend({beforeSetup:function(p){p.effects[0].element.setStyle({height:"0px"}).show()},afterFinishInternal:function(p){p.effects[0].element.undoClipping().undoPositioned().setStyle(b)}},d))}})};Effect.Shrink=function(e){e=$(e);var d=Object.extend({direction:"center",moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.none},arguments[1]||{});var b={top:e.style.top,left:e.style.left,height:e.style.height,width:e.style.width,opacity:e.getInlineOpacity()};var h=e.getDimensions();var g,f;switch(d.direction){case"top-left":g=f=0;break;case"top-right":g=h.width;f=0;break;case"bottom-left":g=0;f=h.height;break;case"bottom-right":g=h.width;f=h.height;break;case"center":g=h.width/2;f=h.height/2;break}return new Effect.Parallel([new Effect.Opacity(e,{sync:true,to:0,from:1,transition:d.opacityTransition}),new Effect.Scale(e,window.opera?1:0,{sync:true,transition:d.scaleTransition,restoreAfterFinish:true}),new Effect.Move(e,{x:g,y:f,sync:true,transition:d.moveTransition})],Object.extend({beforeStartInternal:function(l){l.effects[0].element.makePositioned().makeClipping()},afterFinishInternal:function(l){l.effects[0].element.hide().undoClipping().undoPositioned().setStyle(b)}},d))};Effect.Pulsate=function(e){e=$(e);var d=arguments[1]||{},b=e.getInlineOpacity(),g=d.transition||Effect.Transitions.linear,f=function(h){return 1-g((-Math.cos((h*(d.pulses||5)*2)*Math.PI)/2)+0.5)};return new Effect.Opacity(e,Object.extend(Object.extend({duration:2,from:0,afterFinishInternal:function(h){h.element.setStyle({opacity:b})}},d),{transition:f}))};Effect.Fold=function(d){d=$(d);var b={top:d.style.top,left:d.style.left,width:d.style.width,height:d.style.height};d.makeClipping();return new Effect.Scale(d,5,Object.extend({scaleContent:false,scaleX:false,afterFinishInternal:function(e){new Effect.Scale(d,1,{scaleContent:false,scaleY:false,afterFinishInternal:function(f){f.element.hide().undoClipping().setStyle(b)}})}},arguments[1]||{}))};Effect.Morph=Class.create(Effect.Base,{initialize:function(e){this.element=$(e);if(!this.element){throw (Effect._elementDoesNotExistError)}var b=Object.extend({style:{}},arguments[1]||{});if(!Object.isString(b.style)){this.style=$H(b.style)}else{if(b.style.include(":")){this.style=b.style.parseStyle()}else{this.element.addClassName(b.style);this.style=$H(this.element.getStyles());this.element.removeClassName(b.style);var d=this.element.getStyles();this.style=this.style.reject(function(f){return f.value==d[f.key]});b.afterFinishInternal=function(f){f.element.addClassName(f.options.style);f.transforms.each(function(g){f.element.style[g.style]=""})}}}this.start(b)},setup:function(){function b(d){if(!d||["rgba(0, 0, 0, 0)","transparent"].include(d)){d="#ffffff"}d=d.parseColor();return $R(0,2).map(function(e){return parseInt(d.slice(e*2+1,e*2+3),16)})}this.transforms=this.style.map(function(l){var h=l[0],g=l[1],f=null;if(g.parseColor("#zzzzzz")!="#zzzzzz"){g=g.parseColor();f="color"}else{if(h=="opacity"){g=parseFloat(g);if(Prototype.Browser.IE&&(!this.element.currentStyle.hasLayout)){this.element.setStyle({zoom:1})}}else{if(Element.CSS_LENGTH.test(g)){var e=g.match(/^([\+\-]?[0-9\.]+)(.*)$/);g=parseFloat(e[1]);f=(e.length==3)?e[2]:null}}}var d=this.element.getStyle(h);return{style:h.camelize(),originalValue:f=="color"?b(d):parseFloat(d||0),targetValue:f=="color"?b(g):g,unit:f}}.bind(this)).reject(function(d){return((d.originalValue==d.targetValue)||(d.unit!="color"&&(isNaN(d.originalValue)||isNaN(d.targetValue))))})},update:function(b){var f={},d,e=this.transforms.length;while(e--){f[(d=this.transforms[e]).style]=d.unit=="color"?"#"+(Math.round(d.originalValue[0]+(d.targetValue[0]-d.originalValue[0])*b)).toColorPart()+(Math.round(d.originalValue[1]+(d.targetValue[1]-d.originalValue[1])*b)).toColorPart()+(Math.round(d.originalValue[2]+(d.targetValue[2]-d.originalValue[2])*b)).toColorPart():(d.originalValue+(d.targetValue-d.originalValue)*b).toFixed(3)+(d.unit===null?"":d.unit)}this.element.setStyle(f,true)}});Effect.Transform=Class.create({initialize:function(b){this.tracks=[];this.options=arguments[1]||{};this.addTracks(b)},addTracks:function(b){b.each(function(d){d=$H(d);var e=d.values().first();this.tracks.push($H({ids:d.keys().first(),effect:Effect.Morph,options:{style:e}}))}.bind(this));return this},play:function(){return new Effect.Parallel(this.tracks.map(function(b){var f=b.get("ids"),e=b.get("effect"),d=b.get("options");var g=[$(f)||$$(f)].flatten();return g.map(function(h){return new e(h,Object.extend({sync:true},d))})}).flatten(),this.options)}});Element.CSS_PROPERTIES=$w("backgroundColor backgroundPosition borderBottomColor borderBottomStyle borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth borderRightColor borderRightStyle borderRightWidth borderSpacing borderTopColor borderTopStyle borderTopWidth bottom clip color fontSize fontWeight height left letterSpacing lineHeight marginBottom marginLeft marginRight marginTop markerOffset maxHeight maxWidth minHeight minWidth opacity outlineColor outlineOffset outlineWidth paddingBottom paddingLeft paddingRight paddingTop right textIndent top width wordSpacing zIndex");Element.CSS_LENGTH=/^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;String.__parseStyleElement=document.createElement("div");String.prototype.parseStyle=function(){var d,b=$H();if(Prototype.Browser.WebKit){d=new Element("div",{style:this}).style}else{String.__parseStyleElement.innerHTML='<div style="'+this+'"></div>';d=String.__parseStyleElement.childNodes[0].style}Element.CSS_PROPERTIES.each(function(e){if(d[e]){b.set(e,d[e])}});if(Prototype.Browser.IE&&this.include("opacity")){b.set("opacity",this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1])}return b};if(document.defaultView&&document.defaultView.getComputedStyle){Element.getStyles=function(d){var b=document.defaultView.getComputedStyle($(d),null);return Element.CSS_PROPERTIES.inject({},function(e,f){e[f]=b[f];return e})}}else{Element.getStyles=function(d){d=$(d);var b=d.currentStyle,e;e=Element.CSS_PROPERTIES.inject({},function(f,g){f[g]=b[g];return f});if(!e.opacity){e.opacity=d.getOpacity()}return e}}Effect.Methods={morph:function(b,d){b=$(b);new Effect.Morph(b,Object.extend({style:d},arguments[2]||{}));return b},visualEffect:function(e,g,d){e=$(e);var f=g.dasherize().camelize(),b=f.charAt(0).toUpperCase()+f.substring(1);new Effect[b](e,d);return e},highlight:function(d,b){d=$(d);new Effect.Highlight(d,b);return d}};$w("fade appear grow shrink fold blindUp blindDown slideUp slideDown pulsate shake puff squish switchOff dropOut").each(function(b){Effect.Methods[b]=function(e,d){e=$(e);Effect[b.charAt(0).toUpperCase()+b.substring(1)](e,d);return e}});$w("getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles").each(function(b){Effect.Methods[b]=Element[b]});Element.addMethods(Effect.Methods);function validateCreditCard(e){var d="0123456789";var b="";for(i=0;i<e.length;i++){x=e.charAt(i);if(d.indexOf(x,0)!=-1){b+=x}}j=b.length/2;k=Math.floor(j);m=Math.ceil(j)-k;c=0;for(i=0;i<k;i++){a=b.charAt(i*2+m)*2;c+=a>9?Math.floor(a/10+a%10):a}for(i=0;i<k+m;i++){c+=b.charAt(i*2+1-m)*1}return(c%10==0)}var Validator=Class.create();Validator.prototype={initialize:function(e,d,f,b){if(typeof f=="function"){this.options=$H(b);this._test=f}else{this.options=$H(f);this._test=function(){return true}}this.error=d||"Validation failed.";this.className=e},test:function(b,d){return(this._test(b,d)&&this.options.all(function(e){return Validator.methods[e.key]?Validator.methods[e.key](b,d,e.value):true}))}};Validator.methods={pattern:function(b,e,d){return Validation.get("IsEmpty").test(b)||d.test(b)},minLength:function(b,e,d){return b.length>=d},maxLength:function(b,e,d){return b.length<=d},min:function(b,e,d){return b>=parseFloat(d)},max:function(b,e,d){return b<=parseFloat(d)},notOneOf:function(b,e,d){return $A(d).all(function(f){return b!=f})},oneOf:function(b,e,d){return $A(d).any(function(f){return b==f})},is:function(b,e,d){return b==d},isNot:function(b,e,d){return b!=d},equalToField:function(b,e,d){return b==$F(d)},notEqualToField:function(b,e,d){return b!=$F(d)},include:function(b,e,d){return $A(d).all(function(f){return Validation.get(f).test(b,e)})}};var Validation=Class.create();Validation.defaultOptions={onSubmit:true,stopOnFirst:false,immediate:false,focusOnError:true,useTitles:false,addClassNameToContainer:false,containerClassName:".input-box",onFormValidate:function(b,d){},onElementValidate:function(b,d){}};Validation.prototype={initialize:function(d,b){this.form=$(d);if(!this.form){return}this.options=Object.extend({onSubmit:Validation.defaultOptions.onSubmit,stopOnFirst:Validation.defaultOptions.stopOnFirst,immediate:Validation.defaultOptions.immediate,focusOnError:Validation.defaultOptions.focusOnError,useTitles:Validation.defaultOptions.useTitles,onFormValidate:Validation.defaultOptions.onFormValidate,onElementValidate:Validation.defaultOptions.onElementValidate},b||{});if(this.options.onSubmit){Event.observe(this.form,"submit",this.onSubmit.bind(this),false)}if(this.options.immediate){Form.getElements(this.form).each(function(e){if(e.tagName.toLowerCase()=="select"){Event.observe(e,"blur",this.onChange.bindAsEventListener(this))}if(e.type.toLowerCase()=="radio"||e.type.toLowerCase()=="checkbox"){Event.observe(e,"click",this.onChange.bindAsEventListener(this))}else{Event.observe(e,"change",this.onChange.bindAsEventListener(this))}},this)}},onChange:function(b){Validation.isOnChange=true;Validation.validate(Event.element(b),{useTitle:this.options.useTitles,onElementValidate:this.options.onElementValidate});Validation.isOnChange=false},onSubmit:function(b){if(!this.validate()){Event.stop(b)}},validate:function(){var b=false;var d=this.options.useTitles;var g=this.options.onElementValidate;try{if(this.options.stopOnFirst){b=Form.getElements(this.form).all(function(e){if(e.hasClassName("local-validation")&&!this.isElementInForm(e,this.form)){return true}return Validation.validate(e,{useTitle:d,onElementValidate:g})},this)}else{b=Form.getElements(this.form).collect(function(e){if(e.hasClassName("local-validation")&&!this.isElementInForm(e,this.form)){return true}if(e.hasClassName("validation-disabled")){return true}return Validation.validate(e,{useTitle:d,onElementValidate:g})},this).all()}}catch(f){}if(!b&&this.options.focusOnError){try{Form.getElements(this.form).findAll(function(e){return $(e).hasClassName("validation-failed")}).first().focus()}catch(f){}}this.options.onFormValidate(b,this.form);return b},reset:function(){Form.getElements(this.form).each(Validation.reset)},isElementInForm:function(e,d){var b=e.up("form");if(b==d){return true}return false}};Object.extend(Validation,{validate:function(e,b){b=Object.extend({useTitle:false,onElementValidate:function(f,g){}},b||{});e=$(e);var d=$w(e.className);return result=d.all(function(f){var g=Validation.test(f,e,b.useTitle);b.onElementValidate(g,e);return g})},insertAdvice:function(f,d){var b=$(f).up(".field-row");if(b){Element.insert(b,{after:d})}else{if(f.up("td.value")){f.up("td.value").insert({bottom:d})}else{if(f.advaiceContainer&&$(f.advaiceContainer)){$(f.advaiceContainer).update(d)}else{switch(f.type.toLowerCase()){case"checkbox":case"radio":var e=f.parentNode;if(e){Element.insert(e,{bottom:d})}else{Element.insert(f,{after:d})}break;default:Element.insert(f,{after:d})}}}}},showAdvice:function(e,d,b){if(!e.advices){e.advices=new Hash()}else{e.advices.each(function(f){if(!d||f.value.id!=d.id){this.hideAdvice(e,f.value)}}.bind(this))}e.advices.set(b,d);if(typeof Effect=="undefined"){d.style.display="block"}else{if(!d._adviceAbsolutize){new Effect.Appear(d,{duration:1})}else{Position.absolutize(d);d.show();d.setStyle({top:d._adviceTop,left:d._adviceLeft,width:d._adviceWidth,"z-index":1000});d.addClassName("advice-absolute")}}},hideAdvice:function(d,b){if(b!=null){new Effect.Fade(b,{duration:1,afterFinishInternal:function(){b.hide()}})}},updateCallback:function(elm,status){if(typeof elm.callbackFunction!="undefined"){eval(elm.callbackFunction+"('"+elm.id+"','"+status+"')")}},ajaxError:function(g,f){var e="validate-ajax";var d=Validation.getAdvice(e,g);if(d==null){d=this.createAdvice(e,g,false,f)}this.showAdvice(g,d,"validate-ajax");this.updateCallback(g,"failed");g.addClassName("validation-failed");g.addClassName("validate-ajax");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=g.up(Validation.defaultOptions.containerClassName);if(b&&this.allowContainerClassName(g)){b.removeClassName("validation-passed");b.addClassName("validation-error")}}},allowContainerClassName:function(b){if(b.type=="radio"||b.type=="checkbox"){return b.hasClassName("change-container-classname")}return true},test:function(g,o,l){var d=Validation.get(g);var n="__advice"+g.camelize();try{if(Validation.isVisible(o)&&!d.test($F(o),o)){var f=Validation.getAdvice(g,o);if(f==null){f=this.createAdvice(g,o,l)}this.showAdvice(o,f,g);this.updateCallback(o,"failed");o[n]=1;if(!o.advaiceContainer){o.removeClassName("validation-passed");o.addClassName("validation-failed")}if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=o.up(Validation.defaultOptions.containerClassName);if(b&&this.allowContainerClassName(o)){b.removeClassName("validation-passed");b.addClassName("validation-error")}}return false}else{var f=Validation.getAdvice(g,o);this.hideAdvice(o,f);this.updateCallback(o,"passed");o[n]="";o.removeClassName("validation-failed");o.addClassName("validation-passed");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var b=o.up(Validation.defaultOptions.containerClassName);if(b&&!b.down(".validation-failed")&&this.allowContainerClassName(o)){if(!Validation.get("IsEmpty").test(o.value)||!this.isVisible(o)){b.addClassName("validation-passed")}else{b.removeClassName("validation-passed")}b.removeClassName("validation-error")}}return true}}catch(h){throw (h)}},isVisible:function(b){while(b.tagName!="BODY"){if(!$(b).visible()){return false}b=b.parentNode}return true},getAdvice:function(b,d){return $("advice-"+b+"-"+Validation.getElmID(d))||$("advice-"+Validation.getElmID(d))},createAdvice:function(e,n,l,d){var b=Validation.get(e);var h=l?((n&&n.title)?n.title:b.error):b.error;if(d){h=d}if(jQuery.mage.__){h=jQuery.mage.__(h)}advice='<div class="validation-advice" id="advice-'+e+"-"+Validation.getElmID(n)+'" style="display:none">'+h+"</div>";Validation.insertAdvice(n,advice);advice=Validation.getAdvice(e,n);if($(n).hasClassName("absolute-advice")){var g=$(n).getDimensions();var f=Position.cumulativeOffset(n);advice._adviceTop=(f[1]+g.height)+"px";advice._adviceLeft=(f[0])+"px";advice._adviceWidth=(g.width)+"px";advice._adviceAbsolutize=true}return advice},getElmID:function(b){return b.id?b.id:b.name},reset:function(d){d=$(d);var b=$w(d.className);b.each(function(g){var h="__advice"+g.camelize();if(d[h]){var f=Validation.getAdvice(g,d);if(f){f.hide()}d[h]=""}d.removeClassName("validation-failed");d.removeClassName("validation-passed");if(Validation.defaultOptions.addClassNameToContainer&&Validation.defaultOptions.containerClassName!=""){var e=d.up(Validation.defaultOptions.containerClassName);if(e){e.removeClassName("validation-passed");e.removeClassName("validation-error")}}})},add:function(f,e,g,d){var b={};b[f]=new Validator(f,e,g,d);Object.extend(Validation.methods,b)},addAllThese:function(b){var d={};$A(b).each(function(e){d[e[0]]=new Validator(e[0],e[1],e[2],(e.length>3?e[3]:{}))});Object.extend(Validation.methods,d)},get:function(b){return Validation.methods[b]?Validation.methods[b]:Validation.methods._LikeNoIDIEverSaw_},methods:{_LikeNoIDIEverSaw_:new Validator("_LikeNoIDIEverSaw_","",{})}});Validation.add("IsEmpty","",function(b){return(b==""||(b==null)||(b.length==0)||/^\s+$/.test(b))});Validation.addAllThese([["validate-no-html-tags","HTML tags are not allowed",function(b){return !/<(\/)?\w+/.test(b)}],["validate-select","Please select an option.",function(b){return((b!="none")&&(b!=null)&&(b.length!=0))}],["required-entry","This is a required field.",function(b){return !Validation.get("IsEmpty").test(b)}],["validate-number","Please enter a valid number in this field.",function(b){return Validation.get("IsEmpty").test(b)||(!isNaN(parseNumber(b))&&/^\s*-?\d*(\.\d*)?\s*$/.test(b))}],["validate-number-range","The value is not within the specified range.",function(e,g){if(Validation.get("IsEmpty").test(e)){return true}var f=parseNumber(e);if(isNaN(f)){return false}var d=/^number-range-(-?[\d.,]+)?-(-?[\d.,]+)?$/,b=true;$w(g.className).each(function(l){var h=d.exec(l);if(h){b=b&&(h[1]==null||h[1]==""||f>=parseNumber(h[1]))&&(h[2]==null||h[2]==""||f<=parseNumber(h[2]))}});return b}],["validate-digits","Please use numbers only in this field. Please avoid spaces or other characters such as dots or commas.",function(b){return Validation.get("IsEmpty").test(b)||!/[^\d]/.test(b)}],["validate-digits-range","The value is not within the specified range.",function(e,g){if(Validation.get("IsEmpty").test(e)){return true}var f=parseNumber(e);if(isNaN(f)){return false}var d=/^digits-range-(-?\d+)?-(-?\d+)?$/,b=true;$w(g.className).each(function(l){var h=d.exec(l);if(h){b=b&&(h[1]==null||h[1]==""||f>=parseNumber(h[1]))&&(h[2]==null||h[2]==""||f<=parseNumber(h[2]))}});return b}],["validate-range","The value is not within the specified range.",function(f,l){var g,h;if(Validation.get("IsEmpty").test(f)){return true}else{if(Validation.get("validate-digits").test(f)){g=h=parseNumber(f)}else{var e=/^(-?\d+)?-(-?\d+)?$/.exec(f);if(e){g=parseNumber(e[1]);h=parseNumber(e[2]);if(g>h){return false}}else{return false}}}var d=/^range-(-?\d+)?-(-?\d+)?$/,b=true;$w(l.className).each(function(n){var q=d.exec(n);if(q){var p=parseNumber(q[1]);var o=parseNumber(q[2]);b=b&&(isNaN(p)||g>=p)&&(isNaN(o)||h<=o)}});return b}],["validate-alpha","Please use letters only (a-z or A-Z) in this field.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z]+$/.test(b)}],["validate-code","Please use only letters (a-z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-z]+[a-z0-9_]+$/.test(b)}],["validate-alphanum","Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z0-9]+$/.test(b)}],["validate-alphanum-with-spaces","Please use only letters (a-z or A-Z), numbers (0-9) or spaces only in this field.",function(b){return Validation.get("IsEmpty").test(b)||/^[a-zA-Z0-9 ]+$/.test(b)}],["validate-street",'Please use only letters (a-z or A-Z), numbers (0-9), spaces and "#" in this field.',function(b){return Validation.get("IsEmpty").test(b)||/^[ \w]{3,}([A-Za-z]\.)?([ \w]*\#\d+)?(\r\n| )[ \w]{3,}/.test(b)}],["validate-phoneStrict","Please enter a valid phone number (Ex: 123-456-7890).",function(b){return Validation.get("IsEmpty").test(b)||/^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(b)}],["validate-phoneLax","Please enter a valid phone number (Ex: 123-456-7890).",function(b){return Validation.get("IsEmpty").test(b)||/^((\d[-. ]?)?((\(\d{3}\))|\d{3}))?[-. ]?\d{3}[-. ]?\d{4}$/.test(b)}],["validate-fax","Please enter a valid fax number (Ex: 123-456-7890).",function(b){return Validation.get("IsEmpty").test(b)||/^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(b)}],["validate-date","Please enter a valid date.",function(b){var d=new Date(b);return Validation.get("IsEmpty").test(b)||!isNaN(d)}],["validate-date-range","Make sure the To Date is later than or the same as the From Date.",function(e,h){var d=/\bdate-range-(\w+)-(\w+)\b/.exec(h.className);if(!d||d[2]=="to"||Validation.get("IsEmpty").test(e)){return true}var f=new Date().getFullYear()+"";var b=function(l){l=l.split(/[.\/]/);if(l[2]&&l[2].length<4){l[2]=f.substr(0,l[2].length)+l[2]}return new Date(l.join("/")).getTime()};var g=Element.select(h.form,".validate-date-range.date-range-"+d[1]+"-to");return !g.length||Validation.get("IsEmpty").test(g[0].value)||b(e)<=b(g[0].value)}],["validate-email","Please enter a valid email address (Ex: johndoe@domain.com).",function(b){return Validation.get("IsEmpty").test(b)||/^([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*@([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*\.(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]){2,})$/i.test(b)}],["validate-emailSender","Please use only visible characters and spaces.",function(b){return Validation.get("IsEmpty").test(b)||/^[\S ]+$/.test(b)}],["validate-password","Please enter 6 or more characters. Leading or trailing spaces will be ignored.",function(b){var d=b.strip();return !(d.length>0&&d.length<6)}],["validate-admin-password","Please enter 7 or more characters, using both numeric and alphabetic.",function(b){var d=b.strip();if(0==d.length){return true}if(!(/[a-z]/i.test(b))||!(/[0-9]/.test(b))){return false}return !(d.length<7)}],["validate-cpassword","Please make sure your passwords match.",function(b){var d=$("confirmation")?$("confirmation"):$$(".validate-cpassword")[0];var g=false;if($("password")){g=$("password")}var h=$$(".validate-password");for(var e=0;e<h.size();e++){var f=h[e];if(f.up("form").id==d.up("form").id){g=f}}if($$(".validate-admin-password").size()){g=$$(".validate-admin-password")[0]}return(g.value==d.value)}],["validate-both-passwords","Please make sure your passwords match.",function(e,d){var b=$(d.form[d.name=="password"?"confirmation":"password"]),f=d.value==b.value;if(f&&b.hasClassName("validation-failed")){Validation.test(this.className,b)}return b.value==""||f}],["validate-url","Please enter a valid URL. Protocol is required (http://, https:// or ftp://)",function(b){b=(b||"").replace(/^\s+/,"").replace(/\s+$/,"");return Validation.get("IsEmpty").test(b)||/^(http|https|ftp):\/\/(([A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))(\.[A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))*)(:(\d+))?(\/[A-Z0-9~](([A-Z0-9_~-]|\.)*[A-Z0-9~]|))*\/?(.*)?$/i.test(b)}],["validate-clean-url",'Please enter a valid URL (Ex: "http://www.example.com" or "www.example.com").',function(b){return Validation.get("IsEmpty").test(b)||/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(b)||/^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(b)}],["validate-identifier",'Please enter a valid URL Key (Ex: "example-page", "example-page.html" or "anotherlevel/example-page").',function(b){return Validation.get("IsEmpty").test(b)||/^[a-z0-9][a-z0-9_\/-]+(\.[a-z0-9_-]+)?$/.test(b)}],["validate-xml-identifier","Please enter a valid XML-identifier (Ex: something_1, block5, id-4).",function(b){return Validation.get("IsEmpty").test(b)||/^[A-Z][A-Z0-9_\/-]*$/i.test(b)}],["validate-ssn","Please enter a valid social security number (Ex: 123-45-6789).",function(b){return Validation.get("IsEmpty").test(b)||/^\d{3}-?\d{2}-?\d{4}$/.test(b)}],["validate-zip-us","Please enter a valid zip code (Ex: 90602 or 90602-1234).",function(b){return Validation.get("IsEmpty").test(b)||/(^\d{5}$)|(^\d{5}-\d{4}$)/.test(b)}],["validate-zip-international","Please enter a valid zip code.",function(b){return true}],["validate-date-au",'Please use this date format: dd/mm/yyyy (Ex: "17/03/2006" for the 17th of March, 2006).',function(b){if(Validation.get("IsEmpty").test(b)){return true}var e=/^(\d{2})\/(\d{2})\/(\d{4})$/;if(!e.test(b)){return false}var f=new Date(b.replace(e,"$2/$1/$3"));return(parseInt(RegExp.$2,10)==(1+f.getMonth()))&&(parseInt(RegExp.$1,10)==f.getDate())&&(parseInt(RegExp.$3,10)==f.getFullYear())}],["validate-currency-dollar","Please enter a valid $ amount (Ex: $100.00).",function(b){return Validation.get("IsEmpty").test(b)||/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(b)}],["validate-one-required","Please select one of the options above.",function(b,f){var e=f.parentNode;var d=e.getElementsByTagName("INPUT");return $A(d).any(function(g){return $F(g)})}],["validate-one-required-by-name","Please select one of the options.",function(d,g){var b=$$('input[name="'+g.name.replace(/([\\"])/g,"\\$1")+'"]');var e=1;for(var f=0;f<b.length;f++){if((b[f].type=="checkbox"||b[f].type=="radio")&&b[f].checked==true){e=0}if(Validation.isOnChange&&(b[f].type=="checkbox"||b[f].type=="radio")){Validation.reset(b[f])}}if(e==0){return true}else{return false}}],["validate-not-negative-number","Please enter a number 0 or greater in this field.",function(b){if(Validation.get("IsEmpty").test(b)){return true}b=parseNumber(b);return !isNaN(b)&&b>=0}],["validate-zero-or-greater","Please enter a number 0 or greater in this field.",function(b){return Validation.get("validate-not-negative-number").test(b)}],["validate-greater-than-zero","Please enter a number greater than 0 in this field.",function(b){if(Validation.get("IsEmpty").test(b)){return true}b=parseNumber(b);return !isNaN(b)&&b>0}],["validate-state","Please select State/Province.",function(b){return(b!=0||b=="")}],["validate-new-password","Please enter 6 or more characters. Leading or trailing spaces will be ignored.",function(b){if(!Validation.get("validate-password").test(b)){return false}if(Validation.get("IsEmpty").test(b)&&b!=""){return false}return true}],["validate-cc-number","Please enter a valid credit card number.",function(b,e){var d=$(e.id.substr(0,e.id.indexOf("_cc_number"))+"_cc_type");if(d&&typeof Validation.creditCartTypes.get(d.value)!="undefined"&&Validation.creditCartTypes.get(d.value)[2]==false){if(!Validation.get("IsEmpty").test(b)&&Validation.get("validate-digits").test(b)){return true}else{return false}}return validateCreditCard(b)}],["validate-cc-type","Credit card number does not match credit card type.",function(d,g){g.value=removeDelimiters(g.value);d=removeDelimiters(d);var f=$(g.id.substr(0,g.id.indexOf("_cc_number"))+"_cc_type");if(!f){return true}var e=f.value;if(typeof Validation.creditCartTypes.get(e)=="undefined"){return false}if(Validation.creditCartTypes.get(e)[0]==false){return true}var b="";Validation.creditCartTypes.each(function(h){if(h.value[0]&&d.match(h.value[0])){b=h.key;throw $break}});if(b!=e){return false}if(f.hasClassName("validation-failed")&&Validation.isOnChange){Validation.validate(f)}return true}],["validate-cc-type-select","Card type does not match credit card number.",function(d,e){var b=$(e.id.substr(0,e.id.indexOf("_cc_type"))+"_cc_number");if(Validation.isOnChange&&Validation.get("IsEmpty").test(b.value)){return true}if(Validation.get("validate-cc-type").test(b.value,b)){Validation.validate(b)}return Validation.get("validate-cc-type").test(b.value,b)}],["validate-cc-exp","Incorrect credit card expiration date.",function(b,l){var h=b;var g=$(l.id.substr(0,l.id.indexOf("_expiration"))+"_expiration_yr").value;var f=new Date();var e=f.getMonth()+1;var d=f.getFullYear();if(h<e&&g==d){return false}return true}],["validate-cc-cvn","Please enter a valid credit card verification number.",function(b,g){var f=$(g.id.substr(0,g.id.indexOf("_cc_cid"))+"_cc_type");if(!f){return true}var d=f.value;if(typeof Validation.creditCartTypes.get(d)=="undefined"){return false}var e=Validation.creditCartTypes.get(d)[1];if(b.match(e)){return true}return false}],["validate-ajax","",function(b,d){return true}],["validate-data","Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.",function(b){if(b!=""&&b){return/^[A-Za-z]+[A-Za-z0-9_]+$/.test(b)}return true}],["validate-css-length","Please input a valid CSS-length (Ex: 100px, 77pt, 20em, .5ex or 50%).",function(b){if(b!=""&&b){return/^[0-9\.]+(px|pt|em|ex|%)?$/.test(b)&&(!(/\..*\./.test(b)))&&!(/\.$/.test(b))}return true}],["validate-length","Text length does not meet the specified text range.",function(d,g){var e=new RegExp(/^maximum-length-[0-9]+$/);var f=new RegExp(/^minimum-length-[0-9]+$/);var b=true;$w(g.className).each(function(l,h){if(l.match(e)&&b){var n=l.split("-")[2];b=(d.length<=n)}if(l.match(f)&&b&&!Validation.get("IsEmpty").test(d)){var n=l.split("-")[2];b=(d.length>=n)}});return b}],["validate-percents","Please enter a number lower than 100.",{max:100}],["required-file","Please select a file.",function(d,e){var b=!Validation.get("IsEmpty").test(d);if(b===false){ovId=e.id+"_value";if($(ovId)){b=!Validation.get("IsEmpty").test($(ovId).value)}}return b}],["validate-cc-ukss","Please enter issue number or start date for switch/solo card type.",function(o,g){var b;if(g.id.match(/(.)+_cc_issue$/)){b=g.id.indexOf("_cc_issue")}else{if(g.id.match(/(.)+_start_month$/)){b=g.id.indexOf("_start_month")}else{b=g.id.indexOf("_start_year")}}var f=g.id.substr(0,b);var d=$(f+"_cc_type");if(!d){return true}var n=d.value;if(["SS","SM","SO"].indexOf(n)==-1){return true}$(f+"_cc_issue").advaiceContainer=$(f+"_start_month").advaiceContainer=$(f+"_start_year").advaiceContainer=$(f+"_cc_type_ss_div").down(".adv-container");var h=$(f+"_cc_issue").value;var l=$(f+"_start_month").value;var p=$(f+"_start_year").value;var e=(l&&p)?true:false;if(!e&&!h){return false}return true}]]);function removeDelimiters(b){b=b.replace(/\s/g,"");b=b.replace(/\-/g,"");return b}function parseNumber(b){if(typeof b!="string"){return parseFloat(b)}var e=b.indexOf(".");var d=b.indexOf(",");if(e!=-1&&d!=-1){if(d>e){b=b.replace(".","").replace(",",".")}else{b=b.replace(",","")}}else{if(d!=-1){b=b.replace(",",".")}}return parseFloat(b)}Validation.creditCartTypes=$H({SO:[new RegExp("^(6334[5-9]([0-9]{11}|[0-9]{13,14}))|(6767([0-9]{12}|[0-9]{14,15}))$"),new RegExp("^([0-9]{3}|[0-9]{4})?$"),true],SM:[new RegExp("(^(5[0678])[0-9]{11,18}$)|(^(6[^05])[0-9]{11,18}$)|(^(601)[^1][0-9]{9,16}$)|(^(6011)[0-9]{9,11}$)|(^(6011)[0-9]{13,16}$)|(^(65)[0-9]{11,13}$)|(^(65)[0-9]{15,18}$)|(^(49030)[2-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49033)[5-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49110)[1-2]([0-9]{10}$|[0-9]{12,13}$))|(^(49117)[4-9]([0-9]{10}$|[0-9]{12,13}$))|(^(49118)[0-2]([0-9]{10}$|[0-9]{12,13}$))|(^(4936)([0-9]{12}$|[0-9]{14,15}$))"),new RegExp("^([0-9]{3}|[0-9]{4})?$"),true],VI:[new RegExp("^4[0-9]{12}([0-9]{3})?$"),new RegExp("^[0-9]{3}$"),true],MC:[new RegExp("^5[1-5][0-9]{14}$"),new RegExp("^[0-9]{3}$"),true],AE:[new RegExp("^3[47][0-9]{13}$"),new RegExp("^[0-9]{4}$"),true],DI:[new RegExp("^6(011|4[4-9][0-9]|5[0-9]{2})[0-9]{12}$"),new RegExp("^[0-9]{3}$"),true],JCB:[new RegExp("^(3[0-9]{15}|(2131|1800)[0-9]{11})$"),new RegExp("^[0-9]{3,4}$"),true],OT:[false,new RegExp("^([0-9]{3}|[0-9]{4})?$"),false]});function popWin(d,e,b){var e=window.open(d,e,b);e.focus()}function setLocation(b){window.location.href=b}function setPLocation(d,b){if(b){window.opener.focus()}window.opener.location.href=d}function setLanguageCode(e,f){var b=window.location.href;var h="",g;if(g=b.match(/\#(.*)$/)){b=b.replace(/\#(.*)$/,"");h=g[0]}if(b.match(/[?]/)){var d=/([?&]store=)[a-z0-9_]*/;if(b.match(d)){b=b.replace(d,"$1"+e)}else{b+="&store="+e}var d=/([?&]from_store=)[a-z0-9_]*/;if(b.match(d)){b=b.replace(d,"")}}else{b+="?store="+e}if(typeof(f)!="undefined"){b+="&from_store="+f}b+=h;setLocation(b)}function decorateGeneric(h,e){var l=["odd","even","first","last"];var d={};var g=h.length;if(g){if(typeof(e)=="undefined"){e=l}if(!e.length){return}for(var b in l){d[l[b]]=false}for(var b in e){d[e[b]]=true}if(d.first){Element.addClassName(h[0],"first")}if(d.last){Element.addClassName(h[g-1],"last")}for(var f=0;f<g;f++){if((f+1)%2==0){if(d.even){Element.addClassName(h[f],"even")}}else{if(d.odd){Element.addClassName(h[f],"odd")}}}}}function decorateTable(h,e){var h=$(h);if(h){var b={tbody:false,"tbody tr":["odd","even","first","last"],"thead tr":["first","last"],"tfoot tr":["first","last"],"tr td":["last"]};if(typeof(e)!="undefined"){for(var d in e){b[d]=e[d]}}if(b.tbody){decorateGeneric(h.select("tbody"),b.tbody)}if(b["tbody tr"]){decorateGeneric(h.select("tbody tr"),b["tbody tr"])}if(b["thead tr"]){decorateGeneric(h.select("thead tr"),b["thead tr"])}if(b["tfoot tr"]){decorateGeneric(h.select("tfoot tr"),b["tfoot tr"])}if(b["tr td"]){var g=h.select("tr");if(g.length){for(var f=0;f<g.length;f++){decorateGeneric(g[f].getElementsByTagName("TD"),b["tr td"])}}}}}function decorateList(e,d){if($(e)){if(typeof(d)=="undefined"){var b=$(e).select("li")}else{var b=$(e).childElements()}decorateGeneric(b,["odd","even","last"])}}function decorateDataList(b){b=$(b);if(b){decorateGeneric(b.select("dt"),["odd","even","last"]);decorateGeneric(b.select("dd"),["odd","even","last"])}}function parseSidUrl(f,e){var d=f.indexOf("/?SID=");var b="";e=(e!=undefined)?e:"";if(d>-1){b="?"+f.substring(d+2);f=f.substring(0,d+1)}return f+e+b}function formatCurrency(n,q,g){var l=isNaN(q.precision=Math.abs(q.precision))?2:q.precision;var v=isNaN(q.requiredPrecision=Math.abs(q.requiredPrecision))?2:q.requiredPrecision;l=v;var t=isNaN(q.integerRequired=Math.abs(q.integerRequired))?1:q.integerRequired;var p=q.decimalSymbol==undefined?",":q.decimalSymbol;var e=q.groupSymbol==undefined?".":q.groupSymbol;var d=q.groupLength==undefined?3:q.groupLength;var u="";if(g==undefined||g==true){u=n<0?"-":(g?"+":"")}else{if(g==false){u=""}}var h=parseInt(n=Math.abs(+n||0).toFixed(l))+"";var f=(h.length<t)?(t-h.length):0;while(f){h="0"+h;f--}j=(j=h.length)>d?j%d:0;re=new RegExp("(\\d{"+d+"})(?=\\d)","g");var b=(j?h.substr(0,j)+e:"")+h.substr(j).replace(re,"$1"+e)+(l?p+Math.abs(n-h).toFixed(l).replace(/-/,0).slice(2):"");var o="";if(q.pattern.indexOf("{sign}")==-1){o=u+q.pattern}else{o=q.pattern.replace("{sign}",u)}return o.replace("%s",b).replace(/^\s\s*/,"").replace(/\s\s*$/,"")}function expandDetails(d,b){if(Element.hasClassName(d,"show-details")){$$(b).each(function(e){e.hide()});Element.removeClassName(d,"show-details")}else{$$(b).each(function(e){e.show()});Element.addClassName(d,"show-details")}}var isIE=navigator.appVersion.match(/MSIE/)=="MSIE";if(!window.Varien){var Varien=new Object()}Varien.showLoading=function(){var b=$("loading-process");b&&b.show()};Varien.hideLoading=function(){var b=$("loading-process");b&&b.hide()};Varien.GlobalHandlers={onCreate:function(){Varien.showLoading()},onComplete:function(){if(Ajax.activeRequestCount==0){Varien.hideLoading()}}};Ajax.Responders.register(Varien.GlobalHandlers);Varien.searchForm=Class.create();Varien.searchForm.prototype={initialize:function(d,e,b){this.form=$(d);this.field=$(e);this.emptyText=b;Event.observe(this.form,"submit",this.submit.bind(this));Event.observe(this.field,"focus",this.focus.bind(this));Event.observe(this.field,"blur",this.blur.bind(this));this.blur()},submit:function(b){if(this.field.value==this.emptyText||this.field.value==""){Event.stop(b);return false}return true},focus:function(b){if(this.field.value==this.emptyText){this.field.value=""}},blur:function(b){if(this.field.value==""){this.field.value=this.emptyText}}};Varien.DateElement=Class.create();Varien.DateElement.prototype={initialize:function(b,d,f,e){if(b=="id"){this.day=$(d+"day");this.month=$(d+"month");this.year=$(d+"year");this.full=$(d+"full");this.advice=$(d+"date-advice")}else{if(b=="container"){this.day=d.day;this.month=d.month;this.year=d.year;this.full=d.full;this.advice=d.advice}else{return}}this.required=f;this.format=e;this.day.addClassName("validate-custom");this.day.validate=this.validate.bind(this);this.month.addClassName("validate-custom");this.month.validate=this.validate.bind(this);this.year.addClassName("validate-custom");this.year.validate=this.validate.bind(this);this.setDateRange(false,false);this.year.setAttribute("autocomplete","off");this.advice.hide()},validate:function(){var l=false,o=parseInt(this.day.value,10)||0,f=parseInt(this.month.value,10)||0,h=parseInt(this.year.value,10)||0;if(this.day.value.strip().empty()&&this.month.value.strip().empty()&&this.year.value.strip().empty()){if(this.required){l="Please enter a date."}else{this.full.value=""}}else{if(!o||!f||!h){l="Please enter a valid full date."}else{var d=new Date,n=0,e=null;d.setYear(h);d.setMonth(f-1);d.setDate(32);n=32-d.getDate();if(!n||n>31){n=31}if(o<1||o>n){e="day";l="Please enter a valid day (1-%1)."}else{if(f<1||f>12){e="month";l="Please enter a valid month (1-12)."}else{if(o%10==o){this.day.value="0"+o}if(f%10==f){this.month.value="0"+f}this.full.value=this.format.replace(/%[mb]/i,this.month.value).replace(/%[de]/i,this.day.value).replace(/%y/i,this.year.value);var b=this.month.value+"/"+this.day.value+"/"+this.year.value;var g=new Date(b);if(isNaN(g)){l="Please enter a valid date."}else{this.setFullDate(g)}}}var p=false;if(!l&&!this.validateData()){e=this.validateDataErrorType;p=this.validateDataErrorText;l=p}}}if(l!==false){if(jQuery.mage.__){l=jQuery.mage.__(l)}if(!p){this.advice.innerHTML=l.replace("%1",n)}else{this.advice.innerHTML=this.errorTextModifier(l)}this.advice.show();return false}this.day.removeClassName("validation-failed");this.month.removeClassName("validation-failed");this.year.removeClassName("validation-failed");this.advice.hide();return true},validateData:function(){var d=this.fullDate.getFullYear();var b=new Date;this.curyear=b.getFullYear();return(d>=1900&&d<=this.curyear)},validateDataErrorType:"year",validateDataErrorText:"Please enter a valid year (1900-%1).",errorTextModifier:function(b){return b.replace("%1",this.curyear)},setDateRange:function(b,d){this.minDate=b;this.maxDate=d},setFullDate:function(b){this.fullDate=b}};Varien.DOB=Class.create();Varien.DOB.prototype={initialize:function(b,g,f){var e=$$(b)[0];var d={};d.day=Element.select(e,".dob-day input")[0];d.month=Element.select(e,".dob-month input")[0];d.year=Element.select(e,".dob-year input")[0];d.full=Element.select(e,".dob-full input")[0];d.advice=Element.select(e,".validation-advice")[0];new Varien.DateElement("container",d,g,f)}};Varien.dateRangeDate=Class.create();Varien.dateRangeDate.prototype=Object.extend(new Varien.DateElement(),{validateData:function(){var b=true;if(this.minDate||this.maxValue){if(this.minDate){this.minDate=new Date(this.minDate);this.minDate.setHours(0);if(isNaN(this.minDate)){this.minDate=new Date("1/1/1900")}b=b&&(this.fullDate>=this.minDate)}if(this.maxDate){this.maxDate=new Date(this.maxDate);this.minDate.setHours(0);if(isNaN(this.maxDate)){this.maxDate=new Date()}b=b&&(this.fullDate<=this.maxDate)}if(this.maxDate&&this.minDate){this.validateDataErrorText="Please enter a valid date between %s and %s"}else{if(this.maxDate){this.validateDataErrorText="Please enter a valid date less than or equal to %s"}else{if(this.minDate){this.validateDataErrorText="Please enter a valid date equal to or greater than %s"}else{this.validateDataErrorText=""}}}}return b},validateDataErrorText:"Date should be between %s and %s",errorTextModifier:function(b){if(this.minDate){b=b.sub("%s",this.dateFormat(this.minDate))}if(this.maxDate){b=b.sub("%s",this.dateFormat(this.maxDate))}return b},dateFormat:function(b){return(b.getMonth()+1)+"/"+b.getDate()+"/"+b.getFullYear()}});Varien.FileElement=Class.create();Varien.FileElement.prototype={initialize:function(b){this.fileElement=$(b);this.hiddenElement=$(b+"_value");this.fileElement.observe("change",this.selectFile.bind(this))},selectFile:function(b){this.hiddenElement.value=this.fileElement.getValue()}};Validation.addAllThese([["validate-custom"," ",function(b,d){return d.validate()}]]);Element.addMethods({getInnerText:function(b){b=$(b);if(b.innerText&&!Prototype.Browser.Opera){return b.innerText}return b.innerHTML.stripScripts().unescapeHTML().replace(/[\n\r\s]+/g," ").strip()}});function fireEvent(d,e){if(document.createEvent){var b=document.createEvent("HTMLEvents");b.initEvent(e,true,true);return d.dispatchEvent(b)}else{var b=document.createEventObject();return d.fireEvent("on"+e,b)}}function modulo(b,f){var e=f/10000;var d=b%f;if(Math.abs(d-f)<e||Math.abs(d)<e){d=0}return d}if((typeof Range!="undefined")&&!Range.prototype.createContextualFragment){Range.prototype.createContextualFragment=function(b){var e=document.createDocumentFragment(),d=document.createElement("div");e.appendChild(d);d.outerHTML=b;return e}}var byteConvert=function(b){if(isNaN(b)){return""}var d=["bytes","KB","MB","GB","TB","PB","EB","ZB","YB"];var f=Math.floor(Math.log(b)/Math.log(2));if(f<1){f=0}var e=Math.floor(f/10);b=b/Math.pow(2,10*e);if(b.toString().length>b.toFixed(2).toString().length){b=b.toFixed(2)}return b+" "+d[e]};var SessionError=Class.create();SessionError.prototype={initialize:function(b){this.errorText=b},toString:function(){return"Session Error:"+this.errorText}};Ajax.Request.addMethods({initialize:function($super,d,b){$super(b);this.transport=Ajax.getTransport();if(!d.match(new RegExp("[?&]isAjax=true",""))){d=d.match(new RegExp("\\?","g"))?d+"&isAjax=true":d+"?isAjax=true"}if(Object.isString(this.options.parameters)&&this.options.parameters.indexOf("form_key=")==-1){this.options.parameters+="&"+Object.toQueryString({form_key:FORM_KEY})}else{if(!this.options.parameters){this.options.parameters={form_key:FORM_KEY}}if(!this.options.parameters.form_key){this.options.parameters.form_key=FORM_KEY}}this.request(d)},respondToReadyState:function(b){var g=Ajax.Request.Events[b],d=new Ajax.Response(this);if(g=="Complete"){try{this._complete=true;if(d.responseText.isJSON()){var f=d.responseText.evalJSON();if(f.ajaxExpired&&f.ajaxRedirect){window.location.replace(f.ajaxRedirect);throw new SessionError("session expired")}}(this.options["on"+d.status]||this.options["on"+(this.success()?"Success":"Failure")]||Prototype.emptyFunction)(d,d.headerJSON)}catch(h){this.dispatchException(h);if(h instanceof SessionError){return}}var l=d.getHeader("Content-type");if(this.options.evalJS=="force"||(this.options.evalJS&&this.isSameOrigin()&&l&&l.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))){this.evalResponse()}}try{(this.options["on"+g]||Prototype.emptyFunction)(d,d.headerJSON);Ajax.Responders.dispatch("on"+g,this,d,d.headerJSON)}catch(h){this.dispatchException(h)}if(g=="Complete"){this.transport.onreadystatechange=Prototype.emptyFunction}}});Ajax.Updater.respondToReadyState=Ajax.Request.respondToReadyState;var varienLoader=new Class.create();varienLoader.prototype={initialize:function(b){this.callback=false;this.cache=$H();this.caching=b||false;this.url=false},getCache:function(b){if(this.cache.get(b)){return this.cache.get(b)}return false},load:function(b,d,f){this.url=b;this.callback=f;if(this.caching){var e=this.getCache(b);if(e){this.processResult(e);return}}if(typeof(d.updaterId)!="undefined"){new varienUpdater(d.updaterId,b,{evalScripts:true,onComplete:this.processResult.bind(this),onFailure:this._processFailure.bind(this)})}else{new Ajax.Request(b,{method:"post",parameters:d||{},onComplete:this.processResult.bind(this),onFailure:this._processFailure.bind(this)})}},_processFailure:function(b){location.href=BASE_URL},processResult:function(b){if(this.caching){this.cache.set(this.url,b)}if(this.callback){this.callback(b.responseText)}}};if(!window.varienLoaderHandler){var varienLoaderHandler=new Object()}varienLoaderHandler.handler={onCreate:function(b){if(b.options.loaderArea===false){return}jQuery("body").trigger("processStart")},onException:function(b){jQuery("body").trigger("processStop")},onComplete:function(b){jQuery("body").trigger("processStop")}};function setLoaderPosition(){var e=$("loading_mask_loader");if(e&&Prototype.Browser.IE){var d=e.getDimensions();var f=document.viewport.getDimensions();var b=document.viewport.getScrollOffsets();e.style.left=Math.floor(f.width/2+b.left-d.width/2)+"px";e.style.top=Math.floor(f.height/2+b.top-d.height/2)+"px";e.style.position="absolute"}}function toggleSelectsUnderBlock(f,b){if(Prototype.Browser.IE){var e=document.getElementsByTagName("select");for(var d=0;d<e.length;d++){if(b){if(e[d].needShowOnSuccess){e[d].needShowOnSuccess=false;e[d].style.visibility=""}}else{if(Element.visible(e[d])){e[d].style.visibility="hidden";e[d].needShowOnSuccess=true}}}}}Ajax.Responders.register(varienLoaderHandler.handler);var varienUpdater=Class.create(Ajax.Updater,{updateContent:function($super,b){if(b.isJSON()){var d=b.evalJSON();if(d.ajaxExpired&&d.ajaxRedirect){window.location.replace(d.ajaxRedirect)}}else{$super(b)}}});function setLocation(b){window.location.href=b}function confirmSetLocation(d,b){if(confirm(d)){setLocation(b)}return false}function deleteConfirm(d,b){confirmSetLocation(d,b)}function setElementDisable(d,b){if($(d)){$(d).disabled=b}}function toggleParentVis(b){b=$(b).parentNode;if(b.style.display=="none"){b.style.display=""}else{b.style.display="none"}}function toggleFieldsetVis(d){id=d;d=$(d);if(d.style.display=="none"){d.style.display=""}else{d.style.display="none"}d=d.parentNode.childElements();for(var b=0;b<d.length;b++){if(d[b].id!=undefined&&d[b].id==id&&d[(b-1)].classNames()=="entry-edit-head"){if(d[b-1].style.display=="none"){d[b-1].style.display=""}else{d[b-1].style.display="none"}}}}function toggleVis(b){b=$(b);if(b.style.display=="none"){b.style.display=""}else{b.style.display="none"}}function imagePreview(b){if($(b)){var d=window.open("","preview","width=400,height=400,resizable=1,scrollbars=1");d.document.open();d.document.write('<body style="padding:0;margin:0"><img src="'+$(b).src+'" id="image_preview"/></body>');d.document.close();Event.observe(d,"load",function(){var e=d.document.getElementById("image_preview");d.resizeTo(e.width+40,e.height+80)})}}function checkByProductPriceType(b){if(b.id=="price_type"){this.productPriceType=b.value;return false}else{if(b.id=="price"&&this.productPriceType==0){return false}return true}}Event.observe(window,"load",function(){if($("price_default")&&$("price_default").checked){$("price").disabled="disabled"}});function toggleSeveralValueElements(f,e,b,d){if(e&&f){if(Object.prototype.toString.call(e)!="[object Array]"){e=[e]}e.each(function(g){toggleValueElements(f,g,b,d)})}}function toggleValueElements(l,d,f,h){if(d&&l){var n=[l];if(typeof f!="undefined"){if(Object.prototype.toString.call(f)!="[object Array]"){f=[f]}for(var g=0;g<f.length;g++){n.push(f[g])}}var e=Element.select(d,["select","input","textarea","button","img"]).filter(function(o){return(o.readAttribute("type")!="hidden")});var b=(h!=undefined?h:l.checked);e.each(function(p){if(checkByProductPriceType(p)){var o=n.length;while(o--&&p!=n[o]){}if(o!=-1){return}p.disabled=b;if(b){p.addClassName("disabled")}else{p.removeClassName("disabled")}if(p.nodeName.toLowerCase()=="img"){b?p.hide():p.show()}}})}}function submitAndReloadArea(e,d){if($(e)){var b=$(e).select("input","select","textarea");var f=Form.serializeElements(b,true);d=d+(d.match(new RegExp("\\?"))?"&isAjax=true":"?isAjax=true");new Ajax.Request(d,{parameters:$H(f),loaderArea:e,onSuccess:function(l){try{if(l.responseText.isJSON()){var g=l.responseText.evalJSON();if(g.error){alert(g.message)}if(g.ajaxExpired&&g.ajaxRedirect){setLocation(g.ajaxRedirect)}}else{$(e).update(l.responseText)}}catch(h){$(e).update(l.responseText)}}})}}function syncOnchangeValue(d,e){var b={baseElem:d,distElem:e};Event.observe(d,"change",function(){if($(this.baseElem)&&$(this.distElem)){$(this.distElem).value=$(this.baseElem).value}}.bind(b))}function updateElementAtCursor(e,f,g){if(g==undefined){g=window.self}if(document.selection){e.focus();sel=g.document.selection.createRange();sel.text=f}else{if(e.selectionStart||e.selectionStart=="0"){var d=e.selectionStart;var b=e.selectionEnd;e.value=e.value.substring(0,d)+f+e.value.substring(b,e.value.length)}else{e.value+=f}}}function firebugEnabled(){if(window.console&&window.console.firebug){return true}return false}function disableElement(b){b.disabled=true;b.addClassName("disabled")}function enableElement(b){b.disabled=false;b.removeClassName("disabled")}function disableElements(b){$$("."+b).each(disableElement)}function enableElements(b){$$("."+b).each(enableElement)}var Cookie={all:function(){var d=document.cookie.split(";");var b={};d.each(function(f,e){var g=f.strip().split("=");b[unescape(g[0])]=unescape(g[1])});return b},read:function(d){var b=this.all();if(b[d]){return b[d]}return null},write:function(h,f,g){var b="";if(g){var e=new Date();e.setTime(e.getTime()+(g*1000));b="; expires="+e.toGMTString()}var d="/"+BASE_URL.split("/").slice(3).join("/");document.cookie=escape(h)+"="+escape(f)+b+"; path="+d},clear:function(b){this.write(b,"",-1)}};var Fieldset={cookiePrefix:"fh-",applyCollapse:function(b){if($(b+"-state")){collapsed=$(b+"-state").value==1?0:1}else{collapsed=$(b+"-head").collapsed}if(collapsed==1||collapsed===undefined){$(b+"-head").removeClassName("open");if($(b+"-head").up(".section-config")){$(b+"-head").up(".section-config").removeClassName("active")}$(b).hide()}else{$(b+"-head").addClassName("open");if($(b+"-head").up(".section-config")){$(b+"-head").up(".section-config").addClassName("active")}$(b).show()}},toggleCollapse:function(b,d){if($(b+"-state")){collapsed=$(b+"-state").value==1?0:1}else{collapsed=$(b+"-head").collapsed}if(collapsed==1||collapsed===undefined){if($(b+"-state")){$(b+"-state").value=1}$(b+"-head").collapsed=0}else{if($(b+"-state")){$(b+"-state").value=0}$(b+"-head").collapsed=1}this.applyCollapse(b);if(typeof d!="undefined"){this.saveState(d,{container:b,value:$(b+"-state").value})}},addToPrefix:function(b){this.cookiePrefix+=b+"-"},saveState:function(b,d){new Ajax.Request(b,{method:"get",parameters:Object.toQueryString(d),loaderArea:false})}};var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var b="";var p,n,h,o,l,g,f;var d=0;if(typeof window.btoa==="function"){return window.btoa(e)}e=Base64._utf8_encode(e);while(d<e.length){p=e.charCodeAt(d++);n=e.charCodeAt(d++);h=e.charCodeAt(d++);o=p>>2;l=((p&3)<<4)|(n>>4);g=((n&15)<<2)|(h>>6);f=h&63;if(isNaN(n)){g=f=64}else{if(isNaN(h)){f=64}}b=b+this._keyStr.charAt(o)+this._keyStr.charAt(l)+this._keyStr.charAt(g)+this._keyStr.charAt(f)}return b},decode:function(e){var b="";var p,n,h;var o,l,g,f;var d=0;if(typeof window.atob==="function"){return window.atob(e)}e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(d<e.length){o=this._keyStr.indexOf(e.charAt(d++));l=this._keyStr.indexOf(e.charAt(d++));g=this._keyStr.indexOf(e.charAt(d++));f=this._keyStr.indexOf(e.charAt(d++));p=(o<<2)|(l>>4);n=((l&15)<<4)|(g>>2);h=((g&3)<<6)|f;b=b+String.fromCharCode(p);if(g!=64){b=b+String.fromCharCode(n)}if(f!=64){b=b+String.fromCharCode(h)}}b=Base64._utf8_decode(b);return b},mageEncode:function(b){return this.encode(b).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,",")},mageDecode:function(b){b=b.replace(/\-/g,"+").replace(/_/g,"/").replace(/,/g,"=");return this.decode(b)},idEncode:function(b){return this.encode(b).replace(/\+/g,":").replace(/\//g,"_").replace(/=/g,"-")},idDecode:function(b){b=b.replace(/\-/g,"=").replace(/_/g,"/").replace(/\:/g,"+");return this.decode(b)},_utf8_encode:function(d){d=d.replace(/\r\n/g,"\n");var b="";for(var f=0;f<d.length;f++){var e=d.charCodeAt(f);if(e<128){b+=String.fromCharCode(e)}else{if((e>127)&&(e<2048)){b+=String.fromCharCode((e>>6)|192);b+=String.fromCharCode((e&63)|128)}else{b+=String.fromCharCode((e>>12)|224);b+=String.fromCharCode(((e>>6)&63)|128);b+=String.fromCharCode((e&63)|128)}}}return b},_utf8_decode:function(b){var d="";var e=0;var f=c1=c2=0;while(e<b.length){f=b.charCodeAt(e);if(f<128){d+=String.fromCharCode(f);e++}else{if((f>191)&&(f<224)){c2=b.charCodeAt(e+1);d+=String.fromCharCode(((f&31)<<6)|(c2&63));e+=2}else{c2=b.charCodeAt(e+1);c3=b.charCodeAt(e+2);d+=String.fromCharCode(((f&15)<<12)|((c2&63)<<6)|(c3&63));e+=3}}}return d}};function sortNumeric(d,b){return d-b}(function(){var globals=["Prototype","Abstract","Try","Class","PeriodicalExecuter","Template","$break","Enumerable","$A","$w","$H","Hash","$R","ObjectRange","Ajax","$","Form","Field","$F","Toggle","Insertion","$continue","Position","Windows","Dialog","array","WindowUtilities","Builder","Effect","validateCreditCard","Validator","Validation","removeDelimiters","parseNumber","popWin","setLocation","setPLocation","setLanguageCode","decorateGeneric","decorateTable","decorateList","decorateDataList","parseSidUrl","formatCurrency","expandDetails","isIE","Varien","fireEvent","modulo","byteConvert","SessionError","varienLoader","varienLoaderHandler","setLoaderPosition","toggleSelectsUnderBlock","varienUpdater","confirmSetLocation","deleteConfirm","setElementDisable","toggleParentVis","toggleFieldsetVis","toggleVis","imagePreview","checkByProductPriceType","toggleSeveralValueElements","toggleValueElements","submitAndReloadArea","syncOnchangeValue","updateElementAtCursor","firebugEnabled","disableElement","enableElement","disableElements","enableElements","Cookie","Fieldset","Base64","sortNumeric","Element","$$","Sizzle","Selector","Window"];globals.forEach(function(prop){window[prop]=eval(prop)})})(); \ No newline at end of file diff --git a/lib/web/mage/backend/notification.js b/lib/web/mage/backend/notification.js index 7232e0310cddd185b88cbf5128cbf2502ba0172a..e333f25e991d80917c7f1b05a69bcd6ddd18a068 100644 --- a/lib/web/mage/backend/notification.js +++ b/lib/web/mage/backend/notification.js @@ -13,7 +13,8 @@ define([ $.widget('mage.notification', { options: { templates: { - global: '<div class="messages"><div class="message <% if (data.error) { %>error<% } %>"><div><%- data.message %></div></div></div>' + global: '<div id="messages"><div class="message <% if (data.error) { %>error<% } %>"><div><%- data.message %></div></div></div>', + error: '<div id="messages"><div class="messages"><div class="message message-error error"><div data-ui-id="messages-message-error"><%- data.message %></div></div></div></div>' } }, @@ -47,12 +48,16 @@ define([ * @param {Object} data - Data with a message to be displayed. */ add: function (data) { - var message = mageTemplate(this.options.templates.global, { + var template = data.error ? this.options.templates.error : this.options.templates.global; + var message = mageTemplate(template, { data: data }); - - $('#messages').append(message); - + if (typeof data.insertMethod === 'function') { + data.insertMethod(message); + } else { + var messageContainer = data.messageContainer || '#messages'; + $(messageContainer).prepend(message); + } return this; }, diff --git a/lib/web/mage/backend/validation.js b/lib/web/mage/backend/validation.js index ac7dc1dc1715958f4d7ea303b67170aed5bc6a28..4603e71b68bc2fe4ec6bf179b614a6127f6d2d16 100644 --- a/lib/web/mage/backend/validation.js +++ b/lib/web/mage/backend/validation.js @@ -145,34 +145,14 @@ * @param {Object} data - Data that came from backend. */ _showErrors: function(data) { - var attributes = data.attributes || {}, - element; - - if (data.attribute) { - attributes[data.attribute] = data.message; - } - - $('body').notification('clear'); - - _.each(attributes, function(message, code) { - element = this._getByCode(code); - - if(!element.length){ - $('body').notification('add', { - error: true, - message: message - }); - - return; - } - - element - .addClass('validate-ajax-error') - .data('msg-validate-ajax-error', message); - - this.validate.element(element); - - }, this); + $('body').notification('clear') + .notification('add', { + error: data.error, + message: data.message, + insertMethod: function(message) { + $('.messages:first').html(message); + } + }); }, /** diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index fbcf394becd3215ce0484cbefb6ddb585879c73c..1bc9729b4dad2c266e3d24406b960f35945fb0a1 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -443,13 +443,13 @@ function(v) { return $.mage.isEmptyNoTrim(v) || /^[A-Za-z]+[A-Za-z0-9_]+$/.test(v); }, - 'Please use only letters (a-z or A-Z), numbers (0-9) or underscore(_) in this field, first character should be a letter.' + 'Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.' ], "validate-street": [ function(v) { return $.mage.isEmptyNoTrim(v) || /^[ \w]{3,}([A-Za-z]\.)?([ \w]*\#\d+)?(\r\n| )[ \w]{3,}/.test(v); }, - 'Please use only letters (a-z or A-Z) or numbers (0-9) or spaces and # only in this field.' + 'Please use only letters (a-z or A-Z), numbers (0-9), spaces and "#" in this field.' ], "validate-phoneStrict": [ function(v) { @@ -467,19 +467,19 @@ function(v) { return $.mage.isEmptyNoTrim(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v); }, - 'Please enter a valid fax number. For example (123) 456-7890 or 123-456-7890.' + 'Please enter a valid fax number (Ex: 123-456-7890).' ], "validate-email": [ function(v) { return $.mage.isEmptyNoTrim(v) || /^([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*@([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*\.(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]){2,})$/i.test(v); }, - 'Please enter a valid email address. For example johndoe@domain.com.' + 'Please enter a valid email address (Ex: johndoe@domain.com).' ], "validate-emailSender": [ function(v) { return $.mage.isEmptyNoTrim(v) || /^[\S ]+$/.test(v); }, - 'Please enter a valid email address. For example johndoe@domain.com.' + 'Please enter a valid email address (Ex: johndoe@domain.com).' ], "validate-password": [ function(v) { @@ -513,7 +513,7 @@ } return true; }, - 'Please enter 7 or more characters. Password should contain both numeric and alphabetic characters.' + 'Please enter 7 or more characters, using both numeric and alphabetic.' ], "validate-url": [ function(v) { @@ -538,21 +538,21 @@ return $.mage.isEmptyNoTrim(v) || /^[A-Z][A-Z0-9_\/-]*$/i.test(v); }, - 'Please enter a valid XML-identifier. For example something_1, block5, id-4.' + 'Please enter a valid XML-identifier (Ex: something_1, block5, id-4).' ], "validate-ssn": [ function(v) { return $.mage.isEmptyNoTrim(v) || /^\d{3}-?\d{2}-?\d{4}$/.test(v); }, - 'Please enter a valid social security number. For example 123-45-6789.' + 'Please enter a valid social security number (Ex: 123-45-6789).' ], "validate-zip-us": [ function(v) { return $.mage.isEmptyNoTrim(v) || /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(v); }, - 'Please enter a valid zip code. For example 90602 or 90602-1234.' + 'Please enter a valid zip code (Ex: 90602 or 90602-1234).' ], "validate-date-au": [ function(v) { @@ -618,7 +618,7 @@ } return true; }, - 'Please input a valid CSS-length. For example 100px or 77pt or 20em or .5ex or 50%.' + 'Please input a valid CSS-length (Ex: 100px, 77pt, 20em, .5ex or 50%).' ], /** @description Additional methods */ "validate-number": [ @@ -771,13 +771,13 @@ function(v) { return $.mage.isEmptyNoTrim(v) || /^[a-z]+[a-z0-9_]+$/.test(v); }, - 'Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.' + 'Please use only letters (a-z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.' ], "validate-alphanum": [ function(v) { return $.mage.isEmptyNoTrim(v) || /^[a-zA-Z0-9]+$/.test(v); }, - 'Please use only letters (a-z or A-Z) or numbers (0-9) only in this field. No spaces or other characters are allowed.' + 'Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.' ], "validate-date": [ function(v) { @@ -806,7 +806,7 @@ return !dependentElements.length || $.mage.isEmptyNoTrim(dependentElements[0].value) || normalizedTime(v) <= normalizedTime(dependentElements[0].value); }, - 'The From Date value should be less than or equal to the To Date value.' + 'Make sure the To Date is later than or the same as the From Date.' ], "validate-cpassword": [ function() { @@ -833,7 +833,7 @@ function(v) { return $.mage.isEmptyNoTrim(v) || /^[a-z0-9][a-z0-9_\/-]+(\.[a-z0-9_-]+)?$/.test(v); }, - 'Please enter a valid URL Key. For example "example-page", "example-page.html" or "anotherlevel/example-page".' + 'Please enter a valid URL Key (Ex: "example-page", "example-page.html" or "anotherlevel/example-page").' ], "validate-zip-international": [ /*function(v) { @@ -853,7 +853,7 @@ return $(elm).val(); }).length > 0; }, - 'Please select one of the above options.' + 'Please select one of the options above.' ], "validate-state": [ function(v) { diff --git a/lib/web/mage/validation/validation.js b/lib/web/mage/validation/validation.js index d666d2025c2636cb00b27e5d2af2c8baa584323d..d93beb2abcc6c3e369bde604c45734c477f66c26 100644 --- a/lib/web/mage/validation/validation.js +++ b/lib/web/mage/validation/validation.js @@ -122,7 +122,7 @@ dateEntered = new Date(); dateEntered.setFullYear(year, month - 1, day); if (dateEntered > today) { - this.dobErrorMessage = $.mage.__('Please enter a date in the past.'); + this.dobErrorMessage = $.mage.__('Please enter a date from the past.'); return false; } diff --git a/lib/web/prototype/validation.js b/lib/web/prototype/validation.js index ae52b8cb4a1ed78fdac2274e062419fd8f47947f..059a2354764d22991ed385dace0d5997b04a0969 100644 --- a/lib/web/prototype/validation.js +++ b/lib/web/prototype/validation.js @@ -513,32 +513,32 @@ Validation.addAllThese([ ['validate-alpha', 'Please use letters only (a-z or A-Z) in this field.', function (v) { return Validation.get('IsEmpty').test(v) || /^[a-zA-Z]+$/.test(v) }], - ['validate-code', 'Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.', function (v) { + ['validate-code', 'Please use only letters (a-z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.', function (v) { return Validation.get('IsEmpty').test(v) || /^[a-z]+[a-z0-9_]+$/.test(v) }], - ['validate-alphanum', 'Please use only letters (a-z or A-Z) or numbers (0-9) only in this field. No spaces or other characters are allowed.', function(v) { + ['validate-alphanum', 'Please use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed.', function(v) { return Validation.get('IsEmpty').test(v) || /^[a-zA-Z0-9]+$/.test(v) }], ['validate-alphanum-with-spaces', 'Please use only letters (a-z or A-Z), numbers (0-9) or spaces only in this field.', function(v) { return Validation.get('IsEmpty').test(v) || /^[a-zA-Z0-9 ]+$/.test(v) }], - ['validate-street', 'Please use only letters (a-z or A-Z) or numbers (0-9) or spaces and # only in this field.', function(v) { + ['validate-street', 'Please use only letters (a-z or A-Z), numbers (0-9), spaces and "#" in this field.', function(v) { return Validation.get('IsEmpty').test(v) || /^[ \w]{3,}([A-Za-z]\.)?([ \w]*\#\d+)?(\r\n| )[ \w]{3,}/.test(v) }], - ['validate-phoneStrict', 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.', function(v) { + ['validate-phoneStrict', 'Please enter a valid phone number (Ex: 123-456-7890).', function(v) { return Validation.get('IsEmpty').test(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v); }], - ['validate-phoneLax', 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.', function(v) { + ['validate-phoneLax', 'Please enter a valid phone number (Ex: 123-456-7890).', function(v) { return Validation.get('IsEmpty').test(v) || /^((\d[-. ]?)?((\(\d{3}\))|\d{3}))?[-. ]?\d{3}[-. ]?\d{4}$/.test(v); }], - ['validate-fax', 'Please enter a valid fax number. For example (123) 456-7890 or 123-456-7890.', function(v) { + ['validate-fax', 'Please enter a valid fax number (Ex: 123-456-7890).', function(v) { return Validation.get('IsEmpty').test(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v); }], ['validate-date', 'Please enter a valid date.', function(v) { var test = new Date(v); return Validation.get('IsEmpty').test(v) || !isNaN(test); }], - ['validate-date-range', 'The From Date value should be less than or equal to the To Date value.', function(v, elm) { + ['validate-date-range', 'Make sure the To Date is later than or the same as the From Date.', function(v, elm) { var m = /\bdate-range-(\w+)-(\w+)\b/.exec(elm.className); if (!m || m[2] == 'to' || Validation.get('IsEmpty').test(v)) { return true; @@ -557,7 +557,7 @@ Validation.addAllThese([ return !dependentElements.length || Validation.get('IsEmpty').test(dependentElements[0].value) || normalizedTime(v) <= normalizedTime(dependentElements[0].value); }], - ['validate-email', 'Please enter a valid email address. For example johndoe@domain.com.', function (v) { + ['validate-email', 'Please enter a valid email address (Ex: johndoe@domain.com).', function (v) { //return Validation.get('IsEmpty').test(v) || /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(v) //return Validation.get('IsEmpty').test(v) || /^[\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9][\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9\.]{1,30}[\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9]@([a-z0-9_-]{1,30}\.){1,5}[a-z]{2,4}$/i.test(v) return Validation.get('IsEmpty').test(v) || /^([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*@([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z0-9-]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*\.(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]){2,})$/i.test(v) @@ -569,7 +569,7 @@ Validation.addAllThese([ var pass=v.strip(); /*strip leading and trailing spaces*/ return !(pass.length>0 && pass.length < 6); }], - ['validate-admin-password', 'Please enter 7 or more characters. Password should contain both numeric and alphabetic characters.', function(v) { + ['validate-admin-password', 'Please enter 7 or more characters, using both numeric and alphabetic.', function(v) { var pass=v.strip(); if (0 == pass.length) { return true; @@ -611,26 +611,26 @@ Validation.addAllThese([ v = (v || '').replace(/^\s+/, '').replace(/\s+$/, ''); return Validation.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))(\.[A-Z0-9]([A-Z0-9_-]*[A-Z0-9]|))*)(:(\d+))?(\/[A-Z0-9~](([A-Z0-9_~-]|\.)*[A-Z0-9~]|))*\/?(.*)?$/i.test(v) }], - ['validate-clean-url', 'Please enter a valid URL. For example http://www.example.com or www.example.com', function (v) { + ['validate-clean-url', 'Please enter a valid URL (Ex: "http://www.example.com" or "www.example.com").', function (v) { return Validation.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(v) || /^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(v) }], - ['validate-identifier', 'Please enter a valid URL Key. For example "example-page", "example-page.html" or "anotherlevel/example-page".', function (v) { + ['validate-identifier', 'Please enter a valid URL Key (Ex: "example-page", "example-page.html" or "anotherlevel/example-page").', function (v) { return Validation.get('IsEmpty').test(v) || /^[a-z0-9][a-z0-9_\/-]+(\.[a-z0-9_-]+)?$/.test(v) }], - ['validate-xml-identifier', 'Please enter a valid XML-identifier. For example something_1, block5, id-4.', function (v) { + ['validate-xml-identifier', 'Please enter a valid XML-identifier (Ex: something_1, block5, id-4).', function (v) { return Validation.get('IsEmpty').test(v) || /^[A-Z][A-Z0-9_\/-]*$/i.test(v) }], - ['validate-ssn', 'Please enter a valid social security number. For example 123-45-6789.', function(v) { + ['validate-ssn', 'Please enter a valid social security number (Ex: 123-45-6789).', function(v) { return Validation.get('IsEmpty').test(v) || /^\d{3}-?\d{2}-?\d{4}$/.test(v); }], - ['validate-zip-us', 'Please enter a valid zip code. For example 90602 or 90602-1234.', function(v) { + ['validate-zip-us', 'Please enter a valid zip code (Ex: 90602 or 90602-1234).', function(v) { return Validation.get('IsEmpty').test(v) || /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(v); }], ['validate-zip-international', 'Please enter a valid zip code.', function(v) { //return Validation.get('IsEmpty').test(v) || /(^[A-z0-9]{2,10}([\s]{0,1}|[\-]{0,1})[A-z0-9]{2,10}$)/.test(v); return true; }], - ['validate-date-au', 'Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.', function(v) { + ['validate-date-au', 'Please use this date format: dd/mm/yyyy (Ex: "17/03/2006" for the 17th of March, 2006).', function(v) { if(Validation.get('IsEmpty').test(v)) return true; var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/; if(!regex.test(v)) return false; @@ -639,14 +639,14 @@ Validation.addAllThese([ (parseInt(RegExp.$1, 10) == d.getDate()) && (parseInt(RegExp.$3, 10) == d.getFullYear() ); }], - ['validate-currency-dollar', 'Please enter a valid $ amount. For example $100.00.', function(v) { + ['validate-currency-dollar', 'Please enter a valid $ amount (Ex: $100.00).', function(v) { // [$]1[##][,###]+[.##] // [$]1###+[.##] // [$]0.## // [$].## return Validation.get('IsEmpty').test(v) || /^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(v) }], - ['validate-one-required', 'Please select one of the above options.', function (v,elm) { + ['validate-one-required', 'Please select one of the options above.', function (v,elm) { var p = elm.parentNode; var options = p.getElementsByTagName('INPUT'); return $A(options).any(function(elm) { @@ -792,19 +792,19 @@ Validation.addAllThese([ return false; }], ['validate-ajax', '', function(v, elm) { return true; }], - ['validate-data', 'Please use only letters (a-z or A-Z), numbers (0-9) or underscore(_) in this field, first character should be a letter.', function (v) { + ['validate-data', 'Please use only letters (a-z or A-Z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter.', function (v) { if(v != '' && v) { return /^[A-Za-z]+[A-Za-z0-9_]+$/.test(v); } return true; }], - ['validate-css-length', 'Please input a valid CSS-length. For example 100px or 77pt or 20em or .5ex or 50%.', function (v) { + ['validate-css-length', 'Please input a valid CSS-length (Ex: 100px, 77pt, 20em, .5ex or 50%).', function (v) { if (v != '' && v) { return /^[0-9\.]+(px|pt|em|ex|%)?$/.test(v) && (!(/\..*\./.test(v))) && !(/\.$/.test(v)); } return true; }], - ['validate-length', 'Text length does not satisfy specified text range.', function (v, elm) { + ['validate-length', 'Text length does not meet the specified text range.', function (v, elm) { var reMax = new RegExp(/^maximum-length-[0-9]+$/); var reMin = new RegExp(/^minimum-length-[0-9]+$/); var result = true; @@ -821,7 +821,7 @@ Validation.addAllThese([ return result; }], ['validate-percents', 'Please enter a number lower than 100.', {max:100}], - ['required-file', 'Please select a file', function(v, elm) { + ['required-file', 'Please select a file.', function(v, elm) { var result = !Validation.get('IsEmpty').test(v); if (result === false) { ovId = elm.id + '_value'; diff --git a/lib/web/varien/js.js b/lib/web/varien/js.js index 934a071f207d96a20d74e4b6b5a6e35d61bf4f6d..c8fa3d7b8ed37ba161a4acbe517b4af459f89d9c 100644 --- a/lib/web/varien/js.js +++ b/lib/web/varien/js.js @@ -365,7 +365,7 @@ Varien.DateElement.prototype = { && this.year.value.strip().empty() ) { if (this.required) { - error = 'This date is a required value.'; + error = 'Please enter a date.'; } else { this.full.value = ''; } diff --git a/package.json b/package.json index 55e65759502a19f9b7a8bed20ea637dbbeb615fc..c2f3cb1eaaf9edd5e19767c82f75782f022f1373 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "grunt-contrib-less": "^0.12.0", "grunt-contrib-watch": "^0.6.1", "grunt-exec": "^0.4.6", + "grunt-replace": "^0.9.2", "grunt-styledocco": "^0.1.4", "grunt-template-jasmine-requirejs": "^0.2.3", "grunt-text-replace": "^0.4.0", diff --git a/pub/.htaccess b/pub/.htaccess index 7cac070b85bf7b33c187cfcefd3bf6e8e456306b..6e6f63c43581f2cb307f894376f92f02a0574fcc 100755 --- a/pub/.htaccess +++ b/pub/.htaccess @@ -36,7 +36,6 @@ ############################################ ## adjust memory limit -# php_value memory_limit 64M php_value memory_limit 256M php_value max_execution_time 18000 diff --git a/pub/errors/processor.php b/pub/errors/processor.php index 7a25b8ee1f5ed387685cbad55509fccaa5678ff4..73d1925e8a300f47d534a682aecd224a152f3f23 100755 --- a/pub/errors/processor.php +++ b/pub/errors/processor.php @@ -225,7 +225,13 @@ class Processor */ public function getViewFileUrl() { - return $this->getBaseUrl() . self::ERROR_DIR . '/' . $this->_config->skin . '/'; + //The url needs to be updated base on Document root path. + return $this->getBaseUrl() . + str_replace( + str_replace('\\', '/', $this->_indexDir), + '', + str_replace('\\', '/', $this->_errorDir) + ) . $this->_config->skin . '/'; } /** @@ -385,11 +391,6 @@ class Processor protected function _getFilePath($file, $directories = null) { if (is_null($directories)) { - $directories = []; - - if (!$this->_root) { - $directories[] = $this->_indexDir . self::ERROR_DIR . '/'; - } $directories[] = $this->_errorDir; } @@ -408,16 +409,6 @@ class Processor */ protected function _getTemplatePath($template) { - $directories = []; - - if (!$this->_root) { - $directories[] = $this->_indexDir . self::ERROR_DIR . '/' . $this->_config->skin . '/'; - - if ($this->_config->skin != self::DEFAULT_SKIN) { - $directories[] = $this->_indexDir . self::ERROR_DIR . '/' . self::DEFAULT_SKIN . '/'; - } - } - $directories[] = $this->_errorDir . $this->_config->skin . '/'; if ($this->_config->skin != self::DEFAULT_SKIN) { diff --git a/setup/config/di.config.php b/setup/config/di.config.php index 8d0f258ba828764481e37cc435a4fbddddc63cff..30e6af237e912b1c07e670645486e2db7ec80acc 100644 --- a/setup/config/di.config.php +++ b/setup/config/di.config.php @@ -28,6 +28,8 @@ return [ 'Zend\ServiceManager\ServiceLocatorInterface' => 'ServiceManager', 'Magento\Framework\DB\LoggerInterface' => 'Magento\Framework\DB\Logger\Null', 'Magento\Framework\Locale\ConfigInterface' => 'Magento\Framework\Locale\Config', + 'Magento\Framework\Module\ModuleRegistryInterface' => 'Magento\Framework\Module\Registrar', + 'Magento\Framework\Filesystem\DriverInterface' => 'Magento\Framework\Filesystem\Driver\File', ], ], ], diff --git a/setup/index.php b/setup/index.php index 7c7b069afc31cd45bff2c2e2cf69d7fbc37c877c..51f1ef3bfadeb81db930deffb6a0e6415439a22a 100644 --- a/setup/index.php +++ b/setup/index.php @@ -23,4 +23,9 @@ try { HTML; exit(1); } + +// For Setup Wizard we are using our customized error handler +$handler = new \Magento\Framework\App\ErrorHandler(); +set_error_handler([$handler, 'handler']); + \Zend\Mvc\Application::init(require __DIR__ . '/config/application.config.php')->run(); diff --git a/setup/pub/magento/setup/customize-your-store.js b/setup/pub/magento/setup/customize-your-store.js index 2d33921503fa57911d0a55017018b794021896ce..ef4721f703ab78d0d44db713e102a95e9c2fd832 100644 --- a/setup/pub/magento/setup/customize-your-store.js +++ b/setup/pub/magento/setup/customize-your-store.js @@ -11,6 +11,7 @@ angular.module('customize-your-store', ['ngStorage', 'ngSanitize']) currency: 'USD', language: 'en_US', useSampleData: false, + cleanUpDatabase: false, loadedAllModules: false, showModulesControl: false, selectAll: true, diff --git a/setup/pub/magento/setup/install.js b/setup/pub/magento/setup/install.js index e519ec9ba653880905b94689312675e89dd610fc..2f34edd1ad1c8ebfafd02608908bebddf57b117d 100644 --- a/setup/pub/magento/setup/install.js +++ b/setup/pub/magento/setup/install.js @@ -10,6 +10,8 @@ angular.module('install', ['ngStorage']) $scope.isInProgress = false; $scope.isConsole = false; $scope.isDisabled = false; + $scope.isSampleDataError = false; + $scope.isShowCleanUpBox = false; $scope.toggleConsole = function () { $scope.isConsole = $scope.isConsole === false; }; @@ -34,6 +36,9 @@ angular.module('install', ['ngStorage']) $scope.progressText = response.data.progress + '%'; } else { $scope.displayFailure(); + if (response.data.isSampleDataError) { + $scope.isSampleDataError = true; + } } if ($scope.isInProgress) { $timeout(function() { @@ -43,7 +48,24 @@ angular.module('install', ['ngStorage']) }); }; + $scope.showCleanUpBox = function() { + $scope.isShowCleanUpBox = true; + }; + $scope.hideCleanUpBox = function() { + $scope.isShowCleanUpBox = false; + }; + $scope.startCleanup = function(performClenup) { + $scope.hideCleanUpBox(); + $scope.isSampleDataError = false; + $localStorage.store.cleanUpDatabase = performClenup; + $scope.start(); + }; + $scope.start = function () { + if ($scope.isSampleDataError) { + $scope.showCleanUpBox(); + return; + } var data = { 'db': $localStorage.db, 'admin': $localStorage.admin, @@ -60,6 +82,9 @@ angular.module('install', ['ngStorage']) $scope.nextState(); } else { $scope.displayFailure(); + if (response.isSampleDataError) { + $scope.isSampleDataError = true; + } } }); progress.get(function () { diff --git a/setup/pub/styles/setup.css b/setup/pub/styles/setup.css index d667b416c7a211c9990db9a8b32bf896fdadc6a6..e12156d57ae3689e58eb72dd7331041b8f2bcc11 100644 --- a/setup/pub/styles/setup.css +++ b/setup/pub/styles/setup.css @@ -3,4 +3,4 @@ * See COPYING.txt for license details. */ -html{box-sizing:border-box;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}*,:after,:before{box-sizing:inherit}:focus{box-shadow:none;outline:0}._keyfocus :focus{box-shadow:0 0 0 1px #008bdb}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}embed,img,object,video{max-width:100%}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}:after,:before{box-sizing:content-box}.abs-clearer:after,.form-row:after,.header:after,.nav:after,.row:after{content:"";display:table;clear:both}.ng-cloak{display:none!important}.hide.hide{display:none}.show.show{display:block}.text-center{text-align:center}.text-right{text-align:right}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/light/opensans-300.eot);src:url(../../pub/fonts/opensans/light/opensans-300.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/light/opensans-300.woff2) format('woff2'),url(../../pub/fonts/opensans/light/opensans-300.woff) format('woff'),url(../../pub/fonts/opensans/light/opensans-300.ttf) format('truetype'),url('../../pub/fonts/opensans/light/opensans-300.svg#Open Sans') format('svg');font-weight:300;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/regular/opensans-400.eot);src:url(../../pub/fonts/opensans/regular/opensans-400.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/regular/opensans-400.woff2) format('woff2'),url(../../pub/fonts/opensans/regular/opensans-400.woff) format('woff'),url(../../pub/fonts/opensans/regular/opensans-400.ttf) format('truetype'),url('../../pub/fonts/opensans/regular/opensans-400.svg#Open Sans') format('svg');font-weight:400;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/semibold/opensans-600.eot);src:url(../../pub/fonts/opensans/semibold/opensans-600.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/semibold/opensans-600.woff2) format('woff2'),url(../../pub/fonts/opensans/semibold/opensans-600.woff) format('woff'),url(../../pub/fonts/opensans/semibold/opensans-600.ttf) format('truetype'),url('../../pub/fonts/opensans/semibold/opensans-600.svg#Open Sans') format('svg');font-weight:600;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/bold/opensans-700.eot);src:url(../../pub/fonts/opensans/bold/opensans-700.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/bold/opensans-700.woff2) format('woff2'),url(../../pub/fonts/opensans/bold/opensans-700.woff) format('woff'),url(../../pub/fonts/opensans/bold/opensans-700.ttf) format('truetype'),url('../../pub/fonts/opensans/bold/opensans-700.svg#Open Sans') format('svg');font-weight:700;font-style:normal}html{font-size:62.5%}body{color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:400;line-height:1.4}h1,h2,h3,h4,h5,h6{font-weight:400;margin-top:0}p{margin:0 0 1em}a{color:#008bdb;text-decoration:none}a:hover{color:#0fa7ff;text-decoration:underline}@font-face{font-family:Icons;src:url(../../pub/fonts/icons/icons.eot);src:url(../../pub/fonts/icons/icons.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/icons/icons.woff2) format('woff2'),url(../../pub/fonts/icons/icons.woff) format('woff'),url(../../pub/fonts/icons/icons.ttf) format('truetype'),url(../../pub/fonts/icons/icons.svg#Icons) format('svg');font-weight:400;font-style:normal}[class*=icon-]{display:inline-block;line-height:1}[class*=icon-]:after{font-family:Icons}.icon-success-thick:after{content:'\e600'}.icon-success:after{content:'\e601'}.icon-collapse:after{content:'\e602'}.icon-failed-thick:after{content:'\e603'}.icon-failed:after{content:'\e604'}.icon-expand:after{content:'\e605'}.icon-warning:after{content:'\e606'}.icon-failed-round,.icon-success-round{border-radius:100%;color:#fff;font-size:2.5rem;height:1em;position:relative;text-align:center;width:1em}.icon-failed-round:after,.icon-success-round:after{bottom:0;font-size:.8em;left:0;position:absolute;right:0;top:.15em}.icon-success-round{background-color:#79a22e}.icon-success-round:after{content:'\e600'}.icon-failed-round{background-color:#e22626}.icon-failed-round:after{content:'\e603'}dl,ol,ul{margin-top:0}.list{margin-bottom:1em;padding-left:0}.list>li{display:block;margin-bottom:.75em;position:relative}.list>li>.icon-failed,.list>li>.icon-success{font-size:1.6em;left:-.1em;position:absolute;top:0}.list>li>.icon-success{color:#79a22e}.list>li>.icon-failed{color:#e22626}.list-item-failed,.list-item-icon,.list-item-success{padding-left:3.5rem}.list-item-failed:before,.list-item-success:before{font-family:Icons;font-size:1.6em;left:-.1em;position:absolute;top:-.2em}.list-item-success:before{color:#79a22e;content:'\e601'}.list-item-failed:before{color:#e22626;content:'\e604'}.list-definition{margin:0 0 3rem;padding:0}.list-definition>dt{clear:left;float:left}.list-definition>dd{margin-bottom:1em;margin-left:20rem}.btn-wrap{margin:0 auto}.btn-wrap .btn{width:100%}.btn{background:#e3e3e3;border:none;color:#514943;display:inline-block;font-size:1.6rem;font-weight:600;padding:.45em .5em;text-align:center}.btn:hover{background-color:#dbdbdb;color:#514943;text-decoration:none}.btn:active{background-color:#d6d6d6}.btn.disabled,.btn[disabled]{cursor:default;opacity:.5;pointer-events:none}.ie9 .btn.disabled,.ie9 .btn[disabled]{background-color:#f0f0f0;opacity:1;text-shadow:none}.btn-large{padding:.75em 1.25em}.btn-link{background-color:transparent;border:none;color:#008bdb;font-family:1.6rem;font-size:1.5rem}.btn-link:hover{background-color:transparent;color:#0fa7ff}.btn-prime{background-color:#eb5202;color:#fff;text-shadow:1px 1px 0 rgba(0,0,0,.25)}.btn-prime:hover{background-color:#f65405;background-repeat:repeat-x;background-image:linear-gradient(to right,#e04f00 0,#f65405 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#e04f00', endColorstr='#f65405', GradientType=1);color:#fff}.btn-prime:active{background-color:#e04f00;background-repeat:repeat-x;background-image:linear-gradient(to right,#f65405 0,#e04f00 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f65405', endColorstr='#e04f00', GradientType=1)}.ie9 .btn-prime.disabled,.ie9 .btn-prime[disabled]{background-color:#fd6e23}.ie9 .btn-prime.disabled:active,.ie9 .btn-prime.disabled:hover,.ie9 .btn-prime[disabled]:active,.ie9 .btn-prime[disabled]:hover{background-color:#fd6e23;-webkit-filter:none;filter:none}.btn-secondary{background-color:#514943;color:#fff}.btn-secondary:hover{background-color:#5f564f;color:#fff}.btn-secondary:active{background-color:#574e48}.ie9 .btn-secondary.disabled,.ie9 .btn-secondary[disabled]{background-color:#514943}.ie9 .btn-secondary.disabled:active,.ie9 .btn-secondary.disabled:hover,.ie9 .btn-secondary[disabled]:active,.ie9 .btn-secondary[disabled]:hover{background-color:#514943;-webkit-filter:none;filter:none}[class*=btn-wrap-triangle]{overflow:hidden;position:relative}[class*=btn-wrap-triangle] .btn:after{border-style:solid;content:'';height:0;position:absolute;top:0;width:0}.btn-wrap-triangle-right{display:inline-block;padding-right:1.74rem;position:relative}.btn-wrap-triangle-right .btn{text-indent:.92rem}.btn-wrap-triangle-right .btn:after{border-color:transparent transparent transparent #e3e3e3;border-width:1.84rem 0 1.84rem 1.84rem;left:100%;margin-left:-1.74rem}.btn-wrap-triangle-right .btn:hover:after{border-left-color:#dbdbdb}.btn-wrap-triangle-right .btn:active:after{border-left-color:#d6d6d6}.btn-wrap-triangle-right .btn:not(.disabled):active,.btn-wrap-triangle-right .btn:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn.disabled:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:after{border-color:transparent transparent transparent #f0f0f0}.ie9 .btn-wrap-triangle-right .btn.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:hover:after{border-left-color:#f0f0f0}.btn-wrap-triangle-right .btn-prime:after{border-color:transparent transparent transparent #eb5202}.btn-wrap-triangle-right .btn-prime:hover:after{border-left-color:#f65405}.btn-wrap-triangle-right .btn-prime:active:after{border-left-color:#e04f00}.btn-wrap-triangle-right .btn-prime:not(.disabled):active,.btn-wrap-triangle-right .btn-prime:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:after{border-color:transparent transparent transparent #fd6e23}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:hover:after{border-left-color:#fd6e23}.btn-wrap-triangle-left{display:inline-block;padding-left:1.74rem}.btn-wrap-triangle-left .btn{text-indent:-.92rem}.btn-wrap-triangle-left .btn:after{border-color:transparent #e3e3e3 transparent transparent;border-width:1.84rem 1.84rem 1.84rem 0;margin-right:-1.74rem;right:100%}.btn-wrap-triangle-left .btn:hover:after{border-right-color:#dbdbdb}.btn-wrap-triangle-left .btn:active:after{border-right-color:#d6d6d6}.btn-wrap-triangle-left .btn:not(.disabled):active,.btn-wrap-triangle-left .btn:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn.disabled:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:after{border-color:transparent #f0f0f0 transparent transparent}.ie9 .btn-wrap-triangle-left .btn.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:hover:after{border-right-color:#f0f0f0}.btn-wrap-triangle-left .btn-prime:after{border-color:transparent #eb5202 transparent transparent}.btn-wrap-triangle-left .btn-prime:hover:after{border-right-color:#e04f00}.btn-wrap-triangle-left .btn-prime:active:after{border-right-color:#f65405}.btn-wrap-triangle-left .btn-prime:not(.disabled):active,.btn-wrap-triangle-left .btn-prime:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:after{border-color:transparent #fd6e23 transparent transparent}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:hover:after{border-right-color:#fd6e23}.btn-expand{background-color:transparent;border:none;color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;padding:0;position:relative}.btn-expand.expanded:after{border-color:transparent transparent #303030;border-width:0 .285em .36em}.btn-expand.expanded:hover:after{border-color:transparent transparent #3d3d3d}.btn-expand:hover{background-color:transparent;border:none;color:#3d3d3d}.btn-expand:hover:after{border-color:#3d3d3d transparent transparent}.btn-expand:after{border-color:#303030 transparent transparent;border-style:solid;border-width:.36em .285em 0;content:'';height:0;left:100%;margin-left:.5em;margin-top:-.18em;position:absolute;top:50%;width:0}[class*=col-] .form-el-input,[class*=col-] .form-el-select{width:100%}.form-fieldset{border:none;margin:0 0 1em;padding:0}.form-row{margin-bottom:2.2rem}.form-row .form-row{margin-bottom:.4rem}.form-row .form-label{display:block;font-weight:600;padding:.6rem 2.1em 0 0;text-align:right}.form-row .form-label.required{position:relative}.form-row .form-label.required:after{color:#eb5202;content:'*';font-size:1.15em;position:absolute;right:.7em;top:.5em}.form-row .form-el-checkbox+.form-label:before,.form-row .form-el-radio+.form-label:before{top:.7rem}.form-row .form-el-checkbox+.form-label:after,.form-row .form-el-radio+.form-label:after{top:1.1rem}input:not([disabled]):focus,textarea:not([disabled]):focus{box-shadow:none}.form-el-input{border:1px solid #adadad;border-radius:2px;color:#303030;padding:.35em .55em .5em}.form-el-input:hover{border-color:#949494}.form-el-input:focus{border-color:#008bdb}.form-label{margin-bottom:.5em}[class*=form-label][for]{cursor:pointer}.form-el-insider-wrap{display:table;width:100%}.form-el-insider-input{display:table-cell;width:100%}.form-el-insider{border-radius:2px;display:table-cell;vertical-align:top;padding:.43em .55em .5em 0}.form-legend,.form-legend-expand,.form-legend-light{display:block;margin:0}.form-legend,.form-legend-expand{margin-bottom:2.5em;padding-top:1.5em;font-weight:600;font-size:1.25em}.form-legend{width:100%;border-top:1px solid #ccc}.form-legend-light{margin-bottom:1.5em;font-size:1em}.form-legend-expand{transition:opacity .2s linear;cursor:pointer}.form-legend-expand:hover{opacity:.85}.form-legend-expand.expanded:after{content:'\e602'}.form-legend-expand:after{margin-left:.5em;font-weight:400;font-size:1.15em;font-family:Icons;content:'\e605';vertical-align:sub}.form-el-checkbox,.form-el-radio{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.form-el-checkbox.disabled+.form-label,.form-el-checkbox.disabled+.form-label:before,.form-el-checkbox[disabled]+.form-label,.form-el-checkbox[disabled]+.form-label:before,.form-el-radio.disabled+.form-label,.form-el-radio.disabled+.form-label:before,.form-el-radio[disabled]+.form-label,.form-el-radio[disabled]+.form-label:before{cursor:default;opacity:.5;pointer-events:none}.form-el-checkbox:not(.disabled)+.form-label:hover:before,.form-el-checkbox:not([disabled])+.form-label:hover:before,.form-el-radio:not(.disabled)+.form-label:hover:before,.form-el-radio:not([disabled])+.form-label:hover:before{border-color:#514943}.form-el-checkbox+.form-label,.form-el-radio+.form-label{font-weight:400;padding-left:2em;padding-right:0;position:relative;text-align:left;transition:border-color .1s linear}.form-el-checkbox+.form-label:before,.form-el-radio+.form-label:before{border:1px solid;content:'';left:0;position:absolute;top:.1rem;transition:border-color .1s linear}.form-el-checkbox+.form-label:before{border-color:#adadad;border-radius:2px;height:1.4rem;line-height:1;width:1.4rem}.form-el-checkbox:checked+.form-label::before{content:'\e600';font-family:Icons}.form-el-radio+.form-label:before{background-color:#fff;border:1px solid #adadad;border-radius:100%;height:1.6rem;width:1.6rem}.form-el-radio+.form-label:after{background:0 0;border:.5rem solid transparent;border-radius:100%;content:'';height:0;left:.4rem;position:absolute;top:.5rem;transition:background .3s linear;width:0}.form-el-radio:checked+.form-label{cursor:default}.form-el-radio:checked+.form-label:after{border-color:#514943}.form-select-label{border:1px solid #adadad;border-radius:2px;color:#303030;cursor:pointer;display:block;overflow:hidden;position:relative}.form-select-label:hover,.form-select-label:hover:after{border-color:#949494}.form-select-label:active,.form-select-label:active:after,.form-select-label:focus,.form-select-label:focus:after{border-color:#008bdb}.form-select-label:after{background:#e3e3e3;border-left:1px solid #adadad;bottom:0;content:'';position:absolute;right:0;top:0;width:2.36em;z-index:-2}.ie9 .form-select-label:after{display:none}.form-select-label:before{border-color:#303030 transparent transparent;border-style:solid;border-width:5px 4px 0;content:'';height:0;margin-right:-4px;margin-top:-2.5px;position:absolute;right:1.18em;top:50%;width:0;z-index:-1}.ie9 .form-select-label:before{display:none}.form-select-label .form-el-select{background:0 0;border:none;border-radius:0;content:'';display:block;margin:0;padding:.35em calc(2.36em + 10%) .5em .55em;width:110%}.ie9 .form-select-label .form-el-select{padding-right:.55em;width:100%}.form-el-select{background:#fff;border:1px solid #adadad;border-radius:2px;color:#303030;display:block;padding:.35em .55em}.multiselect-custom{position:relative;height:45.2rem;border:1px solid #adadad;overflow:auto;margin:0 0 1.5rem}.multiselect-custom ul{margin:0;padding:0;list-style:none;min-width:29rem}.multiselect-custom .item{padding:1rem 1.4rem}.multiselect-custom .selected{background-color:#e0f6fe}.multiselect-custom .form-label{margin-bottom:0}[class*=form-el-].invalid{border-color:#e22626}[class*=form-el-].invalid+.error-container{display:block}.error-container{background-color:#fffbbb;border:1px solid #ee7d7d;border-radius:2px;color:#514943;display:none;font-size:1.19rem;margin-top:.2rem;padding:.4235em .6655em .605em}.check-result-message{margin-left:.5em;min-height:3.68rem;-webkit-align-items:center;-ms-align-items:center;-ms-flex-align:center;align-items:center;display:-webkit-flex;display:-ms-flexbox;display:flex}.check-result-text{margin-left:.5em}.pseudo-table{display:table}.pseudo-td{display:table-cell}.messages{margin:0 0 2rem}.message{background:#fffbbb;border:none;border-radius:0;color:#333;font-size:14px;margin:0 0 1px;padding:1.8rem 4rem 1.8rem 5.5rem;position:relative;text-shadow:none}.message:before{background:0 0;border:0;color:#007bdb;content:'\e61a';font-family:Icons;font-size:1.9rem;font-style:normal;font-weight:400;height:auto;left:1.9rem;line-height:inherit;margin-top:-1.3rem;position:absolute;speak:none;text-shadow:none;top:50%;width:auto}.message-notice:before{color:#007bdb;content:'\e61a'}.message-warning:before{color:#eb5202;content:'\e623'}.message-error{background:#fcc}.message-error:before{color:#e22626;content:'\e632';font-size:1.5rem;left:2.2rem;margin-top:-1rem}.message-success:before{color:#79a22e;content:'\e62d'}.message-spinner:before{display:none}.message-spinner .spinner{font-size:2.5rem;left:1.5rem;position:absolute;top:1.5rem}.message-in-rating-edit{margin-left:1.8rem;margin-right:1.8rem}.message{margin-bottom:3rem}.container{display:block;margin:0 auto 4rem;max-width:100rem;padding:0 2rem}.row{margin-left:0;margin-right:0}.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9,.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{min-height:1px;padding-left:0;padding-right:0;position:relative}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}.nav{background-color:#f8f8f8;border-bottom:1px solid #e3e3e3;border-top:1px solid #e3e3e3;display:none;padding:2.2rem 1.5rem 0 0}.nav .btn-group,.nav-bar-outer-actions{float:right;margin-bottom:1.7rem}.nav .btn-group .btn-wrap,.nav-bar-outer-actions .btn-wrap{float:right;margin-left:.5rem;margin-right:.5rem}.nav-bar-outer-actions{margin-top:-10.6rem;padding-right:1.5rem}.btn-wrap-try-again{width:9.5rem}.btn-wrap-next,.btn-wrap-prev{width:8.5rem}.nav-bar{counter-reset:i;float:left;margin:0 1rem 1.7rem 0;padding:0;position:relative;white-space:nowrap}.nav-bar:before{background-color:#d4d4d4;background-repeat:repeat-x;background-image:linear-gradient(to bottom,#d1d1d1 0,#d4d4d4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d1d1d1', endColorstr='#d4d4d4', GradientType=0);border-bottom:1px solid #d9d9d9;border-top:1px solid #bfbfbf;content:'';height:.8rem;left:5.15rem;position:absolute;right:5.15rem;top:.7rem}.nav-bar>li{display:inline-block;font-size:0;position:relative;vertical-align:top;width:10.3rem}.nav-bar>li:first-child:after{display:none}.nav-bar>li:after{background-color:#514943;content:'';height:.5rem;left:calc(-50% + .25rem);position:absolute;right:calc(50% + .7rem);top:.9rem}.nav-bar>li.disabled:before{bottom:0;content:'';left:0;position:absolute;right:0;top:0;z-index:1}.nav-bar>li.active~li:after{display:none}.nav-bar>li.active~li a:after{background-color:transparent;border-color:transparent;color:#a6a6a6}.nav-bar>li.active a{color:#000}.nav-bar>li.active a:hover{cursor:default}.nav-bar>li.active a:after{background-color:#fff;content:''}.nav-bar a{color:#514943;display:block;font-size:1.2rem;font-weight:600;line-height:1.2;overflow:hidden;padding:3rem .5em 0;position:relative;text-align:center;text-overflow:ellipsis}.nav-bar a:hover{text-decoration:none}.nav-bar a:after{background-color:#514943;border:.4rem solid #514943;border-radius:100%;color:#fff;content:counter(i);counter-increment:i;height:.7rem;left:50%;line-height:.6;margin-left:-.8rem;position:absolute;right:auto;text-align:center;top:.4rem;width:.7rem}.nav-bar a:before{background-color:#d6d6d6;border:1px solid transparent;border-bottom-color:#d9d9d9;border-radius:100%;border-top-color:#bfbfbf;content:'';height:2.1rem;left:50%;line-height:1;margin-left:-1.2rem;position:absolute;top:0;width:2.1rem}.tooltip{display:block;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.19rem;font-weight:400;line-height:1.4;opacity:0;position:absolute;visibility:visible;z-index:10}.tooltip.in{opacity:.9}.tooltip.top{margin-top:-4px;padding:8px 0}.tooltip.right{margin-left:4px;padding:0 8px}.tooltip.bottom{margin-top:4px;padding:8px 0}.tooltip.left{margin-left:-4px;padding:0 8px}.tooltip-inner{background-color:#fff;border:1px solid #adadad;border-radius:0;box-shadow:1px 1px 1px #ccc;color:#41362f;max-width:20rem;padding:.5em 1em;text-decoration:none}.tooltip-arrow,.tooltip-arrow:after{border:solid transparent;height:0;position:absolute;width:0}.tooltip-arrow:after{content:'';position:absolute}.tooltip.top .tooltip-arrow,.tooltip.top .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:50%;margin-left:-8px}.tooltip.top-left .tooltip-arrow,.tooltip.top-left .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;margin-bottom:-8px;right:8px}.tooltip.top-right .tooltip-arrow,.tooltip.top-right .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:8px;margin-bottom:-8px}.tooltip.right .tooltip-arrow,.tooltip.right .tooltip-arrow:after{border-right-color:#949494;border-width:8px 8px 8px 0;left:1px;margin-top:-8px;top:50%}.tooltip.right .tooltip-arrow:after{border-right-color:#fff;border-width:6px 7px 6px 0;margin-left:0;margin-top:-6px}.tooltip.left .tooltip-arrow,.tooltip.left .tooltip-arrow:after{border-left-color:#949494;border-width:8px 0 8px 8px;margin-top:-8px;right:0;top:50%}.tooltip.bottom .tooltip-arrow,.tooltip.bottom .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:50%;margin-left:-8px;top:0}.tooltip.bottom-left .tooltip-arrow,.tooltip.bottom-left .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;margin-top:-8px;right:8px;top:0}.tooltip.bottom-right .tooltip-arrow,.tooltip.bottom-right .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:8px;margin-top:-8px;top:0}.password-strength{display:block;margin:0 -.3rem 1em;white-space:nowrap}.password-strength.password-strength-too-short .password-strength-item:first-child,.password-strength.password-strength-weak .password-strength-item:first-child,.password-strength.password-strength-weak .password-strength-item:first-child+.password-strength-item{background-color:#e22626}.password-strength.password-strength-fair .password-strength-item:first-child,.password-strength.password-strength-fair .password-strength-item:first-child+.password-strength-item,.password-strength.password-strength-fair .password-strength-item:first-child+.password-strength-item+.password-strength-item{background-color:#ef672f}.password-strength.password-strength-good .password-strength-item:first-child,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item+.password-strength-item,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item+.password-strength-item+.password-strength-item,.password-strength.password-strength-strong .password-strength-item{background-color:#79a22e}.password-strength .password-strength-item{background-color:#ccc;display:inline-block;font-size:0;height:1.4rem;margin-right:.3rem;width:calc(20% - .6rem)}@-webkit-keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}.progress{background-color:#fafafa;border:1px solid #ccc;height:3rem;margin-bottom:3rem;overflow:hidden}.progress-bar{background-color:#79a22e;color:#fff;float:left;font-size:1.19rem;height:100%;line-height:3rem;text-align:center;transition:width .6s ease;width:0}.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.spinner{display:inline-block;font-size:4rem;height:1em;margin-right:1.5rem;position:relative;width:1em}@-webkit-keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}@keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}.spinner>span:nth-child(1){-webkit-animation-delay:.27s;animation-delay:.27s;-webkit-transform:rotate(-315deg);-ms-transform:rotate(-315deg);transform:rotate(-315deg)}.spinner>span:nth-child(2){-webkit-animation-delay:.36s;animation-delay:.36s;-webkit-transform:rotate(-270deg);-ms-transform:rotate(-270deg);transform:rotate(-270deg)}.spinner>span:nth-child(3){-webkit-animation-delay:.45s;animation-delay:.45s;-webkit-transform:rotate(-225deg);-ms-transform:rotate(-225deg);transform:rotate(-225deg)}.spinner>span:nth-child(4){-webkit-animation-delay:.54s;animation-delay:.54s;-webkit-transform:rotate(-180deg);-ms-transform:rotate(-180deg);transform:rotate(-180deg)}.spinner>span:nth-child(5){-webkit-animation-delay:.63s;animation-delay:.63s;-webkit-transform:rotate(-135deg);-ms-transform:rotate(-135deg);transform:rotate(-135deg)}.spinner>span:nth-child(6){-webkit-animation-delay:.72s;animation-delay:.72s;-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}.spinner>span:nth-child(7){-webkit-animation-delay:.81s;animation-delay:.81s;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg)}.spinner>span:nth-child(8){-webkit-animation-delay:.9;animation-delay:.9;-webkit-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg)}.spinner>span{-webkit-animation-direction:linear;animation-direction:linear;-webkit-animation-duration:.72s;animation-duration:.72s;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:fade;animation-name:fade;-webkit-transform:scale(0.4);-ms-transform:scale(0.4);transform:scale(0.4);background-color:#fff;border-radius:6px;clip:rect(0 .28571429em .1em 0);height:.1em;margin-top:.5em;position:absolute;width:1em}.ie9 .spinner{background:url(../../pub/images/ajax-loader.gif) center no-repeat}.ie9 .spinner>span{display:none}.main{padding-bottom:2rem;padding-top:3rem}.header{display:none}.header .logo{float:left;height:4.1rem;width:3.5rem}.header-title{font-size:2.8rem;letter-spacing:.02em;margin:2.5rem 0 3.5rem 5rem}.page-title{font-size:2rem;margin-bottom:1.3em}.accent-box{margin-bottom:2rem}.accent-box .btn-prime{margin-top:1.5rem}.page-landing{margin:7.6% auto 0;max-width:44rem;text-align:center}.page-landing .logo{height:5.6rem;margin-bottom:2rem;width:19.2rem}.page-landing .text-version{margin-bottom:3rem}.page-landing .text-welcome{margin-bottom:6.5rem}.page-landing .text-terms{margin-bottom:2.5rem;text-align:center}.page-landing .btn-submit{margin-bottom:20px}.page-license .license-text{margin-bottom:2rem}.page-license .page-license-footer{text-align:right}.rediness-check-item{margin-bottom:4rem}.readiness-check-title{font-size:1.4rem;font-weight:700;margin-bottom:.1rem;margin-left:7.5rem}.readiness-check-content{margin-left:7.5rem;margin-right:22rem}.readiness-check-content .readiness-check-title{margin-left:0}.readiness-check-content .list{margin-top:-.3rem}.rediness-check-side{float:right;padding-left:2.4rem;width:22rem}.rediness-check-side .side-title{margin-bottom:0}.readiness-check-icon{float:left;margin-left:2rem;margin-top:.7rem}.page-web-configuration .form-el-insider-wrap{width:auto}.page-web-configuration .form-el-insider{width:15.4rem}.page-web-configuration .form-el-insider-input .form-el-input{width:16.5rem}.customize-your-store .customize-your-store-default .legend{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.customize-your-store .advanced-modules-count,.customize-your-store .advanced-modules-select{padding-left:1.5rem}.customize-your-store .customize-your-store-advanced{min-width:0}.customize-your-store .message-error:before{margin-top:0;top:1.8rem}.customize-your-store .message-error a{color:#333;text-decoration:underline}.customize-your-store .message-error .form-label:before{background:#fff}.content-install{margin-bottom:2rem}.console{border:1px solid #ccc;font-family:'Courier New',Courier,monospace;font-weight:300;margin:1rem 0 2rem;max-height:20rem;overflow-y:auto;padding:1.5rem 2rem 2rem}.console .text-danger{color:#e22626}.console .text-success{color:#090}.console .hidden{display:none}.content-success .btn-prime{margin-top:1.5rem}.jumbo-title{font-size:3.6rem}.jumbo-title .jumbo-icon{font-size:3.8rem;margin-right:.25em;position:relative;top:.15em}@media all and (max-width:1047px){.nav{padding-bottom:5.38rem;padding-left:1.5rem;text-align:center}.nav-bar{display:inline-block;float:none;margin-right:0;vertical-align:top}.nav .btn-group,.nav-bar-outer-actions{display:inline-block;float:none;margin-top:-8.48rem;text-align:center;vertical-align:top;width:100%}.nav-bar-outer-actions{padding-right:0}.nav-bar-outer-actions .outer-actions-inner-wrap{display:inline-block}}@media all and (min-width:768px){.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9{float:left}.col-m-12{width:100%}.col-m-11{width:91.66666667%}.col-m-10{width:83.33333333%}.col-m-9{width:75%}.col-m-8{width:66.66666667%}.col-m-7{width:58.33333333%}.col-m-6{width:50%}.col-m-5{width:41.66666667%}.col-m-4{width:33.33333333%}.col-m-3{width:25%}.col-m-2{width:16.66666667%}.col-m-1{width:8.33333333%}.col-m-pull-12{right:100%}.col-m-pull-11{right:91.66666667%}.col-m-pull-10{right:83.33333333%}.col-m-pull-9{right:75%}.col-m-pull-8{right:66.66666667%}.col-m-pull-7{right:58.33333333%}.col-m-pull-6{right:50%}.col-m-pull-5{right:41.66666667%}.col-m-pull-4{right:33.33333333%}.col-m-pull-3{right:25%}.col-m-pull-2{right:16.66666667%}.col-m-pull-1{right:8.33333333%}.col-m-pull-0{right:auto}.col-m-push-12{left:100%}.col-m-push-11{left:91.66666667%}.col-m-push-10{left:83.33333333%}.col-m-push-9{left:75%}.col-m-push-8{left:66.66666667%}.col-m-push-7{left:58.33333333%}.col-m-push-6{left:50%}.col-m-push-5{left:41.66666667%}.col-m-push-4{left:33.33333333%}.col-m-push-3{left:25%}.col-m-push-2{left:16.66666667%}.col-m-push-1{left:8.33333333%}.col-m-push-0{left:auto}.col-m-offset-12{margin-left:100%}.col-m-offset-11{margin-left:91.66666667%}.col-m-offset-10{margin-left:83.33333333%}.col-m-offset-9{margin-left:75%}.col-m-offset-8{margin-left:66.66666667%}.col-m-offset-7{margin-left:58.33333333%}.col-m-offset-6{margin-left:50%}.col-m-offset-5{margin-left:41.66666667%}.col-m-offset-4{margin-left:33.33333333%}.col-m-offset-3{margin-left:25%}.col-m-offset-2{margin-left:16.66666667%}.col-m-offset-1{margin-left:8.33333333%}.col-m-offset-0{margin-left:0}}@media all and (min-width:1048px){.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9{float:left}.col-l-12{width:100%}.col-l-11{width:91.66666667%}.col-l-10{width:83.33333333%}.col-l-9{width:75%}.col-l-8{width:66.66666667%}.col-l-7{width:58.33333333%}.col-l-6{width:50%}.col-l-5{width:41.66666667%}.col-l-4{width:33.33333333%}.col-l-3{width:25%}.col-l-2{width:16.66666667%}.col-l-1{width:8.33333333%}.col-l-pull-12{right:100%}.col-l-pull-11{right:91.66666667%}.col-l-pull-10{right:83.33333333%}.col-l-pull-9{right:75%}.col-l-pull-8{right:66.66666667%}.col-l-pull-7{right:58.33333333%}.col-l-pull-6{right:50%}.col-l-pull-5{right:41.66666667%}.col-l-pull-4{right:33.33333333%}.col-l-pull-3{right:25%}.col-l-pull-2{right:16.66666667%}.col-l-pull-1{right:8.33333333%}.col-l-pull-0{right:auto}.col-l-push-12{left:100%}.col-l-push-11{left:91.66666667%}.col-l-push-10{left:83.33333333%}.col-l-push-9{left:75%}.col-l-push-8{left:66.66666667%}.col-l-push-7{left:58.33333333%}.col-l-push-6{left:50%}.col-l-push-5{left:41.66666667%}.col-l-push-4{left:33.33333333%}.col-l-push-3{left:25%}.col-l-push-2{left:16.66666667%}.col-l-push-1{left:8.33333333%}.col-l-push-0{left:auto}.col-l-offset-12{margin-left:100%}.col-l-offset-11{margin-left:91.66666667%}.col-l-offset-10{margin-left:83.33333333%}.col-l-offset-9{margin-left:75%}.col-l-offset-8{margin-left:66.66666667%}.col-l-offset-7{margin-left:58.33333333%}.col-l-offset-6{margin-left:50%}.col-l-offset-5{margin-left:41.66666667%}.col-l-offset-4{margin-left:33.33333333%}.col-l-offset-3{margin-left:25%}.col-l-offset-2{margin-left:16.66666667%}.col-l-offset-1{margin-left:8.33333333%}.col-l-offset-0{margin-left:0}}@media all and (min-width:1440px){.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{float:left}.col-xl-12{width:100%}.col-xl-11{width:91.66666667%}.col-xl-10{width:83.33333333%}.col-xl-9{width:75%}.col-xl-8{width:66.66666667%}.col-xl-7{width:58.33333333%}.col-xl-6{width:50%}.col-xl-5{width:41.66666667%}.col-xl-4{width:33.33333333%}.col-xl-3{width:25%}.col-xl-2{width:16.66666667%}.col-xl-1{width:8.33333333%}.col-xl-pull-12{right:100%}.col-xl-pull-11{right:91.66666667%}.col-xl-pull-10{right:83.33333333%}.col-xl-pull-9{right:75%}.col-xl-pull-8{right:66.66666667%}.col-xl-pull-7{right:58.33333333%}.col-xl-pull-6{right:50%}.col-xl-pull-5{right:41.66666667%}.col-xl-pull-4{right:33.33333333%}.col-xl-pull-3{right:25%}.col-xl-pull-2{right:16.66666667%}.col-xl-pull-1{right:8.33333333%}.col-xl-pull-0{right:auto}.col-xl-push-12{left:100%}.col-xl-push-11{left:91.66666667%}.col-xl-push-10{left:83.33333333%}.col-xl-push-9{left:75%}.col-xl-push-8{left:66.66666667%}.col-xl-push-7{left:58.33333333%}.col-xl-push-6{left:50%}.col-xl-push-5{left:41.66666667%}.col-xl-push-4{left:33.33333333%}.col-xl-push-3{left:25%}.col-xl-push-2{left:16.66666667%}.col-xl-push-1{left:8.33333333%}.col-xl-push-0{left:auto}.col-xl-offset-12{margin-left:100%}.col-xl-offset-11{margin-left:91.66666667%}.col-xl-offset-10{margin-left:83.33333333%}.col-xl-offset-9{margin-left:75%}.col-xl-offset-8{margin-left:66.66666667%}.col-xl-offset-7{margin-left:58.33333333%}.col-xl-offset-6{margin-left:50%}.col-xl-offset-5{margin-left:41.66666667%}.col-xl-offset-4{margin-left:33.33333333%}.col-xl-offset-3{margin-left:25%}.col-xl-offset-2{margin-left:16.66666667%}.col-xl-offset-1{margin-left:8.33333333%}.col-xl-offset-0{margin-left:0}}@media all and (max-width:767px){.list-definition>dt{float:none}.list-definition>dd{margin-left:0}.form-row .form-label{text-align:left}.form-row .form-label.required:after{position:static}.nav{padding-bottom:0;padding-left:0;padding-right:0}.nav-bar-outer-actions{margin-top:0}.nav-bar{display:block;margin-bottom:0;margin-left:auto;margin-right:auto;width:30.9rem}.nav-bar:before{display:none}.nav-bar>li{float:left;min-height:9rem}.nav-bar>li:after{display:none}.nav-bar>li:nth-child(4n){clear:both}.nav-bar a{line-height:1.4}.tooltip{display:none!important}.readiness-check-content{margin-right:2rem}.form-el-insider,.form-el-insider-wrap,.page-web-configuration .form-el-insider-input,.page-web-configuration .form-el-insider-input .form-el-input{display:block;width:100%}}@media all and (max-width:479px){.nav-bar{width:23.175rem}.nav-bar>li{width:7.725rem}.nav .btn-group .btn-wrap-try-again,.nav-bar-outer-actions .btn-wrap-try-again{clear:both;display:block;float:none;margin-left:auto;margin-right:auto;margin-top:1rem;padding-top:1rem}} \ No newline at end of file +html{box-sizing:border-box;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}*,:after,:before{box-sizing:inherit}:focus{box-shadow:none;outline:0}._keyfocus :focus{box-shadow:0 0 0 1px #008bdb}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}mark{background:#ff0;color:#000}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}embed,img,object,video{max-width:100%}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}:after,:before{box-sizing:content-box}.abs-clearer:after,.form-row:after,.header:after,.nav:after,.row:after{content:"";display:table;clear:both}.ng-cloak{display:none!important}.hide.hide{display:none}.show.show{display:block}.text-center{text-align:center}.text-right{text-align:right}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/light/opensans-300.eot);src:url(../../pub/fonts/opensans/light/opensans-300.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/light/opensans-300.woff2) format('woff2'),url(../../pub/fonts/opensans/light/opensans-300.woff) format('woff'),url(../../pub/fonts/opensans/light/opensans-300.ttf) format('truetype'),url('../../pub/fonts/opensans/light/opensans-300.svg#Open Sans') format('svg');font-weight:300;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/regular/opensans-400.eot);src:url(../../pub/fonts/opensans/regular/opensans-400.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/regular/opensans-400.woff2) format('woff2'),url(../../pub/fonts/opensans/regular/opensans-400.woff) format('woff'),url(../../pub/fonts/opensans/regular/opensans-400.ttf) format('truetype'),url('../../pub/fonts/opensans/regular/opensans-400.svg#Open Sans') format('svg');font-weight:400;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/semibold/opensans-600.eot);src:url(../../pub/fonts/opensans/semibold/opensans-600.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/semibold/opensans-600.woff2) format('woff2'),url(../../pub/fonts/opensans/semibold/opensans-600.woff) format('woff'),url(../../pub/fonts/opensans/semibold/opensans-600.ttf) format('truetype'),url('../../pub/fonts/opensans/semibold/opensans-600.svg#Open Sans') format('svg');font-weight:600;font-style:normal}@font-face{font-family:'Open Sans';src:url(../../pub/fonts/opensans/bold/opensans-700.eot);src:url(../../pub/fonts/opensans/bold/opensans-700.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/opensans/bold/opensans-700.woff2) format('woff2'),url(../../pub/fonts/opensans/bold/opensans-700.woff) format('woff'),url(../../pub/fonts/opensans/bold/opensans-700.ttf) format('truetype'),url('../../pub/fonts/opensans/bold/opensans-700.svg#Open Sans') format('svg');font-weight:700;font-style:normal}html{font-size:62.5%}body{color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:400;line-height:1.4}h1,h2,h3,h4,h5,h6{font-weight:400;margin-top:0}p{margin:0 0 1em}a{color:#008bdb;text-decoration:none}a:hover{color:#0fa7ff;text-decoration:underline}@font-face{font-family:Icons;src:url(../../pub/fonts/icons/icons.eot);src:url(../../pub/fonts/icons/icons.eot?#iefix) format('embedded-opentype'),url(../../pub/fonts/icons/icons.woff2) format('woff2'),url(../../pub/fonts/icons/icons.woff) format('woff'),url(../../pub/fonts/icons/icons.ttf) format('truetype'),url(../../pub/fonts/icons/icons.svg#Icons) format('svg');font-weight:400;font-style:normal}[class*=icon-]{display:inline-block;line-height:1}[class*=icon-]:after{font-family:Icons}.icon-success-thick:after{content:'\e600'}.icon-success:after{content:'\e601'}.icon-collapse:after{content:'\e602'}.icon-failed-thick:after{content:'\e603'}.icon-failed:after{content:'\e604'}.icon-expand:after{content:'\e605'}.icon-warning:after{content:'\e606'}.icon-failed-round,.icon-success-round{border-radius:100%;color:#fff;font-size:2.5rem;height:1em;position:relative;text-align:center;width:1em}.icon-failed-round:after,.icon-success-round:after{bottom:0;font-size:.8em;left:0;position:absolute;right:0;top:.15em}.icon-success-round{background-color:#79a22e}.icon-success-round:after{content:'\e600'}.icon-failed-round{background-color:#e22626}.icon-failed-round:after{content:'\e603'}dl,ol,ul{margin-top:0}.list{margin-bottom:1em;padding-left:0}.list>li{display:block;margin-bottom:.75em;position:relative}.list>li>.icon-failed,.list>li>.icon-success{font-size:1.6em;left:-.1em;position:absolute;top:0}.list>li>.icon-success{color:#79a22e}.list>li>.icon-failed{color:#e22626}.list-item-failed,.list-item-icon,.list-item-success{padding-left:3.5rem}.list-item-failed:before,.list-item-success:before{font-family:Icons;font-size:1.6em;left:-.1em;position:absolute;top:-.2em}.list-item-success:before{color:#79a22e;content:'\e601'}.list-item-failed:before{color:#e22626;content:'\e604'}.list-definition{margin:0 0 3rem;padding:0}.list-definition>dt{clear:left;float:left}.list-definition>dd{margin-bottom:1em;margin-left:20rem}.btn-wrap{margin:0 auto}.btn-wrap .btn{width:100%}.btn{background:#e3e3e3;border:none;color:#514943;display:inline-block;font-size:1.6rem;font-weight:600;padding:.45em .9em;text-align:center}.btn:hover{background-color:#dbdbdb;color:#514943;text-decoration:none}.btn:active{background-color:#d6d6d6}.btn.disabled,.btn[disabled]{cursor:default;opacity:.5;pointer-events:none}.ie9 .btn.disabled,.ie9 .btn[disabled]{background-color:#f0f0f0;opacity:1;text-shadow:none}.btn-large{padding:.75em 1.25em}.btn-link{background-color:transparent;border:none;color:#008bdb;font-family:1.6rem;font-size:1.5rem}.btn-link:hover{background-color:transparent;color:#0fa7ff}.btn-prime{background-color:#eb5202;color:#fff;text-shadow:1px 1px 0 rgba(0,0,0,.25)}.btn-prime:hover{background-color:#f65405;background-repeat:repeat-x;background-image:-webkit-linear-gradient(left,color-stop(#e04f00 0),color-stop(#f65405 100%));background-image:linear-gradient(to right,#e04f00 0,#f65405 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#e04f00', endColorstr='#f65405', GradientType=1);color:#fff}.btn-prime:active{background-color:#e04f00;background-repeat:repeat-x;background-image:-webkit-linear-gradient(left,color-stop(#f65405 0),color-stop(#e04f00 100%));background-image:linear-gradient(to right,#f65405 0,#e04f00 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f65405', endColorstr='#e04f00', GradientType=1)}.ie9 .btn-prime.disabled,.ie9 .btn-prime[disabled]{background-color:#fd6e23}.ie9 .btn-prime.disabled:active,.ie9 .btn-prime.disabled:hover,.ie9 .btn-prime[disabled]:active,.ie9 .btn-prime[disabled]:hover{background-color:#fd6e23;filter:none}.btn-secondary{background-color:#514943;color:#fff}.btn-secondary:hover{background-color:#5f564f;color:#fff}.btn-secondary:active{background-color:#574e48}.ie9 .btn-secondary.disabled,.ie9 .btn-secondary[disabled]{background-color:#514943}.ie9 .btn-secondary.disabled:active,.ie9 .btn-secondary.disabled:hover,.ie9 .btn-secondary[disabled]:active,.ie9 .btn-secondary[disabled]:hover{background-color:#514943;filter:none}[class*=btn-wrap-triangle]{overflow:hidden;position:relative}[class*=btn-wrap-triangle] .btn:after{border-style:solid;content:'';height:0;position:absolute;top:0;width:0}.btn-wrap-triangle-right{display:inline-block;padding-right:1.74rem;position:relative}.btn-wrap-triangle-right .btn{text-indent:.92rem}.btn-wrap-triangle-right .btn:after{border-color:transparent transparent transparent #e3e3e3;border-width:1.84rem 0 1.84rem 1.84rem;left:100%;margin-left:-1.74rem}.btn-wrap-triangle-right .btn:hover:after{border-left-color:#dbdbdb}.btn-wrap-triangle-right .btn:active:after{border-left-color:#d6d6d6}.btn-wrap-triangle-right .btn:not(.disabled):active,.btn-wrap-triangle-right .btn:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn.disabled:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:after{border-color:transparent transparent transparent #f0f0f0}.ie9 .btn-wrap-triangle-right .btn.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn[disabled]:hover:after{border-left-color:#f0f0f0}.btn-wrap-triangle-right .btn-prime:after{border-color:transparent transparent transparent #eb5202}.btn-wrap-triangle-right .btn-prime:hover:after{border-left-color:#f65405}.btn-wrap-triangle-right .btn-prime:active:after{border-left-color:#e04f00}.btn-wrap-triangle-right .btn-prime:not(.disabled):active,.btn-wrap-triangle-right .btn-prime:not([disabled]):active{left:1px}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:after{border-color:transparent transparent transparent #fd6e23}.ie9 .btn-wrap-triangle-right .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-right .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-right .btn-prime[disabled]:hover:after{border-left-color:#fd6e23}.btn-wrap-triangle-left{display:inline-block;padding-left:1.74rem}.btn-wrap-triangle-left .btn{text-indent:-.92rem}.btn-wrap-triangle-left .btn:after{border-color:transparent #e3e3e3 transparent transparent;border-width:1.84rem 1.84rem 1.84rem 0;margin-right:-1.74rem;right:100%}.btn-wrap-triangle-left .btn:hover:after{border-right-color:#dbdbdb}.btn-wrap-triangle-left .btn:active:after{border-right-color:#d6d6d6}.btn-wrap-triangle-left .btn:not(.disabled):active,.btn-wrap-triangle-left .btn:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn.disabled:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:after{border-color:transparent #f0f0f0 transparent transparent}.ie9 .btn-wrap-triangle-left .btn.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn[disabled]:hover:after{border-right-color:#f0f0f0}.btn-wrap-triangle-left .btn-prime:after{border-color:transparent #eb5202 transparent transparent}.btn-wrap-triangle-left .btn-prime:hover:after{border-right-color:#e04f00}.btn-wrap-triangle-left .btn-prime:active:after{border-right-color:#f65405}.btn-wrap-triangle-left .btn-prime:not(.disabled):active,.btn-wrap-triangle-left .btn-prime:not([disabled]):active{right:1px}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:after{border-color:transparent #fd6e23 transparent transparent}.ie9 .btn-wrap-triangle-left .btn-prime.disabled:active:after,.ie9 .btn-wrap-triangle-left .btn-prime.disabled:hover:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:active:after,.ie9 .btn-wrap-triangle-left .btn-prime[disabled]:hover:after{border-right-color:#fd6e23}.btn-expand{background-color:transparent;border:none;color:#303030;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.4rem;font-weight:700;padding:0;position:relative}.btn-expand.expanded:after{border-color:transparent transparent #303030;border-width:0 .285em .36em}.btn-expand.expanded:hover:after{border-color:transparent transparent #3d3d3d}.btn-expand:hover{background-color:transparent;border:none;color:#3d3d3d}.btn-expand:hover:after{border-color:#3d3d3d transparent transparent}.btn-expand:after{border-color:#303030 transparent transparent;border-style:solid;border-width:.36em .285em 0;content:'';height:0;left:100%;margin-left:.5em;margin-top:-.18em;position:absolute;top:50%;width:0}[class*=col-] .form-el-input,[class*=col-] .form-el-select{width:100%}.form-fieldset{border:none;margin:0 0 1em;padding:0}.form-row{margin-bottom:2.2rem}.form-row .form-row{margin-bottom:.4rem}.form-row .form-label{display:block;font-weight:600;padding:.6rem 2.1em 0 0;text-align:right}.form-row .form-label.required{position:relative}.form-row .form-label.required:after{color:#eb5202;content:'*';font-size:1.15em;position:absolute;right:.7em;top:.5em}.form-row .form-el-checkbox+.form-label:before,.form-row .form-el-radio+.form-label:before{top:.7rem}.form-row .form-el-checkbox+.form-label:after,.form-row .form-el-radio+.form-label:after{top:1.1rem}input:not([disabled]):focus,textarea:not([disabled]):focus{box-shadow:none}.form-el-input{border:1px solid #adadad;border-radius:2px;color:#303030;padding:.35em .55em .5em}.form-el-input:hover{border-color:#949494}.form-el-input:focus{border-color:#008bdb}.form-label{margin-bottom:.5em}[class*=form-label][for]{cursor:pointer}.form-el-insider-wrap{display:table;width:100%}.form-el-insider-input{display:table-cell;width:100%}.form-el-insider{border-radius:2px;display:table-cell;vertical-align:top;padding:.43em .55em .5em 0}.form-legend,.form-legend-expand,.form-legend-light{display:block;margin:0}.form-legend,.form-legend-expand{margin-bottom:2.5em;padding-top:1.5em;font-weight:600;font-size:1.25em}.form-legend{width:100%;border-top:1px solid #ccc}.form-legend-light{margin-bottom:1.5em;font-size:1em}.form-legend-expand{transition:opacity .2s linear;cursor:pointer}.form-legend-expand:hover{opacity:.85}.form-legend-expand.expanded:after{content:'\e602'}.form-legend-expand:after{margin-left:.5em;font-weight:400;font-size:1.15em;font-family:Icons;content:'\e605';vertical-align:sub}.form-el-checkbox,.form-el-radio{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.form-el-checkbox.disabled+.form-label,.form-el-checkbox.disabled+.form-label:before,.form-el-checkbox[disabled]+.form-label,.form-el-checkbox[disabled]+.form-label:before,.form-el-radio.disabled+.form-label,.form-el-radio.disabled+.form-label:before,.form-el-radio[disabled]+.form-label,.form-el-radio[disabled]+.form-label:before{cursor:default;opacity:.5;pointer-events:none}.form-el-checkbox:not(.disabled)+.form-label:hover:before,.form-el-checkbox:not([disabled])+.form-label:hover:before,.form-el-radio:not(.disabled)+.form-label:hover:before,.form-el-radio:not([disabled])+.form-label:hover:before{border-color:#514943}.form-el-checkbox+.form-label,.form-el-radio+.form-label{font-weight:400;padding-left:2em;padding-right:0;position:relative;text-align:left;transition:border-color .1s linear}.form-el-checkbox+.form-label:before,.form-el-radio+.form-label:before{border:1px solid;content:'';left:0;position:absolute;top:.1rem;transition:border-color .1s linear}.form-el-checkbox+.form-label:before{border-color:#adadad;border-radius:2px;height:1.4rem;line-height:1;width:1.4rem}.form-el-checkbox:checked+.form-label::before{content:'\e600';font-family:Icons}.form-el-radio+.form-label:before{background-color:#fff;border:1px solid #adadad;border-radius:100%;height:1.6rem;width:1.6rem}.form-el-radio+.form-label:after{background:0 0;border:.5rem solid transparent;border-radius:100%;content:'';height:0;left:.4rem;position:absolute;top:.5rem;transition:background .3s linear;width:0}.form-el-radio:checked+.form-label{cursor:default}.form-el-radio:checked+.form-label:after{border-color:#514943}.form-select-label{border:1px solid #adadad;border-radius:2px;color:#303030;cursor:pointer;display:block;overflow:hidden;position:relative}.form-select-label:hover,.form-select-label:hover:after{border-color:#949494}.form-select-label:active,.form-select-label:active:after,.form-select-label:focus,.form-select-label:focus:after{border-color:#008bdb}.form-select-label:after{background:#e3e3e3;border-left:1px solid #adadad;bottom:0;content:'';position:absolute;right:0;top:0;width:2.36em;z-index:-2}.ie9 .form-select-label:after{display:none}.form-select-label:before{border-color:#303030 transparent transparent;border-style:solid;border-width:5px 4px 0;content:'';height:0;margin-right:-4px;margin-top:-2.5px;position:absolute;right:1.18em;top:50%;width:0;z-index:-1}.ie9 .form-select-label:before{display:none}.form-select-label .form-el-select{background:0 0;border:none;border-radius:0;content:'';display:block;margin:0;padding:.35em calc(2.36em + 10%) .5em .55em;width:110%}.ie9 .form-select-label .form-el-select{padding-right:.55em;width:100%}.form-el-select{background:#fff;border:1px solid #adadad;border-radius:2px;color:#303030;display:block;padding:.35em .55em}.multiselect-custom{position:relative;height:45.2rem;border:1px solid #adadad;overflow:auto;margin:0 0 1.5rem}.multiselect-custom ul{margin:0;padding:0;list-style:none;min-width:29rem}.multiselect-custom .item{padding:1rem 1.4rem}.multiselect-custom .selected{background-color:#e0f6fe}.multiselect-custom .form-label{margin-bottom:0}[class*=form-el-].invalid{border-color:#e22626}[class*=form-el-].invalid+.error-container{display:block}.error-container{background-color:#fffbbb;border:1px solid #ee7d7d;border-radius:2px;color:#514943;display:none;font-size:1.19rem;margin-top:.2rem;padding:.4235em .6655em .605em}.check-result-message{margin-left:.5em;min-height:3.68rem;-webkit-align-items:center;-ms-align-items:center;align-items:center;display:-webkit-flex;display:-ms-flexbox;display:flex}.check-result-text{margin-left:.5em}.pseudo-table{display:table}.pseudo-td{display:table-cell}.messages .message:last-child{margin:0 0 2rem}.message{background:#fffbbb;border:none;border-radius:0;color:#333;font-size:14px;margin:0 0 1px;padding:1.8rem 4rem 1.8rem 5.5rem;position:relative;text-shadow:none}.message:before{background:0 0;border:0;color:#007bdb;content:'\e61a';font-family:Icons;font-size:1.9rem;font-style:normal;font-weight:400;height:auto;left:1.9rem;line-height:inherit;margin-top:-1.3rem;position:absolute;speak:none;text-shadow:none;top:50%;width:auto}.message-notice:before{color:#007bdb;content:'\e61a'}.message-warning:before{color:#eb5202;content:'\e623'}.message-error{background:#fcc}.message-error:before{color:#e22626;content:'\e632';font-size:1.5rem;left:2.2rem;margin-top:-1rem}.message-success:before{color:#79a22e;content:'\e62d'}.message-spinner:before{display:none}.message-spinner .spinner{font-size:2.5rem;left:1.5rem;position:absolute;top:1.5rem}.message-in-rating-edit{margin-left:1.8rem;margin-right:1.8rem}.message{margin-bottom:3rem}.container{display:block;margin:0 auto 4rem;max-width:100rem;padding:0 2rem}.row{margin-left:0;margin-right:0}.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9,.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{min-height:1px;padding-left:0;padding-right:0;position:relative}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}.nav{background-color:#f8f8f8;border-bottom:1px solid #e3e3e3;border-top:1px solid #e3e3e3;display:none;padding:2.2rem 1.5rem 0 0}.nav .btn-group,.nav-bar-outer-actions{float:right;margin-bottom:1.7rem}.nav .btn-group .btn-wrap,.nav-bar-outer-actions .btn-wrap{float:right;margin-left:.5rem;margin-right:.5rem}.nav .btn-group .btn-wrap .btn,.nav-bar-outer-actions .btn-wrap .btn{padding-left:.5rem;padding-right:.5rem}.nav-bar-outer-actions{margin-top:-10.6rem;padding-right:1.5rem}.btn-wrap-try-again{width:9.5rem}.btn-wrap-next,.btn-wrap-prev{width:8.5rem}.nav-bar{counter-reset:i;float:left;margin:0 1rem 1.7rem 0;padding:0;position:relative;white-space:nowrap}.nav-bar:before{background-color:#d4d4d4;background-repeat:repeat-x;background-image:-webkit-linear-gradient(top,#d1d1d1 0,#d4d4d4 100%);background-image:linear-gradient(to bottom,#d1d1d1 0,#d4d4d4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#d1d1d1', endColorstr='#d4d4d4', GradientType=0);border-bottom:1px solid #d9d9d9;border-top:1px solid #bfbfbf;content:'';height:.8rem;left:5.15rem;position:absolute;right:5.15rem;top:.7rem}.nav-bar>li{display:inline-block;font-size:0;position:relative;vertical-align:top;width:10.3rem}.nav-bar>li:first-child:after{display:none}.nav-bar>li:after{background-color:#514943;content:'';height:.5rem;left:calc(-50% + .25rem);position:absolute;right:calc(50% + .7rem);top:.9rem}.nav-bar>li.disabled:before{bottom:0;content:'';left:0;position:absolute;right:0;top:0;z-index:1}.nav-bar>li.active~li:after{display:none}.nav-bar>li.active~li a:after{background-color:transparent;border-color:transparent;color:#a6a6a6}.nav-bar>li.active a{color:#000}.nav-bar>li.active a:hover{cursor:default}.nav-bar>li.active a:after{background-color:#fff;content:''}.nav-bar a{color:#514943;display:block;font-size:1.2rem;font-weight:600;line-height:1.2;overflow:hidden;padding:3rem .5em 0;position:relative;text-align:center;text-overflow:ellipsis}.nav-bar a:hover{text-decoration:none}.nav-bar a:after{background-color:#514943;border:.4rem solid #514943;border-radius:100%;color:#fff;content:counter(i);counter-increment:i;height:.7rem;left:50%;line-height:.6;margin-left:-.8rem;position:absolute;right:auto;text-align:center;top:.4rem;width:.7rem}.nav-bar a:before{background-color:#d6d6d6;border:1px solid transparent;border-bottom-color:#d9d9d9;border-radius:100%;border-top-color:#bfbfbf;content:'';height:2.1rem;left:50%;line-height:1;margin-left:-1.2rem;position:absolute;top:0;width:2.1rem}.tooltip{display:block;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:1.19rem;font-weight:400;line-height:1.4;opacity:0;position:absolute;visibility:visible;z-index:10}.tooltip.in{opacity:.9}.tooltip.top{margin-top:-4px;padding:8px 0}.tooltip.right{margin-left:4px;padding:0 8px}.tooltip.bottom{margin-top:4px;padding:8px 0}.tooltip.left{margin-left:-4px;padding:0 8px}.tooltip-inner{background-color:#fff;border:1px solid #adadad;border-radius:0;box-shadow:1px 1px 1px #ccc;color:#41362f;max-width:20rem;padding:.5em 1em;text-decoration:none}.tooltip-arrow,.tooltip-arrow:after{border:solid transparent;height:0;position:absolute;width:0}.tooltip-arrow:after{content:'';position:absolute}.tooltip.top .tooltip-arrow,.tooltip.top .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:50%;margin-left:-8px}.tooltip.top-left .tooltip-arrow,.tooltip.top-left .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;margin-bottom:-8px;right:8px}.tooltip.top-right .tooltip-arrow,.tooltip.top-right .tooltip-arrow:after{border-top-color:#949494;border-width:8px 8px 0;bottom:0;left:8px;margin-bottom:-8px}.tooltip.right .tooltip-arrow,.tooltip.right .tooltip-arrow:after{border-right-color:#949494;border-width:8px 8px 8px 0;left:1px;margin-top:-8px;top:50%}.tooltip.right .tooltip-arrow:after{border-right-color:#fff;border-width:6px 7px 6px 0;margin-left:0;margin-top:-6px}.tooltip.left .tooltip-arrow,.tooltip.left .tooltip-arrow:after{border-left-color:#949494;border-width:8px 0 8px 8px;margin-top:-8px;right:0;top:50%}.tooltip.bottom .tooltip-arrow,.tooltip.bottom .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:50%;margin-left:-8px;top:0}.tooltip.bottom-left .tooltip-arrow,.tooltip.bottom-left .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;margin-top:-8px;right:8px;top:0}.tooltip.bottom-right .tooltip-arrow,.tooltip.bottom-right .tooltip-arrow:after{border-bottom-color:#949494;border-width:0 8px 8px;left:8px;margin-top:-8px;top:0}.password-strength{display:block;margin:0 -.3rem 1em;white-space:nowrap}.password-strength.password-strength-too-short .password-strength-item:first-child,.password-strength.password-strength-weak .password-strength-item:first-child,.password-strength.password-strength-weak .password-strength-item:first-child+.password-strength-item{background-color:#e22626}.password-strength.password-strength-fair .password-strength-item:first-child,.password-strength.password-strength-fair .password-strength-item:first-child+.password-strength-item,.password-strength.password-strength-fair .password-strength-item:first-child+.password-strength-item+.password-strength-item{background-color:#ef672f}.password-strength.password-strength-good .password-strength-item:first-child,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item+.password-strength-item,.password-strength.password-strength-good .password-strength-item:first-child+.password-strength-item+.password-strength-item+.password-strength-item,.password-strength.password-strength-strong .password-strength-item{background-color:#79a22e}.password-strength .password-strength-item{background-color:#ccc;display:inline-block;font-size:0;height:1.4rem;margin-right:.3rem;width:calc(20% - .6rem)}@-webkit-keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:4rem 0}to{background-position:0 0}}.progress{background-color:#fafafa;border:1px solid #ccc;height:3rem;margin-bottom:3rem;overflow:hidden}.progress-bar{background-color:#79a22e;color:#fff;float:left;font-size:1.19rem;height:100%;line-height:3rem;text-align:center;transition:width .6s ease;width:0}.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.spinner{display:inline-block;font-size:4rem;height:1em;margin-right:1.5rem;position:relative;width:1em}@-moz-keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}@-webkit-keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}@-ms-keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}@keyframes fade{0%{background-color:#514943}100%{background-color:#fff}}.spinner>span:nth-child(1){-webkit-animation-delay:.27s;-moz-animation-delay:.27s;-ms-animation-delay:.27s;animation-delay:.27s;-webkit-transform:rotate(-315deg);-moz-transform:rotate(-315deg);-ms-transform:rotate(-315deg);transform:rotate(-315deg)}.spinner>span:nth-child(2){-webkit-animation-delay:.36s;-moz-animation-delay:.36s;-ms-animation-delay:.36s;animation-delay:.36s;-webkit-transform:rotate(-270deg);-moz-transform:rotate(-270deg);-ms-transform:rotate(-270deg);transform:rotate(-270deg)}.spinner>span:nth-child(3){-webkit-animation-delay:.45s;-moz-animation-delay:.45s;-ms-animation-delay:.45s;animation-delay:.45s;-webkit-transform:rotate(-225deg);-moz-transform:rotate(-225deg);-ms-transform:rotate(-225deg);transform:rotate(-225deg)}.spinner>span:nth-child(4){-webkit-animation-delay:.54s;-moz-animation-delay:.54s;-ms-animation-delay:.54s;animation-delay:.54s;-webkit-transform:rotate(-180deg);-moz-transform:rotate(-180deg);-ms-transform:rotate(-180deg);transform:rotate(-180deg)}.spinner>span:nth-child(5){-webkit-animation-delay:.63s;-moz-animation-delay:.63s;-ms-animation-delay:.63s;animation-delay:.63s;-webkit-transform:rotate(-135deg);-moz-transform:rotate(-135deg);-ms-transform:rotate(-135deg);transform:rotate(-135deg)}.spinner>span:nth-child(6){-webkit-animation-delay:.72s;-moz-animation-delay:.72s;-ms-animation-delay:.72s;animation-delay:.72s;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}.spinner>span:nth-child(7){-webkit-animation-delay:.81s;-moz-animation-delay:.81s;-ms-animation-delay:.81s;animation-delay:.81s;-webkit-transform:rotate(-45deg);-moz-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg)}.spinner>span:nth-child(8){-webkit-animation-delay:.9;-moz-animation-delay:.9;-ms-animation-delay:.9;animation-delay:.9;-webkit-transform:rotate(0deg);-moz-transform:rotate(0deg);-ms-transform:rotate(0deg);transform:rotate(0deg)}.spinner>span{-webkit-animation-direction:linear;-moz-animation-direction:linear;-ms-animation-direction:linear;animation-direction:linear;-webkit-animation-duration:.72s;-moz-animation-duration:.72s;-ms-animation-duration:.72s;animation-duration:.72s;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;-ms-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:fade;-moz-animation-name:fade;-ms-animation-name:fade;animation-name:fade;-webkit-transform:scale(0.4);-moz-transform:scale(0.4);-ms-transform:scale(0.4);transform:scale(0.4);background-color:#fff;border-radius:6px;clip:rect(0 .28571429em .1em 0);height:.1em;margin-top:.5em;position:absolute;width:1em}.ie9 .spinner{background:url(../../pub/images/ajax-loader.gif) center no-repeat}.ie9 .spinner>span{display:none}.main{padding-bottom:2rem;padding-top:3rem}.header{display:none}.header .logo{float:left;height:4.1rem;width:3.5rem}.header-title{font-size:2.8rem;letter-spacing:.02em;margin:2.5rem 0 3.5rem 5rem}.page-title{font-size:2rem;margin-bottom:1.3em}.accent-box{margin-bottom:2rem}.accent-box .btn-prime{margin-top:1.5rem}.page-landing{margin:7.6% auto 0;max-width:44rem;text-align:center}.page-landing .logo{height:5.6rem;margin-bottom:2rem;width:19.2rem}.page-landing .text-version{margin-bottom:3rem}.page-landing .text-welcome{margin-bottom:6.5rem}.page-landing .text-terms{margin-bottom:2.5rem;text-align:center}.page-landing .btn-submit{margin-bottom:20px}.page-license .license-text{margin-bottom:2rem}.page-license .page-license-footer{text-align:right}.rediness-check-item{margin-bottom:4rem}.readiness-check-title{font-size:1.4rem;font-weight:700;margin-bottom:.1rem;margin-left:7.5rem}.readiness-check-content{margin-left:7.5rem;margin-right:22rem}.readiness-check-content .readiness-check-title{margin-left:0}.readiness-check-content .list{margin-top:-.3rem}.rediness-check-side{float:right;padding-left:2.4rem;width:22rem}.rediness-check-side .side-title{margin-bottom:0}.readiness-check-icon{float:left;margin-left:2rem;margin-top:.7rem}.page-web-configuration .form-el-insider-wrap{width:auto}.page-web-configuration .form-el-insider{width:15.4rem}.page-web-configuration .form-el-insider-input .form-el-input{width:16.5rem}.customize-your-store .customize-your-store-default .legend{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.customize-your-store .advanced-modules-count,.customize-your-store .advanced-modules-select{padding-left:1.5rem}.customize-your-store .customize-your-store-advanced{min-width:0}.customize-your-store .message-error:before{margin-top:0;top:1.8rem}.customize-your-store .message-error a{color:#333;text-decoration:underline}.customize-your-store .message-error .form-label:before{background:#fff}.customize-your-store .customize-database-clean p{margin-top:25px}.content-install{margin-bottom:2rem}.console{border:1px solid #ccc;font-family:'Courier New',Courier,monospace;font-weight:300;margin:1rem 0 2rem;max-height:20rem;overflow-y:auto;padding:1.5rem 2rem 2rem}.console .text-danger{color:#e22626}.console .text-success{color:#090}.console .hidden{display:none}.content-success .btn-prime{margin-top:1.5rem}.jumbo-title{font-size:3.6rem}.jumbo-title .jumbo-icon{font-size:3.8rem;margin-right:.25em;position:relative;top:.15em}.install-database-clean{margin-top:40px}.install-database-clean .btn{margin-right:10px}@media all and (max-width:1047px){.nav{padding-bottom:5.38rem;padding-left:1.5rem;text-align:center}.nav-bar{display:inline-block;float:none;margin-right:0;vertical-align:top}.nav .btn-group,.nav-bar-outer-actions{display:inline-block;float:none;margin-top:-8.48rem;text-align:center;vertical-align:top;width:100%}.nav-bar-outer-actions{padding-right:0}.nav-bar-outer-actions .outer-actions-inner-wrap{display:inline-block}}@media all and (min-width:768px){.col-m-1,.col-m-10,.col-m-11,.col-m-12,.col-m-2,.col-m-3,.col-m-4,.col-m-5,.col-m-6,.col-m-7,.col-m-8,.col-m-9{float:left}.col-m-12{width:100%}.col-m-11{width:91.66666667%}.col-m-10{width:83.33333333%}.col-m-9{width:75%}.col-m-8{width:66.66666667%}.col-m-7{width:58.33333333%}.col-m-6{width:50%}.col-m-5{width:41.66666667%}.col-m-4{width:33.33333333%}.col-m-3{width:25%}.col-m-2{width:16.66666667%}.col-m-1{width:8.33333333%}.col-m-pull-12{right:100%}.col-m-pull-11{right:91.66666667%}.col-m-pull-10{right:83.33333333%}.col-m-pull-9{right:75%}.col-m-pull-8{right:66.66666667%}.col-m-pull-7{right:58.33333333%}.col-m-pull-6{right:50%}.col-m-pull-5{right:41.66666667%}.col-m-pull-4{right:33.33333333%}.col-m-pull-3{right:25%}.col-m-pull-2{right:16.66666667%}.col-m-pull-1{right:8.33333333%}.col-m-pull-0{right:auto}.col-m-push-12{left:100%}.col-m-push-11{left:91.66666667%}.col-m-push-10{left:83.33333333%}.col-m-push-9{left:75%}.col-m-push-8{left:66.66666667%}.col-m-push-7{left:58.33333333%}.col-m-push-6{left:50%}.col-m-push-5{left:41.66666667%}.col-m-push-4{left:33.33333333%}.col-m-push-3{left:25%}.col-m-push-2{left:16.66666667%}.col-m-push-1{left:8.33333333%}.col-m-push-0{left:auto}.col-m-offset-12{margin-left:100%}.col-m-offset-11{margin-left:91.66666667%}.col-m-offset-10{margin-left:83.33333333%}.col-m-offset-9{margin-left:75%}.col-m-offset-8{margin-left:66.66666667%}.col-m-offset-7{margin-left:58.33333333%}.col-m-offset-6{margin-left:50%}.col-m-offset-5{margin-left:41.66666667%}.col-m-offset-4{margin-left:33.33333333%}.col-m-offset-3{margin-left:25%}.col-m-offset-2{margin-left:16.66666667%}.col-m-offset-1{margin-left:8.33333333%}.col-m-offset-0{margin-left:0}}@media all and (min-width:1048px){.col-l-1,.col-l-10,.col-l-11,.col-l-12,.col-l-2,.col-l-3,.col-l-4,.col-l-5,.col-l-6,.col-l-7,.col-l-8,.col-l-9{float:left}.col-l-12{width:100%}.col-l-11{width:91.66666667%}.col-l-10{width:83.33333333%}.col-l-9{width:75%}.col-l-8{width:66.66666667%}.col-l-7{width:58.33333333%}.col-l-6{width:50%}.col-l-5{width:41.66666667%}.col-l-4{width:33.33333333%}.col-l-3{width:25%}.col-l-2{width:16.66666667%}.col-l-1{width:8.33333333%}.col-l-pull-12{right:100%}.col-l-pull-11{right:91.66666667%}.col-l-pull-10{right:83.33333333%}.col-l-pull-9{right:75%}.col-l-pull-8{right:66.66666667%}.col-l-pull-7{right:58.33333333%}.col-l-pull-6{right:50%}.col-l-pull-5{right:41.66666667%}.col-l-pull-4{right:33.33333333%}.col-l-pull-3{right:25%}.col-l-pull-2{right:16.66666667%}.col-l-pull-1{right:8.33333333%}.col-l-pull-0{right:auto}.col-l-push-12{left:100%}.col-l-push-11{left:91.66666667%}.col-l-push-10{left:83.33333333%}.col-l-push-9{left:75%}.col-l-push-8{left:66.66666667%}.col-l-push-7{left:58.33333333%}.col-l-push-6{left:50%}.col-l-push-5{left:41.66666667%}.col-l-push-4{left:33.33333333%}.col-l-push-3{left:25%}.col-l-push-2{left:16.66666667%}.col-l-push-1{left:8.33333333%}.col-l-push-0{left:auto}.col-l-offset-12{margin-left:100%}.col-l-offset-11{margin-left:91.66666667%}.col-l-offset-10{margin-left:83.33333333%}.col-l-offset-9{margin-left:75%}.col-l-offset-8{margin-left:66.66666667%}.col-l-offset-7{margin-left:58.33333333%}.col-l-offset-6{margin-left:50%}.col-l-offset-5{margin-left:41.66666667%}.col-l-offset-4{margin-left:33.33333333%}.col-l-offset-3{margin-left:25%}.col-l-offset-2{margin-left:16.66666667%}.col-l-offset-1{margin-left:8.33333333%}.col-l-offset-0{margin-left:0}}@media all and (min-width:1440px){.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9{float:left}.col-xl-12{width:100%}.col-xl-11{width:91.66666667%}.col-xl-10{width:83.33333333%}.col-xl-9{width:75%}.col-xl-8{width:66.66666667%}.col-xl-7{width:58.33333333%}.col-xl-6{width:50%}.col-xl-5{width:41.66666667%}.col-xl-4{width:33.33333333%}.col-xl-3{width:25%}.col-xl-2{width:16.66666667%}.col-xl-1{width:8.33333333%}.col-xl-pull-12{right:100%}.col-xl-pull-11{right:91.66666667%}.col-xl-pull-10{right:83.33333333%}.col-xl-pull-9{right:75%}.col-xl-pull-8{right:66.66666667%}.col-xl-pull-7{right:58.33333333%}.col-xl-pull-6{right:50%}.col-xl-pull-5{right:41.66666667%}.col-xl-pull-4{right:33.33333333%}.col-xl-pull-3{right:25%}.col-xl-pull-2{right:16.66666667%}.col-xl-pull-1{right:8.33333333%}.col-xl-pull-0{right:auto}.col-xl-push-12{left:100%}.col-xl-push-11{left:91.66666667%}.col-xl-push-10{left:83.33333333%}.col-xl-push-9{left:75%}.col-xl-push-8{left:66.66666667%}.col-xl-push-7{left:58.33333333%}.col-xl-push-6{left:50%}.col-xl-push-5{left:41.66666667%}.col-xl-push-4{left:33.33333333%}.col-xl-push-3{left:25%}.col-xl-push-2{left:16.66666667%}.col-xl-push-1{left:8.33333333%}.col-xl-push-0{left:auto}.col-xl-offset-12{margin-left:100%}.col-xl-offset-11{margin-left:91.66666667%}.col-xl-offset-10{margin-left:83.33333333%}.col-xl-offset-9{margin-left:75%}.col-xl-offset-8{margin-left:66.66666667%}.col-xl-offset-7{margin-left:58.33333333%}.col-xl-offset-6{margin-left:50%}.col-xl-offset-5{margin-left:41.66666667%}.col-xl-offset-4{margin-left:33.33333333%}.col-xl-offset-3{margin-left:25%}.col-xl-offset-2{margin-left:16.66666667%}.col-xl-offset-1{margin-left:8.33333333%}.col-xl-offset-0{margin-left:0}}@media all and (max-width:767px){.list-definition>dt{float:none}.list-definition>dd{margin-left:0}.form-row .form-label{text-align:left}.form-row .form-label.required:after{position:static}.nav{padding-bottom:0;padding-left:0;padding-right:0}.nav-bar-outer-actions{margin-top:0}.nav-bar{display:block;margin-bottom:0;margin-left:auto;margin-right:auto;width:30.9rem}.nav-bar:before{display:none}.nav-bar>li{float:left;min-height:9rem}.nav-bar>li:after{display:none}.nav-bar>li:nth-child(4n){clear:both}.nav-bar a{line-height:1.4}.tooltip{display:none!important}.readiness-check-content{margin-right:2rem}.form-el-insider,.form-el-insider-wrap,.page-web-configuration .form-el-insider-input,.page-web-configuration .form-el-insider-input .form-el-input{display:block;width:100%}}@media all and (max-width:479px){.nav-bar{width:23.175rem}.nav-bar>li{width:7.725rem}.nav .btn-group .btn-wrap-try-again,.nav-bar-outer-actions .btn-wrap-try-again{clear:both;display:block;float:none;margin-left:auto;margin-right:auto;margin-top:1rem;padding-top:1rem}} \ No newline at end of file diff --git a/setup/src/Magento/Setup/Console/Command/AbstractMaintenanceCommand.php b/setup/src/Magento/Setup/Console/Command/AbstractMaintenanceCommand.php index ebb36b354cbe7b952135f6bb1e76866df1e23105..0606c91367431f5d82501759a537c9c77a7c8183 100644 --- a/setup/src/Magento/Setup/Console/Command/AbstractMaintenanceCommand.php +++ b/setup/src/Magento/Setup/Console/Command/AbstractMaintenanceCommand.php @@ -53,7 +53,7 @@ abstract class AbstractMaintenanceCommand extends AbstractSetupCommand self::INPUT_KEY_IP, null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, - 'Allowed IP addresses' + "Allowed IP addresses (use 'none' to clear allowed IP list)" ), ]; $this->setDefinition($options); diff --git a/setup/src/Magento/Setup/Console/Command/AbstractModuleCommand.php b/setup/src/Magento/Setup/Console/Command/AbstractModuleCommand.php index b33d9582e37825ec5be122074081c438ef1db26a..b6e38f7ec2b7530a0fe1e4d0741d8b08a6ca4c7b 100644 --- a/setup/src/Magento/Setup/Console/Command/AbstractModuleCommand.php +++ b/setup/src/Magento/Setup/Console/Command/AbstractModuleCommand.php @@ -121,7 +121,7 @@ abstract class AbstractModuleCommand extends AbstractSetupCommand $output->writeln('<info>- ' . implode("\n- ", $modulesToChange) . '</info>'); $output->writeln(''); $output->writeln( - '<info>To make sure that the enabled modules are properly registered,' + '<info>To make sure the modules are properly enabled,' . " run 'setup:upgrade'.</info>" ); } else { diff --git a/setup/src/Magento/Setup/Console/Command/AbstractSetupCommand.php b/setup/src/Magento/Setup/Console/Command/AbstractSetupCommand.php index 7803cacfed564b1b2a75329bb22eaa9610fedb3e..fc133a0107f14269e717ee0a8b2177a078ab2b5b 100644 --- a/setup/src/Magento/Setup/Console/Command/AbstractSetupCommand.php +++ b/setup/src/Magento/Setup/Console/Command/AbstractSetupCommand.php @@ -27,8 +27,8 @@ abstract class AbstractSetupCommand extends Command null, InputOption::VALUE_REQUIRED, 'Add to any command to customize Magento initialization parameters' . PHP_EOL . - "For example: 'MAGE_MODE=developer&MAGE_DIRS[base][path]" . - "=/var/www/example.com&MAGE_DIRS[cache][path]=/var/tmp/cache'" + 'For example: "MAGE_MODE=developer&MAGE_DIRS[base][path]' . + '=/var/www/example.com&MAGE_DIRS[cache][path]=/var/tmp/cache"' ); } } diff --git a/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php b/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php index 411969ae2d84f29f7d17166f85317c6e99241fb5..78b1b41a711041712ee53c04630380a1af86d114 100644 --- a/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php +++ b/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php @@ -45,7 +45,7 @@ class AdminUserCreateCommand extends AbstractSetupCommand protected function configure() { $this->setName('admin:user:create') - ->setDescription('Creates admin user') + ->setDescription('Creates an administrator') ->setDefinition($this->getOptionsList()); parent::configure(); } @@ -62,7 +62,9 @@ class AdminUserCreateCommand extends AbstractSetupCommand } $installer = $this->installerFactory->create(new ConsoleLogger($output)); $installer->installAdminUser($input->getOptions()); - $output->writeln('<info>Created admin user ' . $input->getOption(AdminAccount::KEY_USER) . '</info>'); + $output->writeln( + '<info>Created Magento administrator user named ' . $input->getOption(AdminAccount::KEY_USER) . '</info>' + ); } /** @@ -73,11 +75,21 @@ class AdminUserCreateCommand extends AbstractSetupCommand public function getOptionsList() { return [ - new InputOption(AdminAccount::KEY_USER, null, InputOption::VALUE_REQUIRED, 'Admin user'), - new InputOption(AdminAccount::KEY_PASSWORD, null, InputOption::VALUE_REQUIRED, 'Admin password', ''), - new InputOption(AdminAccount::KEY_EMAIL, null, InputOption::VALUE_REQUIRED, 'Admin email'), - new InputOption(AdminAccount::KEY_FIRST_NAME, null, InputOption::VALUE_REQUIRED, 'Admin first name'), - new InputOption(AdminAccount::KEY_LAST_NAME, null, InputOption::VALUE_REQUIRED, 'Admin last name'), + new InputOption(AdminAccount::KEY_USER, null, InputOption::VALUE_REQUIRED, '(Required) Admin user'), + new InputOption(AdminAccount::KEY_PASSWORD, null, InputOption::VALUE_REQUIRED, '(Required) Admin password'), + new InputOption(AdminAccount::KEY_EMAIL, null, InputOption::VALUE_REQUIRED, '(Required) Admin email'), + new InputOption( + AdminAccount::KEY_FIRST_NAME, + null, + InputOption::VALUE_REQUIRED, + '(Required) Admin first name' + ), + new InputOption( + AdminAccount::KEY_LAST_NAME, + null, + InputOption::VALUE_REQUIRED, + '(Required) Admin last name' + ), ]; } @@ -95,7 +107,10 @@ class AdminUserCreateCommand extends AbstractSetupCommand ->setLastname($input->getOption(AdminAccount::KEY_LAST_NAME)) ->setUsername($input->getOption(AdminAccount::KEY_USER)) ->setEmail($input->getOption(AdminAccount::KEY_EMAIL)) - ->setPassword($input->getOption(AdminAccount::KEY_PASSWORD)); + ->setPassword( + $input->getOption(AdminAccount::KEY_PASSWORD) === null + ? '' : $input->getOption(AdminAccount::KEY_PASSWORD) + ); $validator = new \Magento\Framework\Validator\Object; $this->validationRules->addUserInfoRules($validator); diff --git a/setup/src/Magento/Setup/Console/Command/ConfigSetCommand.php b/setup/src/Magento/Setup/Console/Command/ConfigSetCommand.php index eaca97c02042a2f3b21050cbc4c1149e7b8409f7..328f6c7df7d173fefa622d5d2ad21d4d79bc4d01 100644 --- a/setup/src/Magento/Setup/Console/Command/ConfigSetCommand.php +++ b/setup/src/Magento/Setup/Console/Command/ConfigSetCommand.php @@ -60,7 +60,7 @@ class ConfigSetCommand extends AbstractSetupCommand $options = $this->configModel->getAvailableOptions(); $this->setName('setup:config:set') - ->setDescription('Sets deployment configuration') + ->setDescription('Creates or modifies the deployment configuration') ->setDefinition($options); parent::configure(); diff --git a/setup/src/Magento/Setup/Console/Command/DbDataUpgradeCommand.php b/setup/src/Magento/Setup/Console/Command/DbDataUpgradeCommand.php index b915fa2a83067e27757b3d24ba884edac8c671b3..258646ca9da717a080935e4cc93eee7faa1af7b0 100644 --- a/setup/src/Magento/Setup/Console/Command/DbDataUpgradeCommand.php +++ b/setup/src/Magento/Setup/Console/Command/DbDataUpgradeCommand.php @@ -61,7 +61,7 @@ class DbDataUpgradeCommand extends AbstractSetupCommand protected function execute(InputInterface $input, OutputInterface $output) { if (!$this->deploymentConfig->isAvailable()) { - $output->writeln("<info>No information is available: the application is not installed.</info>"); + $output->writeln("<info>No information is available: the Magento application is not installed.</info>"); return; } $installer = $this->installFactory->create(new ConsoleLogger($output)); diff --git a/setup/src/Magento/Setup/Console/Command/DbSchemaUpgradeCommand.php b/setup/src/Magento/Setup/Console/Command/DbSchemaUpgradeCommand.php index fc3f5bd9888acbd89a44216d1f144650e6f4403d..5dc06e06300ba9108714001312fe537c6186dce6 100644 --- a/setup/src/Magento/Setup/Console/Command/DbSchemaUpgradeCommand.php +++ b/setup/src/Magento/Setup/Console/Command/DbSchemaUpgradeCommand.php @@ -61,7 +61,7 @@ class DbSchemaUpgradeCommand extends AbstractSetupCommand protected function execute(InputInterface $input, OutputInterface $output) { if (!$this->deploymentConfig->isAvailable()) { - $output->writeln("<info>No information is available: the application is not installed.</info>"); + $output->writeln("<info>No information is available: the Magento application is not installed.</info>"); return; } $installer = $this->installFactory->create(new ConsoleLogger($output)); diff --git a/setup/src/Magento/Setup/Console/Command/DbStatusCommand.php b/setup/src/Magento/Setup/Console/Command/DbStatusCommand.php index 7d996aec45e7e2a928a44a14ce237557fc029a10..531cfa919c47d0fb42354807dcb446f442384d0e 100644 --- a/setup/src/Magento/Setup/Console/Command/DbStatusCommand.php +++ b/setup/src/Magento/Setup/Console/Command/DbStatusCommand.php @@ -50,7 +50,7 @@ class DbStatusCommand extends AbstractSetupCommand protected function configure() { $this->setName('setup:db:status') - ->setDescription('Checks if update of DB schema or data is required'); + ->setDescription('Checks if DB schema or data requires upgrade'); parent::configure(); } @@ -60,7 +60,7 @@ class DbStatusCommand extends AbstractSetupCommand protected function execute(InputInterface $input, OutputInterface $output) { if (!$this->deploymentConfig->isAvailable()) { - $output->writeln("<info>No information is available: the application is not installed.</info>"); + $output->writeln("<info>No information is available: the Magento application is not installed.</info>"); return; } /** @var DbVersionInfo $dbVersionInfo */ diff --git a/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php b/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php index 9c75faf07f03469b7dd2e6d97fa70bf57a099b16..7606a2e17bf0b902394ea8bb3c583d8ab22136c2 100644 --- a/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php +++ b/setup/src/Magento/Setup/Console/Command/DiCompileCommand.php @@ -6,6 +6,7 @@ namespace Magento\Setup\Console\Command; +use Magento\Framework\Filesystem; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\App\DeploymentConfig; @@ -22,29 +23,22 @@ use Symfony\Component\Console\Output\OutputInterface; */ class DiCompileCommand extends Command { - /** - * @var DeploymentConfig - */ + /** @var DeploymentConfig */ private $deploymentConfig; - /** - * @var ObjectManagerInterface - */ + /** @var ObjectManagerInterface */ private $objectManager; - /** - * @var Manager - */ + /** @var Manager */ private $taskManager; - /** - * @var DirectoryList - */ + /** @var DirectoryList */ private $directoryList; - /** - * @var array - */ + /** @var Filesystem */ + private $filesystem; + + /** @var array */ private $excludedPathsList; /** @@ -54,17 +48,20 @@ class DiCompileCommand extends Command * @param DirectoryList $directoryList * @param Manager $taskManager * @param ObjectManagerProvider $objectManagerProvider + * @param Filesystem $filesystem */ public function __construct( DeploymentConfig $deploymentConfig, DirectoryList $directoryList, Manager $taskManager, - ObjectManagerProvider $objectManagerProvider + ObjectManagerProvider $objectManagerProvider, + Filesystem $filesystem ) { $this->deploymentConfig = $deploymentConfig; - $this->directoryList = $directoryList; - $this->objectManager = $objectManagerProvider->get(); - $this->taskManager = $taskManager; + $this->directoryList = $directoryList; + $this->objectManager = $objectManagerProvider->get(); + $this->taskManager = $taskManager; + $this->filesystem = $filesystem; parent::__construct(); } @@ -92,6 +89,7 @@ class DiCompileCommand extends Command $output->writeln('You cannot run this command because the Magento application is not installed.'); return; } + $this->objectManager->get('Magento\Framework\App\Cache')->clean(); $compiledPathsList = [ 'application' => $appCodePath, 'library' => $libraryPath . '/Magento/Framework', @@ -102,7 +100,7 @@ class DiCompileCommand extends Command 'framework' => '#^' . $libraryPath . '/[\\w]+/[\\w]+/([\\w]+/)?Test#' ]; $dataAttributesIncludePattern = [ - 'service_data_attributes' => '/\/etc\/([a-zA-Z_]*\/service_data_attributes|service_data_attributes)\.xml$/' + 'extension_attributes' => '/\/etc\/([a-zA-Z_]*\/extension_attributes|extension_attributes)\.xml$/' ]; $this->configureObjectManager($output); @@ -141,6 +139,13 @@ class DiCompileCommand extends Command ]; try { + $this->cleanupFilesystem( + [ + DirectoryList::CACHE, + DirectoryList::GENERATION, + DirectoryList::DI, + ] + ); foreach ($operations as $operationCode => $arguments) { $this->taskManager->addOperation( $operationCode, @@ -154,6 +159,19 @@ class DiCompileCommand extends Command } } + /** + * Delete directories by their code from "var" directory + * + * @param array $directoryCodeList + * @return void + */ + private function cleanupFilesystem($directoryCodeList) + { + foreach ($directoryCodeList as $code) { + $this->filesystem->getDirectoryWrite($code)->delete(); + } + } + /** * Configure Object Manager * diff --git a/setup/src/Magento/Setup/Console/Command/InfoCurrencyListCommand.php b/setup/src/Magento/Setup/Console/Command/InfoCurrencyListCommand.php index e39d0292876f69344e8ee445e53fad22f7f66982..c64db3845fd5fc1e91aa39b7c6678cf23657506a 100644 --- a/setup/src/Magento/Setup/Console/Command/InfoCurrencyListCommand.php +++ b/setup/src/Magento/Setup/Console/Command/InfoCurrencyListCommand.php @@ -38,7 +38,7 @@ class InfoCurrencyListCommand extends Command protected function configure() { $this->setName('info:currency:list') - ->setDescription('Prints list of available currencies'); + ->setDescription('Displays the list of available currencies'); parent::configure(); } diff --git a/setup/src/Magento/Setup/Console/Command/InfoLanguageListCommand.php b/setup/src/Magento/Setup/Console/Command/InfoLanguageListCommand.php index 648a3490f71a78c6938d5e9852eee4939ac14fe3..dfa4f5887df2c61ff17a6b3a06c5e3c917c21c2f 100644 --- a/setup/src/Magento/Setup/Console/Command/InfoLanguageListCommand.php +++ b/setup/src/Magento/Setup/Console/Command/InfoLanguageListCommand.php @@ -38,7 +38,7 @@ class InfoLanguageListCommand extends Command protected function configure() { $this->setName('info:language:list') - ->setDescription('Prints list of available language locales'); + ->setDescription('Displays the list of available language locales'); parent::configure(); } diff --git a/setup/src/Magento/Setup/Console/Command/InfoTimezoneListCommand.php b/setup/src/Magento/Setup/Console/Command/InfoTimezoneListCommand.php index fd79c63770508bf6baeaf84ab57eaa0a8972a996..dca141fac6d0fe73ed263492a09db647a735a5b2 100644 --- a/setup/src/Magento/Setup/Console/Command/InfoTimezoneListCommand.php +++ b/setup/src/Magento/Setup/Console/Command/InfoTimezoneListCommand.php @@ -38,7 +38,7 @@ class InfoTimezoneListCommand extends Command protected function configure() { $this->setName('info:timezone:list') - ->setDescription('Prints list of available timezones'); + ->setDescription('Displays the list of available timezones'); parent::configure(); } diff --git a/setup/src/Magento/Setup/Console/Command/InstallCommand.php b/setup/src/Magento/Setup/Console/Command/InstallCommand.php index 3bc8622022592ccbef7eee3edd6edfe01a3c594e..f11f0ff3646bb5d4ffe5e7bb67c79fbd0d99dcbd 100644 --- a/setup/src/Magento/Setup/Console/Command/InstallCommand.php +++ b/setup/src/Magento/Setup/Console/Command/InstallCommand.php @@ -110,7 +110,7 @@ class InstallCommand extends AbstractSetupCommand ) ]); $this->setName('setup:install') - ->setDescription('Installs Magento Application') + ->setDescription('Installs the Magento application') ->setDefinition($inputOptions); parent::configure(); } diff --git a/setup/src/Magento/Setup/Console/Command/InstallStoreConfigurationCommand.php b/setup/src/Magento/Setup/Console/Command/InstallStoreConfigurationCommand.php index d1641d960e9faca1f17f7cd189cb0db3a7882602..425ed23f6e1796be07cceeec64d7fe52fcefcc77 100644 --- a/setup/src/Magento/Setup/Console/Command/InstallStoreConfigurationCommand.php +++ b/setup/src/Magento/Setup/Console/Command/InstallStoreConfigurationCommand.php @@ -22,6 +22,9 @@ use Magento\Framework\Validator\Timezone; use Magento\Framework\Validator\Currency; use Magento\Framework\Url\Validator; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class InstallStoreConfigurationCommand extends AbstractSetupCommand { /** @@ -67,7 +70,7 @@ class InstallStoreConfigurationCommand extends AbstractSetupCommand protected function configure() { $this->setName('setup:store-config:set') - ->setDescription('Installs store configuration') + ->setDescription('Installs the store configuration') ->setDefinition($this->getOptionsList()); parent::configure(); } diff --git a/setup/src/Magento/Setup/Console/Command/MaintenanceStatusCommand.php b/setup/src/Magento/Setup/Console/Command/MaintenanceStatusCommand.php index 9ff1c2f97c23f822f676973a90e2938e1bdc0a4b..a1bd254e763eb13450f3fbfd505b4dee87a5611a 100644 --- a/setup/src/Magento/Setup/Console/Command/MaintenanceStatusCommand.php +++ b/setup/src/Magento/Setup/Console/Command/MaintenanceStatusCommand.php @@ -40,7 +40,7 @@ class MaintenanceStatusCommand extends AbstractSetupCommand protected function configure() { $this->setName('maintenance:status') - ->setDescription('Checks maintenance mode status'); + ->setDescription('Displays maintenance mode status'); parent::configure(); } diff --git a/setup/src/Magento/Setup/Console/Command/UninstallCommand.php b/setup/src/Magento/Setup/Console/Command/UninstallCommand.php index 0982c6381974d08b8fbd2663b2f9ef700580697b..802b3c51cd8e3784b773748a8036f5f00dfcd522 100644 --- a/setup/src/Magento/Setup/Console/Command/UninstallCommand.php +++ b/setup/src/Magento/Setup/Console/Command/UninstallCommand.php @@ -34,7 +34,7 @@ class UninstallCommand extends AbstractSetupCommand protected function configure() { $this->setName('setup:uninstall') - ->setDescription('Uninstalls Magento application'); + ->setDescription('Uninstalls the Magento application'); parent::configure(); } diff --git a/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php b/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php index 2c7b54bd294f1ed79d6669ed737348d718bcf4f8..c070a795331ae83e9765de8f1c979a2828cfa361 100644 --- a/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php +++ b/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php @@ -40,8 +40,7 @@ class UpgradeCommand extends AbstractSetupCommand { $this->setName('setup:upgrade') ->setDescription( - 'Upgrades installed application after the code base has changed, ' - . 'including DB schema and data' + 'Upgrades the Magento application, DB data, and schema' ); parent::configure(); } diff --git a/setup/src/Magento/Setup/Controller/CustomizeYourStore.php b/setup/src/Magento/Setup/Controller/CustomizeYourStore.php index 11e2a4b4900647b6173ff973c961fd497a28e4ba..34d8ca58eb95b48050980066f5d89bf57447ea3a 100644 --- a/setup/src/Magento/Setup/Controller/CustomizeYourStore.php +++ b/setup/src/Magento/Setup/Controller/CustomizeYourStore.php @@ -43,6 +43,8 @@ class CustomizeYourStore extends AbstractActionController 'currency' => $this->list->getCurrencyList(), 'language' => $this->list->getLocaleList(), 'isSampledataEnabled' => $this->sampleData->isDeployed(), + 'isSampleDataInstalled' => $this->sampleData->isInstalledSuccessfully(), + 'isSampleDataErrorInstallation' => $this->sampleData->isInstallationError() ]); $view->setTerminal(true); return $view; diff --git a/setup/src/Magento/Setup/Controller/DatabaseCheck.php b/setup/src/Magento/Setup/Controller/DatabaseCheck.php index 959c4ccc64d51b332a19c63b8ee4274af6973b7e..8d5a2380a860bf7247f4541f0a8674633f47fbab 100644 --- a/setup/src/Magento/Setup/Controller/DatabaseCheck.php +++ b/setup/src/Magento/Setup/Controller/DatabaseCheck.php @@ -5,8 +5,6 @@ */ namespace Magento\Setup\Controller; -use Magento\Setup\Model\InstallerFactory; -use Magento\Setup\Model\WebLogger; use Zend\Json\Json; use Zend\Mvc\Controller\AbstractActionController; use Zend\View\Model\JsonModel; @@ -14,13 +12,6 @@ use Magento\Setup\Validator\DbValidator; class DatabaseCheck extends AbstractActionController { - /** - * WebLogger to access log - * - * @var WebLogger - */ - private $webLogger; - /** * @var DbValidator */ @@ -30,12 +21,10 @@ class DatabaseCheck extends AbstractActionController /** * Constructor * - * @param WebLogger $webLogger * @param DbValidator $dbValidator */ - public function __construct(WebLogger $webLogger, DbValidator $dbValidator) + public function __construct(DbValidator $dbValidator) { - $this->webLogger = $webLogger; $this->dbValidator = $dbValidator; } diff --git a/setup/src/Magento/Setup/Controller/Environment.php b/setup/src/Magento/Setup/Controller/Environment.php index 3d323043d0ca0e34a2a45337bd1d7242fafcf49e..527cbeafabd022dcabe7e92fc0e87e8516eb117e 100644 --- a/setup/src/Magento/Setup/Controller/Environment.php +++ b/setup/src/Magento/Setup/Controller/Environment.php @@ -97,7 +97,6 @@ class Environment extends AbstractActionController $responseType = ResponseTypeInterface::RESPONSE_TYPE_SUCCESS; $settings = array_merge( - $this->checkRawPost(), $this->checkXDebugNestedLevel() ); @@ -176,40 +175,6 @@ class Environment extends AbstractActionController return new JsonModel($data); } - /** - * Checks if PHP version >= 5.6.0 and always_populate_raw_post_data is set - * - * @return array - */ - private function checkRawPost() - { - $data = []; - $error = false; - $iniSetting = ini_get('always_populate_raw_post_data'); - - if (version_compare(PHP_VERSION, '5.6.0') >= 0 && (int)$iniSetting > -1) { - $error = true; - } - - $message = sprintf( - 'Your PHP Version is %s, but always_populate_raw_post_data = %d. - $HTTP_RAW_POST_DATA is deprecated from PHP 5.6 onwards and will stop the installer from running. - Please open your php.ini file and set always_populate_raw_post_data to -1. - If you need more help please call your hosting provider. - ', - PHP_VERSION, - ini_get('always_populate_raw_post_data') - ); - - $data['rawpost'] = [ - 'message' => $message, - 'helpUrl' => 'http://php.net/manual/en/ini.core.php#ini.always-populate-settings-data', - 'error' => $error - ]; - - return $data; - } - /** * Checks if xdebug.max_nesting_level is set 200 or more * @return array @@ -218,7 +183,7 @@ class Environment extends AbstractActionController { $data = []; $error = false; - + $currentExtensions = $this->phpInformation->getCurrent(); if (in_array('xdebug', $currentExtensions)) { diff --git a/setup/src/Magento/Setup/Controller/Install.php b/setup/src/Magento/Setup/Controller/Install.php index 7333add5e8aed490c1377a050c356866adb38b71..4e5232c36026605e1787ea79d04aaca01b465914 100644 --- a/setup/src/Magento/Setup/Controller/Install.php +++ b/setup/src/Magento/Setup/Controller/Install.php @@ -94,6 +94,9 @@ class Install extends AbstractActionController } catch (\Exception $e) { $this->log->logError($e); $json->setVariable('success', false); + if ($e instanceof \Magento\Setup\SampleDataException) { + $json->setVariable('isSampleDataError', true); + } } return $json; } @@ -107,6 +110,7 @@ class Install extends AbstractActionController { $percent = 0; $success = false; + $json = new JsonModel(); try { $progress = $this->progressFactory->createFromLog($this->log); $percent = sprintf('%d', $progress->getRatio() * 100); @@ -114,8 +118,11 @@ class Install extends AbstractActionController $contents = $this->log->get(); } catch (\Exception $e) { $contents = [(string)$e]; + if ($e instanceof \Magento\Setup\SampleDataException) { + $json->setVariable('isSampleDataError', true); + } } - return new JsonModel(['progress' => $percent, 'success' => $success, 'console' => $contents]); + return $json->setVariables(['progress' => $percent, 'success' => $success, 'console' => $contents]); } /** @@ -178,6 +185,8 @@ class Install extends AbstractActionController ? $source['store']['currency'] : ''; $result[InstallCommand::INPUT_KEY_USE_SAMPLE_DATA] = isset($source['store']['useSampleData']) ? $source['store']['useSampleData'] : ''; + $result[InstallCommand::INPUT_KEY_CLEANUP_DB] = isset($source['store']['cleanUpDatabase']) + ? $source['store']['cleanUpDatabase'] : ''; return $result; } diff --git a/setup/src/Magento/Setup/Fixtures/ConfigsApplyFixture.php b/setup/src/Magento/Setup/Fixtures/ConfigsApplyFixture.php index 1dfd544552adb68775e876078f3a1457f68d7f23..0bf803025cb558dc8037c295d2b5d148c347e2d4 100644 --- a/setup/src/Magento/Setup/Fixtures/ConfigsApplyFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ConfigsApplyFixture.php @@ -28,10 +28,13 @@ class ConfigsApplyFixture extends Fixture $this->fixtureModel->resetObjectManager(); foreach ($configs['config'] as $config) { + $backendModel = isset($config['backend_model']) + ? + $config['backend_model'] : 'Magento\Framework\App\Config\Value'; /** - * @var \Magento\Framework\App\Config\Value $configData + * @var \Magento\Framework\App\Config\ValueInterface $configData */ - $configData = $this->fixtureModel->getObjectManager()->create('Magento\Framework\App\Config\Value'); + $configData = $this->fixtureModel->getObjectManager()->create($backendModel); $configData->setPath($config['path']) ->setScope($config['scope']) ->setScopeId($config['scopeId']) diff --git a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php index 7d8297a1a6480b8e3ee52998f9e79092424e3be8..0d298434c6acc44d17d8a274a8a81b9ab41ee6a2 100644 --- a/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/ConfigurableProductsFixture.php @@ -29,14 +29,13 @@ class ConfigurableProductsFixture extends Fixture { return [ 'sku', - '_store', - '_attribute_set', - '_type', - '_category', - '_root_category', - '_product_websites', + 'store_view_code', + 'attribute_set_code', + 'product_type', + 'categories', + 'product_websites', 'color', - 'configurable_variations', + 'configurable_variation', 'cost', 'country_of_manufacture', 'created_at', @@ -77,8 +76,8 @@ class ConfigurableProductsFixture extends Fixture 'special_from_date', 'special_price', 'special_to_date', - 'status', - 'tax_class_id', + 'product_online', + 'tax_class_name', 'thumbnail', 'thumbnail_label', 'updated_at', @@ -137,6 +136,8 @@ class ConfigurableProductsFixture extends Fixture '_super_attribute_code', '_super_attribute_option', '_super_attribute_price_corr', + 'configurable_variations', + 'configurable_variation_prices', ]; } @@ -144,26 +145,24 @@ class ConfigurableProductsFixture extends Fixture * Get CSV template rows * * @param Closure|mixed $productCategory - * @param Closure|mixed $productRootCategory * @param Closure|mixed $productWebsite * * @SuppressWarnings(PHPMD) * * @return array */ - protected function getRows($productCategory, $productRootCategory, $productWebsite) + protected function getRows($productCategory, $productWebsite) { return [ [ 'sku' => 'Configurable Product %s-option 1', - '_store' => '', - '_attribute_set' => 'Default', - '_type' => 'simple', - '_category' => $productCategory, - '_root_category' => $productRootCategory, - '_product_websites' => $productWebsite, + 'store_view_code' => '', + 'attribute_set_code' => 'Default', + 'product_type' => 'simple', + 'categories' => $productCategory, + 'product_websites' => $productWebsite, 'color' => '', - 'configurable_variations' => 'option 1', + 'configurable_variation' => 'option 1', 'cost' => '', 'country_of_manufacture' => '', 'created_at' => '2013-10-25 15:12:32', @@ -193,7 +192,7 @@ class ConfigurableProductsFixture extends Fixture 'news_to_date' => '', 'options_container' => 'Block after Info Column', 'page_layout' => '', - 'price' => '10.0000', + 'price' => '10', 'quantity_and_stock_status' => 'In Stock', 'related_tgtr_position_behavior' => '', 'related_tgtr_position_limit' => '', @@ -204,21 +203,21 @@ class ConfigurableProductsFixture extends Fixture 'special_from_date' => '', 'special_price' => '', 'special_to_date' => '', - 'status' => '1', - 'tax_class_id' => '2', + 'product_online' => '1', + 'tax_class_name' => 'Taxable Goods', 'thumbnail' => '', 'thumbnail_label' => '', 'updated_at' => '2013-10-25 15:12:32', 'upsell_tgtr_position_behavior' => '', 'upsell_tgtr_position_limit' => '', 'url_key' => 'configurable-product-%s-option-1', - 'url_path' => 'configurable-product-%s-option-1.html', + 'url_path' => 'configurable-product-%s-option-1', 'variations' => '', 'variations_1382710717' => '', 'variations_1382710773' => '', 'variations_1382710861' => '', - 'visibility' => '1', - 'weight' => '1.0000', + 'visibility' => 'Not Visible Individually', + 'weight' => '1', 'qty' => '111.0000', 'min_qty' => '0.0000', 'use_config_min_qty' => '1', @@ -267,14 +266,13 @@ class ConfigurableProductsFixture extends Fixture ], [ 'sku' => 'Configurable Product %s-option 2', - '_store' => '', - '_attribute_set' => 'Default', - '_type' => 'simple', - '_category' => $productCategory, - '_root_category' => $productRootCategory, - '_product_websites' => $productWebsite, + 'store_view_code' => '', + 'attribute_set_code' => 'Default', + 'product_type' => 'simple', + 'categories' => $productCategory, + 'product_websites' => $productWebsite, 'color' => '', - 'configurable_variations' => 'option 2', + 'configurable_variation' => 'option 2', 'cost' => '', 'country_of_manufacture' => '', 'created_at' => '2013-10-25 15:12:35', @@ -304,7 +302,7 @@ class ConfigurableProductsFixture extends Fixture 'news_to_date' => '', 'options_container' => 'Block after Info Column', 'page_layout' => '', - 'price' => '10.0000', + 'price' => '10', 'quantity_and_stock_status' => 'In Stock', 'related_tgtr_position_behavior' => '', 'related_tgtr_position_limit' => '', @@ -315,21 +313,21 @@ class ConfigurableProductsFixture extends Fixture 'special_from_date' => '', 'special_price' => '', 'special_to_date' => '', - 'status' => '1', - 'tax_class_id' => '2', + 'product_online' => '1', + 'tax_class_name' => 'Taxable Goods', 'thumbnail' => '', 'thumbnail_label' => '', 'updated_at' => '2013-10-25 15:12:35', 'upsell_tgtr_position_behavior' => '', 'upsell_tgtr_position_limit' => '', 'url_key' => 'configurable-product-%s-option-2', - 'url_path' => 'configurable-product-%s-option-2.html', + 'url_path' => 'configurable-product-%s-option-2', 'variations' => '', 'variations_1382710717' => '', 'variations_1382710773' => '', 'variations_1382710861' => '', - 'visibility' => '1', - 'weight' => '1.0000', + 'visibility' => 'Not Visible Individually', + 'weight' => '1', 'qty' => '111.0000', 'min_qty' => '0.0000', 'use_config_min_qty' => '1', @@ -371,21 +369,16 @@ class ConfigurableProductsFixture extends Fixture '_media_label' => '', '_media_position' => '', '_media_is_disabled' => '', - '_super_products_sku' => '', - '_super_attribute_code' => '', - '_super_attribute_option' => '', - '_super_attribute_price_corr' => '', ], [ 'sku' => 'Configurable Product %s-option 3', - '_store' => '', - '_attribute_set' => 'Default', - '_type' => 'simple', - '_category' => $productCategory, - '_root_category' => $productRootCategory, - '_product_websites' => $productWebsite, + 'store_view_code' => '', + 'attribute_set_code' => 'Default', + 'product_type' => 'simple', + 'categories' => $productCategory, + 'product_websites' => $productWebsite, 'color' => '', - 'configurable_variations' => 'option 3', + 'configurable_variation' => 'option 3', 'cost' => '', 'country_of_manufacture' => '', 'created_at' => '2013-10-25 15:12:37', @@ -415,7 +408,7 @@ class ConfigurableProductsFixture extends Fixture 'news_to_date' => '', 'options_container' => 'Block after Info Column', 'page_layout' => '', - 'price' => '10.0000', + 'price' => '10', 'quantity_and_stock_status' => 'In Stock', 'related_tgtr_position_behavior' => '', 'related_tgtr_position_limit' => '', @@ -426,21 +419,21 @@ class ConfigurableProductsFixture extends Fixture 'special_from_date' => '', 'special_price' => '', 'special_to_date' => '', - 'status' => '1', - 'tax_class_id' => '2', + 'product_online' => '1', + 'tax_class_name' => 'Taxable Goods', 'thumbnail' => '', 'thumbnail_label' => '', 'updated_at' => '2013-10-25 15:12:37', 'upsell_tgtr_position_behavior' => '', 'upsell_tgtr_position_limit' => '', 'url_key' => 'configurable-product-%s-option-3', - 'url_path' => 'configurable-product-%s-option-3.html', + 'url_path' => 'configurable-product-%s-option-3', 'variations' => '', 'variations_1382710717' => '', 'variations_1382710773' => '', 'variations_1382710861' => '', - 'visibility' => '1', - 'weight' => '1.0000', + 'visibility' => 'Not Visible Individually', + 'weight' => '1', 'qty' => '111.0000', 'min_qty' => '0.0000', 'use_config_min_qty' => '1', @@ -482,21 +475,16 @@ class ConfigurableProductsFixture extends Fixture '_media_label' => '', '_media_position' => '', '_media_is_disabled' => '', - '_super_products_sku' => '', - '_super_attribute_code' => '', - '_super_attribute_option' => '', - '_super_attribute_price_corr' => '', ], [ 'sku' => 'Configurable Product %s', - '_store' => '', - '_attribute_set' => 'Default', - '_type' => 'configurable', - '_category' => $productCategory, - '_root_category' => $productRootCategory, - '_product_websites' => $productWebsite, + 'store_view_code' => '', + 'attribute_set_code' => 'Default', + 'product_type' => 'configurable', + 'categories' => $productCategory, + 'product_websites' => $productWebsite, 'color' => '', - 'configurable_variations' => '', + 'configurable_variation' => '', 'cost' => '', 'country_of_manufacture' => '', 'created_at' => '2013-10-25 15:12:39', @@ -526,7 +514,7 @@ class ConfigurableProductsFixture extends Fixture 'news_to_date' => '', 'options_container' => 'Block after Info Column', 'page_layout' => '', - 'price' => '10.0000', + 'price' => '10', 'quantity_and_stock_status' => 'In Stock', 'related_tgtr_position_behavior' => '', 'related_tgtr_position_limit' => '', @@ -537,20 +525,20 @@ class ConfigurableProductsFixture extends Fixture 'special_from_date' => '', 'special_price' => '', 'special_to_date' => '', - 'status' => '1', - 'tax_class_id' => '2', + 'product_online' => '1', + 'tax_class_name' => 'Taxable Goods', 'thumbnail' => '', 'thumbnail_label' => '', 'updated_at' => '2013-10-25 15:12:39', 'upsell_tgtr_position_behavior' => '', 'upsell_tgtr_position_limit' => '', 'url_key' => 'configurable-product-%s', - 'url_path' => 'configurable-product-%s.html', + 'url_path' => 'configurable-product-%s', 'variations' => '', 'variations_1382710717' => '', 'variations_1382710773' => '', 'variations_1382710861' => '', - 'visibility' => '4', + 'visibility' => 'Catalog, Search', 'weight' => '', 'qty' => 333, 'min_qty' => '0.0000', @@ -593,232 +581,8 @@ class ConfigurableProductsFixture extends Fixture '_media_label' => '', '_media_position' => '', '_media_is_disabled' => '', - '_super_products_sku' => 'Configurable Product %s-option 1', - '_super_attribute_code' => 'configurable_variations', - '_super_attribute_option' => 'option 1', - '_super_attribute_price_corr' => '10.0000', - ], - [ - 'sku' => '', - '_store' => '', - '_attribute_set' => '', - '_type' => '', - '_category' => '', - '_root_category' => '', - '_product_websites' => '', - 'color' => '', - 'configurable_variations' => '', - 'cost' => '', - 'country_of_manufacture' => '', - 'created_at' => '', - 'custom_design' => '', - 'custom_design_from' => '', - 'custom_design_to' => '', - 'custom_layout_update' => '', - 'description' => '', - 'enable_googlecheckout' => '', - 'gallery' => '', - 'gift_message_available' => '', - 'gift_wrapping_available' => '', - 'gift_wrapping_price' => '', - 'has_options' => '', - 'image' => '', - 'image_label' => '', - 'is_returnable' => '', - 'manufacturer' => '', - 'meta_description' => '', - 'meta_keyword' => '', - 'meta_title' => '', - 'minimal_price' => '', - 'msrp' => '', - 'msrp_display_actual_price_type' => '', - 'name' => '', - 'news_from_date' => '', - 'news_to_date' => '', - 'options_container' => '', - 'page_layout' => '', - 'price' => '', - 'quantity_and_stock_status' => '', - 'related_tgtr_position_behavior' => '', - 'related_tgtr_position_limit' => '', - 'required_options' => '', - 'short_description' => '', - 'small_image' => '', - 'small_image_label' => '', - 'special_from_date' => '', - 'special_price' => '', - 'special_to_date' => '', - 'status' => '', - 'tax_class_id' => '', - 'thumbnail' => '', - 'thumbnail_label' => '', - 'updated_at' => '', - 'upsell_tgtr_position_behavior' => '', - 'upsell_tgtr_position_limit' => '', - 'url_key' => '', - 'url_path' => '', - 'variations' => '', - 'variations_1382710717' => '', - 'variations_1382710773' => '', - 'variations_1382710861' => '', - 'visibility' => '', - 'weight' => '', - 'qty' => 333, - 'min_qty' => '', - 'use_config_min_qty' => '', - 'is_qty_decimal' => '', - 'backorders' => '', - 'use_config_backorders' => '', - 'min_sale_qty' => '', - 'use_config_min_sale_qty' => '', - 'max_sale_qty' => '', - 'use_config_max_sale_qty' => '', - 'is_in_stock' => '', - 'notify_stock_qty' => '', - 'use_config_notify_stock_qty' => '', - 'manage_stock' => '', - 'use_config_manage_stock' => '', - 'use_config_qty_increments' => '', - 'qty_increments' => '', - 'use_config_enable_qty_inc' => '', - 'enable_qty_increments' => '', - 'is_decimal_divided' => '', - '_related_sku' => '', - '_related_position' => '', - '_crosssell_sku' => '', - '_crosssell_position' => '', - '_upsell_sku' => '', - '_upsell_position' => '', - '_associated_sku' => '', - '_associated_default_qty' => '', - '_associated_position' => '', - '_tier_price_website' => '', - '_tier_price_customer_group' => '', - '_tier_price_qty' => '', - '_tier_price_price' => '', - '_group_price_website' => '', - '_group_price_customer_group' => '', - '_group_price_price' => '', - '_media_attribute_id' => '', - '_media_image' => '', - '_media_label' => '', - '_media_position' => '', - '_media_is_disabled' => '', - '_super_products_sku' => 'Configurable Product %s-option 2', - '_super_attribute_code' => 'configurable_variations', - '_super_attribute_option' => 'option 2', - '_super_attribute_price_corr' => '20.0000', - ], - [ - 'sku' => '', - '_store' => '', - '_attribute_set' => '', - '_type' => '', - '_category' => '', - '_root_category' => '', - '_product_websites' => '', - 'color' => '', - 'configurable_variations' => '', - 'cost' => '', - 'country_of_manufacture' => '', - 'created_at' => '', - 'custom_design' => '', - 'custom_design_from' => '', - 'custom_design_to' => '', - 'custom_layout_update' => '', - 'description' => '', - 'enable_googlecheckout' => '', - 'gallery' => '', - 'gift_message_available' => '', - 'gift_wrapping_available' => '', - 'gift_wrapping_price' => '', - 'has_options' => '', - 'image' => '', - 'image_label' => '', - 'is_returnable' => '', - 'manufacturer' => '', - 'meta_description' => '', - 'meta_keyword' => '', - 'meta_title' => '', - 'minimal_price' => '', - 'msrp' => '', - 'msrp_display_actual_price_type' => '', - 'name' => '', - 'news_from_date' => '', - 'news_to_date' => '', - 'options_container' => '', - 'page_layout' => '', - 'price' => '', - 'quantity_and_stock_status' => '', - 'related_tgtr_position_behavior' => '', - 'related_tgtr_position_limit' => '', - 'required_options' => '', - 'short_description' => '', - 'small_image' => '', - 'small_image_label' => '', - 'special_from_date' => '', - 'special_price' => '', - 'special_to_date' => '', - 'status' => '', - 'tax_class_id' => '', - 'thumbnail' => '', - 'thumbnail_label' => '', - 'updated_at' => '', - 'upsell_tgtr_position_behavior' => '', - 'upsell_tgtr_position_limit' => '', - 'url_key' => '', - 'url_path' => '', - 'variations' => '', - 'variations_1382710717' => '', - 'variations_1382710773' => '', - 'variations_1382710861' => '', - 'visibility' => '', - 'weight' => '', - 'qty' => 333, - 'min_qty' => '', - 'use_config_min_qty' => '', - 'is_qty_decimal' => '', - 'backorders' => '', - 'use_config_backorders' => '', - 'min_sale_qty' => '', - 'use_config_min_sale_qty' => '', - 'max_sale_qty' => '', - 'use_config_max_sale_qty' => '', - 'is_in_stock' => '', - 'notify_stock_qty' => '', - 'use_config_notify_stock_qty' => '', - 'manage_stock' => '', - 'use_config_manage_stock' => '', - 'use_config_qty_increments' => '', - 'qty_increments' => '', - 'use_config_enable_qty_inc' => '', - 'enable_qty_increments' => '', - 'is_decimal_divided' => '', - '_related_sku' => '', - '_related_position' => '', - '_crosssell_sku' => '', - '_crosssell_position' => '', - '_upsell_sku' => '', - '_upsell_position' => '', - '_associated_sku' => '', - '_associated_default_qty' => '', - '_associated_position' => '', - '_tier_price_website' => '', - '_tier_price_customer_group' => '', - '_tier_price_qty' => '', - '_tier_price_price' => '', - '_group_price_website' => '', - '_group_price_customer_group' => '', - '_group_price_price' => '', - '_media_attribute_id' => '', - '_media_image' => '', - '_media_label' => '', - '_media_position' => '', - '_media_is_disabled' => '', - '_super_products_sku' => 'Configurable Product %s-option 3', - '_super_attribute_code' => 'configurable_variations', - '_super_attribute_option' => 'option 3', - '_super_attribute_price_corr' => '30.0000', + 'configurable_variations' => 'sku=Configurable Product %s-option 1,configurable_variation=option 1|sku=Configurable Product %s-option 2,configurable_variation=option 2|sku=Configurable Product %s-option 3,configurable_variation=option 3', + 'configurable_variation_prices' => 'name=configurable_variation,value=option 1,price=10.0000|name=configurable_variation,value=option 2,price=20.0000|name=configurable_variation,value=option 3,price=30.0000', ], ]; @@ -881,10 +645,7 @@ class ConfigurableProductsFixture extends Fixture return $result[$index % count($result)][0]; }; $productCategory = function ($index) use ($result) { - return $result[$index % count($result)][1]; - }; - $productRootCategory = function ($index) use ($result) { - return $result[$index % count($result)][2]; + return $result[$index % count($result)][2] . '/' . $result[$index % count($result)][1]; }; /** @@ -892,12 +653,12 @@ class ConfigurableProductsFixture extends Fixture */ $pattern = new Pattern(); $pattern->setHeaders($this->getHeaders()); - $pattern->setRowsSet($this->getRows($productCategory, $productRootCategory, $productWebsite)); + $pattern->setRowsSet($this->getRows($productCategory, $productWebsite)); /** @var \Magento\ImportExport\Model\Import $import */ $import = $this->fixtureModel->getObjectManager()->create( 'Magento\ImportExport\Model\Import', - ['data' => ['entity' => 'catalog_product', 'behavior' => 'replace']] + ['data' => ['entity' => 'catalog_product', 'behavior' => 'append']] ); $source = new Generator($pattern, $configurablesCount); diff --git a/setup/src/Magento/Setup/Fixtures/EavVariationsFixture.php b/setup/src/Magento/Setup/Fixtures/EavVariationsFixture.php index c5ea2edf5f29f5ab3aca316a12fd0e50ad62e0df..13a9369b069c514e9d643e905178d0d0eeafdfe6 100644 --- a/setup/src/Magento/Setup/Fixtures/EavVariationsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/EavVariationsFixture.php @@ -58,7 +58,7 @@ class EavVariationsFixture extends Fixture ], ], 'default' => ['option_0'], - 'attribute_code' => 'configurable_variations', + 'attribute_code' => 'configurable_variation', 'is_global' => '1', 'default_value_text' => '', 'default_value_yesno' => '0', diff --git a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php index 0be4568b4bcbe0945051101c56f0ebadf3df19c1..15f9601cf2f9584e2ac9a25fbd99fefff6722cf9 100644 --- a/setup/src/Magento/Setup/Fixtures/OrdersFixture.php +++ b/setup/src/Magento/Setup/Fixtures/OrdersFixture.php @@ -208,15 +208,15 @@ class OrdersFixture extends Fixture $quoteAddressId[0] = $entityId * 2 - 1; $quoteAddressId[1] = $entityId * 2; - $queries[] = "INSERT INTO `{$quoteAddressTableName}` (`address_id`, `quote_id`, `created_at`, `updated_at`, `customer_id`, `save_in_address_book`, `customer_address_id`, `address_type`, `email`, `prefix`, `firstname`, `middlename`, `lastname`, `suffix`, `company`, `street`, `city`, `region`, `region_id`, `postcode`, `country_id`, `telephone`, `fax`, `same_as_billing`, `collect_shipping_rates`, `shipping_method`, `shipping_description`, `weight`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `tax_amount`, `base_tax_amount`, `shipping_amount`, `base_shipping_amount`, `shipping_tax_amount`, `base_shipping_tax_amount`, `discount_amount`, `base_discount_amount`, `grand_total`, `base_grand_total`, `customer_notes`, `applied_taxes`, `discount_description`, `shipping_discount_amount`, `base_shipping_discount_amount`, `subtotal_incl_tax`, `base_subtotal_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `shipping_hidden_tax_amount`, `base_shipping_hidden_tax_amnt`, `shipping_incl_tax`, `base_shipping_incl_tax`, `free_shipping`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`, `gift_message_id`) VALUES ({$quoteAddressId[0]}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', NULL, 1, NULL, 'billing', '{$email}', NULL, '{$firstName}', NULL, '{$lastName}', NULL, '{$company}', '{$address}', '{$city}', '{$state}', 1, '{$zip}', '{$country}', '{$phone}', NULL, 0, 0, NULL, NULL, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, NULL, NULL, 0.0000, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, 0.0000, NULL, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);"; - $queries[] = "INSERT INTO `{$quoteAddressTableName}` (`address_id`, `quote_id`, `created_at`, `updated_at`, `customer_id`, `save_in_address_book`, `customer_address_id`, `address_type`, `email`, `prefix`, `firstname`, `middlename`, `lastname`, `suffix`, `company`, `street`, `city`, `region`, `region_id`, `postcode`, `country_id`, `telephone`, `fax`, `same_as_billing`, `collect_shipping_rates`, `shipping_method`, `shipping_description`, `weight`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `tax_amount`, `base_tax_amount`, `shipping_amount`, `base_shipping_amount`, `shipping_tax_amount`, `base_shipping_tax_amount`, `discount_amount`, `base_discount_amount`, `grand_total`, `base_grand_total`, `customer_notes`, `applied_taxes`, `discount_description`, `shipping_discount_amount`, `base_shipping_discount_amount`, `subtotal_incl_tax`, `base_subtotal_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `shipping_hidden_tax_amount`, `base_shipping_hidden_tax_amnt`, `shipping_incl_tax`, `base_shipping_incl_tax`, `free_shipping`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`, `gift_message_id`) VALUES ({$quoteAddressId[1]}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', NULL, 0, NULL, 'shipping', '{$email}', NULL, '{$firstName}', NULL, '{$lastName}', NULL, '{$company}', '{$address}', '{$city}', '{$state}', 1, '{$zip}', '{$country}', '{$phone}', NULL, 1, 0, 'flatrate_flatrate', 'Flat Rate - Fixed', 2.0000, 17.0000, 17.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 10.0000, 0.0000, 0.0000, -1.7000, -1.7000, 25.3000, 25.3000, NULL, 'a:0:{}', NULL, 0.0000, 0.0000, 17.0000, NULL, 0.0000, 0.0000, 0.0000, NULL, 10.0000, 10.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries[] = "INSERT INTO `{$quoteAddressTableName}` (`address_id`, `quote_id`, `created_at`, `updated_at`, `customer_id`, `save_in_address_book`, `customer_address_id`, `address_type`, `email`, `prefix`, `firstname`, `middlename`, `lastname`, `suffix`, `company`, `street`, `city`, `region`, `region_id`, `postcode`, `country_id`, `telephone`, `fax`, `same_as_billing`, `collect_shipping_rates`, `shipping_method`, `shipping_description`, `weight`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `tax_amount`, `base_tax_amount`, `shipping_amount`, `base_shipping_amount`, `shipping_tax_amount`, `base_shipping_tax_amount`, `discount_amount`, `base_discount_amount`, `grand_total`, `base_grand_total`, `customer_notes`, `applied_taxes`, `discount_description`, `shipping_discount_amount`, `base_shipping_discount_amount`, `subtotal_incl_tax`, `base_subtotal_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `shipping_discount_tax_compensation_amount`, `base_shipping_discount_tax_compensation_amnt`, `shipping_incl_tax`, `base_shipping_incl_tax`, `free_shipping`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`, `gift_message_id`) VALUES ({$quoteAddressId[0]}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', NULL, 1, NULL, 'billing', '{$email}', NULL, '{$firstName}', NULL, '{$lastName}', NULL, '{$company}', '{$address}', '{$city}', '{$state}', 1, '{$zip}', '{$country}', '{$phone}', NULL, 0, 0, NULL, NULL, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, NULL, NULL, 0.0000, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, 0.0000, NULL, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries[] = "INSERT INTO `{$quoteAddressTableName}` (`address_id`, `quote_id`, `created_at`, `updated_at`, `customer_id`, `save_in_address_book`, `customer_address_id`, `address_type`, `email`, `prefix`, `firstname`, `middlename`, `lastname`, `suffix`, `company`, `street`, `city`, `region`, `region_id`, `postcode`, `country_id`, `telephone`, `fax`, `same_as_billing`, `collect_shipping_rates`, `shipping_method`, `shipping_description`, `weight`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `tax_amount`, `base_tax_amount`, `shipping_amount`, `base_shipping_amount`, `shipping_tax_amount`, `base_shipping_tax_amount`, `discount_amount`, `base_discount_amount`, `grand_total`, `base_grand_total`, `customer_notes`, `applied_taxes`, `discount_description`, `shipping_discount_amount`, `base_shipping_discount_amount`, `subtotal_incl_tax`, `base_subtotal_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `shipping_discount_tax_compensation_amount`, `base_shipping_discount_tax_compensation_amnt`, `shipping_incl_tax`, `base_shipping_incl_tax`, `free_shipping`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`, `gift_message_id`) VALUES ({$quoteAddressId[1]}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', NULL, 0, NULL, 'shipping', '{$email}', NULL, '{$firstName}', NULL, '{$lastName}', NULL, '{$company}', '{$address}', '{$city}', '{$state}', 1, '{$zip}', '{$country}', '{$phone}', NULL, 1, 0, 'flatrate_flatrate', 'Flat Rate - Fixed', 2.0000, 17.0000, 17.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 10.0000, 0.0000, 0.0000, -1.7000, -1.7000, 25.3000, 25.3000, NULL, 'a:0:{}', NULL, 0.0000, 0.0000, 17.0000, NULL, 0.0000, 0.0000, 0.0000, NULL, 10.0000, 10.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL);"; $quoteItemId[0] = $entityId * 4 - 3; $quoteItemId[1] = $entityId * 4 - 2; $quoteItemId[2] = $entityId * 4 - 1; $quoteItemId[3] = $entityId * 4; - $queries[] = "INSERT INTO `{$quoteItemTableName}` (`item_id`, `quote_id`, `created_at`, `updated_at`, `product_id`, `store_id`, `parent_item_id`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `weight`, `qty`, `price`, `base_price`, `custom_price`, `discount_percent`, `discount_amount`, `base_discount_amount`, `tax_percent`, `tax_amount`, `base_tax_amount`, `row_total`, `base_row_total`, `row_total_with_discount`, `row_weight`, `product_type`, `base_tax_before_discount`, `tax_before_discount`, `original_custom_price`, `redirect_url`, `base_cost`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `free_shipping`, `gift_message_id`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$quoteItemId[0]}, {$quoteId}, '1970-01-01 03:00:00', '1970-01-01 03:00:00', {$simpleProductId[0]($entityId)}, {$productStoreId($entityId)}, NULL, 0, '{$simpleProductSku[0]($entityId)}', '{$simpleProductName[0]($entityId)}', NULL, '1', NULL, 0, 0, 1.0000, 1.0000, 8.5000, 8.5000, NULL, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 1.0000, 'simple', NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; - $queries[] = "INSERT INTO `{$quoteItemTableName}` (`item_id`, `quote_id`, `created_at`, `updated_at`, `product_id`, `store_id`, `parent_item_id`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `weight`, `qty`, `price`, `base_price`, `custom_price`, `discount_percent`, `discount_amount`, `base_discount_amount`, `tax_percent`, `tax_amount`, `base_tax_amount`, `row_total`, `base_row_total`, `row_total_with_discount`, `row_weight`, `product_type`, `base_tax_before_discount`, `tax_before_discount`, `original_custom_price`, `redirect_url`, `base_cost`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `free_shipping`, `gift_message_id`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$quoteItemId[1]}, {$quoteId}, '1970-01-01 03:00:00', '1970-01-01 03:00:00', {$simpleProductId[1]($entityId)}, {$productStoreId($entityId)}, NULL, 0, '{$simpleProductSku[1]($entityId)}', '{$simpleProductName[1]($entityId)}', NULL, '1', NULL, 0, 0, 1.0000, 1.0000, 8.5000, 8.5000, NULL, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 1.0000, 'simple', NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries[] = "INSERT INTO `{$quoteItemTableName}` (`item_id`, `quote_id`, `created_at`, `updated_at`, `product_id`, `store_id`, `parent_item_id`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `weight`, `qty`, `price`, `base_price`, `custom_price`, `discount_percent`, `discount_amount`, `base_discount_amount`, `tax_percent`, `tax_amount`, `base_tax_amount`, `row_total`, `base_row_total`, `row_total_with_discount`, `row_weight`, `product_type`, `base_tax_before_discount`, `tax_before_discount`, `original_custom_price`, `redirect_url`, `base_cost`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `free_shipping`, `gift_message_id`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$quoteItemId[0]}, {$quoteId}, '1970-01-01 03:00:00', '1970-01-01 03:00:00', {$simpleProductId[0]($entityId)}, {$productStoreId($entityId)}, NULL, 0, '{$simpleProductSku[0]($entityId)}', '{$simpleProductName[0]($entityId)}', NULL, '1', NULL, 0, 0, 1.0000, 1.0000, 8.5000, 8.5000, NULL, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 1.0000, 'simple', NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries[] = "INSERT INTO `{$quoteItemTableName}` (`item_id`, `quote_id`, `created_at`, `updated_at`, `product_id`, `store_id`, `parent_item_id`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `weight`, `qty`, `price`, `base_price`, `custom_price`, `discount_percent`, `discount_amount`, `base_discount_amount`, `tax_percent`, `tax_amount`, `base_tax_amount`, `row_total`, `base_row_total`, `row_total_with_discount`, `row_weight`, `product_type`, `base_tax_before_discount`, `tax_before_discount`, `original_custom_price`, `redirect_url`, `base_cost`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `free_shipping`, `gift_message_id`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$quoteItemId[1]}, {$quoteId}, '1970-01-01 03:00:00', '1970-01-01 03:00:00', {$simpleProductId[1]($entityId)}, {$productStoreId($entityId)}, NULL, 0, '{$simpleProductSku[1]($entityId)}', '{$simpleProductName[1]($entityId)}', NULL, '1', NULL, 0, 0, 1.0000, 1.0000, 8.5000, 8.5000, NULL, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 1.0000, 'simple', NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; $quoteItemOptionId[0] = $entityId * 8 - 7; $quoteItemOptionId[1] = $entityId * 8 - 6; @@ -243,7 +243,7 @@ class OrdersFixture extends Fixture $queries[] = "INSERT INTO `{$reportEventTableName}` (`event_id`, `logged_at`, `event_type_id`, `object_id`, `subject_id`, `subtype`, `store_id`) VALUES ({$reportEventId[1]}, '{$time}', 4, {$simpleProductId[1]($entityId)}, 2, 1, {$productStoreId($entityId)});"; $salesOrderId = $quoteId; - $queries[] = "INSERT INTO `{$salesOrderTableName}` (`entity_id`, `state`, `status`, `coupon_code`, `protect_code`, `shipping_description`, `is_virtual`, `store_id`, `customer_id`, `base_discount_amount`, `base_discount_canceled`, `base_discount_invoiced`, `base_discount_refunded`, `base_grand_total`, `base_shipping_amount`, `base_shipping_canceled`, `base_shipping_invoiced`, `base_shipping_refunded`, `base_shipping_tax_amount`, `base_shipping_tax_refunded`, `base_subtotal`, `base_subtotal_canceled`, `base_subtotal_invoiced`, `base_subtotal_refunded`, `base_tax_amount`, `base_tax_canceled`, `base_tax_invoiced`, `base_tax_refunded`, `base_to_global_rate`, `base_to_order_rate`, `base_total_canceled`, `base_total_invoiced`, `base_total_invoiced_cost`, `base_total_offline_refunded`, `base_total_online_refunded`, `base_total_paid`, `base_total_qty_ordered`, `base_total_refunded`, `discount_amount`, `discount_canceled`, `discount_invoiced`, `discount_refunded`, `grand_total`, `shipping_amount`, `shipping_canceled`, `shipping_invoiced`, `shipping_refunded`, `shipping_tax_amount`, `shipping_tax_refunded`, `store_to_base_rate`, `store_to_order_rate`, `subtotal`, `subtotal_canceled`, `subtotal_invoiced`, `subtotal_refunded`, `tax_amount`, `tax_canceled`, `tax_invoiced`, `tax_refunded`, `total_canceled`, `total_invoiced`, `total_offline_refunded`, `total_online_refunded`, `total_paid`, `total_qty_ordered`, `total_refunded`, `can_ship_partially`, `can_ship_partially_item`, `customer_is_guest`, `customer_note_notify`, `billing_address_id`, `customer_group_id`, `edit_increment`, `email_sent`, `send_email`, `forced_shipment_with_invoice`, `payment_auth_expiration`, `quote_address_id`, `quote_id`, `shipping_address_id`, `adjustment_negative`, `adjustment_positive`, `base_adjustment_negative`, `base_adjustment_positive`, `base_shipping_discount_amount`, `base_subtotal_incl_tax`, `base_total_due`, `payment_authorization_amount`, `shipping_discount_amount`, `subtotal_incl_tax`, `total_due`, `weight`, `customer_dob`, `increment_id`, `applied_rule_ids`, `base_currency_code`, `customer_email`, `customer_firstname`, `customer_lastname`, `customer_middlename`, `customer_prefix`, `customer_suffix`, `customer_taxvat`, `discount_description`, `ext_customer_id`, `ext_order_id`, `global_currency_code`, `hold_before_state`, `hold_before_status`, `order_currency_code`, `original_increment_id`, `relation_child_id`, `relation_child_real_id`, `relation_parent_id`, `relation_parent_real_id`, `remote_ip`, `shipping_method`, `store_currency_code`, `store_name`, `x_forwarded_for`, `customer_note`, `created_at`, `updated_at`, `total_item_count`, `customer_gender`, `hidden_tax_amount`, `base_hidden_tax_amount`, `shipping_hidden_tax_amount`, `base_shipping_hidden_tax_amnt`, `hidden_tax_invoiced`, `base_hidden_tax_invoiced`, `hidden_tax_refunded`, `base_hidden_tax_refunded`, `shipping_incl_tax`, `base_shipping_incl_tax`, `coupon_rule_name`, `gift_message_id`) VALUES ({$salesOrderId}, 'new', 'pending', NULL, '272ecb', 'Flat Rate - Fixed', 0, {$productStoreId($entityId)}, NULL, -1.7000, NULL, NULL, NULL, 25.3000, 10.0000, NULL, NULL, NULL, 0.0000, NULL, 17.0000, NULL, NULL, NULL, 0.0000, NULL, NULL, NULL, 1.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1.7000, NULL, NULL, NULL, 25.3000, 10.0000, NULL, NULL, NULL, 0.0000, NULL, 0.0000, 0.0000, 17.0000, NULL, NULL, NULL, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2.0000, NULL, NULL, NULL, 1, 1, 2, 0, NULL, 1, 1, NULL, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, NULL, 17.0000, 25.3000, NULL, NULL, 17.0000, 25.3000, 2.0000, NULL, {$orderNumber}, '1', 'USD', '{$email}', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'USD', NULL, NULL, 'USD', NULL, NULL, NULL, NULL, NULL, '127.0.0.1', 'flatrate_flatrate', 'USD', '{$productStoreName($entityId)}', NULL, NULL, '{$time}', '{$time}', 2, NULL, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, 10.0000, 10.0000, NULL, NULL);"; + $queries[] = "INSERT INTO `{$salesOrderTableName}` (`entity_id`, `state`, `status`, `coupon_code`, `protect_code`, `shipping_description`, `is_virtual`, `store_id`, `customer_id`, `base_discount_amount`, `base_discount_canceled`, `base_discount_invoiced`, `base_discount_refunded`, `base_grand_total`, `base_shipping_amount`, `base_shipping_canceled`, `base_shipping_invoiced`, `base_shipping_refunded`, `base_shipping_tax_amount`, `base_shipping_tax_refunded`, `base_subtotal`, `base_subtotal_canceled`, `base_subtotal_invoiced`, `base_subtotal_refunded`, `base_tax_amount`, `base_tax_canceled`, `base_tax_invoiced`, `base_tax_refunded`, `base_to_global_rate`, `base_to_order_rate`, `base_total_canceled`, `base_total_invoiced`, `base_total_invoiced_cost`, `base_total_offline_refunded`, `base_total_online_refunded`, `base_total_paid`, `base_total_qty_ordered`, `base_total_refunded`, `discount_amount`, `discount_canceled`, `discount_invoiced`, `discount_refunded`, `grand_total`, `shipping_amount`, `shipping_canceled`, `shipping_invoiced`, `shipping_refunded`, `shipping_tax_amount`, `shipping_tax_refunded`, `store_to_base_rate`, `store_to_order_rate`, `subtotal`, `subtotal_canceled`, `subtotal_invoiced`, `subtotal_refunded`, `tax_amount`, `tax_canceled`, `tax_invoiced`, `tax_refunded`, `total_canceled`, `total_invoiced`, `total_offline_refunded`, `total_online_refunded`, `total_paid`, `total_qty_ordered`, `total_refunded`, `can_ship_partially`, `can_ship_partially_item`, `customer_is_guest`, `customer_note_notify`, `billing_address_id`, `customer_group_id`, `edit_increment`, `email_sent`, `send_email`, `forced_shipment_with_invoice`, `payment_auth_expiration`, `quote_address_id`, `quote_id`, `shipping_address_id`, `adjustment_negative`, `adjustment_positive`, `base_adjustment_negative`, `base_adjustment_positive`, `base_shipping_discount_amount`, `base_subtotal_incl_tax`, `base_total_due`, `payment_authorization_amount`, `shipping_discount_amount`, `subtotal_incl_tax`, `total_due`, `weight`, `customer_dob`, `increment_id`, `applied_rule_ids`, `base_currency_code`, `customer_email`, `customer_firstname`, `customer_lastname`, `customer_middlename`, `customer_prefix`, `customer_suffix`, `customer_taxvat`, `discount_description`, `ext_customer_id`, `ext_order_id`, `global_currency_code`, `hold_before_state`, `hold_before_status`, `order_currency_code`, `original_increment_id`, `relation_child_id`, `relation_child_real_id`, `relation_parent_id`, `relation_parent_real_id`, `remote_ip`, `shipping_method`, `store_currency_code`, `store_name`, `x_forwarded_for`, `customer_note`, `created_at`, `updated_at`, `total_item_count`, `customer_gender`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `shipping_discount_tax_compensation_amount`, `base_shipping_discount_tax_compensation_amnt`, `discount_tax_compensation_invoiced`, `base_discount_tax_compensation_invoiced`, `discount_tax_compensation_refunded`, `base_discount_tax_compensation_refunded`, `shipping_incl_tax`, `base_shipping_incl_tax`, `coupon_rule_name`, `gift_message_id`) VALUES ({$salesOrderId}, 'new', 'pending', NULL, '272ecb', 'Flat Rate - Fixed', 0, {$productStoreId($entityId)}, NULL, -1.7000, NULL, NULL, NULL, 25.3000, 10.0000, NULL, NULL, NULL, 0.0000, NULL, 17.0000, NULL, NULL, NULL, 0.0000, NULL, NULL, NULL, 1.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1.7000, NULL, NULL, NULL, 25.3000, 10.0000, NULL, NULL, NULL, 0.0000, NULL, 0.0000, 0.0000, 17.0000, NULL, NULL, NULL, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2.0000, NULL, NULL, NULL, 1, 1, 2, 0, NULL, 1, 1, NULL, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, NULL, 17.0000, 25.3000, NULL, NULL, 17.0000, 25.3000, 2.0000, NULL, {$orderNumber}, '1', 'USD', '{$email}', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'USD', NULL, NULL, 'USD', NULL, NULL, NULL, NULL, NULL, '127.0.0.1', 'flatrate_flatrate', 'USD', '{$productStoreName($entityId)}', NULL, NULL, '{$time}', '{$time}', 2, NULL, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, 10.0000, 10.0000, NULL, NULL);"; $salesOrderAddressId[0] = $quoteAddressId[0]; $salesOrderAddressId[1] = $quoteAddressId[1]; @@ -257,8 +257,8 @@ class OrdersFixture extends Fixture $salesOrderItemId[1] = $quoteItemId[1]; $salesOrderItemId[2] = $quoteItemId[2]; $salesOrderItemId[3] = $quoteItemId[3]; - $queries[] = "INSERT INTO `{$salesOrderItemTableName}` (`item_id`, `order_id`, `parent_item_id`, `quote_item_id`, `store_id`, `created_at`, `updated_at`, `product_id`, `product_type`, `product_options`, `weight`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `qty_backordered`, `qty_canceled`, `qty_invoiced`, `qty_ordered`, `qty_refunded`, `qty_shipped`, `base_cost`, `price`, `base_price`, `original_price`, `base_original_price`, `tax_percent`, `tax_amount`, `base_tax_amount`, `tax_invoiced`, `base_tax_invoiced`, `discount_percent`, `discount_amount`, `base_discount_amount`, `discount_invoiced`, `base_discount_invoiced`, `amount_refunded`, `base_amount_refunded`, `row_total`, `base_row_total`, `row_invoiced`, `base_row_invoiced`, `row_weight`, `base_tax_before_discount`, `tax_before_discount`, `ext_order_item_id`, `locked_do_invoice`, `locked_do_ship`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `hidden_tax_invoiced`, `base_hidden_tax_invoiced`, `hidden_tax_refunded`, `base_hidden_tax_refunded`, `tax_canceled`, `hidden_tax_canceled`, `tax_refunded`, `base_tax_refunded`, `discount_refunded`, `base_discount_refunded`, `free_shipping`, `gift_message_id`, `gift_message_available`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$salesOrderItemId[0]}, {$salesOrderId}, NULL, {$quoteItemId[0]}, {$productStoreId($entityId)}, '{$time}', '0000-00-00 00:00:00', {$simpleProductId[0]($entityId)}, 'simple', 'a:1:{s:15:\"info_buyRequest\";a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[0]}:\"{$simpleProductId[0]($entityId)}\";s:3:\"qty\";i:1;}}', 1.0000, 0, '{$simpleProductSku[0]($entityId)}', '{$simpleProductName[0]($entityId)}', NULL, '1', NULL, 0, 0, NULL, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, NULL, 8.5000, 8.5000, 10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 0.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; - $queries[] = "INSERT INTO `{$salesOrderItemTableName}` (`item_id`, `order_id`, `parent_item_id`, `quote_item_id`, `store_id`, `created_at`, `updated_at`, `product_id`, `product_type`, `product_options`, `weight`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `qty_backordered`, `qty_canceled`, `qty_invoiced`, `qty_ordered`, `qty_refunded`, `qty_shipped`, `base_cost`, `price`, `base_price`, `original_price`, `base_original_price`, `tax_percent`, `tax_amount`, `base_tax_amount`, `tax_invoiced`, `base_tax_invoiced`, `discount_percent`, `discount_amount`, `base_discount_amount`, `discount_invoiced`, `base_discount_invoiced`, `amount_refunded`, `base_amount_refunded`, `row_total`, `base_row_total`, `row_invoiced`, `base_row_invoiced`, `row_weight`, `base_tax_before_discount`, `tax_before_discount`, `ext_order_item_id`, `locked_do_invoice`, `locked_do_ship`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `hidden_tax_amount`, `base_hidden_tax_amount`, `hidden_tax_invoiced`, `base_hidden_tax_invoiced`, `hidden_tax_refunded`, `base_hidden_tax_refunded`, `tax_canceled`, `hidden_tax_canceled`, `tax_refunded`, `base_tax_refunded`, `discount_refunded`, `base_discount_refunded`, `free_shipping`, `gift_message_id`, `gift_message_available`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$salesOrderItemId[1]}, {$salesOrderId}, NULL, {$quoteItemId[1]}, {$productStoreId($entityId)}, '{$time}', '0000-00-00 00:00:00', {$simpleProductId[1]($entityId)}, 'simple', 'a:1:{s:15:\"info_buyRequest\";a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[1]}:\"{$simpleProductId[1]($entityId)}\";s:3:\"qty\";i:1;}}', 1.0000, 0, '{$simpleProductSku[1]($entityId)}', '{$simpleProductName[1]($entityId)}', NULL, '1', NULL, 0, 0, NULL, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, NULL, 8.5000, 8.5000, 10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 0.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries[] = "INSERT INTO `{$salesOrderItemTableName}` (`item_id`, `order_id`, `parent_item_id`, `quote_item_id`, `store_id`, `created_at`, `updated_at`, `product_id`, `product_type`, `product_options`, `weight`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `qty_backordered`, `qty_canceled`, `qty_invoiced`, `qty_ordered`, `qty_refunded`, `qty_shipped`, `base_cost`, `price`, `base_price`, `original_price`, `base_original_price`, `tax_percent`, `tax_amount`, `base_tax_amount`, `tax_invoiced`, `base_tax_invoiced`, `discount_percent`, `discount_amount`, `base_discount_amount`, `discount_invoiced`, `base_discount_invoiced`, `amount_refunded`, `base_amount_refunded`, `row_total`, `base_row_total`, `row_invoiced`, `base_row_invoiced`, `row_weight`, `base_tax_before_discount`, `tax_before_discount`, `ext_order_item_id`, `locked_do_invoice`, `locked_do_ship`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `discount_tax_compensation_invoiced`, `base_discount_tax_compensation_invoiced`, `discount_tax_compensation_refunded`, `base_discount_tax_compensation_refunded`, `tax_canceled`, `discount_tax_compensation_canceled`, `tax_refunded`, `base_tax_refunded`, `discount_refunded`, `base_discount_refunded`, `free_shipping`, `gift_message_id`, `gift_message_available`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$salesOrderItemId[0]}, {$salesOrderId}, NULL, {$quoteItemId[0]}, {$productStoreId($entityId)}, '{$time}', '0000-00-00 00:00:00', {$simpleProductId[0]($entityId)}, 'simple', 'a:1:{s:15:\"info_buyRequest\";a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[0]}:\"{$simpleProductId[0]($entityId)}\";s:3:\"qty\";i:1;}}', 1.0000, 0, '{$simpleProductSku[0]($entityId)}', '{$simpleProductName[0]($entityId)}', NULL, '1', NULL, 0, 0, NULL, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, NULL, 8.5000, 8.5000, 10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 0.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; + $queries[] = "INSERT INTO `{$salesOrderItemTableName}` (`item_id`, `order_id`, `parent_item_id`, `quote_item_id`, `store_id`, `created_at`, `updated_at`, `product_id`, `product_type`, `product_options`, `weight`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `qty_backordered`, `qty_canceled`, `qty_invoiced`, `qty_ordered`, `qty_refunded`, `qty_shipped`, `base_cost`, `price`, `base_price`, `original_price`, `base_original_price`, `tax_percent`, `tax_amount`, `base_tax_amount`, `tax_invoiced`, `base_tax_invoiced`, `discount_percent`, `discount_amount`, `base_discount_amount`, `discount_invoiced`, `base_discount_invoiced`, `amount_refunded`, `base_amount_refunded`, `row_total`, `base_row_total`, `row_invoiced`, `base_row_invoiced`, `row_weight`, `base_tax_before_discount`, `tax_before_discount`, `ext_order_item_id`, `locked_do_invoice`, `locked_do_ship`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `discount_tax_compensation_invoiced`, `base_discount_tax_compensation_invoiced`, `discount_tax_compensation_refunded`, `base_discount_tax_compensation_refunded`, `tax_canceled`, `discount_tax_compensation_canceled`, `tax_refunded`, `base_tax_refunded`, `discount_refunded`, `base_discount_refunded`, `free_shipping`, `gift_message_id`, `gift_message_available`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$salesOrderItemId[1]}, {$salesOrderId}, NULL, {$quoteItemId[1]}, {$productStoreId($entityId)}, '{$time}', '0000-00-00 00:00:00', {$simpleProductId[1]($entityId)}, 'simple', 'a:1:{s:15:\"info_buyRequest\";a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[1]}:\"{$simpleProductId[1]($entityId)}\";s:3:\"qty\";i:1;}}', 1.0000, 0, '{$simpleProductSku[1]($entityId)}', '{$simpleProductName[1]($entityId)}', NULL, '1', NULL, 0, 0, NULL, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, NULL, 8.5000, 8.5000, 10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 0.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);"; $salesOrderPaymentId = $salesOrderId; $queries[] = "INSERT INTO `{$salesOrderPaymentTableName}` (`entity_id`, `parent_id`, `base_shipping_captured`, `shipping_captured`, `amount_refunded`, `base_amount_paid`, `amount_canceled`, `base_amount_authorized`, `base_amount_paid_online`, `base_amount_refunded_online`, `base_shipping_amount`, `shipping_amount`, `amount_paid`, `amount_authorized`, `base_amount_ordered`, `base_shipping_refunded`, `shipping_refunded`, `base_amount_refunded`, `amount_ordered`, `base_amount_canceled`, `quote_payment_id`, `additional_data`, `cc_exp_month`, `cc_ss_start_year`, `echeck_bank_name`, `method`, `cc_debug_request_body`, `cc_secure_verify`, `protection_eligibility`, `cc_approval`, `cc_last_4`, `cc_status_description`, `echeck_type`, `cc_debug_response_serialized`, `cc_ss_start_month`, `echeck_account_type`, `last_trans_id`, `cc_cid_status`, `cc_owner`, `cc_type`, `po_number`, `cc_exp_year`, `cc_status`, `echeck_routing_number`, `account_status`, `anet_trans_method`, `cc_debug_response_body`, `cc_ss_issue`, `echeck_account_name`, `cc_avs_status`, `cc_number_enc`, `cc_trans_id`, `address_status`, `additional_information`) VALUES ({$salesOrderPaymentId}, {$salesOrderId}, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 10.0000, 10.0000, NULL, NULL, 25.3000, NULL, NULL, NULL, 25.3000, NULL, NULL, NULL, NULL, '0', NULL, 'checkmo', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '0', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'a:1:{s:53:\"a:1:{s:12:\"method_title\";s:19:\"Check / Money order\";}\";N;}');"; diff --git a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php index 56e255e87eabf52b85bb850a314c71fb9aba50eb..ab977626ac4d6769acfc40bd0f414dec62047bf8 100644 --- a/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php +++ b/setup/src/Magento/Setup/Fixtures/SimpleProductsFixture.php @@ -53,7 +53,7 @@ class SimpleProductsFixture extends Fixture $pathSize = count($structure); if ($pathSize > 1) { $path = []; - for ($i = 1; $i < $pathSize; $i++) { + for ($i = 0; $i < $pathSize; $i++) { $path[] = $category->load($structure[$i])->getName(); } array_shift($path); @@ -102,33 +102,33 @@ class SimpleProductsFixture extends Fixture protected function getPattern($productWebsiteClosure, $productCategoryClosure) { return [ - '_attribute_set' => 'Default', - '_type' => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE, - '_product_websites' => $productWebsiteClosure, - '_category' => $productCategoryClosure, + 'attribute_set_code' => 'Default', + 'product_type' => \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE, + 'product_websites' => $productWebsiteClosure, + 'categories' => $productCategoryClosure, 'name' => 'Simple Product %s', 'short_description' => 'Short simple product description %s', 'weight' => 1, 'description' => 'Full simple product Description %s', 'sku' => 'product_dynamic_%s', 'price' => 10, - 'visibility' => \Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH, - 'status' => \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED, - 'tax_class_id' => 2, + 'visibility' => 'Catalog, Search', + 'product_online' => \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED, + 'tax_class_name' => 'Taxable Goods', /** * actually it saves without stock data, but by default system won't show on the * frontend products out of stock */ 'is_in_stock' => 1, 'qty' => 100500, - 'use_config_min_qty' => '1', - 'use_config_backorders' => '1', - 'use_config_min_sale_qty' => '1', - 'use_config_max_sale_qty' => '1', - 'use_config_notify_stock_qty' => '1', - 'use_config_manage_stock' => '1', - 'use_config_qty_increments' => '1', - 'use_config_enable_qty_inc' => '1', + 'out_of_stock_qty' => 'Use Config', + 'allow_backorders' => 'Use Config', + 'min_cart_qty' => 'Use Config', + 'max_cart_qty' => 'Use Config', + 'notify_on_stock_below' => 'Use Config', + 'manage_stock' => 'Use Config', + 'qty_increments' => 'Use Config', + 'enable_qty_incremements' => 'Use Config', ]; } diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php index 7edb61f9763c2750a9e38dc4d9149198fefb77bc..4ff4a044eff51178f651f1304e571d27047df638 100644 --- a/setup/src/Magento/Setup/Model/Installer.php +++ b/setup/src/Magento/Setup/Model/Installer.php @@ -1014,7 +1014,7 @@ class Installer return; } $dbName = $connection->quoteIdentifier($config[ConfigOptionsListConstants::KEY_NAME]); - $this->log->log("Recreating database {$dbName}"); + $this->log->log("Cleaning up database {$dbName}"); $connection->query("DROP DATABASE IF EXISTS {$dbName}"); $connection->query("CREATE DATABASE IF NOT EXISTS {$dbName}"); return; @@ -1056,7 +1056,10 @@ class Installer private function assertDeploymentConfigExists() { if (!$this->deploymentConfig->isAvailable()) { - throw new \Magento\Setup\Exception("Can't run this operation: deployment configuration is absent."); + throw new \Magento\Setup\Exception( + "Can't run this operation: deployment configuration is absent." + . " Run 'magento setup:config:set --help' for options." + ); } } @@ -1099,14 +1102,22 @@ class Installer * * @param array $request * @return void + * @throws \Magento\Setup\SampleDataException * * @SuppressWarnings(PHPMD.UnusedPrivateMethod) Called by install() via callback. */ private function installSampleData($request) { - $userName = isset($request[AdminAccount::KEY_USER]) ? $request[AdminAccount::KEY_USER] : ''; - $this->objectManagerProvider->reset(); - $this->sampleData->install($this->objectManagerProvider->get(), $this->log, $userName); + try { + $userName = isset($request[AdminAccount::KEY_USER]) ? $request[AdminAccount::KEY_USER] : ''; + $this->objectManagerProvider->reset(); + $this->sampleData->install($this->objectManagerProvider->get(), $this->log, $userName); + } catch (\Exception $e) { + throw new \Magento\Setup\SampleDataException( + "Error during sample data installation: {$e->getMessage()}", + $e->getCode() + ); + } } /** diff --git a/setup/src/Magento/Setup/Model/InstallerFactory.php b/setup/src/Magento/Setup/Model/InstallerFactory.php index 32a1e693df30ec8c89ad8105c1da3f773fdc5f8e..cddcfd649b7a05fe34d623146171af8c06b40e14 100644 --- a/setup/src/Magento/Setup/Model/InstallerFactory.php +++ b/setup/src/Magento/Setup/Model/InstallerFactory.php @@ -8,8 +8,6 @@ namespace Magento\Setup\Model; use Zend\ServiceManager\ServiceLocatorInterface; use Magento\Setup\Module\ResourceFactory; -use Magento\Framework\App\ErrorHandler; -use Magento\Framework\App\State\CleanupFiles; class InstallerFactory { @@ -35,9 +33,6 @@ class InstallerFactory { $this->serviceLocator = $serviceLocator; $this->resourceFactory = $resourceFactory; - // For Setup Wizard we are using our customized error handler - $handler = new ErrorHandler(); - set_error_handler([$handler, 'handler']); } /** diff --git a/setup/src/Magento/Setup/Model/SampleData.php b/setup/src/Magento/Setup/Model/SampleData.php index ad75e70bb72a5c8f7715e69851421150e699618f..a65fb57df40028a9ac20a1e362cd62d71bf11ba7 100644 --- a/setup/src/Magento/Setup/Model/SampleData.php +++ b/setup/src/Magento/Setup/Model/SampleData.php @@ -47,6 +47,47 @@ class SampleData return file_exists($this->directoryList->getPath(DirectoryList::MODULES) . self::PATH); } + /** + * Get state object or null if state object cannot be initialized + * + * @return null|\Magento\SampleData\Helper\State + */ + protected function getState() + { + if ($this->isDeployed() && class_exists('Magento\SampleData\Helper\State')) { + return new \Magento\SampleData\Helper\State(); + } + return null; + } + + /** + * Check whether installation of sample data was successful + * + * @return bool + */ + public function isInstalledSuccessfully() + { + $state = $this->getState(); + if (!$state) { + return false; + } + return \Magento\SampleData\Helper\State::STATE_FINISHED == $state->getState(); + } + + /** + * Check whether there was unsuccessful attempt to install Sample data + * + * @return bool + */ + public function isInstallationError() + { + $state = $this->getState(); + if (!$state) { + return false; + } + return \Magento\SampleData\Helper\State::STATE_STARTED == $state->getState(); + } + /** * Installation routine for creating sample data * diff --git a/setup/src/Magento/Setup/Module/Di/App/Task/Operation/ServiceDataAttributesGenerator.php b/setup/src/Magento/Setup/Module/Di/App/Task/Operation/ServiceDataAttributesGenerator.php index eed75e7e329eae5f0d6b2242dba0af662b9d0216..3e8ee94b8bd28a6dffd8cd363fe4a22fd494ef28 100644 --- a/setup/src/Magento/Setup/Module/Di/App/Task/Operation/ServiceDataAttributesGenerator.php +++ b/setup/src/Magento/Setup/Module/Di/App/Task/Operation/ServiceDataAttributesGenerator.php @@ -59,7 +59,7 @@ class ServiceDataAttributesGenerator implements OperationInterface } $files = $this->directoryScanner->scan($this->data['path'], $this->data['filePatterns']); - $repositories = $this->serviceDataAttributesScanner->collectEntities($files['service_data_attributes']); + $repositories = $this->serviceDataAttributesScanner->collectEntities($files['extension_attributes']); foreach ($repositories as $entityName) { class_exists($entityName); } diff --git a/setup/src/Magento/Setup/Module/Di/App/Task/OperationFactory.php b/setup/src/Magento/Setup/Module/Di/App/Task/OperationFactory.php index 69406279ccab9b56603c428721c03139d24ff64e..dd6bfa1f5ff3adf2395ccfcc871a3ec7fe5efe4a 100644 --- a/setup/src/Magento/Setup/Module/Di/App/Task/OperationFactory.php +++ b/setup/src/Magento/Setup/Module/Di/App/Task/OperationFactory.php @@ -35,7 +35,7 @@ class OperationFactory /** * Service data attributes generator */ - const DATA_ATTRIBUTES_GENERATOR = 'service_data_attributes_generator'; + const DATA_ATTRIBUTES_GENERATOR = 'extension_attributes_generator'; /** * Application code generator diff --git a/setup/src/Magento/Setup/Module/Di/Code/Scanner/ServiceDataAttributesScanner.php b/setup/src/Magento/Setup/Module/Di/Code/Scanner/ServiceDataAttributesScanner.php index 6fc9e341008105ccec0bc9f8cd3b15a850342dca..462a0989a52df825a624433863418c146f704dbf 100644 --- a/setup/src/Magento/Setup/Module/Di/Code/Scanner/ServiceDataAttributesScanner.php +++ b/setup/src/Magento/Setup/Module/Di/Code/Scanner/ServiceDataAttributesScanner.php @@ -11,7 +11,7 @@ namespace Magento\Setup\Module\Di\Code\Scanner; class ServiceDataAttributesScanner implements ScannerInterface { /** - * Scan provided service_data_attributes.xml and find extenstion classes. + * Scan provided extension_attributes.xml and find extenstion classes. * * @param array $files * @return array diff --git a/setup/src/Magento/Setup/SampleDataException.php b/setup/src/Magento/Setup/SampleDataException.php new file mode 100644 index 0000000000000000000000000000000000000000..05337f2ab72a84c3ded343546ace82c41bcdf61e --- /dev/null +++ b/setup/src/Magento/Setup/SampleDataException.php @@ -0,0 +1,11 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Setup; + +class SampleDataException extends \Exception +{ +} diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php index 867cd2df7b2412d310f01f24e51a5cb0bbe7bce3..1fb2fc2720905746c15b8eeba8521ee2f2e76ba8 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php @@ -51,7 +51,7 @@ class AdminUserCreateCommandTest extends \PHPUnit_Framework_TestCase $installerMock->expects($this->once())->method('installAdminUser')->with($data); $this->installerFactoryMock->expects($this->once())->method('create')->willReturn($installerMock); $commandTester->execute($options); - $this->assertEquals('Created admin user user' . PHP_EOL, $commandTester->getDisplay()); + $this->assertEquals('Created Magento administrator user named user' . PHP_EOL, $commandTester->getDisplay()); } public function testGetOptionsList() @@ -82,18 +82,18 @@ class AdminUserCreateCommandTest extends \PHPUnit_Framework_TestCase public function validateDataProvider() { return [ - [[null, 'Doe', 'admin', 'test@test.com', '123123q'], ['First Name is a required field.']], + [[null, 'Doe', 'admin', 'test@test.com', '123123q', '123123q'], ['First Name is a required field.']], [ - ['John', null, null, 'test@test.com', '123123q'], + ['John', null, null, 'test@test.com', '123123q', '123123q'], ['User Name is a required field.', 'Last Name is a required field.'], ], - [['John', 'Doe', 'admin', null, '123123q'], ['Please enter a valid email.']], + [['John', 'Doe', 'admin', null, '123123q', '123123q'], ['Please enter a valid email.']], [ - ['John', 'Doe', 'admin', 'test', '123123q'], + ['John', 'Doe', 'admin', 'test', '123123q', '123123q'], ["'test' is not a valid email address in the basic format local-part@hostname"] ], [ - ['John', 'Doe', 'admin', 'test@test.com', ''], + ['John', 'Doe', 'admin', 'test@test.com', '', ''], [ 'Password is required field.', 'Your password must be at least 7 characters.', @@ -101,17 +101,17 @@ class AdminUserCreateCommandTest extends \PHPUnit_Framework_TestCase ] ], [ - ['John', 'Doe', 'admin', 'test@test.com', '123123'], + ['John', 'Doe', 'admin', 'test@test.com', '123123', '123123'], [ 'Your password must be at least 7 characters.', 'Your password must include both numeric and alphabetic characters.' ] ], [ - ['John', 'Doe', 'admin', 'test@test.com', '1231231'], + ['John', 'Doe', 'admin', 'test@test.com', '1231231', '1231231'], ['Your password must include both numeric and alphabetic characters.'] ], - [['John', 'Doe', 'admin', 'test@test.com', '123123q'], []], + [['John', 'Doe', 'admin', 'test@test.com', '123123q', '123123q'], []], ]; } } diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/DbDataUpgradeCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/DbDataUpgradeCommandTest.php index 50494cd968b1ccf56db4596f6303f68eb8d59bf8..0c178b61d6906a7f952d418e61b5cb8ccbe54e64 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/DbDataUpgradeCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/DbDataUpgradeCommandTest.php @@ -51,7 +51,7 @@ class DbDataUpgradeCommandTest extends \PHPUnit_Framework_TestCase ); $commandTester->execute([]); $this->assertStringMatchesFormat( - 'No information is available: the application is not installed.%w', + 'No information is available: the Magento application is not installed.%w', $commandTester->getDisplay() ); } diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/DbSchemaUpgradeCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/DbSchemaUpgradeCommandTest.php index 6300175f95926f4c476d23ecc9252ea545d819ec..27f0746d90af263b29eeda08d6b37f3cb481c656 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/DbSchemaUpgradeCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/DbSchemaUpgradeCommandTest.php @@ -35,7 +35,7 @@ class DbSchemaUpgradeCommandTest extends DbDataUpgradeCommandTest ); $commandTester->execute([]); $this->assertStringMatchesFormat( - 'No information is available: the application is not installed.%w', + 'No information is available: the Magento application is not installed.%w', $commandTester->getDisplay() ); } diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/DbStatusCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/DbStatusCommandTest.php index d16758b51e6c99d4437423e59564f0b095c8621c..91b6a01f69f17fdfa2804c64d4a9c55b26a7ac52 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/DbStatusCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/DbStatusCommandTest.php @@ -123,7 +123,7 @@ class DbStatusCommandTest extends \PHPUnit_Framework_TestCase $tester = new CommandTester($this->command); $tester->execute([]); $this->assertStringMatchesFormat( - 'No information is available: the application is not installed.%w', + 'No information is available: the Magento application is not installed.%w', $tester->getDisplay() ); } diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/DiCompileCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/DiCompileCommandTest.php index f307af40de47385540ac3975226e03825212561a..450c74b14fb9bf372b4eb35131ca06d8e67b806c 100644 --- a/setup/src/Magento/Setup/Test/Unit/Console/Command/DiCompileCommandTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/DiCompileCommandTest.php @@ -10,26 +10,24 @@ use Symfony\Component\Console\Tester\CommandTester; class DiCompileCommandTest extends \PHPUnit_Framework_TestCase { - /** - * @var \Magento\Framework\App\DeploymentConfig|\PHPUnit_Framework_MockObject_MockObject - */ + /** @var \Magento\Framework\App\DeploymentConfig|\PHPUnit_Framework_MockObject_MockObject */ private $deploymentConfig; - /** - * @var \Magento\Setup\Module\Di\App\Task\Manager|\PHPUnit_Framework_MockObject_MockObject - */ + /** @var \Magento\Setup\Module\Di\App\Task\Manager|\PHPUnit_Framework_MockObject_MockObject */ private $manager; - /** - * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject - */ + /** @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ private $objectManager; - /** - * @var DiCompileCommand - */ + /** @var DiCompileCommand|\PHPUnit_Framework_MockObject_MockObject */ private $command; + /** @var \Magento\Framework\App\Cache|\PHPUnit_Framework_MockObject_MockObject */ + private $cacheMock; + + /** @var \Magento\Framework\Filesystem|\PHPUnit_Framework_MockObject_MockObject */ + private $filesystem; + public function setUp() { $this->deploymentConfig = $this->getMock('Magento\Framework\App\DeploymentConfig', [], [], '', false); @@ -46,15 +44,26 @@ class DiCompileCommandTest extends \PHPUnit_Framework_TestCase '', false ); - $objectManagerProvider->expects($this->once())->method('get')->willReturn($this->objectManager); + $this->cacheMock = $this->getMockBuilder('Magento\Framework\App\Cache') + ->disableOriginalConstructor() + ->getMock(); + + $objectManagerProvider->expects($this->once()) + ->method('get') + ->willReturn($this->objectManager); $this->manager = $this->getMock('Magento\Setup\Module\Di\App\Task\Manager', [], [], '', false); $directoryList = $this->getMock('Magento\Framework\App\Filesystem\DirectoryList', [], [], '', false); + $this->filesystem = $this->getMockBuilder('Magento\Framework\Filesystem') + ->disableOriginalConstructor() + ->getMock(); + $directoryList->expects($this->exactly(3))->method('getPath'); $this->command = new DiCompileCommand( $this->deploymentConfig, $directoryList, $this->manager, - $objectManagerProvider + $objectManagerProvider, + $this->filesystem ); } @@ -71,6 +80,15 @@ class DiCompileCommandTest extends \PHPUnit_Framework_TestCase public function testExecute() { + $this->objectManager->expects($this->once()) + ->method('get') + ->with('Magento\Framework\App\Cache') + ->willReturn($this->cacheMock); + $this->cacheMock->expects($this->once())->method('clean'); + $writeDirectory = $this->getMock('Magento\Framework\Filesystem\Directory\WriteInterface'); + $writeDirectory->expects($this->atLeastOnce())->method('delete'); + $this->filesystem->expects($this->atLeastOnce())->method('getDirectoryWrite')->willReturn($writeDirectory); + $this->deploymentConfig->expects($this->once())->method('isAvailable')->willReturn(true); $this->objectManager->expects($this->once())->method('configure'); $this->manager->expects($this->exactly(6))->method('addOperation'); diff --git a/setup/src/Magento/Setup/Test/Unit/Controller/CustomizeYourStoreTest.php b/setup/src/Magento/Setup/Test/Unit/Controller/CustomizeYourStoreTest.php index 2c1d1169ac7c5828f07e1ed7828de692f4006881..f029c6ac15234f5cb8257c0ad71a3289c2c145a9 100644 --- a/setup/src/Magento/Setup/Test/Unit/Controller/CustomizeYourStoreTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Controller/CustomizeYourStoreTest.php @@ -40,6 +40,10 @@ class CustomizeYourStoreTest extends \PHPUnit_Framework_TestCase public function testIndexAction($expected) { $this->sampleData->expects($this->once())->method('isDeployed')->willReturn($expected['isSampledataEnabled']); + $this->sampleData->expects($this->once())->method('isInstalledSuccessfully') + ->willReturn($expected['isSampleDataInstalled']); + $this->sampleData->expects($this->once())->method('isInstallationError') + ->willReturn($expected['isSampleDataErrorInstallation']); $this->lists->expects($this->once())->method('getTimezoneList')->willReturn($expected['timezone']); $this->lists->expects($this->once())->method('getCurrencyList')->willReturn($expected['currency']); $this->lists->expects($this->once())->method('getLocaleList')->willReturn($expected['language']); @@ -64,8 +68,13 @@ class CustomizeYourStoreTest extends \PHPUnit_Framework_TestCase $timezones = ['timezone' => ['America/New_York'=>'EST', 'America/Chicago' => 'CST']]; $currency = ['currency' => ['USD'=>'US Dollar', 'EUR' => 'Euro']]; $language = ['language' => ['en_US'=>'English (USA)', 'en_UK' => 'English (UK)']]; - $sampleDataTrue = ['isSampledataEnabled' => true]; - $sampleDataFalse = ['isSampledataEnabled' => false]; + $sampleData = [ + 'isSampledataEnabled' => null, + 'isSampleDataInstalled' => null, + 'isSampleDataErrorInstallation' => null + ]; + $sampleDataTrue = array_merge($sampleData, ['isSampledataEnabled' => true]); + $sampleDataFalse = array_merge($sampleData, ['isSampledataEnabled' => false]); return [ 'with_all_data' => [array_merge($timezones, $currency, $language, $sampleDataTrue)], @@ -76,7 +85,7 @@ class CustomizeYourStoreTest extends \PHPUnit_Framework_TestCase 'empty_timezone_data' => [array_merge(['timezone' => []], $currency, $language, $sampleDataTrue)], 'empty_language_data' => [array_merge($timezones, $currency, ['language' => []], $sampleDataTrue)], 'false_sample_data' => [array_merge($timezones, $currency, $language, $sampleDataFalse)], - 'no_sample_data' => [array_merge($timezones, $currency, $language, ['isSampledataEnabled' => null])], + 'no_sample_data' => [array_merge($timezones, $currency, $language, $sampleData)], ]; } diff --git a/setup/src/Magento/Setup/Test/Unit/Controller/DatabaseCheckTest.php b/setup/src/Magento/Setup/Test/Unit/Controller/DatabaseCheckTest.php index b813bc506ef321a73070e637ba1861e9953047a9..afafcbc914300b47fffca23143c69af399c1c3a4 100644 --- a/setup/src/Magento/Setup/Test/Unit/Controller/DatabaseCheckTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Controller/DatabaseCheckTest.php @@ -25,9 +25,8 @@ class DatabaseCheckTest extends \PHPUnit_Framework_TestCase public function setUp() { - $webLogger = $this->getMock('\Magento\Setup\Model\WebLogger', [], [], '', false); $this->dbValidator = $this->getMock('Magento\Setup\Validator\DbValidator', [], [], '', false); - $this->controller = new DatabaseCheck($webLogger, $this->dbValidator); + $this->controller = new DatabaseCheck($this->dbValidator); } public function testIndexAction() diff --git a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php index 0fb1ca0c6b16fd78a3585be56af24f64e78c6649..931d8e315e68c42205d3687b4ee9d84a539b1de0 100644 --- a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php @@ -434,7 +434,7 @@ class InstallerTest extends \PHPUnit_Framework_TestCase $this->connection->expects($this->at(0))->method('quoteIdentifier')->with('magento')->willReturn('`magento`'); $this->connection->expects($this->at(1))->method('query')->with('DROP DATABASE IF EXISTS `magento`'); $this->connection->expects($this->at(2))->method('query')->with('CREATE DATABASE IF NOT EXISTS `magento`'); - $this->logger->expects($this->once())->method('log')->with('Recreating database `magento`'); + $this->logger->expects($this->once())->method('log')->with('Cleaning up database `magento`'); $this->object->cleanupDb(); } } diff --git a/setup/src/Magento/Setup/Test/Unit/Module/Di/App/Task/ServiceDataAttributesGeneratorTest.php b/setup/src/Magento/Setup/Test/Unit/Module/Di/App/Task/ServiceDataAttributesGeneratorTest.php index dc11cccd596624ab0cf994cdad6adb602196299e..92212e3d79cb9fd7eb9ca2a0b9296d77f818bded 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/Di/App/Task/ServiceDataAttributesGeneratorTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/Di/App/Task/ServiceDataAttributesGeneratorTest.php @@ -76,7 +76,7 @@ class ServiceDataAttributesGeneratorTest extends \PHPUnit_Framework_TestCase 'path' => 'path/to/app', 'filePatterns' => ['di' => 'di.xml'], ]; - $files = ['service_data_attributes' => []]; + $files = ['extension_attributes' => []]; $model = new ServiceDataAttributesGenerator( $this->directoryScannerMock, $this->serviceDataAttributesScannerMock, @@ -91,7 +91,7 @@ class ServiceDataAttributesGeneratorTest extends \PHPUnit_Framework_TestCase )->willReturn($files); $this->serviceDataAttributesScannerMock->expects($this->once()) ->method('collectEntities') - ->with($files['service_data_attributes']) + ->with($files['extension_attributes']) ->willReturn([]); $model->doOperation(); diff --git a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/ServiceDataAttributesScannerTest.php b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/ServiceDataAttributesScannerTest.php index e96951ab59e9d110bd02e0a8ba59f44fb1b50b81..b7697813590c90cd3845ef83ad5936ce5fb5a110 100644 --- a/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/ServiceDataAttributesScannerTest.php +++ b/setup/src/Magento/Setup/Test/Unit/Module/Di/Code/Scanner/ServiceDataAttributesScannerTest.php @@ -23,7 +23,7 @@ class ServiceDataAttributesScannerTest extends \PHPUnit_Framework_TestCase protected function setUp() { $this->model = new ServiceDataAttributesScanner(); - $this->testFile = str_replace('\\', '/', realpath(__DIR__ . '/../../') . '/_files/service_data_attributes.xml'); + $this->testFile = str_replace('\\', '/', realpath(__DIR__ . '/../../') . '/_files/extension_attributes.xml'); } public function testCollectEntities() diff --git a/app/code/Magento/GiftMessage/etc/service_data_attributes.xml b/setup/src/Magento/Setup/Test/Unit/Module/Di/_files/extension_attributes.xml similarity index 95% rename from app/code/Magento/GiftMessage/etc/service_data_attributes.xml rename to setup/src/Magento/Setup/Test/Unit/Module/Di/_files/extension_attributes.xml index bc8a926dfb86f1a247e0ddbcceade7545b42b660..604ebb9dc9ab6850e9e98729f20a2ac9b9bfb5e1 100644 --- a/app/code/Magento/GiftMessage/etc/service_data_attributes.xml +++ b/setup/src/Magento/Setup/Test/Unit/Module/Di/_files/extension_attributes.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/service_data_attributes.xsd"> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> <extension_attributes for="Magento\Sales\Api\Data\OrderInterface"> <attribute code="gift_message" type="Magento\GiftMessage\Api\Data\MessageInterface" /> </extension_attributes> diff --git a/setup/view/magento/setup/customize-your-store.phtml b/setup/view/magento/setup/customize-your-store.phtml index 9209bce525b8e92ec9c4b11647bf19c5b4a6c658..8a6037453f184e32a49993ddebb59b6d2cf49dfd 100644 --- a/setup/view/magento/setup/customize-your-store.phtml +++ b/setup/view/magento/setup/customize-your-store.phtml @@ -43,6 +43,28 @@ <label class="form-label" for="useSampleData"> Use Sample Data </label> + + <?php if ($this->isSampleDataInstalled || $this->isSampleDataErrorInstallation): ?> + <div class="customize-database-clean"> + <p> + <?php if ($this->isSampleDataInstalled): ?> + You have already installed sample data. If you want to re-install it, your database has to be cleaned up + <?php endif; ?> + <?php if ($this->isSampleDataErrorInstallation): ?> + Your sample data is broken. If you want to re-install it, your database has to be cleaned up + <?php endif; ?> + </p> + <input + type="checkbox" + ng-model="store.cleanUpDatabase" + class="form-el-checkbox" + id="cleanUpDatabase" + > + <label class="form-label" for="cleanUpDatabase"> + Clean up automatically + </label> + </div> + <?php endif; ?> </div> </div> diff --git a/setup/view/magento/setup/install.phtml b/setup/view/magento/setup/install.phtml index 2d87470762de45ad0d7ae9b8d2616dc2d5f2f3c0..28936ec19f73a54ce8286c14fe2e010810e2dece 100644 --- a/setup/view/magento/setup/install.phtml +++ b/setup/view/magento/setup/install.phtml @@ -74,3 +74,28 @@ <div class="console" ng-bind-html="log"></div> </div> </div> + +<div class="install-database-clean" ng-show="isShowCleanUpBox"> + <p>To install sample data you should clean up you database</p> + <button + type="button" + class="btn btn-secondary" + ng-disabled="isDisabled" + ng-click="startCleanup(true)"> + Clean up automatically + </button> + <button + type="button" + class="btn btn-secondary" + ng-disabled="isDisabled" + ng-click="startCleanup(false)"> + Proceed without clean up + </button> + <button + type="button" + class="btn" + ng-disabled="isDisabled" + ng-click="hideCleanUpBox()"> + Cancel + </button> +</div> diff --git a/setup/view/magento/setup/readiness-check/progress.phtml b/setup/view/magento/setup/readiness-check/progress.phtml index d247f60402d7bb0a46cdd36ecf4361f7c3f5d6aa..38f17626b0349c1eddfcbc73bfddf60b814ebff8 100644 --- a/setup/view/magento/setup/readiness-check/progress.phtml +++ b/setup/view/magento/setup/readiness-check/progress.phtml @@ -101,7 +101,7 @@ <div class="readiness-check-content"> <h3 class="readiness-check-title">PHP Settings Check</h3> <p> - Your PHP setting is correct. + Your PHP settings are correct. </p> </div> @@ -171,7 +171,7 @@ <div class="rediness-check-side"> <p class="side-title">Need Help?</p> - <a href="#" target="_blank">PHP Extension Help</a> <?php // ToDo UI: missing url ?> + <a href="http://devdocs.magento.com/guides/v1.0/install-gde/system-requirements.html" target="_blank">PHP Extension Help</a> </div> <span class="readiness-check-icon icon-failed-round"></span> @@ -188,9 +188,7 @@ <p> The best way to resolve this is to install the correct missing extensions. The exact fix depends on our server, your host, and other system variables. <br> - Our - <a href="#">PHP Extension Help</a> <?php // ToDo UI: missing url ?> - can get you started. + Our <a href="http://devdocs.magento.com/guides/v1.0/install-gde/system-requirements.html" target="_blank">PHP Extension Help</a> can get you started. </p> <p> If you need more help, please call your hosting provider. diff --git a/setup/view/styles/components/_navigation-bar.less b/setup/view/styles/components/_navigation-bar.less index 483c4d3d1681e3e4dc1f2dcb29faabecbcb06592..ce0bf08437d2304946ab1be0c799b88c39746521 100644 --- a/setup/view/styles/components/_navigation-bar.less +++ b/setup/view/styles/components/_navigation-bar.less @@ -54,6 +54,10 @@ float: right; margin-left: .5rem; margin-right: .5rem; + .btn { + padding-left: .5rem; + padding-right: .5rem; + } } } diff --git a/setup/view/styles/lib/_buttons.less b/setup/view/styles/lib/_buttons.less index 42ef9ca8bd5ff0ce93aff0c47f168a3bdc95fa44..734145bddc7431d55a5fce0b6fed2f2977135ba9 100644 --- a/setup/view/styles/lib/_buttons.less +++ b/setup/view/styles/lib/_buttons.less @@ -48,7 +48,7 @@ display: inline-block; font-size: @btn__base__font-size; font-weight: @font-weight__semibold; - padding: @btn__base__padding-top .5em; + padding: @btn__base__padding-top .9em; text-align: center; &:hover { background-color: @btn__base__hover__background-color; diff --git a/setup/view/styles/pages/_customize-your-store.less b/setup/view/styles/pages/_customize-your-store.less index 6ce32711934faeaa0332ce90c39092cda221f6a9..10294499329485d4aa145120ee961bd83fe60b25 100644 --- a/setup/view/styles/pages/_customize-your-store.less +++ b/setup/view/styles/pages/_customize-your-store.less @@ -31,4 +31,9 @@ } } } + .customize-database-clean { + p { + margin-top: @indent__m; + } + } } diff --git a/setup/view/styles/pages/_install.less b/setup/view/styles/pages/_install.less index 91ec20435e1f27fef1bf9cb9e9c1ea34ace0deac..127644e615ff4014938af0775f3df72cdeb6b213 100644 --- a/setup/view/styles/pages/_install.less +++ b/setup/view/styles/pages/_install.less @@ -55,3 +55,10 @@ top: .15em; } } + +.install-database-clean { + margin-top: @indent__xl; + .btn { + margin-right: @indent__s; + } +}