0

I added custom field Image and Qty in Product Customizable Options. I add those filed to Product Option Value in Product Rest API. So how can it possible.

Method: GET

API Request URL: http://localhost/magentosample231/rest/V1/products/24-MB01

Reposne:

{
    "id": 1,
    "sku": "24-MB01",
    "name": "Joust Duffle Bag",
    "attribute_set_id": 15,
    "price": 34,
    "status": 1,
    "visibility": 4,
    "type_id": "simple",
    "created_at": "2019-08-30 07:14:51",
    "updated_at": "2019-10-16 11:56:24",
    "extension_attributes": {
        "website_ids": [
            1
        ],
        "category_links": [
            {
                "position": 0,
                "category_id": "3"
            },
            {
                "position": 0,
                "category_id": "4"
            }
        ],
        "stock_item": {
            "item_id": 1,
            "product_id": 1,
            "stock_id": 1,
            "qty": 100,
            "is_in_stock": true,
            "is_qty_decimal": false,
            "show_default_notification_message": false,
            "use_config_min_qty": true,
            "min_qty": 0,
            "use_config_min_sale_qty": 1,
            "min_sale_qty": 1,
            "use_config_max_sale_qty": true,
            "max_sale_qty": 10000,
            "use_config_backorders": true,
            "backorders": 0,
            "use_config_notify_stock_qty": true,
            "notify_stock_qty": 1,
            "use_config_qty_increments": true,
            "qty_increments": 0,
            "use_config_enable_qty_inc": true,
            "enable_qty_increments": false,
            "use_config_manage_stock": true,
            "manage_stock": true,
            "low_stock_date": null,
            "is_decimal_divided": false,
            "stock_status_changed_auto": 0
        }
    },
    "product_links": [
        {
            "sku": "24-MB01",
            "link_type": "crosssell",
            "linked_product_sku": "24-WG086",
            "linked_product_type": "simple",
            "position": 1
        },
        {
            "sku": "24-MB01",
            "link_type": "crosssell",
            "linked_product_sku": "24-WG083-blue",
            "linked_product_type": "simple",
            "position": 2
        },
        {
            "sku": "24-MB01",
            "link_type": "crosssell",
            "linked_product_sku": "24-UG01",
            "linked_product_type": "simple",
            "position": 3
        },
        {
            "sku": "24-MB01",
            "link_type": "crosssell",
            "linked_product_sku": "24-WG085_Group",
            "linked_product_type": "grouped",
            "position": 4
        },
        {
            "sku": "24-MB01",
            "link_type": "upsell",
            "linked_product_sku": "24-MB02",
            "linked_product_type": "simple",
            "position": 1
        },
        {
            "sku": "24-MB01",
            "link_type": "upsell",
            "linked_product_sku": "24-MB03",
            "linked_product_type": "simple",
            "position": 2
        },
        {
            "sku": "24-MB01",
            "link_type": "upsell",
            "linked_product_sku": "24-MB05",
            "linked_product_type": "simple",
            "position": 3
        },
        {
            "sku": "24-MB01",
            "link_type": "upsell",
            "linked_product_sku": "24-MB06",
            "linked_product_type": "simple",
            "position": 4
        },
        {
            "sku": "24-MB01",
            "link_type": "upsell",
            "linked_product_sku": "24-UB02",
            "linked_product_type": "simple",
            "position": 5
        },
        {
            "sku": "24-MB01",
            "link_type": "upsell",
            "linked_product_sku": "24-WB03",
            "linked_product_type": "simple",
            "position": 6
        },
        {
            "sku": "24-MB01",
            "link_type": "upsell",
            "linked_product_sku": "24-WB04",
            "linked_product_type": "simple",
            "position": 7
        },
        {
            "sku": "24-MB01",
            "link_type": "upsell",
            "linked_product_sku": "24-WB07",
            "linked_product_type": "simple",
            "position": 8
        }
    ],
    "options": [
        {
            "product_sku": "24-MB01",
            "option_id": 1,
            "title": "Test",
            "type": "drop_down",
            "sort_order": 1,
            "is_require": true,
            "max_characters": 0,
            "image_size_x": 0,
            "image_size_y": 0,
            "values": [
                {
                    "title": "Test1",
                    "sort_order": 1,
                    "price": 10,
                    "price_type": "fixed",
                    "sku": "24-MB01",
                    "option_type_id": 1
                },
                {
                    "title": "Test2",
                    "sort_order": 2,
                    "price": 12,
                    "price_type": "fixed",
                    "sku": "24-MB01",
                    "option_type_id": 2
                }
            ]
        }
    ],
    "media_gallery_entries": [
        {
            "id": 1,
            "media_type": "image",
            "label": "Image",
            "position": 1,
            "disabled": false,
            "types": [
                "image",
                "small_image",
                "thumbnail"
            ],
            "file": "/m/b/mb01-blue-0.jpg"
        }
    ],
    "tier_prices": [],
    "custom_attributes": [
        {
            "attribute_code": "activity",
            "value": []
        },
        {
            "attribute_code": "style_bags",
            "value": []
        },
        {
            "attribute_code": "material",
            "value": []
        },
        {
            "attribute_code": "color",
            "value": [
                {
                    "Title": "Color",
                    "label": "Black",
                    "code": "49",
                    "Visible on Storefront": "1"
                }
            ]
        },
        {
            "attribute_code": "strap_bags",
            "value": []
        },
        {
            "attribute_code": "features_bags",
            "value": []
        },
        {
            "attribute_code": "image",
            "value": "/m/b/mb01-blue-0.jpg"
        },
        {
            "attribute_code": "small_image",
            "value": "/m/b/mb01-blue-0.jpg"
        },
        {
            "attribute_code": "thumbnail",
            "value": "/m/b/mb01-blue-0.jpg"
        },
        {
            "attribute_code": "options_container",
            "value": "container1"
        },
        {
            "attribute_code": "msrp_display_actual_price_type",
            "value": "0"
        },
        {
            "attribute_code": "url_key",
            "value": "joust-duffle-bag"
        },
        {
            "attribute_code": "gift_message_available",
            "value": "0"
        },
        {
            "attribute_code": "required_options",
            "value": "1"
        },
        {
            "attribute_code": "has_options",
            "value": "1"
        },
        {
            "attribute_code": "image_label",
            "value": "Image"
        },
        {
            "attribute_code": "small_image_label",
            "value": "Image"
        },
        {
            "attribute_code": "thumbnail_label",
            "value": "Image"
        },
        {
            "attribute_code": "tax_class_id",
            "value": "0"
        },
        {
            "attribute_code": "category_ids",
            "value": [
                "3",
                "4"
            ]
        },
        {
            "attribute_code": "description",
            "value": "<p>The sporty Joust Duffle Bag can't be beat - not in the gym, not on the luggage carousel, not anywhere. Big enough to haul a basketball or soccer ball and some sneakers with plenty of room to spare, it's ideal for athletes with places to go.<p>\r\n<ul>\r\n<li>Dual top handles.</li>\r\n<li>Adjustable shoulder strap.</li>\r\n<li>Full-length zipper.</li>\r\n<li>L 29\" x W 13\" x H 11\".</li>\r\n</ul>"
        },
        {
            "attribute_code": "eco_collection",
            "value": "0"
        },
        {
            "attribute_code": "performance_fabric",
            "value": "0"
        },
        {
            "attribute_code": "erin_recommends",
            "value": "0"
        },
        {
            "attribute_code": "new",
            "value": "0"
        },
        {
            "attribute_code": "sale",
            "value": "0"
        }
    ]
}

