Passed
Branch develop (21edb4)
by
unknown
41:33
created

doc_generic_mo_odt::write_file()   F

Complexity

Conditions 27
Paths 16425

Size

Total Lines 288
Code Lines 113

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 27
eloc 113
nop 6
dl 0
loc 288
rs 0
c 0
b 0
f 0
nc 16425

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
/* Copyright (C) 2010-2012 	Laurent Destailleur <[email protected]>
3
 * Copyright (C) 2012		Juanjo Menent		<[email protected]>
4
 * Copyright (C) 2014		Marcos García		<[email protected]>
5
 * Copyright (C) 2016		Charlie Benke		<[email protected]>
6
 * Copyright (C) 2018-2021  Philippe Grand      <[email protected]>
7
 * Copyright (C) 2018       Frédéric France     <[email protected]>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
 * or see https://www.gnu.org/
22
 */
23
24
/**
25
 *	\file       htdocs/core/modules/mrp/doc/doc_generic_mo_odt.modules.php
26
 *	\ingroup    mrp
27
 *	\brief      File of class to build ODT documents for MOs
28
 */
29
30
require_once DOL_DOCUMENT_ROOT.'/core/modules/mrp/modules_mo.php';
31
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
32
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
33
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
34
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
35
require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php';
36
37
38
/**
39
 *	Class to build documents using ODF templates generator
40
 */
41
class doc_generic_mo_odt extends ModelePDFMo
42
{
43
	/**
44
	 * Issuer
45
	 * @var Societe
46
	 */
47
	public $emetteur;
48
49
	/**
50
	 * @var array Minimum version of PHP required by module.
51
	 * e.g.: PHP ≥ 5.6 = array(5, 6)
52
	 */
53
	public $phpmin = array(5, 6);
54
55
	/**
56
	 * @var string Dolibarr version of the loaded document
57
	 */
58
	public $version = 'dolibarr';
59
60
61
	/**
62
	 *	Constructor
63
	 *
64
	 *  @param		DoliDB		$db      Database handler
65
	 */
66
	public function __construct($db)
67
	{
68
		global $conf, $langs, $mysoc;
69
70
		// Load translation files required by the page
71
		$langs->loadLangs(array("main", "companies"));
72
73
		$this->db = $db;
74
		$this->name = "ODT templates";
75
		$this->description = $langs->trans("DocumentModelOdt");
76
		$this->scandir = 'MRP_MO_ADDON_PDF_ODT_PATH'; // Name of constant that is used to save list of directories to scan
77
78
		// Page size for A4 format
79
		$this->type = 'odt';
80
		$this->page_largeur = 0;
81
		$this->page_hauteur = 0;
82
		$this->format = array($this->page_largeur, $this->page_hauteur);
83
		$this->marge_gauche = 0;
84
		$this->marge_droite = 0;
85
		$this->marge_haute = 0;
86
		$this->marge_basse = 0;
87
88
		$this->option_logo = 1; // Display logo
89
		$this->option_tva = 0; // Manage the vat option
90
		$this->option_modereg = 0; // Display payment mode
91
		$this->option_condreg = 0; // Display payment terms
92
		$this->option_codeproduitservice = 0; // Display product-service code
93
		$this->option_multilang = 1; // Available in several languages
94
		$this->option_escompte = 0; // Displays if there has been a discount
95
		$this->option_credit_note = 0; // Support credit notes
96
		$this->option_freetext = 1; // Support add of a personalised text
97
		$this->option_draft_watermark = 0; // Support add of a watermark on drafts
98
99
		// Get source company
100
		$this->emetteur = $mysoc;
101
		if (!$this->emetteur->country_code) {
102
			$this->emetteur->country_code = substr($langs->defaultlang, -2); // By default if not defined
103
		}
104
	}
105
106
107
	/**
108
	 *	Return description of a module
109
	 *
110
	 *	@param	Translate	$langs      Lang object to use for output
111
	 *	@return string       			Description
112
	 */
113
	public function info($langs)
114
	{
115
		global $conf, $langs;
116
117
		// Load translation files required by the page
118
		$langs->loadLangs(array("errors", "companies"));
119
120
		$form = new Form($this->db);
121
122
		$texte = $this->description.".<br>\n";
123
		$texte .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
124
		$texte .= '<input type="hidden" name="token" value="'.newToken().'">';
125
		$texte .= '<input type="hidden" name="action" value="setModuleOptions">';
126
		$texte .= '<input type="hidden" name="param1" value="MRP_MO_ADDON_PDF_ODT_PATH">';
127
		$texte .= '<table class="nobordernopadding" width="100%">';
128
129
		// List of directories area
130
		$texte .= '<tr><td>';
131
		$texttitle = $langs->trans("ListOfDirectories");
132
		$listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->MRP_MO_ADDON_PDF_ODT_PATH)));
