Tidy up some logic, restore firstRowTitles setting

Refs #1856
This commit is contained in:
Samuel Georges 2016-03-26 14:10:05 +11:00
parent 2a60e34558
commit a035acdc2c
5 changed files with 135 additions and 128 deletions

View File

@ -7,7 +7,7 @@ use Response;
use Backend;
use BackendAuth;
use Backend\Classes\ControllerBehavior;
use Backend\Classes\StreamFilterTranscode;
use Backend\Behaviors\ImportExportController\TranscodeFilter;
use League\Csv\Reader as CsvReader;
use League\Csv\Writer as CsvWriter;
use ApplicationException;
@ -175,20 +175,14 @@ class ImportExportController extends ControllerBehavior
try {
$model = $this->importGetModel();
$matches = post('column_match', []);
$importOptions = [
'sessionKey' => $this->importUploadFormWidget->getSessionKey()
];
if ($optionData = post('ImportOptions')) {
$model->fill($optionData);
}
if (post('format_preset') == 'custom') {
$importOptions['delimiter'] = post('format_delimiter');
$importOptions['enclosure'] = post('format_enclosure');
$importOptions['escape'] = post('format_escape');
$importOptions['encoding'] = post('format_encoding');
}
$importOptions = $this->getFormatOptionsFromPost();
$importOptions['sessionKey'] = $this->importUploadFormWidget->getSessionKey();
$importOptions['firstRowTitles'] = post('first_row_titles', false);
$model->import($matches, $importOptions);
@ -310,8 +304,10 @@ class ImportExportController extends ControllerBehavior
});
}
// Prevents unfriendly error to be thrown due to bad encoding at response time
if (false === json_encode($firstRow)) {
/*
* Prevents unfriendly error to be thrown due to bad encoding at response time.
*/
if (json_encode($firstRow) === false) {
throw new ApplicationException(Lang::get('backend::lang.import_export.encoding_not_supported_error'));
}
@ -395,19 +391,13 @@ class ImportExportController extends ControllerBehavior
try {
$model = $this->exportGetModel();
$columns = $this->processExportColumnsFromPost();
$exportOptions = [
'sessionKey' => $this->exportFormatFormWidget->getSessionKey()
];
if ($optionData = post('ExportOptions')) {
$model->fill($optionData);
}
if (post('format_preset') == 'custom') {
$exportOptions['delimiter'] = post('format_delimiter');
$exportOptions['enclosure'] = post('format_enclosure');
$exportOptions['escape'] = post('format_escape');
}
$exportOptions = $this->getFormatOptionsFromPost();
$exportOptions['sessionKey'] = $this->exportFormatFormWidget->getSessionKey();
$reference = $model->export($columns, $exportOptions);
$fileUrl = $this->controller->actionUrl(
@ -705,7 +695,6 @@ class ImportExportController extends ControllerBehavior
return $this->controller->actionUrl($type);
}
/**
* Create a new CSV reader with options selected by the user
* @param string $path
@ -715,14 +704,7 @@ class ImportExportController extends ControllerBehavior
protected function createCsvReader($path)
{
$reader = CsvReader::createFromPath($path);
if (post('format_preset') == 'custom') {
$options = [
'delimiter' => post('format_delimiter'),
'enclosure' => post('format_enclosure'),
'escape' => post('format_escape'),
'encoding' => post('format_encoding')
];
$options = $this->getFormatOptionsFromPost();
if ($options['delimiter'] !== null) {
$reader->setDelimiter($options['delimiter']);
@ -736,18 +718,45 @@ class ImportExportController extends ControllerBehavior
$reader->setEscape($options['escape']);
}
if ($options['encoding'] !== null) {
if ($reader->isActiveStreamFilter()) {
if (
$options['encoding'] !== null &&
$reader->isActiveStreamFilter()
) {
$reader->appendStreamFilter(sprintf(
'%s%s:%s',
StreamFilterTranscode::FILTER_NAME,
TranscodeFilter::FILTER_NAME,
strtolower($options['encoding']),
'utf-8'
));
}
}
}
return $reader;
}
/**
* Returns the file format options from postback. This method
* can be used to define presets.
* @return array
*/
protected function getFormatOptionsFromPost()
{
$presetMode = post('format_preset');
$options = [
'delimiter' => null,
'enclosure' => null,
'escape' => null,
'encoding' => null
];
if ($presetMode == 'custom') {
$options['delimiter'] = post('format_delimiter');
$options['enclosure'] = post('format_enclosure');
$options['escape'] = post('format_escape');
$options['encoding'] = post('format_encoding');
}
return $options;
}
}

View File

@ -0,0 +1,69 @@
<?php namespace Backend\Behaviors\ImportExportController;
use php_user_filter;
stream_filter_register(StreamFilterTranscode::FILTER_NAME . "*", StreamFilterTranscode::class);
/**
* Transcode stream filter.
*
* Convert CSV source files from one encoding to another.
*/
class TranscodeFilter extends php_user_filter
{
const FILTER_NAME = 'october.csv.transcode.';
protected $encodingFrom = 'auto';
protected $encodingTo;
public function filter($in, $out, &$consumed, $closing)
{
while ($resource = stream_bucket_make_writeable($in)) {
$resource->data = @mb_convert_encoding(
$resource->data,
$this->encodingTo,
$this->encodingFrom
);
$consumed += $resource->datalen;
stream_bucket_append($out, $resource);
}
return PSFS_PASS_ON;
}
public function onCreate()
{
if (strpos($this->filtername, self::FILTER_NAME) !== 0) {
return false;
}
$params = substr($this->filtername, strlen(self::FILTER_NAME));
if (!preg_match('/^([-\w]+)(:([-\w]+))?$/', $params, $matches)) {
return false;
}
if (isset($matches[1])) {
$this->encodingFrom = $matches[1];
}
$this->encodingTo = mb_internal_encoding();
if (isset( $matches[3] )) {
$this->encodingTo = $matches[3];
}
$this->params['locale'] = setlocale(LC_CTYPE, '0');
if (stripos($this->params['locale'], 'UTF-8') === false) {
setlocale(LC_CTYPE, 'en_US.UTF-8');
}
return true;
}
public function onClose()
{
setlocale(LC_CTYPE, $this->params['locale']);
}
}

View File

@ -1,71 +0,0 @@
<?php namespace Backend\Classes;
use php_user_filter;
// Register the class for it to be usable by the CSV Lib
stream_filter_register(StreamFilterTranscode::FILTER_NAME . "*", StreamFilterTranscode::class);
/**
* A universal transcode stream filter.
* Used by the backend import model to convert source file from one encoding to another.
* The system must support both source and target encoding encoding.
*
* @credits https://github.com/thephpleague/csv/blob/master/examples/lib/FilterTranscode.php
* @package october\backend
*/
class StreamFilterTranscode extends php_user_filter
{
const FILTER_NAME = 'convert.transcode.';
private $encoding_from = 'auto';
private $encoding_to;
public function onCreate()
{
if (strpos($this->filtername, self::FILTER_NAME) !== 0) {
return false;
}
$params = substr($this->filtername, strlen(self::FILTER_NAME));
if ( ! preg_match('/^([-\w]+)(:([-\w]+))?$/', $params, $matches)) {
return false;
}
if (isset( $matches[1] )) {
$this->encoding_from = $matches[1];
}
$this->encoding_to = mb_internal_encoding();
if (isset( $matches[3] )) {
$this->encoding_to = $matches[3];
}
$this->params['locale'] = setlocale(LC_CTYPE, '0');
if (stripos($this->params['locale'], 'UTF-8') === false) {
setlocale(LC_CTYPE, 'en_US.UTF-8');
}
return true;
}
public function onClose()
{
setlocale(LC_CTYPE, $this->params['locale']);
}
public function filter($in, $out, &$consumed, $closing)
{
while ($res = stream_bucket_make_writeable($in)) {
$res->data = @mb_convert_encoding($res->data, $this->encoding_to, $this->encoding_from);
$consumed += $res->datalen;
stream_bucket_append($out, $res);
}
return PSFS_PASS_ON;
}
}

View File

@ -16,7 +16,6 @@ use SplTempFileObject;
*/
abstract class ExportModel extends Model
{
/**
* Called when data is being exported.
* The return value should be an array in the format of:
@ -202,5 +201,4 @@ abstract class ExportModel extends Model
return implode($delimeter, $newData);
}
}

View File

@ -1,5 +1,6 @@
<?php namespace Backend\Models;
use Lang;
use Model;
use League\Csv\Reader as CsvReader;
@ -179,7 +180,8 @@ abstract class ImportModel extends Model
$file = $this
->import_file()
->withDeferred($sessionKey)
->first();
->first()
;
if (!$file) {
return null;
@ -195,7 +197,7 @@ abstract class ImportModel extends Model
*/
public function getFormatEncodingOptions()
{
return \Lang::get('backend::lang.import_export.encodings');
return Lang::get('backend::lang.import_export.encodings');
}
//