33 * Copyright 2015 Adobe
44 * All Rights Reserved.
55 */
6+
67namespace Magento \Catalog \Model \CustomOptions ;
78
9+ use Magento \Catalog \Api \Data \CustomOptionInterface ;
10+ use Magento \Catalog \Api \Data \ProductCustomOptionInterface ;
11+ use Magento \Catalog \Api \ProductRepositoryInterface ;
12+ use Magento \Catalog \Model \Product \Option \Type \File \ImageContentProcessor ;
813use Magento \Framework \DataObject ;
14+ use Magento \Framework \Exception \NoSuchEntityException ;
915use Magento \Quote \Api \Data \CartItemInterface ;
1016use Magento \Quote \Model \Quote \Item \CartItemProcessorInterface ;
1117use Magento \Quote \Api \Data \ProductOptionExtensionFactory ;
1218use Magento \Quote \Model \Quote \ProductOptionFactory ;
1319
20+ /**
21+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
22+ */
1423class CustomOptionProcessor implements CartItemProcessorInterface
1524{
1625 /**
@@ -45,41 +54,63 @@ class CustomOptionProcessor implements CartItemProcessorInterface
4554 */
4655 private $ serializer ;
4756
57+ /**
58+ * @var ProductRepositoryInterface
59+ */
60+ private $ productRepository ;
61+
62+ /**
63+ * @var ImageContentProcessor
64+ */
65+ private $ imageContentProcessor ;
66+
4867 /**
4968 * @param DataObject\Factory $objectFactory
5069 * @param ProductOptionFactory $productOptionFactory
5170 * @param ProductOptionExtensionFactory $extensionFactory
5271 * @param CustomOptionFactory $customOptionFactory
5372 * @param \Magento\Framework\Serialize\Serializer\Json|null $serializer
73+ * @param ProductRepositoryInterface|null $productRepository
74+ * @param ImageContentProcessor|null $imageContentProcessor
5475 */
5576 public function __construct (
5677 \Magento \Framework \DataObject \Factory $ objectFactory ,
5778 \Magento \Quote \Model \Quote \ProductOptionFactory $ productOptionFactory ,
5879 \Magento \Quote \Api \Data \ProductOptionExtensionFactory $ extensionFactory ,
5980 \Magento \Catalog \Model \CustomOptions \CustomOptionFactory $ customOptionFactory ,
60- ?\Magento \Framework \Serialize \Serializer \Json $ serializer = null
81+ ?\Magento \Framework \Serialize \Serializer \Json $ serializer = null ,
82+ ?ProductRepositoryInterface $ productRepository = null ,
83+ ?ImageContentProcessor $ imageContentProcessor = null
6184 ) {
6285 $ this ->objectFactory = $ objectFactory ;
6386 $ this ->productOptionFactory = $ productOptionFactory ;
6487 $ this ->extensionFactory = $ extensionFactory ;
6588 $ this ->customOptionFactory = $ customOptionFactory ;
6689 $ this ->serializer = $ serializer ?: \Magento \Framework \App \ObjectManager::getInstance ()
6790 ->get (\Magento \Framework \Serialize \Serializer \Json::class);
91+ $ this ->productRepository = $ productRepository
92+ ?: \Magento \Framework \App \ObjectManager::getInstance ()
93+ ->get (ProductRepositoryInterface::class);
94+ $ this ->imageContentProcessor = $ imageContentProcessor
95+ ?: \Magento \Framework \App \ObjectManager::getInstance ()
96+ ->get (ImageContentProcessor::class);
6897 }
6998
7099 /**
71100 * @inheritDoc
72101 */
73102 public function convertToBuyRequest (CartItemInterface $ cartItem )
74103 {
75- if ($ cartItem ->getProductOption ()
76- && $ cartItem ->getProductOption ()->getExtensionAttributes ()
77- && $ cartItem ->getProductOption ()->getExtensionAttributes ()->getCustomOptions ()) {
104+ if ($ cartItem ->getProductOption ()?->getExtensionAttributes()?->getCustomOptions()) {
78105 $ customOptions = $ cartItem ->getProductOption ()->getExtensionAttributes ()->getCustomOptions ();
79- if (!empty ($ customOptions ) && is_array ( $ customOptions ) ) {
106+ if (!empty ($ customOptions )) {
80107 $ requestData = [];
108+ $ productOptions = $ this ->getProductCustomOptions ($ cartItem );
81109 foreach ($ customOptions as $ option ) {
82- $ requestData ['options ' ][$ option ->getOptionId ()] = $ option ->getOptionValue ();
110+ $ requestData ['options ' ][$ option ->getOptionId ()] = $ this ->getCustomOptionValue (
111+ $ option ,
112+ $ productOptions [$ option ->getOptionId ()] ?? null
113+ );
83114 }
84115 return $ this ->objectFactory ->create ($ requestData );
85116 }
@@ -99,7 +130,6 @@ public function processOptions(CartItemInterface $cartItem)
99130 ? $ cartItem ->getProductOption ()
100131 : $ this ->productOptionFactory ->create ();
101132
102- /** @var \Magento\Quote\Api\Data\ProductOptionExtensionInterface $extensibleAttribute */
103133 $ extensibleAttribute = $ productOption ->getExtensionAttributes ()
104134 ? $ productOption ->getExtensionAttributes ()
105135 : $ this ->extensionFactory ->create ();
@@ -136,7 +166,7 @@ protected function getOptions(CartItemInterface $cartItem)
136166 protected function updateOptionsValues (array &$ options )
137167 {
138168 foreach ($ options as $ optionId => &$ optionValue ) {
139- /** @var \Magento\Catalog\Model\CustomOptions\ CustomOption $option */
169+ /** @var CustomOption $option */
140170 $ option = $ this ->customOptionFactory ->create ();
141171 $ option ->setOptionId ($ optionId );
142172 if (is_array ($ optionValue )) {
@@ -204,4 +234,55 @@ private function getUrlBuilder()
204234 }
205235 return $ this ->urlBuilder ;
206236 }
237+
238+ /**
239+ * Get Product Options
240+ *
241+ * @param CartItemInterface $cartItem
242+ * @return ProductCustomOptionInterface[]
243+ */
244+ private function getProductCustomOptions (CartItemInterface $ cartItem ): array
245+ {
246+ try {
247+ $ product = $ this ->productRepository ->get ($ cartItem ->getSku ());
248+ } catch (NoSuchEntityException ) {
249+ $ product = null ;
250+ }
251+
252+ $ options = [];
253+ foreach ($ product ?->getHasOptions() ? $ product ->getOptions () : [] as $ option ) {
254+ $ options [$ option ->getOptionId ()] = $ option ;
255+ }
256+ return $ options ;
257+ }
258+
259+ /**
260+ * Get custom option value depending on the type of custom option
261+ *
262+ * @param CustomOptionInterface $customOption
263+ * @param ProductCustomOptionInterface|null $productCustomOption
264+ * @return string|array|null
265+ */
266+ private function getCustomOptionValue (
267+ CustomOptionInterface $ customOption ,
268+ ?ProductCustomOptionInterface $ productCustomOption = null
269+ ): mixed {
270+ if ($ customOption ->getExtensionAttributes ()?->getFileInfo()) {
271+ if ($ productCustomOption
272+ && $ productCustomOption ->getType () === ProductCustomOptionInterface::OPTION_TYPE_FILE
273+ ) {
274+ return $ this ->imageContentProcessor ->process (
275+ $ customOption ->getExtensionAttributes ()->getFileInfo (),
276+ $ productCustomOption
277+ );
278+ } elseif ($ customOption instanceof CustomOption) {
279+ // Check if the custom option is an instance of CustomOption for backward compatibility
280+ // Bypass CustomOption::getOptionValue as the current implementation would process the file
281+ // even if it is not a file option.
282+ return $ customOption ->getData (CustomOptionInterface::OPTION_VALUE );
283+ }
284+ }
285+
286+ return $ customOption ->getOptionValue ();
287+ }
207288}
0 commit comments