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