Passed
Branch develop (30d2c8)
by
unknown
26:49
created

doc_generic_ticket_odt::write_file()   F

Complexity

Conditions 32
Paths > 20000

Size

Total Lines 213
Code Lines 123

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 32
eloc 123
nc 187257
nop 6
dl 0
loc 213
rs 0
c 1
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
/* Copyright (C) 2010-2012 	Laurent Destailleur <[email protected]>
3
 * Copyright (C) 2012		Juanjo Menent		<[email protected]>
4
 * Copyright (C) 2018-2020  Frédéric France         <[email protected]>
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 3 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18
* or see https://www.gnu.org/
19
*/
20
21
/**
22
 *	\file       htdocs/core/modules/ticket/doc/doc_generic_ticket_odt.modules.php
23
 *	\ingroup    ticket
24
 *	\brief      File of class to build ODT documents for tickets
25
 */
26
27
require_once DOL_DOCUMENT_ROOT.'/core/modules/ticket/modules_ticket.php';
28
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
29
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
30
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
31
require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php';
32
33
34
/**
35
 *	Class to build documents using ODF templates generator
36
 */
37
class doc_generic_ticket_odt extends ModelePDFTicket
38
{
39
	/**
40
	 * @var Societe Issuer
41
	 */
42
	public $emetteur;
43
44
	/**
45
	 * @var array Minimum version of PHP required by module.
46
	 * e.g.: PHP ≥ 5.6 = array(5, 6)
47
	 */
48
	public $phpmin = array(5, 6);
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 $conf, $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 = 'TICKET_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; // Affiche logo
85
		$this->option_tva = 0; // Gere option tva USER_TVAOPTION
86
		$this->option_multilang = 1; // Dispo en plusieurs langues
87
		$this->option_freetext = 0; // Support add of a personalised text
88
		$this->option_draft_watermark = 0; // Support add of a watermark on drafts
89
90
		// Recupere emetteur
91
		$this->emetteur = $mysoc;
92
		if (!$this->emetteur->country_code) $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default if not defined
93
	}
94
95
96
	/**
97
	 *	Return description of a module
98
	 *
99
	 *	@param	Translate	$langs      Lang object to use for output
100
	 *	@return string       			Description
101
	 */
102
	public function info($langs)
103
	{
104
		global $conf, $langs;
105
106
		// Load translation files required by the page
107
		$langs->loadLangs(array('companies', 'errors'));
108
109
		$form = new Form($this->db);
110
111
		$texte = $this->description.".<br>\n";
112
		$texte .= '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" enctype="multipart/form-data">';
113
		$texte .= '<input type="hidden" name="token" value="'.newToken().'">';
114
		$texte .= '<input type="hidden" name="action" value="setModuleOptions">';
115
		$texte .= '<input type="hidden" name="param1" value="TICKET_ADDON_PDF_ODT_PATH">';
116
117
		$texte .= '<table class="nobordernopadding" width="100%">';
118
119
		// List of directories area
120
		$texte .= '<tr><td>';
121
		$texttitle = $langs->trans("ListOfDirectories");
122
		$listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->TICKET_ADDON_PDF_ODT_PATH)));
123
		$listoffiles = array();
124
		foreach ($listofdir as $key=>$tmpdir)
125
		{
126
			$tmpdir = trim($tmpdir);
127
			$tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir);
128
			if (!$tmpdir) {
129
				unset($listofdir[$key]); continue;
130
			}
131
			if (!is_dir($tmpdir)) $texttitle .= img_warning($langs->trans("ErrorDirNotFound", $tmpdir), 0);
132
			else {
133
				$tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.(ods|odt)');
134
				if (count($tmpfiles)) $listoffiles = array_merge($listoffiles, $tmpfiles);
135
			}
136
		}
137
		$texthelp = $langs->trans("ListOfDirectoriesForModelGenODT");
138
		// Add list of substitution keys
139
		$texthelp .= '<br>'.$langs->trans("FollowingSubstitutionKeysCanBeUsed").'<br>';
140
		$texthelp .= $langs->transnoentitiesnoconv("FullListOnOnlineDocumentation"); // This contains an url, we don't modify it
141
142
		$texte .= $form->textwithpicto($texttitle, $texthelp, 1, 'help', '', 1);
143
		$texte .= '<div><div style="display: inline-block; min-width: 100px; vertical-align: middle;">';
144
		$texte .= '<textarea class="flat" cols="60" name="value1">';
145
		$texte .= $conf->global->TICKET_ADDON_PDF_ODT_PATH;
146
		$texte .= '</textarea>';
147
		$texte .= '</div><div style="display: inline-block; vertical-align: middle;">';
148
		$texte .= '<input type="submit" class="button" value="'.$langs->trans("Modify").'" name="Button">';
149
		$texte .= '<br></div></div>';
150
151
		// Scan directories
152
		if (count($listofdir))
