Skip to content

Commit 080a349

Browse files
committed
Fix #30073 - Store specific text swatch attribute option label with value 0 (zero) can't be saved and automatically replaced with Admin Label value of option
1 parent d7ff26b commit 080a349

File tree

2 files changed

+228
-156
lines changed

2 files changed

+228
-156
lines changed

app/code/Magento/Swatches/Model/Plugin/EavAttribute.php

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,20 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Swatches\Model\Plugin;
79

810
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
911
use Magento\Framework\App\ObjectManager;
1012
use Magento\Framework\Exception\InputException;
13+
use Magento\Framework\Exception\LocalizedException;
1114
use Magento\Framework\Serialize\Serializer\Json;
15+
use Magento\Swatches\Helper\Data;
1216
use Magento\Swatches\Model\ResourceModel\Swatch as SwatchResource;
17+
use Magento\Swatches\Model\ResourceModel\Swatch\CollectionFactory;
1318
use Magento\Swatches\Model\Swatch;
19+
use Magento\Swatches\Model\SwatchFactory;
1420

1521
/**
1622
* Plugin model for Catalog Resource Attribute
@@ -21,11 +27,6 @@ class EavAttribute
2127
{
2228
const DEFAULT_STORE_ID = 0;
2329

24-
/**
25-
* @var SwatchResource
26-
*/
27-
private $swatchResource;
28-
2930
/**
3031
* Base option title used for string operations to detect is option already exists or new
3132
*/
@@ -37,20 +38,30 @@ class EavAttribute
3738
private const API_OPTION_PREFIX = 'id_';
3839

3940
/**
40-
* @var \Magento\Swatches\Model\ResourceModel\Swatch\CollectionFactory
41+
* @var CollectionFactory
4142
*/
4243
protected $swatchCollectionFactory;
4344

4445
/**
45-
* @var \Magento\Swatches\Model\SwatchFactory
46+
* @var SwatchFactory
4647
*/
4748
protected $swatchFactory;
4849

4950
/**
50-
* @var \Magento\Swatches\Helper\Data
51+
* @var Data
5152
*/
5253
protected $swatchHelper;
5354

