Passed
Push — EXTRACT_CLASSES ( d4f850...56e940 )
by Rafael
41:39
created

doc_generic_task_odt::write_file()   F

Complexity

Conditions 62
Paths > 20000

Size

Total Lines 397
Code Lines 257

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 62
eloc 257
nc 627189469
nop 3
dl 0
loc 397
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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