See the reposne there is a "options"

"options": [
        {
            "product_sku": "24-MB01",
            "option_id": 1,
            "title": "Test",
            "type": "drop_down",
            "sort_order": 1,
            "is_require": true,
            "max_characters": 0,
            "image_size_x": 0,
            "image_size_y": 0,
            "values": [
                {
                    "title": "Test1",
                    "sort_order": 1,
                    "price": 10,
                    "price_type": "fixed",
                    "sku": "24-MB01",
                    "option_type_id": 1
                },
                {
                    "title": "Test2",
                    "sort_order": 2,
                    "price": 12,
                    "price_type": "fixed",
                    "sku": "24-MB01",
                    "option_type_id": 2
                }
            ]
        }
    ],

I have to add my custom added options field Image and Qty in to the Options Value like same as below.

 "options": [
    {
        "product_sku": "24-MB01",
        "option_id": 1,
        "title": "Test",
        "type": "drop_down",
        "sort_order": 1,
        "is_require": true,
        "max_characters": 0,
        "image_size_x": 0,
        "image_size_y": 0,
        "values": [
            {
                "title": "Test1",
                "sort_order": 1,
                "price": 10,
                "price_type": "fixed",
                "sku": "24-MB01",
                "option_type_id": 1,
                "image": "test.jpg",
                "qty": 2
            },
            {
                "title": "Test2",
                "sort_order": 2,
                "price": 12,
                "price_type": "fixed",
                "sku": "24-MB01",
                "option_type_id": 2,
                "image": "info.jpg",
                "qty": 1
            }
        ]
    }
],

