Skip to content

Commit 3ea631e

Browse files
ENGCOM-4776: #21737 Duplicating product with translated url keys over multiple sto… #22178
- Merge Pull Request #22178 from yvechirko/magento2:#21737_Duplicating_product_url_keys - Merged commits: 1. 48b0ab8 2. 30b0f91 3. 4e15099 4. 0c88939 5. a45d519
2 parents d08ae59 + a45d519 commit 3ea631e

File tree

88 files changed

+2178
-495
lines changed

Some content is hidden

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

88 files changed

+2178
-495
lines changed

app/code/Magento/Backend/Block/Dashboard/Graph.php

Lines changed: 66 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Backend\Block\Dashboard;
79

810
/**
@@ -15,7 +17,7 @@ class Graph extends \Magento\Backend\Block\Dashboard\AbstractDashboard
1517
/**
1618
* Api URL
1719
*/
18-
const API_URL = 'http://chart.apis.google.com/chart';
20+
const API_URL = 'https://image-charts.com/chart';
1921

2022
/**
2123
* All series
@@ -76,6 +78,7 @@ class Graph extends \Magento\Backend\Block\Dashboard\AbstractDashboard
7678
/**
7779
* Google chart api data encoding
7880
*
81+
* @deprecated since the Google Image Charts API not accessible from March 14, 2019
7982
* @var string
8083
*/
8184
protected $_encoding = 'e';
@@ -187,11 +190,12 @@ public function getChartUrl($directUrl = true)
187190
{
188191
$params = [
189192
'cht' => 'lc',
190-
'chf' => 'bg,s,ffffff',
191-
'chco' => 'ef672f',
192193
'chls' => '7',
193-
'chxs' => '0,676056,15,0,l,676056|1,676056,15,0,l,676056',
194-
'chm' => 'h,f2ebde,0,0:1:.1,1,-1',
194+
'chf' => 'bg,s,f4f4f4|c,lg,90,ffffff,0.1,ededed,0',
195+
'chm' => 'B,f4d4b2,0,0,0',
196+
'chco' => 'db4814',
197+
'chxs' => '0,0,11|1,0,11',
198+
'chma' => '15,15,15,15'
195199
];
196200

197201
$this->_allSeries = $this->getRowsData($this->_dataRows);
@@ -279,20 +283,11 @@ public function getChartUrl($directUrl = true)
279283
$this->_axisLabels['x'] = $dates;
280284
$this->_allSeries = $datas;
281285

282-
//Google encoding values
283-
if ($this->_encoding == "s") {
284-
// simple encoding
285-
$params['chd'] = "s:";
286-
$dataDelimiter = "";
287-
$dataSetdelimiter = ",";
288-
$dataMissing = "_";
289-
} else {
290-
// extended encoding
291-
$params['chd'] = "e:";
292-
$dataDelimiter = "";
293-
$dataSetdelimiter = ",";
294-
$dataMissing = "__";
295-
}
286+
// Image-Charts Awesome data format values
287+
$params['chd'] = "a:";
288+
$dataDelimiter = ",";
289+
$dataSetdelimiter = "|";
290+
$dataMissing = "_";
296291

297292
// process each string in the array, and find the max length
298293
$localmaxvalue = [0];
@@ -306,7 +301,6 @@ public function getChartUrl($directUrl = true)
306301
$minvalue = min($localminvalue);
307302

308303
// default values
309-
$yrange = 0;
310304
$yLabels = [];
311305
$miny = 0;
312306
$maxy = 0;
@@ -321,52 +315,21 @@ public function getChartUrl($directUrl = true)
321315
$maxy = ceil($maxvalue + 1);
322316
$yLabels = range($miny, $maxy, 1);
323317
}
324-
$yrange = $maxy;
325318
$yorigin = 0;
326319
}
327320

328321
$chartdata = [];
329322

