diff --git a/app/code/Magento/Catalog/Model/Product/Option/Type/File.php b/app/code/Magento/Catalog/Model/Product/Option/Type/File.php index 2b809914ab71d..095ce653b5e66 100644 --- a/app/code/Magento/Catalog/Model/Product/Option/Type/File.php +++ b/app/code/Magento/Catalog/Model/Product/Option/Type/File.php @@ -6,13 +6,14 @@ namespace Magento\Catalog\Model\Product\Option\Type; -use Magento\Catalog\Model\Product\Exception as ProductException; use Magento\Catalog\Helper\Product as ProductHelper; +use Magento\Catalog\Model\Product\Exception as ProductException; +use Magento\Catalog\Model\Product\Type\AbstractType; use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\Filesystem; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem; use Magento\Framework\Serialize\Serializer\Json; -use Magento\Framework\App\ObjectManager; /** * Catalog product option file type @@ -353,10 +354,17 @@ public function getFormattedOptionValue($optionValue) if ($value === null) { return $optionValue; } + $optionId = str_replace( + AbstractType::OPTION_PREFIX, + '', + (string)$this->getConfigurationItemOption()->getCode() + ); $customOptionUrlParams = $this->getCustomOptionUrlParams() ? $this->getCustomOptionUrlParams() : [ 'id' => $this->getConfigurationItemOption()->getId(), + 'item' => $this->getConfigurationItemOption()->getItemId(), + 'option' => $optionId, 'key' => $value['secret_key'] ]; diff --git a/app/code/Magento/Sales/Controller/Download/DownloadCustomOption.php b/app/code/Magento/Sales/Controller/Download/DownloadCustomOption.php index 14551758140b6..dd06f6e56dc7d 100644 --- a/app/code/Magento/Sales/Controller/Download/DownloadCustomOption.php +++ b/app/code/Magento/Sales/Controller/Download/DownloadCustomOption.php @@ -1,19 +1,25 @@ resultForwardFactory = $resultForwardFactory; @@ -60,6 +73,9 @@ public function __construct( $this->serializer = $serializer ?: ObjectManager::getInstance()->get( \Magento\Framework\Serialize\Serializer\Json::class ); + $this->itemCollectionFactory = $itemCollectionFactory ?: ObjectManager::getInstance()->get( + CollectionFactory::class + ); } /** @@ -72,6 +88,8 @@ public function __construct( public function execute() { $quoteItemOptionId = $this->getRequest()->getParam('id'); + $quoteItemId = $this->getRequest()->getParam('item'); + $optionId = $this->getRequest()->getParam('option'); /** @var $option \Magento\Quote\Model\Quote\Item\Option */ $option = $this->_objectManager->create( \Magento\Quote\Model\Quote\Item\Option::class @@ -80,9 +98,35 @@ public function execute() $resultForward = $this->resultForwardFactory->create(); if (!$option->getId()) { + $optionData = $this->getOptionFromSalesItem($quoteItemId, $optionId); + } else { + $optionData = $this->getOptionFromQuoteItem($option); + } + + if ($optionData) { + try { + $info = $this->serializer->unserialize($optionData); + if ($this->getRequest()->getParam('key') != $info['secret_key']) { + return $resultForward->forward('noroute'); + } + return $this->download->createResponse($info); + } catch (\Exception $e) { + return $resultForward->forward('noroute'); + } + } else { return $resultForward->forward('noroute'); } + $this->endExecute(); + } + /** + * Get custom option data from quote item option + * + * @param \Magento\Quote\Model\Quote\Item\Option $option + * @return string|null + */ + protected function getOptionFromQuoteItem($option) + { $optionId = null; if ($option->getCode() && strpos($option->getCode(), AbstractType::OPTION_PREFIX) === 0) { $optionId = str_replace(AbstractType::OPTION_PREFIX, '', $option->getCode()); @@ -100,19 +144,37 @@ public function execute() } if ($productOption->getId() && $productOption->getType() != 'file') { - return $resultForward->forward('noroute'); + return null; } + return $option->getValue(); + } - try { - $info = $this->serializer->unserialize($option->getValue()); - if ($this->getRequest()->getParam('key') != $info['secret_key']) { - return $resultForward->forward('noroute'); + /** + * Get custom option data from sales item + * + * @param string|null $quoteItemId + * @param string|null $optionId + * @return string|null + */ + protected function getOptionFromSalesItem($quoteItemId, $optionId) + { + if (!$quoteItemId || !$optionId) { + return null; + } + $collection = $this->itemCollectionFactory->create(); + $quoteItem = $collection->addFieldToFilter(OrderItemInterface::QUOTE_ITEM_ID, $quoteItemId)->getFirstItem(); + if ($quoteItem && $quoteItem->getId()) { + try { + $options = $quoteItem->getProductOptionByCode('options'); + $key = array_search($optionId, array_column($options, 'option_id')); + if ($key !== false && $options[$key]['option_value'] && $options[$key]['option_type'] == 'file') { + return $options[$key]['option_value']; + } + } catch (\Exception $e) { + return null; } - return $this->download->createResponse($info); - } catch (\Exception $e) { - return $resultForward->forward('noroute'); } - $this->endExecute(); + return null; } /** diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Download/DownloadCustomOptionTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Download/DownloadCustomOptionTest.php index 4ac04cf3461e7..af68b1ae247e6 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Download/DownloadCustomOptionTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Download/DownloadCustomOptionTest.php @@ -1,7 +1,7 @@ onlyMethods(['serialize', 'unserialize']) ->getMock(); + $this->itemCollectionFactoryMock = $this->getMockBuilder(CollectionFactory::class) + ->disableOriginalConstructor() + ->onlyMethods(['create']) + ->getMock(); + $requestMock = $this->getMockBuilder(Http::class) ->disableOriginalConstructor() ->onlyMethods(['getParam']) @@ -160,7 +171,8 @@ protected function setUp(): void 'resultForwardFactory' => $resultForwardFactoryMock, 'download' => $this->downloadMock, 'unserialize' => $this->createMock(Unserialize::class), - 'serializer' => $this->serializerMock + 'serializer' => $this->serializerMock, + 'itemCollectionFactory' => $this->itemCollectionFactoryMock ] ) ->getMock(); diff --git a/app/code/Magento/Sales/etc/db_schema.xml b/app/code/Magento/Sales/etc/db_schema.xml index 2190e78371db4..aac7e78264bbc 100644 --- a/app/code/Magento/Sales/etc/db_schema.xml +++ b/app/code/Magento/Sales/etc/db_schema.xml @@ -604,6 +604,9 @@ + + +