Magento 2, Magento Development, Customization, Extension Development and Integration, Optimization, SEO and Responsive Design

Magento 2, Magento Development, Customization, Extension Development and Integration, Optimization, SEO and Responsive Design

Add Product Grid In Customer Admin Section And Save The Checkbox Values To Database - Magento 2

In one of my project i want to add product grid in Magento 2 admin customer section with a separate tab. And also want to save selected product checkbox value to my custom database. After spending 2 days i found solution after merging few codes that i found.

So i have created my custom magento 2 module that will do this all thing. It will add new tab in customer admin section and also save checkbox value to custom database.


Product Grid In Customer Admin Section


Here is the quick steps to create module.
OR
You can download module here,
Note: This module also include code to show selected product in front-end.
Download

Step1: HK/Productattach/registration.php
<?php

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

Step2: HK/Productattach/Block/Adminhtml/Edit/Tab/Products.php
<?php

namespace HK\Productattach\Block\Adminhtml\Edit\Tab;

use HK\Productattach\Model\ProductattachFactory;

class Products extends \Magento\Backend\Block\Widget\Grid\Extended
{
    /**
     * @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory
     */
    private $productCollectionFactory;

    //private $attachModel;

    /**
     * @var ProductattachFactory
     */
    private $contactFactory;

    /**
     * @var \Magento\Framework\Registry
     */
    private $registry;

    /**
     * Products constructor.
     * @param \Magento\Backend\Block\Template\Context $context
     * @param \Magento\Backend\Helper\Data $backendHelper
     * @param \Magento\Framework\Registry $registry
     * @param ProductattachFactory $contactFactory
     * @param \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Backend\Helper\Data $backendHelper,
        \Magento\Framework\Registry $registry,
        ProductattachFactory $contactFactory,
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
        array $data = []
    ) {
        $this->contactFactory = $contactFactory;
        $this->productCollectionFactory = $productCollectionFactory;
        $this->registry = $registry;
        //$this->attachModel = $attachModel;
        parent::__construct($context, $backendHelper, $data);
    }

    /**
     * _construct
     * @return void
     */
    public function _construct()
    {
        parent::_construct();
        $this->setId('productsGrid');
        $this->setDefaultSort('entity_id');
        $this->setDefaultDir('DESC');
        $this->setSaveParametersInSession(true);
        $this->setUseAjax(true);
        if ($this->getRequest()->getParam('productattach_id')) {
        //if ($this->getRequest()->getParam('id')) {
            $this->setDefaultFilter(['in_product' => 1]);
        }
    }

    /**
     * @param \Magento\Backend\Block\Widget\Grid\Column $column
     * @return $this
     */
    public function _addColumnFilterToCollection($column)
    {
        if ($column->getId() == 'in_product') {
            $productIds = $this->_getSelectedProducts();

            if (empty($productIds)) {
                $productIds = 0;
            }
            if ($column->getFilter()->getValue()) {
                $this->getCollection()->addFieldToFilter('entity_id', ['in' => $productIds]);
            } else {
                if ($productIds) {
                    $this->getCollection()->addFieldToFilter('entity_id', ['nin' => $productIds]);
                }
            }
        } else {
            parent::_addColumnFilterToCollection($column);
        }

        return $this;
    }

    /**
     * prepare collection
     */
    public function _prepareCollection()
    {
        $collection = $this->productCollectionFactory->create();
        $collection->addAttributeToSelect('name');
        $collection->addAttributeToSelect('sku');
        $collection->addAttributeToSelect('price');
        $this->setCollection($collection);
        return parent::_prepareCollection();
    }

