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