diff --git a/app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php b/app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php index b67cf4acd9f34..031c7f7ae3ec0 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php +++ b/app/code/Magento/Catalog/Model/ProductRepository/MediaGalleryProcessor.php @@ -82,6 +82,7 @@ public function __construct( * @throws InputException * @throws StateException * @throws LocalizedException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function processMediaGallery(ProductInterface $product, array $mediaGalleryEntries) :void { @@ -113,6 +114,9 @@ public function processMediaGallery(ProductInterface $product, array $mediaGalle // phpcs:ignore Magento2.Performance.ForeachArrayMerge $existingMediaGallery[$key] = array_merge($existingEntry, $updatedEntry); } + } elseif (!empty($newEntries) && isset($existingEntry['value_id'])) { + //avoid deleting an exiting image while adding a new one + unset($existingMediaGallery[$key]); } elseif ($this->canRemoveImage($product, $existingEntry)) { //set the removed flag $existingEntry['removed'] = true; diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductRepository/MediaGalleryProcessorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepository/MediaGalleryProcessorTest.php new file mode 100644 index 0000000000000..a57dd391a8cad --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductRepository/MediaGalleryProcessorTest.php @@ -0,0 +1,180 @@ +processorMock = $this->getMockBuilder(Processor::class) + ->disableOriginalConstructor() + ->getMock(); + $this->contentFactoryMock = $this->getMockBuilder(ImageContentInterfaceFactory::class) + ->disableOriginalConstructor() + ->getMock(); + $this->imageProcessorMock = $this->getMockBuilder(ImageProcessorInterface::class) + ->disableOriginalConstructor() + ->getMock(); + $this->deleteValidatorMock = $this->getMockBuilder(DeleteValidator::class) + ->disableOriginalConstructor() + ->getMock(); + $this->productMock = $this->getMockBuilder(Product::class) + ->addMethods(['getMediaGallery']) + ->onlyMethods(['hasGalleryAttribute', 'getMediaConfig', 'getMediaAttributes']) + ->disableOriginalConstructor() + ->getMock(); + + $this->galleryProcessor = new MediaGalleryProcessor( + $this->processorMock, + $this->contentFactoryMock, + $this->imageProcessorMock, + $this->deleteValidatorMock + ); + } + + /** + * The media gallery array should not have "removed" key while adding the new entry + * + * @return void + */ + public function testProcessMediaGallery(): void + { + $initialExitingEntry = [ + 'value_id' => 5, + "label" => "new_label_text", + 'file' => 'filename1', + 'position' => 10, + 'disabled' => false, + 'types' => ['image', 'small_image'] + ]; + $newEntriesData = [ + 'images' => [ + $initialExitingEntry, + [ + 'value_id' => null, + 'label' => "label_text", + 'position' => 10, + 'disabled' => false, + 'types' => ['image', 'small_image'], + 'content' => [ + 'data' => [ + ImageContentInterface::NAME => 'filename', + ImageContentInterface::TYPE => 'image/jpeg', + ImageContentInterface::BASE64_ENCODED_DATA => 'encoded_content' + ] + ], + 'media_type' => 'media_type' + ] + ] + ]; + $newExitingEntriesData = [ + 'images' => [ + $initialExitingEntry, + [ + 'value_id' => 6, + "label" => "label_text2", + 'file' => 'filename2', + 'position' => 10, + 'disabled' => false, + 'types' => ['image', 'small_image'] + ] + ] + ]; + $this->productMock->method('getMediaGallery') + ->willReturnOnConsecutiveCalls( + $newExitingEntriesData['images'], + $newExitingEntriesData['images'] + ); + $this->productMock->expects($this->any()) + ->method('getMediaAttributes') + ->willReturn(["image" => "imageAttribute", "small_image" => "small_image_attribute"]); + $this->productMock->method('hasGalleryAttribute')->willReturn(true); + $mediaTmpPath = '/tmp'; + $absolutePath = '/a/b/filename.jpg'; + $this->processorMock->expects($this->once())->method('clearMediaAttribute') + ->with($this->productMock, ['image', 'small_image']); + $mediaConfigMock = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock(); + $mediaConfigMock->expects($this->once())->method('getTmpMediaShortUrl')->with($absolutePath) + ->willReturn($mediaTmpPath . $absolutePath); + $this->productMock->expects($this->once())->method('getMediaConfig')->willReturn($mediaConfigMock); + //verify new entries + $contentDataObject = $this->getMockBuilder(ImageContent::class) + ->disableOriginalConstructor() + ->setMethods(null) + ->getMock(); + $this->contentFactoryMock->expects($this->once())->method('create')->willReturn($contentDataObject); + $this->imageProcessorMock->expects($this->once())->method('processImageContent')->willReturn($absolutePath); + $imageFileUri = $mediaTmpPath . $absolutePath; + $this->processorMock->expects($this->once())->method('addImage') + ->willReturnCallback( + function ($product, $imageFileUri) use ($newEntriesData) { + foreach ($product['media_gallery']['images'] as $entry) { + if (isset($entry['value_id'])) { + $this->assertArrayNotHasKey('removed', $entry); + } + } + $this->productMock->setData('media_gallery', $newEntriesData); + return $imageFileUri; + } + ); + $this->processorMock->expects($this->once())->method('updateImage') + ->with( + $this->productMock, + $imageFileUri, + [ + 'label' => 'label_text', + 'position' => 10, + 'disabled' => false, + 'media_type' => 'media_type', + ] + ); + $this->galleryProcessor->processMediaGallery($this->productMock, $newEntriesData['images']); + } +} diff --git a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Category/Move.php b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Category/Move.php index 5a5b805ba189e..67384df9e570e 100644 --- a/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Category/Move.php +++ b/app/code/Magento/CatalogUrlRewrite/Model/Category/Plugin/Category/Move.php @@ -9,7 +9,7 @@ use Magento\Catalog\Model\CategoryFactory; use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator; use Magento\CatalogUrlRewrite\Model\Category\ChildrenCategoriesProvider; -use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; /** * Perform url updating for children categories. @@ -31,19 +31,27 @@ class Move */ private $categoryFactory; + /** + * @var StoreManagerInterface + */ + private $storeManager; + /** * @param CategoryUrlPathGenerator $categoryUrlPathGenerator * @param ChildrenCategoriesProvider $childrenCategoriesProvider * @param CategoryFactory $categoryFactory + * @param StoreManagerInterface $storeManager */ public function __construct( CategoryUrlPathGenerator $categoryUrlPathGenerator, ChildrenCategoriesProvider $childrenCategoriesProvider, - CategoryFactory $categoryFactory + CategoryFactory $categoryFactory, + StoreManagerInterface $storeManager ) { $this->categoryUrlPathGenerator = $categoryUrlPathGenerator; $this->childrenCategoriesProvider = $childrenCategoriesProvider; $this->categoryFactory = $categoryFactory; + $this->storeManager = $storeManager; } /** @@ -67,6 +75,7 @@ public function afterChangeParent( $categoryStoreId = $category->getStoreId(); foreach ($category->getStoreIds() as $storeId) { $category->setStoreId($storeId); + $this->removeObsoleteUrlPathEntries($category); $this->updateCategoryUrlKeyForStore($category); $category->unsUrlPath(); $category->setUrlPath($this->categoryUrlPathGenerator->getUrlPath($category)); @@ -92,24 +101,13 @@ private function updateCategoryUrlKeyForStore(Category $category) $category->setUrlKey($item->getUrlKey()); } - /** - * Check is global scope. - * - * @param int|null $storeId - * @return bool - */ - private function isGlobalScope($storeId) - { - return null === $storeId || $storeId == Store::DEFAULT_STORE_ID; - } - /** * Updates url_path for child categories. * * @param Category $category * @return void */ - private function updateUrlPathForChildren($category) + private function updateUrlPathForChildren(Category $category): void { foreach ($this->childrenCategoriesProvider->getChildren($category, true) as $childCategory) { $childCategory->setStoreId($category->getStoreId()); @@ -118,4 +116,27 @@ private function updateUrlPathForChildren($category) $childCategory->getResource()->saveAttribute($childCategory, 'url_path'); } } + + /** + * Clean obsolete entries + * + * @param Category $category + * @return void + */ + private function removeObsoleteUrlPathEntries(Category $category): void + { + if ($this->storeManager->hasSingleStore()) { + return; + } + $origPath = $category->getOrigData('path'); + $path = $category->getData('path'); + if ($origPath != null && $path != null && $origPath != $path) { + $category->unsUrlPath(); + $category->getResource()->saveAttribute($category, 'url_path'); + foreach ($this->childrenCategoriesProvider->getChildren($category, true) as $childCategory) { + $childCategory->unsUrlPath(); + $childCategory->getResource()->saveAttribute($childCategory, 'url_path'); + } + } + } } diff --git a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Category/MoveTest.php b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Category/MoveTest.php index 44997591a6901..0a2341432bd84 100644 --- a/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Category/MoveTest.php +++ b/app/code/Magento/CatalogUrlRewrite/Test/Unit/Model/Category/Plugin/Category/MoveTest.php @@ -14,6 +14,7 @@ use Magento\CatalogUrlRewrite\Model\Category\Plugin\Category\Move as CategoryMovePlugin; use Magento\CatalogUrlRewrite\Model\CategoryUrlPathGenerator; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Store\Model\StoreManagerInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -49,6 +50,11 @@ class MoveTest extends TestCase */ private $categoryFactory; + /** + * @var StoreManagerInterface|MockObject + */ + private $storeManagerMock; + /** * @var CategoryMovePlugin */ @@ -59,28 +65,45 @@ protected function setUp(): void $this->objectManager = new ObjectManager($this); $this->categoryUrlPathGeneratorMock = $this->getMockBuilder(CategoryUrlPathGenerator::class) ->disableOriginalConstructor() - ->setMethods(['getUrlPath']) + ->onlyMethods(['getUrlPath']) ->getMock(); $this->childrenCategoriesProviderMock = $this->getMockBuilder(ChildrenCategoriesProvider::class) ->disableOriginalConstructor() - ->setMethods(['getChildren']) + ->onlyMethods(['getChildren']) ->getMock(); $this->categoryFactory = $this->getMockBuilder(CategoryFactory::class) ->disableOriginalConstructor() ->getMock(); $this->subjectMock = $this->getMockBuilder(CategoryResourceModel::class) ->disableOriginalConstructor() + ->onlyMethods(['saveAttribute']) ->getMock(); + $this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); $this->categoryMock = $this->getMockBuilder(Category::class) ->disableOriginalConstructor() - ->setMethods(['getResource', 'setUrlPath', 'getStoreIds', 'getStoreId', 'setStoreId']) + ->onlyMethods( + [ + 'getResource', + 'getStoreIds', + 'getStoreId', + 'setStoreId', + 'getData', + 'getOrigData', + 'getId', + 'getUrlKey' + ] + ) + ->addMethods(['setUrlPath', 'unsUrlPath', 'setUrlKey']) ->getMock(); $this->plugin = $this->objectManager->getObject( CategoryMovePlugin::class, [ 'categoryUrlPathGenerator' => $this->categoryUrlPathGeneratorMock, 'childrenCategoriesProvider' => $this->childrenCategoriesProviderMock, - 'categoryFactory' => $this->categoryFactory + 'categoryFactory' => $this->categoryFactory, + 'storeManager' => $this->storeManagerMock ] ); } @@ -92,27 +115,41 @@ public function testAfterChangeParent() { $urlPath = 'test/path'; $storeIds = [0, 1]; - $originalCategory = $this->getMockBuilder(Category::class) - ->disableOriginalConstructor() - ->getMock(); - $this->categoryFactory->method('create') - ->willReturn($originalCategory); - $this->categoryMock->method('getResource') - ->willReturn($this->subjectMock); - $this->categoryMock->expects($this->once()) - ->method('getStoreIds') - ->willReturn($storeIds); - $this->childrenCategoriesProviderMock->expects($this->exactly(2)) - ->method('getChildren') + + $this->storeManagerMock->expects($this->exactly(2))->method('hasSingleStore')->willReturn(false); + $this->categoryMock->expects($this->exactly(4))->method('getStoreId') + ->willReturnOnConsecutiveCalls(0, 0, 1, 0); + $this->categoryMock->expects($this->once())->method('getStoreIds')->willReturn($storeIds); + $this->categoryMock->expects($this->exactly(4))->method('setStoreId') + ->willReturnOnConsecutiveCalls(0, 0, 1, 0); + + $this->categoryMock->expects($this->exactly(2))->method('getData') + ->willReturnOnConsecutiveCalls('1/3/5', '1/3/5'); + $this->categoryMock->expects($this->exactly(2))->method('getOrigData') + ->willReturnOnConsecutiveCalls('1/2/5', '1/2/5'); + $this->categoryMock->expects($this->exactly(6))->method('unsUrlPath')->willReturnSelf(); + $this->childrenCategoriesProviderMock->expects($this->exactly(4))->method('getChildren') ->with($this->categoryMock, true) - ->willReturn([]); - $this->categoryUrlPathGeneratorMock->expects($this->exactly(2)) - ->method('getUrlPath') - ->with($this->categoryMock) - ->willReturn($urlPath); - $this->categoryMock->expects($this->exactly(2)) - ->method('setUrlPath') - ->with($urlPath); + ->willReturnOnConsecutiveCalls([$this->categoryMock], [$this->categoryMock], [], []); + + $this->categoryMock->expects($this->exactly(6))->method('getResource')->willReturn($this->subjectMock); + $this->subjectMock->expects($this->exactly(6))->method('saveAttribute') + ->with($this->categoryMock, 'url_path')->willReturnSelf(); + $this->categoryMock->expects($this->exactly(2))->method('getId')->willReturnSelf(); + + $originalCategory = $this->getMockBuilder(Category::class)->disableOriginalConstructor()->getMock(); + $originalCategory->expects($this->exactly(2))->method('getUrlKey')->willReturn('url-key'); + $originalCategory->expects($this->exactly(2))->method('setStoreId')->willReturnSelf(); + $originalCategory->expects($this->exactly(2))->method('load')->willReturnSelf(); + $this->categoryFactory->expects($this->exactly(2))->method('create') + ->willReturn($originalCategory); + $this->categoryMock->expects($this->exactly(2))->method('setUrlKey')->with('url-key') + ->willReturnSelf(); + + $this->categoryUrlPathGeneratorMock->expects($this->exactly(3))->method('getUrlPath') + ->with($this->categoryMock)->willReturn($urlPath); + $this->categoryMock->expects($this->exactly(3))->method('setUrlPath')->with($urlPath); + $this->assertSame( $this->subjectMock, $this->plugin->afterChangeParent( diff --git a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php index 4a22dc83a1f31..84cd7314c9975 100644 --- a/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php +++ b/app/code/Magento/CustomerImportExport/Model/Import/CustomerComposite.php @@ -21,36 +21,36 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit * Names that begins with underscore is not an attribute. This name convention is for * to avoid interference with same attribute name. */ - const COLUMN_ADDRESS_PREFIX = '_address_'; + public const COLUMN_ADDRESS_PREFIX = '_address_'; - const COLUMN_DEFAULT_BILLING = '_address_default_billing_'; + public const COLUMN_DEFAULT_BILLING = '_address_default_billing_'; - const COLUMN_DEFAULT_SHIPPING = '_address_default_shipping_'; + public const COLUMN_DEFAULT_SHIPPING = '_address_default_shipping_'; /**#@-*/ /**#@+ * Data row scopes */ - const SCOPE_DEFAULT = 1; + public const SCOPE_DEFAULT = 1; - const SCOPE_ADDRESS = -1; + public const SCOPE_ADDRESS = -1; /**#@-*/ /**#@+ * Component entity names */ - const COMPONENT_ENTITY_CUSTOMER = 'customer'; + public const COMPONENT_ENTITY_CUSTOMER = 'customer'; - const COMPONENT_ENTITY_ADDRESS = 'address'; + public const COMPONENT_ENTITY_ADDRESS = 'address'; /**#@-*/ /** * Error code for orphan rows */ - const ERROR_ROW_IS_ORPHAN = 'rowIsOrphan'; + public const ERROR_ROW_IS_ORPHAN = 'rowIsOrphan'; /** * @var \Magento\CustomerImportExport\Model\Import\Customer @@ -85,14 +85,14 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit ]; /** - * Customer attributes + * Customer attribute * * @var string[] */ protected $_customerAttributes = []; /** - * Address attributes + * Address attribute * * @var string[] */ @@ -134,9 +134,9 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit protected $needColumnCheck = true; /** - * Valid column names + * Valid column name * - * @array + * @var string[] */ protected $validColumnNames = [ Customer::COLUMN_DEFAULT_BILLING, @@ -145,7 +145,7 @@ class CustomerComposite extends \Magento\ImportExport\Model\Import\AbstractEntit ]; /** - * {@inheritdoc} + * @var string */ protected $masterAttributeCode = 'email'; @@ -278,12 +278,19 @@ protected function _initAddressAttributes() */ protected function _importData() { + if ($this->getIds()) { + $this->_customerEntity->setIds($this->getIds()); + } $result = $this->_customerEntity->importData(); $this->countItemsCreated += $this->_customerEntity->getCreatedItemsCount(); $this->countItemsUpdated += $this->_customerEntity->getUpdatedItemsCount(); $this->countItemsDeleted += $this->_customerEntity->getDeletedItemsCount(); if ($this->getBehavior() != \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE) { - $result = $result && $this->_addressEntity->setCustomerAttributes($this->_customerAttributes)->importData(); + $addressEntityObject = $this->_addressEntity->setCustomerAttributes($this->_customerAttributes); + if ($this->getIds() && $addressEntityObject !== null) { + $addressEntityObject->setIds($this->getIds()); + } + $result = $result && $addressEntityObject->importData(); } if ($result) { $this->indexerProcessor->markIndexerAsInvalid(); diff --git a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/CustomerComposite/Data.php b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/CustomerComposite/Data.php index 26ffe809e5c20..00b6b6c1247cf 100644 --- a/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/CustomerComposite/Data.php +++ b/app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/CustomerComposite/Data.php @@ -81,7 +81,7 @@ protected function _prepareRow(array $rowData) { $entityCustomer = CustomerComposite::COMPONENT_ENTITY_CUSTOMER; if ($this->_entityType == $entityCustomer) { - if ($rowData['_scope'] == CustomerComposite::SCOPE_DEFAULT) { + if ((isset($rowData['_scope'])) && $rowData['_scope'] == CustomerComposite::SCOPE_DEFAULT) { return $rowData; } else { return null; diff --git a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php index 91cb1f516bb9f..88fbb5b6a971c 100644 --- a/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php +++ b/app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/CustomerCompositeTest.php @@ -255,6 +255,7 @@ protected function _getModelMockForPrepareRowForDb() protected function _getModelMockForImportData($isDeleteBehavior, $customerImport, $addressImport) { $customerEntity = $this->_getCustomerEntityMock(); + $customerEntity->expects($this->once())->method('setIds')->willReturnSelf(); $customerEntity->expects($this->once())->method('importData')->willReturn($customerImport); $addressEntity = $this->_getAddressEntityMock(); @@ -262,7 +263,8 @@ protected function _getModelMockForImportData($isDeleteBehavior, $customerImport if ($isDeleteBehavior || !$customerImport) { $addressEntity->expects($this->never())->method('importData'); } else { - $addressEntity->expects($this->once())->method('setCustomerAttributes')->willReturnSelf(); + $addressEntity->expects($this->atMost(2))->method('setCustomerAttributes')->willReturnSelf(); + $addressEntity->expects($this->once())->method('setIds')->willReturnSelf(); $addressEntity->expects($this->once())->method('importData')->willReturn($addressImport); } @@ -270,7 +272,9 @@ protected function _getModelMockForImportData($isDeleteBehavior, $customerImport $data['customer_entity'] = $customerEntity; $data['address_entity'] = $addressEntity; - return $this->_createModelMock($data); + $obj = $this->_createModelMock($data); + $obj->setIds([1, 2]); + return $obj; } /** diff --git a/app/code/Magento/Reports/Model/ResourceModel/Quote/Item/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Quote/Item/Collection.php index 9d8f89629c761..43ebd2137fc92 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Quote/Item/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Quote/Item/Collection.php @@ -121,7 +121,7 @@ public function prepareActiveCartItems() $quoteItemsSelect->reset() ->from(['main_table' => $this->getTable('quote_item')], '') - ->columns(['main_table.product_id', 'main_table.name']) + ->columns(['main_table.product_id', 'main_table.name', 'main_table.price']) ->columns(['carts' => new \Zend_Db_Expr('COUNT(main_table.item_id)')]) ->columns('quote.base_to_global_rate') ->joinInner( diff --git a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Report/Quote/CollectionTest.php b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Report/Quote/CollectionTest.php index 90d224ee417db..7927f33b1c95c 100644 --- a/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Report/Quote/CollectionTest.php +++ b/app/code/Magento/Reports/Test/Unit/Model/ResourceModel/Report/Quote/CollectionTest.php @@ -67,6 +67,7 @@ public function testGetSelectCountSql() public function testPrepareActiveCartItems() { + static $i = 0; /** @var MockObject $collection */ $constructArgs = $this->objectManager ->getConstructArguments(QuoteItemCollection::class); @@ -79,7 +80,25 @@ public function testPrepareActiveCartItems() $collection->expects($this->exactly(2))->method('getSelect')->willReturn($this->selectMock); $this->selectMock->expects($this->once())->method('reset')->willReturnSelf(); $this->selectMock->expects($this->once())->method('from')->willReturnSelf(); - $this->selectMock->expects($this->atLeastOnce())->method('columns')->willReturnSelf(); + $this->selectMock->expects($this->atLeastOnce())->method('columns') + ->with(self::callback(function ($columns) use (&$i) { + switch ($i) { + case 0: + $this->assertContains('main_table.product_id', $columns); + $this->assertContains('main_table.name', $columns); + $this->assertContains('main_table.price', $columns); + $i++; + break; + case 1: + $this->assertEquals(['carts' => new \Zend_Db_Expr('COUNT(main_table.item_id)')], $columns); + $i++; + break; + case 2: + $this->assertEquals('quote.base_to_global_rate', $columns); + $i++; + } + return true; + }))->willReturnSelf(); $this->selectMock->expects($this->once())->method('joinInner')->willReturnSelf(); $this->selectMock->expects($this->once())->method('where')->willReturnSelf(); $this->selectMock->expects($this->once())->method('group')->willReturnSelf(); diff --git a/lib/web/mage/requirejs/mixins.js b/lib/web/mage/requirejs/mixins.js index cb5ee8e462054..bebd10b1d6ee3 100644 --- a/lib/web/mage/requirejs/mixins.js +++ b/lib/web/mage/requirejs/mixins.js @@ -6,11 +6,11 @@ define('mixins', [ 'module' ], function (module) { 'use strict'; - var contexts = require.s.contexts, defContextName = '_', defContext = contexts[defContextName], - unbundledContext = require.s.newContext('$'), + unbundledContextName = '$', + unbundledContext = contexts[unbundledContextName] = require.s.newContext(unbundledContextName), defaultConfig = defContext.config, unbundledConfig = { baseUrl: defaultConfig.baseUrl, @@ -205,7 +205,10 @@ require([ var contexts = require.s.contexts, defContextName = '_', defContext = contexts[defContextName], + unbundledContextName = '$', + unbundledContext = contexts[unbundledContextName], originalContextRequire = defContext.require, + originalContextConfigure = defContext.configure, processNames = mixins.processNames; /** @@ -219,6 +222,15 @@ require([ return originalContextRequire(deps, callback, errback); }; + /** + * Wrap original context configuration to update unbundled context, + * that way it is able to respect any changes done after mixins module has initialized. + */ + defContext.configure = function (cfg) { + originalContextConfigure(cfg); + unbundledContext.configure(cfg); + }; + /** * Copy properties of original 'require' method. */