133
		$listoffiles = array();
134
		foreach ($listofdir as $key => $tmpdir) {
135
			$tmpdir = trim($tmpdir);
136
			$tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir);
137
			if (!$tmpdir) {
138
				unset($listofdir[$key]);
139
				continue;
140
			}
141
			if (!is_dir($tmpdir)) {
142
				$texttitle .= img_warning($langs->trans("ErrorDirNotFound", $tmpdir), 0);
143
			} else {
144
				$tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.(ods|odt)');
145
				if (count($tmpfiles)) {
146
					$listoffiles = array_merge($listoffiles, $tmpfiles);
147
				}
148
			}
149
		}
150
		$texthelp = $langs->trans("ListOfDirectoriesForModelGenODT");
151
		// Add list of substitution keys
152
		$texthelp .= '<br>'.$langs->trans("FollowingSubstitutionKeysCanBeUsed").'<br>';
153
		$texthelp .= $langs->transnoentitiesnoconv("FullListOnOnlineDocumentation"); // This contains an url, we don't modify it
154
155
		$texte .= $form->textwithpicto($texttitle, $texthelp, 1, 'help', '', 1);
156
		$texte .= '<div><div style="display: inline-block; min-width: 100px; vertical-align: middle;">';
157
		$texte .= '<textarea class="flat" cols="60" name="value1">';
158
		$texte .= $conf->global->MRP_MO_ADDON_PDF_ODT_PATH;
159
		$texte .= '</textarea>';
160
		$texte .= '</div><div style="display: inline-block; vertical-align: middle;">';
161
		$texte .= '<input type="submit" class="button small" value="'.$langs->trans("Modify").'" name="Button">';
162
		$texte .= '<br></div></div>';
163
164
		// Scan directories
165
		$nbofiles = count($listoffiles);
166
		if (!empty($conf->global->MRP_MO_ADDON_PDF_ODT_PATH)) {
167
			$texte .= $langs->trans("NumberOfModelFilesFound").': <b>';
168
			//$texte.=$nbofiles?'<a id="a_'.get_class($this).'" href="#">':'';
169
			$texte .= count($listoffiles);
170
			//$texte.=$nbofiles?'</a>':'';
171
			$texte .= '</b>';
172
		}
173
174
		if ($nbofiles) {
175
			$texte .= '<div id="div_'.get_class($this).'" class="hiddenx">';
176
			// Show list of found files
177
			foreach ($listoffiles as $file) {
178
				$texte .= '- '.$file['name'].' <a href="'.DOL_URL_ROOT.'/document.php?modulepart=doctemplates&file=mrps/'.urlencode(basename($file['name'])).'">'.img_picto('', 'listlight').'</a><br>';
179
			}
180
			$texte .= '</div>';
181
		}
182
183
		$texte .= '</td>';
184
185
		$texte .= '<td rowspan="2" class="tdtop hideonsmartphone">';
186
		$texte .= $langs->trans("ExampleOfDirectoriesForModelGen");
187
		$texte .= '</td>';
