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