153
		{
154
			$texte .= $langs->trans("NumberOfModelFilesFound").': <b>'.count($listoffiles).'</b>';
155
156
			$texte .= '<div id="div_'.get_class($this).'" class="hiddenx">';
157
			// Show list of found files
158
			foreach ($listoffiles as $file) {
159
				$texte .= '- '.$file['name'].' <a href="'.DOL_URL_ROOT.'/document.php?modulepart=doctemplates&file=tickets/'.urlencode(basename($file['name'])).'">'.img_picto('', 'listlight').'</a><br>';
160
			}
161
			$texte .= '</div>';
162
		}
163
		// Add input to upload a new template file.
164
		$texte .= '<div>'.$langs->trans("UploadNewTemplate").' <input type="file" name="uploadfile">';
165
		$texte .= '<input type="hidden" value="TICKET_ADDON_PDF_ODT_PATH" name="keyforuploaddir">';
166
		$texte .= '<input type="submit" class="button" value="'.dol_escape_htmltag($langs->trans("Upload")).'" name="upload">';
167
		$texte .= '</div>';
168
169
		$texte .= '</td>';
170
171
		$texte .= '<td rowspan="2" class="tdtop hideonsmartphone">';
172
		$texte .= $langs->trans("ExampleOfDirectoriesForModelGen");
173
		$texte .= '</td>';
174
		$texte .= '</tr>';
175
176
		$texte .= '</table>';
177
		$texte .= '</form>';
178
179
		return $texte;
180
	}
181
182
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
183
	/**
184
	 *  Function to build a document on disk using the generic odt module.
185
	 *
186
	 *	@param		User		$object				Object source to build document
187
	 *	@param		Translate	$outputlangs		Lang output object
188
	 * 	@param		string		$srctemplatepath	Full path of source filename for generator using a template file
189
	 *  @param		int			$hidedetails		Do not show line details
190
	 *  @param		int			$hidedesc			Do not show desc
191
	 *  @param		int			$hideref			Do not show ref
192
	 *	@return		int         					1 if OK, <=0 if KO
193
	 */
194
	public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
195
	{
196
		// phpcs:enable
197
		global $user, $langs, $conf, $mysoc, $hookmanager;
198
199
		if (empty($srctemplatepath))
200
		{
201
			dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING);
202
			return -1;
203
		}
204
205
		// Add odtgeneration hook
206
		if (!is_object($hookmanager))
207
		{
208
			include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
209
			$hookmanager = new HookManager($this->db);
210
		}
211
		$hookmanager->initHooks(array('odtgeneration'));
212
		global $action;
213
214
		if (!is_object($outputlangs)) $outputlangs = $langs;
215
		$sav_charset_output = $outputlangs->charset_output;
216
		$outputlangs->charset_output = 'UTF-8';
217
218
		// Load translation files required by the page
219
		$outputlangs->loadLangs(array("main", "companies", "bills", "dict"));
220
221
		if ($conf->user->dir_output)
222
		{
223
			// If $object is id instead of object
224
			if (!is_object($object))
225
			{
226
				$id = $object;
227
				$object = new User($this->db);
228
				$result = $object->fetch($id);
229
				if ($result < 0)
230
				{
231
					dol_print_error($this->db, $object->error);
232
					return -1;
233
				}
234
			}
235
236
			$object->fetch_thirdparty();
237
238
			$dir = $conf->user->dir_output;
239
			$objectref = dol_sanitizeFileName($object->ref);
240
			if (!preg_match('/specimen/i', $objectref)) $dir .= "/".$objectref;
241
			$file = $dir."/".$objectref.".odt";
242
243
			if (!file_exists($dir))
244
			{
245
				if (dol_mkdir($dir) < 0)
246
				{
247
					$this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
248
					return -1;
249
				}
250
			}
251
252
			if (file_exists($dir))
253
			{
254
				//print "srctemplatepath=".$srctemplatepath;	// Src filename
255
				$newfile = basename($srctemplatepath);
256
				$newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile);
257
				$newfiletmp = preg_replace('/template_/i', '', $newfiletmp);
258
				$newfiletmp = preg_replace('/modele_/i', '', $newfiletmp);
259
260
				$newfiletmp = $objectref.'_'.$newfiletmp;
261
262
				// Get extension (ods or odt)
263
				$newfileformat = substr($newfile, strrpos($newfile, '.') + 1);
264
				if (!empty($conf->global->MAIN_DOC_USE_TIMING))
265
				{
266
					$format = $conf->global->MAIN_DOC_USE_TIMING;
267
					if ($format == '1') $format = '%Y%m%d%H%M%S';
268
					$filename = $newfiletmp.'-'.dol_print_date(dol_now(), $format).'.'.$newfileformat;
269
				} else {
270
					$filename = $newfiletmp.'.'.$newfileformat;
271
				}
272
				$file = $dir.'/'.$filename;
273
				//print "newdir=".$dir;
274
				//print "newfile=".$newfile;
275
				//print "file=".$file;
276
				//print "conf->user->dir_temp=".$conf->user->dir_temp;
277
278
				dol_mkdir($conf->user->dir_temp);
279
280
281
				// If CUSTOMER contact defined on user, we use it
282
				$usecontact = false;
283
				$arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
284
				if (count($arrayidcontact) > 0)
285
				{
286
					$usecontact = true;
287
					$result = $object->fetch_contact($arrayidcontact[0]);
288
				}
289
290
				// Recipient name
291
				if (!empty($usecontact))
292
				{
293
					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)))) {
294
						$socobject = $object->contact;
295
					} else {
296
						$socobject = $object->thirdparty;
297
						// if we have a CUSTOMER contact and we dont use it as recipient we store the contact object for later use
298
						$contactobject = $object->contact;
299
					}
