dolibarr 20.0.5
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-2024 Frédéric France <frederic.france@free.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
31require_once DOL_DOCUMENT_ROOT.'/core/modules/project/modules_project.php';
32require_once DOL_DOCUMENT_ROOT.'/core/modules/project/task/modules_task.php';
33require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
34require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
35require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
36require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
37require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
41require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php';
42require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
43if (isModEnabled("propal")) {
44 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
45}
46if (isModEnabled('invoice')) {
47 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
48}
49if (isModEnabled('invoice')) {
50 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
51}
52if (isModEnabled('order')) {
53 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
54}
55if (isModEnabled("supplier_invoice")) {
56 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
57}
58if (isModEnabled("supplier_order")) {
59 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
60}
61if (isModEnabled('contract')) {
62 require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
63}
64if (isModEnabled('intervention')) {
65 require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
66}
67if (isModEnabled('deplacement')) {
68 require_once DOL_DOCUMENT_ROOT.'/compta/deplacement/class/deplacement.class.php';
69}
70if (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['lastname'],
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 // Add odtgeneration hook
471 if (!is_object($hookmanager)) {
472 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
473 $hookmanager = new HookManager($this->db);
474 }
475 $hookmanager->initHooks(array('odtgeneration'));
476 global $action;
477
478 if (!is_object($outputlangs)) {
479 $outputlangs = $langs;
480 }
481 $sav_charset_output = $outputlangs->charset_output;
482 $outputlangs->charset_output = 'UTF-8';
483
484 // Load translation files required by the page
485 $outputlangs->loadLangs(array("main", "dict", "companies", "projects"));
486
487 if ($conf->project->dir_output) {
488 // If $object is id instead of object
489 if (!is_object($object)) {
490 $id = $object;
491 $object = new Task($this->db);
492 $result = $object->fetch($id);
493 if ($result < 0) {
494 dol_print_error($this->db, $object->error);
495 return -1;
496 }
497 }
498 $project = new Project($this->db);
499 $project->fetch($object->fk_project);
500 $project->fetch_thirdparty();
501
502 $dir = $conf->project->dir_output."/".$project->ref."/";
503 $objectref = dol_sanitizeFileName($object->ref);
504 if (!preg_match('/specimen/i', $objectref)) {
505 $dir .= "/".$objectref;
506 }
507 $file = $dir."/".$objectref.".odt";
508
509 if (!file_exists($dir)) {
510 if (dol_mkdir($dir) < 0) {
511 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
512 return -1;
513 }
514 }
515
516
517 if (file_exists($dir)) {
518 //print "srctemplatepath=".$srctemplatepath; // Src filename
519 $newfile = basename($srctemplatepath);
520 $newfiletmp = preg_replace('/\.(ods|odt)/i', '', $newfile);
521 $newfiletmp = preg_replace('/template_/i', '', $newfiletmp);
522 $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp);
523 $newfiletmp = $objectref . '_' . $newfiletmp;
524 //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt';
525 $file = $dir . '/' . $newfiletmp . '.odt';
526 //print "newdir=".$dir;
527 //print "newfile=".$newfile;
528 //print "file=".$file;
529 //print "conf->societe->dir_temp=".$conf->societe->dir_temp;
530
531 dol_mkdir($conf->project->dir_temp);
532 if (!is_writable($conf->project->dir_temp)) {
533 $this->error = $langs->transnoentities("ErrorFailedToWriteInTempDirectory", $conf->project->dir_temp);
534 dol_syslog('Error in write_file: ' . $this->error, LOG_ERR);
535 return -1;
536 }
537
538 $socobject = $project->thirdparty;
539
540 // Make substitution
541 $substitutionarray = array(
542 '__FROM_NAME__' => $this->emetteur->name,
543 '__FROM_EMAIL__' => $this->emetteur->email,
544 );
545 complete_substitutions_array($substitutionarray, $langs, $object);
546 // Call the ODTSubstitution hook
547 $tmparray = array();
548 $action = '';
549 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
550 $reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
551
552 // Open and load template
553 require_once ODTPHP_PATH.'odf.php';
554 try {
555 $odfHandler = new Odf(
556 $srctemplatepath,
557 array(
558 'PATH_TO_TMP' => $conf->project->dir_temp,
559 'ZIP_PROXY' => getDolGlobalString('MAIN_ODF_ZIP_PROXY', 'PclZipProxy'), // PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy.
560 'DELIMITER_LEFT' => '{',
561 'DELIMITER_RIGHT' => '}'
562 )
563 );
564 } catch (Exception $e) {
565 $this->error = $e->getMessage();
566 return -1;
567 }
568 // After construction $odfHandler->contentXml contains content and
569 // [!-- BEGIN row.lines --]*[!-- END row.lines --] has been replaced by
570 // [!-- BEGIN lines --]*[!-- END lines --]
571 //print html_entity_decode($odfHandler->__toString());
572 //print exit;
573
574
575 // Define substitution array
576 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
577 $array_object_from_properties = $this->get_substitutionarray_each_var_object($object, $outputlangs);
578 $array_objet = $this->get_substitutionarray_object($project, $outputlangs);
579 $array_user = $this->get_substitutionarray_user($user, $outputlangs);
580 $array_soc = $this->get_substitutionarray_mysoc($mysoc, $outputlangs);
581 $array_thirdparty = $this->get_substitutionarray_thirdparty($socobject, $outputlangs);
582 $array_other = $this->get_substitutionarray_other($outputlangs);
583
584 $tmparray = array_merge($substitutionarray, $array_object_from_properties, $array_user, $array_soc, $array_thirdparty, $array_objet, $array_other);
585 complete_substitutions_array($tmparray, $outputlangs, $object);
586
587 foreach ($tmparray as $key => $value) {
588 try {
589 if (preg_match('/logo$/', $key)) { // Image
590 if (file_exists($value)) {
591 $odfHandler->setImage($key, $value);
592 } else {
593 $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
594 }
595 } else { // Text
596 $odfHandler->setVars($key, $value, true, 'UTF-8');
597 }
598 } catch (OdfException $e) {
599 dol_syslog($e->getMessage(), LOG_INFO);
600 }
601 }
602
603 // Replace tags of lines for tasks
604 try {
605 // Security check
606 $socid = 0;
607 if (!empty($project->fk_soc)) {
608 $socid = $project->fk_soc;
609 }
610
611 $tmparray = $this->get_substitutionarray_tasks($object, $outputlangs);
612 complete_substitutions_array($tmparray, $outputlangs, $object);
613 foreach ($tmparray as $key => $val) {
614 try {
615 $odfHandler->setVars($key, $val, true, 'UTF-8');
616 } catch (OdfException $e) {
617 dol_syslog($e->getMessage(), LOG_INFO);
618 } catch (SegmentException $e) {
619 dol_syslog($e->getMessage(), LOG_INFO);
620 }
621 }
622
623 // Replace tags of lines for contacts task
624 $sourcearray = array('internal', 'external');
625 $contact_arrray = array();
626 foreach ($sourcearray as $source) {
627 $contact_temp = $object->liste_contact(-1, $source);
628 if ((is_array($contact_temp) && count($contact_temp) > 0)) {
629 $contact_arrray = array_merge($contact_arrray, $contact_temp);
630 }
631 }
632 if ((is_array($contact_arrray) && count($contact_arrray) > 0)) {
633 $listlinestaskres = $odfHandler->setSegment('tasksressources');
634
635 foreach ($contact_arrray as $contact) {
636 if ($contact['source'] == 'internal') {
637 $objectdetail = new User($this->db);
638 $objectdetail->fetch($contact['id']);
639 $contact['socname'] = $mysoc->name;
640 } elseif ($contact['source'] == 'external') {
641 $objectdetail = new Contact($this->db);
642 $objectdetail->fetch($contact['id']);
643
644 $soc = new Societe($this->db);
645 $soc->fetch($contact['socid']);
646 $contact['socname'] = $soc->name;
647 }
648 $contact['fullname'] = $objectdetail->getFullName($outputlangs, 1);
649
650 $tmparray = $this->get_substitutionarray_tasksressource($contact, $outputlangs);
651
652 foreach ($tmparray as $key => $val) {
653 try {
654 $listlinestaskres->setVars($key, $val, true, 'UTF-8');
655 } catch (OdfException $e) {
656 dol_syslog($e->getMessage(), LOG_INFO);
657 } catch (SegmentException $e) {
658 dol_syslog($e->getMessage(), LOG_INFO);
659 }
660 }
661 $listlinestaskres->merge();
662 }
663 $odfHandler->mergeSegment($listlinestaskres);
664 }
665
666 // Time resources
667 $sql = "SELECT t.rowid, t.element_date as task_date, t.element_duration as task_duration, t.fk_user, t.note";
668 $sql .= ", u.lastname, u.firstname";
669 $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t";
670 $sql .= " , ".MAIN_DB_PREFIX."user as u";
671 $sql .= " WHERE t.fk_element =".((int) $object->id);
672 $sql .= " AND t.elementtype = 'task'";
673 $sql .= " AND t.fk_user = u.rowid";
674 $sql .= " ORDER BY t.element_date DESC";
675
676 $resql = $this->db->query($sql);
677 if ($resql) {
678 $num = $this->db->num_rows($resql);
679 $i = 0;
680 $tasks = array();
681 $listlinestasktime = $odfHandler->setSegment('taskstimes');
682 while ($i < $num) {
683 $row = $this->db->fetch_array($resql);
684 if (!empty($row['fk_user'])) {
685 $objectdetail = new User($this->db);
686 $objectdetail->fetch($row['fk_user']);
687 // TODO Use a cache to aoid fetch for same user
688 $row['fullcivname'] = $objectdetail->getFullName($outputlangs, 1);
689 } else {
690 $row['fullcivname'] = '';
691 }
692
693 $tmparray = $this->get_substitutionarray_taskstime($row, $outputlangs);
694
695 foreach ($tmparray as $key => $val) {
696 try {
697 $listlinestasktime->setVars($key, $val, true, 'UTF-8');
698 } catch (OdfException $e) {
699 dol_syslog($e->getMessage(), LOG_INFO);
700 } catch (SegmentException $e) {
701 dol_syslog($e->getMessage(), LOG_INFO);
702 }
703 }
704 $listlinestasktime->merge();
705 $i++;
706 }
707 $this->db->free($resql);
708
709 $odfHandler->mergeSegment($listlinestasktime);
710 }
711
712
713 // Replace tags of project files
714 $listtasksfiles = $odfHandler->setSegment('tasksfiles');
715
716 $upload_dir = $conf->project->dir_output.'/'.dol_sanitizeFileName($project->ref).'/'.dol_sanitizeFileName($object->ref);
717 $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', 'name', SORT_ASC, 1);
718
719
720 foreach ($filearray as $filedetail) {
721 $tmparray = $this->get_substitutionarray_task_file($filedetail, $outputlangs);
722 //dol_syslog(get_class($this).'::main $tmparray'.var_export($tmparray,true));
723 foreach ($tmparray as $key => $val) {
724 try {
725 $listtasksfiles->setVars($key, $val, true, 'UTF-8');
726 } catch (OdfException $e) {
727 dol_syslog($e->getMessage(), LOG_INFO);
728 } catch (SegmentException $e) {
729 dol_syslog($e->getMessage(), LOG_INFO);
730 }
731 }
732 $listtasksfiles->merge();
733 }
734 //$listlines->merge();
735
736 $odfHandler->mergeSegment($listtasksfiles);
737 } catch (OdfException $e) {
738 $this->error = $e->getMessage();
739 dol_syslog($this->error, LOG_WARNING);
740 return -1;
741 }
742
743
744
745 // Replace tags of project files
746 try {
747 $listlines = $odfHandler->setSegment('projectfiles');
748
749 $upload_dir = $conf->project->dir_output.'/'.dol_sanitizeFileName($object->ref);
750 $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', 'name', SORT_ASC, 1);
751
752
753 foreach ($filearray as $filedetail) {
754 //dol_syslog(get_class($this).'::main $filedetail'.var_export($filedetail,true));
755 $tmparray = $this->get_substitutionarray_project_file($filedetail, $outputlangs);
756
757 foreach ($tmparray as $key => $val) {
758 try {
759 $listlines->setVars($key, $val, true, 'UTF-8');
760 } catch (OdfException $e) {
761 dol_syslog($e->getMessage(), LOG_INFO);
762 } catch (SegmentException $e) {
763 dol_syslog($e->getMessage(), LOG_INFO);
764 }
765 }
766 $listlines->merge();
767 }
768 $odfHandler->mergeSegment($listlines);
769 } catch (OdfException $e) {
770 $this->error = $e->getMessage();
771 dol_syslog($this->error, LOG_WARNING);
772 return -1;
773 }
774
775 // Replace tags of lines for contacts
776 $sourcearray = array('internal', 'external');
777 $contact_arrray = array();
778 foreach ($sourcearray as $source) {
779 $contact_temp = $project->liste_contact(-1, $source);
780 if ((is_array($contact_temp) && count($contact_temp) > 0)) {
781 $contact_arrray = array_merge($contact_arrray, $contact_temp);
782 }
783 }
784 if ((is_array($contact_arrray) && count($contact_arrray) > 0)) {
785 try {
786 $listlines = $odfHandler->setSegment('projectcontacts');
787
788 foreach ($contact_arrray as $contact) {
789 if ($contact['source'] == 'internal') {
790 $objectdetail = new User($this->db);
791 $objectdetail->fetch($contact['id']);
792 $contact['socname'] = $mysoc->name;
793 } elseif ($contact['source'] == 'external') {
794 $objectdetail = new Contact($this->db);
795 $objectdetail->fetch($contact['id']);
796
797 $soc = new Societe($this->db);
798 $soc->fetch($contact['socid']);
799 $contact['socname'] = $soc->name;
800 }
801 $contact['fullname'] = $objectdetail->getFullName($outputlangs, 1);
802
803 $tmparray = $this->get_substitutionarray_project_contacts($contact, $outputlangs);
804
805 foreach ($tmparray as $key => $val) {
806 try {
807 $listlines->setVars($key, $val, true, 'UTF-8');
808 } catch (OdfException $e) {
809 dol_syslog($e->getMessage(), LOG_INFO);
810 } catch (SegmentException $e) {
811 dol_syslog($e->getMessage(), LOG_INFO);
812 }
813 }
814 $listlines->merge();
815 }
816 $odfHandler->mergeSegment($listlines);
817 } catch (OdfException $e) {
818 $this->error = $e->getMessage();
819 dol_syslog($this->error, LOG_WARNING);
820 return -1;
821 }
822 }
823
824
825 // Call the beforeODTSave hook
826 $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
827 $reshook = $hookmanager->executeHooks('beforeODTSave', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
828
829
830 // Write new file
831 if (getDolGlobalString('MAIN_ODT_AS_PDF')) {
832 try {
833 $odfHandler->exportAsAttachedPDF($file);
834 } catch (Exception $e) {
835 $this->error = $e->getMessage();
836 dol_syslog($e->getMessage(), LOG_INFO);
837 return -1;
838 }
839 } else {
840 try {
841 $odfHandler->saveToDisk($file);
842 } catch (Exception $e) {
843 $this->error = $e->getMessage();
844 dol_syslog($e->getMessage(), LOG_INFO);
845 return -1;
846 }
847 }
848 $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
849 $reshook = $hookmanager->executeHooks('afterODTCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
850
851 dolChmod($file);
852
853 $odfHandler = null; // Destroy object
854
855 $this->result = array('fullpath' => $file);
856
857 return 1; // Success
858 } else {
859 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
860 return -1;
861 }
862 }
863
864 return -1;
865 }
866}
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.
Class to manage hooks.
Parent class for task models.
Class to manage projects.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Class to manage Dolibarr users.
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.
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 $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after 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.
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:137
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:140
getMaxFileSizeArray()
Return the max allowed for file upload.