    /**
     * @return $this
     */
    public function _prepareColumns()
    {

        //$model = $this->attachModel;

        $this->addColumn(
            'in_product',
            [
                'header_css_class' => 'a-center',
                'type' => 'checkbox',
                'name' => 'in_product',
                'align' => 'center',
                'index' => 'entity_id',
                'values' => $this->_getSelectedProducts(),
            ]
        );

        $this->addColumn(
            'entity_id',
            [
                'header' => __('Product ID'),
                'type' => 'number',
                'index' => 'entity_id',
                'header_css_class' => 'col-id',
                'column_css_class' => 'col-id',
            ]
        );
        $this->addColumn(
            'names',
            [
                'header' => __('Name'),
                'index' => 'name',
                'class' => 'xxx',
                'width' => '50px',
            ]
        );
        $this->addColumn(
            'sku',
            [
                'header' => __('Sku'),
                'index' => 'sku',
                'class' => 'xxx',
                'width' => '50px',
            ]
        );
        $this->addColumn(
            'price',
            [
                'header' => __('Price'),
                'type' => 'currency',
                'index' => 'price',
                'width' => '50px',
            ]
        );

        return parent::_prepareColumns();
    }

    /**
     * @return string
     */
    public function getGridUrl()
    {
        return $this->getUrl('*/*/productsgrid', ['_current' => true]);
    }
    
    public function getTabUrl()
    {
        $id = 0;
        $customerId = $this->getRequest()->getParam('id');
        
        $_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $hkproductCollection = $_objectManager->create('HK\Productattach\Model\Productattach');
        $hkproductCollection = $hkproductCollection->getCollection()->addFieldToFilter('customer_id', $customerId);
        
        if($hkproductCollection->count() > 0){
            $id = $hkproductCollection->getFirstItem()->getId();
        }
        
        return $this->getUrl('productattach/*/products', ['productattach_id' => $id, '_current' => true]);
    }

    /**
     * @param  object $row
     * @return string
     */
    public function getRowUrl($row)
    {
        return '';
    }

    public function _getSelectedProducts()
    {
        $contact = $this->getContact();
        return $contact->getProducts($contact);
    }

    /**
     * Retrieve selected products
     *
     * @return array
     */
    public function getSelectedProducts()
    {
        $contact = $this->getContact();
        $selected = $contact->getProducts($contact);
        
        if (!is_array($selected)) {
            $selected = [];
        }
        return $selected;
    }

    public function getContact()
    {
        $contactId = $this->getRequest()->getParam('productattach_id');
        $contact = $this->contactFactory->create();
        
        if ($contactId) {
            $contact->load($contactId);
        }
        return $contact;
    }

    /**
     * {@inheritdoc}
     */
    public function canShowTab()
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function isHidden()
    {
        return true;
    }
    
    public function isAjaxLoaded()
    {
        return true;
    }
    
    public function getTabLabel()
    {
        return __('Customer Products');
    }

    /**
     * @return \Magento\Framework\Phrase
     */
    public function getTabTitle()
    {
        return __('Customer Products');
    }
}

Step3: HK/Productattach/Controller/Adminhtml/Index/Products.php
<?php

namespace HK\Productattach\Controller\Adminhtml\Index;

use Magento\Backend\App\Action;

class Products extends \Magento\Backend\App\Action
{
    /**
     * @var \Magento\Framework\View\Result\LayoutFactory
     */
    private $resultLayoutFactory;

    /**
     * Products constructor.
     * @param Action\Context $context
     * @param \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory
     */
    public function __construct(
        Action\Context $context,
        \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory
    ) {
        parent::__construct($context);
        $this->resultLayoutFactory = $resultLayoutFactory;
    }

    /**
     * @return bool
     */
    public function _isAllowed()
    {
        return true;
    }

    /**
     * Save action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {

        $resultLayout = $this->resultLayoutFactory->create();
        $resultLayout->getLayout()->getBlock('productattach.edit.tab.products')
                     ->setInProducts($this->getRequest()->getPost('index_products', null));

        return $resultLayout;
    }
}


Step4: HK/Productattach/Controller/Adminhtml/Index/ProductsGrid.php
<?php

namespace HK\Productattach\Controller\Adminhtml\Index;

use Magento\Backend\App\Action;

class ProductsGrid extends \Magento\Backend\App\Action
{

    /**
     * @var \Magento\Framework\View\Result\LayoutFactory
     */
    private $resultLayoutFactory;

