Showing posts with label controller. Show all posts
Showing posts with label controller. Show all posts

Tuesday 26 June 2018

How to create configurable product with simple products with attributes using controller in Magento 2 Programmatically | Custom | Custom Module

How to create configurable product with simple products in Magento 2


Step 1 : Create Cotroller

<?php

namespace Jaydip\Kansagra\Controller\Jaydip;

use Magento\Framework\App\Action\Context;

class Createproduct extends \Magento\Framework\App\Action\Action {

    protected $_resultpageFactory;
    protected $_eavAttributeFactory;
    protected $eavConfig;
    protected $directoryList;
    protected $file;

    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $pageFactory,
        \Magento\Framework\App\Filesystem\DirectoryList $directoryList,
        \Magento\Framework\Filesystem\Io\File $file) {

        $this->_resultpageFactory = $pageFactory;
        $this->directoryList = $directoryList;
        $this->file = $file;
        return parent::__construct($context);
    }

    public function execute() {

        /*$postdata = $this->_request->getPost('product');*/
        $postdata = array(
                    'name' => 'Jaydip Kansagra Test product',
                    'magentoid' => 0,
                    'description' => 'description',
                    'categoryid' => 3,
                    'handle'    => 'jaydipkansagra',
                    'image'     => 'https://domain.com/jaydipkansagra.jpg',
                    'variants' => array(
                        '7407003205687' => array(
                            'id' => 7407003205687,
                            'title' => 'Jaydip Kansagra Test product Child 1',
                            'magechildid' => 0,
                            'sku' => 'CASCADETANK-Black',
                            'inventory' => 1,
                            'price' => 31.95,
                            'c_price' => 0,
                            'weight' => 6.8079,
                            'barcode' => 0,
                            'images'    => array(
                                0 => 'https://domain.com/jaydipkansagra.jpg'
                            )

                        ),
                        '7407003238455' => array(
                            'id' => 7407003238455,
                            'title' => 'Jaydip Kansagra Test product child 2',
                            'magechildid' => 0,
                            'sku' => 'CASCADETANK-Rainbow',
                            'inventory' => 1,
                            'price' => 31.95,
                            'c_price' => 0,
                            'weight' => 6.8079,
                            'barcode' => 0,
                            'images'    => array(
                                0 => 'https://domain.com/jaydipkansagra.jpg'
                            )
                        )

                    ),
                    'options'=> array(
                        'name'=>'Color',
                        'value'=>array(
                            0=> 'Red',
                            1=> 'Green'
                        )
                    )
        );

        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $productattr = $objectManager->create('Jaydip\Kansagra\Helper\Productattr');
        $channelstore = $objectManager->create('Magento\Customer\Model\Session');
        $channelstore = $channelstore->getChannelStore();

        if($postdata['magentoid'] > 0){

            $productCollection = $objectManager->create('Magento\Catalog\Model\ResourceModel\Product\Collection');
            $productCollection->addAttributeToSelect('*');
            $productCollection->addAttributeToFilter('entity_id', array('eq' => $postdata['magentoid']));
            $productCollection->addAttributeToFilter('type_id', array('eq' => 'configurable'));
            $magentoproduct = array();

            $magentoproduct['child'] = array();
            foreach ($productCollection as $product):
                if($product->getTypeId() == 'configurable'){
                    $_children = $product->getTypeInstance()->getUsedProducts($product);
                    foreach ($_children as $child){
                        $product = $objectManager->create('Magento\Catalog\Model\Product')->load($child->getId());
                        $magentoproduct['child'][] = json_decode(json_encode($product->getData()));
                    }
                }
            endforeach;
        }

        //Remove product from vapejuice which is removed
        if(isset($magentoproduct['child'])){
            foreach ($magentoproduct['child'] as $child):
                if(!isset($postdata['variants'][$child->source_variant_id])){
                    $registry = $objectManager->get('\Magento\Framework\Registry');
                    $registry->register('isSecureArea', true);
                    $removeproduct = $objectManager->create('\Magento\Catalog\Model\Product');
                    $removeproduct->load($child->entity_id);
                    $removeproduct->delete();
                }
            endforeach;
        }

        //Create / or get Attribute detail
        $attributes = $attrgroup = $associatedProductIds = array();
        foreach ($postdata['options'] as $j=>$option):
            $j++;
            foreach ($option['values'] as $value):
                try {
                    $attributes[$j][$value] = $productattr->createOrGetId($option['name'], $value);
                } catch (\Exception $e) {
                    echo $e->getMessage();
                }
            endforeach;

        endforeach;

        foreach ($postdata['variants'] as $variant): //Create Simple product

            $weight = $variant['weight'];
            $weight = ($weight!=0)?$weight:1;
            $price = $variant['price'];
            $inventory = $variant['inventory'];

            $product = $objectManager->create('\Magento\Catalog\Model\Product');
            if(isset($variant['magechildid']) && $variant['magechildid'] > 0){
                $product->load($variant['magechildid']);
            }

            $varianttitle = $variant['title'];
            $title = $postdata['name'].$varianttitle;
            $urltitle = str_replace(' ', '-', $title);
            $urlkey = preg_replace("#[^a-zA-Z0-9]+/[^a-zA-Z0-9]+#", "", strtolower($urltitle));
            $sku = ($variant['sku'] != '')?$variant['sku']:$urltitle;

            $product->setName($title);
            $product->setUrlKey($urlkey);
            $product->setSku($sku);
            $product->setAttributeSetId(4);
            $product->setStatus(1);
            $product->setWebsiteIds(array(1));
            $product->setWeight($weight);
            $product->setVisibility(1);
            $product->setTaxClassId(0);
            $product->setCategoryIds([$postdata['categoryid']]);
            $product->setTypeId('simple');
            $product->setPrice($price);

            //Set attribute value for simple product
            foreach ($attributes as $k=>$attribute):
                $attr = $attribute[$variant['option'.$k]];
                $attrlabel = 'set'.ucfirst(strtolower($attr['attrcode']));
                $product->$attrlabel($attr['optionid']);
                $attrgroup[] = $attr['attrid'];
            endforeach;

            $product->setStockData(
                array(
                    'use_config_manage_stock' => 1,
                    'manage_stock' => 1,
                    'is_in_stock' => 1,
                    'qty' => $inventory
                )
            );

            //Set Images
            foreach ($postdata['images'] as $simage):

                $imagePath = $simage;
                if (@getimagesize($imagePath)) {
                    $this->setImage($product, $imagePath, false, $imageType = ['image', 'small_image', 'thumbnail']);
                }

            endforeach;

            $product->save();

            $associatedProductIds[] = $product->getId();
            //pre(json_decode(json_encode($product->getData())));
        endforeach;

        $postproductnm = $postdata['name'];
        $postproductdesc = $postdata['description'];

        $attrgroup = array_unique($attrgroup);

        $mainurl = str_replace(' ', '-', strtolower($postdata['name']));

        //Create master simple product for make it configurable
        $product = $objectManager->create('\Magento\Catalog\Model\Product');
        if(isset($postdata['magentoid']) && $postdata['magentoid'] > 0){
            $product->load($postdata['magentoid']);
        }
        $product->setName($postproductnm); // Name of Product
        $product->setDescription($postproductdesc); // Description of Product
        $product->setSku($mainurl); // Set your sku here
        $product->setUrlKey($postdata['handle']); // Set your URL here
        $product->setAttributeSetId(4); // Attribute set id
        $product->setStatus(1); // Status on product enabled/ disabled 1/0
        $product->setCategoryIds([$postdata['categoryid']]);
        $product->setWebsiteIds(array(1)); // Website Ids
        $product->setWeight($variant['weight']); // weight of product
        $product->setVisibility(4); // visibilty of product (catalog / search / catalog, search / Not visible individually)
        $product->setTaxClassId(0); // Tax class id
        $product->setTypeId('simple'); // type of product (simple/virtual/downloadable/configurable)

        $product->setStockData(
            array(
                'use_config_manage_stock' => 1,
                'manage_stock' => 1,
                'is_in_stock' => 1,
                'qty' => 1
            )
        );

        if(isset($postdata['image'])){

            $imagePath = $postdata['image'];
            if (@getimagesize($imagePath)) {
                $this->setImage($product, $imagePath, false, $imageType = ['image', 'small_image', 'thumbnail']);
            }    
        }

        $product->save();

        //Create configurable which is Master simple product with assign simple product to Configurable product
        $productId = $product->getId(); // Master simple Product Id
        $product = $objectManager->create('Magento\Catalog\Model\Product')->load($productId); // Load Master simple Product
        $attributeModel = $objectManager->create('Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute');
        $position = 0;
        $attributes = $attrgroup; // Super Attribute Ids Used To Create Configurable Product
        foreach ($attributes as $attributeId) {
            $data = array('attribute_id' => $attributeId, 'product_id' => $productId, 'position' => $position);
            $position++;
            $attributeModel->setData($data)->save();
        }
        $product->setTypeId("configurable"); // Setting Product Type As Configurable
        $product->setAffectConfigurableProductAttributes(4);
        $objectManager->create('Magento\ConfigurableProduct\Model\Product\Type\Configurable')->setUsedProductAttributeIds($attributes, $product);
        $product->setNewVariationsAttributeSetId(4); // Setting Attribute Set Id
        $product->setAssociatedProductIds($associatedProductIds);// Setting Associated Products
        $product->setCanSaveConfigurableAttributes(true);
        $product->save();
        pre(json_encode($product->getData()));exit;
    }

    protected function getMediaDirTmpDir()
    {
        return $this->directoryList->getPath($this->directoryList::MEDIA) . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
    }

    protected function setImage($product, $imageUrl, $visible = false, $imageType = [])
    {
        /** @var string $tmpDir */
        $tmpDir = $this->getMediaDirTmpDir();
        /** create folder if it is not exists */
        $this->file->checkAndCreateFolder($tmpDir);
        /** @var string $newFileName */
        $newFileName = $tmpDir . baseName($imageUrl);

        /** read file from URL and copy it to the new destination */
        $result = $this->file->read($imageUrl, $newFileName);
        if ($result) {
            /** add saved file to the $product gallery */
            $product->addImageToMediaGallery($newFileName, $imageType, true, $visible);
        }
        return $result;
    }

}

