3

As per my requirement, I want to import CSV into my custom table, for that i have reviewed the following URL http://www.blogtreat.com/how-to-import-csv-file-to-custom-module-table-in-magento-2/

In this, while uploading the CSV file and hit the check data, the file is validating after that it's showing an import button, but when i hit the import button, nothing is happening.

enter image description here

class Imageimport extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
{
    const ID = 'id';
    const PRODUCT_SKU = 'product_sku';
    const PRODUCT_MAIN_IMAGE = 'product_main_image';
    const TIME = 'time';
    const TABLE_ENTITY = 'product_image_import';
    /**
     * Validation failure message template definitions
     *
     * @var array
     */
    protected $_messageTemplates = [
        ValidatorInterface::ERROR_ID_IS_EMPTY => 'Empty',
    ];

    protected $_permanentAttributes = [self::ID];

    /**
     * If we should check column names
     *
     * @var bool
     */
    protected $needColumnCheck = true;

    /**
     * Valid column names
     *
     * @array
     */
    protected $validColumnNames = [
        self::ID,
        self::PRODUCT_SKU,
        self::PRODUCT_MAIN_IMAGE,
    ];

    /**
     * Need to log in import history
     *
     * @var bool
     */
    protected $logInHistory = true;

    protected $_validators = [];

    /**
     * @var \Magento\Framework\Stdlib\DateTime\DateTime
     */
    protected $_connection;

    protected $_resource;

