Skip to content

Commit cc3ce37

Browse files
committed
Merge remote-tracking branch 'origin/2.3-develop' into mtf-eol
2 parents cb30dd8 + 4dac65b commit cc3ce37

File tree

83 files changed

+3071
-230
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+3071
-230
lines changed

app/code/Magento/Catalog/Model/ProductRepository.php

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,11 @@ protected function initializeProductData(array $productData, $createNew)
369369
if ($createNew) {
370370
$product = $this->productFactory->create();
371371
$this->assignProductToWebsites($product);
372+
} elseif (!empty($productData['id'])) {
373+
$this->removeProductFromLocalCacheById($productData['id']);
374+
$product = $this->getById($productData['id']);
372375
} else {
373-
$this->removeProductFromLocalCache($productData['sku']);
376+
$this->removeProductFromLocalCacheBySku($productData['sku']);
374377
$product = $this->get($productData['sku']);
375378
}
376379

@@ -512,7 +515,7 @@ public function save(ProductInterface $product, $saveOptions = false)
512515
$tierPrices = $product->getData('tier_price');
513516

514517
try {
515-
$existingProduct = $this->get($product->getSku());
518+
$existingProduct = $product->getId() ? $this->getById($product->getId()) : $this->get($product->getSku());
516519

517520
$product->setData(
518521
$this->resourceModel->getLinkField(),
@@ -570,8 +573,8 @@ public function save(ProductInterface $product, $saveOptions = false)
570573
$product->getCategoryIds()
571574
);
572575
}
573-
$this->removeProductFromLocalCache($product->getSku());
574-
unset($this->instancesById[$product->getId()]);
576+
$this->removeProductFromLocalCacheBySku($product->getSku());
577+
$this->removeProductFromLocalCacheById($product->getId());
575578

576579
return $this->get($product->getSku(), false, $product->getStoreId());
577580
}
@@ -584,8 +587,8 @@ public function delete(ProductInterface $product)
584587
$sku = $product->getSku();
585588
$productId = $product->getId();
586589
try {
587-
$this->removeProductFromLocalCache($product->getSku());
588-
unset($this->instancesById[$product->getId()]);
590+
$this->removeProductFromLocalCacheBySku($product->getSku());
591+
$this->removeProductFromLocalCacheById($product->getId());
589592
$this->resourceModel->delete($product);
590593
} catch (ValidatorException $e) {
591594
throw new CouldNotSaveException(__($e->getMessage()), $e);
@@ -595,8 +598,8 @@ public function delete(ProductInterface $product)
595598
$e
596599
);
597600
}
598-
$this->removeProductFromLocalCache($sku);
599-
unset($this->instancesById[$productId]);
601+
$this->removeProductFromLocalCacheBySku($sku);
602+
$this->removeProductFromLocalCacheById($productId);
600603

601604
return true;
602605
}
@@ -753,25 +756,36 @@ private function getProductFromLocalCache(string $sku, string $cacheKey)
753756
}
754757

755758
/**
756-
* Removes product in the local cache.
759+
* Removes product in the local cache by sku.
757760
*
758761
* @param string $sku
759762
* @return void
760763
*/
761-
private function removeProductFromLocalCache(string $sku) :void
764+
private function removeProductFromLocalCacheBySku(string $sku): void
762765
{
763766
$preparedSku = $this->prepareSku($sku);
764767
unset($this->instances[$preparedSku]);
765768
}
766769