Step 2 : Create Helper for attribute



<?php

/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Jaydip\Kansagra\Helper;

use Magento\Framework\Registry;

class Productattr extends \Magento\Framework\App\Helper\AbstractHelper {

    /**
     * @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface
     */
    protected $attributeRepository;

    /**
     * @var array
     */
    protected $attributeValues;

    /**
     * @var \Magento\Eav\Model\Entity\Attribute\Source\TableFactory
     */
    protected $tableFactory;

    /**
     * @var \Magento\Eav\Api\AttributeOptionManagementInterface
     */
    protected $attributeOptionManagement;

    /**
     * @var \Magento\Eav\Api\Data\AttributeOptionLabelInterfaceFactory
     */
    protected $optionLabelFactory;

    /**
     * @var \Magento\Eav\Api\Data\AttributeOptionInterfaceFactory
     */
    protected $optionFactory;

    protected $eavAttributeFactory;

    protected $attributeManagement;

    protected $config;

    /**
     * Data constructor.
     *
     * @param \Magento\Framework\App\Helper\Context $context
     * @param \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository
     * @param \Magento\Eav\Model\Entity\Attribute\Source\TableFactory $tableFactory
     * @param \Magento\Eav\Api\AttributeOptionManagementInterface $attributeOptionManagement
     * @param \Magento\Eav\Api\Data\AttributeOptionLabelInterfaceFactory $optionLabelFactory
     * @param \Magento\Eav\Api\Data\AttributeOptionInterfaceFactory $optionFactory
     */
    public function __construct(
        \Magento\Framework\App\Helper\Context $context,
        \Magento\Catalog\Model\Config $config,
        \Magento\Catalog\Api\ProductAttributeRepositoryInterface $attributeRepository,
        \Magento\Eav\Model\Entity\Attribute\Source\TableFactory $tableFactory,
        \Magento\Eav\Api\AttributeOptionManagementInterface $attributeOptionManagement,
        \Magento\Eav\Api\Data\AttributeOptionLabelInterfaceFactory $optionLabelFactory,
        \Magento\Eav\Api\Data\AttributeOptionInterfaceFactory $optionFactory,
        \Magento\Eav\Api\AttributeManagementInterface $attributeManagement,
        \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory $eavAttributeFactory
    ) {
        parent::__construct($context);

        $this->attributeRepository = $attributeRepository;
        $this->tableFactory = $tableFactory;
        $this->attributeOptionManagement = $attributeOptionManagement;
        $this->optionLabelFactory = $optionLabelFactory;
        $this->optionFactory = $optionFactory;
        $this->eavAttributeFactory = $eavAttributeFactory;
        $this->config = $config;
        $this->attributeManagement = $attributeManagement;
    }