    /**
     * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
     */
    public function __construct(
        \Magento\Framework\Json\Helper\Data $jsonHelper,
        \Magento\ImportExport\Helper\Data $importExportData,
        \Magento\ImportExport\Model\ResourceModel\Import\Data $importData,
        \Magento\Framework\App\ResourceConnection $resource,
        \Magento\ImportExport\Model\ResourceModel\Helper $resourceHelper,
        \Magento\Framework\Stdlib\StringUtils $string,
        ProcessingErrorAggregatorInterface $errorAggregator
    ) {
        $this->jsonHelper = $jsonHelper;
        $this->_importExportData = $importExportData;
        $this->_resourceHelper = $resourceHelper;
        $this->_dataSourceModel = $importData;
        $this->_resource = $resource;
        $this->_connection = $resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION);
        $this->errorAggregator = $errorAggregator;
    }

    public function getValidColumnNames() {
        return $this->validColumnNames;
    }

    /**
     * Entity type code getter.
     *
     * @return string
     */
    public function getEntityTypeCode() {
        return 'product_image_import';
    }

    /**
     * Row validation.
     *
     * @param array $rowData
     * @param int $rowNum
     * @return bool
     */
    public function validateRow(array $rowData, $rowNum) {
        $title = false;
        if (isset($this->_validatedRows[$rowNum])) {
            return !$this->getErrorAggregator()->isRowInvalid($rowNum);
        }

        $this->_validatedRows[$rowNum] = true;

        if (!isset($rowData[self::ID]) || empty($rowData[self::ID])) {
            $this->addRowError(ValidatorInterface::ERROR_MESSAGE_IS_EMPTY, $rowNum);
            return false;
        }
        return !$this->getErrorAggregator()->isRowInvalid($rowNum);
    }

    /**
     * Create advanced question data from raw data.
     *
     * @throws \Exception
     * @return bool Result of operation.
     */
    protected function _importData() {
        if (\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE == $this->getBehavior()) {
            $this->deleteEntity();
        } elseif (\Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE == $this->getBehavior()) {
            $this->replaceEntity();
        } elseif (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND == $this->getBehavior()) {
            $this->saveEntity();
        }
        return true;
    }

    /**
     * Save question
     *
     * @return $this
     */
    public function saveEntity() {
        $this->saveAndReplaceEntity();
        return $this;
    }

    /**
     * Replace question
     *
     * @return $this
     */
    public function replaceEntity() {
        $this->saveAndReplaceEntity();
        return $this;
    }

    /**
     * Deletes question data from raw data.
     *
     * @return $this
     */
    public function deleteEntity() {
        $ids = [];
        while ($bunch = $this->_dataSourceModel->getNextBunch()) {
            foreach ($bunch as $rowNum => $rowData) {
                $this->validateRow($rowData, $rowNum);
                if (!$this->getErrorAggregator()->isRowInvalid($rowNum)) {
                    $rowId = $rowData[self::ID];
                    $ids[] = $rowId;
                }
                if ($this->getErrorAggregator()->hasToBeTerminated()) {
                    $this->getErrorAggregator()->addRowToSkip($rowNum);
                }
            }
        }
        if ($ids) {
            $this->deleteEntityFinish(array_unique($ids),self::TABLE_ENTITY);
        }
        return $this;
    }

    /**
     * Save and replace question
     *
     * @return $this
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     * @SuppressWarnings(PHPMD.NPathComplexity)
     */
    protected function saveAndReplaceEntity() {
        $behavior = $this->getBehavior();
        $ids = [];
        while ($bunch = $this->_dataSourceModel->getNextBunch()) {
            $entityList = [];
            $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/templog.log');
            $logger = new \Zend\Log\Logger();
            $logger->addWriter($writer);

            $logger->info(print_r($bunch,1));
            foreach ($bunch as $rowNum => $rowData) {
                if (!$this->validateRow($rowData, $rowNum)) {
                    $this->addRowError(ValidatorInterface::ERROR_MESSAGE_IS_EMPTY, $rowNum);
                    continue;
                }
                if ($this->getErrorAggregator()->hasToBeTerminated()) {
                    $this->getErrorAggregator()->addRowToSkip($rowNum);
                    continue;
                }
                $rowId= $rowData[self::ID];
                $ids[] = $rowId;
                $entityList[$rowId][] = [
                  self::ID => $rowData[self::ID],
                  self::PRODUCT_SKU => $rowData[self::PRODUCT_SKU],
                  self::PRODUCT_MAIN_IMAGE => $rowData[self::PRODUCT_MAIN_IMAGE],
                ];
            }
            $logger->info(print_r($entityList,1));
            if (\Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE == $behavior) {
                if ($ids) {
                    if ($this->deleteEntityFinish(array_unique(  $ids), self::TABLE_ENTITY)) {
                        $this->saveEntityFinish($entityList, self::TABLE_ENTITY);
                    }
                }
            } elseif (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND == $behavior) {
                $this->saveEntityFinish($entityList, self::TABLE_ENTITY);
            }

        }
        return $this;
    }

    /**
     * Save question
     *
     * @param array $priceData
     * @param string $table
     * @return $this
     */
    protected function saveEntityFinish(array $entityData, $table) {
        if ($entityData) {
            $tableName = $this->_connection->getTableName($table);
            $entityIn = [];
            foreach ($entityData as $id => $entityRows) {
                    foreach ($entityRows as $row) {
                        $entityIn[] = $row;
                    }
            }
            if ($entityIn) {
                $this->_connection->insertOnDuplicate($tableName, $entityIn,[
                self::ID,
                self::PRODUCT_SKU,
                self::PRODUCT_MAIN_IMAGE
            ]);
            }
        }
        return $this;
    }

    protected function deleteEntityFinish(array $ids, $table) {

        if ($table && $ids) {
            try {
                $this->countItemsDeleted += $this->_connection->delete(
                    $this->_connection->getTableName($table),
                    $this->_connection->quoteInto('id IN (?)', $ids)
                );
                return true;
            } catch (\Exception $e) {
                return false;
            }
        } else {
            return false;
        }
    }

Kindly check and let me know your thoughts and ideab, it will help me to resolve the issue

7
  • will it be able to reach your import controller. Check that first, to do so, go to your import controller file and print something and exit or die it.
    – Akash
    Commented Oct 17, 2018 at 11:32
  • @John, There is no request sending to a controller and anywhere, i followed the above mentioned link, kindly check and share your idea
    – senthil
    Commented Oct 17, 2018 at 11:34
  • in your customimport.php file, have you change these data ? const ID = 'entity_id'; const QUESTION = 'question'; const DATE = 'create_at'; const TABLE_ENTITY = 'faq';
    – Akash
    Commented Oct 17, 2018 at 11:40
  • Yes, I have changed as follows const ID = 'id'; const PRODUCT_SKU = 'product_sku'; const PRODUCT_MAIN_IMAGE = 'product_main_image'; const TABLE_Entity = 'product_image_import'; and changed everywhere in that file
    – senthil
    Commented Oct 17, 2018 at 11:43
  • on the same file, check if the data passed correctly to this function saveAndReplaceEntity()
    – Akash
    Commented Oct 17, 2018 at 11:49