188
		$texte .= '</tr>';
189
190
		$texte .= '</table>';
191
		$texte .= '</form>';
192
193
		return $texte;
194
	}
195
196
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
197
	/**
198
	 *  Function to build a document on disk using the generic odt module.
199
	 *
200
	 *	@param		MO			$object				Object source to build document
201
	 *	@param		Translate	$outputlangs		Lang output object
202
	 * 	@param		string		$srctemplatepath	Full path of source filename for generator using a template file
203
	 *  @param		int			$hidedetails		Do not show line details
204
	 *  @param		int			$hidedesc			Do not show desc
205
	 *  @param		int			$hideref			Do not show ref
206
	 *	@return		int         					1 if OK, <=0 if KO
207
	 */
208
	public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
209
	{
210
		// phpcs:enable
211
		global $user, $langs, $conf, $mysoc, $hookmanager;
212
213
		if (empty($srctemplatepath)) {
214
			dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING);
215
			return -1;
216
		}
217
218
		// Add odtgeneration hook
219
		if (!is_object($hookmanager)) {
220
			include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
221
			$hookmanager = new HookManager($this->db);
222
		}
223
		$hookmanager->initHooks(array('odtgeneration'));
224
		global $action;
225
226
		if (!is_object($outputlangs)) {
227
			$outputlangs = $langs;
228
		}
229
		$sav_charset_output = $outputlangs->charset_output;
230
		$outputlangs->charset_output = 'UTF-8';
231
232
		$outputlangs->loadLangs(array("main", "dict", "companies", "bills"));
233
234
		if ($conf->mrp->dir_output) {
235
			// If $object is id instead of object
236
			if (!is_object($object)) {
237
				$id = $object;
238
				$object = new MO($this->db);
239
				$result = $object->fetch($id);
240
				if ($result < 0) {
241
					dol_print_error($this->db, $object->error);
242
					return -1;
243
				}
244
			}
245
246
			$object->fetch_thirdparty();
247
248
			$dir = $conf->mrp->multidir_output[isset($object->entity) ? $object->entity : 1];
249
			$objectref = dol_sanitizeFileName($object->ref);
250
			if (!preg_match('/specimen/i', $objectref)) {
251
				$dir .= "/".$objectref;
252
			}
253
			$file = $dir."/".$objectref.".odt";
254
255
			if (!file_exists($dir)) {
256
				if (dol_mkdir($dir) < 0) {
257
					$this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
258
					return -1;
259
				}
260
			}
261
262
			if (file_exists($dir)) {
263
				//print "srctemplatepath=".$srctemplatepath;	// Src filename
264
				$newfile = basename($srctemplatepath);
265
				$newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile);
266
				$newfiletmp = preg_replace('/template_/i', '', $newfiletmp);
267
				$newfiletmp = preg_replace('/modele_/i', '', $newfiletmp);
268
				$newfiletmp = $objectref.'_'.$newfiletmp;
269
				//$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt';
270
				// Get extension (ods or odt)
271
				$newfileformat = substr($newfile, strrpos($newfile, '.') + 1);
272
				if (!empty($conf->global->MAIN_DOC_USE_TIMING)) {
273
					$format = $conf->global->MAIN_DOC_USE_TIMING;
274
					if ($format == '1') {
275
						$format = '%Y%m%d%H%M%S';
276
					}
277
					$filename = $newfiletmp.'-'.dol_print_date(dol_now(), $format).'.'.$newfileformat;
278
				} else {
279
					$filename = $newfiletmp.'.'.$newfileformat;
280
				}
281
				$file = $dir.'/'.$filename;
282
				//print "newdir=".$dir;
283
				//print "newfile=".$newfile;
284
				//print "file=".$file;
285
				//print "conf->societe->dir_temp=".$conf->societe->dir_temp;
286
287
				dol_mkdir($conf->mrp->dir_temp);
288
				if (!is_writable($conf->mrp->dir_temp)) {
289
					$this->error = "Failed to write in temp directory ".$conf->mrp->dir_temp;
290
					dol_syslog('Error in write_file: '.$this->error, LOG_ERR);
291
					return -1;
292
				}
293
294
				// If CUSTOMER contact defined on order, we use it
295
				$usecontact = false;
296
				$arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
297
				if (count($arrayidcontact) > 0) {
298
					$usecontact = true;
299
					$result = $object->fetch_contact($arrayidcontact[0]);
300
				}
301
302
				// Recipient name
303
				$contactobject = null;
304
				if (!empty($usecontact)) {
305
					if ($usecontact && ($object->contact->fk_soc != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)))) {
306
						$socobject = $object->contact;
307
					} else {
308
						$socobject = $object->thirdparty;
309
						// if we have a CUSTOMER contact and we dont use it as recipient we store the contact object for later use
310
						$contactobject = $object->contact;
311
					}