767770
/**
768-
* Saves product in the local cache.
771+
* Removes product in the local cache by id.
772+
*
773+
* @param string|null $id
774+
* @return void
775+
*/
776+
private function removeProductFromLocalCacheById(?string $id): void
777+
{
778+
unset($this->instancesById[$id]);
779+
}
780+
781+
/**
782+
* Saves product in the local cache by sku.
769783
*
770784
* @param Product $product
771785
* @param string $cacheKey
772786
* @return void
773787
*/
774-
private function saveProductInLocalCache(Product $product, string $cacheKey) : void
788+
private function saveProductInLocalCache(Product $product, string $cacheKey): void
775789
{
776790
$preparedSku = $this->prepareSku($product->getSku());
777791
$this->instances[$preparedSku][$cacheKey] = $product;
@@ -800,8 +814,8 @@ private function prepareSku(string $sku): string
800814
private function saveProduct($product): void
801815
{
802816
try {
803-
$this->removeProductFromLocalCache($product->getSku());
804-
unset($this->instancesById[$product->getId()]);
817+
$this->removeProductFromLocalCacheBySku($product->getSku());
818+
$this->removeProductFromLocalCacheById($product->getId());
805819
$this->resourceModel->save($product);
806820
} catch (ConnectionException $exception) {
807821
throw new TemporaryCouldNotSaveException(

app/code/Magento/Catalog/Model/ResourceModel/Product/Image.php

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public function __construct(
5454
}
5555

5656
/**
57-
* Returns product images
57+
* Get all product images.
5858
*
5959
* @return \Generator
6060
*/
@@ -75,7 +75,28 @@ public function getAllProductImages(): \Generator
7575
}
7676

7777
/**
78-
* Get the number of unique pictures of products
78+
* Get used product images.
79+
*
80+
* @return \Generator
81+
*/
82+
public function getUsedProductImages(): \Generator
83+
{
84+
$batchSelectIterator = $this->batchQueryGenerator->generate(
85+
'value_id',
86+
$this->getUsedImagesSelect(),
87+
$this->batchSize,
88+
\Magento\Framework\DB\Query\BatchIteratorInterface::NON_UNIQUE_FIELD_ITERATOR
89+
);
90+
91+
foreach ($batchSelectIterator as $select) {
92+
foreach ($this->connection->fetchAll($select) as $key => $value) {
93+
yield $key => $value;
94+
}
95+
}
96+
}
97+
98+
/**
99+
* Get the number of unique images of products.
79100
*
80101
* @return int
81102
*/
@@ -92,7 +113,24 @@ public function getCountAllProductImages(): int
92113
}
93114

94115
/**
95-
* Return Select to fetch all products images
116+
* Get the number of unique and used images of products.
117+
*
118+
* @return int
119+
*/
120+
public function getCountUsedProductImages(): int
121+
{
122+
$select = $this->getUsedImagesSelect()
123+
->reset('columns')
124+
->reset('distinct')
125+
->columns(
126+
new \Zend_Db_Expr('count(distinct value)')
127+
);
128+
129+
return (int) $this->connection->fetchOne($select);
130+
}
131+
132+
/**
133+
* Return select to fetch all products images.
96134
*
97135
* @return Select
98136
*/
@@ -106,4 +144,23 @@ private function getVisibleImagesSelect(): Select
106144
'disabled = 0'
107145
);
108146
}
147+
148+
/**
149+
* Return select to fetch all used product images.
150+
*
151+
* @return Select
152+
*/
153+
private function getUsedImagesSelect(): Select
154+
{
155+
return $this->connection->select()->distinct()
156+
->from(
157+
['images' => $this->resourceConnection->getTableName(Gallery::GALLERY_TABLE)],
158+
'value as filepath'
159+
)->joinInner(
160+
['image_value' => $this->resourceConnection->getTableName(Gallery::GALLERY_VALUE_TABLE)],
161+
'images.value_id = image_value.value_id'
162+
)->where(
163+
'images.disabled = 0 AND image_value.disabled = 0'
164+
);
165+
}
109166
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AdminAnchorCategoryActionGroup">
12+
<arguments>
13+
<argument name="categoryName" type="string"/>
14+
</arguments>
15+
<!--Open Category page-->
16+
<amOnPage url="{{AdminCategoryPage.url}}" stepKey="openAdminCategoryIndexPage"/>
17+
<waitForPageLoad stepKey="waitForPageToLoaded"/>
18+
<click selector="{{AdminCategorySidebarTreeSection.expandAll}}" stepKey="clickOnExpandTree"/>
19+
<waitForPageLoad stepKey="waitForCategoryToLoad"/>
20+
<click selector="{{AdminCategorySidebarTreeSection.categoryInTree(categoryName)}}" stepKey="selectCategory"/>
21+
<waitForPageLoad stepKey="waitForPageToLoad"/>
22+
23+
<!--Enable Anchor for category -->
24+
<scrollTo selector="{{CategoryDisplaySettingsSection.DisplaySettingTab}}" x="0" y="-80" stepKey="scrollToDisplaySetting"/>
25+
<click selector="{{CategoryDisplaySettingsSection.DisplaySettingTab}}" stepKey="selectDisplaySetting"/>
26+
<checkOption selector="{{CategoryDisplaySettingsSection.anchor}}" stepKey="enableAnchor"/>
27+
<click selector="{{AdminCategoryMainActionsSection.SaveButton}}" stepKey="saveSubCategory"/>
28+
</actionGroup>
29+
</actionGroups>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AdminAssignCategoryToProductAndSaveActionGroup">
12+
<arguments>
13+
<argument name="categoryName" type="string"/>
14+
</arguments>
15+
<!-- on edit Product page catalog/product/edit/id/{{product_id}}/ -->
16+
<click selector="{{AdminProductFormSection.categoriesDropdown}}" stepKey="openDropDown"/>
17+
<checkOption selector="{{AdminProductFormSection.selectCategory(categoryName)}}" stepKey="selectCategory"/>
18+
<click selector="{{AdminProductFormSection.done}}" stepKey="clickDone"/>
19+
<waitForPageLoad stepKey="waitForApplyCategory"/>
20+
<click selector="{{AdminProductFormSection.save}}" stepKey="clickSave"/>
21+
<waitForPageLoad stepKey="waitForSavingProduct"/>
22+
<see userInput="You saved the product." selector="{{CatalogProductsSection.messageSuccessSavedProduct}}" stepKey="seeSuccessMessage"/>
23+
</actionGroup>
24+
</actionGroups>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AdminUnassignCategoryOnProductAndSaveActionGroup">
12+
<arguments>
13+
<argument name="categoryName" type="string"/>
14+
</arguments>
15+
<!-- on edit Product page catalog/product/edit/id/{{product_id}}/ -->
16+
<click selector="{{AdminProductFormSection.unselectCategories(categoryName)}}" stepKey="clearCategory"/>
17+
<waitForPageLoad stepKey="waitForDelete"/>
18+
<click selector="{{AdminProductFormSection.save}}" stepKey="clickSave"/>
19+
<waitForPageLoad stepKey="waitForSavingProduct"/>
20+
<see userInput="You saved the product." selector="{{CatalogProductsSection.messageSuccessSavedProduct}}" stepKey="seeSuccessMessage"/>
21+
</actionGroup>
22+
</actionGroups>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
10+
<actionGroup name="OpenStoreFrontProductPageActionGroup">
11+
<arguments>
12+
<argument name="productUrlKey" type="string"/>
13+
</arguments>
14+
<amOnPage url="{{StorefrontProductPage.url(productUrlKey)}}" stepKey="amOnProductPage"/>
15+
<waitForPageLoad stepKey="waitForProductPageLoad"/>
16+
</actionGroup>
17+
</actionGroups>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="StorefrontGoToCategoryPageActionGroup">
12+
<arguments>
13+
<argument name="categoryName" type="string"/>
14+
</arguments>
15+
<amOnPage url="{{StorefrontHomePage.url}}" stepKey="onFrontend"/>
16+
<waitForPageLoad stepKey="waitForStorefrontPageLoad"/>
17+
<click selector="{{StorefrontHeaderSection.NavigationCategoryByName(categoryName)}}" stepKey="toCategory"/>
18+
<waitForPageLoad stepKey="waitForCategoryPage"/>
19+
</actionGroup>
20+
<actionGroup name="StorefrontGoToSubCategoryPageActionGroup" extends="StorefrontGoToCategoryPageActionGroup">
21+
<arguments>
22+
<argument name="subCategoryName" type="string"/>
23+
</arguments>
24+
<moveMouseOver selector="{{StorefrontHeaderSection.NavigationCategoryByName(categoryName)}}" stepKey="toCategory"/>
25+
<click selector="{{StorefrontHeaderSection.NavigationCategoryByName(subCategoryName)}}" stepKey="openSubCategory" after="toCategory"/>
26+
</actionGroup>
27+
</actionGroups>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd">
11+
<entity name="customGroup">
12+
<data key="name">Custom Group</data>
13+
</entity>
14+
<entity name="emptyGroup">
15+
<data key="name">Empty Group</data>
16+
</entity>
17+
</entities>