3 Answers 3

2

First create a Import Button in your Ui-component File

[vendor_name] \ [module_name] \view\adminhtml\ui_component

uiComponenetFileName.xml

<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Ui/etc/ui_configuration.xsd">

            <!-- main part of the grid -->
                <argument name="data" xsi:type="array">
                   <!-- define  date source -->
                <item name="js_config" xsi:type="array">
                    <item name="provider" xsi:type="string">locator_record_locator_list.locator_record_locator_list_data_source</item>
                    <item name="deps" xsi:type="string">locator_record_locator_list.locator_record_locator_list_data_source</item>
                </item>
                <!-- for columns -->
                <item name="spinner" xsi:type="string">locator_records_columns</item>
                <!--  for Add new record button  -->
                <item name="buttons" xsi:type="array">
                    <item name="add" xsi:type="array">
                        <item name="name" xsi:type="string">add</item>
                        <item name="label" xsi:type="string" translate="true">Add New Location</item>
                        <item name="class" xsi:type="string">primary</item>
                        <item name="url" xsi:type="string">*/*/addlocation</item>
                        <item name="sortOrder" xsi:type="number">10</item>
                    </item>
                    <item name="import" xsi:type="array">
                        <item name="name" xsi:type="string">import</item>
                        <item name="label" xsi:type="string" translate="true">Import Locatore</item>
                        <item name="class" xsi:type="string">secondary</item>
                        <item name="url" xsi:type="string">*/dataimport/importdata</item>
                        <item name="sortOrder" xsi:type="number">20</item>
                    </item>
                    <item name="export" xsi:type="array">
                        <item name="name" xsi:type="string">export</item>
                        <item name="label" xsi:type="string" translate="true">Export locatore</item>
                        <item name="class" xsi:type="string">secondary</item>
                        <item name="url" xsi:type="string">*/*/exportdata</item>
                        <item name="sortOrder" xsi:type="number">30</item>
                    </item>
                </item>
            </argument>
.........................
.........................
.........................

Now this Import Button Call Import Data Form

[vendor_name] \ [module_name] \Controller\Adminhtml\Dataimport

Importdata.php

<?php

namespace [vendor_name]\ [module_name] \Controller\Adminhtml\Dataimport;

use Magento\Framework\Controller\ResultFactory;

class Importdata extends \Magento\Backend\App\Action
{
    private $coreRegistry;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Registry $coreRegistry
    ) {                                 

       parent::__construct($context);
       $this->coreRegistry = $coreRegistry;
    }

    public function execute()
    {
        $rowData = $this->_objectManager->create('[vendor_name] \ [module_name] \Model\Locator');
        $this->coreRegistry->register('row_data', $rowData);
        $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
        $resultPage->getConfig()->getTitle()->prepend(__('Import Locator Data'));
        return $resultPage;
    }

    // used for acl.xml
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('[vendor_name]_[module_name]::add_datalocation');
    }
}

create a Layout File which Call your Block File

[vendor_name] \ [module_name] \view\adminhtml\layout

[controller_name]_dataimport_importdata.xml

<?xml version="1.0"?>

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="content">
           <block class="[vendor_name] \ [module_name] \Block\Adminhtml\Dataimport\Importdata" name="importdata_locator" />
        </referenceContainer>
    </body>
</page>

create a block File for Import Data Form

[vendor_name] \ [module_name] \Block\Adminhtml\Dataimport

Importdata.php

<?php 

namespace [vendor_name] \ [module_name] \Block\Adminhtml\Dataimport;

class Importdata extends \Magento\Backend\Block\Widget\Form\Container
{
    protected $_coreRegistry = null;

    public function __construct(
        \Magento\Backend\Block\Widget\Context $context,
        \Magento\Framework\Registry $registry,
        array $data = []
    ) {
        $this->_coreRegistry = $registry;
        parent::__construct($context, $data);
    }

    protected function _construct()
    {
        $this->_objectId = 'row_id';
        $this->_blockGroup = '[module_name]_[vendor_name]';
        $this->_controller = 'adminhtml_dataimport';
        parent::_construct();
        $this->buttonList->remove('back');
        $this->buttonList->update('save', 'label', __('Import'));
        $this->buttonList->remove('reset');

        $this->addButton(
                    'backhome',
                    [
                        'label' => __('Back'),
                        'on_click' => sprintf("location.href = '%s';", $this->getUrl('[route_name] / [controller_name] /index')),
                        'class' => 'back',
                        'level' => -2
                    ]
                );


    }


    public function getHeaderText()
    {
        return __('Import Location Data');
    }

    protected function _isAllowedAction($resourceId)
    {
        return $this->_authorization->isAllowed($resourceId);
    }


    public function getFormActionUrl()
    {
        if ($this->hasFormActionUrl()) {
            return $this->getData('form_action_url');
        }
        return $this->getUrl('[route_name] / dataimport/save');
    }
}

the above file call import form

[vendor_name] \ [module_name] \Block\Adminhtml\Dataimport\Edit

Form.php

<?php

namespace [vendor_name] \ [module_name] \Block\Adminhtml\Dataimport\Edit;

use Magento\Framework\View\Asset\Repository; 

class Form extends \Magento\Backend\Block\Widget\Form\Generic
{
    protected $_assetRepo;

    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Data\FormFactory $formFactory,
        \Magento\Framework\View\Asset\Repository $assetRepo,
        array $data = []
    ) {   
        parent::__construct($context, $registry, $formFactory, $data);
    }


    protected function _prepareForm()
    {   
        $path = $this->_assetRepo->getUrl("[vendor_name]_[module_name]::img/[vendor_name]_[module_name]_Sample_File.csv");

        $model = $this->_coreRegistry->registry('row_data');

        $form = $this->_formFactory->create(
            ['data' => [
                            'id' => 'edit_form',
                            'enctype' => 'multipart/form-data',
                            'action' => $this->getData('action'),
                            'method' => 'post'
                        ]
            ]
        );

        $form->setHtmlIdPrefix('datalocation_');

           $fieldset = $form->addFieldset(
                'base_fieldset',
                ['legend' => __('Import Location '), 'class' => 'fieldset-wide']
            );

       $importdata_script =  $fieldset->addField(
            'importdata',
            'file', 
                array(
                        'label'     => 'Upload File',
                        'required'  => true,
                        'name'      => 'importdata',  
                        'note' => 'Allow File type: .csv and .xls', 
                     )
        );

        $importdata_script->setAfterElementHtml("   

        <span id='sample-file-span' ><a id='sample-file-link' href='".$path."'  >Download Sample File</a></span>

            <script type=\"text/javascript\">

            document.getElementById('[route_name]_importdata').onchange = function () { 

                var fileInput = document.getElementById('[route_name]_importdata');

                var filePath = fileInput.value;

                var allowedExtensions = /(\.csv|\.xls)$/i; 

                if(!allowedExtensions.exec(filePath))
                {
                    alert('Please upload file having extensions .csv or .xls only.');
                    fileInput.value = '';
                }

            };

            </script>"
        );


        $form->setValues($model->getData());
        $form->setUseContainer(true);
        $this->setForm($form);

        return parent::_prepareForm();
    }

}

this import form check whether file is valid or not, now create file which read your uploaded file and insert into table .

[vendor_name] \ [module_name] \Controller\Adminhtml\Dataimport*

Save.php

<?php

namespace [vendor_name]\[module_name]\Controller\Adminhtml\Dataimport;

use Magento\Backend\App\Action;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Filesystem;
use Magento\MediaStorage\Model\File\UploaderFactory;
use Magento\Framework\Image\AdapterFactory;
use Magento\Store\Model\ScopeInterface; 


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

    protected $fileSystem;

    protected $uploaderFactory;

    protected $request;

    protected $adapterFactory;


    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Filesystem $fileSystem,
        \Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory,
        \Magento\Framework\App\RequestInterface $request,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        AdapterFactory $adapterFactory

    ) {
        parent::__construct($context);
        $this->fileSystem = $fileSystem;
        $this->request = $request;
        $this->scopeConfig = $scopeConfig;
        $this->adapterFactory = $adapterFactory;
        $this->uploaderFactory = $uploaderFactory;
    }

    public function execute()
    { 

         if ( (isset($_FILES['importdata']['name'])) && ($_FILES['importdata']['name'] != '') ) 
         {
            try 
           {    
                $uploaderFactory = $this->uploaderFactory->create(['fileId' => 'importdata']);
                $uploaderFactory->setAllowedExtensions(['csv', 'xls']);
                $uploaderFactory->setAllowRenameFiles(true);
                $uploaderFactory->setFilesDispersion(true);

                $mediaDirectory = $this->fileSystem->getDirectoryRead(DirectoryList::MEDIA);
                $destinationPath = $mediaDirectory->getAbsolutePath('[vendor_name]_[module_name]_IMPORTDATA');

                $result = $uploaderFactory->save($destinationPath);

                if (!$result) 
                   {
                     throw new LocalizedException
                     (
                        __('File cannot be saved to path: $1', $destinationPath)
                     );

                   }
                else
                    {   
                        $imagePath = '[vendor_name]_[module_name]_IMPORTDATA'.$result['file'];

                        $mediaDirectory = $this->fileSystem->getDirectoryRead(DirectoryList::MEDIA);

                        $destinationfilePath = $mediaDirectory->getAbsolutePath($imagePath);

                        /* file read operation */

                        $f_object = fopen($destinationfilePath, "r");

                        $column = fgetcsv($f_object);

                        // column name must be same as the Sample file name 

                        if($f_object)
                        {
                            if( ($column[0] == 'Col_name_1') && ($column[1] == 'Col_name_2') && ($column[2] == 'Col_name_3') && ($column[3] == 'Col_name_4') && ($column[4] == 'Col_name_5') )
                            {   

                                $count = 0;

                                while (($columns = fgetcsv($f_object)) !== FALSE) 
                                {

                                    $rowData = $this->_objectManager->create('Dolphin\Storelocator\Model\Storelocator');

                                    if($columns[0] != 'Col_name_1')// unique Name like Primary key
                                    {   
                                        $count++;

                                    /// here this are all the Getter Setter Method which are call to set value 
                                    // the auto increment column name not used to set value 

                                        $rowData->setCol_name_1($columns[1]);

                                        $rowData->setCol_name_2($columns[2]);

                                        $rowData->setCol_name_3($columns[3]);

                                        $rowData->setCol_name_4($columns[4]);

                                        $rowData->setCol_name_5($columns[5]);

                                        $rowData->save();   

                                    }

                                } 

                            $this->messageManager->addSuccess(__('A total of %1 record(s) have been Added.', $count));
                            $this->_redirect('[route_name]/[controller_name]/index');
                            }
                            else
                            {
                                $this->messageManager->addError(__("invalid Formated File"));
                                $this->_redirect('[route_name]/dataimport/importdata');
                            }

                        } 
                        else
                        {
                            $this->messageManager->addError(__("File hase been empty"));
                            $this->_redirect('[route_name]/dataimport/importdata');
                        }

                    }                   

           } 
           catch (\Exception $e) 
          {   
               $this->messageManager->addError(__($e->getMessage()));
               $this->_redirect('[controller_name]/dataimport/importdata');
          }

         }
         else
         {
            $this->messageManager->addError(__("Please try again."));
            $this->_redirect('[controller_name]/dataimport/importdata');
         }
    }
}