Any help would be appreciated. Thanks!

2 Answers 2

1

I took a quick look and I think you have to work around this class \Magento\Catalog\Model\Product\Option, there is a method called addValue() which is a public function. You might do a plugin. Hope it helps.

1
  • I appreciate your suggestion, your given path is correct. I have also check to print the $value object in addValue() function and getting all the options. But how can I add that missing options to Product Rest API Options as a Value ? Oct 17, 2019 at 12:14
1

Finally I have added product custom option value to product Rest API using Plugin Magento\Catalog\Model\Product\Option\ReadHandler class.

Follow below file path to create custom module and add the product custom option value to the Product Rest API.

File path: magento/app/code/Vendor/ProductoptionsApi/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_ProductoptionsApi',
    __DIR__
);

File path: magento/app/code/Vendor/ProductoptionsApi/etc/module.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_ProductoptionsApi" setup_version="1.0.0">
    </module>
</config>

File path: magento/app/code/Vendor/ProductoptionsApi/etc/webapi_rest/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Model\Product\Option\ReadHandler">
        <plugin name="updateProductCustomOptionsValue" type="Vendor\ProductoptionsApi\Plugin\ProductCustomOptionsValue"/>
    </type>
</config>

File path: magento/app/code/Vendor/ProductoptionsApi/Plugin/ProductCustomOptionsValue.php

<?php

namespace Vendor\ProductoptionsApi\Plugin;

use Magento\Catalog\Api\ProductCustomOptionRepositoryInterface;
use Magento\Catalog\Model\Product\OptionFactory;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\EntityManager\Operation\ExtensionInterface;

class ProductCustomOptionsValue
{
    /**
     * @var ProductCustomOptionRepositoryInterface
     */
    protected $optionRepository;

    /**
     * @param ProductCustomOptionRepositoryInterface $optionRepository
     */
    public function __construct(
        ProductCustomOptionRepositoryInterface $optionRepository,
        \Vendor\ProductoptionsApi\Helper\OptionsProvider $optionProvider,
        \Magento\Catalog\Block\Product\View\Options $productOptions
    ) {
        $this->optionRepository = $optionRepository;
        $this->optionProvider = $optionProvider;
        $this->productOptions = $productOptions;
    }

    public function afterExecute(\Magento\Catalog\Model\Product\Option\ReadHandler $subject, $result, $entity, $arguments = [])
    {
        $options = $dataOption = [];
        $productSku = $entity->getSku();
        $options = $this->productOptions->decorateArray($this->optionRepository->getProductOptions($entity));
        $dataOption = $this->optionProvider->getExtendedOptionsConfig($options, $productSku);

        if($dataOption != '' && $dataOption != null && $dataOption != '[]'){
            $entity->setOptions($dataOption);
        }else{
           $options = [];
            /** @var $entity \Magento\Catalog\Api\Data\ProductInterface */
            foreach ($this->optionRepository->getProductOptions($entity) as $option) {
                $option->setProduct($entity);
                $options[] = $option;
            }
            $entity->setOptions($options);
        }
        return $entity;
    }
}

File path: magento/app/code/Vendor/ProductoptionsApi/Helper/OptionsProvider.php

<?php

declare(strict_types=1);

namespace Vendor\ProductoptionsApi\Helper;

use \MageWorx\OptionBase\Model\Product\Option\Attributes as OptionAttributes;
use \MageWorx\OptionBase\Model\Product\Option\Value\Attributes as OptionValueAttributes;
use Magento\Framework\Pricing\Helper\Data;
use Magento\Catalog\Helper\Image as ImageHelper;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\FileSystemException;
use Magento\Framework\Json\EncoderInterface;
use Magento\Framework\View\Element\AbstractBlock;
use MageWorx\OptionFeatures\Model\Image;
use MageWorx\OptionFeatures\Model\Product\Option\Value\Media\Config;