55+
/**
56+
* @var Json
57+
*/
58+
private $serializer;
59+
60+
/**
61+
* @var SwatchResource
62+
*/
63+
private $swatchResource;
64+
5465
/**
5566
* Array which contains links for new created attributes for swatches
5667
*
@@ -66,23 +77,16 @@ class EavAttribute
6677
protected $isSwatchExists;
6778

6879
/**
69-
* Serializer from arrays to string.
70-
*
71-
* @var Json
72-
*/
73-
private $serializer;
74-
75-
/**
76-
* @param \Magento\Swatches\Model\ResourceModel\Swatch\CollectionFactory $collectionFactory
77-
* @param \Magento\Swatches\Model\SwatchFactory $swatchFactory
78-
* @param \Magento\Swatches\Helper\Data $swatchHelper
80+
* @param CollectionFactory $collectionFactory
81+
* @param SwatchFactory $swatchFactory
82+
* @param Data $swatchHelper
7983
* @param Json|null $serializer
8084
* @param SwatchResource|null $swatchResource
8185
*/
8286
public function __construct(
83-
\Magento\Swatches\Model\ResourceModel\Swatch\CollectionFactory $collectionFactory,
84-
\Magento\Swatches\Model\SwatchFactory $swatchFactory,
85-
\Magento\Swatches\Helper\Data $swatchHelper,
87+
CollectionFactory $collectionFactory,
88+
SwatchFactory $swatchFactory,
89+
Data $swatchHelper,
8690
Json $serializer = null,
8791
SwatchResource $swatchResource = null
8892
) {
@@ -97,6 +101,7 @@ public function __construct(
97101
* Set base data to Attribute
98102
*
99103
* @param Attribute $attribute
104+
*
100105
* @return void
101106
*/
102107
public function beforeBeforeSave(Attribute $attribute)
@@ -113,8 +118,9 @@ public function beforeBeforeSave(Attribute $attribute)
113118
* Swatch save operations
114119
*
115120
* @param Attribute $attribute
116-
* @throws \Magento\Framework\Exception\LocalizedException
121+
*
117122
* @return void
123+
* @throws LocalizedException
118124
*/
119125
public function afterAfterSave(Attribute $attribute)
120126
{
@@ -129,6 +135,7 @@ public function afterAfterSave(Attribute $attribute)
129135
* Substitute suitable options and swatches arrays
130136
*
131137
* @param Attribute $attribute
138+
*
132139
* @return void
133140
*/
134141
protected function setProperOptionsArray(Attribute $attribute)
@@ -164,8 +171,9 @@ protected function setProperOptionsArray(Attribute $attribute)
164171
* Prepare attribute for conversion from any swatch type to dropdown
165172
*
166173
* @param Attribute $attribute
167-
* @throws \Magento\Framework\Exception\LocalizedException
174+
*
168175
* @return void
176+
* @throws LocalizedException
169177
*/
170178
protected function convertSwatchToDropdown(Attribute $attribute)
171179
{
@@ -187,8 +195,9 @@ protected function convertSwatchToDropdown(Attribute $attribute)
187195
* Creates array which link new option ids
188196
*
189197
* @param Attribute $attribute
198+
*
190199
* @return Attribute
191-
* @throws \Magento\Framework\Exception\LocalizedException
200+
* @throws LocalizedException
192201
*/
193202
protected function processSwatchOptions(Attribute $attribute)
194203
{
@@ -209,15 +218,14 @@ protected function processSwatchOptions(Attribute $attribute)
209218
* Get options array without deleted items
210219
*
211220
* @param array $optionsArray
221+
*
212222
* @return array
213223
*/
214224
protected function prepareOptionIds(array $optionsArray)
215225
{
216226
if (isset($optionsArray['value']) && is_array($optionsArray['value'])) {
217227
foreach (array_keys($optionsArray['value']) as $optionId) {
218-
if (isset($optionsArray['delete']) && isset($optionsArray['delete'][$optionId])
219-
&& $optionsArray['delete'][$optionId] == 1
220-
) {
228+
if (isset($optionsArray['delete'][$optionId]) && $optionsArray['delete'][$optionId] == 1) {
221229
unset($optionsArray['value'][$optionId]);
222230
}
223231
}
@@ -230,6 +238,7 @@ protected function prepareOptionIds(array $optionsArray)
230238
*
231239
* @param array $optionsArray
232240
* @param array $attributeSavedOptions
241+
*
233242
* @return void
234243
*/
235244
protected function prepareOptionLinks(array $optionsArray, array $attributeSavedOptions)
@@ -249,6 +258,7 @@ protected function prepareOptionLinks(array $optionsArray, array $attributeSaved
249258
* Save all Swatches data
250259
*
251260
* @param Attribute $attribute
261+
*
252262
* @return void
253263
*/
254264
protected function saveSwatchParams(Attribute $attribute)
@@ -266,6 +276,7 @@ protected function saveSwatchParams(Attribute $attribute)
266276
* Save Visual Swatch data
267277
*
268278
* @param Attribute $attribute
279+
*
269280
* @return void
270281
*/
271282
protected function processVisualSwatch(Attribute $attribute)
@@ -294,7 +305,7 @@ protected function processVisualSwatch(Attribute $attribute)
294305
*
295306
* @param array $attributeOptions
296307
* @param int|null $swatchType
297-
* @throws \Magento\Framework\Exception\LocalizedException
308+
* @throws LocalizedException
298309
*/
299310
private function cleanEavAttributeOptionSwatchValues(array $attributeOptions, int $swatchType = null)
300311
{
@@ -309,7 +320,7 @@ private function cleanEavAttributeOptionSwatchValues(array $attributeOptions, in
309320
* Cleaning the text type of swatch option values after switching.
310321
*
311322
* @param array $attributeOptions
312-
* @throws \Magento\Framework\Exception\LocalizedException
323+
* @throws LocalizedException
313324
*/
314325
private function cleanTextSwatchValuesAfterSwitch(array $attributeOptions)
315326
{
@@ -320,6 +331,7 @@ private function cleanTextSwatchValuesAfterSwitch(array $attributeOptions)
320331
* Get the visual swatch type based on its value
321332
*
322333
* @param string $value
334+
*
323335
* @return int
324336
*/
325337
private function determineSwatchType($value)
@@ -330,13 +342,15 @@ private function determineSwatchType($value)
330342
} elseif (!empty($value) && $value[0] == '/') {
331343
$swatchType = Swatch::SWATCH_TYPE_VISUAL_IMAGE;
332344
}
345+
333346
return $swatchType;
334347
}
335348

336349
/**
337350
* Save Textual Swatch data
338351
*
339352
* @param Attribute $attribute
353+
*
340354
* @return void
341355
*/
342356
protected function processTextualSwatch(Attribute $attribute)
@@ -352,7 +366,7 @@ protected function processTextualSwatch(Attribute $attribute)
352366
}
353367
$defaultSwatchValue = reset($storeValues);
354368
foreach ($storeValues as $storeId => $value) {
355-
if (!$value) {
369+
if ($value === null || $value === '') {
356370
$value = $defaultSwatchValue;
357371
}
358372
$swatch = $this->loadSwatchIfExists($optionId, $storeId);
@@ -361,7 +375,7 @@ protected function processTextualSwatch(Attribute $attribute)
361375
$swatch,
362376
$optionId,
363377
$storeId,
364-
\Magento\Swatches\Model\Swatch::SWATCH_TYPE_TEXTUAL,
378+
Swatch::SWATCH_TYPE_TEXTUAL,
365379
$value
366380
);
367381
$this->isSwatchExists = null;
@@ -374,13 +388,16 @@ protected function processTextualSwatch(Attribute $attribute)
374388
* Get option id. If it not exist get it from dependency link array
375389
*
376390
* @param integer $optionId
391+
*
377392
* @return int
378393
*/
379394
protected function getAttributeOptionId($optionId)
380395
{
381-
if (substr($optionId, 0, 6) == self::BASE_OPTION_TITLE || substr($optionId, 0, 3) == self::API_OPTION_PREFIX) {
382-
$optionId = isset($this->dependencyArray[$optionId]) ? $this->dependencyArray[$optionId] : null;
396+
if (strpos((string)$optionId, self::BASE_OPTION_TITLE) === 0 ||
397+
strpos((string)$optionId, self::API_OPTION_PREFIX) === 0) {
398+
$optionId = $this->dependencyArray[$optionId] ?? null;
383399
}
400+
384401
return $optionId;
385402
}
386403

@@ -389,11 +406,13 @@ protected function getAttributeOptionId($optionId)
389406
*
390407
* @param Attribute $attribute
391408
* @param integer $optionId
409+
*
392410
* @return bool
393411
*/
394412
protected function isOptionForDelete(Attribute $attribute, $optionId)
395413
{
396414
$isOptionForDelete = $attribute->getData('option/delete/' . $optionId);
415+
397416
return isset($isOptionForDelete) && $isOptionForDelete;
398417
}
399418

@@ -402,6 +421,7 @@ protected function isOptionForDelete(Attribute $attribute, $optionId)
402421
*
403422
* @param int $optionId
404423
* @param int $storeId
424+
*
405425
* @return Swatch
406426
*/
407427
protected function loadSwatchIfExists($optionId, $storeId)
@@ -415,6 +435,7 @@ protected function loadSwatchIfExists($optionId, $storeId)
415435
if ($loadedSwatch->getId()) {
416436
$this->isSwatchExists = true;
417437
}
438+
418439
return $loadedSwatch;
419440
}
420441

@@ -426,6 +447,7 @@ protected function loadSwatchIfExists($optionId, $storeId)
426447
* @param integer $storeId
427448
* @param integer $type
428449
* @param string $value
450+
*
429451
* @return void
430452
*/
431453
protected function saveSwatchData($swatch, $optionId, $storeId, $type, $value)
@@ -446,6 +468,7 @@ protected function saveSwatchData($swatch, $optionId, $storeId, $type, $value)
446468
* Save default swatch value using Swatch model instead of Eav model
447469
*
448470
* @param Attribute $attribute
471+
*
449472
* @return void
450473
*/
451474
protected function saveDefaultSwatchOptionValue(Attribute $attribute)
@@ -455,7 +478,7 @@ protected function saveDefaultSwatchOptionValue(Attribute $attribute)
455478
}
456479
$defaultValue = $attribute->getData('default/0');
457480
if (!empty($defaultValue)) {
458-
/** @var \Magento\Swatches\Model\Swatch $swatch */
481+
/** @var Swatch $swatch */
459482
$swatch = $this->swatchFactory->create();
460483
$swatch->getResource()->saveDefaultSwatchOption(
461484
$attribute->getId(),
@@ -468,6 +491,7 @@ protected function saveDefaultSwatchOptionValue(Attribute $attribute)
468491
* Validate that attribute options exist
469492
*
470493
* @param Attribute $attribute
494+
*
471495
* @return bool
472496
* @throws InputException
473497
*/
@@ -482,6 +506,7 @@ protected function validateOptions(Attribute $attribute)
482506
if ($options && !$this->isOptionsValid($options, $attribute)) {
483507
throw new InputException(__('Admin is a required field in each row'));
484508
}
509+
485510
return true;
486511
}
487512

@@ -490,22 +515,26 @@ protected function validateOptions(Attribute $attribute)
490515
*
491516
* @param array $options
492517
* @param Attribute $attribute
518+
*
493519
* @return bool
494520
*/
495521
protected function isOptionsValid(array $options, Attribute $attribute)
496522
{
497523
if (!isset($options['value'])) {
498524
return false;
499525
}
526+
500527
foreach ($options['value'] as $optionId => $option) {
501528
// do not validate options marked as deleted
502529
if ($this->isOptionForDelete($attribute, $optionId)) {
503530
continue;
504531
}
532+
505533
if (!isset($option[0]) || $option[0] === '') {
506534
return false;
507535
}
508536
}
537+
509538
return true;
510539
}
511540

@@ -516,13 +545,15 @@ protected function isOptionsValid(array $options, Attribute $attribute)
516545
*
517546
* @param Attribute $attribute
518547
* @param bool $result
548+
*
519549
* @return bool
520550
*/
521551
public function afterUsesSource(Attribute $attribute, $result)
522552
{
523553
if ($this->swatchHelper->isSwatchAttribute($attribute)) {
524554
return true;
525555
}
556+
526557
return $result;
527558
}
528559
}

0 commit comments

Comments
 (0)