Now you can Click on the Import Button and upload .csv file and import data.

I Hope This Helps You.

11
  • if anyone have any doubt please ask here I will give you right Solution
    – Msquare
    Commented Oct 13, 2019 at 5:58
  • where do you put the XML in your first step?
    – AdRock
    Commented Nov 15, 2019 at 13:50
  • @AdRock I put remaining XML. If you have a any other doubt you can ask me.
    – Msquare
    Commented Nov 15, 2019 at 17:54
  • will you please help me please where to look that import button in admin @Msquare
    – Prits
    Commented Aug 19, 2020 at 13:42
  • yes that is process of putting import button in admin in this post. please follow
    – Msquare
    Commented Aug 19, 2020 at 13:46
1

app/code/VendoreName/CustomDataImport/etc

db_schema.xml

<?xml version="1.0"?>

<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
    <table name="custom_import">
        <column xsi:type="int" name="entity_id" padding="10" unsigned="true" nullable="false" comment="Entity Id" identity="true" />
        <column xsi:type="varchar" name="name" nullable="false" length="255" comment="Product Name"/>
        <column xsi:type="int" name="duration" padding="10" unsigned="true" nullable="false" comment="Duration"/>
        <constraint xsi:type="primary" referenceId="CUSTOM_IMPORT_ID_PRIMARY">
            <column name="entity_id"/>
        </constraint>
    </table>
