diff --git a/app/code/Magento/Cookie/view/frontend/web/js/notices.js b/app/code/Magento/Cookie/view/frontend/web/js/notices.js
index d7f0fa3874756..0b526ca5c27e3 100644
--- a/app/code/Magento/Cookie/view/frontend/web/js/notices.js
+++ b/app/code/Magento/Cookie/view/frontend/web/js/notices.js
@@ -20,7 +20,10 @@ define([
$(this.options.cookieAllowButtonSelector).on('click', $.proxy(function() {
var cookieExpires = new Date(new Date().getTime() + this.options.cookieLifetime * 1000);
- $.mage.cookies.set(this.options.cookieName, this.options.cookieValue, {expires: cookieExpires});
+ $.mage.cookies.set(this.options.cookieName, JSON.stringify(this.options.cookieValue), {
+ expires: cookieExpires
+ });
+
if ($.mage.cookies.get(this.options.cookieName)) {
window.location.reload();
} else {
diff --git a/app/code/Magento/Customer/Model/Address.php b/app/code/Magento/Customer/Model/Address.php
index 75bdb7601a341..f012edb6700d4 100644
--- a/app/code/Magento/Customer/Model/Address.php
+++ b/app/code/Magento/Customer/Model/Address.php
@@ -350,7 +350,9 @@ public function reindex()
{
/** @var \Magento\Framework\Indexer\IndexerInterface $indexer */
$indexer = $this->indexerRegistry->get(Customer::CUSTOMER_GRID_INDEXER_ID);
- $indexer->reindexRow($this->getCustomerId());
+ if (!$indexer->isScheduled()) {
+ $indexer->reindexRow($this->getCustomerId());
+ }
}
/**
diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php
index 6327b7e3c5c76..6f19fc02e0b11 100644
--- a/app/code/Magento/Customer/Model/Customer.php
+++ b/app/code/Magento/Customer/Model/Customer.php
@@ -1076,7 +1076,9 @@ public function reindex()
{
/** @var \Magento\Framework\Indexer\IndexerInterface $indexer */
$indexer = $this->indexerRegistry->get(self::CUSTOMER_GRID_INDEXER_ID);
- $indexer->reindexRow($this->getId());
+ if (!$indexer->isScheduled()) {
+ $indexer->reindexRow($this->getId());
+ }
}
/**
diff --git a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php
index a996b059455eb..d037f866ffaca 100644
--- a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php
+++ b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php
@@ -14,6 +14,7 @@
/**
* Customer repository.
+ *
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class CustomerRepository implements \Magento\Customer\Api\CustomerRepositoryInterface
@@ -131,15 +132,19 @@ public function __construct(
/**
* {@inheritdoc}
- * @SuppressWarnings(PHPMD.CyclomaticComplexity)
- * @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function save(\Magento\Customer\Api\Data\CustomerInterface $customer, $passwordHash = null)
{
$prevCustomerData = null;
+ $prevCustomerDataArr = null;
+
if ($customer->getId()) {
$prevCustomerData = $this->getById($customer->getId());
+ $prevCustomerDataArr = $prevCustomerData->__toArray();
}
+
+ /** @var $customer \Magento\Customer\Model\Data\Customer */
+ $customerArr = $customer->__toArray();
$customer = $this->imageProcessor->save(
$customer,
CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER,
@@ -151,15 +156,17 @@ public function save(\Magento\Customer\Api\Data\CustomerInterface $customer, $pa
$customerData = $this->extensibleDataObjectConverter->toNestedArray(
$customer,
[],
- '\Magento\Customer\Api\Data\CustomerInterface'
+ \Magento\Customer\Api\Data\CustomerInterface::class
);
$customer->setAddresses($origAddresses);
$customerModel = $this->customerFactory->create(['data' => $customerData]);
$storeId = $customerModel->getStoreId();
+
if ($storeId === null) {
$customerModel->setStoreId($this->storeManager->getStore()->getId());
}
+
$customerModel->setId($customer->getId());
// Need to use attribute set or future updates can cause data loss
@@ -169,19 +176,7 @@ public function save(\Magento\Customer\Api\Data\CustomerInterface $customer, $pa
);
}
// Populate model with secure data
- if ($customer->getId()) {
- $customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId());
- $customerModel->setRpToken($customerSecure->getRpToken());
- $customerModel->setRpTokenCreatedAt($customerSecure->getRpTokenCreatedAt());
- $customerModel->setPasswordHash($customerSecure->getPasswordHash());
- $customerModel->setFailuresNum($customerSecure->getFailuresNum());
- $customerModel->setFirstFailure($customerSecure->getFirstFailure());
- $customerModel->setLockExpires($customerSecure->getLockExpires());
- } else {
- if ($passwordHash) {
- $customerModel->setPasswordHash($passwordHash);
- }
- }
+ $this->populateCustomerModelWithSecureData($customer, $passwordHash, $customerModel);
// If customer email was changed, reset RpToken info
if ($prevCustomerData
@@ -190,36 +185,16 @@ public function save(\Magento\Customer\Api\Data\CustomerInterface $customer, $pa
$customerModel->setRpToken(null);
$customerModel->setRpTokenCreatedAt(null);
}
+
+ $this->setDefaultBilling($customerArr, $prevCustomerDataArr, $customerModel);
+
+ $this->setDefaultShipping($customerArr, $prevCustomerDataArr, $customerModel);
+
$customerModel->save();
$this->customerRegistry->push($customerModel);
$customerId = $customerModel->getId();
- if ($customer->getAddresses() !== null) {
- if ($customer->getId()) {
- $existingAddresses = $this->getById($customer->getId())->getAddresses();
- $getIdFunc = function ($address) {
- return $address->getId();
- };
- $existingAddressIds = array_map($getIdFunc, $existingAddresses);
- } else {
- $existingAddressIds = [];
- }
-
- $savedAddressIds = [];
- foreach ($customer->getAddresses() as $address) {
- $address->setCustomerId($customerId)
- ->setRegion($address->getRegion());
- $this->addressRepository->save($address);
- if ($address->getId()) {
- $savedAddressIds[] = $address->getId();
- }
- }
-
- $addressIdsToDelete = array_diff($existingAddressIds, $savedAddressIds);
- foreach ($addressIdsToDelete as $addressId) {
- $this->addressRepository->deleteById($addressId);
- }
- }
+ $this->updateAddresses($customer, $customerId);
$savedCustomer = $this->get($customer->getEmail(), $customer->getWebsiteId());
$this->eventManager->dispatch(
@@ -256,7 +231,10 @@ public function getList(SearchCriteriaInterface $searchCriteria)
$searchResults->setSearchCriteria($searchCriteria);
/** @var \Magento\Customer\Model\ResourceModel\Customer\Collection $collection */
$collection = $this->customerFactory->create()->getCollection();
- $this->extensionAttributesJoinProcessor->process($collection, 'Magento\Customer\Api\Data\CustomerInterface');
+ $this->extensionAttributesJoinProcessor->process(
+ $collection,
+ \Magento\Customer\Api\Data\CustomerInterface::class
+ );
// This is needed to make sure all the attributes are properly loaded
foreach ($this->customerMetadata->getAllAttributesMetadata() as $metadata) {
$collection->addAttributeToSelect($metadata->getAttributeCode());
@@ -336,4 +314,112 @@ protected function addFilterGroupToCollection(
$collection->addFieldToFilter($fields);
}
}
+
+ /**
+ * Update customer addresses.
+ *
+ * @param \Magento\Framework\Api\CustomAttributesDataInterface $customer
+ * @param int $customerId
+ * @return void
+ * @throws \Magento\Framework\Exception\InputException
+ */
+ private function updateAddresses(\Magento\Framework\Api\CustomAttributesDataInterface $customer, $customerId)
+ {
+ if ($customer->getAddresses() !== null) {
+ if ($customer->getId()) {
+ $existingAddresses = $this->getById($customer->getId())->getAddresses();
+ $getIdFunc = function ($address) {
+ return $address->getId();
+ };
+ $existingAddressIds = array_map($getIdFunc, $existingAddresses);
+ } else {
+ $existingAddressIds = [];
+ }
+
+ $savedAddressIds = [];
+ foreach ($customer->getAddresses() as $address) {
+ $address->setCustomerId($customerId)
+ ->setRegion($address->getRegion());
+ $this->addressRepository->save($address);
+ if ($address->getId()) {
+ $savedAddressIds[] = $address->getId();
+ }
+ }
+
+ $addressIdsToDelete = array_diff($existingAddressIds, $savedAddressIds);
+ foreach ($addressIdsToDelete as $addressId) {
+ $this->addressRepository->deleteById($addressId);
+ }
+ }
+ }
+
+ /**
+ * Populate customer model with secure data.
+ *
+ * @param \Magento\Framework\Api\CustomAttributesDataInterface $customer
+ * @param string $passwordHash
+ * @param \Magento\Customer\Model\Customer\Interceptor $customerModel
+ * @return void
+ */
+ private function populateCustomerModelWithSecureData(
+ \Magento\Framework\Api\CustomAttributesDataInterface $customer,
+ $passwordHash,
+ $customerModel
+ ) {
+ if ($customer->getId()) {
+ $customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId());
+ $customerModel->setRpToken($customerSecure->getRpToken());
+ $customerModel->setRpTokenCreatedAt($customerSecure->getRpTokenCreatedAt());
+ $customerModel->setPasswordHash($customerSecure->getPasswordHash());
+ $customerModel->setFailuresNum($customerSecure->getFailuresNum());
+ $customerModel->setFirstFailure($customerSecure->getFirstFailure());
+ $customerModel->setLockExpires($customerSecure->getLockExpires());
+ } else {
+ if ($passwordHash) {
+ $customerModel->setPasswordHash($passwordHash);
+ }
+ }
+ }
+
+ /**
+ * Set default billing.
+ *
+ * @param array $customerArr
+ * @param array $prevCustomerDataArr
+ * @param \Magento\Customer\Model\Customer\Interceptor $customerModel
+ * @return void
+ */
+ private function setDefaultBilling(
+ $customerArr,
+ $prevCustomerDataArr,
+ $customerModel
+ ) {
+ if (!array_key_exists('default_billing', $customerArr) &&
+ null !== $prevCustomerDataArr &&
+ array_key_exists('default_billing', $prevCustomerDataArr)
+ ) {
+ $customerModel->setDefaultBilling($prevCustomerDataArr['default_billing']);
+ }
+ }
+
+ /**
+ * Set default shipping.
+ *
+ * @param array $customerArr
+ * @param array $prevCustomerDataArr
+ * @param \Magento\Customer\Model\Customer\Interceptor $customerModel
+ * @return void
+ */
+ private function setDefaultShipping(
+ $customerArr,
+ $prevCustomerDataArr,
+ $customerModel
+ ) {
+ if (!array_key_exists('default_shipping', $customerArr) &&
+ null !== $prevCustomerDataArr &&
+ array_key_exists('default_shipping', $prevCustomerDataArr)
+ ) {
+ $customerModel->setDefaultShipping($prevCustomerDataArr['default_shipping']);
+ }
+ }
}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php
index 0152b8631051e..0178d2d9c86b6 100644
--- a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php
@@ -91,77 +91,78 @@ class CustomerRepositoryTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->customerResourceModel =
- $this->getMock('Magento\Customer\Model\ResourceModel\Customer', [], [], '', false);
- $this->customerRegistry = $this->getMock('Magento\Customer\Model\CustomerRegistry', [], [], '', false);
- $this->dataObjectHelper = $this->getMock('Magento\Framework\Api\DataObjectHelper', [], [], '', false);
- $this->customerFactory = $this->getMock('Magento\Customer\Model\CustomerFactory', ['create'], [], '', false);
+ $this->getMock(\Magento\Customer\Model\ResourceModel\Customer::class, [], [], '', false);
+ $this->customerRegistry = $this->getMock(\Magento\Customer\Model\CustomerRegistry::class, [], [], '', false);
+ $this->dataObjectHelper = $this->getMock(\Magento\Framework\Api\DataObjectHelper::class, [], [], '', false);
+ $this->customerFactory = $this->getMock(
+ \Magento\Customer\Model\CustomerFactory::class,
+ ['create'],
+ [],
+ '',
+ false
+ );
$this->customerSecureFactory = $this->getMock(
- 'Magento\Customer\Model\Data\CustomerSecureFactory',
+ \Magento\Customer\Model\Data\CustomerSecureFactory::class,
['create'],
[],
'',
false
);
-
$this->addressRepository = $this->getMock(
- 'Magento\Customer\Model\ResourceModel\AddressRepository',
+ \Magento\Customer\Model\ResourceModel\AddressRepository::class,
[],
[],
'',
false
);
-
$this->customerMetadata = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\CustomerMetadataInterface',
+ \Magento\Customer\Api\CustomerMetadataInterface::class,
[],
'',
false
);
$this->searchResultsFactory = $this->getMock(
- 'Magento\Customer\Api\Data\CustomerSearchResultsInterfaceFactory',
+ \Magento\Customer\Api\Data\CustomerSearchResultsInterfaceFactory::class,
['create'],
[],
'',
false
);
$this->eventManager = $this->getMockForAbstractClass(
- 'Magento\Framework\Event\ManagerInterface',
+ \Magento\Framework\Event\ManagerInterface::class,
[],
'',
false
);
$this->storeManager = $this->getMockForAbstractClass(
- 'Magento\Store\Model\StoreManagerInterface',
+ \Magento\Store\Model\StoreManagerInterface::class,
[],
'',
false
);
$this->extensibleDataObjectConverter = $this->getMock(
- 'Magento\Framework\Api\ExtensibleDataObjectConverter',
+ \Magento\Framework\Api\ExtensibleDataObjectConverter::class,
[],
[],
'',
false
);
$this->imageProcessor = $this->getMockForAbstractClass(
- 'Magento\Framework\Api\ImageProcessorInterface',
+ \Magento\Framework\Api\ImageProcessorInterface::class,
[],
'',
false
);
$this->extensionAttributesJoinProcessor = $this->getMockForAbstractClass(
- 'Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface',
- [],
- '',
- false
- );
- $this->customer = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\Data\CustomerInterface',
+ \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface::class,
[],
'',
false
);
-
+ $this->customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)
+ ->setMethods(['__toArray'])
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
$this->model = new \Magento\Customer\Model\ResourceModel\CustomerRepository(
$this->customerFactory,
$this->customerSecureFactory,
@@ -187,9 +188,9 @@ public function testSave()
$customerId = 1;
$storeId = 2;
- $region = $this->getMockForAbstractClass('Magento\Customer\Api\Data\RegionInterface', [], '', false);
+ $region = $this->getMockForAbstractClass(\Magento\Customer\Api\Data\RegionInterface::class, [], '', false);
$address = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\Data\AddressInterface',
+ \Magento\Customer\Api\Data\AddressInterface::class,
[],
'',
false,
@@ -203,7 +204,7 @@ public function testSave()
]
);
$address2 = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\Data\AddressInterface',
+ \Magento\Customer\Api\Data\AddressInterface::class,
[],
'',
false,
@@ -217,7 +218,7 @@ public function testSave()
]
);
$customerModel = $this->getMock(
- 'Magento\Customer\Model\Customer',
+ \Magento\Customer\Model\Customer::class,
[
'getId',
'setId',
@@ -238,8 +239,11 @@ public function testSave()
'',
false
);
+ $this->customer->expects($this->atLeastOnce())
+ ->method('__toArray')
+ ->willReturn(['default_billing', 'default_shipping']);
$customerAttributesMetaData = $this->getMockForAbstractClass(
- 'Magento\Framework\Api\CustomAttributesDataInterface',
+ \Magento\Framework\Api\CustomAttributesDataInterface::class,
[],
'',
false,
@@ -254,7 +258,7 @@ public function testSave()
]
);
$customerSecureData = $this->getMock(
- 'Magento\Customer\Model\Data\CustomerSecure',
+ \Magento\Customer\Model\Data\CustomerSecure::class,
[
'getRpToken',
'getRpTokenCreatedAt',
@@ -305,7 +309,7 @@ public function testSave()
->with([$address]);
$this->extensibleDataObjectConverter->expects($this->once())
->method('toNestedArray')
- ->with($customerAttributesMetaData, [], '\Magento\Customer\Api\Data\CustomerInterface')
+ ->with($customerAttributesMetaData, [], \Magento\Customer\Api\Data\CustomerInterface::class)
->willReturn(['customerData']);
$this->customerFactory->expects($this->once())
->method('create')
@@ -428,9 +432,9 @@ public function testSaveWithPasswordHash()
$storeId = 2;
$passwordHash = 'ukfa4sdfa56s5df02asdf4rt';
- $region = $this->getMockForAbstractClass('Magento\Customer\Api\Data\RegionInterface', [], '', false);
+ $region = $this->getMockForAbstractClass(\Magento\Customer\Api\Data\RegionInterface::class, [], '', false);
$address = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\Data\AddressInterface',
+ \Magento\Customer\Api\Data\AddressInterface::class,
[],
'',
false,
@@ -444,7 +448,7 @@ public function testSaveWithPasswordHash()
]
);
$address2 = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\Data\AddressInterface',
+ \Magento\Customer\Api\Data\AddressInterface::class,
[],
'',
false,
@@ -457,8 +461,12 @@ public function testSaveWithPasswordHash()
'getId'
]
);
+ $this->customer->expects($this->atLeastOnce())
+ ->method('__toArray')
+ ->willReturn(['default_billing', 'default_shipping']);
+
$customerModel = $this->getMock(
- 'Magento\Customer\Model\Customer',
+ \Magento\Customer\Model\Customer::class,
[
'getId',
'setId',
@@ -477,7 +485,7 @@ public function testSaveWithPasswordHash()
false
);
$customerAttributesMetaData = $this->getMockForAbstractClass(
- 'Magento\Framework\Api\CustomAttributesDataInterface',
+ \Magento\Framework\Api\CustomAttributesDataInterface::class,
[],
'',
false,
@@ -529,7 +537,7 @@ public function testSaveWithPasswordHash()
->with([$address]);
$this->extensibleDataObjectConverter->expects($this->once())
->method('toNestedArray')
- ->with($customerAttributesMetaData, [], '\Magento\Customer\Api\Data\CustomerInterface')
+ ->with($customerAttributesMetaData, [], \Magento\Customer\Api\Data\CustomerInterface::class)
->willReturn(['customerData']);
$this->customerFactory->expects($this->once())
->method('create')
@@ -600,24 +608,30 @@ public function testSaveWithPasswordHash()
*/
public function testGetList()
{
- $sortOrder = $this->getMock('Magento\Framework\Api\SortOrder', [], [], '', false);
- $filterGroup = $this->getMock('Magento\Framework\Api\Search\FilterGroup', [], [], '', false);
- $filter = $this->getMock('Magento\Framework\Api\Filter', [], [], '', false);
- $collection = $this->getMock('Magento\Customer\Model\ResourceModel\Customer\Collection', [], [], '', false);
+ $sortOrder = $this->getMock(\Magento\Framework\Api\SortOrder::class, [], [], '', false);
+ $filterGroup = $this->getMock(\Magento\Framework\Api\Search\FilterGroup::class, [], [], '', false);
+ $filter = $this->getMock(\Magento\Framework\Api\Filter::class, [], [], '', false);
+ $collection = $this->getMock(
+ \Magento\Customer\Model\ResourceModel\Customer\Collection::class,
+ [],
+ [],
+ '',
+ false
+ );
$searchResults = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\Data\AddressSearchResultsInterface',
+ \Magento\Customer\Api\Data\AddressSearchResultsInterface::class,
[],
'',
false
);
$searchCriteria = $this->getMockForAbstractClass(
- 'Magento\Framework\Api\SearchCriteriaInterface',
+ \Magento\Framework\Api\SearchCriteriaInterface::class,
[],
'',
false
);
$customerModel = $this->getMock(
- 'Magento\Customer\Model\Customer',
+ \Magento\Customer\Model\Customer::class,
[
'getId',
'setId',
@@ -636,7 +650,7 @@ public function testGetList()
false
);
$metadata = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\Data\AttributeMetadataInterface',
+ \Magento\Customer\Api\Data\AttributeMetadataInterface::class,
[],
'',
false
@@ -656,7 +670,7 @@ public function testGetList()
->willReturn($collection);
$this->extensionAttributesJoinProcessor->expects($this->once())
->method('process')
- ->with($collection, 'Magento\Customer\Api\Data\CustomerInterface');
+ ->with($collection, \Magento\Customer\Api\Data\CustomerInterface::class);
$this->customerMetadata->expects($this->once())
->method('getAllAttributesMetadata')
->willReturn([$metadata]);
@@ -757,7 +771,7 @@ public function testDeleteById()
{
$customerId = 14;
$customerModel = $this->getMock(
- 'Magento\Customer\Model\Customer',
+ \Magento\Customer\Model\Customer::class,
['delete'],
[],
'',
@@ -781,7 +795,7 @@ public function testDelete()
{
$customerId = 14;
$customerModel = $this->getMock(
- 'Magento\Customer\Model\Customer',
+ \Magento\Customer\Model\Customer::class,
['delete'],
[],
'',
diff --git a/app/code/Magento/Customer/composer.json b/app/code/Magento/Customer/composer.json
index 8cae6cd06075b..4cac0502e8a79 100644
--- a/app/code/Magento/Customer/composer.json
+++ b/app/code/Magento/Customer/composer.json
@@ -29,7 +29,7 @@
"magento/module-customer-sample-data": "Sample Data version:100.1.*"
},
"type": "magento2-module",
- "version": "100.1.6",
+ "version": "100.1.7",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml
index bd9d9e88e754b..48e02e6d030f2 100644
--- a/app/code/Magento/Customer/etc/di.xml
+++ b/app/code/Magento/Customer/etc/di.xml
@@ -318,4 +318,15 @@
Magento\Customer\Model\Cache\Type\Notification
+
+
+
+ -
+
- customer_entity
+ - customer
+ - entity_id
+
+
+
+
diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php
index 6acb7cd43b866..9fa4a8954d588 100644
--- a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php
+++ b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php
@@ -370,10 +370,6 @@ protected function _prepareDataForUpdate(array $rowData)
// attribute values
foreach (array_intersect_key($rowData, $this->_attributes) as $attributeCode => $value) {
- if ($newCustomer && !strlen($value)) {
- continue;
- }
-
$attributeParameters = $this->_attributes[$attributeCode];
if ('select' == $attributeParameters['type']) {
$value = isset($attributeParameters['options'][strtolower($value)])
diff --git a/app/code/Magento/CustomerImportExport/composer.json b/app/code/Magento/CustomerImportExport/composer.json
index d958f64f29af4..cebe1bf462dd9 100644
--- a/app/code/Magento/CustomerImportExport/composer.json
+++ b/app/code/Magento/CustomerImportExport/composer.json
@@ -12,7 +12,7 @@
"magento/framework": "100.1.*"
},
"type": "magento2-module",
- "version": "100.1.2",
+ "version": "100.1.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Directory/composer.json b/app/code/Magento/Directory/composer.json
index fad19febc0d52..25b730775fe2a 100644
--- a/app/code/Magento/Directory/composer.json
+++ b/app/code/Magento/Directory/composer.json
@@ -10,7 +10,7 @@
"lib-libxml": "*"
},
"type": "magento2-module",
- "version": "100.1.3",
+ "version": "100.1.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php
index 24e3a741a36e9..e89b5449bc078 100644
--- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php
+++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php
@@ -14,6 +14,7 @@
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
use Magento\Framework\App\Config\Element;
use Magento\Framework\App\ResourceConnection\Config;
+use Magento\Framework\DataObject;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Model\AbstractModel;
use Magento\Framework\Model\ResourceModel\Db\ObjectRelationProcessor;
@@ -204,6 +205,13 @@ abstract class AbstractEntity extends AbstractResource implements EntityInterfac
*/
protected $objectRelationProcessor;
+ /**
+ * Attributes stored by scope (store id and attribute set id).
+ *
+ * @var array
+ */
+ private $attributesByScope;
+
/**
* @param Context $context
* @param array $data
@@ -447,6 +455,20 @@ public function getAttribute($attribute)
return $attribute;
}
+ /**
+ * Adding attribute to entity by scope.
+ *
+ * @param AbstractAttribute $attribute
+ * @param string $suffix
+ * @return $this
+ */
+ public function addAttributeByScope(AbstractAttribute $attribute, $suffix)
+ {
+ $attributeCode = $attribute->getAttributeCode();
+ $this->attributesByScope[$suffix][$attributeCode] = $attribute;
+ return $this->addAttribute($attribute);
+ }
+
/**
* Adding attribute to entity
*
@@ -572,6 +594,31 @@ protected function _isApplicableAttribute($object, $attribute)
return true;
}
+ /**
+ * Get attributes by scope
+ *
+ * @return array
+ */
+ private function getAttributesByScope($suffix)
+ {
+ return !empty($this->attributesByScope[$suffix])
+ ? $this->attributesByScope[$suffix]
+ : $this->getAttributesByCode();
+ }
+
+ /**
+ * Get attributes cache suffix.
+ *
+ * @param DataObject $object
+ * @return string
+ */
+ private function getAttributesCacheSuffix(DataObject $object)
+ {
+ $attributeSetId = $object->getAttributeSetId() ?: 0;
+ $storeId = $object->getStoreId() ?: 0;
+ return $storeId . '-' . $attributeSetId;
+ }
+
/**
* Walk through the attributes and run method with optional arguments
*
@@ -607,7 +654,8 @@ public function walkAttributes($partMethod, array $args = [], $collectExceptionM
break;
}
$results = [];
- foreach ($this->getAttributesByCode() as $attrCode => $attribute) {
+ $suffix = $this->getAttributesCacheSuffix($args[0]);
+ foreach ($this->getAttributesByScope($suffix) as $attrCode => $attribute) {
if (isset($args[0]) && is_object($args[0]) && !$this->_isApplicableAttribute($args[0], $attribute)) {
continue;
}
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
index 96cd1f8b19525..ca8e761578565 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/AbstractAttribute.php
@@ -111,6 +111,20 @@ abstract class AbstractAttribute extends \Magento\Framework\Model\AbstractExtens
*/
protected $dataObjectHelper;
+ /**
+ * Array of attribute types that have empty string as a possible value.
+ *
+ * @var array
+ */
+ private static $emptyStringTypes = [
+ 'int',
+ 'decimal',
+ 'datetime',
+ 'varchar',
+ 'text',
+ 'static',
+ ];
+
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
@@ -174,7 +188,7 @@ public function __construct(
*/
protected function _construct()
{
- $this->_init('Magento\Eav\Model\ResourceModel\Entity\Attribute');
+ $this->_init(\Magento\Eav\Model\ResourceModel\Entity\Attribute::class);
}
/**
@@ -588,17 +602,38 @@ protected function _getDefaultSourceModel()
}
/**
+ * Check if Value is empty.
+ *
* @param array|null|bool|int|float|string $value
* @return bool
*/
public function isValueEmpty($value)
{
- /** @var array $emptyStringTypes list of attribute types that treat empty string as a possible value */
- $emptyStringTypes = ['int', 'decimal', 'datetime', 'varchar', 'text', 'static'];
return (is_array($value) && count($value) == 0)
|| $value === null
|| ($value === false && $this->getBackend()->getType() != 'int')
- || ($value === '' && in_array($this->getBackend()->getType(), $emptyStringTypes));
+ || ($value === '' && $this->isInEmptyStringTypes());
+ }
+
+ /**
+ * Check if attribute empty value is valid.
+ *
+ * @param array|null|bool|int|float|string $value
+ * @return bool
+ */
+ public function isAllowedEmptyTextValue($value)
+ {
+ return $this->isInEmptyStringTypes() && $value === '';
+ }
+
+ /**
+ * Check is attribute type in allowed empty string types.
+ *
+ * @return bool
+ */
+ private function isInEmptyStringTypes()
+ {
+ return in_array($this->getBackend()->getType(), self::$emptyStringTypes);
}
/**
@@ -1056,7 +1091,7 @@ public function setOptions(array $options = null)
foreach ($options as $option) {
$optionData = $this->dataObjectProcessor->buildOutputDataArray(
$option,
- '\Magento\Eav\Api\Data\AttributeOptionInterface'
+ \Magento\Eav\Api\Data\AttributeOptionInterface::class
);
$optionDataArray[] = $optionData;
}
@@ -1082,7 +1117,7 @@ protected function convertToObjects(array $options)
$this->dataObjectHelper->populateWithArray(
$optionDataObject,
$option,
- '\Magento\Eav\Api\Data\AttributeOptionInterface'
+ \Magento\Eav\Api\Data\AttributeOptionInterface::class
);
$dataObjects[] = $optionDataObject;
}
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Backend/ArrayBackend.php b/app/code/Magento/Eav/Model/Entity/Attribute/Backend/ArrayBackend.php
index 47a998a95ecb5..919e041803dfa 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/Backend/ArrayBackend.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/Backend/ArrayBackend.php
@@ -38,11 +38,16 @@ public function beforeSave($object)
*/
public function validate($object)
{
- $attributeCode = $this->getAttribute()->getAttributeCode();
+ $attribute = $this->getAttribute();
+ $attributeCode = $attribute->getAttributeCode();
$data = $object->getData($attributeCode);
+ $assigned = $object->hasData($attributeCode);
if (is_array($data)) {
$object->setData($attributeCode, implode(',', array_filter($data)));
+ } elseif (empty($data) && $assigned) {
+ $object->setData($attributeCode, null);
}
+
return parent::validate($object);
}
}
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php b/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
index 1da1ddab5d07d..f160072735d39 100644
--- a/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/Source/Table.php
@@ -5,6 +5,9 @@
*/
namespace Magento\Eav\Model\Entity\Attribute\Source;
+use Magento\Framework\App\ObjectManager;
+use Magento\Store\Model\StoreManagerInterface;
+
class Table extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
{
/**
@@ -24,6 +27,13 @@ class Table extends \Magento\Eav\Model\Entity\Attribute\Source\AbstractSource
*/
protected $_attrOptionFactory;
+ /**
+ * Store manager interface.
+ *
+ * @var StoreManagerInterface
+ */
+ private $storeManager;
+
/**
* @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory $attrOptionCollectionFactory
* @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory $attrOptionFactory
@@ -47,24 +57,31 @@ public function __construct(
public function getAllOptions($withEmpty = true, $defaultValues = false)
{
$storeId = $this->getAttribute()->getStoreId();
+ if ($storeId === null) {
+ $storeId = $this->getStoreManager()->getStore()->getId();
+ }
if (!is_array($this->_options)) {
$this->_options = [];
}
if (!is_array($this->_optionsDefault)) {
$this->_optionsDefault = [];
}
- if (!isset($this->_options[$storeId])) {
+
+ $attributeId = $this->getAttribute()->getId();
+ if (!isset($this->_options[$storeId][$attributeId])) {
$collection = $this->_attrOptionCollectionFactory->create()->setPositionOrder(
'asc'
)->setAttributeFilter(
- $this->getAttribute()->getId()
+ $attributeId
)->setStoreFilter(
- $this->getAttribute()->getStoreId()
+ $storeId
)->load();
- $this->_options[$storeId] = $collection->toOptionArray();
- $this->_optionsDefault[$storeId] = $collection->toOptionArray('default_value');
+ $this->_options[$storeId][$attributeId] = $collection->toOptionArray();
+ $this->_optionsDefault[$storeId][$attributeId] = $collection->toOptionArray('default_value');
}
- $options = $defaultValues ? $this->_optionsDefault[$storeId] : $this->_options[$storeId];
+ $options = $defaultValues
+ ? $this->_optionsDefault[$storeId][$attributeId]
+ : $this->_options[$storeId][$attributeId];
if ($withEmpty) {
$options = $this->addEmptyOption($options);
}
@@ -72,6 +89,21 @@ public function getAllOptions($withEmpty = true, $defaultValues = false)
return $options;
}
+ /**
+ * Get StoreManager dependency.
+ *
+ * @return StoreManagerInterface
+ * @deprecated
+ */
+ private function getStoreManager()
+ {
+ if ($this->storeManager === null) {
+ $this->storeManager = ObjectManager::getInstance()->get(StoreManagerInterface::class);
+ }
+
+ return $this->storeManager;
+ }
+
/**
* Retrieve Option values array by ids
*
diff --git a/app/code/Magento/Eav/Model/Entity/AttributeLoader.php b/app/code/Magento/Eav/Model/Entity/AttributeLoader.php
index 683c4dbb96e15..e5fef6f1a9ab8 100644
--- a/app/code/Magento/Eav/Model/Entity/AttributeLoader.php
+++ b/app/code/Magento/Eav/Model/Entity/AttributeLoader.php
@@ -70,7 +70,7 @@ public function loadAllAttributes(AbstractEntity $resource, DataObject $object =
$attributes = $this->cache->getAttributes($typeCode, $suffix);
if ($attributes) {
foreach ($attributes as $attribute) {
- $resource->addAttribute($attribute);
+ $resource->addAttributeByScope($attribute, $suffix);
}
return $resource;
}
diff --git a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php
index c91aab658d2c2..c45e0e54dd807 100644
--- a/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php
+++ b/app/code/Magento/Eav/Model/ResourceModel/UpdateHandler.php
@@ -5,12 +5,12 @@
*/
namespace Magento\Eav\Model\ResourceModel;
-use Magento\Framework\App\ObjectManager;
-use Magento\Framework\EntityManager\MetadataPool;
use Magento\Eav\Api\AttributeRepositoryInterface as AttributeRepository;
use Magento\Framework\Api\SearchCriteriaBuilder;
-use Magento\Framework\Model\Entity\ScopeResolver;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\EntityManager\Operation\AttributeInterface;
+use Magento\Framework\Model\Entity\ScopeResolver;
/**
* Class UpdateHandler
@@ -125,51 +125,54 @@ public function execute($entityType, $entityData, $arguments = [])
: null; // @todo verify is it normal to not have attributer_set_id
$snapshot = $this->readSnapshot->execute($entityType, $entityDataForSnapshot);
foreach ($this->getAttributes($entityType, $attributeSetId) as $attribute) {
- if ($attribute->isStatic()) {
- continue;
- }
- /**
- * Only scalar values can be stored in generic tables
- */
- if (isset($entityData[$attribute->getAttributeCode()])
- && !is_scalar($entityData[$attribute->getAttributeCode()])) {
+ $code = $attribute->getAttributeCode();
+ $isAllowedValueType = array_key_exists($code, $entityData)
+ && (is_scalar($entityData[$code]) || $entityData[$code] === null);
+
+ if ($attribute->isStatic() || !$isAllowedValueType) {
continue;
}
- if (isset($snapshot[$attribute->getAttributeCode()])
- && $snapshot[$attribute->getAttributeCode()] !== false
- && (array_key_exists($attribute->getAttributeCode(), $entityData)
- && $attribute->isValueEmpty($entityData[$attribute->getAttributeCode()]))
- ) {
- $this->attributePersistor->registerDelete(
- $entityType,
- $entityData[$metadata->getLinkField()],
- $attribute->getAttributeCode()
- );
- }
- if ((!array_key_exists($attribute->getAttributeCode(), $snapshot)
- || $snapshot[$attribute->getAttributeCode()] === false)
- && array_key_exists($attribute->getAttributeCode(), $entityData)
- && !$attribute->isValueEmpty($entityData[$attribute->getAttributeCode()])
- ) {
- $this->attributePersistor->registerInsert(
- $entityType,
- $entityData[$metadata->getLinkField()],
- $attribute->getAttributeCode(),
- $entityData[$attribute->getAttributeCode()]
- );
- }
- if (array_key_exists($attribute->getAttributeCode(), $snapshot)
- && $snapshot[$attribute->getAttributeCode()] !== false
- && array_key_exists($attribute->getAttributeCode(), $entityData)
- && $snapshot[$attribute->getAttributeCode()] != $entityData[$attribute->getAttributeCode()]
- && !$attribute->isValueEmpty($entityData[$attribute->getAttributeCode()])
- ) {
- $this->attributePersistor->registerUpdate(
- $entityType,
- $entityData[$metadata->getLinkField()],
- $attribute->getAttributeCode(),
- $entityData[$attribute->getAttributeCode()]
- );
+
+ $newValue = $entityData[$code];
+ $isValueEmpty = $attribute->isValueEmpty($newValue);
+ $isAllowedEmptyStringValue = $attribute->isAllowedEmptyTextValue($newValue);
+
+ if (array_key_exists($code, $snapshot)) {
+ $snapshotValue = $snapshot[$code];
+ /** 'FALSE' value for attributes can't be update or delete */
+ if ($snapshotValue === false) {
+ continue;
+ }
+
+ if (!$isValueEmpty || $isAllowedEmptyStringValue) {
+ /** NOT Updated value for attributes not need to update */
+ if ($snapshotValue === $newValue) {
+ continue;
+ }
+
+ $this->attributePersistor->registerUpdate(
+ $entityType,
+ $entityData[$metadata->getLinkField()],
+ $code,
+ $newValue
+ );
+ } else {
+ $this->attributePersistor->registerDelete(
+ $entityType,
+ $entityData[$metadata->getLinkField()],
+ $code
+ );
+ }
+ } else {
+ /** Only not empty value of attribute is insertable */
+ if (!$isValueEmpty || $isAllowedEmptyStringValue) {
+ $this->attributePersistor->registerInsert(
+ $entityType,
+ $entityData[$metadata->getLinkField()],
+ $code,
+ $newValue
+ );
+ }
}
}
$this->attributePersistor->flush($entityType, $context);
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php
index 2bb3feba73a18..5a06025254465 100644
--- a/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/AbstractEntityTest.php
@@ -317,8 +317,6 @@ public function testSave($attributeCode, $attributeSetId, $productData, $product
->getMock();
$model->expects($this->any())->method('_getValue')->will($this->returnValue($eavConfig));
$model->expects($this->any())->method('getConnection')->will($this->returnValue($this->_getConnectionMock()));
-
-
$eavConfig->expects($this->any())->method('getAttribute')->will(
$this->returnCallback(
function ($entityType, $attributeCode) use ($attributes) {
@@ -337,19 +335,29 @@ public function productAttributesDataProvider()
[
'test_attr',
$attributeSetId,
- ['test_attr' => 'test_attr', 'attribute_set_id' => $attributeSetId, 'entity_id' => null],
+ [
+ 'test_attr' => 'test_attr',
+ 'attribute_set_id' => $attributeSetId,
+ 'entity_id' => null,
+ 'store_id' => 1
+ ],
null,
],
[
'test_attr',
$attributeSetId,
- ['test_attr' => 'test_attr', 'attribute_set_id' => $attributeSetId, 'entity_id' => 12345],
+ [
+ 'test_attr' => 'test_attr',
+ 'attribute_set_id' => $attributeSetId,
+ 'entity_id' => 12345,
+ 'store_id' => 1
+ ],
['test_attr' => 'test_attr']
],
[
'test_attr',
$attributeSetId,
- ['test_attr' => '99.99', 'attribute_set_id' => $attributeSetId, 'entity_id' => 12345],
+ ['test_attr' => '99.99', 'attribute_set_id' => $attributeSetId, 'entity_id' => 12345, 'store_id' => 1],
['test_attr' => '99.9900']
]
];
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php
index 6c1d1fa83e8b4..d7e0c3c41a3a0 100644
--- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/AbstractAttributeTest.php
@@ -119,7 +119,7 @@ public function testConvertToObjects()
]
);
$dataObjectHelperMock->expects($this->once())->method('populateWithArray')
- ->with($attributeOptionMock, ['some value'], '\Magento\Eav\Api\Data\AttributeOptionInterface')
+ ->with($attributeOptionMock, ['some value'], \Magento\Eav\Api\Data\AttributeOptionInterface::class)
->willReturnSelf();
$dataFactoryMock->expects($this->once())->method('create')->willReturn($attributeOptionMock);
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayBackendTest.php
similarity index 82%
rename from app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayTest.php
rename to app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayBackendTest.php
index 0a8adb7534cde..e454f1f22f7bb 100644
--- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayTest.php
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Backend/ArrayBackendTest.php
@@ -5,7 +5,7 @@
*/
namespace Magento\Eav\Test\Unit\Model\Entity\Attribute\Backend;
-class ArrayTest extends \PHPUnit_Framework_TestCase
+class ArrayBackendTest extends \PHPUnit_Framework_TestCase
{
/**
* @var \Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend
@@ -20,13 +20,13 @@ class ArrayTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->_attribute = $this->getMock(
- 'Magento\Eav\Model\Entity\Attribute',
+ \Magento\Eav\Model\Entity\Attribute::class,
['getAttributeCode', '__wakeup'],
[],
'',
false
);
- $logger = $this->getMock('Psr\Log\LoggerInterface');
+ $logger = $this->getMock(\Psr\Log\LoggerInterface::class);
$this->_model = new \Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend($logger);
$this->_model->setAttribute($this->_attribute);
}
@@ -37,9 +37,10 @@ protected function setUp()
public function testValidate($data)
{
$this->_attribute->expects($this->atLeastOnce())->method('getAttributeCode')->will($this->returnValue('code'));
- $product = new \Magento\Framework\DataObject(['code' => $data]);
+ $product = new \Magento\Framework\DataObject(['code' => $data, 'empty' => '']);
$this->_model->validate($product);
$this->assertEquals('1,2,3', $product->getCode());
+ $this->assertEquals(null, $product->getEmpty());
}
public static function attributeValueDataProvider()
diff --git a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Source/TableTest.php b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Source/TableTest.php
index 38b88f44a451b..443f09e342764 100644
--- a/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Source/TableTest.php
+++ b/app/code/Magento/Eav/Test/Unit/Model/Entity/Attribute/Source/TableTest.php
@@ -6,7 +6,17 @@
namespace Magento\Eav\Test\Unit\Model\Entity\Attribute\Source;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
+use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\Store\Api\Data\StoreInterface;
+use Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection as AttributeOptionCollection;
+/**
+ * Tests \Magento\Eav\Model\Entity\Attribute\Source\Table.
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
class TableTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -25,12 +35,37 @@ class TableTest extends \PHPUnit_Framework_TestCase
*/
private $attrOptionFactory;
+ /**
+ * @var AbstractSource | \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $sourceMock;
+
+ /**
+ * @var AbstractAttribute | \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $abstractAttributeMock;
+
+ /**
+ * @var StoreManagerInterface | \PHPUnit_Framework_MockObject_MockObject
+ */
+ private $storeManagerMock;
+
+ /**
+ * @var StoreInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $storeMock;
+
+ /**
+ * @var AttributeOptionCollection|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $attributeOptionCollectionMock;
+
protected function setUp()
{
$objectManager = new ObjectManager($this);
$this->collectionFactory = $this->getMock(
- 'Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory',
+ \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory::class,
[
'create',
'setPositionOrder',
@@ -45,51 +80,68 @@ protected function setUp()
false
);
+ $this->attributeOptionCollectionMock = $this->getMockBuilder(AttributeOptionCollection::class)
+ ->setMethods(['toOptionArray'])
+ ->disableOriginalConstructor()
+ ->getMock();
+
$this->attrOptionFactory = $this->getMockBuilder(
- 'Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory'
+ \Magento\Eav\Model\ResourceModel\Entity\Attribute\OptionFactory::class
)
->setMethods(['create'])
->disableOriginalConstructor()
->getMockForAbstractClass();
+ $this->sourceMock = $this->getMockBuilder(AbstractSource::class)
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
+ $this->abstractAttributeMock = $this->getMockBuilder(AbstractAttribute::class)
+ ->setMethods(
+ [
+ 'getFrontend', 'getAttributeCode', '__wakeup', 'getStoreId',
+ 'getId', 'getIsRequired', 'getEntity', 'getBackend'
+ ]
+ )
+ ->disableOriginalConstructor()
+ ->getMockForAbstractClass();
+
$this->model = $objectManager->getObject(
- 'Magento\Eav\Model\Entity\Attribute\Source\Table',
+ \Magento\Eav\Model\Entity\Attribute\Source\Table::class,
[
'attrOptionCollectionFactory' => $this->collectionFactory,
'attrOptionFactory' => $this->attrOptionFactory
]
);
+
+ $this->model->setAttribute($this->abstractAttributeMock);
+
+ $this->storeManagerMock = $this->getMockForAbstractClass(StoreManagerInterface::class);
+ $this->storeMock = $this->getMockForAbstractClass(StoreInterface::class);
+
+ $objectManager->setBackwardCompatibleProperty(
+ $this->model,
+ 'storeManager',
+ $this->storeManagerMock
+ );
}
public function testGetFlatColumns()
{
$abstractFrontendMock = $this->getMock(
- 'Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend',
+ \Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend::class,
[],
[],
'',
false
);
- $abstractAttributeMock = $this->getMock(
- '\Magento\Eav\Model\Entity\Attribute\AbstractAttribute',
- ['getFrontend', 'getAttributeCode', '__wakeup'],
- [],
- '',
- false
- );
-
- $abstractAttributeMock->expects(
- $this->any()
- )->method(
- 'getFrontend'
- )->will(
- $this->returnValue($abstractFrontendMock)
- );
-
- $abstractAttributeMock->expects($this->any())->method('getAttributeCode')->will($this->returnValue('code'));
-
- $this->model->setAttribute($abstractAttributeMock);
+ $this->abstractAttributeMock->expects($this->any())
+ ->method('getFrontend')
+ ->willReturn(($abstractFrontendMock));
+ $this->abstractAttributeMock->expects($this->any())
+ ->method('getAttributeCode')
+ ->willReturn('code');
$flatColumns = $this->model->getFlatColumns();
@@ -118,25 +170,16 @@ public function testGetSpecificOptions($optionIds, $withEmpty)
$storeId = 5;
$options = [['label' => 'The label', 'value' => 'A value']];
- $attribute = $this->getMock(
- 'Magento\Eav\Model\Entity\Attribute\AbstractAttribute',
- ['getId', 'getStoreId', 'getIsRequired', '__wakeup'],
- [],
- '',
- false
- );
- $attribute->expects($this->once())
+ $this->abstractAttributeMock->expects($this->once())
->method('getId')
->willReturn($attributeId);
- $attribute->expects($this->once())
+ $this->abstractAttributeMock->expects($this->once())
->method('getStoreId')
->willReturn($storeId);
- $attribute->expects($this->any())
+ $this->abstractAttributeMock->expects($this->any())
->method('getIsRequired')
->willReturn(false);
- $this->model->setAttribute($attribute);
-
$this->collectionFactory->expects($this->once())
->method('create')
->willReturnSelf();
@@ -188,22 +231,14 @@ public function testGetOptionText($optionsIds, $value, $options, $expectedResult
{
$attributeId = 1;
$storeId = 5;
- $attribute = $this->getMock(
- 'Magento\Eav\Model\Entity\Attribute\AbstractAttribute',
- ['getId', 'getStoreId', '__wakeup'],
- [],
- '',
- false
- );
- $attribute->expects($this->once())
+
+ $this->abstractAttributeMock->expects($this->once())
->method('getId')
->willReturn($attributeId);
- $attribute->expects($this->once())
+ $this->abstractAttributeMock->expects($this->once())
->method('getStoreId')
->willReturn($storeId);
- $this->model->setAttribute($attribute);
-
$this->collectionFactory->expects($this->once())
->method('create')
->willReturnSelf();
@@ -250,36 +285,44 @@ public function testAddValueSortToCollection()
{
$attributeCode = 'attribute_code';
$dir = \Magento\Framework\DB\Select::SQL_ASC;
- $collection = $this->getMockBuilder('Magento\Eav\Model\Entity\Collection\AbstractCollection')
+ $collection = $this->getMockBuilder(\Magento\Eav\Model\Entity\Collection\AbstractCollection::class)
->setMethods([ 'getSelect', 'getStoreId'])
->disableOriginalConstructor()
->getMockForAbstractClass();
- $attribute = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
+
+ $this->abstractAttributeMock = $this->getMockBuilder(
+ \Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class
+ )
->setMethods(['getAttributeCode', 'getEntity', 'getBackend', 'getId'])
->disableOriginalConstructor()
->getMockForAbstractClass();
- $attribute->expects($this->any())->method('getAttributeCode')->willReturn($attributeCode);
- $entity = $this->getMockBuilder('Magento\Eav\Model\Entity\AbstractEntity')
+ $this->abstractAttributeMock->expects($this->any())->method('getAttributeCode')->willReturn($attributeCode);
+ $entity = $this->getMockBuilder(\Magento\Eav\Model\Entity\AbstractEntity::class)
->setMethods(['getLinkField'])
->disableOriginalConstructor()
->getMockForAbstractClass();
- $attribute->expects($this->once())->method('getEntity')->willReturn($entity);
+
+ $this->abstractAttributeMock->expects($this->once())->method('getEntity')->willReturn($entity);
$entity->expects($this->once())->method('getLinkField')->willReturn('entity_id');
- $select = $this->getMockBuilder('Magento\Framework\DB\Select')
+ $select = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
->setMethods(['joinLeft', 'getConnection', 'order'])
->disableOriginalConstructor()
->getMock();
$collection->expects($this->any())->method('getSelect')->willReturn($select);
$select->expects($this->any())->method('joinLeft')->willReturnSelf();
- $backend = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend')
+ $backend = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend::class)
->setMethods(['getTable'])
->disableOriginalConstructor()
->getMockForAbstractClass();
- $attribute->expects($this->any())->method('getBackend')->willReturn($backend);
+
+ $this->abstractAttributeMock->expects($this->any())->method('getBackend')->willReturn($backend);
+
$backend->expects($this->any())->method('getTable')->willReturn('table_name');
- $attribute->expects($this->any())->method('getId')->willReturn(1);
+
+ $this->abstractAttributeMock->expects($this->any())->method('getId')->willReturn(1);
+
$collection->expects($this->once())->method('getStoreId')->willReturn(1);
- $connection = $this->getMockBuilder('Magento\Framework\DB\Adapter\AdapterInterface')
+ $connection = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class)
->disableOriginalConstructor()
->getMock();
$expr = $this->getMockBuilder('Zend_Db_Expr')
@@ -287,15 +330,119 @@ public function testAddValueSortToCollection()
->getMock();
$connection->expects($this->once())->method('getCheckSql')->willReturn($expr);
$select->expects($this->once())->method('getConnection')->willReturn($connection);
- $attrOption = $this->getMockBuilder('Magento\Eav\Model\ResourceModel\Entity\Attribute\Option')
+ $attrOption = $this->getMockBuilder(\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option::class)
->disableOriginalConstructor()
->getMock();
$this->attrOptionFactory->expects($this->once())->method('create')->willReturn($attrOption);
- $attrOption->expects($this->once())->method('addOptionValueToCollection')->with($collection, $attribute, $expr)
+
+ $attrOption->expects($this->once())->method('addOptionValueToCollection')
+ ->with($collection, $this->abstractAttributeMock, $expr)
->willReturnSelf();
+
$select->expects($this->once())->method('order')->with("{$attributeCode} {$dir}");
- $this->model->setAttribute($attribute);
+ $this->model->setAttribute($this->abstractAttributeMock);
$this->assertEquals($this->model, $this->model->addValueSortToCollection($collection, $dir));
}
+
+ /**
+ * @param bool $withEmpty
+ * @param bool $defaultValues
+ * @param array $options
+ * @param array $optionsDefault
+ * @param array $expectedResult
+ *
+ * @dataProvider getAllOptionsDataProvider
+ *
+ * @return void
+ */
+ public function testGetAllOptions(
+ $withEmpty,
+ $defaultValues,
+ array $options,
+ array $optionsDefault,
+ array $expectedResult
+ ) {
+ $storeId = '1';
+ $attributeId = '42';
+
+ $this->abstractAttributeMock->expects($this->once())
+ ->method('getStoreId')
+ ->willReturn(null);
+
+ $this->storeManagerMock->expects($this->once())
+ ->method('getStore')
+ ->willReturn($this->storeMock);
+
+ $this->storeMock->expects($this->once())
+ ->method('getId')
+ ->willReturn($storeId);
+
+ $this->abstractAttributeMock->expects($this->once())
+ ->method('getId')
+ ->willReturn($attributeId);
+
+ $this->collectionFactory->expects($this->once())
+ ->method('create')
+ ->willReturnSelf();
+ $this->collectionFactory->expects($this->once())
+ ->method('setPositionOrder')
+ ->willReturnSelf();
+ $this->collectionFactory->expects($this->once())
+ ->method('setAttributeFilter')
+ ->with($attributeId)
+ ->willReturnSelf();
+ $this->collectionFactory->expects($this->once())
+ ->method('setStoreFilter')
+ ->with($storeId)
+ ->willReturnSelf();
+ $this->collectionFactory->expects($this->once())
+ ->method('load')
+ ->willReturn($this->attributeOptionCollectionMock);
+
+ $this->attributeOptionCollectionMock->expects($this->any())
+ ->method('toOptionArray')
+ ->willReturnMap(
+ [
+ ['value', $options],
+ ['default_value', $optionsDefault]
+ ]
+ );
+
+ $this->assertEquals($expectedResult, $this->model->getAllOptions($withEmpty, $defaultValues));
+ }
+
+ /**
+ * @return array
+ */
+ public function getAllOptionsDataProvider()
+ {
+ return [
+ [
+ false,
+ false,
+ [['value' => '16', 'label' => 'black'], ['value' => '17', 'label' => 'white']],
+ [['value' => '16', 'label' => 'blck'], ['value' => '17', 'label' => 'wht']],
+ [['value' => '16', 'label' => 'black'], ['value' => '17', 'label' => 'white']]
+ ],
+ [
+ false,
+ true,
+ [['value' => '16', 'label' => 'black'], ['value' => '17', 'label' => 'white']],
+ [['value' => '16', 'label' => 'blck'], ['value' => '17', 'label' => 'wht']],
+ [['value' => '16', 'label' => 'blck'], ['value' => '17', 'label' => 'wht']]
+ ],
+ [
+ true,
+ false,
+ [['value' => '16', 'label' => 'black'], ['value' => '17', 'label' => 'white']],
+ [['value' => '16', 'label' => 'blck'], ['value' => '17', 'label' => 'wht']],
+ [
+ ['label' => ' ', 'value' => ''],
+ ['value' => '16', 'label' => 'black'],
+ ['value' => '17', 'label' => 'white']
+ ]
+ ]
+ ];
+ }
}
diff --git a/app/code/Magento/Eav/composer.json b/app/code/Magento/Eav/composer.json
index d1665c4702063..12a37f0edc51b 100644
--- a/app/code/Magento/Eav/composer.json
+++ b/app/code/Magento/Eav/composer.json
@@ -11,7 +11,7 @@
"magento/framework": "100.1.*"
},
"type": "magento2-module",
- "version": "100.1.5",
+ "version": "100.1.6",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Email/Model/Design/Backend/Logo.php b/app/code/Magento/Email/Model/Design/Backend/Logo.php
index cee848737ad54..d8e5e71dec494 100644
--- a/app/code/Magento/Email/Model/Design/Backend/Logo.php
+++ b/app/code/Magento/Email/Model/Design/Backend/Logo.php
@@ -7,10 +7,13 @@
use Magento\Theme\Model\Design\Backend\Logo as DesignLogo;
+/**
+ * Class to handle email logo image
+ */
class Logo extends DesignLogo
{
/**
- * The tail part of directory path for uploading
+ * The tail part of directory path for uploading.
*/
const UPLOAD_DIR = 'email/logo';
@@ -22,7 +25,7 @@ class Logo extends DesignLogo
protected $maxFileSize = 2048;
/**
- * Getter for allowed extensions of uploaded files
+ * Getter for allowed extensions of uploaded files.
*
* @return string[]
*/
diff --git a/app/code/Magento/Email/Model/Plugin/TransportInterfacePlugin.php b/app/code/Magento/Email/Model/Plugin/TransportInterfacePlugin.php
new file mode 100644
index 0000000000000..066ef61d9714e
--- /dev/null
+++ b/app/code/Magento/Email/Model/Plugin/TransportInterfacePlugin.php
@@ -0,0 +1,57 @@
+scopeConfig = $scopeConfig;
+ }
+
+ /**
+ * Omit email sending if disabled.
+ *
+ * @param TransportInterface $subject
+ * @param \Closure $proceed
+ * @return void
+ * @throws MailException
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function aroundSendMessage(
+ TransportInterface $subject,
+ \Closure $proceed
+ ) {
+ if (!$this->scopeConfig->isSetFlag(self::XML_PATH_SYSTEM_SMTP_DISABLE, ScopeInterface::SCOPE_STORE)) {
+ $proceed();
+ }
+ }
+}
diff --git a/app/code/Magento/Email/Model/Template.php b/app/code/Magento/Email/Model/Template.php
index 268c58effb8ae..bda17b00f9557 100644
--- a/app/code/Magento/Email/Model/Template.php
+++ b/app/code/Magento/Email/Model/Template.php
@@ -5,26 +5,11 @@
*/
namespace Magento\Email\Model;
-use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\StoreManagerInterface;
/**
* Template model
*
- * Example:
- *
- * // Loading of template
- * \Magento\Email\Model\TemplateFactory $templateFactory
- * $templateFactory->create()->load($this->_scopeConfig->getValue(
- * 'path_to_email_template_id_config',
- * \Magento\Store\Model\ScopeInterface::SCOPE_STORE
- * ));
- * $variables = array(
- * 'someObject' => $this->_coreResourceEmailTemplate
- * 'someString' => 'Some string value'
- * );
- * $emailTemplate->send('some@domain.com', 'Name Of User', $variables);
- *
* @method \Magento\Email\Model\ResourceModel\Template _getResource()
* @method \Magento\Email\Model\ResourceModel\Template getResource()
* @method string getTemplateCode()
@@ -62,7 +47,10 @@ class Template extends AbstractTemplate implements \Magento\Framework\Mail\Templ
const XML_PATH_SENDING_RETURN_PATH_EMAIL = 'system/smtp/return_path_email';
/**
- * Config path to mail sending setting that shows if email communications are disabled
+ * Config path to mail sending setting that shows if email communications are disabled.
+ *
+ * @deprecated
+ * @see \Magento\Email\Model\Plugin\TransportInterfacePlugin::XML_PATH_SYSTEM_SMTP_DISABLE
*/
const XML_PATH_SYSTEM_SMTP_DISABLE = 'system/smtp/disable';
@@ -190,14 +178,13 @@ public function setId($value)
}
/**
- * Return true if this template can be used for sending queue as main template
+ * Return true if this template can be used for sending queue as main template.
*
* @return bool
*/
public function isValidForSend()
{
- return !$this->scopeConfig->isSetFlag(Template::XML_PATH_SYSTEM_SMTP_DISABLE, ScopeInterface::SCOPE_STORE)
- && $this->getSenderName() && $this->getSenderEmail() && $this->getTemplateSubject();
+ return $this->getSenderName() && $this->getSenderEmail() && $this->getTemplateSubject();
}
/**
diff --git a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php
index 189734260d0cb..240e147f2da3a 100644
--- a/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php
+++ b/app/code/Magento/Email/Test/Unit/Model/TemplateTest.php
@@ -5,7 +5,6 @@
*/
namespace Magento\Email\Test\Unit\Model;
-use Magento\Email\Model\Template\Filter;
use Magento\Framework\App\Area;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\App\TemplateTypesInterface;
@@ -426,18 +425,14 @@ public function testGetAndSetId()
}
/**
- * @param $isSMTPDisabled bool
* @param $senderName string
* @param $senderEmail string
* @param $templateSubject string
+ * @param $expectedValue
* @dataProvider isValidForSendDataProvider
*/
- public function testIsValidForSend($isSMTPDisabled, $senderName, $senderEmail, $templateSubject, $expectedValue)
+ public function testIsValidForSend($senderName, $senderEmail, $templateSubject, $expectedValue)
{
- $this->scopeConfig->expects($this->once())
- ->method('isSetFlag')
- ->with('system/smtp/disable', ScopeInterface::SCOPE_STORE)
- ->will($this->returnValue($isSMTPDisabled));
$model = $this->getModelMock(['getSenderName', 'getSenderEmail', 'getTemplateSubject']);
$model->expects($this->any())
->method('getSenderName')
@@ -455,35 +450,24 @@ public function isValidForSendDataProvider()
{
return [
'should be valid' => [
- 'isSMTPDisabled' => false,
'senderName' => 'sender name',
'senderEmail' => 'email@example.com',
'templateSubject' => 'template subject',
'expectedValue' => true
],
- 'no smtp so not valid' => [
- 'isSMTPDisabled' => true,
- 'senderName' => 'sender name',
- 'senderEmail' => 'email@example.com',
- 'templateSubject' => 'template subject',
- 'expectedValue' => false
- ],
'no sender name so not valid' => [
- 'isSMTPDisabled' => false,
'senderName' => '',
'senderEmail' => 'email@example.com',
'templateSubject' => 'template subject',
'expectedValue' => false
],
'no sender email so not valid' => [
- 'isSMTPDisabled' => false,
'senderName' => 'sender name',
'senderEmail' => '',
'templateSubject' => 'template subject',
'expectedValue' => false
],
'no subject so not valid' => [
- 'isSMTPDisabled' => false,
'senderName' => 'sender name',
'senderEmail' => 'email@example.com',
'templateSubject' => '',
diff --git a/app/code/Magento/Email/composer.json b/app/code/Magento/Email/composer.json
index 0ccfe00b4f744..7380d2a27a6ae 100644
--- a/app/code/Magento/Email/composer.json
+++ b/app/code/Magento/Email/composer.json
@@ -3,16 +3,16 @@
"description": "N/A",
"require": {
"php": "~5.6.5|7.0.2|7.0.4|~7.0.6",
- "magento/module-theme": "100.1.*",
"magento/module-config": "100.1.*",
"magento/module-store": "100.1.*",
"magento/module-cms": "101.0.*",
+ "magento/module-theme": "100.1.*",
"magento/module-backend": "100.1.*",
"magento/module-variable": "100.1.*",
"magento/framework": "100.1.*"
},
"type": "magento2-module",
- "version": "100.1.3",
+ "version": "100.1.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Email/etc/di.xml b/app/code/Magento/Email/etc/di.xml
index f23d296efc032..a5784d75cbff6 100644
--- a/app/code/Magento/Email/etc/di.xml
+++ b/app/code/Magento/Email/etc/di.xml
@@ -59,5 +59,6 @@
+
diff --git a/app/code/Magento/Email/etc/module.xml b/app/code/Magento/Email/etc/module.xml
index eb2b5cdf25a74..1e8317ca19e2e 100644
--- a/app/code/Magento/Email/etc/module.xml
+++ b/app/code/Magento/Email/etc/module.xml
@@ -10,6 +10,7 @@
+
diff --git a/app/code/Magento/GiftMessage/Model/OrderItemRepository.php b/app/code/Magento/GiftMessage/Model/OrderItemRepository.php
index bc22a1a64bad8..ffc52f272bc00 100644
--- a/app/code/Magento/GiftMessage/Model/OrderItemRepository.php
+++ b/app/code/Magento/GiftMessage/Model/OrderItemRepository.php
@@ -23,6 +23,13 @@ class OrderItemRepository implements \Magento\GiftMessage\Api\OrderItemRepositor
*/
protected $orderFactory;
+ /**
+ * Cached orders data.
+ *
+ * @var \Magento\Sales\Api\Data\OrderInterface[]
+ */
+ private $orders;
+
/**
* Store manager interface.
*
@@ -127,6 +134,7 @@ public function save($orderId, $orderItemId, \Magento\GiftMessage\Api\Data\Messa
$this->giftMessageSaveModel->setGiftmessages($message);
try {
$this->giftMessageSaveModel->saveAllInOrder();
+ unset($this->orders[$orderId]);
} catch (\Exception $e) {
throw new CouldNotSaveException(__('Could not add gift message to order: "%1"', $e->getMessage()), $e);
}
@@ -142,14 +150,19 @@ public function save($orderId, $orderItemId, \Magento\GiftMessage\Api\Data\Messa
*/
protected function getItemById($orderId, $orderItemId)
{
+ if (!isset($this->orders[$orderId])) {
+ $this->orders[$orderId] = $this->orderFactory->create()->load($orderId);
+ }
+
/** @var \Magento\Sales\Api\Data\OrderInterface $order */
- $order = $this->orderFactory->create()->load($orderId);
+ $order = $this->orders[$orderId];
/** @var \Magento\Sales\Api\Data\OrderItemInterface $item */
- foreach ($order->getItems() as $item) {
- if ($item->getItemId() === $orderItemId) {
- return $item;
- }
+ $item = $order->getItemById($orderItemId);
+
+ if ($item !== null) {
+ return $item;
}
+
return false;
}
}
diff --git a/app/code/Magento/GiftMessage/Test/Unit/Model/OrderItemRepositoryTest.php b/app/code/Magento/GiftMessage/Test/Unit/Model/OrderItemRepositoryTest.php
new file mode 100644
index 0000000000000..df6edd71f7577
--- /dev/null
+++ b/app/code/Magento/GiftMessage/Test/Unit/Model/OrderItemRepositoryTest.php
@@ -0,0 +1,503 @@
+orderMock = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['load', 'getItemById', 'getIsVirtual'])
+ ->getMock();
+ $this->orderFactoryMock = $this->getMockBuilder(\Magento\Sales\Model\OrderFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMock();
+ $this->helperMock = $this->getMockBuilder(\Magento\GiftMessage\Helper\Message::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getStore'])
+ ->getMockForAbstractClass();
+ $this->storeMock = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)
+ ->disableOriginalConstructor()
+ ->setMethods([])
+ ->getMock();
+ $this->messageFactoryMock = $this->getMockBuilder(\Magento\GiftMessage\Model\MessageFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMock();
+ $this->giftMessageSaveModelMock = $this->getMockBuilder(\Magento\GiftMessage\Model\Save::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setGiftmessages', 'saveAllInOrder'])
+ ->getMock();
+ $this->storeManagerMock->expects($this->any())
+ ->method('getStore')
+ ->willReturn($this->storeMock);
+
+ $this->orderItemRepository = $helper->getObject(
+ \Magento\GiftMessage\Model\OrderItemRepository::class,
+ [
+ 'orderFactory' => $this->orderFactoryMock,
+ 'storeManager' => $this->storeManagerMock,
+ 'helper' => $this->helperMock,
+ 'messageFactory' => $this->messageFactoryMock,
+ 'giftMessageSaveModel' => $this->giftMessageSaveModelMock
+ ]
+ );
+ }
+
+ /**
+ * @covers \Magento\GiftMessage\Model\OrderItemRepository::get
+ *
+ * @return void
+ */
+ public function testGet()
+ {
+ $orderId = 1;
+ $orderItemId = 2;
+ $messageId = 3;
+ $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getGiftMessageId'])
+ ->getMock();
+ $messageMock = $this->getMockBuilder(\Magento\GiftMessage\Model\Message::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->orderFactoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($this->orderMock);
+ $this->orderMock->expects($this->once())
+ ->method('load')
+ ->willReturnSelf();
+ $this->orderMock->expects($this->once())
+ ->method('getItemById')
+ ->with($orderItemId)
+ ->willReturn($orderItemMock);
+ $this->helperMock->expects($this->once())
+ ->method('isMessagesAllowed')
+ ->with('order_item', $orderItemMock, $this->storeMock)
+ ->willReturn(true);
+ $orderItemMock->expects($this->once())
+ ->method('getGiftMessageId')
+ ->willReturn($messageId);
+ $this->messageFactoryMock->expects($this->any())
+ ->method('create')
+ ->willReturn($messageMock);
+ $messageMock->expects($this->once())
+ ->method('load')
+ ->with($messageId)
+ ->willReturnSelf();
+
+ $this->assertEquals($messageMock, $this->orderItemRepository->get($orderId, $orderItemId));
+ }
+
+ /**
+ * @covers \Magento\GiftMessage\Model\OrderItemRepository::get
+ *
+ * @return void
+ */
+ public function testGetNoSuchEntityExceptionOnGetItemById()
+ {
+ $orderId = 1;
+ $orderItemId = 2;
+
+ $this->orderFactoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($this->orderMock);
+ $this->orderMock->expects($this->once())
+ ->method('load')
+ ->willReturnSelf();
+ $this->orderMock->expects($this->once())
+ ->method('getItemById')
+ ->with($orderItemId)
+ ->willReturn(null);
+ $this->helperMock->expects($this->never())->method('isMessagesAllowed');
+
+ try {
+ $this->orderItemRepository->get($orderId, $orderItemId);
+ $this->fail('Expected NoSuchEntityException not caught');
+ } catch (NoSuchEntityException $exception) {
+ $this->assertEquals('There is no item with provided id in the order', $exception->getMessage());
+ }
+ }
+
+ /**
+ * @covers \Magento\GiftMessage\Model\OrderItemRepository::get
+ *
+ * @return void
+ */
+ public function testGetNoSuchEntityExceptionOnIsMessageAllowed()
+ {
+ $orderId = 1;
+ $orderItemId = 2;
+ $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getGiftMessageId'])
+ ->getMock();
+
+ $this->orderFactoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($this->orderMock);
+ $this->orderMock->expects($this->once())
+ ->method('load')
+ ->willReturnSelf();
+ $this->orderMock->expects($this->once())
+ ->method('getItemById')
+ ->with($orderItemId)
+ ->willReturn($orderItemMock);
+ $this->helperMock->expects($this->once())
+ ->method('isMessagesAllowed')
+ ->with('order_item', $orderItemMock, $this->storeMock)
+ ->willReturn(false);
+ $orderItemMock->expects($this->never())->method('getGiftMessageId');
+
+ try {
+ $this->orderItemRepository->get($orderId, $orderItemId);
+ $this->fail('Expected NoSuchEntityException not caught');
+ } catch (NoSuchEntityException $exception) {
+ $this->assertEquals(
+ 'There is no item with provided id in the order or gift message isn\'t allowed',
+ $exception->getMessage()
+ );
+ }
+ }
+
+ /**
+ * @covers \Magento\GiftMessage\Model\OrderItemRepository::get
+ *
+ * @return void
+ */
+ public function testGetNoSuchEntityExceptionOnGetGiftMessageId()
+ {
+ $orderId = 1;
+ $orderItemId = 2;
+ $messageId = null;
+ $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getGiftMessageId'])
+ ->getMock();
+ $this->orderFactoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($this->orderMock);
+ $this->orderMock->expects($this->once())
+ ->method('load')
+ ->willReturnSelf();
+ $this->orderMock->expects($this->once())
+ ->method('getItemById')
+ ->with($orderItemId)
+ ->willReturn($orderItemMock);
+ $this->helperMock->expects($this->once())
+ ->method('isMessagesAllowed')
+ ->with('order_item', $orderItemMock, $this->storeMock)
+ ->willReturn(true);
+ $orderItemMock->expects($this->once())
+ ->method('getGiftMessageId')
+ ->willReturn($messageId);
+ $this->messageFactoryMock->expects($this->never())->method('create');
+
+ try {
+ $this->orderItemRepository->get($orderId, $orderItemId);
+ $this->fail('Expected NoSuchEntityException not caught');
+ } catch (NoSuchEntityException $exception) {
+ $this->assertEquals('There is no item with provided id in the order', $exception->getMessage());
+ }
+ }
+
+ /**
+ * @covers \Magento\GiftMessage\Model\OrderItemRepository::save
+ *
+ * @return void
+ */
+ public function testSave()
+ {
+ $orderId = 1;
+ $orderItemId = 2;
+ $message[$orderItemId] = [
+ 'type' => 'order_item',
+ 'sender' => 'sender_value',
+ 'recipient' => 'recipient_value',
+ 'message' => 'message_value',
+ ];
+ $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getGiftMessageId'])
+ ->getMock();
+ $messageMock = $this->getMockBuilder(\Magento\GiftMessage\Api\Data\MessageInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->orderFactoryMock->expects($this->any())
+ ->method('create')
+ ->willReturn($this->orderMock);
+ $this->orderMock->expects($this->any())
+ ->method('load')
+ ->willReturnSelf();
+ $this->orderMock->expects($this->once())
+ ->method('getItemById')
+ ->with($orderItemId)
+ ->willReturn($orderItemMock);
+ $this->orderMock->expects($this->once())
+ ->method('getIsVirtual')
+ ->willReturn(false);
+ $this->helperMock->expects($this->once())
+ ->method('isMessagesAllowed')
+ ->with('order_item', $orderItemMock, $this->storeMock)
+ ->willReturn(true);
+ $messageMock->expects($this->once())
+ ->method('getSender')
+ ->willReturn('sender_value');
+ $messageMock->expects($this->once())
+ ->method('getRecipient')
+ ->willReturn('recipient_value');
+ $messageMock->expects($this->once())
+ ->method('getMessage')
+ ->willReturn('message_value');
+ $this->giftMessageSaveModelMock->expects($this->once())
+ ->method('setGiftmessages')
+ ->with($message);
+ $this->giftMessageSaveModelMock->expects($this->once())
+ ->method('saveAllInOrder');
+
+ $this->assertTrue($this->orderItemRepository->save($orderId, $orderItemId, $messageMock));
+ }
+
+ /**
+ * @covers \Magento\GiftMessage\Model\OrderItemRepository::save
+ *
+ * @return void
+ */
+ public function testSaveNoSuchEntityException()
+ {
+ $orderId = 1;
+ $orderItemId = 2;
+ $messageMock = $this->getMockBuilder(\Magento\GiftMessage\Api\Data\MessageInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->orderFactoryMock->expects($this->any())
+ ->method('create')
+ ->willReturn($this->orderMock);
+ $this->orderMock->expects($this->any())
+ ->method('load')
+ ->willReturnSelf();
+ $this->orderMock->expects($this->once())
+ ->method('getItemById')
+ ->with($orderItemId)
+ ->willReturn(null);
+ $this->orderMock->expects($this->never())
+ ->method('getIsVirtual');
+
+ try {
+ $this->orderItemRepository->save($orderId, $orderItemId, $messageMock);
+ $this->fail('Expected NoSuchEntityException not caught');
+ } catch (NoSuchEntityException $exception) {
+ $this->assertEquals('There is no item with provided id in the order', $exception->getMessage());
+ }
+ }
+
+ /**
+ * @covers \Magento\GiftMessage\Model\OrderItemRepository::save
+ *
+ * @return void
+ */
+ public function testSaveInvalidTransitionException()
+ {
+ $orderId = 1;
+ $orderItemId = 2;
+ $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getGiftMessageId'])
+ ->getMock();
+ $messageMock = $this->getMockBuilder(\Magento\GiftMessage\Api\Data\MessageInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->orderFactoryMock->expects($this->any())
+ ->method('create')
+ ->willReturn($this->orderMock);
+ $this->orderMock->expects($this->any())
+ ->method('load')
+ ->willReturnSelf();
+ $this->orderMock->expects($this->once())
+ ->method('getItemById')
+ ->with($orderItemId)
+ ->willReturn($orderItemMock);
+ $this->orderMock->expects($this->once())
+ ->method('getIsVirtual')
+ ->willReturn(true);
+ $this->helperMock->expects($this->never())
+ ->method('isMessagesAllowed');
+
+ try {
+ $this->orderItemRepository->save($orderId, $orderItemId, $messageMock);
+ $this->fail('Expected InvalidTransitionException not caught');
+ } catch (InvalidTransitionException $exception) {
+ $this->assertEquals('Gift Messages are not applicable for virtual products', $exception->getMessage());
+ }
+ }
+
+ /**
+ * @covers \Magento\GiftMessage\Model\OrderItemRepository::save
+ *
+ * @return void
+ */
+ public function testSaveCouldNotSaveException()
+ {
+ $orderId = 1;
+ $orderItemId = 2;
+ $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getGiftMessageId'])
+ ->getMock();
+ $messageMock = $this->getMockBuilder(\Magento\GiftMessage\Api\Data\MessageInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->orderFactoryMock->expects($this->any())
+ ->method('create')
+ ->willReturn($this->orderMock);
+ $this->orderMock->expects($this->any())
+ ->method('load')
+ ->willReturnSelf();
+ $this->orderMock->expects($this->once())
+ ->method('getItemById')
+ ->with($orderItemId)
+ ->willReturn($orderItemMock);
+ $this->orderMock->expects($this->once())
+ ->method('getIsVirtual')
+ ->willReturn(false);
+ $this->helperMock->expects($this->once())
+ ->method('isMessagesAllowed')
+ ->with('order_item', $orderItemMock, $this->storeMock)
+ ->willReturn(false);
+ $messageMock->expects($this->never())
+ ->method('getSender');
+
+ try {
+ $this->orderItemRepository->save($orderId, $orderItemId, $messageMock);
+ $this->fail('Expected CouldNotSaveException not caught');
+ } catch (CouldNotSaveException $exception) {
+ $this->assertEquals('Gift Message is not available', $exception->getMessage());
+ }
+ }
+
+ /**
+ * @covers \Magento\GiftMessage\Model\OrderItemRepository::save
+ *
+ * @return void
+ */
+ public function testSaveCouldNotSaveExceptionOnSaveAllInOrder()
+ {
+ $orderId = 1;
+ $orderItemId = 2;
+ $message[$orderItemId] = [
+ 'type' => 'order_item',
+ 'sender' => 'sender_value',
+ 'recipient' => 'recipient_value',
+ 'message' => 'message_value',
+ ];
+ $excep = new \Exception('Exception message');
+ $orderItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getGiftMessageId'])
+ ->getMock();
+ $messageMock = $this->getMockBuilder(\Magento\GiftMessage\Api\Data\MessageInterface::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->orderFactoryMock->expects($this->any())
+ ->method('create')
+ ->willReturn($this->orderMock);
+ $this->orderMock->expects($this->any())
+ ->method('load')
+ ->willReturnSelf();
+ $this->orderMock->expects($this->once())
+ ->method('getItemById')
+ ->with($orderItemId)
+ ->willReturn($orderItemMock);
+ $this->orderMock->expects($this->once())
+ ->method('getIsVirtual')
+ ->willReturn(false);
+ $this->helperMock->expects($this->once())
+ ->method('isMessagesAllowed')
+ ->with('order_item', $orderItemMock, $this->storeMock)
+ ->willReturn(true);
+ $messageMock->expects($this->once())
+ ->method('getSender')
+ ->willReturn('sender_value');
+ $messageMock->expects($this->once())
+ ->method('getRecipient')
+ ->willReturn('recipient_value');
+ $messageMock->expects($this->once())
+ ->method('getMessage')
+ ->willReturn('message_value');
+ $this->giftMessageSaveModelMock->expects($this->once())
+ ->method('setGiftmessages')
+ ->with($message);
+ $this->giftMessageSaveModelMock->expects($this->once())
+ ->method('saveAllInOrder')
+ ->will($this->throwException($excep));
+
+ try {
+ $this->orderItemRepository->save($orderId, $orderItemId, $messageMock);
+ $this->fail('Expected CouldNotSaveException not caught');
+ } catch (CouldNotSaveException $exception) {
+ $this->assertEquals(
+ 'Could not add gift message to order: "' . $excep->getMessage() . '"',
+ $exception->getMessage()
+ );
+ }
+ }
+}
diff --git a/app/code/Magento/GiftMessage/composer.json b/app/code/Magento/GiftMessage/composer.json
index 446def3f0179b..a5e64bf0510f5 100644
--- a/app/code/Magento/GiftMessage/composer.json
+++ b/app/code/Magento/GiftMessage/composer.json
@@ -17,7 +17,7 @@
"magento/module-multishipping": "100.1.*"
},
"type": "magento2-module",
- "version": "100.1.3",
+ "version": "100.1.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/GiftMessage/view/frontend/web/js/model/gift-message.js b/app/code/Magento/GiftMessage/view/frontend/web/js/model/gift-message.js
index bd9da994f9639..c64c4c0012381 100644
--- a/app/code/Magento/GiftMessage/view/frontend/web/js/model/gift-message.js
+++ b/app/code/Magento/GiftMessage/view/frontend/web/js/model/gift-message.js
@@ -78,7 +78,7 @@ define(['uiElement', 'underscore', 'mage/url'],
},
afterSubmit: function() {
window.location.href = url.build('checkout/cart/updatePost')
- + '?form_key=' + window.giftOptionsConfig.giftMessage.formKey
+ + '?form_key=' + window.checkoutConfig.formKey
+ '&cart[]';
},
getSubmitParams: function(remove) {
diff --git a/app/code/Magento/Newsletter/Model/Template.php b/app/code/Magento/Newsletter/Model/Template.php
index 694097700cdd7..e8f1fabd04683 100644
--- a/app/code/Magento/Newsletter/Model/Template.php
+++ b/app/code/Magento/Newsletter/Model/Template.php
@@ -232,15 +232,12 @@ protected function getFilterFactory()
}
/**
- * Check if template can be added to newsletter queue
+ * Check if template can be added to newsletter queue.
*
* @return boolean
*/
public function isValidForSend()
{
- return !$this->scopeConfig->isSetFlag(
- \Magento\Email\Model\Template::XML_PATH_SYSTEM_SMTP_DISABLE,
- \Magento\Store\Model\ScopeInterface::SCOPE_STORE
- ) && $this->getTemplateSenderName() && $this->getTemplateSenderEmail() && $this->getTemplateSubject();
+ return $this->getTemplateSenderName() && $this->getTemplateSenderEmail() && $this->getTemplateSubject();
}
}
diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/TemplateTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/TemplateTest.php
index 30c94d28ffd91..7381da3a716a7 100644
--- a/app/code/Magento/Newsletter/Test/Unit/Model/TemplateTest.php
+++ b/app/code/Magento/Newsletter/Test/Unit/Model/TemplateTest.php
@@ -336,6 +336,8 @@ public function testGetProcessedTemplate($variables, $templateType, $storeId, $e
}
/**
+ * Get processed template data provider.
+ *
* @return array
*/
public function getProcessedTemplateDataProvider()
@@ -379,4 +381,56 @@ public function getProcessedTemplateDataProvider()
],
];
}
+
+ /**
+ * @param $senderName string
+ * @param $senderEmail string
+ * @param $templateSubject string
+ * @param $expectedValue
+ * @dataProvider isValidForSendDataProvider
+ */
+ public function testIsValidForSend($senderName, $senderEmail, $templateSubject, $expectedValue)
+ {
+ $model = $this->getModelMock(['getTemplateSenderName', 'getTemplateSenderEmail', 'getTemplateSubject']);
+ $model->expects($this->any())
+ ->method('getTemplateSenderName')
+ ->will($this->returnValue($senderName));
+ $model->expects($this->any())
+ ->method('getTemplateSenderEmail')
+ ->will($this->returnValue($senderEmail));
+ $model->expects($this->any())
+ ->method('getTemplateSubject')
+ ->will($this->returnValue($templateSubject));
+ $this->assertEquals($expectedValue, $model->isValidForSend());
+ }
+
+ public function isValidForSendDataProvider()
+ {
+ return [
+ 'should be valid' => [
+ 'senderName' => 'sender name',
+ 'senderEmail' => 'email@example.com',
+ 'templateSubject' => 'template subject',
+ 'expectedValue' => true
+ ],
+ 'no sender name so not valid' => [
+ 'senderName' => '',
+ 'senderEmail' => 'email@example.com',
+ 'templateSubject' => 'template subject',
+ 'expectedValue' => false
+ ],
+ 'no sender email so not valid' => [
+ 'senderName' => 'sender name',
+ 'senderEmail' => '',
+ 'templateSubject' => 'template subject',
+ 'expectedValue' => false
+ ],
+ 'no subject so not valid' => [
+ 'senderName' => 'sender name',
+ 'senderEmail' => 'email@example.com',
+ 'templateSubject' => '',
+ 'expectedValue' => false
+ ],
+ ];
+ }
}
diff --git a/app/code/Magento/Newsletter/composer.json b/app/code/Magento/Newsletter/composer.json
index 5308117b239a4..01c085aeca665 100644
--- a/app/code/Magento/Newsletter/composer.json
+++ b/app/code/Magento/Newsletter/composer.json
@@ -15,7 +15,7 @@
"magento/framework": "100.1.*"
},
"type": "magento2-module",
- "version": "100.1.2",
+ "version": "100.1.3",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/PageCache/Model/App/FrontController/BuiltinPlugin.php b/app/code/Magento/PageCache/Model/App/FrontController/BuiltinPlugin.php
index d6794fbd9d891..88eaca8bf49f0 100644
--- a/app/code/Magento/PageCache/Model/App/FrontController/BuiltinPlugin.php
+++ b/app/code/Magento/PageCache/Model/App/FrontController/BuiltinPlugin.php
@@ -64,10 +64,10 @@ public function aroundDispatch(
\Closure $proceed,
\Magento\Framework\App\RequestInterface $request
) {
+ $this->version->process();
if (!$this->config->isEnabled() || $this->config->getType() != \Magento\PageCache\Model\Config::BUILT_IN) {
return $proceed($request);
}
- $this->version->process();
$result = $this->kernel->load();
if ($result === false) {
$result = $proceed($request);
diff --git a/app/code/Magento/PageCache/Test/Unit/Model/App/FrontController/BuiltinPluginTest.php b/app/code/Magento/PageCache/Test/Unit/Model/App/FrontController/BuiltinPluginTest.php
index ebbc3955dc271..6eb5308eaea7c 100644
--- a/app/code/Magento/PageCache/Test/Unit/Model/App/FrontController/BuiltinPluginTest.php
+++ b/app/code/Magento/PageCache/Test/Unit/Model/App/FrontController/BuiltinPluginTest.php
@@ -219,7 +219,7 @@ public function testAroundDispatchDisabled($state)
->method('isEnabled')
->will($this->returnValue(true));
$this->versionMock
- ->expects($this->never())
+ ->expects($this->once())
->method('process');
$this->stateMock->expects($this->any())
->method('getMode')
diff --git a/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js b/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js
index 8a786fbb4fb30..28232dcd0d352 100644
--- a/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js
+++ b/app/code/Magento/PageCache/view/frontend/web/js/page-cache.js
@@ -24,6 +24,18 @@ define([
* @param {jQuery} element - Comment holder
*/
(function lookup(element) {
+ var iframeHostName;
+
+ // prevent cross origin iframe content reading
+ if ($(element).prop('tagName') === 'IFRAME') {
+ iframeHostName = $('').prop('href', $(element).prop('src'))
+ .prop('hostname');
+
+ if (window.location.hostname !== iframeHostName) {
+ return [];
+ }
+ }
+
$(element).contents().each(function (index, el) {
switch (el.nodeType) {
case 1: // ELEMENT_NODE
@@ -35,14 +47,7 @@ define([
break;
case 9: // DOCUMENT_NODE
- var hostName = window.location.hostname,
- iFrameHostName = $('')
- .prop('href', element.prop('src'))
- .prop('hostname');
-
- if (hostName === iFrameHostName) {
- lookup($(el).find('body'));
- }
+ lookup($(el).find('body'));
break;
}
});
@@ -159,17 +164,16 @@ define([
* @protected
*/
_replacePlaceholder: function (placeholder, html) {
+ var startReplacing = false,
+ prevSibling = null,
+ parent, contents, yy, len, element;
+
if (!placeholder || !html) {
return;
}
- var parent = $(placeholder.openElement).parent(),
- contents = parent.contents(),
- startReplacing = false,
- prevSibling = null,
- yy,
- len,
- element;
+ parent = $(placeholder.openElement).parent();
+ contents = parent.contents();
for (yy = 0, len = contents.length; yy < len; yy++) {
element = contents[yy];
diff --git a/app/code/Magento/Payment/composer.json b/app/code/Magento/Payment/composer.json
index 1d4ef3781964e..31baa881958a5 100644
--- a/app/code/Magento/Payment/composer.json
+++ b/app/code/Magento/Payment/composer.json
@@ -12,7 +12,7 @@
"magento/framework": "100.1.*"
},
"type": "magento2-module",
- "version": "100.1.5",
+ "version": "100.1.6",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Paypal/Model/Express/Checkout.php b/app/code/Magento/Paypal/Model/Express/Checkout.php
index be185ce7b0ac0..a35a5eea96a6b 100644
--- a/app/code/Magento/Paypal/Model/Express/Checkout.php
+++ b/app/code/Magento/Paypal/Model/Express/Checkout.php
@@ -12,6 +12,8 @@
use Magento\Quote\Model\Quote\Address;
use Magento\Framework\DataObject;
use Magento\Paypal\Model\Cart as PaypalCart;
+use Magento\Framework\App\ObjectManager;
+use Magento\Sales\Api\OrderRepositoryInterface;
/**
* Wrapper that performs Paypal Express and Checkout communication
@@ -70,7 +72,7 @@ class Checkout
*
* @var string
*/
- protected $_apiType = 'Magento\Paypal\Model\Api\Nvp';
+ protected $_apiType = \Magento\Paypal\Model\Api\Nvp::class;
/**
* Payment method type
@@ -268,6 +270,13 @@ class Checkout
*/
protected $totalsCollector;
+ /**
+ * Order repository interface.
+ *
+ * @var OrderRepositoryInterface
+ */
+ private $orderRepository;
+
/**
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Customer\Model\Url $customerUrl
@@ -538,6 +547,12 @@ public function start($returnUrl, $cancelUrl, $button = null)
}
$this->_api->setSuppressShipping(true);
} else {
+ $billingAddress = $this->_quote->getBillingAddress();
+
+ if ($billingAddress) {
+ $this->_api->setBillingAddress($billingAddress);
+ }
+
$address = $this->_quote->getShippingAddress();
$isOverridden = 0;
if (true === $address->validate()) {
@@ -668,6 +683,7 @@ public function returnFromPaypal($token)
$this->_setExportedAddressData($billingAddress, $exportedBillingAddress);
$billingAddress->setCustomerNote($exportedBillingAddress->getData('note'));
$quote->setBillingAddress($billingAddress);
+ $quote->setCheckoutMethod($this->getCheckoutMethod());
// import payment info
$payment = $quote->getPayment();
@@ -789,7 +805,8 @@ public function place($token, $shippingMethodCode = null)
$this->ignoreAddressValidation();
$this->_quote->collectTotals();
- $order = $this->quoteManagement->submit($this->_quote);
+ $orderId = $this->quoteManagement->placeOrder($this->_quote->getId());
+ $order = $this->getOrderRepository()->get($orderId);
if (!$order) {
return;
@@ -1157,4 +1174,21 @@ protected function prepareGuestQuote()
->setCustomerGroupId(\Magento\Customer\Model\Group::NOT_LOGGED_IN_ID);
return $this;
}
+
+ /**
+ * Returns order repository instance.
+ *
+ * @return OrderRepositoryInterface
+ *
+ * @deprecated
+ */
+ private function getOrderRepository()
+ {
+ if ($this->orderRepository === null) {
+ $this->orderRepository = ObjectManager::getInstance()
+ ->get(OrderRepositoryInterface::class);
+ }
+
+ return $this->orderRepository;
+ }
}
diff --git a/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php b/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php
index c08770ee191fc..7efb940766336 100644
--- a/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php
+++ b/app/code/Magento/Paypal/Model/Payflow/Service/Request/SecureToken.php
@@ -3,6 +3,7 @@
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Paypal\Model\Payflow\Service\Request;
use Magento\Framework\Math\Random;
@@ -11,7 +12,6 @@
use Magento\Paypal\Model\Payflow\Transparent;
use Magento\Paypal\Model\Payflowpro;
use Magento\Quote\Model\Quote;
-use Magento\Sales\Model\Order\Payment;
/**
* Class SecureToken
@@ -64,6 +64,7 @@ public function requestToken(Quote $quote)
$request->setTrxtype(Payflowpro::TRXTYPE_AUTH_ONLY);
$request->setVerbosity('HIGH');
$request->setAmt(0);
+ $request->setCurrency($quote->getBaseCurrencyCode());
$request->setCreatesecuretoken('Y');
$request->setSecuretokenid($this->mathRandom->getUniqueHash());
$request->setReturnurl($this->url->getUrl('paypal/transparent/response'));
diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Request/SecureTokenTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Request/SecureTokenTest.php
index 77a7591116eda..32cf13fbf73e1 100644
--- a/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Request/SecureTokenTest.php
+++ b/app/code/Magento/Paypal/Test/Unit/Model/Payflow/Service/Request/SecureTokenTest.php
@@ -3,6 +3,7 @@
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Paypal\Test\Unit\Model\Payflow\Service\Request;
use Magento\Framework\Math\Random;
@@ -10,6 +11,8 @@
use Magento\Framework\UrlInterface;
use Magento\Paypal\Model\Payflow\Service\Request\SecureToken;
use Magento\Paypal\Model\Payflow\Transparent;
+use Magento\Paypal\Model\PayflowConfig;
+use Magento\Quote\Model\Quote;
/**
* Test class for \Magento\Paypal\Model\Payflow\Service\Request\SecureToken
@@ -36,11 +39,16 @@ class SecureTokenTest extends \PHPUnit_Framework_TestCase
*/
protected $url;
+ /** @var DataObject */
+ private $request;
+
protected function setUp()
{
- $this->url = $this->getMock('Magento\Framework\UrlInterface', [], [], '', false);
- $this->mathRandom = $this->getMock('Magento\Framework\Math\Random', [], [], '', false);
- $this->transparent = $this->getMock('Magento\Paypal\Model\Payflow\Transparent', [], [], '', false);
+ $this->url = $this->buildMock(UrlInterface::class);
+ $this->mathRandom = $this->buildMock(Random::class);
+ $this->request = new DataObject();
+
+ $this->transparent = $this->buildPaymentService($this->request);
$this->model = new SecureToken(
$this->url,
@@ -49,23 +57,13 @@ protected function setUp()
);
}
+ /**
+ * Test Request Token
+ */
public function testRequestToken()
{
- $request = new DataObject();
$secureTokenID = 'Sdj46hDokds09c8k2klaGJdKLl032ekR';
- $this->transparent->expects($this->once())
- ->method('buildBasicRequest')
- ->willReturn($request);
- $this->transparent->expects($this->once())
- ->method('fillCustomerContacts');
- $this->transparent->expects($this->once())
- ->method('getConfig')
- ->willReturn($this->getMock('Magento\Paypal\Model\PayflowConfig', [], [], '', false));
- $this->transparent->expects($this->once())
- ->method('postRequest')
- ->willReturn(new DataObject());
-
$this->mathRandom->expects($this->once())
->method('getUniqueHash')
->willReturn($secureTokenID);
@@ -73,10 +71,79 @@ public function testRequestToken()
$this->url->expects($this->exactly(3))
->method('getUrl');
- $quote = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false);
+ /** @var Quote | \PHPUnit_Framework_MockObject_MockObject $quote */
+ $quote = $this->buildMock(Quote::class);
+
+ $this->model->requestToken($quote);
+
+ $this->assertEquals($secureTokenID, $this->request->getSecuretokenid());
+ }
+
+ /**
+ * Test request currency
+ *
+ * @dataProvider currencyProvider
+ * @param $currency
+ */
+ public function testCurrency($currency)
+ {
+ /** @var Quote | \PHPUnit_Framework_MockObject_MockObject $quote */
+ $quote = $this->buildMock(Quote::class, ['getBaseCurrencyCode']);
+ $quote->expects(self::atLeastOnce())
+ ->method('getBaseCurrencyCode')
+ ->willReturn($currency);
$this->model->requestToken($quote);
- $this->assertEquals($secureTokenID, $request->getSecuretokenid());
+ $this->assertEquals($currency, $this->request->getCurrency());
+ }
+
+ /**
+ * Builds default mock object
+ *
+ * @param string $class className
+ * @param array|null $methods
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ private function buildMock($class, array $methods = [])
+ {
+ return $this->getMockBuilder($class)
+ ->disableOriginalConstructor()
+ ->setMethods($methods)
+ ->getMock();
+ }
+
+ /**
+ * Creates payment method service
+ *
+ * @param DataObject $request
+ * @return Transparent | \PHPUnit_Framework_MockObject_MockObject
+ */
+ private function buildPaymentService(DataObject $request)
+ {
+ $service = $this->buildMock(Transparent::class);
+ $service->expects($this->once())
+ ->method('buildBasicRequest')
+ ->willReturn($request);
+ $service->expects($this->once())
+ ->method('fillCustomerContacts');
+ $service->expects($this->once())
+ ->method('getConfig')
+ ->willReturn($this->buildMock(PayflowConfig::class));
+ $service->expects($this->once())
+ ->method('postRequest')
+ ->willReturn(new DataObject());
+
+ return $service;
+ }
+
+ /**
+ * DataProvider for testing currency
+ *
+ * @return array
+ */
+ public function currencyProvider()
+ {
+ return [['GBP'], [null], ['USD']];
}
}
diff --git a/app/code/Magento/Paypal/composer.json b/app/code/Magento/Paypal/composer.json
index cbafbba884ec0..2e1350b0cdb80 100644
--- a/app/code/Magento/Paypal/composer.json
+++ b/app/code/Magento/Paypal/composer.json
@@ -25,7 +25,7 @@
"magento/module-checkout-agreements": "100.1.*"
},
"type": "magento2-module",
- "version": "100.1.5",
+ "version": "100.1.6",
"license": [
"proprietary"
],
diff --git a/app/code/Magento/Quote/Model/Quote.php b/app/code/Magento/Quote/Model/Quote.php
index a7fd735fdc673..4264faa6e5de4 100644
--- a/app/code/Magento/Quote/Model/Quote.php
+++ b/app/code/Magento/Quote/Model/Quote.php
@@ -487,7 +487,7 @@ public function __construct(
*/
protected function _construct()
{
- $this->_init('Magento\Quote\Model\ResourceModel\Quote');
+ $this->_init(\Magento\Quote\Model\ResourceModel\Quote::class);
}
/**
@@ -962,7 +962,7 @@ public function setCustomer(\Magento\Customer\Api\Data\CustomerInterface $custom
$this->extensibleDataObjectConverter->toFlatArray(
$customer,
[],
- '\Magento\Customer\Api\Data\CustomerInterface'
+ \Magento\Customer\Api\Data\CustomerInterface::class
)
);
$customer->setAddresses($origAddresses);
@@ -1570,6 +1570,11 @@ public function addProduct(
__('We found an invalid request for adding product to quote.')
);
}
+ if (!$product->isSalable()) {
+ throw new \Magento\Framework\Exception\LocalizedException(
+ __('Product that you are trying to add is not available.')
+ );
+ }
$cartCandidates = $product->getTypeInstance()->prepareForCartAdvanced($request, $product, $processMode);
diff --git a/app/code/Magento/Quote/Model/Quote/Address/Total/Collector.php b/app/code/Magento/Quote/Model/Quote/Address/Total/Collector.php
index 1b6503e9558f0..d1d428c1c2d43 100644
--- a/app/code/Magento/Quote/Model/Quote/Address/Total/Collector.php
+++ b/app/code/Magento/Quote/Model/Quote/Address/Total/Collector.php
@@ -136,7 +136,7 @@ protected function _initModelInstance($class, $totalCode, $totalConfig)
}
/**
- * Initialize retrievers array
+ * Initialize retrievers array.
*
* @return $this
* @SuppressWarnings(PHPMD.UnusedPrivateMethod)
@@ -148,6 +148,9 @@ private function _initRetrievers()
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$this->_store
);
+ if ($sorts === null) {
+ $sorts = [];
+ }
foreach ($sorts as $code => $sortOrder) {
if (isset($this->_models[$code])) {
// Reserve enough space for collisions
@@ -164,6 +167,7 @@ private function _initRetrievers()
foreach ($notSorted as $code) {
$this->_retrievers[] = $this->_models[$code];
}
+
return $this;
}
}
diff --git a/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php b/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php
index 289dc05c365ba..bf44378b3a543 100644
--- a/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php
+++ b/app/code/Magento/Quote/Model/Quote/Address/Total/Shipping.php
@@ -59,11 +59,8 @@ public function collect(
$addressWeight = $address->getWeight();
$freeMethodWeight = $address->getFreeMethodWeight();
+ $addressFreeShipping = $address->getFreeShipping();
- $isAllFree = $this->freeShipping->isFreeShipping($quote, $shippingAssignment->getItems());
- if ($isAllFree && !$address->getFreeShipping()) {
- $address->setFreeShipping(true);
- }
$total->setTotalAmount($this->getCode(), 0);
$total->setBaseTotalAmount($this->getCode(), 0);
@@ -99,7 +96,7 @@ public function collect(
$itemQty = $child->getTotalQty();
$rowWeight = $itemWeight * $itemQty;
$addressWeight += $rowWeight;
- if ($address->getFreeShipping() || $child->getFreeShipping() === true) {
+ if ($addressFreeShipping || $child->getFreeShipping() === true) {
$rowWeight = 0;
} elseif (is_numeric($child->getFreeShipping())) {
$freeQty = $child->getFreeShipping();
@@ -117,7 +114,7 @@ public function collect(
$itemWeight = $item->getWeight();
$rowWeight = $itemWeight * $item->getQty();
$addressWeight += $rowWeight;
- if ($address->getFreeShipping() || $item->getFreeShipping() === true) {
+ if ($addressFreeShipping || $item->getFreeShipping() === true) {
$rowWeight = 0;
} elseif (is_numeric($item->getFreeShipping())) {
$freeQty = $item->getFreeShipping();
@@ -137,7 +134,7 @@ public function collect(
$itemWeight = $item->getWeight();
$rowWeight = $itemWeight * $item->getQty();
$addressWeight += $rowWeight;
- if ($address->getFreeShipping() || $item->getFreeShipping() === true) {
+ if ($addressFreeShipping || $item->getFreeShipping() === true) {
$rowWeight = 0;
} elseif (is_numeric($item->getFreeShipping())) {
$freeQty = $item->getFreeShipping();
@@ -158,6 +155,10 @@ public function collect(
$address->setWeight($addressWeight);
$address->setFreeMethodWeight($freeMethodWeight);
+ $address->setFreeShipping(
+ $this->freeShipping->isFreeShipping($quote, $shippingAssignment->getItems())
+ );
+
$address->collectShippingRates();
if ($method) {
@@ -179,6 +180,7 @@ public function collect(
}
}
}
+
return $this;
}
diff --git a/app/code/Magento/Quote/Model/Quote/ShippingAssignment/ShippingAssignmentProcessor.php b/app/code/Magento/Quote/Model/Quote/ShippingAssignment/ShippingAssignmentProcessor.php
index fdf819c8d864c..45d55a4be794f 100644
--- a/app/code/Magento/Quote/Model/Quote/ShippingAssignment/ShippingAssignmentProcessor.php
+++ b/app/code/Magento/Quote/Model/Quote/ShippingAssignment/ShippingAssignmentProcessor.php
@@ -9,7 +9,10 @@
use Magento\Quote\Api\Data\ShippingAssignmentInterface;
use Magento\Framework\Exception\InputException;
use Magento\Quote\Model\ShippingAssignmentFactory;
-use Magento\Quote\Model\Quote\Item\CartItemPersister;
+use Magento\Customer\Api\AddressRepositoryInterface;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\App\ObjectManager;
class ShippingAssignmentProcessor
{
@@ -24,45 +27,65 @@ class ShippingAssignmentProcessor
protected $shippingProcessor;
/**
- * @var CartItemPersister
+ * @var \Magento\Quote\Model\Quote\Item\CartItemPersister
*/
protected $cartItemPersister;
+ /**
+ * Customer address CRUD interface.
+ *
+ * @var AddressRepositoryInterface
+ */
+ private $addressRepository;
+
/**
* @param ShippingAssignmentFactory $shippingAssignmentFactory
* @param ShippingProcessor $shippingProcessor
- * @param CartItemPersister $cartItemPersister
+ * @param \Magento\Quote\Model\Quote\Item\CartItemPersister $cartItemPersister
+ * @param AddressRepositoryInterface $addressRepository
*/
public function __construct(
ShippingAssignmentFactory $shippingAssignmentFactory,
ShippingProcessor $shippingProcessor,
- CartItemPersister $cartItemPersister
+ \Magento\Quote\Model\Quote\Item\CartItemPersister $cartItemPersister,
+ AddressRepositoryInterface $addressRepository = null
) {
$this->shippingAssignmentFactory = $shippingAssignmentFactory;
$this->shippingProcessor = $shippingProcessor;
$this->cartItemPersister = $cartItemPersister;
+ $this->addressRepository = $addressRepository
+ ?: ObjectManager::getInstance()->get(AddressRepositoryInterface::class);
}
/**
+ * Create shipping assignment.
+ *
* @param CartInterface $quote
+ *
* @return \Magento\Quote\Api\Data\ShippingAssignmentInterface
*/
public function create(CartInterface $quote)
{
/** @var \Magento\Quote\Model\Quote $quote */
$shippingAddress = $quote->getShippingAddress();
+
/** @var \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment */
$shippingAssignment = $this->shippingAssignmentFactory->create();
$shippingAssignment->setItems($quote->getItems());
$shippingAssignment->setShipping($this->shippingProcessor->create($shippingAddress));
+
return $shippingAssignment;
}
/**
+ * Save shipping assignment.
+ *
* @param ShippingAssignmentInterface $shippingAssignment
* @param CartInterface $quote
+ *
* @return void
- * @throws InputException
+ *
+ * @throws InputException|LocalizedException
*/
public function save(CartInterface $quote, ShippingAssignmentInterface $shippingAssignment)
{
@@ -73,6 +96,17 @@ public function save(CartInterface $quote, ShippingAssignmentInterface $shipping
$this->cartItemPersister->save($quote, $item);
}
}
+
+ $shippingAddress = $shippingAssignment->getShipping()->getAddress();
+
+ if ($shippingAddress->getCustomerAddressId()) {
+ try {
+ $this->addressRepository->getById($shippingAddress->getCustomerAddressId());
+ } catch (NoSuchEntityException $e) {
+ $shippingAddress->setCustomerAddressId(null);
+ }
+ }
+
$this->shippingProcessor->save($shippingAssignment->getShipping(), $quote);
}
}
diff --git a/app/code/Magento/Quote/Model/QuoteRepository/SaveHandler.php b/app/code/Magento/Quote/Model/QuoteRepository/SaveHandler.php
index 647946e141a63..e91becaf3cf88 100644
--- a/app/code/Magento/Quote/Model/QuoteRepository/SaveHandler.php
+++ b/app/code/Magento/Quote/Model/QuoteRepository/SaveHandler.php
@@ -7,6 +7,8 @@
use Magento\Quote\Api\Data\CartInterface;
use Magento\Framework\Exception\InputException;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Exception\NoSuchEntityException;
class SaveHandler
{
@@ -30,26 +32,40 @@ class SaveHandler
*/
private $shippingAssignmentPersister;
+ /**
+ * Customer address CRUD interface.
+ *
+ * @var \Magento\Customer\Api\AddressRepositoryInterface
+ */
+ private $addressRepository;
+
/**
* @param \Magento\Quote\Model\ResourceModel\Quote $quoteResource
* @param \Magento\Quote\Model\Quote\Item\CartItemPersister $cartItemPersister
* @param \Magento\Quote\Model\Quote\Address\BillingAddressPersister $billingAddressPersister
* @param \Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentPersister $shippingAssignmentPersister
+ * @param \Magento\Customer\Api\AddressRepositoryInterface $addressRepository
*/
public function __construct(
\Magento\Quote\Model\ResourceModel\Quote $quoteResource,
\Magento\Quote\Model\Quote\Item\CartItemPersister $cartItemPersister,
\Magento\Quote\Model\Quote\Address\BillingAddressPersister $billingAddressPersister,
- \Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentPersister $shippingAssignmentPersister
+ \Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentPersister $shippingAssignmentPersister,
+ \Magento\Customer\Api\AddressRepositoryInterface $addressRepository = null
) {
$this->quoteResourceModel = $quoteResource;
$this->cartItemPersister = $cartItemPersister;
$this->billingAddressPersister = $billingAddressPersister;
$this->shippingAssignmentPersister = $shippingAssignmentPersister;
+ $this->addressRepository = $addressRepository
+ ?: ObjectManager::getInstance()->get(\Magento\Customer\Api\AddressRepositoryInterface::class);
}
/**
+ * Process and save quote data.
+ *
* @param CartInterface $quote
+ *
* @return CartInterface
*
* @throws InputException
@@ -62,6 +78,7 @@ public function save(CartInterface $quote)
/** @var \Magento\Quote\Model\Quote $quote */
// Quote Item processing
$items = $quote->getItems();
+
if ($items) {
foreach ($items as $item) {
/** @var \Magento\Quote\Model\Quote\Item $item */
@@ -73,30 +90,46 @@ public function save(CartInterface $quote)
// Billing Address processing
$billingAddress = $quote->getBillingAddress();
+
if ($billingAddress) {
+ if ($billingAddress->getCustomerAddressId()) {
+ try {
+ $this->addressRepository->getById($billingAddress->getCustomerAddressId());
+ } catch (NoSuchEntityException $e) {
+ $billingAddress->setCustomerAddressId(null);
+ }
+ }
+
$this->billingAddressPersister->save($quote, $billingAddress);
}
$this->processShippingAssignment($quote);
-
$this->quoteResourceModel->save($quote->collectTotals());
+
return $quote;
}
/**
+ * Process shipping assignment.
+ *
* @param \Magento\Quote\Model\Quote $quote
+ *
* @return void
+ *
* @throws InputException
*/
private function processShippingAssignment($quote)
{
// Shipping Assignments processing
$extensionAttributes = $quote->getExtensionAttributes();
+
if (!$quote->isVirtual() && $extensionAttributes && $extensionAttributes->getShippingAssignments()) {
$shippingAssignments = $extensionAttributes->getShippingAssignments();
+
if (count($shippingAssignments) > 1) {
- throw new InputException(__("Only 1 shipping assignment can be set"));
+ throw new InputException(__('Only 1 shipping assignment can be set'));
}
+
$this->shippingAssignmentPersister->save($quote, $shippingAssignments[0]);
}
}
diff --git a/app/code/Magento/Quote/Setup/UpgradeSchema.php b/app/code/Magento/Quote/Setup/UpgradeSchema.php
index deaef9c8a18c6..b4a730142b7a7 100644
--- a/app/code/Magento/Quote/Setup/UpgradeSchema.php
+++ b/app/code/Magento/Quote/Setup/UpgradeSchema.php
@@ -55,6 +55,38 @@ public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $con
$setup->getFkName('quote_item', 'product_id', 'catalog_product_entity', 'entity_id')
);
}
+ if (version_compare($context->getVersion(), '2.0.4', '<')) {
+ $setup->getConnection(self::$connectionName)->changeColumn(
+ $setup->getTable('quote_address', self::$connectionName),
+ 'firstname',
+ 'firstname',
+ [
+ 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+ 'length' => 255,
+ 'comment' => 'Firstname'
+ ]
+ );
+ $setup->getConnection(self::$connectionName)->changeColumn(
+ $setup->getTable('quote_address', self::$connectionName),
+ 'middlename',
+ 'middlename',
+ [
+ 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+ 'length' => 40,
+ 'comment' => 'Middlename'
+ ]
+ );
+ $setup->getConnection(self::$connectionName)->changeColumn(
+ $setup->getTable('quote_address', self::$connectionName),
+ 'lastname',
+ 'lastname',
+ [
+ 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
+ 'length' => 255,
+ 'comment' => 'Lastname'
+ ]
+ );
+ }
$setup->endSetup();
}
}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/ShippingAssignment/ShippingAssignmentProcessorTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/ShippingAssignment/ShippingAssignmentProcessorTest.php
index e74070c3eaee7..2f1b1c093604e 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/Quote/ShippingAssignment/ShippingAssignmentProcessorTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/ShippingAssignment/ShippingAssignmentProcessorTest.php
@@ -5,107 +5,199 @@
*/
namespace Magento\Quote\Test\Unit\Model\Quote\ShippingAssignment;
-use Magento\Quote\Api\Data\ShippingAssignmentInterface;
-use Magento\Quote\Api\Data\ShippingInterface;
-use Magento\Quote\Model\Quote;
-use Magento\Quote\Model\ShippingAssignmentFactory;
-use Magento\Quote\Model\Quote\Item\CartItemPersister;
use Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentProcessor;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+use Magento\Quote\Model\ShippingAssignmentFactory;
use Magento\Quote\Model\Quote\ShippingAssignment\ShippingProcessor;
-use PHPUnit_Framework_MockObject_MockObject as MockObject;
+use Magento\Quote\Model\Quote\Item\CartItemPersister;
+use Magento\Customer\Api\AddressRepositoryInterface;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Api\Data\ShippingAssignmentInterface;
+use Magento\Quote\Model\Quote\Address as QuoteAddress;
+use Magento\Quote\Api\Data\ShippingInterface;
+use Magento\Quote\Model\Quote\Item as QuoteItem;
+use Magento\Framework\Exception\NoSuchEntityException;
/**
- * Class ShippingAssignmentProcessorTest
+ * ShippingAssignmentProcessor test.
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class ShippingAssignmentProcessorTest extends \PHPUnit_Framework_TestCase
{
/**
- * @var ShippingAssignmentFactory|MockObject
+ * @var ShippingAssignmentProcessor
*/
- private $shippingAssignmentFactory;
+ private $shippingAssignmentProcessor;
/**
- * @var ShippingProcessor|MockObject
+ * @var ObjectManagerHelper
*/
- private $shippingProcessor;
+ private $objectManagerHelper;
/**
- * @var CartItemPersister|MockObject
+ * @var ShippingAssignmentFactory|\PHPUnit_Framework_MockObject_MockObject
*/
- private $cartItemPersister;
+ private $shippingAssignmentFactoryMock;
/**
- * @var ShippingAssignmentProcessor
+ * @var ShippingProcessor|\PHPUnit_Framework_MockObject_MockObject
*/
- private $shippingAssignmentProcessor;
+ private $shippingProcessorMock;
+
+ /**
+ * @var CartItemPersister|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $cartItemPersisterMock;
+
+ /**
+ * @var AddressRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $addressRepositoryMock;
+
+ /**
+ * @var Quote|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $quoteMock;
+
+ /**
+ * @var ShippingAssignmentInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $shippingAssignmentMock;
+
+ /**
+ * @var QuoteAddress|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $shippingAddressMock;
+
+ /**
+ * @var ShippingInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $shippingMock;
protected function setUp()
{
- $this->shippingAssignmentFactory = $this->getMockBuilder(ShippingAssignmentFactory::class)
+ $this->shippingAssignmentFactoryMock = $this->getMockBuilder(ShippingAssignmentFactory::class)
->disableOriginalConstructor()
->getMock();
-
- $this->shippingProcessor = $this->getMockBuilder(ShippingProcessor::class)
+ $this->shippingProcessorMock = $this->getMockBuilder(ShippingProcessor::class)
->disableOriginalConstructor()
->getMock();
-
- $this->cartItemPersister = $this->getMockBuilder(CartItemPersister::class)
+ $this->cartItemPersisterMock = $this->getMockBuilder(CartItemPersister::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->addressRepositoryMock = $this->getMockBuilder(AddressRepositoryInterface::class)
+ ->getMockForAbstractClass();
+ $this->quoteMock = $this->getMockBuilder(Quote::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->shippingAssignmentMock = $this->getMockBuilder(ShippingAssignmentInterface::class)
+ ->getMockForAbstractClass();
+ $this->shippingAddressMock = $this->getMockBuilder(QuoteAddress::class)
->disableOriginalConstructor()
->getMock();
+ $this->shippingMock = $this->getMockBuilder(ShippingInterface::class)
+ ->getMockForAbstractClass();
+
+ $this->quoteMock->expects(static::any())
+ ->method('getShippingAddress')
+ ->willReturn($this->shippingAddressMock);
+ $this->shippingAssignmentMock->expects(static::any())
+ ->method('getShipping')
+ ->willReturn($this->shippingMock);
+ $this->shippingMock->expects(static::any())
+ ->method('getAddress')
+ ->willReturn($this->shippingAddressMock);
- $this->shippingAssignmentProcessor = new ShippingAssignmentProcessor(
- $this->shippingAssignmentFactory,
- $this->shippingProcessor,
- $this->cartItemPersister
+ $this->objectManagerHelper = new ObjectManagerHelper($this);
+ $this->shippingAssignmentProcessor = $this->objectManagerHelper->getObject(
+ ShippingAssignmentProcessor::class,
+ [
+ 'shippingAssignmentFactory' => $this->shippingAssignmentFactoryMock,
+ 'shippingProcessor' => $this->shippingProcessorMock,
+ 'cartItemPersister' => $this->cartItemPersisterMock,
+ 'addressRepository' => $this->addressRepositoryMock
+ ]
);
}
/**
- * Test saving shipping assignments with deleted cart items
- *
- * @covers \Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentProcessor::save
+ * Tests save() method with deleted cart items.
*/
public function testSaveWithDeletedCartItems()
{
- $shippingAssignment = $this->getMockForAbstractClass(ShippingAssignmentInterface::class);
- $shipping = $this->getMockForAbstractClass(ShippingInterface::class);
- $quoteId = 1;
+ $quoteItemId = 1;
- $quote = $this->getMockBuilder(Quote::class)
- ->disableOriginalConstructor()
- ->getMock();
- $quoteItem = $this->getMockBuilder(\Magento\Quote\Model\Quote\Item::class)
- ->disableOriginalConstructor()
- ->getMock();
- $quoteItem->expects(static::once())
- ->method('isDeleted')
- ->willReturn(true);
- $quoteItem->expects(static::once())
- ->method('getItemId')
- ->willReturn($quoteId);
-
- $quote->expects(static::once())
+ $this->shippingAssignmentMock->expects(static::once())
+ ->method('getItems')
+ ->willReturn([$this->createQuoteItemMock($quoteItemId, true)]);
+ $this->quoteMock->expects(static::atLeastOnce())
->method('getItemById')
- ->with($quoteId)
+ ->with($quoteItemId)
->willReturn(null);
+ $this->cartItemPersisterMock->expects(static::never())
+ ->method('save');
+ $this->shippingAddressMock->expects(static::atLeastOnce())
+ ->method('getCustomerAddressId')
+ ->willReturn(null);
+ $this->addressRepositoryMock->expects(static::never())
+ ->method('getById');
+ $this->shippingProcessorMock->expects(static::once())
+ ->method('save')
+ ->with($this->shippingMock, $this->quoteMock);
- $shippingAssignment->expects(static::once())
- ->method('getItems')
- ->willReturn([$quoteItem]);
- $shippingAssignment->expects(static::once())
- ->method('getShipping')
- ->willReturn($shipping);
+ $this->shippingAssignmentProcessor->save($this->quoteMock, $this->shippingAssignmentMock);
+ }
- $this->cartItemPersister->expects(static::never())
- ->method('save');
+ /**
+ * Tests save() method with not existing customer address.
+ */
+ public function testSaveWithNotExistingCustomerAddress()
+ {
+ $customerAddressId = 11;
- $this->shippingProcessor->expects(static::once())
+ $this->shippingAssignmentMock->expects(static::atLeastOnce())
+ ->method('getItems')
+ ->willReturn([]);
+ $this->shippingAddressMock->expects(static::atLeastOnce())
+ ->method('getCustomerAddressId')
+ ->willReturn($customerAddressId);
+ $this->addressRepositoryMock->expects(static::once())
+ ->method('getById')
+ ->with($customerAddressId)
+ ->willThrowException(new NoSuchEntityException());
+ $this->shippingAddressMock->expects(static::once())
+ ->method('setCustomerAddressId')
+ ->with(null)
+ ->willReturn($this->shippingAddressMock);
+ $this->shippingProcessorMock->expects(static::once())
->method('save')
- ->with($shipping, $quote);
+ ->with($this->shippingMock, $this->quoteMock);
- $this->shippingAssignmentProcessor->save(
- $quote,
- $shippingAssignment
- );
+ $this->shippingAssignmentProcessor->save($this->quoteMock, $this->shippingAssignmentMock);
+ }
+
+ /**
+ * Create quote item mock.
+ *
+ * @param int|string $id
+ * @param bool $isDeleted
+ *
+ * @return QuoteItem|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private function createQuoteItemMock($id, $isDeleted)
+ {
+ $quoteItemMock = $this->getMockBuilder(QuoteItem::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $quoteItemMock->expects(static::any())
+ ->method('getItemId')
+ ->willReturn($id);
+ $quoteItemMock->expects(static::any())
+ ->method('isDeleted')
+ ->willReturn($isDeleted);
+
+ return $quoteItemMock;
}
}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteRepository/SaveHandlerTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteRepository/SaveHandlerTest.php
index 633beb6c1853a..86bb3ddcf3386 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/QuoteRepository/SaveHandlerTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteRepository/SaveHandlerTest.php
@@ -3,11 +3,26 @@
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-
namespace Magento\Quote\Test\Unit\Model\QuoteRepository;
use Magento\Quote\Model\QuoteRepository\SaveHandler;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+use Magento\Quote\Model\ResourceModel\Quote as QuoteResourceModel;
+use Magento\Quote\Model\Quote\Item\CartItemPersister;
+use Magento\Quote\Model\Quote\Address\BillingAddressPersister;
+use Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentPersister;
+use Magento\Customer\Api\AddressRepositoryInterface;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\Quote\Address as QuoteAddress;
+use Magento\Quote\Api\Data\CartExtensionInterface;
+use Magento\Quote\Model\Quote\Item as QuoteItem;
+use Magento\Framework\Exception\NoSuchEntityException;
+/**
+ * SaveHandler test.
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
class SaveHandlerTest extends \PHPUnit_Framework_TestCase
{
/**
@@ -16,124 +31,201 @@ class SaveHandlerTest extends \PHPUnit_Framework_TestCase
private $saveHandler;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var ObjectManagerHelper
*/
- private $cartItemPersister;
+ private $objectManagerHelper;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var QuoteResourceModel|\PHPUnit_Framework_MockObject_MockObject
*/
- private $billingAddressPersister;
+ private $quoteResourceModelMock;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var CartItemPersister|\PHPUnit_Framework_MockObject_MockObject
*/
- private $quoteResourceModel;
+ private $cartItemPersisterMock;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var BillingAddressPersister|\PHPUnit_Framework_MockObject_MockObject
*/
- private $shippingAssignmentPersister;
+ private $billingAddressPersisterMock;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var ShippingAssignmentPersister|\PHPUnit_Framework_MockObject_MockObject
*/
- private $quoteMock;
+ private $shippingAssignmentPersisterMock;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var AddressRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
*/
- private $itemMock;
+ private $addressRepositoryMock;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var Quote|\PHPUnit_Framework_MockObject_MockObject
*/
- private $billingAddressMock;
+ private $quoteMock;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var QuoteAddress|\PHPUnit_Framework_MockObject_MockObject
*/
- private $extensionAttributeMock;
+ private $billingAddressMock;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var CartExtensionInterface|\PHPUnit_Framework_MockObject_MockObject
*/
- private $shippingAssignmentMock;
+ private $extensionAttributesMock;
protected function setUp()
{
- $this->quoteResourceModel = $this->getMock(\Magento\Quote\Model\ResourceModel\Quote::class, [], [], '', false);
- $this->cartItemPersister = $this->getMock(
- \Magento\Quote\Model\Quote\Item\CartItemPersister::class,
- [],
- [],
- '',
- false
- );
- $this->billingAddressPersister = $this->getMock(
- \Magento\Quote\Model\Quote\Address\BillingAddressPersister::class,
- [],
- [],
- '',
- false
- );
- $this->shippingAssignmentPersister = $this->getMock(
- \Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentPersister::class,
- [],
- [],
- '',
- false
- );
- $methods = [
- 'getItems', 'setLastAddedItem', 'getBillingAddress', 'getIsActive',
- 'getExtensionAttributes', 'isVirtual', 'collectTotals'
- ];
- $this->quoteMock = $this->getMock(\Magento\Quote\Model\Quote::class, $methods, [], '', false);
- $this->itemMock = $this->getMock(\Magento\Quote\Model\Quote\Item::class, [], [], '', false);
- $this->billingAddressMock = $this->getMock(\Magento\Quote\Model\Quote\Address::class, [], [], '', false);
- $this->extensionAttributeMock = $this->getMock(\Magento\Quote\Api\Data\CartExtensionInterface::class);
- $this->shippingAssignmentMock =
- $this->getMock(
- \Magento\Quote\Api\Data\CartExtension::class,
- ['getShippingAssignments', 'setShippingAssignments'],
- [],
- '',
- false
- );
- $this->saveHandler = new SaveHandler(
- $this->quoteResourceModel,
- $this->cartItemPersister,
- $this->billingAddressPersister,
- $this->shippingAssignmentPersister
- );
+ $this->quoteResourceModelMock = $this->getMockBuilder(QuoteResourceModel::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->cartItemPersisterMock = $this->getMockBuilder(CartItemPersister::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->billingAddressPersisterMock = $this->getMockBuilder(BillingAddressPersister::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->shippingAssignmentPersisterMock = $this->getMockBuilder(ShippingAssignmentPersister::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->addressRepositoryMock = $this->getMockBuilder(AddressRepositoryInterface::class)
+ ->getMockForAbstractClass();
+ $this->quoteMock = $this->getMockBuilder(Quote::class)
+ ->disableOriginalConstructor()
+ ->setMethods(
+ [
+ 'getItems', 'setLastAddedItem', 'getBillingAddress', 'getExtensionAttributes', 'isVirtual',
+ 'collectTotals'
+ ]
+ )
+ ->getMock();
+ $this->billingAddressMock = $this->getMockBuilder(QuoteAddress::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->extensionAttributesMock = $this->getMockBuilder(CartExtensionInterface::class)
+ ->getMockForAbstractClass();
+
+ $this->quoteMock->expects(static::any())
+ ->method('getBillingAddress')
+ ->willReturn($this->billingAddressMock);
+ $this->quoteMock->expects(static::any())
+ ->method('getExtensionAttributes')
+ ->willReturn($this->extensionAttributesMock);
+ $this->objectManagerHelper = new ObjectManagerHelper($this);
+ $this->saveHandler = $this->objectManagerHelper->getObject(
+ SaveHandler::class,
+ [
+ 'quoteResource' => $this->quoteResourceModelMock,
+ 'cartItemPersister' => $this->cartItemPersisterMock,
+ 'billingAddressPersister' => $this->billingAddressPersisterMock,
+ 'shippingAssignmentPersister' => $this->shippingAssignmentPersisterMock,
+ 'addressRepository' => $this->addressRepositoryMock
+ ]
+ );
}
+ /**
+ * Tests save() method for virtual quote.
+ */
public function testSaveForVirtualQuote()
{
- $this->quoteMock->expects($this->once())->method('getItems')->willReturn([$this->itemMock]);
- $this->itemMock->expects($this->once())->method('isDeleted')->willReturn(false);
- $this->cartItemPersister
- ->expects($this->once())
+ $quoteItemMock = $this->createQuoteItemMock(false);
+
+ $this->quoteMock->expects(static::atLeastOnce())
+ ->method('getItems')
+ ->willReturn([$quoteItemMock]);
+ $this->cartItemPersisterMock->expects(static::once())
->method('save')
- ->with($this->quoteMock, $this->itemMock)
- ->willReturn($this->itemMock);
- $this->quoteMock->expects($this->once())->method('setLastAddedItem')->with($this->itemMock);
- $this->quoteMock->expects($this->once())->method('getBillingAddress')->willReturn($this->billingAddressMock);
- $this->billingAddressPersister
- ->expects($this->once())
+ ->with($this->quoteMock, $quoteItemMock)
+ ->willReturn($quoteItemMock);
+ $this->quoteMock->expects(static::once())
+ ->method('setLastAddedItem')
+ ->with($quoteItemMock)
+ ->willReturnSelf();
+ $this->billingAddressMock->expects(static::atLeastOnce())
+ ->method('getCustomerAddressId')
+ ->willReturn(null);
+ $this->billingAddressMock->expects(static::never())
+ ->method('getCustomerAddress');
+ $this->billingAddressPersisterMock->expects(static::once())
->method('save')
->with($this->quoteMock, $this->billingAddressMock);
- $this->quoteMock
- ->expects($this->once())
- ->method('getExtensionAttributes')
- ->willReturn($this->extensionAttributeMock);
- $this->extensionAttributeMock
- ->expects($this->never())
+ $this->quoteMock->expects(static::atLeastOnce())
+ ->method('isVirtual')
+ ->willReturn(true);
+ $this->extensionAttributesMock->expects(static::never())
+ ->method('getShippingAssignments');
+ $this->quoteMock->expects(static::atLeastOnce())
+ ->method('collectTotals')
+ ->willReturnSelf();
+ $this->quoteResourceModelMock->expects(static::once())
+ ->method('save')
+ ->with($this->quoteMock)
+ ->willReturnSelf();
+
+ $this->assertSame($this->quoteMock, $this->saveHandler->save($this->quoteMock));
+ }
+
+ /**
+ * Tests save() method with not existing customer address.
+ */
+ public function testSaveWithNotExistingCustomerAddress()
+ {
+ $customerAddressId = 5;
+
+ $this->quoteMock->expects(static::atLeastOnce())
+ ->method('getItems')
+ ->willReturn([]);
+ $this->quoteMock->expects(static::never())
+ ->method('setLastAddedItem');
+ $this->billingAddressMock->expects(static::atLeastOnce())
+ ->method('getCustomerAddressId')
+ ->willReturn($customerAddressId);
+ $this->addressRepositoryMock->expects(static::once())
+ ->method('getById')
+ ->with($customerAddressId)
+ ->willThrowException(new NoSuchEntityException());
+ $this->billingAddressMock->expects(static::once())
+ ->method('setCustomerAddressId')
+ ->willReturn(null);
+ $this->billingAddressPersisterMock->expects(static::once())
+ ->method('save')
+ ->with($this->quoteMock, $this->billingAddressMock);
+ $this->quoteMock->expects(static::atLeastOnce())
+ ->method('isVirtual')
+ ->willReturn(true);
+ $this->extensionAttributesMock->expects(static::never())
->method('getShippingAssignments');
- $this->quoteMock->expects($this->once())->method('isVirtual')->willReturn(true);
- $this->quoteMock->expects($this->once())->method('collectTotals')->willReturn($this->quoteMock);
- $this->quoteResourceModel->expects($this->once())->method('save')->with($this->quoteMock);
- $this->assertEquals($this->quoteMock, $this->saveHandler->save($this->quoteMock));
+ $this->quoteMock->expects(static::atLeastOnce())
+ ->method('collectTotals')
+ ->willReturnSelf();
+ $this->quoteResourceModelMock->expects(static::once())
+ ->method('save')
+ ->with($this->quoteMock)
+ ->willReturnSelf();
+
+ $this->assertSame($this->quoteMock, $this->saveHandler->save($this->quoteMock));
+ }
+
+ /**
+ * Create quote item mock.
+ *
+ * @param bool $isDeleted
+ *
+ * @return QuoteItem|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private function createQuoteItemMock($isDeleted)
+ {
+ $quoteItemMock = $this->getMockBuilder(QuoteItem::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $quoteItemMock->expects(static::any())
+ ->method('isDeleted')
+ ->willReturn($isDeleted);
+
+ return $quoteItemMock;
}
}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php
index 5869540f8dca9..2b32ac639ef36 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php
@@ -148,14 +148,14 @@ class QuoteTest extends \PHPUnit_Framework_TestCase
protected function setUp()
{
$this->quoteAddressFactoryMock = $this->getMock(
- 'Magento\Quote\Model\Quote\AddressFactory',
+ \Magento\Quote\Model\Quote\AddressFactory::class,
['create'],
[],
'',
false
);
$this->quoteAddressMock = $this->getMock(
- 'Magento\Quote\Model\Quote\Address',
+ \Magento\Quote\Model\Quote\Address::class,
[
'isDeleted', 'getCollection', 'getId', 'getCustomerAddressId',
'__wakeup', 'getAddressType', 'getDeleteImmediately', 'validateMinimumAmount', 'setData'
@@ -165,21 +165,21 @@ protected function setUp()
false
);
$this->quoteAddressCollectionMock = $this->getMock(
- 'Magento\Quote\Model\ResourceModel\Quote\Address\Collection',
+ \Magento\Quote\Model\ResourceModel\Quote\Address\Collection::class,
[],
[],
'',
false
);
$this->extensibleDataObjectConverterMock = $this->getMock(
- 'Magento\Framework\Api\ExtensibleDataObjectConverter',
+ \Magento\Framework\Api\ExtensibleDataObjectConverter::class,
['toFlatArray'],
[],
'',
false
);
$this->customerRepositoryMock = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\CustomerRepositoryInterface',
+ \Magento\Customer\Api\CustomerRepositoryInterface::class,
[],
'',
false,
@@ -188,14 +188,14 @@ protected function setUp()
['getById', 'save']
);
$this->objectCopyServiceMock = $this->getMock(
- 'Magento\Framework\DataObject\Copy',
+ \Magento\Framework\DataObject\Copy::class,
['copyFieldsetToTarget'],
[],
'',
false
);
- $this->productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false);
- $this->objectFactoryMock = $this->getMock('\Magento\Framework\DataObject\Factory', ['create'], [], '', false);
+ $this->productMock = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false);
+ $this->objectFactoryMock = $this->getMock(\Magento\Framework\DataObject\Factory::class, ['create'], [], '', false);
$this->quoteAddressFactoryMock->expects(
$this->any()
)->method(
@@ -210,76 +210,76 @@ protected function setUp()
)->will(
$this->returnValue($this->quoteAddressCollectionMock)
);
- $this->eventManagerMock = $this->getMockBuilder('Magento\Framework\Event\Manager')
+ $this->eventManagerMock = $this->getMockBuilder(\Magento\Framework\Event\Manager::class)
->disableOriginalConstructor()
->getMock();
- $this->storeManagerMock = $this->getMockBuilder('Magento\Store\Model\StoreManager')
+ $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManager::class)
->disableOriginalConstructor()
->getMock();
- $this->resourceMock = $this->getMockBuilder('Magento\Quote\Model\ResourceModel\Quote')
+ $this->resourceMock = $this->getMockBuilder(\Magento\Quote\Model\ResourceModel\Quote::class)
->disableOriginalConstructor()
->getMock();
- $this->contextMock = $this->getMockBuilder('Magento\Framework\Model\Context')
+ $this->contextMock = $this->getMockBuilder(\Magento\Framework\Model\Context::class)
->disableOriginalConstructor()
->getMock();
- $this->customerFactoryMock = $this->getMockBuilder('Magento\Customer\Model\CustomerFactory')
+ $this->customerFactoryMock = $this->getMockBuilder(\Magento\Customer\Model\CustomerFactory::class)
->disableOriginalConstructor()
->setMethods(['create'])
->getMock();
- $this->groupRepositoryMock = $this->getMockBuilder('Magento\Customer\Api\GroupRepositoryInterface')
+ $this->groupRepositoryMock = $this->getMockBuilder(\Magento\Customer\Api\GroupRepositoryInterface::class)
->disableOriginalConstructor()
->getMock();
$this->contextMock->expects($this->any())
->method('getEventDispatcher')
->will($this->returnValue($this->eventManagerMock));
$this->quoteItemCollectionFactoryMock = $this->getMock(
- 'Magento\Quote\Model\ResourceModel\Quote\Item\CollectionFactory',
+ \Magento\Quote\Model\ResourceModel\Quote\Item\CollectionFactory::class,
['create'],
[],
'',
false
);
$this->quotePaymentCollectionFactoryMock = $this->getMock(
- 'Magento\Quote\Model\ResourceModel\Quote\Payment\CollectionFactory',
+ \Magento\Quote\Model\ResourceModel\Quote\Payment\CollectionFactory::class,
['create'],
[],
'',
false
);
$this->paymentFactoryMock = $this->getMock(
- 'Magento\Quote\Model\Quote\PaymentFactory',
+ \Magento\Quote\Model\Quote\PaymentFactory::class,
['create'],
[],
'',
false
);
- $this->scopeConfig = $this->getMockBuilder('Magento\Framework\App\Config')
+ $this->scopeConfig = $this->getMockBuilder(\Magento\Framework\App\Config::class)
->disableOriginalConstructor()
->getMock();
- $this->addressRepositoryMock = $this->getMockForAbstractClass('Magento\Customer\Api\AddressRepositoryInterface',
+ $this->addressRepositoryMock = $this->getMockForAbstractClass(\Magento\Customer\Api\AddressRepositoryInterface::class,
[],
'',
false
);
- $this->criteriaBuilderMock = $this->getMockBuilder('Magento\Framework\Api\SearchCriteriaBuilder')
+ $this->criteriaBuilderMock = $this->getMockBuilder(\Magento\Framework\Api\SearchCriteriaBuilder::class)
->disableOriginalConstructor()
->getMock();
- $this->filterBuilderMock = $this->getMockBuilder('Magento\Framework\Api\FilterBuilder')
+ $this->filterBuilderMock = $this->getMockBuilder(\Magento\Framework\Api\FilterBuilder::class)
->disableOriginalConstructor()
->getMock();
$this->extensionAttributesJoinProcessorMock = $this->getMock(
- 'Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface',
+ \Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface::class,
[],
[],
'',
false
);
$this->customerDataFactoryMock = $this->getMock(
- 'Magento\Customer\Api\Data\CustomerInterfaceFactory',
+ \Magento\Customer\Api\Data\CustomerInterfaceFactory::class,
['create'],
[],
'',
@@ -287,7 +287,7 @@ protected function setUp()
);
$this->quote = (new ObjectManager($this))
->getObject(
- 'Magento\Quote\Model\Quote',
+ \Magento\Quote\Model\Quote::class,
[
'quoteAddressFactory' => $this->quoteAddressFactoryMock,
'storeManager' => $this->storeManagerMock,
@@ -386,7 +386,7 @@ public function dataProviderForTestIsMultipleShippingAddresses()
protected function getAddressMock($type)
{
$shippingAddressMock = $this->getMock(
- 'Magento\Quote\Model\Quote\Address',
+ \Magento\Quote\Model\Quote\Address::class,
['getAddressType', '__wakeup'],
[],
'',
@@ -400,7 +400,7 @@ protected function getAddressMock($type)
public function testGetStoreIdNoId()
{
- $storeMock = $this->getMockBuilder('Magento\Store\Model\Store')
+ $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class)
->disableOriginalConstructor()
->getMock();
$storeMock->expects($this->once())
@@ -426,7 +426,7 @@ public function testGetStore()
{
$storeId = 1;
- $storeMock = $this->getMockBuilder('Magento\Store\Model\Store')
+ $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class)
->disableOriginalConstructor()
->getMock();
$this->storeManagerMock->expects($this->once())
@@ -436,14 +436,14 @@ public function testGetStore()
$this->quote->setStoreId($storeId);
$result = $this->quote->getStore();
- $this->assertInstanceOf('Magento\Store\Model\Store', $result);
+ $this->assertInstanceOf(\Magento\Store\Model\Store::class, $result);
}
public function testSetStore()
{
$storeId = 1;
- $storeMock = $this->getMockBuilder('Magento\Store\Model\Store')
+ $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class)
->disableOriginalConstructor()
->getMock();
$storeMock->expects($this->once())
@@ -451,7 +451,7 @@ public function testSetStore()
->will($this->returnValue($storeId));
$result = $this->quote->setStore($storeMock);
- $this->assertInstanceOf('Magento\Quote\Model\Quote', $result);
+ $this->assertInstanceOf(\Magento\Quote\Model\Quote::class, $result);
}
public function testGetSharedWebsiteStoreIds()
@@ -459,7 +459,7 @@ public function testGetSharedWebsiteStoreIds()
$sharedIds = null;
$storeIds = [1, 2, 3];
- $websiteMock = $this->getMockBuilder('Magento\Store\Model\Website')
+ $websiteMock = $this->getMockBuilder(\Magento\Store\Model\Website::class)
->disableOriginalConstructor()
->getMock();
$websiteMock->expects($this->once())
@@ -478,14 +478,14 @@ public function testGetSharedStoreIds()
$storeIds = [1, 2, 3];
$storeId = 1;
- $websiteMock = $this->getMockBuilder('Magento\Store\Model\Website')
+ $websiteMock = $this->getMockBuilder(\Magento\Store\Model\Website::class)
->disableOriginalConstructor()
->getMock();
$websiteMock->expects($this->once())
->method('getStoreIds')
->will($this->returnValue($storeIds));
- $storeMock = $this->getMockBuilder('Magento\Store\Model\Store')
+ $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class)
->disableOriginalConstructor()
->getMock();
$storeMock->expects($this->once())
@@ -515,7 +515,7 @@ public function testLoadActive()
->method('dispatch');
$result = $this->quote->loadActive($quoteId);
- $this->assertInstanceOf('Magento\Quote\Model\Quote', $result);
+ $this->assertInstanceOf(\Magento\Quote\Model\Quote::class, $result);
}
public function testloadByIdWithoutStore()
@@ -530,7 +530,7 @@ public function testloadByIdWithoutStore()
->method('dispatch');
$result = $this->quote->loadByIdWithoutStore($quoteId);
- $this->assertInstanceOf('Magento\Quote\Model\Quote', $result);
+ $this->assertInstanceOf(\Magento\Quote\Model\Quote::class, $result);
}
/**
@@ -540,7 +540,7 @@ public function testSetCustomerAddressData()
{
$customerId = 1;
$addressMock = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\Data\AddressInterface',
+ \Magento\Customer\Api\Data\AddressInterface::class,
[],
'',
false,
@@ -554,15 +554,15 @@ public function testSetCustomerAddressData()
$addresses = [$addressMock];
- $customerMock = $this->getMockForAbstractClass('Magento\Customer\Api\Data\CustomerInterface', [], '', false);
+ $customerMock = $this->getMockForAbstractClass(\Magento\Customer\Api\Data\CustomerInterface::class, [], '', false);
$customerResultMock = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\Data\CustomerInterface',
+ \Magento\Customer\Api\Data\CustomerInterface::class,
[],
'',
false
);
$requestMock = $this->getMock(
- '\Magento\Framework\DataObject'
+ \Magento\Framework\DataObject::class
);
$this->extensibleDataObjectConverterMock->expects($this->any())
@@ -586,7 +586,7 @@ public function testSetCustomerAddressData()
->with($this->equalTo(['customer_id' => $customerId]))
->will($this->returnValue($requestMock));
$result = $this->quote->setCustomerAddressData([$addressMock]);
- $this->assertInstanceOf('Magento\Quote\Model\Quote', $result);
+ $this->assertInstanceOf(\Magento\Quote\Model\Quote::class, $result);
$this->assertEquals($customerResultMock, $this->quote->getCustomer());
}
@@ -594,7 +594,7 @@ public function testGetCustomerTaxClassId()
{
$groupId = 1;
$taxClassId = 1;
- $groupMock = $this->getMockForAbstractClass('Magento\Customer\Api\Data\GroupInterface', [], '', false);
+ $groupMock = $this->getMockForAbstractClass(\Magento\Customer\Api\Data\GroupInterface::class, [], '', false);
$groupMock->expects($this->once())
->method('getTaxClassId')
->willReturn($taxClassId);
@@ -774,7 +774,7 @@ public function testRemoveAddress()
$this->quote->setId($id);
$result = $this->quote->removeAddress($id);
- $this->assertInstanceOf('Magento\Quote\Model\Quote', $result);
+ $this->assertInstanceOf(\Magento\Quote\Model\Quote::class, $result);
}
public function testRemoveAllAddresses()
@@ -817,7 +817,7 @@ public function testRemoveAllAddresses()
$this->quote->setId($id);
$result = $this->quote->removeAllAddresses();
- $this->assertInstanceOf('Magento\Quote\Model\Quote', $result);
+ $this->assertInstanceOf(\Magento\Quote\Model\Quote::class, $result);
}
/**
@@ -832,15 +832,19 @@ public function testAddProductNoCandidates()
{
$expectedResult = 'test_string';
$requestMock = $this->getMock(
- '\Magento\Framework\DataObject'
+ \Magento\Framework\DataObject::class
);
$this->objectFactoryMock->expects($this->once())
->method('create')
->with($this->equalTo(['qty' => 1]))
->will($this->returnValue($requestMock));
-
+
+ $this->productMock->expects($this->once())
+ ->method('isSalable')
+ ->willReturn(true);
+
$typeInstanceMock = $this->getMock(
- 'Magento\Catalog\Model\Product\Type\Simple',
+ \Magento\Catalog\Model\Product\Type\Simple::class,
[
'prepareForCartAdvanced'
],
@@ -862,7 +866,7 @@ public function testAddProductNoCandidates()
public function testAddProductItemPreparation()
{
$itemMock = $this->getMock(
- '\Magento\Quote\Model\Quote\Item',
+ \Magento\Quote\Model\Quote\Item::class,
[],
[],
'',
@@ -871,7 +875,7 @@ public function testAddProductItemPreparation()
$expectedResult = $itemMock;
$requestMock = $this->getMock(
- '\Magento\Framework\DataObject'
+ \Magento\Framework\DataObject::class
);
$this->objectFactoryMock->expects($this->once())
->method('create')
@@ -879,7 +883,7 @@ public function testAddProductItemPreparation()
->will($this->returnValue($requestMock));
$typeInstanceMock = $this->getMock(
- 'Magento\Catalog\Model\Product\Type\Simple',
+ \Magento\Catalog\Model\Product\Type\Simple::class,
[
'prepareForCartAdvanced'
],
@@ -889,7 +893,7 @@ public function testAddProductItemPreparation()
);
$productMock = $this->getMock(
- 'Magento\Catalog\Model\Product',
+ \Magento\Catalog\Model\Product::class,
[
'getParentProductId',
'setStickWithinParent',
@@ -901,7 +905,7 @@ public function testAddProductItemPreparation()
);
$collectionMock = $this->getMock(
- 'Magento\Quote\Model\ResourceModel\Quote\Item\Collection',
+ \Magento\Quote\Model\ResourceModel\Quote\Item\Collection::class,
[],
[],
'',
@@ -920,6 +924,10 @@ public function testAddProductItemPreparation()
$this->quoteItemCollectionFactoryMock->expects($this->once())
->method('create')
->will($this->returnValue($collectionMock));
+
+ $this->productMock->expects($this->once())
+ ->method('isSalable')
+ ->willReturn(true);
$typeInstanceMock->expects($this->once())
->method('prepareForCartAdvanced')
@@ -988,7 +996,7 @@ public function testGetPaymentIsNotDeleted()
{
$this->quote->setId(1);
$payment = $this->getMock(
- 'Magento\Quote\Model\Quote\Payment',
+ \Magento\Quote\Model\Quote\Payment::class,
['setQuote', 'isDeleted', '__wakeup'],
[],
'',
@@ -1000,7 +1008,7 @@ public function testGetPaymentIsNotDeleted()
->method('isDeleted')
->willReturn(false);
$quotePaymentCollectionMock = $this->getMock(
- 'Magento\Quote\Model\ResourceModel\Quote\Payment\Collection',
+ \Magento\Quote\Model\ResourceModel\Quote\Payment\Collection::class,
['setQuoteFilter', 'getFirstItem'],
[],
'',
@@ -1017,14 +1025,14 @@ public function testGetPaymentIsNotDeleted()
->method('create')
->willReturn($quotePaymentCollectionMock);
- $this->assertInstanceOf('\Magento\Quote\Model\Quote\Payment', $this->quote->getPayment());
+ $this->assertInstanceOf(\Magento\Quote\Model\Quote\Payment::class, $this->quote->getPayment());
}
public function testGetPaymentIsDeleted()
{
$this->quote->setId(1);
$payment = $this->getMock(
- 'Magento\Quote\Model\Quote\Payment',
+ \Magento\Quote\Model\Quote\Payment::class,
['setQuote', 'isDeleted', 'getId', '__wakeup'],
[],
'',
@@ -1039,7 +1047,7 @@ public function testGetPaymentIsDeleted()
->method('getId')
->willReturn(1);
$quotePaymentCollectionMock = $this->getMock(
- 'Magento\Quote\Model\ResourceModel\Quote\Payment\Collection',
+ \Magento\Quote\Model\ResourceModel\Quote\Payment\Collection::class,
['setQuoteFilter', 'getFirstItem'],
[],
'',
@@ -1060,19 +1068,19 @@ public function testGetPaymentIsDeleted()
->method('create')
->willReturn($payment);
- $this->assertInstanceOf('\Magento\Quote\Model\Quote\Payment', $this->quote->getPayment());
+ $this->assertInstanceOf(\Magento\Quote\Model\Quote\Payment::class, $this->quote->getPayment());
}
public function testAddItem()
{
- $item = $this->getMock('Magento\Quote\Model\Quote\Item', ['setQuote', 'getId'], [], '', false);
+ $item = $this->getMock(\Magento\Quote\Model\Quote\Item::class, ['setQuote', 'getId'], [], '', false);
$item->expects($this->once())
->method('setQuote');
$item->expects($this->once())
->method('getId')
->willReturn(false);
$itemsMock = $this->getMock(
- 'Magento\Eav\Model\Entity\Collection\AbstractCollection',
+ \Magento\Eav\Model\Entity\Collection\AbstractCollection::class,
['setQuote', 'addItem'],
[],
'',
@@ -1100,7 +1108,7 @@ public function testAddItem()
public function testBeforeSaveIsVirtualQuote(array $productTypes, $expected)
{
$storeId = 1;
- $currencyMock = $this->getMockBuilder('Magento\Directory\Model\Currency')
+ $currencyMock = $this->getMockBuilder(\Magento\Directory\Model\Currency::class)
->disableOriginalConstructor()
->getMock();
$currencyMock->expects($this->any())
@@ -1109,7 +1117,7 @@ public function testBeforeSaveIsVirtualQuote(array $productTypes, $expected)
$currencyMock->expects($this->any())
->method('getRate')
->will($this->returnValue('test_rate'));
- $storeMock = $this->getMockBuilder('Magento\Store\Model\Store')
+ $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class)
->disableOriginalConstructor()
->getMock();
$storeMock->expects($this->once())
@@ -1126,7 +1134,7 @@ public function testBeforeSaveIsVirtualQuote(array $productTypes, $expected)
$this->quote->setStoreId($storeId);
$collectionMock = $this->getMock(
- 'Magento\Quote\Model\ResourceModel\Quote\Item\Collection',
+ \Magento\Quote\Model\ResourceModel\Quote\Item\Collection::class,
[],
[],
'',
@@ -1134,11 +1142,11 @@ public function testBeforeSaveIsVirtualQuote(array $productTypes, $expected)
);
$items = [];
foreach ($productTypes as $type) {
- $productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false);
+ $productMock = $this->getMock(\Magento\Catalog\Model\Product::class, [], [], '', false);
$productMock->expects($this->any())->method('getIsVirtual')->willReturn($type);
$itemMock = $this->getMock(
- 'Magento\Quote\Model\Quote\Item',
+ \Magento\Quote\Model\Quote\Item::class,
['isDeleted', 'getParentItemId', 'getProduct'],
[],
'',
@@ -1183,7 +1191,7 @@ public function dataProviderForTestBeforeSaveIsVirtualQuote()
public function testGetItemsCollection()
{
- $itemCollectionMock = $this->getMockBuilder('Magento\Quote\Model\ResourceModel\Quote\Collection')
+ $itemCollectionMock = $this->getMockBuilder(\Magento\Quote\Model\ResourceModel\Quote\Collection::class)
->disableOriginalConstructor()
->setMethods(['setQuote'])
->getMock();
@@ -1194,7 +1202,7 @@ public function testGetItemsCollection()
$this->extensionAttributesJoinProcessorMock->expects($this->once())
->method('process')
->with(
- $this->isInstanceOf('Magento\Quote\Model\ResourceModel\Quote\Collection')
+ $this->isInstanceOf(\Magento\Quote\Model\ResourceModel\Quote\Collection::class)
);
$itemCollectionMock->expects($this->once())->method('setQuote')->with($this->quote);
@@ -1203,7 +1211,7 @@ public function testGetItemsCollection()
public function testGetAllItems()
{
- $itemOneMock = $this->getMockBuilder('Magento\Quote\Model\ResourceModel\Quote\Item')
+ $itemOneMock = $this->getMockBuilder(\Magento\Quote\Model\ResourceModel\Quote\Item::class)
->setMethods(['isDeleted'])
->disableOriginalConstructor()
->getMock();
@@ -1211,7 +1219,7 @@ public function testGetAllItems()
->method('isDeleted')
->willReturn(false);
- $itemTwoMock = $this->getMockBuilder('Magento\Quote\Model\ResourceModel\Quote\Item')
+ $itemTwoMock = $this->getMockBuilder(\Magento\Quote\Model\ResourceModel\Quote\Item::class)
->setMethods(['isDeleted'])
->disableOriginalConstructor()
->getMock();
diff --git a/app/code/Magento/Quote/composer.json b/app/code/Magento/Quote/composer.json
index 6ec106d49c93c..bd5a1359df322 100644
--- a/app/code/Magento/Quote/composer.json
+++ b/app/code/Magento/Quote/composer.json
@@ -20,7 +20,7 @@
"magento/framework": "100.1.*"
},
"type": "magento2-module",
- "version": "100.1.4",
+ "version": "100.1.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Quote/etc/module.xml b/app/code/Magento/Quote/etc/module.xml
index f706b31daf21a..337117181e444 100644
--- a/app/code/Magento/Quote/etc/module.xml
+++ b/app/code/Magento/Quote/etc/module.xml
@@ -6,6 +6,6 @@
*/
-->
-
+
diff --git a/app/code/Magento/Reports/composer.json b/app/code/Magento/Reports/composer.json
index 7ad926bf489e5..dc5f421f84961 100644
--- a/app/code/Magento/Reports/composer.json
+++ b/app/code/Magento/Reports/composer.json
@@ -22,7 +22,7 @@
"magento/framework": "100.1.*"
},
"type": "magento2-module",
- "version": "100.1.3",
+ "version": "100.1.4",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php b/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php
index c738aa172978d..3879b3cabcc6a 100644
--- a/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php
+++ b/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php
@@ -602,7 +602,9 @@ public function getBindArgumentValue()
*/
public function getMappedSqlField()
{
- if (!$this->isAttributeSetOrCategory()) {
+ if ($this->getAttribute() == 'sku') {
+ $mappedSqlField = 'e.sku';
+ } elseif (!$this->isAttributeSetOrCategory()) {
$mappedSqlField = $this->getEavAttributeTableAlias() . '.value';
} elseif ($this->getAttribute() == 'category_ids') {
$mappedSqlField = 'e.entity_id';
diff --git a/app/code/Magento/Rule/composer.json b/app/code/Magento/Rule/composer.json
index c7bc9fbf77db5..7b6889b9d1a11 100644
--- a/app/code/Magento/Rule/composer.json
+++ b/app/code/Magento/Rule/composer.json
@@ -11,7 +11,7 @@
"lib-libxml": "*"
},
"type": "magento2-module",
- "version": "100.1.4",
+ "version": "100.1.5",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Sales/Block/Order/Items.php b/app/code/Magento/Sales/Block/Order/Items.php
index 2b908d01b36d5..7cbecd76d6296 100644
--- a/app/code/Magento/Sales/Block/Order/Items.php
+++ b/app/code/Magento/Sales/Block/Order/Items.php
@@ -14,28 +14,116 @@
class Items extends \Magento\Sales\Block\Items\AbstractItems
{
/**
- * Core registry
+ * Core registry.
*
* @var \Magento\Framework\Registry
*/
protected $_coreRegistry = null;
+ /**
+ * Order items per page.
+ *
+ * @var int
+ */
+ private $itemsPerPage;
+
+ /**
+ * Sales order item collection factory.
+ *
+ * @var \Magento\Sales\Model\ResourceModel\Order\Item\CollectionFactory
+ */
+ private $itemCollectionFactory;
+
+ /**
+ * Sales order item collection.
+ *
+ * @var \Magento\Sales\Model\ResourceModel\Order\Item\Collection|null
+ */
+ private $itemCollection;
+
/**
* @param \Magento\Framework\View\Element\Template\Context $context
* @param \Magento\Framework\Registry $registry
* @param array $data
+ * @param \Magento\Sales\Model\ResourceModel\Order\Item\CollectionFactory|null $itemCollectionFactory
*/
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
\Magento\Framework\Registry $registry,
- array $data = []
+ array $data = [],
+ \Magento\Sales\Model\ResourceModel\Order\Item\CollectionFactory $itemCollectionFactory = null
) {
$this->_coreRegistry = $registry;
+ $this->itemCollectionFactory = $itemCollectionFactory ?: \Magento\Framework\App\ObjectManager::getInstance()
+ ->get(\Magento\Sales\Model\ResourceModel\Order\Item\CollectionFactory::class);
parent::__construct($context, $data);
}
/**
- * Retrieve current order model instance
+ * Init pager block and item collection with page size and current page number.
+ *
+ * @return $this
+ */
+ protected function _prepareLayout()
+ {
+ $this->itemsPerPage = $this->_scopeConfig->getValue('sales/orders/items_per_page');
+
+ $this->itemCollection = $this->itemCollectionFactory->create();
+ $this->itemCollection->setOrderFilter($this->getOrder());
+ $this->itemCollection->filterByParent(null);
+
+ /** @var \Magento\Theme\Block\Html\Pager $pagerBlock */
+ $pagerBlock = $this->getChildBlock('sales_order_item_pager');
+ if ($pagerBlock) {
+ $pagerBlock->setLimit($this->itemsPerPage);
+ //here pager updates collection parameters
+ $pagerBlock->setCollection($this->itemCollection);
+ $pagerBlock->setAvailableLimit([$this->itemsPerPage]);
+ $pagerBlock->setShowAmounts($this->isPagerDisplayed());
+ }
+
+ return parent::_prepareLayout();
+ }
+
+ /**
+ * Determine if the pager should be displayed for order items list.
+ * To be called from templates(after _prepareLayout()).
+ *
+ * @return bool
+ */
+ public function isPagerDisplayed()
+ {
+ $pagerBlock = $this->getChildBlock('sales_order_item_pager');
+
+ return $pagerBlock && ($this->itemCollection->getSize() > $this->itemsPerPage);
+ }
+
+ /**
+ * Get visible items for current page.
+ * To be called from templates(after _prepareLayout()).
+ *
+ * @return \Magento\Framework\DataObject[]
+ */
+ public function getItems()
+ {
+ return $this->itemCollection->getItems();
+ }
+
+ /**
+ * Get pager HTML according to our requirements.
+ * To be called from templates(after _prepareLayout()).
+ *
+ * @return string HTML output
+ */
+ public function getPagerHtml()
+ {
+ /** @var \Magento\Theme\Block\Html\Pager $pagerBlock */
+ $pagerBlock = $this->getChildBlock('sales_order_item_pager');
+ return $pagerBlock ? $pagerBlock->toHtml() : '';
+ }
+
+ /**
+ * Retrieve current order model instance.
*
* @return \Magento\Sales\Model\Order
*/
diff --git a/app/code/Magento/Sales/CustomerData/LastOrderedItems.php b/app/code/Magento/Sales/CustomerData/LastOrderedItems.php
index df510552010fe..ac354535baada 100644
--- a/app/code/Magento/Sales/CustomerData/LastOrderedItems.php
+++ b/app/code/Magento/Sales/CustomerData/LastOrderedItems.php
@@ -7,10 +7,15 @@
use Magento\Customer\CustomerData\SectionSourceInterface;
+/**
+ * Returns information for "Recently Ordered" widget.
+ * It contains limited list of salable products from the last placed order.
+ * Qty of products to display is limited by LastOrderedItems::SIDEBAR_ORDER_LIMIT constant.
+ */
class LastOrderedItems implements SectionSourceInterface
{
/**
- * Limit of orders in side bar
+ * Limit of orders in side bar.
*/
const SIDEBAR_ORDER_LIMIT = 5;
@@ -44,6 +49,13 @@ class LastOrderedItems implements SectionSourceInterface
*/
protected $stockRegistry;
+ /**
+ * Store manager interface.
+ *
+ * @var \Magento\Store\Model\StoreManagerInterface
+ */
+ private $_storeManager;
+
/**
* @param \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory
* @param \Magento\Sales\Model\Order\Config $orderConfig
@@ -66,7 +78,7 @@ public function __construct(
}
/**
- * Init customer order for display on front
+ * Init last placed customer order to display on front.
*
* @return void
*/
@@ -96,8 +108,9 @@ protected function getItems()
if ($order) {
$website = $this->_storeManager->getStore()->getWebsiteId();
+ /** @var \Magento\Sales\Model\Order\Item $item */
foreach ($order->getParentItemsRandomCollection($limit) as $item) {
- if ($item->getProduct() && in_array($website, $item->getProduct()->getWebsiteIds())) {
+ if ($item->hasData('product') && in_array($website, $item->getProduct()->getWebsiteIds())) {
$items[] = [
'id' => $item->getId(),
'name' => $item->getName(),
diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php
index a97d486af4447..49d723f8906e8 100644
--- a/app/code/Magento/Sales/Model/AdminOrder/Create.php
+++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php
@@ -608,7 +608,7 @@ public function initFromOrderItem(\Magento\Sales\Model\Order\Item $orderItem, $q
}
$product = $this->_objectManager->create(
- 'Magento\Catalog\Model\Product'
+ \Magento\Catalog\Model\Product::class
)->setStoreId(
$this->getSession()->getStoreId()
)->load(
@@ -662,7 +662,7 @@ public function getCustomerWishlist($cacheReload = false)
$customerId = (int)$this->getSession()->getCustomerId();
if ($customerId) {
- $this->_wishlist = $this->_objectManager->create('Magento\Wishlist\Model\Wishlist');
+ $this->_wishlist = $this->_objectManager->create(\Magento\Wishlist\Model\Wishlist::class);
$this->_wishlist->loadByCustomerId($customerId, true);
$this->_wishlist->setStore(
$this->getSession()->getStore()
@@ -716,7 +716,9 @@ public function getCustomerCompareList()
}
$customerId = (int)$this->getSession()->getCustomerId();
if ($customerId) {
- $this->_compareList = $this->_objectManager->create('Magento\Catalog\Model\Product\Compare\ListCompare');
+ $this->_compareList = $this->_objectManager->create(
+ \Magento\Catalog\Model\Product\Compare\ListCompare::class
+ );
} else {
$this->_compareList = false;
}
@@ -762,7 +764,7 @@ public function moveQuoteItem($item, $moveTo, $qty)
$info->setOptions($this->_prepareOptionsForRequest($item))->setQty($qty);
$product = $this->_objectManager->create(
- 'Magento\Catalog\Model\Product'
+ \Magento\Catalog\Model\Product::class
)->setStoreId(
$this->getQuote()->getStoreId()
)->load(
@@ -784,7 +786,7 @@ public function moveQuoteItem($item, $moveTo, $qty)
if ($cart && is_null($item->getOptionByCode('additional_options'))) {
//options and info buy request
$product = $this->_objectManager->create(
- 'Magento\Catalog\Model\Product'
+ \Magento\Catalog\Model\Product::class
)->setStoreId(
$this->getQuote()->getStoreId()
)->load(
@@ -819,13 +821,17 @@ public function moveQuoteItem($item, $moveTo, $qty)
$wishlist = null;
if (!isset($moveTo[1])) {
$wishlist = $this->_objectManager->create(
- 'Magento\Wishlist\Model\Wishlist'
+ \Magento\Wishlist\Model\Wishlist::class
)->loadByCustomerId(
$this->getSession()->getCustomerId(),
true
);
} else {
- $wishlist = $this->_objectManager->create('Magento\Wishlist\Model\Wishlist')->load($moveTo[1]);
+ $wishlist = $this->_objectManager->create(
+ \Magento\Wishlist\Model\Wishlist::class
+ )
+ ->load($moveTo[1]);
+
if (!$wishlist->getId() || $wishlist->getCustomerId() != $this->getSession()->getCustomerId()
) {
$wishlist = null;
@@ -885,7 +891,7 @@ public function applySidebarData($data)
if (isset($data['add_order_item'])) {
foreach ($data['add_order_item'] as $orderItemId => $value) {
/* @var $orderItem \Magento\Sales\Model\Order\Item */
- $orderItem = $this->_objectManager->create('Magento\Sales\Model\Order\Item')->load($orderItemId);
+ $orderItem = $this->_objectManager->create(\Magento\Sales\Model\Order\Item::class)->load($orderItemId);
$item = $this->initFromOrderItem($orderItem);
if (is_string($item)) {
throw new \Magento\Framework\Exception\LocalizedException(__($item));
@@ -904,7 +910,7 @@ public function applySidebarData($data)
if (isset($data['add_wishlist_item'])) {
foreach ($data['add_wishlist_item'] as $itemId => $qty) {
$item = $this->_objectManager->create(
- 'Magento\Wishlist\Model\Item'
+ \Magento\Wishlist\Model\Item::class
)->loadWithOptions(
$itemId,
'info_buyRequest'
@@ -957,12 +963,15 @@ public function removeItem($itemId, $from)
case 'wishlist':
$wishlist = $this->getCustomerWishlist();
if ($wishlist) {
- $item = $this->_objectManager->create('Magento\Wishlist\Model\Item')->load($itemId);
+ $item = $this->_objectManager->create(\Magento\Wishlist\Model\Item::class)->load($itemId);
$item->delete();
}
break;
case 'compared':
- $this->_objectManager->create('Magento\Catalog\Model\Product\Compare\Item')->load($itemId)->delete();
+ $this->_objectManager->create(
+ \Magento\Catalog\Model\Product\Compare\Item::class
+ )
+ ->load($itemId)->delete();
break;
}
@@ -1003,7 +1012,7 @@ public function addProduct($product, $config = 1)
if (!$product instanceof \Magento\Catalog\Model\Product) {
$productId = $product;
$product = $this->_objectManager->create(
- 'Magento\Catalog\Model\Product'
+ \Magento\Catalog\Model\Product::class
)->setStore(
$this->getSession()->getStore()
)->setStoreId(
@@ -1103,7 +1112,7 @@ public function updateQuoteItems($items)
protected function _parseOptions(\Magento\Quote\Model\Quote\Item $item, $additionalOptions)
{
$productOptions = $this->_objectManager->get(
- 'Magento\Catalog\Model\Product\Option\Type\DefaultType'
+ \Magento\Catalog\Model\Product\Option\Type\DefaultType::class
)->setProduct(
$item->getProduct()
)->getProductOptions();
@@ -1115,11 +1124,15 @@ protected function _parseOptions(\Magento\Quote\Model\Quote\Item $item, $additio
if (strlen(trim($_additionalOption))) {
try {
if (strpos($_additionalOption, ':') === false) {
- throw new \Magento\Framework\Exception\LocalizedException(__('There is an error in one of the option rows.'));
+ throw new \Magento\Framework\Exception\LocalizedException(
+ __('There is an error in one of the option rows.')
+ );
}
list($label, $value) = explode(':', $_additionalOption, 2);
} catch (\Exception $e) {
- throw new \Magento\Framework\Exception\LocalizedException(__('There is an error in one of the option rows.'));
+ throw new \Magento\Framework\Exception\LocalizedException(
+ __('There is an error in one of the option rows.')
+ );
}
$label = trim($label);
$value = trim($value);
@@ -1132,7 +1145,7 @@ protected function _parseOptions(\Magento\Quote\Model\Quote\Item $item, $additio
$option = $item->getProduct()->getOptionById($optionId);
$group = $this->_objectManager->get(
- 'Magento\Catalog\Model\Product\Option'
+ \Magento\Catalog\Model\Product\Option::class
)->groupFactory(
$option->getType()
)->setOption(
@@ -1231,7 +1244,7 @@ protected function _prepareOptionsForRequest($item)
$optionValue = $item->getOptionByCode('option_' . $optionId)->getValue();
$group = $this->_objectManager->get(
- 'Magento\Catalog\Model\Product\Option'
+ \Magento\Catalog\Model\Product\Option::class
)->groupFactory(
$option->getType()
)->setOption(
@@ -1255,7 +1268,7 @@ protected function _prepareOptionsForRequest($item)
*/
protected function _parseCustomPrice($price)
{
- $price = $this->_objectManager->get('Magento\Framework\Locale\FormatInterface')->getNumber($price);
+ $price = $this->_objectManager->get(\Magento\Framework\Locale\FormatInterface::class)->getNumber($price);
$price = $price > 0 ? $price : 0;
return $price;
@@ -1360,7 +1373,7 @@ public function setShippingAddress($address)
{
if (is_array($address)) {
$shippingAddress = $this->_objectManager->create(
- 'Magento\Quote\Model\Quote\Address'
+ \Magento\Quote\Model\Quote\Address::class
)->setData(
$address
)->setAddressType(
@@ -1428,7 +1441,7 @@ public function setBillingAddress($address)
{
if (is_array($address)) {
$billingAddress = $this->_objectManager->create(
- 'Magento\Quote\Model\Quote\Address'
+ \Magento\Quote\Model\Quote\Address::class
)->setData(
$address
)->setAddressType(
@@ -1543,6 +1556,11 @@ public function setPaymentData($data)
public function applyCoupon($code)
{
$code = trim((string)$code);
+ $this->getQuote()->getShippingAddress()->setCollectShippingRates(true);
+
+ if (empty($code)) {
+ $this->getQuote()->getShippingAddress()->setFreeShipping(null);
+ }
$this->getQuote()->setCouponCode($code);
$this->setRecollect(true);
@@ -1568,7 +1586,7 @@ public function setAccountData($accountData)
$this->dataObjectHelper->populateWithArray(
$customer,
$data,
- '\Magento\Customer\Api\Data\CustomerInterface'
+ \Magento\Customer\Api\Data\CustomerInterface::class
);
$this->getQuote()->updateCustomerData($customer);
$data = [];
@@ -1690,7 +1708,7 @@ protected function _validateCustomerData(\Magento\Customer\Api\Data\CustomerInte
$this->dataObjectHelper->populateWithArray(
$customer,
$data,
- '\Magento\Customer\Api\Data\CustomerInterface'
+ \Magento\Customer\Api\Data\CustomerInterface::class
);
return $customer;
}
diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php
index 1b6c53482909e..09e03dca659cb 100644
--- a/app/code/Magento/Sales/Model/Order.php
+++ b/app/code/Magento/Sales/Model/Order.php
@@ -184,6 +184,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface
/**
* @var \Magento\Catalog\Api\ProductRepositoryInterface
+ * @deprecated Remove unused dependency.
*/
protected $productRepository;
@@ -778,38 +779,24 @@ protected function _canReorder($ignoreSalable = false)
}
$products = [];
- foreach ($this->getItemsCollection() as $item) {
+ $itemsCollection = $this->getItemsCollection();
+ foreach ($itemsCollection as $item) {
$products[] = $item->getProductId();
}
if (!empty($products)) {
- /*
- * @TODO ACPAOC: Use product collection here, but ensure that product
- * is loaded with order store id, otherwise there'll be problems with isSalable()
- * for composite products
- *
- */
- /*
- $productsCollection = $this->_productFactory->create()->getCollection()
+ $productsCollection = $this->productListFactory->create()
->setStoreId($this->getStoreId())
->addIdFilter($products)
->addAttributeToSelect('status')
->load();
- foreach ($productsCollection as $product) {
- if (!$product->isSalable()) {
+ foreach ($itemsCollection as $item) {
+ $product = $productsCollection->getItemById($item->getProductId());
+ if (!$product) {
return false;
}
- }
- */
-
- foreach ($products as $productId) {
- try {
- $product = $this->productRepository->getById($productId, false, $this->getStoreId());
- if (!$ignoreSalable && !$product->isSalable()) {
- return false;
- }
- } catch (NoSuchEntityException $noEntityException) {
+ if (!$ignoreSalable && !$product->isSalable()) {
return false;
}
}
@@ -1451,6 +1438,7 @@ public function setPayment(\Magento\Sales\Api\Data\OrderPaymentInterface $paymen
}
/*********************** STATUSES ***************************/
+
/**
* Return collection of order status history items.
*
@@ -2004,6 +1992,7 @@ public function setExtensionAttributes(\Magento\Sales\Api\Data\OrderExtensionInt
}
//@codeCoverageIgnoreStart
+
/**
* Returns adjustment_negative
*
@@ -4352,5 +4341,6 @@ public function setShippingMethod($shippingMethod)
{
return $this->setData('shipping_method', $shippingMethod);
}
+
//@codeCoverageIgnoreEnd
}
diff --git a/app/code/Magento/Sales/Model/Order/Address/Renderer.php b/app/code/Magento/Sales/Model/Order/Address/Renderer.php
index 515461c1c4b2a..a8214b6eabfa9 100644
--- a/app/code/Magento/Sales/Model/Order/Address/Renderer.php
+++ b/app/code/Magento/Sales/Model/Order/Address/Renderer.php
@@ -48,6 +48,7 @@ public function __construct(
*/
public function format(Address $address, $type)
{
+ $this->addressConfig->setStore($address->getOrder()->getStoreId());
$formatType = $this->addressConfig->getFormatByCode($type);
if (!$formatType || !$formatType->getRenderer()) {
return null;
diff --git a/app/code/Magento/Sales/Model/Order/Payment.php b/app/code/Magento/Sales/Model/Order/Payment.php
index 8b4670b8c11d0..942a34cd73cfa 100644
--- a/app/code/Magento/Sales/Model/Order/Payment.php
+++ b/app/code/Magento/Sales/Model/Order/Payment.php
@@ -1272,7 +1272,7 @@ public function getAuthorizationTransaction()
*/
public function isCaptureFinal($amountToCapture)
{
- $total = $this->getOrder()->getTotalDue();
+ $total = $this->getOrder()->getBaseTotalDue();
return $this->formatAmount($total, true) == $this->formatAmount($amountToCapture, true);
}
diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Payment/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Payment/Collection.php
index d0ad42bee9c99..f4a7414530c58 100644
--- a/app/code/Magento/Sales/Model/ResourceModel/Order/Payment/Collection.php
+++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Payment/Collection.php
@@ -5,7 +5,6 @@
*/
namespace Magento\Sales\Model\ResourceModel\Order\Payment;
-use Magento\Sales\Api\Data\OrderPaymentInterface;
use Magento\Sales\Api\Data\OrderPaymentSearchResultInterface;
use Magento\Sales\Model\ResourceModel\Order\Collection\AbstractCollection;
@@ -68,7 +67,7 @@ protected function _construct()
}
/**
- * Unserialize additional_information in each item
+ * Unserialize additional_information in each item.
*
* @return $this
*/
@@ -76,34 +75,8 @@ protected function _afterLoad()
{
foreach ($this->_items as $item) {
$this->getResource()->unserializeFields($item);
- if (!empty($item->getData(OrderPaymentInterface::ADDITIONAL_INFORMATION))) {
- $additionalInfo = $this->convertAdditionalInfo(
- $item->getData(OrderPaymentInterface::ADDITIONAL_INFORMATION)
- );
- $item->setData(OrderPaymentInterface::ADDITIONAL_INFORMATION, $additionalInfo);
- }
}
- return parent::_afterLoad();
- }
- /**
- * Convert multidimensional additional information array to single
- *
- * @param array $info
- * @return array
- */
- private function convertAdditionalInfo($info)
- {
- $result = [];
- foreach ($info as $key => $item) {
- if (is_array($item)) {
- $result += $this->convertAdditionalInfo($item);
- unset($info[$key]);
- } else {
- $result[$key] = $item;
- }
- }
-
- return $result;
+ return parent::_afterLoad();
}
}
diff --git a/app/code/Magento/Sales/Observer/ConvertAdditionalInfoObserver.php b/app/code/Magento/Sales/Observer/ConvertAdditionalInfoObserver.php
new file mode 100644
index 0000000000000..f2853c30126ec
--- /dev/null
+++ b/app/code/Magento/Sales/Observer/ConvertAdditionalInfoObserver.php
@@ -0,0 +1,80 @@
+state = $state;
+ }
+
+ /**
+ * Convert additional info from multidimensional array into single one for API calls.
+ *
+ * @param Observer $observer
+ * @return void
+ */
+ public function execute(\Magento\Framework\Event\Observer $observer)
+ {
+ /** @var Collection $paymentCollection */
+ $paymentCollection = $observer->getData('order_payment_collection');
+ $areaCode = $this->state->getAreaCode();
+ if ($areaCode == Area::AREA_WEBAPI_REST || $areaCode == Area::AREA_WEBAPI_SOAP) {
+ foreach ($paymentCollection as $payment) {
+ if (!empty($payment->getData(OrderPaymentInterface::ADDITIONAL_INFORMATION))) {
+ $additionalInfo = $this->convertAdditionalInfo(
+ $payment->getData(OrderPaymentInterface::ADDITIONAL_INFORMATION)
+ );
+ $payment->setData(OrderPaymentInterface::ADDITIONAL_INFORMATION, $additionalInfo);
+ }
+ }
+ }
+ }
+
+ /**
+ * Convert multidimensional additional information array to single.
+ *
+ * @param array $info
+ * @return array
+ */
+ private function convertAdditionalInfo($info)
+ {
+ $result = [];
+ foreach ($info as $key => $item) {
+ if (is_array($item)) {
+ $result += $this->convertAdditionalInfo($item);
+ unset($info[$key]);
+ } else {
+ $result[$key] = $item;
+ }
+ }
+
+ return $result;
+ }
+}
diff --git a/app/code/Magento/Sales/Test/Unit/CustomerData/LastOrderedItemsTest.php b/app/code/Magento/Sales/Test/Unit/CustomerData/LastOrderedItemsTest.php
new file mode 100644
index 0000000000000..c9af2cf5b9a7c
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Unit/CustomerData/LastOrderedItemsTest.php
@@ -0,0 +1,183 @@
+objectManagerHelper = new ObjectManagerHelper($this);
+
+ $this->orderCollectionFactoryMock =
+ $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\CollectionFactory::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['create'])
+ ->getMock();
+ $this->orderConfigMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Config::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->customerSessionMock = $this->getMockBuilder(\Magento\Customer\Model\Session::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->stockRegistryMock = $this->getMockBuilder(\Magento\CatalogInventory\Api\StockRegistryInterface::class)
+ ->getMockForAbstractClass();
+ $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
+ ->getMockForAbstractClass();
+ $this->orderMock = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $this->section = new \Magento\Sales\CustomerData\LastOrderedItems(
+ $this->orderCollectionFactoryMock,
+ $this->orderConfigMock,
+ $this->customerSessionMock,
+ $this->stockRegistryMock,
+ $this->storeManagerMock
+ );
+ }
+
+ /**
+ * @covers \Magento\Sales\CustomerData\LastOrderedItems
+ *
+ * @return void
+ */
+ public function testGetSectionData()
+ {
+ $websiteId = 4;
+ $expectedItem = [
+ 'id' => 1,
+ 'name' => 'Product Name',
+ 'url' => 'http://example.com',
+ 'is_saleable' => true,
+ ];
+ $productId = 10;
+
+ $stockItemMock = $this->getMockBuilder(\Magento\CatalogInventory\Api\Data\StockItemInterface::class)
+ ->getMockForAbstractClass();
+ $itemWithProductMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $itemWithoutProductMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $items = [$itemWithoutProductMock, $itemWithProductMock];
+ $this->getLastOrderMock();
+ $storeMock = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)->getMockForAbstractClass();
+ $this->storeManagerMock->expects($this->once())->method('getStore')->willReturn($storeMock);
+ $storeMock->expects($this->any())->method('getWebsiteId')->willReturn($websiteId);
+ $this->orderMock->expects($this->once())
+ ->method('getParentItemsRandomCollection')
+ ->with(\Magento\Sales\CustomerData\LastOrderedItems::SIDEBAR_ORDER_LIMIT)
+ ->willReturn($items);
+
+ $itemWithProductMock->expects($this->once())->method('hasData')->with('product')->willReturn(true);
+ $itemWithProductMock->expects($this->any())->method('getProduct')->willReturn($productMock);
+ $productMock->expects($this->once())->method('getWebsiteIds')->willReturn([1, 4]);
+ $itemWithProductMock->expects($this->once())->method('getId')->willReturn($expectedItem['id']);
+ $itemWithProductMock->expects($this->once())->method('getName')->willReturn($expectedItem['name']);
+ $productMock->expects($this->once())->method('getProductUrl')->willReturn($expectedItem['url']);
+ $this->stockRegistryMock->expects($this->once())->method('getStockItem')->willReturn($stockItemMock);
+ $productMock->expects($this->once())->method('getId')->willReturn($productId);
+ $itemWithProductMock->expects($this->once())->method('getStore')->willReturn($storeMock);
+ $this->stockRegistryMock
+ ->expects($this->once())
+ ->method('getStockItem')
+ ->with($productId, $websiteId)
+ ->willReturn($stockItemMock);
+ $stockItemMock->expects($this->once())->method('getIsInStock')->willReturn($expectedItem['is_saleable']);
+ $itemWithoutProductMock->expects($this->once())->method('hasData')->with('product')->willReturn(false);
+
+ $this->assertEquals(['items' => [$expectedItem]], $this->section->getSectionData());
+ }
+
+ /**
+ * Return last order mock object.
+ *
+ * @return \PHPUnit_Framework_MockObject_MockObject
+ */
+ private function getLastOrderMock()
+ {
+ $customerId = 1;
+ $visibleOnFrontStatuses = ['complete'];
+
+ $orderCollectionMock = $this->objectManagerHelper
+ ->getCollectionMock(\Magento\Sales\Model\ResourceModel\Order\Collection::class, [$this->orderMock]);
+ $this->customerSessionMock->expects($this->once())->method('getCustomerId')->willReturn($customerId);
+ $this->orderConfigMock
+ ->expects($this->once())
+ ->method('getVisibleOnFrontStatuses')
+ ->willReturn($visibleOnFrontStatuses);
+ $this->orderCollectionFactoryMock->expects($this->once())->method('create')->willReturn($orderCollectionMock);
+ $orderCollectionMock->expects($this->at(0))
+ ->method('addAttributeToFilter')
+ ->with('customer_id', $customerId)
+ ->willReturnSelf();
+ $orderCollectionMock->expects($this->at(1))
+ ->method('addAttributeToFilter')
+ ->with('status', ['in' => $visibleOnFrontStatuses])
+ ->willReturnSelf();
+ $orderCollectionMock->expects($this->once())
+ ->method('addAttributeToSort')
+ ->willReturnSelf();
+ $orderCollectionMock->expects($this->once())
+ ->method('setPage')
+ ->willReturnSelf();
+
+ return $this->orderMock;
+ }
+}
diff --git a/app/code/Magento/Sales/Test/Unit/Model/AdminOrder/CreateTest.php b/app/code/Magento/Sales/Test/Unit/Model/AdminOrder/CreateTest.php
index 007c529439e41..fce267d48f283 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/AdminOrder/CreateTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/AdminOrder/CreateTest.php
@@ -92,98 +92,98 @@ class CreateTest extends \PHPUnit_Framework_TestCase
*/
protected function setUp()
{
- $objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface');
- $eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface');
- $registryMock = $this->getMock('Magento\Framework\Registry');
- $configMock = $this->getMock('Magento\Sales\Model\Config', [], [], '', false);
- $this->sessionQuoteMock = $this->getMock('Magento\Backend\Model\Session\Quote', [], [], '', false);
- $loggerMock = $this->getMock('Psr\Log\LoggerInterface');
- $copyMock = $this->getMock('Magento\Framework\DataObject\Copy', [], [], '', false);
- $messageManagerMock = $this->getMock('Magento\Framework\Message\ManagerInterface');
+ $objectManagerMock = $this->getMock(\Magento\Framework\ObjectManagerInterface::class);
+ $eventManagerMock = $this->getMock(\Magento\Framework\Event\ManagerInterface::class);
+ $registryMock = $this->getMock(\Magento\Framework\Registry::class);
+ $configMock = $this->getMock(\Magento\Sales\Model\Config::class, [], [], '', false);
+ $this->sessionQuoteMock = $this->getMock(\Magento\Backend\Model\Session\Quote::class, [], [], '', false);
+ $loggerMock = $this->getMock(\Psr\Log\LoggerInterface::class);
+ $copyMock = $this->getMock(\Magento\Framework\DataObject\Copy::class, [], [], '', false);
+ $messageManagerMock = $this->getMock(\Magento\Framework\Message\ManagerInterface::class);
$this->formFactoryMock = $this->getMock(
- 'Magento\Customer\Model\Metadata\FormFactory',
+ \Magento\Customer\Model\Metadata\FormFactory::class,
['create'],
[],
'',
false
);
$this->customerFactoryMock = $this->getMock(
- 'Magento\Customer\Api\Data\CustomerInterfaceFactory',
+ \Magento\Customer\Api\Data\CustomerInterfaceFactory::class,
['create'],
[],
'',
false
);
- $this->itemUpdater = $this->getMock('Magento\Quote\Model\Quote\Item\Updater', [], [], '', false);
+ $this->itemUpdater = $this->getMock(\Magento\Quote\Model\Quote\Item\Updater::class, [], [], '', false);
- $this->objectFactory = $this->getMockBuilder('\Magento\Framework\DataObject\Factory')
+ $this->objectFactory = $this->getMockBuilder(\Magento\Framework\DataObject\Factory::class)
->disableOriginalConstructor()
->setMethods(['create'])
->getMock();
$this->customerMapper = $this->getMockBuilder(
- 'Magento\Customer\Model\Customer\Mapper'
+ \Magento\Customer\Model\Customer\Mapper::class
)->setMethods(['toFlatArray'])->disableOriginalConstructor()->getMock();
$this->quoteInitializerMock = $this->getMock(
- 'Magento\Sales\Model\AdminOrder\Product\Quote\Initializer',
+ \Magento\Sales\Model\AdminOrder\Product\Quote\Initializer::class,
[],
[],
'',
false
);
$this->customerRepositoryMock = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\CustomerRepositoryInterface',
+ \Magento\Customer\Api\CustomerRepositoryInterface::class,
[],
'',
false
);
$this->addressRepositoryMock = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\AddressRepositoryInterface',
+ \Magento\Customer\Api\AddressRepositoryInterface::class,
[],
'',
false
);
$this->addressFactoryMock = $this->getMock(
- 'Magento\Customer\Api\Data\AddressInterfaceFactory',
+ \Magento\Customer\Api\Data\AddressInterfaceFactory::class,
[],
[],
'',
false
);
$this->groupRepositoryMock = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\GroupRepositoryInterface',
+ \Magento\Customer\Api\GroupRepositoryInterface::class,
[],
'',
false
);
$this->scopeConfigMock = $this->getMockForAbstractClass(
- 'Magento\Framework\App\Config\ScopeConfigInterface',
+ \Magento\Framework\App\Config\ScopeConfigInterface::class,
[],
'',
false
);
$this->emailSenderMock = $this->getMock(
- 'Magento\Sales\Model\AdminOrder\EmailSender',
+ \Magento\Sales\Model\AdminOrder\EmailSender::class,
[],
[],
'',
false
);
$this->accountManagementMock = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\AccountManagementInterface',
+ \Magento\Customer\Api\AccountManagementInterface::class,
[],
'',
false
);
- $this->dataObjectHelper = $this->getMockBuilder('Magento\Framework\Api\DataObjectHelper')
+ $this->dataObjectHelper = $this->getMockBuilder(\Magento\Framework\Api\DataObjectHelper::class)
->disableOriginalConstructor()
->getMock();
$objectManagerHelper = new ObjectManagerHelper($this);
$this->adminOrderCreate = $objectManagerHelper->getObject(
- 'Magento\Sales\Model\AdminOrder\Create',
+ \Magento\Sales\Model\AdminOrder\Create::class,
[
'objectManager' => $objectManagerMock,
'eventManager' => $eventManagerMock,
@@ -220,7 +220,7 @@ public function testSetAccountData()
foreach ($attributes as $attribute) {
$attributeMock = $this->getMock(
- 'Magento\Customer\Api\Data\AttributeMetadataInterface',
+ \Magento\Customer\Api\Data\AttributeMetadataInterface::class,
[],
[],
'',
@@ -233,7 +233,7 @@ public function testSetAccountData()
}
$customerGroupMock = $this->getMockForAbstractClass(
- 'Magento\Customer\Api\Data\GroupInterface',
+ \Magento\Customer\Api\Data\GroupInterface::class,
[],
'',
false,
@@ -242,7 +242,7 @@ public function testSetAccountData()
['getTaxClassId']
);
$customerGroupMock->expects($this->once())->method('getTaxClassId')->will($this->returnValue($taxClassId));
- $customerFormMock = $this->getMock('Magento\Customer\Model\Metadata\Form', [], [], '', false);
+ $customerFormMock = $this->getMock(\Magento\Customer\Model\Metadata\Form::class, [], [], '', false);
$customerFormMock->expects($this->any())
->method('getAttributes')
->will($this->returnValue([$attributeMocks[1]]));
@@ -251,15 +251,15 @@ public function testSetAccountData()
$customerFormMock->expects($this->any())
->method('prepareRequest')
- ->will($this->returnValue($this->getMock('Magento\Framework\App\RequestInterface')));
+ ->will($this->returnValue($this->getMock(\Magento\Framework\App\RequestInterface::class)));
- $customerMock = $this->getMock('Magento\Customer\Api\Data\CustomerInterface', [], [], '', false);
+ $customerMock = $this->getMock(\Magento\Customer\Api\Data\CustomerInterface::class, [], [], '', false);
$this->customerMapper->expects($this->atLeastOnce())
->method('toFlatArray')
->willReturn(['group_id' => 1]);
- $quoteMock = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false);
+ $quoteMock = $this->getMock(\Magento\Quote\Model\Quote::class, [], [], '', false);
$quoteMock->expects($this->any())->method('getCustomer')->will($this->returnValue($customerMock));
$quoteMock->expects($this->once())
->method('addData')
@@ -274,7 +274,7 @@ public function testSetAccountData()
->with(
$customerMock,
['group_id' => 1],
- '\Magento\Customer\Api\Data\CustomerInterface'
+ \Magento\Customer\Api\Data\CustomerInterface::class
);
$this->formFactoryMock->expects($this->any())->method('create')->will($this->returnValue($customerFormMock));
@@ -303,9 +303,9 @@ public function testUpdateQuoteItemsEmptyConfiguredOption()
]
];
- $itemMock = $this->getMock('Magento\Quote\Model\Quote\Item', [], [], '', false);
+ $itemMock = $this->getMock(\Magento\Quote\Model\Quote\Item::class, [], [], '', false);
- $quoteMock = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false);
+ $quoteMock = $this->getMock(\Magento\Quote\Model\Quote::class, [], [], '', false);
$quoteMock->expects($this->once())
->method('getItemById')
->will($this->returnValue($itemMock));
@@ -331,12 +331,12 @@ public function testUpdateQuoteItemsWithConfiguredOption()
]
];
- $itemMock = $this->getMock('Magento\Quote\Model\Quote\Item', [], [], '', false);
+ $itemMock = $this->getMock(\Magento\Quote\Model\Quote\Item::class, [], [], '', false);
$itemMock->expects($this->once())
->method('getQty')
->will($this->returnValue($qty));
- $quoteMock = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false);
+ $quoteMock = $this->getMock(\Magento\Quote\Model\Quote::class, [], [], '', false);
$quoteMock->expects($this->once())
->method('updateItem')
->will($this->returnValue($itemMock));
@@ -352,4 +352,32 @@ public function testUpdateQuoteItemsWithConfiguredOption()
$this->adminOrderCreate->setRecollect(false);
$this->adminOrderCreate->updateQuoteItems($items);
}
+
+ public function testApplyCoupon()
+ {
+ $couponCode = '';
+ $quoteMock = $this->getMock(
+ \Magento\Quote\Model\Quote::class,
+ ['getShippingAddress', 'setCouponCode'],
+ [],
+ '',
+ false
+ );
+ $this->sessionQuoteMock->expects($this->once())->method('getQuote')->willReturn($quoteMock);
+
+ $addressMock = $this->getMock(
+ \Magento\Quote\Model\Quote\Address::class,
+ ['setCollectShippingRates', 'setFreeShipping'],
+ [],
+ '',
+ false
+ );
+ $quoteMock->expects($this->exactly(2))->method('getShippingAddress')->willReturn($addressMock);
+ $quoteMock->expects($this->once())->method('setCouponCode')->with($couponCode)->willReturnSelf();
+
+ $addressMock->expects($this->once())->method('setCollectShippingRates')->with(true)->willReturnSelf();
+ $addressMock->expects($this->once())->method('setFreeShipping')->with(null)->willReturnSelf();
+
+ $this->adminOrderCreate->applyCoupon($couponCode);
+ }
}
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Address/RendererTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Address/RendererTest.php
new file mode 100644
index 0000000000000..c52e99aa2b6bb
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Address/RendererTest.php
@@ -0,0 +1,145 @@
+customerAddressConfigMock = $this->getMockBuilder(CustomerAddressConfig::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->eventManagerMock = $this->getMockBuilder(EventManager::class)
+ ->getMockForAbstractClass();
+ $this->orderAddressMock = $this->getMockBuilder(OrderAddress::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->orderMock = $this->getMockBuilder(Order::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->customerAddressBlockRendererMock = $this->getMockBuilder(CustomerAddressBlockRenderer::class)
+ ->getMockForAbstractClass();
+
+ $this->orderAddressMock->expects(static::any())
+ ->method('getOrder')
+ ->willReturn($this->orderMock);
+
+ $this->objectManagerHelper = new ObjectManagerHelper($this);
+ $this->orderAddressRenderer = $this->objectManagerHelper->getObject(
+ OrderAddressRenderer::class,
+ [
+ 'addressConfig' => $this->customerAddressConfigMock,
+ 'eventManager' => $this->eventManagerMock
+ ]
+ );
+ }
+
+ public function testFormat()
+ {
+ $type = 'html';
+ $formatType = new DataObject(['renderer' => $this->customerAddressBlockRendererMock]);
+ $addressData = ['address', 'data'];
+ $result = 'result string';
+
+ $this->setStoreExpectations(1);
+ $this->customerAddressConfigMock->expects(static::atLeastOnce())
+ ->method('getFormatByCode')
+ ->with($type)
+ ->willReturn($formatType);
+ $this->eventManagerMock->expects(static::once())
+ ->method('dispatch')
+ ->with('customer_address_format', ['type' => $formatType, 'address' => $this->orderAddressMock]);
+ $this->orderAddressMock->expects(static::atLeastOnce())
+ ->method('getData')
+ ->willReturn($addressData);
+ $this->customerAddressBlockRendererMock->expects(static::once())
+ ->method('renderArray')
+ ->with($addressData, null)
+ ->willReturn($result);
+
+ $this->assertEquals($result, $this->orderAddressRenderer->format($this->orderAddressMock, $type));
+ }
+
+ public function testFormatNoRenderer()
+ {
+ $type = 'html';
+
+ $this->setStoreExpectations(1);
+ $this->customerAddressConfigMock->expects(static::atLeastOnce())
+ ->method('getFormatByCode')
+ ->with($type)
+ ->willReturn(null);
+ $this->eventManagerMock->expects(static::never())
+ ->method('dispatch');
+
+ $this->assertEquals(null, $this->orderAddressRenderer->format($this->orderAddressMock, $type));
+ }
+
+ /**
+ * Set expectations for store
+ *
+ * @param string|int $storeId
+ * @return void
+ */
+ private function setStoreExpectations($storeId)
+ {
+ $this->orderMock->expects(static::atLeastOnce())
+ ->method('getStoreId')
+ ->willReturn($storeId);
+ $this->customerAddressConfigMock->expects(static::atLeastOnce())
+ ->method('setStore')
+ ->with($storeId)
+ ->willReturnSelf();
+ }
+}
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php
index eb30addb74122..3a626c3469d1b 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php
@@ -1520,7 +1520,7 @@ public function testIsCaptureFinal()
$partialAmount = 12.00;
$this->orderMock->expects(static::exactly(2))
- ->method('getTotalDue')
+ ->method('getBaseTotalDue')
->willReturn($amount);
static::assertFalse($this->payment->isCaptureFinal($partialAmount));
diff --git a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php
index a1d8d3c4ae59f..a047a934ed334 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php
@@ -6,14 +6,15 @@
namespace Magento\Sales\Test\Unit\Model;
use Magento\Catalog\Api\Data\ProductInterface;
-use Magento\Catalog\Api\ProductRepositoryInterface;
-use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Sales\Api\Data\OrderInterface;
use Magento\Sales\Model\Order;
use Magento\Sales\Model\ResourceModel\Order\Status\History\CollectionFactory as HistoryCollectionFactory;
-use Magento\Sales\Model\ResourceModel\Order\Item;
+use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;
/**
* Test class for \Magento\Sales\Model\Order
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class OrderTest extends \PHPUnit_Framework_TestCase
{
@@ -68,79 +69,81 @@ class OrderTest extends \PHPUnit_Framework_TestCase
protected $salesOrderCollectionMock;
/**
- * @var ProductRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var ProductCollectionFactory|\PHPUnit_Framework_MockObject_MockObject
*/
- private $productRepository;
+ private $productCollectionFactoryMock;
protected function setUp()
{
$helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
$this->paymentCollectionFactoryMock = $this->getMock(
- 'Magento\Sales\Model\ResourceModel\Order\Payment\CollectionFactory',
+ \Magento\Sales\Model\ResourceModel\Order\Payment\CollectionFactory::class,
['create'],
[],
'',
false
);
$this->orderItemCollectionFactoryMock = $this->getMock(
- 'Magento\Sales\Model\ResourceModel\Order\Item\CollectionFactory',
+ \Magento\Sales\Model\ResourceModel\Order\Item\CollectionFactory::class,
['create'],
[],
'',
false
);
$this->historyCollectionFactoryMock = $this->getMock(
- 'Magento\Sales\Model\ResourceModel\Order\Status\History\CollectionFactory',
+ \Magento\Sales\Model\ResourceModel\Order\Status\History\CollectionFactory::class,
['create'],
[],
'',
false
);
- $this->salesOrderCollectionFactoryMock = $this->getMock(
- 'Magento\Sales\Model\ResourceModel\Order\CollectionFactory',
+ $this->productCollectionFactoryMock = $this->getMock(
+ \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory::class,
['create'],
[],
'',
false
);
- $this->item = $this->getMock(
- 'Magento\Sales\Model\ResourceModel\Order\Item',
- ['isDeleted', 'getQtyToInvoice', 'getParentItemId', 'getQuoteItemId', 'getLockedDoInvoice'],
+ $this->salesOrderCollectionFactoryMock = $this->getMock(
+ \Magento\Sales\Model\ResourceModel\Order\CollectionFactory::class,
+ ['create'],
[],
'',
false
);
- $this->item = $this->getMockBuilder(Item::class)
- ->disableOriginalConstructor()
- ->setMethods([
+ $this->item = $this->getMock(
+ \Magento\Sales\Model\ResourceModel\Order\Item::class,
+ [
'isDeleted',
'getQtyToInvoice',
'getParentItemId',
'getQuoteItemId',
'getLockedDoInvoice',
'getProductId'
- ])
- ->getMock();
- $this->salesOrderCollectionMock = $this->getMockBuilder('Magento\Sales\Model\ResourceModel\Order\Collection')
- ->disableOriginalConstructor()
+ ],
+ [],
+ '',
+ false
+ );
+ $this->salesOrderCollectionMock = $this->getMockBuilder(
+ \Magento\Sales\Model\ResourceModel\Order\Collection::class
+ )->disableOriginalConstructor()
->setMethods(['addFieldToFilter', 'load', 'getFirstItem'])
->getMock();
- $collection = $this->getMock('Magento\Sales\Model\ResourceModel\Order\Item\Collection', [], [], '', false);
- $collection->expects($this->any())
- ->method('setOrderFilter')
- ->willReturnSelf();
- $collection->expects($this->any())
- ->method('getItems')
- ->willReturn([$this->item]);
- $collection->expects(self::any())
- ->method('getIterator')
- ->willReturn(new \ArrayIterator([$this->item]));
- $this->orderItemCollectionFactoryMock->expects($this->any())
- ->method('create')
- ->willReturn($collection);
+ $collection = $this->getMock(
+ \Magento\Sales\Model\ResourceModel\Order\Item\Collection::class,
+ [],
+ [],
+ '',
+ false
+ );
+ $collection->expects($this->any())->method('setOrderFilter')->willReturnSelf();
+ $collection->expects($this->any())->method('getItems')->willReturn([$this->item]);
+ $collection->expects($this->any())->method('getIterator')->willReturn(new \ArrayIterator([$this->item]));
+ $this->orderItemCollectionFactoryMock->expects($this->any())->method('create')->willReturn($collection);
$this->priceCurrency = $this->getMockForAbstractClass(
- 'Magento\Framework\Pricing\PriceCurrencyInterface',
+ \Magento\Framework\Pricing\PriceCurrencyInterface::class,
[],
'',
false,
@@ -149,18 +152,13 @@ protected function setUp()
['round']
);
- $this->productRepository = $this->getMockBuilder(ProductRepositoryInterface::class)
- ->getMockForAbstractClass();
-
$this->incrementId = '#00000001';
- $this->eventManager = $this->getMock('Magento\Framework\Event\Manager', [], [], '', false);
- $context = $this->getMock('Magento\Framework\Model\Context', ['getEventDispatcher'], [], '', false);
- $context->expects($this->any())
- ->method('getEventDispatcher')
- ->willReturn($this->eventManager);
+ $this->eventManager = $this->getMock(\Magento\Framework\Event\Manager::class, [], [], '', false);
+ $context = $this->getMock(\Magento\Framework\Model\Context::class, ['getEventDispatcher'], [], '', false);
+ $context->expects($this->any())->method('getEventDispatcher')->willReturn($this->eventManager);
$this->order = $helper->getObject(
- 'Magento\Sales\Model\Order',
+ \Magento\Sales\Model\Order::class,
[
'paymentCollectionFactory' => $this->paymentCollectionFactoryMock,
'orderItemCollectionFactory' => $this->orderItemCollectionFactoryMock,
@@ -169,7 +167,7 @@ protected function setUp()
'historyCollectionFactory' => $this->historyCollectionFactoryMock,
'salesOrderCollectionFactory' => $this->salesOrderCollectionFactoryMock,
'priceCurrency' => $this->priceCurrency,
- 'productRepository' => $this->productRepository
+ 'productListFactory' => $this->productCollectionFactoryMock
]
);
}
@@ -180,7 +178,7 @@ public function testGetItemById()
$fakeOrderItemId = 2;
$orderItem = $this->getMock(
- 'Magento\Sales\Model\Order\Item',
+ \Magento\Sales\Model\Order\Item::class,
[],
[],
'',
@@ -380,7 +378,7 @@ public function testCanNotCreditMemoWithForced()
public function testCanEditIfHasInvoices()
{
- $invoiceCollection = $this->getMockBuilder('Magento\Sales\Model\ResourceModel\Order\Invoice\Collection')
+ $invoiceCollection = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Invoice\Collection::class)
->disableOriginalConstructor()
->setMethods(['count'])
->getMock();
@@ -405,7 +403,7 @@ public function testCanReorder()
$this->order->setState(Order::STATE_PROCESSING);
$this->order->setActionFlag(Order::ACTION_FLAG_REORDER, true);
- $this->item->expects(static::once())
+ $this->item->expects($this->any())
->method('getProductId')
->willReturn($productId);
@@ -416,10 +414,29 @@ public function testCanReorder()
->method('isSalable')
->willReturn(true);
- $this->productRepository->expects(static::once())
- ->method('getById')
- ->with($productId, false)
+ $productCollection = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product\Collection::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setStoreId', 'addIdFilter', 'load', 'getItemById', 'addAttributeToSelect'])
+ ->getMock();
+ $productCollection->expects($this->once())
+ ->method('setStoreId')
+ ->willReturnSelf();
+ $productCollection->expects($this->once())
+ ->method('addIdFilter')
+ ->willReturnSelf();
+ $productCollection->expects($this->once())
+ ->method('addAttributeToSelect')
+ ->willReturnSelf();
+ $productCollection->expects($this->once())
+ ->method('load')
+ ->willReturnSelf();
+ $productCollection->expects($this->once())
+ ->method('getItemById')
+ ->with($productId)
->willReturn($product);
+ $this->productCollectionFactoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($productCollection);
$this->assertTrue($this->order->canReorder());
}
@@ -455,7 +472,7 @@ public function testCanReorderProductNotExists()
$this->order->setState(Order::STATE_PROCESSING);
$this->order->setActionFlag(Order::ACTION_FLAG_REORDER, true);
- $this->item->expects(static::once())
+ $this->item->expects($this->any())
->method('getProductId')
->willReturn($productId);
@@ -465,10 +482,29 @@ public function testCanReorderProductNotExists()
$product->expects(static::never())
->method('isSalable');
- $this->productRepository->expects(static::once())
- ->method('getById')
- ->with($productId, false)
- ->willThrowException(new NoSuchEntityException(__('Requested product doesn\'t exist')));
+ $productCollection = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product\Collection::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setStoreId', 'addIdFilter', 'load', 'getItemById', 'addAttributeToSelect'])
+ ->getMock();
+ $productCollection->expects($this->once())
+ ->method('setStoreId')
+ ->willReturnSelf();
+ $productCollection->expects($this->once())
+ ->method('addIdFilter')
+ ->willReturnSelf();
+ $productCollection->expects($this->once())
+ ->method('load')
+ ->willReturnSelf();
+ $productCollection->expects($this->once())
+ ->method('getItemById')
+ ->with($productId)
+ ->willReturn(null);
+ $this->productCollectionFactoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($productCollection);
+ $productCollection->expects($this->once())
+ ->method('addAttributeToSelect')
+ ->willReturnSelf();
$this->assertFalse($this->order->canReorder());
}
@@ -483,7 +519,7 @@ public function testCanReorderProductNotSalable()
$this->order->setState(Order::STATE_PROCESSING);
$this->order->setActionFlag(Order::ACTION_FLAG_REORDER, true);
- $this->item->expects(static::once())
+ $this->item->expects($this->any())
->method('getProductId')
->willReturn($productId);
@@ -494,17 +530,36 @@ public function testCanReorderProductNotSalable()
->method('isSalable')
->willReturn(false);
- $this->productRepository->expects(static::once())
- ->method('getById')
- ->with($productId, false)
+ $productCollection = $this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Product\Collection::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['setStoreId', 'addIdFilter', 'load', 'getItemById', 'addAttributeToSelect'])
+ ->getMock();
+ $productCollection->expects($this->once())
+ ->method('setStoreId')
+ ->willReturnSelf();
+ $productCollection->expects($this->once())
+ ->method('addIdFilter')
+ ->willReturnSelf();
+ $productCollection->expects($this->once())
+ ->method('load')
+ ->willReturnSelf();
+ $productCollection->expects($this->once())
+ ->method('getItemById')
+ ->with($productId)
->willReturn($product);
+ $this->productCollectionFactoryMock->expects($this->once())
+ ->method('create')
+ ->willReturn($productCollection);
+ $productCollection->expects($this->once())
+ ->method('addAttributeToSelect')
+ ->willReturnSelf();
$this->assertFalse($this->order->canReorder());
}
public function testCanCancelCanReviewPayment()
{
- $paymentMock = $this->getMockBuilder('Magento\Sales\Model\ResourceModel\Order\Payment')
+ $paymentMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Payment::class)
->disableOriginalConstructor()
->setMethods(['isDeleted', 'canReviewPayment', 'canFetchTransactionInfo', '__wakeUp'])
->getMock();
@@ -522,7 +577,7 @@ public function testCanCancelCanReviewPayment()
public function testCanCancelAllInvoiced()
{
- $paymentMock = $this->getMockBuilder('Magento\Sales\Model\ResourceModel\Order\Payment')
+ $paymentMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Payment::class)
->disableOriginalConstructor()
->setMethods(['isDeleted', 'canReviewPayment', 'canFetchTransactionInfo', '__wakeUp'])
->getMock();
@@ -533,7 +588,7 @@ public function testCanCancelAllInvoiced()
->method('canFetchTransactionInfo')
->will($this->returnValue(false));
$collectionMock = $this->getMock(
- 'Magento\Sales\Model\ResourceModel\Order\Item\Collection',
+ \Magento\Sales\Model\ResourceModel\Order\Item\Collection::class,
['getItems', 'setOrderFilter'],
[],
'',
@@ -564,7 +619,7 @@ public function testCanCancelAllInvoiced()
public function testCanCancelState()
{
- $paymentMock = $this->getMockBuilder('Magento\Sales\Model\ResourceModel\Order\Payment')
+ $paymentMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Payment::class)
->disableOriginalConstructor()
->setMethods(['isDeleted', 'canReviewPayment', 'canFetchTransactionInfo', '__wakeUp'])
->getMock();
@@ -589,7 +644,7 @@ public function testCanCancelState()
*/
public function testCanCancelActionFlag($cancelActionFlag)
{
- $paymentMock = $this->getMockBuilder('Magento\Sales\Model\ResourceModel\Order\Payment')
+ $paymentMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Payment::class)
->disableOriginalConstructor()
->setMethods(['isDeleted', 'canReviewPayment', 'canFetchTransactionInfo', '__wakeUp'])
->getMock();
@@ -632,7 +687,7 @@ public function testCanVoidPayment($actionFlags, $orderState)
{
$helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
/** @var Order $order */
- $order = $helper->getObject('Magento\Sales\Model\Order');
+ $order = $helper->getObject(\Magento\Sales\Model\Order::class);
foreach ($actionFlags as $action => $flag) {
$order->setActionFlag($action, $flag);
}
@@ -677,7 +732,7 @@ protected function preparePaymentMock($paymentMock)
{
$iterator = new \ArrayIterator([$paymentMock]);
- $collectionMock = $this->getMockBuilder('Magento\Sales\Model\ResourceModel\Order\Payment\Collection')
+ $collectionMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Payment\Collection::class)
->disableOriginalConstructor()
->setMethods(['setOrderFilter', 'getIterator'])
->getMock();
@@ -702,7 +757,9 @@ protected function preparePaymentMock($paymentMock)
*/
protected function _prepareOrderPayment($order, $mockedMethods = [])
{
- $payment = $this->getMockBuilder('Magento\Sales\Model\Order\Payment')->disableOriginalConstructor()->getMock();
+ $payment = $this->getMockBuilder(\Magento\Sales\Model\Order\Payment::class)
+ ->disableOriginalConstructor()
+ ->getMock();
foreach ($mockedMethods as $method => $value) {
$payment->expects($this->any())->method($method)->will($this->returnValue($value));
}
@@ -755,7 +812,7 @@ protected function _getOrderStatuses()
*/
protected function prepareItemMock($qtyInvoiced)
{
- $itemMock = $this->getMockBuilder('Magento\Sales\Model\ResourceModel\Order\Item')
+ $itemMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Item::class)
->disableOriginalConstructor()
->setMethods(['isDeleted', 'filterByTypes', 'filterByParent', 'getQtyToInvoice', '__wakeUp'])
->getMock();
@@ -766,7 +823,7 @@ protected function prepareItemMock($qtyInvoiced)
$iterator = new \ArrayIterator([$itemMock]);
- $itemCollectionMock = $this->getMockBuilder('Magento\Sales\Model\ResourceModel\Order\Item\Collection')
+ $itemCollectionMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Item\Collection::class)
->disableOriginalConstructor()
->setMethods(['setOrderFilter', 'getIterator', 'getItems'])
->getMock();
@@ -822,7 +879,7 @@ public function testGetEntityType()
public function testGetStatusHistories()
{
$itemMock = $this->getMockForAbstractClass(
- 'Magento\Sales\Api\Data\OrderStatusHistoryInterface',
+ \Magento\Sales\Api\Data\OrderStatusHistoryInterface::class,
[],
'',
false,
@@ -830,12 +887,12 @@ public function testGetStatusHistories()
true,
['setOrder']
);
- $dbMock = $this->getMockBuilder('Magento\Framework\Data\Collection\AbstractDb')
+ $dbMock = $this->getMockBuilder(\Magento\Framework\Data\Collection\AbstractDb::class)
->setMethods(['setOrder'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$collectionMock = $this->getMock(
- 'Magento\Sales\Model\ResourceModel\Order\Status\History\Collection',
+ \Magento\Sales\Model\ResourceModel\Order\Status\History\Collection::class,
[
'setOrderFilter',
'setOrder',
@@ -891,6 +948,81 @@ public function testLoadByIncrementIdAndStoreId()
$this->assertSame($this->order, $this->order->loadByIncrementIdAndStoreId($incrementId, $storeId));
}
+ /**
+ * Tests setPayment() method with Id.
+ *
+ * @return void
+ */
+ public function testSetPaymentWithId()
+ {
+ $this->order->setId(123);
+ $payment = $this->getMockBuilder(\Magento\Sales\Model\Order\Payment::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->order->setData(OrderInterface::PAYMENT, $payment);
+ $this->order->setDataChanges(false);
+ $payment->expects($this->once())
+ ->method('setOrder')
+ ->with($this->order)
+ ->willReturnSelf();
+ $payment->expects($this->once())
+ ->method('setParentId')
+ ->with(123)
+ ->willReturnSelf();
+ $payment->expects($this->any())
+ ->method('getId')
+ ->willReturn(1);
+ $this->order->setPayment($payment);
+
+ $this->assertEquals(
+ $this->order->getData(
+ OrderInterface::PAYMENT
+ ),
+ $payment
+ );
+
+ $this->assertFalse(
+ $this->order->hasDataChanges()
+ );
+ }
+
+ /**
+ * Tests setPayment() method without Id.
+ *
+ * @return void
+ */
+ public function testSetPaymentNoId()
+ {
+ $this->order->setId(123);
+ $this->order->setDataChanges(false);
+ $payment = $this->getMockBuilder(\Magento\Sales\Model\Order\Payment::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $payment->expects($this->once())
+ ->method('setOrder')
+ ->with($this->order)
+ ->willReturnSelf();
+ $payment->expects($this->once())
+ ->method('setParentId')
+ ->with(123)
+ ->willReturnSelf();
+ $payment->expects($this->any())
+ ->method('getId')
+ ->willReturn(null);
+ $this->order->setPayment($payment);
+
+ $this->assertEquals(
+ $this->order->getData(
+ OrderInterface::PAYMENT
+ ),
+ $payment
+ );
+
+ $this->assertTrue(
+ $this->order->hasDataChanges()
+ );
+ }
+
public function notInvoicingStatesProvider()
{
return [
diff --git a/app/code/Magento/Sales/composer.json b/app/code/Magento/Sales/composer.json
index 14bec37e8085b..dcc3fce8b31c8 100644
--- a/app/code/Magento/Sales/composer.json
+++ b/app/code/Magento/Sales/composer.json
@@ -32,7 +32,7 @@
"magento/module-sales-sample-data": "Sample Data version:100.1.*"
},
"type": "magento2-module",
- "version": "100.1.6",
+ "version": "100.1.7",
"license": [
"OSL-3.0",
"AFL-3.0"
diff --git a/app/code/Magento/Sales/etc/config.xml b/app/code/Magento/Sales/etc/config.xml
index 3961f19f2cf60..6bd5e5800c689 100644
--- a/app/code/Magento/Sales/etc/config.xml
+++ b/app/code/Magento/Sales/etc/config.xml
@@ -22,6 +22,7 @@
1
+ 20
480
diff --git a/app/code/Magento/Sales/etc/events.xml b/app/code/Magento/Sales/etc/events.xml
index 464f5a615b84f..164d7a23267f0 100644
--- a/app/code/Magento/Sales/etc/events.xml
+++ b/app/code/Magento/Sales/etc/events.xml
@@ -51,4 +51,7 @@
+
+
+
diff --git a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml
index fab43830ef493..4ee02048df2e7 100644
--- a/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml
+++ b/app/code/Magento/Sales/view/adminhtml/ui_component/sales_order_grid.xml
@@ -187,7 +187,7 @@
- Magento_Ui/js/grid/columns/date
- date
- Purchase Date
- - MMM dd, YYYY, H:MM:SS A
+ - MMM dd, YYYY, H:mm:ss A
diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js
index f30568215befd..673fba9792dfa 100644
--- a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js
+++ b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js
@@ -434,7 +434,7 @@ define([
},
applyCoupon : function(code){
- this.loadArea(['items', 'shipping_method', 'totals', 'billing_method'], true, {'order[coupon][code]':code, reset_shipping: true});
+ this.loadArea(['items', 'shipping_method', 'totals', 'billing_method'], true, {'order[coupon][code]':code, reset_shipping: 0});
this.orderItemChanged = false;
},
diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml
index 4bf37ca59189e..c680cf48b91bc 100644
--- a/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml
+++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_view.xml
@@ -26,6 +26,7 @@
+
colspan="4" class="mark"
diff --git a/app/code/Magento/Sales/view/frontend/templates/order/items.phtml b/app/code/Magento/Sales/view/frontend/templates/order/items.phtml
index a100910e82aaf..72e2a899e18f0 100644
--- a/app/code/Magento/Sales/view/frontend/templates/order/items.phtml
+++ b/app/code/Magento/Sales/view/frontend/templates/order/items.phtml
@@ -6,13 +6,19 @@
// @codingStandardsIgnoreFile
+/** @var \Magento\Sales\Block\Order\Items $block */
?>
-getOrder() ?>
-
-
-
-
-
+
+
+
+
+ isPagerDisplayed()): ?>
+
+
+
+
|
|
@@ -20,55 +26,58 @@
|
|
-
- getItemsCollection(); ?>
-
- count(); ?>
-
-
- getParentItem()) {
- continue;
-} ?>
-
- getItemHtml($_item) ?>
- helper('Magento\GiftMessage\Helper\Message')->isMessagesAllowed('order_item', $_item) && $_item->getGiftMessageId()): ?>
- helper('Magento\GiftMessage\Helper\Message')->getGiftMessageForEntity($_item); ?>
+
+ getItems(); ?>
+
+
+ getParentItem()) continue; ?>
+
+ getItemHtml($item) ?>
+ helper('Magento\GiftMessage\Helper\Message')->isMessagesAllowed('order_item', $item) && $item->getGiftMessageId()): ?>
+ helper('Magento\GiftMessage\Helper\Message')->getGiftMessageForEntity($item); ?>
+ id="order-item-gift-message-link-getId() ?>"
+ class="action show"
+ aria-controls="order-item-gift-message-getId() ?>"
+ data-item-id="getId() ?>">
- helper('Magento\GiftMessage\Helper\Message')->getGiftMessageForEntity($_item); ?>
-
+ helper('Magento\GiftMessage\Helper\Message')->getGiftMessageForEntity($item); ?>
+
- - escapeHtml($_giftMessage->getSender()) ?>
- - escapeHtml($_giftMessage->getRecipient()) ?>
- - helper('Magento\GiftMessage\Helper\Message')->getEscapedGiftMessage($_item) ?>
+ - escapeHtml($giftMessage->getSender()) ?>
+ - escapeHtml($giftMessage->getRecipient()) ?>
+ - helper('Magento\GiftMessage\Helper\Message')->getEscapedGiftMessage($item) ?>
|
-
-
-
+
+
+
+ isPagerDisplayed()): ?>
+
+
+
+
getChildHtml('order_totals') ?>
-
-
-
-
-