How to create system configuration file field with allowed formats(csv/xls) validation.
1 Answer
You can see an example in the native magento module - module-offline-shipping
.
CSV Import Field was declared in the system.xml
file:
<field id="import" translate="label" type="Magento\OfflineShipping\Block\Adminhtml\Form\Field\Import" sortOrder="6" showInDefault="0" showInWebsite="1" showInStore="0">
<label>Import</label>
<backend_model>Magento\OfflineShipping\Model\Config\Backend\Tablerate</backend_model>
</field>
You should use a backend model to store your file in the database (or somewhere else). Example of the backend model is available here vendor/magento/module-offline-shipping/Model/Config/Backend/Tablerate.php
. All magic are in this method:
/**
* @return $this
*/
public function afterSave()
{
/** @var \Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate $tableRate */
$tableRate = $this->_tablerateFactory->create();
$tableRate->uploadAndImport($this);
return parent::afterSave();
}
File processing is in the uploadAndImport
method of the \Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate
class:
/**
* Upload table rate file and import data from it
*
* @param \Magento\Framework\DataObject $object
* @throws \Magento\Framework\Exception\LocalizedException
* @return \Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate
* @todo: this method should be refactored as soon as updated design will be provided
* @see https://wiki.corp.x.com/display/MCOMS/Magento+Filesystem+Decisions
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function uploadAndImport(\Magento\Framework\DataObject $object)
{
/**
* @var \Magento\Framework\App\Config\Value $object
*/
if (empty($_FILES['groups']['tmp_name']['tablerate']['fields']['import']['value'])) {
return $this;
}
$filePath = $_FILES['groups']['tmp_name']['tablerate']['fields']['import']['value'];
$websiteId = $this->storeManager->getWebsite($object->getScopeId())->getId();
$conditionName = $this->getConditionName($object);
$file = $this->getCsvFile($filePath);
try {
// delete old data by website and condition name
$condition = [
'website_id = ?' => $websiteId,
'condition_name = ?' => $conditionName,
];
$this->deleteByCondition($condition);
$columns = $this->import->getColumns();
$conditionFullName = $this->_getConditionFullName($conditionName);
foreach ($this->import->getData($file, $websiteId, $conditionName, $conditionFullName) as $bunch) {
$this->importData($columns, $bunch);
}
} catch (\Exception $e) {
$this->logger->critical($e);
throw new \Magento\Framework\Exception\LocalizedException(
__('Something went wrong while importing table rates.')
);
} finally {
$file->close();
}
if ($this->import->hasErrors()) {
$error = __(
'We couldn\'t import this file because of these errors: %1',
implode(" \n", $this->import->getErrors())
);
throw new \Magento\Framework\Exception\LocalizedException($error);
}
}
PS: field's attribute type
can be changed from the Magento\OfflineShipping\Block\Adminhtml\Form\Field\Import
to the file
if you do not want to add additional html to it.