Passed
Push — CHECK_API ( 78ffdd...fa4f39 )
by Rafael
41:29
created

doc_generic_odt::write_file()   F

Complexity

Conditions 35
Paths > 20000

Size

Total Lines 246
Code Lines 156

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 35
eloc 156
nc 363101
nop 6
dl 0
loc 246
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-2011  Laurent Destailleur     <[email protected]>
4
 * Copyright (C) 2016	    Charlie Benke           <[email protected]>
5
 * Copyright (C) 2018-2024  Frédéric France         <[email protected]>
6
 * Copyright (C) 2024       Rafael San José             <[email protected]>
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20
 * or see https://www.gnu.org/
21
 */
22
23
use Dolibarr\Code\Contact\Classes\Contact;
24
25
/**
26
 *  \file       htdocs/core/modules/societe/doc/doc_generic_odt.modules.php
27
 *  \ingroup    societe
28
 *  \brief      File of class to build ODT documents for third parties
29
 */
30
31
require_once constant('DOL_DOCUMENT_ROOT') . '/core/modules/societe/modules_societe.class.php';
32
33
use Dolibarr\Code\Societe\Classes\Societe;
34
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/company.lib.php';
35
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
36
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/doc.lib.php';
37
38
39
/**
40
 *  Class to build documents using ODF templates generator
41
 */
42
class doc_generic_odt extends ModeleThirdPartyDoc
43
{
44
    /**
45
     * @var string Dolibarr version of the loaded document
46
     */
47
    public $version = 'dolibarr';
48
49
50
    /**
51
     *  Constructor
52
     *
53
     *  @param      DoliDB      $db      Database handler
54
     */
55
    public function __construct($db)
56
    {
57
        global $langs, $mysoc;
58
59
        // Load translation files required by the page
60
        $langs->loadLangs(array("main", "companies"));
61
62
        $this->db = $db;
63
        $this->name = "ODT templates";
64
        $this->description = $langs->trans("DocumentModelOdt");
65
        $this->scandir = 'COMPANY_ADDON_PDF_ODT_PATH'; // Name of constant that is used to save list of directories to scan
66
67
        // Page size for A4 format
68
        $this->type = 'odt';
69
        $this->page_largeur = 0;
70
        $this->page_hauteur = 0;
71
        $this->format = array($this->page_largeur, $this->page_hauteur);
72
        $this->marge_gauche = 0;
73
        $this->marge_droite = 0;
74
        $this->marge_haute = 0;
75
        $this->marge_basse = 0;
76
77
        $this->option_logo = 1; // Display logo
78
        $this->option_freetext = 0; // Support add of a personalised text
79
        $this->option_draft_watermark = 0; // Support add of a watermark on drafts
80
81
        // Retrieves transmitter
82
        $this->emetteur = $mysoc;
83
        if (!$this->emetteur->country_code) {
84
            $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
85
        }
86
    }
87
88
89
    /**
90
     * Return description of a module
91
     *
92
     * @param   Translate   $langs      Object language
93
     * @return  string                  Description
94
     */
95
    public function info($langs)
96
    {
97
        global $conf, $langs;
98
99
        // Load traductions files required by page
100
        $langs->loadLangs(array("companies", "errors"));
101
102
        $form = new Form($this->db);
103
104
        $texte = $this->description . ".<br>\n";
105
        $texte .= '<!-- form for option of ODT templates -->';
106
        $texte .= '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST" enctype="multipart/form-data">';
107
        $texte .= '<input type="hidden" name="token" value="' . newToken() . '">';
108
        $texte .= '<input type="hidden" name="page_y" value="">';
109
        $texte .= '<input type="hidden" name="action" value="setModuleOptions">';
110
        $texte .= '<input type="hidden" name="param1" value="COMPANY_ADDON_PDF_ODT_PATH">';
111
        $texte .= '<table class="nobordernopadding centpercent">';
112
113
        // List of directories area
114
        $texte .= '<tr><td>';
115
        $texttitle = $langs->trans("ListOfDirectories");
116
        $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim(getDolGlobalString('COMPANY_ADDON_PDF_ODT_PATH'))));
