Skip to content

Commit beae948

Browse files
committed
MAGETWO-57153: [Backport] - [Github] Custom options not displayed correctly on a store view level #2908 #5885 - for 2.1
1 parent 7ea39cd commit beae948

File tree

25 files changed

+686
-181
lines changed

25 files changed

+686
-181
lines changed

app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,18 @@ public function initializeFromData(\Magento\Catalog\Model\Product $product, arra
199199
$customOptions = [];
200200
foreach ($options as $customOptionData) {
201201
if (empty($customOptionData['is_delete'])) {
202+
if (empty($customOptionData['option_id'])) {
203+
$customOptionData['option_id'] = null;
204+
}
205+
202206
if (isset($customOptionData['values'])) {
203207
$customOptionData['values'] = array_filter($customOptionData['values'], function ($valueData) {
204208
return empty($valueData['is_delete']);
205209
});
206210
}
211+
207212
$customOption = $this->getCustomOptionFactory()->create(['data' => $customOptionData]);
208213
$customOption->setProductSku($product->getSku());
209-
$customOption->setOptionId(null);
210214
$customOptions[] = $customOption;
211215
}
212216
}
@@ -315,21 +319,59 @@ public function mergeProductOptions($productOptions, $overwriteOptions)
315319
return $productOptions;
316320
}
317321

318-
foreach ($productOptions as $index => $option) {
322+
foreach ($productOptions as $optionIndex => $option) {
319323
$optionId = $option['option_id'];
324+
$option = $this->overwriteValue(
325+
$optionId,
326+
$option,
327+
$overwriteOptions
328+
);
320329

321-
if (!isset($overwriteOptions[$optionId])) {
322-
continue;
330+
if (isset($option['values']) && isset($overwriteOptions[$optionId]['values'])) {
331+
foreach ($option['values'] as $valueIndex => $value) {
332+
if (isset($value['option_type_id'])) {
333+
$valueId = $value['option_type_id'];
334+
$value = $this->overwriteValue(
335+
$valueId,
336+
$value,
337+
$overwriteOptions[$optionId]['values']
338+
);
339+
340+
$option['values'][$valueIndex] = $value;
341+
}
342+
}
323343
}
324344

345+
$productOptions[$optionIndex] = $option;
346+
}
347+
348+
return $productOptions;
349+
}
350+
351+
/**
352+
* Overwrite values of fields to default, if there are option id and field
353+
* name in array overwriteOptions.
354+
*
355+
* @param int $optionId
356+
* @param array $option
357+
* @param array $overwriteOptions
358+
*
359+
* @return array
360+
*/
361+
private function overwriteValue($optionId, $option, $overwriteOptions)
362+
{
363+
if (isset($overwriteOptions[$optionId])) {
325364
foreach ($overwriteOptions[$optionId] as $fieldName => $overwrite) {
326365
if ($overwrite && isset($option[$fieldName]) && isset($option['default_' . $fieldName])) {
327-
$productOptions[$index][$fieldName] = $option['default_' . $fieldName];
366+
$option[$fieldName] = $option['default_' . $fieldName];
367+
if ('title' == $fieldName) {
368+
$option['is_delete_store_title'] = 1;
369+
}
328370
}
329371
}
330372
}
331373

332-
return $productOptions;
374+
return $option;
333375
}
334376

335377
/**
@@ -339,8 +381,9 @@ private function getCustomOptionFactory()
339381
{
340382
if (null === $this->customOptionFactory) {
341383
$this->customOptionFactory = \Magento\Framework\App\ObjectManager::getInstance()
342-
->get('Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory');
384+
->get(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class);
343385
}
386+
344387
return $this->customOptionFactory;
345388
}
346389

@@ -351,8 +394,9 @@ private function getProductLinkFactory()
351394
{
352395
if (null === $this->productLinkFactory) {
353396
$this->productLinkFactory = \Magento\Framework\App\ObjectManager::getInstance()
354-
->get('Magento\Catalog\Api\Data\ProductLinkInterfaceFactory');
397+
->get(\Magento\Catalog\Api\Data\ProductLinkInterfaceFactory::class);
355398
}
399+
356400
return $this->productLinkFactory;
357401
}
358402

@@ -363,8 +407,9 @@ private function getProductRepository()
363407
{
364408
if (null === $this->productRepository) {
365409
$this->productRepository = \Magento\Framework\App\ObjectManager::getInstance()
366-
->get('Magento\Catalog\Api\ProductRepositoryInterface\Proxy');
410+
->get(\Magento\Catalog\Api\ProductRepositoryInterface\Proxy::class);
367411
}
412+
368413
return $this->productRepository;
369414
}
370415

@@ -377,6 +422,7 @@ private function getLinkResolver()
377422
if (!is_object($this->linkResolver)) {
378423
$this->linkResolver = ObjectManager::getInstance()->get(LinkResolver::class);
379424
}
425+
380426
return $this->linkResolver;
381427
}
382428

@@ -391,6 +437,7 @@ private function getDateTimeFilter()
391437
$this->dateTimeFilter = \Magento\Framework\App\ObjectManager::getInstance()
392438
->get(\Magento\Framework\Stdlib\DateTime\Filter\DateTime::class);
393439
}
440+
394441
return $this->dateTimeFilter;
395442
}
396443
}

app/code/Magento/Catalog/Model/Product/Option/Repository.php

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,53 @@ public function duplicate(
133133
*/
134134
public function save(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $option)
135135
{
136+
/** @var string $productSku */
136137
$productSku = $option->getProductSku();
138+
137139
if (!$productSku) {
138140
throw new CouldNotSaveException(__('ProductSku should be specified'));
139141
}
142+
143+
/** @var \Magento\Catalog\Model\Product $product */
140144
$product = $this->productRepository->get($productSku);
145+
/** @var \Magento\Framework\EntityManager\EntityMetadataInterface $metadata */
141146
$metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class);
142147
$option->setData('product_id', $product->getData($metadata->getLinkField()));
143-
$option->setOptionId(null);
148+
$option->setData('store_id', $product->getStoreId());
149+
150+
if ($option->getOptionId()) {
151+
152+
$options = $product->getOptions();
153+
154+
if (!$options) {
155+
$options = $this->getProductOptions($product);
156+
}
157+
158+
$persistedOption = array_filter(
159+
$options,
160+
function ($iOption) use ($option) {
161+
return $option->getOptionId() == $iOption->getOptionId();
162+
}
163+
);
164+
$persistedOption = reset($persistedOption);
165+
166+
if (!$persistedOption) {
167+
throw new NoSuchEntityException();
168+
}
169+
170+
/** @var array $originalValues */
171+
$originalValues = $persistedOption->getValues();
172+
/** @var array $newValues */
173+
$newValues = $option->getData('values');
174+
175+
if ($newValues) {
176+
$newValues = $this->markRemovedValues($newValues, $originalValues);
177+
$option->setData('values', $newValues);
178+
}
179+
}
180+
144181
$option->save();
182+
145183
return $option;
146184
}
147185

