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

doc_generic_myobject_odt::write_file()   F

Complexity

Conditions 43
Paths > 20000

Size

Total Lines 288
Code Lines 182

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 43
eloc 182
nop 6
dl 0
loc 288
rs 0
c 1
b 0
f 0
nc 20572713

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/mymodule/doc/doc_generic_myobject_odt.modules.php
26
 *	\ingroup    mymodule
27
 *	\brief      File of class to build ODT documents for myobjects
28
 */
29
30
dol_include_once('/mymodule/core/modules/mymodule/modules_myobject.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_myobject_odt extends ModelePDFMyObject
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 = 'MYMODULE_MYOBJECT_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 FACTURE_TVAOPTION
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="MYMODULE_MYOBJECT_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->MYMODULE_MYOBJECT_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->MYMODULE_MYOBJECT_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->MYMODULE_MYOBJECT_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="hidden">';
176
			foreach ($listoffiles as $file) {
177
				$texte .= '- '.$file['name'].' <a href="'.DOL_URL_ROOT.'/document.php?modulepart=doctemplates&file=mymodule_myobject/'.urlencode(basename($file['name'])).'">'.img_picto('', 'listlight').'</a><br>';
178
			}
179
			$texte .= '</div>';
180
		}
181
182
		$texte .= '</td>';
183
184
		$texte .= '<td rowspan="2" class="tdtop hideonsmartphone">';
185
		$texte .= $langs->trans("ExampleOfDirectoriesForModelGen");
186
		$texte .= '</td>';
187
		$texte .= '</tr>';
188
189
		$texte .= '</table>';
190
		$texte .= '</form>';
191
192
		return $texte;
193
	}
194
195
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
196
	/**
197
	 *  Function to build a document on disk using the generic odt module.
198
	 *
199
	 *	@param		MyObject	$object				Object source to build document
200
	 *	@param		Translate	$outputlangs		Lang output object
201
	 * 	@param		string		$srctemplatepath	Full path of source filename for generator using a template file
202
	 *  @param		int			$hidedetails		Do not show line details
203
	 *  @param		int			$hidedesc			Do not show desc
204
	 *  @param		int			$hideref			Do not show ref
205
	 *	@return		int         					1 if OK, <=0 if KO
206
	 */
207
	public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
208
	{
209
		// phpcs:enable
210
		global $user, $langs, $conf, $mysoc, $hookmanager;
211
212
		if (empty($srctemplatepath)) {
213
			dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING);
214
			return -1;
215
		}
216
217
		// Add odtgeneration hook
218
		if (!is_object($hookmanager)) {
219
			include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
220
			$hookmanager = new HookManager($this->db);
221
		}
222
		$hookmanager->initHooks(array('odtgeneration'));
223
		global $action;
224
225
		if (!is_object($outputlangs)) {
226
			$outputlangs = $langs;
227
		}
228
		$sav_charset_output = $outputlangs->charset_output;
229
		$outputlangs->charset_output = 'UTF-8';
230
231
		$outputlangs->loadLangs(array("main", "dict", "companies", "bills"));
