dolibarr 24.0.0-beta
pdf_strato.modules.php
Go to the documentation of this file.
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-2024 Philippe Grand <philippe.grand@atoo-net.com>
8 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
9 * Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
10 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
11 * Copyright (C) 2024 Nick Fragoulis
12 * Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
13 * Copyright (C) 2024 Éric Seigne <eric.seigne@cap-rel.fr>
14 * Copyright (C) 2025 William Mead <william@m34d.com>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <https://www.gnu.org/licenses/>.
28 * or see https://www.gnu.org/
29 */
30
36require_once DOL_DOCUMENT_ROOT.'/core/modules/contract/modules_contract.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
40require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
41require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
42
43
48{
52 public $db;
53
57 public $entity;
58
62 public $name;
63
67 public $description;
68
72 public $update_main_doc_field;
73
77 public $type;
78
83 public $version = 'dolibarr';
84
88 public $recipient;
89
95 public function __construct($db)
96 {
97 global $langs, $mysoc;
98
99 $this->db = $db;
100 $this->name = 'strato';
101 $this->description = $langs->trans("StandardContractsTemplate");
102 $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
103
104 // Dimension page
105 $this->type = 'pdf';
106 $formatarray = pdf_getFormat();
107
108 $this->page_largeur = $formatarray['width'];
109 $this->page_hauteur = $formatarray['height'];
110 $this->format = array($this->page_largeur, $this->page_hauteur);
111 $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
112 $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
113 $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
114 $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
115 $this->corner_radius = getDolGlobalInt('MAIN_PDF_FRAME_CORNER_RADIUS', 0);
116 $this->option_logo = 1; // Display logo
117 $this->option_tva = 0; // Manage the vat option FACTURE_TVAOPTION
118 $this->option_modereg = 0; // Display payment mode
119 $this->option_condreg = 0; // Display payment terms
120 $this->option_multilang = 0; // Available in several languages
121 $this->option_draft_watermark = 1; // Support add of a watermark on drafts
122
123 // Define position of columns
124 $this->posxdesc = $this->marge_gauche + 1;
125
126 if ($mysoc === null) {
127 dol_syslog(get_class($this).'::__construct() Global $mysoc should not be null.'. getCallerInfoString(), LOG_ERR);
128 return;
129 }
130
131 // Get source company
132 $this->emetteur = $mysoc;
133 if (empty($this->emetteur->country_code)) {
134 $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
135 }
136 }
137
138 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
150 public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
151 {
152 // phpcs:enable
153 global $user, $langs, $conf, $mysoc, $db, $hookmanager, $nblines;
154
155 if (!is_object($outputlangs)) {
156 $outputlangs = $langs;
157 }
158 // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
159 if (getDolGlobalString('MAIN_USE_FPDF')) {
160 $outputlangs->charset_output = 'ISO-8859-1';
161 }
162
163 // Load translation files required by page
164 $outputlangs->loadLangs(array("main", "dict", "companies", "contracts", "compta"));
165
166 // Show Draft Watermark
167 if ($object->status == $object::STATUS_DRAFT && (getDolGlobalString('CONTRACT_DRAFT_WATERMARK'))) {
168 $this->watermark = getDolGlobalString('CONTRACT_DRAFT_WATERMARK');
169 }
170
171 global $outputlangsbis;
172 $outputlangsbis = null;
173 if (getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE') && $outputlangs->defaultlang != getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE')) {
174 $outputlangsbis = new Translate('', $conf);
175 $outputlangsbis->setDefaultLang(getDolGlobalString('PDF_USE_ALSO_LANGUAGE_CODE'));
176 $outputlangsbis->loadLangs(array("main", "dict", "companies", "contracts", "compta"));
177 }
178
179 $nblines = count($object->lines);
180
181 if ($conf->contract->multidir_output[$conf->entity]) {
182 $object->fetch_thirdparty();
183
184 // Definition of $dir and $file
185 if ($object->specimen) {
187 $file = $dir."/SPECIMEN.pdf";
188 } else {
189 $objectref = dol_sanitizeFileName($object->ref);
190 $dir = getMultidirOutput($object)."/".$objectref;
191 $file = $dir."/".$objectref.".pdf";
192 }
193
194 if ($dir === null) {
195 dol_syslog(get_class($this).'::'.__METHOD__."Target directory should not be null.". getCallerInfoString(), LOG_ERR);
196 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", "Null dir");
197 return 0;
198 }
199
200 if (!file_exists($dir)) {
201 if (dol_mkdir($dir) < 0) {
202 $this->error = $langs->transnoentitiesnoconv("ErrorCanNotCreateDir", $dir);
203 return 0;
204 }
205 }
206
207 if (file_exists($dir)) {
208 // Add pdfgeneration hook
209 if (!is_object($hookmanager)) {
210 include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
211 $hookmanager = new HookManager($this->db);
212 }
213 $hookmanager->initHooks(array('pdfgeneration'));
214 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
215 global $action;
216 $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
217
218 // Set nblines with the new lines content after hook
219 $nblines = (is_array($object->lines) ? count($object->lines) : 0);
220
221 // Create pdf instance
222 $pdf = pdf_getInstance($this->format);
223 $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
224 $pdf->setAutoPageBreak(true, 0);
225
226 $heightforinfotot = 50; // Height reserved to output the info and total part
227 $heightforfreetext = getDolGlobalInt('MAIN_PDF_FREETEXT_HEIGHT', 5); // Height reserved to output the free text on last page
228 $heightforfooter = $this->marge_basse + 9; // Height reserved to output the footer (value include bottom margin)
229 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS')) {
230 $heightforfooter += 6;
231 }
232
233 if (class_exists('TCPDF')) {
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 (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND')) {
240 $logodir = $conf->mycompany->dir_output;
241 if (!empty($conf->mycompany->multidir_output[$object->entity ?? $conf->entity])) {
242 $logodir = $conf->mycompany->multidir_output[$object->entity ?? $conf->entity];
243 }
244 $pagecount = $pdf->setSourceFile($logodir.'/' . getDolGlobalString('MAIN_ADD_PDF_BACKGROUND'));
245 $tplidx = $pdf->importPage(1);
246 }
247
248 $pdf->Open();
249 $pagenb = 0;
250 $pdf->SetDrawColor(128, 128, 128);
251
252 $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
253 $pdf->SetSubject($outputlangs->transnoentities("Contract"));
254 $pdf->SetCreator("Dolibarr ".DOL_VERSION);
255 $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getAnonymisableFullName($outputlangs)));
256 $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Contract")." ".$outputlangs->convToOutputCharset($object->thirdparty->name));
257 if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
258 $pdf->SetCompression(false);
259 }
260
261 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
262 $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
263
264 // New page
265 $pdf->AddPage();
266 if (!empty($tplidx)) {
267 $pdf->useTemplate($tplidx);
268 }
269 $pagenb++;
270 $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs, (is_object($outputlangsbis) ? $outputlangsbis : null));
271 $pdf->SetFont('', '', $default_font_size - 1);
272 $pdf->MultiCell(0, 3, ''); // Set interline to 3
273 $pdf->SetTextColor(0, 0, 0);
274
275 $tab_top = 90;
276 $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 : 10);
277
278 // Display notes
279 $notetoshow = empty($object->note_public) ? '' : $object->note_public;
280
281 // Extrafields in note
282 $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
283 if (!empty($extranote)) {
284 $notetoshow = dol_concatdesc($notetoshow, $extranote);
285 }
286
287 if (!empty($notetoshow)) {
288 $tab_top -= 2;
289
290 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
291 complete_substitutions_array($substitutionarray, $outputlangs, $object);
292 $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
293 $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
294
295 $pdf->SetFont('', '', $default_font_size - 1);
296 $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($notetoshow), 0, 1);
297 $nexY = $pdf->GetY();
298 $height_note = $nexY - $tab_top;
299
300 // Rect takes a length in 3rd parameter
301 $pdf->SetDrawColor(192, 192, 192);
302 $pdf->RoundedRect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 2, $this->corner_radius, '1234', 'D');
303
304 $tab_top = $nexY + 6;
305 }
306
307 $iniY = $tab_top + 7;
308 $curY = $tab_top + 7;
309 $nexY = $tab_top + 2;
310
311 $pdf->SetXY($this->marge_gauche, $tab_top);
312
313 $pdf->MultiCell(0, 2, ''); // Set interline to 3. Then writeMultiCell must use 3 also.
314
315 $nblines = count($object->lines);
316
317 // Loop on each lines
318 for ($i = 0; $i < $nblines; $i++) {
319 $objectligne = $object->lines[$i];
320
321 $valide = $objectligne->id ? 1 : 0;
322
323 if ($valide > 0 || $object->specimen) {
324 $curX = $this->posxdesc - 1;
325 $curY = $nexY;
326 $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
327 $pdf->SetTextColor(0, 0, 0);
328
329 $pdf->setTopMargin($tab_top_newpage);
330 $pdf->setPageOrientation('', true, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
331 $pageposbefore = $pdf->getPage();
332
333 // Description of product line
334
335 if (!empty($objectligne->date_start)) {
336 $datei = dol_print_date((int) $objectligne->date_start, 'day', false, $outputlangs, true);
337 } else {
338 $datei = $langs->trans("Unknown");
339 }
340
341 if (!empty($objectligne->date_end)) {
342 $durationi = convertSecondToTime((int) $objectligne->date_end - (int) $objectligne->date_start, 'allwithouthour');
343 $datee = dol_print_date($objectligne->date_end, 'day', false, $outputlangs, true);
344 } else {
345 $durationi = $langs->trans("Unknown");
346 $datee = $langs->trans("Unknown");
347 }
348
349 if (!empty($objectligne->date_start_real)) {
350 $daters = dol_print_date((int) $objectligne->date_start_real, 'day', false, $outputlangs, true);
351 } else {
352 $daters = $langs->trans("Unknown");
353 }
354
355 if (!empty($objectligne->date_end_real)) {
356 $datere = dol_print_date((int) $objectligne->date_end_real, 'day', false, $outputlangs, true);
357 } else {
358 $datere = $langs->trans("Unknown");
359 }
360
361 $txtpredefinedservice = $objectligne->product_ref;
362 if ($objectligne->product_label) {
363 $txtpredefinedservice .= ' - ';
364 $txtpredefinedservice .= $objectligne->product_label;
365 }
366
367 $desc = dol_htmlentitiesbr($objectligne->desc, 1); // Desc (not empty for free lines)
368 $txt = '';
369 if (!getDolGlobalString('CONTRACT_HIDE_QTY_ON_PDF')) {
370 $txt .= $outputlangs->transnoentities("Quantity") . ' : <strong>' . $objectligne->qty . '</strong>';
371 }
372 if (!getDolGlobalString('CONTRACT_HIDE_PRICE_ON_PDF')) {
373 $txt .= ' - ' . $outputlangs->transnoentities("UnitPrice") . ' : <strong>' . price($objectligne->subprice) . '</strong>';
374 }
375 if (!getDolGlobalString('CONTRACT_HIDE_PLANNED_DATE_ON_PDF')) {
376 $txt .= '<br>';
377 $txt .= $outputlangs->transnoentities("DateStartPlannedShort")." : <strong>".$datei."</strong> - ".$outputlangs->transnoentities("DateEndPlanned")." : <strong>".$datee.'</strong>';
378 }
379 if (!getDolGlobalString('CONTRACT_HIDE_REAL_DATE_ON_PDF')) {
380 $txt .= '<br>';
381 $txt .= $outputlangs->transnoentities("DateStartRealShort")." : <strong>".$daters.'</strong>';
382 if (!empty($objectligne->date_end_real)) {
383 $txt .= " - ".$outputlangs->transnoentities("DateEndRealShort")." : <strong>".$datere.'</strong>';
384 }
385 }
386
387 $pdf->startTransaction();
388 $pdf->writeHTMLCell(0, 0, $curX, $curY, dol_concatdesc($txtpredefinedservice, dol_concatdesc($txt, $desc)), false, 1, false);
389 $pageposafter = $pdf->getPage();
390 if ($pageposafter > $pageposbefore) { // There is a pagebreak
391 $pdf->rollbackTransaction(true);
392 $pageposafter = $pageposbefore;
393 //print $pageposafter.'-'.$pageposbefore;exit;
394 $pdf->setPageOrientation('', true, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
395 $pdf->writeHTMLCell(0, 0, $curX, $curY, dol_concatdesc($txtpredefinedservice, dol_concatdesc($txt, $desc)), false, 1, false);
396 $pageposafter = $pdf->getPage();
397 $posyafter = $pdf->GetY();
398 if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
399 if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
400 $pdf->AddPage('', '', true);
401 if (!empty($tplidx)) {
402 $pdf->useTemplate($tplidx);
403 }
404 if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
405 $this->_pagehead($pdf, $object, 0, $outputlangs);
406 }
407 $pdf->setPage($pageposafter + 1);
408 }
409 } else {
410 // We found a page break
411
412 // Allows data in the first page if description is long enough to break in multiples pages
413 if (getDolGlobalString('MAIN_PDF_DATA_ON_FIRST_PAGE')) {
414 $showpricebeforepagebreak = 1;
415 } else {
416 $showpricebeforepagebreak = 0;
417 }
418 }
419 } else { // No pagebreak
420 $pdf->commitTransaction();
421 }
422 $posYAfterDescription = $pdf->GetY();
423
424 $nexY = $pdf->GetY() + 2;
425 $pageposafter = $pdf->getPage();
426
427 $pdf->setPage($pageposbefore);
428 $pdf->setTopMargin($this->marge_haute);
429 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
430
431 // We suppose that a too long description is moved completely on next page
432 if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
433 $pdf->setPage($pageposafter);
434 $curY = $tab_top_newpage;
435 }
436
437 $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font
438
439 // Detect if some page were added automatically and output _tableau for past pages
440 while ($pagenb < $pageposafter) {
441 $pdf->setPage($pagenb);
442 if ($pagenb == 1) {
443 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext, 0, $outputlangs, 0, 1);
444 } else {
445 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter - $heightforfreetext, 0, $outputlangs, 1, 1);
446 }
447 $this->_pagefoot($pdf, $object, $outputlangs, 1);
448 $pagenb++;
449 $pdf->setPage($pagenb);
450 $pdf->setPageOrientation('', true, 0); // The only function to edit the bottom margin of current page to set it.
451 if (!getDolGlobalString('MAIN_PDF_DONOTREPEAT_HEAD')) {
452 $this->_pagehead($pdf, $object, 0, $outputlangs);
453 }
454 if (!empty($tplidx)) {
455 $pdf->useTemplate($tplidx);
456 }
457 }
458
459 if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) { // @phan-suppress-current-line PhanUndeclaredProperty
460 if ($pagenb == 1) {
461 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext, 0, $outputlangs, 0, 1);
462 } else {
463 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter - $heightforfreetext, 0, $outputlangs, 1, 1);
464 }
465 $this->_pagefoot($pdf, $object, $outputlangs, 1);
466 // New page
467 $pdf->AddPage();
468 if (!empty($tplidx)) {
469 $pdf->useTemplate($tplidx);
470 }
471 $pagenb++;
472 }
473 }
474 }
475
476
477 // Show square
478 if ($pagenb == 1) {
479 $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0);
480 $this->tabSignature($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, $outputlangs);
481 $bottomlasttab = $this->page_hauteur - $heightforfooter - $heightforfooter + 1;
482 } else {
483 $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0);
484 $this->tabSignature($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, $outputlangs);
485 $bottomlasttab = $this->page_hauteur - $heightforfooter - $heightforfooter + 1;
486 }
487
488 $this->_pagefoot($pdf, $object, $outputlangs);
489 if (method_exists($pdf, 'AliasNbPages')) {
490 $pdf->AliasNbPages(); // @phan-suppress-current-line PhanUndeclaredMethod
491 }
492
493 // Add terms of sale
494 if (getDolGlobalString('MAIN_INFO_CONTRACT_TERMSOFSALE') && getDolGlobalInt('MAIN_PDF_ADD_TERMSOFSALE_CONTRACT')) {
495 $termsofsalefilename = getDolGlobalString('MAIN_INFO_CONTRACT_TERMSOFSALE');
496 $termsofsale = $conf->contract->dir_output.'/'.$termsofsalefilename;
497 if (!empty($conf->contract->multidir_output[$object->entity ?? $conf->entity])) {
498 $termsofsale = $conf->contract->multidir_output[$object->entity ?? $conf->entity].'/'.$termsofsalefilename;
499 }
500 if (file_exists($termsofsale) && is_readable($termsofsale)) {
501 $pagecount = $pdf->setSourceFile($termsofsale);
502 for ($i = 1; $i <= $pagecount; $i++) {
503 $tplIdx = $pdf->importPage($i);
504 if ($tplIdx !== false) {
505 $s = $pdf->getTemplatesize($tplIdx);
506 $pdf->AddPage($s['h'] > $s['w'] ? 'P' : 'L');
507 $pdf->useTemplate($tplIdx);
508 } else {
509 setEventMessages(null, array($termsofsale.' cannot be added, probably protected PDF'), 'warnings');
510 }
511 }
512 }
513 }
514
515 $pdf->Close();
516
517 $pdf->Output($file, 'F');
518
519 // Add pdfgeneration hook
520 $hookmanager->initHooks(array('pdfgeneration'));
521 $parameters = array('file' => $file, 'object' => $object, 'outputlangs' => $outputlangs);
522 global $action;
523 $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
524 $this->warnings = $hookmanager->warnings;
525 if ($reshook < 0) {
526 $this->error = $hookmanager->error;
527 $this->errors = $hookmanager->errors;
528 dolChmod($file);
529 return -1;
530 }
531
532 dolChmod($file);
533
534 $this->result = array('fullpath' => $file);
535
536 return 1; // No error
537 } else {
538 $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
539 return 0;
540 }
541 } else {
542 $this->error = $langs->transnoentities("ErrorConstantNotDefined", "CONTRACT_OUTPUTDIR");
543 return 0;
544 }
545 }
546
547 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
560 protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0)
561 {
562 global $conf;
563
564 // Force to disable hidetop and hidebottom
565 $hidebottom = 0;
566 if ($hidetop) {
567 $hidetop = -1;
568 }
569
570 //$default_font_size = pdf_getPDFFontSize($outputlangs);
571
572 /*
573 $pdf->SetXY($this->marge_gauche, $tab_top);
574 $pdf->MultiCell(190,8,$outputlangs->transnoentities("Description"),0,'L',0);
575 $pdf->line($this->marge_gauche, $tab_top + 8, $this->page_largeur-$this->marge_droite, $tab_top + 8);
576
577 $pdf->SetFont('','', $default_font_size - 1);
578
579 $pdf->MultiCell(0, 3, ''); // Set interline to 3
580 $pdf->SetXY($this->marge_gauche, $tab_top + 8);
581 $text=$object->description;
582 if ($object->duree > 0)
583 {
584 $totaltime=convertSecondToTime($object->duree,'all',$conf->global->MAIN_DURATION_OF_WORKDAY);
585 $text.=($text?' - ':'').$langs->trans("Total").": ".$totaltime;
586 }
587 $desc=dol_htmlentitiesbr($text,1);
588 //print $outputlangs->convToOutputCharset($desc); exit;
589
590 $pdf->writeHTMLCell(180, 3, 10, $tab_top + 8, $outputlangs->convToOutputCharset($desc), 0, 1);
591 $nexY = $pdf->GetY();
592
593 $pdf->line($this->marge_gauche, $nexY, $this->page_largeur-$this->marge_droite, $nexY);
594
595 $pdf->MultiCell(0, 3, ''); // Set interline to 3. Then writeMultiCell must use 3 also.
596 */
597
598 // Output Rect
599 $this->printRoundedRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height + 3, $this->corner_radius, $hidetop, $hidebottom, 'D'); // Rect takes a length in 3rd parameter and 4th parameter
600 }
601
611 protected function tabSignature(&$pdf, $tab_top, $tab_height, $outputlangs)
612 {
613 $pdf->SetDrawColor(128, 128, 128);
614 $posmiddle = $this->marge_gauche + round(($this->page_largeur - $this->marge_gauche - $this->marge_droite) / 2);
615 $posy = $tab_top + $tab_height + 3 + 3;
616
617 if (!getDolGlobalString('CONTRACT_HIDE_MYCOMPANY_SIGNATURE_SECTION_PDF')) {
618 $pdf->SetXY($this->marge_gauche, $posy);
619 $pdf->MultiCell($posmiddle - $this->marge_gauche - 5, 5, $outputlangs->transnoentities("ContactNameAndSignature", $this->emetteur->name), 0, 'L', false);
620
621 $pdf->SetXY($this->marge_gauche, $posy + 5);
622 $pdf->RoundedRect($this->marge_gauche, $posy + 5, $posmiddle - $this->marge_gauche - 5, 20, $this->corner_radius, '1234', 'D');
623 }
624
625 if (!getDolGlobalString('CONTRACT_HIDE_THIRPARTY_SIGNATURE_SECTION_PDF') && is_object($this->recipient)) {
626 $pdf->SetXY($posmiddle + 5, $posy);
627 $recipientname = pdfBuildThirdpartyName($this->recipient, $outputlangs);
628 $pdf->MultiCell($this->page_largeur - $this->marge_droite - $posmiddle - 5, 5, $outputlangs->transnoentities("ContactNameAndSignature", $recipientname), 0, 'L', false);
629
630 $pdf->SetXY($posmiddle + 5, $posy + 5);
631 $pdf->RoundedRect($posmiddle + 5, $posy + 5, $this->page_largeur - $this->marge_droite - $posmiddle - 5, 20, $this->corner_radius, '1234', 'D');
632 }
633 }
634
635 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
647 protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis = null, $titlekey = "Contract")
648 {
649 // phpcs:enable
650 global $conf;
651
652 $top_shift = 0;
653
654 $ltrdirection = 'L';
655 if ($outputlangs->trans("DIRECTION") == 'rtl') {
656 $ltrdirection = 'R';
657 }
658
659 // Load traductions files required by page
660 $outputlangs->loadLangs(array("main", "dict", "contract", "companies"));
661
662 $default_font_size = pdf_getPDFFontSize($outputlangs);
663
664 pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
665
666 $pdf->SetTextColor(0, 0, 60);
667 $pdf->SetFont('', 'B', $default_font_size + 3);
668
669 $w = 100;
670
671 $posy = $this->marge_haute;
672 $posx = $this->page_largeur - $this->marge_droite - $w;
673
674 $pdf->SetXY($this->marge_gauche, $posy);
675
676 // Logo
677 if (!getDolGlobalString('PDF_DISABLE_MYCOMPANY_LOGO')) {
678 if ($this->emetteur->logo) {
679 $logodir = $conf->mycompany->dir_output;
680 if (getMultidirOutput($object, 'mycompany')) {
681 $logodir = getMultidirOutput($object, 'mycompany');
682 }
683 if (!getDolGlobalString('MAIN_PDF_USE_LARGE_LOGO')) {
684 $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
685 } else {
686 $logo = $logodir.'/logos/'.$this->emetteur->logo;
687 }
688 if (is_readable($logo)) {
689 $height = pdf_getHeightForLogo($logo);
690 $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
691 } else {
692 $pdf->SetTextColor(200, 0, 0);
693 $pdf->SetFont('', 'B', $default_font_size - 2);
694 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
695 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
696 }
697 } else {
698 $text = $this->emetteur->name;
699 $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $ltrdirection);
700 }
701 }
702
703 $pdf->SetFont('', 'B', $default_font_size + 3);
704 $pdf->SetXY($posx, $posy);
705 $pdf->SetTextColor(0, 0, 60);
706 $title = $outputlangs->transnoentities($titlekey);
707 $title .= ' '.$outputlangs->convToOutputCharset($object->ref);
708 if ($object->status == $object::STATUS_DRAFT) {
709 $pdf->SetTextColor(128, 0, 0);
710 $title .= ' - '.$outputlangs->transnoentities("NotValidated");
711 }
712 $pdf->MultiCell($w, 3, $title, '', 'R');
713
714 $pdf->SetFont('', 'B', $default_font_size);
715
716 /*
717 $posy += 5;
718 $pdf->SetXY($posx, $posy);
719 $pdf->SetTextColor(0, 0, 60);
720 $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Ref")." : ".$outputlangs->convToOutputCharset($object->ref), '', 'R');
721 */
722
723 $posy += 3;
724 $pdf->SetFont('', '', $default_font_size - 1);
725
726 $posy += 4;
727 $pdf->SetXY($posx, $posy);
728 $pdf->SetTextColor(0, 0, 60);
729 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date_contrat, "day", false, $outputlangs, true), '', 'R');
730
731 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_CODE') && $object->thirdparty->code_client) {
732 $posy += 4;
733 $pdf->SetXY($posx, $posy);
734 $pdf->SetTextColor(0, 0, 60);
735 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities((string) $object->thirdparty->code_client), '', 'R');
736 }
737
738 if (!getDolGlobalString('MAIN_PDF_HIDE_CUSTOMER_ACCOUNTING_CODE') && $object->thirdparty->code_compta_client) {
739 $posy += 4;
740 $pdf->SetXY($posx, $posy);
741 $pdf->SetTextColor(0, 0, 60);
742 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerAccountancyCode")." : ".$outputlangs->transnoentities((string) $object->thirdparty->code_compta_client), '', 'R');
743 }
744
745 if ($showaddress) {
746 // Sender properties
747 $carac_emetteur = '';
748 // Add internal contact of object if defined
749 $arrayidcontact = $object->getIdContact('internal', 'INTERREPFOLL');
750 if (count($arrayidcontact) > 0) {
751 $object->fetch_user($arrayidcontact[0]);
752 $labelbeforecontactname = ($outputlangs->transnoentities("FromContactName") != 'FromContactName' ? $outputlangs->transnoentities("FromContactName") : $outputlangs->transnoentities("Name"));
753 $carac_emetteur .= ($carac_emetteur ? "\n" : '').$labelbeforecontactname.": ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs));
754 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ' (' : '';
755 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && !empty($object->user->office_phone)) ? $object->user->office_phone : '';
756 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') && getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ', ' : '';
757 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT') && !empty($object->user->email)) ? $object->user->email : '';
758 $carac_emetteur .= (getDolGlobalInt('PDF_SHOW_PHONE_AFTER_USER_CONTACT') || getDolGlobalInt('PDF_SHOW_EMAIL_AFTER_USER_CONTACT')) ? ')' : '';
759 $carac_emetteur .= "\n";
760 }
761
762 $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
763
764 // Show sender
765 $posy = 42;
766 $posx = $this->marge_gauche;
767 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
768 $posx = $this->page_largeur - $this->marge_droite - 80;
769 }
770 $hautcadre = 40;
771
772 // Show sender frame
773 if (!getDolGlobalString('MAIN_PDF_NO_SENDER_FRAME')) {
774 $pdf->SetTextColor(0, 0, 0);
775 $pdf->SetFont('', '', $default_font_size - 2);
776 $pdf->SetXY($posx, $posy - 5);
777 $pdf->SetXY($posx, $posy);
778 $pdf->SetFillColor(230, 230, 230);
779 $pdf->RoundedRect($posx, $posy, 82, $hautcadre, $this->corner_radius, '1234', 'F');
780 $pdf->SetTextColor(0, 0, 60);
781 }
782
783 // Show sender name
784 if (!getDolGlobalString('MAIN_PDF_HIDE_SENDER_NAME')) {
785 $pdf->SetXY($posx + 2, $posy + 3);
786 $pdf->SetTextColor(0, 0, 60);
787 $pdf->SetFont('', 'B', $default_font_size);
788 $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L');
789 $posy = $pdf->getY();
790 }
791
792 // Show sender information
793 $pdf->SetXY($posx + 2, $posy);
794 $pdf->SetFont('', '', $default_font_size - 1);
795 $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L');
796
797
798 // If CUSTOMER contact defined, we use it
799 $usecontact = false;
800 $arrayidcontact = $object->getIdContact('external', 'CUSTOMER');
801 if (count($arrayidcontact) > 0) {
802 $usecontact = true;
803 $result = $object->fetch_contact($arrayidcontact[0]);
804 }
805
806 // Recipient name
807 if ($usecontact && ($object->contact->socid != $object->thirdparty->id) && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || getDolGlobalString('MAIN_USE_COMPANY_NAME_OF_CONTACT'))) {
808 $this->recipient = $object->contact;
809 } else {
810 $this->recipient = $object->thirdparty;
811 }
812
813 $recipientname = '';
814 if ($this->recipient instanceof Contact || $this->recipient instanceof Societe) {
815 $recipientname = pdfBuildThirdpartyName($this->recipient, $outputlangs);
816 }
817
818 $mode = 'target';
819 $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, (isset($object->contact) ? $object->contact : ''), ($usecontact ? 1 : 0), $mode, $object);
820
821 // Show recipient
822 $widthrecbox = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 92 : 100;
823 if ($this->page_largeur < 210) {
824 $widthrecbox = 84; // To work with US executive format
825 }
826 $posy = getDolGlobalString('MAIN_PDF_USE_ISO_LOCATION') ? 40 : 42;
827 $posy += $top_shift;
828 $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
829 if (getDolGlobalString('MAIN_INVERT_SENDER_RECIPIENT')) {
830 $posx = $this->marge_gauche;
831 }
832
833 // Show recipient frame
834 if (!getDolGlobalString('MAIN_PDF_NO_RECIPENT_FRAME')) {
835 $pdf->SetTextColor(0, 0, 0);
836 $pdf->SetFont('', '', $default_font_size - 2);
837 $pdf->SetXY($posx + 2, $posy - 5);
838 $pdf->RoundedRect($posx, $posy, $widthrecbox, $hautcadre, $this->corner_radius, '1234', 'D');
839 $pdf->SetTextColor(0, 0, 0);
840 }
841
842 // Show recipient name
843 $pdf->SetXY($posx + 2, $posy + 3);
844 $pdf->SetFont('', 'B', $default_font_size);
845 $pdf->MultiCell($widthrecbox, 4, $recipientname, 0, $ltrdirection);
846
847 $posy = $pdf->getY();
848
849 // Show recipient information
850 $pdf->SetFont('', '', $default_font_size - 1);
851 $pdf->SetXY($posx + 2, $posy);
852 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
853 $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, $ltrdirection);
854 }
855
856 $pdf->SetTextColor(0, 0, 0);
857
858 return $top_shift;
859 }
860
861 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
871 protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
872 {
873 $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
874 return pdf_pagefoot($pdf, $outputlangs, 'CONTRACT_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext, $this->page_largeur, $this->watermark);
875 }
876}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
printRoundedRect($pdf, $x, $y, $w, $h, $r, $hidetop=0, $hidebottom=0, $style='D')
Print a rounded rectangle on the PDF.
Class to manage contact/addresses.
Class to manage hooks.
Parent class to manage intervention document templates.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to build contracts documents with model Strato.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf on disk.
tabSignature(&$pdf, $tab_top, $tab_height, $outputlangs)
Show footer signature of page.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
_pagehead(&$pdf, $object, $showaddress, $outputlangs, $outputlangsbis=null, $titlekey="Contract")
Show top header of page.
__construct($db)
Constructor.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0)
Show table for lines.
global $mysoc
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition date.lib.php:248
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!function_exists( 'dolEscapeXML')) convertBackOfficeMediasLinksToPublicLinks($notetoshow)
Convert links to local wrapper to medias files into a string into a public external URL readable on i...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
getCallerInfoString()
Get caller info as a string that can be appended to a log message.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getMultidirOutput($object, $module='', $forobject=0, $mode='output')
Return the full path of the directory where a module (or an object of a module) stores its files.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
pdf_getFormat($outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition pdf.lib.php:87
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:294
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:317
pdf_pagehead($pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:747
pdf_pagefoot($pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0, $page_largeur=0, $watermark='')
Show footer of page for PDF generation.
Definition pdf.lib.php:1421
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:273
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formatted for output on PDF documents.
Definition pdf.lib.php:438
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0, $include=null)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition pdf.lib.php:1135
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition pdf.lib.php:129
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition pdf.lib.php:393
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:130
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:133