diff --git a/CHANGELOG.md b/CHANGELOG.md index 74d8042f568dc..bd296367839e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,81 @@ +2.0.0.0-dev84 +============= +* Fixed bugs: + * Fixed an issue where an invalidly filled option did not become in focus after saving attempt on the Create New Order page in the backend + * Fixed an issue with the default configuration not being applied properly in the CAPTCHA configuration section + * Fixed an issue with optional State/Province fields on the Create New Order page being marked as required + * Fixed an issue with incorrect Customer model usage on session in community modules + * Fixed an issue where cache was not invalidated after applying catalog price rule + * Fixed an issue where an admin with custom permissions could not create Shopping Cart Price Rule/Catalog Price Rule + * Fixed an issue with REST request and response format being inconsistent + * Fixed an issue where there was an error on a bundle product page if bundle items contained an out of stock product + * Fixed a JS issue which appeared when adding associated products for a grouped product + * Fixed an issue where layered navigation was absent on the Advanced Search results page + * Fixed an issue where the leading "0" in numbers were truncated when exporting using Excel XML + * Fixed the price type attribute filter in Layered Navigation + * Fixed an issue with a fatal error in \Magento\Framework\ArchiveTest when bz2 extension was not installed + * Fixed an issue where an admin could search product by attributes set on the Store View level (except default store view) + * Fixed an issue where extra spaces in search values were not ignored during search and thus wrong search results were given +* GitHub requests: + * [#542] Fix ImportExport bug which occurs while importing multiple rows per entity + * [#544] Performance tests not working +* Framework improvements: + * Covered the following Magento application components with unit tests: + * `Customer/Model/Address.php` + * `Customer/Model/Address/AbstractAddress.php ` + * `Customer/Model/Address/Converter.php` + * `Customer/Model/Customer.php` + * `Customer/Model/Customer/Attribute/Backend/Billing.php` + * `Customer/Model/Customer/Attribute/Backend/Shipping.php` + * `Customer/Model/Customer/Attribute/Backend/Store.php ` + * `Customer/Model/Customer/Attribute/Backend/Website.php ` + * `Customer/Model/Customer/Attribute/Backend/PasswordTest.php` + * `Customer/Helper/Address.php` + * `Customer/Helper/View.php` + * `Customer/Service/V1/CustomerAccountService.php` + * Covered Magento lib with unit tests: + * `lib/internal/Magento/Framework/Filter/*` + * `lib/internal/Magento/Framework/Model/Resource/Db/AbstractDb.php` + * `lib/internal/Magento/Framework/Model/Resource/Db/Collection/AbstractCollection.php` + * `lib/internal/Magento/Framework/File/Uploader.php` + * `lib/internal/Magento/Framework/File/Csv.php` + * `lib/internal/Magento/Framework/Less/File/Collector/Aggregated.php` + * `lib/internal/Magento/Framework/Less/File/Collector/Library.php` + * `lib/internal/Magento/Framework/Locale/Config.php` + * `lib/internal/Magento/Framework/Locale/Currency.php` + * `lib/internal/Magento/Framework/App/Config/Element.php` + * `lib/internal/Magento/Framework/App/Config/Value.php` + * `lib/internal/Magento/Framework/App/DefaultPath/DefaultPath.php` + * `lib/internal/Magento/Framework/App/EntryPoint/EntryPoint.php` + * `lib/internal/Magento/Framework/App/Helper/AbstractHelper.php` + * `lib/internal/Magento/Framework/App/Resource/ConnectionFactory.php` + * `lib/internal/Magento/Framework/App/Route/Config.php` + * Implemented the ability for a mobile client to get a partial response + * Added authentication support for mobile + * Refactored the Oauth lib exception not to reference module classes + * Moved the authorization services according to the new directory format: was \Magento\Authz\Service\AuthorizationV1Interface, became \Magento\Authz\Service\V1\AuthorizationInterface + * Moved the integration services according to the new directory format: + * Was \Magento\Integration\Service\IntegrationV1, became \Magento\Integration\Service\V1\Integration + * Was \Magento\Integration\Service\OauthV1, became \Magento\Integration\Service\V1\Oauth + * Improved security of the integration registration + * Introduced language packages with ability to inherit dictionaries +* Improved modularity of ImportExport +* Created Service API for Magento_Catalog module: + * Implemented Product Attribute Media API + * Implemented Product Group Price API + * Implemented Product Attribute Write API + * Implemented Product Attribute Options Read and Write API +* Created Service for the Magento Tax module: + * Implemented Tax Rule Service + * Implemented Tax Rate Service + * Implemented Tax Calculation Data Objects + * Implemented Tax Calculation Builders + * Implemented Tax Calculation Service +* Covered the part of the Catalog Module with unit tests +* Added PayPall Bill Me Later button +* Streamlined checkout experience +* Improved order review page for PayPal Express Checkout + 2.0.0.0-dev83 ============= * Created the Service API for the Magento_Catalog Module: @@ -221,7 +299,7 @@ * Fixed price inconsistencies between catalog and shopping cart * Added support for maintaining consistent price including tax for customers with different tax rates * Added support for applying tax rules with different priorities to subtotal only - + * Fixed bugs: * Removed the extra '%' sign in the error\notice message on Gift Card Accounts page on the backend * Fixed an issue with image uploading functionality in the Catalog configuration diff --git a/app/code/Magento/AdminNotification/etc/module.xml b/app/code/Magento/AdminNotification/etc/module.xml index 2c770837bb583..e767d17381c06 100644 --- a/app/code/Magento/AdminNotification/etc/module.xml +++ b/app/code/Magento/AdminNotification/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Authorizenet/etc/module.xml b/app/code/Magento/Authorizenet/etc/module.xml index 715f39adf7555..4b5c4d3a0a340 100644 --- a/app/code/Magento/Authorizenet/etc/module.xml +++ b/app/code/Magento/Authorizenet/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Authz/Service/AuthorizationV1.php b/app/code/Magento/Authz/Service/AuthorizationV1.php index 54e3214e36049..f8844e9bcf017 100644 --- a/app/code/Magento/Authz/Service/AuthorizationV1.php +++ b/app/code/Magento/Authz/Service/AuthorizationV1.php @@ -23,18 +23,18 @@ */ namespace Magento\Authz\Service; -use Magento\Framework\Acl\Builder as AclBuilder; -use Magento\Framework\Acl; use Magento\Authz\Model\UserIdentifier; +use Magento\Framework\Acl; +use Magento\Framework\Acl\Builder as AclBuilder; +use Magento\Framework\Acl\RootResource as RootAclResource; use Magento\Framework\Logger; -use Magento\Webapi\ServiceException as ServiceException; -use Magento\Webapi\ServiceResourceNotFoundException; use Magento\User\Model\Resource\Role\CollectionFactory as RoleCollectionFactory; use Magento\User\Model\Resource\Rules\CollectionFactory as RulesCollectionFactory; use Magento\User\Model\Role; use Magento\User\Model\RoleFactory; use Magento\User\Model\RulesFactory; -use Magento\Framework\Acl\RootResource as RootAclResource; +use Magento\Webapi\ServiceException as ServiceException; +use Magento\Webapi\ServiceResourceNotFoundException; /** * Authorization service. @@ -44,6 +44,9 @@ */ class AuthorizationV1 implements AuthorizationV1Interface { + const PERMISSION_ANONYMOUS = 'anonymous'; + const PERMISSION_SELF = 'self'; + /** * @var AclBuilder */ @@ -121,29 +124,12 @@ public function __construct( */ public function isAllowed($resources, UserIdentifier $userIdentifier = null) { - $resources = is_array($resources) ? $resources : array($resources); + $resources = is_array($resources) ? $resources : [$resources]; $userIdentifier = $userIdentifier ? $userIdentifier : $this->_userIdentifier; - try { - $role = $this->_getUserRole($userIdentifier); - if (!$role) { - throw new ServiceResourceNotFoundException( - __( - 'Role for user with ID "%1" and user type "%2" cannot be found.', - $userIdentifier->getUserId(), - $userIdentifier->getUserType() - ) - ); - } - foreach ($resources as $resource) { - if (!$this->_aclBuilder->getAcl()->isAllowed($role->getId(), $resource)) { - return false; - } - } + if ($this->_isAnonymousOrSelfAllowed($resources, $userIdentifier)) { return true; - } catch (\Exception $e) { - $this->_logger->logException($e); - return false; } + return $this->_isUserWithRoleAllowed($resources, $userIdentifier); } /** @@ -180,7 +166,12 @@ public function grantAllPermissions(UserIdentifier $userIdentifier) */ public function getAllowedResources(UserIdentifier $userIdentifier) { - $allowedResources = array(); + if ($userIdentifier->getUserType() == UserIdentifier::USER_TYPE_GUEST) { + return [self::PERMISSION_ANONYMOUS]; + } elseif ($userIdentifier->getUserType() == UserIdentifier::USER_TYPE_CUSTOMER) { + return [self::PERMISSION_SELF]; + } + $allowedResources = []; try { $role = $this->_getUserRole($userIdentifier); if (!$role) { @@ -234,6 +225,9 @@ public function removePermissions(UserIdentifier $userIdentifier) protected function _createRole($userIdentifier) { $userType = $userIdentifier->getUserType(); + if (!$this->_canRoleBeCreatedForUserType($userType)) { + throw new \LogicException("The role with user type '{$userType}' cannot be created"); + } $userId = $userIdentifier->getUserId(); switch ($userType) { case UserIdentifier::USER_TYPE_INTEGRATION: @@ -246,17 +240,12 @@ protected function _createRole($userIdentifier) throw new \LogicException("Unknown user type: '{$userType}'."); } $role = $this->_roleFactory->create(); - $role->setRoleName( - $roleName - )->setUserType( - $userType - )->setUserId( - $userId - )->setRoleType( - $roleType - )->setParentId( - $parentId - )->save(); + $role->setRoleName($roleName) + ->setUserType($userType) + ->setUserId($userId) + ->setRoleType($roleType) + ->setParentId($parentId) + ->save(); return $role; } @@ -270,6 +259,9 @@ protected function _createRole($userIdentifier) protected function _deleteRole($userIdentifier) { $userType = $userIdentifier->getUserType(); + if (!$this->_canRoleBeCreatedForUserType($userType)) { + throw new \LogicException("The role with user type '{$userType}' cannot be created or deleted."); + } $userId = $userIdentifier->getUserId(); switch ($userType) { case UserIdentifier::USER_TYPE_INTEGRATION: @@ -287,13 +279,19 @@ protected function _deleteRole($userIdentifier) * * @param UserIdentifier $userIdentifier * @return Role|false Return false in case when no role associated with provided user was found. + * @throws \LogicException */ protected function _getUserRole($userIdentifier) { + if (!$this->_canRoleBeCreatedForUserType($userIdentifier)) { + throw new \LogicException( + "The role with user type '{$userIdentifier->getUserType()}' does not exist and cannot be created" + ); + } $roleCollection = $this->_roleCollectionFactory->create(); $userType = $userIdentifier->getUserType(); - $userId = $userIdentifier->getUserId(); /** @var Role $role */ + $userId = $userIdentifier->getUserId(); $role = $roleCollection->setUserFilter($userId, $userType)->getFirstItem(); return $role->getId() ? $role : false; } @@ -304,6 +302,7 @@ protected function _getUserRole($userIdentifier) * @param Role $role * @param string[] $resources * @return void + * @throws \LogicException */ protected function _associateResourcesWithRole($role, array $resources) { @@ -311,4 +310,70 @@ protected function _associateResourcesWithRole($role, array $resources) $rules = $this->_rulesFactory->create(); $rules->setRoleId($role->getId())->setResources($resources)->saveRel(); } + + /** + * Check if there role can be associated with user having provided user type. + * + * Roles cannot be created for guests and customers. + * + * @param string $userType + * @return bool + */ + protected function _canRoleBeCreatedForUserType($userType) + { + return ($userType != UserIdentifier::USER_TYPE_CUSTOMER) && ($userType != UserIdentifier::USER_TYPE_GUEST); + } + + /** + * Check if the user has permission to access the requested resources. + * + * @param string[] $resources + * @param UserIdentifier $userIdentifier + * @return bool + */ + protected function _isAnonymousOrSelfAllowed($resources, UserIdentifier $userIdentifier) + { + if (count($resources) == 1) { + $resource = reset($resources); + $isAnonymousAccess = ($resource == self::PERMISSION_ANONYMOUS); + $isSelfAccess = ($userIdentifier->getUserType() == UserIdentifier::USER_TYPE_CUSTOMER) + && ($resource == self::PERMISSION_SELF); + if ($isAnonymousAccess || $isSelfAccess) { + return true; + } + } + return false; + } + + /** + * Check if user who has role is allowed to access requested resources. + * + * @param string[] $resources + * @param UserIdentifier $userIdentifier + * @return bool + */ + protected function _isUserWithRoleAllowed($resources, UserIdentifier $userIdentifier) + { + try { + $role = $this->_getUserRole($userIdentifier); + if (!$role) { + throw new ServiceResourceNotFoundException( + __( + 'Role for user with ID "%1" and user type "%2" cannot be found.', + $userIdentifier->getUserId(), + $userIdentifier->getUserType() + ) + ); + } + foreach ($resources as $resource) { + if (!$this->_aclBuilder->getAcl()->isAllowed($role->getId(), $resource)) { + return false; + } + } + return true; + } catch (\Exception $e) { + $this->_logger->logException($e); + return false; + } + } } diff --git a/app/code/Magento/Authz/etc/module.xml b/app/code/Magento/Authz/etc/module.xml index ff58965b959a6..4079bb85393af 100644 --- a/app/code/Magento/Authz/etc/module.xml +++ b/app/code/Magento/Authz/etc/module.xml @@ -24,7 +24,10 @@ */ --> - + + + + diff --git a/app/code/Magento/Backend/Block/Widget/Grid.php b/app/code/Magento/Backend/Block/Widget/Grid.php index 92ab24922cf47..3cade6d445fe9 100644 --- a/app/code/Magento/Backend/Block/Widget/Grid.php +++ b/app/code/Magento/Backend/Block/Widget/Grid.php @@ -397,17 +397,6 @@ protected function _prepareCollection() return $this; } - /** - * Decode URL encoded filter value recursive callback method - * - * @param string &$value - * @return void - */ - protected function _decodeFilter(&$value) - { - $value = $this->_backendHelper->decodeFilter($value); - } - /** * Apply pagination to collection * diff --git a/app/code/Magento/Backend/Helper/Data.php b/app/code/Magento/Backend/Helper/Data.php index 2b5abe6a3c78f..d72ed1653b27b 100644 --- a/app/code/Magento/Backend/Helper/Data.php +++ b/app/code/Magento/Backend/Helper/Data.php @@ -177,21 +177,22 @@ public function prepareFilterString($filterString) $data = array(); $filterString = base64_decode($filterString); parse_str($filterString, $data); - array_walk_recursive($data, array($this, 'decodeFilter')); + array_walk_recursive( + $data, + // @codingStandardsIgnoreStart + /** + * Decodes URL-encoded string and trims whitespaces from the beginning and end of a string + * + * @param string $value + */ + // @codingStandardsIgnoreEnd + function (&$value) { + $value = trim(rawurldecode($value)); + } + ); return $data; } - /** - * Decode URL encoded filter value recursive callback method - * - * @param string &$value - * @return void - */ - public function decodeFilter(&$value) - { - $value = rawurldecode($value); - } - /** * Generate unique token for reset password confirmation link * diff --git a/app/code/Magento/Backend/Model/Search/Catalog.php b/app/code/Magento/Backend/Model/Search/Catalog.php index 005eeaf01d467..2a63c068e96f7 100644 --- a/app/code/Magento/Backend/Model/Search/Catalog.php +++ b/app/code/Magento/Backend/Model/Search/Catalog.php @@ -81,7 +81,7 @@ public function load() 'name' )->addAttributeToSelect( 'description' - )->addSearchFilter( + )->addBackendSearchFilter( $this->getQuery() )->setCurPage( $this->getStart() diff --git a/app/code/Magento/Backend/etc/module.xml b/app/code/Magento/Backend/etc/module.xml index 7a69975949581..101b83e07768a 100644 --- a/app/code/Magento/Backend/etc/module.xml +++ b/app/code/Magento/Backend/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Backup/etc/module.xml b/app/code/Magento/Backup/etc/module.xml index 9009e6191b1c0..20db9e5b28c9d 100644 --- a/app/code/Magento/Backup/etc/module.xml +++ b/app/code/Magento/Backup/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php index ac700c144f574..00438ad0d5db9 100644 --- a/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php +++ b/app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php @@ -303,8 +303,12 @@ protected function calculateDynamicBundleAmount($basePriceValue, $bundleProduct, public function createSelectionPriceList($option, $bundleProduct) { $priceList = []; + $selections = $option->getSelections(); + if ($selections === null) { + return $priceList; + } /* @var $selection \Magento\Bundle\Model\Selection|\Magento\Catalog\Model\Product */ - foreach ($option->getSelections() as $selection) { + foreach ($selections as $selection) { if (!$selection->isSalable()) { // @todo CatalogInventory Show out of stock Products continue; diff --git a/app/code/Magento/Bundle/etc/module.xml b/app/code/Magento/Bundle/etc/module.xml index 8c1f43a62a039..8184420b5d516 100644 --- a/app/code/Magento/Bundle/etc/module.xml +++ b/app/code/Magento/Bundle/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Captcha/etc/module.xml b/app/code/Magento/Captcha/etc/module.xml index 4bc5e602611f1..71cade06549b5 100644 --- a/app/code/Magento/Captcha/etc/module.xml +++ b/app/code/Magento/Captcha/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php index 23228c4a1cb3b..3fda0549932a3 100644 --- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php +++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Sortby.php @@ -59,23 +59,13 @@ public function __construct(\Magento\Framework\Logger $logger, \Magento\Framewor public function validate($object) { $attributeCode = $this->getAttribute()->getName(); - $postDataConfig = $object->getData('use_post_data_config'); - if ($postDataConfig) { - $isUseConfig = in_array($attributeCode, $postDataConfig); - } else { - $isUseConfig = false; - $postDataConfig = array(); - } + $postDataConfig = $object->getData('use_post_data_config') ?: array(); + $isUseConfig = in_array($attributeCode, $postDataConfig); if ($this->getAttribute()->getIsRequired()) { $attributeValue = $object->getData($attributeCode); - if ($this->getAttribute()->isValueEmpty($attributeValue)) { - if (is_array($attributeValue) && count($attributeValue) > 0) { - } else { - if (!$isUseConfig) { - return false; - } - } + if ($this->getAttribute()->isValueEmpty($attributeValue) && !$isUseConfig) { + return false; } } @@ -87,30 +77,21 @@ public function validate($object) } if ($attributeCode == 'default_sort_by') { - if ($available = $object->getData('available_sort_by')) { - if (!is_array($available)) { - $available = explode(',', $available); - } - $data = !in_array( - 'default_sort_by', - $postDataConfig - ) ? $object->getData( - $attributeCode - ) : $this->_scopeConfig->getValue( - "catalog/frontend/default_sort_by", - \Magento\Store\Model\ScopeInterface::SCOPE_STORE + $available = $object->getData('available_sort_by') ?: array(); + $available = is_array($available) ? $available : explode(',', $available); + $data = !in_array( + 'default_sort_by', + $postDataConfig + ) ? $object->getData( + $attributeCode + ) : $this->_scopeConfig->getValue( + "catalog/frontend/default_sort_by", + \Magento\Store\Model\ScopeInterface::SCOPE_STORE + ); + if (!in_array($data, $available) && !in_array('available_sort_by', $postDataConfig)) { + throw new \Magento\Framework\Model\Exception( + __('Default Product Listing Sort by does not exist in Available Product Listing Sort By.') ); - if (!in_array($data, $available)) { - throw new \Magento\Framework\Model\Exception( - __('Default Product Listing Sort by does not exist in Available Product Listing Sort By.') - ); - } - } else { - if (!in_array('available_sort_by', $postDataConfig)) { - throw new \Magento\Framework\Model\Exception( - __('Default Product Listing Sort by does not exist in Available Product Listing Sort By.') - ); - } } } diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Source/Mode.php b/app/code/Magento/Catalog/Model/Category/Attribute/Source/Mode.php index f9ed2f4463beb..feefc513de92f 100644 --- a/app/code/Magento/Catalog/Model/Category/Attribute/Source/Mode.php +++ b/app/code/Magento/Catalog/Model/Category/Attribute/Source/Mode.php @@ -32,6 +32,7 @@ class Mode extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource { /** * {@inheritdoc} + * @codeCoverageIgnore */ public function getAllOptions() { diff --git a/app/code/Magento/Catalog/Model/Config/Source/ListMode.php b/app/code/Magento/Catalog/Model/Config/Source/ListMode.php index d1ea806813d4d..b812221de11d0 100644 --- a/app/code/Magento/Catalog/Model/Config/Source/ListMode.php +++ b/app/code/Magento/Catalog/Model/Config/Source/ListMode.php @@ -27,6 +27,8 @@ class ListMode implements \Magento\Framework\Option\ArrayInterface { /** * {@inheritdoc} + * + * @codeCoverageIgnore */ public function toOptionArray() { diff --git a/app/code/Magento/Catalog/Model/Config/Source/Price/Scope.php b/app/code/Magento/Catalog/Model/Config/Source/Price/Scope.php index a16018e08e360..45965b8901100 100644 --- a/app/code/Magento/Catalog/Model/Config/Source/Price/Scope.php +++ b/app/code/Magento/Catalog/Model/Config/Source/Price/Scope.php @@ -27,6 +27,8 @@ class Scope implements \Magento\Framework\Option\ArrayInterface { /** * {@inheritdoc} + * + * @codeCoverageIgnore */ public function toOptionArray() { diff --git a/app/code/Magento/Catalog/Model/Config/Source/Price/Step.php b/app/code/Magento/Catalog/Model/Config/Source/Price/Step.php index 3ae5e66617702..7aa4dde94c53a 100644 --- a/app/code/Magento/Catalog/Model/Config/Source/Price/Step.php +++ b/app/code/Magento/Catalog/Model/Config/Source/Price/Step.php @@ -27,6 +27,8 @@ class Step implements \Magento\Framework\Option\ArrayInterface { /** * {@inheritdoc} + * + * @codeCoverageIgnore */ public function toOptionArray() { diff --git a/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php index 68fe07a697cf9..6ac0f4429ac2e 100644 --- a/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php +++ b/app/code/Magento/Catalog/Model/Config/Source/Product/Options/Price.php @@ -32,6 +32,8 @@ class Price implements \Magento\Framework\Option\ArrayInterface { /** * {@inheritdoc} + * + * @codeCoverageIgnore */ public function toOptionArray() { diff --git a/app/code/Magento/Catalog/Model/Config/Source/Product/Thumbnail.php b/app/code/Magento/Catalog/Model/Config/Source/Product/Thumbnail.php index cb4bcb7215abb..dc478debc2dff 100644 --- a/app/code/Magento/Catalog/Model/Config/Source/Product/Thumbnail.php +++ b/app/code/Magento/Catalog/Model/Config/Source/Product/Thumbnail.php @@ -35,6 +35,8 @@ class Thumbnail implements \Magento\Framework\Option\ArrayInterface /** * {@inheritdoc} + * + * @codeCoverageIgnore */ public function toOptionArray() { diff --git a/app/code/Magento/Catalog/Model/Config/Source/TimeFormat.php b/app/code/Magento/Catalog/Model/Config/Source/TimeFormat.php index f3a188164cfde..b467ba85b327e 100644 --- a/app/code/Magento/Catalog/Model/Config/Source/TimeFormat.php +++ b/app/code/Magento/Catalog/Model/Config/Source/TimeFormat.php @@ -27,6 +27,8 @@ class TimeFormat implements \Magento\Framework\Option\ArrayInterface { /** * {@inheritdoc} + * + * @codeCoverageIgnore */ public function toOptionArray() { diff --git a/app/code/Magento/Catalog/Model/Config/Source/Watermark/Position.php b/app/code/Magento/Catalog/Model/Config/Source/Watermark/Position.php index 9ed316cbf9729..b9b5ccd8e1baa 100644 --- a/app/code/Magento/Catalog/Model/Config/Source/Watermark/Position.php +++ b/app/code/Magento/Catalog/Model/Config/Source/Watermark/Position.php @@ -35,6 +35,7 @@ class Position implements \Magento\Framework\Option\ArrayInterface /** * Get available options * + * @codeCoverageIgnore * @return array */ public function toOptionArray() diff --git a/app/code/Magento/Catalog/Model/Layer/Filter/Decimal.php b/app/code/Magento/Catalog/Model/Layer/Filter/Decimal.php index cc37f0b9642f5..bc434112ad16a 100644 --- a/app/code/Magento/Catalog/Model/Layer/Filter/Decimal.php +++ b/app/code/Magento/Catalog/Model/Layer/Filter/Decimal.php @@ -58,8 +58,8 @@ public function __construct( array $data = array() ) { $this->_resource = $filterDecimalFactory->create(); - parent::__construct($filterItemFactory, $storeManager, $layer, $data); $this->_requestVar = 'decimal'; + parent::__construct($filterItemFactory, $storeManager, $layer, $data); } /** @@ -86,7 +86,7 @@ public function apply(\Zend_Controller_Request_Abstract $request) * Filter must be string: $index, $range */ $filter = $request->getParam($this->getRequestVar()); - if (!$filter) { + if (!$filter || is_array($filter)) { return $this; } diff --git a/app/code/Magento/Catalog/Model/Layer/Filter/Price.php b/app/code/Magento/Catalog/Model/Layer/Filter/Price.php index 460891d3f66d0..78adcb1eb053c 100644 --- a/app/code/Magento/Catalog/Model/Layer/Filter/Price.php +++ b/app/code/Magento/Catalog/Model/Layer/Filter/Price.php @@ -417,7 +417,7 @@ public function apply(\Zend_Controller_Request_Abstract $request) * Filter must be string: $fromPrice-$toPrice */ $filter = $request->getParam($this->getRequestVar()); - if (!$filter) { + if (!$filter || is_array($filter)) { return $this; } diff --git a/app/code/Magento/Catalog/Model/Layer/State.php b/app/code/Magento/Catalog/Model/Layer/State.php index 13cdccbb8cc91..374fc4969b1a9 100644 --- a/app/code/Magento/Catalog/Model/Layer/State.php +++ b/app/code/Magento/Catalog/Model/Layer/State.php @@ -23,17 +23,21 @@ */ namespace Magento\Catalog\Model\Layer; +use Magento\Catalog\Model\Layer\Filter\Item; +use Magento\Framework\Model\Exception; +use Magento\Framework\Object; + /** * Layered navigation state model * * @author Magento Core Team */ -class State extends \Magento\Framework\Object +class State extends Object { /** * Add filter item to layer state * - * @param \Magento\Catalog\Model\Layer\Filter\Item $filter + * @param Item $filter * @return $this */ public function addFilter($filter) @@ -47,14 +51,14 @@ public function addFilter($filter) /** * Set layer state filter items * - * @param array $filters + * @param Item[] $filters * @return $this - * @throws \Magento\Framework\Model\Exception + * @throws Exception */ public function setFilters($filters) { if (!is_array($filters)) { - throw new \Magento\Framework\Model\Exception(__('The filters must be an array.')); + throw new Exception(__('The filters must be an array.')); } $this->setData('filters', $filters); return $this; @@ -63,7 +67,7 @@ public function setFilters($filters) /** * Get applied to layer filter items * - * @return array + * @return Item[] */ public function getFilters() { diff --git a/app/code/Magento/Catalog/Model/Product.php b/app/code/Magento/Catalog/Model/Product.php index ff187dc790845..99317d82065d7 100644 --- a/app/code/Magento/Catalog/Model/Product.php +++ b/app/code/Magento/Catalog/Model/Product.php @@ -622,7 +622,7 @@ public function getStoreIds() * * @param int $groupId Retrieve attributes of the specified group * @param bool $skipSuper Not used - * @return array + * @return \Magento\Eav\Model\Entity\Attribute\AbstractAttribute[] */ public function getAttributes($groupId = null, $skipSuper = false) { diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php index 3f007f47d416f..5c0b87889784b 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Media.php @@ -172,9 +172,7 @@ public function validate($object) if ($this->getAttribute()->getIsRequired()) { $value = $object->getData($this->getAttribute()->getAttributeCode()); if ($this->getAttribute()->isValueEmpty($value)) { - if (!(is_array($value) && count($value) > 0)) { - return false; - } + return false; } } if ($this->getAttribute()->getIsUnique()) { diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php b/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php index bf512d3b159f8..d90a58cebf5ec 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Frontend/Image.php @@ -53,19 +53,17 @@ public function __construct(\Magento\Store\Model\StoreManagerInterface $storeMan * Returns url to product image * * @param \Magento\Catalog\Model\Product $product + * * @return string|false */ public function getUrl($product) { $image = $product->getData($this->getAttribute()->getAttributeCode()); - if ($image) { - $url = $this->_storeManager->getStore( - $product->getStore() - )->getBaseUrl( - \Magento\Framework\UrlInterface::URL_TYPE_MEDIA - ) . 'catalog/product/' . $image; - } else { - $url = false; + $url = false; + if (!empty($image)) { + $url = $this->_storeManager->getStore($product->getStore()) + ->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) + . 'catalog/product/' . $image; } return $url; } diff --git a/app/code/Magento/Catalog/Model/Product/Condition.php b/app/code/Magento/Catalog/Model/Product/Condition.php index 6339d7a3f5562..16e7fd353f3b6 100644 --- a/app/code/Magento/Catalog/Model/Product/Condition.php +++ b/app/code/Magento/Catalog/Model/Product/Condition.php @@ -23,14 +23,21 @@ */ namespace Magento\Catalog\Model\Product; +use Magento\Eav\Model\Entity\Collection\AbstractCollection; use Magento\Framework\DB\Adapter\AdapterInterface; use Magento\Framework\DB\Select; -use Magento\Eav\Model\Entity\Collection\AbstractCollection; +/** + * @method string getPkFieldName() + * @method Condition setPkFieldName(string $fieldName) + * @method string|array getTable() + * @method Condition setTable($table) + */ class Condition extends \Magento\Framework\Object implements \Magento\Catalog\Model\Product\Condition\ConditionInterface { /** * @param AbstractCollection $collection + * * @return $this */ public function applyToCollection($collection) @@ -47,6 +54,7 @@ public function applyToCollection($collection) /** * @param AdapterInterface $dbAdapter + * * @return Select|string */ public function getIdsSelect($dbAdapter) diff --git a/app/code/Magento/Catalog/Model/Product/Option.php b/app/code/Magento/Catalog/Model/Product/Option.php index ad7163ce18679..d6e9f7754e164 100644 --- a/app/code/Magento/Catalog/Model/Product/Option.php +++ b/app/code/Magento/Catalog/Model/Product/Option.php @@ -515,27 +515,6 @@ public function getOptionValuesByOptionId($optionIds, $store_id) return $collection; } - /** - * Prepare array of options for duplicate - * - * @return array - */ - public function prepareOptionForDuplicate() - { - $this->setProductId(null); - $this->setOptionId(null); - $newOption = $this->__toArray(); - if ($_values = $this->getValues()) { - $newValuesArray = array(); - foreach ($_values as $_value) { - $newValuesArray[] = $_value->prepareValueForDuplicate(); - } - $newOption['values'] = $newValuesArray; - } - - return $newOption; - } - /** * Duplicate options for product * diff --git a/app/code/Magento/Catalog/Model/Product/Option/Value.php b/app/code/Magento/Catalog/Model/Product/Option/Value.php index d2e3d4b9a9ba0..dcc8d625a4ffa 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Value.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Value.php @@ -294,19 +294,6 @@ public function deleteValues($option_type_id) return $this; } - /** - * Prepare array of option values for duplicate - * - * @return array - */ - public function prepareValueForDuplicate() - { - $this->setOptionId(null); - $this->setOptionTypeId(null); - - return $this->__toArray(); - } - /** * Duplicate product options value * diff --git a/app/code/Magento/Catalog/Model/Product/Type.php b/app/code/Magento/Catalog/Model/Product/Type.php index a4f650371dbba..7f7e1f776e20b 100644 --- a/app/code/Magento/Catalog/Model/Product/Type.php +++ b/app/code/Magento/Catalog/Model/Product/Type.php @@ -219,11 +219,8 @@ public function getAllOption() */ public function getAllOptions() { - $res = array(); - $res[] = array('value' => '', 'label' => ''); - foreach ($this->getOptionArray() as $index => $value) { - $res[] = array('value' => $index, 'label' => $value); - } + $res = $this->getOptions(); + array_unshift($res, ['value' => '', 'label' => '']); return $res; } @@ -234,9 +231,9 @@ public function getAllOptions() */ public function getOptions() { - $res = array(); + $res = []; foreach ($this->getOptionArray() as $index => $value) { - $res[] = array('value' => $index, 'label' => $value); + $res[] = ['value' => $index, 'label' => $value]; } return $res; } diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php index 902ef5373583d..eaab2830dd41c 100644 --- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php +++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php @@ -263,7 +263,7 @@ public function getParentIdsByChild($childId) * Get array of product set attributes * * @param \Magento\Catalog\Model\Product $product - * @return array + * @return \Magento\Eav\Model\Entity\Attribute\AbstractAttribute[] */ public function getSetAttributes($product) { @@ -297,7 +297,7 @@ public function attributesCompare($attributeOne, $attributeTwo) * Retrieve product type attributes * * @param \Magento\Catalog\Model\Product $product - * @return array + * @return \Magento\Eav\Model\Entity\Attribute\AbstractAttribute[] */ public function getEditableAttributes($product) { diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Attribute.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Attribute.php index 33c971db73b9b..924bd369d2a86 100644 --- a/app/code/Magento/Catalog/Service/V1/Data/Eav/Attribute.php +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Attribute.php @@ -33,6 +33,7 @@ class Attribute extends AbstractObject const IS_USER_DEFINED = 'is_user_defined'; const LABEL = 'frontend_label'; const DEFAULT_VALUE = 'default_value'; + const FRONTEND_INPUT = 'frontend_input'; /** * Get attribute ID @@ -95,4 +96,14 @@ public function getIsUserDefined() { return $this->_get(self::IS_USER_DEFINED); } + + /** + * Get frontend input type + * + * @return string + */ + public function getFrontendInput() + { + return $this->_get(self::FRONTEND_INPUT); + } } diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeBuilder.php index 55cbfbabcc41a..9729c8b1464fc 100644 --- a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeBuilder.php +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeBuilder.php @@ -92,4 +92,15 @@ public function setIsUserDefined($isUserDefined) { return $this->_set(Attribute::IS_USER_DEFINED, $isUserDefined); } + + /** + * Set frontend input type + * + * @param string $type + * @return $this + */ + public function setFrontendInput($type) + { + return $this->_set(Attribute::FRONTEND_INPUT, $type); + } } diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadata.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadata.php index 5606c3f7b048b..2adec8b2921e6 100644 --- a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadata.php +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadata.php @@ -23,10 +23,12 @@ */ namespace Magento\Catalog\Service\V1\Data\Eav; +use \Magento\Framework\Service\Data\Eav\AbstractObject; + /** * Class AttributeMetadata */ -class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject +class AttributeMetadata extends AbstractObject { /**#@+ * Constants used as keys into $_data @@ -41,6 +43,8 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject const OPTIONS = 'options'; + const SYSTEM = 'system'; + const VISIBLE = 'visible'; const REQUIRED = 'required'; @@ -53,6 +57,10 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject const BACKEND_TYPE = 'backend_type'; + const SOURCE_MODEL = 'source_model'; + + const BACKEND_MODEL = 'backend_model'; + const DEFAULT_VALUE = 'default_value'; const UNIQUE = 'unique'; @@ -94,7 +102,7 @@ class AttributeMetadata extends \Magento\Framework\Service\Data\AbstractObject /** * Retrieve id of the attribute. * - * @return string + * @return string|null */ public function getAttributeId() { @@ -104,17 +112,27 @@ public function getAttributeId() /** * Retrieve code of the attribute. * - * @return string + * @return string|null */ public function getAttributeCode() { return $this->_get(self::ATTRIBUTE_CODE); } + /** + * Retrieve is system attribute flag + * + * @return bool|null + */ + public function isSystem() + { + return $this->_get(self::SYSTEM); + } + /** * Frontend HTML for input element. * - * @return string + * @return string|null */ public function getFrontendInput() { @@ -124,7 +142,7 @@ public function getFrontendInput() /** * Retrieve validation rules. * - * @return \Magento\Catalog\Service\V1\Data\Eav\ValidationRule[] + * @return \Magento\Catalog\Service\V1\Data\Eav\ValidationRule[]|null */ public function getValidationRules() { @@ -134,7 +152,7 @@ public function getValidationRules() /** * Whether attribute is visible on frontend. * - * @return bool + * @return bool|null */ public function isVisible() { @@ -144,7 +162,7 @@ public function isVisible() /** * Whether attribute is required. * - * @return bool + * @return bool|null */ public function isRequired() { @@ -154,7 +172,7 @@ public function isRequired() /** * Return options of the attribute (key => value pairs for select) * - * @return \Magento\Catalog\Service\V1\Data\Eav\Option[] + * @return \Magento\Catalog\Service\V1\Data\Eav\Option[]|null */ public function getOptions() { @@ -164,7 +182,7 @@ public function getOptions() /** * Whether current attribute has been defined by a user. * - * @return bool + * @return bool|null */ public function isUserDefined() { @@ -174,7 +192,7 @@ public function isUserDefined() /** * Get label which supposed to be displayed on frontend. * - * @return string + * @return \Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel[]|null */ public function getFrontendLabel() { @@ -184,7 +202,7 @@ public function getFrontendLabel() /** * Get the note attribute for the element. * - * @return string + * @return string|null */ public function getNote() { @@ -194,17 +212,37 @@ public function getNote() /** * Get backend type. * - * @return string + * @return string|null */ public function getBackendType() { return $this->_get(self::BACKEND_TYPE); } + /** + * Get backend model + * + * @return string|null + */ + public function getBackendModel() + { + return $this->_get(self::BACKEND_MODEL); + } + + /** + * Get source model + * + * @return string|null + */ + public function getSourceModel() + { + return $this->_get(self::SOURCE_MODEL); + } + /** * Get default value for the element. * - * @return string + * @return string|null */ public function getDefaultValue() { @@ -214,7 +252,7 @@ public function getDefaultValue() /** * Whether this is a unique attribute * - * @return string + * @return string|null */ public function isUnique() { @@ -233,7 +271,7 @@ public function isUnique() * - 'bundle', * - 'downloadable' * - * @return string[] + * @return string[]|null */ public function getApplyTo() { @@ -243,7 +281,7 @@ public function getApplyTo() /** * Whether the attribute can be used for configurable products * - * @return string + * @return string|null */ public function isConfigurable() { @@ -253,7 +291,7 @@ public function isConfigurable() /** * Whether the attribute can be used in Quick Search * - * @return string + * @return string|null */ public function isSearchable() { @@ -263,7 +301,7 @@ public function isSearchable() /** * Whether the attribute can be used in Advanced Search * - * @return string + * @return string|null */ public function isVisibleInAdvancedSearch() { @@ -273,7 +311,7 @@ public function isVisibleInAdvancedSearch() /** * Whether the attribute can be compared on the frontend * - * @return string + * @return string|null */ public function isComparable() { @@ -283,7 +321,7 @@ public function isComparable() /** * Whether the attribute can be used for promo rules * - * @return string + * @return string|null */ public function isUsedForPromoRules() { @@ -293,7 +331,7 @@ public function isUsedForPromoRules() /** * Whether the attribute is visible on the frontend * - * @return string + * @return string|null */ public function isVisibleOnFront() { @@ -303,7 +341,7 @@ public function isVisibleOnFront() /** * Whether the attribute can be used in product listing * - * @return string + * @return string|null */ public function getUsedInProductListing() { @@ -313,7 +351,7 @@ public function getUsedInProductListing() /** * Retrieve attribute scope * - * @return string + * @return string|null */ public function getScope() { @@ -323,7 +361,7 @@ public function getScope() /** * Retrieve frontend class of attribute * - * @return string + * @return string|null */ public function getFrontendClass() { @@ -333,7 +371,7 @@ public function getFrontendClass() /** * Enable WYSIWYG flag * - * @return bool + * @return bool|null */ public function isWysiwygEnabled() { @@ -343,7 +381,7 @@ public function isWysiwygEnabled() /** * Whether the HTML tags are allowed on the frontend * - * @return bool + * @return bool|null */ public function isHtmlAllowedOnFront() { @@ -353,7 +391,7 @@ public function isHtmlAllowedOnFront() /** * Whether it is used for sorting in product listing * - * @return bool + * @return bool|null * @SuppressWarnings(PHPMD.BooleanGetMethodName) */ public function getUsedForSortBy() @@ -364,7 +402,7 @@ public function getUsedForSortBy() /** * Whether it used in layered navigation * - * @return bool + * @return bool|null */ public function isFilterable() { @@ -374,7 +412,7 @@ public function isFilterable() /** * Whether it is used in search results layered navigation * - * @return bool + * @return bool|null */ public function isFilterableInSearch() { @@ -384,7 +422,7 @@ public function isFilterableInSearch() /** * Get position * - * @return int + * @return int|null */ public function getPosition() { diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilder.php index 3e996fa2ad3ac..7da8259f70e45 100644 --- a/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilder.php +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/AttributeMetadataBuilder.php @@ -23,8 +23,7 @@ */ namespace Magento\Catalog\Service\V1\Data\Eav; -use Magento\Framework\Service\Data\AbstractObjectBuilder; -use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; +use Magento\Framework\Service\Data\Eav\AbstractObjectBuilder; /** * Class AttributeMetadataBuilder @@ -45,23 +44,34 @@ class AttributeMetadataBuilder extends AbstractObjectBuilder */ protected $validationRuleBuilder; + /** + * @var Product\Attribute\FrontendLabelBuilder + */ + protected $frontendLabelBuilder; + /** * Initializes builder. * + * @param \Magento\Framework\Service\Data\ObjectFactory $objectFactory + * @param \Magento\Framework\Service\Data\Eav\AttributeValueBuilder $valueBuilder * @param OptionBuilder $optionBuilder * @param ValidationRuleBuilder $validationRuleBuilder - * @param \Magento\Framework\Service\Data\ObjectFactory $objectFactory + * @param Product\Attribute\FrontendLabelBuilder $frontendLabelBuilder */ public function __construct( \Magento\Framework\Service\Data\ObjectFactory $objectFactory, + \Magento\Framework\Service\Data\Eav\AttributeValueBuilder $valueBuilder, OptionBuilder $optionBuilder, - ValidationRuleBuilder $validationRuleBuilder + ValidationRuleBuilder $validationRuleBuilder, + Product\Attribute\FrontendLabelBuilder $frontendLabelBuilder ) { - parent::__construct($objectFactory); + parent::__construct($objectFactory, $valueBuilder); $this->optionBuilder = $optionBuilder; $this->validationRuleBuilder = $validationRuleBuilder; + $this->frontendLabelBuilder = $frontendLabelBuilder; $this->_data[AttributeMetadata::OPTIONS] = array(); $this->_data[AttributeMetadata::VALIDATION_RULES] = array(); + $this->_data[AttributeMetadata::FRONTEND_LABEL] = array(); } /** @@ -86,6 +96,17 @@ public function setAttributeCode($attributeCode) return $this->_set(AttributeMetadata::ATTRIBUTE_CODE, $attributeCode); } + /** + * Set whether the attribute system or not + * + * @param bool $isSystem + * @return $this + */ + public function setSystem($isSystem) + { + return $this->_set(AttributeMetadata::SYSTEM, $isSystem); + } + /** * Set front end input * @@ -155,7 +176,7 @@ public function setUserDefined($isUserDefined) /** * Set front end label * - * @param string $frontendLabel + * @param \Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel[] $frontendLabel * @return $this */ public function setFrontendLabel($frontendLabel) @@ -183,6 +204,28 @@ public function setBackendType($backendType) return $this->_set(AttributeMetadata::BACKEND_TYPE, $backendType); } + /** + * Set backend model + * + * @param string $value + * @return $this + */ + public function setBackendModel($value) + { + return $this->_set(AttributeMetadata::BACKEND_MODEL, $value); + } + + /** + * Set source model + * + * @param string $value + * @return $this + */ + public function setSourceModel($value) + { + return $this->_set(AttributeMetadata::SOURCE_MODEL, $value); + } + /** * Set default value for the element * @@ -411,6 +454,7 @@ public function setFrontendClass($frontendClass) /** * {@inheritdoc} + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function _setDataValues(array $data) { @@ -432,6 +476,15 @@ protected function _setDataValues(array $data) $data[AttributeMetadata::VALIDATION_RULES] = $validationRules; } + // fill frontend labels + if (isset($data[AttributeMetadata::FRONTEND_LABEL]) && is_array($data[AttributeMetadata::FRONTEND_LABEL])) { + $frontendLabel = []; + foreach ($data[AttributeMetadata::FRONTEND_LABEL] as $key => $value) { + $frontendLabel[$key] = $this->frontendLabelBuilder->populateWithArray($value)->create(); + } + $data[AttributeMetadata::FRONTEND_LABEL] = $frontendLabel; + } + if (array_key_exists(AttributeMetadata::APPLY_TO, $data)) { $data[AttributeMetadata::APPLY_TO] = $this->processApplyToValue($data[AttributeMetadata::APPLY_TO]); } diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Option.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option.php index 4bb117b3697fc..19cbe278dcd30 100644 --- a/app/code/Magento/Catalog/Service/V1/Data/Eav/Option.php +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option.php @@ -37,6 +37,12 @@ class Option extends \Magento\Framework\Service\Data\AbstractObject const VALUE = 'value'; + const ORDER = 'order'; + + const STORE_LABELS = 'store_labels'; + + const IS_DEFAULT = 'default'; + /** * Get option label * @@ -50,10 +56,40 @@ public function getLabel() /** * Get option value * - * @return string + * @return string|null */ public function getValue() { return $this->_get(self::VALUE); } + + /** + * Get option order + * + * @return int|null + */ + public function getOrder() + { + return $this->_get(self::ORDER); + } + + /** + * is default + * + * @return bool|null + */ + public function isDefault() + { + return $this->_get(self::IS_DEFAULT); + } + + /** + * Set option label for store scopes + * + * @return \Magento\Catalog\Service\V1\Data\Eav\Option\Label[]|null + */ + public function getStoreLabels() + { + return $this->_get(Option::STORE_LABELS); + } } diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/Label.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/Label.php new file mode 100644 index 0000000000000..44b449ff67346 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/Label.php @@ -0,0 +1,58 @@ +_get(self::LABEL); + } + + /** + * Get store id + * + * @return int + */ + public function getStoreId() + { + return $this->_get(self::STORE_ID); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/LabelBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/LabelBuilder.php new file mode 100644 index 0000000000000..67b10003e1c3a --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Option/LabelBuilder.php @@ -0,0 +1,52 @@ +_set(Label::LABEL, $label); + } + + /** + * Set store id + * + * @param int $value + * @return $this + */ + public function setStoreId($value) + { + return $this->_set(Label::STORE_ID, $value); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/OptionBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/OptionBuilder.php index 893e33265e97e..cd7d935cf10ac 100644 --- a/app/code/Magento/Catalog/Service/V1/Data/Eav/OptionBuilder.php +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/OptionBuilder.php @@ -49,4 +49,37 @@ public function setValue($value) { return $this->_set(Option::VALUE, $value); } + + /** + * Get option label + * + * @param int $value + * @return $this + */ + public function setOrder($value) + { + return $this->_set(Option::ORDER, $value); + } + + /** + * Get option order + * + * @param bool $value + * @return $this + */ + public function setDefault($value) + { + return $this->_set(Option::IS_DEFAULT, $value); + } + + /** + * Set option label for store scope + * + * @param \Magento\Catalog\Service\V1\Data\Eav\Option\Label[] $value + * @return $this + */ + public function setStoreLabels($value) + { + return $this->_set(Option::STORE_LABELS, $value); + } } diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabel.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabel.php new file mode 100644 index 0000000000000..35fe144767164 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabel.php @@ -0,0 +1,58 @@ +_get(self::STORE_ID); + } + + /** + * Get label + * + * @return string + */ + public function getLabel() + { + return $this->_get(self::LABEL); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabelBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabelBuilder.php new file mode 100644 index 0000000000000..d5760cdc1964b --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/FrontendLabelBuilder.php @@ -0,0 +1,53 @@ +_set(FrontendLabel::STORE_ID, $value); + } + + /** + * Set label + * + * @param string $label + * @return $this + */ + public function setLabel($label) + { + return $this->_set(FrontendLabel::LABEL, $label); + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Data/ProductAttributeType.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/Type.php similarity index 86% rename from app/code/Magento/Catalog/Service/V1/Data/ProductAttributeType.php rename to app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/Type.php index c4f1778b9815e..dbc20c98100dd 100644 --- a/app/code/Magento/Catalog/Service/V1/Data/ProductAttributeType.php +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/Type.php @@ -21,13 +21,13 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Catalog\Service\V1\Data; +namespace Magento\Catalog\Service\V1\Data\Eav\Product\Attribute; /** - * Class ProductAttributeType - * @package Magento\Catalog\Service\V1\Data + * Class Type + * @package Magento\Catalog\Service\V1\Data\Eav\Product\Attribute */ -class ProductAttributeType extends \Magento\Framework\Service\Data\AbstractObject +class Type extends \Magento\Framework\Service\Data\AbstractObject { /** * Constants used as keys into $_data diff --git a/app/code/Magento/Catalog/Service/V1/Data/ProductAttributeTypeBuilder.php b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/TypeBuilder.php similarity index 77% rename from app/code/Magento/Catalog/Service/V1/Data/ProductAttributeTypeBuilder.php rename to app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/TypeBuilder.php index 570e9a581d5ac..b10dbb881c629 100644 --- a/app/code/Magento/Catalog/Service/V1/Data/ProductAttributeTypeBuilder.php +++ b/app/code/Magento/Catalog/Service/V1/Data/Eav/Product/Attribute/TypeBuilder.php @@ -21,13 +21,13 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Catalog\Service\V1\Data; +namespace Magento\Catalog\Service\V1\Data\Eav\Product\Attribute; /** - * Class ProductAttributeTypeBuilder - * @package Magento\Catalog\Service\V1\Data\Eav + * Class TypeBuilder + * @package Magento\Catalog\Service\V1\Data\Eav\Product\Attribute */ -class ProductAttributeTypeBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder +class TypeBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder { /** * Set option label @@ -37,7 +37,7 @@ class ProductAttributeTypeBuilder extends \Magento\Framework\Service\Data\Abstra */ public function setLabel($label) { - return $this->_set(ProductAttributeType::LABEL, $label); + return $this->_set(Type::LABEL, $label); } /** @@ -48,6 +48,6 @@ public function setLabel($label) */ public function setValue($value) { - return $this->_set(ProductAttributeType::VALUE, $value); + return $this->_set(Type::VALUE, $value); } } diff --git a/app/code/Magento/Catalog/Service/V1/Data/Product/Attribute/SearchResults.php b/app/code/Magento/Catalog/Service/V1/Data/Product/Attribute/SearchResults.php new file mode 100644 index 0000000000000..01659feb56742 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Data/Product/Attribute/SearchResults.php @@ -0,0 +1,41 @@ +metadataService = $metadataService; + $this->inputTypeFactory = $inputTypeFactory; + $this->attributeTypeBuilder = $attributeTypeBuilder; + $this->searchResultsBuilder = $searchResultsBuilder; + $this->attributeCollection = $attributeCollection; + $this->attributeBuilder = $attributeBuilder; + } + + /** + * {@inheritdoc} + */ + public function types() + { + $types = []; + $inputType = $this->inputTypeFactory->create(); + + foreach ($inputType->toOptionArray() as $option) { + $types[] = $this->attributeTypeBuilder->populateWithArray($option)->create(); + } + return $types; + } + + /** + * {@inheritdoc} + */ + public function info($id) + { + return $this->metadataService->getAttributeMetadata( + ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT, + $id + ); + } + + /** + * {@inheritdoc} + */ + public function search(\Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria) + { + $this->searchResultsBuilder->setSearchCriteria($searchCriteria); + + //Add filters from root filter group to the collection + foreach ($searchCriteria->getFilterGroups() as $group) { + $this->addFilterGroupToCollection($group, $this->attributeCollection); + } + $sortOrders = $searchCriteria->getSortOrders(); + if ($sortOrders) { + foreach ($searchCriteria->getSortOrders() as $field => $direction) { + $field = $this->translateField($field); + $this->attributeCollection->addOrder($field, $direction == SearchCriteria::SORT_ASC ? 'ASC' : 'DESC'); + } + } + $this->attributeCollection->join( + array('additional_table' => $this->attributeCollection->getTable('catalog_eav_attribute')), + 'main_table.attribute_id = additional_table.attribute_id', + [ + 'frontend_input_renderer', + 'is_global', + 'is_visible', + 'is_searchable', + 'is_filterable', + 'is_comparable', + 'is_visible_on_front', + 'is_html_allowed_on_front', + 'is_used_for_price_rules', + 'is_filterable_in_search', + 'used_in_product_listing', + 'used_for_sort_by', + 'apply_to', + 'is_visible_in_advanced_search', + 'position', + 'is_wysiwyg_enabled', + 'is_used_for_promo_rules', + 'is_configurable', + 'search_weight', + ] + ); + + $this->attributeCollection->setCurPage($searchCriteria->getCurrentPage()); + $this->attributeCollection->setPageSize($searchCriteria->getPageSize()); + $this->searchResultsBuilder->setTotalCount($this->attributeCollection->getSize()); + + $attributes = array(); + /** @var \Magento\Eav\Model\Entity\Attribute $attribute */ + foreach ($this->attributeCollection as $attribute) { + $attributes[] = $this->attributeBuilder->setId($attribute->getAttributeId()) + ->setCode($attribute->getAttributeCode()) + ->setFrontendLabel($attribute->getData('frontend_label')) + ->setDefaultValue($attribute->getDefaultValue()) + ->setIsRequired((boolean)$attribute->getData('is_required')) + ->setIsUserDefined((boolean)$attribute->getData('is_user_defined')) + ->setFrontendInput($attribute->getData('frontend_input')) + ->create(); + } + + $this->searchResultsBuilder->setItems($attributes); + return $this->searchResultsBuilder->create(); + } + + /** + * Helper function that adds a FilterGroup to the collection. + * + * @param FilterGroup $filterGroup + * @param \Magento\Eav\Model\Resource\Entity\Attribute\Collection $collection + * @return void + * @throws \Magento\Framework\Exception\InputException + */ + protected function addFilterGroupToCollection(FilterGroup $filterGroup, Collection $collection) + { + $fields = []; + $conditions = []; + foreach ($filterGroup->getFilters() as $filter) { + $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; + $fields[] = $this->translateField($filter->getField()); + $conditions[] = [$condition => $filter->getValue()]; + } + if ($fields) { + $collection->addFieldToFilter($fields, $conditions); + } + } + + /** + * Translates a field name to a DB column name for use in collection queries. + * + * @param string $field a field name that should be translated to a DB column name. + * @return string + */ + protected function translateField($field) + { + switch ($field) { + case Attribute::ID: + return 'attribute_id'; + case Attribute::CODE: + return 'attribute_code'; + default: + return $field; + } + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/ReadServiceInterface.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/ReadServiceInterface.php new file mode 100644 index 0000000000000..c9e17e77c1628 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/ReadServiceInterface.php @@ -0,0 +1,56 @@ +eavConfig = $eavConfig; + $this->attributeFactory = $attributeFactory; + $this->filter = $filter; + $this->helper = $helper; + $this->inputtypeValidatorFactory = $inputtypeValidatorFactory; + } + + /** + * {@inheritdoc} + */ + public function create(\Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata $attributeMetadata) + { + /** + * @var $model \Magento\Catalog\Model\Resource\Eav\Attribute + */ + $model = $this->attributeFactory->create(); + $data = $attributeMetadata->__toArray(); + // unset attribute id because we create new attribute (does not rewrite existing one) + unset($data[AttributeMetadata::ATTRIBUTE_ID]); + + // define frontend label + if (!$attributeMetadata->getFrontendLabel()) { + throw InputException::requiredField(AttributeMetadata::FRONTEND_LABEL); + } + $data[AttributeMetadata::FRONTEND_LABEL] = []; + foreach ($attributeMetadata->getFrontendLabel() as $label) { + $data[AttributeMetadata::FRONTEND_LABEL][$label->getStoreId()] = $label->getLabel(); + } + if (!isset($data[AttributeMetadata::FRONTEND_LABEL][0]) || !$data[AttributeMetadata::FRONTEND_LABEL][0]) { + throw InputException::invalidFieldValue(AttributeMetadata::FRONTEND_LABEL, null); + } + + $data[AttributeMetadata::ATTRIBUTE_CODE] = + $attributeMetadata->getAttributeCode() ?: $this->generateCode($data[AttributeMetadata::FRONTEND_LABEL][0]); + $this->validateCode($data[AttributeMetadata::ATTRIBUTE_CODE]); + $this->validateFrontendInput($attributeMetadata->getFrontendInput()); + + $data[AttributeMetadata::BACKEND_TYPE] = $model->getBackendTypeByInput($attributeMetadata->getFrontendInput()); + $data[AttributeMetadata::SOURCE_MODEL] = + $this->helper->getAttributeSourceModelByInputType($attributeMetadata->getFrontendInput()); + $data[AttributeMetadata::BACKEND_MODEL] = + $this->helper->getAttributeBackendModelByInputType($attributeMetadata->getFrontendInput()); + + $model->addData($data); + + $model->setEntityTypeId($this->eavConfig->getEntityType(\Magento\Catalog\Model\Product::ENTITY)->getId()) + ->setIsUserDefined(1); + + return $model->save()->getAttributeCode(); + } + + /** + * {@inheritdoc} + */ + public function update($id, AttributeMetadata $attribute) + { + /** @var \Magento\Catalog\Model\Resource\Eav\Attribute $attributeModel */ + $model = $this->attributeFactory->create(); + $model->loadByCode(\Magento\Catalog\Model\Product::ENTITY, $id); + if (!$model->getId()) { + throw NoSuchEntityException::singleField(AttributeMetadata::ATTRIBUTE_CODE, $id); + } + + $data = $attribute->__toArray(); + + // this fields should not be changed + $data[AttributeMetadata::ATTRIBUTE_ID] = $model->getAttributeId(); + $data[AttributeMetadata::USER_DEFINED] = $model->getIsUserDefined(); + $data[AttributeMetadata::FRONTEND_INPUT] = $model->getFrontendInput(); + + if (isset($data[AttributeMetadata::FRONTEND_LABEL]) && is_array($data[AttributeMetadata::FRONTEND_LABEL])) { + $frontendLabel[0] = $model->getFrontendLabel(); + foreach ($data[AttributeMetadata::FRONTEND_LABEL] as $item) { + if (isset($item[FrontendLabel::STORE_ID], $item[FrontendLabel::LABEL])) { + $frontendLabel[$item[FrontendLabel::STORE_ID]] = $item[FrontendLabel::LABEL]; + } + } + $data[AttributeMetadata::FRONTEND_LABEL] = $frontendLabel; + } + + if (!$model->getIsUserDefined()) { + // Unset attribute field for system attributes + unset($data[AttributeMetadata::APPLY_TO]); + } + + try { + $model->addData($data); + $model->save(); + } catch (\Exception $e) { + throw new CouldNotSaveException('Could not update product attribute' . $e->getMessage()); + } + + return $model->getAttributeCode(); + } + + /** + * {@inheritdoc} + */ + public function remove($attributeId) + { + $model = $this->eavConfig->getAttribute(ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT, $attributeId); + if (!$model || !$model->getId()) { + //product attribute does not exist + throw NoSuchEntityException::singleField(AttributeMetadata::ATTRIBUTE_ID, $attributeId); + } + $model->delete(); + return true; + } + + /** + * Generate code from label + * + * @param string $label + * @return string + */ + protected function generateCode($label) + { + $code = substr(preg_replace('/[^a-z_0-9]/', '_', $this->filter->translitUrl($label)), 0, 30); + $validatorAttrCode = new \Zend_Validate_Regex(array('pattern' => '/^[a-z][a-z_0-9]{0,29}[a-z0-9]$/')); + if (!$validatorAttrCode->isValid($code)) { + $code = 'attr_' . ($code ?: substr(md5(time()), 0, 8)); + } + return $code; + } + + /** + * Validate attribute code + * + * @param string $code + * @return void + * @throws \Magento\Framework\Exception\InputException + */ + protected function validateCode($code) + { + $validatorAttrCode = new \Zend_Validate_Regex(array('pattern' => '/^[a-z][a-z_0-9]{0,30}$/')); + if (!$validatorAttrCode->isValid($code)) { + throw InputException::invalidFieldValue('attribute_code', $code); + } + } + + /** + * Validate Frontend Input Type + * + * @param string $frontendInput + * @return void + * @throws \Magento\Framework\Exception\InputException + */ + protected function validateFrontendInput($frontendInput) + { + $validator = $this->inputtypeValidatorFactory->create(); + if (!$validator->isValid($frontendInput)) { + throw InputException::invalidFieldValue('frontend_input', $frontendInput); + } + } +} diff --git a/app/code/Magento/Catalog/Service/V1/Product/Attribute/WriteServiceInterface.php b/app/code/Magento/Catalog/Service/V1/Product/Attribute/WriteServiceInterface.php new file mode 100644 index 0000000000000..1458c40ca538f --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/Product/Attribute/WriteServiceInterface.php @@ -0,0 +1,62 @@ +setDefaultValue($attribute->getDefaultValue()) ->setIsRequired((boolean)$attribute->getData('is_required')) ->setIsUserDefined((boolean)$attribute->getData('is_user_defined')) + ->setFrontendInput($attribute->getData('frontend_input')) ->create(); } return $attributes; diff --git a/app/code/Magento/Catalog/Service/V1/ProductAttributeReadService.php b/app/code/Magento/Catalog/Service/V1/ProductAttributeReadService.php deleted file mode 100644 index 27fd89b3490a9..0000000000000 --- a/app/code/Magento/Catalog/Service/V1/ProductAttributeReadService.php +++ /dev/null @@ -1,88 +0,0 @@ -metadataService = $metadataService; - $this->inputTypeFactory = $inputTypeFactory; - $this->attributeTypeBuilder = $attributeTypeBuilder; - } - - /** - * {@inheritdoc} - */ - public function types() - { - $types = []; - $inputType = $this->inputTypeFactory->create(); - - foreach ($inputType->toOptionArray() as $option) { - $types[] = $this->attributeTypeBuilder->populateWithArray($option)->create(); - } - return $types; - } - - /** - * {@inheritdoc} - */ - public function info($id) - { - return $this->metadataService->getAttributeMetadata( - ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT, - $id - ); - } -} diff --git a/app/code/Magento/Catalog/Service/V1/ProductAttributeService.php b/app/code/Magento/Catalog/Service/V1/ProductAttributeService.php new file mode 100644 index 0000000000000..81afa4f9a32b4 --- /dev/null +++ b/app/code/Magento/Catalog/Service/V1/ProductAttributeService.php @@ -0,0 +1,109 @@ +metadataService = $metadataService; + $this->eavConfig = $eavConfig; + $this->optionCollectionFactory = $optionCollectionFactory; + } + + /** + * {@inheritdoc} + */ + public function options($id) + { + return $this->metadataService->getAttributeMetadata( + ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT, + $id + )->getOptions(); + } + + /** + * {@inheritdoc} + */ + public function addOption($id, \Magento\Catalog\Service\V1\Data\Eav\Option $option) + { + $model = $this->eavConfig->getAttribute( + \Magento\Catalog\Service\V1\ProductMetadataServiceInterface::ENTITY_TYPE_PRODUCT, + $id + ); + if (!$model) { + throw new \Magento\Framework\Exception\StateException('Attribute does no exist'); + } + + if (!$model->usesSource()) { + throw new \Magento\Framework\Exception\StateException('Attribute doesn\'t have any option'); + } + + $key = 'new_option'; + + $options = []; + $options['value'][$key][0] = $option->getLabel(); + $options['order'][$key] = $option->getOrder(); + + if (is_array($option->getStoreLabels())) { + foreach ($option->getStoreLabels() as $label) { + $options['value'][$key][$label->getStoreId()] = $label->getLabel(); + } + } + + if ($option->isDefault()) { + $model->setDefault([$key]); + } + + $model->setOption($options); + $model->save(); + return true; + } +} diff --git a/app/code/Magento/Catalog/Service/V1/ProductAttributeReadServiceInterface.php b/app/code/Magento/Catalog/Service/V1/ProductAttributeServiceInterface.php similarity index 70% rename from app/code/Magento/Catalog/Service/V1/ProductAttributeReadServiceInterface.php rename to app/code/Magento/Catalog/Service/V1/ProductAttributeServiceInterface.php index 7a1717db1cf13..e4d5e1b0eab53 100644 --- a/app/code/Magento/Catalog/Service/V1/ProductAttributeReadServiceInterface.php +++ b/app/code/Magento/Catalog/Service/V1/ProductAttributeServiceInterface.php @@ -26,25 +26,26 @@ use Magento\Catalog\Service\V1\Data\ProductAttributeType; /** - * Class ProductAttributeReadServiceInterface - * @package Magento\Catalog\Service\V1 + * Class ProductAttributeServiceInterface */ -interface ProductAttributeReadServiceInterface +interface ProductAttributeServiceInterface { /** - * Retrieve list of product attribute types + * Retrieve list of attribute options * - * @return \Magento\Catalog\Service\V1\Data\ProductAttributeType[] + * @param string $id + * @return \Magento\Catalog\Service\V1\Data\Eav\Option[] + * + * @throws \Magento\Framework\Exception\NoSuchEntityException */ - public function types(); + public function options($id); /** - * Get full information about a required attribute with the list of options + * Add option to attribute * - * @param string $id - * @return \Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata - * - * @throws \Magento\Framework\Exception\NoSuchEntityException + * @param string $id + * @param \Magento\Catalog\Service\V1\Data\Eav\Option $option + * @return bool */ - public function info($id); + public function addOption($id, \Magento\Catalog\Service\V1\Data\Eav\Option $option); } diff --git a/app/code/Magento/Catalog/Service/V1/ProductMetadataService.php b/app/code/Magento/Catalog/Service/V1/ProductMetadataService.php index 979a89caeec04..8f2e5201bb7fc 100644 --- a/app/code/Magento/Catalog/Service/V1/ProductMetadataService.php +++ b/app/code/Magento/Catalog/Service/V1/ProductMetadataService.php @@ -26,6 +26,7 @@ use Magento\Eav\Model\Entity\Attribute\AbstractAttribute; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Catalog\Service\V1\Data\Eav\AttributeMetadata; +use Magento\Catalog\Service\V1\Data\Eav\Product\Attribute\FrontendLabel; /** * Class ProductMetadataService @@ -43,16 +44,6 @@ class ProductMetadataService implements ProductMetadataServiceInterface */ private $scopeResolver; - /** - * @var Data\Eav\OptionBuilder - */ - private $optionBuilder; - - /** - * @var Data\Eav\ValidationRuleBuilder - */ - private $validationRuleBuilder; - /** * @var Data\Eav\AttributeMetadataBuilder */ @@ -61,21 +52,15 @@ class ProductMetadataService implements ProductMetadataServiceInterface /** * @param \Magento\Eav\Model\Config $eavConfig * @param \Magento\Framework\App\ScopeResolverInterface $scopeResolver - * @param Data\Eav\OptionBuilder $optionBuilder - * @param Data\Eav\ValidationRuleBuilder $validationRuleBuilder * @param Data\Eav\AttributeMetadataBuilder $attributeMetadataBuilder */ public function __construct( \Magento\Eav\Model\Config $eavConfig, \Magento\Framework\App\ScopeResolverInterface $scopeResolver, - Data\Eav\OptionBuilder $optionBuilder, - Data\Eav\ValidationRuleBuilder $validationRuleBuilder, Data\Eav\AttributeMetadataBuilder $attributeMetadataBuilder ) { $this->eavConfig = $eavConfig; $this->scopeResolver = $scopeResolver; - $this->optionBuilder = $optionBuilder; - $this->validationRuleBuilder = $validationRuleBuilder; $this->attributeMetadataBuilder = $attributeMetadataBuilder; } @@ -159,18 +144,16 @@ private function createMetadataAttribute($attribute) $data[AttributeMetadata::SCOPE] = $attribute->isScopeGlobal() ? 'global' : ($attribute->isScopeWebsite() ? 'website' : 'store'); - // fill frontend labels - $data[AttributeMetadata::FRONTEND_LABEL] = array( - array( - 'store_id' => 0, - 'label' => $attribute->getFrontendLabel() - ) + $data[AttributeMetadata::FRONTEND_LABEL] = []; + $data[AttributeMetadata::FRONTEND_LABEL][0] = array( + FrontendLabel::STORE_ID => 0, + FrontendLabel::LABEL => $attribute->getFrontendLabel() ); if (is_array($attribute->getStoreLabels())) { foreach ($attribute->getStoreLabels() as $storeId => $label) { - $data[AttributeMetadata::FRONTEND_LABEL][] = array( - 'store_id' => $storeId, - 'label' => $label + $data[AttributeMetadata::FRONTEND_LABEL][$storeId] = array( + FrontendLabel::STORE_ID => $storeId, + FrontendLabel::LABEL => $label ); } } diff --git a/app/code/Magento/Catalog/Service/V1/ProductService.php b/app/code/Magento/Catalog/Service/V1/ProductService.php index ff88e63a3df72..2e3b28eeeb041 100644 --- a/app/code/Magento/Catalog/Service/V1/ProductService.php +++ b/app/code/Magento/Catalog/Service/V1/ProductService.php @@ -74,7 +74,7 @@ class ProductService implements ProductServiceInterface private $converter; /** - * @var Data\SearchResultsBuilder + * @var \Magento\Catalog\Service\V1\Data\Product\SearchResultsBuilder */ private $searchResultsBuilder; @@ -86,7 +86,7 @@ class ProductService implements ProductServiceInterface * @param \Magento\Catalog\Model\Resource\Product\CollectionFactory $productCollection * @param ProductMetadataServiceInterface $metadataService * @param \Magento\Catalog\Service\V1\Data\Converter $converter - * @param Data\SearchResultsBuilder $searchResultsBuilder + * @param \Magento\Catalog\Service\V1\Data\Product\SearchResultsBuilder $searchResultsBuilder */ public function __construct( Product\Initialization\Helper $initializationHelper, @@ -96,7 +96,7 @@ public function __construct( \Magento\Catalog\Model\Resource\Product\CollectionFactory $productCollection, ProductMetadataServiceInterface $metadataService, \Magento\Catalog\Service\V1\Data\Converter $converter, - Data\SearchResultsBuilder $searchResultsBuilder + \Magento\Catalog\Service\V1\Data\Product\SearchResultsBuilder $searchResultsBuilder ) { $this->initializationHelper = $initializationHelper; $this->productMapper = $productMapper; diff --git a/app/code/Magento/Catalog/Service/V1/ProductServiceInterface.php b/app/code/Magento/Catalog/Service/V1/ProductServiceInterface.php index 02d4ca463a490..5d44ee353e3de 100644 --- a/app/code/Magento/Catalog/Service/V1/ProductServiceInterface.php +++ b/app/code/Magento/Catalog/Service/V1/ProductServiceInterface.php @@ -72,10 +72,10 @@ public function create(\Magento\Catalog\Service\V1\Data\Product $product); public function update($id, \Magento\Catalog\Service\V1\Data\Product $product); /** - * get product list product + * Get product list * * @param \Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria - * @return \Magento\Catalog\Service\V1\Data\SearchResults containing Data\Product objects + * @return \Magento\Catalog\Service\V1\Data\Product\SearchResults containing Data\Product objects */ public function search(\Magento\Framework\Service\V1\Data\SearchCriteria $searchCriteria); } diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index e38c660f426e7..a7f281199ba85 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -26,7 +26,9 @@ - + + + @@ -222,10 +224,6 @@ Magento\Indexer\Model\IndexerInterface - - - - diff --git a/app/code/Magento/Catalog/etc/module.xml b/app/code/Magento/Catalog/etc/module.xml index 32387b3f84067..dbd9e2cec081d 100644 --- a/app/code/Magento/Catalog/etc/module.xml +++ b/app/code/Magento/Catalog/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + @@ -48,7 +48,6 @@ - diff --git a/app/code/Magento/Catalog/etc/webapi.xml b/app/code/Magento/Catalog/etc/webapi.xml index aa3c9ec05ca23..68c16392095b0 100644 --- a/app/code/Magento/Catalog/etc/webapi.xml +++ b/app/code/Magento/Catalog/etc/webapi.xml @@ -56,13 +56,37 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -181,6 +205,18 @@ + + + + + + + + + + + + diff --git a/app/code/Magento/Catalog/i18n/de_DE.csv b/app/code/Magento/Catalog/i18n/de_DE.csv index 1ab046da2d972..500edd1417362 100644 --- a/app/code/Magento/Catalog/i18n/de_DE.csv +++ b/app/code/Magento/Catalog/i18n/de_DE.csv @@ -269,6 +269,8 @@ "Enable Quantity Increments","Anzahlzunahme aktivieren" "Enable WYSIWYG","WYSIWYG aktivieren" "Enabled","Aktiviert" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","Entity-Modelltyp muss eine Anwendung von \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType sein" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","Entity-Modelltyp muss eine Anwendung von \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType sein" "Error during retrieval of option value: %s","Fehler bei Abfragen von Optionswert: %s" "Exclude","Auschließen" "Expand All","Alle erweitern" diff --git a/app/code/Magento/Catalog/i18n/en_US.csv b/app/code/Magento/Catalog/i18n/en_US.csv index 73557c01ae258..8fb4e90e6c572 100644 --- a/app/code/Magento/Catalog/i18n/en_US.csv +++ b/app/code/Magento/Catalog/i18n/en_US.csv @@ -270,6 +270,8 @@ "Enable Quantity Increments","Enable Quantity Increments" "Enable WYSIWYG","Enable WYSIWYG" "Enabled","Enabled" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType" "Error during retrieval of option value: %s","Error during retrieval of option value: %s" "Exclude","Exclude" "Expand All","Expand All" diff --git a/app/code/Magento/Catalog/i18n/es_ES.csv b/app/code/Magento/Catalog/i18n/es_ES.csv index 9ea8012442dfe..7978c1de1e2e9 100644 --- a/app/code/Magento/Catalog/i18n/es_ES.csv +++ b/app/code/Magento/Catalog/i18n/es_ES.csv @@ -269,6 +269,8 @@ "Enable Quantity Increments","Posibilitar Incrementos de Cantidad" "Enable WYSIWYG","Habilitar WYSIWYG" "Enabled","Habilitado" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","El modelo de tipo de entidad debe ser una instancia de \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","El modelo de tipo de entidad debe ser una instancia de \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType" "Error during retrieval of option value: %s","Error al recuperar el valor de la opción: %s" "Exclude","Excluir" "Expand All","Expandir todo" diff --git a/app/code/Magento/Catalog/i18n/fr_FR.csv b/app/code/Magento/Catalog/i18n/fr_FR.csv index b1eee5ea79157..ccbe17f0aa1f3 100644 --- a/app/code/Magento/Catalog/i18n/fr_FR.csv +++ b/app/code/Magento/Catalog/i18n/fr_FR.csv @@ -269,6 +269,8 @@ "Enable Quantity Increments","Activer quantité" "Enable WYSIWYG","Permettre WYSIWYG" "Enabled","Activé" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","Le type de modèle de l'entité doit être une instance de \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","Le type de modèle de l'entité doit être une instance de \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType" "Error during retrieval of option value: %s","Erreur lors de la récupération de la valeur de l'option:% s" "Exclude","Exclure" "Expand All","Tout développer" diff --git a/app/code/Magento/Catalog/i18n/nl_NL.csv b/app/code/Magento/Catalog/i18n/nl_NL.csv index 3bba923d85ba6..c2249b5662d35 100644 --- a/app/code/Magento/Catalog/i18n/nl_NL.csv +++ b/app/code/Magento/Catalog/i18n/nl_NL.csv @@ -269,6 +269,8 @@ "Enable Quantity Increments","Sta Quantity Incrementen toe" "Enable WYSIWYG","Sta WYSIWYG toe" "Enabled","Aan" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","Entiteit type model moet een instantie zijn van \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","Entiteit type model moet een instantie zijn van \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType" "Error during retrieval of option value: %s","Fout bij het ophalen van optie waarde: %s" "Exclude","Sluit Uit" "Expand All","Klap Alles Uit" diff --git a/app/code/Magento/Catalog/i18n/pt_BR.csv b/app/code/Magento/Catalog/i18n/pt_BR.csv index ff867c22e0acd..967d22f0d00f0 100644 --- a/app/code/Magento/Catalog/i18n/pt_BR.csv +++ b/app/code/Magento/Catalog/i18n/pt_BR.csv @@ -269,6 +269,8 @@ "Enable Quantity Increments","Habilitar Incrementos na Qtde." "Enable WYSIWYG","Habilitar WYSIWYG" "Enabled","Ativado" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","Modelo de tipo de entidade deve ser uma instância de \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","Modelo de tipo de entidade deve ser uma instância de \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType" "Error during retrieval of option value: %s","Erro ao recuperar valor de opção: %s" "Exclude","Excluir" "Expand All","Expandir Todos" diff --git a/app/code/Magento/Catalog/i18n/zh_CN.csv b/app/code/Magento/Catalog/i18n/zh_CN.csv index 79ac27d8357d2..02cb740b1d829 100644 --- a/app/code/Magento/Catalog/i18n/zh_CN.csv +++ b/app/code/Magento/Catalog/i18n/zh_CN.csv @@ -269,6 +269,8 @@ "Enable Quantity Increments","启用数量增量" "Enable WYSIWYG","启用所见即所得" "Enabled","已启用" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType","实体类型模块必须为\Magento\CatalogImportExport\Model\ImportExport\Export\Product\Type\AbstractType的实例" +"Entity type model must be an instance of \Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType","实体类型模块必须为\Magento\CatalogImportExport\Model\ImportExport\Import\Product\Type\AbstractType的实例" "Error during retrieval of option value: %s","获取选项值 %s的过程中出错" "Exclude","排除" "Expand All","全部展开" diff --git a/app/code/Magento/ImportExport/Model/Export/Entity/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php similarity index 98% rename from app/code/Magento/ImportExport/Model/Export/Entity/Product.php rename to app/code/Magento/CatalogImportExport/Model/Export/Product.php index e42ee802051ee..2e4f8fc812f4e 100644 --- a/app/code/Magento/ImportExport/Model/Export/Entity/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ImportExport\Model\Export\Entity; +namespace Magento\CatalogImportExport\Model\Export; /** * Export entity product model @@ -196,7 +196,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity protected $_attributeColFactory; /** - * @var \Magento\ImportExport\Model\Export\Entity\Product\Type\Factory + * @var \Magento\CatalogImportExport\Model\Export\Product\Type\Factory */ protected $_typeFactory; @@ -208,7 +208,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity protected $_linkTypeProvider; /** - * @var \Magento\ImportExport\Model\Export\RowCustomizerInterface + * @var \Magento\CatalogImportExport\Model\Export\RowCustomizerInterface */ protected $rowCustomizer; @@ -228,7 +228,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity * @param \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $attributeColFactory * @param Product\Type\Factory $_typeFactory * @param \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider - * @param \Magento\ImportExport\Model\Export\RowCustomizerInterface $rowCustomizer + * @param \Magento\CatalogImportExport\Model\Export\RowCustomizerInterface $rowCustomizer */ public function __construct( \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, @@ -244,9 +244,9 @@ public function __construct( \Magento\CatalogInventory\Model\Resource\Stock\ItemFactory $itemFactory, \Magento\Catalog\Model\Resource\Product\Option\CollectionFactory $optionColFactory, \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $attributeColFactory, - \Magento\ImportExport\Model\Export\Entity\Product\Type\Factory $_typeFactory, + \Magento\CatalogImportExport\Model\Export\Product\Type\Factory $_typeFactory, \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider, - \Magento\ImportExport\Model\Export\RowCustomizerInterface $rowCustomizer + \Magento\CatalogImportExport\Model\Export\RowCustomizerInterface $rowCustomizer ) { $this->_entityCollection = $collection; $this->_exportConfig = $exportConfig; @@ -320,16 +320,16 @@ protected function _initCategories() */ protected function _initTypeModels() { - $productTypes = $this->_exportConfig->getProductTypes(); + $productTypes = $this->_exportConfig->getEntityTypes($this->getEntityTypeCode()); foreach ($productTypes as $productTypeName => $productTypeConfig) { if (!($model = $this->_typeFactory->create($productTypeConfig['model']))) { throw new \Magento\Framework\Model\Exception("Entity type model '{$productTypeConfig['model']}' is not found"); } - if (!$model instanceof \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType) { + if (!$model instanceof \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType) { throw new \Magento\Framework\Model\Exception( __( 'Entity type model must be an instance of' - . ' \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType' + . ' \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType' ) ); } diff --git a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/AbstractType.php similarity index 97% rename from app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/AbstractType.php rename to app/code/Magento/CatalogImportExport/Model/Export/Product/Type/AbstractType.php index 07610b487fdc8..1864bbf7f9d1c 100644 --- a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/AbstractType.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/AbstractType.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ImportExport\Model\Export\Entity\Product\Type; +namespace Magento\CatalogImportExport\Model\Export\Product\Type; use Magento\Catalog\Model\Resource\Eav\Attribute; diff --git a/app/code/Magento/ConfigurableProduct/Model/Export/Entity/Product/Type/Configurable.php b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Configurable.php similarity index 84% rename from app/code/Magento/ConfigurableProduct/Model/Export/Entity/Product/Type/Configurable.php rename to app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Configurable.php index 52cf67e705071..290a8019075f8 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Export/Entity/Product/Type/Configurable.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Configurable.php @@ -21,8 +21,8 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ConfigurableProduct\Model\Export\Entity\Product\Type; +namespace Magento\CatalogImportExport\Model\Export\Product\Type; -class Configurable extends \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType +class Configurable extends \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType { } diff --git a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Factory.php b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Factory.php similarity index 92% rename from app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Factory.php rename to app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Factory.php index aaa6ff1fb6044..40ad5f678ccc1 100644 --- a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Factory.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Factory.php @@ -25,7 +25,7 @@ /** * Export product type factory */ -namespace Magento\ImportExport\Model\Export\Entity\Product\Type; +namespace Magento\CatalogImportExport\Model\Export\Product\Type; class Factory { @@ -46,7 +46,7 @@ public function __construct(\Magento\Framework\ObjectManager $objectManager) /** * @param string $className - * @return \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType + * @return \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType * @throws \InvalidArgumentException */ public function create($className) diff --git a/app/code/Magento/GroupedProduct/Model/Export/Entity/Product/Type/Grouped.php b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Grouped.php similarity index 87% rename from app/code/Magento/GroupedProduct/Model/Export/Entity/Product/Type/Grouped.php rename to app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Grouped.php index 89939d3e6df8f..feda0988b4879 100644 --- a/app/code/Magento/GroupedProduct/Model/Export/Entity/Product/Type/Grouped.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Grouped.php @@ -23,9 +23,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\GroupedProduct\Model\Export\Entity\Product\Type; - -use Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType; +namespace Magento\CatalogImportExport\Model\Export\Product\Type; class Grouped extends AbstractType { diff --git a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Simple.php b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Simple.php similarity index 93% rename from app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Simple.php rename to app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Simple.php index b267fa2918131..9482fa028e25c 100644 --- a/app/code/Magento/ImportExport/Model/Export/Entity/Product/Type/Simple.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product/Type/Simple.php @@ -21,14 +21,14 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ImportExport\Model\Export\Entity\Product\Type; +namespace Magento\CatalogImportExport\Model\Export\Product\Type; /** * Export entity product type simple model * * @author Magento Core Team */ -class Simple extends \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType +class Simple extends \Magento\CatalogImportExport\Model\Export\Product\Type\AbstractType { /** * Overridden attributes parameters. diff --git a/app/code/Magento/ConfigurableProduct/Model/Export/RowCustomizer.php b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer.php similarity index 97% rename from app/code/Magento/ConfigurableProduct/Model/Export/RowCustomizer.php rename to app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer.php index b7b7846c3431c..97db1a13b3ca6 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Export/RowCustomizer.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer.php @@ -21,9 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ConfigurableProduct\Model\Export; - -use Magento\ImportExport\Model\Export\RowCustomizerInterface; +namespace Magento\CatalogImportExport\Model\Export; class RowCustomizer implements RowCustomizerInterface { diff --git a/app/code/Magento/ImportExport/Model/Export/RowCustomizer/Composite.php b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer/Composite.php similarity index 95% rename from app/code/Magento/ImportExport/Model/Export/RowCustomizer/Composite.php rename to app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer/Composite.php index 626698d74d86c..d1e93ffcaa675 100644 --- a/app/code/Magento/ImportExport/Model/Export/RowCustomizer/Composite.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizer/Composite.php @@ -21,9 +21,9 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ImportExport\Model\Export\RowCustomizer; +namespace Magento\CatalogImportExport\Model\Export\RowCustomizer; -use Magento\ImportExport\Model\Export\RowCustomizerInterface; +use Magento\CatalogImportExport\Model\Export\RowCustomizerInterface; use Magento\Framework\ObjectManager; class Composite implements RowCustomizerInterface diff --git a/app/code/Magento/ImportExport/Model/Export/RowCustomizerInterface.php b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizerInterface.php similarity index 97% rename from app/code/Magento/ImportExport/Model/Export/RowCustomizerInterface.php rename to app/code/Magento/CatalogImportExport/Model/Export/RowCustomizerInterface.php index 6aaf6a0a88b0b..18231f0e29c46 100644 --- a/app/code/Magento/ImportExport/Model/Export/RowCustomizerInterface.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/RowCustomizerInterface.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ImportExport\Model\Export; +namespace Magento\CatalogImportExport\Model\Export; /** * Interface RowCustomizerInterface diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php similarity index 97% rename from app/code/Magento/ImportExport/Model/Import/Entity/Product.php rename to app/code/Magento/CatalogImportExport/Model/Import/Product.php index c3df73de55654..a8607a1a938aa 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ImportExport\Model\Import\Entity; +namespace Magento\CatalogImportExport\Model\Import; /** * Import entity product model @@ -341,14 +341,14 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity /** * Media files uploader * - * @var \Magento\ImportExport\Model\Import\Uploader + * @var \Magento\CatalogImportExport\Model\Import\Uploader */ protected $_fileUploader; /** * Import entity which provide import of product custom options * - * @var \Magento\ImportExport\Model\Import\Entity\Product\Option + * @var \Magento\CatalogImportExport\Model\Import\Product\Option */ protected $_optionEntity; @@ -377,7 +377,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity protected $_importConfig; /** - * @var \Magento\ImportExport\Model\Import\Proxy\Product\ResourceFactory + * @var \Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceFactory */ protected $_resourceFactory; @@ -407,7 +407,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity protected $_storeManager; /** - * @var \Magento\ImportExport\Model\Import\Entity\Product\Type\Factory + * @var \Magento\CatalogImportExport\Model\Import\Product\Type\Factory */ protected $_productTypeFactory; @@ -417,12 +417,12 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity protected $_linkFactory; /** - * @var \Magento\ImportExport\Model\Import\Proxy\ProductFactory + * @var \Magento\CatalogImportExport\Model\Import\Proxy\ProductFactory */ protected $_proxyProdFactory; /** - * @var \Magento\ImportExport\Model\Import\UploaderFactory + * @var \Magento\CatalogImportExport\Model\Import\UploaderFactory */ protected $_uploaderFactory; @@ -473,17 +473,17 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity * @param \Magento\CatalogInventory\Service\V1\StockItem $stockItemService * @param \Magento\Catalog\Helper\Data $catalogData * @param \Magento\ImportExport\Model\Import\Config $importConfig - * @param \Magento\ImportExport\Model\Import\Proxy\Product\ResourceFactory $resourceFactory - * @param Product\OptionFactory $optionFactory + * @param \Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceFactory $resourceFactory + * @param \Magento\CatalogImportExport\Model\Import\Product\OptionFactory $optionFactory * @param \Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory $setColFactory * @param \Magento\Catalog\Model\Resource\Category\CollectionFactory $categoryColFactory * @param \Magento\Customer\Service\V1\CustomerGroupServiceInterface $customerGroupService * @param \Magento\Catalog\Model\ProductFactory $productFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param Product\Type\Factory $productTypeFactory + * @param \Magento\CatalogImportExport\Model\Import\Product\Type\Factory $productTypeFactory * @param \Magento\Catalog\Model\Resource\Product\LinkFactory $linkFactory - * @param \Magento\ImportExport\Model\Import\Proxy\ProductFactory $proxyProdFactory - * @param \Magento\ImportExport\Model\Import\UploaderFactory $uploaderFactory + * @param \Magento\CatalogImportExport\Model\Import\Proxy\ProductFactory $proxyProdFactory + * @param \Magento\CatalogImportExport\Model\Import\UploaderFactory $uploaderFactory * @param \Magento\Framework\App\Filesystem $filesystem * @param \Magento\CatalogInventory\Model\Resource\Stock\ItemFactory $stockResItemFac * @param \Magento\CatalogInventory\Model\Stock\ItemFactory $stockItemFactory @@ -504,17 +504,17 @@ public function __construct( \Magento\CatalogInventory\Service\V1\StockItem $stockItemService, \Magento\Catalog\Helper\Data $catalogData, \Magento\ImportExport\Model\Import\Config $importConfig, - \Magento\ImportExport\Model\Import\Proxy\Product\ResourceFactory $resourceFactory, - \Magento\ImportExport\Model\Import\Entity\Product\OptionFactory $optionFactory, + \Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceFactory $resourceFactory, + \Magento\CatalogImportExport\Model\Import\Product\OptionFactory $optionFactory, \Magento\Eav\Model\Resource\Entity\Attribute\Set\CollectionFactory $setColFactory, \Magento\Catalog\Model\Resource\Category\CollectionFactory $categoryColFactory, \Magento\Customer\Service\V1\CustomerGroupServiceInterface $customerGroupService, \Magento\Catalog\Model\ProductFactory $productFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\ImportExport\Model\Import\Entity\Product\Type\Factory $productTypeFactory, + \Magento\CatalogImportExport\Model\Import\Product\Type\Factory $productTypeFactory, \Magento\Catalog\Model\Resource\Product\LinkFactory $linkFactory, - \Magento\ImportExport\Model\Import\Proxy\ProductFactory $proxyProdFactory, - \Magento\ImportExport\Model\Import\UploaderFactory $uploaderFactory, + \Magento\CatalogImportExport\Model\Import\Proxy\ProductFactory $proxyProdFactory, + \Magento\CatalogImportExport\Model\Import\UploaderFactory $uploaderFactory, \Magento\Framework\App\Filesystem $filesystem, \Magento\CatalogInventory\Model\Resource\Stock\ItemFactory $stockResItemFac, \Magento\CatalogInventory\Model\Stock\ItemFactory $stockItemFactory, @@ -562,7 +562,7 @@ public function __construct( /** * Retrieve instance of product custom options import entity * - * @return \Magento\ImportExport\Model\Import\Entity\Product\Option + * @return \Magento\CatalogImportExport\Model\Import\Product\Option */ public function getOptionEntity() { @@ -736,7 +736,7 @@ protected function _initStores() */ protected function _initTypeModels() { - $productTypes = $this->_importConfig->getProductTypes(); + $productTypes = $this->_importConfig->getEntityTypes($this->getEntityTypeCode()); foreach ($productTypes as $productTypeName => $productTypeConfig) { $params = array($this, $productTypeName); if (!($model = $this->_productTypeFactory->create($productTypeConfig['model'], array('params' => $params))) @@ -745,11 +745,11 @@ protected function _initTypeModels() sprintf("Entity type model '%s' is not found", $productTypeConfig['model']) ); } - if (!$model instanceof \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType) { + if (!$model instanceof \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType) { throw new \Magento\Framework\Model\Exception( __( 'Entity type model must be an instance of ' . - 'Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType' + 'Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType' ) ); } @@ -1246,7 +1246,7 @@ protected function _saveProductEntity(array $entityRowsIn, array $entityRowsUp) */ protected function _saveProducts() { - /** @var $resource \Magento\ImportExport\Model\Import\Proxy\Product\Resource */ + /** @var $resource \Magento\CatalogImportExport\Model\Import\Proxy\Product\Resource */ $resource = $this->_resourceFactory->create(); $priceIsGlobal = $this->_catalogData->isPriceGlobal(); $productLimit = null; @@ -1549,7 +1549,7 @@ protected function _saveProductGroupPrices(array $groupPriceData) /** * Returns an object for upload a media files * - * @return \Magento\ImportExport\Model\Import\Uploader + * @return \Magento\CatalogImportExport\Model\Import\Uploader * @throws \Magento\Framework\Model\Exception */ protected function _getUploader() diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Option.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php similarity index 99% rename from app/code/Magento/ImportExport/Model/Import/Entity/Product/Option.php rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php index 161b84e065035..976c73d7c770f 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Option.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Option.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ImportExport\Model\Import\Entity\Product; +namespace Magento\CatalogImportExport\Model\Import\Product; /** * Entity class which provide possibility to import product custom options @@ -187,7 +187,7 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity /** * Parent import product entity * - * @var \Magento\ImportExport\Model\Import\Entity\Product + * @var \Magento\CatalogImportExport\Model\Import\Product */ protected $_productEntity; diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/AbstractType.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php similarity index 94% rename from app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/AbstractType.php rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php index 720026151ab5a..10901d740ab93 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/AbstractType.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ImportExport\Model\Import\Entity\Product\Type; +namespace Magento\CatalogImportExport\Model\Import\Product\Type; /** * Import entity abstract product type model @@ -78,7 +78,7 @@ abstract class AbstractType /** * Product entity object. * - * @var \Magento\ImportExport\Model\Import\Entity\Product + * @var \Magento\CatalogImportExport\Model\Import\Product */ protected $_entityModel; @@ -120,7 +120,7 @@ public function __construct( $params[1] ) || !is_object( $params[0] - ) || !$params[0] instanceof \Magento\ImportExport\Model\Import\Entity\Product + ) || !$params[0] instanceof \Magento\CatalogImportExport\Model\Import\Product ) { throw new \Magento\Framework\Model\Exception(__('Please correct the parameters.')); } @@ -140,7 +140,7 @@ public function __construct( * @param string $attrSetName Name of attribute set. * @param array $attrParams Refined attribute parameters. * @param mixed $attribute - * @return \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType */ protected function _addAttributeParams($attrSetName, array $attrParams, $attribute) { @@ -159,7 +159,7 @@ protected function _addAttributeParams($attrSetName, array $attrParams, $attribu protected function _getProductAttributes($attrSetData) { if (is_array($attrSetData)) { - return $this->_attributes[$attrSetData[\Magento\ImportExport\Model\Import\Entity\Product::COL_ATTR_SET]]; + return $this->_attributes[$attrSetData[\Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET]]; } else { return $this->_attributes[$attrSetData]; } @@ -272,7 +272,7 @@ public function isRowValid(array $rowData, $rowNum, $isNewProduct = true) $error = false; $rowScope = $this->_entityModel->getRowScope($rowData); - if (\Magento\ImportExport\Model\Import\Entity\Product::SCOPE_NULL != $rowScope) { + if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_NULL != $rowScope) { foreach ($this->_getProductAttributes($rowData) as $attrCode => $attrParams) { // check value for non-empty in the case of required attribute? if (isset($rowData[$attrCode]) && strlen($rowData[$attrCode])) { @@ -280,7 +280,7 @@ public function isRowValid(array $rowData, $rowNum, $isNewProduct = true) } elseif ($this->_isAttributeRequiredCheckNeeded($attrCode) && $attrParams['is_required']) { // For the default scope - if this is a new product or // for an old product, if the imported doc has the column present for the attrCode - if (\Magento\ImportExport\Model\Import\Entity\Product::SCOPE_DEFAULT == $rowScope && + if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT == $rowScope && ($isNewProduct || array_key_exists( $attrCode, @@ -288,7 +288,7 @@ public function isRowValid(array $rowData, $rowNum, $isNewProduct = true) )) ) { $this->_entityModel->addRowError( - \Magento\ImportExport\Model\Import\Entity\Product::ERROR_VALUE_IS_REQUIRED, + \Magento\CatalogImportExport\Model\Import\Product::ERROR_VALUE_IS_REQUIRED, $rowNum, $attrCode ); diff --git a/app/code/Magento/ConfigurableProduct/Model/Import/Entity/Product/Type/Configurable.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Configurable.php similarity index 97% rename from app/code/Magento/ConfigurableProduct/Model/Import/Entity/Product/Type/Configurable.php rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Configurable.php index b1ec11bc37182..8baafce4c66ea 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Import/Entity/Product/Type/Configurable.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Configurable.php @@ -23,9 +23,9 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ConfigurableProduct\Model\Import\Entity\Product\Type; +namespace Magento\CatalogImportExport\Model\Import\Product\Type; -class Configurable extends \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType +class Configurable extends \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType { /** * Error codes. @@ -178,7 +178,7 @@ public function __construct( * @param string $attrSetName Name of attribute set. * @param array $attrParams Refined attribute parameters. * @param mixed $attribute - * @return \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType */ protected function _addAttributeParams($attrSetName, array $attrParams, $attribute) { @@ -410,7 +410,7 @@ protected function _processSuperData(array $superData, array &$superAttributes) * Save product type specific data. * * @throws \Exception - * @return \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) @@ -450,8 +450,8 @@ public function saveData() } // remember SCOPE_DEFAULT row data $scope = $this->_entityModel->getRowScope($rowData); - if (\Magento\ImportExport\Model\Import\Entity\Product::SCOPE_DEFAULT == $scope) { - $productData = $newSku[$rowData[\Magento\ImportExport\Model\Import\Entity\Product::COL_SKU]]; + if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT == $scope) { + $productData = $newSku[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]]; if ($this->_type != $productData['type_id']) { $productData = null; diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Factory.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Factory.php similarity index 93% rename from app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Factory.php rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Factory.php index 13863a2ae73f9..50c6107622551 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Factory.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Factory.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ImportExport\Model\Import\Entity\Product\Type; +namespace Magento\CatalogImportExport\Model\Import\Product\Type; /** * Import product type factory @@ -46,7 +46,7 @@ public function __construct(\Magento\Framework\ObjectManager $objectManager) /** * @param string $className * @param array $arguments - * @return \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType * @throws \InvalidArgumentException */ public function create($className, array $arguments = array()) diff --git a/app/code/Magento/GroupedProduct/Model/Import/Entity/Product/Type/Grouped.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Grouped.php similarity index 93% rename from app/code/Magento/GroupedProduct/Model/Import/Entity/Product/Type/Grouped.php rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Grouped.php index f4a553a6217cc..7492697f6a771 100644 --- a/app/code/Magento/GroupedProduct/Model/Import/Entity/Product/Type/Grouped.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Grouped.php @@ -23,9 +23,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\GroupedProduct\Model\Import\Entity\Product\Type; - -use Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType; +namespace Magento\CatalogImportExport\Model\Import\Product\Type; class Grouped extends AbstractType { @@ -96,7 +94,7 @@ public function getBehavior() /** * Save product type specific data. * - * @return \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType + * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) @@ -149,16 +147,16 @@ public function saveData() continue; } $scope = $this->_entityModel->getRowScope($rowData); - if (\Magento\ImportExport\Model\Import\Entity\Product::SCOPE_DEFAULT == $scope) { - $productData = $newSku[$rowData[\Magento\ImportExport\Model\Import\Entity\Product::COL_SKU]]; + if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT == $scope) { + $productData = $newSku[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]]; } else { - $colAttrSet = \Magento\ImportExport\Model\Import\Entity\Product::COL_ATTR_SET; + $colAttrSet = \Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET; $rowData[$colAttrSet] = $productData['attr_set_code']; - $rowData[\Magento\ImportExport\Model\Import\Entity\Product::COL_TYPE] = $productData['type_id']; + $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE] = $productData['type_id']; } $productId = $productData['entity_id']; - if ($this->_type != $rowData[\Magento\ImportExport\Model\Import\Entity\Product::COL_TYPE]) { + if ($this->_type != $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE]) { continue; } $linksData['product_ids'][$productId] = true; diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Simple.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Simple.php similarity index 91% rename from app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Simple.php rename to app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Simple.php index 53fa01691333d..15ed63ce9ac76 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/Product/Type/Simple.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/Type/Simple.php @@ -21,14 +21,14 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ImportExport\Model\Import\Entity\Product\Type; +namespace Magento\CatalogImportExport\Model\Import\Product\Type; /** * Import entity simple product type * * @author Magento Core Team */ -class Simple extends \Magento\ImportExport\Model\Import\Entity\Product\Type\AbstractType +class Simple extends \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType { /** * Attributes' codes which will be allowed anyway, independently from its visibility property. diff --git a/app/code/Magento/ImportExport/Model/Import/Proxy/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product.php similarity index 95% rename from app/code/Magento/ImportExport/Model/Import/Proxy/Product.php rename to app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product.php index b9f86ab1517df..3588c75530217 100644 --- a/app/code/Magento/ImportExport/Model/Import/Proxy/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product.php @@ -27,7 +27,7 @@ * * @author Magento Core Team */ -namespace Magento\ImportExport\Model\Import\Proxy; +namespace Magento\CatalogImportExport\Model\Import\Proxy; class Product extends \Magento\Catalog\Model\Product { diff --git a/app/code/Magento/ImportExport/Model/Import/Proxy/Product/Resource.php b/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product/Resource.php similarity index 95% rename from app/code/Magento/ImportExport/Model/Import/Proxy/Product/Resource.php rename to app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product/Resource.php index fb25a62fbb4d1..a701d312e29d1 100644 --- a/app/code/Magento/ImportExport/Model/Import/Proxy/Product/Resource.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Proxy/Product/Resource.php @@ -27,7 +27,7 @@ * * @author Magento Core Team */ -namespace Magento\ImportExport\Model\Import\Proxy\Product; +namespace Magento\CatalogImportExport\Model\Import\Proxy\Product; class Resource extends \Magento\Catalog\Model\Resource\Product { diff --git a/app/code/Magento/ImportExport/Model/Import/Uploader.php b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php similarity index 99% rename from app/code/Magento/ImportExport/Model/Import/Uploader.php rename to app/code/Magento/CatalogImportExport/Model/Import/Uploader.php index e7ce134a3cd96..04dc6c2090f17 100644 --- a/app/code/Magento/ImportExport/Model/Import/Uploader.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Uploader.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\ImportExport\Model\Import; +namespace Magento\CatalogImportExport\Model\Import; /** * Import entity product model diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/Import.php b/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Flat/Plugin/Import.php similarity index 96% rename from app/code/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/Import.php rename to app/code/Magento/CatalogImportExport/Model/Indexer/Product/Flat/Plugin/Import.php index 2813821c4e8e5..f411fa94d106f 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Plugin/Import.php +++ b/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Flat/Plugin/Import.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Catalog\Model\Indexer\Product\Flat\Plugin; +namespace Magento\CatalogImportExport\Model\Indexer\Product\Flat\Plugin; class Import { diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Plugin/Import.php b/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/Import.php similarity index 88% rename from app/code/Magento/Catalog/Model/Indexer/Product/Price/Plugin/Import.php rename to app/code/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/Import.php index 68eba09acff2a..ad29f49e9d09c 100644 --- a/app/code/Magento/Catalog/Model/Indexer/Product/Price/Plugin/Import.php +++ b/app/code/Magento/CatalogImportExport/Model/Indexer/Product/Price/Plugin/Import.php @@ -21,9 +21,9 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Catalog\Model\Indexer\Product\Price\Plugin; +namespace Magento\CatalogImportExport\Model\Indexer\Product\Price\Plugin; -class Import extends AbstractPlugin +class Import extends \Magento\Catalog\Model\Indexer\Product\Price\Plugin\AbstractPlugin { /** * After import handler diff --git a/app/code/Magento/GroupedProduct/etc/export.xml b/app/code/Magento/CatalogImportExport/etc/config.xml similarity index 85% rename from app/code/Magento/GroupedProduct/etc/export.xml rename to app/code/Magento/CatalogImportExport/etc/config.xml index 9a6547bf3e92d..7b8a9c1f6e71c 100644 --- a/app/code/Magento/GroupedProduct/etc/export.xml +++ b/app/code/Magento/CatalogImportExport/etc/config.xml @@ -23,6 +23,9 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ --> - - + + + + + diff --git a/app/code/Magento/CatalogImportExport/etc/di.xml b/app/code/Magento/CatalogImportExport/etc/di.xml new file mode 100644 index 0000000000000..3b23b8aa68751 --- /dev/null +++ b/app/code/Magento/CatalogImportExport/etc/di.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + Magento\CatalogImportExport\Model\Export\RowCustomizer + + + + diff --git a/app/code/Magento/ImportExport/etc/export.xml b/app/code/Magento/CatalogImportExport/etc/export.xml similarity index 66% rename from app/code/Magento/ImportExport/etc/export.xml rename to app/code/Magento/CatalogImportExport/etc/export.xml index ee9f966cb5053..9d3fce872ca89 100644 --- a/app/code/Magento/ImportExport/etc/export.xml +++ b/app/code/Magento/CatalogImportExport/etc/export.xml @@ -24,8 +24,10 @@ */ --> - - - + + + + + diff --git a/app/code/Magento/ImportExport/etc/import.xml b/app/code/Magento/CatalogImportExport/etc/import.xml similarity index 59% rename from app/code/Magento/ImportExport/etc/import.xml rename to app/code/Magento/CatalogImportExport/etc/import.xml index a6052786aed54..74324b3e3ba45 100644 --- a/app/code/Magento/ImportExport/etc/import.xml +++ b/app/code/Magento/CatalogImportExport/etc/import.xml @@ -24,7 +24,12 @@ */ --> - - - + + + + + + + + diff --git a/app/code/Magento/CatalogImportExport/etc/module.xml b/app/code/Magento/CatalogImportExport/etc/module.xml new file mode 100644 index 0000000000000..c770dde9d5ef5 --- /dev/null +++ b/app/code/Magento/CatalogImportExport/etc/module.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/CatalogInventory/etc/module.xml b/app/code/Magento/CatalogInventory/etc/module.xml index 0ba165098ca7b..609eab35846ac 100644 --- a/app/code/Magento/CatalogInventory/etc/module.xml +++ b/app/code/Magento/CatalogInventory/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/CatalogRule/etc/adminhtml/di.xml b/app/code/Magento/CatalogRule/etc/adminhtml/di.xml index 944adad1f573c..2951c5c618a84 100644 --- a/app/code/Magento/CatalogRule/etc/adminhtml/di.xml +++ b/app/code/Magento/CatalogRule/etc/adminhtml/di.xml @@ -28,6 +28,7 @@ block_html + full_page diff --git a/app/code/Magento/CatalogRule/etc/module.xml b/app/code/Magento/CatalogRule/etc/module.xml index 4eb5a509cf02c..da7cd1f9cc130 100644 --- a/app/code/Magento/CatalogRule/etc/module.xml +++ b/app/code/Magento/CatalogRule/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/CatalogSearch/Controller/Advanced.php b/app/code/Magento/CatalogSearch/Controller/Advanced.php index effeaabf9456a..6b2cb3c897589 100644 --- a/app/code/Magento/CatalogSearch/Controller/Advanced.php +++ b/app/code/Magento/CatalogSearch/Controller/Advanced.php @@ -92,18 +92,16 @@ public function indexAction() */ public function resultAction() { - $this->_view->loadLayout(); try { $this->_catalogSearchAdvanced->addFilters($this->getRequest()->getQuery()); } catch (\Magento\Framework\Model\Exception $e) { $this->messageManager->addError($e->getMessage()); - $defaultUrl = $this->_urlFactory->create()->addQueryParams( - $this->getRequest()->getQuery() - )->getUrl( - '*/*/' - ); + $defaultUrl = $this->_urlFactory->create() + ->addQueryParams($this->getRequest()->getQuery()) + ->getUrl('*/*/'); $this->getResponse()->setRedirect($this->_redirect->error($defaultUrl)); } + $this->_view->loadLayout(); $this->_view->renderLayout(); } } diff --git a/app/code/Magento/CatalogSearch/Model/Advanced.php b/app/code/Magento/CatalogSearch/Model/Advanced.php index 7c4329b46a39c..138588428880d 100644 --- a/app/code/Magento/CatalogSearch/Model/Advanced.php +++ b/app/code/Magento/CatalogSearch/Model/Advanced.php @@ -21,6 +21,23 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ +namespace Magento\CatalogSearch\Model; + +use Magento\Catalog\Model\Config; +use Magento\Catalog\Model\Product\Visibility; +use Magento\Catalog\Model\ProductFactory; +use Magento\Catalog\Model\Resource\Eav\Attribute; +use Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory; +use Magento\CatalogSearch\Model\Resource\Advanced\Collection; +use Magento\CatalogSearch\Model\Resource\EngineInterface; +use Magento\CatalogSearch\Model\Resource\EngineProvider; +use Magento\Framework\Model\Exception; +use Magento\Framework\Model\Context; +use Magento\Framework\Registry; +use Magento\Store\Model\StoreManagerInterface; +use Magento\Directory\Model\Currency; +use Magento\Directory\Model\CurrencyFactory; +use Magento\Eav\Model\Entity\Attribute as EntityAttribute; /** * Catalog advanced search model @@ -45,25 +62,6 @@ * * @author Magento Core Team */ -namespace Magento\CatalogSearch\Model; - -use Magento\Catalog\Model\Config; -use Magento\Catalog\Model\Product\Visibility; -use Magento\Catalog\Model\ProductFactory; -use Magento\Catalog\Model\Resource\Eav\Attribute; -use Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory; -use Magento\CatalogSearch\Helper\Data; -use Magento\CatalogSearch\Model\Resource\Advanced\Collection; -use Magento\CatalogSearch\Model\Resource\EngineInterface; -use Magento\CatalogSearch\Model\Resource\EngineProvider; -use Magento\Framework\Model\Exception; -use Magento\Framework\Model\Context; -use Magento\Framework\Registry; -use Magento\Store\Model\StoreManagerInterface; -use Magento\Directory\Model\Currency; -use Magento\Directory\Model\CurrencyFactory; -use Magento\Eav\Model\Entity\Attribute as EntityAttribute; - class Advanced extends \Magento\Framework\Model\AbstractModel { /** @@ -138,7 +136,6 @@ class Advanced extends \Magento\Framework\Model\AbstractModel * @param Visibility $catalogProductVisibility * @param Config $catalogConfig * @param EngineProvider $engineProvider - * @param Data $helper * @param CurrencyFactory $currencyFactory * @param ProductFactory $productFactory * @param StoreManagerInterface $storeManager @@ -151,7 +148,6 @@ public function __construct( Visibility $catalogProductVisibility, Config $catalogConfig, EngineProvider $engineProvider, - Data $helper, CurrencyFactory $currencyFactory, ProductFactory $productFactory, StoreManagerInterface $storeManager, @@ -203,7 +199,7 @@ public function getAttributes() * * @param array $values * @return $this - * @throws \Magento\Framework\Model\Exception + * @throws Exception */ public function addFilters($values) { @@ -238,7 +234,7 @@ public function addFilters($values) $this->_addSearchCriteria($attribute, $value); } } - } else if ($attribute->isIndexable()) { + } elseif ($attribute->isIndexable()) { if (!is_string($value) || strlen($value) != 0) { if ($this->_getResource()->addIndexableAttributeModifiedFilter( $this->getProductCollection(), @@ -272,9 +268,10 @@ public function addFilters($values) } } if ($allConditions) { + $this->_registry->register('advanced_search_conditions', $allConditions); $this->getProductCollection()->addFieldsToFilter($allConditions); - } else if (!$hasConditions) { - throw new \Magento\Framework\Model\Exception(__('Please specify at least one search term.')); + } elseif (!$hasConditions) { + throw new Exception(__('Please specify at least one search term.')); } return $this; @@ -324,7 +321,7 @@ protected function _addSearchCriteria($attribute, $value) } if (($attribute->getFrontendInput() == 'select' || - $attribute->getFrontendInput() == 'multiselect') && is_array($value) + $attribute->getFrontendInput() == 'multiselect') && is_array($value) ) { foreach ($value as $key => $val) { $value[$key] = $attribute->getSource()->getOptionText($val); @@ -334,7 +331,7 @@ protected function _addSearchCriteria($attribute, $value) } } $value = implode(', ', $value); - } else if ($attribute->getFrontendInput() == 'select' || $attribute->getFrontendInput() == 'multiselect') { + } elseif ($attribute->getFrontendInput() == 'select' || $attribute->getFrontendInput() == 'multiselect') { $value = $attribute->getSource()->getOptionText($value); if (is_array($value)) { $value = $value['label']; @@ -386,13 +383,13 @@ public function getProductCollection() */ public function prepareProductCollection($collection) { - $collection->addAttributeToSelect( - $this->_catalogConfig->getProductAttributes() - )->setStore( - $this->_storeManager->getStore() - )->addMinimalPrice()->addTaxPercents()->addStoreFilter()->setVisibility( - $this->_catalogProductVisibility->getVisibleInSearchIds() - ); + $collection + ->addAttributeToSelect($this->_catalogConfig->getProductAttributes()) + ->setStore($this->_storeManager->getStore()) + ->addMinimalPrice() + ->addTaxPercents() + ->addStoreFilter() + ->setVisibility($this->_catalogProductVisibility->getVisibleInSearchIds()); return $this; } diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Advanced.php b/app/code/Magento/CatalogSearch/Model/Layer/Advanced.php new file mode 100644 index 0000000000000..831dbe38d7e17 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Model/Layer/Advanced.php @@ -0,0 +1,65 @@ +catalogConfig = $catalogConfig; + $this->helper = $helper; + $this->storeManager = $storeManager; + $this->productVisibility = $productVisibility; + $this->_registry = $registry; + } + + /** + * @param \Magento\Catalog\Model\Resource\Product\Collection $collection + * @param \Magento\Catalog\Model\Category $category + * @return void + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function filter( + $collection, + \Magento\Catalog\Model\Category $category + ) { + $collection + ->addAttributeToSelect($this->catalogConfig->getProductAttributes()) + ->addFieldsToFilter($this->_registry->registry('advanced_search_conditions')) + ->setStore($this->storeManager->getStore()) + ->addMinimalPrice() + ->addTaxPercents() + ->addStoreFilter() + ->setVisibility($this->productVisibility->getVisibleInSearchIds()); + } +} diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Advanced/Context.php b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/Context.php new file mode 100644 index 0000000000000..809ca9fd7c53d --- /dev/null +++ b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/Context.php @@ -0,0 +1,41 @@ +addDisplayInAdvancedSearchFilter()->addVisibleFilter(); + return $collection; + } +} diff --git a/app/code/Magento/CatalogSearch/Model/Layer/Advanced/ItemCollectionProvider.php b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/ItemCollectionProvider.php new file mode 100644 index 0000000000000..41a23bb1ff809 --- /dev/null +++ b/app/code/Magento/CatalogSearch/Model/Layer/Advanced/ItemCollectionProvider.php @@ -0,0 +1,57 @@ +advancedCollectionFactory = $fulltextCollectionFactory; + } + + /** + * Retrieve item colleciton + * + * @param \Magento\Catalog\Model\Category $category + * @return \Magento\CatalogSearch\Model\Resource\Advanced\Collection + */ + public function getCollection(\Magento\Catalog\Model\Category $category) + { + return $this->advancedCollectionFactory->create(); + } +} diff --git a/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php b/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php index ee15a21acb22a..d27a819b8db11 100644 --- a/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php +++ b/app/code/Magento/CatalogSearch/Model/Resource/Search/Collection.php @@ -72,7 +72,7 @@ class Collection extends \Magento\Catalog\Model\Resource\Product\Collection * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Catalog\Model\Resource\Product\Attribute\CollectionFactory $attributeCollectionFactory * @param \Zend_Db_Adapter_Abstract $connection - * + * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -134,6 +134,22 @@ public function addSearchFilter($query) return $this; } + /** + * Add backend search query filter (search by all stores) + * + * @param string $query + * @return $this + */ + public function addBackendSearchFilter($query) + { + $this->_searchQuery = $query; + $this->addFieldToFilter( + 'entity_id', + array('in' => new \Zend_Db_Expr($this->_getSearchEntityIdsSql($query, false))) + ); + return $this; + } + /** * Retrieve collection of all attributes * @@ -192,9 +208,10 @@ protected function _hasAttributeOptionsAndSearchable($attribute) * Retrieve SQL for search entities * * @param mixed $query + * @param bool $searchOnlyInCurrentStore Search only in current store or in all stores * @return string */ - protected function _getSearchEntityIdsSql($query) + protected function _getSearchEntityIdsSql($query, $searchOnlyInCurrentStore = true) { $tables = array(); $selects = array(); @@ -226,6 +243,15 @@ protected function _getSearchEntityIdsSql($query) } } + if ($searchOnlyInCurrentStore) { + $joinCondition = $this->getConnection()->quoteInto( + 't1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id AND t2.store_id = ?', + $this->getStoreId() + ); + } else { + $joinCondition = 't1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id'; + } + $ifValueId = $this->getConnection()->getIfNullSql('t2.value', 't1.value'); foreach ($tables as $table => $attributeIds) { $selects[] = $this->getConnection()->select()->from( @@ -233,10 +259,7 @@ protected function _getSearchEntityIdsSql($query) 'entity_id' )->joinLeft( array('t2' => $table), - $this->getConnection()->quoteInto( - 't1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id AND t2.store_id = ?', - $this->getStoreId() - ), + $joinCondition, array() )->where( 't1.attribute_id IN (?)', diff --git a/app/code/Magento/CatalogSearch/etc/di.xml b/app/code/Magento/CatalogSearch/etc/di.xml index a58caa081c68a..279573603076f 100644 --- a/app/code/Magento/CatalogSearch/etc/di.xml +++ b/app/code/Magento/CatalogSearch/etc/di.xml @@ -31,4 +31,14 @@ + + + Magento\CatalogSearch\Model\Layer\Advanced\FilterableAttributeList + + + + + Magento\CatalogSearch\Model\Layer\Advanced + + diff --git a/app/code/Magento/CatalogSearch/etc/module.xml b/app/code/Magento/CatalogSearch/etc/module.xml index 15534ff9c5c6e..b796f63bc8203 100644 --- a/app/code/Magento/CatalogSearch/etc/module.xml +++ b/app/code/Magento/CatalogSearch/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Centinel/etc/module.xml b/app/code/Magento/Centinel/etc/module.xml index 932a47ea503c6..68c17c369578c 100644 --- a/app/code/Magento/Centinel/etc/module.xml +++ b/app/code/Magento/Centinel/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Checkout/etc/module.xml b/app/code/Magento/Checkout/etc/module.xml index 9ce20e05288ee..a4558a93dc165 100644 --- a/app/code/Magento/Checkout/etc/module.xml +++ b/app/code/Magento/Checkout/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/CheckoutAgreements/etc/module.xml b/app/code/Magento/CheckoutAgreements/etc/module.xml index 32e7c203f9ad3..9c3698c779340 100644 --- a/app/code/Magento/CheckoutAgreements/etc/module.xml +++ b/app/code/Magento/CheckoutAgreements/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Cms/etc/module.xml b/app/code/Magento/Cms/etc/module.xml index f06763b72809a..a1e90deba9cc7 100644 --- a/app/code/Magento/Cms/etc/module.xml +++ b/app/code/Magento/Cms/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml index a3b9a10ce9a4c..35789f99cbee9 100644 --- a/app/code/Magento/ConfigurableProduct/etc/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/di.xml @@ -61,13 +61,6 @@ - - - - Magento\ConfigurableProduct\Model\Export\RowCustomizer - - - diff --git a/app/code/Magento/ConfigurableProduct/etc/module.xml b/app/code/Magento/ConfigurableProduct/etc/module.xml index 3779cf96d8669..7601658945adb 100644 --- a/app/code/Magento/ConfigurableProduct/etc/module.xml +++ b/app/code/Magento/ConfigurableProduct/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + @@ -43,7 +43,6 @@ - diff --git a/app/code/Magento/Connect/etc/module.xml b/app/code/Magento/Connect/etc/module.xml index 24f1b50b98c94..8930208afa6c3 100644 --- a/app/code/Magento/Connect/etc/module.xml +++ b/app/code/Magento/Connect/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Contact/etc/module.xml b/app/code/Magento/Contact/etc/module.xml index d0181bcdf9d89..48aad3b40e857 100644 --- a/app/code/Magento/Contact/etc/module.xml +++ b/app/code/Magento/Contact/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Core/etc/di.xml b/app/code/Magento/Core/etc/di.xml index 7746ba1f0d87e..11f0d9edf03e3 100644 --- a/app/code/Magento/Core/etc/di.xml +++ b/app/code/Magento/Core/etc/di.xml @@ -271,11 +271,6 @@ fieldset_config - - - Magento\Framework\Locale\Hierarchy\Config\Reader - - core diff --git a/app/code/Magento/Core/etc/module.xml b/app/code/Magento/Core/etc/module.xml index a48515d1fb7a9..f0f46573fddb5 100644 --- a/app/code/Magento/Core/etc/module.xml +++ b/app/code/Magento/Core/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Cron/etc/module.xml b/app/code/Magento/Cron/etc/module.xml index 98f73ba7c4e5e..c4fa40f4b81de 100644 --- a/app/code/Magento/Cron/etc/module.xml +++ b/app/code/Magento/Cron/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/CurrencySymbol/etc/module.xml b/app/code/Magento/CurrencySymbol/etc/module.xml index 572b7c34aa46d..c8cd1384a86b7 100644 --- a/app/code/Magento/CurrencySymbol/etc/module.xml +++ b/app/code/Magento/CurrencySymbol/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Customer/Controller/Adminhtml/Index.php b/app/code/Magento/Customer/Controller/Adminhtml/Index.php index 8d93dd946f3b5..7a07a12c9b66b 100644 --- a/app/code/Magento/Customer/Controller/Adminhtml/Index.php +++ b/app/code/Magento/Customer/Controller/Adminhtml/Index.php @@ -619,39 +619,6 @@ protected function _extractCustomerAddressData() return $result; } - /** - * Export customer grid to CSV format - * - * @return \Magento\Framework\App\ResponseInterface - */ - public function exportCsvAction() - { - $this->_view->loadLayout(); - $fileName = 'customers.csv'; - /** @var \Magento\Backend\Block\Widget\Grid\ExportInterface $exportBlock */ - $exportBlock = $this->_view->getLayout()->getChildBlock('admin.block.customer.grid', 'grid.export'); - return $this->_fileFactory->create( - $fileName, - $exportBlock->getCsvFile(), - \Magento\Framework\App\Filesystem::VAR_DIR - ); - } - - /** - * Export customer grid to XML format - * - * @return \Magento\Framework\App\ResponseInterface - */ - public function exportXmlAction() - { - $this->_view->loadLayout(); - $fileName = 'customers.xml'; - /** @var \Magento\Backend\Block\Widget\Grid\ExportInterface $exportBlock */ - $exportBlock = $this->_view->getLayout()->getChildBlock('admin.block.customer.grid', 'grid.export'); - $content = $exportBlock->getExcelFile($fileName); - return $this->_fileFactory->create($fileName, $content, \Magento\Framework\App\Filesystem::VAR_DIR); - } - /** * Customer orders grid * diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php index 4dae23458ad1d..c9e5159b97ea2 100644 --- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php +++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php @@ -142,16 +142,17 @@ public function __construct( public function getName() { $name = ''; - $config = $this->_eavConfig; - if ($config->getAttribute('customer_address', 'prefix')->getIsVisible() && $this->getPrefix()) { + if ($this->_eavConfig->getAttribute('customer_address', 'prefix')->getIsVisible() && $this->getPrefix()) { $name .= $this->getPrefix() . ' '; } $name .= $this->getFirstname(); - if ($config->getAttribute('customer_address', 'middlename')->getIsVisible() && $this->getMiddlename()) { + if ($this->_eavConfig->getAttribute('customer_address', 'middlename')->getIsVisible() + && $this->getMiddlename() + ) { $name .= ' ' . $this->getMiddlename(); } $name .= ' ' . $this->getLastname(); - if ($config->getAttribute('customer_address', 'suffix')->getIsVisible() && $this->getSuffix()) { + if ($this->_eavConfig->getAttribute('customer_address', 'suffix')->getIsVisible() && $this->getSuffix()) { $name .= ' ' . $this->getSuffix(); } return $name; @@ -170,7 +171,7 @@ public function getStreet($line = 0) $lines = explode("\n", $this->getStreetFull()); if (0 === $line || $line === null) { return $lines; - } else if (isset($lines[$line - 1])) { + } elseif (isset($lines[$line - 1])) { return $lines[$line - 1]; } else { return ''; @@ -253,7 +254,7 @@ public function setData($key, $value = null) { if (is_array($key)) { $key = $this->_implodeStreetField($key); - } else if ($key == 'street') { + } elseif ($key == 'street') { $value = $this->_implodeStreetValue($value); } return parent::setData($key, $value); @@ -313,24 +314,17 @@ public function getRegion() $regionId = $this->getData('region_id'); $region = $this->getData('region'); - if ($regionId) { - if ($this->getRegionModel($regionId)->getCountryId() == $this->getCountryId()) { - $region = $this->getRegionModel($regionId)->getName(); - $this->setData('region', $region); - } - } - - if (!empty($region) && is_string($region)) { - $this->setData('region', $region); - } elseif (!$regionId && is_numeric($region)) { + if (!$regionId && is_numeric($region)) { if ($this->getRegionModel($region)->getCountryId() == $this->getCountryId()) { $this->setData('region', $this->getRegionModel($region)->getName()); $this->setData('region_id', $region); } - } elseif ($regionId && !$region) { + } elseif ($regionId) { if ($this->getRegionModel($regionId)->getCountryId() == $this->getCountryId()) { $this->setData('region', $this->getRegionModel($regionId)->getName()); } + } elseif (is_string($region)) { + $this->setData('region', $region); } return $this->getData('region'); diff --git a/app/code/Magento/Customer/Model/Address/Converter.php b/app/code/Magento/Customer/Model/Address/Converter.php index 84d61f660673a..50f0ddb4d8cac 100644 --- a/app/code/Magento/Customer/Model/Address/Converter.php +++ b/app/code/Magento/Customer/Model/Address/Converter.php @@ -30,7 +30,6 @@ use Magento\Customer\Model\Address as AddressModel; use Magento\Customer\Model\Address\AbstractAddress; use Magento\Customer\Service\V1\Data\Region; -use Magento\Customer\Service\V1\Data\RegionBuilder; use Magento\Customer\Service\V1\CustomerMetadataServiceInterface; use Magento\Customer\Service\V1\Data\AddressConverter; @@ -54,33 +53,25 @@ class Converter */ protected $_addressFactory; - /** - * @var RegionBuilder - */ - private $_regionBuilder; - /** * Customer metadata service * * @var \Magento\Customer\Service\V1\CustomerMetadataServiceInterface */ - private $_metadataService; + protected $_metadataService; /** * @param AddressBuilder $addressBuilder * @param AddressFactory $addressFactory - * @param RegionBuilder $regionBuilder * @param CustomerMetadataServiceInterface $metadataService */ public function __construct( AddressBuilder $addressBuilder, AddressFactory $addressFactory, - RegionBuilder $regionBuilder, CustomerMetadataServiceInterface $metadataService ) { $this->_addressBuilder = $addressBuilder; $this->_addressFactory = $addressFactory; - $this->_regionBuilder = $regionBuilder; $this->_metadataService = $metadataService; } @@ -110,7 +101,7 @@ public function updateAddressModel(AddressModel $addressModel, Address $address) // Set all attributes $attributes = AddressConverter::toFlatArray($address); foreach ($attributes as $attributeCode => $attributeData) { - if (Address::KEY_REGION == $attributeCode && $address->getRegion() instanceof Region) { + if (Address::KEY_REGION === $attributeCode && $address->getRegion() instanceof Region) { $addressModel->setDataUsingMethod(Region::KEY_REGION, $address->getRegion()->getRegion()); $addressModel->setDataUsingMethod(Region::KEY_REGION_CODE, $address->getRegion()->getRegionCode()); $addressModel->setDataUsingMethod(Region::KEY_REGION_ID, $address->getRegion()->getRegionId()); @@ -170,9 +161,7 @@ public function createAddressFromModel(AbstractAddress $addressModel, $defaultBi } if ($addressModel->getCustomerId() || $addressModel->getParentId()) { - $customerId = $addressModel->getCustomerId() ? $addressModel - ->getCustomerId() : $addressModel - ->getParentId(); + $customerId = $addressModel->getCustomerId() ?: $addressModel->getParentId(); $this->_addressBuilder->setCustomerId($customerId); } diff --git a/app/code/Magento/Customer/Model/Converter.php b/app/code/Magento/Customer/Model/Converter.php index 911e43fd6a337..f714ccc5f4ea5 100644 --- a/app/code/Magento/Customer/Model/Converter.php +++ b/app/code/Magento/Customer/Model/Converter.php @@ -28,6 +28,7 @@ use Magento\Customer\Service\V1\Data\Customer as CustomerDataObject; use Magento\Customer\Service\V1\Data\CustomerBuilder as CustomerDataObjectBuilder; use Magento\Framework\Service\EavDataObjectConverter; +use Magento\Store\Model\StoreManagerInterface; /** * Customer Model converter. @@ -46,14 +47,24 @@ class Converter */ protected $_customerFactory; + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + protected $storeManager; + /** * @param CustomerDataObjectBuilder $customerBuilder * @param CustomerFactory $customerFactory + * @param StoreManagerInterface $storeManager */ - public function __construct(CustomerDataObjectBuilder $customerBuilder, CustomerFactory $customerFactory) - { + public function __construct( + CustomerDataObjectBuilder $customerBuilder, + CustomerFactory $customerFactory, + StoreManagerInterface $storeManager + ) { $this->_customerBuilder = $customerBuilder; $this->_customerFactory = $customerFactory; + $this->storeManager = $storeManager; } /** @@ -120,7 +131,7 @@ public function getCustomerModelByEmail($customerEmail, $websiteId = null) { $customer = $this->_customerFactory->create(); if (!isset($websiteId)) { - $websiteId = $this->_storeManager->getWebsiteId(); + $websiteId = $this->storeManager->getDefaultStoreView()->getWebsiteId(); } $customer->setWebsiteId($websiteId); diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php index 948aab750afbd..06071b38d0802 100644 --- a/app/code/Magento/Customer/Model/Customer.php +++ b/app/code/Magento/Customer/Model/Customer.php @@ -702,16 +702,8 @@ public function isAddressPrimary(Address $address) */ public function sendNewAccountEmail($type = 'registered', $backUrl = '', $storeId = '0') { - /** - * 'registered' welcome email, when confirmation is disabled - * 'confirmed' welcome email, when confirmation is enabled - * 'confirmation' email with confirmation link - */ - $types = array( - 'registered' => self::XML_PATH_REGISTER_EMAIL_TEMPLATE, - 'confirmed' => self::XML_PATH_CONFIRMED_EMAIL_TEMPLATE, - 'confirmation' => self::XML_PATH_CONFIRM_EMAIL_TEMPLATE - ); + $types = $this->getTemplateTypes(); + if (!isset($types[$type])) { throw new \Magento\Framework\Model\Exception(__('Wrong transactional account email type')); } @@ -1301,4 +1293,22 @@ protected function _createCustomerAttribute() { return $this->_attributeFactory->create(); } + + /** + * @return array + */ + protected function getTemplateTypes() + { + /** + * 'registered' welcome email, when confirmation is disabled + * 'confirmed' welcome email, when confirmation is enabled + * 'confirmation' email with confirmation link + */ + $types = array( + 'registered' => self::XML_PATH_REGISTER_EMAIL_TEMPLATE, + 'confirmed' => self::XML_PATH_CONFIRMED_EMAIL_TEMPLATE, + 'confirmation' => self::XML_PATH_CONFIRM_EMAIL_TEMPLATE, + ); + return $types; + } } diff --git a/app/code/Magento/Customer/Service/V1/Data/Address.php b/app/code/Magento/Customer/Service/V1/Data/Address.php index b305edc8cb537..fdb214b9a0b22 100644 --- a/app/code/Magento/Customer/Service/V1/Data/Address.php +++ b/app/code/Magento/Customer/Service/V1/Data/Address.php @@ -27,13 +27,15 @@ class Address extends \Magento\Framework\Service\Data\Eav\AbstractObject { - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ + // FIXME: This constant relates to a quote address object, not this Data Object const ADDRESS_TYPE_BILLING = 'billing'; + // FIXME: This constant relates to a quote address object, not this Data Object const ADDRESS_TYPE_SHIPPING = 'shipping'; + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ const KEY_COUNTRY_ID = 'country_id'; const KEY_DEFAULT_BILLING = 'default_billing'; diff --git a/app/code/Magento/Customer/Service/V1/Data/SearchResults.php b/app/code/Magento/Customer/Service/V1/Data/SearchResults.php index 38a03fcb0ab21..b4c6f1005b0c0 100644 --- a/app/code/Magento/Customer/Service/V1/Data/SearchResults.php +++ b/app/code/Magento/Customer/Service/V1/Data/SearchResults.php @@ -27,7 +27,7 @@ /** * SearchResults Service Data Object used for the search service requests */ -class SearchResults extends \Magento\Framework\Service\Data\AbstractObject +class SearchResults extends \Magento\Framework\Service\V1\Data\SearchResults { /** * Get items @@ -36,26 +36,6 @@ class SearchResults extends \Magento\Framework\Service\Data\AbstractObject */ public function getItems() { - return is_null($this->_get('items')) ? array() : $this->_get('items'); - } - - /** - * Get search criteria - * - * @return \Magento\Framework\Service\V1\Data\SearchCriteria - */ - public function getSearchCriteria() - { - return $this->_get('search_criteria'); - } - - /** - * Get total count - * - * @return int - */ - public function getTotalCount() - { - return $this->_get('total_count'); + return parent::getItems(); } } diff --git a/app/code/Magento/Customer/Service/V1/Data/SearchResultsBuilder.php b/app/code/Magento/Customer/Service/V1/Data/SearchResultsBuilder.php index ec44597bc8bfc..1557a0cf0bece 100644 --- a/app/code/Magento/Customer/Service/V1/Data/SearchResultsBuilder.php +++ b/app/code/Magento/Customer/Service/V1/Data/SearchResultsBuilder.php @@ -24,45 +24,40 @@ namespace Magento\Customer\Service\V1\Data; -use Magento\Framework\Service\V1\Data\SearchCriteria; +use Magento\Framework\Service\Data\ObjectFactory; +use Magento\Framework\Service\V1\Data\SearchCriteriaBuilder; +use Magento\Framework\Service\V1\Data\AbstractSearchResultsBuilder; /** * Builder for the SearchResults Service Data Object * - * @method SearchResults create() + * @method \Magento\Customer\Service\V1\Data\SearchResults create() */ -class SearchResultsBuilder extends \Magento\Framework\Service\Data\AbstractObjectBuilder +class SearchResultsBuilder extends AbstractSearchResultsBuilder { /** - * Set search criteria + * Constructor * - * @param SearchCriteria $searchCriteria - * @return $this + * @param ObjectFactory $objectFactory + * @param SearchCriteriaBuilder $searchCriteriaBuilder + * @param CustomerDetailsBuilder $customerDetailsObjectBuilder */ - public function setSearchCriteria(SearchCriteria $searchCriteria) - { - return $this->_set('search_criteria', $searchCriteria); - } - - /** - * Set total count - * - * @param int $totalCount - * @return $this - */ - public function setTotalCount($totalCount) - { - return $this->_set('total_count', $totalCount); + public function __construct( + ObjectFactory $objectFactory, + SearchCriteriaBuilder $searchCriteriaBuilder, + CustomerDetailsBuilder $customerDetailsObjectBuilder + ) { + parent::__construct($objectFactory, $searchCriteriaBuilder, $customerDetailsObjectBuilder); } /** - * Set items + * Set customer details items * - * @param \Magento\Customer\Service\V1\Data\CustomerDetails[] $items + * @param \Magento\Customer\Service\V1\Data\CustomerDetails[] $customerDetailsItems * @return $this */ - public function setItems($items) + public function setItems($customerDetailsItems) { - return $this->_set('items', $items); + return parent::setItems($customerDetailsItems); } } diff --git a/app/code/Magento/Customer/etc/config.xml b/app/code/Magento/Customer/etc/config.xml index 5e929dc649527..dcbc481bf7dbd 100644 --- a/app/code/Magento/Customer/etc/config.xml +++ b/app/code/Magento/Customer/etc/config.xml @@ -103,11 +103,5 @@ T: {{var telephone}} {{depend vat_id}}
VAT: {{var vat_id}}{{/depend}}|]]> - - - 10000 -
5000
-
-
diff --git a/app/code/Magento/Customer/etc/module.xml b/app/code/Magento/Customer/etc/module.xml index c69e0ccb726d0..91d05a2966cf1 100644 --- a/app/code/Magento/Customer/etc/module.xml +++ b/app/code/Magento/Customer/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + @@ -46,7 +46,6 @@ -
diff --git a/app/code/Magento/Customer/etc/webapi.xml b/app/code/Magento/Customer/etc/webapi.xml index 44c3142d66e2c..2d2179ffa7a68 100644 --- a/app/code/Magento/Customer/etc/webapi.xml +++ b/app/code/Magento/Customer/etc/webapi.xml @@ -140,7 +140,7 @@ - + @@ -155,6 +155,15 @@
+ + + + + + + null + + diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid_block.xml b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid_block.xml index f9ff7bdfb0041..765642a13cade 100644 --- a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid_block.xml +++ b/app/code/Magento/Customer/view/adminhtml/layout/customer_index_grid_block.xml @@ -38,20 +38,6 @@ 1 - - - - - customer/*/exportCsv - CSV - - - customer/*/exportXml - Excel XML - - - - entity_id diff --git a/app/code/Magento/CustomerImportExport/Controller/Adminhtml/Index.php b/app/code/Magento/CustomerImportExport/Controller/Adminhtml/Index.php new file mode 100644 index 0000000000000..c5a7c5ba225cd --- /dev/null +++ b/app/code/Magento/CustomerImportExport/Controller/Adminhtml/Index.php @@ -0,0 +1,82 @@ +_fileFactory = $fileFactory; + parent::__construct($context); + } + + /** + * Export customer grid to CSV format + * + * @return \Magento\Framework\App\ResponseInterface + */ + public function exportCsvAction() + { + $this->_view->loadLayout(); + $fileName = 'customers.csv'; + /** @var \Magento\Backend\Block\Widget\Grid\ExportInterface $exportBlock */ + $exportBlock = $this->_view->getLayout()->getChildBlock('admin.block.customer.grid', 'grid.export'); + return $this->_fileFactory->create( + $fileName, + $exportBlock->getCsvFile(), + \Magento\Framework\App\Filesystem::VAR_DIR + ); + } + + /** + * Export customer grid to XML format + * + * @return \Magento\Framework\App\ResponseInterface + */ + public function exportXmlAction() + { + $this->_view->loadLayout(); + $fileName = 'customers.xml'; + /** @var \Magento\Backend\Block\Widget\Grid\ExportInterface $exportBlock */ + $exportBlock = $this->_view->getLayout()->getChildBlock('admin.block.customer.grid', 'grid.export'); + $content = $exportBlock->getExcelFile($fileName); + return $this->_fileFactory->create($fileName, $content, \Magento\Framework\App\Filesystem::VAR_DIR); + } +} diff --git a/app/code/Magento/Customer/Model/ImportExport/Export/Address.php b/app/code/Magento/CustomerImportExport/Model/Export/Address.php similarity index 97% rename from app/code/Magento/Customer/Model/ImportExport/Export/Address.php rename to app/code/Magento/CustomerImportExport/Model/Export/Address.php index e4dfce921f2d7..bd8929afe956d 100644 --- a/app/code/Magento/Customer/Model/ImportExport/Export/Address.php +++ b/app/code/Magento/CustomerImportExport/Model/Export/Address.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Customer\Model\ImportExport\Export; +namespace Magento\CustomerImportExport\Model\Export; class Address extends \Magento\ImportExport\Model\Export\Entity\AbstractEav { @@ -124,7 +124,7 @@ class Address extends \Magento\ImportExport\Model\Export\Entity\AbstractEav * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Eav\Model\Config $eavConfig * @param \Magento\Customer\Model\Resource\Customer\CollectionFactory $customerColFactory - * @param \Magento\Customer\Model\ImportExport\Export\CustomerFactory $eavCustomerFactory + * @param \Magento\CustomerImportExport\Model\Export\CustomerFactory $eavCustomerFactory * @param \Magento\Customer\Model\Resource\Address\CollectionFactory $addressColFactory * @param array $data */ @@ -136,7 +136,7 @@ public function __construct( \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, \Magento\Eav\Model\Config $eavConfig, \Magento\Customer\Model\Resource\Customer\CollectionFactory $customerColFactory, - \Magento\Customer\Model\ImportExport\Export\CustomerFactory $eavCustomerFactory, + \Magento\CustomerImportExport\Model\Export\CustomerFactory $eavCustomerFactory, \Magento\Customer\Model\Resource\Address\CollectionFactory $addressColFactory, array $data = array() ) { diff --git a/app/code/Magento/Customer/Model/ImportExport/Export/Customer.php b/app/code/Magento/CustomerImportExport/Model/Export/Customer.php similarity index 99% rename from app/code/Magento/Customer/Model/ImportExport/Export/Customer.php rename to app/code/Magento/CustomerImportExport/Model/Export/Customer.php index a92369d3d7110..58bda0850c83a 100644 --- a/app/code/Magento/Customer/Model/ImportExport/Export/Customer.php +++ b/app/code/Magento/CustomerImportExport/Model/Export/Customer.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Customer\Model\ImportExport\Export; +namespace Magento\CustomerImportExport\Model\Export; /** * Export entity customer model diff --git a/app/code/Magento/Customer/Model/ImportExport/Import/AbstractCustomer.php b/app/code/Magento/CustomerImportExport/Model/Import/AbstractCustomer.php similarity index 95% rename from app/code/Magento/Customer/Model/ImportExport/Import/AbstractCustomer.php rename to app/code/Magento/CustomerImportExport/Model/Import/AbstractCustomer.php index 846d3863f823c..2af423a80986a 100644 --- a/app/code/Magento/Customer/Model/ImportExport/Import/AbstractCustomer.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/AbstractCustomer.php @@ -21,9 +21,9 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Customer\Model\ImportExport\Import; +namespace Magento\CustomerImportExport\Model\Import; -use Magento\Customer\Model\Resource\ImportExport\Import\Customer\Storage; +use Magento\CustomerImportExport\Model\Resource\Import\Customer\Storage; /** * Import entity abstract customer model @@ -76,7 +76,7 @@ abstract class AbstractCustomer extends \Magento\ImportExport\Model\Import\Entit protected $_customerStorage; /** - * @var \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory + * @var \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory */ protected $_storageFactory; @@ -95,7 +95,7 @@ abstract class AbstractCustomer extends \Magento\ImportExport\Model\Import\Entit * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\ImportExport\Model\Export\Factory $collectionFactory * @param \Magento\Eav\Model\Config $eavConfig - * @param \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory + * @param \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory * @param array $data */ public function __construct( @@ -108,7 +108,7 @@ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\ImportExport\Model\Export\Factory $collectionFactory, \Magento\Eav\Model\Config $eavConfig, - \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory, + \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory, array $data = array() ) { $this->_storageFactory = $storageFactory; diff --git a/app/code/Magento/Customer/Model/ImportExport/Import/Address.php b/app/code/Magento/CustomerImportExport/Model/Import/Address.php similarity index 98% rename from app/code/Magento/Customer/Model/ImportExport/Import/Address.php rename to app/code/Magento/CustomerImportExport/Model/Import/Address.php index 168925e298077..e685f184a64c2 100644 --- a/app/code/Magento/Customer/Model/ImportExport/Import/Address.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Address.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Customer\Model\ImportExport\Import; +namespace Magento\CustomerImportExport\Model\Import; class Address extends AbstractCustomer { @@ -236,7 +236,7 @@ class Address extends AbstractCustomer * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\ImportExport\Model\Export\Factory $collectionFactory * @param \Magento\Eav\Model\Config $eavConfig - * @param \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory + * @param \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory * @param \Magento\Customer\Model\AddressFactory $addressFactory * @param \Magento\Directory\Model\Resource\Region\CollectionFactory $regionColFactory * @param \Magento\Customer\Model\CustomerFactory $customerFactory @@ -255,7 +255,7 @@ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\ImportExport\Model\Export\Factory $collectionFactory, \Magento\Eav\Model\Config $eavConfig, - \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory, + \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory, \Magento\Customer\Model\AddressFactory $addressFactory, \Magento\Directory\Model\Resource\Region\CollectionFactory $regionColFactory, \Magento\Customer\Model\CustomerFactory $customerFactory, diff --git a/app/code/Magento/Customer/Model/ImportExport/Import/Customer.php b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php similarity index 98% rename from app/code/Magento/Customer/Model/ImportExport/Import/Customer.php rename to app/code/Magento/CustomerImportExport/Model/Import/Customer.php index bf67390988b34..86a218799485f 100644 --- a/app/code/Magento/Customer/Model/ImportExport/Import/Customer.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Customer\Model\ImportExport\Import; +namespace Magento\CustomerImportExport\Model\Import; class Customer extends AbstractCustomer { @@ -142,7 +142,7 @@ class Customer extends AbstractCustomer * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\ImportExport\Model\Export\Factory $collectionFactory * @param \Magento\Eav\Model\Config $eavConfig - * @param \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory + * @param \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory * @param \Magento\Customer\Model\Resource\Attribute\CollectionFactory $attrCollectionFactory * @param \Magento\Customer\Model\CustomerFactory $customerFactory * @param array $data @@ -157,7 +157,7 @@ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\ImportExport\Model\Export\Factory $collectionFactory, \Magento\Eav\Model\Config $eavConfig, - \Magento\Customer\Model\Resource\ImportExport\Import\Customer\StorageFactory $storageFactory, + \Magento\CustomerImportExport\Model\Resource\Import\Customer\StorageFactory $storageFactory, \Magento\Customer\Model\Resource\Attribute\CollectionFactory $attrCollectionFactory, \Magento\Customer\Model\CustomerFactory $customerFactory, array $data = array() diff --git a/app/code/Magento/Customer/Model/ImportExport/Import/CustomerComposite.php b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php similarity index 95% rename from app/code/Magento/Customer/Model/ImportExport/Import/CustomerComposite.php rename to app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php index 73129b34dc821..0a668311f528e 100644 --- a/app/code/Magento/Customer/Model/ImportExport/Import/CustomerComposite.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Customer\Model\ImportExport\Import; +namespace Magento\CustomerImportExport\Model\Import; /** * Import entity customer combined model @@ -68,12 +68,12 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit const ERROR_ROW_IS_ORPHAN = 'rowIsOrphan'; /** - * @var \Magento\Customer\Model\ImportExport\Import\Customer + * @var \Magento\CustomerImportExport\Model\Import\Customer */ protected $_customerEntity; /** - * @var \Magento\Customer\Model\ImportExport\Import\Address + * @var \Magento\CustomerImportExport\Model\Import\Address */ protected $_addressEntity; @@ -153,9 +153,9 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit * @param \Magento\ImportExport\Model\ImportFactory $importFactory * @param \Magento\ImportExport\Model\Resource\Helper $resourceHelper * @param \Magento\Framework\App\Resource $resource - * @param \Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite\DataFactory $dataFactory - * @param \Magento\Customer\Model\ImportExport\Import\CustomerFactory $customerFactory - * @param \Magento\Customer\Model\ImportExport\Import\AddressFactory $addressFactory + * @param \Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite\DataFactory $dataFactory + * @param \Magento\CustomerImportExport\Model\Import\CustomerFactory $customerFactory + * @param \Magento\CustomerImportExport\Model\Import\AddressFactory $addressFactory * @param array $data * * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -167,9 +167,9 @@ public function __construct( \Magento\ImportExport\Model\ImportFactory $importFactory, \Magento\ImportExport\Model\Resource\Helper $resourceHelper, \Magento\Framework\App\Resource $resource, - \Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite\DataFactory $dataFactory, - \Magento\Customer\Model\ImportExport\Import\CustomerFactory $customerFactory, - \Magento\Customer\Model\ImportExport\Import\AddressFactory $addressFactory, + \Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite\DataFactory $dataFactory, + \Magento\CustomerImportExport\Model\Import\CustomerFactory $customerFactory, + \Magento\CustomerImportExport\Model\Import\AddressFactory $addressFactory, array $data = array() ) { parent::__construct($coreData, $string, $scopeConfig, $importFactory, $resourceHelper, $resource, $data); diff --git a/app/code/Magento/Customer/Model/Resource/ImportExport/Import/Customer/Storage.php b/app/code/Magento/CustomerImportExport/Model/Resource/Import/Customer/Storage.php similarity index 98% rename from app/code/Magento/Customer/Model/Resource/ImportExport/Import/Customer/Storage.php rename to app/code/Magento/CustomerImportExport/Model/Resource/Import/Customer/Storage.php index be27ccdc9a681..1808b39b81edd 100644 --- a/app/code/Magento/Customer/Model/Resource/ImportExport/Import/Customer/Storage.php +++ b/app/code/Magento/CustomerImportExport/Model/Resource/Import/Customer/Storage.php @@ -21,7 +21,7 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Customer\Model\Resource\ImportExport\Import\Customer; +namespace Magento\CustomerImportExport\Model\Resource\Import\Customer; class Storage { diff --git a/app/code/Magento/Customer/Model/Resource/ImportExport/Import/CustomerComposite/Data.php b/app/code/Magento/CustomerImportExport/Model/Resource/Import/CustomerComposite/Data.php similarity index 96% rename from app/code/Magento/Customer/Model/Resource/ImportExport/Import/CustomerComposite/Data.php rename to app/code/Magento/CustomerImportExport/Model/Resource/Import/CustomerComposite/Data.php index e3afc316e831d..87855c948daab 100644 --- a/app/code/Magento/Customer/Model/Resource/ImportExport/Import/CustomerComposite/Data.php +++ b/app/code/Magento/CustomerImportExport/Model/Resource/Import/CustomerComposite/Data.php @@ -21,9 +21,9 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Customer\Model\Resource\ImportExport\Import\CustomerComposite; +namespace Magento\CustomerImportExport\Model\Resource\Import\CustomerComposite; -use Magento\Customer\Model\ImportExport\Import\CustomerComposite; +use Magento\CustomerImportExport\Model\Import\CustomerComposite; class Data extends \Magento\ImportExport\Model\Resource\Import\Data { diff --git a/app/code/Magento/ConfigurableProduct/etc/export.xml b/app/code/Magento/CustomerImportExport/etc/adminhtml/routes.xml similarity index 77% rename from app/code/Magento/ConfigurableProduct/etc/export.xml rename to app/code/Magento/CustomerImportExport/etc/adminhtml/routes.xml index 5c91ae4c28b34..45c5ae9691488 100644 --- a/app/code/Magento/ConfigurableProduct/etc/export.xml +++ b/app/code/Magento/CustomerImportExport/etc/adminhtml/routes.xml @@ -23,6 +23,10 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ --> - - - + + + + + + + \ No newline at end of file diff --git a/app/code/Magento/ConfigurableProduct/etc/import.xml b/app/code/Magento/CustomerImportExport/etc/config.xml similarity index 79% rename from app/code/Magento/ConfigurableProduct/etc/import.xml rename to app/code/Magento/CustomerImportExport/etc/config.xml index b1225ec43dd4a..134643cda8056 100644 --- a/app/code/Magento/ConfigurableProduct/etc/import.xml +++ b/app/code/Magento/CustomerImportExport/etc/config.xml @@ -23,6 +23,13 @@ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) */ --> - - + + + + + 10000 +
5000
+
+
+
diff --git a/app/code/Magento/Customer/etc/export.xml b/app/code/Magento/CustomerImportExport/etc/export.xml similarity index 86% rename from app/code/Magento/Customer/etc/export.xml rename to app/code/Magento/CustomerImportExport/etc/export.xml index d04a666696290..cd125c8ab8091 100644 --- a/app/code/Magento/Customer/etc/export.xml +++ b/app/code/Magento/CustomerImportExport/etc/export.xml @@ -24,6 +24,6 @@ */ --> - - + + diff --git a/app/code/Magento/Customer/etc/import.xml b/app/code/Magento/CustomerImportExport/etc/import.xml similarity index 76% rename from app/code/Magento/Customer/etc/import.xml rename to app/code/Magento/CustomerImportExport/etc/import.xml index 5513b3ea241e4..9ac4c55985d00 100644 --- a/app/code/Magento/Customer/etc/import.xml +++ b/app/code/Magento/CustomerImportExport/etc/import.xml @@ -24,7 +24,7 @@ */ --> - - - + + + diff --git a/app/code/Magento/CustomerImportExport/etc/module.xml b/app/code/Magento/CustomerImportExport/etc/module.xml new file mode 100644 index 0000000000000..c86315663dcb0 --- /dev/null +++ b/app/code/Magento/CustomerImportExport/etc/module.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_exportcsv.xml b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportcsv.xml similarity index 100% rename from app/code/Magento/Customer/view/adminhtml/layout/customer_index_exportcsv.xml rename to app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportcsv.xml diff --git a/app/code/Magento/Customer/view/adminhtml/layout/customer_index_exportxml.xml b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportxml.xml similarity index 100% rename from app/code/Magento/Customer/view/adminhtml/layout/customer_index_exportxml.xml rename to app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_import_export_index_exportxml.xml diff --git a/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_index_grid_block.xml b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_index_grid_block.xml new file mode 100644 index 0000000000000..019d8f08b4a41 --- /dev/null +++ b/app/code/Magento/CustomerImportExport/view/adminhtml/layout/customer_index_grid_block.xml @@ -0,0 +1,44 @@ + + + + + + + + + customer_import_export/*/exportCsv + CSV + + + customer_import_export/*/exportXml + Excel XML + + + + + + diff --git a/app/code/Magento/DesignEditor/etc/module.xml b/app/code/Magento/DesignEditor/etc/module.xml index 9cdbed9c9d096..19dc07ee289fc 100644 --- a/app/code/Magento/DesignEditor/etc/module.xml +++ b/app/code/Magento/DesignEditor/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Dhl/etc/module.xml b/app/code/Magento/Dhl/etc/module.xml index 63ad7d986951e..f2422aba3b8d0 100644 --- a/app/code/Magento/Dhl/etc/module.xml +++ b/app/code/Magento/Dhl/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Directory/etc/module.xml b/app/code/Magento/Directory/etc/module.xml index 4ebeb70547d0e..3a7eb13d6537c 100644 --- a/app/code/Magento/Directory/etc/module.xml +++ b/app/code/Magento/Directory/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Downloadable/etc/module.xml b/app/code/Magento/Downloadable/etc/module.xml index be2513d638dc5..d17b2b48cbd58 100644 --- a/app/code/Magento/Downloadable/etc/module.xml +++ b/app/code/Magento/Downloadable/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php index 12b109b527cba..d835114262623 100644 --- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php +++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php @@ -536,9 +536,7 @@ protected function _getDefaultSourceModel() public function isValueEmpty($value) { $attrType = $this->getBackend()->getType(); - $isEmpty = is_array( - $value - ) || + $isEmpty = (is_array($value) && count($value) == 0) || $value === null || $value === false && $attrType != 'int' || $value === '' && ($attrType == 'int' || diff --git a/app/code/Magento/Eav/etc/module.xml b/app/code/Magento/Eav/etc/module.xml index d20dbc8669df9..a07332047bb12 100644 --- a/app/code/Magento/Eav/etc/module.xml +++ b/app/code/Magento/Eav/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Email/etc/module.xml b/app/code/Magento/Email/etc/module.xml index a6e229044674c..bbc8e18e27a4c 100644 --- a/app/code/Magento/Email/etc/module.xml +++ b/app/code/Magento/Email/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Fedex/etc/module.xml b/app/code/Magento/Fedex/etc/module.xml index f335996dc1926..1635c68fe69c1 100644 --- a/app/code/Magento/Fedex/etc/module.xml +++ b/app/code/Magento/Fedex/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/GiftMessage/etc/module.xml b/app/code/Magento/GiftMessage/etc/module.xml index 9dd4428274f65..4cf7227736ef4 100644 --- a/app/code/Magento/GiftMessage/etc/module.xml +++ b/app/code/Magento/GiftMessage/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/GoogleAdwords/etc/module.xml b/app/code/Magento/GoogleAdwords/etc/module.xml index ca5ea54fe48c1..dbfe014290e69 100644 --- a/app/code/Magento/GoogleAdwords/etc/module.xml +++ b/app/code/Magento/GoogleAdwords/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/GoogleAnalytics/etc/module.xml b/app/code/Magento/GoogleAnalytics/etc/module.xml index 3f2b5f92209c1..ca8c5f720e187 100644 --- a/app/code/Magento/GoogleAnalytics/etc/module.xml +++ b/app/code/Magento/GoogleAnalytics/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/GoogleOptimizer/etc/module.xml b/app/code/Magento/GoogleOptimizer/etc/module.xml index 8db326345d6ef..e54380514d7ca 100644 --- a/app/code/Magento/GoogleOptimizer/etc/module.xml +++ b/app/code/Magento/GoogleOptimizer/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/GoogleShopping/etc/module.xml b/app/code/Magento/GoogleShopping/etc/module.xml index 75d213e2b0b3c..f9ef0d68485ea 100644 --- a/app/code/Magento/GoogleShopping/etc/module.xml +++ b/app/code/Magento/GoogleShopping/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/GroupedProduct/etc/module.xml b/app/code/Magento/GroupedProduct/etc/module.xml index f4d35a7d072f1..3363c1f1cb2c1 100644 --- a/app/code/Magento/GroupedProduct/etc/module.xml +++ b/app/code/Magento/GroupedProduct/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + @@ -42,7 +42,6 @@ - diff --git a/app/code/Magento/ImportExport/Helper/Data.php b/app/code/Magento/ImportExport/Helper/Data.php index b1bb25070f612..e5c8acd37f59e 100644 --- a/app/code/Magento/ImportExport/Helper/Data.php +++ b/app/code/Magento/ImportExport/Helper/Data.php @@ -101,7 +101,7 @@ public function getLocalValidPaths() } /** - * Retrieve size of bunch (how much products should be involved in one import iteration) + * Retrieve size of bunch (how many entities should be involved in one import iteration) * * @return int */ diff --git a/app/code/Magento/ImportExport/Model/Export/Config.php b/app/code/Magento/ImportExport/Model/Export/Config.php index e33eb2612a04b..1f45555066144 100644 --- a/app/code/Magento/ImportExport/Model/Export/Config.php +++ b/app/code/Magento/ImportExport/Model/Export/Config.php @@ -49,13 +49,15 @@ public function getEntities() } /** - * Retrieve export product types configuration + * Retrieve export entity types configuration * + * @param string $entity * @return array */ - public function getProductTypes() + public function getEntityTypes($entity) { - return $this->get('productTypes'); + $entities = $this->getEntities(); + return isset($entities[$entity]) ? $entities[$entity]['types'] : []; } /** diff --git a/app/code/Magento/ImportExport/Model/Export/Config/Converter.php b/app/code/Magento/ImportExport/Model/Export/Config/Converter.php index 7efef561c11f0..becbc4ec2fc43 100644 --- a/app/code/Magento/ImportExport/Model/Export/Config/Converter.php +++ b/app/code/Magento/ImportExport/Model/Export/Config/Converter.php @@ -34,33 +34,43 @@ class Converter implements \Magento\Framework\Config\ConverterInterface */ public function convert($source) { - $output = array('entities' => array(), 'productTypes' => array(), 'fileFormats' => array()); + $output = array('entities' => array(), 'fileFormats' => array()); /** @var \DOMNodeList $entities */ $entities = $source->getElementsByTagName('entity'); - /** @var DOMNode $entityConfig */ + /** @var \DOMNode $entityConfig */ foreach ($entities as $entityConfig) { $attributes = $entityConfig->attributes; $name = $attributes->getNamedItem('name')->nodeValue; $label = $attributes->getNamedItem('label')->nodeValue; $model = $attributes->getNamedItem('model')->nodeValue; + $entityAttributeFilterType = $attributes->getNamedItem('entityAttributeFilterType')->nodeValue; - $output['entities'][$name] = array('name' => $name, 'label' => $label, 'model' => $model); + $output['entities'][$name] = array( + 'name' => $name, + 'label' => $label, + 'model' => $model, + 'types' => [], + 'entityAttributeFilterType' => $entityAttributeFilterType + ); } - /** @var \DOMNodeList $productTypes */ - $productTypes = $source->getElementsByTagName('productType'); - /** @var DOMNode $productTypeConfig */ - foreach ($productTypes as $productTypeConfig) { - $attributes = $productTypeConfig->attributes; + /** @var \DOMNodeList $entityTypes */ + $entityTypes = $source->getElementsByTagName('entityType'); + /** @var \DOMNode $entityTypeConfig */ + foreach ($entityTypes as $entityTypeConfig) { + $attributes = $entityTypeConfig->attributes; $model = $attributes->getNamedItem('model')->nodeValue; $name = $attributes->getNamedItem('name')->nodeValue; + $entity = $attributes->getNamedItem('entity')->nodeValue; - $output['productTypes'][$name] = array('name' => $name, 'model' => $model); + if (isset($output['entities'][$entity])) { + $output['entities'][$entity]['types'][$name] = array('name' => $name, 'model' => $model); + } } /** @var \DOMNodeList $fileFormats */ $fileFormats = $source->getElementsByTagName('fileFormat'); - /** @var DOMNode $fileFormatConfig */ + /** @var \DOMNode $fileFormatConfig */ foreach ($fileFormats as $fileFormatConfig) { $attributes = $fileFormatConfig->attributes; $name = $attributes->getNamedItem('name')->nodeValue; diff --git a/app/code/Magento/ImportExport/Model/Export/Config/Reader.php b/app/code/Magento/ImportExport/Model/Export/Config/Reader.php index 3af7804593e0d..e99cf220038a5 100644 --- a/app/code/Magento/ImportExport/Model/Export/Config/Reader.php +++ b/app/code/Magento/ImportExport/Model/Export/Config/Reader.php @@ -32,7 +32,7 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem */ protected $_idAttributes = array( '/config/entity' => 'name', - '/config/productType' => 'name', + '/config/entityType' => ['entity', 'name'], '/config/fileFormat' => 'name' ); diff --git a/app/code/Magento/ImportExport/Model/Export/ConfigInterface.php b/app/code/Magento/ImportExport/Model/Export/ConfigInterface.php index f44dc05dc9762..75c11464707ec 100644 --- a/app/code/Magento/ImportExport/Model/Export/ConfigInterface.php +++ b/app/code/Magento/ImportExport/Model/Export/ConfigInterface.php @@ -40,9 +40,10 @@ public function getEntities(); public function getFileFormats(); /** - * Retrieve import product types configuration + * Retrieve import entity types configuration * + * @param string $entity * @return array */ - public function getProductTypes(); + public function getEntityTypes($entity); } diff --git a/app/code/Magento/ImportExport/Model/Import.php b/app/code/Magento/ImportExport/Model/Import.php index 9e2c52e676021..3d32f02d68d80 100644 --- a/app/code/Magento/ImportExport/Model/Import.php +++ b/app/code/Magento/ImportExport/Model/Import.php @@ -75,15 +75,6 @@ class Import extends \Magento\ImportExport\Model\AbstractModel */ protected $_entityAdapter; - /** - * Entity invalidated indexes. - * - * @var \Magento\ImportExport\Model\Import\Entity\AbstractEntity - */ - protected static $_entityInvalidatedIndexes = array( - 'catalog_product' => array('catalog_product_price', 'catalogsearch_fulltext', 'catalog_product_flat') - ); - /** * Import export data * @@ -470,66 +461,6 @@ public function isImportAllowed() return $this->_getEntityAdapter()->isImportAllowed(); } - /** - * Import source file structure to DB. - * - * @return void - */ - public function expandSource() - { - /** @var $writer \Magento\ImportExport\Model\Export\Adapter\Csv */ - $writer = $this->_csvFactory->create(array('destination' => $this->getWorkingDir() . "big0.csv")); - $regExps = array('last' => '/(.*?)(\d+)$/', 'middle' => '/(.*?)(\d+)(.*)$/'); - $colReg = array( - 'sku' => 'last', - 'name' => 'last', - 'description' => 'last', - 'short_description' => 'last', - 'url_key' => 'middle', - 'meta_title' => 'last', - 'meta_keyword' => 'last', - 'meta_description' => 'last', - '_related_sku' => 'last', - '_crosssell_sku' => 'last', - '_upsell_sku' => 'last', - '_custom_option_sku' => 'middle', - '_custom_option_row_sku' => 'middle', - '_super_products_sku' => 'last', - '_associated_sku' => 'last' - ); - $size = self::DEFAULT_SIZE; - - $filename = 'catalog_product.csv'; - $filenameFormat = 'big%s.csv'; - foreach ($this->_getSourceAdapter($this->getWorkingDir() . $filename) as $row) { - $writer->writeRow($row); - } - $count = self::MAX_IMPORT_CHUNKS; - for ($i = 1; $i < $count; $i++) { - $writer = $this->_csvFactory->create( - array('destination' => $this->getWorkingDir() . sprintf($filenameFormat, $i)) - ); - - $adapter = $this->_getSourceAdapter($this->getWorkingDir() . sprintf($filenameFormat, $i - 1)); - foreach ($adapter as $row) { - $writer->writeRow($row); - } - $adapter = $this->_getSourceAdapter($this->getWorkingDir() . sprintf($filenameFormat, $i - 1)); - foreach ($adapter as $row) { - foreach ($colReg as $colName => $regExpType) { - if (!empty($row[$colName])) { - preg_match($regExps[$regExpType], $row[$colName], $matches); - - $row[$colName] = $matches[1] . ($matches[2] + $size) . ('middle' == - $regExpType ? $matches[3] : ''); - } - } - $writer->writeRow($row); - } - $size *= 2; - } - } - /** * Move uploaded file and create source adapter instance. * @@ -635,12 +566,12 @@ public function validateSource(\Magento\ImportExport\Model\Import\AbstractSource */ public function invalidateIndex() { - if (!isset(self::$_entityInvalidatedIndexes[$this->getEntity()])) { + $relatedIndexers = $this->_importConfig->getRelatedIndexers($this->getEntity()); + if (empty($relatedIndexers)) { return $this; } - $indexers = self::$_entityInvalidatedIndexes[$this->getEntity()]; - foreach ($indexers as $indexer) { + foreach ($relatedIndexers as $indexer) { $indexProcess = $this->_indexer->getProcessByCode($indexer); if ($indexProcess) { $indexProcess->changeStatus(\Magento\Index\Model\Process::STATUS_REQUIRE_REINDEX); diff --git a/app/code/Magento/ImportExport/Model/Import/Config.php b/app/code/Magento/ImportExport/Model/Import/Config.php index 1628e3a76b5f7..d10c571593201 100644 --- a/app/code/Magento/ImportExport/Model/Import/Config.php +++ b/app/code/Magento/ImportExport/Model/Import/Config.php @@ -49,12 +49,26 @@ public function getEntities() } /** - * Retrieve import product types configuration + * Retrieve import entity types configuration * + * @param string $entity * @return array */ - public function getProductTypes() + public function getEntityTypes($entity) { - return $this->get('productTypes'); + $entities = $this->getEntities(); + return isset($entities[$entity]) ? $entities[$entity]['types'] : []; + } + + /** + * Retrieve a list of indexes which are affected by import of the specified entity. + * + * @param string $entity + * @return array + */ + public function getRelatedIndexers($entity) + { + $entities = $this->getEntities(); + return isset($entities[$entity]) ? $entities[$entity]['relatedIndexers'] : []; } } diff --git a/app/code/Magento/ImportExport/Model/Import/Config/Converter.php b/app/code/Magento/ImportExport/Model/Import/Config/Converter.php index ee029a69ba6c9..c70ef45957881 100644 --- a/app/code/Magento/ImportExport/Model/Import/Config/Converter.php +++ b/app/code/Magento/ImportExport/Model/Import/Config/Converter.php @@ -34,10 +34,10 @@ class Converter implements \Magento\Framework\Config\ConverterInterface */ public function convert($source) { - $output = array('entities' => array(), 'productTypes' => array()); - /** @var \DOMNodeList $events */ + $output = array('entities' => array()); + /** @var \DOMNodeList $entities */ $entities = $source->getElementsByTagName('entity'); - /** @var DOMNode $entityConfig */ + /** @var \DOMNode $entityConfig */ foreach ($entities as $entityConfig) { $attributes = $entityConfig->attributes; $name = $attributes->getNamedItem('name')->nodeValue; @@ -49,19 +49,37 @@ public function convert($source) 'name' => $name, 'label' => $label, 'behaviorModel' => $behaviorModel, - 'model' => $model + 'model' => $model, + 'types' => [], + 'relatedIndexers' => [] ); } - /** @var \DOMNodeList $events */ - $productTypes = $source->getElementsByTagName('productType'); - /** @var DOMNode $productTypeConfig */ - foreach ($productTypes as $productTypeConfig) { - $attributes = $productTypeConfig->attributes; + /** @var \DOMNodeList $entityTypes */ + $entityTypes = $source->getElementsByTagName('entityType'); + /** @var \DOMNode $entityTypeConfig */ + foreach ($entityTypes as $entityTypeConfig) { + $attributes = $entityTypeConfig->attributes; $name = $attributes->getNamedItem('name')->nodeValue; $model = $attributes->getNamedItem('model')->nodeValue; + $entity = $attributes->getNamedItem('entity')->nodeValue; - $output['productTypes'][$name] = array('name' => $name, 'model' => $model); + if (isset($output['entities'][$entity])) { + $output['entities'][$entity]['types'][$name] = array('name' => $name, 'model' => $model); + } + } + + /** @var \DOMNodeList $relatedIndexers */ + $relatedIndexers = $source->getElementsByTagName('relatedIndexer'); + /** @var \DOMNode $relatedIndexerConfig */ + foreach ($relatedIndexers as $relatedIndexerConfig) { + $attributes = $relatedIndexerConfig->attributes; + $name = $attributes->getNamedItem('name')->nodeValue; + $entity = $attributes->getNamedItem('entity')->nodeValue; + + if (isset($output['entities'][$entity])) { + $output['entities'][$entity]['relatedIndexers'][$name] = array('name' => $name); + } } return $output; } diff --git a/app/code/Magento/ImportExport/Model/Import/Config/Reader.php b/app/code/Magento/ImportExport/Model/Import/Config/Reader.php index c5ffde57603e9..473b8e20406be 100644 --- a/app/code/Magento/ImportExport/Model/Import/Config/Reader.php +++ b/app/code/Magento/ImportExport/Model/Import/Config/Reader.php @@ -30,7 +30,11 @@ class Reader extends \Magento\Framework\Config\Reader\Filesystem * * @var array */ - protected $_idAttributes = array('/config/entity' => 'name', '/config/productType' => 'name'); + protected $_idAttributes = array( + '/config/entity' => 'name', + '/config/entityType' => ['entity', 'name'], + '/config/relatedIndexers' => ['entity', 'name'] + ); /** * @param \Magento\Framework\Config\FileResolverInterface $fileResolver diff --git a/app/code/Magento/ImportExport/Model/Import/ConfigInterface.php b/app/code/Magento/ImportExport/Model/Import/ConfigInterface.php index b0e83ba0971d4..09412af615fb7 100644 --- a/app/code/Magento/ImportExport/Model/Import/ConfigInterface.php +++ b/app/code/Magento/ImportExport/Model/Import/ConfigInterface.php @@ -33,9 +33,18 @@ interface ConfigInterface public function getEntities(); /** - * Retrieve import product types configuration + * Retrieve import entity types configuration * + * @param string $entity * @return array */ - public function getProductTypes(); + public function getEntityTypes($entity); + + /** + * Retrieve a list of indexes which are affected by import of the specified entity. + * + * @param string $entity + * @return array + */ + public function getRelatedIndexers($entity); } diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php index a9c9a809ede43..d538afdb5dccd 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php @@ -310,7 +310,7 @@ protected function _prepareRowForDb(array $rowData) protected function _saveValidatedBunches() { $source = $this->_getSource(); - $productDataSize = 0; + $currentDataSize = 0; $bunchRows = array(); $startNewBunch = false; $nextRowBackup = array(); @@ -325,7 +325,7 @@ protected function _saveValidatedBunches() $this->_dataSourceModel->saveBunch($this->getEntityTypeCode(), $this->getBehavior(), $bunchRows); $bunchRows = $nextRowBackup; - $productDataSize = strlen(serialize($bunchRows)); + $currentDataSize = strlen(serialize($bunchRows)); $startNewBunch = false; $nextRowBackup = array(); } @@ -345,12 +345,12 @@ protected function _saveValidatedBunches() $isBunchSizeExceeded = $bunchSize > 0 && count($bunchRows) >= $bunchSize; - if ($productDataSize + $rowSize >= $maxDataSize || $isBunchSizeExceeded) { + if ($currentDataSize + $rowSize >= $maxDataSize || $isBunchSizeExceeded) { $startNewBunch = true; $nextRowBackup = array($source->key() => $rowData); } else { $bunchRows[$source->key()] = $rowData; - $productDataSize += $rowSize; + $currentDataSize += $rowSize; } } $source->next(); diff --git a/app/code/Magento/ImportExport/etc/di.xml b/app/code/Magento/ImportExport/etc/di.xml index 0f22db67afc88..9e68c41b71649 100644 --- a/app/code/Magento/ImportExport/etc/di.xml +++ b/app/code/Magento/ImportExport/etc/di.xml @@ -26,7 +26,6 @@ - diff --git a/app/code/Magento/ImportExport/etc/export.xsd b/app/code/Magento/ImportExport/etc/export.xsd index 6f1cb2439ef12..c55da5a826b20 100644 --- a/app/code/Magento/ImportExport/etc/export.xsd +++ b/app/code/Magento/ImportExport/etc/export.xsd @@ -28,7 +28,7 @@ - + @@ -41,15 +41,6 @@ - - - - Export product type name must be unique. - - - - - @@ -70,14 +61,16 @@ + - + - Export product type declaration. + Export entity type declaration. + diff --git a/app/code/Magento/ImportExport/etc/import.xsd b/app/code/Magento/ImportExport/etc/import.xsd index d7986b3d927e3..ce78486632ea3 100644 --- a/app/code/Magento/ImportExport/etc/import.xsd +++ b/app/code/Magento/ImportExport/etc/import.xsd @@ -28,7 +28,8 @@ - + + @@ -40,15 +41,6 @@ - - - - Import product type name must be unique. - - - - - @@ -63,16 +55,27 @@ - + - Import product type declaration. + Import entity type declaration. + + + + + Related index type declaration. + + + + + + diff --git a/app/code/Magento/ImportExport/etc/module.xml b/app/code/Magento/ImportExport/etc/module.xml index 620e9e9784722..79e5ba267a3b3 100644 --- a/app/code/Magento/ImportExport/etc/module.xml +++ b/app/code/Magento/ImportExport/etc/module.xml @@ -24,19 +24,13 @@ */ --> - - - - + - - - diff --git a/app/code/Magento/ImportExport/i18n/de_DE.csv b/app/code/Magento/ImportExport/i18n/de_DE.csv index 81144bd120fa7..9cb478aa704eb 100644 --- a/app/code/Magento/ImportExport/i18n/de_DE.csv +++ b/app/code/Magento/ImportExport/i18n/de_DE.csv @@ -17,8 +17,6 @@ "Entity Attributes","Entitätenattribute" "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","Entity-Adapter-Objekt muss eine Anwendung von \Magento\ImportExport\Model\Import\Entity\Abstract sein" "Entity is unknown","Entity ist unbekannt" -"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","Entity-Modelltyp muss eine Anwendung von \Magento\ImportExport\Model\Import\Entity\Abstract sein" -"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","Entity-Modelltyp muss eine Anwendung von \Magento\ImportExport\Model\Import\Entity\Abstract sein" "Error in data structure: behaviors are mixed","Fehler in der Datenstruktur: Vorgehensweisen sind unterschiedlich" "Error in data structure: entity codes are mixed","Fehler in der Datenstruktur: Entity-Codes sind unterschiedlich" "Export","Export" diff --git a/app/code/Magento/ImportExport/i18n/en_US.csv b/app/code/Magento/ImportExport/i18n/en_US.csv index 0a40a1c4e6978..962df32c6e537 100644 --- a/app/code/Magento/ImportExport/i18n/en_US.csv +++ b/app/code/Magento/ImportExport/i18n/en_US.csv @@ -17,8 +17,6 @@ "Entity Attributes","Entity Attributes" "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract" "Entity is unknown","Entity is unknown" -"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType" -"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract" "Error in data structure: behaviors are mixed","Error in data structure: behaviors are mixed" "Error in data structure: entity codes are mixed","Error in data structure: entity codes are mixed" "Export","Export" diff --git a/app/code/Magento/ImportExport/i18n/es_ES.csv b/app/code/Magento/ImportExport/i18n/es_ES.csv index dcb5a99694fa8..eec75a789d9a2 100644 --- a/app/code/Magento/ImportExport/i18n/es_ES.csv +++ b/app/code/Magento/ImportExport/i18n/es_ES.csv @@ -17,8 +17,6 @@ "Entity Attributes","Atributos de la Entidad" "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","El objeto de adaptador de entidad debe ser una instancia de \Magento\ImportExport\Model\Import\Entity\Abstract" "Entity is unknown","Entidad desconocida" -"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","El modelo de tipo de entidad debe ser una instancia de \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType" -"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","El modelo de tipo de entidad debe ser una instancia de \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract" "Error in data structure: behaviors are mixed","Error en la estructura de datos: hay conductas mezcladas" "Error in data structure: entity codes are mixed","Error en la estructura de datos: hay códigos de entidad mezclados" "Export","Exportar" diff --git a/app/code/Magento/ImportExport/i18n/fr_FR.csv b/app/code/Magento/ImportExport/i18n/fr_FR.csv index 8173cf0a379e7..0d1bdd15ff411 100644 --- a/app/code/Magento/ImportExport/i18n/fr_FR.csv +++ b/app/code/Magento/ImportExport/i18n/fr_FR.csv @@ -17,8 +17,6 @@ "Entity Attributes","Attributs de l'entité" "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","L'objet adaptateur doit être une isntance de \Magento\ImportExport\Model\Import\Entity\Abstract" "Entity is unknown","Entitée inconnue" -"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","Le type de modèle de l'entité doit être une instance de \Magento\ImportExport\Model\Import\Entity\Abstract" -"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","Le type de modèle de l'entité doit être une instance de \Magento\ImportExport\Model\Import\Entity\Abstract" "Error in data structure: behaviors are mixed","Erreur dans la structure des données : les comportements sont mélangés" "Error in data structure: entity codes are mixed","Erreur dans la structure des données : les codes d'entité sont mélangés" "Export","Exporter" diff --git a/app/code/Magento/ImportExport/i18n/nl_NL.csv b/app/code/Magento/ImportExport/i18n/nl_NL.csv index 7ecd00543297b..1e1dc6c99f66e 100644 --- a/app/code/Magento/ImportExport/i18n/nl_NL.csv +++ b/app/code/Magento/ImportExport/i18n/nl_NL.csv @@ -17,8 +17,6 @@ "Entity Attributes","Eenheidattributen" "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","Entiteit adapterobject moet een instantie zijn van Magento_ImportExport_model_Import_Entity_Abstract" "Entity is unknown","Entiteit is onbekend" -"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","Entiteit type model moet een instantie zijn van \Magento\ImportExport\Model\Export_Entiteit_Product_Type_Abstract" -"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","Entiteit type model moet een instantie zijn van \Magento\ImportExport\Model\Import_Entiteit_Product_Type_Abstract" "Error in data structure: behaviors are mixed","Fout in datastructuur: gedragingen zijn gemengd" "Error in data structure: entity codes are mixed","Fout in datastructuur: entiteitcodes zijn gemengd" "Export","Export" diff --git a/app/code/Magento/ImportExport/i18n/pt_BR.csv b/app/code/Magento/ImportExport/i18n/pt_BR.csv index 30cb102184031..adfeda3cb848d 100644 --- a/app/code/Magento/ImportExport/i18n/pt_BR.csv +++ b/app/code/Magento/ImportExport/i18n/pt_BR.csv @@ -17,8 +17,6 @@ "Entity Attributes","Atributos da entidade" "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","Objeto adaptador da entidade deve ser uma instância de \Magento\ImportExport\Model\Import\Entity\Abstract" "Entity is unknown","Entidade desconhecida" -"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","Modelo de tipo de entidade deve ser uma instância de \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType" -"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","Modelo de tipo de entidade deve ser uma instância de \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract" "Error in data structure: behaviors are mixed","Erro na estrutura de dados: os comportamentos estão misturados" "Error in data structure: entity codes are mixed","Erro na estrutura de dados: os códigos de entidade estão misturados" "Export","Exportar" diff --git a/app/code/Magento/ImportExport/i18n/zh_CN.csv b/app/code/Magento/ImportExport/i18n/zh_CN.csv index eb832ccb3b707..bed37847c2265 100644 --- a/app/code/Magento/ImportExport/i18n/zh_CN.csv +++ b/app/code/Magento/ImportExport/i18n/zh_CN.csv @@ -17,8 +17,6 @@ "Entity Attributes","编辑属性" "Entity adapter object must be an instance of \Magento\ImportExport\Model\Import\Entity\Abstract","实体适配器对象必须为\Magento\ImportExport\Model\Import\Entity\Abstract的实例" "Entity is unknown","未知实体" -"Entity type model must be an instance of \Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType","实体类型模块必须为\Magento\ImportExport\Model\Export\Entity\Product\Type\AbstractType的实例" -"Entity type model must be an instance of \Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract","实体类型模块必须为\Magento\ImportExport\Model\Import\Entity\Product\Type\Abstract的实例" "Error in data structure: behaviors are mixed","数据结构有误:行为是混合的" "Error in data structure: entity codes are mixed","数据结构有误:实体代码是混合的" "Export","导出" diff --git a/app/code/Magento/ImportExport/sql/importexport_setup/install-1.6.0.0.php b/app/code/Magento/ImportExport/sql/importexport_setup/install-1.6.0.0.php index db778d4a17414..f3e4445712909 100644 --- a/app/code/Magento/ImportExport/sql/importexport_setup/install-1.6.0.0.php +++ b/app/code/Magento/ImportExport/sql/importexport_setup/install-1.6.0.0.php @@ -60,42 +60,4 @@ ); $installer->getConnection()->createTable($table); -/** - * Add unique key for 'catalog_product_link_attribute_int' table - */ -$installer->getConnection()->addIndex( - $installer->getTable('catalog_product_link_attribute_int'), - $installer->getIdxName( - 'catalog_product_link_attribute_int', - array('product_link_attribute_id', 'link_id'), - \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE - ), - array('product_link_attribute_id', 'link_id'), - \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_UNIQUE -); - -/** - * Add foreign keys for 'catalog_product_link_attribute_int' table - */ -$installer->getConnection()->addForeignKey( - $installer->getFkName('catalog_product_link_attribute_int', 'link_id', 'catalog_product_link', 'link_id'), - $installer->getTable('catalog_product_link_attribute_int'), - 'link_id', - $installer->getTable('catalog_product_link'), - 'link_id' -); - -$installer->getConnection()->addForeignKey( - $installer->getFkName( - 'catalog_product_link_attribute_int', - 'product_link_attribute_id', - 'catalog_product_link_attribute', - 'product_link_attribute_id' - ), - $installer->getTable('catalog_product_link_attribute_int'), - 'product_link_attribute_id', - $installer->getTable('catalog_product_link_attribute'), - 'product_link_attribute_id' -); - $installer->endSetup(); diff --git a/app/code/Magento/Index/etc/module.xml b/app/code/Magento/Index/etc/module.xml index 7adaab6cadc48..8ff8a9e206d54 100644 --- a/app/code/Magento/Index/etc/module.xml +++ b/app/code/Magento/Index/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Indexer/etc/module.xml b/app/code/Magento/Indexer/etc/module.xml index 22eadde60c568..6e4005bd52607 100644 --- a/app/code/Magento/Indexer/etc/module.xml +++ b/app/code/Magento/Indexer/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Install/etc/module.xml b/app/code/Magento/Install/etc/module.xml index 45e9608efdf9d..bb2fd20c81ddc 100644 --- a/app/code/Magento/Install/etc/module.xml +++ b/app/code/Magento/Install/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Integration/Block/Adminhtml/Widget/Grid/Column/Renderer/Name.php b/app/code/Magento/Integration/Block/Adminhtml/Widget/Grid/Column/Renderer/Name.php new file mode 100644 index 0000000000000..2e270d68ff82f --- /dev/null +++ b/app/code/Magento/Integration/Block/Adminhtml/Widget/Grid/Column/Renderer/Name.php @@ -0,0 +1,47 @@ +getEndpoint(), 'http:') === 0) { + $text .= 'Integration not secure'; + } + return $text; + } +} diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration.php index ec032ac70029a..ab82118a0f789 100644 --- a/app/code/Magento/Integration/Controller/Adminhtml/Integration.php +++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration.php @@ -26,7 +26,7 @@ use Magento\Backend\App\Action; use Magento\Integration\Block\Adminhtml\Integration\Edit\Tab\Info; use Magento\Integration\Exception as IntegrationException; -use Magento\Integration\Service\OauthV1Interface as IntegrationOauthService; +use Magento\Integration\Service\V1\OauthInterface as IntegrationOauthService; use Magento\Integration\Model\Integration as IntegrationModel; /** @@ -52,7 +52,7 @@ class Integration extends Action /** @var \Magento\Framework\Logger */ protected $_logger; - /** @var \Magento\Integration\Service\IntegrationV1Interface */ + /** @var \Magento\Integration\Service\V1\IntegrationInterface */ private $_integrationService; /** @var IntegrationOauthService */ @@ -64,6 +64,9 @@ class Integration extends Action /** @var \Magento\Integration\Helper\Data */ protected $_integrationData; + /** @var \Magento\Integration\Model\Resource\Integration\Collection */ + protected $_integrationCollection; + /** * @var \Magento\Framework\Escaper */ @@ -73,21 +76,23 @@ class Integration extends Action * @param \Magento\Backend\App\Action\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Logger $logger - * @param \Magento\Integration\Service\IntegrationV1Interface $integrationService + * @param \Magento\Integration\Service\V1\IntegrationInterface $integrationService * @param IntegrationOauthService $oauthService * @param \Magento\Core\Helper\Data $coreHelper * @param \Magento\Integration\Helper\Data $integrationData * @param \Magento\Framework\Escaper $escaper + * @param \Magento\Integration\Model\Resource\Integration\Collection $integrationCollection */ public function __construct( \Magento\Backend\App\Action\Context $context, \Magento\Framework\Registry $registry, \Magento\Framework\Logger $logger, - \Magento\Integration\Service\IntegrationV1Interface $integrationService, + \Magento\Integration\Service\V1\IntegrationInterface $integrationService, IntegrationOauthService $oauthService, \Magento\Core\Helper\Data $coreHelper, \Magento\Integration\Helper\Data $integrationData, - \Magento\Framework\Escaper $escaper + \Magento\Framework\Escaper $escaper, + \Magento\Integration\Model\Resource\Integration\Collection $integrationCollection ) { parent::__construct($context); $this->_registry = $registry; @@ -97,6 +102,7 @@ public function __construct( $this->_coreHelper = $coreHelper; $this->_integrationData = $integrationData; $this->escaper = $escaper; + $this->_integrationCollection = $integrationCollection; parent::__construct($context); } @@ -107,6 +113,13 @@ public function __construct( */ public function indexAction() { + $unsecureEndpointsCount = $this->_integrationCollection->addUnsecureEndpointFilter()->getSize(); + if ($unsecureEndpointsCount > 0) { + // @codingStandardsIgnoreStart + $this->messageManager->addNotice(__('Warning! Integrations not using HTTPS are insecure and potentially expose private or personally identifiable information') + // @codingStandardsIgnoreEnd + ); + } $this->_view->loadLayout(); $this->_setActiveMenu('Magento_Integration::system_integrations'); $this->_addBreadcrumb(__('Integrations'), __('Integrations')); diff --git a/app/code/Magento/Integration/Controller/Token.php b/app/code/Magento/Integration/Controller/Token.php index 8e954b18fb2c8..e3d368fe19694 100644 --- a/app/code/Magento/Integration/Controller/Token.php +++ b/app/code/Magento/Integration/Controller/Token.php @@ -23,8 +23,8 @@ */ namespace Magento\Integration\Controller; -use Magento\Integration\Service\OauthV1Interface as IntegrationOauthService; -use Magento\Integration\Service\IntegrationV1Interface as IntegrationService; +use Magento\Integration\Service\V1\OauthInterface as IntegrationOauthService; +use Magento\Integration\Service\V1\IntegrationInterface as IntegrationService; use Magento\Integration\Model\Integration as IntegrationModel; /** diff --git a/app/code/Magento/Integration/Model/Manager.php b/app/code/Magento/Integration/Model/Manager.php index f895f8f540593..c8331b8370daf 100644 --- a/app/code/Magento/Integration/Model/Manager.php +++ b/app/code/Magento/Integration/Model/Manager.php @@ -35,7 +35,7 @@ class Manager /** * Integration service * - * @var \Magento\Integration\Service\IntegrationV1Interface + * @var \Magento\Integration\Service\V1\IntegrationInterface */ protected $_integrationService; @@ -48,11 +48,11 @@ class Manager /** * @param Config $integrationConfig - * @param \Magento\Integration\Service\IntegrationV1Interface $integrationService + * @param \Magento\Integration\Service\V1\IntegrationInterface $integrationService */ public function __construct( Config $integrationConfig, - \Magento\Integration\Service\IntegrationV1Interface $integrationService + \Magento\Integration\Service\V1\IntegrationInterface $integrationService ) { $this->_integrationService = $integrationService; $this->_integrationConfig = $integrationConfig; diff --git a/app/code/Magento/Integration/Model/Oauth/Nonce/Generator.php b/app/code/Magento/Integration/Model/Oauth/Nonce/Generator.php index f825bbe6fcd8e..16a040f82b05c 100644 --- a/app/code/Magento/Integration/Model/Oauth/Nonce/Generator.php +++ b/app/code/Magento/Integration/Model/Oauth/Nonce/Generator.php @@ -23,7 +23,6 @@ */ namespace Magento\Integration\Model\Oauth\Nonce; -use Magento\Framework\Oauth\OauthInterface; use Magento\Framework\Oauth\ConsumerInterface; use Magento\Framework\Oauth\NonceGeneratorInterface; @@ -96,9 +95,8 @@ public function validateNonce(ConsumerInterface $consumer, $nonce, $timestamp) try { $timestamp = (int)$timestamp; if ($timestamp <= 0 || $timestamp > time() + self::TIME_DEVIATION) { - throw new \Magento\Framework\Oauth\Exception( - __('Incorrect timestamp value in the oauth_timestamp parameter'), - OauthInterface::ERR_TIMESTAMP_REFUSED + throw new \Magento\Framework\Oauth\OauthInputException( + 'Incorrect timestamp value in the oauth_timestamp parameter' ); } @@ -107,8 +105,8 @@ public function validateNonce(ConsumerInterface $consumer, $nonce, $timestamp) if ($nonceObj->getNonce()) { throw new \Magento\Framework\Oauth\Exception( - __('The nonce is already being used by the consumer with ID %1', $consumer->getId()), - OauthInterface::ERR_NONCE_USED + 'The nonce is already being used by the consumer with ID %1', + [$consumer->getId()] ); } @@ -116,7 +114,7 @@ public function validateNonce(ConsumerInterface $consumer, $nonce, $timestamp) } catch (\Magento\Framework\Oauth\Exception $exception) { throw $exception; } catch (\Exception $exception) { - throw new \Magento\Framework\Oauth\Exception(__('An error occurred validating the nonce')); + throw new \Magento\Framework\Oauth\Exception('An error occurred validating the nonce'); } } } diff --git a/app/code/Magento/Integration/Model/Oauth/Token.php b/app/code/Magento/Integration/Model/Oauth/Token.php index 17031e0c46615..67f2a3632d417 100644 --- a/app/code/Magento/Integration/Model/Oauth/Token.php +++ b/app/code/Magento/Integration/Model/Oauth/Token.php @@ -210,17 +210,17 @@ public function createVerifierToken($consumerId) public function authorize($userId, $userType) { if (!$this->getId() || !$this->getConsumerId()) { - throw new OauthException(__('Token is not ready to be authorized')); + throw new OauthException('Token is not ready to be authorized'); } if ($this->getAuthorized()) { - throw new OauthException(__('Token is already authorized')); + throw new OauthException('Token is already authorized'); } if (self::USER_TYPE_ADMIN == $userType) { $this->setAdminId($userId); } elseif (self::USER_TYPE_CUSTOMER == $userType) { $this->setCustomerId($userId); } else { - throw new OauthException(__('User type is unknown')); + throw new OauthException('User type is unknown'); } $this->setVerifier($this->_oauthHelper->generateVerifier()); @@ -241,7 +241,7 @@ public function authorize($userId, $userType) public function convertToAccess() { if (self::TYPE_REQUEST != $this->getType()) { - throw new OauthException(__('Cannot convert to access token due to token is not request type')); + throw new OauthException('Cannot convert to access token due to token is not request type'); } $this->setType(self::TYPE_ACCESS); @@ -289,7 +289,7 @@ public function getUserType() } elseif ($this->getCustomerId()) { return self::USER_TYPE_CUSTOMER; } else { - throw new OauthException(__('User type is unknown')); + throw new OauthException('User type is unknown'); } } diff --git a/app/code/Magento/Integration/Model/Oauth/Token/Provider.php b/app/code/Magento/Integration/Model/Oauth/Token/Provider.php index 80ae2077b0564..8ca3ff82b52b2 100644 --- a/app/code/Magento/Integration/Model/Oauth/Token/Provider.php +++ b/app/code/Magento/Integration/Model/Oauth/Token/Provider.php @@ -23,7 +23,6 @@ */ namespace Magento\Integration\Model\Oauth\Token; -use Magento\Framework\Oauth\OauthInterface; use Magento\Framework\Oauth\TokenProviderInterface; class Provider implements TokenProviderInterface @@ -76,8 +75,7 @@ public function validateConsumer($consumer) $expiry = $this->_dataHelper->getConsumerExpirationPeriod(); if ($this->_date->timestamp() - $consumerTS > $expiry) { throw new \Magento\Framework\Oauth\Exception( - __('Consumer key has expired'), - OauthInterface::ERR_CONSUMER_KEY_INVALID + 'Consumer key has expired' ); } return true; @@ -91,8 +89,7 @@ public function createRequestToken($consumer) $token = $this->getTokenByConsumerId($consumer->getId()); if ($token->getType() != \Magento\Integration\Model\Oauth\Token::TYPE_VERIFIER) { throw new \Magento\Framework\Oauth\Exception( - __('Cannot create request token because consumer token is not a verifier token'), - OauthInterface::ERR_TOKEN_REJECTED + 'Cannot create request token because consumer token is not a verifier token' ); } $requestToken = $token->createRequestToken($token->getId(), $consumer->getCallbackUrl()); @@ -108,8 +105,7 @@ public function validateRequestToken($requestToken, $consumer, $oauthVerifier) if (!$this->_isTokenAssociatedToConsumer($token, $consumer)) { throw new \Magento\Framework\Oauth\Exception( - __('Request token is not associated with the specified consumer'), - OauthInterface::ERR_TOKEN_REJECTED + 'Request token is not associated with the specified consumer' ); } @@ -117,8 +113,7 @@ public function validateRequestToken($requestToken, $consumer, $oauthVerifier) // In this flow (token flow) the token has to be of type "request" else its marked as reused. if (\Magento\Integration\Model\Oauth\Token::TYPE_REQUEST != $token->getType()) { throw new \Magento\Framework\Oauth\Exception( - __('Token is already being used'), - OauthInterface::ERR_TOKEN_USED + 'Token is already being used' ); } @@ -136,7 +131,7 @@ public function getAccessToken($consumer) $token = $this->getTokenByConsumerId($consumer->getId()); if (\Magento\Integration\Model\Oauth\Token::TYPE_REQUEST != $token->getType()) { throw new \Magento\Framework\Oauth\Exception( - __('Cannot get access token because consumer token is not a request token') + 'Cannot get access token because consumer token is not a request token' ); } $accessToken = $token->convertToAccess(); @@ -152,20 +147,17 @@ public function validateAccessTokenRequest($accessToken, $consumer) if (!$this->_isTokenAssociatedToConsumer($token, $consumer)) { throw new \Magento\Framework\Oauth\Exception( - __('Token is not associated with the specified consumer'), - OauthInterface::ERR_TOKEN_REJECTED + 'Token is not associated with the specified consumer' ); } if (\Magento\Integration\Model\Oauth\Token::TYPE_ACCESS != $token->getType()) { throw new \Magento\Framework\Oauth\Exception( - __('Token is not an access token'), - OauthInterface::ERR_TOKEN_REJECTED + 'Token is not an access token' ); } if ($token->getRevoked()) { throw new \Magento\Framework\Oauth\Exception( - __('Access token has been revoked'), - OauthInterface::ERR_TOKEN_REVOKED + 'Access token has been revoked' ); } @@ -183,15 +175,13 @@ public function validateAccessToken($accessToken) if (\Magento\Integration\Model\Oauth\Token::TYPE_ACCESS != $token->getType()) { throw new \Magento\Framework\Oauth\Exception( - __('Token is not an access token'), - OauthInterface::ERR_TOKEN_REJECTED + 'Token is not an access token' ); } if ($token->getRevoked()) { throw new \Magento\Framework\Oauth\Exception( - __('Access token has been revoked'), - OauthInterface::ERR_TOKEN_REVOKED + 'Access token has been revoked' ); } @@ -213,8 +203,7 @@ public function getConsumerByKey($consumerKey) { if (strlen($consumerKey) != \Magento\Framework\Oauth\Helper\Oauth::LENGTH_CONSUMER_KEY) { throw new \Magento\Framework\Oauth\Exception( - __('Consumer key is not the correct length'), - OauthInterface::ERR_CONSUMER_KEY_REJECTED + 'Consumer key is not the correct length' ); } @@ -222,8 +211,7 @@ public function getConsumerByKey($consumerKey) if (!$consumer->getId()) { throw new \Magento\Framework\Oauth\Exception( - __('A consumer having the specified key does not exist'), - OauthInterface::ERR_CONSUMER_KEY_REJECTED + 'A consumer having the specified key does not exist' ); } @@ -242,20 +230,17 @@ protected function _validateVerifierParam($oauthVerifier, $tokenVerifier) { if (!is_string($oauthVerifier)) { throw new \Magento\Framework\Oauth\Exception( - __('Verifier is invalid'), - OauthInterface::ERR_VERIFIER_INVALID + 'Verifier is invalid' ); } if (!$this->validateOauthToken($oauthVerifier)) { throw new \Magento\Framework\Oauth\Exception( - __('Verifier is not the correct length'), - OauthInterface::ERR_VERIFIER_INVALID + 'Verifier is not the correct length' ); } if ($tokenVerifier != $oauthVerifier) { throw new \Magento\Framework\Oauth\Exception( - __('Token verifier and verifier token do not match'), - OauthInterface::ERR_VERIFIER_INVALID + 'Token verifier and verifier token do not match' ); } } @@ -273,8 +258,8 @@ protected function _getConsumer($consumerId) if (!$consumer->getId()) { throw new \Magento\Framework\Oauth\Exception( - __('A consumer with the ID %1 does not exist', $consumerId), - OauthInterface::ERR_TOKEN_REJECTED + 'A consumer with the ID %1 does not exist', + [$consumerId] ); } @@ -292,8 +277,7 @@ protected function _getToken($token) { if (!$this->validateOauthToken($token)) { throw new \Magento\Framework\Oauth\Exception( - __('Token is not the correct length'), - OauthInterface::ERR_TOKEN_REJECTED + 'Token is not the correct length' ); } @@ -301,8 +285,7 @@ protected function _getToken($token) if (!$tokenObj->getId()) { throw new \Magento\Framework\Oauth\Exception( - __('Specified token does not exist'), - OauthInterface::ERR_TOKEN_REJECTED + 'Specified token does not exist' ); } @@ -322,8 +305,8 @@ public function getTokenByConsumerId($consumerId) if (!$token->getId()) { throw new \Magento\Framework\Oauth\Exception( - __('A token with consumer ID %1 does not exist', $consumerId), - OauthInterface::ERR_TOKEN_REJECTED + 'A token with consumer ID %1 does not exist', + [$consumerId] ); } diff --git a/app/code/Magento/Integration/Model/Resource/Integration/Collection.php b/app/code/Magento/Integration/Model/Resource/Integration/Collection.php index 837e9f132be7a..7000a98e04458 100644 --- a/app/code/Magento/Integration/Model/Resource/Integration/Collection.php +++ b/app/code/Magento/Integration/Model/Resource/Integration/Collection.php @@ -37,4 +37,14 @@ protected function _construct() { $this->_init('Magento\Integration\Model\Integration', 'Magento\Integration\Model\Resource\Integration'); } + + /** + * Get unsecure enpoints + * + * @return $this + */ + public function addUnsecureEndpointFilter() + { + return $this->addFieldToFilter('endpoint', ['like' => 'http:%']); + } } diff --git a/app/code/Magento/Integration/Service/IntegrationV1.php b/app/code/Magento/Integration/Service/V1/Integration.php similarity index 96% rename from app/code/Magento/Integration/Service/IntegrationV1.php rename to app/code/Magento/Integration/Service/V1/Integration.php index b667f3827e9df..9158e6de05f32 100644 --- a/app/code/Magento/Integration/Service/IntegrationV1.php +++ b/app/code/Magento/Integration/Service/V1/Integration.php @@ -21,18 +21,18 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Integration\Service; +namespace Magento\Integration\Service\V1; use Magento\Integration\Model\Integration\Factory as IntegrationFactory; use Magento\Integration\Model\Integration as IntegrationModel; -use Magento\Integration\Service\OauthV1Interface as IntegrationOauthService; +use Magento\Integration\Service\V1\OauthInterface as IntegrationOauthService; /** * Integration Service. * * This service is used to interact with integrations. */ -class IntegrationV1 implements \Magento\Integration\Service\IntegrationV1Interface +class Integration implements \Magento\Integration\Service\V1\IntegrationInterface { /** * @var IntegrationFactory diff --git a/app/code/Magento/Integration/Service/IntegrationV1Interface.php b/app/code/Magento/Integration/Service/V1/IntegrationInterface.php similarity index 96% rename from app/code/Magento/Integration/Service/IntegrationV1Interface.php rename to app/code/Magento/Integration/Service/V1/IntegrationInterface.php index 1b8dfa4d0db78..473d6926dd4e1 100644 --- a/app/code/Magento/Integration/Service/IntegrationV1Interface.php +++ b/app/code/Magento/Integration/Service/V1/IntegrationInterface.php @@ -21,14 +21,14 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Integration\Service; +namespace Magento\Integration\Service\V1; use Magento\Integration\Model\Integration as IntegrationModel; /** * Integration Service Interface */ -interface IntegrationV1Interface +interface IntegrationInterface { /** * Create a new Integration diff --git a/app/code/Magento/Integration/Service/OauthV1.php b/app/code/Magento/Integration/Service/V1/Oauth.php similarity index 95% rename from app/code/Magento/Integration/Service/OauthV1.php rename to app/code/Magento/Integration/Service/V1/Oauth.php index acbcdc3037f34..054de2b401356 100644 --- a/app/code/Magento/Integration/Service/OauthV1.php +++ b/app/code/Magento/Integration/Service/V1/Oauth.php @@ -21,9 +21,8 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Integration\Service; +namespace Magento\Integration\Service\V1; -use Magento\Framework\Oauth\OauthInterface; use Magento\Integration\Model\Oauth\Token\Provider as TokenProvider; use Magento\Integration\Model\Oauth\Token; use Magento\Integration\Model\Oauth\Token\Factory as TokenFactory; @@ -38,7 +37,7 @@ * TODO: Fix coupling between objects * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class OauthV1 implements OauthV1Interface +class Oauth implements OauthInterface { /** * @var \Magento\Store\Model\StoreManagerInterface @@ -127,7 +126,7 @@ public function createConsumer($consumerData) throw $exception; } catch (\Exception $exception) { throw new \Magento\Framework\Oauth\Exception( - __('Unexpected error. Unable to create oAuth consumer account.') + 'Unexpected error. Unable to create oAuth consumer account.' ); } } @@ -184,7 +183,7 @@ public function loadConsumer($consumerId) throw $exception; } catch (\Exception $exception) { throw new \Magento\Framework\Oauth\Exception( - __('Unexpected error. Unable to load oAuth consumer account.') + 'Unexpected error. Unable to load oAuth consumer account.' ); } } @@ -200,7 +199,7 @@ public function loadConsumerByKey($key) throw $exception; } catch (\Exception $exception) { throw new \Magento\Framework\Oauth\Exception( - __('Unexpected error. Unable to load oAuth consumer account.') + 'Unexpected error. Unable to load oAuth consumer account.' ); } } @@ -242,7 +241,7 @@ public function postToConsumer($consumerId, $endpointUrl) } catch (\Exception $exception) { $this->_logger->logException($exception); throw new \Magento\Framework\Oauth\Exception( - __('Unable to post data to consumer due to an unexpected error') + 'Unable to post data to consumer due to an unexpected error' ); } } diff --git a/app/code/Magento/Integration/Service/OauthV1Interface.php b/app/code/Magento/Integration/Service/V1/OauthInterface.php similarity index 98% rename from app/code/Magento/Integration/Service/OauthV1Interface.php rename to app/code/Magento/Integration/Service/V1/OauthInterface.php index 6731d4f030ee4..7a1859b1bd4ee 100644 --- a/app/code/Magento/Integration/Service/OauthV1Interface.php +++ b/app/code/Magento/Integration/Service/V1/OauthInterface.php @@ -21,14 +21,14 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -namespace Magento\Integration\Service; +namespace Magento\Integration\Service\V1; use Magento\Integration\Model\Oauth\Token; /** * Integration oAuth Service Interface */ -interface OauthV1Interface +interface OauthInterface { /** * Create a new consumer account. diff --git a/app/code/Magento/Integration/etc/di.xml b/app/code/Magento/Integration/etc/di.xml index 7b4ba5c7dec2a..1557064be5b65 100644 --- a/app/code/Magento/Integration/etc/di.xml +++ b/app/code/Magento/Integration/etc/di.xml @@ -24,8 +24,8 @@ */ --> - - + + diff --git a/app/code/Magento/Integration/etc/module.xml b/app/code/Magento/Integration/etc/module.xml index e25b38c846e55..e16c617dce958 100644 --- a/app/code/Magento/Integration/etc/module.xml +++ b/app/code/Magento/Integration/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml b/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml index 472b36bbb20ac..c738e2992d166 100644 --- a/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml +++ b/app/code/Magento/Integration/view/adminhtml/layout/adminhtml_integration_grid_block.xml @@ -51,6 +51,7 @@ text name name + Magento\Integration\Block\Adminhtml\Widget\Grid\Column\Renderer\Name 1
diff --git a/app/code/Magento/Integration/view/adminhtml/web/js/integration.js b/app/code/Magento/Integration/view/adminhtml/web/js/integration.js index 69157d6ca4de9..e65a16b13857a 100644 --- a/app/code/Magento/Integration/view/adminhtml/web/js/integration.js +++ b/app/code/Magento/Integration/view/adminhtml/web/js/integration.js @@ -300,6 +300,10 @@ // Get integration name either from current element or from neighbor column var integrationName = $(ctx).attr('data-row-name') || $(ctx).parents('tr').find('.col-name').html().trim(); + if (integrationName.indexOf(' -1) { + // Remove unsecure URL warning from popup window title if it is present + integrationName = integrationName.substring(0, integrationName.indexOf('searchFilterList + + + Magento\CatalogSearch\Model\Layer\Advanced + Magento\Catalog\Model\Layer\Search\AvailabilityFlag + advancedSearchFilterList + + Magento\Catalog\Model\Layer\Category @@ -48,4 +55,9 @@ Magento\Catalog\Model\Layer\Search + + + Magento\CatalogSearch\Model\Layer\Advanced + +
diff --git a/app/code/Magento/LayeredNavigation/etc/module.xml b/app/code/Magento/LayeredNavigation/etc/module.xml index c0aa73544598d..b16e24563ebda 100644 --- a/app/code/Magento/LayeredNavigation/etc/module.xml +++ b/app/code/Magento/LayeredNavigation/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/LayeredNavigation/view/frontend/layout/catalogsearch_advanced_result.xml b/app/code/Magento/LayeredNavigation/view/frontend/layout/catalogsearch_advanced_result.xml new file mode 100644 index 0000000000000..21260bcdc509b --- /dev/null +++ b/app/code/Magento/LayeredNavigation/view/frontend/layout/catalogsearch_advanced_result.xml @@ -0,0 +1,33 @@ + + + + + + + + + + diff --git a/app/code/Magento/Log/etc/module.xml b/app/code/Magento/Log/etc/module.xml index deeb8f6a6d188..f9ec0aeae871e 100644 --- a/app/code/Magento/Log/etc/module.xml +++ b/app/code/Magento/Log/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Multishipping/etc/module.xml b/app/code/Magento/Multishipping/etc/module.xml index d9b44bf9785bc..31cfef37fe5e6 100644 --- a/app/code/Magento/Multishipping/etc/module.xml +++ b/app/code/Magento/Multishipping/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Newsletter/etc/module.xml b/app/code/Magento/Newsletter/etc/module.xml index 0ed329fcb4222..3f4d2f1b35071 100644 --- a/app/code/Magento/Newsletter/etc/module.xml +++ b/app/code/Magento/Newsletter/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/OfflinePayments/etc/module.xml b/app/code/Magento/OfflinePayments/etc/module.xml index cecfda746ac1b..24f917885dbea 100644 --- a/app/code/Magento/OfflinePayments/etc/module.xml +++ b/app/code/Magento/OfflinePayments/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/OfflineShipping/etc/module.xml b/app/code/Magento/OfflineShipping/etc/module.xml index a8fd8cafc290e..bd98e5a2db568 100644 --- a/app/code/Magento/OfflineShipping/etc/module.xml +++ b/app/code/Magento/OfflineShipping/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Ogone/etc/module.xml b/app/code/Magento/Ogone/etc/module.xml index 7858fceddce93..d5a600a2aa7da 100644 --- a/app/code/Magento/Ogone/etc/module.xml +++ b/app/code/Magento/Ogone/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/PageCache/etc/module.xml b/app/code/Magento/PageCache/etc/module.xml index 85eb07eae8cd0..4d3e606528743 100644 --- a/app/code/Magento/PageCache/etc/module.xml +++ b/app/code/Magento/PageCache/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/PayPalRecurringPayment/Model/Api/Nvp.php b/app/code/Magento/PayPalRecurringPayment/Model/Api/Nvp.php index 585ae7c71a2b3..2e0e73571745e 100644 --- a/app/code/Magento/PayPalRecurringPayment/Model/Api/Nvp.php +++ b/app/code/Magento/PayPalRecurringPayment/Model/Api/Nvp.php @@ -96,6 +96,9 @@ class Nvp extends \Magento\Paypal\Model\Api\Nvp * @param \Magento\Directory\Model\RegionFactory $regionFactory * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory * @param \Magento\Directory\Model\CountryFactory $countryFactory + * @param \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory + * @param \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory + * @param \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory * @param \Magento\RecurringPayment\Model\QuoteImporter $quoteImporter * @param array $data */ @@ -106,6 +109,9 @@ public function __construct( \Magento\Directory\Model\RegionFactory $regionFactory, \Magento\Framework\Logger\AdapterFactory $logAdapterFactory, \Magento\Directory\Model\CountryFactory $countryFactory, + \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory, + \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory, + \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory, \Magento\RecurringPayment\Model\QuoteImporter $quoteImporter, array $data = array() ) { @@ -116,6 +122,9 @@ public function __construct( $regionFactory, $logAdapterFactory, $countryFactory, + $processableExceptionFactory, + $frameworkExceptionFactory, + $curlFactory, $data ); $this->_quoteImporter = $quoteImporter; diff --git a/app/code/Magento/PayPalRecurringPayment/etc/module.xml b/app/code/Magento/PayPalRecurringPayment/etc/module.xml index 8f0cd9b74a67f..1a7957cf93bbe 100644 --- a/app/code/Magento/PayPalRecurringPayment/etc/module.xml +++ b/app/code/Magento/PayPalRecurringPayment/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Payment/etc/module.xml b/app/code/Magento/Payment/etc/module.xml index 59f19e657f1d0..08103caabeffe 100644 --- a/app/code/Magento/Payment/etc/module.xml +++ b/app/code/Magento/Payment/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php index b980a40108709..f1577d038dbd9 100644 --- a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php +++ b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/ApiWizard.php @@ -28,6 +28,11 @@ */ class ApiWizard extends \Magento\Backend\Block\System\Config\Form\Field { + /** + * Path to block template + */ + const WIZARD_TEMPLATE = 'system/config/api_wizard.phtml'; + /** * Set template to itself * @@ -37,7 +42,7 @@ protected function _prepareLayout() { parent::_prepareLayout(); if (!$this->getTemplate()) { - $this->setTemplate('system/config/api_wizard.phtml'); + $this->setTemplate(static::WIZARD_TEMPLATE); } return $this; } diff --git a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/BmlApiWizard.php b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/BmlApiWizard.php new file mode 100644 index 0000000000000..96b1f2357a61a --- /dev/null +++ b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/BmlApiWizard.php @@ -0,0 +1,52 @@ +getOriginalData(); + $this->addData( + array( + 'button_label' => __($originalData['button_label']), + 'button_url' => $originalData['button_url'], + 'html_id' => $element->getHtmlId(), + ) + ); + return $this->_toHtml(); + } +} diff --git a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Location.php b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Location.php index 03f52d5de07e8..c7a044c9b91d7 100644 --- a/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Location.php +++ b/app/code/Magento/Paypal/Block/Adminhtml/System/Config/Fieldset/Location.php @@ -252,6 +252,26 @@ public function render(\Magento\Framework\Data\Form\Element\AbstractElement $ele } paypalConflictsObject.ecCheckAvailability(); paypalConflictsObject.sharePayflowEnabling(enabler, isEvent); + }, + handleBmlEnabler: function(event) { + required = Event.element(event); + var bml = $(required).bmlEnabler; + if (required.value == "1") { + bml.value = "1"; + } + paypalConflictsObject.toggleBmlEnabler(required); + }, + + toggleBmlEnabler: function(required) { + var bml = $(required).bmlEnabler; + if (!bml) { + return; + } + if (required.value != "1") { + bml.value = "0"; + $(bml).disable(); + } + $(bml).requiresObj.indicateEnabled(); } }; @@ -308,9 +328,19 @@ public function render(\Magento\Framework\Data\Form\Element\AbstractElement $ele $(ecPayflowScopeElement).click(); } } + $$(".paypal-bml").each(function(bmlEnabler) { + $(bmlEnabler).classNames().each(function(className) { + if (className.indexOf("requires-") !== -1) { + var required = $(className.replace("requires-", "")); + required.bmlEnabler = bmlEnabler; + Event.observe(required, "change", paypalConflictsObject.handleBmlEnabler); + } + }); + }); $$(".paypal-enabler").each(function(enablerElement) { paypalConflictsObject.checkPaymentConflicts(enablerElement, "initial"); + paypalConflictsObject.toggleBmlEnabler(enablerElement); }); if (paypalConflictsObject.isConflict || paypalConflictsObject.ecMissed) { var notification = \'' . diff --git a/app/code/Magento/Paypal/Block/Bml/Banners.php b/app/code/Magento/Paypal/Block/Bml/Banners.php new file mode 100644 index 0000000000000..96d29f791e93e --- /dev/null +++ b/app/code/Magento/Paypal/Block/Bml/Banners.php @@ -0,0 +1,80 @@ +_section = isset($data['section']) ? (string)$data['section'] : ''; + $this->_position = isset($data['position']) ? (int)$data['position'] : 0; + $this->_paypalConfig = $paypalConfig; + parent::__construct($context, $data); + } + + /** + * Disable block output if banner turned off or PublisherId is miss + * + * @return string + */ + protected function _toHtml() + { + $publisherId = $this->_paypalConfig->getBmlPublisherId(); + $display = $this->_paypalConfig->getBmlDisplay($this->_section); + $position = $this->_paypalConfig->getBmlPosition($this->_section); + if (!$publisherId || $display == 0 || $this->_position != $position) { + return ''; + } + $this->setData('publisher_id', $publisherId); + $this->setData('size', $this->_paypalConfig->getBmlSize($this->_section)); + return parent::_toHtml(); + } +} diff --git a/app/code/Magento/Paypal/Block/Bml/Form.php b/app/code/Magento/Paypal/Block/Bml/Form.php new file mode 100644 index 0000000000000..e057f8fbb1832 --- /dev/null +++ b/app/code/Magento/Paypal/Block/Bml/Form.php @@ -0,0 +1,56 @@ +_config = $this->_paypalConfigFactory->create()->setMethod($this->getMethodCode()); + /** @var $mark \Magento\Framework\View\Element\Template */ + $mark = $this->_getMarkTemplate(); + $mark->setPaymentAcceptanceMarkHref( + 'https://www.securecheckout.billmelater.com/paycapture-content/' + . 'fetch?hash=AU826TU8&content=/bmlweb/ppwpsiw.html' + )->setPaymentAcceptanceMarkSrc('https://www.paypalobjects.com/en_US/i/logo/logo_BMLPP_90x34.gif') + ->setPaymentWhatIs(__('See terms')); + + $this->_initializeRedirectTemplateWithMark($mark); + } +} diff --git a/app/code/Magento/Paypal/Block/Bml/Shortcut.php b/app/code/Magento/Paypal/Block/Bml/Shortcut.php new file mode 100644 index 0000000000000..61d55a5c657a9 --- /dev/null +++ b/app/code/Magento/Paypal/Block/Bml/Shortcut.php @@ -0,0 +1,196 @@ +_paymentData = $paymentData; + $this->_mathRandom = $mathRandom; + $this->_shortcutValidator = $shortcutValidator; + + $this->_paymentMethodCode = $paymentMethodCode; + $this->_startAction = $startAction; + $this->_alias = $alias; + $this->_bmlMethodCode = $bmlMethodCode; + parent::__construct($context, $data); + } + + /** + * @return \Magento\Framework\View\Element\AbstractBlock + */ + protected function _beforeToHtml() + { + $result = parent::_beforeToHtml(); + $isInCatalog = $this->getIsInCatalogProduct(); + if (!$this->_shortcutValidator->validate($this->_paymentMethodCode, $isInCatalog)) { + $this->_shouldRender = false; + return $result; + } + + /** @var \Magento\Paypal\Model\Express $method */ + $method = $this->_paymentData->getMethodInstance($this->_bmlMethodCode); + if (!$method || !$method->isAvailable()) { + $this->_shouldRender = false; + return $result; + } + + $this->setShortcutHtmlId($this->_mathRandom->getUniqueHash('ec_shortcut_bml_')) + ->setCheckoutUrl($this->getUrl($this->_startAction)) + ->setImageUrl(self::SHORTCUT_IMAGE) + ->setAdditionalLinkImage( + [ + 'href' => 'https://www.securecheckout.billmelater.com/paycapture-content/' + . 'fetch?hash=AU826TU8&content=/bmlweb/ppwpsiw.html', + 'src' => 'https://www.paypalobjects.com/webstatic/en_US/btn/btn_bml_text.png' + ] + ); + + return $result; + } + + /** + * Render the block if needed + * + * @return string + */ + protected function _toHtml() + { + if (!$this->_shouldRender) { + return ''; + } + return parent::_toHtml(); + } + + /** + * Check is "OR" label position before shortcut + * + * @return bool + */ + public function isOrPositionBefore() + { + return $this->getShowOrPosition() == CatalogBlock\ShortcutButtons::POSITION_BEFORE; + } + + /** + * Check is "OR" label position after shortcut + * + * @return bool + */ + public function isOrPositionAfter() + { + return $this->getShowOrPosition() == CatalogBlock\ShortcutButtons::POSITION_AFTER; + } + + /** + * Get shortcut alias + * + * @return string + */ + public function getAlias() + { + return $this->_alias; + } +} diff --git a/app/code/Magento/Paypal/Block/Express/Review.php b/app/code/Magento/Paypal/Block/Express/Review.php index 1f64895327eab..bf3005b4035d1 100644 --- a/app/code/Magento/Paypal/Block/Express/Review.php +++ b/app/code/Magento/Paypal/Block/Express/Review.php @@ -240,8 +240,6 @@ protected function _beforeToHtml() { $methodInstance = $this->_quote->getPayment()->getMethodInstance(); $this->setPaymentMethodTitle($methodInstance->getTitle()); - $this->setUpdateOrderSubmitUrl($this->getUrl("{$this->_controllerPath}/updateOrder")); - $this->setUpdateShippingMethodsUrl($this->getUrl("{$this->_controllerPath}/updateShippingMethods")); $this->setShippingRateRequired(true); if ($this->_quote->getIsVirtual()) { @@ -263,11 +261,13 @@ protected function _beforeToHtml() } } + $canEditShippingAddress = $this->_quote->getMayEditShippingAddress() && $this->_quote->getPayment() + ->getAdditionalInformation(\Magento\Paypal\Model\Express\Checkout::PAYMENT_INFO_BUTTON) == 1; // misc shipping parameters $this->setShippingMethodSubmitUrl( $this->getUrl("{$this->_controllerPath}/saveShippingMethod") )->setCanEditShippingAddress( - $this->_quote->getMayEditShippingAddress() + $canEditShippingAddress )->setCanEditShippingMethod( $this->_quote->getMayEditShippingMethod() ); diff --git a/app/code/Magento/Paypal/Block/Express/Shortcut.php b/app/code/Magento/Paypal/Block/Express/Shortcut.php index 8f508fad6dea1..86c0c87bc24cc 100644 --- a/app/code/Magento/Paypal/Block/Express/Shortcut.php +++ b/app/code/Magento/Paypal/Block/Express/Shortcut.php @@ -24,6 +24,7 @@ namespace Magento\Paypal\Block\Express; use Magento\Catalog\Block as CatalogBlock; +use Magento\Paypal\Helper\Shortcut\ValidatorInterface; /** * Paypal express checkout shortcut link @@ -42,35 +43,28 @@ class Shortcut extends \Magento\Framework\View\Element\Template implements Catal * * @var string */ - protected $_paymentMethodCode = \Magento\Paypal\Model\Config::METHOD_WPP_EXPRESS; + protected $_paymentMethodCode = ''; /** * Start express action * * @var string */ - protected $_startAction = 'paypal/express/start'; + protected $_startAction = ''; /** * Express checkout model factory name * * @var string */ - protected $_checkoutType = 'Magento\Paypal\Model\Express\Checkout'; + protected $_checkoutType = ''; /** - * Core registry + * Shortcut alias * - * @var \Magento\Framework\Registry - */ - protected $_registry; - - /** - * Payment data - * - * @var \Magento\Payment\Helper\Data + * @var string */ - protected $_paymentData; + protected $_alias = ''; /** * Paypal data @@ -79,11 +73,6 @@ class Shortcut extends \Magento\Framework\View\Element\Template implements Catal */ protected $_paypalData; - /** - * @var \Magento\Customer\Model\Session - */ - protected $_customerSession; - /** * @var \Magento\Paypal\Model\ConfigFactory */ @@ -102,12 +91,7 @@ class Shortcut extends \Magento\Framework\View\Element\Template implements Catal /** * @var \Magento\Framework\Math\Random */ - protected $mathRandom; - - /** - * @var \Magento\Catalog\Model\ProductTypes\ConfigInterface - */ - protected $productTypeConfig; + protected $_mathRandom; /** * @var \Magento\Customer\Helper\Session\CurrentCustomer @@ -119,46 +103,56 @@ class Shortcut extends \Magento\Framework\View\Element\Template implements Catal */ protected $_localeResolver; + /** + * @var ValidatorInterface + */ + private $_shortcutValidator; + /** * @param \Magento\Framework\View\Element\Template\Context $context * @param \Magento\Paypal\Helper\Data $paypalData - * @param \Magento\Payment\Helper\Data $paymentData - * @param \Magento\Framework\Registry $registry - * @param \Magento\Customer\Model\Session $customerSession * @param \Magento\Paypal\Model\ConfigFactory $paypalConfigFactory * @param \Magento\Paypal\Model\Express\Checkout\Factory $checkoutFactory * @param \Magento\Framework\Math\Random $mathRandom - * @param \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig * @param \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer * @param \Magento\Framework\Locale\ResolverInterface $localeResolver + * @param ValidatorInterface $shortcutValidator + * @param string $paymentMethodCode + * @param string $startAction + * @param string $checkoutType + * @param string $alias * @param \Magento\Checkout\Model\Session $checkoutSession * @param array $data */ public function __construct( \Magento\Framework\View\Element\Template\Context $context, \Magento\Paypal\Helper\Data $paypalData, - \Magento\Payment\Helper\Data $paymentData, - \Magento\Framework\Registry $registry, - \Magento\Customer\Model\Session $customerSession, \Magento\Paypal\Model\ConfigFactory $paypalConfigFactory, \Magento\Paypal\Model\Express\Checkout\Factory $checkoutFactory, \Magento\Framework\Math\Random $mathRandom, - \Magento\Catalog\Model\ProductTypes\ConfigInterface $productTypeConfig, \Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer, \Magento\Framework\Locale\ResolverInterface $localeResolver, + ValidatorInterface $shortcutValidator, + $paymentMethodCode, + $startAction, + $checkoutType, + $alias, \Magento\Checkout\Model\Session $checkoutSession = null, array $data = array() ) { - $this->_registry = $registry; $this->_paypalData = $paypalData; - $this->_paymentData = $paymentData; - $this->_customerSession = $customerSession; $this->_paypalConfigFactory = $paypalConfigFactory; $this->_checkoutSession = $checkoutSession; $this->_checkoutFactory = $checkoutFactory; - $this->mathRandom = $mathRandom; - $this->productTypeConfig = $productTypeConfig; + $this->_mathRandom = $mathRandom; $this->_localeResolver = $localeResolver; + $this->_shortcutValidator = $shortcutValidator; + + $this->_paymentMethodCode = $paymentMethodCode; + $this->_startAction = $startAction; + $this->_checkoutType = $checkoutType; + $this->_alias = $alias; + parent::__construct($context, $data); $this->_isScopePrivate = true; $this->currentCustomer = $currentCustomer; @@ -170,48 +164,22 @@ public function __construct( protected function _beforeToHtml() { $result = parent::_beforeToHtml(); - $params = array($this->_paymentMethodCode); - $config = $this->_paypalConfigFactory->create(array('params' => $params)); - $isInCatalog = $this->getIsInCatalogProduct(); - $quote = $isInCatalog || !$this->_checkoutSession ? null : $this->_checkoutSession->getQuote(); + /** @var \Magento\Paypal\Model\Config $config */ + $config = $this->_paypalConfigFactory->create(); + $config->setMethod($this->_paymentMethodCode); - // check visibility on cart or product page - $context = $isInCatalog ? 'visible_on_product' : 'visible_on_cart'; - if (!$config->getConfigValue($context)) { - $this->_shouldRender = false; - return $result; - } + $isInCatalog = $this->getIsInCatalogProduct(); - if ($isInCatalog) { - // Show PayPal shortcut on a product view page only if product has nonzero price - /** @var $currentProduct \Magento\Catalog\Model\Product */ - $currentProduct = $this->_registry->registry('current_product'); - if (!is_null($currentProduct)) { - $productPrice = (double)$currentProduct->getFinalPrice(); - if (empty($productPrice) && !$this->productTypeConfig->isProductSet($currentProduct->getTypeId())) { - $this->_shouldRender = false; - return $result; - } - } - } - // validate minimum quote amount and validate quote for zero grandtotal - if (null !== $quote && (!$quote->validateMinimumAmount() || - !$quote->getGrandTotal() && !$quote->hasNominalItems()) - ) { + if (!$this->_shortcutValidator->validate($this->_paymentMethodCode, $isInCatalog)) { $this->_shouldRender = false; return $result; } - // check payment method availability - $methodInstance = $this->_paymentData->getMethodInstance($this->_paymentMethodCode); - if (!$methodInstance || !$methodInstance->isAvailable($quote)) { - $this->_shouldRender = false; - return $result; - } + $quote = $isInCatalog || !$this->_checkoutSession ? null : $this->_checkoutSession->getQuote(); // set misc data $this->setShortcutHtmlId( - $this->mathRandom->getUniqueHash('ec_shortcut_') + $this->_mathRandom->getUniqueHash('ec_shortcut_') )->setCheckoutUrl( $this->getUrl($this->_startAction) ); @@ -220,6 +188,7 @@ protected function _beforeToHtml() if ($isInCatalog || null === $quote) { $this->setImageUrl($config->getExpressCheckoutShortcutImageUrl($this->_localeResolver->getLocaleCode())); } else { + /**@todo refactor checkout model. Move getCheckoutShortcutImageUrl to helper or separate model */ $parameters = array('params' => array('quote' => $quote, 'config' => $config)); $checkoutModel = $this->_checkoutFactory->create($this->_checkoutType, $parameters); $this->setImageUrl($checkoutModel->getCheckoutShortcutImageUrl()); @@ -282,6 +251,6 @@ public function isOrPositionAfter() */ public function getAlias() { - return 'product.info.addtocart.paypal'; + return $this->_alias; } } diff --git a/app/code/Magento/Paypal/Block/Payflow/Bml/Form.php b/app/code/Magento/Paypal/Block/Payflow/Bml/Form.php new file mode 100644 index 0000000000000..ad152b7e398ce --- /dev/null +++ b/app/code/Magento/Paypal/Block/Payflow/Bml/Form.php @@ -0,0 +1,37 @@ +_config = $this->_paypalConfigFactory->create()->setMethod($this->getMethodCode()); - /** @var $mark \Magento\Framework\View\Element\Template */ - $mark = $this->_layout->createBlock('Magento\Framework\View\Element\Template'); - $mark->setTemplate( - 'Magento_Paypal::payment/mark.phtml' - )->setPaymentAcceptanceMarkHref( + $mark = $this->_getMarkTemplate(); + $mark->setPaymentAcceptanceMarkHref( $this->_config->getPaymentMarkWhatIsPaypalUrl($this->_localeResolver) )->setPaymentAcceptanceMarkSrc( $this->_config->getPaymentMarkImageUrl($this->_localeResolver->getLocaleCode()) ); + // known issue: code above will render only static mark image - $this->setTemplate( - 'Magento_Paypal::payment/redirect.phtml' - )->setRedirectMessage( - __('You will be redirected to the PayPal website when you place an order.') - )->setMethodTitle( - // Output PayPal mark, omit title - '' - )->setMethodLabelAfterHtml( - $mark->toHtml() - ); + $this->_initializeRedirectTemplateWithMark($mark); return parent::_construct(); } @@ -108,4 +97,39 @@ public function getMethodCode() { return $this->_methodCode; } + + /** + * Get initialized mark template + * + * @return \Magento\Framework\View\Element\Template + */ + protected function _getMarkTemplate() + { + /** @var $mark \Magento\Framework\View\Element\Template */ + $mark = $this->_layout->createBlock('Magento\Framework\View\Element\Template'); + $mark->setTemplate( + 'Magento_Paypal::payment/mark.phtml' + ); + return $mark; + } + + /** + * Initializes redirect template and set mark + * @param \Magento\Framework\View\Element\Template $mark + * + * @return void + */ + protected function _initializeRedirectTemplateWithMark(\Magento\Framework\View\Element\Template $mark) + { + $this->setTemplate( + 'Magento_Paypal::payment/redirect.phtml' + )->setRedirectMessage( + __('You will be redirected to the PayPal website when you place an order.') + )->setMethodTitle( + // Output PayPal mark, omit title + '' + )->setMethodLabelAfterHtml( + $mark->toHtml() + ); + } } diff --git a/app/code/Magento/Paypal/Controller/Bml.php b/app/code/Magento/Paypal/Controller/Bml.php new file mode 100644 index 0000000000000..fe6c91bba4b00 --- /dev/null +++ b/app/code/Magento/Paypal/Controller/Bml.php @@ -0,0 +1,41 @@ +_forward('start', 'payflowexpress', 'paypal', [ + 'bml' => 1, + 'button' => $this->getRequest()->getParam('button') + ]); + } +} diff --git a/app/code/Magento/Paypal/Controller/Express/AbstractExpress.php b/app/code/Magento/Paypal/Controller/Express/AbstractExpress.php index 3c96bea469214..6a311d71dec8d 100644 --- a/app/code/Magento/Paypal/Controller/Express/AbstractExpress.php +++ b/app/code/Magento/Paypal/Controller/Express/AbstractExpress.php @@ -26,6 +26,7 @@ use Magento\Checkout\Model\Type\Onepage; use Magento\Framework\App\Action\Action as AppAction; use Magento\Checkout\Controller\Express\RedirectLoginInterface; +use Magento\Paypal\Model\Api\ProcessableException as ApiProcessableException; /** * Abstract Express Checkout Controller @@ -181,6 +182,9 @@ public function startAction() $this->_checkout->setIsBillingAgreementRequested($isBaRequested); } + // Bill Me Later + $this->_checkout->setIsBml((bool)$this->getRequest()->getParam('bml')); + // giropay $this->_checkout->prepareGiropayUrls( $this->_url->getUrl('checkout/onepage/success'), @@ -188,9 +192,11 @@ public function startAction() $this->_url->getUrl('checkout/onepage/success') ); + $button = (bool)$this->getRequest()->getParam(\Magento\Paypal\Model\Express\Checkout::PAYMENT_INFO_BUTTON); $token = $this->_checkout->start( $this->_url->getUrl('*/*/return'), - $this->_url->getUrl('*/*/cancel') + $this->_url->getUrl('*/*/cancel'), + $button ); $url = $this->_checkout->getRedirectUrl(); if ($token && $url) { @@ -268,10 +274,21 @@ public function cancelAction() */ public function returnAction() { + if ($this->getRequest()->getParam('retry_authorization') == 'true' + && is_array($this->_getCheckoutSession()->getPaypalTransactionData()) + ) { + $this->_forward('placeOrder'); + return; + } try { + $this->_getCheckoutSession()->unsPaypalTransactionData(); $this->_initCheckout(); $this->_checkout->returnFromPaypal($this->_initToken()); - $this->_redirect('*/*/review'); + if ($this->_checkout->canSkipOrderReviewStep()) { + $this->_forward('placeOrder'); + } else { + $this->_redirect('*/*/review'); + } return; } catch (\Magento\Framework\Model\Exception $e) { $this->messageManager->addError($e->getMessage()); @@ -386,7 +403,7 @@ public function updateShippingMethodsAction() } catch (\Magento\Framework\Model\Exception $e) { $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { - $this->messageManager->addError(__('We can\'t update Order data.')); + $this->messageManager->addError(__('We can\'t update shipping method.')); $this->_objectManager->get('Magento\Framework\Logger')->logException($e); } $this->getResponse()->setBody( @@ -394,41 +411,6 @@ public function updateShippingMethodsAction() ); } - /** - * Update Order (combined action for ajax and regular request) - * - * @return void - */ - public function updateOrderAction() - { - try { - $isAjax = $this->getRequest()->getParam('isAjax'); - $this->_initCheckout(); - $this->_checkout->updateOrder($this->getRequest()->getParams()); - if ($isAjax) { - $this->_view->loadLayout('paypal_express_review_details'); - $this->getResponse()->setBody( - $this->_view->getLayout()->getBlock('root')->setQuote($this->_getQuote())->toHtml() - ); - return; - } - } catch (\Magento\Framework\Model\Exception $e) { - $this->messageManager->addError($e->getMessage()); - } catch (\Exception $e) { - $this->messageManager->addError(__('We can\'t update Order data.')); - $this->_objectManager->get('Magento\Framework\Logger')->logException($e); - } - if ($isAjax) { - $this->getResponse()->setBody( - '' - ); - } else { - $this->_redirect('*/*/review'); - } - } - /** * Submit the order * @@ -479,13 +461,75 @@ public function placeOrderAction() $this->_initToken(false); // no need in token anymore $this->_redirect('checkout/onepage/success'); return; + } catch (ApiProcessableException $e) { + $this->_processPaypalApiError($e); } catch (\Magento\Framework\Model\Exception $e) { $this->messageManager->addError($e->getMessage()); + $this->_redirect('*/*/review'); } catch (\Exception $e) { $this->messageManager->addError(__('We can\'t place the order.')); $this->_objectManager->get('Magento\Framework\Logger')->logException($e); + $this->_redirect('*/*/review'); + } + } + + /** + * Process PayPal API's processable errors + * + * @param \Magento\Paypal\Model\Api\ProcessableException $exception + * @return void + */ + protected function _processPaypalApiError($exception) + { + switch ($exception->getCode()) { + case ApiProcessableException::API_MAX_PAYMENT_ATTEMPTS_EXCEEDED: + case ApiProcessableException::API_TRANSACTION_EXPIRED: + $this->getResponse()->setRedirect( + $this->_getQuote()->getPayment()->getCheckoutRedirectUrl() + ); + break; + case ApiProcessableException::API_DO_EXPRESS_CHECKOUT_FAIL: + $this->_redirectSameToken(); + break; + case ApiProcessableException::API_UNABLE_TRANSACTION_COMPLETE: + if ($this->_config->getPaymentAction() == \Magento\Payment\Model\Method\AbstractMethod::ACTION_ORDER) { + $paypalTransactionData = $this->_getCheckoutSession()->getPaypalTransactionData(); + $this->getResponse()->setRedirect( + $this->_config->getExpressCheckoutOrderUrl($paypalTransactionData['transaction_id']) + ); + } else { + $this->_redirectSameToken(); + } + break; + default: + $this->_redirectToCartAndShowError($exception->getUserMessage()); + break; } - $this->_redirect('*/*/review'); + } + + /** + * Redirect customer back to PayPal with the same token + * + * @return void + */ + protected function _redirectSameToken() + { + $token = $this->_initToken(); + $this->getResponse()->setRedirect( + $this->_config->getExpressCheckoutStartUrl($token) + ); + } + + /** + * Redirect customer to shopping cart and show error message + * + * @param string $errorMessage + * @return void + */ + protected function _redirectToCartAndShowError($errorMessage) + { + $this->messageManager->addError($errorMessage); + $this->_redirect('checkout/cart'); } /** @@ -494,7 +538,7 @@ public function placeOrderAction() * @return void * @throws \Magento\Framework\Model\Exception */ - private function _initCheckout() + protected function _initCheckout() { $quote = $this->_getQuote(); if (!$quote->hasItems() || $quote->getHasError()) { diff --git a/app/code/Magento/Paypal/Controller/Payflowbml.php b/app/code/Magento/Paypal/Controller/Payflowbml.php new file mode 100644 index 0000000000000..9e165d8bcbc3c --- /dev/null +++ b/app/code/Magento/Paypal/Controller/Payflowbml.php @@ -0,0 +1,41 @@ +_forward('start', 'express', 'paypal', [ + 'bml' => 1, + 'button' => $this->getRequest()->getParam('button') + ]); + } +} diff --git a/app/code/Magento/Paypal/Helper/Shortcut/CheckoutValidator.php b/app/code/Magento/Paypal/Helper/Shortcut/CheckoutValidator.php new file mode 100644 index 0000000000000..ccfd8445741e7 --- /dev/null +++ b/app/code/Magento/Paypal/Helper/Shortcut/CheckoutValidator.php @@ -0,0 +1,110 @@ +_checkoutSession = $checkoutSession; + $this->_paymentData = $paymentData; + $this->_shortcutValidator = $shortcutValidator; + } + + /** + * Validates shortcut + * + * @param string $code + * @param bool $isInCatalog + * @return bool + */ + public function validate($code, $isInCatalog) + { + return $this->_shortcutValidator->isContextAvailable($code, $isInCatalog) + && $this->_shortcutValidator->isPriceOrSetAvailable($isInCatalog) + && $this->isMethodQuoteAvailable($code, $isInCatalog) + && $this->isQuoteSummaryValid($isInCatalog); + } + + /** + * Сhecks payment method and quote availability + * + * @param string $paymentCode + * @param bool $isInCatalog + * @return bool + */ + public function isMethodQuoteAvailable($paymentCode, $isInCatalog) + { + $quote = $isInCatalog ? null : $this->_checkoutSession->getQuote(); + // check payment method availability + /** @var \Magento\Payment\Model\Method\AbstractMethod $methodInstance */ + $methodInstance = $this->_paymentData->getMethodInstance($paymentCode); + if (!$methodInstance || !$methodInstance->isAvailable($quote)) { + return false; + } + return true; + } + + /** + * Validates minimum quote amount and zero grand total + * + * @param bool $isInCatalog + * @return bool + */ + public function isQuoteSummaryValid($isInCatalog) + { + $quote = $isInCatalog ? null : $this->_checkoutSession->getQuote(); + // validate minimum quote amount and validate quote for zero grandtotal + if (null !== $quote && (!$quote->validateMinimumAmount() || + !$quote->getGrandTotal() && !$quote->hasNominalItems()) + ) { + return false; + } + return true; + } +} diff --git a/app/code/Magento/Paypal/Helper/Shortcut/Factory.php b/app/code/Magento/Paypal/Helper/Shortcut/Factory.php new file mode 100644 index 0000000000000..8aa148929f07d --- /dev/null +++ b/app/code/Magento/Paypal/Helper/Shortcut/Factory.php @@ -0,0 +1,64 @@ +_objectManager = $objectManager; + } + + /** + * @param mixed $parameter + * @return \Magento\Paypal\Helper\Shortcut\ValidatorInterface + */ + public function create($parameter = null) + { + $instanceName = self::DEFAULT_VALIDATOR; + if (is_object($parameter) && $parameter instanceof \Magento\Checkout\Model\Session) { + $instanceName = self::CHECKOUT_VALIDATOR; + } + return $this->_objectManager->create($instanceName); + } +} diff --git a/app/code/Magento/Paypal/Helper/Shortcut/Validator.php b/app/code/Magento/Paypal/Helper/Shortcut/Validator.php new file mode 100644 index 0000000000000..fdcc41231812d --- /dev/null +++ b/app/code/Magento/Paypal/Helper/Shortcut/Validator.php @@ -0,0 +1,145 @@ +_paypalConfigFactory = $paypalConfigFactory; + $this->_registry = $registry; + $this->_productTypeConfig = $productTypeConfig; + $this->_paymentData = $paymentData; + } + + /** + * Validates shortcut + * + * @param string $code + * @param bool $isInCatalog + * @return bool + */ + public function validate($code, $isInCatalog) + { + return $this->isContextAvailable($code, $isInCatalog) + && $this->isPriceOrSetAvailable($isInCatalog) + && $this->isMethodAvailable($code); + } + + /** + * Checks visibility of context (cart or product page) + * + * @param string $paymentCode Payment method code + * @param bool $isInCatalog + * @return bool + */ + public function isContextAvailable($paymentCode, $isInCatalog) + { + /** @var \Magento\Paypal\Model\Config $config */ + $config = $this->_paypalConfigFactory->create(); + $config->setMethod($paymentCode); + + // check visibility on cart or product page + $context = $isInCatalog ? 'visible_on_product' : 'visible_on_cart'; + if (!$config->getConfigValue($context)) { + return false; + } + return true; + } + + /** + * Check is product available depending on final price or type set(configurable) + * + * @param bool $isInCatalog + * @return bool + */ + public function isPriceOrSetAvailable($isInCatalog) + { + if ($isInCatalog) { + // Show PayPal shortcut on a product view page only if product has nonzero price + /** @var $currentProduct \Magento\Catalog\Model\Product */ + $currentProduct = $this->_registry->registry('current_product'); + if (!is_null($currentProduct)) { + $productPrice = (double)$currentProduct->getFinalPrice(); + if (empty($productPrice) && !$this->_productTypeConfig->isProductSet($currentProduct->getTypeId())) { + return false; + } + } + } + return true; + } + + /** + * Сhecks payment method and quote availability + * + * @param string $paymentCode + * @return bool + */ + public function isMethodAvailable($paymentCode) + { + // check payment method availability + /** @var \Magento\Payment\Model\Method\AbstractMethod $methodInstance */ + $methodInstance = $this->_paymentData->getMethodInstance($paymentCode); + if (!$methodInstance || !$methodInstance->isAvailable()) { + return false; + } + return true; + } +} diff --git a/app/code/Magento/Paypal/Helper/Shortcut/ValidatorInterface.php b/app/code/Magento/Paypal/Helper/Shortcut/ValidatorInterface.php new file mode 100644 index 0000000000000..faa70df0a4574 --- /dev/null +++ b/app/code/Magento/Paypal/Helper/Shortcut/ValidatorInterface.php @@ -0,0 +1,37 @@ + 'payflowcolor', 'LOCALECODE' => 'locale_code', 'PAL' => 'pal', + 'USERSELECTEDFUNDINGSOURCE' => 'funding_source', // transaction info 'TRANSACTIONID' => 'transaction_id', @@ -274,7 +275,8 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi 'ITEMAMT', 'SHIPPINGAMT', 'TAXAMT', - 'REQBILLINGADDRESS' + 'REQBILLINGADDRESS', + 'USERSELECTEDFUNDINGSOURCE' ); /** @@ -753,6 +755,21 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi */ protected $_countryFactory; + /** + * @var \Magento\Paypal\Model\Api\ProcessableExceptionFactory + */ + protected $_processableExceptionFactory; + + /** + * @var \Magento\Framework\Model\ExceptionFactory + */ + protected $_frameworkExceptionFactory; + + /** + * @var \Magento\Framework\HTTP\Adapter\CurlFactory + */ + protected $_curlFactory; + /** * @param \Magento\Customer\Helper\Address $customerAddress * @param \Magento\Framework\Logger $logger @@ -760,6 +777,9 @@ class Nvp extends \Magento\Paypal\Model\Api\AbstractApi * @param \Magento\Directory\Model\RegionFactory $regionFactory * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory * @param \Magento\Directory\Model\CountryFactory $countryFactory + * @param \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory + * @param \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory + * @param \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory * @param array $data */ public function __construct( @@ -769,10 +789,16 @@ public function __construct( \Magento\Directory\Model\RegionFactory $regionFactory, \Magento\Framework\Logger\AdapterFactory $logAdapterFactory, \Magento\Directory\Model\CountryFactory $countryFactory, + \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory, + \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory, + \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory, array $data = array() ) { parent::__construct($customerAddress, $logger, $localeResolver, $regionFactory, $logAdapterFactory, $data); $this->_countryFactory = $countryFactory; + $this->_processableExceptionFactory = $processableExceptionFactory; + $this->_frameworkExceptionFactory = $frameworkExceptionFactory; + $this->_curlFactory = $curlFactory; } /** @@ -1173,7 +1199,7 @@ public function call($methodName, array $request) $debugData = array('url' => $this->getApiEndpoint(), $methodName => $request); try { - $http = new \Magento\Framework\HTTP\Adapter\Curl(); + $http = $this->_curlFactory->create(); $config = array('timeout' => 60, 'verifypeer' => $this->_config->getConfigValue('verifyPeer')); if ($this->getUseProxy()) { $config['proxy'] = $this->getProxyHost() . ':' . $this->getProxyPort(); @@ -1253,46 +1279,100 @@ public function setRawResponseNeeded($flag) * * @param array $response * @return void - * @throws \Magento\Framework\Model\Exception + * @throws \Magento\Paypal\Model\Api\ProcessableException|\Magento\Framework\Model\Exception */ protected function _handleCallErrors($response) + { + $errors = $this->_extractErrorsFromResponse($response); + if (empty($errors)) { + return; + } + + $errorMessages = array(); + foreach ($errors as $error) { + $errorMessages[] = $error['message']; + $this->_callErrors[] = $error['code']; + } + $errorMessages = implode(' ', $errorMessages); + + $exceptionLogMessage = sprintf( + 'PayPal NVP gateway errors: %s Correlation ID: %s. Version: %s.', + $errorMessages, + isset($response['CORRELATIONID']) ? $response['CORRELATIONID'] : '', + isset($response['VERSION']) ? $response['VERSION'] : '' + ); + + $exception = count($errors) == 1 && $this->_isProcessableError($errors[0]['code']) + ? $this->_processableExceptionFactory->create( + ['message' => $exceptionLogMessage, 'code' => $errors[0]['code']] + ) : $this->_frameworkExceptionFactory->create( + ['message' => $exceptionLogMessage, 'code' => 0] + ); + $this->_logger->logException($exception); + + $exception->setMessage(__('PayPal gateway has rejected request. %1', $errorMessages)); + + throw $exception; + } + + /** + * Format error message from error code, short error message and long error message + * + * @param string $errorCode + * @param string $shortErrorMessage + * @param string $longErrorMessage + * @return string + */ + protected function _formatErrorMessage($errorCode, $shortErrorMessage, $longErrorMessage) + { + $longErrorMessage = preg_replace('/\.$/', '', $longErrorMessage); + $shortErrorMessage = preg_replace('/\.$/', '', $shortErrorMessage); + + return $longErrorMessage ? sprintf('%s (#%s: %s).', $longErrorMessage, $errorCode, $shortErrorMessage) + : sprintf('#%s: %s.', $errorCode, $shortErrorMessage); + } + + /** + * Check whether PayPal error can be processed + * + * @param int $errorCode + * @return bool + */ + protected function _isProcessableError($errorCode) + { + $processableErrorsList = $this->getProcessableErrors(); + + if (!$processableErrorsList || !is_array($processableErrorsList)) { + return false; + } + + return in_array($errorCode, $processableErrorsList); + } + + /** + * Extract errors from PayPal's response and return them in array + * + * @param array $response + * @return array + */ + protected function _extractErrorsFromResponse($response) { $errors = array(); + for ($i = 0; isset($response["L_ERRORCODE{$i}"]); $i++) { - $longMessage = isset( - $response["L_LONGMESSAGE{$i}"] - ) ? preg_replace( - '/\.$/', - '', + $errorCode = $response["L_ERRORCODE{$i}"]; + $errorMessage = $this->_formatErrorMessage( + $errorCode, + $response["L_SHORTMESSAGE{$i}"], $response["L_LONGMESSAGE{$i}"] - ) : ''; - $shortMessage = preg_replace('/\.$/', '', $response["L_SHORTMESSAGE{$i}"]); - $errors[] = $longMessage ? sprintf( - '%s (#%s: %s).', - $longMessage, - $response["L_ERRORCODE{$i}"], - $shortMessage - ) : sprintf( - '#%s: %s.', - $response["L_ERRORCODE{$i}"], - $shortMessage ); - $this->_callErrors[] = $response["L_ERRORCODE{$i}"]; - } - if ($errors) { - $errors = implode(' ', $errors); - $e = new \Magento\Framework\Model\Exception( - sprintf( - 'PayPal NVP gateway errors: %s Correlation ID: %s. Version: %s.', - $errors, - isset($response['CORRELATIONID']) ? $response['CORRELATIONID'] : '', - isset($response['VERSION']) ? $response['VERSION'] : '' - ) + $errors[] = array ( + 'code' => $errorCode, + 'message' => $errorMessage ); - $this->_logger->logException($e); - $e->setMessage(__('The PayPal gateway has rejected this request. %1', $errors)); - throw $e; } + + return $errors; } /** @@ -1403,21 +1483,7 @@ protected function _exportAddressses($data) \Magento\Framework\Object\Mapper::accumulateByMap($data, $shippingAddress, $this->_shippingAddressMap); $this->_applyStreetAndRegionWorkarounds($shippingAddress); // PayPal doesn't provide detailed shipping name fields, so the name will be overwritten - $firstName = $data['SHIPTONAME']; - $lastName = null; - if (isset($data['FIRSTNAME']) && $data['LASTNAME']) { - $firstName = $data['FIRSTNAME']; - $lastName = $data['LASTNAME']; - } - $shippingAddress->addData( - array( - 'prefix' => null, - 'firstname' => $firstName, - 'middlename' => null, - 'lastname' => $lastName, - 'suffix' => null - ) - ); + $shippingAddress->addData(['firstname' => $data['SHIPTONAME']]); $this->setExportedShippingAddress($shippingAddress); } } diff --git a/app/code/Magento/Paypal/Model/Api/PayflowNvp.php b/app/code/Magento/Paypal/Model/Api/PayflowNvp.php index 6450d5b29f491..7961ea26bb4e8 100644 --- a/app/code/Magento/Paypal/Model/Api/PayflowNvp.php +++ b/app/code/Magento/Paypal/Model/Api/PayflowNvp.php @@ -153,7 +153,8 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp 'ECI' => 'centinel_eci', 'XID' => 'centinel_xid', 'VPAS' => 'centinel_vpas_result', - 'ECISUBMITTED3DS' => 'centinel_eci_result' + 'ECISUBMITTED3DS' => 'centinel_eci_result', + 'USERSELECTEDFUNDINGSOURCE' => 'funding_source' ); /** @@ -264,7 +265,8 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp 'HDRBORDERCOLOR', 'HDRBACKCOLOR', 'PAYFLOWCOLOR', - 'LOCALECODE' + 'LOCALECODE', + 'USERSELECTEDFUNDINGSOURCE' ); /** @@ -448,6 +450,9 @@ class PayflowNvp extends \Magento\Paypal\Model\Api\Nvp * @param \Magento\Directory\Model\RegionFactory $regionFactory * @param \Magento\Framework\Logger\AdapterFactory $logAdapterFactory * @param \Magento\Directory\Model\CountryFactory $countryFactory + * @param \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory + * @param \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory + * @param \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory * @param \Magento\Framework\Math\Random $mathRandom * @param array $data */ @@ -458,10 +463,12 @@ public function __construct( \Magento\Directory\Model\RegionFactory $regionFactory, \Magento\Framework\Logger\AdapterFactory $logAdapterFactory, \Magento\Directory\Model\CountryFactory $countryFactory, + \Magento\Paypal\Model\Api\ProcessableExceptionFactory $processableExceptionFactory, + \Magento\Framework\Model\ExceptionFactory $frameworkExceptionFactory, + \Magento\Framework\HTTP\Adapter\CurlFactory $curlFactory, \Magento\Framework\Math\Random $mathRandom, array $data = array() ) { - $this->mathRandom = $mathRandom; parent::__construct( $customerAddress, $logger, @@ -469,8 +476,12 @@ public function __construct( $regionFactory, $logAdapterFactory, $countryFactory, + $processableExceptionFactory, + $frameworkExceptionFactory, + $curlFactory, $data ); + $this->mathRandom = $mathRandom; } /** diff --git a/app/code/Magento/Paypal/Model/Api/ProcessableException.php b/app/code/Magento/Paypal/Model/Api/ProcessableException.php new file mode 100644 index 0000000000000..3fae6df966b42 --- /dev/null +++ b/app/code/Magento/Paypal/Model/Api/ProcessableException.php @@ -0,0 +1,64 @@ +getCode()) { + case self::API_INTERNAL_ERROR: + case self::API_UNABLE_PROCESS_PAYMENT_ERROR_CODE: + $message = __("I'm sorry - but we were not able to process your payment. Please try another payment method or contact us so we can assist you."); + break; + case self::API_COUNTRY_FILTER_DECLINE: + case self::API_MAXIMUM_AMOUNT_FILTER_DECLINE: + case self::API_OTHER_FILTER_DECLINE: + $message = __("I'm sorry - but we are not able to complete your transaction. Please contact us so we can assist you."); + break; + default: + $message = $this->getMessage(); + } + return $message; + } +} diff --git a/app/code/Magento/Paypal/Model/Bml.php b/app/code/Magento/Paypal/Model/Bml.php new file mode 100644 index 0000000000000..7e08dd4d047b1 --- /dev/null +++ b/app/code/Magento/Paypal/Model/Bml.php @@ -0,0 +1,50 @@ +_urlBuilder->getUrl('paypal/bml/start'); + } +} diff --git a/app/code/Magento/Paypal/Model/Config.php b/app/code/Magento/Paypal/Model/Config.php index 9d62ad04439e7..20caf2cdf5334 100644 --- a/app/code/Magento/Paypal/Model/Config.php +++ b/app/code/Magento/Paypal/Model/Config.php @@ -39,6 +39,11 @@ class Config */ const METHOD_WPP_EXPRESS = 'paypal_express'; + /** + * PayPal Bill Me Later - Express Checkout + */ + const METHOD_WPP_BML = 'paypal_express_bml'; + /** * PayPal Website Payments Pro - Direct Payments */ @@ -49,6 +54,11 @@ class Config */ const METHOD_WPP_PE_EXPRESS = 'payflow_express'; + /** + * PayPal Bill Me Later - Express Checkout (Payflow Edition) + */ + const METHOD_WPP_PE_BML = 'payflow_express_bml'; + /** * Payflow Pro Gateway */ @@ -168,6 +178,11 @@ class Config /**#@-*/ + /** + * Config path for enabling/disabling order review step in express checkout + */ + const XML_PATH_PAYPAL_EXPRESS_SKIP_ORDER_REVIEW_STEP_FLAG = 'payment/paypal_express/skip_order_review_step'; + /** * Default URL for centinel API (PayPal Direct) * @@ -740,6 +755,12 @@ public function isMethodAvailable($methodCode = null) $result = true; } break; + case self::METHOD_WPP_BML: + // check for express payments dependence + if (!$this->isMethodActive(self::METHOD_WPP_EXPRESS)) { + $result = false; + } + break; case self::METHOD_WPP_PE_EXPRESS: // check for direct payments dependence if ($this->isMethodActive(self::METHOD_PAYFLOWLINK) @@ -749,6 +770,12 @@ public function isMethodAvailable($methodCode = null) $result = false; } break; + case self::METHOD_WPP_PE_BML: + // check for express payments dependence + if (!$this->isMethodActive(self::METHOD_WPP_PE_EXPRESS)) { + $result = false; + } + break; case self::METHOD_BILLING_AGREEMENT: $result = $this->isWppApiAvailabe(); break; @@ -778,8 +805,6 @@ public function getConfigValue($key) $this->_storeId ); $value = $this->_prepareValue($underscored, $value); - $this->{$key} = $value; - $this->{$underscored} = $value; return $value; } return null; @@ -832,13 +857,7 @@ public function getSupportedBuyerCountryCodes() */ public function getMerchantCountry() { - $countryCode = $this->_scopeConfig->getValue( - $this->_mapGeneralFieldset( - 'merchant_country', - \Magento\Store\Model\ScopeInterface::SCOPE_STORE, - $this->_storeId - ) - ); + $countryCode = $this->_scopeConfig->getValue($this->_mapGeneralFieldset('merchant_country')); if (!$countryCode) { $countryCode = $this->_coreData->getDefaultCountry($this->_storeId); } @@ -873,7 +892,12 @@ public function isMethodSupportedForCountry($method = null, $countryCode = null) public function getCountryMethods($countryCode = null) { $countryMethods = [ - 'other' => [self::METHOD_WPS, self::METHOD_WPP_EXPRESS, self::METHOD_BILLING_AGREEMENT], + 'other' => [ + self::METHOD_WPS, + self::METHOD_WPP_EXPRESS, + self::METHOD_BILLING_AGREEMENT, + self::METHOD_WPP_BML + ], 'US' => [ self::METHOD_PAYFLOWADVANCED, self::METHOD_WPP_DIRECT, @@ -881,8 +905,10 @@ public function getCountryMethods($countryCode = null) self::METHOD_PAYFLOWPRO, self::METHOD_PAYFLOWLINK, self::METHOD_WPP_EXPRESS, + self::METHOD_WPP_BML, self::METHOD_BILLING_AGREEMENT, - self::METHOD_WPP_PE_EXPRESS + self::METHOD_WPP_PE_EXPRESS, + self::METHOD_WPP_PE_BML ], 'CA' => [ self::METHOD_WPP_DIRECT, @@ -890,14 +916,17 @@ public function getCountryMethods($countryCode = null) self::METHOD_PAYFLOWPRO, self::METHOD_PAYFLOWLINK, self::METHOD_WPP_EXPRESS, + self::METHOD_WPP_BML, self::METHOD_BILLING_AGREEMENT, - self::METHOD_WPP_PE_EXPRESS + self::METHOD_WPP_PE_EXPRESS, + self::METHOD_WPP_PE_BML ], 'GB' => [ self::METHOD_WPP_DIRECT, self::METHOD_WPS, self::METHOD_HOSTEDPRO, self::METHOD_WPP_EXPRESS, + self::METHOD_WPP_BML, self::METHOD_BILLING_AGREEMENT ], 'AU' => [ @@ -905,46 +934,54 @@ public function getCountryMethods($countryCode = null) self::METHOD_PAYFLOWPRO, self::METHOD_HOSTEDPRO, self::METHOD_WPP_EXPRESS, + self::METHOD_WPP_BML, self::METHOD_BILLING_AGREEMENT ], 'NZ' => [ self::METHOD_WPS, self::METHOD_PAYFLOWPRO, self::METHOD_WPP_EXPRESS, + self::METHOD_WPP_BML, self::METHOD_BILLING_AGREEMENT ], 'JP' => [ self::METHOD_WPS, self::METHOD_HOSTEDPRO, self::METHOD_WPP_EXPRESS, + self::METHOD_WPP_BML, self::METHOD_BILLING_AGREEMENT ], 'FR' => [ self::METHOD_WPS, self::METHOD_HOSTEDPRO, self::METHOD_WPP_EXPRESS, + self::METHOD_WPP_BML, self::METHOD_BILLING_AGREEMENT ], 'IT' => [ self::METHOD_WPS, self::METHOD_HOSTEDPRO, self::METHOD_WPP_EXPRESS, + self::METHOD_WPP_BML, self::METHOD_BILLING_AGREEMENT ], 'ES' => [ self::METHOD_WPS, self::METHOD_HOSTEDPRO, self::METHOD_WPP_EXPRESS, + self::METHOD_WPP_BML, self::METHOD_BILLING_AGREEMENT ], 'HK' => [ self::METHOD_WPS, self::METHOD_HOSTEDPRO, self::METHOD_WPP_EXPRESS, + self::METHOD_WPP_BML, self::METHOD_BILLING_AGREEMENT ], 'DE' => [ self::METHOD_WPP_EXPRESS, + self::METHOD_WPP_BML, self::METHOD_BILLING_AGREEMENT ] ]; @@ -954,6 +991,40 @@ public function getCountryMethods($countryCode = null) return isset($countryMethods[$countryCode]) ? $countryMethods[$countryCode] : $countryMethods['other']; } + /** + * Return start url for PayPal Basic + * + * @param string $token + * @return string + */ + public function getPayPalBasicStartUrl($token) + { + $params = array( + 'cmd' => '_express-checkout', + 'token' => $token, + ); + + if ($this->isOrderReviewStepDisabled()) { + $params['useraction'] = 'commit'; + } + + return $this->getPaypalUrl($params); + } + + /** + * Check whether order review step enabled in configuration + * + * @return bool + */ + public function isOrderReviewStepDisabled() + { + return $this->_scopeConfig->getValue( + self::XML_PATH_PAYPAL_EXPRESS_SKIP_ORDER_REVIEW_STEP_FLAG, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $this->_storeId + ); + } + /** * Get url for dispatching customer to express checkout start * @@ -965,6 +1036,17 @@ public function getExpressCheckoutStartUrl($token) return $this->getPaypalUrl(array('cmd' => '_express-checkout', 'token' => $token)); } + /** + * Get url for dispatching customer to checkout retrial + * + * @param string $orderId + * @return string + */ + public function getExpressCheckoutOrderUrl($orderId) + { + return $this->getPaypalUrl(array('cmd' => '_express-checkout', 'order_id' => $orderId)); + } + /** * Get url that allows to edit checkout details on paypal side * @@ -1219,22 +1301,15 @@ public function getAdditionalOptionsLogoUrl($localeCode, $type = false) /** * BN code getter * - * @param string|null $countryCode ISO 3166-1 * @return string */ - public function getBuildNotationCode($countryCode = null) + public function getBuildNotationCode() { - $product = 'WPP'; - if ($this->_methodCode && isset($this->_buildNotationPPMap[$this->_methodCode])) { - $product = $this->_buildNotationPPMap[$this->_methodCode]; - } - if (null === $countryCode) { - $countryCode = $this->_matchBnCountryCode($this->getMerchantCountry()); - } - if ($countryCode) { - $countryCode = '_' . $countryCode; - } - return sprintf('Magento_Cart_%s%s', $product, $countryCode); + return $this->_scopeConfig->getValue( + 'paypal/bncode', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $this->_storeId + ); } /** @@ -1539,6 +1614,12 @@ protected function _getSpecificConfigPath($fieldName) case self::METHOD_WPS: $path = $this->_mapStandardFieldset($fieldName); break; + case self::METHOD_WPP_BML: + $path = $this->_mapBmlFieldset($fieldName); + break; + case self::METHOD_WPP_PE_BML: + $path = $this->_mapBmlPayflowFieldset($fieldName); + break; case self::METHOD_WPP_EXPRESS: case self::METHOD_WPP_PE_EXPRESS: $path = $this->_mapExpressFieldset($fieldName); @@ -1555,6 +1636,7 @@ protected function _getSpecificConfigPath($fieldName) if ($path === null) { switch ($this->_methodCode) { case self::METHOD_WPP_EXPRESS: + case self::METHOD_WPP_BML: case self::METHOD_WPP_DIRECT: case self::METHOD_BILLING_AGREEMENT: case self::METHOD_HOSTEDPRO: @@ -1577,42 +1659,6 @@ protected function _getSpecificConfigPath($fieldName) return $path; } - /** - * Check wheter specified country code is supported by build notation codes for specific countries - * - * @param string $code - * @return string|null - */ - private function _matchBnCountryCode($code) - { - switch ($code) { - // GB == UK - case 'GB': - return 'UK'; - // Australia, Austria, Belgium, Canada, China, France, Germany, Hong Kong, Italy - case 'AU': - case 'AT': - case 'BE': - case 'CA': - case 'CN': - case 'FR': - case 'DE': - case 'HK': - case 'IT': - // Japan, Mexico, Netherlands, Poland, Singapore, Spain, Switzerland, United Kingdom, United States - case 'JP': - case 'MX': - case 'NL': - case 'PL': - case 'SG': - case 'ES': - case 'CH': - case 'UK': - case 'US': - return $code; - } - } - /** * Map PayPal Standard config fields * @@ -1654,6 +1700,40 @@ protected function _mapExpressFieldset($fieldName) } } + /** + * Map PayPal Express Bill Me Later config fields + * + * @param string $fieldName + * @return string|null + */ + protected function _mapBmlFieldset($fieldName) + { + switch ($fieldName) + { + case 'allow_ba_signup': + return "payment/" . self::METHOD_WPP_EXPRESS . "/{$fieldName}"; + default: + return $this->_mapExpressFieldset($fieldName); + } + } + + /** + * Map PayPal Express Bill Me Later config fields (Payflow Edition) + * + * @param string $fieldName + * @return string|null + */ + protected function _mapBmlPayflowFieldset($fieldName) + { + switch ($fieldName) + { + case 'allow_ba_signup': + return "payment/" . self::METHOD_WPP_PE_EXPRESS . "/{$fieldName}"; + default: + return $this->_mapExpressFieldset($fieldName); + } + } + /** * Map PayPal Direct config fields * @@ -1821,4 +1901,75 @@ public function getApiCertificate() $websiteId = $this->_storeManager->getStore($this->_storeId)->getWebsiteId(); return $this->_certFactory->create()->loadByWebsite($websiteId, false)->getCertPath(); } + + /** + * Get PublisherId from stored config + * + * @return mixed + */ + public function getBmlPublisherId() + { + return $this->_scopeConfig->getValue( + 'payment/' . self::METHOD_WPP_BML . '/publisher_id', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $this->_storeId + ); + } + + /** + * Get Display option from stored config + * @param string $section + * + * @return mixed + */ + public function getBmlDisplay($section) + { + $display = $this->_scopeConfig->getValue( + 'payment/' . self::METHOD_WPP_BML . '/' . $section . '_display', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $this->_storeId + ); + $bmlActive = $this->_scopeConfig->getValue( + 'payment/' . self::METHOD_WPP_BML . '/active', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $this->_storeId + ); + $bmlUkActive = $this->_scopeConfig->getValue( + 'payment/' . self::METHOD_WPP_PE_BML . '/active', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $this->_storeId + ); + return (($bmlActive && $this->isMethodActive(self::METHOD_WPP_EXPRESS)) + || ($bmlUkActive && $this->isMethodActive(self::METHOD_WPP_PE_EXPRESS))) ? $display : 0; + } + + /** + * Get Position option from stored config + * @param string $section + * + * @return mixed + */ + public function getBmlPosition($section) + { + return $this->_scopeConfig->getValue( + 'payment/' . self::METHOD_WPP_BML . '/' . $section . '_position', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $this->_storeId + ); + } + + /** + * Get Size option from stored config + * @param string $section + * + * @return mixed + */ + public function getBmlSize($section) + { + return $this->_scopeConfig->getValue( + 'payment/' . self::METHOD_WPP_BML . '/' . $section . '_size', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $this->_storeId + ); + } } diff --git a/app/code/Magento/Paypal/Model/Express.php b/app/code/Magento/Paypal/Model/Express.php index 6a48cd19f66ba..e4d2ecfe65c39 100644 --- a/app/code/Magento/Paypal/Model/Express.php +++ b/app/code/Magento/Paypal/Model/Express.php @@ -25,6 +25,7 @@ use Magento\Paypal\Model\Express\Checkout as ExpressCheckout; use Magento\Paypal\Model\Api\Nvp; +use Magento\Paypal\Model\Api\ProcessableException as ApiProcessableException; use Magento\Sales\Model\Order\Payment; use Magento\Sales\Model\Order\Payment\Transaction; use Magento\Sales\Model\Quote; @@ -169,6 +170,16 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod */ protected $_cartFactory; + /** + * @var \Magento\Checkout\Model\Session + */ + protected $_checkoutSession; + + /** + * @var \Magento\Framework\Model\ExceptionFactory + */ + protected $_exception; + /** * @param \Magento\Framework\Event\ManagerInterface $eventManager * @param \Magento\Payment\Helper\Data $paymentData @@ -178,6 +189,8 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\UrlInterface $urlBuilder * @param \Magento\Paypal\Model\CartFactory $cartFactory + * @param \Magento\Checkout\Model\Session $checkoutSession + * @param \Magento\Framework\Model\ExceptionFactory $exception * @param array $data */ public function __construct( @@ -189,12 +202,16 @@ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\UrlInterface $urlBuilder, \Magento\Paypal\Model\CartFactory $cartFactory, + \Magento\Checkout\Model\Session $checkoutSession, + \Magento\Framework\Model\ExceptionFactory $exception, array $data = array() ) { parent::__construct($eventManager, $paymentData, $scopeConfig, $logAdapterFactory, $data); $this->_storeManager = $storeManager; $this->_urlBuilder = $urlBuilder; $this->_cartFactory = $cartFactory; + $this->_checkoutSession = $checkoutSession; + $this->_exception = $exception; $proInstance = array_shift($data); if ($proInstance && $proInstance instanceof \Magento\Paypal\Model\Pro) { @@ -203,6 +220,29 @@ public function __construct( $this->_pro = $proFactory->create(); } $this->_pro->setMethod($this->_code); + $this->_setApiProcessableErrors(); + } + + /** + * Set processable error codes to API model + * + * @return \Magento\Paypal\Model\Api\Nvp + */ + protected function _setApiProcessableErrors() + { + return $this->_pro->getApi()->setProcessableErrors( + [ + ApiProcessableException::API_INTERNAL_ERROR, + ApiProcessableException::API_UNABLE_PROCESS_PAYMENT_ERROR_CODE, + ApiProcessableException::API_DO_EXPRESS_CHECKOUT_FAIL, + ApiProcessableException::API_UNABLE_TRANSACTION_COMPLETE, + ApiProcessableException::API_TRANSACTION_EXPIRED, + ApiProcessableException::API_MAX_PAYMENT_ATTEMPTS_EXCEEDED, + ApiProcessableException::API_COUNTRY_FILTER_DECLINE, + ApiProcessableException::API_MAXIMUM_AMOUNT_FILTER_DECLINE, + ApiProcessableException::API_OTHER_FILTER_DECLINE + ] + ); } /** @@ -298,7 +338,12 @@ public function getConfigData($field, $storeId = null) */ public function order(\Magento\Framework\Object $payment, $amount) { - $this->_placeOrder($payment, $amount); + $paypalTransactionData = $this->_checkoutSession->getPaypalTransactionData(); + if (!is_array($paypalTransactionData)) { + $this->_placeOrder($payment, $amount); + } else { + $this->_importToPayment($this->_pro->getApi()->setData($paypalTransactionData), $payment); + } $payment->setAdditionalInformation($this->_isOrderPaymentActionKey, true); @@ -309,7 +354,7 @@ public function order(\Magento\Framework\Object $payment, $amount) $order = $payment->getOrder(); $orderTransactionId = $payment->getTransactionId(); - $api = $this->_callDoAuthorize($amount, $payment, $payment->getTransactionId()); + $api = $this->_callDoAuthorize($amount, $payment, $orderTransactionId); $state = \Magento\Sales\Model\Order::STATE_PROCESSING; $status = true; @@ -427,7 +472,9 @@ public function capture(\Magento\Framework\Object $payment, $amount) if ($authorizationTransaction->getIsClosed() || $voided) { if ($payment->getAdditionalInformation($this->_authorizationCountKey) > $maxAuthorizationNumber - 1) { - throw new \Magento\Framework\Model\Exception(__('The maximum number of child authorizations is reached.')); + $this->_exception->create( + ['message' => __('The maximum number of child authorizations is reached.')] + ); } $api = $this->_callDoAuthorize($amount, $payment, $authorizationTransaction->getParentTxnId()); @@ -728,13 +775,19 @@ public function canCapture() */ protected function _callDoAuthorize($amount, $payment, $parentTransactionId) { - $api = $this->_pro->resetApi()->getApi()->setAmount( - $amount - )->setCurrencyCode( - $payment->getOrder()->getBaseCurrencyCode() - )->setTransactionId( - $parentTransactionId - )->callDoAuthorization(); + $apiData = $this->_pro->getApi()->getData(); + foreach ($apiData as $k => $v) { + if (is_object($v)) { + unset($apiData[$k]); + } + } + $this->_checkoutSession->setPaypalTransactionData($apiData); + $this->_pro->resetApi(); + $api = $this->_setApiProcessableErrors() + ->setAmount($amount) + ->setCurrencyCode($payment->getOrder()->getBaseCurrencyCode()) + ->setTransactionId($parentTransactionId) + ->callDoAuthorization(); $payment->setAdditionalInformation( $this->_authorizationCountKey, diff --git a/app/code/Magento/Paypal/Model/Express/Checkout.php b/app/code/Magento/Paypal/Model/Express/Checkout.php index e014d89c4d517..b3ca649ad73f3 100644 --- a/app/code/Magento/Paypal/Model/Express/Checkout.php +++ b/app/code/Magento/Paypal/Model/Express/Checkout.php @@ -51,6 +51,13 @@ class Checkout const PAYMENT_INFO_TRANSPORT_REDIRECT = 'paypal_express_checkout_redirect_required'; const PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT = 'paypal_ec_create_ba'; + /** + * Flag which says that was used PayPal Express Checkout button for checkout + * Uses additional_information as storage + * @var string + */ + const PAYMENT_INFO_BUTTON = 'button'; + /** * @var \Magento\Sales\Model\Quote */ @@ -124,6 +131,13 @@ class Checkout */ protected $_isBARequested = false; + /** + * Flag for Bill Me Later mode + * + * @var bool + */ + protected $_isBml = false; + /** * Customer ID * @@ -326,7 +340,6 @@ public function __construct( $this->_customerData = $customerData; $this->_taxData = $taxData; $this->_checkoutData = $checkoutData; - $this->_customerSession = $customerSession; $this->_configCacheType = $configCacheType; $this->_logger = $logger; $this->_localeResolver = $localeResolver; @@ -347,6 +360,8 @@ public function __construct( $this->_customerDetailsBuilder = $customerDetailsBuilder; $this->_encryptor = $encryptor; $this->_messageManager = $messageManager; + $this->_customerSession = isset($params['session']) + && $params['session'] instanceof \Magento\Customer\Model\Session ? $params['session'] : $customerSession; if (isset($params['config']) && $params['config'] instanceof PaypalConfig) { $this->_config = $params['config']; @@ -423,6 +438,18 @@ public function setIsBillingAgreementRequested($flag) return $this; } + /** + * Set flag that forces to use BillMeLater + * + * @param bool $isBml + * @return $this + */ + public function setIsBml($isBml) + { + $this->_isBml = $isBml; + return $this; + } + /** * Setter for customer * @@ -459,10 +486,11 @@ public function setCustomerWithAddressChange( * * @param string $returnUrl * @param string $cancelUrl + * @param bool|null $button * @return string * @throws \Magento\Framework\Model\Exception */ - public function start($returnUrl, $cancelUrl) + public function start($returnUrl, $cancelUrl, $button = null) { $this->_quote->collectTotals(); @@ -478,12 +506,15 @@ public function start($returnUrl, $cancelUrl) $this->_quote->reserveOrderId()->save(); // prepare API $this->_getApi(); + $solutionType = $this->_config->getMerchantCountry() == 'DE' + ? \Magento\Paypal\Model\Config::EC_SOLUTION_TYPE_MARK + : $this->_config->getConfigValue('solutionType'); $this->_api->setAmount($this->_quote->getBaseGrandTotal()) ->setCurrencyCode($this->_quote->getBaseCurrencyCode()) ->setInvNum($this->_quote->getReservedOrderId()) ->setReturnUrl($returnUrl) ->setCancelUrl($cancelUrl) - ->setSolutionType($this->_config->getConfigValue('solutionType')) + ->setSolutionType($solutionType) ->setPaymentAction($this->_config->getConfigValue('paymentAction')) ; if ($this->_giropayUrls) { @@ -497,6 +528,10 @@ public function start($returnUrl, $cancelUrl) ); } + if ($this->_isBml) { + $this->_api->setFundingSource('BML'); + } + $this->_setBillingAgreementRequest(); if ($this->_config->getConfigValue('requireBillingAddress') == PaypalConfig::REQUIRE_BILLING_ADDRESS_ALL) { @@ -555,12 +590,33 @@ public function start($returnUrl, $cancelUrl) $this->_api->callSetExpressCheckout(); $token = $this->_api->getToken(); - $this->_redirectUrl = $this->_config->getExpressCheckoutStartUrl($token); + $this->_redirectUrl = $button ? $this->_config->getExpressCheckoutStartUrl($token) + : $this->_config->getPayPalBasicStartUrl($token); + + $payment = $this->_quote->getPayment(); + $payment->unsAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT); + // Set flag that we came from Express Checkout button + if (!empty($button)) { + $payment->setAdditionalInformation(self::PAYMENT_INFO_BUTTON, 1); + } elseif ($payment->hasAdditionalInformation(self::PAYMENT_INFO_BUTTON)) { + $payment->unsAdditionalInformation(self::PAYMENT_INFO_BUTTON); + } + $payment->save(); - $this->_quote->getPayment()->unsAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT)->save(); return $token; } + /** + * Check whether system can skip order review page before placing order + * + * @return bool + */ + public function canSkipOrderReviewStep() + { + $isOnepageCheckout = !$this->_quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON); + return $this->_config->isOrderReviewStepDisabled() && $isOnepageCheckout; + } + /** * Update quote when returned from PayPal * rewrite billing address by paypal @@ -579,25 +635,20 @@ public function returnFromPaypal($token) $this->_ignoreAddressValidation(); - // import billing address - $billingAddress = $quote->getBillingAddress(); - $exportedBillingAddress = $this->_api->getExportedBillingAddress(); - $quote->setCustomerEmail($billingAddress->getEmail()); - $quote->setCustomerPrefix($billingAddress->getPrefix()); - $quote->setCustomerFirstname($billingAddress->getFirstname()); - $quote->setCustomerMiddlename($billingAddress->getMiddlename()); - $quote->setCustomerLastname($billingAddress->getLastname()); - $quote->setCustomerSuffix($billingAddress->getSuffix()); - $quote->setCustomerNote($exportedBillingAddress->getData('note')); - $this->_setExportedAddressData($billingAddress, $exportedBillingAddress); - // import shipping address $exportedShippingAddress = $this->_api->getExportedShippingAddress(); if (!$quote->getIsVirtual()) { $shippingAddress = $quote->getShippingAddress(); if ($shippingAddress) { - if ($exportedShippingAddress) { + if ($exportedShippingAddress + && $quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON) == 1 + ) { $this->_setExportedAddressData($shippingAddress, $exportedShippingAddress); + // PayPal doesn't provide detailed shipping info: prefix, middlename, lastname, suffix + $shippingAddress->setPrefix(null); + $shippingAddress->setMiddlename(null); + $shippingAddress->setLastname(null); + $shippingAddress->setSuffix(null); $shippingAddress->setCollectShippingRates(true); $shippingAddress->setSameAsBilling(0); } @@ -618,6 +669,32 @@ public function returnFromPaypal($token) } } + // import billing address + $portBillingFromShipping = $quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON) == 1 + && $this->_config->getConfigValue( + 'requireBillingAddress' + ) != \Magento\Paypal\Model\Config::REQUIRE_BILLING_ADDRESS_ALL + && !$quote->isVirtual(); + if ($portBillingFromShipping) { + $billingAddress = clone $shippingAddress; + $billingAddress->unsAddressId()->unsAddressType(); + $data = $billingAddress->getData(); + $data['save_in_address_book'] = 0; + $quote->getBillingAddress()->addData($data); + $quote->getShippingAddress()->setSameAsBilling(1); + } else { + $billingAddress = $quote->getBillingAddress(); + } + $exportedBillingAddress = $this->_api->getExportedBillingAddress(); + $quote->setCustomerEmail($billingAddress->getEmail()); + $quote->setCustomerPrefix($billingAddress->getPrefix()); + $quote->setCustomerFirstname($billingAddress->getFirstname()); + $quote->setCustomerMiddlename($billingAddress->getMiddlename()); + $quote->setCustomerLastname($billingAddress->getLastname()); + $quote->setCustomerSuffix($billingAddress->getSuffix()); + $quote->setCustomerNote($exportedBillingAddress->getData('note')); + $this->_setExportedAddressData($billingAddress, $exportedBillingAddress); + // import payment info $payment = $quote->getPayment(); $payment->setMethod($this->_methodType); @@ -703,43 +780,11 @@ public function updateShippingMethod($methodCode) if ($methodCode != $shippingAddress->getShippingMethod()) { $this->_ignoreAddressValidation(); $shippingAddress->setShippingMethod($methodCode)->setCollectShippingRates(true); - $this->_quote->collectTotals(); + $this->_quote->collectTotals()->save(); } } } - /** - * Update order data - * - * @param array $data - * @return void - */ - public function updateOrder($data) - { - /** @var $checkout \Magento\Checkout\Model\Type\Onepage */ - $checkout = $this->_checkoutOnepageFactory->create(); - - $this->_quote->setTotalsCollectedFlag(true); - $checkout->setQuote($this->_quote); - if (isset($data['billing'])) { - if (isset($data['customer-email'])) { - $data['billing']['email'] = $data['customer-email']; - } - $checkout->saveBilling($data['billing'], 0); - } - if (!$this->_quote->getIsVirtual() && isset($data['shipping'])) { - $checkout->saveShipping($data['shipping'], 0); - } - - if (isset($data['shipping_method'])) { - $this->updateShippingMethod($data['shipping_method']); - } - $this->_quote->setTotalsCollectedFlag(false); - $this->_quote->collectTotals(); - $this->_quote->setDataChanges(true); - $this->_quote->save(); - } - /** * Place the order when customer returned from PayPal until this moment all quote data must be valid. * @@ -886,20 +931,31 @@ public function getCheckoutMethod() */ protected function _setExportedAddressData($address, $exportedAddress) { - foreach ($exportedAddress->getExportedKeys() as $key) { - $oldData = $address->getDataUsingMethod($key); - $isEmpty = null; - if (is_array($oldData)) { - foreach ($oldData as $val) { - if (!empty($val)) { - $isEmpty = false; - break; + // Exported data is more priority if we came from Express Checkout button + $isButton = (bool)$this->_quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_BUTTON); + if (!$isButton) { + foreach ($exportedAddress->getExportedKeys() as $key) { + $oldData = $address->getDataUsingMethod($key); + $isEmpty = null; + if (is_array($oldData)) { + foreach ($oldData as $val) { + if (!empty($val)) { + $isEmpty = false; + break; + } + $isEmpty = true; } - $isEmpty = true; + } + if (empty($oldData) || $isEmpty === true) { + $address->setDataUsingMethod($key, $exportedAddress->getData($key)); } } - if (empty($oldData) || $isEmpty === true) { - $address->setDataUsingMethod($key, $exportedAddress->getData($key)); + } else { + foreach ($exportedAddress->getExportedKeys() as $key) { + $data = $exportedAddress->getData($key); + if (!empty($data)) { + $address->setDataUsingMethod($key, $data); + } } } } diff --git a/app/code/Magento/Paypal/Model/Observer.php b/app/code/Magento/Paypal/Model/Observer.php index bb4e0f0958863..c2d6515ab78ee 100644 --- a/app/code/Magento/Paypal/Model/Observer.php +++ b/app/code/Magento/Paypal/Model/Observer.php @@ -81,6 +81,16 @@ class Observer */ protected $_checkoutSession; + /** + * @var \Magento\Paypal\Helper\Shortcut\Factory + */ + protected $_shortcutFactory; + + /** + * Shortcut template path + */ + const SHORTCUT_TEMPLATE = 'express/shortcut.phtml'; + /** * @param \Magento\Core\Helper\Data $coreData * @param \Magento\Paypal\Helper\Hss $paypalHss @@ -91,6 +101,7 @@ class Observer * @param \Magento\Framework\AuthorizationInterface $authorization * @param \Magento\Paypal\Model\Billing\AgreementFactory $agreementFactory * @param \Magento\Checkout\Model\Session $checkoutSession + * @param \Magento\Paypal\Helper\Shortcut\Factory $shortcutFactory */ public function __construct( \Magento\Core\Helper\Data $coreData, @@ -101,7 +112,8 @@ public function __construct( \Magento\Framework\App\ViewInterface $view, \Magento\Framework\AuthorizationInterface $authorization, \Magento\Paypal\Model\Billing\AgreementFactory $agreementFactory, - \Magento\Checkout\Model\Session $checkoutSession + \Magento\Checkout\Model\Session $checkoutSession, + \Magento\Paypal\Helper\Shortcut\Factory $shortcutFactory ) { $this->_coreData = $coreData; $this->_paypalHss = $paypalHss; @@ -112,6 +124,7 @@ public function __construct( $this->_authorization = $authorization; $this->_agreementFactory = $agreementFactory; $this->_checkoutSession = $checkoutSession; + $this->_shortcutFactory = $shortcutFactory; } /** @@ -255,33 +268,34 @@ public function addPaypalShortcuts(EventObserver $observer) { /** @var \Magento\Catalog\Block\ShortcutButtons $shortcutButtons */ $shortcutButtons = $observer->getEvent()->getContainer(); - // PayPal Express Checkout - $shortcut = $shortcutButtons->getLayout()->createBlock( + $blocks = [ 'Magento\Paypal\Block\Express\Shortcut', - '', - array('checkoutSession' => $observer->getEvent()->getCheckoutSession()) - ); - $shortcut->setIsInCatalogProduct( - $observer->getEvent()->getIsCatalogProduct() - )->setShowOrPosition( - $observer->getEvent()->getOrPosition() - )->setTemplate( - 'express/shortcut.phtml' - ); - $shortcutButtons->addShortcut($shortcut); - // PayPal Express Checkout Payflow Edition - $shortcut = $shortcutButtons->getLayout()->createBlock( 'Magento\Paypal\Block\PayflowExpress\Shortcut', - '', - array('checkoutSession' => $observer->getEvent()->getCheckoutSession()) - ); - $shortcut->setIsInCatalogProduct( - $observer->getEvent()->getIsCatalogProduct() - )->setShowOrPosition( - $observer->getEvent()->getOrPosition() - )->setTemplate( - 'express/shortcut.phtml' - ); - $shortcutButtons->addShortcut($shortcut); + 'Magento\Paypal\Block\Bml\Shortcut', + 'Magento\Paypal\Block\Payflow\Bml\Shortcut' + ]; + foreach ($blocks as $blockInstanceName) { + $params = [ + 'shortcutValidator' => $this->_shortcutFactory->create($observer->getEvent()->getCheckoutSession()) + ]; + if (!in_array('Bml', explode('/', $blockInstanceName))) { + $params['checkoutSession'] = $observer->getEvent()->getCheckoutSession(); + } + + // we believe it's \Magento\Framework\View\Element\Template + $shortcut = $shortcutButtons->getLayout()->createBlock( + $blockInstanceName, + '', + $params + ); + $shortcut->setIsInCatalogProduct( + $observer->getEvent()->getIsCatalogProduct() + )->setShowOrPosition( + $observer->getEvent()->getOrPosition() + )->setTemplate( + self::SHORTCUT_TEMPLATE + ); + $shortcutButtons->addShortcut($shortcut); + } } } diff --git a/app/code/Magento/Paypal/Block/PayflowExpress/Shortcut.php b/app/code/Magento/Paypal/Model/Payflow/Bml.php similarity index 63% rename from app/code/Magento/Paypal/Block/PayflowExpress/Shortcut.php rename to app/code/Magento/Paypal/Model/Payflow/Bml.php index adbf3c76148c2..e7e3f706a6cdd 100644 --- a/app/code/Magento/Paypal/Block/PayflowExpress/Shortcut.php +++ b/app/code/Magento/Paypal/Model/Payflow/Bml.php @@ -21,42 +21,32 @@ * @copyright Copyright (c) 2014 X.commerce, Inc. (http://www.magentocommerce.com) * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ + +namespace Magento\Paypal\Model\Payflow; -/** - * Paypal expess checkout shortcut link - */ -namespace Magento\Paypal\Block\PayflowExpress; +use Magento\Paypal\Model; -class Shortcut extends \Magento\Paypal\Block\Express\Shortcut +class Bml extends Model\Express { /** * Payment method code - * * @var string */ - protected $_paymentMethodCode = \Magento\Paypal\Model\Config::METHOD_WPP_PE_EXPRESS; + protected $_code = Model\Config::METHOD_WPP_PE_BML; /** - * Start express action - * - * @var string - */ - protected $_startAction = 'paypal/payflowexpress/start'; - - /** - * Express checkout model factory name - * + * Checkout payment form * @var string */ - protected $_checkoutType = 'Magento\Paypal\Model\PayflowExpress\Checkout'; + protected $_formBlockType = 'Magento\Paypal\Block\Payflow\Bml\Form'; /** - * Get shortcut alias + * Checkout redirect URL getter for onepage checkout * * @return string */ - public function getAlias() + public function getCheckoutRedirectUrl() { - return 'product.info.addtocart.payflow'; + return $this->_urlBuilder->getUrl('paypal/payflowbml/start'); } } diff --git a/app/code/Magento/Paypal/Model/PayflowExpress.php b/app/code/Magento/Paypal/Model/PayflowExpress.php index 50d0c2081fbd6..b98753af0689e 100644 --- a/app/code/Magento/Paypal/Model/PayflowExpress.php +++ b/app/code/Magento/Paypal/Model/PayflowExpress.php @@ -59,6 +59,8 @@ class PayflowExpress extends \Magento\Paypal\Model\Express * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\UrlInterface $urlBuilder * @param CartFactory $cartFactory + * @param \Magento\Checkout\Model\Session $checkoutSession + * @param \Magento\Framework\Model\ExceptionFactory $exception * @param InfoFactory $paypalInfoFactory * @param array $data */ @@ -71,6 +73,8 @@ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\UrlInterface $urlBuilder, CartFactory $cartFactory, + \Magento\Checkout\Model\Session $checkoutSession, + \Magento\Framework\Model\ExceptionFactory $exception, InfoFactory $paypalInfoFactory, array $data = array() ) { @@ -83,6 +87,8 @@ public function __construct( $storeManager, $urlBuilder, $cartFactory, + $checkoutSession, + $exception, $data ); $this->_paypalInfoFactory = $paypalInfoFactory; diff --git a/app/code/Magento/Paypal/Model/Payflowlink.php b/app/code/Magento/Paypal/Model/Payflowlink.php index d63d3ffa155ea..989980c6f452c 100644 --- a/app/code/Magento/Paypal/Model/Payflowlink.php +++ b/app/code/Magento/Paypal/Model/Payflowlink.php @@ -561,6 +561,8 @@ protected function _buildBasicRequest(\Magento\Framework\Object $payment) /** @var \Magento\Paypal\Model\Payflow\Request $request */ $request = $this->_requestFactory->create(); $cscEditable = $this->getConfigData('csc_editable'); + /** @var \Magento\Paypal\Model\Config $config */ + $config = $this->_configFactory->create(); $request->setUser( $this->getConfigData('user', $this->_getStoreId()) )->setVendor( @@ -573,7 +575,7 @@ protected function _buildBasicRequest(\Magento\Framework\Object $payment) $this->getConfigData('verbosity', $this->_getStoreId()) )->setData( 'BNCODE', - $this->getConfigData('bncode') + $config->getBuildNotationCode() )->setTender( self::TENDER_CC )->setCancelurl( diff --git a/app/code/Magento/Paypal/Model/Payflowpro.php b/app/code/Magento/Paypal/Model/Payflowpro.php index dd9934815ae8c..2a08c4e4c308f 100644 --- a/app/code/Magento/Paypal/Model/Payflowpro.php +++ b/app/code/Magento/Paypal/Model/Payflowpro.php @@ -683,6 +683,8 @@ protected function _buildPlaceRequest(\Magento\Framework\Object $payment, $amoun protected function _buildBasicRequest(\Magento\Framework\Object $payment) { $request = new \Magento\Framework\Object(); + /** @var \Magento\Paypal\Model\Config $config */ + $config = $this->_configFactory->create(); $request->setUser( $this->getConfigData('user') )->setVendor( @@ -693,6 +695,9 @@ protected function _buildBasicRequest(\Magento\Framework\Object $payment) $this->getConfigData('pwd') )->setVerbosity( $this->getConfigData('verbosity') + )->setData( + 'BNCODE', + $config->getBuildNotationCode() )->setTender( self::TENDER_CC )->setRequestId( diff --git a/app/code/Magento/Paypal/Model/System/Config/Source/BmlPosition.php b/app/code/Magento/Paypal/Model/System/Config/Source/BmlPosition.php new file mode 100644 index 0000000000000..94c008f53dcbb --- /dev/null +++ b/app/code/Magento/Paypal/Model/System/Config/Source/BmlPosition.php @@ -0,0 +1,80 @@ + __('Header (center)'), + '1' => __('Sidebar (right)') + ]; + } + + /** + * Bml positions source getter for Catalog Category Page + * + * @return array + */ + public function getBmlPositionsCCP() + { + return [ + '0' => __('Header (center)'), + '1' => __('Sidebar (right)') + ]; + } + + /** + * Bml positions source getter for Catalog Product Page + * + * @return array + */ + public function getBmlPositionsCPP() + { + return [ + '0' => __('Header (center)'), + '1' => __('Near Bill Me Later checkout button') + ]; + } + + /** + * Bml positions source getter for Checkout Cart Page + * + * @return array + */ + public function getBmlPositionsCheckout() + { + return [ + '0' => __('Header (center)'), + '1' => __('Near Bill Me Later checkout button') + ]; + } +} diff --git a/app/code/Magento/Paypal/Model/System/Config/Source/BmlSize.php b/app/code/Magento/Paypal/Model/System/Config/Source/BmlSize.php new file mode 100644 index 0000000000000..a1c846c7812e3 --- /dev/null +++ b/app/code/Magento/Paypal/Model/System/Config/Source/BmlSize.php @@ -0,0 +1,163 @@ + '190 x 100', + '234x60' => '234 x 60', + '300x50' => '300 x 50', + '468x60' => '468 x 60', + '728x90' => '728 x 90', + '800x66' => '800 x 66' + ]; + } + + /** + * Options getter for Home Page and position Sidebar (right) + * + * @return array + */ + public function getBmlSizeHPS() + { + return [ + '120x90' => '120 x 90', + '190x100' => '190 x 100', + '234x60' => '234 x 60', + '120x240' => '120 x 240', + '120x600' => '120 x 600', + '234x400' => '234 x 400', + '250x250' => '250 x 250' + ]; + } + + /** + * Options getter for Catalog Category Page and position Center + * + * @return array + */ + public function getBmlSizeCCPC() + { + return [ + '190x100' => '190 x 100', + '234x60' => '234 x 60', + '300x50' => '300 x 50', + '468x60' => '468 x 60', + '728x90' => '728 x 90', + '800x66' => '800 x 66' + ]; + } + + /** + * Options getter for Catalog Category Page and position Sidebar (right) + * + * @return array + */ + public function getBmlSizeCCPS() + { + return [ + '120x90' => '120 x 90', + '190x100' => '190 x 100', + '234x60' => '234 x 60', + '120x240' => '120 x 240', + '120x600' => '120 x 600', + '234x400' => '234 x 400', + '250x250' => '250 x 250' + ]; + } + + /** + * Options getter for Catalog Product Page and position Center + * + * @return array + */ + public function getBmlSizeCPPC() + { + return [ + '190x100' => '190 x 100', + '234x60' => '234 x 60', + '300x50' => '300 x 50', + '468x60' => '468 x 60', + '728x90' => '728 x 90', + '800x66' => '800 x 66' + ]; + } + + /** + * Options getter for Catalog Product Page and position Near Bill Me Later checkout button + * + * @return array + */ + public function getBmlSizeCPPN() + { + return [ + '120x90' => '120 x 90', + '190x100' => '190 x 100', + '234x60' => '234 x 60', + '120x240' => '120 x 240', + '120x600' => '120 x 600', + '234x400' => '234 x 400', + '250x250' => '250 x 250' + ]; + } + + /** + * Options getter for Checkout Cart Page and position Center + * + * @return array + */ + public function getBmlSizeCheckoutC() + { + return [ + '234x60' => '234 x 60', + '300x50' => '300 x 50', + '468x60' => '468 x 60', + '728x90' => '728 x 90', + '800x66' => '800 x 66' + ]; + } + + /** + * Options getter for Checkout Cart Page and position Near Bill Me Later checkout button + * + * @return array + */ + public function getBmlSizeCheckoutN() + { + return [ + '234x60' => '234 x 60', + '300x50' => '300 x 50', + '468x60' => '468 x 60' + ]; + } +} diff --git a/app/code/Magento/Paypal/etc/adminhtml/system.xml b/app/code/Magento/Paypal/etc/adminhtml/system.xml index 82bf0a09bf352..6f826847aefca 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system.xml @@ -79,6 +79,109 @@ paypal-enabler 1 + + Learn More]]> + + + + + + + + + Why Advertise Financing?
+ Give your sales a boost when you advertise financing.
PayPal helps turn browsers into buyers with financing + from Bill Me Later®. Your customers have more time to pay, while you get paid up front – at no additional cost to you. + Use PayPal’s free banner ads that let you advertise Bill Me Later® financing as a payment option when your customers check out with PayPal. + The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15% + or more. See Details.]]> +
+ + + + + + + + + payment/paypal_express_bml/homepage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPH + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPS + + 1 + + + + + + + + + + payment/paypal_express_bml/categorypage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPS + + 1 + + + + + + + + + + payment/paypal_express_bml/productpage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPN + + 1 + + + + + + + + + + + payment/paypal_express_bml/checkout_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutN + 1 + + 1 + + + +
@@ -250,6 +353,7 @@ + @@ -639,6 +743,111 @@ + + + Learn More]]> + + payment/paypal_express_bml/active + + + + + + + + Why Advertise Financing?
+ Give your sales a boost when you advertise financing.
PayPal helps turn browsers into buyers with financing + from Bill Me Later®. Your customers have more time to pay, while you get paid up front – at no additional cost to you. + Use PayPal’s free banner ads that let you advertise Bill Me Later® financing as a payment option when your customers check out with PayPal. + The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15% + or more. See Details.]]> +
+ + + + + + + + + payment/paypal_express_bml/homepage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPH + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPS + + 1 + + + + + + + + + + payment/paypal_express_bml/categorypage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPS + + 1 + + + + + + + + + + payment/paypal_express_bml/productpage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPN + + 1 + + + + + + + + + + payment/paypal_express_bml/checkout_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutN + 1 + + 1 + + + +
@@ -865,6 +1074,153 @@ paypal-enabler paypal-ec-enabler + + + + Learn More]]> + + payment/paypal_express_bml/active + Magento\Backend\Model\Config\Source\Yesno + 1 + + + + paypal-bml + + @@ -1004,6 +1360,12 @@ Magento\Paypal\Model\Config::getExpressCheckoutBASignupOptions 1 + + + payment/paypal_express/skip_order_review_step + Magento\Backend\Model\Config\Source\Yesno + 1 + @@ -1230,6 +1592,110 @@ paypal-enabler paypal-ec-separate + + + Learn More]]> + + + + + + + + + Why Advertise Financing?
+ Give your sales a boost when you advertise financing.
PayPal helps turn browsers into buyers with financing + from Bill Me Later®. Your customers have more time to pay, while you get paid up front – at no additional cost to you. + Use PayPal’s free banner ads that let you advertise Bill Me Later® financing as a payment option when your customers check out with PayPal. + The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15% + or more. See Details.]]> +
+ + + + + + + + + payment/paypal_express_bml/homepage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPH + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPS + + 1 + + + + + + + + + + payment/paypal_express_bml/categorypage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPS + + 1 + + + + + + + + + + payment/paypal_express_bml/productpage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPN + + 1 + + + + + + + + + + payment/paypal_express_bml/checkout_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutN + 1 + + 1 + + + +
@@ -1394,7 +1860,7 @@ 1 - + payment/payflow_advanced/active Magento\Backend\Model\Config\Source\Yesno @@ -1410,6 +1876,110 @@ + + Learn More]]> + + + + + + + + + + Why Advertise Financing?
+ Give your sales a boost when you advertise financing.
PayPal helps turn browsers into buyers with financing + from Bill Me Later®. Your customers have more time to pay, while you get paid up front – at no additional cost to you. + Use PayPal’s free banner ads that let you advertise Bill Me Later® financing as a payment option when your customers check out with PayPal. + The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15% + or more. See Details.]]> +
+ + + + + + + + + payment/paypal_express_bml/homepage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPH + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPS + + 1 + + + + + + + + + + payment/paypal_express_bml/categorypage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPS + + 1 + + + + + + + + + + payment/paypal_express_bml/productpage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPN + + 1 + + + + + + + + + + + payment/paypal_express_bml/checkout_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutN + 1 + + 1 + + + +
@@ -1572,6 +2142,116 @@ + + + + + Learn More]]> + + payment/payflow_express_bml/active + Magento\Backend\Model\Config\Source\Yesno + 1 + paypal-bml + + + + + + + + Why Advertise Financing?
+ Give your sales a boost when you advertise financing.
PayPal helps turn browsers into buyers with financing + from Bill Me Later®. Your customers have more time to pay, while you get paid up front – at no additional cost to you. + Use PayPal’s free banner ads that let you advertise Bill Me Later® financing as a payment option when your customers check out with PayPal. + The PayPal Advertising Program has been shown to generate additional purchases as well as increase consumer's average purchase sizes by 15% + or more. See Details.]]> +
+ + + + + + + + + payment/paypal_express_bml/homepage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPH + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeHPS + + 1 + + + + + + + + + + payment/paypal_express_bml/categorypage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCCPS + + 1 + + + + + + + + + + payment/paypal_express_bml/productpage_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCPPN + + 1 + + + + + + + + + + payment/paypal_express_bml/checkout_size + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutC + 1 + + 0 + + + + Magento\Paypal\Model\System\Config\Source\BmlSize::getBmlSizeCheckoutN + 1 + + 1 + + + +
@@ -1656,12 +2336,14 @@ Magento\Backend\Model\Config\Source\Yesno 1 + + payment/paypal_express/active payment/payflow_express/active @@ -1745,6 +2427,7 @@ + @@ -1758,7 +2441,13 @@ Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Group Add another payment method to your existing solution or as a stand-alone option. https://www.paypal-marketing.com/emarketing/partner/na/merchantlineup/home.page#mainTab=checkoutlineup&subTab=newlineup - + + + + + + +
@@ -1777,6 +2466,7 @@ + payment/paypal_express/active payment/payflow_express/active diff --git a/app/code/Magento/Paypal/etc/config.xml b/app/code/Magento/Paypal/etc/config.xml index 6202193ac0097..76ef61da6a0e5 100644 --- a/app/code/Magento/Paypal/etc/config.xml +++ b/app/code/Magento/Paypal/etc/config.xml @@ -26,6 +26,7 @@ + Magento_Cart_Community @@ -61,7 +62,13 @@ 29 1 1 + 1 + + Magento\Paypal\Model\Bml + Bill Me Later + paypal + Magento\Paypal\Model\Direct PayPal Payments Pro @@ -89,6 +96,11 @@ 1 Magento\Paypal\Model\PayflowExpress + + Magento\Paypal\Model\Payflow\Bml + Bill Me Later + paypal + Magento\Paypal\Model\Payflowpro Payflow Pro diff --git a/app/code/Magento/Paypal/etc/di.xml b/app/code/Magento/Paypal/etc/di.xml index e9488eaa55119..ea1b152a85dad 100644 --- a/app/code/Magento/Paypal/etc/di.xml +++ b/app/code/Magento/Paypal/etc/di.xml @@ -51,4 +51,37 @@ Magento\Paypal\Model\Payflow\ProFactory + + + + Magento\Paypal\Model\Config::METHOD_WPP_EXPRESS + paypal/express/start/button/1 + Magento\Paypal\Model\Express\Checkout + product.info.addtocart.paypal + + + + + Magento\Paypal\Model\Config::METHOD_WPP_PE_EXPRESS + paypal/payflowexpress/start/button/1 + Magento\Paypal\Model\PayflowExpress\Checkout + product.info.addtocart.payflow + + + + + Magento\Paypal\Model\Config::METHOD_WPP_EXPRESS + paypal/bml/start/button/1 + Magento\Paypal\Model\Config::METHOD_WPP_BML + product.info.addtocart.paypalbml + + + + + Magento\Paypal\Model\Config::METHOD_WPP_PE_EXPRESS + paypal/payflowbml/start/button/1 + Magento\Paypal\Model\Config::METHOD_WPP_PE_BML + product.info.addtocart.payflowbml + + diff --git a/app/code/Magento/Paypal/etc/module.xml b/app/code/Magento/Paypal/etc/module.xml index 06a0b12f1558f..a15d87db00156 100644 --- a/app/code/Magento/Paypal/etc/module.xml +++ b/app/code/Magento/Paypal/etc/module.xml @@ -24,7 +24,7 @@ */ --> - + diff --git a/app/code/Magento/Paypal/view/adminhtml/templates/system/config/bml_api_wizard.phtml b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/bml_api_wizard.phtml new file mode 100644 index 0000000000000..0ecb30227ad21 --- /dev/null +++ b/app/code/Magento/Paypal/view/adminhtml/templates/system/config/bml_api_wizard.phtml @@ -0,0 +1,34 @@ + + +
+ +
\ No newline at end of file diff --git a/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml b/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml index 3ff6aca71647f..231c027d4a468 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/catalog_category_view.xml @@ -24,7 +24,21 @@ */ --> - + + + + + categorypage + 0 + + diff --git a/app/code/Magento/Paypal/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Paypal/view/frontend/layout/catalog_product_view.xml new file mode 100644 index 0000000000000..206662b17aa69 --- /dev/null +++ b/app/code/Magento/Paypal/view/frontend/layout/catalog_product_view.xml @@ -0,0 +1,43 @@ + + + + + + + productpage + 0 + + + + + + + productpage + 1 + + + + diff --git a/app/code/Magento/Paypal/view/frontend/layout/checkout_cart_index.xml b/app/code/Magento/Paypal/view/frontend/layout/checkout_cart_index.xml new file mode 100644 index 0000000000000..ff8df46b11fd9 --- /dev/null +++ b/app/code/Magento/Paypal/view/frontend/layout/checkout_cart_index.xml @@ -0,0 +1,43 @@ + + + + + + + checkout + 0 + + + + + + + checkout + 1 + + + + diff --git a/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_index.xml index f8ed5a58e7f67..f80df51b352ef 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_index.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/checkout_onepage_index.xml @@ -30,4 +30,12 @@ + + + + checkout + 0 + + + diff --git a/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml b/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml index 3ff6aca71647f..e8f4d422533a8 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/cms_index_index.xml @@ -26,5 +26,19 @@ + + + + homepage + 0 + + diff --git a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml index 4629e28332c60..373939fdfb25c 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/paypal_express_review.xml @@ -36,10 +36,6 @@ - - + template="express/review.phtml"> paypal/payflowexpress + diff --git a/app/code/Magento/Paypal/view/frontend/templates/bml.phtml b/app/code/Magento/Paypal/view/frontend/templates/bml.phtml new file mode 100644 index 0000000000000..26448addf9daf --- /dev/null +++ b/app/code/Magento/Paypal/view/frontend/templates/bml.phtml @@ -0,0 +1,38 @@ + + + \ No newline at end of file diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml index af05fd0c913a4..dd3f730f57093 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/express/review.phtml @@ -23,89 +23,123 @@ */ /** @var $this \Magento\Paypal\Block\Express\Review */ -$billingBlock = $this->getChildBlock('billing')->setFieldNamePrefix('billing')->setHideEmailAddress(true); -$shippingAddress = $this->getShippingAddress(); ?>

