dolibarr  20.0.0-beta
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  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <https://www.gnu.org/licenses/>.
22  * or see https://www.gnu.org/
23  */
24 
31 require_once DOL_DOCUMENT_ROOT.'/core/modules/project/modules_project.php';
32 require_once DOL_DOCUMENT_ROOT.'/core/modules/project/task/modules_task.php';
33 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
36 require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
37 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
38 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
39 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
40 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
41 require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php';
42 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
43 if (isModEnabled("propal")) {
44  require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
45 }
46 if (isModEnabled('invoice')) {
47  require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
48 }
49 if (isModEnabled('invoice')) {
50  require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
51 }
52 if (isModEnabled('order')) {
53  require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
54 }
55 if (isModEnabled("supplier_invoice")) {
56  require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
57 }
58 if (isModEnabled("supplier_order")) {
59  require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
60 }
61 if (isModEnabled('contract')) {
62  require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
63 }
64 if (isModEnabled('intervention')) {
65  require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
66 }
67 if (isModEnabled('deplacement')) {
68  require_once DOL_DOCUMENT_ROOT.'/compta/deplacement/class/deplacement.class.php';
69 }
70 if (isModEnabled('agenda')) {
71  require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
72 }
73 
74 
79 {
84  public $version = 'dolibarr';
85 
86 
92  public function __construct($db)
93  {
94  global $langs, $mysoc;
95 
96  // Load translation files required by the page
97  $langs->loadLangs(array("main", "companies"));
98 
99  $this->db = $db;
100  $this->name = "ODT templates";
101  $this->description = $langs->trans("DocumentModelOdt");
102  $this->scandir = 'PROJECT_TASK_ADDON_PDF_ODT_PATH'; // Name of constant that is used to save list of directories to scan
103 
104  // Page size for A4 format
105  $this->type = 'odt';
106  $this->page_largeur = 0;
107  $this->page_hauteur = 0;
108  $this->format = array($this->page_largeur, $this->page_hauteur);
109  $this->marge_gauche = 0;
110  $this->marge_droite = 0;
111  $this->marge_haute = 0;
112  $this->marge_basse = 0;
113 
114  $this->option_logo = 1; // Display logo
115  $this->option_tva = 0; // Manage the vat option COMMANDE_TVAOPTION
116  $this->option_modereg = 0; // Display payment mode
117  $this->option_condreg = 0; // Display payment terms
118  $this->option_multilang = 0; // Available in several languages
119  $this->option_escompte = 0; // Displays if there has been a discount
120  $this->option_credit_note = 0; // Support credit notes
121  $this->option_freetext = 1; // Support add of a personalised text
122  $this->option_draft_watermark = 0; // Support add of a watermark on drafts
123 
124  // Get source company
125  $this->emetteur = $mysoc;
126  if (!$this->emetteur->country_code) {
127  $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
128  }
129  }
130 
131 
132  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
141  public function get_substitutionarray_object($object, $outputlangs, $array_key = 'object')
142  {
143  // phpcs:enable
144  global $extrafields;
145 
146  if (!$object instanceof Project) {
147  dol_syslog("Expected Project object, got ".gettype($object), LOG_ERR);
148  return array();
149  }
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 $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  return array(
232  'projcontacts_id' => $contact['id'],
233  'projcontacts_rowid' => $contact['rowid'],
234  'projcontacts_role' => $contact['libelle'],
235  'projcontacts_lastname' => $contact['lastname'],
236  'projcontacts_firstname' => $contact['firstname'],
237  'projcontacts_fullcivname' => $contact['fullname'],
238  'projcontacts_socname' => $contact['socname'],
239  'projcontacts_email' => $contact['email']
240  );
241  }
242 
243  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
251  public function get_substitutionarray_project_file($file, $outputlangs)
252  {
253  // phpcs:enable
254  return array(
255  'projfile_name' => $file['name'],
256  'projfile_date' => dol_print_date($file['date'], 'day'),
257  'projfile_size' => $file['size']
258  );
259  }
260 
261  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
269  public function get_substitutionarray_project_reference($refdetail, $outputlangs)
270  {
271  // phpcs:enable
272  return array(
273  'projref_type' => $refdetail['type'],
274  'projref_ref' => $refdetail['ref'],
275  'projref_date' => dol_print_date($refdetail['date'], 'day'),
276  'projref_socname' => $refdetail['socname'],
277  'projref_amountht' => price($refdetail['amountht'], 0, $outputlangs),
278  'projref_amountttc' => price($refdetail['amountttc'], 0, $outputlangs),
279  'projref_status' => $refdetail['status']
280  );
281  }
282 
283  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
291  public function get_substitutionarray_tasksressource($taskresource, $outputlangs)
292  {
293  // phpcs:enable
294 
295  //dol_syslog(get_class($this).'::get_substitutionarray_tasksressource taskressource='.var_export($taskressource,true),LOG_DEBUG);
296  return array(
297  'taskressource_rowid' => $taskresource['rowid'],
298  'taskressource_role' => $taskresource['libelle'],
299  'taskressource_lastname' => $taskresource['lastname'],
300  'taskressource_firstname' => $taskresource['firstname'],
301  'taskressource_fullcivname' => $taskresource['fullname'],
302  'taskressource_socname' => $taskresource['socname'],
303  'taskressource_email' => $taskresource['email']
304  );
305  }
306 
307  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
315  public function get_substitutionarray_taskstime($tasktime, $outputlangs)
316  {
317  // phpcs:enable
318  global $conf;
319 
320  return array(
321  'tasktime_rowid' => $tasktime['rowid'],
322  'tasktime_task_date' => dol_print_date($tasktime['task_date'], 'day'),
323  'tasktime_task_duration' => convertSecondToTime($tasktime['task_duration'], 'all'),
324  'tasktime_note' => $tasktime['note'],
325  'tasktime_fk_user' => $tasktime['fk_user'],
326  'tasktime_user_name' => $tasktime['name'],
327  'tasktime_user_first' => $tasktime['firstname'],
328  'tasktime_fullcivname' => $tasktime['fullcivname']
329  );
330  }
331 
332  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
340  public function get_substitutionarray_task_file($file, $outputlangs)
341  {
342  // phpcs:enable
343  return array(
344  'tasksfile_name' => $file['name'],
345  'tasksfile_date' => dol_print_date($file['date'], 'day'),
346  'tasksfile_size' => $file['size']
347  );
348  }
349 
350 
357  public function info($langs)
358  {
359  global $conf, $langs;
360 
361  // Load translation files required by the page
362  $langs->loadLangs(array("errors", "companies"));
363 
364  $form = new Form($this->db);
365 
366  $texte = $this->description.".<br>\n";
367  $texte .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" enctype="multipart/form-data">';
368  $texte .= '<input type="hidden" name="token" value="'.newToken().'">';
369  $texte .= '<input type="hidden" name="page_y" value="">';
370  $texte .= '<input type="hidden" name="action" value="setModuleOptions">';
371  $texte .= '<input type="hidden" name="param1" value="PROJECT_TASK_ADDON_PDF_ODT_PATH">';
372  $texte .= '<table class="nobordernopadding centpercent">';
373 
374  // List of directories area
375  $texte .= '<tr><td>';
376  $texttitle = $langs->trans("ListOfDirectories");
377  $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->PROJECT_TASK_ADDON_PDF_ODT_PATH)));
378  $listoffiles = array();
379  foreach ($listofdir as $key => $tmpdir) {
380  $tmpdir = trim($tmpdir);
381  $tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir);
382  if (!$tmpdir) {
383  unset($listofdir[$key]);
384  continue;
385  }
386  if (!is_dir($tmpdir)) {
387  $texttitle .= img_warning($langs->trans("ErrorDirNotFound", $tmpdir), 0);
388  } else {
389  $tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.(ods|odt)');
390  if (count($tmpfiles)) {
391  $listoffiles = array_merge($listoffiles, $tmpfiles);
392  }
393  }
394  }
395  $texthelp = $langs->trans("ListOfDirectoriesForModelGenODT");
396  $texthelp .= '<br><br><span class="opacitymedium">'.$langs->trans("ExampleOfDirectoriesForModelGen").'</span>';
397  // Add list of substitution keys
398  $texthelp .= '<br>'.$langs->trans("FollowingSubstitutionKeysCanBeUsed").'<br>';
399  $texthelp .= $langs->transnoentitiesnoconv("FullListOnOnlineDocumentation"); // This contains an url, we don't modify it
400 
401  $texte .= $form->textwithpicto($texttitle, $texthelp, 1, 'help', '', 1, 3, $this->name);
402  $texte .= '<div><div style="display: inline-block; min-width: 100px; vertical-align: middle;">';
403  $texte .= '<textarea class="flat" cols="60" name="value1">';
404  $texte .= getDolGlobalString('PROJECT_TASK_ADDON_PDF_ODT_PATH');
405  $texte .= '</textarea>';
406  $texte .= '</div><div style="display: inline-block; vertical-align: middle;">';
407  $texte .= '<input type="submit" class="button button-edit reposition smallpaddingimp" name="modify" value="'.dol_escape_htmltag($langs->trans("Modify")).'">';
408  $texte .= '<br></div></div>';
409 
410  // Scan directories
411  $nbofiles = count($listoffiles);
412  if (getDolGlobalString('PROJECT_TASK_ADDON_PDF_ODT_PATH')) {
413  $texte .= $langs->trans("NumberOfModelFilesFound").': <b>';
414  //$texte.=$nbofiles?'<a id="a_'.get_class($this).'" href="#">':'';
415  $texte .= $nbofiles;
416  //$texte.=$nbofiles?'</a>':'';
417  $texte .= '</b>';
418  }
419 
420  if ($nbofiles) {
421  $texte .= '<div id="div_'.get_class($this).'" class="hiddenx">';
422  // Show list of found files
423  foreach ($listoffiles as $file) {
424  $texte .= '- '.$file['name'].' <a href="'.DOL_URL_ROOT.'/document.php?modulepart=doctemplates&file=tasks/'.urlencode(basename($file['name'])).'">'.img_picto('', 'listlight').'</a>';
425  $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>';
426  $texte .= '<br>';
427  }
428  $texte .= '</div>';
429  }
430  // Add input to upload a new template file.
431  $texte .= '<div>'.$langs->trans("UploadNewTemplate");
432  $maxfilesizearray = getMaxFileSizeArray();
433  $maxmin = $maxfilesizearray['maxmin'];
434  if ($maxmin > 0) {
435  $texte .= '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
436  }
437  $texte .= ' <input type="file" name="uploadfile">';
438  $texte .= '<input type="hidden" value="PROJECT_TASK_ADDON_PDF_ODT_PATH" name="keyforuploaddir">';
439  $texte .= '<input type="submit" class="button smallpaddingimp reposition" value="'.dol_escape_htmltag($langs->trans("Upload")).'" name="upload">';
440  $texte .= '</div>';
441  $texte .= '</td>';
442 
443  $texte .= '</tr>';
444 
445  $texte .= '</table>';
446  $texte .= '</form>';
447 
448  return $texte;
449  }
450 
451  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
460  public function write_file($object, $outputlangs, $srctemplatepath)
461  {
462  // phpcs:enable
463  global $user, $langs, $conf, $mysoc, $hookmanager;
464 
465  if (empty($srctemplatepath)) {
466  dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING);
467  return -1;
468  }
469 
470  if (!is_object($outputlangs)) {
471  $outputlangs = $langs;
472  }
473  $sav_charset_output = $outputlangs->charset_output;
474  $outputlangs->charset_output = 'UTF-8';
475 
476  // Load translation files required by the page
477  $outputlangs->loadLangs(array("main", "dict", "companies", "projects"));
478 
479  if ($conf->project->dir_output) {
480  // If $object is id instead of object
481  if (!is_object($object)) {
482  $id = $object;
483  $object = new Task($this->db);
484  $result = $object->fetch($id);
485  if ($result < 0) {
486  dol_print_error($this->db, $object->error);
487  return -1;
488  }
489  }
490  $project = new Project($this->db);
491  $project->fetch($object->fk_project);
492  $project->fetch_thirdparty();
493 
494  $dir = $conf->project->dir_output."/".$project->ref."/";
495  $objectref = dol_sanitizeFileName($object->ref);
496  if (!preg_match('/specimen/i', $objectref)) {
497  $dir .= "/".$objectref;
498  }
499  $file = $dir."/".$objectref.".odt";
500 
501  if (!file_exists($dir)) {
502  if (dol_mkdir($dir) < 0) {
503  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
504  return -1;
505  }
506  }
507 
508 
509  if (file_exists($dir)) {
510  //print "srctemplatepath=".$srctemplatepath; // Src filename
511  $newfile = basename($srctemplatepath);
512  $newfiletmp = preg_replace('/\.(ods|odt)/i', '', $newfile);
513  $newfiletmp = preg_replace('/template_/i', '', $newfiletmp);
514  $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp);
515  $newfiletmp = $objectref . '_' . $newfiletmp;
516  //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt';
517  $file = $dir . '/' . $newfiletmp . '.odt';
518  //print "newdir=".$dir;
519  //print "newfile=".$newfile;
520  //print "file=".$file;
521  //print "conf->societe->dir_temp=".$conf->societe->dir_temp;
522 
523  dol_mkdir($conf->project->dir_temp);
524  if (!is_writable($conf->project->dir_temp)) {
525  $this->error = $langs->transnoentities("ErrorFailedToWriteInTempDirectory", $conf->project->dir_temp);
526  dol_syslog('Error in write_file: ' . $this->error, LOG_ERR);
527  return -1;
528  }
529 
530  $socobject = $project->thirdparty;
531 
532  // Make substitution
533  $substitutionarray = array(
534  '__FROM_NAME__' => $this->emetteur->name,
535  '__FROM_EMAIL__' => $this->emetteur->email,
536  );
537  complete_substitutions_array($substitutionarray, $langs, $object);
538  // Call the ODTSubstitution hook
539  $tmparray = array();
540  $action = '';
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  $odfHandler->setVars($key, $value, true, 'UTF-8');
589  }
590  } catch (OdfException $e) {
591  dol_syslog($e->getMessage(), LOG_INFO);
592  }
593  }
594 
595  // Replace tags of lines for tasks
596  try {
597  // Security check
598  $socid = 0;
599  if (!empty($project->fk_soc)) {
600  $socid = $project->fk_soc;
601  }
602 
603  $tmparray = $this->get_substitutionarray_tasks($object, $outputlangs);
604  complete_substitutions_array($tmparray, $outputlangs, $object);
605  foreach ($tmparray as $key => $val) {
606  try {
607  $odfHandler->setVars($key, $val, true, 'UTF-8');
608  } catch (OdfException $e) {
609  dol_syslog($e->getMessage(), LOG_INFO);
610  } catch (SegmentException $e) {
611  dol_syslog($e->getMessage(), LOG_INFO);
612  }
613  }
614 
615  // Replace tags of lines for contacts task
616  $sourcearray = array('internal', 'external');
617  $contact_arrray = array();
618  foreach ($sourcearray as $source) {
619  $contact_temp = $object->liste_contact(-1, $source);
620  if ((is_array($contact_temp) && count($contact_temp) > 0)) {
621  $contact_arrray = array_merge($contact_arrray, $contact_temp);
622  }
623  }
624  if ((is_array($contact_arrray) && count($contact_arrray) > 0)) {
625  $listlinestaskres = $odfHandler->setSegment('tasksressources');
626 
627  foreach ($contact_arrray as $contact) {
628  if ($contact['source'] == 'internal') {
629  $objectdetail = new User($this->db);
630  $objectdetail->fetch($contact['id']);
631  $contact['socname'] = $mysoc->name;
632  } elseif ($contact['source'] == 'external') {
633  $objectdetail = new Contact($this->db);
634  $objectdetail->fetch($contact['id']);
635 
636  $soc = new Societe($this->db);
637  $soc->fetch($contact['socid']);
638  $contact['socname'] = $soc->name;
639  }
640  $contact['fullname'] = $objectdetail->getFullName($outputlangs, 1);
641 
642  $tmparray = $this->get_substitutionarray_tasksressource($contact, $outputlangs);
643 
644  foreach ($tmparray as $key => $val) {
645  try {
646  $listlinestaskres->setVars($key, $val, true, 'UTF-8');
647  } catch (OdfException $e) {
648  dol_syslog($e->getMessage(), LOG_INFO);
649  } catch (SegmentException $e) {
650  dol_syslog($e->getMessage(), LOG_INFO);
651  }
652  }
653  $listlinestaskres->merge();
654  }
655  $odfHandler->mergeSegment($listlinestaskres);
656  }
657 
658  // Time resources
659  $sql = "SELECT t.rowid, t.element_date as task_date, t.element_duration as task_duration, t.fk_user, t.note";
660  $sql .= ", u.lastname, u.firstname";
661  $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t";
662  $sql .= " , ".MAIN_DB_PREFIX."user as u";
663  $sql .= " WHERE t.fk_element =".((int) $object->id);
664  $sql .= " AND t.elementtype = 'task'";
665  $sql .= " AND t.fk_user = u.rowid";
666  $sql .= " ORDER BY t.element_date DESC";
667 
668  $resql = $this->db->query($sql);
669  if ($resql) {
670  $num = $this->db->num_rows($resql);
671  $i = 0;
672  $tasks = array();
673  $listlinestasktime = $odfHandler->setSegment('taskstimes');
674  while ($i < $num) {
675  $row = $this->db->fetch_array($resql);
676  if (!empty($row['fk_user'])) {
677  $objectdetail = new User($this->db);
678  $objectdetail->fetch($row['fk_user']);
679  // TODO Use a cache to aoid fetch for same user
680  $row['fullcivname'] = $objectdetail->getFullName($outputlangs, 1);
681  } else {
682  $row['fullcivname'] = '';
683  }
684 
685  $tmparray = $this->get_substitutionarray_taskstime($row, $outputlangs);
686 
687  foreach ($tmparray as $key => $val) {
688  try {
689  $listlinestasktime->setVars($key, $val, true, 'UTF-8');
690  } catch (OdfException $e) {
691  dol_syslog($e->getMessage(), LOG_INFO);
692  } catch (SegmentException $e) {
693  dol_syslog($e->getMessage(), LOG_INFO);
694  }
695  }
696  $listlinestasktime->merge();
697  $i++;
698  }
699  $this->db->free($resql);
700 
701  $odfHandler->mergeSegment($listlinestasktime);
702  }
703 
704 
705  // Replace tags of project files
706  $listtasksfiles = $odfHandler->setSegment('tasksfiles');
707 
708  $upload_dir = $conf->project->dir_output.'/'.dol_sanitizeFileName($project->ref).'/'.dol_sanitizeFileName($object->ref);
709  $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', 'name', SORT_ASC, 1);
710 
711 
712  foreach ($filearray as $filedetail) {
713  $tmparray = $this->get_substitutionarray_task_file($filedetail, $outputlangs);
714  //dol_syslog(get_class($this).'::main $tmparray'.var_export($tmparray,true));
715  foreach ($tmparray as $key => $val) {
716  try {
717  $listtasksfiles->setVars($key, $val, true, 'UTF-8');
718  } catch (OdfException $e) {
719  dol_syslog($e->getMessage(), LOG_INFO);
720  } catch (SegmentException $e) {
721  dol_syslog($e->getMessage(), LOG_INFO);
722  }
723  }
724  $listtasksfiles->merge();
725  }
726  //$listlines->merge();
727 
728  $odfHandler->mergeSegment($listtasksfiles);
729  } catch (OdfException $e) {
730  $this->error = $e->getMessage();
731  dol_syslog($this->error, LOG_WARNING);
732  return -1;
733  }
734 
735 
736 
737  // Replace tags of project files
738  try {
739  $listlines = $odfHandler->setSegment('projectfiles');
740 
741  $upload_dir = $conf->project->dir_output.'/'.dol_sanitizeFileName($object->ref);
742  $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', 'name', SORT_ASC, 1);
743 
744 
745  foreach ($filearray as $filedetail) {
746  //dol_syslog(get_class($this).'::main $filedetail'.var_export($filedetail,true));
747  $tmparray = $this->get_substitutionarray_project_file($filedetail, $outputlangs);
748 
749  foreach ($tmparray as $key => $val) {
750  try {
751  $listlines->setVars($key, $val, true, 'UTF-8');
752  } catch (OdfException $e) {
753  dol_syslog($e->getMessage(), LOG_INFO);
754  } catch (SegmentException $e) {
755  dol_syslog($e->getMessage(), LOG_INFO);
756  }
757  }
758  $listlines->merge();
759  }
760  $odfHandler->mergeSegment($listlines);
761  } catch (OdfException $e) {
762  $this->error = $e->getMessage();
763  dol_syslog($this->error, LOG_WARNING);
764  return -1;
765  }
766 
767  // Replace tags of lines for contacts
768  $sourcearray = array('internal', 'external');
769  $contact_arrray = array();
770  foreach ($sourcearray as $source) {
771  $contact_temp = $project->liste_contact(-1, $source);
772  if ((is_array($contact_temp) && count($contact_temp) > 0)) {
773  $contact_arrray = array_merge($contact_arrray, $contact_temp);
774  }
775  }
776  if ((is_array($contact_arrray) && count($contact_arrray) > 0)) {
777  try {
778  $listlines = $odfHandler->setSegment('projectcontacts');
779 
780  foreach ($contact_arrray as $contact) {
781  if ($contact['source'] == 'internal') {
782  $objectdetail = new User($this->db);
783  $objectdetail->fetch($contact['id']);
784  $contact['socname'] = $mysoc->name;
785  } elseif ($contact['source'] == 'external') {
786  $objectdetail = new Contact($this->db);
787  $objectdetail->fetch($contact['id']);
788 
789  $soc = new Societe($this->db);
790  $soc->fetch($contact['socid']);
791  $contact['socname'] = $soc->name;
792  }
793  $contact['fullname'] = $objectdetail->getFullName($outputlangs, 1);
794 
795  $tmparray = $this->get_substitutionarray_project_contacts($contact, $outputlangs);
796 
797  foreach ($tmparray as $key => $val) {
798  try {
799  $listlines->setVars($key, $val, true, 'UTF-8');
800  } catch (OdfException $e) {
801  dol_syslog($e->getMessage(), LOG_INFO);
802  } catch (SegmentException $e) {
803  dol_syslog($e->getMessage(), LOG_INFO);
804  }
805  }
806  $listlines->merge();
807  }
808  $odfHandler->mergeSegment($listlines);
809  } catch (OdfException $e) {
810  $this->error = $e->getMessage();
811  dol_syslog($this->error, LOG_WARNING);
812  return -1;
813  }
814  }
815 
816 
817  // Call the beforeODTSave hook
818  $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
819  $reshook = $hookmanager->executeHooks('beforeODTSave', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
820 
821 
822  // Write new file
823  if (getDolGlobalString('MAIN_ODT_AS_PDF')) {
824  try {
825  $odfHandler->exportAsAttachedPDF($file);
826  } catch (Exception $e) {
827  $this->error = $e->getMessage();
828  dol_syslog($e->getMessage(), LOG_INFO);
829  return -1;
830  }
831  } else {
832  try {
833  $odfHandler->saveToDisk($file);
834  } catch (Exception $e) {
835  $this->error = $e->getMessage();
836  dol_syslog($e->getMessage(), LOG_INFO);
837  return -1;
838  }
839  }
840  $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
841  $reshook = $hookmanager->executeHooks('afterODTCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
842 
843  dolChmod($file);
844 
845  $odfHandler = null; // Destroy object
846 
847  $this->result = array('fullpath' => $file);
848 
849  return 1; // Success
850  } else {
851  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
852  return -1;
853  }
854  }
855 
856  return -1;
857  }
858 }
if($user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition: card.php:58
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 task models.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Definition: task.class.php:41
Class to manage Dolibarr users.
Definition: user.class.php:50
Class to build documents using ODF templates generator.
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.
get_substitutionarray_tasksressource($taskresource, $outputlangs)
Define array with couple substitution key => substitution value.
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('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') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:745
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:242
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($utf8_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:63
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
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.
dolChmod($filepath, $newmask='')
Change mod of a file.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
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.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null, $include=null)
Return array of possible common substitutions.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
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:123
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:126
getMaxFileSizeArray()
Return the max allowed for file upload.