117
        $listoffiles = array();
118
        foreach ($listofdir as $key => $tmpdir) {
119
            $tmpdir = trim($tmpdir);
120
            $tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir);
121
            if (!$tmpdir) {
122
                unset($listofdir[$key]);
123
                continue;
124
            }
125
            if (!is_dir($tmpdir)) {
126
                $texttitle .= img_warning($langs->trans("ErrorDirNotFound", $tmpdir), 0);
127
            } else {
128
                $tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.od(s|t)$', '', 'name', SORT_ASC, 0, true); // Disable hook for the moment
129
                if (count($tmpfiles)) {
130
                    $listoffiles = array_merge($listoffiles, $tmpfiles);
131
                }
132
            }
133
        }
134
        $texthelp = $langs->trans("ListOfDirectoriesForModelGenODT");
135
        $texthelp .= '<br><br><span class="opacitymedium">' . $langs->trans("ExampleOfDirectoriesForModelGen") . '</span>';
136
        // Add list of substitution keys
137
        $texthelp .= '<br>' . $langs->trans("FollowingSubstitutionKeysCanBeUsed") . '<br>';
138
        $texthelp .= $langs->transnoentitiesnoconv("FullListOnOnlineDocumentation"); // This contains an url, we don't modify it
139
140
        if (!getDolGlobalString('MAIN_NO_MULTIDIR_FOR_ODT')) {
141
            $texte .= $form->textwithpicto($texttitle, $texthelp, 1, 'help', '', 1, 3, $this->name);
142
            $texte .= '<div><div style="display: inline-block; min-width: 100px; vertical-align: middle;">';
143
            //$texte .= '<table><tr><td>';
144
            $texte .= '<textarea class="flat" cols="60" name="value1">';
145
            $texte .= getDolGlobalString('COMPANY_ADDON_PDF_ODT_PATH');
146
            $texte .= '</textarea>';
147
            //$texte .= '</td>';
148
            //$texte .= '<td class="center">&nbsp; ';
149
            $texte .= '</div><div style="display: inline-block; vertical-align: middle;">';
150
            $texte .= '<input type="submit" class="button button-edit reposition smallpaddingimp" name="modify" value="' . dol_escape_htmltag($langs->trans("Modify")) . '">';
151
            //$texte .= '</td>';
152
            //$texte .= '</tr>';
153
            //$texte .= '</table>';
154
            $texte .= '</div></div>';
155
        } else {
156
            $texte .= '<br>';
157
            $texte .= '<input type="hidden" name="value1" value="COMPANY_ADDON_PDF_ODT_PATH">';
158
        }
159
160
        // Scan directories
161
        $nbofiles = count($listoffiles);
162
        if (getDolGlobalString('COMPANY_ADDON_PDF_ODT_PATH')) {
163
            $texte .= $langs->trans("NumberOfModelFilesFound") . ': <b>';
164
            //$texte.=$nbofiles?'<a id="a_'.get_class($this).'" href="#">':'';
165
            $texte .= $nbofiles;
166
            //$texte.=$nbofiles?'</a>':'';
167
            $texte .= '</b>';
168
        }
169
170
        if ($nbofiles) {
171
            $texte .= '<div id="div_' . get_class($this) . '" class="hiddenx">';
172
            // Show list of found files
173
            foreach ($listoffiles as $file) {
174
                $texte .= '- ' . $file['name'] . ' &nbsp; <a class="reposition" href="' . constant('BASE_URL') . 'document.php?modulepart=doctemplates&file=thirdparties/' . urlencode(basename($file['name'])) . '">' . img_picto('', 'listlight') . '</a>';
175
                $texte .= ' &nbsp; <a class="reposition" href="' . $_SERVER["PHP_SELF"] . '?modulepart=doctemplates&keyforuploaddir=COMPANY_ADDON_PDF_ODT_PATH&action=deletefile&token=' . newToken() . '&file=' . urlencode(basename($file['name'])) . '">' . img_picto('', 'delete') . '</a>';
176
                $texte .= '<br>';
177
            }
178
            $texte .= '</div>';
179
        }