</schema>

enter image description here

app/code/VendoreName/CustomDataImport/etc

import.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_ImportExport:etc/import.xsd">
    <entity name="custom_import" label="Custom Import" model="VendoreName\CustomDataImport\Model\Import\CustomImport" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Basic" />
</config>

app/code/VendoreName/CustomDataImport/Files/Sample

custom_import.csv

entity_id,name,duration
,"Name 1",90
2,"Name 3",120

app/code/VendoreName/CustomDataImport/etc

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\ImportExport\Model\Import\SampleFileProvider">
        <arguments>
            <argument name="samples" xsi:type="array">
                <item name="custom_import" xsi:type="string">VendoreName_CustomDataImport</item>
            </argument>
        </arguments>
    </type>

</config>

app/code/VendoreName/CustomDataImport/Model/Import

CustomImport.php

<?php

namespace VendoreName\CustomDataImport\Model\Import;

use Exception;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\Json\Helper\Data as JsonHelper;
use Magento\ImportExport\Helper\Data as ImportHelper;
use Magento\ImportExport\Model\Import;
use Magento\ImportExport\Model\Import\Entity\AbstractEntity;
use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface;
use Magento\ImportExport\Model\ResourceModel\Helper;
use Magento\ImportExport\Model\ResourceModel\Import\Data;

