Skip to content

Commit 9a2fbca

Browse files
committed
Merge remote-tracking branch 'origin/MAGETWO-57153' into 2.1-develop-pr32
2 parents 70eeb9c + 53a7daf commit 9a2fbca

File tree

30 files changed

+1321
-236
lines changed

30 files changed

+1321
-236
lines changed

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

Lines changed: 76 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ class Helper
7474
* @var \Magento\Framework\Stdlib\DateTime\Filter\DateTime
7575
*/
7676
private $dateTimeFilter;
77+
78+
/**
79+
* @var \Magento\Catalog\Model\Product\LinkTypeProvider
80+
*/
81+
private $linkTypeProvider;
7782

7883
/**
7984
* Helper constructor.
@@ -83,21 +88,25 @@ class Helper
8388
* @param ProductLinks $productLinks
8489
* @param \Magento\Backend\Helper\Js $jsHelper
8590
* @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter
91+
* @param \Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider
8692
*/
8793
public function __construct(
8894
\Magento\Framework\App\RequestInterface $request,
8995
\Magento\Store\Model\StoreManagerInterface $storeManager,
9096
StockDataFilter $stockFilter,
9197
\Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks $productLinks,
9298
\Magento\Backend\Helper\Js $jsHelper,
93-
\Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter
99+
\Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter,
100+
\Magento\Catalog\Model\Product\LinkTypeProvider $linkTypeProvider = null
94101
) {
95102
$this->request = $request;
96103
$this->storeManager = $storeManager;
97104
$this->stockFilter = $stockFilter;
98105
$this->productLinks = $productLinks;
99106
$this->jsHelper = $jsHelper;
100107
$this->dateFilter = $dateFilter;
108+
$this->linkTypeProvider = $linkTypeProvider ?: \Magento\Framework\App\ObjectManager::getInstance()
109+
->get(\Magento\Catalog\Model\Product\LinkTypeProvider::class);
101110
}
102111

103112
/**
@@ -199,14 +208,18 @@ public function initializeFromData(\Magento\Catalog\Model\Product $product, arra
199208
$customOptions = [];
200209
foreach ($options as $customOptionData) {
201210
if (empty($customOptionData['is_delete'])) {
211+
if (empty($customOptionData['option_id'])) {
212+
$customOptionData['option_id'] = null;
213+
}
214+
202215
if (isset($customOptionData['values'])) {
203216
$customOptionData['values'] = array_filter($customOptionData['values'], function ($valueData) {
204217
return empty($valueData['is_delete']);
205218
});
206219
}
220+
207221
$customOption = $this->getCustomOptionFactory()->create(['data' => $customOptionData]);
208222
$customOption->setProductSku($product->getSku());
209-
$customOption->setOptionId(null);
210223
$customOptions[] = $customOption;
211224
}
212225
}
@@ -247,11 +260,17 @@ protected function setProductLinks(\Magento\Catalog\Model\Product $product)
247260

248261
$product = $this->productLinks->initializeLinks($product, $links);
249262
$productLinks = $product->getProductLinks();
250-
$linkTypes = [
251-
'related' => $product->getRelatedReadonly(),
252-
'upsell' => $product->getUpsellReadonly(),
253-
'crosssell' => $product->getCrosssellReadonly()
254-
];
263+
$linkTypes = [];
264+
265+
/** @var \Magento\Catalog\Api\Data\ProductLinkTypeInterface $linkTypeObject */
266+
foreach ($this->linkTypeProvider->getItems() as $linkTypeObject) {
267+
$linkTypes[$linkTypeObject->getName()] = $product->getData($linkTypeObject->getName() . '_readonly');
268+
}
269+
270+
// skip linkTypes that were already processed on initializeLinks plugins
271+
foreach ($productLinks as $productLink) {
272+
unset($linkTypes[$productLink->getLinkType()]);
273+
}
255274