    /**
     * ProductsGrid constructor.
     * @param Action\Context $context
     * @param \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory
     */
    public function __construct(
        Action\Context $context,
        \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory
    ) {
        parent::__construct($context);
        $this->resultLayoutFactory = $resultLayoutFactory;
    }

    /**
     * @return bool
     */
    public function _isAllowed()
    {
        return true;
    }

    /**
     * Save action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $resultLayout = $this->resultLayoutFactory->create();
        $resultLayout->getLayout()->getBlock('productattach.edit.tab.products')
                     ->setInBanner($this->getRequest()->getPost('index_products', null));

        return $resultLayout;
    }
}


Step5: HK/Productattach/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="HK_Productattach" setup_version="1.0.2">
        <sequence>
            <module name="Magento_Backend"/>
            <module name="Magento_Sales"/>
            <module name="Magento_Quote"/>
            <module name="Magento_Checkout"/>
            <module name="Magento_Catalog"/>
        </sequence>
    </module>
</config>

Step6: HK/Productattach/etc/adminhtml/routes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="productattach" frontName="productattach">
            <module name="HK_Productattach" />
        </route>
    </router>
</config>

Step7: HK/Productattach/etc/adminhtml/events.xml
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="adminhtml_customer_save_after">
        <observer name="customer_save_after" instance="HK\Productattach\Observer\Customersaveafter" />
    </event>
</config>

Step8: HK/Productattach/Model/Productattach.php
<?php
namespace HK\Productattach\Model;

class Productattach extends \Magento\Framework\Model\AbstractModel
{
    
    /**
     * Return unique ID(s) for each object in system
     *
     * @return array
     */
    public function getIdentities()
    {
        return [self::CACHE_TAG . '_' . $this->getId()];
    }
    
    /**
     * Initialize resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('HK\Productattach\Model\ResourceModel\Productattach');
    }
    
    public function getProducts(\HK\Productattach\Model\Productattach $object)
    {
        $id = $object->getId();
        $tbl = $this->getResource()->getTable("hk_productattach");
        $select = $this->getResource()->getConnection()->select()->from(
            $tbl,
            ['products']
        )
        ->where(
            'productattach_id = ?',
            (int)$id
        );

        $products = $this->getResource()->getConnection()->fetchCol($select);
        
        if ($products) {
            $products = explode('&', $products[0]);
        }

        return $products;
    }
}

Step9: HK/Productattach/Model/ProductattachFactory.php
<?php

namespace HK\Productattach\Model;

class ProductattachFactory
{
    /**
     * @var \Magento\Framework\ObjectManagerInterface
     */
    protected $_objectManager;

    /**
     * @param \Magento\Framework\ObjectManagerInterface $objectManager
     */
    public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager)
    {
        $this->_objectManager = $objectManager;
    }

    /**
     * Create new country model
     *
     * @param array $arguments
     * @return \Magento\Directory\Model\Country
     */
    public function create(array $arguments = [])
    {
        return $this->_objectManager->create('HK\Productattach\Model\Productattach', $arguments, false);
    }
}

Step10: HK/Productattach/Model/ResourceModel/Productattach.php
<?php
namespace HK\Productattach\Model\ResourceModel;

