ExportTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. <?php
  2. /* Copyright (C) 2010 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2023 Alexandre Janniaux <alexandre.janniaux@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. * or see https://www.gnu.org/
  18. */
  19. /**
  20. * \file test/phpunit/ExportTest.php
  21. * \ingroup test
  22. * \brief PHPUnit test
  23. * \remarks To run this script as CLI: phpunit filename.php
  24. */
  25. global $conf,$user,$langs,$db;
  26. //define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver
  27. //require_once 'PHPUnit/Autoload.php';
  28. require_once dirname(__FILE__).'/../../htdocs/master.inc.php';
  29. require_once dirname(__FILE__).'/../../htdocs/exports/class/export.class.php';
  30. require_once dirname(__FILE__).'/../../htdocs/core/lib/files.lib.php';
  31. if (! defined('NOREQUIREUSER')) {
  32. define('NOREQUIREUSER', '1');
  33. }
  34. if (! defined('NOREQUIREDB')) {
  35. define('NOREQUIREDB', '1');
  36. }
  37. if (! defined('NOREQUIRESOC')) {
  38. define('NOREQUIRESOC', '1');
  39. }
  40. if (! defined('NOREQUIRETRAN')) {
  41. define('NOREQUIRETRAN', '1');
  42. }
  43. if (! defined('NOCSRFCHECK')) {
  44. define('NOCSRFCHECK', '1');
  45. }
  46. if (! defined('NOTOKENRENEWAL')) {
  47. define('NOTOKENRENEWAL', '1');
  48. }
  49. if (! defined('NOREQUIREMENU')) {
  50. define('NOREQUIREMENU', '1'); // If there is no menu to show
  51. }
  52. if (! defined('NOREQUIREHTML')) {
  53. define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php
  54. }
  55. if (! defined('NOREQUIREAJAX')) {
  56. define('NOREQUIREAJAX', '1');
  57. }
  58. if (! defined("NOLOGIN")) {
  59. define("NOLOGIN", '1'); // If this page is public (can be called outside logged session)
  60. }
  61. /**
  62. * Class for PHPUnit tests
  63. *
  64. * @backupGlobals disabled
  65. * @backupStaticAttributes enabled
  66. * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased.
  67. */
  68. class ExportTest extends PHPUnit\Framework\TestCase
  69. {
  70. protected $savconf;
  71. protected $savuser;
  72. protected $savlangs;
  73. protected $savdb;
  74. /**
  75. * Constructor
  76. * We save global variables into local variables
  77. *
  78. * @param string $name Name
  79. * @return ExportTest
  80. */
  81. public function __construct($name = '')
  82. {
  83. parent::__construct($name);
  84. //$this->sharedFixture
  85. global $conf,$user,$langs,$db;
  86. $this->savconf=$conf;
  87. $this->savuser=$user;
  88. $this->savlangs=$langs;
  89. $this->savdb=$db;
  90. print __METHOD__." db->type=".$db->type." user->id=".$user->id;
  91. //print " - db ".$db->db;
  92. print "\n";
  93. }
  94. /**
  95. * setUpBeforeClass
  96. *
  97. * @return void
  98. */
  99. public static function setUpBeforeClass(): void
  100. {
  101. global $conf,$user,$langs,$db;
  102. //$db->begin(); // This is to have all actions inside a transaction even if test launched without suite.
  103. print __METHOD__."\n";
  104. }
  105. /**
  106. * tearDownAfterClass
  107. *
  108. * @return void
  109. */
  110. public static function tearDownAfterClass(): void
  111. {
  112. global $conf,$user,$langs,$db;
  113. //$db->rollback();
  114. print __METHOD__."\n";
  115. }
  116. /**
  117. * Init phpunit tests
  118. *
  119. * @return void
  120. */
  121. protected function setUp(): void
  122. {
  123. global $conf,$user,$langs,$db;
  124. $conf=$this->savconf;
  125. $user=$this->savuser;
  126. $langs=$this->savlangs;
  127. $db=$this->savdb;
  128. print __METHOD__."\n";
  129. }
  130. /**
  131. * End phpunit tests
  132. *
  133. * @return void
  134. */
  135. protected function tearDown(): void
  136. {
  137. print __METHOD__."\n";
  138. }
  139. /**
  140. * Other tests
  141. *
  142. * @return void
  143. */
  144. public function testExportCsvUtf()
  145. {
  146. global $conf,$user,$langs,$db;
  147. $model='csvutf8';
  148. $conf->global->EXPORT_CSV_SEPARATOR_TO_USE = ',';
  149. print 'EXPORT_CSV_SEPARATOR_TO_USE = '.$conf->global->EXPORT_CSV_SEPARATOR_TO_USE;
  150. // Creation of class to export using model ExportXXX
  151. $dir = DOL_DOCUMENT_ROOT . "/core/modules/export/";
  152. $file = "export_".$model.".modules.php";
  153. $classname = "Export".$model;
  154. require_once $dir.$file;
  155. $objmodel = new $classname($db);
  156. // First test without option USE_STRICT_CSV_RULES
  157. unset($conf->global->USE_STRICT_CSV_RULES);
  158. $valtotest='A simple string';
  159. print __METHOD__." valtotest=".$valtotest."\n";
  160. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  161. print __METHOD__." result=".$result."\n";
  162. $this->assertEquals($result, 'A simple string');
  163. $valtotest='A string with , and ; inside';
  164. print __METHOD__." valtotest=".$valtotest."\n";
  165. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  166. print __METHOD__." result=".$result."\n";
  167. $this->assertEquals($result, '"A string with , and ; inside"', 'Error in csvClean for '.$file);
  168. $valtotest='A string with " inside';
  169. print __METHOD__." valtotest=".$valtotest."\n";
  170. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  171. print __METHOD__." result=".$result."\n";
  172. $this->assertEquals($result, '"A string with "" inside"');
  173. $valtotest='A string with " inside and '."\r\n".' carriage returns';
  174. print __METHOD__." valtotest=".$valtotest."\n";
  175. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  176. print __METHOD__." result=".$result."\n";
  177. $this->assertEquals($result, '"A string with "" inside and \n carriage returns"');
  178. $valtotest='A string with <a href="aaa"><strong>html<br>content</strong></a> inside<br>'."\n";
  179. print __METHOD__." valtotest=".$valtotest."\n";
  180. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  181. print __METHOD__." result=".$result."\n";
  182. $this->assertEquals($result, '"A string with <a href=""aaa""><strong>html<br>content</strong></a> inside"');
  183. // Same tests with strict mode
  184. $conf->global->USE_STRICT_CSV_RULES = 1;
  185. $valtotest='A simple string';
  186. print __METHOD__." valtotest=".$valtotest."\n";
  187. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  188. print __METHOD__." result=".$result."\n";
  189. $this->assertEquals($result, 'A simple string');
  190. $valtotest='A string with , and ; inside';
  191. print __METHOD__." valtotest=".$valtotest."\n";
  192. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  193. print __METHOD__." result=".$result."\n";
  194. $this->assertEquals($result, '"A string with , and ; inside"');
  195. $valtotest='A string with " inside';
  196. print __METHOD__." valtotest=".$valtotest."\n";
  197. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  198. print __METHOD__." result=".$result."\n";
  199. $this->assertEquals($result, '"A string with "" inside"');
  200. $valtotest='A string with " inside and '."\r\n".' carriage returns';
  201. print __METHOD__." valtotest=".$valtotest."\n";
  202. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  203. print __METHOD__." result=".$result."\n";
  204. $this->assertEquals($result, "\"A string with \"\" inside and \r\n carriage returns\"");
  205. $valtotest='A string with <a href="aaa"><strong>html<br>content</strong></a> inside<br>'."\n";
  206. print __METHOD__." valtotest=".$valtotest."\n";
  207. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  208. print __METHOD__." result=".$result."\n";
  209. $this->assertEquals($result, '"A string with <a href=""aaa""><strong>html<br>content</strong></a> inside"');
  210. }
  211. /**
  212. * Other tests
  213. *
  214. * @return void
  215. */
  216. public function testExportOther()
  217. {
  218. global $conf,$user,$langs,$db;
  219. $model='csviso';
  220. $conf->global->EXPORT_CSV_SEPARATOR_TO_USE = ',';
  221. print 'EXPORT_CSV_SEPARATOR_TO_USE = '.$conf->global->EXPORT_CSV_SEPARATOR_TO_USE;
  222. // Creation of class to export using model ExportXXX
  223. $dir = DOL_DOCUMENT_ROOT . "/core/modules/export/";
  224. $file = "export_".$model.".modules.php";
  225. $classname = "Export".$model;
  226. require_once $dir.$file;
  227. $objmodel = new $classname($db);
  228. // First test without option USE_STRICT_CSV_RULES
  229. unset($conf->global->USE_STRICT_CSV_RULES);
  230. $valtotest='A simple string';
  231. print __METHOD__." valtotest=".$valtotest."\n";
  232. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  233. print __METHOD__." result=".$result."\n";
  234. $this->assertEquals($result, 'A simple string');
  235. $valtotest='A string with , and ; inside';
  236. print __METHOD__." valtotest=".$valtotest."\n";
  237. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  238. print __METHOD__." result=".$result."\n";
  239. $this->assertEquals($result, '"A string with , and ; inside"', 'Error in csvClean for '.$file);
  240. $valtotest='A string with " inside';
  241. print __METHOD__." valtotest=".$valtotest."\n";
  242. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  243. print __METHOD__." result=".$result."\n";
  244. $this->assertEquals($result, '"A string with "" inside"');
  245. $valtotest='A string with " inside and '."\r\n".' carriage returns';
  246. print __METHOD__." valtotest=".$valtotest."\n";
  247. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  248. print __METHOD__." result=".$result."\n";
  249. $this->assertEquals($result, '"A string with "" inside and \n carriage returns"');
  250. $valtotest='A string with <a href="aaa"><strong>html<br>content</strong></a> inside<br>'."\n";
  251. print __METHOD__." valtotest=".$valtotest."\n";
  252. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  253. print __METHOD__." result=".$result."\n";
  254. $this->assertEquals($result, '"A string with <a href=""aaa""><strong>html<br>content</strong></a> inside"');
  255. // Same tests with strict mode
  256. $conf->global->USE_STRICT_CSV_RULES = 1;
  257. $valtotest='A simple string';
  258. print __METHOD__." valtotest=".$valtotest."\n";
  259. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  260. print __METHOD__." result=".$result."\n";
  261. $this->assertEquals($result, 'A simple string');
  262. $valtotest='A string with , and ; inside';
  263. print __METHOD__." valtotest=".$valtotest."\n";
  264. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  265. print __METHOD__." result=".$result."\n";
  266. $this->assertEquals($result, '"A string with , and ; inside"');
  267. $valtotest='A string with " inside';
  268. print __METHOD__." valtotest=".$valtotest."\n";
  269. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  270. print __METHOD__." result=".$result."\n";
  271. $this->assertEquals($result, '"A string with "" inside"');
  272. $valtotest='A string with " inside and '."\r\n".' carriage returns';
  273. print __METHOD__." valtotest=".$valtotest."\n";
  274. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  275. print __METHOD__." result=".$result."\n";
  276. $this->assertEquals($result, "\"A string with \"\" inside and \r\n carriage returns\"");
  277. $valtotest='A string with <a href="aaa"><strong>html<br>content</strong></a> inside<br>'."\n";
  278. print __METHOD__." valtotest=".$valtotest."\n";
  279. $result = $objmodel->csvClean($valtotest, $langs->charset_output);
  280. print __METHOD__." result=".$result."\n";
  281. $this->assertEquals($result, '"A string with <a href=""aaa""><strong>html<br>content</strong></a> inside"');
  282. }
  283. /**
  284. * Test export function for a personalized dataset
  285. *
  286. * @depends testExportOther
  287. * @return void
  288. */
  289. public function testExportPersonalizedExport()
  290. {
  291. global $conf,$user,$langs,$db;
  292. $sql = "SELECT f.ref as f_ref, f.total_ht as f_total, f.total_tva as f_tva FROM ".MAIN_DB_PREFIX."facture f";
  293. $objexport=new Export($db);
  294. //$objexport->load_arrays($user,$datatoexport);
  295. // Define properties
  296. $datatoexport='test';
  297. $array_selected = array("f.ref"=>1, "f.total"=>2, "f.tva"=>3);
  298. $array_export_fields = array("f.ref"=>"FacNumber", "f.total"=>"FacTotal", "f.tva"=>"FacVat");
  299. $array_alias = array("f_ref"=>"ref", "f_total"=>"total", "f_tva"=>"tva");
  300. $objexport->array_export_fields[0]=$array_export_fields;
  301. $objexport->array_export_alias[0]=$array_alias;
  302. dol_mkdir($conf->export->dir_temp);
  303. $model='csviso';
  304. // Build export file
  305. print "Process build_file for model = ".$model."\n";
  306. $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), $sql);
  307. $expectedresult = 1;
  308. $this->assertEquals($expectedresult, $result, 'Error in CSV export');
  309. $model='csvutf8';
  310. // Build export file
  311. print "Process build_file for model = ".$model."\n";
  312. $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), $sql);
  313. $expectedresult = 1;
  314. $this->assertEquals($expectedresult, $result, 'Error in CSV export');
  315. $model='tsv';
  316. // Build export file
  317. print "Process build_file for model = ".$model."\n";
  318. $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), $sql);
  319. $expectedresult=1;
  320. $this->assertEquals($expectedresult, $result, 'Error in TSV export');
  321. $model='excel2007';
  322. // Build export file
  323. /* ko on php 7.4 on travis (zip not available) */
  324. print "Process build_file for model = ".$model."\n";
  325. $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), $sql);
  326. $expectedresult=1;
  327. $this->assertEquals($expectedresult, $result, 'Error in Excel2007 export');
  328. return true;
  329. }
  330. /**
  331. * Test export function for a personalized dataset with filters
  332. *
  333. * @depends testExportPersonalizedExport
  334. * @return void
  335. */
  336. public function testExportPersonalizedWithFilter()
  337. {
  338. global $conf,$user,$langs,$db;
  339. /*
  340. $sql = "SELECT f.ref as f_ref, f.total_ht as f_total_ht, f.total_tva as f_total_tva FROM ".MAIN_DB_PREFIX."facture f";
  341. $objexport=new Export($db);
  342. //$objexport->load_arrays($user,$datatoexport);
  343. // Define properties
  344. $datatoexport='test_filtered';
  345. $array_selected = array("f.ref"=>1, "f.total_ht"=>2, "f.total_tva"=>3);
  346. $array_export_fields = array("f.ref"=>"FacNumber", "f.total_ht"=>"FacTotal", "f.total_tva"=>"FacVat");
  347. $array_filtervalue = array("f.total_ht" => ">100");
  348. $array_filtered = array("f.total_ht" => 1);
  349. $array_alias = array("f_ref"=>"ref", "f_total_ht"=>"total_ht", "f_total_tva"=>"total_tva");
  350. $objexport->array_export_fields[0]=$array_export_fields;
  351. $objexport->array_export_alias[0]=$array_alias;
  352. dol_mkdir($conf->export->dir_temp);
  353. $model='csv';
  354. // Build export file
  355. $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, $array_filtervalue, $sql);
  356. $expectedresult=1;
  357. $this->assertEquals($expectedresult,$result);
  358. $model='tsv';
  359. // Build export file
  360. $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, $array_filtervalue, $sql);
  361. $expectedresult=1;
  362. $this->assertEquals($expectedresult,$result);
  363. $model='excel';
  364. // Build export file
  365. $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, $array_filtervalue, $sql);
  366. $expectedresult=1;
  367. $this->assertEquals($expectedresult,$result);
  368. */
  369. $this->assertEquals(true, true);
  370. return true;
  371. }
  372. /**
  373. * Test export function for all dataset predefined into modules
  374. *
  375. * @depends testExportPersonalizedWithFilter
  376. * @return void
  377. */
  378. public function testExportModulesDatasets()
  379. {
  380. global $conf,$user,$langs,$db;
  381. $model='csviso';
  382. $filterdatatoexport='';
  383. //$filterdatatoexport='';
  384. //$array_selected = array("s.rowid"=>1, "s.nom"=>2); // Mut be fields found into declaration of dataset
  385. // Load properties of arrays to make export
  386. $objexport=new Export($db);
  387. $result=$objexport->load_arrays($user, $filterdatatoexport); // This load ->array_export_xxx properties for datatoexport
  388. // Loop on each dataset
  389. foreach ($objexport->array_export_code as $key => $datatoexport) {
  390. $exportfile=$conf->export->dir_temp.'/'.$user->id.'/export_'.$datatoexport.'.csv';
  391. print "Process export for dataset ".$datatoexport." into ".$exportfile."\n";
  392. dol_delete_file($exportfile);
  393. // Generate $array_selected
  394. $i=0;
  395. $array_selected=array();
  396. foreach ($objexport->array_export_fields[$key] as $key => $val) {
  397. $array_selected[$key]=$i++;
  398. }
  399. //var_dump($array_selected);
  400. // Build export file
  401. $sql = "";
  402. $result=$objexport->build_file($user, $model, $datatoexport, $array_selected, array(), $sql);
  403. $expectedresult = 1;
  404. $this->assertEquals($expectedresult, $result, "Call build_file() to export ".$exportfile.' failed: '.$objexport->error);
  405. $result=dol_is_file($exportfile);
  406. $this->assertTrue($result, 'File '.$exportfile.' not found');
  407. }
  408. return true;
  409. }
  410. }