dolibarr  19.0.0-dev
doc_generic_task_odt.modules.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2010-2012 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2012 Juanjo Menent <jmenent@2byte.es>
4  * Copyright (C) 2013 Florian Henry <florian.henry@ope-concept.pro>
5  * Copyright (C) 2016 Charlie Benke <charlie@patas-monkey.com>
6  * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
7  * Copyright (C) 2023 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  * or see https://www.gnu.org/
22  */
23 
30 require_once DOL_DOCUMENT_ROOT.'/core/modules/project/modules_project.php';
31 require_once DOL_DOCUMENT_ROOT.'/core/modules/project/task/modules_task.php';
32 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
36 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
37 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
38 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
39 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
40 require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php';
41 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
42 if (isModEnabled("propal")) {
43  require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
44 }
45 if (isModEnabled('facture')) {
46  require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
47 }
48 if (isModEnabled('facture')) {
49  require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
50 }
51 if (isModEnabled('commande')) {
52  require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
53 }
54 if (isModEnabled("supplier_invoice")) {
55  require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
56 }
57 if (isModEnabled("supplier_order")) {
58  require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
59 }
60 if (isModEnabled('contrat')) {
61  require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
62 }
63 if (isModEnabled('ficheinter')) {
64  require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
65 }
66 if (isModEnabled('deplacement')) {
67  require_once DOL_DOCUMENT_ROOT.'/compta/deplacement/class/deplacement.class.php';
68 }
69 if (isModEnabled('agenda')) {
70  require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
71 }
72 
73 
78 {
83  public $emetteur;
84 
89  public $version = 'dolibarr';
90 
91 
97  public function __construct($db)
98  {
99  global $conf, $langs, $mysoc;
100 
101  // Load translation files required by the page
102  $langs->loadLangs(array("main", "companies"));
103 
104  $this->db = $db;
105  $this->name = "ODT templates";
106  $this->description = $langs->trans("DocumentModelOdt");
107  $this->scandir = 'PROJECT_TASK_ADDON_PDF_ODT_PATH'; // Name of constant that is used to save list of directories to scan
108 
109  // Page size for A4 format
110  $this->type = 'odt';
111  $this->page_largeur = 0;
112  $this->page_hauteur = 0;
113  $this->format = array($this->page_largeur, $this->page_hauteur);
114  $this->marge_gauche = 0;
115  $this->marge_droite = 0;
116  $this->marge_haute = 0;
117  $this->marge_basse = 0;
118 
119  $this->option_logo = 1; // Display logo
120  $this->option_tva = 0; // Manage the vat option COMMANDE_TVAOPTION
121  $this->option_modereg = 0; // Display payment mode
122  $this->option_condreg = 0; // Display payment terms
123  $this->option_multilang = 0; // Available in several languages
124  $this->option_escompte = 0; // Displays if there has been a discount
125  $this->option_credit_note = 0; // Support credit notes
126  $this->option_freetext = 1; // Support add of a personalised text
127  $this->option_draft_watermark = 0; // Support add of a watermark on drafts
128 
129  // Get source company
130  $this->emetteur = $mysoc;
131  if (!$this->emetteur->country_code) {
132  $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
133  }
134  }
135 
136 
137  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
146  public function get_substitutionarray_object($object, $outputlangs, $array_key = 'object')
147  {
148  // phpcs:enable
149  global $conf, $extrafields;
150 
151  $resarray = array(
152  $array_key.'_id'=>$object->id,
153  $array_key.'_ref'=>$object->ref,
154  $array_key.'_title'=>$object->title,
155  $array_key.'_description'=>$object->description,
156  $array_key.'_date_creation'=>dol_print_date($object->date_c, 'day'),
157  $array_key.'_date_modification'=>dol_print_date($object->date_m, 'day'),
158  $array_key.'_date_start'=>dol_print_date($object->date_start, 'day'),
159  $array_key.'_date_end'=>dol_print_date($object->date_end, 'day'),
160  $array_key.'_note_private'=>$object->note_private,
161  $array_key.'_note_public'=>$object->note_public,
162  $array_key.'_public'=>$object->public,
163  $array_key.'_statut'=>$object->getLibStatut()
164  );
165 
166  // Retrieve extrafields
167  if (is_array($object->array_options) && count($object->array_options)) {
168  $object->fetch_optionals();
169 
170  $resarray = $this->fill_substitutionarray_with_extrafields($object, $resarray, $extrafields, $array_key, $outputlangs);
171  }
172 
173  return $resarray;
174  }
175 
176  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
185  public function get_substitutionarray_tasks($task, $outputlangs, $array_key = 'task')
186  {
187  // phpcs:enable
188  global $conf, $extrafields;
189 
190  $resarray = array(
191  'task_ref'=>$task->ref,
192  'task_fk_project'=>$task->fk_project,
193  'task_projectref'=>$task->projectref,
194  'task_projectlabel'=>$task->projectlabel,
195  'task_label'=>$task->label,
196  'task_description'=>$task->description,
197  'task_fk_parent'=>$task->fk_task_parent,
198  'task_duration'=>$task->duration_effective,
199  'task_duration_formated'=>convertSecondToTime($task->duration_effective, 'allhourmin'),
200  'task_planned_workload'=>$task->planned_workload,
201  'task_planned_workload_formated'=>convertSecondToTime($task->planned_workload, 'allhourmin'),
202  'task_progress'=>$task->progress,
203  'task_public'=>$task->public,
204  'task_date_start'=>dol_print_date($task->date_start, 'day'),
205  'task_date_end'=>dol_print_date($task->date_end, 'day'),
206  'task_note_private'=>$task->note_private,
207  'task_note_public'=>$task->note_public
208  );
209 
210  // Retrieve extrafields
211  if (is_array($task->array_options) && count($task->array_options)) {
212  $task->fetch_optionals();
213 
214  $resarray = $this->fill_substitutionarray_with_extrafields($task, $resarray, $extrafields, $array_key, $outputlangs);
215  }
216 
217  return $resarray;
218  }
219 
220  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
228  public function get_substitutionarray_project_contacts($contact, $outputlangs)
229  {
230  // phpcs:enable
231  global $conf;
232 
233  return array(
234  'projcontacts_id'=>$contact['id'],
235  'projcontacts_rowid'=>$contact['rowid'],
236  'projcontacts_role'=>$contact['libelle'],
237  'projcontacts_lastname'=>$contact['lastname'],
238  'projcontacts_firstname'=>$contact['firstname'],
239  'projcontacts_fullcivname'=>$contact['fullname'],
240  'projcontacts_socname'=>$contact['socname'],
241  'projcontacts_email'=>$contact['email']
242  );
243  }
244 
245  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
253  public function get_substitutionarray_project_file($file, $outputlangs)
254  {
255  // phpcs:enable
256  global $conf;
257 
258  return array(
259  'projfile_name'=>$file['name'],
260  'projfile_date'=>dol_print_date($file['date'], 'day'),
261  'projfile_size'=>$file['size']
262  );
263  }
264 
265  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
273  public function get_substitutionarray_project_reference($refdetail, $outputlangs)
274  {
275  // phpcs:enable
276  global $conf;
277 
278  return array(
279  'projref_type'=>$refdetail['type'],
280  'projref_ref'=>$refdetail['ref'],
281  'projref_date'=>dol_print_date($refdetail['date'], 'day'),
282  'projref_socname'=>$refdetail['socname'],
283  'projref_amountht'=>price($refdetail['amountht'], 0, $outputlangs),
284  'projref_amountttc'=>price($refdetail['amountttc'], 0, $outputlangs),
285  'projref_status'=>$refdetail['status']
286  );
287  }
288 
289  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
297  public function get_substitutionarray_tasksressource($taskressource, $outputlangs)
298  {
299  // phpcs:enable
300  global $conf;
301  //dol_syslog(get_class($this).'::get_substitutionarray_tasksressource taskressource='.var_export($taskressource,true),LOG_DEBUG);
302  return array(
303  'taskressource_rowid'=>$taskressource['rowid'],
304  'taskressource_role'=>$taskressource['libelle'],
305  'taskressource_lastname'=>$taskressource['lastname'],
306  'taskressource_firstname'=>$taskressource['firstname'],
307  'taskressource_fullcivname'=>$taskressource['fullname'],
308  'taskressource_socname'=>$taskressource['socname'],
309  'taskressource_email'=>$taskressource['email']
310  );
311  }
312 
313  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
321  public function get_substitutionarray_taskstime($tasktime, $outputlangs)
322  {
323  // phpcs:enable
324  global $conf;
325 
326  return array(
327  'tasktime_rowid'=>$tasktime['rowid'],
328  'tasktime_task_date'=>dol_print_date($tasktime['task_date'], 'day'),
329  'tasktime_task_duration'=>convertSecondToTime($tasktime['task_duration'], 'all'),
330  'tasktime_note'=>$tasktime['note'],
331  'tasktime_fk_user'=>$tasktime['fk_user'],
332  'tasktime_user_name'=>$tasktime['name'],
333  'tasktime_user_first'=>$tasktime['firstname'],
334  'tasktime_fullcivname'=>$tasktime['fullcivname']
335  );
336  }
337 
338  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
346  public function get_substitutionarray_task_file($file, $outputlangs)
347  {
348  // phpcs:enable
349  global $conf;
350 
351  return array(
352  'tasksfile_name'=>$file['name'],
353  'tasksfile_date'=>dol_print_date($file['date'], 'day'),
354  'tasksfile_size'=>$file['size']
355  );
356  }
357 
358 
365  public function info($langs)
366  {
367  global $conf, $langs;
368 
369  // Load translation files required by the page
370  $langs->loadLangs(array("errors", "companies"));
371 
372  $form = new Form($this->db);
373 
374  $texte = $this->description.".<br>\n";
375  $texte .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
376  $texte .= '<input type="hidden" name="token" value="'.newToken().'">';
377  $texte .= '<input type="hidden" name="page_y" value="">';
378  $texte .= '<input type="hidden" name="action" value="setModuleOptions">';
379  $texte .= '<input type="hidden" name="param1" value="PROJECT_TASK_ADDON_PDF_ODT_PATH">';
380  $texte .= '<table class="nobordernopadding" width="100%">';
381 
382  // List of directories area
383  $texte .= '<tr><td>';
384  $texttitle = $langs->trans("ListOfDirectories");
385  $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->PROJECT_TASK_ADDON_PDF_ODT_PATH)));
386  $listoffiles = array();
387  foreach ($listofdir as $key => $tmpdir) {
388  $tmpdir = trim($tmpdir);
389  $tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir);
390  if (!$tmpdir) {
391  unset($listofdir[$key]);
392  continue;
393  }
394  if (!is_dir($tmpdir)) {
395  $texttitle .= img_warning($langs->trans("ErrorDirNotFound", $tmpdir), 0);
396  } else {
397  $tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.(ods|odt)');
398  if (count($tmpfiles)) {
399  $listoffiles = array_merge($listoffiles, $tmpfiles);
400  }
401  }
402  }
403  $texthelp = $langs->trans("ListOfDirectoriesForModelGenODT");
404  // Add list of substitution keys
405  $texthelp .= '<br>'.$langs->trans("FollowingSubstitutionKeysCanBeUsed").'<br>';
406  $texthelp .= $langs->transnoentitiesnoconv("FullListOnOnlineDocumentation"); // This contains an url, we don't modify it
407 
408  $texte .= $form->textwithpicto($texttitle, $texthelp, 1, 'help', '', 1);
409  $texte .= '<div><div style="display: inline-block; min-width: 100px; vertical-align: middle;">';
410  $texte .= '<textarea class="flat" cols="60" name="value1">';
411  $texte .= $conf->global->PROJECT_TASK_ADDON_PDF_ODT_PATH;
412  $texte .= '</textarea>';
413  $texte .= '</div><div style="display: inline-block; vertical-align: middle;">';
414  $texte .= '<input type="submit" class="button small reposition" name="modify" value="'.$langs->trans("Modify").'">';
415  $texte .= '<br></div></div>';
416 
417  // Scan directories
418  $nbofiles = count($listoffiles);
419  if (!empty($conf->global->PROJECT_TASK_ADDON_PDF_ODT_PATH)) {
420  $texte .= $langs->trans("NumberOfModelFilesFound").': <b>';
421  //$texte.=$nbofiles?'<a id="a_'.get_class($this).'" href="#">':'';
422  $texte .= $nbofiles;
423  //$texte.=$nbofiles?'</a>':'';
424  $texte .= '</b>';
425  }
426 
427  if ($nbofiles) {
428  $texte .= '<div id="div_'.get_class($this).'" class="hiddenx">';
429  // Show list of found files
430  foreach ($listoffiles as $file) {
431  $texte .= '- '.$file['name'].' <a href="'.DOL_URL_ROOT.'/document.php?modulepart=doctemplates&file=tasks/'.urlencode(basename($file['name'])).'">'.img_picto('', 'listlight').'</a>';
432  $texte .= ' &nbsp; <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?modulepart=doctemplates&keyforuploaddir=PROJECT_TASK_ADDON_PDF_ODT_PATH&action=deletefile&token='.newToken().'&file='.urlencode(basename($file['name'])).'">'.img_picto('', 'delete').'</a>';
433  $texte .= '<br>';
434  }
435  $texte .= '</div>';
436  }
437 
438  $texte .= '</td>';
439 
440  $texte .= '<td rowspan="2" class="tdtop hideonsmartphone">';
441  $texte .= '<span class="opacitymedium">';
442  $texte .= $langs->trans("ExampleOfDirectoriesForModelGen");
443  $texte .= '</span>';
444  $texte .= '</td>';
445  $texte .= '</tr>';
446 
447  $texte .= '</table>';
448  $texte .= '</form>';
449 
450  return $texte;
451  }
452 
453  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
462  public function write_file($object, $outputlangs, $srctemplatepath)
463  {
464  // phpcs:enable
465  global $user, $langs, $conf, $mysoc, $hookmanager;
466 
467  if (empty($srctemplatepath)) {
468  dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING);
469  return -1;
470  }
471 
472  if (!is_object($outputlangs)) {
473  $outputlangs = $langs;
474  }
475  $sav_charset_output = $outputlangs->charset_output;
476  $outputlangs->charset_output = 'UTF-8';
477 
478  // Load translation files required by the page
479  $outputlangs->loadLangs(array("main", "dict", "companies", "projects"));
480 
481  if ($conf->project->dir_output) {
482  // If $object is id instead of object
483  if (!is_object($object)) {
484  $id = $object;
485  $object = new Task($this->db);
486  $result = $object->fetch($id);
487  if ($result < 0) {
488  dol_print_error($this->db, $object->error);
489  return -1;
490  }
491  }
492  $project = new Project($this->db);
493  $project->fetch($object->fk_project);
494  $project->fetch_thirdparty();
495 
496  $dir = $conf->project->dir_output."/".$project->ref."/";
497  $objectref = dol_sanitizeFileName($object->ref);
498  if (!preg_match('/specimen/i', $objectref)) {
499  $dir .= "/".$objectref;
500  }
501  $file = $dir."/".$objectref.".odt";
502 
503  if (!file_exists($dir)) {
504  if (dol_mkdir($dir) < 0) {
505  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
506  return -1;
507  }
508  }
509 
510 
511  if (file_exists($dir)) {
512  //print "srctemplatepath=".$srctemplatepath; // Src filename
513  $newfile = basename($srctemplatepath);
514  $newfiletmp = preg_replace('/\.(ods|odt)/i', '', $newfile);
515  $newfiletmp = preg_replace('/template_/i', '', $newfiletmp);
516  $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp);
517  $newfiletmp = $objectref . '_' . $newfiletmp;
518  //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt';
519  $file = $dir . '/' . $newfiletmp . '.odt';
520  //print "newdir=".$dir;
521  //print "newfile=".$newfile;
522  //print "file=".$file;
523  //print "conf->societe->dir_temp=".$conf->societe->dir_temp;
524 
525  dol_mkdir($conf->project->dir_temp);
526  if (!is_writable($conf->project->dir_temp)) {
527  $this->error = $langs->transnoentities("ErrorFailedToWriteInTempDirectory", $conf->project->dir_temp);
528  dol_syslog('Error in write_file: ' . $this->error, LOG_ERR);
529  return -1;
530  }
531 
532  $socobject = $project->thirdparty;
533 
534  // Make substitution
535  $substitutionarray = array(
536  '__FROM_NAME__' => $this->emetteur->name,
537  '__FROM_EMAIL__' => $this->emetteur->email,
538  );
539  complete_substitutions_array($substitutionarray, $langs, $object);
540  // Call the ODTSubstitution hook
541  $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray);
542  $reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
543 
544  // Open and load template
545  require_once ODTPHP_PATH.'odf.php';
546  try {
547  $odfHandler = new Odf(
548  $srctemplatepath,
549  array(
550  'PATH_TO_TMP' => $conf->project->dir_temp,
551  'ZIP_PROXY' => 'PclZipProxy', // PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy.
552  'DELIMITER_LEFT' => '{',
553  'DELIMITER_RIGHT' => '}'
554  )
555  );
556  } catch (Exception $e) {
557  $this->error = $e->getMessage();
558  return -1;
559  }
560  // After construction $odfHandler->contentXml contains content and
561  // [!-- BEGIN row.lines --]*[!-- END row.lines --] has been replaced by
562  // [!-- BEGIN lines --]*[!-- END lines --]
563  //print html_entity_decode($odfHandler->__toString());
564  //print exit;
565 
566 
567  // Define substitution array
568  $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
569  $array_object_from_properties = $this->get_substitutionarray_each_var_object($object, $outputlangs);
570  $array_objet = $this->get_substitutionarray_object($project, $outputlangs);
571  $array_user = $this->get_substitutionarray_user($user, $outputlangs);
572  $array_soc = $this->get_substitutionarray_mysoc($mysoc, $outputlangs);
573  $array_thirdparty = $this->get_substitutionarray_thirdparty($socobject, $outputlangs);
574  $array_other = $this->get_substitutionarray_other($outputlangs);
575 
576  $tmparray = array_merge($substitutionarray, $array_object_from_properties, $array_user, $array_soc, $array_thirdparty, $array_objet, $array_other);
577  complete_substitutions_array($tmparray, $outputlangs, $object);
578 
579  foreach ($tmparray as $key => $value) {
580  try {
581  if (preg_match('/logo$/', $key)) { // Image
582  if (file_exists($value)) {
583  $odfHandler->setImage($key, $value);
584  } else {
585  $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
586  }
587  } else // Text
588  {
589  $odfHandler->setVars($key, $value, true, 'UTF-8');
590  }
591  } catch (OdfException $e) {
592  dol_syslog($e->getMessage(), LOG_INFO);
593  }
594  }
595 
596  // Replace tags of lines for tasks
597  try {
598  // Security check
599  $socid = 0;
600  if (!empty($project->fk_soc)) {
601  $socid = $project->fk_soc;
602  }
603 
604  $tmparray = $this->get_substitutionarray_tasks($object, $outputlangs);
605  complete_substitutions_array($tmparray, $outputlangs, $object);
606  foreach ($tmparray as $key => $val) {
607  try {
608  $odfHandler->setVars($key, $val, true, 'UTF-8');
609  } catch (OdfException $e) {
610  dol_syslog($e->getMessage(), LOG_INFO);
611  } catch (SegmentException $e) {
612  dol_syslog($e->getMessage(), LOG_INFO);
613  }
614  }
615 
616  // Replace tags of lines for contacts task
617  $sourcearray = array('internal', 'external');
618  $contact_arrray = array();
619  foreach ($sourcearray as $source) {
620  $contact_temp = $object->liste_contact(-1, $source);
621  if ((is_array($contact_temp) && count($contact_temp) > 0)) {
622  $contact_arrray = array_merge($contact_arrray, $contact_temp);
623  }
624  }
625  if ((is_array($contact_arrray) && count($contact_arrray) > 0)) {
626  $listlinestaskres = $odfHandler->setSegment('tasksressources');
627 
628  foreach ($contact_arrray as $contact) {
629  if ($contact['source'] == 'internal') {
630  $objectdetail = new User($this->db);
631  $objectdetail->fetch($contact['id']);
632  $contact['socname'] = $mysoc->name;
633  } elseif ($contact['source'] == 'external') {
634  $objectdetail = new Contact($this->db);
635  $objectdetail->fetch($contact['id']);
636 
637  $soc = new Societe($this->db);
638  $soc->fetch($contact['socid']);
639  $contact['socname'] = $soc->name;
640  }
641  $contact['fullname'] = $objectdetail->getFullName($outputlangs, 1);
642 
643  $tmparray = $this->get_substitutionarray_tasksressource($contact, $outputlangs);
644 
645  foreach ($tmparray as $key => $val) {
646  try {
647  $listlinestaskres->setVars($key, $val, true, 'UTF-8');
648  } catch (OdfException $e) {
649  dol_syslog($e->getMessage(), LOG_INFO);
650  } catch (SegmentException $e) {
651  dol_syslog($e->getMessage(), LOG_INFO);
652  }
653  }
654  $listlinestaskres->merge();
655  }
656  $odfHandler->mergeSegment($listlinestaskres);
657  }
658 
659  // Time ressources
660  $sql = "SELECT t.rowid, t.element_date as task_date, t.element_duration as task_duration, t.fk_user, t.note";
661  $sql .= ", u.lastname, u.firstname";
662  $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t";
663  $sql .= " , ".MAIN_DB_PREFIX."user as u";
664  $sql .= " WHERE t.fk_element =".((int) $object->id);
665  $sql .= " AND t.elementtype = 'task'";
666  $sql .= " AND t.fk_user = u.rowid";
667  $sql .= " ORDER BY t.element_date DESC";
668 
669  $resql = $this->db->query($sql);
670  if ($resql) {
671  $num = $this->db->num_rows($resql);
672  $i = 0;
673  $tasks = array();
674  $listlinestasktime = $odfHandler->setSegment('taskstimes');
675  while ($i < $num) {
676  $row = $this->db->fetch_array($resql);
677  if (!empty($row['fk_user'])) {
678  $objectdetail = new User($this->db);
679  $objectdetail->fetch($row['fk_user']);
680  // TODO Use a cache to aoid fetch for same user
681  $row['fullcivname'] = $objectdetail->getFullName($outputlangs, 1);
682  } else {
683  $row['fullcivname'] = '';
684  }
685 
686  $tmparray = $this->get_substitutionarray_taskstime($row, $outputlangs);
687 
688  foreach ($tmparray as $key => $val) {
689  try {
690  $listlinestasktime->setVars($key, $val, true, 'UTF-8');
691  } catch (OdfException $e) {
692  dol_syslog($e->getMessage(), LOG_INFO);
693  } catch (SegmentException $e) {
694  dol_syslog($e->getMessage(), LOG_INFO);
695  }
696  }
697  $listlinestasktime->merge();
698  $i++;
699  }
700  $this->db->free($resql);
701 
702  $odfHandler->mergeSegment($listlinestasktime);
703  }
704 
705 
706  // Replace tags of project files
707  $listtasksfiles = $odfHandler->setSegment('tasksfiles');
708 
709  $upload_dir = $conf->project->dir_output.'/'.dol_sanitizeFileName($project->ref).'/'.dol_sanitizeFileName($object->ref);
710  $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', 'name', SORT_ASC, 1);
711 
712 
713  foreach ($filearray as $filedetail) {
714  $tmparray = $this->get_substitutionarray_task_file($filedetail, $outputlangs);
715  //dol_syslog(get_class($this).'::main $tmparray'.var_export($tmparray,true));
716  foreach ($tmparray as $key => $val) {
717  try {
718  $listtasksfiles->setVars($key, $val, true, 'UTF-8');
719  } catch (OdfException $e) {
720  dol_syslog($e->getMessage(), LOG_INFO);
721  } catch (SegmentException $e) {
722  dol_syslog($e->getMessage(), LOG_INFO);
723  }
724  }
725  $listtasksfiles->merge();
726  }
727  //$listlines->merge();
728 
729  $odfHandler->mergeSegment($listtasksfiles);
730  } catch (OdfException $e) {
731  $this->error = $e->getMessage();
732  dol_syslog($this->error, LOG_WARNING);
733  return -1;
734  }
735 
736 
737 
738  // Replace tags of project files
739  try {
740  $listlines = $odfHandler->setSegment('projectfiles');
741 
742  $upload_dir = $conf->project->dir_output.'/'.dol_sanitizeFileName($object->ref);
743  $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', 'name', SORT_ASC, 1);
744 
745 
746  foreach ($filearray as $filedetail) {
747  //dol_syslog(get_class($this).'::main $filedetail'.var_export($filedetail,true));
748  $tmparray = $this->get_substitutionarray_project_file($filedetail, $outputlangs);
749 
750  foreach ($tmparray as $key => $val) {
751  try {
752  $listlines->setVars($key, $val, true, 'UTF-8');
753  } catch (OdfException $e) {
754  dol_syslog($e->getMessage(), LOG_INFO);
755  } catch (SegmentException $e) {
756  dol_syslog($e->getMessage(), LOG_INFO);
757  }
758  }
759  $listlines->merge();
760  }
761  $odfHandler->mergeSegment($listlines);
762  } catch (OdfException $e) {
763  $this->error = $e->getMessage();
764  dol_syslog($this->error, LOG_WARNING);
765  return -1;
766  }
767 
768  // Replace tags of lines for contacts
769  $sourcearray = array('internal', 'external');
770  $contact_arrray = array();
771  foreach ($sourcearray as $source) {
772  $contact_temp = $project->liste_contact(-1, $source);
773  if ((is_array($contact_temp) && count($contact_temp) > 0)) {
774  $contact_arrray = array_merge($contact_arrray, $contact_temp);
775  }
776  }
777  if ((is_array($contact_arrray) && count($contact_arrray) > 0)) {
778  try {
779  $listlines = $odfHandler->setSegment('projectcontacts');
780 
781  foreach ($contact_arrray as $contact) {
782  if ($contact['source'] == 'internal') {
783  $objectdetail = new User($this->db);
784  $objectdetail->fetch($contact['id']);
785  $contact['socname'] = $mysoc->name;
786  } elseif ($contact['source'] == 'external') {
787  $objectdetail = new Contact($this->db);
788  $objectdetail->fetch($contact['id']);
789 
790  $soc = new Societe($this->db);
791  $soc->fetch($contact['socid']);
792  $contact['socname'] = $soc->name;
793  }
794  $contact['fullname'] = $objectdetail->getFullName($outputlangs, 1);
795 
796  $tmparray = $this->get_substitutionarray_project_contacts($contact, $outputlangs);
797 
798  foreach ($tmparray as $key => $val) {
799  try {
800  $listlines->setVars($key, $val, true, 'UTF-8');
801  } catch (OdfException $e) {
802  dol_syslog($e->getMessage(), LOG_INFO);
803  } catch (SegmentException $e) {
804  dol_syslog($e->getMessage(), LOG_INFO);
805  }
806  }
807  $listlines->merge();
808  }
809  $odfHandler->mergeSegment($listlines);
810  } catch (OdfException $e) {
811  $this->error = $e->getMessage();
812  dol_syslog($this->error, LOG_WARNING);
813  return -1;
814  }
815  }
816 
817 
818  // Call the beforeODTSave hook
819  $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray);
820  $reshook = $hookmanager->executeHooks('beforeODTSave', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
821 
822 
823  // Write new file
824  if (!empty($conf->global->MAIN_ODT_AS_PDF)) {
825  try {
826  $odfHandler->exportAsAttachedPDF($file);
827  } catch (Exception $e) {
828  $this->error = $e->getMessage();
829  dol_syslog($e->getMessage(), LOG_INFO);
830  return -1;
831  }
832  } else {
833  try {
834  $odfHandler->saveToDisk($file);
835  } catch (Exception $e) {
836  $this->error = $e->getMessage();
837  dol_syslog($e->getMessage(), LOG_INFO);
838  return -1;
839  }
840  }
841  $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray);
842  $reshook = $hookmanager->executeHooks('afterODTCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
843 
844  dolChmod($file);
845 
846  $odfHandler = null; // Destroy object
847 
848  $this->result = array('fullpath'=>$file);
849 
850  return 1; // Success
851  } else {
852  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
853  return -1;
854  }
855  }
856 
857  return -1;
858  }
859 }
get_substitutionarray_each_var_object(&$object, $outputlangs, $recursive=1)
Define array with couple substitution key => substitution value.
get_substitutionarray_mysoc($mysoc, $outputlangs)
Define array with couple substitution key => substitution value.
get_substitutionarray_other($outputlangs)
Define array with couple substitution key => substitution value.
fill_substitutionarray_with_extrafields($object, $array_to_fill, $extrafields, $array_key, $outputlangs)
Fill array with couple extrafield key => extrafield value Note that vars into substitutions array are...
get_substitutionarray_thirdparty($object, $outputlangs, $array_key='company')
Define array with couple substitution key => substitution value For example {company_name},...
get_substitutionarray_user($user, $outputlangs)
Define array with couple substitution key => substitution value.
Class to manage contact/addresses.
Class to manage generation of HTML components Only common components must be here.
Parent class for projects models.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Definition: task.class.php:40
Class to manage Dolibarr users.
Definition: user.class.php:48
Class to build documents using ODF templates generator.
get_substitutionarray_tasksressource($taskressource, $outputlangs)
Define array with couple substitution key => substitution value.
get_substitutionarray_task_file($file, $outputlangs)
Define array with couple substitution key => substitution value.
get_substitutionarray_taskstime($tasktime, $outputlangs)
Define array with couple substitution key => substitution value.
get_substitutionarray_tasks($task, $outputlangs, $array_key='task')
Define array with couple substitution key => substitution value.
get_substitutionarray_object($object, $outputlangs, $array_key='object')
Define array with couple substitution key => substitution value.
get_substitutionarray_project_contacts($contact, $outputlangs)
Define array with couple substitution key => substitution value.
get_substitutionarray_project_file($file, $outputlangs)
Define array with couple substitution key => substitution value.
info($langs)
Return description of a module.
write_file($object, $outputlangs, $srctemplatepath)
Function to build a document on disk using the generic odt module.
get_substitutionarray_project_reference($refdetail, $outputlangs)
Define array with couple substitution key => substitution value.
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition: date.lib.php:239
print *****$script_file(".$version.") pid cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:62
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dolChmod($filepath, $newmask='')
Change mod of a file.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
newToken()
Return the value of token currently saved into session with name 'newtoken'.
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null, $include=null)
Return array of possible common substitutions.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:120
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:123