class Productattach extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
    /**
     * Initialize resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('hk_productattach', 'productattach_id');
    }
}

Step11: HK/Productattach/Model/ResourceModel/Productattach/Collection.php
<?php

namespace HK\Productattach\Model\ResourceModel\Productattach;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{

    /**
     * Define resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('HK\Productattach\Model\Productattach', 'HK\Productattach\Model\ResourceModel\Productattach');
        //$this->_map['fields']['page_id'] = 'main_table.page_id';
    }

}

Step12: HK/Productattach/Observer/Customersaveafter.php
<?php

namespace HK\Productattach\Observer;

use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;

class Customersaveafter implements ObserverInterface {

    protected $objectManager;

    public function __construct(
        \Magento\Framework\ObjectManagerInterface $objectManager
    ) {
        $this->objectManager = $objectManager;
    }

    public function execute(EventObserver $observer) {

        $customer = $observer->getEvent()->getData('customer');
        $products = $observer->getRequest()->getPost('products');
        
  $_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
  $hkproductModel = $this->objectManager->create('HK\Productattach\Model\Productattach');
  $hkproductCollection = $hkproductModel->getCollection()->addFieldToFilter('customer_id', $customer->getId());
  
  if($hkproductCollection->count() > 0){
   $hkproductCollection = $hkproductCollection->getFirstItem();
   $hkproductCollection->setProducts($products);
   $hkproductCollection->save();
  }else{
   if($products){
    $hkproductModel->setData(array('products'=>$products, 'customer_id' => $customer->getId()));
    $hkproductModel->save();
   }
  }
    }
}

Step13: HK/Productattach/Setup/InstallSchema.php
<?php

namespace HK\Productattach\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Ddl\Table;
use Magento\Framework\DB\Adapter\AdapterInterface;

class InstallSchema implements InstallSchemaInterface {

    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) {
        $installer = $setup;

        $installer->startSetup();
        
  $installer->getConnection()->dropTable($installer->getTable('hk_productattach'));

  $hk_productattach = $installer->getConnection()->newTable($installer->getTable('hk_productattach'));

  $hk_productattach->addColumn(
   'productattach_id',
   \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
   null,
   ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
   'Entity Id'
  );

  $hk_productattach->addColumn(
   'customer_id',
   \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
   null,
   ['nullable' => true,'default' => null],
   'Customer ID'
  );

  $hk_productattach->addColumn(
   'products',
   \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
   null,
   ['nullable' => true,'default' => null],
   'Assigned Products'
  );

  $hk_productattach->addColumn(
   'created_at',
   \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
   null,
   ['nullable' => false],
   'Created At'
  );

  $installer->getConnection()->createTable($hk_productattach);
  $installer->endSetup();
  
        $installer->endSetup();
    }
}

Step14: HK/Productattach/view/adminhtml/layout/customer_index_edit.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left"
      xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="customer_form">
            <block class="HK\Productattach\Block\Adminhtml\Edit\Tab\Products" name="customer_edit_tab_products">
                <action method="setTabLabel">
                    <argument name="label" xsi:type="string">Customer Products</argument>
                </action>
            </block>
        </referenceBlock>
    </body>
</page>

Step15: HK/Productattach/view/adminhtml/layout/productattach_index_products.xml
<?xml version="1.0" encoding="UTF-8"?>
<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd">
    <container name="root" label="Root">
        <block class="HK\Productattach\Block\Adminhtml\Edit\Tab\Products" name="productattach.edit.tab.products"/>
        <block class="Magento\Backend\Block\Widget\Grid\Serializer" name="products_grid_serializer">
            <arguments>
                <argument name="grid_block" xsi:type="string">productattach.edit.tab.products</argument>
                <argument name="callback" xsi:type="string">getSelectedProducts</argument>
                <argument name="input_element_name" xsi:type="string">products</argument>
                <argument name="reload_param_name" xsi:type="string">index_products</argument>
            </arguments>
        </block>
        <block class="Magento\Framework\View\Element\Template" name="grid_scriptjs" template="HK_Productattach::scriptjs.phtml"/>
    </container>
</layout>

Step16: HK/Productattach/view/adminhtml/layout/productattach_index_productsgrid.xml
<?xml version="1.0" encoding="UTF-8"?>
<layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd">
    <container name="root" label="Root">
        <block class="HK\Productattach\Block\Adminhtml\Edit\Tab\Products" name="productattach.edit.tab.products"/>
    </container>
</layout>

Step17: HK/Productattach/view/adminhtml/templates/scriptjs.phtml
<script>
    require([
        "jquery",

    ], function($){     
        $("input[name='products']").attr('data-form-part','customer_form');      
    });
</script>

Now run following commands and you are done.
php bin/magento setup:upgrade
php bin/magento setup:static-content:deploy

I hope this will help someone.
Thanks

Magento2 Upload files using mediastorage module and ajax

How to upload files using magento2 mediastorage module in amin – Want to upload files in magento2 then no need to worry about file upload functions, here you will find the method to upload files using magento2 mediastorage module and ajax.



For this you just need to follow these easy steps and your file will be uploaded to custom directory with proper validations.

Step1: Add following code in your phtml file

<div class="form_parent">
 <form class="form" method="post" id="frm_attachment" enctype="multipart/form-data" autocomplete="off">
  <div class="admin__field field field-email">
   <label class="label admin__field-label"><span>Attachment</span></label>
   <div class="admin__field-control control">
    <button type="button" class="scalable action-show-hide" id="uploadAttachment"><span><span><span>Upload</span></span></span></button>
    <input type="file" id="attachment" name="attachment" style="display: none;"/>
   </div>
  </div>
 </form>
</div>
<div id="attachmentFiles"></div>

<script>
    require(['jquery'], function ($) {
        $(document).ready(function ($) {
            
            $(document).on('click', '#attachmentFiles .action-remove', function(){
               if (window.confirm("Are you sure you want to delete?")) {
                   var attachmentPath = $(this).attr("data-image");
                   var divID = $(this).parents(".base-image").attr("id");
                   var imageID = $(this).parents(".base-image").find(".hiddneattachID").val();
                   
                   jQuery.ajax({
                        url: "<?php echo $block->getBaseUrl() . 'admin/hk/attachment/deleteAttachment?isAjax=true' ?>",
                        type: "POST",
                        data: {filename: attachmentPath, form_key: window.FORM_KEY, imageID:imageID},
                        showLoader: true,
                        success: function (response) {
                            if(response.success == true){
                                $(".base-image#"+divID).remove();
                            }
                            alert(response.message);
                        },
                       error: function (response) {
                            alert(response.message);
                       }
                    });
               } 
            });
            
            $('#uploadAttachment').click(function(){ $('#attachment').trigger('click'); });
            
            $("#attachment").change(function(){
                var data = $("#frm_attachment").get(0);
                
                jQuery.ajax({
                     url: "<?php echo $block->getBaseUrl() . 'admin/hk/attachment/addAttachment?isAjax=true' ?>",
                     type: "POST",
                     data: new FormData(data),
                     processData: false,
                     contentType: false,
                     showLoader: true,
                     success: function (response) {
                         alert(response.message);
                         $("#attachmentFiles").append(response.data.html);
                         $('#frm_attachment')[0].reset();
                     },
                    error: function (response) {
                         alert(response.message);
                         $('#frm_attachment')[0].reset();
                    }
                 });
            });
        });
    });
</script>

Step2: Create AddAttachment.php file to upload your file

<?php

namespace HK\Attachment\Controller\Adminhtml\Action;

use Magento\Framework\Json\Helper\Data as JsonHelper;

class AddAttachment extends \Magento\Backend\App\Action {
    
    protected $_mediaDirectory;
    protected $_fileUploaderFactory;
    public $_storeManager;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        JsonHelper $jsonHelper,
        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager
    ) {
        parent::__construct($context);
        $this->jsonHelper = $jsonHelper;
        $this->resultJsonFactory = $resultJsonFactory;
        $this->_mediaDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
        $this->_fileUploaderFactory = $fileUploaderFactory;
        $this->_storeManager = $storeManager;
    }

    
    public function execute(){
        
        $_postData = $this->getRequest()->getPost();
        
        $message = "";
        $newFileName = "";
        $error = false;
        $data = array();
        
        try{
            $target = $this->_mediaDirectory->getAbsolutePath('leads/');        
            
   //attachment is the input file name posted from your form
            $uploader = $this->_fileUploaderFactory->create(['fileId' => 'attachment']);
            
            //$_fileType = $uploader->getFileExtension();
            $newFileName = uniqid().'.'.$_fileType;
            
            /** Allowed extension types */
            $uploader->setAllowedExtensions(['jpg', 'jpeg', 'gif', 'png', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'csv']);
            /** rename file name if already exists */
            $uploader->setAllowRenameFiles(true);
            
            $result = $uploader->save($target, $newFileName); //Use this if you want to change your file name
   //$result = $uploader->save($target);
            if ($result['file']) {
                
                $_mediaUrl = $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
                $_iconArray = array(
                    'pdf' => $_mediaUrl.'leads/default/icon-pdf.png',
                    'doc' => $_mediaUrl.'leads/default/icon-doc.png',
                    'docx' => $_mediaUrl.'leads/default/icon-docx.png',
                    'xls' => $_mediaUrl.'leads/default/icon-xls.png',
                    'xlsx' => $_mediaUrl.'leads/default/icon-xlsx.png',
                    'csv' => $_mediaUrl.'leads/default/icon-csv.png',
                );
                
                if(isset($_iconArray[$_fileType])){
                    $_src = $_iconArray[$_fileType];
                }else{
                    $_src = $_mediaUrl.'leads/'.$newFileName;
                }
                
                $error = false;
                $message = "File has been successfully uploaded";
                
                $html = '<div class="image item base-image" data-role="image" id="'. uniqid().'">
                            <div class="product-image-wrapper">
                                <img class="product-image" data-role="image-element" src="'.$_src.'" alt="">
                                <div class="actions">
                                    <button type="button" class="action-remove" data-role="delete-button" data-image="'.$newFileName.'" title="Delete image"><span>Delete image</span></button>
                                </div>
                                <div class="image-fade"><span>Hidden</span></div>
                            </div>
                            <div class="item-description">
                                <div class="item-title" data-role="img-title"></div>
                                <div class="item-size">
                                    <a href="'.$_mediaUrl.'leads/'.$newFileName.'" target="_blank"><span data-role="image-dimens">'.$newFileName.'</span></a>
                                </div>
                            </div>
                        </div>';
                
                $data = array('filename' => $newFileName, 'path' => $_mediaUrl.'leads/'.$newFileName, 'fileType' => $_fileType, 'html' => $html);
            }
        } catch (\Exception $e) {
            $error = true;
            $message = $e->getMessage();
        }
        
        $resultJson = $this->resultJsonFactory->create();

        return $resultJson->setData([
                    'message' => $message,
                    'data' => $data,
                    'error' => $error
        ]);
    }
}


