Notice: You are browsing the documentation for PrestaShop 9, which is currently in development.
You might want to read the documentation for the current version, PrestaShop 8. Read the current version of this page
The import workflow consists of the following steps:
This page consists of import configuration, where you select the import data source and choose wanted options, such as field separators, import language, whether old data should be truncated or not, etc.
All configuration which is selected in this page, is represented by the PrestaShop\PrestaShop\Core\Import\Configuration\ImportConfigInterface
.
The default implementation of the mentioned configuration interface (PrestaShop\PrestaShop\Core\Import\Configuration\ImportConfigInterface
) in PrestaShop can be seen in PrestaShop\PrestaShop\Core\Import\Configuration\ImportConfig
class.
This class is a value object, which values are not supposed to change during one import operation.
The default ImportConfig
implementation can be instantiated using the factory PrestaShop\PrestaShop\Core\Import\Configuration\ImportConfigFactory
.
In the second import step we can configure only two things that are directly related to the import:
The number of rows to skip from the top of import file value is also held in the default ImportConfig
implementation and is exposed by the PrestaShop\PrestaShop\Core\Import\Configuration\ImportConfigInterface
.
The interface fits well for this configuration value, because the value is not supposed to change during the import operation.
PrestaShop\PrestaShop\Core\Import\Entity
.PrestaShop\PrestaShop\Core\Import\EntityField\EntityField
.PrestaShop\PrestaShop\Core\Import\File\DataRow\DataRow
.This class holds all import types, that are available by default in PrestaShop and allows to retrieve them easily:
<?php
// src/Core/Import/Entity.php
final class Entity
{
const TYPE_CATEGORIES = 0;
const TYPE_PRODUCTS = 1;
const TYPE_COMBINATIONS = 2;
const TYPE_CUSTOMERS = 3;
const TYPE_ADDRESSES = 4;
const TYPE_MANUFACTURERS = 5;
const TYPE_SUPPLIERS = 6;
const TYPE_ALIAS = 7;
const TYPE_STORE_CONTACTS = 8;
<...>
}
Entity field is described by an implementation of PrestaShop\PrestaShop\Core\Import\EntityField\EntityFieldInterface
.
Entity fields are stored in collections, by implementing PrestaShop\PrestaShop\Core\Import\EntityField\EntityFieldCollectionInterface
.
Entity field collection default implementation is this class: PrestaShop\PrestaShop\Core\Import\EntityField\EntityFieldCollection
.
Entity field collections are provided by providers, which implement PrestaShop\PrestaShop\Core\Import\EntityField\Provider\EntityFieldsProviderInterface
.
Every entity, which is available for import in PrestaShop, has it’s own fields provider in the PrestaShop\PrestaShop\Core\Import\EntityField\Provider
namespace.
For example, the entity fields provider for Customer
entity builds the entity fields collection in the following way:
<?php
// src/Core/Import/EntityField/Provider/CustomerFieldsProvider.php
final class CustomerFieldsProvider implements EntityFieldsProviderInterface
{
public function getCollection()
{
$fields = [
new EntityField('id', $this->trans('ID', 'Admin.Global')),
new EntityField('active', $this->trans('Active (0/1)')),
new EntityField('id_gender', $this->trans('Titles ID (Mr = 1, Ms = 2, else 0)')),
new EntityField('email', $this->trans('Email', 'Admin.Global'), '', true),
new EntityField('passwd', $this->trans('Password', 'Admin.Global'), '', true),
new EntityField('birthday', $this->trans('Birth date (yyyy-mm-dd)')),
new EntityField('lastname', $this->trans('Last name', 'Admin.Global'), '', true),
new EntityField('firstname', $this->trans('First name', 'Admin.Global'), '', true),
new EntityField('newsletter', $this->trans('Newsletter (0/1)')),
new EntityField('optin', $this->trans('Partner offers (0/1)')),
new EntityField('date_add', $this->trans('Registration date (yyyy-mm-dd)')),
new EntityField('group', $this->trans('Groups (x,y,z...)')),
new EntityField('id_default_group', $this->trans('Default group ID')),
new EntityField(
'id_shop',
$this->trans('ID / Name of shop'),
$this->trans('Ignore this field if you don\'t use the Multistore tool. If you leave this field empty, the default shop will be used.', 'Admin.Advparameters.Help')
),
];
return EntityFieldCollection::createFromArray($fields);
}
// ...
}
DataRow
is an object representation of a data row from import source file.
DataRow
is described by an interface PrestaShop\PrestaShop\Core\Import\File\DataRow\DataRowInterface
and can be used in collections to represent multiple rows of data.
DataRow
collections can be built using DataRowCollectionFactory
, which should implement the PrestaShop\PrestaShop\Core\Import\File\DataRow\Factory\DataRowCollectionFactoryInterface
.
Currently there is one DataRowCollectionFactory
implementation available in PrestaShop, which builds the DataRowCollection
by reading a data file:
<?php
// src/Core/Import/File/DataRow/Factory/DataRowCollectionFactory.php
final class DataRowCollectionFactory implements DataRowCollectionFactoryInterface
{
// ...
public function buildFromFile(SplFileInfo $file, $maxRowsInCollection = null)
{
$dataRowCollection = new DataRowCollection();
$rowIndex = 0;
foreach ($this->fileReader->read($file) as $dataRow) {
if (null !== $maxRowsInCollection && $rowIndex >= $maxRowsInCollection) {
break;
}
$dataRowCollection->addDataRow($dataRow);
++$rowIndex;
}
return $dataRowCollection;
}
}
The import operation can be imaged as multiple smaller import processes running one after another, until the data is fully imported or critical errors occur.
Import operation can be described by three essential parts:
To run the import process we have to prepare the configuration for it.
As mentioned in previous topics, there are two configuration objects (ImportConfig
and ImportRuntimeConfig
), that have to be prepared for the import process. Both of them can be built using factories, which are described by interfaces PrestaShop\PrestaShop\Core\Import\Configuration\ImportConfigFactoryInterface
and PrestaShop\PrestaShop\Core\Import\Configuration\ImportRuntimeConfigFactoryInterface
.
There is one implementation of each of the two configuration interfaces in PrestaShop. Both of them are available to build the relevant import config object out of Symfony Request
:
<?php
// src/Core/Import/Configuration/ImportConfigFactory.php
final class ImportConfigFactory implements ImportConfigFactoryInterface
{
public function buildFromRequest(Request $request)
{
$separator = $request->request->get(
'separator',
$request->getSession()->get('separator', ImportSettings::DEFAULT_SEPARATOR)
);
$multivalueSeparator = $request->request->get(
'multiple_value_separator',
$request->getSession()->get('multiple_value_separator', ImportSettings::DEFAULT_MULTIVALUE_SEPARATOR)
);
return new ImportConfig(
$request->request->get('csv', $request->getSession()->get('csv')),
$request->request->getInt('entity', $request->getSession()->get('entity', 0)),
$request->request->get('iso_lang', $request->getSession()->get('iso_lang')),
$separator,
$multivalueSeparator,
$request->request->getBoolean('truncate', $request->getSession()->get('truncate', false)),
$request->request->getBoolean('regenerate', $request->getSession()->get('regenerate', false)),
$request->request->getBoolean('match_ref', $request->getSession()->get('match_ref', false)),
$request->request->getBoolean('forceIDs', $request->getSession()->get('forceIDs', false)),
$request->request->getBoolean('sendemail', $request->getSession()->get('sendemail', true)),
$request->request->getInt('skip', 0)
);
}
}
<?php
// src/Core/Import/Configuration/ImportRuntimeConfigFactory.php
final class ImportRuntimeConfigFactory implements ImportRuntimeConfigFactoryInterface
{
public function buildFromRequest(Request $request)
{
$sharedData = $request->request->get('crossStepsVars', []);
return new ImportRuntimeConfig(
$request->request->getBoolean('validateOnly'),
$request->request->getInt('offset'),
$request->request->getInt('limit'),
json_decode($sharedData, true),
$request->request->get('type_value', [])
);
}
}
To handle the import process we must prepare an ImportHandler
, which will have access to our specific logic for import operation. The ImportHandler
should implement PrestaShop/PrestaShop/Core/Import/Handler/ImportHandlerInterface
.
There are three main methods exposed by the interface, which are essential for import logic execution:
<?php
// src/Core/Import/Handler/ImportHandlerInterface.php
interface ImportHandlerInterface
{
/**
* Executed before import process is started.
*/
public function setUp(ImportConfigInterface $importConfig, ImportRuntimeConfigInterface $runtimeConfig);
/**
* Imports one data row.
*/
public function importRow(
ImportConfigInterface $importConfig,
ImportRuntimeConfigInterface $runtimeConfig,
DataRowInterface $dataRow
);
/**
* Executed when the import process is completed.
*/
public function tearDown(ImportConfigInterface $importConfig, ImportRuntimeConfigInterface $runtimeConfig);
// ...
}
setUp()
- executed before each import process. You can set prerequisites in this method, log some data, or execute additional operations that should be executed before starting the import. The method has both ImportConfigInterface
and ImportRuntimeConfigInterface
as arguments, meaning you can access the configuration if needed for import preparation.importRow()
- executed for every row that’s being imported. This method should run the logic, that imports the data for one row. In addition to import configuration, this method also has a PrestaShop\PrestaShop\Core\Import\File\DataRow\DataRowInterface
as an argument, which is an object representation of the current row from the import data source.tearDown()
- executed when the import process is finished. Useful for actions that have to be done only once after each process.The Importer
is responsible for running the import logic from ImportHandler
, and applying the import configuration properly during the process.
Importer
is an object that implements the PrestaShop\PrestaShop\Core\Import\ImporterInterface
. PrestaShop comes with one Importer
implementation (PrestaShop\PrestaShop\Core\Import\Importer
), which can be easily used for your needs.
The PrestaShop\PrestaShop\Core\Import\ImporterInterface
exposes only one method:
<?php
// src/Core/Import/ImporterInterface.php
interface ImporterInterface
{
/**
* Process the import.
*/
public function import(
ImportConfigInterface $importConfig,
ImportRuntimeConfigInterface $runtimeConfig,
ImportHandlerInterface $importHandler
);
}
import()
method accepts the import configurations and the import handler implementation as arguments and will execute the import logic automatically.
The processImportAction()
controller action (from the example below) imports one batch of the import data at a time.
It can be run multiple times, until all data is fully imported.
The controller action below is being called multiple times (via AJAX) by the JavaScript part of the import component, until all data is imported from the source file:
<?php
// src/PrestaShopBundle/Controller/Admin/Configure/AdvancedParameters/ImportController.php
public function processImportAction(Request $request)
{
$importer = $this->get('prestashop.core.import.importer');
$importConfigFactory = $this->get('prestashop.core.import.config_factory');
$runtimeConfigFactory = $this->get('prestashop.core.import.runtime_config_factory');
$importHandlerFinder = $this->get('prestashop.adapter.import.handler_finder');
// Building the configuration objects
$importConfig = $importConfigFactory->buildFromRequest($request);
$runtimeConfig = $runtimeConfigFactory->buildFromRequest($request);
// Running the import process
$importer->import(
$importConfig,
$runtimeConfig,
$importHandlerFinder->find($importConfig->getEntityType()) // Finding import handler
);
return $this->json($runtimeConfig->toArray());
}
Since the import operation can be heavy and take many resources to complete (depending on the amount of data to be imported), in PrestaShop it is being executed in smaller processes. To achieve that, some JavaScript code is being used, which continuously fires AJAX requests that trigger the import processing on the server, until the import finishes.
All JavaScript code, which is used by the import component, can be found under admin-dev/themes/new-theme/js/pages/import-data/
directory.
We can find different JavaScript components there, which are explained below.
EntityFieldsValidator
Responsible for validating selected entity fields in import page 2 data table. It makes sure that you don’t miss any required fields, prevents you from selecting same field twice and shows error messages if you do.
ImportBatchSizeCalculator
Calculates the most reasonable batch size for each import process, depending on server’s response time. It adapts the batch size of the next import iteration by measuring how long it took for the server to process the data in previous import iteration.
ImportDataTable
Responsible for pagination functionality in the import data preview table. The pagination arrows appear below the data table and can be used to peek the source file preview forward or backwards.
ImportMatchConfiguration
Responsible for saving, loading or deleting import matches configurations. Import match configuration allows saving the matched entity fields for later reusability.
PostSizeChecker
Responsible for checking if POST size limit is being reached. It’s used in each import process, to make sure it won’t reach the limits.
ImportProgressModal
Responsible for displaying the import progress for the end user in a modal window. It updates the progress bar of the modal, displays messages, shows/hides the buttons in modal when asked for.
Importer
Executes import process and fires AJAX import requests continuously.
It uses the PostSizeChecker
, ImportBatchCalculator
and ImportProgressModal
components internally and connects them to execute the import process.
ImportDataPage
Responsible for running the Importer
component when the end user clicks Import button.
Collects data from the import match configuration form and passes it to the Importer
.