256275
foreach ($linkTypes as $linkType => $readonly) {
257276
if (isset($links[$linkType]) && !$readonly) {
@@ -315,21 +334,58 @@ public function mergeProductOptions($productOptions, $overwriteOptions)
315334
return $productOptions;
316335
}
317336

318-
foreach ($productOptions as $index => $option) {
337+
foreach ($productOptions as $optionIndex => $option) {
319338
$optionId = $option['option_id'];
339+
$option = $this->overwriteValue(
340+
$optionId,
341+
$option,
342+
$overwriteOptions
343+
);
320344

321-
if (!isset($overwriteOptions[$optionId])) {
322-
continue;
345+
if (isset($option['values']) && isset($overwriteOptions[$optionId]['values'])) {
346+
foreach ($option['values'] as $valueIndex => $value) {
347+
if (isset($value['option_type_id'])) {
348+
$valueId = $value['option_type_id'];
349+
$value = $this->overwriteValue(
350+
$valueId,
351+
$value,
352+
$overwriteOptions[$optionId]['values']
353+
);
354+
355+
$option['values'][$valueIndex] = $value;
356+
}
357+
}
323358
}
324359

360+
$productOptions[$optionIndex] = $option;
361+
}
362+
363+
return $productOptions;
364+
}
365+
366+
/**
367+
* Overwrite values of fields to default, if there are option id and field name in array overwriteOptions.
368+
*
369+
* @param int $optionId
370+
* @param array $option
371+
* @param array $overwriteOptions
372+
*
373+
* @return array
374+
*/
375+
private function overwriteValue($optionId, $option, $overwriteOptions)
376+
{
377+
if (isset($overwriteOptions[$optionId])) {
325378
foreach ($overwriteOptions[$optionId] as $fieldName => $overwrite) {
326379
if ($overwrite && isset($option[$fieldName]) && isset($option['default_' . $fieldName])) {
327-
$productOptions[$index][$fieldName] = $option['default_' . $fieldName];
380+
$option[$fieldName] = $option['default_' . $fieldName];
381+
if ('title' == $fieldName) {
382+
$option['is_delete_store_title'] = 1;
383+
}
328384
}
329385
}
330386
}
331387

332-
return $productOptions;
388+
return $option;
333389
}
334390

335391
/**
@@ -339,8 +395,9 @@ private function getCustomOptionFactory()
339395
{
340396
if (null === $this->customOptionFactory) {
341397
$this->customOptionFactory = \Magento\Framework\App\ObjectManager::getInstance()
342-
->get('Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory');
398+
->get(\Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory::class);
343399
}
400+
344401
return $this->customOptionFactory;
345402
}
346403

@@ -351,8 +408,9 @@ private function getProductLinkFactory()
351408
{
352409
if (null === $this->productLinkFactory) {
353410
$this->productLinkFactory = \Magento\Framework\App\ObjectManager::getInstance()
354-
->get('Magento\Catalog\Api\Data\ProductLinkInterfaceFactory');
411+
->get(\Magento\Catalog\Api\Data\ProductLinkInterfaceFactory::class);
355412
}
413+
356414
return $this->productLinkFactory;
357415
}
358416

@@ -363,8 +421,9 @@ private function getProductRepository()
363421
{
364422
if (null === $this->productRepository) {
365423
$this->productRepository = \Magento\Framework\App\ObjectManager::getInstance()
366-
->get('Magento\Catalog\Api\ProductRepositoryInterface\Proxy');
424+
->get(\Magento\Catalog\Api\ProductRepositoryInterface\Proxy::class);
367425
}
426+
368427
return $this->productRepository;
369428
}
370429

@@ -377,6 +436,7 @@ private function getLinkResolver()
377436
if (!is_object($this->linkResolver)) {
378437
$this->linkResolver = ObjectManager::getInstance()->get(LinkResolver::class);
379438
}
439+
380440
return $this->linkResolver;
381441
}
382442

@@ -391,6 +451,7 @@ private function getDateTimeFilter()
391451
$this->dateTimeFilter = \Magento\Framework\App\ObjectManager::getInstance()
392452
->get(\Magento\Framework\Stdlib\DateTime\Filter\DateTime::class);
393453
}
454+
394455
return $this->dateTimeFilter;
395456
}
396457
}

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

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,11 +137,44 @@ public function save(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $opt
137137
if (!$productSku) {
138138
throw new CouldNotSaveException(__('ProductSku should be specified'));
139139
}
140+
/** @var \Magento\Catalog\Model\Product $product */
140141
$product = $this->productRepository->get($productSku);
142+
/** @var \Magento\Framework\EntityManager\EntityMetadataInterface $metadata */
141143
$metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class);
142144
$option->setData('product_id', $product->getData($metadata->getLinkField()));
143-
$option->setOptionId(null);
145+
$option->setData('store_id', $product->getStoreId());
146+
147+
if ($option->getOptionId()) {
148+
$options = $product->getOptions();
149+
if (!$options) {
150+
$options = $this->getProductOptions($product);
151+
}
152+
$persistedOption = array_filter(
153+
$options,
154+
function ($iOption) use ($option) {
155+
return $option->getOptionId() == $iOption->getOptionId();
156+
}
157+
);
158+
$persistedOption = reset($persistedOption);
159+
160+
if (!$persistedOption) {
161+
throw new NoSuchEntityException();
162+
}
163+
164+
/** @var array $originalValues */
165+
$originalValues = $persistedOption->getValues();
166+
/** @var array $newValues */
167+
$newValues = $option->getData('values');
168+
if ($newValues) {
169+
if (isset($originalValues)) {
170+
$newValues = $this->markRemovedValues($newValues, $originalValues);
171+
}
172+
$option->setData('values', $newValues);
173+
}
174+
}
175+
144176
$option->save();
177+
145178
return $option;
146179
}
147180

