1

How to create system configuration file field with allowed formats(csv/xls) validation.

1 Answer 1

3

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.

Your Answer

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

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