/**
 * Class Courses
 */
class CustomImport extends AbstractEntity
{
    const ENTITY_CODE = 'custom_import';
    const TABLE = 'custom_import';
    const ENTITY_ID_COLUMN = 'entity_id';

    /**
     * If we should check column names
     */
    protected $needColumnCheck = true;

    /**
     * Need to log in import history
     */
    protected $logInHistory = true;

    /**
     * Permanent entity columns.
     */
    protected $_permanentAttributes = [
        'entity_id',
    ];

    /**
     * Valid column names
     */
    protected $validColumnNames = [
        'entity_id',
        'name',
        'duration',
    ];

    /**
     * @var AdapterInterface
     */
    protected $connection;

    /**
     * @var ResourceConnection
     */
    private $resource;

    /**
     * Courses constructor.
     *
     * @param JsonHelper $jsonHelper
     * @param ImportHelper $importExportData
     * @param Data $importData
     * @param ResourceConnection $resource
     * @param Helper $resourceHelper
     * @param ProcessingErrorAggregatorInterface $errorAggregator
     */
    public function __construct(
        JsonHelper $jsonHelper,
        ImportHelper $importExportData,
        Data $importData,
        ResourceConnection $resource,
        Helper $resourceHelper,
        ProcessingErrorAggregatorInterface $errorAggregator
    ) {
        $this->jsonHelper = $jsonHelper;
        $this->_importExportData = $importExportData;
        $this->_resourceHelper = $resourceHelper;
        $this->_dataSourceModel = $importData;
        $this->resource = $resource;
        $this->connection = $resource->getConnection(ResourceConnection::DEFAULT_CONNECTION);
        $this->errorAggregator = $errorAggregator;
        $this->initMessageTemplates();
    }

    /**
     * Entity type code getter.
     *
     * @return string
     */
    public function getEntityTypeCode()
    {
        return static::ENTITY_CODE;
    }

    /**
     * Get available columns
     *
     * @return array
     */
    public function getValidColumnNames(): array
    {
        return $this->validColumnNames;
    }

    /**
     * Row validation
     *
     * @param array $rowData
     * @param int $rowNum
     *
     * @return bool
     */
    public function validateRow(array $rowData, $rowNum): bool
    {
        $name = $rowData['name'] ?? '';
        $duration = (int) $rowData['duration'] ?? 0;

        if (!$name) {
            $this->addRowError('NameIsRequired', $rowNum);
        }

        if (!$duration) {
            $this->addRowError('DurationIsRequired', $rowNum);
        }

        if (isset($this->_validatedRows[$rowNum])) {
            return !$this->getErrorAggregator()->isRowInvalid($rowNum);
        }

        $this->_validatedRows[$rowNum] = true;

        return !$this->getErrorAggregator()->isRowInvalid($rowNum);
    }

