7
7
8
8
namespace Magento \Catalog \Model \Product \Option ;
9
9
10
+ use Magento \Catalog \Api \Data \ProductCustomOptionInterface ;
11
+ use Magento \Catalog \Api \Data \ProductInterface ;
10
12
use Magento \Catalog \Api \ProductCustomOptionRepositoryInterface as OptionRepository ;
13
+ use Magento \Catalog \Model \Product \Option ;
14
+ use Magento \Framework \App \ObjectManager ;
11
15
use Magento \Framework \EntityManager \Operation \ExtensionInterface ;
16
+ use Magento \Catalog \Model \ResourceModel \Product \Relation ;
17
+ use Magento \Framework \Exception \CouldNotSaveException ;
12
18
13
19
/**
14
- * Class SaveHandler
20
+ * SaveHandler for product option
21
+ *
22
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
15
23
*/
16
24
class SaveHandler implements ExtensionInterface
17
25
{
26
+ /**
27
+ * @var string[]
28
+ */
29
+ private $ compositeProductTypes = ['grouped ' , 'configurable ' , 'bundle ' ];
30
+
18
31
/**
19
32
* @var OptionRepository
20
33
*/
21
34
protected $ optionRepository ;
22
35
36
+ /**
37
+ * @var Relation
38
+ */
39
+ private $ relation ;
40
+
23
41
/**
24
42
* @param OptionRepository $optionRepository
43
+ * @param Relation|null $relation
25
44
*/
26
45
public function __construct (
27
- OptionRepository $ optionRepository
46
+ OptionRepository $ optionRepository ,
47
+ ?Relation $ relation = null
28
48
) {
29
49
$ this ->optionRepository = $ optionRepository ;
50
+ $ this ->relation = $ relation ?: ObjectManager::getInstance ()->get (Relation::class);
30
51
}
31
52
32
53
/**
33
54
* Perform action on relation/extension attribute
34
55
*
35
56
* @param object $entity
36
57
* @param array $arguments
37
- * @return \Magento\Catalog\Api\Data\ ProductInterface|object
58
+ * @return ProductInterface|object
38
59
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
39
60
*/
40
61
public function execute ($ entity , $ arguments = [])
@@ -47,20 +68,19 @@ public function execute($entity, $arguments = [])
47
68
$ optionIds = [];
48
69
49
70
if ($ options ) {
50
- $ optionIds = array_map (function ($ option ) {
51
- /** @var \Magento\Catalog\Model\Product\Option $option */
71
+ $ optionIds = array_map (function (Option $ option ) {
52
72
return $ option ->getOptionId ();
53
73
}, $ options );
54
74
}
55
75
56
- /** @var \Magento\Catalog\Api\Data\ ProductInterface $entity */
76
+ /** @var ProductInterface $entity */
57
77
foreach ($ this ->optionRepository ->getProductOptions ($ entity ) as $ option ) {
58
78
if (!in_array ($ option ->getOptionId (), $ optionIds )) {
59
79
$ this ->optionRepository ->delete ($ option );
60
80
}
61
81
}
62
82
if ($ options ) {
63
- $ this ->processOptionsSaving ($ options , (bool )$ entity ->dataHasChangedFor ('sku ' ), ( string ) $ entity-> getSku () );
83
+ $ this ->processOptionsSaving ($ options , (bool )$ entity ->dataHasChangedFor ('sku ' ), $ entity );
64
84
}
65
85
66
86
return $ entity ;
@@ -71,15 +91,43 @@ public function execute($entity, $arguments = [])
71
91
*
72
92
* @param array $options
73
93
* @param bool $hasChangedSku
74
- * @param string $newSku
94
+ * @param ProductInterface $product
95
+ * @return void
96
+ * @throws CouldNotSaveException
75
97
*/
76
- private function processOptionsSaving (array $ options , bool $ hasChangedSku , string $ newSku )
98
+ private function processOptionsSaving (array $ options , bool $ hasChangedSku , ProductInterface $ product ): void
77
99
{
100
+ $ isProductHasRelations = $ this ->isProductHasRelations ($ product );
101
+ /** @var ProductCustomOptionInterface $option */
78
102
foreach ($ options as $ option ) {
103
+ if (!$ isProductHasRelations && $ option ->getIsRequire ()) {
104
+ $ message = 'Required custom options cannot be added to a simple product '
105
+ . ' that is a part of a composite product. ' ;
106
+ throw new CouldNotSaveException (__ ($ message ));
107
+ }
108
+
79
109
if ($ hasChangedSku && $ option ->hasData ('product_sku ' )) {
80
- $ option ->setProductSku ($ newSku );
110
+ $ option ->setProductSku ($ product -> getSku () );
81
111
}
82
112
$ this ->optionRepository ->save ($ option );
83
113
}
84
114
}
115
+
116
+ /**
117
+ * Check if product doesn't belong to composite product
118
+ *
119
+ * @param ProductInterface $product
120
+ * @return bool
121
+ */
122
+ private function isProductHasRelations (ProductInterface $ product ): bool
123
+ {
124
+ $ result = true ;
125
+ if (!in_array ($ product ->getId (), $ this ->compositeProductTypes )
126
+ && $ this ->relation ->getRelationsByChildren ([$ product ->getId ()])
127
+ ) {
128
+ $ result = false ;
129
+ }
130
+
131
+ return $ result ;
132
+ }
85
133
}
0 commit comments