180
        // Add input to upload a new template file.
181
        $texte .= '<div>' . $langs->trans("UploadNewTemplate");
182
        $maxfilesizearray = getMaxFileSizeArray();
183
        $maxmin = $maxfilesizearray['maxmin'];
184
        if ($maxmin > 0) {
185
            $texte .= '<input type="hidden" name="MAX_FILE_SIZE" value="' . ($maxmin * 1024) . '">';    // MAX_FILE_SIZE must precede the field type=file
186
        }
187
        $texte .= ' <input type="file" name="uploadfile">';
188
        $texte .= '<input type="hidden" value="COMPANY_ADDON_PDF_ODT_PATH" name="keyforuploaddir">';
189
        $texte .= '<input type="submit" class="button smallpaddingimp reposition" value="' . dol_escape_htmltag($langs->trans("Upload")) . '" name="upload">';
190
        $texte .= '</div>';
191
        $texte .= '</td>';
192
193
        $texte .= '</tr>';
194
195
        $texte .= '</table>';
196
        $texte .= '</form>';
197
198
        return $texte;
199
    }
200
201
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
202
    /**
203
     *  Function to build a document on disk using the generic odt module.
204
     *
205
     *  @param      Societe     $object             Object source to build document
206
     *  @param      Translate   $outputlangs        Lang output object
207
     *  @param      string      $srctemplatepath    Full path of source filename for generator using a template file
208
     *  @param      int         $hidedetails        Do not show line details
209
     *  @param      int         $hidedesc           Do not show desc
210
     *  @param      int         $hideref            Do not show ref
211
     *  @return     int                             1 if OK, <=0 if KO
212
     */
213
    public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
214
    {
215
		// phpcs:enable
216
        global $user, $langs, $conf, $mysoc, $hookmanager;
217
        global $action;
218
219
        if (empty($srctemplatepath)) {
220
            dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING);
221
            return -1;
222
        }
223
224
        // Add odtgeneration hook
225
        if (!is_object($hookmanager)) {
226
            $hookmanager = new HookManager($this->db);
227
        }
228
        $hookmanager->initHooks(array('odtgeneration'));
229
230
        if (!is_object($outputlangs)) {
231
            $outputlangs = $langs;
232
        }
233
        $sav_charset_output = $outputlangs->charset_output;
234
        $outputlangs->charset_output = 'UTF-8';
235
236
        // Load translation files required by the page
237
        $outputlangs->loadLangs(array("main", "dict", "companies", "projects"));
