1<?php
2/* Copyright (C) 2003		Rodolphe Quiedeville		<rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2010	Laurent Destailleur			<eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2012	Regis Houssin				<regis.houssin@inodbox.com>
5 * Copyright (C) 2008		Raphael Bertrand (Resultic)	<raphael.bertrand@resultic.fr>
6 * Copyright (C) 2011		Fabrice CHERRIER
7 * Copyright (C) 2013-2020  Philippe Grand	            <philippe.grand@atoo-net.com>
8 * Copyright (C) 2015       Marcos García               <marcosgdf@gmail.com>
9 * Copyright (C) 2018-2020  Frédéric France             <frederic.france@netlogic.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 * or see https://www.gnu.org/
24 */
25
26/**
27 *	\file       htdocs/core/modules/contract/doc/pdf_strato.modules.php
28 *	\ingroup    ficheinter
29 *	\brief      Strato contracts template class file
30 */
31require_once DOL_DOCUMENT_ROOT.'/core/modules/contract/modules_contract.php';
32require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
33require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
34require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
35require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
36
37
38/**
39 *	Class to build contracts documents with model Strato
40 */
41class pdf_strato extends ModelePDFContract
42{
43	/**
44	 * @var DoliDb Database handler
45	 */
46	public $db;
47
48	/**
49	 * @var string model name
50	 */
51	public $name;
52
53	/**
54	 * @var string model description (short text)
55	 */
56	public $description;
57
58	/**
59	 * @var string document type
60	 */
61	public $type;
62
63	/**
64	 * @var array Minimum version of PHP required by module.
65	 * e.g.: PHP ≥ 5.6 = array(5, 6)
66	 */
67	public $phpmin = array(5, 6);
68
69	/**
70	 * Dolibarr version of the loaded document
71	 * @var string
72	 */
73	public $version = 'dolibarr';
74
75	/**
76	 * @var int page_largeur
77	 */
78	public $page_largeur;
79
80	/**
81	 * @var int page_hauteur
82	 */
83	public $page_hauteur;
84
85	/**
86	 * @var array format
87	 */
88	public $format;
89
90	/**
91	 * @var int marge_gauche
92	 */
93	public $marge_gauche;
94
95	/**
96	 * @var int marge_droite
97	 */
98	public $marge_droite;
99
100	/**
101	 * @var int marge_haute
102	 */
103	public $marge_haute;
104
105	/**
106	 * @var int marge_basse
107	 */
108	public $marge_basse;
109
110	/**
111	 * Issuer
112	 * @var Societe
113	 */
114	public $emetteur;
115
116	/**
117	 * Recipient
118	 * @var Societe
119	 */
120	public $recipient;
121
122	/**
123	 *	Constructor
124	 *
125	 *  @param		DoliDB		$db      Database handler
126	 */
127	public function __construct($db)
128	{
129		global $conf, $langs, $mysoc;
130
131		$this->db = $db;
132		$this->name = 'strato';
133		$this->description = $langs->trans("StandardContractsTemplate");
134
135		// Page size for A4 format
136		$this->type = 'pdf';
137		$formatarray = pdf_getFormat();
138
139		$this->page_largeur = $formatarray['width'];
140		$this->page_hauteur = $formatarray['height'];
141		$this->format = array($this->page_largeur, $this->page_hauteur);
142		$this->marge_gauche = isset($conf->global->MAIN_PDF_MARGIN_LEFT) ? $conf->global->MAIN_PDF_MARGIN_LEFT : 10;
143		$this->marge_droite = isset($conf->global->MAIN_PDF_MARGIN_RIGHT) ? $conf->global->MAIN_PDF_MARGIN_RIGHT : 10;
144		$this->marge_haute = isset($conf->global->MAIN_PDF_MARGIN_TOP) ? $conf->global->MAIN_PDF_MARGIN_TOP : 10;
145		$this->marge_basse = isset($conf->global->MAIN_PDF_MARGIN_BOTTOM) ? $conf->global->MAIN_PDF_MARGIN_BOTTOM : 10;
146
147		$this->option_logo = 1; // Display logo
148		$this->option_tva = 0; // Manage the vat option FACTURE_TVAOPTION
149		$this->option_modereg = 0; // Display payment mode
150		$this->option_condreg = 0; // Display payment terms
151		$this->option_codeproduitservice = 0; // Display product-service code
152		$this->option_multilang = 0; // Available in several languages
153		$this->option_draft_watermark = 1; // Support add of a watermark on drafts
154
155		// Get source company
156		$this->emetteur = $mysoc;
157		if (empty($this->emetteur->country_code)) $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if not defined
158
159		// Define position of columns
160		$this->posxdesc = $this->marge_gauche + 1;
161	}
162
163	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
164	/**
165	 *  Function to build pdf onto disk
166	 *
167	 *  @param		Contrat			$object				Object to generate
168	 *  @param		Translate		$outputlangs		Lang output object
169	 *  @param		string			$srctemplatepath	Full path of source filename for generator using a template file
170	 *  @param		int				$hidedetails		Do not show line details
171	 *  @param		int				$hidedesc			Do not show desc
172	 *  @param		int				$hideref			Do not show ref
173	 *  @return		int									1=OK, 0=KO
174	 */
175	public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
176	{
177		// phpcs:enable
178		global $user, $langs, $conf, $hookmanager, $mysoc;
179
180		if (!is_object($outputlangs)) $outputlangs = $langs;
181		// For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
182		if (!empty($conf->global->MAIN_USE_FPDF)) $outputlangs->charset_output = 'ISO-8859-1';
183
184		// Load traductions files required by page
185		$outputlangs->loadLangs(array("main", "dict", "companies", "contracts"));
186
187		if ($conf->contrat->dir_output)
188		{
189			$object->fetch_thirdparty();
190
191			// Definition of $dir and $file
192			if ($object->specimen)
193			{
194				$dir = $conf->contrat->dir_output;
195				$file = $dir."/SPECIMEN.pdf";
196			} else {
197				$objectref = dol_sanitizeFileName($object->ref);
198				$dir = $conf->contrat->multidir_output[$object->entity]."/".$objectref;
199				$file = $dir."/".$objectref.".pdf";
200			}
201
202			if (!file_exists($dir))
203			{
204				if (dol_mkdir($dir) < 0)
205				{
206					$this->error = $outputlangs->trans("ErrorCanNotCreateDir", $dir);
207					return 0;
208				}
209			}
210
211			if (file_exists($dir))
212			{
213				// Add pdfgeneration hook
214				if (!is_object($hookmanager))
215				{
216					include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
217					$hookmanager = new HookManager($this->db);
218				}
219				$hookmanager->initHooks(array('pdfgeneration'));
220				$parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
221				global $action;
222				$reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
223
224				$pdf = pdf_getInstance($this->format);
225				$default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
226				$heightforinfotot = 50; // Height reserved to output the info and total part
227				$heightforfreetext = (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT) ? $conf->global->MAIN_PDF_FREETEXT_HEIGHT : 5); // Height reserved to output the free text on last page
228				$heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
229				if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS)) $heightforfooter += 6;
230				$pdf->SetAutoPageBreak(1, 0);
231
232				if (class_exists('TCPDF'))
233				{
234					$pdf->setPrintHeader(false);
235					$pdf->setPrintFooter(false);
236				}
237				$pdf->SetFont(pdf_getPDFFont($outputlangs));
238				// Set path to the background PDF File
239				if (!empty($conf->global->MAIN_ADD_PDF_BACKGROUND))
240				{
241					$pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND);
242					$tplidx = $pdf->importPage(1);
243				}
244
245				$pdf->Open();
246				$pagenb = 0;
247				$pdf->SetDrawColor(128, 128, 128);
248
249				$pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
250				$pdf->SetSubject($outputlangs->transnoentities("ContractCard"));
251				$pdf->SetCreator("Dolibarr ".DOL_VERSION);
252				$pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
253				$pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("ContractCard")." ".$outputlangs->convToOutputCharset($object->thirdparty->name));
254				if (!empty($conf->global->MAIN_DISABLE_PDF_COMPRESSION)) $pdf->SetCompression(false);
255
256				$pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
257
258				// New page
259				$pdf->AddPage();
260				if (!empty($tplidx)) $pdf->useTemplate($tplidx);
261				$pagenb++;
262				$this->_pagehead($pdf, $object, 1, $outputlangs);
263				$pdf->SetFont('', '', $default_font_size - 1);
264				$pdf->MultiCell(0, 3, ''); // Set interline to 3
265				$pdf->SetTextColor(0, 0, 0);
266
267				$tab_top = 90;
268				$tab_top_newpage = (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD) ? 42 : 10);
269
270				// Display notes
271				if (!empty($object->note_public))
272				{
273					$tab_top -= 2;
274
275					$pdf->SetFont('', '', $default_font_size - 1);
276					$pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($object->note_public), 0, 1);
277					$nexY = $pdf->GetY();
278					$height_note = $nexY - $tab_top;
279
280					// Rect takes a length in 3rd parameter
281					$pdf->SetDrawColor(192, 192, 192);
282					$pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1);
283
284					$tab_top = $nexY + 6;
285				}
286
287				$iniY = $tab_top + 7;
288				$curY = $tab_top + 7;
289				$nexY = $tab_top + 2;
290
291				$pdf->SetXY($this->marge_gauche, $tab_top);
292
293				$pdf->MultiCell(0, 2, ''); // Set interline to 3. Then writeMultiCell must use 3 also.
294
295				$nblines = count($object->lines);
296
297				// Loop on each lines
298				for ($i = 0; $i < $nblines; $i++)
299				{
300					$objectligne = $object->lines[$i];
301
302					$valide = $objectligne->id ? 1 : 0;
303
304					if ($valide > 0 || $object->specimen)
305					{
306						$curX = $this->posxdesc - 1;
307						$curY = $nexY;
308						$pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
309						$pdf->SetTextColor(0, 0, 0);
310
311						$pdf->setTopMargin($tab_top_newpage);
312						$pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
313						$pageposbefore = $pdf->getPage();
314
315						// Description of product line
316
317						if ($objectligne->date_ouverture_prevue) {
318							$datei = dol_print_date($objectligne->date_ouverture_prevue, 'day', false, $outputlangs, true);
319						} else {
320							$datei = $langs->trans("Unknown");
321						}
322
323						if ($objectligne->date_fin_validite) {
324							$durationi = convertSecondToTime($objectligne->date_fin_validite - $objectligne->date_ouverture_prevue, 'allwithouthour');
325							$datee = dol_print_date($objectligne->date_fin_validite, 'day', false, $outputlangs, true);
326						} else {
327							$durationi = $langs->trans("Unknown");
328							$datee = $langs->trans("Unknown");
329						}
330
331						if ($objectligne->date_ouverture) {
332							$daters = dol_print_date($objectligne->date_ouverture, 'day', false, $outputlangs, true);
333						} else {
334							$daters = $langs->trans("Unknown");
335						}
336
337						if ($objectligne->date_cloture) {
338							$datere = dol_print_date($objectligne->date_cloture, 'day', false, $outputlangs, true);
339						} else {
340							$datere = $langs->trans("Unknown");
341						}
342
343                        $txtpredefinedservice = $objectligne->product_ref;
344                        if ($objectligne->product_label)
345                        {
346                        	$txtpredefinedservice .= ' - ';
347                        	$txtpredefinedservice .= $objectligne->product_label;
348                        }
349
350						$desc = dol_htmlentitiesbr($objectligne->desc, 1); // Desc (not empty for free lines)
351						$txt = '';
352						$txt .= $outputlangs->transnoentities("Quantity").' : <strong>'.$objectligne->qty.'</strong> - '.$outputlangs->transnoentities("UnitPrice").' : <strong>'.price($objectligne->subprice).'</strong>'; // Desc (not empty for free lines)
353						if (empty($conf->global->CONTRACT_HIDE_PLANNED_DATE_ON_PDF))
354						{
355							$txt .= '<br>';
356							$txt .= $outputlangs->transnoentities("DateStartPlannedShort")." : <strong>".$datei."</strong> - ".$outputlangs->transnoentities("DateEndPlanned")." : <strong>".$datee.'</strong>';
357						}
358						if (empty($conf->global->CONTRACT_HIDE_REAL_DATE_ON_PDF))
359						{
360							$txt .= '<br>';
361							$txt .= $outputlangs->transnoentities("DateStartRealShort")." : <strong>".$daters.'</strong>';
362							if ($objectligne->date_cloture) $txt .= " - ".$outputlangs->transnoentities("DateEndRealShort")." : '<strong>'".$datere.'</strong>';
363						}
364
365						$pdf->startTransaction();
366						$pdf->writeHTMLCell(0, 0, $curX, $curY, dol_concatdesc($txtpredefinedservice, dol_concatdesc($txt, $desc)), 0, 1, 0);
367						$pageposafter = $pdf->getPage();
368						if ($pageposafter > $pageposbefore)	// There is a pagebreak
369						{
370							$pdf->rollbackTransaction(true);
371							$pageposafter = $pageposbefore;
372							//print $pageposafter.'-'.$pageposbefore;exit;
373							$pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
374							$pdf->writeHTMLCell(0, 0, $curX, $curY, dol_concatdesc($txtpredefinedservice, dol_concatdesc($txt, $desc)), 0, 1, 0);
375							$pageposafter = $pdf->getPage();
376							$posyafter = $pdf->GetY();
377
378							if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot)))	// There is no space left for total+free text
379							{
380								if ($i == ($nblines - 1))	// No more lines, and no space left to show total, so we create a new page
381								{
382									$pdf->AddPage('', '', true);
383									if (!empty($tplidx)) $pdf->useTemplate($tplidx);
384									if (empty($conf->global->MAIN_PDF_DONOTREPEAT_HEAD)) $this->_pagehead($pdf, $object, 0, $outputlangs);
385									$pdf->setPage($pageposafter + 1);
386								}
387							} else {
388								// We found a page break
389
390								// Allows data in the first page if description is long enough to break in multiples pages
391								if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE))
392									$showpricebeforepagebreak = 1;
393								else $showpricebeforepagebreak = 0;
394							}
395						} else // No pagebreak
396						{
397							$pdf->commitTransaction();
398						}
399
400						$nexY = $pdf->GetY() + 2;
401						$pageposafter = $pdf->getPage();
402
403						$pdf->setPage($pageposbefore);
404						$pdf->setTopMargin($this->marge_haute);
405						$pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
406
407						// We suppose that a too long description is moved completely on next page
408						if ($pageposafter > $pageposbefore) {
409							$pdf->setPage($pageposafter); $curY = $tab_top_newpage;
410						}
411
412						$pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font
413
414						// Detect if some page were added automatically and output _tableau for past pages
415						while ($pagenb < $pageposafter)
416						{
417							$pdf->setPage($pagenb);
418							if ($pagenb == 1)
419							{
420								$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext, 0, $outputlangs, 0, 1);
421							} else {
422								$this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter - $heightforfreetext, 0, $outputlangs, 1, 1);
423							}
424							$this->_pagefoot($pdf, $object, $outputlangs, 1);
425							$pagenb++;
426							$pdf->setPage($pagenb);
427							$pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
428						}
429
430						if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak)
431						{
432							if ($pagenb == 1)
433							{
434								$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext, 0, $outputlangs, 0, 1);
435							} else {
436								$this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter - $heightforfreetext, 0, $outputlangs, 1, 1);
437							}
438							$this->_pagefoot($pdf, $object, $outputlangs, 1);
439							// New page
440							$pdf->AddPage();
441							if (!empty($tplidx)) $pdf->useTemplate($tplidx);
442							$pagenb++;
443						}
444					}
445				}
446
447				// Show square
448				if ($pagenb == 1)
449				{
450					$this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0);
451					$this->tabSignature($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, $outputlangs);
452					$bottomlasttab = $this->page_hauteur - $heightforfooter - $heightforfooter + 1;
453				} else {
454					$this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0);
455					$this->tabSignature($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, $outputlangs);
456					$bottomlasttab = $this->page_hauteur - $heightforfooter - $heightforfooter + 1;
457				}
458
459				$this->_pagefoot($pdf, $object, $outputlangs);
460				if (method_exists($pdf, 'AliasNbPages')) $pdf->AliasNbPages();
461
462				$pdf->Close();
463
464				$pdf->Output($file, 'F');
465
466				// Add pdfgeneration hook
467				if (!is_object($hookmanager))
468				{
469					include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
470					$hookmanager = new HookManager($this->db);
471				}
472				$hookmanager->initHooks(array('pdfgeneration'));
473				$parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
474				global $action;
475				$reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
476				if ($reshook < 0)
477				{
478					$this->error = $hookmanager->error;
479					$this->errors = $hookmanager->errors;
480				}
481
482				if (!empty($conf->global->MAIN_UMASK))
483				@chmod($file, octdec($conf->global->MAIN_UMASK));
484
485				$this->result = array('fullpath'=>$file);
486
487				return 1;
488			} else {
489				$this->error = $langs->trans("ErrorCanNotCreateDir", $dir);
490				return 0;
491			}
492		} else {
493			$this->error = $langs->trans("ErrorConstantNotDefined", "CONTRACT_OUTPUTDIR");
494			return 0;
495		}
496	}
497
498	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
499	/**
500	 *   Show table for lines
501	 *
502	 *   @param		TCPDF		$pdf     		Object PDF
503	 *   @param		string		$tab_top		Top position of table
504	 *   @param		string		$tab_height		Height of table (rectangle)
505	 *   @param		int			$nexY			Y
506	 *   @param		Translate	$outputlangs	Langs object
507	 *   @param		int			$hidetop		Hide top bar of array
508	 *   @param		int			$hidebottom		Hide bottom bar of array
509	 *   @return	void
510	 */
511	protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0)
512	{
513		global $conf;
514
515		// Force to disable hidetop and hidebottom
516		$hidebottom = 0;
517		if ($hidetop) $hidetop = -1;
518
519		$default_font_size = pdf_getPDFFontSize($outputlangs);
520		/*
521		$pdf->SetXY($this->marge_gauche, $tab_top);
522		$pdf->MultiCell(190,8,$outputlangs->transnoentities("Description"),0,'L',0);
523		$pdf->line($this->marge_gauche, $tab_top + 8, $this->page_largeur-$this->marge_droite, $tab_top + 8);
524
525		$pdf->SetFont('','', $default_font_size - 1);
526
527		$pdf->MultiCell(0, 3, '');		// Set interline to 3
528		$pdf->SetXY($this->marge_gauche, $tab_top + 8);
529		$text=$object->description;
530		if ($object->duree > 0)
531		{
532			$totaltime=convertSecondToTime($object->duree,'all',$conf->global->MAIN_DURATION_OF_WORKDAY);
533			$text.=($text?' - ':'').$langs->trans("Total").": ".$totaltime;
534		}
535		$desc=dol_htmlentitiesbr($text,1);
536		//print $outputlangs->convToOutputCharset($desc); exit;
537
538		$pdf->writeHTMLCell(180, 3, 10, $tab_top + 8, $outputlangs->convToOutputCharset($desc), 0, 1);
539		$nexY = $pdf->GetY();
540
541		$pdf->line($this->marge_gauche, $nexY, $this->page_largeur-$this->marge_droite, $nexY);
542
543		$pdf->MultiCell(0, 3, '');		// Set interline to 3. Then writeMultiCell must use 3 also.
544        */
545
546		// Output Rect
547		$this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height + 3); // Rect takes a length in 3rd parameter and 4th parameter
548	}
549
550	/**
551	 * Show footer signature of page
552	 * @param   TCPDF       $pdf            Object PDF
553	 * @param   int         $tab_top        tab height position
554	 * @param   int         $tab_height     tab height
555	 * @param   Translate   $outputlangs    Object language for output
556	 * @return void
557	 */
558	protected function tabSignature(&$pdf, $tab_top, $tab_height, $outputlangs)
559	{
560		$pdf->SetDrawColor(128, 128, 128);
561		$posmiddle = $this->marge_gauche + round(($this->page_largeur - $this->marge_gauche - $this->marge_droite) / 2);
562		$posy = $tab_top + $tab_height + 3 + 3;
563
564		$pdf->SetXY($this->marge_gauche, $posy);
565		$pdf->MultiCell($posmiddle - $this->marge_gauche - 5, 5, $outputlangs->transnoentities("ContactNameAndSignature", $this->emetteur->name), 0, 'L', 0);
566
567		$pdf->SetXY($this->marge_gauche, $posy + 5);
568		$pdf->MultiCell($posmiddle - $this->marge_gauche - 5, 20, '', 1);
569
570		$pdf->SetXY($posmiddle + 5, $posy);
571		$pdf->MultiCell($this->page_largeur - $this->marge_droite - $posmiddle - 5, 5, $outputlangs->transnoentities("ContactNameAndSignature", $this->recipient->name), 0, 'L', 0);
572
573		$pdf->SetXY($posmiddle + 5, $posy + 5);
574		$pdf->MultiCell($this->page_largeur - $this->marge_droite - $posmiddle - 5, 20, '', 1);
575	}
576
577	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
578	/**
579	 *  Show top header of page.
580	 *
581	 *  @param	TCPDF		$pdf     		Object PDF
582	 *  @param  Contrat		$object     	Object to show
583	 *  @param  int	    	$showaddress    0=no, 1=yes
584	 *  @param  Translate	$outputlangs	Object lang for output
585	 *  @return	void
586	 */
587	protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
588	{
589		global $conf, $langs;
590
591		$default_font_size = pdf_getPDFFontSize($outputlangs);
592
593		// Load traductions files required by page
594		$outputlangs->loadLangs(array("main", "dict", "contract", "companies"));
595
596		pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
597
598		//Affiche le filigrane brouillon - Print Draft Watermark
599		if ($object->statut == 0 && (!empty($conf->global->CONTRACT_DRAFT_WATERMARK)))
600		{
601			pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->CONTRACT_DRAFT_WATERMARK);
602		}
603
604		//Prepare next
605		$pdf->SetTextColor(0, 0, 60);
606		$pdf->SetFont('', 'B', $default_font_size + 3);
607
608		$posx = $this->page_largeur - $this->marge_droite - 100;
609		$posy = $this->marge_haute;
610
611		$pdf->SetXY($this->marge_gauche, $posy);
612
613		// Logo
614		$logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
615		if ($this->emetteur->logo)
616		{
617			if (is_readable($logo))
618			{
619				$height = pdf_getHeightForLogo($logo);
620				$pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
621			} else {
622				$pdf->SetTextColor(200, 0, 0);
623				$pdf->SetFont('', 'B', $default_font_size - 2);
624				$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
625				$pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
626			}
627		} else {
628			$text = $this->emetteur->name;
629			$pdf->MultiCell(100, 4, $outputlangs->convToOutputCharset($text), 0, 'L');
630		}
631
632		$pdf->SetFont('', 'B', $default_font_size + 3);
633		$pdf->SetXY($posx, $posy);
634		$pdf->SetTextColor(0, 0, 60);
635		$title = $outputlangs->transnoentities("ContractCard");
636		$pdf->MultiCell(100, 4, $title, '', 'R');
637
638		$pdf->SetFont('', 'B', $default_font_size + 2);
639
640		$posy += 5;
641		$pdf->SetXY($posx, $posy);
642		$pdf->SetTextColor(0, 0, 60);
643		$pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref), '', 'R');
644
645		$posy += 1;
646		$pdf->SetFont('', '', $default_font_size);
647
648		$posy += 4;
649		$pdf->SetXY($posx, $posy);
650		$pdf->SetTextColor(0, 0, 60);
651		$pdf->MultiCell(100, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date_contrat, "day", false, $outputlangs, true), '', 'R');
652
653		if ($object->thirdparty->code_client)
654		{
655			$posy += 4;
656			$pdf->SetXY($posx, $posy);
657			$pdf->SetTextColor(0, 0, 60);
658			$pdf->MultiCell(100, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R');
659		}
660
661		if ($showaddress)
662		{
663			// Sender properties
664			$carac_emetteur = '';
665			// Add internal contact of proposal if defined
666			$arrayidcontact = $object->getIdContact('internal', 'INTERREPFOLL');
667			if (count($arrayidcontact) > 0)
668			{
669				$object->fetch_user($arrayidcontact[0]);
670				$carac_emetteur .= ($carac_emetteur ? "\n" : '').$outputlangs->transnoentities("Name").": ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs))."\n";
671			}
672
673			$carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
674
675			// Show sender
676			$posy = 42;
677			$posx = $this->marge_gauche;
678			if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) $posx = $this->page_largeur - $this->marge_droite - 80;
679			$hautcadre = 40;
680
681			// Show sender frame
682			$pdf->SetTextColor(0, 0, 0);
683			$pdf->SetFont('', '', $default_font_size - 2);
684			$pdf->SetXY($posx, $posy - 5);
685			$pdf->SetXY($posx, $posy);
686			$pdf->SetFillColor(230, 230, 230);
687			$pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1);
688
689			// Show sender name
690			$pdf->SetXY($posx + 2, $posy + 3);
691			$pdf->SetTextColor(0, 0, 60);
692			$pdf->SetFont('', 'B', $default_font_size);
693			$pdf->MultiCell(80, 3, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L');
694			$posy = $pdf->getY();
695
696			// Show sender information
697			$pdf->SetFont('', '', $default_font_size - 1);
698			$pdf->SetXY($posx + 2, $posy);
699			$pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L');
700
701
702			// If CUSTOMER contact defined, we use it
703			$usecontact = false;
704			$arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
705			if (count($arrayidcontact) > 0)
706			{
707				$usecontact = true;
708				$result = $object->fetch_contact($arrayidcontact[0]);
709			}
710
711			$this->recipient = $object->thirdparty;
712
713			// Recipient name
714			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)))) {
715				$thirdparty = $object->contact;
716			} else {
717				$thirdparty = $object->thirdparty;
718			}
719
720			$this->recipient->name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
721
722			$carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, (isset($object->contact) ? $object->contact : ''), $usecontact, 'target', $object);
723
724			// Show recipient
725			$widthrecbox = 100;
726			if ($this->page_largeur < 210) $widthrecbox = 84; // To work with US executive format
727			$posy = 42;
728			$posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
729			if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) $posx = $this->marge_gauche;
730
731			// Show recipient frame
732			$pdf->SetTextColor(0, 0, 0);
733			$pdf->SetFont('', '', $default_font_size - 2);
734			$pdf->SetXY($posx + 2, $posy - 5);
735			$pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
736			$pdf->SetTextColor(0, 0, 0);
737
738			// Show recipient name
739			$pdf->SetXY($posx + 2, $posy + 3);
740			$pdf->SetFont('', 'B', $default_font_size);
741			$pdf->MultiCell($widthrecbox, 4, $this->recipient->name, 0, 'L');
742
743			$posy = $pdf->getY();
744
745			// Show recipient information
746			$pdf->SetFont('', '', $default_font_size - 1);
747			$pdf->SetXY($posx + 2, $posy);
748			$pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L');
749		}
750	}
751
752	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
753	/**
754	 *   	Show footer of page. Need this->emetteur object
755	 *
756	 *   	@param	PDF			$pdf     			PDF
757	 * 		@param	Contrat		$object				Object to show
758	 *      @param	Translate	$outputlangs		Object lang for output
759	 *      @param	int			$hidefreetext		1=Hide free text
760	 *      @return	integer
761	 */
762	protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
763	{
764		global $conf;
765		$showdetails = empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS) ? 0 : $conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS;
766		return pdf_pagefoot($pdf, $outputlangs, 'CONTRACT_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext);
767	}
768}
769