312
				} else {
313
					$socobject = $object->thirdparty;
314
				}
315
316
				// Make substitution
317
				$substitutionarray = array(
318
					'__QTY_TO_PRODUCE__' => $object->qty,
319
				);
320
				complete_substitutions_array($substitutionarray, $langs, $object);
321
				// Call the ODTSubstitution hook
322
				$parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$substitutionarray);
323
				$reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
324
325
				// Line of free text
326
				$newfreetext = '';
327
				$paramfreetext = 'MRP_MO_FREE_TEXT';
328
				if (!empty($conf->global->$paramfreetext)) {
329
					$newfreetext = make_substitutions($conf->global->$paramfreetext, $substitutionarray);
330
				}
331
332
				// Open and load template
333
				require_once ODTPHP_PATH.'odf.php';
334
				try {
335
					$odfHandler = new odf(
336
						$srctemplatepath,
337
						array(
338
						'PATH_TO_TMP'	  => $conf->mrp->dir_temp,
339
						'ZIP_PROXY'		  => 'PclZipProxy', // PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy.
340
						'DELIMITER_LEFT'  => '{',
341
						'DELIMITER_RIGHT' => '}'
342
						)
343
					);
344
				} catch (Exception $e) {
345
					$this->error = $e->getMessage();
346
					dol_syslog($e->getMessage(), LOG_INFO);
347
					return -1;
348
				}
349
350
				// After construction $odfHandler->contentXml contains content and
351
				// [!-- BEGIN row.lines --]*[!-- END row.lines --] has been replaced by
352
				// [!-- BEGIN lines --]*[!-- END lines --]
353
				//print html_entity_decode($odfHandler->__toString());
354
				//print exit;
