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