@@ -203,7 +236,7 @@ private function getOptionFactory()
203236
{
204237
if (null === $this->optionFactory) {
205238
$this->optionFactory = \Magento\Framework\App\ObjectManager::getInstance()
206-
->get('Magento\Catalog\Model\Product\OptionFactory');
239+
->get(\Magento\Catalog\Model\Product\OptionFactory::class);
207240
}
208241
return $this->optionFactory;
209242
}
@@ -216,7 +249,7 @@ private function getCollectionFactory()
216249
{
217250
if (null === $this->collectionFactory) {
218251
$this->collectionFactory = \Magento\Framework\App\ObjectManager::getInstance()
219-
->get('Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory');
252+
->get(\Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory::class);
220253
}
221254
return $this->collectionFactory;
222255
}
@@ -229,7 +262,7 @@ private function getMetadataPool()
229262
{
230263
if (null === $this->metadataPool) {
231264
$this->metadataPool = \Magento\Framework\App\ObjectManager::getInstance()
232-
->get('Magento\Framework\EntityManager\MetadataPool');
265+
->get(\Magento\Framework\EntityManager\MetadataPool::class);
233266
}
234267
return $this->metadataPool;
235268
}
@@ -242,7 +275,7 @@ private function getHydratorPool()
242275
{
243276
if (null === $this->hydratorPool) {
244277
$this->hydratorPool = \Magento\Framework\App\ObjectManager::getInstance()
245-
->get('Magento\Framework\EntityManager\HydratorPool');
278+
->get(\Magento\Framework\EntityManager\HydratorPool::class);
246279
}
247280
return $this->hydratorPool;
248281
}

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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ protected function validateOptionValue(Option $option)
5151
$storeId = $option->getProduct()->getStoreId();
5252
}
5353
foreach ($values as $value) {
54+
if (isset($value['is_delete']) && (bool)$value['is_delete']) {
55+
continue;
56+
}
5457
$type = isset($value['price_type']) ? $value['price_type'] : null;
5558
$price = isset($value['price']) ? $value['price'] : null;
5659
$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)