Step3: Create DeleteAttachment.php file to delete your file

<?php

namespace HK\Attachment\Controller\Adminhtml\Action;

use Magento\Framework\Json\Helper\Data as JsonHelper;

class DeleteAttachment extends \Magento\Backend\App\Action {
    
    protected $_mediaDirectory;
    protected $_fileUploaderFactory;
    public $_storeManager;
    protected $_file;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        JsonHelper $jsonHelper,
        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\MediaStorage\Model\File\UploaderFactory $fileUploaderFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Filesystem\Driver\File $file
    ) {
        parent::__construct($context);
        $this->jsonHelper = $jsonHelper;
        $this->resultJsonFactory = $resultJsonFactory;
        $this->_mediaDirectory = $filesystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
        $this->_fileUploaderFactory = $fileUploaderFactory;
        $this->_storeManager = $storeManager;
        $this->_file = $file;
    }

    
    public function execute(){
        
        $_postData = $this->getRequest()->getPost();
        
        $message = "";
        $newFileName = "";
        $success = false;
        
        $mediaRootDir = $this->_mediaDirectory->getAbsolutePath();
        $_fileName = $mediaRootDir .'leads/'. $_postData['filename'];
        if ($this->_file->isExists($_fileName))  {
            try{
                $this->attachment->load($_postData['imageID']);
                $this->attachment->delete();
                
                $this->_file->deleteFile($_fileName);
                $message = "File removed successfully.";
                $success = true;
            } catch (Exception $ex) {
                $message = $e->getMessage();
                $success = false;
            }
        }else{
            $message = "File not found.";
            $success = false;
        }
        
        $resultJson = $this->resultJsonFactory->create();

        return $resultJson->setData([
                    'message' => $message,
                    'data' => '',
                    'success' => $success
        ]);         
    }
}