232
233
		if ($conf->mymodule->dir_output) {
234
			// If $object is id instead of object
235
			if (!is_object($object)) {
236
				$id = $object;
237
				$object = new MyObject($this->db);
238
				$result = $object->fetch($id);
239
				if ($result < 0) {
240
					dol_print_error($this->db, $object->error);
241
					return -1;
242
				}
243
			}
244
245
			$object->fetch_thirdparty();
246
247
			$dir = $conf->mymodule->multidir_output[isset($object->entity) ? $object->entity : 1];
248
			$objectref = dol_sanitizeFileName($object->ref);
249
			if (!preg_match('/specimen/i', $objectref)) {
250
				$dir .= "/".$objectref;
251
			}
252
			$file = $dir."/".$objectref.".odt";
253
254
			if (!file_exists($dir)) {
255
				if (dol_mkdir($dir) < 0) {
256
					$this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
257
					return -1;
258
				}
259
			}
260
261
			if (file_exists($dir)) {
262
				//print "srctemplatepath=".$srctemplatepath;	// Src filename
263
				$newfile = basename($srctemplatepath);
264
				$newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile);
265
				$newfiletmp = preg_replace('/template_/i', '', $newfiletmp);
266
				$newfiletmp = preg_replace('/modele_/i', '', $newfiletmp);
267
				$newfiletmp = $objectref.'_'.$newfiletmp;
268
				//$file=$dir.'/'.$newfiletmp.'.'.dol_print_date(dol_now(),'%Y%m%d%H%M%S').'.odt';
269
				// Get extension (ods or odt)
270
				$newfileformat = substr($newfile, strrpos($newfile, '.') + 1);
271
				if (!empty($conf->global->MAIN_DOC_USE_TIMING)) {
272
					$format = $conf->global->MAIN_DOC_USE_TIMING;
273
					if ($format == '1') {
274
						$format = '%Y%m%d%H%M%S';
275
					}
276
					$filename = $newfiletmp.'-'.dol_print_date(dol_now(), $format).'.'.$newfileformat;
277
				} else {
278
					$filename = $newfiletmp.'.'.$newfileformat;
279
				}
280
				$file = $dir.'/'.$filename;
281
				//print "newdir=".$dir;
282
				//print "newfile=".$newfile;
283
				//print "file=".$file;
284
				//print "conf->societe->dir_temp=".$conf->societe->dir_temp;
285
286
				dol_mkdir($conf->mymodule->dir_temp);
287
				if (!is_writable($conf->mymodule->dir_temp)) {
288
					$this->error = "Failed to write in temp directory ".$conf->mymodule->dir_temp;
289
					dol_syslog('Error in write_file: '.$this->error, LOG_ERR);
290
					return -1;
291
				}
292
293
				// If CUSTOMER contact defined on order, we use it
294
				$usecontact = false;
295
				$arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
296
				if (count($arrayidcontact) > 0) {
297
					$usecontact = true;
298
					$result = $object->fetch_contact($arrayidcontact[0]);
299
				}
300
301
				// Recipient name
302
				$contactobject = null;
303
				if (!empty($usecontact)) {
304
					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)))) {
305
						$socobject = $object->contact;
306
					} else {
307
						$socobject = $object->thirdparty;
308
						// if we have a CUSTOMER contact and we dont use it as recipient we store the contact object for later use
309
						$contactobject = $object->contact;
310
					}
311
				} else {
312
					$socobject = $object->thirdparty;
313
				}
314
315
				// Make substitution
316
				$substitutionarray = array(
317
					'__FROM_NAME__' => $this->emetteur->name,
318
					'__FROM_EMAIL__' => $this->emetteur->email,
319
					'__TOTAL_TTC__' => $object->total_ttc,
320
					'__TOTAL_HT__' => $object->total_ht,
321
					'__TOTAL_VAT__' => $object->total_tva
322
				);
323
				complete_substitutions_array($substitutionarray, $langs, $object);
324
				// Call the ODTSubstitution hook
325
				$parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$substitutionarray);
326
				$reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
327
328
				// Line of free text
329
				$newfreetext = '';
330
				$paramfreetext = 'ORDER_FREE_TEXT';
331
				if (!empty($conf->global->$paramfreetext)) {
332
					$newfreetext = make_substitutions($conf->global->$paramfreetext, $substitutionarray);
333
				}
334
335
				// Open and load template
336
				require_once ODTPHP_PATH.'odf.php';
337
				try {
338
					$odfHandler = new odf(
339
						$srctemplatepath,
340
						array(
341
						'PATH_TO_TMP'	  => $conf->mymodule->dir_temp,
342
						'ZIP_PROXY'		  => 'PclZipProxy', // PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy.
343
						'DELIMITER_LEFT'  => '{',
344
						'DELIMITER_RIGHT' => '}'
345
						)
346
					);
347
				} catch (Exception $e) {
348
					$this->error = $e->getMessage();
349
					dol_syslog($e->getMessage(), LOG_INFO);
350
					return -1;
351
				}
352
				// After construction $odfHandler->contentXml contains content and
353
				// [!-- BEGIN row.lines --]*[!-- END row.lines --] has been replaced by
354
				// [!-- BEGIN lines --]*[!-- END lines --]
355
				//print html_entity_decode($odfHandler->__toString());
356
				//print exit;
357
358
359
				// Make substitutions into odt of freetext
360
				try {
361
					$odfHandler->setVars('free_text', $newfreetext, true, 'UTF-8');
362
				} catch (OdfException $e) {
363
					dol_syslog($e->getMessage(), LOG_INFO);
364
				}
365
366
				// Define substitution array
367
				$substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
368
				$array_object_from_properties = $this->get_substitutionarray_each_var_object($object, $outputlangs);