330323
foreach ($this->getAllSeries() as $index => $serie) {
331324
$thisdataarray = $serie;
332-
if ($this->_encoding == "s") {
333-
// SIMPLE ENCODING
334-
for ($j = 0; $j < sizeof($thisdataarray); $j++) {
335-
$currentvalue = $thisdataarray[$j];
336-
if (is_numeric($currentvalue)) {
337-
$ylocation = round(
338-
(strlen($this->_simpleEncoding) - 1) * ($yorigin + $currentvalue) / $yrange
339-
);
340-
$chartdata[] = substr($this->_simpleEncoding, $ylocation, 1) . $dataDelimiter;
341-
} else {
342-
$chartdata[] = $dataMissing . $dataDelimiter;
343-
}
344-
}
345-
} else {
346-
// EXTENDED ENCODING
347-
for ($j = 0; $j < sizeof($thisdataarray); $j++) {
348-
$currentvalue = $thisdataarray[$j];
349-
if (is_numeric($currentvalue)) {
350-
if ($yrange) {
351-
$ylocation = 4095 * ($yorigin + $currentvalue) / $yrange;
352-
} else {
353-
$ylocation = 0;
354-
}
355-
$firstchar = floor($ylocation / 64);
356-
$secondchar = $ylocation % 64;
357-
$mappedchar = substr(
358-
$this->_extendedEncoding,
359-
$firstchar,
360-
1
361-
) . substr(
362-
$this->_extendedEncoding,
363-
$secondchar,
364-
1
365-
);
366-
$chartdata[] = $mappedchar . $dataDelimiter;
367-
} else {
368-
$chartdata[] = $dataMissing . $dataDelimiter;
369-
}
325+
$count = count($thisdataarray);
326+
for ($j = 0; $j < $count; $j++) {
327+
$currentvalue = $thisdataarray[$j];
328+
if (is_numeric($currentvalue)) {
329+
$ylocation = $yorigin + $currentvalue;
330+
$chartdata[] = $ylocation . $dataDelimiter;
331+
} else {
332+
$chartdata[] = $dataMissing . $dataDelimiter;
370333
}
371334
}
372335
$chartdata[] = $dataSetdelimiter;
@@ -381,45 +344,13 @@ public function getChartUrl($directUrl = true)
381344

382345
$valueBuffer = [];
383346

384-
if (sizeof($this->_axisLabels) > 0) {
347+
if (count($this->_axisLabels) > 0) {
385348
$params['chxt'] = implode(',', array_keys($this->_axisLabels));
386349
$indexid = 0;
387350
foreach ($this->_axisLabels as $idx => $labels) {
388351
if ($idx == 'x') {
389-
/**
390-
* Format date
391-
*/
392-
foreach ($this->_axisLabels[$idx] as $_index => $_label) {
393-
if ($_label != '') {
394-
$period = new \DateTime($_label, new \DateTimeZone($timezoneLocal));
395-
switch ($this->getDataHelper()->getParam('period')) {
396-
case '24h':
397-
$this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime(
398-
$period->setTime($period->format('H'), 0, 0),
399-
\IntlDateFormatter::NONE,
400-
\IntlDateFormatter::SHORT
401-
);
402-
break;
403-
case '7d':
404-
case '1m':
405-
$this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime(
406-
$period,
407-
\IntlDateFormatter::SHORT,
408-
\IntlDateFormatter::NONE
409-
);
410-
break;
411-
case '1y':
412-
case '2y':
413-
$this->_axisLabels[$idx][$_index] = date('m/Y', strtotime($_label));
414-
break;
415-
}
416-
} else {
417-
$this->_axisLabels[$idx][$_index] = '';
418-
}
419-
}
420-
352+
$this->formatAxisLabelDate($idx, $timezoneLocal);
421353
$tmpstring = implode('|', $this->_axisLabels[$idx]);
422-
423354
$valueBuffer[] = $indexid . ":|" . $tmpstring;
424355
} elseif ($idx == 'y') {
425356
$valueBuffer[] = $indexid . ":|" . implode('|', $yLabels);
@@ -447,6 +378,46 @@ public function getChartUrl($directUrl = true)
447378
}
448379
}
449380

381+
/**
382+
* Format dates for axis labels
383+
*
384+
* @param string $idx
385+
* @param string $timezoneLocal
386+
*
387+
* @return void
388+
*/
389+
private function formatAxisLabelDate($idx, $timezoneLocal)
390+
{
391+
foreach ($this->_axisLabels[$idx] as $_index => $_label) {
392+
if ($_label != '') {
393+
$period = new \DateTime($_label, new \DateTimeZone($timezoneLocal));
394+
switch ($this->getDataHelper()->getParam('period')) {
395+
case '24h':
396+
$this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime(
397+
$period->setTime($period->format('H'), 0, 0),
398+
\IntlDateFormatter::NONE,
399+
\IntlDateFormatter::SHORT
400+
);
401+
break;
402+
case '7d':
403+
case '1m':
404+
$this->_axisLabels[$idx][$_index] = $this->_localeDate->formatDateTime(
405+
$period,
406+
\IntlDateFormatter::SHORT,
407+
\IntlDateFormatter::NONE
408+
);
409+
break;
410+
case '1y':
411+
case '2y':
412+
$this->_axisLabels[$idx][$_index] = date('m/Y', strtotime($_label));
413+
break;
414+
}
415+
} else {
416+
$this->_axisLabels[$idx][$_index] = '';
417+
}
418+
}
419+
}
420+
450421
/**
451422
* Get rows data
452423
*
@@ -540,6 +511,8 @@ protected function getHeight()
540511
}
541512

542513
/**
514+
* Sets data helper
515+
*
543516
* @param \Magento\Backend\Helper\Dashboard\AbstractDashboard $dataHelper
544517
* @return void
545518
*/

app/code/Magento/Catalog/Model/Product/Copier.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
<?php
22
/**
3-
* Catalog product copier. Creates product duplicate
4-
*
53
* Copyright © Magento, Inc. All rights reserved.
64
* See COPYING.txt for license details.
75
*/
@@ -11,7 +9,11 @@
119
use Magento\Catalog\Model\Product;
1210

1311
/**
14-
* The copier creates product duplicates.
12+
* Catalog product copier.
13+
*
14+
* Creates product duplicate.
15+
*
16+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1517
*/
1618
class Copier
1719
{
@@ -120,10 +122,10 @@ private function setStoresUrl(Product $product, Product $duplicate) : void
120122
$productId = $product->getId();
121123
$productResource = $product->getResource();
122124
$defaultUrlKey = $productResource->getAttributeRawValue(
123-
$productId,
124-
'url_key',
125-
\Magento\Store\Model\Store::DEFAULT_STORE_ID
126-
);
125+
$productId,
126+
'url_key',
127+
\Magento\Store\Model\Store::DEFAULT_STORE_ID
128+
);
127129
$duplicate->setData('save_rewrites_history', false);
128130
foreach ($storeIds as $storeId) {
129131
$isDuplicateSaved = false;
@@ -139,6 +141,7 @@ private function setStoresUrl(Product $product, Product $duplicate) : void
139141
try {
140142
$duplicate->save();
141143
$isDuplicateSaved = true;
144+
// phpcs:ignore Magento2.CodeAnalysis.EmptyBlock
142145
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
143146
}
144147
} while (!$isDuplicateSaved);
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="AddOutOfStockProductToCompareListTest">
12+
<annotations>
13+
<features value="Catalog"/>
14+
<title value="Add out of stock product to compare list"/>
15+
<description value="Add out of stock product to compare list"/>
16+
<severity value="MAJOR"/>
17+
<testCaseId value="MAGETWO-98644"/>
18+
<useCaseId value="MAGETWO-98522"/>
19+
<group value="Catalog"/>
20+
</annotations>
21+
<before>
22+
<actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/>
23+
<magentoCLI command="config:set cataloginventory/options/show_out_of_stock 0" stepKey="displayOutOfStockNo"/>
24+
<magentoCLI command="cache:flush" stepKey="flushCache"/>
25+
<createData entity="SimpleSubCategory" stepKey="category"/>
26+
<createData entity="SimpleProduct4" stepKey="product">
27+
<requiredEntity createDataKey="category"/>
28+
</createData>
29+
</before>
30+
<after>
31+
<magentoCLI command="config:set cataloginventory/options/show_out_of_stock 0" stepKey="displayOutOfStockNo2"/>
32+
<magentoCLI command="cache:flush" stepKey="flushCache"/>
33+
<deleteData createDataKey="product" stepKey="deleteProduct"/>
34+
<deleteData createDataKey="category" stepKey="deleteCategory"/>
35+
<actionGroup ref="logout" stepKey="logout"/>
36+
</after>
37+
<!--Open product page-->
38+
<comment userInput="Open product page" stepKey="openProdPage"/>
39+
<amOnPage url="{{StorefrontProductPage.url($$product.name$$)}}" stepKey="goToSimpleProductPage"/>
40+
<waitForPageLoad stepKey="waitForSimpleProductPage"/>
41+
<!--'Add to compare' link is not available-->
42+
<comment userInput="'Add to compare' link is not available" stepKey="addToCompareLinkAvailability"/>
43+
<dontSeeElement selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="dontSeeAddToCompareLink"/>
44+
<!--Turn on 'out on stock' config-->
45+
<comment userInput="Turn on 'out of stock' config" stepKey="onOutOfStockConfig"/>
46+
<magentoCLI command="config:set cataloginventory/options/show_out_of_stock 1" stepKey="displayOutOfStockYes"/>
47+
<!--Clear cache and reindex-->
48+
<comment userInput="Clear cache and reindex" stepKey="cleanCache"/>
49+
<magentoCLI command="indexer:reindex" stepKey="reindex"/>
50+
<magentoCLI command="cache:flush" stepKey="flushCache"/>
51+
<!--Open product page-->
52+
<comment userInput="Open product page" stepKey="openProductPage"/>
53+
<amOnPage url="{{StorefrontProductPage.url($$product.name$$)}}" stepKey="goToSimpleProductPage2"/>
54+
<waitForPageLoad stepKey="waitForSimpleProductPage2"/>
55+
<!--Click on 'Add to Compare' link-->
56+
<comment userInput="Click on 'Add to Compare' link" stepKey="clickOnAddToCompareLink"/>
57+
<click selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="clickOnAddToCompare"/>
58+
<waitForPageLoad stepKey="waitForProdAddToCmpList"/>
59+
<!--Assert success message-->
60+
<comment userInput="Assert success message" stepKey="assertSuccessMsg"/>
61+
<grabTextFrom selector="{{AdminProductMessagesSection.successMessage}}" stepKey="grabTextFromSuccessMessage"/>
62+
<assertEquals expected='You added product $$product.name$$ to the comparison list.' expectedType="string" actual="($grabTextFromSuccessMessage)" stepKey="assertSuccessMessage"/>
63+
<!--See product in the comparison list-->
64+
<comment userInput="See product in the comparison list" stepKey="seeProductInComparisonList"/>
65+
<amOnPage url="{{StorefrontProductComparePage.url}}" stepKey="navigateToComparePage"/>
66+
<waitForPageLoad stepKey="waitForStorefrontProductComparePageLoad"/>
67+
<seeElement selector="{{StorefrontProductCompareMainSection.ProductLinkByName($product.name$)}}" stepKey="seeProductInCompareList"/>
68+
<!--Go to Category page and delete product from comparison list-->
69+
<comment userInput="Go to Category page and delete prduct from comparison list" stepKey="deletProdFromCmpList"/>
70+
<amOnPage url="{{StorefrontCategoryPage.url($$category.name$$)}}" stepKey="onCategoryPage"/>
71+
<waitForPageLoad time="30" stepKey="waitForPageLoad1"/>
72+
<click selector="{{StorefrontComparisonSidebarSection.ClearAll}}" stepKey="clickClearAll"/>
73+
<waitForPageLoad time="30" stepKey="waitForConfirmPageLoad"/>
74+
<click selector="{{AdminDeleteRoleSection.confirm}}" stepKey="confirmProdDelate"/>
75+
<waitForPageLoad time="30" stepKey="waitForConfirmLoad"/>
76+
<!--Add product to compare list from Category page-->
77+
<comment userInput="Add product to compare list fom Category page" stepKey="addToCmpFromCategPage"/>
78+
<moveMouseOver selector="{{StorefrontCategoryMainSection.ProductItemInfo}}" stepKey="hoverOverProduct"/>
79+
<click selector="{{StorefrontProductInfoMainSection.productAddToCompare}}" stepKey="clickAddToCompare"/>
80+
<waitForPageLoad stepKey="waitProdAddingToCmpList"/>
81+
<!--Assert success message-->
82+
<comment userInput="Assert success message" stepKey="assertSuccessMsg2"/>
83+
<grabTextFrom selector="{{AdminProductMessagesSection.successMessage}}" stepKey="grabTextFromSuccessMessage2"/>
84+
<assertEquals expected='You added product $$product.name$$ to the comparison list.' expectedType="string" actual="($grabTextFromSuccessMessage)" stepKey="assertSuccessMessage2"/>
85+
<!--Check that product displays on add to compare widget-->
86+
<comment userInput="Check that product displays on add to compare widget" stepKey="checkProdNameOnWidget"/>
87+
<seeElement selector="{{StorefrontComparisonSidebarSection.ProductTitleByName($$product.name$$)}}" stepKey="seeProdNameOnCmpWidget"/>
88+
<!--See product in the compare page-->
89+
<comment userInput="See product in the compare page" stepKey="seeProductInComparePage"/>
90+
<amOnPage url="{{StorefrontProductComparePage.url}}" stepKey="navigateToComparePage2"/>
91+
<waitForPageLoad stepKey="waitForStorefrontProductComparePageLoad2"/>
92+
<seeElement selector="{{StorefrontProductCompareMainSection.ProductLinkByName($product.name$)}}" stepKey="seeProductInCompareList2"/>
93+
</test>
94+
</tests>

0 commit comments

Comments
 (0)