PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/commande/core/modules/commande/doc/doc_generic_order_odt.modules.php

https://bitbucket.org/speedealing/speedealing
PHP | 507 lines | 354 code | 55 blank | 98 comment | 34 complexity | aed27ef11d723a02777d2e18a314032a MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0, MIT
  1. <?php
  2. /* Copyright (C) 2010-2012 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2012 Juanjo Menent <jmenent@2byte.es>
  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 <http://www.gnu.org/licenses/>.
  17. * or see http://www.gnu.org/
  18. */
  19. /**
  20. * \file htdocs/core/modules/commande/doc/doc_generic_order_odt.modules.php
  21. * \ingroup commande
  22. * \brief File of class to build ODT documents for third parties
  23. */
  24. require_once DOL_DOCUMENT_ROOT.'/commande/core/modules/commande/modules_commande.php';
  25. require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
  26. require_once DOL_DOCUMENT_ROOT.'/societe/lib/societe.lib.php';
  27. require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
  28. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  29. require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php';
  30. /**
  31. * Class to build documents using ODF templates generator
  32. */
  33. class doc_generic_order_odt extends ModelePDFCommandes
  34. {
  35. var $emetteur; // Objet societe qui emet
  36. var $phpmin = array(5,2,0); // Minimum version of PHP required by module
  37. var $version = 'dolibarr';
  38. /**
  39. * Constructor
  40. *
  41. * @param DoliDB $db Database handler
  42. */
  43. function __construct($db = '')
  44. {
  45. global $conf,$langs,$mysoc;
  46. $langs->load("main");
  47. $langs->load("companies");
  48. $this->db = $db;
  49. $this->name = "ODT templates";
  50. $this->description = $langs->trans("DocumentModelOdt");
  51. $this->scandir = 'COMMANDE_ADDON_PDF_ODT_PATH'; // Name of constant that is used to save list of directories to scan
  52. // Dimension page pour format A4
  53. $this->type = 'odt';
  54. $this->page_largeur = 0;
  55. $this->page_hauteur = 0;
  56. $this->format = array($this->page_largeur,$this->page_hauteur);
  57. $this->marge_gauche=0;
  58. $this->marge_droite=0;
  59. $this->marge_haute=0;
  60. $this->marge_basse=0;
  61. $this->option_logo = 1; // Affiche logo
  62. $this->option_tva = 0; // Gere option tva COMMANDE_TVAOPTION
  63. $this->option_modereg = 0; // Affiche mode reglement
  64. $this->option_condreg = 0; // Affiche conditions reglement
  65. $this->option_codeproduitservice = 0; // Affiche code produit-service
  66. $this->option_multilang = 0; // Dispo en plusieurs langues
  67. $this->option_escompte = 0; // Affiche si il y a eu escompte
  68. $this->option_credit_note = 0; // Support credit notes
  69. $this->option_freetext = 1; // Support add of a personalised text
  70. $this->option_draft_watermark = 0; // Support add of a watermark on drafts
  71. // Recupere emetteur
  72. $this->emetteur=$mysoc;
  73. if (! $this->emetteur->pays_code) $this->emetteur->pays_code=substr($langs->defaultlang,-2); // Par defaut, si n'etait pas defini
  74. }
  75. /**
  76. * Define array with couple substitution key => substitution value
  77. *
  78. * @param Object $object Main object to use as data source
  79. * @param Translate $outputlangs Lang object to use for output
  80. * @return array Array of substitution
  81. */
  82. function get_substitutionarray_object($object,$outputlangs)
  83. {
  84. global $conf;
  85. return array(
  86. 'object_id'=>$object->id,
  87. 'object_ref'=>$object->ref,
  88. 'object_ref_ext'=>$object->ref_ext,
  89. 'object_ref_customer'=>$object->ref_client,
  90. 'object_date'=>dol_print_date($object->date,'day'),
  91. 'object_date_delivery'=>dol_print_date($object->date_livraison,'dayhour'),
  92. 'object_date_creation'=>dol_print_date($object->date_creation,'day'),
  93. 'object_date_modification'=>dol_print_date($object->date_modification,'day'),
  94. 'object_date_validation'=>dol_print_date($object->date_validation,'dayhour'),
  95. 'object_date_close'=>dol_print_date($object->date_cloture,'dayhour'),
  96. 'object_payment_mode_code'=>$object->mode_reglement_code,
  97. 'object_payment_mode'=>($outputlangs->transnoentitiesnoconv('PaymentType'.$object->mode_reglement_code)!='PaymentType'.$object->mode_reglement_code?$outputlangs->transnoentitiesnoconv('PaymentType'.$object->mode_reglement_code):$object->mode_reglement),
  98. 'object_payment_term_code'=>$object->cond_reglement_code,
  99. 'object_payment_term'=>($outputlangs->transnoentitiesnoconv('PaymentCondition'.$object->cond_reglement_code)!='PaymentCondition'.$object->cond_reglement_code?$outputlangs->transnoentitiesnoconv('PaymentCondition'.$object->cond_reglement_code):$object->cond_reglement),
  100. 'object_total_ht'=>price($object->total_ht,0,$outputlangs),
  101. 'object_total_vat'=>price($object->total_tva,0,$outputlangs),
  102. 'object_total_ttc'=>price($object->total_ttc,0,$outputlangs),
  103. 'object_total_discount' => price($object->getTotalDiscount(), 0, $outputlangs),
  104. 'object_vatrate'=>vatrate($object->tva),
  105. 'object_note_private'=>$object->note,
  106. 'object_note'=>$object->note_public,
  107. );
  108. }
  109. /**
  110. * Define array with couple substitution key => substitution value
  111. *
  112. * @param array $line Array of lines
  113. * @param Translate $outputlangs Lang object to use for output
  114. * @return array Return a substitution array
  115. */
  116. function get_substitutionarray_lines($line,$outputlangs)
  117. {
  118. global $conf;
  119. return array(
  120. 'line_fulldesc'=>doc_getlinedesc($line,$outputlangs),
  121. 'line_product_ref'=>$line->product_ref,
  122. 'line_product_label'=>$line->product_label,
  123. 'line_desc'=>$line->desc,
  124. 'line_vatrate'=>vatrate($line->tva_tx,true,$line->info_bits),
  125. 'line_up'=>price($line->subprice, 0, $outputlangs),
  126. 'line_qty'=>$line->qty,
  127. 'line_discount_percent'=>($line->remise_percent?$line->remise_percent.'%':''),
  128. 'line_price_ht'=>price($line->total_ht, 0, $outputlangs),
  129. 'line_price_ttc'=>price($line->total_ttc, 0, $outputlangs),
  130. 'line_price_vat'=>price($line->total_tva, 0, $outputlangs),
  131. 'line_date_start'=>$line->date_start,
  132. 'line_date_end'=>$line->date_end
  133. );
  134. }
  135. /**
  136. * Return description of a module
  137. *
  138. * @param Translate $langs Lang object to use for output
  139. * @return string Description
  140. */
  141. function info($langs)
  142. {
  143. global $conf,$langs;
  144. $langs->load("companies");
  145. $langs->load("errors");
  146. $form = new Form($this->db);
  147. $texte = $this->description.".<br>\n";
  148. $texte.= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
  149. $texte.= '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  150. $texte.= '<input type="hidden" name="action" value="setModuleOptions">';
  151. $texte.= '<input type="hidden" name="param1" value="COMMANDE_ADDON_PDF_ODT_PATH">';
  152. $texte.= '<table class="nobordernopadding" width="100%">';
  153. // List of directories area
  154. $texte.= '<tr><td>';
  155. $texttitle=$langs->trans("ListOfDirectories");
  156. $listofdir=explode(',',preg_replace('/[\r\n]+/',',',trim($conf->global->COMMANDE_ADDON_PDF_ODT_PATH)));
  157. $listoffiles=array();
  158. foreach($listofdir as $key=>$tmpdir)
  159. {
  160. $tmpdir=trim($tmpdir);
  161. $tmpdir=preg_replace('/DOL_DATA_ROOT/',DOL_DATA_ROOT,$tmpdir);
  162. if (! $tmpdir) { unset($listofdir[$key]); continue; }
  163. if (! is_dir($tmpdir)) $texttitle.=img_warning($langs->trans("ErrorDirNotFound",$tmpdir),0);
  164. else
  165. {
  166. $tmpfiles=dol_dir_list($tmpdir,'files',0,'\.odt');
  167. if (count($tmpfiles)) $listoffiles=array_merge($listoffiles,$tmpfiles);
  168. }
  169. }
  170. $texthelp=$langs->trans("ListOfDirectoriesForModelGenODT");
  171. // Add list of substitution keys
  172. $texthelp.='<br>'.$langs->trans("FollowingSubstitutionKeysCanBeUsed").'<br>';
  173. $texthelp.=$langs->transnoentitiesnoconv("FullListOnOnlineDocumentation"); // This contains an url, we don't modify it
  174. $texte.= $form->textwithpicto($texttitle,$texthelp,1,'help','',1);
  175. $texte.= '<table><tr><td>';
  176. $texte.= '<textarea class="flat" cols="60" name="value1">';
  177. $texte.=$conf->global->COMMANDE_ADDON_PDF_ODT_PATH;
  178. $texte.= '</textarea>';
  179. $texte.= '</td>';
  180. $texte.= '<td align="center">&nbsp; ';
  181. $texte.= '<input type="submit" class="button" value="'.$langs->trans("Modify").'" name="Button">';
  182. $texte.= '</td>';
  183. $texte.= '</tr>';
  184. $texte.= '</table>';
  185. // Scan directories
  186. if (count($listofdir)) $texte.=$langs->trans("NumberOfModelFilesFound").': <b>'.count($listoffiles).'</b>';
  187. $texte.= '</td>';
  188. $texte.= '<td valign="top" rowspan="2">';
  189. $texte.= $langs->trans("ExampleOfDirectoriesForModelGen");
  190. $texte.= '</td>';
  191. $texte.= '</tr>';
  192. /*$texte.= '<tr>';
  193. $texte.= '<td align="center">';
  194. $texte.= '<input type="submit" class="button" value="'.$langs->trans("Modify").'" name="Button">';
  195. $texte.= '</td>';
  196. $texte.= '</tr>';*/
  197. $texte.= '</table>';
  198. $texte.= '</form>';
  199. return $texte;
  200. }
  201. /**
  202. * Function to build a document on disk using the generic odt module.
  203. *
  204. * @param Commande $object Object source to build document
  205. * @param Translate $outputlangs Lang output object
  206. * @param string $srctemplatepath Full path of source filename for generator using a template file
  207. * @return int 1 if OK, <=0 if KO
  208. */
  209. function write_file($object,$outputlangs,$srctemplatepath)
  210. {
  211. global $user,$langs,$conf,$mysoc;
  212. if (empty($srctemplatepath))
  213. {
  214. dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING);
  215. return -1;
  216. }
  217. if (! is_object($outputlangs)) $outputlangs=$langs;
  218. $sav_charset_output=$outputlangs->charset_output;
  219. $outputlangs->charset_output='UTF-8';
  220. $outputlangs->load("main");
  221. $outputlangs->load("dict");
  222. $outputlangs->load("companies");
  223. $outputlangs->load("bills");
  224. if ($conf->commande->dir_output)
  225. {
  226. // If $object is id instead of object
  227. if (! is_object($object))
  228. {
  229. $id = $object;
  230. $object = new Commande($this->db);
  231. $result=$object->fetch($id);
  232. if ($result < 0)
  233. {
  234. dol_print_error($this->db,$object->error);
  235. return -1;
  236. }
  237. }
  238. $dir = $conf->commande->dir_output;
  239. $objectref = dol_sanitizeFileName($object->ref);
  240. if (! preg_match('/specimen/i',$objectref)) $dir.= "/" . $objectref;
  241. $file = $dir . "/" . $objectref . ".odt";
  242. if (! file_exists($dir))
  243. {
  244. if (dol_mkdir($dir) < 0)
  245. {
  246. $this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir);
  247. return -1;
  248. }
  249. }
  250. if (file_exists($dir))
  251. {
  252. //print "srctemplatepath=".$srctemplatepath; // Src filename
  253. $newfile=basename($srctemplatepath);
  254. $newfiletmp=preg_replace('/\.odt/i','',$newfile);
  255. $newfiletmp=preg_replace('/template_/i','',$newfiletmp);
  256. $newfiletmp=preg_replace('/modele_/i','',$newfiletmp);
  257. $newfiletmp=$objectref.'_'.$newfiletmp;
  258. //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt';
  259. $file=$dir.'/'.$newfiletmp.'.odt';
  260. //print "newdir=".$dir;
  261. //print "newfile=".$newfile;
  262. //print "file=".$file;
  263. //print "conf->societe->dir_temp=".$conf->societe->dir_temp;
  264. dol_mkdir($conf->commande->dir_temp);
  265. // If BILLING contact defined on invoice, we use it
  266. $usecontact=false;
  267. $arrayidcontact=$object->getIdContact('external','BILLING');
  268. if (count($arrayidcontact) > 0)
  269. {
  270. $usecontact=true;
  271. $result=$object->fetch_contact($arrayidcontact[0]);
  272. }
  273. // Recipient name
  274. if (! empty($usecontact))
  275. {
  276. // On peut utiliser le nom de la societe du contact
  277. if (! empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)) $socobject = $object->contact;
  278. else $socobject = $object->client;
  279. }
  280. else
  281. {
  282. $socobject=$object->client;
  283. }
  284. // Make substitution
  285. $substitutionarray=array(
  286. '__FROM_NAME__' => $this->emetteur->nom,
  287. '__FROM_EMAIL__' => $this->emetteur->email,
  288. '__TOTAL_TTC__' => $object->total_ttc,
  289. '__TOTAL_HT__' => $object->total_ht,
  290. '__TOTAL_VAT__' => $object->total_vat
  291. );
  292. complete_substitutions_array($substitutionarray, $langs, $object);
  293. // Line of free text
  294. $newfreetext='';
  295. $paramfreetext='COMMANDE_FREE_TEXT';
  296. if (! empty($conf->global->$paramfreetext))
  297. {
  298. $newfreetext=make_substitutions($conf->global->$paramfreetext,$substitutionarray);
  299. }
  300. // Open and load template
  301. require_once ODTPHP_PATH.'odf.php';
  302. $odfHandler = new odf(
  303. $srctemplatepath,
  304. array(
  305. 'PATH_TO_TMP' => $conf->commande->dir_temp,
  306. 'ZIP_PROXY' => 'PclZipProxy', // PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy.
  307. 'DELIMITER_LEFT' => '{',
  308. 'DELIMITER_RIGHT' => '}'
  309. )
  310. );
  311. // After construction $odfHandler->contentXml contains content and
  312. // [!-- BEGIN row.lines --]*[!-- END row.lines --] has been replaced by
  313. // [!-- BEGIN lines --]*[!-- END lines --]
  314. //print html_entity_decode($odfHandler->__toString());
  315. //print exit;
  316. // Make substitutions into odt of freetext
  317. try {
  318. $odfHandler->setVars('free_text', $newfreetext, true, 'UTF-8');
  319. }
  320. catch(OdfException $e)
  321. {
  322. }
  323. // Make substitutions into odt of user info
  324. $tmparray=$this->get_substitutionarray_user($user,$outputlangs);
  325. //var_dump($tmparray); exit;
  326. foreach($tmparray as $key=>$value)
  327. {
  328. try {
  329. if (preg_match('/logo$/',$key)) // Image
  330. {
  331. //var_dump($value);exit;
  332. if (file_exists($value)) $odfHandler->setImage($key, $value);
  333. else $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
  334. }
  335. else // Text
  336. {
  337. $odfHandler->setVars($key, $value, true, 'UTF-8');
  338. }
  339. }
  340. catch(OdfException $e)
  341. {
  342. }
  343. }
  344. // Make substitutions into odt of mysoc
  345. $tmparray=$this->get_substitutionarray_mysoc($mysoc,$outputlangs);
  346. //var_dump($tmparray); exit;
  347. foreach($tmparray as $key=>$value)
  348. {
  349. try {
  350. if (preg_match('/logo$/',$key)) // Image
  351. {
  352. //var_dump($value);exit;
  353. if (file_exists($value)) $odfHandler->setImage($key, $value);
  354. else $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
  355. }
  356. else // Text
  357. {
  358. $odfHandler->setVars($key, $value, true, 'UTF-8');
  359. }
  360. }
  361. catch(OdfException $e)
  362. {
  363. }
  364. }
  365. // Make substitutions into odt of thirdparty
  366. $tmparray=$this->get_substitutionarray_thirdparty($socobject,$outputlangs);
  367. foreach($tmparray as $key=>$value)
  368. {
  369. try {
  370. if (preg_match('/logo$/',$key)) // Image
  371. {
  372. if (file_exists($value)) $odfHandler->setImage($key, $value);
  373. else $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
  374. }
  375. else // Text
  376. {
  377. $odfHandler->setVars($key, $value, true, 'UTF-8');
  378. }
  379. }
  380. catch(OdfException $e)
  381. {
  382. }
  383. }
  384. // Replace tags of object + external modules
  385. $tmparray=$this->get_substitutionarray_object($object,$outputlangs);
  386. complete_substitutions_array($tmparray, $outputlangs, $object);
  387. foreach($tmparray as $key=>$value)
  388. {
  389. try {
  390. if (preg_match('/logo$/',$key)) // Image
  391. {
  392. if (file_exists($value)) $odfHandler->setImage($key, $value);
  393. else $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
  394. }
  395. else // Text
  396. {
  397. $odfHandler->setVars($key, $value, true, 'UTF-8');
  398. }
  399. }
  400. catch(OdfException $e)
  401. {
  402. }
  403. }
  404. // Replace tags of lines
  405. try
  406. {
  407. $listlines = $odfHandler->setSegment('lines');
  408. foreach ($object->lines as $line)
  409. {
  410. $tmparray=$this->get_substitutionarray_lines($line,$outputlangs);
  411. complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines");
  412. foreach($tmparray as $key => $val)
  413. {
  414. try
  415. {
  416. $listlines->setVars($key, $val, true, 'UTF-8');
  417. }
  418. catch(OdfException $e)
  419. {
  420. }
  421. catch(SegmentException $e)
  422. {
  423. }
  424. }
  425. $listlines->merge();
  426. }
  427. $odfHandler->mergeSegment($listlines);
  428. }
  429. catch(OdfException $e)
  430. {
  431. $this->error=$e->getMessage();
  432. dol_syslog($this->error, LOG_WARNING);
  433. return -1;
  434. }
  435. // Write new file
  436. //$result=$odfHandler->exportAsAttachedFile('toto');
  437. $odfHandler->saveToDisk($file);
  438. if (! empty($conf->global->MAIN_UMASK))
  439. @chmod($file, octdec($conf->global->MAIN_UMASK));
  440. $odfHandler=null; // Destroy object
  441. return 1; // Success
  442. }
  443. else
  444. {
  445. $this->error=$langs->transnoentities("ErrorCanNotCreateDir",$dir);
  446. return -1;
  447. }
  448. }
  449. return -1;
  450. }
  451. }
  452. ?>