300
				} else {
301
					$socobject = $object->thirdparty;
302
				}
303
304
				// Open and load template
305
				require_once ODTPHP_PATH.'odf.php';
306
				try {
307
					$odfHandler = new odf(
308
						$srctemplatepath,
309
						array(
310
							'PATH_TO_TMP'	  => $conf->user->dir_temp,
311
							'ZIP_PROXY'		  => 'PclZipProxy', // PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy.
312
							'DELIMITER_LEFT'  => '{',
313
							'DELIMITER_RIGHT' => '}'
314
						)
315
					);
316
				} catch (Exception $e)
317
				{
318
					$this->error = $e->getMessage();
319
					dol_syslog($e->getMessage(), LOG_WARNING);
320
					return -1;
321
				}
322
323
				// Make substitutions into odt
324
				$array_user = $this->get_substitutionarray_user($object, $outputlangs);
325
				$array_soc = $this->get_substitutionarray_mysoc($mysoc, $outputlangs);
326
				$array_thirdparty = $this->get_substitutionarray_thirdparty($socobject, $outputlangs);
327
				$array_other = $this->get_substitutionarray_other($outputlangs);
328
				// retrieve contact information for use in object as contact_xxx tags
329
				$array_thirdparty_contact = array();
330
				if ($usecontact && is_object($contactobject)) $array_thirdparty_contact = $this->get_substitutionarray_contact($contactobject, $outputlangs, 'contact');
331
332
				$tmparray = array_merge($array_user, $array_soc, $array_thirdparty, $array_other, $array_thirdparty_contact);
333
				complete_substitutions_array($tmparray, $outputlangs, $object);
334
				$object->fetch_optionals();
335
				// Call the ODTSubstitution hook
336
				$parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray);
337
				$reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
338
				foreach ($tmparray as $key=>$value)
339
				{
340
					try {
341
						if (preg_match('/logo$/', $key)) // Image
342
						{
343
							if (file_exists($value)) $odfHandler->setImage($key, $value);
344
							else $odfHandler->setVars($key, 'ErrorFileNotFound', true, 'UTF-8');
345
						} else // Text
346
						{
347
							$odfHandler->setVars($key, $value, true, 'UTF-8');
348
						}
349
					} catch (OdfException $e)
350
					{
351
						dol_syslog($e->getMessage(), LOG_WARNING);
352
					}
353
				}
354
355
				// Replace labels translated
356
				$tmparray = $outputlangs->get_translations_for_substitutions();
357
				foreach ($tmparray as $key=>$value)
358
				{
359
					try {
360
						$odfHandler->setVars($key, $value, true, 'UTF-8');
361
					} catch (OdfException $e)
362
					{
363
						dol_syslog($e->getMessage(), LOG_WARNING);
364
					}
365
				}
366
367
				// Call the beforeODTSave hook
368
				$parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
369
				$reshook = $hookmanager->executeHooks('beforeODTSave', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
370
371
				// Write new file
372
				if (!empty($conf->global->MAIN_ODT_AS_PDF)) {
373
					try {
374
						$odfHandler->exportAsAttachedPDF($file);
375
					} catch (Exception $e) {
376
						$this->error = $e->getMessage();
377
						dol_syslog($e->getMessage(), LOG_WARNING);
378
						return -1;
379
					}
380
				} else {
381
					try {
382
						$odfHandler->saveToDisk($file);
383
					} catch (Exception $e) {
384
						$this->error = $e->getMessage();
385
						dol_syslog($e->getMessage(), LOG_WARNING);
386
						return -1;
387
					}
388
				}
389
390
				$reshook = $hookmanager->executeHooks('afterODTCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
391
392
				if (!empty($conf->global->MAIN_UMASK))
393
					@chmod($file, octdec($conf->global->MAIN_UMASK));
394
395
				$odfHandler = null; // Destroy object
396
397
				$this->result = array('fullpath'=>$file);
398
399
				return 1; // Success
400
			} else {
401
				$this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
402
				return -1;
403
			}
404
		}
405
406
		return -1;
407
	}
408
409
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
410
	/**
411
	 * get substitution array for object
412
	 *
413
	 * @param User          $object         user
414
	 * @param Translate     $outputlangs    translation object
415
	 * @param string        $array_key      key for array
416
	 * @return array                        array of substitutions
417
	 */
418
	public function get_substitutionarray_object($object, $outputlangs, $array_key = 'object')
419
	{
420
		// phpcs:enable
421
		$array_other = array();
422
		foreach ($object as $key => $value) {
423
			if (!is_array($value) && !is_object($value)) {
424
				$array_other[$array_key.'_'.$key] = $value;
425
			}
426
		}
427
		return $array_other;
428
	}
429
}
430