diff --git a/app/code/Magento/Bundle/Model/Product/Price.php b/app/code/Magento/Bundle/Model/Product/Price.php index d7dd23bc8931e46a74cc4eb728eaa4858522fa0d..73902761e14a527539f29719f6ba7dc30cdc726c 100644 --- a/app/code/Magento/Bundle/Model/Product/Price.php +++ b/app/code/Magento/Bundle/Model/Product/Price.php @@ -118,9 +118,8 @@ class Price extends \Magento\Catalog\Model\Product\Type\Price { $price = 0.0; if ($product->hasCustomOptions()) { - $customOption = $product->getCustomOption('bundle_selection_ids'); - if ($customOption) { - $selectionIds = unserialize($customOption->getValue()); + $selectionIds = $this->getBundleSelectionIds($product); + if ($selectionIds) { $selections = $product->getTypeInstance()->getSelectionsByIds($selectionIds, $product); $selections->addTierPriceData(); $this->_eventManager->dispatch( @@ -145,6 +144,24 @@ class Price extends \Magento\Catalog\Model\Product\Type\Price return $price; } + /** + * Retrieve array of bundle selection IDs + * + * @param \Magento\Catalog\Model\Product $product + * @return array + */ + protected function getBundleSelectionIds(\Magento\Catalog\Model\Product $product) + { + $customOption = $product->getCustomOption('bundle_selection_ids'); + if ($customOption) { + $selectionIds = unserialize($customOption->getValue()); + if (!empty($selectionIds) && is_array($selectionIds)) { + return $selectionIds; + } + } + return []; + } + /** * Get product final price * diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php index 226418b97aed883cabefb2c24e889633c15a5cf0..887d772ea403248fba1ae574e3f5864d0a00fe6b 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/PriceTest.php @@ -146,4 +146,121 @@ class PriceTest extends \PHPUnit_Framework_TestCase [10, 100, 1, true, 10], ]; } + + public function testGetTotalBundleItemsPriceWithNoCustomOptions() + { + $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->once()) + ->method('hasCustomOptions') + ->willReturn(false); + + $this->assertEquals(0, $this->model->getTotalBundleItemsPrice($productMock)); + } + + /** + * @param string|null $value + * @dataProvider dataProviderWithEmptyOptions + */ + public function testGetTotalBundleItemsPriceWithEmptyOptions($value) + { + $dataObjectMock = $this->getMockBuilder('Magento\Framework\DataObject') + ->setMethods(['getValue']) + ->disableOriginalConstructor() + ->getMock(); + + $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->once()) + ->method('hasCustomOptions') + ->willReturn(true); + $productMock->expects($this->once()) + ->method('getCustomOption') + ->with('bundle_selection_ids') + ->willReturn($dataObjectMock); + + $dataObjectMock->expects($this->once()) + ->method('getValue') + ->willReturn($value); + + $this->assertEquals(0, $this->model->getTotalBundleItemsPrice($productMock)); + } + + /** + * @return array + */ + public function dataProviderWithEmptyOptions() + { + return [ + ['a:0:{}'], + [''], + [null], + ]; + } + + public function testGetTotalBundleItemsPriceWithNoItems() + { + $storeId = 1; + + $dataObjectMock = $this->getMockBuilder('Magento\Framework\DataObject') + ->setMethods(['getValue']) + ->disableOriginalConstructor() + ->getMock(); + + $productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->disableOriginalConstructor() + ->getMock(); + + $productTypeMock = $this->getMockBuilder('Magento\Bundle\Model\Product\Type') + ->disableOriginalConstructor() + ->getMock(); + + $selectionsMock = $this->getMockBuilder('Magento\Bundle\Model\ResourceModel\Selection\Collection') + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->once()) + ->method('hasCustomOptions') + ->willReturn(true); + $productMock->expects($this->once()) + ->method('getCustomOption') + ->with('bundle_selection_ids') + ->willReturn($dataObjectMock); + $productMock->expects($this->once()) + ->method('getTypeInstance') + ->willReturn($productTypeMock); + $productMock->expects($this->once()) + ->method('getStoreId') + ->willReturn($storeId); + + $dataObjectMock->expects($this->once()) + ->method('getValue') + ->willReturn('a:1:{i:0;s:1:"1";}'); + + $productTypeMock->expects($this->once()) + ->method('getSelectionsByIds') + ->with([1], $productMock) + ->willReturn($selectionsMock); + + $selectionsMock->expects($this->once()) + ->method('addTierPriceData') + ->willReturnSelf(); + $selectionsMock->expects($this->once()) + ->method('getItems') + ->willReturn([]); + + $this->eventManagerMock->expects($this->once()) + ->method('dispatch') + ->with( + 'prepare_catalog_product_collection_prices', + ['collection' => $selectionsMock, 'store_id' => $storeId] + ) + ->willReturnSelf(); + + $this->assertEquals(0, $this->model->getTotalBundleItemsPrice($productMock)); + } } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php index 0393bf02276257507ebd9f392ef6b499a7866bee..15421607a696fe8e09d9efeddc85c9505dcb4942 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php @@ -133,22 +133,6 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Collection\Abstrac */ protected $_priceDataFieldFilters = []; - /** - * Map of price fields - * - * @var array - */ - protected $_map = [ - 'fields' => [ - 'price' => 'price_index.price', - 'final_price' => 'price_index.final_price', - 'min_price' => 'price_index.min_price', - 'max_price' => 'price_index.max_price', - 'tier_price' => 'price_index.tier_price', - 'special_price' => 'price_index.special_price', - ], - ]; - /** * Price expression sql * diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 500a104861d3bd1f8e74d1454c24dddf30adeab8..06be21a82e3c108edd8838b8834c7b1ac1676051 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -513,6 +513,13 @@ class AccountManagement implements AccountManagementInterface $customer->setStoreId($storeId); } + // Update 'created_in' value with actual store name + if ($customer->getId() === null) { + $storeName = $this->storeManager->getStore($customer->getStoreId()) + ->getName(); + $customer->setCreatedIn($storeName); + } + $customerAddresses = $customer->getAddresses() ?: []; $customer->setAddresses(null); try { diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index d5fc01b379051a1a0f0fe415e6d88c7a4528627f..62d7232bda0f2145e84cb56a94970882295f366a 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -265,7 +265,7 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase ->method('getDefaultStore') ->willReturn($store); $customer = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface')->getMock(); - $customer->expects($this->once()) + $customer->expects($this->atLeastOnce()) ->method('getId') ->willReturn($customerId); $customer->expects($this->once()) @@ -341,7 +341,7 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase ->method('getDefaultStore') ->willReturn($store); $customer = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface')->getMock(); - $customer->expects($this->once()) + $customer->expects($this->atLeastOnce()) ->method('getId') ->willReturn($customerId); $customer->expects($this->once()) @@ -478,6 +478,61 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase $this->accountManagement->createAccountWithPasswordHash($customer, $hash); } + /** + * @expectedException \Magento\Framework\Exception\LocalizedException + */ + public function testCreateAccountWithPasswordHashWithNewCustomerAndLocalizedException() + { + $storeId = 1; + $storeName = 'store_name'; + $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; + + $customerMock = $this->getMockBuilder('Magento\Customer\Api\Data\CustomerInterface') + ->getMockForAbstractClass(); + + $customerMock->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn(null); + $customerMock->expects($this->atLeastOnce()) + ->method('getStoreId') + ->willReturn($storeId); + $customerMock->expects($this->once()) + ->method('setCreatedIn') + ->with($storeName) + ->willReturnSelf(); + $customerMock->expects($this->once()) + ->method('getAddresses') + ->willReturn([]); + $customerMock->expects($this->once()) + ->method('setAddresses') + ->with(null) + ->willReturnSelf(); + + $storeMock = $this->getMockBuilder('Magento\Store\Model\Store') + ->disableOriginalConstructor() + ->getMock(); + + $storeMock->expects($this->once()) + ->method('getName') + ->willReturn($storeName); + + $this->storeManager->expects($this->once()) + ->method('getStore') + ->with($storeId) + ->willReturn($storeMock); + + $exception = new \Magento\Framework\Exception\LocalizedException( + new \Magento\Framework\Phrase('Exception message') + ); + $this->customerRepository + ->expects($this->once()) + ->method('save') + ->with($customerMock, $hash) + ->willThrowException($exception); + + $this->accountManagement->createAccountWithPasswordHash($customerMock, $hash); + } + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ diff --git a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php index 6cf06f839c175efd29b42a98d63b1ecf8f959b82..ef92b5194c5d004e1fbbaa8bc4b86f0c14a78292 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/Customer.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/Customer.php @@ -5,6 +5,7 @@ */ namespace Magento\CustomerImportExport\Model\Import; +use Magento\Customer\Api\Data\CustomerInterface; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; /** @@ -135,25 +136,25 @@ class Customer extends AbstractCustomer /** * Customer fields in file */ - public $customerFields = [ - 'group_id', - 'store_id', - 'updated_at', - 'created_at', - 'created_in', - 'prefix', - 'firstname', - 'middlename', - 'lastname', - 'suffix', - 'dob', + protected $customerFields = [ + CustomerInterface::GROUP_ID, + CustomerInterface::STORE_ID, + CustomerInterface::UPDATED_AT, + CustomerInterface::CREATED_AT, + CustomerInterface::CREATED_IN, + CustomerInterface::PREFIX, + CustomerInterface::FIRSTNAME, + CustomerInterface::MIDDLENAME, + CustomerInterface::LASTNAME, + CustomerInterface::SUFFIX, + CustomerInterface::DOB, 'password_hash', - 'taxvat', - 'confirmation', - 'gender', + CustomerInterface::TAXVAT, + CustomerInterface::CONFIRMATION, + CustomerInterface::GENDER, 'rp_token', 'rp_token_created_at', - ]; + ]; /** * @param \Magento\Framework\Stdlib\StringUtils $string @@ -237,11 +238,6 @@ class Customer extends AbstractCustomer $this->_initStores(true)->_initAttributes(); - $this->validColumnNames = array_merge( - $this->validColumnNames, - $this->customerFields - ); - $this->_customerModel = $customerFactory->create(); /** @var $customerResource \Magento\Customer\Model\ResourceModel\Customer */ $customerResource = $this->_customerModel->getResource(); @@ -562,4 +558,17 @@ class Customer extends AbstractCustomer { return $this->_entityTable; } + + /** + * @inheritDoc + */ + public function getValidColumnNames() + { + $this->validColumnNames = array_merge( + $this->validColumnNames, + $this->customerFields + ); + + return $this->validColumnNames; + } } diff --git a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php index ed7d2f8fe9e85b92ffaf8da22c75b85fb9ffa7b2..a42167fb68134b428490f5f6f804852340899c22 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php @@ -224,13 +224,6 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit } $this->_initAddressAttributes(); - $this->validColumnNames = array_merge( - $this->validColumnNames, - $this->_customerAttributes, - $this->_addressAttributes, - $this->_customerEntity->customerFields - ); - // next customer id if (isset($data['next_customer_id'])) { $this->_nextCustomerId = $data['next_customer_id']; @@ -489,4 +482,19 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit return parent::_prepareRowForDb($rowData); } + + /** + * @inheritDoc + */ + public function getValidColumnNames() + { + $this->validColumnNames = array_merge( + $this->validColumnNames, + $this->_customerAttributes, + $this->_addressAttributes, + $this->_customerEntity->getValidColumnNames() + ); + + return $this->validColumnNames; + } } diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php index 14147d6849de94bee388891d8ecfe389fd252ee5..c52d87b51b419a9e607e6f0a85abb0ae93420414 100644 --- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php +++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php @@ -1296,11 +1296,11 @@ abstract class AbstractEntity extends AbstractResource implements EntityInterfac } elseif (!is_numeric($v) && $v !== $origData[$k] || is_numeric($v) && $v != $origData[$k]) { $update[$attrId] = [ 'value_id' => $attribute->getBackend()->getEntityValueId($newObject), - 'value' => $v, + 'value' => is_array($v) ? array_shift($v) : $v,//@TODO: MAGETWO-44182, ]; } } elseif (!$this->_isAttributeValueEmpty($attribute, $v)) { - $insert[$attrId] = $v; + $insert[$attrId] = is_array($v) ? array_shift($v) : $v;//@TODO: MAGETWO-44182 } } diff --git a/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php index e9b684c2bd2a9aeb74dbbc6368c7ff6c0e6b71a5..085c9261e341229fb19bebc078874f87e9dff561 100644 --- a/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/AbstractEntity.php @@ -792,7 +792,7 @@ abstract class AbstractEntity $emptyHeaderColumns[] = $columnNumber; } elseif (!preg_match('/^[a-z][a-z0-9_]*$/', $columnName)) { $invalidColumns[] = $columnName; - } elseif ($this->needColumnCheck && !in_array($columnName, $this->validColumnNames)) { + } elseif ($this->needColumnCheck && !in_array($columnName, $this->getValidColumnNames())) { $invalidAttributes[] = $columnName; } } @@ -854,4 +854,14 @@ abstract class AbstractEntity $this->countItemsDeleted = count($deleted); return $this; } + + /** + * Retrieve valid column names + * + * @return array + */ + public function getValidColumnNames() + { + return $this->validColumnNames; + } } diff --git a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php index 81422c45e13a871f8162a0535802db1cf96a2df5..9a0971d18e1042fea2339d50508d0816e2cbdac9 100644 --- a/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php +++ b/app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php @@ -763,7 +763,7 @@ abstract class AbstractEntity $emptyHeaderColumns[] = $columnNumber; } elseif (!preg_match('/^[a-z][a-z0-9_]*$/', $columnName)) { $invalidColumns[] = $columnName; - } elseif ($this->needColumnCheck && !in_array($columnName, $this->validColumnNames)) { + } elseif ($this->needColumnCheck && !in_array($columnName, $this->getValidColumnNames())) { $invalidAttributes[] = $columnName; } } @@ -818,4 +818,14 @@ abstract class AbstractEntity { return $this->countItemsDeleted; } + + /** + * Retrieve valid column names + * + * @return array + */ + public function getValidColumnNames() + { + return $this->validColumnNames; + } } diff --git a/app/code/Magento/Theme/view/base/page_layout/empty.xml b/app/code/Magento/Theme/view/base/page_layout/empty.xml index 09d5658a86c4b9e38d7d2b8c83646555b2a97c10..d69d34f79e64a5407baddca36d65d3455099cc5e 100644 --- a/app/code/Magento/Theme/view/base/page_layout/empty.xml +++ b/app/code/Magento/Theme/view/base/page_layout/empty.xml @@ -16,7 +16,7 @@ <container name="main" label="Main Content Container" htmlTag="div" htmlClass="column main"/> </container> </container> - <container name="page.bottom" as="page_bottom" label="Before Page Footer Container" after="main.content" htmlTag="div" htmlClass="page-bottom"/> + <container name="page.bottom.container" as="page_bottom_container" label="Before Page Footer Container" after="main.content" htmlTag="div" htmlClass="page-bottom"/> <container name="before.body.end" as="before_body_end" after="-" label="Page Bottom"/> </container> </container> diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js index 6c5de791d1e87337876b2919c7b1c6180729ff1a..1260a366cc07a2434cc1b5306f8d6dc2711a4f20 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/multiselect.js @@ -20,8 +20,10 @@ define([ * * @returns {Array} */ - normalizeData: function () { - var value = this._super(); + normalizeData: function (value) { + if (utils.isEmpty(value)) { + value = []; + } return _.isString(value) ? value.split(',') : value; }, diff --git a/app/code/Magento/Wishlist/CustomerData/Wishlist.php b/app/code/Magento/Wishlist/CustomerData/Wishlist.php index 2c4379872b8abf1136d02b1fc068c71afbf6c661..c937e334992c272815cd03f1cd2ee74daab80286 100644 --- a/app/code/Magento/Wishlist/CustomerData/Wishlist.php +++ b/app/code/Magento/Wishlist/CustomerData/Wishlist.php @@ -3,7 +3,6 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Wishlist\CustomerData; use Magento\Customer\CustomerData\SectionSourceInterface; @@ -24,9 +23,9 @@ class Wishlist implements SectionSourceInterface protected $wishlistHelper; /** - * @var \Magento\Catalog\Helper\Image + * @var \Magento\Catalog\Helper\ImageFactory */ - protected $imageHelper; + protected $imageHelperFactory; /** * @var \Magento\Framework\App\ViewInterface @@ -41,17 +40,17 @@ class Wishlist implements SectionSourceInterface /** * @param \Magento\Wishlist\Helper\Data $wishlistHelper * @param \Magento\Wishlist\Block\Customer\Sidebar $block - * @param \Magento\Catalog\Helper\Image $imageHelper + * @param \Magento\Catalog\Helper\ImageFactory $imageHelperFactory * @param \Magento\Framework\App\ViewInterface $view */ public function __construct( \Magento\Wishlist\Helper\Data $wishlistHelper, \Magento\Wishlist\Block\Customer\Sidebar $block, - \Magento\Catalog\Helper\Image $imageHelper, + \Magento\Catalog\Helper\ImageFactory $imageHelperFactory, \Magento\Framework\App\ViewInterface $view ) { $this->wishlistHelper = $wishlistHelper; - $this->imageHelper = $imageHelper; + $this->imageHelperFactory = $imageHelperFactory; $this->block = $block; $this->view = $view; } @@ -100,35 +99,77 @@ class Wishlist implements SectionSourceInterface protected function getItems() { $this->view->loadLayout(); + $collection = $this->wishlistHelper->getWishlistItemCollection(); $collection->clear()->setPageSize(self::SIDEBAR_ITEMS_NUMBER) ->setInStockFilter(true)->setOrder('added_at'); + $items = []; - /** @var \Magento\Wishlist\Model\Item $wishlistItem */ foreach ($collection as $wishlistItem) { - $product = $wishlistItem->getProduct(); - $this->imageHelper->init($product, 'wishlist_sidebar_block'); - $items[] = [ - 'image' => [ - 'src' => $this->imageHelper->getUrl(), - 'alt' => $this->imageHelper->getLabel(), - 'width' => $this->imageHelper->getWidth(), - 'height' => $this->imageHelper->getHeight(), - ], - 'product_url' => $this->wishlistHelper->getProductUrl($wishlistItem), - 'product_name' => $product->getName(), - 'product_price' => $this->block->getProductPriceHtml( - $product, - \Magento\Catalog\Pricing\Price\ConfiguredPriceInterface::CONFIGURED_PRICE_CODE, - \Magento\Framework\Pricing\Render::ZONE_ITEM_LIST, - ['item' => $wishlistItem] - ), - 'product_is_saleable_and_visible' => $product->isSaleable() && $product->isVisibleInSiteVisibility(), - 'product_has_required_options' => $product->getTypeInstance()->hasRequiredOptions($product), - 'add_to_cart_params' => $this->wishlistHelper->getAddToCartParams($wishlistItem, true), - 'delete_item_params' => $this->wishlistHelper->getRemoveParams($wishlistItem, true), - ]; + $items[] = $this->getItemData($wishlistItem); } return $items; } + + /** + * Retrieve wishlist item data + * + * @param \Magento\Wishlist\Model\Item $wishlistItem + * @return array + */ + protected function getItemData(\Magento\Wishlist\Model\Item $wishlistItem) + { + $product = $wishlistItem->getProduct(); + return [ + 'image' => $this->getImageData($product), + 'product_url' => $this->wishlistHelper->getProductUrl($wishlistItem), + 'product_name' => $product->getName(), + 'product_price' => $this->block->getProductPriceHtml( + $product, + \Magento\Catalog\Pricing\Price\ConfiguredPriceInterface::CONFIGURED_PRICE_CODE, + \Magento\Framework\Pricing\Render::ZONE_ITEM_LIST, + ['item' => $wishlistItem] + ), + 'product_is_saleable_and_visible' => $product->isSaleable() && $product->isVisibleInSiteVisibility(), + 'product_has_required_options' => $product->getTypeInstance()->hasRequiredOptions($product), + 'add_to_cart_params' => $this->wishlistHelper->getAddToCartParams($wishlistItem, true), + 'delete_item_params' => $this->wishlistHelper->getRemoveParams($wishlistItem, true), + ]; + } + + /** + * Retrieve product image data + * + * @param \Magento\Catalog\Model\Product $product + * @return \Magento\Catalog\Block\Product\Image + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + protected function getImageData($product) + { + /** @var \Magento\Catalog\Helper\Image $helper */ + $helper = $this->imageHelperFactory->create() + ->init($product, 'wishlist_sidebar_block'); + + $template = $helper->getFrame() + ? 'Magento_Catalog/product/image' + : 'Magento_Catalog/product/image_with_borders'; + + $imagesize = $helper->getResizedImageInfo(); + + $width = $helper->getFrame() + ? $helper->getWidth() + : (!empty($imagesize[0]) ? $imagesize[0] : $helper->getWidth()); + + $height = $helper->getFrame() + ? $helper->getHeight() + : (!empty($imagesize[1]) ? $imagesize[1] : $helper->getHeight()); + + return [ + 'template' => $template, + 'src' => $helper->getUrl(), + 'width' => $width, + 'height' => $height, + 'alt' => $helper->getLabel(), + ]; + } } diff --git a/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php b/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php index 24368820dc4df78f31f2bb407631a4a7caadd564..470be780e1269ea0f56088a151171820e67c1368 100644 --- a/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php +++ b/app/code/Magento/Wishlist/Test/Unit/CustomerData/WishlistTest.php @@ -46,16 +46,24 @@ class WishlistTest extends \PHPUnit_Framework_TestCase $this->sidebarMock = $this->getMockBuilder('Magento\Wishlist\Block\Customer\Sidebar') ->disableOriginalConstructor() ->getMock(); + $this->viewMock = $this->getMockBuilder('Magento\Framework\App\ViewInterface') + ->getMockForAbstractClass(); + $this->catalogImageHelperMock = $this->getMockBuilder('Magento\Catalog\Helper\Image') ->disableOriginalConstructor() ->getMock(); - $this->viewMock = $this->getMockBuilder('Magento\Framework\App\ViewInterface') - ->getMockForAbstractClass(); + $imageHelperFactory = $this->getMockBuilder('Magento\Catalog\Helper\ImageFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $imageHelperFactory->expects($this->any()) + ->method('create') + ->willReturn($this->catalogImageHelperMock); $this->model = new Wishlist( $this->wishlistHelperMock, $this->sidebarMock, - $this->catalogImageHelperMock, + $imageHelperFactory, $this->viewMock ); } @@ -83,6 +91,7 @@ class WishlistTest extends \PHPUnit_Framework_TestCase 'items' => [ [ 'image' => [ + 'template' => 'Magento_Catalog/product/image', 'src' => $imageUrl, 'alt' => $imageLabel, 'width' => $imageWidth, @@ -165,6 +174,12 @@ class WishlistTest extends \PHPUnit_Framework_TestCase $this->catalogImageHelperMock->expects($this->once()) ->method('getHeight') ->willReturn($imageHeight); + $this->catalogImageHelperMock->expects($this->any()) + ->method('getFrame') + ->willReturn(true); + $this->catalogImageHelperMock->expects($this->once()) + ->method('getResizedImageInfo') + ->willReturn([]); $this->wishlistHelperMock->expects($this->once()) ->method('getProductUrl') @@ -251,6 +266,7 @@ class WishlistTest extends \PHPUnit_Framework_TestCase 'items' => [ [ 'image' => [ + 'template' => 'Magento_Catalog/product/image', 'src' => $imageUrl, 'alt' => $imageLabel, 'width' => $imageWidth, @@ -266,6 +282,7 @@ class WishlistTest extends \PHPUnit_Framework_TestCase ], [ 'image' => [ + 'template' => 'Magento_Catalog/product/image', 'src' => $imageUrl, 'alt' => $imageLabel, 'width' => $imageWidth, @@ -342,6 +359,12 @@ class WishlistTest extends \PHPUnit_Framework_TestCase $this->catalogImageHelperMock->expects($this->exactly(2)) ->method('getHeight') ->willReturn($imageHeight); + $this->catalogImageHelperMock->expects($this->any()) + ->method('getFrame') + ->willReturn(true); + $this->catalogImageHelperMock->expects($this->exactly(2)) + ->method('getResizedImageInfo') + ->willReturn([]); $this->wishlistHelperMock->expects($this->exactly(2)) ->method('getProductUrl') diff --git a/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml b/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml index bab2e79a75f3310e63bbe5352f47818e81cd74a0..1d7eb6e7dcc73247b72d1999701a863eb97aaf7c 100644 --- a/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml +++ b/app/code/Magento/Wishlist/view/frontend/templates/sidebar.phtml @@ -26,7 +26,7 @@ $wishlistHelper = $this->helper('Magento\Wishlist\Helper\Data'); <li class="product-item"> <div class="product-item-info"> <a class="product-item-photo" data-bind="attr: { href: product_url, title: product_name }"> - <!-- ko template: {name: 'Magento_Wishlist/product_image', data: $data.image} --><!-- /ko --> + <!-- ko template: {name: $data.image.template, data: $data.image} --><!-- /ko --> </a> <div class="product-item-details"> <strong class="product-item-name"> diff --git a/app/code/Magento/Wishlist/view/frontend/web/template/product_image.html b/app/code/Magento/Wishlist/view/frontend/web/template/product_image.html deleted file mode 100644 index da88b3236c986563e459da8021213663f556158a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Wishlist/view/frontend/web/template/product_image.html +++ /dev/null @@ -1,7 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<img class="photo image" data-bind="attr: {src: src, alt: alt}, style: {width: width + 'px', height: height + 'px'}" /> diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php index 65c3aae162bf6ebbf6a8e1a66613c99bb5f8cfac..077f18fbe2cf355d3e95bf698df3e7234d101647 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php @@ -587,7 +587,6 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase 'email' => $email, 'firstname' => $firstName, 'lastname' => $lastName, - 'created_in' => 'Admin', 'id' => null ] ); @@ -603,7 +602,6 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase $this->assertEquals($email, $customerAfter->getEmail()); $this->assertEquals($firstName, $customerAfter->getFirstname()); $this->assertEquals($lastName, $customerAfter->getLastname()); - $this->assertEquals('Admin', $customerAfter->getCreatedIn()); $this->accountManagement->authenticate( $customerAfter->getEmail(), 'aPassword' @@ -807,7 +805,6 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase $customerEntity->setEmail($email) ->setFirstname($firstName) ->setLastname($lastname) - ->setCreatedIn('Admin') ->setId(null); $customer = $this->accountManagement->createAccount($customerEntity, 'aPassword'); @@ -815,7 +812,6 @@ class AccountManagementTest extends \PHPUnit_Framework_TestCase $this->assertEquals($email, $customer->getEmail()); $this->assertEquals($firstName, $customer->getFirstname()); $this->assertEquals($lastname, $customer->getLastname()); - $this->assertEquals('Admin', $customer->getCreatedIn()); $this->accountManagement->authenticate( $customer->getEmail(), 'aPassword', diff --git a/lib/internal/Magento/Framework/Module/DependencyChecker.php b/lib/internal/Magento/Framework/Module/DependencyChecker.php index 44f771fb6ca2083bb7363542cb11d2e2488d318a..71c811daf3c46c390e34299dd82647e052ddf8a9 100644 --- a/lib/internal/Magento/Framework/Module/DependencyChecker.php +++ b/lib/internal/Magento/Framework/Module/DependencyChecker.php @@ -33,6 +33,11 @@ class DependencyChecker */ private $graph; + /** + * @var PackageInfo + */ + protected $packageInfo; + /** * Constructor * @@ -44,8 +49,8 @@ class DependencyChecker { $this->enabledModuleList = $list->getNames(); $this->fullModuleList = $loader->load(); - $packageInfo = $packageInfoFactory->create(); - $this->graph = $this->createGraph($packageInfo); + $this->packageInfo = $packageInfoFactory->create(); + $this->graph = $this->createGraph(); } /** @@ -93,7 +98,11 @@ class DependencyChecker foreach ($moduleNames as $moduleName) { $dependenciesMissing = []; $paths = $this->graph->findPathsToReachableNodes($moduleName, $graphMode); - foreach (array_keys($this->fullModuleList) as $module) { + $modules = array_merge( + array_keys($this->fullModuleList), + $this->packageInfo->getNonExistingDependencies() + ); + foreach ($modules as $module) { if (isset($paths[$module])) { if ($isEnable && !in_array($module, $enabledModules)) { $dependenciesMissing[$module] = $paths[$module]; @@ -110,10 +119,9 @@ class DependencyChecker /** * Create the dependency graph * - * @param PackageInfo $packageInfo * @return Graph */ - private function createGraph(PackageInfo $packageInfo) + private function createGraph() { $nodes = []; $dependencies = []; @@ -121,13 +129,15 @@ class DependencyChecker // build the graph data foreach (array_keys($this->fullModuleList) as $moduleName) { $nodes[] = $moduleName; - foreach ($packageInfo->getRequire($moduleName) as $dependModuleName) { + foreach ($this->packageInfo->getRequire($moduleName) as $dependModuleName) { if ($dependModuleName) { $dependencies[] = [$moduleName, $dependModuleName]; } } } - $nodes = array_unique($nodes); + $nodes = array_unique( + array_merge($nodes, $this->packageInfo->getNonExistingDependencies()) + ); return new Graph($nodes, $dependencies); } diff --git a/lib/internal/Magento/Framework/Module/PackageInfo.php b/lib/internal/Magento/Framework/Module/PackageInfo.php index 97fd828c36d6c3f0540ff8d37808fa172c5f5213..1e2ed5064c8e69bb067e82ae2173ef01b5e1f59a 100644 --- a/lib/internal/Magento/Framework/Module/PackageInfo.php +++ b/lib/internal/Magento/Framework/Module/PackageInfo.php @@ -53,6 +53,11 @@ class PackageInfo */ private $componentRegistrar; + /** + * @var array + */ + protected $nonExistingDependencies = []; + /** * Constructor * @@ -104,7 +109,65 @@ class PackageInfo public function getModuleName($packageName) { $this->load(); - return isset($this->packageModuleMap[$packageName]) ? $this->packageModuleMap[$packageName] : ''; + + $moduleName = null; + if (isset($this->packageModuleMap[$packageName])) { + $moduleName = $this->packageModuleMap[$packageName]; + } elseif ($this->isMagentoPackage($packageName)) { + $moduleName = $this->convertPackageNameToModuleName($packageName); + $this->addNonExistingDependency($moduleName); + } + + return $moduleName; + } + + /** + * Add non existing dependency + * + * @param string $dependency + * @return void + */ + protected function addNonExistingDependency($dependency) + { + if (!isset($this->nonExistingDependencies[$dependency])) { + $this->nonExistingDependencies[$dependency] = $dependency; + } + } + + /** + * Return list of non existing dependencies + * + * @return array + */ + public function getNonExistingDependencies() + { + return $this->nonExistingDependencies; + } + + /** + * Build module name based on internal package name + * + * @param string $packageName + * @return string|null + */ + protected function convertPackageNameToModuleName($packageName) + { + $moduleName = str_replace('magento/module-', '', $packageName); + $moduleName = str_replace('-', ' ', $moduleName); + $moduleName = str_replace(' ', '', ucwords($moduleName)); + + return 'Magento_' . $moduleName; + } + + /** + * Check if package is internal magento module + * + * @param string $packageName + * @return bool + */ + protected function isMagentoPackage($packageName) + { + return strpos($packageName, 'magento/module-') === 0; } /** diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/DependencyCheckerTest.php b/lib/internal/Magento/Framework/Module/Test/Unit/DependencyCheckerTest.php index eb09d4a41ac3bfdfae6e5d06cf44bfba8444b62a..0d7774d8ddad8fef157ddfc18fdf865d1ecd76c9 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/DependencyCheckerTest.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/DependencyCheckerTest.php @@ -70,10 +70,12 @@ class DependencyCheckerTest extends \PHPUnit_Framework_TestCase public function testCheckDependenciesWhenDisableModules() { - $this->listMock - ->expects($this->any()) + $this->listMock->expects($this->any()) ->method('getNames') ->will($this->returnValue(['A', 'B', 'C', 'D', 'E'])); + $this->packageInfoMock->expects($this->atLeastOnce()) + ->method('getNonExistingDependencies') + ->willReturn([]); $this->checker = new DependencyChecker($this->listMock, $this->loaderMock, $this->packageInfoFactoryMock); $actual = $this->checker->checkDependenciesWhenDisableModules(['B', 'D']); @@ -83,6 +85,9 @@ class DependencyCheckerTest extends \PHPUnit_Framework_TestCase public function testCheckDependenciesWhenDisableModulesWithCurEnabledModules() { + $this->packageInfoMock->expects($this->atLeastOnce()) + ->method('getNonExistingDependencies') + ->willReturn([]); $this->checker = new DependencyChecker($this->listMock, $this->loaderMock, $this->packageInfoFactoryMock); $actual = $this->checker->checkDependenciesWhenDisableModules(['B', 'D'], ['C', 'D', 'E']); @@ -92,10 +97,12 @@ class DependencyCheckerTest extends \PHPUnit_Framework_TestCase public function testCheckDependenciesWhenEnableModules() { - $this->listMock - ->expects($this->any()) + $this->listMock->expects($this->any()) ->method('getNames') ->will($this->returnValue(['C'])); + $this->packageInfoMock->expects($this->atLeastOnce()) + ->method('getNonExistingDependencies') + ->willReturn([]); $this->checker = new DependencyChecker($this->listMock, $this->loaderMock, $this->packageInfoFactoryMock); $actual = $this->checker->checkDependenciesWhenEnableModules(['B', 'D']); $expected = [ @@ -107,6 +114,9 @@ class DependencyCheckerTest extends \PHPUnit_Framework_TestCase public function testCheckDependenciesWhenEnableModulesWithCurEnabledModules() { + $this->packageInfoMock->expects($this->atLeastOnce()) + ->method('getNonExistingDependencies') + ->willReturn([]); $this->checker = new DependencyChecker($this->listMock, $this->loaderMock, $this->packageInfoFactoryMock); $actual = $this->checker->checkDependenciesWhenEnableModules(['B', 'D'], ['C']); $expected = [ diff --git a/lib/internal/Magento/Framework/Module/Test/Unit/PackageInfoTest.php b/lib/internal/Magento/Framework/Module/Test/Unit/PackageInfoTest.php index 8a2512c485fd1f1d98cb02ab45019ebd9f3e4c43..4328b62c0c6ce30ee72ed23e5a9477f7f39b4859 100644 --- a/lib/internal/Magento/Framework/Module/Test/Unit/PackageInfoTest.php +++ b/lib/internal/Magento/Framework/Module/Test/Unit/PackageInfoTest.php @@ -57,6 +57,11 @@ class PackageInfoTest extends \PHPUnit_Framework_TestCase $this->assertEquals('C', $this->packageInfo->getModuleName('c')); $this->assertEquals('D', $this->packageInfo->getModuleName('d')); $this->assertEquals('E', $this->packageInfo->getModuleName('e')); + $this->assertEquals( + 'Magento_TestModuleName', + $this->packageInfo->getModuleName('magento/module-test-module-name') + ); + $this->assertArrayHasKey('Magento_TestModuleName', $this->packageInfo->getNonExistingDependencies()); } public function testGetPackageName() diff --git a/lib/internal/Magento/Framework/View/Template/Html/Minifier.php b/lib/internal/Magento/Framework/View/Template/Html/Minifier.php index af80583da16e7f37c084151650869ef3f7c39c89..6b9017a1972ce499a0fdd37a300e0d7d60386412 100644 --- a/lib/internal/Magento/Framework/View/Template/Html/Minifier.php +++ b/lib/internal/Magento/Framework/View/Template/Html/Minifier.php @@ -117,7 +117,7 @@ class Minifier implements MinifierInterface '</', preg_replace( '#((?:<\?php\s+(?!echo|print|if|elseif|else)[^\?]*)\?>)\s+#', - '$1', + '$1 ', preg_replace( '#(?<!' . implode('|', $this->inlineHtmlTags) . ')\> \<#', '><', diff --git a/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php b/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php index a93962b3ae7e689f4ef943e5273b9da9afd8cffc..e598a93c243a47b7cfdab23cad76c441f7d6c010 100644 --- a/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php +++ b/lib/internal/Magento/Framework/View/Test/Unit/Template/Html/MinifierTest.php @@ -117,7 +117,7 @@ class MinifierTest extends \PHPUnit_Framework_TestCase TEXT; $expectedContent = <<<TEXT -<?php /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ ?><?php ?><html><head><title>Test title</title></head><body><a href="http://somelink.com/text.html">Text Link</a> <img src="test.png" alt="some text" /><?php echo \$block->someMethod(); ?> <div style="width: 800px" class="<?php echo \$block->getClass() ?>" /><script> +<?php /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ ?> <?php ?> <html><head><title>Test title</title></head><body><a href="http://somelink.com/text.html">Text Link</a> <img src="test.png" alt="some text" /><?php echo \$block->someMethod(); ?> <div style="width: 800px" class="<?php echo \$block->getClass() ?>" /><script> //<![CDATA[ var someVar = 123; testFunctionCall(function () {