369
				$array_objet = $this->get_substitutionarray_object($object, $outputlangs);
370
				$array_user = $this->get_substitutionarray_user($user, $outputlangs);
371
				$array_soc = $this->get_substitutionarray_mysoc($mysoc, $outputlangs);
372
				$array_thirdparty = $this->get_substitutionarray_thirdparty($socobject, $outputlangs);
373
				$array_other = $this->get_substitutionarray_other($outputlangs);
374
				// retrieve contact information for use in object as contact_xxx tags
375
				$array_thirdparty_contact = array();
376
				if ($usecontact && is_object($contactobject)) {
377
					$array_thirdparty_contact = $this->get_substitutionarray_contact($contactobject, $outputlangs, 'contact');
378
				}
379
380
				$tmparray = array_merge($substitutionarray, $array_object_from_properties, $array_user, $array_soc, $array_thirdparty, $array_objet, $array_other, $array_thirdparty_contact);
381
				complete_substitutions_array($tmparray, $outputlangs, $object);
382
383
				// Call the ODTSubstitution hook
384
				$parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray);
385
				$reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
386
387
				foreach ($tmparray as $key => $value) {
388
					try {
389
						if (preg_match('/logo$/', $key)) {
390
							// Image
391
							if (file_exists($value)) {
392
								$odfHandler->setImage($key, $value);
393
							} else {
394
								$odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
395
							}
396
						} else {
397
							// Text
398
							$odfHandler->setVars($key, $value, true, 'UTF-8');
399
						}
400
					} catch (OdfException $e) {
401
						dol_syslog($e->getMessage(), LOG_INFO);
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
					if ($foundtagforlines) {
415
						$linenumber = 0;
416
						foreach ($object->lines as $line) {
417
							$linenumber++;
418
							$tmparray = $this->get_substitutionarray_lines($line, $outputlangs, $linenumber);
419
							complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines");
420
							// Call the ODTSubstitutionLine hook
421
							$parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray, 'line'=>$line);
422
							$reshook = $hookmanager->executeHooks('ODTSubstitutionLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
423
							foreach ($tmparray as $key => $val) {
424
								try {
425
									$listlines->setVars($key, $val, true, 'UTF-8');
426
								} catch (OdfException $e) {
427
									dol_syslog($e->getMessage(), LOG_INFO);
428
								} catch (SegmentException $e) {
429
									dol_syslog($e->getMessage(), LOG_INFO);
430
								}
431
							}
432
							$listlines->merge();
433
						}
434
						$odfHandler->mergeSegment($listlines);
435
					}
436
				} catch (OdfException $e) {
437
					$this->error = $e->getMessage();
438
					dol_syslog($this->error, LOG_WARNING);
439
					return -1;
440
				}
441
442
				// Replace labels translated
443
				$tmparray = $outputlangs->get_translations_for_substitutions();
444
				foreach ($tmparray as $key => $value) {
445
					try {
446
						$odfHandler->setVars($key, $value, true, 'UTF-8');
447
					} catch (OdfException $e) {
448
						dol_syslog($e->getMessage(), LOG_INFO);
449
					}
450
				}
451
452
				// Call the beforeODTSave hook
453
454
				$parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray);
455
				$reshook = $hookmanager->executeHooks('beforeODTSave', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
456
457
				// Write new file
458
				if (!empty($conf->global->MAIN_ODT_AS_PDF)) {
459
					try {
460
						$odfHandler->exportAsAttachedPDF($file);
461
					} catch (Exception $e) {
462
						$this->error = $e->getMessage();
463
						dol_syslog($e->getMessage(), LOG_INFO);
464
						return -1;
465
					}
466
				} else {
467
					try {
468
						$odfHandler->saveToDisk($file);
469
					} catch (Exception $e) {
470
						$this->error = $e->getMessage();
471
						dol_syslog($e->getMessage(), LOG_INFO);
472
						return -1;
473
					}
474
				}
475
476
				$parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray);
477
				$reshook = $hookmanager->executeHooks('afterODTCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
478
479
				if (!empty($conf->global->MAIN_UMASK)) {
480
					@chmod($file, octdec($conf->global->MAIN_UMASK));
481
				}
482
483
				$odfHandler = null; // Destroy object
484
485
				$this->result = array('fullpath'=>$file);
486
487
				return 1; // Success
488
			} else {
489
				$this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
490
				return -1;
491
			}
492
		}
493
494
		return -1;
495
	}
496
}
497