dolibarr 25.0.0-alpha
doc_generic_project_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-2023 Charlene Benke <charlene@patas-monkey.com>
6 * Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2023 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
8 * Copyright (C) 2024-2026 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.'/projet/class/project.class.php';
33require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
34require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
35require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
36require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php';
41require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
42if (isModEnabled("propal")) {
43 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
44}
45if (isModEnabled('invoice')) {
46 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
47 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
48}
49if (isModEnabled('order')) {
50 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
51}
52if (isModEnabled("supplier_proposal")) {
53 require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php';
54}
55if ((isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD')) || isModEnabled("supplier_invoice")) {
56 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
57}
58if ((isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD')) || 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('agenda')) {
68 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
69}
70if (isModEnabled('shipping')) {
71 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
72}
73if (isModEnabled('expensereport')) {
74 require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereportline.class.php';
75}
76if (isModEnabled('don')) {
77 require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
78}
79if (isModEnabled('loan')) {
80 require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php';
81}
82if (isModEnabled('tax')) {
83 require_once DOL_DOCUMENT_ROOT.'/compta/sociales/class/chargesociales.class.php';
84}
85if (isModEnabled('stock')) {
86 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
87}
88
93{
98 public $version = 'dolibarr';
99
100
106 public function __construct($db)
107 {
108 global $langs, $mysoc;
109
110 // Load traductions files required by page
111 $langs->loadLangs(array("companies", "main"));
112
113 $this->db = $db;
114 $this->name = "ODT templates";
115 $this->description = $langs->trans("DocumentModelOdt");
116 $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
117 $this->scandir = 'PROJECT_ADDON_PDF_ODT_PATH'; // Name of constant that is used to save list of directories to scan
118
119 // Page size for A4 format
120 $this->type = 'odt';
121 $this->page_largeur = 0;
122 $this->page_hauteur = 0;
123 $this->format = array($this->page_largeur, $this->page_hauteur);
124 $this->marge_gauche = 0;
125 $this->marge_droite = 0;
126 $this->marge_haute = 0;
127 $this->marge_basse = 0;
128
129 $this->option_logo = 1; // Display logo
130 $this->option_tva = 0; // Manage the vat option COMMANDE_TVAOPTION
131 $this->option_modereg = 0; // Display payment mode
132 $this->option_condreg = 0; // Display payment terms
133 $this->option_multilang = 1; // Available in several languages
134 $this->option_escompte = 0; // Displays if there has been a discount
135 $this->option_credit_note = 0; // Support credit notes
136 $this->option_freetext = 1; // Support add of a personalised text
137 $this->option_draft_watermark = 0; // Support add of a watermark on drafts
138
139 if ($mysoc === null) {
140 dol_syslog(get_class($this).'::__construct() Global $mysoc should not be null.'. getCallerInfoString(), LOG_ERR);
141 return;
142 }
143
144 // Get source company
145 $this->emetteur = $mysoc;
146 if (!$this->emetteur->country_code) {
147 $this->emetteur->country_code = substr($langs->defaultlang, -2); // Par default, si n'etait pas defini
148 }
149 }
150
151 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
160 public function get_substitutionarray_object($object, $outputlangs, $array_key = 'object')
161 {
162 // phpcs:enable
163 if (!$object instanceof Project) {
164 dol_syslog("Expected Project object, got ".gettype($object), LOG_ERR);
165 return array();
166 }
167
168 $resarray = array(
169 $array_key.'_id' => (int) $object->id,
170 $array_key.'_ref' => (string) $object->ref,
171 $array_key.'_title' => (string) $object->title,
172 $array_key.'_description' => (string) $object->description,
173 $array_key.'_date_creation' => dol_print_date($object->date_c, 'day'),
174 $array_key.'_date_modification' => dol_print_date($object->date_m, 'day'),
175 $array_key.'_date_start' => dol_print_date($object->date_start, 'day'),
176 $array_key.'_date_end' => dol_print_date($object->date_end, 'day'),
177 $array_key.'_note_private' => (string) $object->note_private,
178 $array_key.'_note_public' => (string) $object->note_public,
179 $array_key.'_public' => (string) $object->public,
180 $array_key.'_statut' => $object->getLibStatut()
181 );
182
183 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
184 $extrafields = new ExtraFields($this->db);
185 $extrafields->fetch_name_optionals_label($object->table_element, true);
186 $object->fetch_optionals();
187
188 $resarray = $this->fill_substitutionarray_with_extrafields($object, $resarray, $extrafields, $array_key, $outputlangs);
189
190 return $resarray;
191 }
192
193 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
201 public function get_substitutionarray_tasks(Task $task, $outputlangs)
202 {
203 // phpcs:enable
204 $resarray = array(
205 'task_ref' => $task->ref,
206 'task_fk_project' => $task->fk_project,
207 'task_projectref' => $task->projectref,
208 'task_projectlabel' => $task->projectlabel,
209 'task_label' => $task->label,
210 'task_description' => $task->description,
211 'task_fk_parent' => $task->fk_task_parent,
212 'task_duration' => $task->duration_effective,
213 'task_duration_hour' => convertSecondToTime($task->duration_effective, 'all'),
214 'task_planned_workload' => $task->planned_workload,
215 'task_planned_workload_hour' => convertSecondToTime($task->planned_workload, 'all'),
216 'task_progress' => $task->progress,
217 'task_public' => $task->public,
218 'task_date_start' => dol_print_date($task->date_start, 'day'),
219 'task_date_end' => dol_print_date($task->date_end, 'day'),
220 'task_note_private' => $task->note_private,
221 'task_note_public' => $task->note_public
222 );
223
224 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
225 $extrafields = new ExtraFields($this->db);
226 $extrafields->fetch_name_optionals_label($task->table_element, true);
227 $task->fetch_optionals();
228
229 $resarray = $this->fill_substitutionarray_with_extrafields($task, $resarray, $extrafields, 'task', $outputlangs);
230
231 return $resarray;
232 }
233
234 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
242 public function get_substitutionarray_project_contacts($contact, $outputlangs)
243 {
244 // phpcs:enable
245 $pc = 'projcontacts_'; // prefix to avoid typos
246
247 $ret = array(
248 $pc.'id' => $contact['id'],
249 $pc.'rowid' => $contact['rowid'],
250 $pc.'role' => $contact['libelle'],
251 $pc.'lastname' => $contact['lastname'],
252 $pc.'firstname' => $contact['firstname'],
253 $pc.'civility' => $contact['civility'],
254 $pc.'fullcivname' => $contact['fullname'],
255 $pc.'socname' => $contact['socname'],
256 $pc.'email' => $contact['email']
257 );
258
259 if ($contact['source'] == 'external') {
260 $ret[$pc.'isInternal'] = ''; // not internal
261
262 $ct = new Contact($this->db);
263 $ct->fetch($contact['id']);
264 $ret[$pc.'phone_pro'] = $ct->phone_pro;
265 $ret[$pc.'phone_perso'] = $ct->phone_perso;
266 $ret[$pc.'phone_mobile'] = $ct->phone_mobile;
267
268 // fetch external user extrafields
269 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
270 $extrafields = new ExtraFields($this->db);
271 $extrafields->fetch_name_optionals_label($ct->table_element, true);
272 $extrafields_num = $ct->fetch_optionals();
273 //dol_syslog(get_class($this)."::get_substitutionarray_project_contacts: ===== Number of Extrafields found: ".$extrafields_num, LOG_DEBUG);
274 foreach ($ct->array_options as $efkey => $efval) {
275 dol_syslog(get_class($this)."::get_substitutionarray_project_contacts: +++++ Extrafield ".$efkey." => ".$efval, LOG_DEBUG);
276 $ret[$pc.$efkey] = $efval; // add nothing else because it already comes as 'options_XX'
277 }
278 } elseif ($contact['source'] == 'internal') {
279 $ret[$pc.'isInternal'] = '1'; // this is an internal user
280
281 $ct = new User($this->db);
282 $ct->fetch($contact['id']);
283 $ret[$pc.'phone_pro'] = $ct->office_phone;
284 $ret[$pc.'phone_perso'] = '';
285 $ret[$pc.'phone_mobile'] = $ct->user_mobile;
286 // do internal users have extrafields ?
287 }
288 return $ret;
289 }
290
291 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
299 public function get_substitutionarray_project_file($file, $outputlangs)
300 {
301 // phpcs:enable
302 return array(
303 'projfile_name' => (string) $file['name'],
304 'projfile_date' => dol_print_date($file['date'], 'day'),
305 'projfile_size' => (int) $file['size']
306 );
307 }
308
309 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
317 public function get_substitutionarray_project_reference($refdetail, $outputlangs)
318 {
319 // phpcs:enable
320 return array(
321 'projref_type' => (string) $refdetail['type'],
322 'projref_ref' => (string) $refdetail['ref'],
323 'projref_date' => dol_print_date($refdetail['date'], 'day'),
324 'projref_socname' => (string) $refdetail['socname'],
325 'projref_amountht' => price($refdetail['amountht'], 0, $outputlangs),
326 'projref_amountttc' => price($refdetail['amountttc'], 0, $outputlangs),
327 'projref_status' => (int) $refdetail['status']
328 );
329 }
330
331 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
339 public function get_substitutionarray_tasksressource($taskresource, $outputlangs)
340 {
341 // phpcs:enable
342
343 //dol_syslog(get_class($this).'::get_substitutionarray_tasksressource taskressource='.var_export($taskressource,true),LOG_DEBUG);
344 return array(
345 'taskressource_rowid' => (int) $taskresource['rowid'],
346 'taskressource_role' => (string) $taskresource['libelle'],
347 'taskressource_lastname' => (string) $taskresource['lastname'],
348 'taskressource_firstname' => (string) $taskresource['firstname'],
349 'taskressource_fullcivname' => (string) $taskresource['fullname'],
350 'taskressource_socname' => (string) $taskresource['socname'],
351 'taskressource_email' => (string) $taskresource['email']
352 );
353 }
354
355 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
363 public function get_substitutionarray_taskstime($tasktime, $outputlangs)
364 {
365 // phpcs:enable
366 return array(
367 'tasktime_rowid' => (int) $tasktime['rowid'],
368 'tasktime_task_date' => dol_print_date($tasktime['task_date'], 'day'),
369 'tasktime_task_duration_sec' => (int) $tasktime['task_duration'],
370 'tasktime_task_duration' => convertSecondToTime($tasktime['task_duration'], 'all'),
371 'tasktime_note' => (string) $tasktime['note'],
372 'tasktime_fk_user' => (int) $tasktime['fk_user'],
373 'tasktime_user_name' => (string) $tasktime['name'],
374 'tasktime_user_first' => (string) $tasktime['firstname'],
375 'tasktime_fullcivname' => (string) $tasktime['fullcivname'],
376 'tasktime_amountht' => (float) $tasktime['amountht'],
377 'tasktime_amountttc' => (float) $tasktime['amountttc'],
378 'tasktime_thm' => (float) $tasktime['thm']
379 );
380 }
381
382 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
390 public function get_substitutionarray_task_file($file, $outputlangs)
391 {
392 // phpcs:enable
393 return array(
394 'tasksfile_name' => (string) $file['name'],
395 'tasksfile_date' => dol_print_date($file['date'], 'day'),
396 'tasksfile_size' => (int) $file['size']
397 );
398 }
399
400
407 public function info($langs)
408 {
409 global $conf, $langs;
410
411 // Load translation files required by the page
412 $langs->loadLangs(array("companies", "errors"));
413
414 $form = new Form($this->db);
415
416 $texte = $this->description.".<br>\n";
417 $texte .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" enctype="multipart/form-data">';
418 $texte .= '<input type="hidden" name="token" value="'.newToken().'">';
419 $texte .= '<input type="hidden" name="page_y" value="">';
420 $texte .= '<input type="hidden" name="action" value="setModuleOptions">';
421 $texte .= '<input type="hidden" name="param1" value="PROJECT_ADDON_PDF_ODT_PATH">';
422 $texte .= '<table class="nobordernopadding centpercent">';
423
424 // List of directories area
425 $texte .= '<tr><td>';
426 $texttitle = $langs->trans("ListOfDirectories");
427 $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim(getDolGlobalString('PROJECT_ADDON_PDF_ODT_PATH'))));
428 $listoffiles = array();
429 foreach ($listofdir as $key => $tmpdir) {
430 $tmpdir = trim($tmpdir);
431 $tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir);
432 if (!$tmpdir) {
433 unset($listofdir[$key]);
434 continue;
435 }
436 if (!is_dir($tmpdir)) {
437 $texttitle .= img_warning($langs->trans("ErrorDirNotFound", $tmpdir), '');
438 } else {
439 $tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.(ods|odt)');
440 if (count($tmpfiles)) {
441 $listoffiles = array_merge($listoffiles, $tmpfiles);
442 }
443 }
444 }
445 $texthelp = $langs->trans("ListOfDirectoriesForModelGenODT");
446 $texthelp .= '<br><br><span class="opacitymedium">'.$langs->trans("ExampleOfDirectoriesForModelGen").'</span>';
447 // Add list of substitution keys
448 $texthelp .= '<br>'.$langs->trans("FollowingSubstitutionKeysCanBeUsed").'<br>';
449 $texthelp .= $langs->transnoentitiesnoconv("FullListOnOnlineDocumentation"); // This contains an url, we don't modify it
450
451 $texte .= $form->textwithpicto($texttitle, $texthelp, 1, 'help', '', 1, 3, $this->name);
452 $texte .= '<div><div style="display: inline-block; min-width: 100px; vertical-align: middle;">';
453 $texte .= '<textarea class="flat textareafordir" spellcheck="false" cols="60" name="value1">';
454 $texte .= getDolGlobalString('PROJECT_ADDON_PDF_ODT_PATH');
455 $texte .= '</textarea>';
456 $texte .= '</div><div style="display: inline-block; vertical-align: middle;">';
457 $texte .= '<input type="submit" class="button button-edit reposition smallpaddingimp" name="modify" value="'.dol_escape_htmltag($langs->trans("Modify")).'">';
458 $texte .= '<br></div></div>';
459
460 // Scan directories
461 $nbofiles = count($listoffiles);
462 if (getDolGlobalString('PROJECT_ADDON_PDF_ODT_PATH')) {
463 $texte .= $langs->trans("NumberOfModelFilesFound").': <b>';
464 //$texte.=$nbofiles?'<a id="a_'.get_class($this).'" href="#">':'';
465 $texte .= $nbofiles;
466 //$texte.=$nbofiles?'</a>':'';
467 $texte .= '</b>';
468 }
469
470 if ($nbofiles) {
471 $texte .= '<div id="div_'.get_class($this).'" class="hiddenx">';
472 // Show list of found files
473 foreach ($listoffiles as $file) {
474 $texte .= '- '.$file['name'].' <a href="'.DOL_URL_ROOT.'/document.php?modulepart=doctemplates&file=projects/'.urlencode(basename($file['name'])).'">'.img_picto('', 'listlight').'</a>';
475 $texte .= ' &nbsp; <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?modulepart=doctemplates&keyforuploaddir=PROJECT_ADDON_PDF_ODT_PATH&action=deletefile&token='.newToken().'&file='.urlencode(basename($file['name'])).'">'.img_picto('', 'delete').'</a>';
476 $texte .= '<br>';
477 }
478 $texte .= '</div>';
479 }
480 // Add input to upload a new template file.
481 $texte .= '<div>'.$langs->trans("UploadNewTemplate");
482 $maxfilesizearray = getMaxFileSizeArray();
483 $maxmin = $maxfilesizearray['maxmin'];
484 if ($maxmin > 0) {
485 $texte .= '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
486 }
487 $texte .= ' <input type="file" name="uploadfile">';
488 $texte .= '<input type="hidden" value="PROJECT_ADDON_PDF_ODT_PATH" name="keyforuploaddir">';
489 $texte .= '<input type="submit" class="button smallpaddingimp reposition" value="'.dol_escape_htmltag($langs->trans("Upload")).'" name="upload">';
490 $texte .= '</div>';
491 $texte .= '</td>';
492
493 $texte .= '</tr>';
494
495 $texte .= '</table>';
496 $texte .= '</form>';
497
498 return $texte;
499 }
500
501 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
513 public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
514 {
515 // phpcs:enable
516 global $user, $langs, $conf, $mysoc, $hookmanager;
517
518 if (empty($srctemplatepath)) {
519 dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING);
520 return -1;
521 }
522
523 // Add odtgeneration hook
524 if (!is_object($hookmanager)) {
525 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
526 $hookmanager = new HookManager($this->db);
527 }
528 $hookmanager->initHooks(array('odtgeneration'));
529 global $action;
530
531 if (!is_object($outputlangs)) {
532 $outputlangs = $langs;
533 }
534 $sav_charset_output = $outputlangs->charset_output;
535 $outputlangs->charset_output = 'UTF-8';
536
537 // Load translation files required by the page
538 $outputlangs->loadLangs(array("main", "dict", "companies", "projects"));
539
540 if ($conf->project->dir_output) {
541 // If $object is id instead of object
542 if (!is_object($object)) {
543 $id = $object;
544 $object = new Project($this->db);
545 $result = $object->fetch($id);
546 if ($result < 0) {
547 dol_print_error($this->db, $object->error);
548 return -1;
549 }
550 }
551
552 $object->fetch_thirdparty();
553
554 $dir = $conf->project->dir_output;
555 $objectref = dol_sanitizeFileName($object->ref);
556 if (!preg_match('/specimen/i', $objectref)) {
557 $dir .= "/".$objectref;
558 }
559 $file = $dir."/".$objectref.".odt";
560
561 if (!file_exists($dir)) {
562 if (dol_mkdir($dir) < 0) {
563 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
564 return -1;
565 }
566 }
567
568 if (file_exists($dir)) {
569 //print "srctemplatepath=".$srctemplatepath; // Src filename
570 $newfile = basename($srctemplatepath);
571 $newfiletmp = preg_replace('/\.od[ts]/i', '', $newfile);
572 $newfiletmp = preg_replace('/template_/i', '', $newfiletmp);
573 $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp);
574 $newfiletmp = $objectref . '_' . $newfiletmp;
575 //$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt';
576 // Get extension (ods or odt)
577 $newfileformat = substr($newfile, strrpos($newfile, '.') + 1);
578 if (getDolGlobalString('MAIN_DOC_USE_TIMING')) {
579 $format = getDolGlobalString('MAIN_DOC_USE_TIMING');
580 if ($format == '1') {
581 $format = '%Y%m%d%H%M%S';
582 }
583 $filename = $newfiletmp . '-' . dol_print_date(dol_now(), $format) . '.' . $newfileformat;
584 } else {
585 $filename = $newfiletmp . '.' . $newfileformat;
586 }
587 $file = $dir . '/' . $filename;
588 //print "newdir=".$dir;
589 //print "newfile=".$newfile;
590 //print "file=".$file;
591 //print "conf->societe->dir_temp=".$conf->societe->dir_temp;
592
593 dol_mkdir($conf->project->dir_temp);
594 if (!is_writable($conf->project->dir_temp)) {
595 $this->error = $langs->transnoentities("ErrorFailedToWriteInTempDirectory", $conf->project->dir_temp);
596 dol_syslog('Error in write_file: ' . $this->error, LOG_ERR);
597 return -1;
598 }
599
600 // If PROJECTLEADER contact defined on project, we use it
601 $usecontact = false;
602 $arrayidcontact = $object->getIdContact('external', 'PROJECTLEADER');
603 if (count($arrayidcontact) > 0) {
604 $usecontact = true;
605 $result = $object->fetch_contact($arrayidcontact[0]);
606 }
607
608 // Recipient name
609 $contactobject = null;
610 if (!empty($usecontact)) {
611 // if we have a PROJECTLEADER contact and we don't use it as recipient we store the contact object for later use
612 $contactobject = $object->contact;
613 }
614
615 $socobject = $object->thirdparty;
616
617 // Make substitution
618 $substitutionarray = array(
619 '__FROM_NAME__' => $this->emetteur->name,
620 '__FROM_EMAIL__' => $this->emetteur->email,
621 );
622 complete_substitutions_array($substitutionarray, $langs, $object);
623 // Call the ODTSubstitution hook
624 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$substitutionarray);
625 $reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
626
627 // Open and load template
628 require_once ODTPHP_PATH.'odf.php';
629 try {
630 $odfHandler = new Odf(
631 $srctemplatepath,
632 array(
633 'PATH_TO_TMP' => $conf->project->dir_temp,
634 'ZIP_PROXY' => getDolGlobalString('MAIN_ODF_ZIP_PROXY', 'PclZipProxy'), // PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy.
635 'DELIMITER_LEFT' => '{',
636 'DELIMITER_RIGHT' => '}'
637 )
638 );
639 } catch (Exception $e) {
640 $this->error = $e->getMessage();
641 dol_syslog($e->getMessage(), LOG_INFO);
642 return -1;
643 }
644 // After construction $odfHandler->contentXml contains content and
645 // [!-- BEGIN row.lines --]*[!-- END row.lines --] has been replaced by
646 // [!-- BEGIN lines --]*[!-- END lines --]
647
648 // Define substitution array
649 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
650 $array_object_from_properties = $this->get_substitutionarray_each_var_object($object, $outputlangs);
651 $array_objet = $this->get_substitutionarray_object($object, $outputlangs);
652 $array_user = $this->get_substitutionarray_user($user, $outputlangs);
653 $array_soc = $this->get_substitutionarray_mysoc($mysoc, $outputlangs);
654 $array_thirdparty = $this->get_substitutionarray_thirdparty($socobject, $outputlangs);
655 $array_other = $this->get_substitutionarray_other($outputlangs);
656 // retrieve contact information for use in object as contact_xxx tags
657 $array_project_contact = array();
658 if ($usecontact && is_object($contactobject)) {
659 $array_project_contact = $this->get_substitutionarray_contact($contactobject, $outputlangs, 'contact');
660 }
661
662 $tmparray = array_merge($substitutionarray, $array_object_from_properties, $array_user, $array_soc, $array_thirdparty, $array_objet, $array_other, $array_project_contact);
663 complete_substitutions_array($tmparray, $outputlangs, $object);
664
665 // Call the ODTSubstitution hook
666 $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
667 $reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
668
669 // retrieve the constant to apply a ratio for image size or set the ratio to 1
670 if (getDolGlobalString('MAIN_DOC_ODT_IMAGE_RATIO')) {
671 $ratio = (float) getDolGlobalString('MAIN_DOC_ODT_IMAGE_RATIO');
672 } else {
673 $ratio = 1;
674 }
675
676 foreach ($tmparray as $key => $value) {
677 try {
678 if (preg_match('/logo$/', $key)) { // Image
679 if (file_exists($value)) {
680 $odfHandler->setImage($key, $value, $ratio);
681 } else {
682 $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
683 }
684 } else { // Text
685 $odfHandler->setVars($key, $value, true, 'UTF-8');
686 }
687 } catch (OdfException $e) {
688 dol_syslog($e->getMessage(), LOG_INFO);
689 }
690 }
691
692 // Replace tags of lines for tasks
693 $foundtagfortasks = 1;
694 try {
695 $listlines = $odfHandler->setSegment('tasks');
696 } catch (OdfExceptionSegmentNotFound $e) {
697 // We may arrive here if tags for tasks not present into template
698 $foundtagfortasks = 0;
699 dol_syslog($e->getMessage(), LOG_INFO);
700 }
701 if ($foundtagfortasks && isset($listlines)) {
702 $taskstatic = new Task($this->db);
703
704 // Security check
705 $socid = 0;
706 if (!empty($object->socid)) {
707 $socid = $object->socid;
708 }
709
710 $tasksarray = $taskstatic->getTasksArray(null, null, $object->id, $socid, 0);
711
712
713 foreach ($tasksarray as $task) {
714 $tmparray = $this->get_substitutionarray_tasks($task, $outputlangs);
715 //complete_substitutions_array($tmparray, $outputlangs, $object, $task, "completesubstitutionarray_lines");
716 foreach ($tmparray as $key => $val) {
717 try {
718 $listlines->setVars($key, $val, true, 'UTF-8');
719 } catch (SegmentException $e) {
720 dol_syslog($e->getMessage(), LOG_INFO);
721 }
722 }
723
724 $taskobj = new Task($this->db);
725 $taskobj->fetch($task->id);
726
727 // Replace tags of lines for contacts task
728 $sourcearray = array('internal', 'external');
729 $contact_arrray = array();
730 foreach ($sourcearray as $source) {
731 $contact_temp = $taskobj->liste_contact(-1, $source);
732 if ((is_array($contact_temp) && count($contact_temp) > 0)) {
733 $contact_arrray = array_merge($contact_arrray, $contact_temp);
734 }
735 }
736 if ((is_array($contact_arrray) && count($contact_arrray) > 0)) {
737 $foundtagfortasksressources = 1;
738 try {
739 $listlinestaskres = $listlines->__get('tasksressources');
740 } catch (SegmentException $e) {
741 // We may arrive here if tags for tasksressources not present into template
742 $foundtagfortasksressources = 0;
743 dol_syslog($e->getMessage(), LOG_INFO);
744 }
745 if ($foundtagfortasksressources && isset($listlinestaskres)) {
746 foreach ($contact_arrray as $contact) {
747 if ($contact['source'] == 'internal') {
748 $objectdetail = new User($this->db);
749 $objectdetail->fetch($contact['id']);
750 $contact['socname'] = $mysoc->name;
751 } elseif ($contact['source'] == 'external') {
752 $objectdetail = new Contact($this->db);
753 $objectdetail->fetch($contact['id']);
754
755 $soc = new Societe($this->db);
756 $soc->fetch($contact['socid']);
757 $contact['socname'] = $soc->name;
758 } else {
759 dol_syslog(get_class().'::'.__METHOD__.' Unexpected contact source:'.$contact['source'], LOG_ERR);
760 continue;
761 }
762 $contact['fullname'] = $objectdetail->getFullName($outputlangs, 1);
763
764 $tmparray = $this->get_substitutionarray_tasksressource($contact, $outputlangs);
765
766 foreach ($tmparray as $key => $val) {
767 try {
768 $listlinestaskres->setVars($key, $val, true, 'UTF-8');
769 } catch (SegmentException $e) {
770 dol_syslog($e->getMessage(), LOG_INFO);
771 }
772 }
773 $listlinestaskres->merge();
774 }
775 }
776 }
777
778 //Time resources
779 $sql = "SELECT t.rowid, t.element_date as task_date, t.element_duration as task_duration, t.fk_user, t.note";
780 $sql .= ", u.lastname, u.firstname, t.thm";
781 $sql .= " FROM ".MAIN_DB_PREFIX."element_time as t";
782 $sql .= " , ".MAIN_DB_PREFIX."user as u";
783 $sql .= " WHERE t.fk_element =".((int) $task->id);
784 $sql .= " AND t.elementtype = 'task'";
785 $sql .= " AND t.fk_user = u.rowid";
786 $sql .= " ORDER BY t.element_date DESC";
787
788 $resql = $this->db->query($sql);
789 if ($resql) {
790 $num = $this->db->num_rows($resql);
791 $i = 0;
792 $tasks = array();
793 $row = array();
794 $foundtagfortaskstimes = 1;
795 try {
796 $listlinestasktime = $listlines->__get('taskstimes');
797 } catch (SegmentException $e) {
798 // We may arrive here if tags for taskstimes not present into template
799 $foundtagfortaskstimes = 0;
800 dol_syslog($e->getMessage(), LOG_INFO);
801 }
802 if ($foundtagfortaskstimes && isset($listlinestasktime)) {
803 if (empty($num)) {
804 $row['rowid'] = 0;
805 $row['task_date'] = 0;
806 $row['task_duration'] = 0;
807 //$row['$tasktime'] = '';
808 $row['note'] = '';
809 $row['fk_user'] = 0;
810 $row['name'] = '';
811 $row['firstname'] = '';
812 $row['fullcivname'] = '';
813 $row['amountht'] = 0;
814 $row['amountttc'] = 0;
815 $row['thm'] = 0;
816 $tmparray = $this->get_substitutionarray_taskstime($row, $outputlangs);
817 foreach ($tmparray as $key => $val) {
818 try {
819 $listlinestasktime->setVars($key, $val, true, 'UTF-8');
820 } catch (SegmentException $e) {
821 dol_syslog($e->getMessage(), LOG_INFO);
822 }
823 }
824 $listlinestasktime->merge();
825 }
826 while ($i < $num) {
827 $row = $this->db->fetch_array($resql);
828 if (!empty($row['fk_user'])) {
829 $objectdetail = new User($this->db);
830 $objectdetail->fetch($row['fk_user']);
831 $row['fullcivname'] = $objectdetail->getFullName($outputlangs, 1);
832 } else {
833 $row['fullcivname'] = '';
834 }
835
836 if (!empty($row['thm'])) {
837 $row['amountht'] = ($row['task_duration'] / 3600) * $row['thm'];
838 $defaultvat = get_default_tva($mysoc, $mysoc);
839 $row['amountttc'] = price2num($row['amountht'] * (1 + ($defaultvat / 100)), 'MT');
840 } else {
841 $row['amountht'] = 0;
842 $row['amountttc'] = 0;
843 $row['thm'] = 0;
844 }
845
846 $tmparray = $this->get_substitutionarray_taskstime($row, $outputlangs); // @phpstan-ignore argument.type
847
848 foreach ($tmparray as $key => $val) {
849 try {
850 $listlinestasktime->setVars($key, $val, true, 'UTF-8');
851 } catch (SegmentException $e) {
852 dol_syslog($e->getMessage(), LOG_INFO);
853 }
854 }
855 $listlinestasktime->merge();
856 $i++;
857 }
858 }
859 $this->db->free($resql);
860 }
861
862
863 // Replace tags of project files
864 $foundtagfortasksfiles = 1;
865 try {
866 $listtasksfiles = $listlines->__get('tasksfiles');
867 } catch (SegmentException $e) {
868 // We may arrive here if tags for tasksfiles not present into template
869 $foundtagfortasksfiles = 0;
870 dol_syslog($e->getMessage(), LOG_INFO);
871 }
872 if ($foundtagfortasksfiles && isset($listtasksfiles)) {
873 $upload_dir = $conf->project->dir_output.'/'.dol_sanitizeFileName($object->ref).'/'.dol_sanitizeFileName($task->ref);
874 $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', 'name', SORT_ASC, 1);
875
876
877 foreach ($filearray as $filedetail) {
878 $tmparray = $this->get_substitutionarray_task_file($filedetail, $outputlangs);
879 //dol_syslog(get_class($this).'::main $tmparray'.var_export($tmparray,true));
880 foreach ($tmparray as $key => $val) {
881 try {
882 $listtasksfiles->setVars($key, $val, true, 'UTF-8');
883 } catch (SegmentException $e) {
884 dol_syslog($e->getMessage(), LOG_INFO);
885 }
886 }
887 $listtasksfiles->merge();
888 }
889 }
890 $listlines->merge();
891 }
892 try {
893 $odfHandler->mergeSegment($listlines);
894 } catch (OdfException $e) {
895 $this->error = $e->getMessage();
896 dol_syslog($this->error, LOG_WARNING);
897 return -1;
898 }
899 }
900
901 // Replace tags of project files
902 $foundtagforprojectfiles = 1;
903 try {
904 $listlines = $odfHandler->setSegment('projectfiles');
905 } catch (OdfExceptionSegmentNotFound $e) {
906 // We may arrive here if tags for projectfiles not present into template
907 $foundtagforprojectfiles = 0;
908 dol_syslog($e->getMessage(), LOG_INFO);
909 }
910 if ($foundtagforprojectfiles && isset($listlines)) {
911 $upload_dir = $conf->project->dir_output.'/'.dol_sanitizeFileName($object->ref);
912 $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', 'name', SORT_ASC, 1);
913
914 foreach ($filearray as $filedetail) {
915 //dol_syslog(get_class($this).'::main $filedetail'.var_export($filedetail,true));
916 $tmparray = $this->get_substitutionarray_project_file($filedetail, $outputlangs);
917
918 foreach ($tmparray as $key => $val) {
919 try {
920 $listlines->setVars($key, $val, true, 'UTF-8');
921 } catch (SegmentException $e) {
922 dol_syslog($e->getMessage(), LOG_INFO);
923 }
924 }
925 $listlines->merge();
926 }
927 try {
928 $odfHandler->mergeSegment($listlines);
929 } catch (OdfException $e) {
930 $this->error = $e->getMessage();
931 dol_syslog($this->error, LOG_WARNING);
932 return -1;
933 }
934 }
935
936 // Replace tags of lines for contacts
937 $sourcearray = array('internal', 'external');
938 $contact_arrray = array();
939 foreach ($sourcearray as $source) {
940 $contact_temp = $object->liste_contact(-1, $source);
941 if ((is_array($contact_temp) && count($contact_temp) > 0)) {
942 $contact_arrray = array_merge($contact_arrray, $contact_temp);
943 }
944 }
945 if ((is_array($contact_arrray) && count($contact_arrray) > 0)) {
946 $foundtagforprojectcontacts = 1;
947 try {
948 $listlines = $odfHandler->setSegment('projectcontacts');
949 } catch (OdfExceptionSegmentNotFound $e) {
950 // We may arrive here if tags for projectcontacts not present into template
951 $foundtagforprojectcontacts = 0;
952 dol_syslog($e->getMessage(), LOG_INFO);
953 }
954 if ($foundtagforprojectcontacts && isset($listlines)) {
955 foreach ($contact_arrray as $contact) {
956 $objectdetail = null;
957 if ($contact['source'] == 'internal') {
958 $objectdetail = new User($this->db);
959 $objectdetail->fetch($contact['id']);
960 $contact['socname'] = $mysoc->name;
961 } elseif ($contact['source'] == 'external') {
962 $objectdetail = new Contact($this->db);
963 $objectdetail->fetch($contact['id']);
964
965 $soc = new Societe($this->db);
966 $soc->fetch($contact['socid']);
967 $contact['socname'] = $soc->name;
968 } else {
969 dol_syslog('Unexpected contact source:'.$contact['source'].'.'. getCallerInfoString(), LOG_ERR);
970 continue;
971 }
972 $contact['fullname'] = $objectdetail->getFullName($outputlangs, 1);
973
974 $tmparray = $this->get_substitutionarray_project_contacts($contact, $outputlangs);
975 foreach ($tmparray as $key => $val) {
976 try {
977 $listlines->setVars($key, $val, true, 'UTF-8');
978 } catch (SegmentException $e) {
979 dol_syslog($e->getMessage(), LOG_INFO);
980 }
981 }
982 $listlines->merge();
983 }
984 try {
985 $odfHandler->mergeSegment($listlines);
986 } catch (OdfException $e) {
987 $this->error = $e->getMessage();
988 dol_syslog($this->error, LOG_WARNING);
989 return -1;
990 }
991 }
992 }
993
994 //List of referent
995
996 $listofreferent = array(
997 'propal' => array(
998 'title' => "ListProposalsAssociatedProject",
999 'class' => 'Propal',
1000 'table' => 'propal',
1001 'test' => isModEnabled('propal') && $user->hasRight('propal', 'lire')
1002 ),
1003 'order' => array(
1004 'title' => "ListOrdersAssociatedProject",
1005 'class' => 'Commande',
1006 'table' => 'commande',
1007 'test' => isModEnabled('order') && $user->hasRight('commande', 'lire')
1008 ),
1009 'invoice' => array(
1010 'title' => "ListInvoicesAssociatedProject",
1011 'class' => 'Facture',
1012 'table' => 'facture',
1013 'test' => isModEnabled('invoice') && $user->hasRight('facture', 'lire')
1014 ),
1015 'invoice_predefined' => array(
1016 'title' => "ListPredefinedInvoicesAssociatedProject",
1017 'class' => 'FactureRec',
1018 'table' => 'facture_rec',
1019 'test' => isModEnabled('invoice') && $user->hasRight('facture', 'lire')
1020 ),
1021 'proposal_supplier' => array(
1022 'title' => "ListSupplierProposalsAssociatedProject",
1023 'class' => 'SupplierProposal',
1024 'table' => 'supplier_proposal',
1025 'test' => isModEnabled('supplier_proposal') && $user->hasRight('supplier_proposal', 'lire')
1026 ),
1027 'order_supplier' => array(
1028 'title' => "ListSupplierOrdersAssociatedProject",
1029 'table' => 'commande_fournisseur',
1030 'class' => 'CommandeFournisseur',
1031 'test' => (isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight('fournisseur', 'commande', 'lire')) || (isModEnabled("supplier_order") && $user->hasRight('supplier_order', 'lire'))
1032 ),
1033 'invoice_supplier' => array(
1034 'title' => "ListSupplierInvoicesAssociatedProject",
1035 'table' => 'facture_fourn',
1036 'class' => 'FactureFournisseur',
1037 'test' => (isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight('fournisseur', 'facture', 'lire')) || (isModEnabled("supplier_invoice") && $user->hasRight('supplier_invoice', 'lire'))
1038 ),
1039 'contract' => array(
1040 'title' => "ListContractAssociatedProject",
1041 'class' => 'Contrat',
1042 'table' => 'contrat',
1043 'test' => isModEnabled('contract') && $user->hasRight('contrat', 'lire')
1044 ),
1045 'intervention' => array(
1046 'title' => "ListFichinterAssociatedProject",
1047 'class' => 'Fichinter',
1048 'table' => 'fichinter',
1049 'disableamount' => 1,
1050 'test' => isModEnabled('intervention') && $user->hasRight('ficheinter', 'lire')
1051 ),
1052 'shipping' => array(
1053 'title' => "ListShippingAssociatedProject",
1054 'class' => 'Expedition',
1055 'table' => 'expedition',
1056 'disableamount' => 1,
1057 'test' => isModEnabled('shipping') && $user->hasRight('expedition', 'lire')
1058 ),
1059 'expensereport' => array(
1060 'title' => "ListExpenseReportsAssociatedProject",
1061 'class' => 'ExpenseReportLine',
1062 'table' => 'expensereport_det',
1063 'test' => isModEnabled('expensereport') && $user->hasRight('expensereport', 'lire')
1064 ),
1065 'donation' => array(
1066 'title' => "ListDonationsAssociatedProject",
1067 'class' => 'Don',
1068 'table' => 'don',
1069 'test' => isModEnabled('don') && $user->hasRight('don', 'lire')
1070 ),
1071 'loan' => array(
1072 'title' => "ListLoanAssociatedProject",
1073 'class' => 'Loan',
1074 'table' => 'loan',
1075 'test' => isModEnabled('loan') && $user->hasRight('loan', 'read')
1076 ),
1077 'chargesociales' => array(
1078 'title' => "ListSocialContributionAssociatedProject",
1079 'class' => 'ChargeSociales',
1080 'table' => 'chargesociales',
1081 'urlnew' => DOL_URL_ROOT.'/compta/sociales/card.php?action=create&projectid='.$object->id,
1082 'test' => isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')
1083 ),
1084 'stock_mouvement' => array(
1085 'title' => "ListMouvementStockProject",
1086 'class' => 'MouvementStock',
1087 'table' => 'stock_mouvement',
1088 'test' => (isModEnabled('stock') && $user->hasRight('stock', 'mouvement', 'lire') && getDolGlobalString('STOCK_MOVEMENT_INTO_PROJECT_OVERVIEW'))
1089 ),
1090 'agenda' => array(
1091 'title' => "ListActionsAssociatedProject",
1092 'class' => 'ActionComm',
1093 'table' => 'actioncomm',
1094 'disableamount' => 1,
1095 'test' => isModEnabled('agenda') && $user->hasRight('agenda', 'allactions', 'lire')
1096 ),
1097 );
1098
1099 // Insert list of objects into the project
1100 $foundtagforprojectrefs = 1;
1101 try {
1102 $listlines = $odfHandler->setSegment('projectrefs');
1103 } catch (OdfExceptionSegmentNotFound $e) {
1104 // We may arrive here if tags for projectrefs not present into template
1105 $foundtagforprojectrefs = 0;
1106 dol_syslog($e->getMessage(), LOG_INFO);
1107 }
1108 if ($foundtagforprojectrefs && isset($listlines)) {
1109 foreach ($listofreferent as $keyref => $valueref) {
1110 $title = $valueref['title'];
1111 $tablename = $valueref['table'];
1112 $classname = $valueref['class'];
1113 $qualified = $valueref['test'];
1114 if ($qualified) {
1115 $elementarray = $object->get_element_list($keyref, $tablename);
1116 if (count($elementarray) > 0 && is_array($elementarray)) {
1117 $total_ht = 0;
1118 $total_ttc = 0;
1119 $num = count($elementarray);
1120 for ($i = 0; $i < $num; $i++) {
1121 $ref_array = array();
1122 $ref_array['type'] = (string) $langs->trans($classname);
1123
1124 $element = new $classname($this->db);
1125 $element->fetch((int) $elementarray[$i]);
1126 $element->fetch_thirdparty();
1127
1128 //Ref object
1129 $ref_array['ref'] = (string) $element->ref;
1130
1131 //Date object
1132 $dateref = $element->date;
1133 if (empty($dateref)) {
1134 $dateref = $element->datep;
1135 }
1136 if (empty($dateref)) {
1137 $dateref = $element->date_contrat;
1138 }
1139 $ref_array['date'] = (string) $dateref;
1140
1141 //Soc object
1142 if (is_object($element->thirdparty)) {
1143 $ref_array['socname'] = $element->thirdparty->name;
1144 } else {
1145 $ref_array['socname'] = '';
1146 }
1147
1148 //Amount object
1149 if (empty($valueref['disableamount'])) {
1150 if (!empty($element->total_ht)) {
1151 $ref_array['amountht'] = (float) $element->total_ht;
1152 $ref_array['amountttc'] = (float) $element->total_ttc;
1153 } else {
1154 $ref_array['amountht'] = 0;
1155 $ref_array['amountttc'] = 0;
1156 }
1157 } else {
1158 $ref_array['amountht'] = '';
1159 $ref_array['amountttc'] = '';
1160 }
1161
1162 $ref_array['status'] = method_exists($element, 'getLibStatut') ? $element->getLibStatut(0) : '';
1163
1164 $tmparray = $this->get_substitutionarray_project_reference($ref_array, $outputlangs);
1165
1166 foreach ($tmparray as $key => $val) {
1167 try {
1168 $listlines->setVars($key, $val, true, 'UTF-8');
1169 } catch (SegmentException $e) {
1170 dol_syslog($e->getMessage(), LOG_INFO);
1171 }
1172 }
1173 $listlines->merge();
1174 }
1175 }
1176 }
1177 try {
1178 $odfHandler->mergeSegment($listlines);
1179 } catch (OdfException $e) {
1180 $this->error = $e->getMessage();
1181 dol_syslog($this->error, LOG_WARNING);
1182 return -1;
1183 }
1184 }
1185 }
1186
1187 // Replace labels translated
1188 $tmparray = $outputlangs->get_translations_for_substitutions();
1189 foreach ($tmparray as $key => $value) {
1190 try {
1191 $odfHandler->setVars($key, $value, true, 'UTF-8');
1192 } catch (OdfException $e) {
1193 dol_syslog($e->getMessage(), LOG_INFO);
1194 }
1195 }
1196
1197 // Call the beforeODTSave hook
1198 $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
1199 $reshook = $hookmanager->executeHooks('beforeODTSave', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1200
1201
1202 // Write new file
1203 if (getDolGlobalString('MAIN_ODT_AS_PDF')) {
1204 try {
1205 $odfHandler->exportAsAttachedPDF($file);
1206 } catch (Exception $e) {
1207 $this->error = $e->getMessage();
1208 return -1;
1209 }
1210 } else {
1211 try {
1212 $odfHandler->saveToDisk($file);
1213 } catch (Exception $e) {
1214 $this->error = $e->getMessage();
1215 dol_syslog($e->getMessage(), LOG_INFO);
1216 return -1;
1217 }
1218 }
1219 $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
1220 $reshook = $hookmanager->executeHooks('afterODTCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
1221
1222 dolChmod($file);
1223
1224 $odfHandler = null; // Destroy object
1225
1226 $this->result = array('fullpath' => $file);
1227
1228 return 1; // Success
1229 } else {
1230 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
1231 return -1;
1232 }
1233 }
1234
1235 return -1;
1236 }
1237}
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
$propal type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition propal.php:280
get_substitutionarray_each_var_object(&$object, $outputlangs, $recursive=1)
Define array with couple substitution key => substitution value @phpstan-template T.
get_substitutionarray_mysoc($mysoc, $outputlangs)
Define array with couple substitution key => substitution value.
get_substitutionarray_contact($object, $outputlangs, $array_key='object')
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 standard extra fields.
Class to manage generation of HTML components Only common components must be here.
Class to manage hooks.
Parent class for projects 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_tasks(Task $task, $outputlangs)
Define array with couple substitution key => substitution value.
get_substitutionarray_task_file($file, $outputlangs)
Define array with couple substitution key => substitution value.
get_substitutionarray_project_file($file, $outputlangs)
Define array with couple substitution key => substitution value.
get_substitutionarray_tasksressource($taskresource, $outputlangs)
Define array with couple substitution key => substitution value.
get_substitutionarray_taskstime($tasktime, $outputlangs)
Define array with couple substitution key => substitution value.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build a document on disk using the generic odt module.
get_substitutionarray_project_contacts($contact, $outputlangs)
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_reference($refdetail, $outputlangs)
Define array with couple substitution key => substitution value.
info($langs)
Return description of a module.
global $mysoc
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:253
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.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
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:65
dol_now($mode='gmt')
Return date for now.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
getCallerInfoString()
Get caller info as a string that can be appended to a log message.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
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.
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_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
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)
$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.