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