Create class module export csv for extend csv utf-8 and iso
This commit is contained in:
parent
1c659c6ae8
commit
c5d3474e10
@ -21,43 +21,17 @@
|
|||||||
* \brief File of class to build exports with CSV format
|
* \brief File of class to build exports with CSV format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once DOL_DOCUMENT_ROOT.'/core/modules/export/modules_export.php';
|
require_once DOL_DOCUMENT_ROOT.'/core/modules/export/module_export_csv.php';
|
||||||
|
|
||||||
// avoid timeout for big export
|
// avoid timeout for big export
|
||||||
set_time_limit(0);
|
set_time_limit(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to build export files with format CSV
|
* Class to build export files with format CSV iso
|
||||||
*/
|
*/
|
||||||
class ExportCsv extends ModeleExports
|
class ExportCsvIso extends ExportCsv
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var string ID ex: csv, tsv, excel...
|
|
||||||
*/
|
|
||||||
public $id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string export files label
|
|
||||||
*/
|
|
||||||
public $label;
|
|
||||||
|
|
||||||
public $extension;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dolibarr version of the loaded document
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $version = 'dolibarr';
|
|
||||||
|
|
||||||
public $label_lib;
|
|
||||||
|
|
||||||
public $version_lib;
|
|
||||||
|
|
||||||
public $separator;
|
|
||||||
|
|
||||||
public $handle; // Handle fichier
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -72,6 +46,9 @@ class ExportCsv extends ModeleExports
|
|||||||
if (!empty($conf->global->EXPORT_CSV_SEPARATOR_TO_USE)) {
|
if (!empty($conf->global->EXPORT_CSV_SEPARATOR_TO_USE)) {
|
||||||
$this->separator = $conf->global->EXPORT_CSV_SEPARATOR_TO_USE;
|
$this->separator = $conf->global->EXPORT_CSV_SEPARATOR_TO_USE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$conf->global->EXPORT_CSV_FORCE_CHARSET = 'ISO-8859-1';
|
||||||
|
|
||||||
$this->escape = '"';
|
$this->escape = '"';
|
||||||
$this->enclosure = '"';
|
$this->enclosure = '"';
|
||||||
$this->id = 'csviso'; // Same value then xxx in file name export_xxx.modules.php
|
$this->id = 'csviso'; // Same value then xxx in file name export_xxx.modules.php
|
||||||
@ -85,295 +62,4 @@ class ExportCsv extends ModeleExports
|
|||||||
$this->label_lib = 'Dolibarr';
|
$this->label_lib = 'Dolibarr';
|
||||||
$this->version_lib = DOL_VERSION;
|
$this->version_lib = DOL_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* getDriverId
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDriverId()
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getDriverLabel
|
|
||||||
*
|
|
||||||
* @return string Return driver label
|
|
||||||
*/
|
|
||||||
public function getDriverLabel()
|
|
||||||
{
|
|
||||||
return $this->label;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getDriverDesc
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDriverDesc()
|
|
||||||
{
|
|
||||||
return $this->desc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getDriverExtension
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDriverExtension()
|
|
||||||
{
|
|
||||||
return $this->extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getDriverVersion
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDriverVersion()
|
|
||||||
{
|
|
||||||
return $this->version;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getLabelLabel
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLibLabel()
|
|
||||||
{
|
|
||||||
return $this->label_lib;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getLibVersion
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLibVersion()
|
|
||||||
{
|
|
||||||
return $this->version_lib;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Open output file
|
|
||||||
*
|
|
||||||
* @param string $file Path of filename to generate
|
|
||||||
* @param Translate $outputlangs Output language object
|
|
||||||
* @return int <0 if KO, >=0 if OK
|
|
||||||
*/
|
|
||||||
public function open_file($file, $outputlangs)
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
global $langs;
|
|
||||||
|
|
||||||
dol_syslog("ExportCsv::open_file file=".$file);
|
|
||||||
|
|
||||||
$ret = 1;
|
|
||||||
|
|
||||||
$outputlangs->load("exports");
|
|
||||||
$this->handle = fopen($file, "wt");
|
|
||||||
if (!$this->handle) {
|
|
||||||
$langs->load("errors");
|
|
||||||
$this->error = $langs->trans("ErrorFailToCreateFile", $file);
|
|
||||||
$ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Output header into file
|
|
||||||
*
|
|
||||||
* @param Translate $outputlangs Output language object
|
|
||||||
* @return int <0 if KO, >0 if OK
|
|
||||||
*/
|
|
||||||
public function write_header($outputlangs)
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Output title line into file
|
|
||||||
*
|
|
||||||
* @param array $array_export_fields_label Array with list of label of fields
|
|
||||||
* @param array $array_selected_sorted Array with list of field to export
|
|
||||||
* @param Translate $outputlangs Object lang to translate values
|
|
||||||
* @param array $array_types Array with types of fields
|
|
||||||
* @return int <0 if KO, >0 if OK
|
|
||||||
*/
|
|
||||||
public function write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types)
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
global $conf;
|
|
||||||
|
|
||||||
$outputlangs->charset_output = 'ISO-8859-1';
|
|
||||||
$conf->global->EXPORT_CSV_FORCE_CHARSET = 'ISO-8859-1';
|
|
||||||
|
|
||||||
$selectlabel = array();
|
|
||||||
|
|
||||||
foreach ($array_selected_sorted as $code => $value) {
|
|
||||||
$newvalue = $outputlangs->transnoentities($array_export_fields_label[$code]); // newvalue is now $outputlangs->charset_output encoded
|
|
||||||
$newvalue = $this->csvClean($newvalue, $outputlangs->charset_output);
|
|
||||||
|
|
||||||
fwrite($this->handle, $newvalue.$this->separator);
|
|
||||||
$typefield = isset($array_types[$code]) ? $array_types[$code] : '';
|
|
||||||
|
|
||||||
if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) {
|
|
||||||
$selectlabel[$code."_label"] = $newvalue."_label";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ($selectlabel as $key => $value) {
|
|
||||||
fwrite($this->handle, $value.$this->separator);
|
|
||||||
}
|
|
||||||
fwrite($this->handle, "\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Output record line into file
|
|
||||||
*
|
|
||||||
* @param array $array_selected_sorted Array with list of field to export
|
|
||||||
* @param resource $objp A record from a fetch with all fields from select
|
|
||||||
* @param Translate $outputlangs Object lang to translate values
|
|
||||||
* @param array $array_types Array with types of fields
|
|
||||||
* @return int <0 if KO, >0 if OK
|
|
||||||
*/
|
|
||||||
public function write_record($array_selected_sorted, $objp, $outputlangs, $array_types)
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
global $conf;
|
|
||||||
|
|
||||||
$outputlangs->charset_output = 'ISO-8859-1';
|
|
||||||
$conf->global->EXPORT_CSV_FORCE_CHARSET = 'ISO-8859-1';
|
|
||||||
|
|
||||||
$this->col = 0;
|
|
||||||
|
|
||||||
$reg = array();
|
|
||||||
$selectlabelvalues = array();
|
|
||||||
foreach ($array_selected_sorted as $code => $value) {
|
|
||||||
if (strpos($code, ' as ') == 0) {
|
|
||||||
$alias = str_replace(array('.', '-', '(', ')'), '_', $code);
|
|
||||||
} else {
|
|
||||||
$alias = substr($code, strpos($code, ' as ') + 4);
|
|
||||||
}
|
|
||||||
if (empty($alias)) {
|
|
||||||
dol_print_error('', 'Bad value for field with key='.$code.'. Try to redefine export.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$newvalue = $outputlangs->convToOutputCharset($objp->$alias); // objp->$alias must be utf8 encoded as any var in memory // newvalue is now $outputlangs->charset_output encoded
|
|
||||||
$typefield = isset($array_types[$code]) ? $array_types[$code] : '';
|
|
||||||
|
|
||||||
// Translation newvalue
|
|
||||||
if (preg_match('/^\((.*)\)$/i', $newvalue, $reg)) {
|
|
||||||
$newvalue = $outputlangs->transnoentities($reg[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean data and add encloser if required (depending on value of USE_STRICT_CSV_RULES)
|
|
||||||
$newvalue = $this->csvClean($newvalue, $outputlangs->charset_output);
|
|
||||||
|
|
||||||
if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) {
|
|
||||||
$array = jsonOrUnserialize($typefield);
|
|
||||||
if (is_array($array) && !empty($newvalue)) {
|
|
||||||
$array = $array['options'];
|
|
||||||
$selectlabelvalues[$code."_label"] = $array[$newvalue];
|
|
||||||
} else {
|
|
||||||
$selectlabelvalues[$code."_label"] = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fwrite($this->handle, $newvalue.$this->separator);
|
|
||||||
$this->col++;
|
|
||||||
}
|
|
||||||
foreach ($selectlabelvalues as $key => $value) {
|
|
||||||
fwrite($this->handle, $value.$this->separator);
|
|
||||||
$this->col++;
|
|
||||||
}
|
|
||||||
|
|
||||||
fwrite($this->handle, "\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Output footer into file
|
|
||||||
*
|
|
||||||
* @param Translate $outputlangs Output language object
|
|
||||||
* @return int <0 if KO, >0 if OK
|
|
||||||
*/
|
|
||||||
public function write_footer($outputlangs)
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Close file handle
|
|
||||||
*
|
|
||||||
* @return int <0 if KO, >0 if OK
|
|
||||||
*/
|
|
||||||
public function close_file()
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
fclose($this->handle);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean a cell to respect rules of CSV file cells
|
|
||||||
* Note: It uses $this->separator
|
|
||||||
* Note: We keep this function public to be able to test
|
|
||||||
*
|
|
||||||
* @param string $newvalue String to clean
|
|
||||||
* @param string $charset Input AND Output character set
|
|
||||||
* @return string Value cleaned
|
|
||||||
*/
|
|
||||||
public function csvClean($newvalue, $charset)
|
|
||||||
{
|
|
||||||
global $conf;
|
|
||||||
$addquote = 0;
|
|
||||||
|
|
||||||
// Rule Dolibarr: No HTML
|
|
||||||
//print $charset.' '.$newvalue."\n";
|
|
||||||
//$newvalue=dol_string_nohtmltag($newvalue,0,$charset);
|
|
||||||
$newvalue = dol_htmlcleanlastbr($newvalue);
|
|
||||||
//print $charset.' '.$newvalue."\n";
|
|
||||||
|
|
||||||
// Rule 1 CSV: No CR, LF in cells (except if USE_STRICT_CSV_RULES is 1, we can keep record as it is but we must add quotes)
|
|
||||||
$oldvalue = $newvalue;
|
|
||||||
$newvalue = str_replace("\r", '', $newvalue);
|
|
||||||
$newvalue = str_replace("\n", '\n', $newvalue);
|
|
||||||
if (!empty($conf->global->USE_STRICT_CSV_RULES) && $oldvalue != $newvalue) {
|
|
||||||
// If we must use enclusure on text with CR/LF)
|
|
||||||
if ($conf->global->USE_STRICT_CSV_RULES == 1) {
|
|
||||||
// If we use strict CSV rules (original value must remain but we add quote)
|
|
||||||
$newvalue = $oldvalue;
|
|
||||||
}
|
|
||||||
$addquote = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rule 2 CSV: If value contains ", we must escape with ", and add "
|
|
||||||
if (preg_match('/"/', $newvalue)) {
|
|
||||||
$addquote = 1;
|
|
||||||
$newvalue = str_replace('"', '""', $newvalue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rule 3 CSV: If value contains separator, we must add "
|
|
||||||
if (preg_match('/'.$this->separator.'/', $newvalue)) {
|
|
||||||
$addquote = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($addquote ? '"' : '').$newvalue.($addquote ? '"' : '');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,43 +21,17 @@
|
|||||||
* \brief File of class to build exports with CSV format
|
* \brief File of class to build exports with CSV format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once DOL_DOCUMENT_ROOT.'/core/modules/export/modules_export.php';
|
require_once DOL_DOCUMENT_ROOT.'/core/modules/export/module_export_csv.php';
|
||||||
|
|
||||||
// avoid timeout for big export
|
// avoid timeout for big export
|
||||||
set_time_limit(0);
|
set_time_limit(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to build export files with format CSV
|
* Class to build export files with format CSV utf-8
|
||||||
*/
|
*/
|
||||||
class ExportCsvUtf8 extends ModeleExports
|
class ExportCsvUtf8 extends ExportCsv
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var string ID ex: csv, tsv, excel...
|
|
||||||
*/
|
|
||||||
public $id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string export files label
|
|
||||||
*/
|
|
||||||
public $label;
|
|
||||||
|
|
||||||
public $extension;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dolibarr version of the loaded document
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public $version = 'dolibarr';
|
|
||||||
|
|
||||||
public $label_lib;
|
|
||||||
|
|
||||||
public $version_lib;
|
|
||||||
|
|
||||||
public $separator;
|
|
||||||
|
|
||||||
public $handle; // Handle fichier
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -72,9 +46,11 @@ class ExportCsvUtf8 extends ModeleExports
|
|||||||
if (!empty($conf->global->EXPORT_CSV_SEPARATOR_TO_USE)) {
|
if (!empty($conf->global->EXPORT_CSV_SEPARATOR_TO_USE)) {
|
||||||
$this->separator = $conf->global->EXPORT_CSV_SEPARATOR_TO_USE;
|
$this->separator = $conf->global->EXPORT_CSV_SEPARATOR_TO_USE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$conf->global->EXPORT_CSV_FORCE_CHARSET = 'UTF-8';
|
||||||
|
|
||||||
$this->escape = '"';
|
$this->escape = '"';
|
||||||
$this->enclosure = '"';
|
$this->enclosure = '"';
|
||||||
|
|
||||||
$this->id = 'csvutf8'; // Same value then xxx in file name export_xxx.modules.php
|
$this->id = 'csvutf8'; // Same value then xxx in file name export_xxx.modules.php
|
||||||
$this->label = 'CSV UTF-8'; // Label of driver
|
$this->label = 'CSV UTF-8'; // Label of driver
|
||||||
$this->desc = $langs->trans("CSVFormatDesc", $this->separator, $this->enclosure, $this->escape);
|
$this->desc = $langs->trans("CSVFormatDesc", $this->separator, $this->enclosure, $this->escape);
|
||||||
@ -86,294 +62,4 @@ class ExportCsvUtf8 extends ModeleExports
|
|||||||
$this->label_lib = 'Dolibarr';
|
$this->label_lib = 'Dolibarr';
|
||||||
$this->version_lib = DOL_VERSION;
|
$this->version_lib = DOL_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* getDriverId
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDriverId()
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getDriverLabel
|
|
||||||
*
|
|
||||||
* @return string Return driver label
|
|
||||||
*/
|
|
||||||
public function getDriverLabel()
|
|
||||||
{
|
|
||||||
return $this->label;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getDriverDesc
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDriverDesc()
|
|
||||||
{
|
|
||||||
return $this->desc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getDriverExtension
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDriverExtension()
|
|
||||||
{
|
|
||||||
return $this->extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getDriverVersion
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getDriverVersion()
|
|
||||||
{
|
|
||||||
return $this->version;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getLabelLabel
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLibLabel()
|
|
||||||
{
|
|
||||||
return $this->label_lib;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getLibVersion
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getLibVersion()
|
|
||||||
{
|
|
||||||
return $this->version_lib;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Open output file
|
|
||||||
*
|
|
||||||
* @param string $file Path of filename to generate
|
|
||||||
* @param Translate $outputlangs Output language object
|
|
||||||
* @return int <0 if KO, >=0 if OK
|
|
||||||
*/
|
|
||||||
public function open_file($file, $outputlangs)
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
global $langs;
|
|
||||||
|
|
||||||
dol_syslog("ExportCsv::open_file file=".$file);
|
|
||||||
|
|
||||||
$ret = 1;
|
|
||||||
|
|
||||||
$outputlangs->load("exports");
|
|
||||||
$this->handle = fopen($file, "wt");
|
|
||||||
if (!$this->handle) {
|
|
||||||
$langs->load("errors");
|
|
||||||
$this->error = $langs->trans("ErrorFailToCreateFile", $file);
|
|
||||||
$ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Output header into file
|
|
||||||
*
|
|
||||||
* @param Translate $outputlangs Output language object
|
|
||||||
* @return int <0 if KO, >0 if OK
|
|
||||||
*/
|
|
||||||
public function write_header($outputlangs)
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Output title line into file
|
|
||||||
*
|
|
||||||
* @param array $array_export_fields_label Array with list of label of fields
|
|
||||||
* @param array $array_selected_sorted Array with list of field to export
|
|
||||||
* @param Translate $outputlangs Object lang to translate values
|
|
||||||
* @param array $array_types Array with types of fields
|
|
||||||
* @return int <0 if KO, >0 if OK
|
|
||||||
*/
|
|
||||||
public function write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types)
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
global $conf;
|
|
||||||
|
|
||||||
$outputlangs->charset_output = 'UTF-8';
|
|
||||||
// var_dump($outputlangs->charset_output);exit;
|
|
||||||
// var_dump($conf->global->EXPORT_CSV_FORCE_CHARSET, "here");exit;
|
|
||||||
$selectlabel = array();
|
|
||||||
|
|
||||||
foreach ($array_selected_sorted as $code => $value) {
|
|
||||||
$newvalue = $outputlangs->transnoentities($array_export_fields_label[$code]); // newvalue is now $outputlangs->charset_output encoded
|
|
||||||
$newvalue = $this->csvClean($newvalue, $outputlangs->charset_output);
|
|
||||||
|
|
||||||
fwrite($this->handle, $newvalue.$this->separator);
|
|
||||||
$typefield = isset($array_types[$code]) ? $array_types[$code] : '';
|
|
||||||
|
|
||||||
if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) {
|
|
||||||
$selectlabel[$code."_label"] = $newvalue."_label";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ($selectlabel as $key => $value) {
|
|
||||||
fwrite($this->handle, $value.$this->separator);
|
|
||||||
}
|
|
||||||
fwrite($this->handle, "\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Output record line into file
|
|
||||||
*
|
|
||||||
* @param array $array_selected_sorted Array with list of field to export
|
|
||||||
* @param resource $objp A record from a fetch with all fields from select
|
|
||||||
* @param Translate $outputlangs Object lang to translate values
|
|
||||||
* @param array $array_types Array with types of fields
|
|
||||||
* @return int <0 if KO, >0 if OK
|
|
||||||
*/
|
|
||||||
public function write_record($array_selected_sorted, $objp, $outputlangs, $array_types)
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
global $conf;
|
|
||||||
|
|
||||||
$outputlangs->charset_output = 'UTF-8';
|
|
||||||
// var_dump($conf->global->EXPORT_CSV_FORCE_CHARSET, "here");exit;
|
|
||||||
$this->col = 0;
|
|
||||||
|
|
||||||
$reg = array();
|
|
||||||
$selectlabelvalues = array();
|
|
||||||
foreach ($array_selected_sorted as $code => $value) {
|
|
||||||
if (strpos($code, ' as ') == 0) {
|
|
||||||
$alias = str_replace(array('.', '-', '(', ')'), '_', $code);
|
|
||||||
} else {
|
|
||||||
$alias = substr($code, strpos($code, ' as ') + 4);
|
|
||||||
}
|
|
||||||
if (empty($alias)) {
|
|
||||||
dol_print_error('', 'Bad value for field with key='.$code.'. Try to redefine export.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$newvalue = $outputlangs->convToOutputCharset($objp->$alias); // objp->$alias must be utf8 encoded as any var in memory // newvalue is now $outputlangs->charset_output encoded
|
|
||||||
$typefield = isset($array_types[$code]) ? $array_types[$code] : '';
|
|
||||||
|
|
||||||
// Translation newvalue
|
|
||||||
if (preg_match('/^\((.*)\)$/i', $newvalue, $reg)) {
|
|
||||||
$newvalue = $outputlangs->transnoentities($reg[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean data and add encloser if required (depending on value of USE_STRICT_CSV_RULES)
|
|
||||||
$newvalue = $this->csvClean($newvalue, $outputlangs->charset_output);
|
|
||||||
|
|
||||||
if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) {
|
|
||||||
$array = jsonOrUnserialize($typefield);
|
|
||||||
if (is_array($array) && !empty($newvalue)) {
|
|
||||||
$array = $array['options'];
|
|
||||||
$selectlabelvalues[$code."_label"] = $array[$newvalue];
|
|
||||||
} else {
|
|
||||||
$selectlabelvalues[$code."_label"] = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fwrite($this->handle, $newvalue.$this->separator);
|
|
||||||
$this->col++;
|
|
||||||
}
|
|
||||||
foreach ($selectlabelvalues as $key => $value) {
|
|
||||||
fwrite($this->handle, $value.$this->separator);
|
|
||||||
$this->col++;
|
|
||||||
}
|
|
||||||
|
|
||||||
fwrite($this->handle, "\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Output footer into file
|
|
||||||
*
|
|
||||||
* @param Translate $outputlangs Output language object
|
|
||||||
* @return int <0 if KO, >0 if OK
|
|
||||||
*/
|
|
||||||
public function write_footer($outputlangs)
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
|
||||||
/**
|
|
||||||
* Close file handle
|
|
||||||
*
|
|
||||||
* @return int <0 if KO, >0 if OK
|
|
||||||
*/
|
|
||||||
public function close_file()
|
|
||||||
{
|
|
||||||
// phpcs:enable
|
|
||||||
fclose($this->handle);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean a cell to respect rules of CSV file cells
|
|
||||||
* Note: It uses $this->separator
|
|
||||||
* Note: We keep this function public to be able to test
|
|
||||||
*
|
|
||||||
* @param string $newvalue String to clean
|
|
||||||
* @param string $charset Input AND Output character set
|
|
||||||
* @return string Value cleaned
|
|
||||||
*/
|
|
||||||
public function csvClean($newvalue, $charset)
|
|
||||||
{
|
|
||||||
global $conf;
|
|
||||||
$addquote = 0;
|
|
||||||
|
|
||||||
// Rule Dolibarr: No HTML
|
|
||||||
//print $charset.' '.$newvalue."\n";
|
|
||||||
//$newvalue=dol_string_nohtmltag($newvalue,0,$charset);
|
|
||||||
$newvalue = dol_htmlcleanlastbr($newvalue);
|
|
||||||
//print $charset.' '.$newvalue."\n";
|
|
||||||
|
|
||||||
// Rule 1 CSV: No CR, LF in cells (except if USE_STRICT_CSV_RULES is 1, we can keep record as it is but we must add quotes)
|
|
||||||
$oldvalue = $newvalue;
|
|
||||||
$newvalue = str_replace("\r", '', $newvalue);
|
|
||||||
$newvalue = str_replace("\n", '\n', $newvalue);
|
|
||||||
if (!empty($conf->global->USE_STRICT_CSV_RULES) && $oldvalue != $newvalue) {
|
|
||||||
// If we must use enclusure on text with CR/LF)
|
|
||||||
if ($conf->global->USE_STRICT_CSV_RULES == 1) {
|
|
||||||
// If we use strict CSV rules (original value must remain but we add quote)
|
|
||||||
$newvalue = $oldvalue;
|
|
||||||
}
|
|
||||||
$addquote = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rule 2 CSV: If value contains ", we must escape with ", and add "
|
|
||||||
if (preg_match('/"/', $newvalue)) {
|
|
||||||
$addquote = 1;
|
|
||||||
$newvalue = str_replace('"', '""', $newvalue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rule 3 CSV: If value contains separator, we must add "
|
|
||||||
if (preg_match('/'.$this->separator.'/', $newvalue)) {
|
|
||||||
$addquote = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ($addquote ? '"' : '').$newvalue.($addquote ? '"' : '');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
348
htdocs/core/modules/export/module_export_csv.php
Normal file
348
htdocs/core/modules/export/module_export_csv.php
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
<?php
|
||||||
|
/* Copyright (C) 2006-2013 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file htdocs/core/modules/export/export_csv.modules.php
|
||||||
|
* \ingroup export
|
||||||
|
* \brief File of class to build exports with CSV format
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once DOL_DOCUMENT_ROOT.'/core/modules/export/modules_export.php';
|
||||||
|
|
||||||
|
// avoid timeout for big export
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to build export files with format CSV
|
||||||
|
*/
|
||||||
|
class ExportCsv extends ModeleExports
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string ID ex: csv, tsv, excel...
|
||||||
|
*/
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string export files label
|
||||||
|
*/
|
||||||
|
public $label;
|
||||||
|
|
||||||
|
public $extension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dolibarr version of the loaded document
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $version = 'dolibarr';
|
||||||
|
|
||||||
|
public $label_lib;
|
||||||
|
|
||||||
|
public $version_lib;
|
||||||
|
|
||||||
|
public $separator;
|
||||||
|
|
||||||
|
public $handle; // Handle fichier
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getDriverId
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDriverId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getDriverLabel
|
||||||
|
*
|
||||||
|
* @return string Return driver label
|
||||||
|
*/
|
||||||
|
public function getDriverLabel()
|
||||||
|
{
|
||||||
|
return $this->label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getDriverDesc
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDriverDesc()
|
||||||
|
{
|
||||||
|
return $this->desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getDriverExtension
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDriverExtension()
|
||||||
|
{
|
||||||
|
return $this->extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getDriverVersion
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDriverVersion()
|
||||||
|
{
|
||||||
|
return $this->version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getLabelLabel
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLibLabel()
|
||||||
|
{
|
||||||
|
return $this->label_lib;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getLibVersion
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getLibVersion()
|
||||||
|
{
|
||||||
|
return $this->version_lib;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||||
|
/**
|
||||||
|
* Open output file
|
||||||
|
*
|
||||||
|
* @param string $file Path of filename to generate
|
||||||
|
* @param Translate $outputlangs Output language object
|
||||||
|
* @return int <0 if KO, >=0 if OK
|
||||||
|
*/
|
||||||
|
public function open_file($file, $outputlangs)
|
||||||
|
{
|
||||||
|
// phpcs:enable
|
||||||
|
global $langs;
|
||||||
|
|
||||||
|
dol_syslog("ExportCsv::open_file file=".$file);
|
||||||
|
|
||||||
|
$ret = 1;
|
||||||
|
|
||||||
|
$outputlangs->load("exports");
|
||||||
|
$this->handle = fopen($file, "wt");
|
||||||
|
if (!$this->handle) {
|
||||||
|
$langs->load("errors");
|
||||||
|
$this->error = $langs->trans("ErrorFailToCreateFile", $file);
|
||||||
|
$ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||||
|
/**
|
||||||
|
* Output header into file
|
||||||
|
*
|
||||||
|
* @param Translate $outputlangs Output language object
|
||||||
|
* @return int <0 if KO, >0 if OK
|
||||||
|
*/
|
||||||
|
public function write_header($outputlangs)
|
||||||
|
{
|
||||||
|
// phpcs:enable
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||||
|
/**
|
||||||
|
* Output title line into file
|
||||||
|
*
|
||||||
|
* @param array $array_export_fields_label Array with list of label of fields
|
||||||
|
* @param array $array_selected_sorted Array with list of field to export
|
||||||
|
* @param Translate $outputlangs Object lang to translate values
|
||||||
|
* @param array $array_types Array with types of fields
|
||||||
|
* @return int <0 if KO, >0 if OK
|
||||||
|
*/
|
||||||
|
public function write_title($array_export_fields_label, $array_selected_sorted, $outputlangs, $array_types)
|
||||||
|
{
|
||||||
|
// phpcs:enable
|
||||||
|
global $conf;
|
||||||
|
|
||||||
|
$outputlangs->charset_output = $conf->global->EXPORT_CSV_FORCE_CHARSET;
|
||||||
|
|
||||||
|
$selectlabel = array();
|
||||||
|
|
||||||
|
foreach ($array_selected_sorted as $code => $value) {
|
||||||
|
$newvalue = $outputlangs->transnoentities($array_export_fields_label[$code]); // newvalue is now $outputlangs->charset_output encoded
|
||||||
|
$newvalue = $this->csvClean($newvalue, $outputlangs->charset_output);
|
||||||
|
|
||||||
|
fwrite($this->handle, $newvalue.$this->separator);
|
||||||
|
$typefield = isset($array_types[$code]) ? $array_types[$code] : '';
|
||||||
|
|
||||||
|
if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) {
|
||||||
|
$selectlabel[$code."_label"] = $newvalue."_label";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($selectlabel as $key => $value) {
|
||||||
|
fwrite($this->handle, $value.$this->separator);
|
||||||
|
}
|
||||||
|
fwrite($this->handle, "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||||
|
/**
|
||||||
|
* Output record line into file
|
||||||
|
*
|
||||||
|
* @param array $array_selected_sorted Array with list of field to export
|
||||||
|
* @param resource $objp A record from a fetch with all fields from select
|
||||||
|
* @param Translate $outputlangs Object lang to translate values
|
||||||
|
* @param array $array_types Array with types of fields
|
||||||
|
* @return int <0 if KO, >0 if OK
|
||||||
|
*/
|
||||||
|
public function write_record($array_selected_sorted, $objp, $outputlangs, $array_types)
|
||||||
|
{
|
||||||
|
// phpcs:enable
|
||||||
|
global $conf;
|
||||||
|
|
||||||
|
$outputlangs->charset_output = $conf->global->EXPORT_CSV_FORCE_CHARSET;
|
||||||
|
|
||||||
|
$this->col = 0;
|
||||||
|
|
||||||
|
$reg = array();
|
||||||
|
$selectlabelvalues = array();
|
||||||
|
foreach ($array_selected_sorted as $code => $value) {
|
||||||
|
if (strpos($code, ' as ') == 0) {
|
||||||
|
$alias = str_replace(array('.', '-', '(', ')'), '_', $code);
|
||||||
|
} else {
|
||||||
|
$alias = substr($code, strpos($code, ' as ') + 4);
|
||||||
|
}
|
||||||
|
if (empty($alias)) {
|
||||||
|
dol_print_error('', 'Bad value for field with key='.$code.'. Try to redefine export.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$newvalue = $outputlangs->convToOutputCharset($objp->$alias); // objp->$alias must be utf8 encoded as any var in memory // newvalue is now $outputlangs->charset_output encoded
|
||||||
|
$typefield = isset($array_types[$code]) ? $array_types[$code] : '';
|
||||||
|
|
||||||
|
// Translation newvalue
|
||||||
|
if (preg_match('/^\((.*)\)$/i', $newvalue, $reg)) {
|
||||||
|
$newvalue = $outputlangs->transnoentities($reg[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean data and add encloser if required (depending on value of USE_STRICT_CSV_RULES)
|
||||||
|
$newvalue = $this->csvClean($newvalue, $outputlangs->charset_output);
|
||||||
|
|
||||||
|
if (preg_match('/^Select:/i', $typefield) && $typefield = substr($typefield, 7)) {
|
||||||
|
$array = jsonOrUnserialize($typefield);
|
||||||
|
if (is_array($array) && !empty($newvalue)) {
|
||||||
|
$array = $array['options'];
|
||||||
|
$selectlabelvalues[$code."_label"] = $array[$newvalue];
|
||||||
|
} else {
|
||||||
|
$selectlabelvalues[$code."_label"] = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($this->handle, $newvalue.$this->separator);
|
||||||
|
$this->col++;
|
||||||
|
}
|
||||||
|
foreach ($selectlabelvalues as $key => $value) {
|
||||||
|
fwrite($this->handle, $value.$this->separator);
|
||||||
|
$this->col++;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($this->handle, "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||||
|
/**
|
||||||
|
* Output footer into file
|
||||||
|
*
|
||||||
|
* @param Translate $outputlangs Output language object
|
||||||
|
* @return int <0 if KO, >0 if OK
|
||||||
|
*/
|
||||||
|
public function write_footer($outputlangs)
|
||||||
|
{
|
||||||
|
// phpcs:enable
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||||
|
/**
|
||||||
|
* Close file handle
|
||||||
|
*
|
||||||
|
* @return int <0 if KO, >0 if OK
|
||||||
|
*/
|
||||||
|
public function close_file()
|
||||||
|
{
|
||||||
|
// phpcs:enable
|
||||||
|
fclose($this->handle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean a cell to respect rules of CSV file cells
|
||||||
|
* Note: It uses $this->separator
|
||||||
|
* Note: We keep this function public to be able to test
|
||||||
|
*
|
||||||
|
* @param string $newvalue String to clean
|
||||||
|
* @param string $charset Input AND Output character set
|
||||||
|
* @return string Value cleaned
|
||||||
|
*/
|
||||||
|
public function csvClean($newvalue, $charset)
|
||||||
|
{
|
||||||
|
global $conf;
|
||||||
|
$addquote = 0;
|
||||||
|
|
||||||
|
// Rule Dolibarr: No HTML
|
||||||
|
//print $charset.' '.$newvalue."\n";
|
||||||
|
//$newvalue=dol_string_nohtmltag($newvalue,0,$charset);
|
||||||
|
$newvalue = dol_htmlcleanlastbr($newvalue);
|
||||||
|
//print $charset.' '.$newvalue."\n";
|
||||||
|
|
||||||
|
// Rule 1 CSV: No CR, LF in cells (except if USE_STRICT_CSV_RULES is 1, we can keep record as it is but we must add quotes)
|
||||||
|
$oldvalue = $newvalue;
|
||||||
|
$newvalue = str_replace("\r", '', $newvalue);
|
||||||
|
$newvalue = str_replace("\n", '\n', $newvalue);
|
||||||
|
if (!empty($conf->global->USE_STRICT_CSV_RULES) && $oldvalue != $newvalue) {
|
||||||
|
// If we must use enclusure on text with CR/LF)
|
||||||
|
if ($conf->global->USE_STRICT_CSV_RULES == 1) {
|
||||||
|
// If we use strict CSV rules (original value must remain but we add quote)
|
||||||
|
$newvalue = $oldvalue;
|
||||||
|
}
|
||||||
|
$addquote = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rule 2 CSV: If value contains ", we must escape with ", and add "
|
||||||
|
if (preg_match('/"/', $newvalue)) {
|
||||||
|
$addquote = 1;
|
||||||
|
$newvalue = str_replace('"', '""', $newvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rule 3 CSV: If value contains separator, we must add "
|
||||||
|
if (preg_match('/'.$this->separator.'/', $newvalue)) {
|
||||||
|
$addquote = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($addquote ? '"' : '').$newvalue.($addquote ? '"' : '');
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user