    /**
     * Get attribute by code.
     *
     * @param string $attributeCode
     * @return \Magento\Catalog\Api\Data\ProductAttributeInterface
     */
    public function getAttribute($attributeCode) {
        try {
            return $this->attributeRepository->get($attributeCode);
        } catch (\Exception $e) {
            return false;
        }
    }

    public function addAttribute($attributecode, $attributelabel, $attroptions = array()) {

        $attributeData = array(
            'attribute_code' => $attributecode,
            'is_global' => 1,
            'frontend_label' => $attributelabel,
            'frontend_input' => 'select',
            'default_value_text' => '',
            'default_value_yesno' => 0,
            'default_value_date' => '',
            'default_value_textarea' => '',
            'is_unique' => 0,
            'apply_to' => 0,
            'is_required' => 0,
            'is_configurable' => 1,
            'is_searchable' => 1,
            'is_comparable' => 1,
            'is_visible_in_advanced_search' => 0,
            'is_used_for_price_rules' => 0,
            'is_wysiwyg_enabled' => 0,
            'is_html_allowed_on_front' => 0,
            'is_visible_on_front' => 0,
            'used_in_product_listing' => 0,
            'used_for_sort_by' => 0,
            'is_filterable' => 1,
            'is_filterable_in_search' => 0,
            'backend_type' => 'int',
            'is_user_defined' => 1,
            'group' => 'General',
            'option' => array()
        );
        foreach ($attroptions as $key=>$attroption):
            $attributeData['option']['value']['option_'.$key] = array($attroption, $attroption);
        endforeach;

        try {
            $model = $this->eavAttributeFactory->create();
            $model->addData($attributeData);
            $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
            $entityTypeID = $objectManager->create('Magento\Eav\Model\Entity')
            ->setType('catalog_product')
            ->getTypeId();
            $model->setEntityTypeId($entityTypeID);
            $model->save();

            $group_id = $this->config->getAttributeGroupId(4, 'Attribute Option');
            $this->attributeManagement->assign('catalog_product', 4, $group_id, $model->getAttributeCode(), null);

            return $model;
        } catch (\Exception $e) {
            return $e->getMessage();
        }       
    }

