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