238
239
        if ($conf->societe->multidir_output[$object->entity]) {
240
            $dir = $conf->societe->multidir_output[$object->entity];
241
            $objectref = dol_sanitizeFileName($object->id);
242
            if (!preg_match('/specimen/i', $objectref)) {
243
                $dir .= "/" . $objectref;
244
            }
245
246
            if (!file_exists($dir)) {
247
                if (dol_mkdir($dir) < 0) {
248
                    $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
249
                    return -1;
250
                }
251
            }
252
253
            if (file_exists($dir)) {
254
                //print "srctemplatepath=".$srctemplatepath;    // Src filename
255
                $newfile = basename($srctemplatepath);
256
                $newfiletmp = preg_replace('/\.od(s|t)/i', '', $newfile);
257
                $newfiletmp = preg_replace('/template_/i', '', $newfiletmp);
258
                $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp);
259
                // Get extension (ods or odt)
260
                $newfileformat = substr($newfile, strrpos($newfile, '.') + 1);
261
                if (getDolGlobalString('MAIN_DOC_USE_OBJECT_THIRDPARTY_NAME')) {
262
                    $newfiletmp = dol_sanitizeFileName(dol_string_nospecial($object->name)) . '-' . $newfiletmp;
263
                    $newfiletmp = preg_replace('/__+/', '_', $newfiletmp);  // Replace repeated _ into one _ (to avoid string with substitution syntax)
264
                }
265
                if (getDolGlobalString('MAIN_DOC_USE_TIMING')) {
266
                    $format = getDolGlobalString('MAIN_DOC_USE_TIMING');
267
                    if ($format == '1') {
268
                        $format = '%Y%m%d%H%M%S';
269
                    }
270
                    $filename = $newfiletmp . '-' . dol_print_date(dol_now(), $format) . '.' . $newfileformat;
271
                } else {
272
                    $filename = $newfiletmp . '.' . $newfileformat;
273
                }
274
                $file = $dir . '/' . $filename;
275
                $object->builddoc_filename = $filename; // For triggers
0 ignored issues
show
Bug Best Practice introduced by
The property builddoc_filename does not exist on Dolibarr\Code\Societe\Classes\Societe. Since you implemented __set, consider adding a @property annotation.
Loading history...
276
                $object->context['builddoc_filename'] = $filename; // For triggers
277
                //print "newfileformat=".$newfileformat;
278
                //print "newdir=".$dir;
279
                //print "newfile=".$newfile;
280
                //print "file=".$file;
281
                //print "conf->societe->dir_temp=".$conf->societe->dir_temp;
282
                //exit;
283
284
                dol_mkdir($conf->societe->multidir_temp[$object->entity]);
285
                if (!is_writable($conf->societe->multidir_temp[$object->entity])) {
286
                    $this->error = $langs->transnoentities("ErrorFailedToWriteInTempDirectory", $conf->societe->multidir_temp[$object->entity]);
287
                    dol_syslog('Error in write_file: ' . $this->error, LOG_ERR);
288
                    return -1;
289
                }
290
291
                // Open and load template
292
                require_once ODTPHP_PATH . 'odf.php';
293
                try {
294
                    $odfHandler = new Odf(
295
                        $srctemplatepath,
296
                        array(
297
                            'PATH_TO_TMP'     => $conf->societe->multidir_temp[$object->entity],
298
                            'ZIP_PROXY'       => 'PclZipProxy', // PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy.
299
                            'DELIMITER_LEFT'  => '{',
300
                            'DELIMITER_RIGHT' => '}'
301
                        )
302
                    );
303
                } catch (Exception $e) {
304
                    $this->error = $e->getMessage();
305
                    dol_syslog($e->getMessage(), LOG_INFO);
306
                    return -1;
307
                }
308
                //print $odfHandler->__toString()."\n";
309
310
                // Replace tags of lines for contacts
311
                $contact_arrray = array();
312
313
                $sql = "SELECT p.rowid";
314
                $sql .= " FROM " . MAIN_DB_PREFIX . "socpeople as p";
315
                $sql .= " WHERE p.fk_soc = " . ((int) $object->id);
316
317
                $result = $this->db->query($sql);
318
                $num = $this->db->num_rows($result);
319
320
                if ($num) {
321
                    $i = 0;
322
                    $contactstatic = new Contact($this->db);
323
324
                    while ($i < $num) {
325
                        $obj = $this->db->fetch_object($result);
326
327
                        $contact_arrray[$i] = $obj->rowid;
328
                        $i++;
329
                    }
330
                }
331
                if ((is_array($contact_arrray) && count($contact_arrray) > 0)) {
332
                    $foundtagforlines = 1;
333
                    try {
334
                        $listlines = $odfHandler->setSegment('companycontacts');
335
                    } catch (OdfExceptionSegmentNotFound $e) {
336
                        // We may arrive here if tags for lines not present into template
337
                        $foundtagforlines = 0;
338
                        dol_syslog($e->getMessage(), LOG_INFO);
339
                    }
340
                    if ($foundtagforlines) {
341
                        foreach ($contact_arrray as $array_key => $contact_id) {
342
                            $res_contact = $contactstatic->fetch($contact_id);
343
                            if ((int) $res_contact > 0) {
344
                                $tmparray = $this->get_substitutionarray_contact($contactstatic, $outputlangs, 'contact');
345
                                foreach ($tmparray as $key => $val) {
346
                                    try {
347
                                        $listlines->setVars($key, $val, true, 'UTF-8');
348
                                    } catch (SegmentException $e) {
349
                                        dol_syslog($e->getMessage(), LOG_INFO);
350
                                    }
351
                                }
352
                                $listlines->merge();
353
                            } else {
354
                                $this->error = $contactstatic->error;
355
                                dol_syslog($this->error, LOG_WARNING);
356
                            }
357
                        }
358
                        try {
359
                            $odfHandler->mergeSegment($listlines);
360
                        } catch (OdfException $e) {
361
                            $this->error = $e->getMessage();
362
                            dol_syslog($this->error, LOG_WARNING);
363
                            //return -1;
364
                        }
365
                    }
366
                }
367
368
                // Make substitutions into odt
369
                $array_user = $this->get_substitutionarray_user($user, $outputlangs);
370
                $array_soc = $this->get_substitutionarray_mysoc($mysoc, $outputlangs);
371
                $array_thirdparty = $this->get_substitutionarray_thirdparty($object, $outputlangs);
372
                $array_other = $this->get_substitutionarray_other($outputlangs);
373
374
                $tmparray = array_merge($array_user, $array_soc, $array_thirdparty, $array_other);
375
376
                complete_substitutions_array($tmparray, $outputlangs, $object);
377
378
                // Call the ODTSubstitution hook
379
                $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
380
                $reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
381
382
                // Replace variables into document
383
                foreach ($tmparray as $key => $value) {
384
                    try {
385
                        if (preg_match('/logo$/', $key)) {  // Image
386
                            if (file_exists($value)) {
387
                                $odfHandler->setImage($key, $value);
388
                            } else {
389
                                $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
390
                            }
391
                        } else { // Text
392
                            $odfHandler->setVars($key, $value, true, 'UTF-8');
393
                        }
394
                    } catch (OdfException $e) {
395
                        // setVars failed, probably because key not found
396
                        dol_syslog($e->getMessage(), LOG_INFO);
397
                    }
398
                }
399
400
                // Replace labels translated
401
                $tmparray = $outputlangs->get_translations_for_substitutions();
402
                foreach ($tmparray as $key => $value) {
403
                    try {
404
                        $odfHandler->setVars($key, $value, true, 'UTF-8');
405
                    } catch (OdfException $e) {
406
                        dol_syslog($e->getMessage(), LOG_INFO);
407
                    }
408
                }
409
410
                // Call the beforeODTSave hook
411
                $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
412
                $reshook = $hookmanager->executeHooks('beforeODTSave', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
413
414
                // Write new file
415
                if (getDolGlobalString('MAIN_ODT_AS_PDF')) {
416
                    try {
417
                        $odfHandler->exportAsAttachedPDF($file);
418
                    } catch (Exception $e) {
419
                        $this->error = $e->getMessage();
420
                        dol_syslog($e->getMessage(), LOG_INFO);
421
                        return -1;
422
                    }
423
                } else {
424
                    try {
425
                        $odfHandler->creator = $user->getFullName($outputlangs);
426
                        $odfHandler->title = $object->builddoc_filename;
0 ignored issues
show
Bug Best Practice introduced by
The property builddoc_filename does not exist on Dolibarr\Code\Societe\Classes\Societe. Since you implemented __get, consider adding a @property annotation.
Loading history...
427
                        $odfHandler->subject = $object->builddoc_filename;
428
429
                        if (getDolGlobalString('ODT_ADD_DOLIBARR_ID')) {
430
                            $odfHandler->userdefined['dol_id'] = $object->id;
431
                            $odfHandler->userdefined['dol_element'] = $object->element;
432
                        }
433
434
                        $odfHandler->saveToDisk($file);
435
                    } catch (Exception $e) {
436
                        $this->error = $e->getMessage();
437
                        dol_syslog($e->getMessage(), LOG_INFO);
438
                        return -1;
439
                    }
440
                }
441
                $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray);
442
                $reshook = $hookmanager->executeHooks('afterODTCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
443
444
                dolChmod($file);
445
446
                $odfHandler = null; // Destroy object
447
448
                $this->result = array('fullpath' => $file);
449
450
                return 1; // Success
451
            } else {
452
                $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
453
                return -1;
454
            }
455
        }
456
457
        $this->error = 'UnknownError';
458
        return -1;
459
    }
460
}
461