    /**
     * Find or create a matching attribute option
     *
     * @param string $attributeCode Attribute the option should exist in
     * @param string $label Label to find or add
     * @return int
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function createOrGetId($attributeCode, $label = '') {

        if (strlen($label) < 1) {
            throw new \Magento\Framework\Exception\LocalizedException(
            __('Label for %1 must not be empty.', $attributeCode)
            );
        }

        $label = ucfirst(strtolower($label));
        $attributeLabel = ucfirst(strtolower($attributeCode));
        $attributeCode = preg_replace("/[^a-zA-Z0-9]+/", "", strtolower($attributeCode));

        $attribute = $this->getAttribute($attributeCode);

        if(!$attribute){
            //Create new attribute
            $attribute = $this->addAttribute($attributeCode, $attributeLabel, array($label));
        }

        // Does it already exist?
        $optionId = $this->getOptionId($attributeCode, $label);
        if (!$optionId) {
            // If no, add it.

            /** @var \Magento\Eav\Model\Entity\Attribute\OptionLabel $optionLabel */
            $optionLabel = $this->optionLabelFactory->create();
            $optionLabel->setStoreId(0);
            $optionLabel->setLabel($label);

            $option = $this->optionFactory->create();
            $option->setLabel($optionLabel);
            $option->setStoreLabels([$optionLabel]);
            $option->setSortOrder(0);
            $option->setIsDefault(false);

            $this->attributeOptionManagement->add(
                    \Magento\Catalog\Model\Product::ENTITY, $this->getAttribute($attributeCode)->getAttributeId(), $option
            );

            // Get the inserted ID. Should be returned from the installer, but it isn't.
            $optionId = $this->getOptionId($attributeCode, $label, true);
        }

        return array('attrid'=>$attribute->getAttributeId(), 'attrcode'=>$attributeCode, 'optionid'=>$optionId);
    }

    /**
     * Find the ID of an option matching $label, if any.
     *
     * @param string $attributeCode Attribute code
     * @param string $label Label to find
     * @param bool $force If true, will fetch the options even if they're already cached.
     * @return int|false
     */
    public function getOptionId($attributeCode, $label, $force = false) {
        /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */
        $attribute = $this->getAttribute($attributeCode);

        // Build option array if necessary
        if ($force === true || !isset($this->attributeValues[$attribute->getAttributeId()])) {
            $this->attributeValues[$attribute->getAttributeId()] = [];

            // We have to generate a new sourceModel instance each time through to prevent it from
            // referencing its _options cache. No other way to get it to pick up newly-added values.

            /** @var \Magento\Eav\Model\Entity\Attribute\Source\Table $sourceModel */
            $sourceModel = $this->tableFactory->create();
            $sourceModel->setAttribute($attribute);

            foreach ($sourceModel->getAllOptions() as $option) {
                $this->attributeValues[$attribute->getAttributeId()][$option['label']] = $option['value'];
            }
        }

        // Return option ID if exists
        if (isset($this->attributeValues[$attribute->getAttributeId()][$label])) {
            return $this->attributeValues[$attribute->getAttributeId()][$label];
        }

        // Return false if does not exist
        return false;
    }

}