Magento 2 Add Product Review And Rating Programatically

In this post i am going to explain that how to create product review and rating programatically from csv file in Magento 2.

Magento 2 Add Product Review And Rating Programatically


Create import_review.php file in root of your magento and add following code.

<?php

use Magento\Framework\App\Bootstrap;

require __DIR__ . '/app/bootstrap.php';
$bootstrap = Bootstrap::create(BP, $_SERVER);
$obj = $bootstrap->getObjectManager();
$state = $obj->get('Magento\Framework\App\State');
$state->setAreaCode('frontend');

ini_set('display_errors', 1);

$file = fopen('products_review.csv', 'r');


$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$reviewFactory = $objectManager->get("Magento\Review\Model\ReviewFactory");
$ratingFactory = $objectManager->get("Magento\Review\Model\RatingFactory");
$storeManager = $objectManager->get("Magento\Store\Model\StoreManagerInterface");

$i = 0;
while (($line = fgetcsv($file)) !== FALSE) {
    if (count($line) > 0) {

        $sku = $line[0];
        $review_rating = $line[1];
        $reviewTitle = $line[2];
        $reviewDetail = $line[3];
        $UserEmail = $line[4];
        $customerId = 0;

        if ($i > 0) {
            $productId = $objectManager->get('Magento\Catalog\Model\Product')->getIdBySku($sku);

            if ($productId) {
                $reviewFinalData = array();
                $reviewFinalData['ratings'][1] = $review_rating;
                $reviewFinalData['ratings'][2] = $review_rating;
                $reviewFinalData['ratings'][3] = $review_rating;

                $reviewFinalData['nickname'] = "Guest";

                if ($UserEmail) {
                    $websiteId = $storeManager->getWebsite()->getWebsiteId();
                    $customerFactory = $objectManager->get('\Magento\Customer\Model\CustomerFactory');
                    $customer = $customerFactory->create();
                    $customer->setWebsiteId($websiteId);
                    $customer->loadByEmail($UserEmail);
                    $data = $customer->getData();
                    $customerId = $data['entity_id'];
                    $firstname = $data['firstname'];
                    $lastname = ($data['lastname'] ? " " . $data['lastname'] : "");
                    $reviewFinalData['nickname'] = $firstname . $lastname;
                }

                $reviewFinalData['title'] = $reviewTitle;
                $reviewFinalData['detail'] = $reviewDetail;

                $review = $reviewFactory->create()->setData($reviewFinalData);

                $review->unsetData('review_id');

                $review->setEntityId($review->getEntityIdByCode(\Magento\Review\Model\Review::ENTITY_PRODUCT_CODE))
                        ->setEntityPkValue($productId)
                        ->setStatusId(\Magento\Review\Model\Review::STATUS_APPROVED)//By default set approved
                        ->setStoreId($storeManager->getStore()->getId())
                        ->setStores([$storeManager->getStore()->getId()]);

                if ($customerId) {
                    $review->setCustomerId($customerId);
                }

                $review->save();

                foreach ($reviewFinalData['ratings'] as $ratingId => $optionId) {
                    $ratingFactory->create()
                            ->setRatingId($ratingId)
                            ->setReviewId($review->getId())
                            ->addOptionVote($optionId, $productId);
                }

                $review->aggregate();
            }
        }
    }
    $i++;
}
?>