app/code/Magento/Catalog/Test/Mftf/Section/AdminCategoryProductsSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
1111
<section name="AdminCategoryProductsSection">
1212
<element name="sectionHeader" type="button" selector="div[data-index='assign_products']" timeout="30"/>
13+
<element name="addProducts" type="button" selector="#catalog_category_add_product_tabs" timeout="30"/>
1314
</section>
1415
</sections>

app/code/Magento/Catalog/Test/Mftf/Section/AdminProductAttributeSetEditSection.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,16 @@
1717
<element name="assignedAttribute" type="text" selector="//*[@id='tree-div1']//span[text()='{{attributeName}}']" parameterized="true"/>
1818
<element name="xThLineItemYthAttributeGroup" type="text" selector="//*[@id='tree-div1']/ul/div/li[{{y}}]//li[{{x}}]" parameterized="true"/>
1919
<element name="xThLineItemAttributeGroup" type="text" selector="//*[@id='tree-div1']//span[text()='{{groupName}}']/parent::*/parent::*/parent::*//li[{{x}}]//a/span" parameterized="true"/>
20+
<element name="attributesInGroup" type="text" selector="//span[text()='{{GroupName}}']/../../following-sibling::ul/li" parameterized="true"/>
2021
<!-- Unassigned Attributes Column -->
2122
<element name="unassignedAttributesTree" type="block" selector="#tree-div2"/>
2223
<element name="unassignedAttribute" type="text" selector="//*[@id='tree-div2']//span[text()='{{attributeName}}']" parameterized="true"/>
2324
<element name="xThLineItemUnassignedAttribute" type="text" selector="//*[@id='tree-div2']//li[{{x}}]//a/span" parameterized="true"/>
25+
<!-- Buttons -->
26+
<element name="AddNewGroup" type="button" selector="button[data-ui-id='adminhtml-catalog-product-set-edit-add-group-button']"/>
27+
<!-- Modal Window Add New Group -->
28+
<element name="newGroupName" type="input" selector="input[data-role='promptField']"/>
29+
<element name="buttonOk" type="button" selector=".modal-footer .action-primary.action-accept"/>
30+
<element name="errorLabel" type="text" selector="label.mage-error"/>
2431
</section>
2532
</sections>

0 commit comments

Comments
 (0)