/**
 * class OptionsProvider
 */
class OptionsProvider
{
    /**
     * @var array
     */
    protected $productOptions;

    /**
     * Constructor
     *
     * @param array $components
     */
    public function __construct(
        \Magento\Catalog\Block\Product\View\Options $productOptions,
        OptionAttributes $optionAttributes,
        OptionValueAttributes $optionValueAttributes,
        \Magento\Framework\Json\EncoderInterface $jsonEncoder,
        Data $priceHelper,
        \Magento\Framework\Json\Helper\Data $jsonHelper,
        Config $mediaConfig,
        ImageHelper $imageHelper,
        \Magento\Framework\Filesystem $filesystem
    ) {
        $this->productOptions = $productOptions;
        $this->optionAttributes = $optionAttributes;
        $this->optionValueAttributes = $optionValueAttributes;
        $this->_jsonEncoder = $jsonEncoder;
        $this->priceHelper = $priceHelper;
        $this->jsonHelper = $jsonHelper;
        $this->mediaConfig = $mediaConfig;
        $this->imageHelper = $imageHelper;
        $this->_filesystem = $filesystem;
    }

    public function getExtendedOptionsConfig($options, $productSku = '')
    {
        $config = $result = [];
        $optionAttributes = $this->optionAttributes->getData();
        $optionValueAttributes = $this->optionValueAttributes->getData();
        /** @var \Magento\Catalog\Model\Product\Option $option */
        if (empty($options)) {
            return $this->_jsonEncoder->encode($config);
        }

        foreach ($options as $option) {
            $config[$option->getId()]['title']= $option->getTitle();
            $config[$option->getId()]['type']= $option->getType();
            $config[$option->getId()]['sort_order']= $option->getSortOrder();
            $config[$option->getId()]['option_id']= $option->getId();
            $config[$option->getId()]['product_sku']= $productSku;
            $config[$option->getId()]['is_require']= $option->getIsRequire();
            $config[$option->getId()]['max_characters']= $option->getMaxCharacters();
            $config[$option->getId()]['image_size_x']= $option->getImageSizeX();
            $config[$option->getId()]['image_size_y']= $option->getImageSizeY();
            foreach ($optionAttributes as $optionAttribute) {
                $preparedData = $optionAttribute->prepareDataForFrontend($option);
                if (empty($preparedData) || !is_array($preparedData)) {
                    continue;
                }
                foreach ($preparedData as $preparedDataKey => $preparedDataValue) {
                    $config[$option->getId()][$preparedDataKey] = $preparedDataValue;
                }
            }

            /** @var \Magento\Catalog\Model\Product\Option\Value $value */
            if (empty($option->getValues())) {
                continue;
            }
            $i = 0;
            foreach ($option->getValues() as $value) {

                foreach ($optionValueAttributes as $optionValueAttribute) {
                    $preparedData = $optionValueAttribute->prepareDataForFrontend($value);
                    if (empty($preparedData) || !is_array($preparedData)) {
                        continue;
                    }
                }

                $config[$option->getId()]['values'][$i]['sort_order'] = $value->getSortOrder();
                $config[$option->getId()]['values'][$i]['price_type'] = $value->getPriceType();
                $config[$option->getId()]['values'][$i]['title'] = $value->getTitle();
                $config[$option->getId()]['values'][$i]['price'] = $value->getDefaultPrice();
                $config[$option->getId()]['values'][$i]['dependency'] = $value->getDependency();
                $config[$option->getId()]['values'][$i]['dependency_type'] = $value->getDependencyType();
                $config[$option->getId()]['values'][$i]['image'] = $value->getImagesData();
                $config[$option->getId()]['values'][$i]['option_type_id'] =  $value->getId();
                $config[$option->getId()]['values'][$i]['price_type'] =  $value->getPriceType();

                $config[$option->getId()]['values'][$i]['color_code'] = $value->getTitle();
                $i++;
            }
        }
        return $config;
    }

    public function getDependency($dependency){

        $dependencyArray=[];
        $dependency = json_decode($dependency);
        foreach($dependency as $key=>$value)
        {
            $dependencyArray['key'][$key]=$value[0];
            $dependencyArray['value'][$key]=$value[1];

         }
        return $dependencyArray;
     }
}
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.