-getLayout()->getMessagesBlock()->toHtml() ?>
-
Please confirm your addresses
+ getShippingAddress()): ?> +
+
+
+
+ + + getCanEditShippingAddress()): ?> + + + -
- isCustomerLoggedIn()): ?> - - -
- -
- - setShowAsShippingCheckbox(true)->toHtml(); ?> - - toHtml(); ?> - -
+
+ - -
- -
- getChildBlock('shipping')->setFieldNamePrefix('shipping')->setHideEmailAddress(true)->toHtml(); ?> -
+
+ + getCanEditShippingMethod() || !$this->getCurrentShippingRate()): ?> + getShippingRateGroups()): ?> + getCurrentShippingRate(); ?> +
+ +
+
+ +
+ +

+ + +

renderShippingRateOption($this->getCurrentShippingRate()) ?>

+ + +
+
+
+
+ -
- -
- getChildBlock('shipping_method')->toHtml(); ?> -
- +
+
+
+
+ + + getEditUrl()): ?> + + -
-
- - +
+ escapeHtml($this->getPaymentMethodTitle()) ?> +
+
+
-
- getChildHtml('details') ?> -
+
+
+ +
- getChildHtml('agreements'); ?> -
- - - - +
+ getChildHtml('details') ?>
- + +
+ getChildHtml('agreements'); ?> +
+ + + +
+
+
diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/review/address.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/review/address.phtml deleted file mode 100644 index 38c73911088c5..0000000000000 --- a/app/code/Magento/Paypal/view/frontend/templates/express/review/address.phtml +++ /dev/null @@ -1,194 +0,0 @@ - - -getFieldNamePrefix(); ?> - -getLayout()->createBlock('Magento\Customer\Block\Widget\Name'); -$widgetObject = $this->getAddress()->getFirstname() ? $this->getAddress() : $this->getQuote()->getCustomerData(); -echo $nameWidget - ->setObject($widgetObject) - ->setForceUseCustomerRequiredAttributes(!$this->isCustomerLoggedIn()) - ->setFieldIdFormat($prefix . ':%s') - ->setFieldNameFormat($prefix . '[%s]') - ->toHtml() -?> - -
- - -
- -
-
- -isCustomerLoggedIn() && !$this->getHideEmailAddress()): ?> - - - -helper('Magento\Customer\Helper\Address')->getAttributeValidationClass('street'); ?> -
- - -
- - - helper('Magento\Customer\Helper\Address')->getStreetLines(); $_i <= $_n; $_i++): ?> -
- -
- -
-
- -helper('Magento\Customer\Helper\Address')->isVatAttributeVisible()) : ?> -
- - -
- -
-
- - -
- - -
- -
-
- -
- - -
- - -
-
- -
- - -
- -
-
- -
- - -
- getCountryHtmlSelect($prefix) ?> -
-
- -
- - -
- -
-
- -
- - -
- -
-
- -getChildHtml('form.additional.info'); ?> -getShowAsShippingCheckbox()): ?> -
- getAddress()->getSameAsBilling()): ?>checked="checked"/> - -
- - - diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml index b903823ef7a33..e076babdc281b 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut.phtml @@ -35,8 +35,8 @@ if ($this->isOrPositionBefore()) { $labelPosition = ' after'; } ?> -