You can download sample csv file and script from following link

Download

Basic Simple CRUD Application with Express and MongoDB

In this post i have created a basic simple application using Express and MongoDB to Create, Read, Update and Delete data in MongoDB.

Crud-express-mongodb


To use this application you need to install Node.js and also have some basic knowledge of typing commands.

To check if you have Node installed, open up your command line and run the following code:
node -v

In this example we are going to store databases on cloud like mlab.com. So you need to create your database before starting this. 

Now let's create required files step by step:

Step1: Create server.js file and add following code

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const MongoClient = require('mongodb').MongoClient;

/////Body parser
app.use(bodyParser.urlencoded({extended: true}))
//app.use(bodyParser.json());
app.use(express.static('public'));
app.set('view engine', 'ejs')


/////MongoDB
var db;
var ObjectId = require('mongodb').ObjectID;

MongoClient.connect('your_mongodb_url', (err, database) => {
    if (err) {
        throw err;
    }

    db = database.db('db_name')
    db.collection('customer')
    app.listen(3000, () => {
        console.log('database connected listening on 3000');
    })
})

app.get('/', (req, res) => {
    db.collection('customer').find().toArray((err, result) => {
        if (err) {
            throw err;
        }
        res.render('index.ejs', {data: result})
    })
})

app.post('/addnew', (req, res) => {

    var myobj = {name: req.body.name, address: req.body.address};
    db.collection("customer").insertOne(myobj, function (err, result) {
        if (err) {
            throw err;
        }
        console.log("1 record inserted");
        res.redirect('/')
    });
})