355
				/*
356
357
358
				// Make substitutions into odt of freetext
359
				try {
360
					$odfHandler->setVars('free_text', $newfreetext, true, 'UTF-8');
361
				} catch (OdfException $e) {
362
					dol_syslog($e->getMessage(), LOG_INFO);
363
				}
364
365
				// Define substitution array
366
				$substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
367
				$array_object_from_properties = $this->get_substitutionarray_each_var_object($object, $outputlangs);
368
				$array_objet = $this->get_substitutionarray_object($object, $outputlangs);
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($socobject, $outputlangs);
372
				$array_other = $this->get_substitutionarray_other($outputlangs);
373
				// retrieve contact information for use in object as contact_xxx tags
374
				$array_thirdparty_contact = array();
375
				if ($usecontact && is_object($contactobject)) {
376
					$array_thirdparty_contact = $this->get_substitutionarray_contact($contactobject, $outputlangs, 'contact');
377
				}
378
379
				$tmparray = array_merge($substitutionarray, $array_object_from_properties, $array_user, $array_soc, $array_thirdparty, $array_objet, $array_other, $array_thirdparty_contact);
380
				complete_substitutions_array($tmparray, $outputlangs, $object);
381
382
				// Call the ODTSubstitution hook
383
				$parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray);
384
				$reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
385
386
				foreach ($tmparray as $key => $value) {
387
					try {
388
						if (preg_match('/logo$/', $key)) {
389
							// Image
390
							if (file_exists($value)) {
391
								$odfHandler->setImage($key, $value);
392
							} else {
393
								$odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
394
							}
395
						} else {
396
							// Text
397
							$odfHandler->setVars($key, $value, true, 'UTF-8');
398
						}
399
					} catch (OdfException $e) {
400
						dol_syslog($e->getMessage(), LOG_INFO);
401
					}
402
				}
403
404
				// Replace tags of lines
405
				try {
406
					$foundtagforlines = 1;
407
					try {
408
						$listlines = $odfHandler->setSegment('lines');
409
					} catch (OdfException $e) {
410
						// We may arrive here if tags for lines not present into template
411
						$foundtagforlines = 0;
412
						dol_syslog($e->getMessage(), LOG_INFO);
413
					}
414
415
					if ($foundtagforlines) {
416
						$linenumber = 0;
417
						foreach ($object->lines as $line) {
418
							$linenumber++;
419
							$tmparray = $this->get_substitutionarray_lines($line, $outputlangs, $linenumber);
420
							complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines");
421
							// Call the ODTSubstitutionLine hook
422
							$parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray, 'line'=>$line);
423
							$reshook = $hookmanager->executeHooks('ODTSubstitutionLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
424
							foreach ($tmparray as $key => $val) {
425
								try {
426
									$listlines->setVars($key, $val, true, 'UTF-8');
427
								} catch (OdfException $e) {
428
									dol_syslog($e->getMessage(), LOG_INFO);
429
								} catch (SegmentException $e) {
430
									dol_syslog($e->getMessage(), LOG_INFO);
431
								}
432
							}
433
							$listlines->merge();
434
						}
435
						$odfHandler->mergeSegment($listlines);
436
					}
437
				} catch (OdfException $e) {
438
					$this->error = $e->getMessage();
439
					dol_syslog($this->error, LOG_WARNING);
440
					return -1;
441
				}
442
443
				// Replace labels translated
444
				$tmparray = $outputlangs->get_translations_for_substitutions();
445
				foreach ($tmparray as $key => $value) {
446
					try {
447
						$odfHandler->setVars($key, $value, true, 'UTF-8');
448
					} catch (OdfException $e) {
449
						dol_syslog($e->getMessage(), LOG_INFO);
450
					}
451
				}
452
453
				// Call the beforeODTSave hook
454
455
				$parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray);
456
				$reshook = $hookmanager->executeHooks('beforeODTSave', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
457
				*/
458
				// Write new file
459
				if (!empty($conf->global->MAIN_ODT_AS_PDF)) {
460
					try {
461
						$odfHandler->exportAsAttachedPDF($file);
462
					} catch (Exception $e) {
463
						$this->error = $e->getMessage();
464
						dol_syslog('Error in exportAsAttachedPDF: '.$e->getMessage(), LOG_INFO);
465
						return -1;
466
					}
467
				} else {
468
					try {
469
						$odfHandler->saveToDisk($file);
470
					} catch (Exception $e) {
471
						$this->error = $e->getMessage();
472
						dol_syslog('Error in saveToDisk: '.$e->getMessage(), LOG_INFO);
473
						return -1;
474
					}
475
				}
476
477
				$parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $tmparray seems to be never defined.
Loading history...
478
				$reshook = $hookmanager->executeHooks('afterODTCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
479
480
				if (!empty($conf->global->MAIN_UMASK)) {
481
					@chmod($file, octdec($conf->global->MAIN_UMASK));
482
				}
483
484
				$odfHandler = null; // Destroy object
485
486
				$this->result = array('fullpath'=>$file);
487
488
				return 1; // Success
489
			} else {
490
				$this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
491
				return -1;
492
			}
493
		}
494
495
		return -1;
496
	}
497
}
498