My requirement is import custom csv file to custom table.
please share hints and key points to achieve this?
Thanks.
note: I get crystal clear explanation of custom import option from this link
Please first download the whole zip file from this github link then change the module name as per your requirement. Just alter the two files is enough to import your custom CSV to custom table.
step1: alter app/code/vendor/module_name/etc/import.xml from your download github folder.
<?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="chennai_event" label="Chennai Event" model="Gworks\Chennaievent\Model\Import\CustomerGroup" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Basic" />
</config>
step2: then you should need to create model class as per mention in the above import.xml
app/code/vendor/module_name/Model/Import/CustomerGroup.php
<?php
namespace Gworks\Chennaievent\Model\Import;
use Gworks\Chennaievent\Model\Import\CustomerGroup\RowValidatorInterface as ValidatorInterface;
use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface;
use Magento\Framework\App\ResourceConnection;
class CustomerGroup extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
{
const ID = 'id';
const EVENTNAME = 'event_name';
const IMGURL = 'event_imgurl';
const BANNERIMGURL = 'event_bannerimgurl';
const DESC = 'event_description';
const LDESC = 'event_longdescription';
const PLACE = 'event_place';
const DATE = 'event_date';
const GIFT = 'event_suggestgift';
const TYPE = 'type';
const TABLE_Entity = 'chennai_event';
/**
* Validation failure message template definitions
*
* @var array
*/
protected $_messageTemplates = [
ValidatorInterface::ERROR_TITLE_IS_EMPTY => 'TITLE is empty',
];
protected $_permanentAttributes = [self::ID];
/**
* If we should check column names
*
* @var bool
*/
protected $needColumnCheck = true;
protected $groupFactory;
/**
* Valid column names
*
* @array
*/
protected $validColumnNames = [
self::ID,
self::EVENTNAME,
self::IMGURL,
self::BANNERIMGURL,
self::DESC,
self::LDESC,
self::PLACE,
self::DATE,
self::GIFT,
self::TYPE,
];
/**
* 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,
\Magento\Customer\Model\GroupFactory $groupFactory
) {
$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;
$this->groupFactory = $groupFactory;
}
public function getValidColumnNames()
{
return $this->validColumnNames;
}
/**
* Entity type code getter.
*
* @return string
*/
public function getEntityTypeCode()
{
return 'chennai_event';
}
/**
* 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;
// BEHAVIOR_DELETE use specific validation logic
// if (\Magento\ImportExport\Model\Import::BEHAVIOR_DELETE == $this->getBehavior()) {
if (!isset($rowData[self::ID]) || empty($rowData[self::ID])) {
$this->addRowError(ValidatorInterface::ERROR_TITLE_IS_EMPTY, $rowNum);
return false;
}
return !$this->getErrorAggregator()->isRowInvalid($rowNum);
}
/**
* Create Advanced price 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 newsletter subscriber
*
* @return $this
*/
public function saveEntity()
{
$this->saveAndReplaceEntity();
return $this;
}
/**
* Replace newsletter subscriber
*
* @return $this
*/
public function replaceEntity()
{
$this->saveAndReplaceEntity();
return $this;
}
/**
* Deletes newsletter subscriber data from raw data.
*
* @return $this
*/
public function deleteEntity()
{
$listTitle = [];
while ($bunch = $this->_dataSourceModel->getNextBunch()) {
foreach ($bunch as $rowNum => $rowData) {
$this->validateRow($rowData, $rowNum);
if (!$this->getErrorAggregator()->isRowInvalid($rowNum)) {
$rowTtile = $rowData[self::ID];
$listTitle[] = $rowTtile;
}
if ($this->getErrorAggregator()->hasToBeTerminated()) {
$this->getErrorAggregator()->addRowToSkip($rowNum);
}
}
}
if ($listTitle) {
$this->deleteEntityFinish(array_unique($listTitle),self::TABLE_Entity);
}
return $this;
}
/**
* Save and replace newsletter subscriber
*
* @return $this
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
protected function saveAndReplaceEntity()
{
$behavior = $this->getBehavior();
$listTitle = [];
while ($bunch = $this->_dataSourceModel->getNextBunch()) {
$entityList = [];
foreach ($bunch as $rowNum => $rowData) {
if (!$this->validateRow($rowData, $rowNum)) {
$this->addRowError(ValidatorInterface::ERROR_TITLE_IS_EMPTY, $rowNum);
continue;
}
if ($this->getErrorAggregator()->hasToBeTerminated()) {
$this->getErrorAggregator()->addRowToSkip($rowNum);
continue;
}
$rowTtile= $rowData[self::ID];
$listTitle[] = $rowTtile;
$entityList[$rowTtile][] = [
self::ID => $rowData[self::ID],
self::EVENTNAME => $rowData[self::EVENTNAME],
self::IMGURL => $rowData[self::IMGURL],
self::BANNERIMGURL => $rowData[self::BANNERIMGURL],
self::DESC => $rowData[self::DESC],
self::LDESC => $rowData[self::LDESC],
self::PLACE => $rowData[self::PLACE],
self::DATE => $rowData[self::DATE],
self::GIFT => $rowData[self::GIFT],
self::TYPE => $rowData[self::TYPE],
];
}
if (\Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE == $behavior) {
if ($listTitle) {
if ($this->deleteEntityFinish(array_unique( $listTitle), 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 product prices.
*
* @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::EVENTNAME,
self::IMGURL,
self::BANNERIMGURL,
self::DESC,
self::LDESC,
self::PLACE,
self::DATE,
self::GIFT,
self::TYPE
]);
}
}
return $this;
}
protected function deleteEntityFinish(array $listTitle, $table)
{
if ($table && $listTitle) {
try {
$this->countItemsDeleted += $this->_connection->delete(
$this->_connection->getTableName($table),
$this->_connection->quoteInto('customer_group_code IN (?)', $listTitle)
);
return true;
} catch (\Exception $e) {
return false;
}
} else {
return false;
}
}
}
My table structure
thats it, for any clarity related to this answer please mention in comment.
@Atish Goshwami answer also correct, Why am I update? because with my way I could achieve result within twenty minutes its simple way to done this.
I would suggest to extend the Magento 2's default import functionality.
To do that register a new module (lets say "Custom Import" for now)
Create a module.xml
file at app/code/Foo/CustomImport/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Foo_CustomPriceImport" setup_version="1.0.0"/>
</config>
Next create import.xml
file at app/code/Foo/CustomImport/etc/import.xml
<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="Foo\CustomImport\Model\Import\CustomImport" behaviorModel="Magento\ImportExport\Model\Source\Import\Behavior\Basic" />
</config>
The entry import.xml
will add a new option in the import page "Entity Type" dropdown (System > Data Transfer > Import)
now in the import.xml
the xml attributes:
behaviorModel
: Takes the class name of the model class responsible to handle the logic for the import
label
: Label name of the dropdown option
name
: name for the dropdown option value
Next we need to create the model file at app/code/Foo/CustomImport/Model/Import/CustomPricing.php
class CustomImport extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
You can take the reference of the Magento_AdvancedPricingImportExport
to see the import logic.
First, create an Import Button in your Ui-component File
[vendor_name] \ [module_name] \view\adminhtml\ui_component
uiComponenetFileName.xml
<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</item>
<item name="class" xsi:type="string">primary</item>
<item name="url" xsi:type="string">*/*/add</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 Storelocatore</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>
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 that Calls 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 imported form checks whether a file is valid or not, now create a file that reads your uploaded file and inserts it into the 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 the same as the Sample filename
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('VendoreName\ModuleName\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 the .csv file and import data.
I Hope This Helps You.
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>
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;
}
}