dolibarr 21.0.3
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 if ($mysoc === null) {
125 dol_syslog(get_class($this).'::__construct() Global $mysoc should not be null.'. getCallerInfoString(), LOG_ERR);
126 return;
127 }
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 $extrafields;
150
151 if (!$object instanceof Project) {
152 dol_syslog("Expected Project object, got ".gettype($object), LOG_ERR);
153 return array();
154 }
155
156 $resarray = array(
157 $array_key.'_id' => $object->id,
158 $array_key.'_ref' => $object->ref,
159 $array_key.'_title' => $object->title,
160 $array_key.'_description' => $object->description,
161 $array_key.'_date_creation' => dol_print_date($object->date_c, 'day'),
162 $array_key.'_date_modification' => dol_print_date($object->date_m, 'day'),
163 $array_key.'_date_start' => dol_print_date($object->date_start, 'day'),
164 $array_key.'_date_end' => dol_print_date($object->date_end, 'day'),
165 $array_key.'_note_private' => $object->note_private,
166 $array_key.'_note_public' => $object->note_public,
167 $array_key.'_public' => $object->public,
168 $array_key.'_statut' => $object->getLibStatut()
169 );
170
171 // Retrieve extrafields
172 if (is_array($object->array_options) && count($object->array_options)) {
173 $object->fetch_optionals();
174
175 $resarray = $this->fill_substitutionarray_with_extrafields($object, $resarray, $extrafields, $array_key, $outputlangs);
176 }
177
178 return $resarray;
179 }
180
181 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
190 public function get_substitutionarray_tasks($task, $outputlangs, $array_key = 'task')
191 {
192 // phpcs:enable
193 global $extrafields;
194
195 $resarray = array(
196 'task_ref' => $task->ref,
197 'task_fk_project' => $task->fk_project,
198 'task_projectref' => $task->projectref,
199 'task_projectlabel' => $task->projectlabel,
200 'task_label' => $task->label,
201 'task_description' => $task->description,
202 'task_fk_parent' => $task->fk_task_parent,
203 'task_duration' => $task->duration_effective,
204 'task_duration_formated' => convertSecondToTime($task->duration_effective, 'allhourmin'),
205 'task_planned_workload' => $task->planned_workload,
206 'task_planned_workload_formated' => convertSecondToTime($task->planned_workload, 'allhourmin'),
207 'task_progress' => $task->progress,
208 'task_public' => $task->public,
209 'task_date_start' => dol_print_date($task->date_start, 'day'),
210 'task_date_end' => dol_print_date($task->date_end, 'day'),
211 'task_note_private' => (string) $task->note_private,
212 'task_note_public' => (string) $task->note_public
213 );
214
215 // Retrieve extrafields
216 if (is_array($task->array_options) && count($task->array_options)) {
217 $task->fetch_optionals();
218
219 $resarray = $this->fill_substitutionarray_with_extrafields($task, $resarray, $extrafields, $array_key, $outputlangs);
220 }
221
222 return $resarray;
223 }
224
225 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
233 public function get_substitutionarray_project_contacts($contact, $outputlangs)
234 {
235 // phpcs:enable
236 return array(
237 'projcontacts_id' => $contact['id'],
238 'projcontacts_rowid' => $contact['rowid'],
239 'projcontacts_role' => $contact['libelle'],
240 'projcontacts_lastname' => $contact['lastname'],
241 'projcontacts_firstname' => $contact['firstname'],
242 'projcontacts_fullcivname' => $contact['fullname'],
243 'projcontacts_socname' => $contact['socname'],
244 'projcontacts_email' => $contact['email']
245 );
246 }
247
248 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
256 public function get_substitutionarray_project_file($file, $outputlangs)
257 {
258 // phpcs:enable
259 return array(
260 'projfile_name' => $file['name'],
261 'projfile_date' => dol_print_date($file['date'], 'day'),
262 'projfile_size' => $file['size']
263 );
264 }
265
266 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
274 public function get_substitutionarray_project_reference($refdetail, $outputlangs)
275 {
276 // phpcs:enable
277 return array(
278 'projref_type' => $refdetail['type'],
279 'projref_ref' => $refdetail['ref'],
280 'projref_date' => dol_print_date($refdetail['date'], 'day'),
281 'projref_socname' => $refdetail['socname'],
282 'projref_amountht' => price($refdetail['amountht'], 0, $outputlangs),
283 'projref_amountttc' => price($refdetail['amountttc'], 0, $outputlangs),
284 'projref_status' => $refdetail['status']
285 );
286 }
287
288 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
296 public function get_substitutionarray_tasksressource($taskresource, $outputlangs)
297 {
298 // phpcs:enable
299
300 //dol_syslog(get_class($this).'::get_substitutionarray_tasksressource taskressource='.var_export($taskressource,true),LOG_DEBUG);
301 return array(
302 'taskressource_rowid' => $taskresource['rowid'],
303 'taskressource_role' => $taskresource['libelle'],
304 'taskressource_lastname' => $taskresource['lastname'],
305 'taskressource_firstname' => $taskresource['firstname'],
306 'taskressource_fullcivname' => $taskresource['fullname'],
307 'taskressource_socname' => $taskresource['socname'],
308 'taskressource_email' => $taskresource['email']
309 );
310 }
311
312 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
320 public function get_substitutionarray_taskstime($tasktime, $outputlangs)
321 {
322 // phpcs:enable
323 global $conf;
324
325 return array(
326 'tasktime_rowid' => $tasktime['rowid'],
327 'tasktime_task_date' => dol_print_date($tasktime['task_date'], 'day'),
328 'tasktime_task_duration' => convertSecondToTime($tasktime['task_duration'], 'all'),
329 'tasktime_note' => $tasktime['note'],
330 'tasktime_fk_user' => $tasktime['fk_user'],
331 'tasktime_user_name' => $tasktime['lastname'],
332 'tasktime_user_first' => $tasktime['firstname'],
333 'tasktime_fullcivname' => $tasktime['fullcivname']
334 );
335 }
336
337 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
345 public function get_substitutionarray_task_file($file, $outputlangs)
346 {
347 // phpcs:enable
348 return array(
349 'tasksfile_name' => $file['name'],
350 'tasksfile_date' => dol_print_date($file['date'], 'day'),
351 'tasksfile_size' => $file['size']
352 );
353 }
354
355
362 public function info($langs)
363 {
364 global $conf, $langs;
365
366 // Load translation files required by the page
367 $langs->loadLangs(array("errors", "companies"));
368
369 $form = new Form($this->db);
370
371 $texte = $this->description.".<br>\n";
372 $texte .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" enctype="multipart/form-data">';
373 $texte .= '<input type="hidden" name="token" value="'.newToken().'">';
374 $texte .= '<input type="hidden" name="page_y" value="">';
375 $texte .= '<input type="hidden" name="action" value="setModuleOptions">';
376 $texte .= '<input type="hidden" name="param1" value="PROJECT_TASK_ADDON_PDF_ODT_PATH">';
377 $texte .= '<table class="nobordernopadding centpercent">';
378
379 // List of directories area
380 $texte .= '<tr><td>';
381 $texttitle = $langs->trans("ListOfDirectories");
382 $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->PROJECT_TASK_ADDON_PDF_ODT_PATH)));
383 $listoffiles = array();
384 foreach ($listofdir as $key => $tmpdir) {
385 $tmpdir = trim($tmpdir);
386 $tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir);
387 if (!$tmpdir) {
388 unset($listofdir[$key]);
389 continue;
390 }
391 if (!is_dir($tmpdir)) {
392 $texttitle .= img_warning($langs->trans("ErrorDirNotFound", $tmpdir), '');
393 } else {
394 $tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.(ods|odt)');
395 if (count($tmpfiles)) {
396 $listoffiles = array_merge($listoffiles, $tmpfiles);
397 }
398 }
399 }
400 $texthelp = $langs->trans("ListOfDirectoriesForModelGenODT");
401 $texthelp .= '<br><br><span class="opacitymedium">'.$langs->trans("ExampleOfDirectoriesForModelGen").'</span>';
402 // Add list of substitution keys
403 $texthelp .= '<br>'.$langs->trans("FollowingSubstitutionKeysCanBeUsed").'<br>';
404 $texthelp .= $langs->transnoentitiesnoconv("FullListOnOnlineDocumentation"); // This contains an url, we don't modify it
405
406 $texte .= $form->textwithpicto($texttitle, $texthelp, 1, 'help', '', 1, 3, $this->name);
407 $texte .= '<div><div style="display: inline-block; min-width: 100px; vertical-align: middle;">';
408 $texte .= '<textarea class="flat" cols="60" name="value1">';
409 $texte .= getDolGlobalString('PROJECT_TASK_ADDON_PDF_ODT_PATH');
410 $texte .= '</textarea>';
411 $texte .= '</div><div style="display: inline-block; vertical-align: middle;">';
412 $texte .= '<input type="submit" class="button button-edit reposition smallpaddingimp" name="modify" value="'.dol_escape_htmltag($langs->trans("Modify")).'">';
413 $texte .= '<br></div></div>';
414
415 // Scan directories
416 $nbofiles = count($listoffiles);
417 if (getDolGlobalString('PROJECT_TASK_ADDON_PDF_ODT_PATH')) {
418 $texte .= $langs->trans("NumberOfModelFilesFound").': <b>';
419 //$texte.=$nbofiles?'<a id="a_'.get_class($this).'" href="#">':'';
420 $texte .= $nbofiles;
421 //$texte.=$nbofiles?'</a>':'';
422 $texte .= '</b>';
423 }
424
425 if ($nbofiles) {
426 $texte .= '<div id="div_'.get_class($this).'" class="hiddenx">';
427 // Show list of found files
428 foreach ($listoffiles as $file) {
429 $texte .= '- '.$file['name'].' <a href="'.DOL_URL_ROOT.'/document.php?modulepart=doctemplates&file=tasks/'.urlencode(basename($file['name'])).'">'.img_picto('', 'listlight').'</a>';
430 $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>';
431 $texte .= '<br>';
432 }
433 $texte .= '</div>';
434 }
435 // Add input to upload a new template file.
436 $texte .= '<div>'.$langs->trans("UploadNewTemplate");
437 $maxfilesizearray = getMaxFileSizeArray();
438 $maxmin = $maxfilesizearray['maxmin'];
439 if ($maxmin > 0) {
440 $texte .= '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
441 }
442 $texte .= ' <input type="file" name="uploadfile">';
443 $texte .= '<input type="hidden" value="PROJECT_TASK_ADDON_PDF_ODT_PATH" name="keyforuploaddir">';
444 $texte .= '<input type="submit" class="button smallpaddingimp reposition" value="'.dol_escape_htmltag($langs->trans("Upload")).'" name="upload">';
445 $texte .= '</div>';
446 $texte .= '</td>';
447
448 $texte .= '</tr>';
449
450 $texte .= '</table>';
451 $texte .= '</form>';
452
453 return $texte;
454 }
455
456 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
465 public function write_file($object, $outputlangs, $srctemplatepath = '')
466 {
467 // phpcs:enable
468 global $user, $langs, $conf, $mysoc, $hookmanager;
469
470 if (empty($srctemplatepath)) {
471 dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING);
472 return -1;
473 }
474
475 // Add odtgeneration hook
476 if (!is_object($hookmanager)) {
477 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
478 $hookmanager = new HookManager($this->db);
479 }
480 $hookmanager->initHooks(array('odtgeneration'));
481 global $action;
482
483 if (!is_object($outputlangs)) {
484 $outputlangs = $langs;
485 }
486 $sav_charset_output = $outputlangs->charset_output;
487 $outputlangs->charset_output = 'UTF-8';
488
489 // Load translation files required by the page
490 $outputlangs->loadLangs(array("main", "dict", "companies", "projects"));
491
492 if ($conf->project->dir_output) {
493 // If $object is id instead of object
494 if (!is_object($object)) {
495 $id = $object;
496 $object = new Task($this->db);
497 $result = $object->fetch($id);
498 if ($result < 0) {
499 dol_print_error($this->db, $object->error);
500 return -1;
501 }
502 }
503 $project = new Project($this->db);
504 $project->fetch($object->fk_project);
505 $project->fetch_thirdparty();
506
507 $dir = $conf->project->dir_output."/".$project->ref."/";
508 $objectref = dol_sanitizeFileName($object->ref);
509 if (!preg_match('/specimen/i', $objectref)) {
510 $dir .= "/".$objectref;
511 }
512 $file = $dir."/".$objectref.".odt";
513
514 if (!file_exists($dir)) {
515 if (dol_mkdir($dir) < 0) {
516 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
517 return -1;
518 }
519 }
520
521
522 if (file_exists($dir)) {
523 //print "srctemplatepath=".$srctemplatepath; // Src filename
524 $newfile = basename($srctemplatepath);
525 $newfiletmp = preg_replace('/\.(ods|odt)/i', '', $newfile);
526 $newfiletmp = preg_replace('/template_/i', '', $newfiletmp);
527 $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp);
528 $newfiletmp = $objectref . '_' . $newfiletmp;
529 //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt';
530 $file = $dir . '/' . $newfiletmp . '.odt';
531 //print "newdir=".$dir;
532 //print "newfile=".$newfile;
533 //print "file=".$file;
534 //print "conf->societe->dir_temp=".$conf->societe->dir_temp;
535
536 dol_mkdir($conf->project->dir_temp);
537 if (!is_writable($conf->project->dir_temp)) {
538 $this->error = $langs->transnoentities("ErrorFailedToWriteInTempDirectory", $conf->project->dir_temp);
539 dol_syslog('Error in write_file: ' . $this->error, LOG_ERR);
540 return -1;
541 }
542
543 $socobject = $project->thirdparty;
544
545 // Make substitution
546 $substitutionarray = array(
547 '__FROM_NAME__' => $this->emetteur->name,
548 '__FROM_EMAIL__' => $this->emetteur->email,
549 );
550 complete_substitutions_array($substitutionarray, $langs, $object);
551 // Call the ODTSubstitution hook
552 $tmparray = array();
553 $action = '';
554 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
555 $reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
556
557 // Open and load template
558 require_once ODTPHP_PATH.'odf.php';
559 try {
560 $odfHandler = new Odf(
561 $srctemplatepath,
562 array(
563 'PATH_TO_TMP' => $conf->project->dir_temp,
564 'ZIP_PROXY' => getDolGlobalString('MAIN_ODF_ZIP_PROXY', 'PclZipProxy'), // PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy.
565 'DELIMITER_LEFT' => '{',
566 'DELIMITER_RIGHT' => '}'
567 )
568 );
569 } catch (Exception $e) {
570 $this->error = $e->getMessage();
571 return -1;
572 }
573 // After construction $odfHandler->contentXml contains content and
574 // [!-- BEGIN row.lines --]*[!-- END row.lines --] has been replaced by
575 // [!-- BEGIN lines --]*[!-- END lines --]
576 //print html_entity_decode($odfHandler->__toString());
577 //print exit;
578
579
580 // Define substitution array
581 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
582 $array_object_from_properties = $this->get_substitutionarray_each_var_object($object, $outputlangs);
583 $array_objet = $this->get_substitutionarray_object($project, $outputlangs);
584 $array_user = $this->get_substitutionarray_user($user, $outputlangs);
585 $array_soc = $this->get_substitutionarray_mysoc($mysoc, $outputlangs);
586 $array_thirdparty = $this->get_substitutionarray_thirdparty($socobject, $outputlangs);
587 $array_other = $this->get_substitutionarray_other($outputlangs);
588
589 $tmparray = array_merge($substitutionarray, $array_object_from_properties, $array_user, $array_soc, $array_thirdparty, $array_objet, $array_other);
590 complete_substitutions_array($tmparray, $outputlangs, $object);
591
592 foreach ($tmparray as $key => $value) {
593 try {
594 if (preg_match('/logo$/', $key)) { // Image
595 if (file_exists($value)) {
596 $odfHandler->setImage($key, $value);
597 } else {
598 $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
599 }
600 } else { // Text
601 $odfHandler->setVars($key, $value, true, 'UTF-8');
602 }
603 } catch (OdfException $e) {
604 dol_syslog($e->getMessage(), LOG_INFO);
605 }
606 }
607
608 // Replace tags of lines for tasks
609 try {
610 // Security check
611 $socid = 0;
612 if (!empty($project->fk_soc)) {
613 $socid = $project->fk_soc;
614 }
615
616 $tmparray = $this->get_substitutionarray_tasks($object, $outputlangs);
617 complete_substitutions_array($tmparray, $outputlangs, $object);
618 foreach ($tmparray as $key => $val) {
619 try {
620 $odfHandler->setVars($key, $val, true, 'UTF-8');
621 } catch (OdfException $e) {
622 dol_syslog($e->getMessage(), LOG_INFO);
623 }
624 }
625
626 // Replace tags of lines for contacts task
627 $sourcearray = array('internal', 'external');
628 $contact_arrray = array();
629 foreach ($sourcearray as $source) {
630 $contact_temp = $object->liste_contact(-1, $source);
631 if ((is_array($contact_temp) && count($contact_temp) > 0)) {
632 $contact_arrray = array_merge($contact_arrray, $contact_temp);
633 }
634 }
635 // Check for segment
636 $foundtagforlines = 1;
637 try {
638 $listlinestaskres = $odfHandler->setSegment('tasksressources');
639 } catch (OdfExceptionSegmentNotFound $e) {
640 // We may arrive here if tags for lines not present into template
641 $foundtagforlines = 0;
642 dol_syslog($e->getMessage(), LOG_INFO);
643 }
644 if ($foundtagforlines && (is_array($contact_arrray) && count($contact_arrray) > 0)) {
645 foreach ($contact_arrray as $contact) {
646 if ($contact['source'] == 'internal') {
647 $objectdetail = new User($this->db);
648 $objectdetail->fetch($contact['id']);
649 $contact['socname'] = $mysoc->name;
650 } elseif ($contact['source'] == 'external') {
651 $objectdetail = new Contact($this->db);
652 $objectdetail->fetch($contact['id']);
653
654 $soc = new Societe($this->db);
655 $soc->fetch($contact['socid']);
656 $contact['socname'] = $soc->name;
657 }
658 $contact['fullname'] = $objectdetail->getFullName($outputlangs, 1);
659
660 $tmparray = $this->get_substitutionarray_tasksressource($contact, $outputlangs);
661
662 foreach ($tmparray as $key => $val) {
663 try {
664 $listlinestaskres->setVars($key, $val, true, 'UTF-8');
665 } catch (SegmentException $e) {
666 dol_syslog($e->getMessage(), LOG_INFO);
667 }
668 }
669 $listlinestaskres->merge();
670 }
671 $odfHandler->mergeSegment($listlinestaskres);
672 }
673
674 // Check for segment
675 $foundtagforlines = 1;
676 try {
677 $listlinestasktime = $odfHandler->setSegment('taskstimes');
678 } catch (OdfExceptionSegmentNotFound $e) {
679 // We may arrive here if tags for lines not present into template
680 $foundtagforlines = 0;
681 dol_syslog($e->getMessage(), LOG_INFO);
682 }
683
684 // Time resources
685 $sql = "SELECT t.rowid, t.element_date as task_date, t.element_duration as task_duration, t.fk_user, t.note";
686 $sql .= ", u.lastname, u.firstname";
687 $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t";
688 $sql .= " , ".MAIN_DB_PREFIX."user as u";
689 $sql .= " WHERE t.fk_element =".((int) $object->id);
690 $sql .= " AND t.elementtype = 'task'";
691 $sql .= " AND t.fk_user = u.rowid";
692 $sql .= " ORDER BY t.element_date DESC";
693
694 $resql = $this->db->query($sql);
695 if ($foundtagforlines && $resql) {
696 $num = $this->db->num_rows($resql);
697 $i = 0;
698 $tasks = array();
699
700 while ($i < $num) {
701 $row = $this->db->fetch_array($resql);
702 if (!empty($row['fk_user'])) {
703 $objectdetail = new User($this->db);
704 $objectdetail->fetch($row['fk_user']);
705 // TODO Use a cache to avoid fetch for same user
706 $row['fullcivname'] = $objectdetail->getFullName($outputlangs, 1);
707 } else {
708 $row['fullcivname'] = '';
709 }
710
711 $tmparray = $this->get_substitutionarray_taskstime($row, $outputlangs);
712
713 foreach ($tmparray as $key => $val) {
714 try {
715 $listlinestasktime->setVars($key, $val, true, 'UTF-8');
716 } catch (SegmentException $e) {
717 dol_syslog($e->getMessage(), LOG_INFO);
718 }
719 }
720 $listlinestasktime->merge();
721 $i++;
722 }
723 $this->db->free($resql);
724
725 $odfHandler->mergeSegment($listlinestasktime);
726 }
727
728
729 // Replace tags of project files
730 // Check for segment
731 $foundtagforlines = 1;
732 try {
733 $listtasksfiles = $odfHandler->setSegment('tasksfiles');
734 } catch (OdfExceptionSegmentNotFound $e) {
735 // We may arrive here if tags for lines not present into template
736 $foundtagforlines = 0;
737 dol_syslog($e->getMessage(), LOG_INFO);
738 }
739 if ($foundtagforlines) {
740 $upload_dir = $conf->project->dir_output.'/'.dol_sanitizeFileName($project->ref).'/'.dol_sanitizeFileName($object->ref);
741 $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', 'name', SORT_ASC, 1);
742
743 foreach ($filearray as $filedetail) {
744 $tmparray = $this->get_substitutionarray_task_file($filedetail, $outputlangs);
745 //dol_syslog(get_class($this).'::main $tmparray'.var_export($tmparray,true));
746 foreach ($tmparray as $key => $val) {
747 try {
748 $listtasksfiles->setVars($key, $val, true, 'UTF-8');
749 } catch (SegmentException $e) {
750 dol_syslog($e->getMessage(), LOG_INFO);
751 }
752 }
753 $listtasksfiles->merge();
754 }
755 //$listlines->merge();
756
757 $odfHandler->mergeSegment($listtasksfiles);
758 }
759 } catch (OdfException $e) {
760 $this->error = $e->getMessage();
761 dol_syslog($this->error, LOG_WARNING);
762 return -1;
763 }
764
765
766 // Replace tags of project files
767 // Check for segment
768 $foundtagforlines = 1;
769 try {
770 $listlines = $odfHandler->setSegment('projectfiles');
771 } catch (OdfExceptionSegmentNotFound $e) {
772 // We may arrive here if tags for lines not present into template
773 $foundtagforlines = 0;
774 dol_syslog($e->getMessage(), LOG_INFO);
775 }
776 if ($foundtagforlines) {
777 try {
778 $upload_dir = $conf->project->dir_output.'/'.dol_sanitizeFileName($object->ref);
779 $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', 'name', SORT_ASC, 1);
780
781 foreach ($filearray as $filedetail) {
782 //dol_syslog(get_class($this).'::main $filedetail'.var_export($filedetail,true));
783 $tmparray = $this->get_substitutionarray_project_file($filedetail, $outputlangs);
784
785 foreach ($tmparray as $key => $val) {
786 try {
787 $listlines->setVars($key, $val, true, 'UTF-8');
788 } catch (SegmentException $e) {
789 dol_syslog($e->getMessage(), LOG_INFO);
790 }
791 }
792 $listlines->merge();
793 }
794 $odfHandler->mergeSegment($listlines);
795 } catch (OdfException $e) {
796 $this->error = $e->getMessage();
797 dol_syslog($this->error, LOG_WARNING);
798 return -1;
799 }
800 }
801
802 // Replace tags of lines for contacts
803 $sourcearray = array('internal', 'external');
804 $contact_arrray = array();
805 foreach ($sourcearray as $source) {
806 $contact_temp = $project->liste_contact(-1, $source);
807 if ((is_array($contact_temp) && count($contact_temp) > 0)) {
808 $contact_arrray = array_merge($contact_arrray, $contact_temp);
809 }
810 }
811 // Check for segment
812 $foundtagforlines = 1;
813 try {
814 $listlines = $odfHandler->setSegment('projectcontacts');
815 } catch (OdfExceptionSegmentNotFound $e) {
816 // We may arrive here if tags for lines not present into template
817 $foundtagforlines = 0;
818 dol_syslog($e->getMessage(), LOG_INFO);
819 }
820 if ($foundtagforlines && (is_array($contact_arrray) && count($contact_arrray) > 0)) {
821 try {
822 foreach ($contact_arrray as $contact) {
823 if ($contact['source'] == 'internal') {
824 $objectdetail = new User($this->db);
825 $objectdetail->fetch($contact['id']);
826 $contact['socname'] = $mysoc->name;
827 } elseif ($contact['source'] == 'external') {
828 $objectdetail = new Contact($this->db);
829 $objectdetail->fetch($contact['id']);
830
831 $soc = new Societe($this->db);
832 $soc->fetch($contact['socid']);
833 $contact['socname'] = $soc->name;
834 }
835 $contact['fullname'] = $objectdetail->getFullName($outputlangs, 1);
836
837 $tmparray = $this->get_substitutionarray_project_contacts($contact, $outputlangs);
838
839 foreach ($tmparray as $key => $val) {
840 try {
841 $listlines->setVars($key, $val, true, 'UTF-8');
842 } catch (SegmentException $e) {
843 dol_syslog($e->getMessage(), LOG_INFO);
844 }
845 }
846 $listlines->merge();
847 }
848 $odfHandler->mergeSegment($listlines);
849 } catch (OdfException $e) {
850 $this->error = $e->getMessage();
851 dol_syslog($this->error, LOG_WARNING);
852 return -1;
853 }
854 }
855
856
857 // Call the beforeODTSave hook
858 $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
859 $reshook = $hookmanager->executeHooks('beforeODTSave', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
860
861
862 // Write new file
863 if (getDolGlobalString('MAIN_ODT_AS_PDF')) {
864 try {
865 $odfHandler->exportAsAttachedPDF($file);
866 } catch (Exception $e) {
867 $this->error = $e->getMessage();
868 dol_syslog($e->getMessage(), LOG_INFO);
869 return -1;
870 }
871 } else {
872 try {
873 $odfHandler->saveToDisk($file);
874 } catch (Exception $e) {
875 $this->error = $e->getMessage();
876 dol_syslog($e->getMessage(), LOG_INFO);
877 return -1;
878 }
879 }
880 $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
881 $reshook = $hookmanager->executeHooks('afterODTCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
882
883 dolChmod($file);
884
885 $odfHandler = null; // Destroy object
886
887 $this->result = array('fullpath' => $file);
888
889 return 1; // Success
890 } else {
891 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
892 return -1;
893 }
894 }
895
896 return -1;
897 }
898}
$id
Definition account.php:48
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
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.
write_file($object, $outputlangs, $srctemplatepath='')
Function to build a document on disk using the generic odt module.
info($langs)
Return description of a 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:244
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_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
getCallerInfoString()
Get caller info as a string that can be appended to a log message.
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_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.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a 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)
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:150
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:153
getMaxFileSizeArray()
Return the max allowed for file upload.