    /**
     * Init Error Messages
     */
    private function initMessageTemplates()
    {
        $this->addMessageTemplate(
            'NameIsRequired',
            __('The name cannot be empty.')
        );
        $this->addMessageTemplate(
            'DurationIsRequired',
            __('Duration should be greater than 0.')
        );
    }

    /**
     * Import data
     *
     * @return bool
     *
     * @throws Exception
     */
    protected function _importData(): bool
    {
        switch ($this->getBehavior()) {
            case Import::BEHAVIOR_DELETE:
                $this->deleteEntity();
                break;
            case Import::BEHAVIOR_REPLACE:
                $this->saveAndReplaceEntity();
                break;
            case Import::BEHAVIOR_APPEND:
                $this->saveAndReplaceEntity();
                break;
        }

        return true;
    }

    /**
     * Delete entities
     *
     * @return bool
     */
    private function deleteEntity(): bool
    {
        $rows = [];
        while ($bunch = $this->_dataSourceModel->getNextBunch()) {
            foreach ($bunch as $rowNum => $rowData) {
                $this->validateRow($rowData, $rowNum);

                if (!$this->getErrorAggregator()->isRowInvalid($rowNum)) {
                    $rowId = $rowData[static::ENTITY_ID_COLUMN];
                    $rows[] = $rowId;
                }

                if ($this->getErrorAggregator()->hasToBeTerminated()) {
                    $this->getErrorAggregator()->addRowToSkip($rowNum);
                }
            }
        }

        if ($rows) {
            return $this->deleteEntityFinish(array_unique($rows));
        }

        return false;
    }

    /**
     * Save and replace entities
     *
     * @return void
     */
    private function saveAndReplaceEntity()
    {
        $behavior = $this->getBehavior();
        $rows = [];
        while ($bunch = $this->_dataSourceModel->getNextBunch()) {
            $entityList = [];

            foreach ($bunch as $rowNum => $row) {
                if (!$this->validateRow($row, $rowNum)) {
                    continue;
                }

                if ($this->getErrorAggregator()->hasToBeTerminated()) {
                    $this->getErrorAggregator()->addRowToSkip($rowNum);

                    continue;
                }

                $rowId = $row[static::ENTITY_ID_COLUMN];
                $rows[] = $rowId;
                $columnValues = [];

                foreach ($this->getAvailableColumns() as $columnKey) {
                    $columnValues[$columnKey] = $row[$columnKey];
                }

                $entityList[$rowId][] = $columnValues;
                $this->countItemsCreated += (int) !isset($row[static::ENTITY_ID_COLUMN]);
                $this->countItemsUpdated += (int) isset($row[static::ENTITY_ID_COLUMN]);
            }
            if (Import::BEHAVIOR_REPLACE === $behavior) {
                if ($rows && $this->deleteEntityFinish(array_unique($rows))) {
                    $this->saveEntityFinish($entityList);
                }
            } elseif (Import::BEHAVIOR_APPEND === $behavior) {
                $this->saveEntityFinish($entityList);
            }
        }
    }

    /**
     * Save entities
     *
     * @param array $entityData
     *
     * @return bool
     */
    private function saveEntityFinish(array $entityData): bool
    {
        if ($entityData) {
            $tableName = $this->connection->getTableName(static::TABLE);
            $rows = [];

            foreach ($entityData as $entityRows) {
                foreach ($entityRows as $row) {
                    $rows[] = $row;
                }
            }

            if ($rows) {
                $this->connection->insertOnDuplicate($tableName, $rows, $this->getAvailableColumns());

                return true;
            }

            return false;
        }
    }

    /**
     * Delete entities
     *
     * @param array $entityIds
     *
     * @return bool
     */
    private function deleteEntityFinish(array $entityIds): bool
    {
        if ($entityIds) {
            try {
                $this->countItemsDeleted += $this->connection->delete(
                    $this->connection->getTableName(static::TABLE),
                    $this->connection->quoteInto(static::ENTITY_ID_COLUMN . ' IN (?)', $entityIds)
                );

                return true;
            } catch (Exception $e) {
                return false;
            }
        }

        return false;
    }

    /**
     * Get available columns
     *
     * @return array
     */
    private function getAvailableColumns(): array
    {
        return $this->validColumnNames;
    }
}
0

how about import data using url of the csv?

0

Your Answer

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

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