@@ -203,7 +241,7 @@ private function getOptionFactory()
203241
{
204242
if (null === $this->optionFactory) {
205243
$this->optionFactory = \Magento\Framework\App\ObjectManager::getInstance()
206-
->get('Magento\Catalog\Model\Product\OptionFactory');
244+
->get(\Magento\Catalog\Model\Product\OptionFactory::class);
207245
}
208246
return $this->optionFactory;
209247
}
@@ -216,7 +254,7 @@ private function getCollectionFactory()
216254
{
217255
if (null === $this->collectionFactory) {
218256
$this->collectionFactory = \Magento\Framework\App\ObjectManager::getInstance()
219-
->get('Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory');
257+
->get(\Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory::class);
220258
}
221259
return $this->collectionFactory;
222260
}
@@ -229,7 +267,7 @@ private function getMetadataPool()
229267
{
230268
if (null === $this->metadataPool) {
231269
$this->metadataPool = \Magento\Framework\App\ObjectManager::getInstance()
232-
->get('Magento\Framework\EntityManager\MetadataPool');
270+
->get(\Magento\Framework\EntityManager\MetadataPool::class);
233271
}
234272
return $this->metadataPool;
235273
}
@@ -242,7 +280,7 @@ private function getHydratorPool()
242280
{
243281
if (null === $this->hydratorPool) {
244282
$this->hydratorPool = \Magento\Framework\App\ObjectManager::getInstance()
245-
->get('Magento\Framework\EntityManager\HydratorPool');
283+
->get(\Magento\Framework\EntityManager\HydratorPool::class);
246284
}
247285
return $this->hydratorPool;
248286
}

app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ class SaveHandler implements ExtensionInterface
2020

2121
/**
2222
* @param OptionRepository $optionRepository
23-
* @param MetadataPool $metadataPool
2423
*/
2524
public function __construct(
2625
OptionRepository $optionRepository
@@ -36,15 +35,32 @@ public function __construct(
3635
*/
3736
public function execute($entity, $arguments = [])
3837
{
38+
$options = $entity->getOptions();
39+
$optionIds = [];
40+
41+
if ($options) {
42+
$optionIds = array_map(
43+
function ($option) {
44+
/** @var \Magento\Catalog\Model\Product\Option $option */
45+
return $option->getOptionId();
46+
},
47+
$options
48+
);
49+
}
50+
3951
/** @var \Magento\Catalog\Api\Data\ProductInterface $entity */
4052
foreach ($this->optionRepository->getProductOptions($entity) as $option) {
41-
$this->optionRepository->delete($option);
53+
if (!in_array($option->getOptionId(), $optionIds)) {
54+
$this->optionRepository->delete($option);
55+
}
4256
}
43-
if ($entity->getOptions()) {
44-
foreach ($entity->getOptions() as $option) {
57+
58+
if ($options) {
59+
foreach ($options as $option) {
4560
$this->optionRepository->save($option);
4661
}
4762
}
63+
4864
return $entity;
4965
}
5066
}

app/code/Magento/Catalog/Model/Product/Option/Validator/Select.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ protected function validateOptionValue(Option $option)
5151
$storeId = $option->getProduct()->getStoreId();
5252
}
5353
foreach ($values as $value) {
54+
55+
if (isset($value['is_delete']) && (bool)$value['is_delete']) {
56+
continue;
57+
}
58+
5459
$type = isset($value['price_type']) ? $value['price_type'] : null;
5560
$price = isset($value['price']) ? $value['price'] : null;
5661
$title = isset($value['title']) ? $value['title'] : null;

app/code/Magento/Catalog/Model/Product/Option/Value.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ public function saveValues()
200200
'store_id',
201201
$this->getOption()->getStoreId()
202202
);
203-
$this->unsetData('option_type_id');
203+
204204
if ($this->getData('is_delete') == '1') {
205205
if ($this->getId()) {
206206
$this->deleteValues($this->getId());

0 commit comments

Comments
 (0)