diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index 85a6ac347e8..7d7697bd91f 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -4267,7 +4267,7 @@ function picto_required()
* Clean a string from all HTML tags and entities
*
* @param string $StringHtml String to clean
- * @param integer $removelinefeed Replace also all lines feeds by a space, otherwise only last one are removed
+ * @param integer $removelinefeed 1=Replace also all lines feeds by a space, 0=Only last one are removed
* @param string $pagecodeto Encoding of input/output string
* @return string String cleaned
*
diff --git a/htdocs/core/modules/export/export_csv.modules.php b/htdocs/core/modules/export/export_csv.modules.php
index 58891ddd2c9..8d35ff63225 100644
--- a/htdocs/core/modules/export/export_csv.modules.php
+++ b/htdocs/core/modules/export/export_csv.modules.php
@@ -206,7 +206,7 @@ class ExportCsv extends ModeleExports
foreach($array_selected_sorted as $code => $value)
{
$newvalue=$outputlangs->transnoentities($array_export_fields_label[$code]); // newvalue is now $outputlangs->charset_output encoded
- $newvalue=$this->csv_clean($newvalue,$outputlangs->charset_output);
+ $newvalue=$this->csvClean($newvalue,$outputlangs->charset_output);
fwrite($this->handle,$newvalue.$this->separator);
}
@@ -250,7 +250,7 @@ class ExportCsv extends ModeleExports
// Translation newvalue
if (preg_match('/^\((.*)\)$/i',$newvalue,$reg)) $newvalue=$outputlangs->transnoentities($reg[1]);
- $newvalue=$this->csv_clean($newvalue,$outputlangs->charset_output);
+ $newvalue=$this->csvClean($newvalue,$outputlangs->charset_output);
if (preg_match('/^Select:/i', $typefield, $reg) && $typefield = substr($typefield, 7))
{
@@ -292,25 +292,28 @@ class ExportCsv extends ModeleExports
/**
* 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
*/
- function csv_clean($newvalue, $charset)
+ public function csvClean($newvalue, $charset)
{
global $conf;
$addquote=0;
// Rule Dolibarr: No HTML
- //print $charset.' '.$newvalue."\n";
- $newvalue=dol_string_nohtmltag($newvalue,1,$charset);
- //print $charset.' '.$newvalue."\n";
-
- // Rule 1 CSV: No CR, LF in cells
+ //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 on, we can keep record as it is but we must add quotes)
$oldvalue=$newvalue;
- $newvalue=str_replace("\r",'\r',$newvalue);
+ $newvalue=str_replace("\r",'',$newvalue);
$newvalue=str_replace("\n",'\n',$newvalue);
if (! empty($conf->global->USE_STRICT_CSV_RULES) && $oldvalue != $newvalue)
{
diff --git a/htdocs/exports/class/export.class.php b/htdocs/exports/class/export.class.php
index 496092b7f73..48c34acd128 100644
--- a/htdocs/exports/class/export.class.php
+++ b/htdocs/exports/class/export.class.php
@@ -526,7 +526,7 @@ class Export
return -1;
}
- // Creation de la classe d'export du model ExportXXX
+ // Creation of class to export using model ExportXXX
$dir = DOL_DOCUMENT_ROOT . "/core/modules/export/";
$file = "export_".$model.".modules.php";
$classname = "Export".$model;
diff --git a/test/phpunit/ExportTest.php b/test/phpunit/ExportTest.php
index 7c14b0ccd64..5c81db11958 100644
--- a/test/phpunit/ExportTest.php
+++ b/test/phpunit/ExportTest.php
@@ -120,9 +120,96 @@ class ExportTest extends PHPUnit_Framework_TestCase
}
+ /**
+ * Other tests
+ *
+ * @return void
+ */
+ public function testExportOther()
+ {
+ global $conf,$user,$langs,$db;
+
+ $model='csv';
+
+ // Creation of class to export using model ExportXXX
+ $dir = DOL_DOCUMENT_ROOT . "/core/modules/export/";
+ $file = "export_".$model.".modules.php";
+ $classname = "Export".$model;
+ require_once $dir.$file;
+ $objmodel = new $classname($this->db);
+
+ // First test without option USE_STRICT_CSV_RULES
+ unset($conf->global->USE_STRICT_CSV_RULES);
+
+ $valtotest='A simple string';
+ print __METHOD__." valtotest=".$valtotest."\n";
+ $result = $objmodel->csvClean($valtotest ,$langs->charset_output);
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals($result, 'A simple string');
+
+ $valtotest='A string with , and ; inside';
+ print __METHOD__." valtotest=".$valtotest."\n";
+ $result = $objmodel->csvClean($valtotest ,$langs->charset_output);
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals($result, '"A string with , and ; inside"');
+
+ $valtotest='A string with " inside';
+ print __METHOD__." valtotest=".$valtotest."\n";
+ $result = $objmodel->csvClean($valtotest ,$langs->charset_output);
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals($result, '"A string with "" inside"');
+
+ $valtotest='A string with " inside and '."\r\n".' carriage returns';
+ print __METHOD__." valtotest=".$valtotest."\n";
+ $result = $objmodel->csvClean($valtotest ,$langs->charset_output);
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals($result, '"A string with "" inside and \n carriage returns"');
+
+ $valtotest='A string with html
content inside
'."\n";
+ print __METHOD__." valtotest=".$valtotest."\n";
+ $result = $objmodel->csvClean($valtotest ,$langs->charset_output);
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals($result, '"A string with html
content inside"');
+
+ // Same tests with strict mode
+ $conf->global->USE_STRICT_CSV_RULES=1;
+
+ $valtotest='A simple string';
+ print __METHOD__." valtotest=".$valtotest."\n";
+ $result = $objmodel->csvClean($valtotest ,$langs->charset_output);
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals($result, 'A simple string');
+
+ $valtotest='A string with , and ; inside';
+ print __METHOD__." valtotest=".$valtotest."\n";
+ $result = $objmodel->csvClean($valtotest ,$langs->charset_output);
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals($result, '"A string with , and ; inside"');
+
+ $valtotest='A string with " inside';
+ print __METHOD__." valtotest=".$valtotest."\n";
+ $result = $objmodel->csvClean($valtotest ,$langs->charset_output);
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals($result, '"A string with "" inside"');
+
+ $valtotest='A string with " inside and '."\r\n".' carriage returns';
+ print __METHOD__." valtotest=".$valtotest."\n";
+ $result = $objmodel->csvClean($valtotest ,$langs->charset_output);
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals($result, "\"A string with \"\" inside and \r\n carriage returns\"");
+
+ $valtotest='A string with html
content inside
'."\n";
+ print __METHOD__." valtotest=".$valtotest."\n";
+ $result = $objmodel->csvClean($valtotest ,$langs->charset_output);
+ print __METHOD__." result=".$result."\n";
+ $this->assertEquals($result, '"A string with html
content inside"');
+
+ }
+
/**
* Test export function for a personalized dataset
*
+ * @depends testExportOther
* @return void
*/
public function testExportPersonalizedExport()
@@ -266,4 +353,5 @@ class ExportTest extends PHPUnit_Framework_TestCase
return true;
}
+
}