////////////////////Update
app.get('/update/:id', (req, res) => {
    var user_id = req.params.id;
    console.log(user_id);
    var query = {_id: ObjectId(user_id)};
    db.collection("customer").find(query).toArray(function (err, result) {
        if (err) {
            throw err;
        }
        console.log(result);
        res.render('update.ejs', {data: result})
    });
})

app.post('/updatepost', (req, res) => {
    var myquery = {_id: ObjectId(req.body.id)};
    //var newvalues = {name: req.body.name, address: req.body.quote};
    var newvalues = {$set: {name: req.body.name, address: req.body.address}};
    var extra = {upsert: true};
    db.collection("customer").updateOne(myquery, newvalues, extra, function (err, result) {
        if (err) {
            throw err;
        }
        console.log("1 record updated");
        res.redirect('/')
    });
})


/////////////////Delete
app.get('/delete/:id', (req, res) => {
    var user_id = req.params.id;
    console.log(user_id);
    var query = {_id: ObjectId(user_id)};
    db.collection("customer").deleteOne(query, function (err, obj) {
        if (err) {
            throw err;
        }
        console.log("1 record deleted");
        res.redirect('/')
    });
})

Note: Replace 'your_mongodb_url' with your mongodb url and 'db_name' with the database name.

Step2: Create package.json file and add following code

{
  "name": "node",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js",
    "dev": "nodemon server.js"
  },
  "author": "Hardik Patel",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.18.2",
    "ejs": "^2.5.7",
    "express": "^4.16.2",
    "mongodb": "^3.0.1"
  },
  "devDependencies": {
    "nodemon": "^1.14.7"
  }
}

Step3: Create new folder 'views'

Step4: In views folder create new file index.ejs and add following code

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Basic CRUD Example</title>
</head>
<body>
  <ul class="quotes">
  <% for(var i=0; i<data.length; i++) {%>
    <li class="quote">
      <span><%= data[i].name %>: </span>
      <span><%= data[i].address %></span>
      <!--<span><%= data[i]._id %></span>-->
      <a href="update/<%= data[i]._id %>">Update</a>
      <a href="delete/<%= data[i]._id %>">Delete</a>
    </li>
  <% } %>
  </ul>

  <form action="/addnew" method="POST">
    <input type="text" placeholder="name" name="name">
    <input type="text" placeholder="address" name="address">
    <button type="submit">Submit</button>
  </form>
</body>
</html>

Step5: In views folder create new file update.ejs and add following code

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Basic CRUD Example</title>
</head>
<body>
  <form action="/updatepost" method="POST">
    <input style="width:300px;" type="text" placeholder="name" name="name" value="<%= data[0].name %>">
    <br><br>
    <input style="width:300px;" type="text" placeholder="address" name="address" value="<%= data[0].address %>">
    <br><br>
    <input style="width:300px;" type="text" placeholder="id" name="id" value="<%= data[0]._id %>">
    <br><br>
    <a href="/">Back</a>
    <button type="submit">Update</button>

  </form>
</body>
</html>

Note: Make sure you have added all required node module in your application. You can download required module from here.


Download

PayEase Payment Gateway For Magento 2

PayEase is the payment service provider in China. After converting our client site to Magento 2, i tried to find Payease payment extension. But unfortunately Payease was not there. So we are unable to process payment without Payease payment method. That is why i have developed my custom PayEase extension for Magento 2. I hope this will help someone else.

payease-payment-method-magento2


Download

 

Copyright @ 2017 HKBlog.