dolibarr 23.0.3
pdf.lib.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (C) 2006-2017 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
5 * Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
6 * Copyright (C) 2010-2012 Regis Houssin <regis.houssin@inodbox.com>
7 * Copyright (C) 2010-2017 Juanjo Menent <jmenent@2byte.es>
8 * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
9 * Copyright (C) 2012 Cédric Salvador <csalvador@gpcsolutions.fr>
10 * Copyright (C) 2012-2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
11 * Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
12 * Copyright (C) 2014 Teddy Andreotti <125155@supinfo.com>
13 * Copyright (C) 2015-2016 Marcos García <marcosgdf@gmail.com>
14 * Copyright (C) 2019 Lenin Rivas <lenin.rivas@servcom-it.com>
15 * Copyright (C) 2020 Nicolas ZABOURI <info@inovea-conseil.com>
16 * Copyright (C) 2021-2022 Anthony Berton <anthony.berton@bb2a.fr>
17 * Copyright (C) 2023-2025 Frédéric France <frederic.france@free.fr>
18 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 3 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program. If not, see <https://www.gnu.org/licenses/>.
32 * or see https://www.gnu.org/
33 */
34
41include_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php';
42
43
50{
51 global $langs, $conf;
52
53 $h = 0;
54 $head = array();
55
56 $head[$h][0] = DOL_URL_ROOT.'/admin/pdf.php';
57 $head[$h][1] = $langs->trans("GlobalParameters");
58 $head[$h][2] = 'general';
59 $h++;
60
61 // Show more tabs from modules
62 // Entries must be declared in modules descriptor with line
63 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
64 // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab
65 complete_head_from_modules($conf, $langs, null, $head, $h, 'pdf_admin');
66
67 if (isModEnabled("propal") || isModEnabled('invoice') || isModEnabled('reception')) {
68 $head[$h][0] = DOL_URL_ROOT.'/admin/pdf_other.php';
69 $head[$h][1] = $langs->trans("SpecificParameters");
70 $head[$h][2] = 'other';
71 $h++;
72 }
73
74 complete_head_from_modules($conf, $langs, null, $head, $h, 'pdf_admin', 'remove');
75
76 return $head;
77}
78
79
87function pdf_getFormat($outputlangs = null, $mode = 'setup')
88{
89 global $conf, $db, $langs;
90
91 dol_syslog("pdf_getFormat Get paper format with mode=".$mode." MAIN_PDF_FORMAT=".getDolGlobalString('MAIN_PDF_FORMAT')." outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null')." and langs->defaultlang=".(is_object($langs) ? $langs->defaultlang : 'null'));
92
93 // Default value if setup was not done and/or entry into c_paper_format not defined
94 $width = 210;
95 $height = 297;
96 $unit = 'mm';
97
98 if ($mode == 'auto' || !getDolGlobalString('MAIN_PDF_FORMAT') || getDolGlobalString('MAIN_PDF_FORMAT') == 'auto') {
99 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
100 $pdfformat = dol_getDefaultFormat($outputlangs);
101 } else {
102 $pdfformat = getDolGlobalString('MAIN_PDF_FORMAT');
103 }
104
105 $sql = "SELECT code, label, width, height, unit FROM ".MAIN_DB_PREFIX."c_paper_format";
106 $sql .= " WHERE code = '".$db->escape($pdfformat)."'";
107 $resql = $db->query($sql);
108 if ($resql) {
109 $obj = $db->fetch_object($resql);
110 if ($obj) {
111 $width = (int) $obj->width;
112 $height = (int) $obj->height;
113 $unit = $obj->unit;
114 }
115 }
116
117 //print "pdfformat=".$pdfformat." width=".$width." height=".$height." unit=".$unit;
118 return array('width' => $width, 'height' => $height, 'unit' => $unit);
119}
120
129function pdf_getInstance($format = '', $metric = 'mm', $pagetype = 'P')
130{
131 global $conf;
132
133 // Define constant for TCPDF
134 if (!defined('K_TCPDF_EXTERNAL_CONFIG')) {
135 define('K_TCPDF_EXTERNAL_CONFIG', 1); // this avoid using tcpdf_config file
136 define('K_PATH_CACHE', DOL_DATA_ROOT.'/admin/temp/');
137 define('K_PATH_URL_CACHE', DOL_DATA_ROOT.'/admin/temp/');
138 dol_mkdir(K_PATH_CACHE);
139 define('K_BLANK_IMAGE', '_blank.png');
140 define('PDF_PAGE_FORMAT', 'A4');
141 define('PDF_PAGE_ORIENTATION', 'P');
142 define('PDF_CREATOR', 'TCPDF');
143 define('PDF_AUTHOR', 'TCPDF');
144 define('PDF_HEADER_TITLE', 'TCPDF Example');
145 define('PDF_HEADER_STRING', "by Dolibarr ERP CRM");
146 define('PDF_UNIT', 'mm');
147 define('PDF_MARGIN_HEADER', 5);
148 define('PDF_MARGIN_FOOTER', 10);
149 define('PDF_MARGIN_TOP', 27);
150 define('PDF_MARGIN_BOTTOM', 25);
151 define('PDF_MARGIN_LEFT', 15);
152 define('PDF_MARGIN_RIGHT', 15);
153 define('PDF_FONT_NAME_MAIN', 'helvetica');
154 define('PDF_FONT_SIZE_MAIN', 10);
155 define('PDF_FONT_NAME_DATA', 'helvetica');
156 define('PDF_FONT_SIZE_DATA', 8);
157 define('PDF_FONT_MONOSPACED', 'courier');
158 define('PDF_IMAGE_SCALE_RATIO', 1.25);
159 define('HEAD_MAGNIFICATION', 1.1);
160 define('K_CELL_HEIGHT_RATIO', 1.25);
161 define('K_TITLE_MAGNIFICATION', 1.3);
162 define('K_SMALL_RATIO', 2 / 3);
163 define('K_THAI_TOPCHARS', true);
164 define('K_TCPDF_CALLS_IN_HTML', true);
165 if (getDolGlobalString('TCPDF_THROW_ERRORS_INSTEAD_OF_DIE')) {
166 define('K_TCPDF_THROW_EXCEPTION_ERROR', true);
167 } else {
168 define('K_TCPDF_THROW_EXCEPTION_ERROR', false);
169 }
170 }
171
172 // Load TCPDF
173 require_once TCPDF_PATH.'tcpdf.php';
174
175 // We need to instantiate tcpdi object (instead of tcpdf) to use merging features. But we can disable it (this will break all merge features).
176 if (!getDolGlobalString('MAIN_DISABLE_TCPDI')) {
177 require_once TCPDI_PATH.'tcpdi.php';
178 }
179
180 //$arrayformat=pdf_getFormat();
181 //$format=array($arrayformat['width'],$arrayformat['height']);
182 //$metric=$arrayformat['unit'];
183
184 //$pdfa = false; // PDF default version
185 $pdfa = getDolGlobalInt('PDF_USE_A', 0); // PDF/A-1 ou PDF/A-3
186
187 if (!getDolGlobalString('MAIN_DISABLE_TCPDI') && class_exists('TCPDI')) {
188 $pdf = new TCPDI($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
189 } else {
190 $pdf = new TCPDF($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
191 }
192
193 // Protection and encryption of pdf
194 if (getDolGlobalString('PDF_SECURITY_ENCRYPTION')) {
195 /* Permission supported by TCPDF
196 - print : Print the document;
197 - modify : Modify the contents of the document by operations other than those controlled by 'fill-forms', 'extract' and 'assemble';
198 - copy : Copy or otherwise extract text and graphics from the document;
199 - annot-forms : Add or modify text annotations, fill in interactive form fields, and, if 'modify' is also set, create or modify interactive form fields (including signature fields);
200 - fill-forms : Fill in existing interactive form fields (including signature fields), even if 'annot-forms' is not specified;
201 - extract : Extract text and graphics (in support of accessibility to users with disabilities or for other purposes);
202 - assemble : Assemble the document (insert, rotate, or delete pages and create bookmarks or thumbnail images), even if 'modify' is not set;
203 - print-high : Print the document to a representation from which a faithful digital copy of the PDF content could be generated. When this is not set, printing is limited to a low-level representation of the appearance, possibly of degraded quality.
204 - owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions.
205 */
206
207 // For TCPDF, we specify permission we want to block
208 $pdfrights = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_RIGHTS') ? json_decode(getDolGlobalString('PDF_SECURITY_ENCRYPTION_RIGHTS'), true) : array('modify', 'copy')); // Json format in llx_const
209
210 // Password for the end user
211 $pdfuserpass = getDolGlobalString('PDF_SECURITY_ENCRYPTION_USERPASS');
212
213 // Password of the owner, created randomly if not defined
214 $pdfownerpass = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_OWNERPASS') ? getDolGlobalString('PDF_SECURITY_ENCRYPTION_OWNERPASS') : null);
215
216 // For encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit
217 $encstrength = getDolGlobalInt('PDF_SECURITY_ENCRYPTION_STRENGTH', 0);
218
219 // Array of recipients containing public-key certificates ('c') and permissions ('p').
220 // For example: array(array('c' => 'file://../examples/data/cert/tcpdf.crt', 'p' => array('print')))
221 $pubkeys = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_PUBKEYS') ? json_decode(getDolGlobalString('PDF_SECURITY_ENCRYPTION_PUBKEYS'), true) : null); // Json format in llx_const
222
223 $pdf->SetProtection($pdfrights, $pdfuserpass, $pdfownerpass, $encstrength, $pubkeys);
224 }
225
226 return $pdf;
227}
228
235function pdf_getEncryption($pathoffile)
236{
237 require_once TCPDF_PATH.'tcpdf_parser.php';
238
239 $isencrypted = false;
240
241 $content = file_get_contents($pathoffile);
242
243 //ob_start();
244 @($parser = new TCPDF_PARSER(ltrim($content)));
245 $tmp = $parser->getParsedData();
246 $xref = $tmp[0];
247 $data = $tmp[1] ?? null;
248 unset($parser);
249 //ob_end_clean();
250
251 if (isset($xref['trailer']['encrypt'])) {
252 $isencrypted = true; // Secured pdf file are currently not supported
253 }
254
255 if (empty($data)) {
256 $isencrypted = true; // Object list not found. Possible secured file
257 }
258
259 return $isencrypted;
260}
261
268function pdf_getPDFFont($outputlangs)
269{
270 if (getDolGlobalString('MAIN_PDF_FORCE_FONT')) {
271 return getDolGlobalString('MAIN_PDF_FORCE_FONT');
272 }
273
274 $font = 'Helvetica'; // By default, for FPDI, or ISO language on TCPDF
275 if (class_exists('TCPDF')) { // If TCPDF on, we can use an UTF8 one like DejaVuSans if required (slower)
276 if ($outputlangs->trans('FONTFORPDF') != 'FONTFORPDF') {
277 $font = $outputlangs->trans('FONTFORPDF');
278 }
279 }
280 return $font;
281}
282
289function pdf_getPDFFontSize($outputlangs)
290{
291 $size = 10; // By default, for FPDI or ISO language on TCPDF
292 if (class_exists('TCPDF')) { // If TCPDF on, we can use an UTF8 font like DejaVuSans if required (slower)
293 if ($outputlangs->trans('FONTSIZEFORPDF') != 'FONTSIZEFORPDF') {
294 $size = (int) $outputlangs->trans('FONTSIZEFORPDF');
295 }
296 }
297 if (getDolGlobalString('MAIN_PDF_FORCE_FONT_SIZE')) {
298 $size = getDolGlobalString('MAIN_PDF_FORCE_FONT_SIZE');
299 }
300
301 return $size;
302}
303
304
312function pdf_getHeightForLogo($logo, $url = false)
313{
314 $height = getDolGlobalInt('MAIN_DOCUMENTS_LOGO_HEIGHT', 20);
315 $maxwidth = 130;
316 include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
317 $tmp = dol_getImageSize($logo, $url);
318 if ($tmp['height']) {
319 $width = round($height * $tmp['width'] / $tmp['height']);
320 if ($width > $maxwidth) {
321 $height = $height * $maxwidth / $width;
322 }
323 }
324 //print $tmp['width'].' '.$tmp['height'].' '.$width; exit;
325 return $height;
326}
327
337function pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
338{
339 // store current object
340 $pdf->startTransaction();
341 // To avoid pagebreak effect or strange behavior of writeHTMLCell when we are out of page, we imagine we are at the begin of page to test the height of the text
342 // Another solution would be to do the test on another PDF instance with samefont, width...
343 $pdf->setY(0);
344 // store starting values
345 $start_y = $pdf->GetY();
346 //var_dump($start_y);
347 $start_page = $pdf->getPage();
348 // call printing functions with content
349 $pdf->writeHTMLCell(0, 0, 0, $start_y, $htmlcontent, 0, 1, false, true, 'J', true);
350 // get the new Y
351 $end_y = $pdf->GetY();
352 $end_page = $pdf->getPage();
353 // calculate height
354 $height = 0;
355 if ($end_page == $start_page) {
356 $height = $end_y - $start_y;
357 } else {
358 for ($page = $start_page; $page <= $end_page; ++$page) {
359 $pdf->setPage($page);
360 $tmpm = $pdf->getMargins();
361 $tMargin = $tmpm['top'];
362 if ($page == $start_page) {
363 // first page
364 $height = $pdf->getPageHeight() - $start_y - $pdf->getBreakMargin();
365 } elseif ($page == $end_page) {
366 // last page
367 $height = $end_y - $tMargin;
368 } else {
369 $height = $pdf->getPageHeight() - $tMargin - $pdf->getBreakMargin();
370 }
371 }
372 }
373 // restore previous object
374 $pdf = $pdf->rollbackTransaction();
375
376 return $height;
377}
378
379
388function pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias = 0)
389{
390 // Recipient name
391 $socname = '';
392
393 if ($thirdparty instanceof Societe) {
394 $socname = $thirdparty->name;
395 if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->name_alias)) {
396 if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
397 $socname = $thirdparty->name_alias." - ".$thirdparty->name;
398 } else {
399 $socname = $thirdparty->name." - ".$thirdparty->name_alias;
400 }
401 }
402 } elseif ($thirdparty instanceof Contact) {
403 if ($thirdparty->socid > 0) {
404 $thirdparty->fetch_thirdparty();
405 $socname = $thirdparty->thirdparty->name;
406 if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->thirdparty->name_alias)) {
407 if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
408 $socname = $thirdparty->thirdparty->name_alias." - ".$thirdparty->thirdparty->name;
409 } else {
410 $socname = $thirdparty->thirdparty->name." - ".$thirdparty->thirdparty->name_alias;
411 }
412 }
413 }
414 } else {
415 throw new InvalidArgumentException('Parameter 1 $thirdparty is not a Societe nor Contact');
416 }
417
418 return $outputlangs->convToOutputCharset((string) $socname);
419}
420
433function pdf_build_address($outputlangs, $sourcecompany, $targetcompany = '', $targetcontact = '', $usecontact = 0, $mode = 'source', $object = null)
434{
435 global $hookmanager;
436
437 if ($mode == 'source' && !is_object($sourcecompany)) {
438 return -1;
439 }
440 if ($mode == 'target' && !is_object($targetcompany)) {
441 return -1;
442 }
443
444 if (!empty($sourcecompany->state_id) && empty($sourcecompany->state)) {
445 $sourcecompany->state = getState($sourcecompany->state_id);
446 }
447 if (!empty($targetcompany->state_id) && empty($targetcompany->state)) {
448 $targetcompany->state = getState($targetcompany->state_id);
449 }
450
451 $reshook = 0;
452 $stringaddress = '';
453 if (is_object($hookmanager)) {
454 $parameters = array('sourcecompany' => &$sourcecompany, 'targetcompany' => &$targetcompany, 'targetcontact' => &$targetcontact, 'outputlangs' => $outputlangs, 'mode' => $mode, 'usecontact' => $usecontact);
455 $action = '';
456 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable
457 $reshook = $hookmanager->executeHooks('pdf_build_address', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
458 $stringaddress .= $hookmanager->resPrint;
459 }
460 if (empty($reshook)) {
461 if ($mode == 'source') {
462 $withCountry = 0;
463 if (isset($targetcompany->country_code) && !empty($sourcecompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
464 $withCountry = 1;
465 }
466
467 $fulladdress = dol_format_address($sourcecompany, $withCountry, "\n", $outputlangs);
468 if ($fulladdress) {
469 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($fulladdress)."\n";
470 }
471
472 if (!getDolGlobalString('MAIN_PDF_DISABLESOURCEDETAILS')) {
473 // Phone
474 if ($sourcecompany->phone) {
475 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("PhoneShort").": ".$outputlangs->convToOutputCharset($sourcecompany->phone);
476 }
477 // Phone mobile
478 if ($sourcecompany->phone_mobile && getDolGlobalString('MAIN_PDF_SHOW_SOURCE_PHONE_MOBILE')) {
479 $stringaddress .= ($stringaddress ? ($sourcecompany->phone ? " - " : "\n") : '').$outputlangs->transnoentities("PhoneShort").": ".$outputlangs->convToOutputCharset($sourcecompany->phone_mobile);
480 }
481 // Fax
482 if ($sourcecompany->fax) {
483 $stringaddress .= ($stringaddress ? ($sourcecompany->phone ? " - " : "\n") : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($sourcecompany->fax);
484 }
485 // EMail
486 if ($sourcecompany->email) {
487 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($sourcecompany->email);
488 }
489 // Web
490 if ($sourcecompany->url) {
491 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($sourcecompany->url);
492 }
493 }
494 // Intra VAT
495 if (getDolGlobalString('MAIN_TVAINTRA_IN_SOURCE_ADDRESS')) {
496 if ($sourcecompany->tva_intra) {
497 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($sourcecompany->tva_intra);
498 }
499 }
500 // Professional Ids
501 $reg = array();
502 if (getDolGlobalString('MAIN_PROFID1_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof1)) {
503 $tmp = $outputlangs->transcountrynoentities("ProfId1", $sourcecompany->country_code);
504 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
505 $tmp = $reg[1];
506 }
507 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof1);
508 }
509 if (getDolGlobalString('MAIN_PROFID2_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof2)) {
510 $tmp = $outputlangs->transcountrynoentities("ProfId2", $sourcecompany->country_code);
511 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
512 $tmp = $reg[1];
513 }
514 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof2);
515 }
516 if (getDolGlobalString('MAIN_PROFID3_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof3)) {
517 $tmp = $outputlangs->transcountrynoentities("ProfId3", $sourcecompany->country_code);
518 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
519 $tmp = $reg[1];
520 }
521 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof3);
522 }
523 if (getDolGlobalString('MAIN_PROFID4_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof4)) {
524 $tmp = $outputlangs->transcountrynoentities("ProfId4", $sourcecompany->country_code);
525 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
526 $tmp = $reg[1];
527 }
528 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof4);
529 }
530 if (getDolGlobalString('MAIN_PROFID5_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof5)) {
531 $tmp = $outputlangs->transcountrynoentities("ProfId5", $sourcecompany->country_code);
532 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
533 $tmp = $reg[1];
534 }
535 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof5);
536 }
537 if (getDolGlobalString('MAIN_PROFID6_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof6)) {
538 $tmp = $outputlangs->transcountrynoentities("ProfId6", $sourcecompany->country_code);
539 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
540 $tmp = $reg[1];
541 }
542 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof6);
543 }
544 if (getDolGlobalString('PDF_ADD_MORE_AFTER_SOURCE_ADDRESS')) {
545 $stringaddress .= ($stringaddress ? "\n" : '') . getDolGlobalString('PDF_ADD_MORE_AFTER_SOURCE_ADDRESS');
546 }
547 }
548
549 if ($mode == 'target' || preg_match('/targetwithdetails/', $mode)) {
550 if ($usecontact && (is_object($targetcontact))) {
551 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($targetcontact->getFullName($outputlangs, 1));
552
553 if (!empty($targetcontact->address)) {
554 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcontact))."\n";
555 } elseif (is_object($targetcompany)) {
556 $companytouseforaddress = $targetcompany;
557
558 // Contact on a thirdparty that is a different thirdparty than the thirdparty of object
559 if ($targetcontact->socid > 0 && $targetcontact->socid != $targetcompany->id) {
560 $targetcontact->fetch_thirdparty();
561 $companytouseforaddress = $targetcontact->thirdparty;
562 }
563
564 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($companytouseforaddress))."\n";
565 }
566 // Country
567 if (!empty($targetcontact->country_code) && $targetcontact->country_code != $sourcecompany->country_code) {
568 $stringaddress .= (($stringaddress && !getDolGlobalString('MAIN_PDF_REMOVE_BREAK_BEFORE_COUNTRY')) ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcontact->country_code));
569 } elseif (empty($targetcontact->country_code) && !empty($targetcompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
570 $stringaddress .= (($stringaddress && !getDolGlobalString('MAIN_PDF_REMOVE_BREAK_BEFORE_COUNTRY')) ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
571 }
572
573 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || preg_match('/targetwithdetails/', $mode)) {
574 // Phone
575 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
576 if (!empty($targetcontact->phone_pro) || !empty($targetcontact->phone_mobile)) {
577 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
578 }
579 if (!empty($targetcontact->phone_pro)) {
580 $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_pro);
581 }
582 if (!empty($targetcontact->phone_pro) && !empty($targetcontact->phone_mobile)) {
583 $stringaddress .= " / ";
584 }
585 if (!empty($targetcontact->phone_mobile)) {
586 $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_mobile);
587 }
588 }
589 // Fax
590 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
591 if ($targetcontact->fax) {
592 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcontact->fax);
593 }
594 }
595 // EMail
596 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
597 if ($targetcontact->email) {
598 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcontact->email);
599 }
600 }
601 // Web
602 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
603 if ($targetcontact->url) {
604 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset((string) $targetcontact->url);
605 }
606 }
607 }
608 } else {
609 if (is_object($targetcompany)) {
610 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcompany));
611 // Country
612 if (!empty($targetcompany->country_code) && $targetcompany->country_code != $sourcecompany->country_code) {
613 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
614 } else {
615 $stringaddress .= ($stringaddress ? "\n" : '');
616 }
617
618 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || preg_match('/targetwithdetails/', $mode)) {
619 // Phone
620 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
621 if (!empty($targetcompany->phone) || !empty($targetcompany->phone_mobile)) {
622 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
623 }
624 if (!empty($targetcompany->phone)) {
625 $stringaddress .= $outputlangs->convToOutputCharset($targetcompany->phone);
626 }
627 if (!empty($targetcompany->phone) && !empty($targetcompany->phone_mobile)) {
628 $stringaddress .= " / ";
629 }
630 if (!empty($targetcompany->phone_mobile)) {
631 $stringaddress .= $outputlangs->convToOutputCharset($targetcompany->phone_mobile);
632 }
633 }
634 // Fax
635 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
636 if ($targetcompany->fax) {
637 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcompany->fax);
638 }
639 }
640 // EMail
641 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
642 if ($targetcompany->email) {
643 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcompany->email);
644 }
645 }
646 // Web
647 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
648 if ($targetcompany->url) {
649 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcompany->url);
650 }
651 }
652 }
653 }
654 }
655
656 // Intra VAT
657 if (!getDolGlobalString('MAIN_TVAINTRA_NOT_IN_ADDRESS')) {
658 if ($usecontact && is_object($targetcontact) && getDolGlobalInt('MAIN_USE_COMPANY_NAME_OF_CONTACT')) {
659 $targetcontact->fetch_thirdparty();
660 if (!empty($targetcontact->thirdparty->id) && $targetcontact->thirdparty->tva_intra) {
661 $stringaddress .= ($stringaddress ? "\n" : '') . $outputlangs->transnoentities("VATIntraShort") . ': ' . $outputlangs->convToOutputCharset($targetcontact->thirdparty->tva_intra);
662 }
663 } elseif (!empty($targetcompany->tva_intra)) {
664 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($targetcompany->tva_intra);
665 }
666 }
667
668 // Legal form
669 if (getDolGlobalString('MAIN_LEGALFORM_IN_ADDRESS') && !empty($targetcompany->forme_juridique_code)) {
670 $tmp = getFormeJuridiqueLabel((string) $targetcompany->forme_juridique_code);
671 $stringaddress .= ($stringaddress ? "\n" : '').$tmp;
672 }
673
674 // Professional Ids
675 if (getDolGlobalString('MAIN_PROFID1_IN_ADDRESS') && !empty($targetcompany->idprof1)) {
676 $tmp = $outputlangs->transcountrynoentities("ProfId1", $targetcompany->country_code);
677 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
678 $tmp = $reg[1];
679 }
680 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof1);
681 }
682 if (getDolGlobalString('MAIN_PROFID2_IN_ADDRESS') && !empty($targetcompany->idprof2)) {
683 $tmp = $outputlangs->transcountrynoentities("ProfId2", $targetcompany->country_code);
684 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
685 $tmp = $reg[1];
686 }
687 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof2);
688 }
689 if (getDolGlobalString('MAIN_PROFID3_IN_ADDRESS') && !empty($targetcompany->idprof3)) {
690 $tmp = $outputlangs->transcountrynoentities("ProfId3", $targetcompany->country_code);
691 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
692 $tmp = $reg[1];
693 }
694 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof3);
695 }
696 if (getDolGlobalString('MAIN_PROFID4_IN_ADDRESS') && !empty($targetcompany->idprof4)) {
697 $tmp = $outputlangs->transcountrynoentities("ProfId4", $targetcompany->country_code);
698 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
699 $tmp = $reg[1];
700 }
701 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof4);
702 }
703 if (getDolGlobalString('MAIN_PROFID5_IN_ADDRESS') && !empty($targetcompany->idprof5)) {
704 $tmp = $outputlangs->transcountrynoentities("ProfId5", $targetcompany->country_code);
705 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
706 $tmp = $reg[1];
707 }
708 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof5);
709 }
710 if (getDolGlobalString('MAIN_PROFID6_IN_ADDRESS') && !empty($targetcompany->idprof6)) {
711 $tmp = $outputlangs->transcountrynoentities("ProfId6", $targetcompany->country_code);
712 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
713 $tmp = $reg[1];
714 }
715 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof6);
716 }
717
718 // Public note
719 if (getDolGlobalString('MAIN_PUBLIC_NOTE_IN_ADDRESS')) {
720 if ($mode == 'source' && !empty($sourcecompany->note_public)) {
721 $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($sourcecompany->note_public);
722 }
723 if (($mode == 'target' || preg_match('/targetwithdetails/', $mode)) && !empty($targetcompany->note_public)) {
724 $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($targetcompany->note_public);
725 }
726 }
727 }
728 }
729
730 return $stringaddress;
731}
732
733
742function pdf_pagehead(&$pdf, $outputlangs, $page_height)
743{
744 global $conf;
745
746 // Add a background image on document only if good setup of const
747 if (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF') && (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF') != '-1')) { // Warning, this option make TCPDF generation being crazy and some content disappeared behind the image
748 $filepath = $conf->mycompany->dir_output.'/logos/' . getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF');
749 if (file_exists($filepath)) {
750 $pdf->setAutoPageBreak(false, 0); // Disable auto pagebreak before adding image
751 if (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF_ALPHA')) {
752 $pdf->SetAlpha(getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_ALPHA'));
753 } // Option for change opacity of background
754 $pdf->Image($filepath, getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_X'), getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_Y'), 0, $page_height);
755 if (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF_ALPHA')) {
756 $pdf->SetAlpha(1);
757 }
758 $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
759 $pdf->setAutoPageBreak(true, 0); // Restore pagebreak
760 }
761 }
762 if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND') && getDolGlobalString('MAIN_ADD_PDF_BACKGROUND') != '-1') {
763 $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
764 }
765}
766
767
780function pdfWriteBlockedLogSignature(&$pdf, $outputlangs, $page_height, $object, &$w, &$posx, &$posy)
781{
782 global $db;
783
784 // Transaction ID
785 include_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
786
787 if (isALNERunningVersion() && isModEnabled('blockedlog')) {
788 if ($object->status > $object::STATUS_DRAFT) {
789 $unalterablelogid = 'UNDEFINED';
790 $sql = "SELECT signature FROM ".MAIN_DB_PREFIX."blockedlog";
791 $sql .= " WHERE action = 'BILL_VALIDATE' AND element = 'facture' AND ref_object = '".$db->escape($object->ref)."'";
792 $sql .= $db->order('rowid', 'DESC');
793 $sql .= $db->plimit(1);
794
795 $resql = $db->query($sql);
796 if ($resql) {
797 $obj = $db->fetch_object($resql);
798 if ($obj) {
799 $unalterablelogid = $obj->signature;
800 }
801 }
802
803 if ($unalterablelogid != 'UNDEFINED') {
804 $posy += 5;
805 $pdf->SetXY($posx, $posy);
806 $pdf->SetTextColor(0, 0, 60);
807 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("SignatureID")." : ".dol_trunc(strtoupper($unalterablelogid), 10), '', 'R');
808 }
809 }
810 }
811}
812
813
824function pdf_getSubstitutionArray($outputlangs, $exclude = null, $object = null, $onlykey = 0, $include = null)
825{
826 $substitutionarray = getCommonSubstitutionArray($outputlangs, $onlykey, $exclude, $object, $include);
827 $substitutionarray['__FROM_NAME__'] = '__FROM_NAME__';
828 $substitutionarray['__FROM_EMAIL__'] = '__FROM_EMAIL__';
829 return $substitutionarray;
830}
831
832
844function pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
845{
846 // Print Draft Watermark
847 if ($unit == 'pt') {
848 $k = 1;
849 } elseif ($unit == 'mm') {
850 $k = 72 / 25.4;
851 } elseif ($unit == 'cm') {
852 $k = 72 / 2.54;
853 } elseif ($unit == 'in') {
854 $k = 72;
855 } else {
856 $k = 1;
857 dol_print_error(null, 'Unexpected unit "'.$unit.'" for pdf_watermark');
858 }
859
860 // Make substitution
861 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, null);
862 complete_substitutions_array($substitutionarray, $outputlangs, null);
863 $text = make_substitutions($text, $substitutionarray, $outputlangs);
864 $text = $outputlangs->convToOutputCharset($text);
865
866 $savx = $pdf->getX();
867 $savy = $pdf->getY();
868
869 $watermark_angle = atan($h / $w) / 2;
870 $watermark_x_pos = 0;
871 $watermark_y_pos = $h / 3;
872 $watermark_x = $w / 2;
873 $watermark_y = $h / 3;
874 $pdf->SetFont('', 'B', 40);
875 $pdf->SetTextColor(255, 0, 0);
876
877 // rotate
878 $pdf->_out(sprintf('q %.5F %.5F %.5F %.5F %.2F %.2F cm 1 0 0 1 %.2F %.2F cm', cos($watermark_angle), sin($watermark_angle), -sin($watermark_angle), cos($watermark_angle), $watermark_x * $k, ($h - $watermark_y) * $k, -$watermark_x * $k, -($h - $watermark_y) * $k));
879 // print watermark
880 $pdf->SetAlpha(0.5);
881 $pdf->SetXY($watermark_x_pos, $watermark_y_pos);
882
883 // set alpha to semi-transparency
884 $pdf->SetAlpha(0.3);
885 $pdf->Cell($w - 20, 25, $outputlangs->convToOutputCharset($text), "", 2, "C", false);
886
887 // antirotate
888 $pdf->_out('Q');
889
890 $pdf->SetXY($savx, $savy);
891
892 // Restore alpha
893 $pdf->SetAlpha(1);
894}
895
896
908function pdfCertifMention(&$pdf, $outputlangs, $seller, $default_font_size, &$posy, $pdftemplate)
909{
910 include_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
911
912 return pdfCertifMentionblockedLog($pdf, $outputlangs, $seller, $default_font_size, $posy, $pdftemplate);
913}
914
915
928function pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber = 0, $default_font_size = 10)
929{
930 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbank.class.php';
931
932 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
933 $diffsizecontent = getDolGlobalInt('PDF_DIFFSIZE_CONTENT', 4);
934 $pdf->SetXY($curx, $cury);
935
936 if (empty($onlynumber)) {
937 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
938 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByTransferOnThisBankAccount').':', 0, 'L', false);
939 $cury += 4;
940 }
941
942 $outputlangs->load("banks");
943
944 // Use correct name of bank id according to country
945 $bickey = "BICNumber";
946 if ($account->getCountryCode() == 'IN') {
947 $bickey = "SWIFT";
948 }
949
950 // Get format of bank account according to its country
951 $usedetailedbban = $account->useDetailedBBAN();
952
953 //$onlynumber=0; $usedetailedbban=1; // For tests
954 if ($usedetailedbban) {
955 $savcurx = $curx;
956
957 if (empty($onlynumber)) {
958 $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
959 $pdf->SetXY($curx, $cury);
960 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', false);
961 $cury += 3;
962 }
963
964 if (!getDolGlobalString('PDF_BANK_HIDE_NUMBER_SHOW_ONLY_BICIBAN')) { // Note that some countries still need bank number, BIC/IBAN not enough for them
965 // Note:
966 // bank = code_banque (FR), sort code (GB, IR. Example: 12-34-56)
967 // desk = code guichet (FR), used only when $usedetailedbban = 1
968 // number = account number
969 // key = check control key used only when $usedetailedbban = 1
970 if (empty($onlynumber)) {
971 $pdf->line($curx + 1, $cury + 1, $curx + 1, $cury + 6);
972 }
973
974 $bank_number_length = 0;
975 foreach ($account->getFieldsToShow() as $val) {
976 $pdf->SetXY($curx, $cury + 4);
977 $pdf->SetFont('', '', $default_font_size - 3);
978
979 if ($val == 'BankCode') {
980 // Bank code
981 $tmplength = 18;
982 $content = $account->code_banque;
983 } elseif ($val == 'DeskCode') {
984 // Desk
985 $tmplength = 18;
986 $content = $account->code_guichet;
987 } elseif ($val == 'BankAccountNumber') {
988 // Number
989 $tmplength = 24;
990 $content = $account->number;
991 } elseif ($val == 'BankAccountNumberKey') {
992 // Key
993 $tmplength = 15;
994 $content = $account->cle_rib;
995 } elseif ($val == 'IBAN' || $val == 'BIC') {
996 // Key
997 $tmplength = 0;
998 $content = '';
999 } else {
1000 dol_print_error($account->db, 'Unexpected value for getFieldsToShow: '.$val);
1001 break;
1002 }
1003
1004 if ($content == '') {
1005 continue;
1006 }
1007
1008 $pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($content), 0, 'C', false);
1009 $pdf->SetXY($curx, $cury + 1);
1010 $curx += $tmplength;
1011 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
1012 $pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities($val), 0, 'C', false);
1013 if (empty($onlynumber)) {
1014 $pdf->line($curx, $cury + 1, $curx, $cury + 7);
1015 }
1016
1017 // Only set this variable when table was printed
1018 $bank_number_length = 8;
1019 }
1020
1021 $curx = $savcurx;
1022 $cury += $bank_number_length;
1023 }
1024 } elseif (!empty($account->number)) {
1025 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
1026 $pdf->SetXY($curx, $cury);
1027 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', false);
1028 $cury += 3;
1029
1030 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
1031 $pdf->SetXY($curx, $cury);
1032 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("BankAccountNumber").': '.$outputlangs->convToOutputCharset($account->number), 0, 'L', false);
1033 $cury += 3;
1034
1035 if ($diffsizecontent <= 2) {
1036 $cury += 1;
1037 }
1038 }
1039
1040 $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
1041
1042 if (empty($onlynumber) && !empty($account->address)) {
1043 $pdf->SetXY($curx, $cury);
1044 $val = $outputlangs->transnoentities("Residence").': '.$outputlangs->convToOutputCharset($account->address);
1045 $pdf->MultiCell(100, 3, $val, 0, 'L', false);
1046 //$nboflines=dol_nboflines_bis($val,120);
1047 //$cury+=($nboflines*3)+2;
1048 $tmpy = $pdf->getStringHeight(100, $val);
1049 $cury += $tmpy;
1050 }
1051
1052 if (!empty($account->owner_name)) {
1053 $pdf->SetXY($curx, $cury);
1054 $val = $outputlangs->transnoentities("BankAccountOwner").': '.$outputlangs->convToOutputCharset($account->owner_name);
1055 $pdf->MultiCell(100, 3, $val, 0, 'L', false);
1056 $tmpy = $pdf->getStringHeight(100, $val);
1057 $cury += $tmpy;
1058 } elseif (!$usedetailedbban) {
1059 $cury += 1;
1060 }
1061
1062 // Use correct name of bank id according to country
1063 $ibankey = FormBank::getIBANLabel($account);
1064
1065 if (!empty($account->iban)) {
1066 //Remove whitespaces to ensure we are dealing with the format we expect
1067 $ibanDisplay_temp = str_replace(' ', '', $outputlangs->convToOutputCharset($account->iban));
1068 $ibanDisplay = "";
1069
1070 $nbIbanDisplay_temp = dol_strlen($ibanDisplay_temp);
1071 for ($i = 0; $i < $nbIbanDisplay_temp; $i++) {
1072 $ibanDisplay .= $ibanDisplay_temp[$i];
1073 if ($i % 4 == 3 && $i > 0) {
1074 $ibanDisplay .= " ";
1075 }
1076 }
1077
1078 $pdf->SetFont('', 'B', $default_font_size - 3);
1079 $pdf->SetXY($curx, $cury);
1080 $pdf->MultiCell(100, 3, $outputlangs->transnoentities($ibankey).': '.$ibanDisplay, 0, 'L', false);
1081 $cury += 3;
1082 }
1083
1084 if (!empty($account->bic)) {
1085 $pdf->SetFont('', 'B', $default_font_size - 3);
1086 $pdf->SetXY($curx, $cury);
1087 $pdf->MultiCell(100, 3, $outputlangs->transnoentities($bickey).': '.$outputlangs->convToOutputCharset($account->bic), 0, 'L', false);
1088 }
1089
1090 return $pdf->getY();
1091}
1092
1110function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails = 0, $hidefreetext = 0, $page_largeur = 0, $watermark = '')
1111{
1112 global $conf, $hookmanager;
1113
1114 $outputlangs->load("dict");
1115 $line = '';
1116 $reg = array();
1117 $marginwithfooter = 0; // Return value
1118
1119 $dims = $pdf->getPageDimensions();
1120
1121 // Line of free text
1122 if (empty($hidefreetext) && getDolGlobalString($paramfreetext)) {
1123 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
1124 // More substitution keys
1125 if (is_object($fromcompany)) {
1126 $substitutionarray['__FROM_NAME__'] = $fromcompany->name;
1127 $substitutionarray['__FROM_EMAIL__'] = $fromcompany->email;
1128 }
1129 complete_substitutions_array($substitutionarray, $outputlangs, $object);
1130 $newfreetext = make_substitutions(getDolGlobalString($paramfreetext), $substitutionarray, $outputlangs);
1131
1132 // Make a change into HTML code to allow to include images from medias directory.
1133 // <img alt="" src="/dolibarr_dev/htdocs/viewimage.php?modulepart=medias&amp;entity=1&amp;file=image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1134 // become
1135 // <img alt="" src="'.DOL_DATA_ROOT.'/medias/image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1136 $newfreetext = preg_replace('/(<img.*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)("[^\/]*\/>)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $newfreetext);
1137
1138 $line .= $outputlangs->convToOutputCharset($newfreetext);
1139 }
1140
1141 // First line of company infos
1142 $line1 = "";
1143 $line2 = "";
1144 $line3 = "";
1145 $line4 = "";
1146
1147 if (is_object($fromcompany) && in_array($showdetails, array(1, 3))) {
1148 // Company name
1149 if ($fromcompany->name) {
1150 $line1 .= ($line1 ? " - " : "").$outputlangs->transnoentities("RegisteredOffice").": ".$fromcompany->name;
1151 }
1152 // Address
1153 if ($fromcompany->address) {
1154 $line1 .= ($line1 ? " - " : "").str_replace("\n", ", ", $fromcompany->address);
1155 }
1156 // Zip code
1157 if ($fromcompany->zip) {
1158 $line1 .= ($line1 ? " - " : "").$fromcompany->zip;
1159 }
1160 // Town
1161 if ($fromcompany->town) {
1162 $line1 .= ($line1 ? " " : "").$fromcompany->town;
1163 }
1164 // Country
1165 if ($fromcompany->country) {
1166 $line1 .= ($line1 ? ", " : "").$fromcompany->country;
1167 }
1168 // Phone
1169 if ($fromcompany->phone) {
1170 $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Phone").": ".$fromcompany->phone;
1171 }
1172 // Fax
1173 if ($fromcompany->fax) {
1174 $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Fax").": ".$fromcompany->fax;
1175 }
1176
1177 // URL
1178 if ($fromcompany->url) {
1179 $line2 .= ($line2 ? " - " : "").$fromcompany->url;
1180 }
1181 // Email
1182 if ($fromcompany->email) {
1183 $line2 .= ($line2 ? " - " : "").$fromcompany->email;
1184 }
1185 }
1186 if ($showdetails == 2 || $showdetails == 3 || (!empty($fromcompany->country_code) && $fromcompany->country_code == 'DE')) {
1187 // Managers
1188 if ($fromcompany->managers) {
1189 $line2 .= ($line2 ? " - " : "").$fromcompany->managers;
1190 }
1191 }
1192
1193 // Line 3 of company infos
1194 // Juridical status
1195 if (!empty($fromcompany->forme_juridique_code)) {
1196 $line3 .= ($line3 ? " - " : "").$outputlangs->convToOutputCharset(getFormeJuridiqueLabel((string) $fromcompany->forme_juridique_code));
1197 }
1198 // Capital
1199 if (!empty($fromcompany->capital)) {
1200 $tmpamounttoshow = price2num($fromcompany->capital); // This field is a free string or a float
1201 if (is_numeric($tmpamounttoshow) && $tmpamounttoshow > 0) {
1202 $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", price($tmpamounttoshow, 0, $outputlangs, 0, 0, 0, getDolCurrency()));
1203 } elseif (!empty($fromcompany->capital)) {
1204 $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", (string) $fromcompany->capital);
1205 }
1206 }
1207 // Prof Id 1
1208 if (!empty($fromcompany->idprof1) && ($fromcompany->country_code != 'FR' || (empty($fromcompany->idprof2) || strpos($fromcompany->idprof2, $fromcompany->idprof1) !== 0))) {
1209 $field = $outputlangs->transcountrynoentities("ProfId1", $fromcompany->country_code);
1210 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1211 $field = $reg[1];
1212 }
1213 $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof1);
1214 }
1215 // Prof Id 2
1216 if (!empty($fromcompany->idprof2)) {
1217 $field = $outputlangs->transcountrynoentities("ProfId2", $fromcompany->country_code);
1218 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1219 $field = $reg[1];
1220 }
1221 $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof2);
1222 }
1223
1224 // Line 4 of company infos
1225 // Prof Id 3
1226 if (!empty($fromcompany->idprof3)) {
1227 $field = $outputlangs->transcountrynoentities("ProfId3", $fromcompany->country_code);
1228 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1229 $field = $reg[1];
1230 }
1231 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof3);
1232 }
1233 // Prof Id 4
1234 if (!empty($fromcompany->idprof4)) {
1235 $field = $outputlangs->transcountrynoentities("ProfId4", $fromcompany->country_code);
1236 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1237 $field = $reg[1];
1238 }
1239 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof4);
1240 }
1241 // Prof Id 5
1242 if (!empty($fromcompany->idprof5)) {
1243 $field = $outputlangs->transcountrynoentities("ProfId5", $fromcompany->country_code);
1244 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1245 $field = $reg[1];
1246 }
1247 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof5);
1248 }
1249 // Prof Id 6
1250 if (!empty($fromcompany->idprof6)) {
1251 $field = $outputlangs->transcountrynoentities("ProfId6", $fromcompany->country_code);
1252 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1253 $field = $reg[1];
1254 }
1255 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof6);
1256 }
1257 // Prof Id 7
1258 if (!empty($fromcompany->idprof7)) {
1259 $field = $outputlangs->transcountrynoentities("ProfId7", $fromcompany->country_code);
1260 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1261 $field = $reg[1];
1262 }
1263 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof7);
1264 }
1265 // Prof Id 8
1266 if (!empty($fromcompany->idprof8)) {
1267 $field = $outputlangs->transcountrynoentities("ProfId8", $fromcompany->country_code);
1268 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1269 $field = $reg[1];
1270 }
1271 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof8);
1272 }
1273 // Prof Id 9
1274 if (!empty($fromcompany->idprof9)) {
1275 $field = $outputlangs->transcountrynoentities("ProfId9", $fromcompany->country_code);
1276 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1277 $field = $reg[1];
1278 }
1279 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof9);
1280 }
1281 // Prof Id 10
1282 if (!empty($fromcompany->idprof10)) {
1283 $field = $outputlangs->transcountrynoentities("ProfId10", $fromcompany->country_code);
1284 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1285 $field = $reg[1];
1286 }
1287 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof10);
1288 }
1289 // IntraCommunautary VAT
1290 if (!empty($fromcompany->tva_intra) && $fromcompany->tva_intra != '') {
1291 $line4 .= ($line4 ? " - " : "").$outputlangs->transnoentities("VATIntraShort").": ".$outputlangs->convToOutputCharset($fromcompany->tva_intra);
1292 }
1293
1294 $pdf->SetFont('', '', 7);
1295 $pdf->SetDrawColor(224, 224, 224);
1296 // Option for footer text color
1297 if (getDolGlobalString('PDF_FOOTER_TEXT_COLOR')) {
1298 $tmparray = sscanf(getDolGlobalString('PDF_FOOTER_TEXT_COLOR'), '%d, %d, %d');
1299 $r = $tmparray[0];
1300 $g = $tmparray[1];
1301 $b = $tmparray[2];
1302 $pdf->SetTextColor($r, $g, $b);
1303 }
1304
1305 // The start of the bottom of this page footer is positioned according to # of lines
1306 $freetextheight = 0;
1307 $align = '';
1308 if ($line) { // Free text
1309 //$line="sample text<br>\nfd<strong>sf</strong>sdf<br>\nghfghg<br>";
1310 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) {
1311 $width = 20000;
1312 $align = 'L'; // By default, ask a manual break: We use a large value 20000, to not have automatic wrap. This make user understand, he need to add CR on its text.
1313 if (getDolGlobalString('MAIN_USE_AUTOWRAP_ON_FREETEXT')) {
1314 $width = 200;
1315 $align = 'C';
1316 }
1317 $freetextheight = $pdf->getStringHeight($width, $line);
1318 } else {
1319 $freetextheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($line, 1, 'UTF-8', 0)); // New method (works for HTML content)
1320 //print '<br>'.$freetextheight;
1321 }
1322 }
1323
1324 $posy = 0;
1325 // For customized footer
1326 if (is_object($hookmanager)) {
1327 $parameters = array('line1' => $line1, 'line2' => $line2, 'line3' => $line3, 'line4' => $line4, 'outputlangs' => $outputlangs);
1328 $action = '';
1329 $hookmanager->executeHooks('pdf_pagefoot', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1330 if (!empty($hookmanager->resPrint) && $hidefreetext == 0) {
1331 $mycustomfooter = $hookmanager->resPrint;
1332 $mycustomfooterheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1333
1334 $marginwithfooter = $marge_basse + $freetextheight + $mycustomfooterheight;
1335 $posy = (float) $marginwithfooter;
1336
1337 // Option for footer background color (without freetext zone)
1338 if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1339 $tmparray = sscanf(getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR'), '%d, %d, %d');
1340 $r = $tmparray[0];
1341 $g = $tmparray[1];
1342 $b = $tmparray[2];
1343 $pdf->setAutoPageBreak(false, 0); // Disable auto pagebreak
1344 $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', array(), $fill_color = array($r, $g, $b));
1345 $pdf->setAutoPageBreak(true, 0); // Restore pagebreak
1346 }
1347
1348 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1349 $pdf->setAutoPageBreak(false, 0);
1350 } // Option for disable auto pagebreak
1351 if ($line) { // Free text
1352 $pdf->SetXY($dims['lm'], -$posy);
1353 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1354 $pdf->MultiCell(0, 3, $line, 0, $align, false);
1355 } else {
1356 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1357 }
1358 $posy -= $freetextheight;
1359 }
1360 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1361 $pdf->setAutoPageBreak(true, 0);
1362 } // Restore pagebreak
1363
1364 $pdf->SetY(-$posy);
1365
1366 // Hide footer line if footer background color is set
1367 if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1368 $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1369 }
1370
1371 // Option for set top margin height of footer after freetext
1372 if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1373 $posy -= (float) getDolGlobalString('PDF_FOOTER_TOP_MARGIN');
1374 } else {
1375 $posy--;
1376 }
1377
1378 if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) {
1379 $pdf->setAutoPageBreak(false, 0);
1380 } // Option for disable auto pagebreak
1381 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $mycustomfooterheight, $dims['lm'], $dims['hk'] - $posy, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1382 if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) {
1383 $pdf->setAutoPageBreak(true, 0);
1384 } // Restore pagebreak
1385
1386 $posy -= $mycustomfooterheight - 3;
1387 } else {
1388 // Else default footer
1389 $marginwithfooter = $marge_basse + $freetextheight + (!empty($line1) ? 3 : 0) + (!empty($line2) ? 3 : 0) + (!empty($line3) ? 3 : 0) + (!empty($line4) ? 3 : 0);
1390 $posy = (float) $marginwithfooter;
1391
1392 // Option for footer background color (without freetext zone)
1393 if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1394 $tmparray = sscanf(getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR'), '%d, %d, %d');
1395 $r = $tmparray[0];
1396 $g = $tmparray[1];
1397 $b = $tmparray[2];
1398 $pdf->setAutoPageBreak(false, 0); // Disable auto pagebreak
1399 $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', array(), $fill_color = array($r, $g, $b));
1400 $pdf->setAutoPageBreak(true, 0); // Restore pagebreak
1401 }
1402
1403 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1404 $pdf->setAutoPageBreak(false, 0);
1405 } // Option for disable auto pagebreak
1406 if ($line) { // Free text
1407 $pdf->SetXY($dims['lm'], -$posy);
1408 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1409 $pdf->MultiCell(0, 3, $line, 0, $align, false);
1410 } else {
1411 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1412 }
1413 $posy -= $freetextheight;
1414 }
1415 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1416 $pdf->setAutoPageBreak(true, 0);
1417 } // Restore pagebreak
1418
1419 $pdf->SetY(-$posy);
1420
1421 // Option for hide all footer (page number will no hidden)
1422 if (!getDolGlobalInt('PDF_FOOTER_HIDDEN')) {
1423 // Hide footer line if footer background color is set
1424 if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1425 $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1426 }
1427
1428 // Option for set top margin height of footer after freetext
1429 if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1430 $posy -= (float) getDolGlobalString('PDF_FOOTER_TOP_MARGIN');
1431 } else {
1432 $posy--;
1433 }
1434
1435 if (!empty($line1)) {
1436 $pdf->SetFont('', 'B', 7);
1437 $pdf->SetXY($dims['lm'], -$posy);
1438 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line1, 0, 'C', false);
1439 $posy -= 3;
1440 $pdf->SetFont('', '', 7);
1441 }
1442
1443 if (!empty($line2)) {
1444 $pdf->SetFont('', 'B', 7);
1445 $pdf->SetXY($dims['lm'], -$posy);
1446 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line2, 0, 'C', false);
1447 $posy -= 3;
1448 $pdf->SetFont('', '', 7);
1449 }
1450
1451 if (!empty($line3)) {
1452 $pdf->SetXY($dims['lm'], -$posy);
1453 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line3, 0, 'C', false);
1454 }
1455
1456 if (!empty($line4)) {
1457 $posy -= 3;
1458 $pdf->SetXY($dims['lm'], -$posy);
1459 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line4, 0, 'C', false);
1460 }
1461 }
1462 }
1463 }
1464
1465 // Show page nb and apply correction for some font.
1466 $pdf->SetXY($dims['wk'] - $dims['rm'] - 18 - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_X', 0), -$posy - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_Y', 0));
1467
1468 $pagination = $pdf->PageNo().' / '.$pdf->getAliasNbPages();
1469 $fontRenderCorrection = 0;
1470 if (in_array(pdf_getPDFFont($outputlangs), array('freemono', 'DejaVuSans'))) {
1471 $fontRenderCorrection = 10;
1472 }
1473 $pdf->MultiCell(18 + $fontRenderCorrection, 2, $pagination, 0, 'R', false);
1474
1475 // Show Draft Watermark
1476 if (!empty($watermark)) {
1477 pdf_watermark($pdf, $outputlangs, $page_hauteur, $page_largeur, 'mm', $watermark);
1478 }
1479
1480 return $marginwithfooter;
1481}
1482
1497function pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
1498{
1499 $linkedobjects = pdf_getLinkedObjects($object, $outputlangs); // May update $object->note_public
1500
1501 if (!empty($linkedobjects)) {
1502 foreach ($linkedobjects as $linkedobject) {
1503 $reftoshow = $linkedobject["ref_title"].' : '.$linkedobject["ref_value"];
1504 if (!empty($linkedobject["date_value"])) {
1505 $reftoshow .= ' / '.$linkedobject["date_value"];
1506 }
1507
1508 $posy += 3;
1509 $pdf->SetXY($posx, $posy);
1510 $pdf->SetFont('', '', (float) $default_font_size - 2);
1511 $pdf->MultiCell($w, $h, $reftoshow, '', $align);
1512 }
1513 }
1514
1515 return $pdf->getY();
1516}
1517
1535function pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref = 0, $hidedesc = 0, $issupplierline = 0, $align = 'J')
1536{
1537 global $hookmanager;
1538
1539 $reshook = 0;
1540 $result = '';
1541 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
1542 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
1543 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1544 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1545 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1546 }
1547 $parameters = array('pdf' => $pdf, 'i' => $i, 'outputlangs' => $outputlangs, 'w' => $w, 'h' => $h, 'posx' => $posx, 'posy' => $posy, 'hideref' => $hideref, 'hidedesc' => $hidedesc, 'issupplierline' => $issupplierline, 'special_code' => $special_code);
1548 $action = '';
1549 // WARNING: A hook must not close/open the PDF transaction. Doing this generates a lot of trouble.
1550 // Test to know if content added by the hooks is already done by the main caller of pdf_writelinedesc
1551 $reshook = $hookmanager->executeHooks('pdf_writelinedesc', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1552
1553 if (!empty($hookmanager->resPrint)) {
1554 $result .= $hookmanager->resPrint;
1555 }
1556 }
1557 if (empty($reshook)) {
1558 $labelproductservice = pdf_getlinedesc($object, $i, $outputlangs, $hideref, $hidedesc, $issupplierline);
1559 $labelproductservice = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $labelproductservice, -1, $nbrep);
1560
1561 //var_dump($labelproductservice);exit;
1562
1563 // Fix bug of some HTML editors that replace links <img src="http://localhostgit/viewimage.php?modulepart=medias&file=image/efd.png" into <img src="http://localhostgit/viewimage.php?modulepart=medias&amp;file=image/efd.png"
1564 // We make the reverse, so PDF generation has the real URL.
1565 $nbrep = 0;
1566 $labelproductservice = preg_replace('/(<img[^>]*src=")([^"]*)(&amp;)([^"]*")/', '\1\2&\4', $labelproductservice, -1, $nbrep);
1567
1568 if (getDolGlobalString('MARGIN_TOP_ZERO_UL')) {
1569 $pdf->setListIndentWidth(5);
1570 $TMarginList = ['ul' => [['h' => 0.1, ],['h' => 0.1, ]], 'li' => [['h' => 0.1, ],],];
1571 $pdf->setHtmlVSpace($TMarginList);
1572 }
1573
1574 // Description
1575 $pdf->writeHTMLCell($w, $h, $posx, $posy, $outputlangs->convToOutputCharset($labelproductservice), 0, 1, false, true, $align, true);
1576 $result .= $labelproductservice;
1577 }
1578 return $result;
1579}
1580
1592function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
1593{
1594 global $db, $conf, $langs;
1595
1596 $idprod = (!empty($object->lines[$i]->fk_product) ? $object->lines[$i]->fk_product : false);
1597 $label = (!empty($object->lines[$i]->label) ? $object->lines[$i]->label : (!empty($object->lines[$i]->product_label) ? $object->lines[$i]->product_label : ''));
1598 $product_barcode = (!empty($object->lines[$i]->product_barcode) ? $object->lines[$i]->product_barcode : "");
1599 $desc = (!empty($object->lines[$i]->desc) ? $object->lines[$i]->desc : (!empty($object->lines[$i]->description) ? $object->lines[$i]->description : ''));
1600 $ref_supplier = (!empty($object->lines[$i]->ref_supplier) ? $object->lines[$i]->ref_supplier : (!empty($object->lines[$i]->ref_fourn) ? $object->lines[$i]->ref_fourn : '')); // TODO Not yet saved for supplier invoices, only supplier orders
1601 $note = (!empty($object->lines[$i]->note) ? $object->lines[$i]->note : '');
1602 $dbatch = (!empty($object->lines[$i]->detail_batch) ? $object->lines[$i]->detail_batch : false);
1603
1604 $multilangsactive = getDolGlobalInt('MAIN_MULTILANGS');
1605
1606 if ($issupplierline) {
1607 include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
1608 $prodser = new ProductFournisseur($db);
1609 } else {
1610 include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
1611 $prodser = new Product($db);
1612
1613 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1614 include_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
1615 }
1616 }
1617
1618 //id
1619 $idprod = (!empty($object->lines[$i]->fk_product) ? $object->lines[$i]->fk_product : false);
1620 if ($idprod) {
1621 $prodser->fetch($idprod);
1622 //load multilangs
1623 if ($multilangsactive) {
1624 $prodser->getMultiLangs();
1625 $object->lines[$i]->multilangs = $prodser->multilangs;
1626 }
1627 }
1628 //label
1629 if (!empty($object->lines[$i]->label)) {
1630 $label = $object->lines[$i]->label;
1631 } else {
1632 if (!empty($object->lines[$i]->multilangs[$outputlangs->defaultlang]['label']) && $multilangsactive) {
1633 $label = $object->lines[$i]->multilangs[$outputlangs->defaultlang]['label'];
1634 } else {
1635 if (!empty($object->lines[$i]->product_label)) {
1636 $label = $object->lines[$i]->product_label;
1637 } else {
1638 $label = '';
1639 }
1640 }
1641 }
1642 //description
1643 if (!empty($object->lines[$i]->desc)) {
1644 $desc = $object->lines[$i]->desc;
1645 } else {
1646 if (!empty($object->lines[$i]->multilangs[$outputlangs->defaultlang]['description']) && $multilangsactive) {
1647 $desc = $object->lines[$i]->multilangs[$outputlangs->defaultlang]['description'];
1648 } else {
1649 if (!empty($object->lines[$i]->description)) {
1650 $desc = $object->lines[$i]->description;
1651 } else {
1652 $desc = '';
1653 }
1654 }
1655 }
1656 //ref supplier
1657 $ref_supplier = (!empty($object->lines[$i]->ref_supplier) ? $object->lines[$i]->ref_supplier : (!empty($object->lines[$i]->ref_fourn) ? $object->lines[$i]->ref_fourn : '')); // TODO Not yet saved for supplier invoices, only supplier orders
1658 //note
1659 $note = (!empty($object->lines[$i]->note) ? $object->lines[$i]->note : '');
1660 //dbatch
1661 $dbatch = (!empty($object->lines[$i]->detail_batch) ? $object->lines[$i]->detail_batch : false);
1662
1663 if ($idprod) {
1664 // If a predefined product and multilang and on other lang, we renamed label with label translated
1665 if ($multilangsactive && ($outputlangs->defaultlang != $langs->defaultlang)) {
1666 $translatealsoifmodified = getDolGlobalString('MAIN_MULTILANG_TRANSLATE_EVEN_IF_MODIFIED'); // By default if value was modified manually, we keep it (no translation because we don't have it)
1667
1668 // TODO Instead of making a compare to see if param was modified, check that content contains reference translation. If yes, add the added part to the new translation
1669 // ($textwasnotmodified is replaced with $textwasmodifiedorcompleted and we add completion).
1670
1671 // Set label
1672 // If we want another language, and if label is same than default language (we did not force it to a specific value), we can use translation.
1673 //var_dump($outputlangs->defaultlang.' - '.$langs->defaultlang.' - '.$label.' - '.$prodser->label);exit;
1674 $textwasnotmodified = ($label == $prodser->label);
1675 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1676 $label = $prodser->multilangs[$outputlangs->defaultlang]["label"];
1677 }
1678
1679 // Set desc
1680 // Manage HTML entities description test because $prodser->description is store with htmlentities but $desc no
1681 $textwasnotmodified = false;
1682 if (!empty($desc) && dol_textishtml($desc) && !empty($prodser->description) && dol_textishtml($prodser->description)) {
1683 $textwasnotmodified = (strpos(dol_html_entity_decode($desc, ENT_QUOTES | ENT_HTML5), dol_html_entity_decode($prodser->description, ENT_QUOTES | ENT_HTML5)) !== false);
1684 } else {
1685 $textwasnotmodified = ($desc == $prodser->description);
1686 }
1687 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["description"])) {
1688 if ($textwasnotmodified) {
1689 $desc = str_replace($prodser->description, $prodser->multilangs[$outputlangs->defaultlang]["description"], $desc);
1690 } elseif ($translatealsoifmodified) {
1691 $desc = $prodser->multilangs[$outputlangs->defaultlang]["description"];
1692 }
1693 }
1694
1695 // Set note
1696 $textwasnotmodified = ($note == $prodser->note_public);
1697 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["other"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1698 $note = $prodser->multilangs[$outputlangs->defaultlang]["other"];
1699 }
1700 }
1701 } elseif (($object->element == 'facture' || $object->element == 'facturefourn') && preg_match('/^\‍(DEPOSIT\‍).+/', $desc)) { // We must not replace '(DEPOSIT)' when it is alone, it will be translated and detailed later
1702 $desc = str_replace('(DEPOSIT)', $outputlangs->trans('Deposit'), $desc);
1703 }
1704
1705 $libelleproduitservice = ''; // Default value
1706 if (!getDolGlobalString('PDF_HIDE_PRODUCT_LABEL_IN_SUPPLIER_LINES')) {
1707 // Description short of product line
1708 $libelleproduitservice = $label;
1709 if (!empty($libelleproduitservice) && getDolGlobalString('PDF_BOLD_PRODUCT_LABEL')) {
1710 // Adding <b> may convert the original string into a HTML string. So we have to first
1711 // convert \n into <br> we text is not already HTML.
1712 if (!dol_textishtml($libelleproduitservice)) {
1713 $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1714 }
1715 $libelleproduitservice = '<b>'.$libelleproduitservice.'</b>';
1716 }
1717 }
1718
1719
1720 // Add ref of subproducts
1721 if (getDolGlobalString('SHOW_SUBPRODUCT_REF_IN_PDF')) {
1722 $prodser->get_sousproduits_arbo();
1723 if (!empty($prodser->sousprods) && is_array($prodser->sousprods) && count($prodser->sousprods)) {
1724 $outputlangs->load('mrp');
1725 $tmparrayofsubproducts = reset($prodser->sousprods);
1726
1727 $qtyText = null;
1728 if (isset($object->lines[$i]->qty) && !empty($object->lines[$i]->qty)) {
1729 $qtyText = $object->lines[$i]->qty;
1730 } elseif (isset($object->lines[$i]->qty_shipped) && !empty($object->lines[$i]->qty_shipped)) {
1731 $qtyText = $object->lines[$i]->qty;
1732 }
1733
1734 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF')) {
1735 foreach ($tmparrayofsubproducts as $subprodval) {
1736 $libelleproduitservice = dol_concatdesc(
1737 dol_concatdesc($libelleproduitservice, " * ".$subprodval[3]),
1738 (!empty($qtyText) ?
1739 $outputlangs->trans('Qty').':'.$qtyText.' x '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1].'= '.$outputlangs->trans('QtyTot').':'.$subprodval[1] * $qtyText :
1740 $outputlangs->trans('Qty').' '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1])
1741 );
1742 }
1743 } else {
1744 foreach ($tmparrayofsubproducts as $subprodval) {
1745 $libelleproduitservice = dol_concatdesc(
1746 dol_concatdesc($libelleproduitservice, " * ".$subprodval[5].(($subprodval[5] && $subprodval[3]) ? ' - ' : '').$subprodval[3]),
1747 (!empty($qtyText) ?
1748 $outputlangs->trans('Qty').':'.$qtyText.' x '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1].'= '.$outputlangs->trans('QtyTot').':'.$subprodval[1] * $qtyText :
1749 $outputlangs->trans('Qty').' '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1])
1750 );
1751 }
1752 }
1753 }
1754 }
1755
1756 if (isModEnabled('barcode') && getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_PRODUCT_BARCODE') && !empty($product_barcode)) {
1757 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $outputlangs->trans("BarCode")." ".$product_barcode);
1758 }
1759
1760 // Description long of product line
1761 if (!empty($desc) && ($desc != $label)) {
1762 if ($desc == '(CREDIT_NOTE)' && $object->lines[$i]->fk_remise_except) {
1763 $discount = new DiscountAbsolute($db);
1764 $discount->fetch($object->lines[$i]->fk_remise_except);
1765 $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1766 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromCreditNote", $sourceref);
1767 } elseif ($desc == '(DEPOSIT)' && $object->lines[$i]->fk_remise_except) {
1768 $discount = new DiscountAbsolute($db);
1769 $discount->fetch($object->lines[$i]->fk_remise_except);
1770 $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1771 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromDeposit", $sourceref);
1772 // Add date of deposit
1773 if (getDolGlobalString('INVOICE_ADD_DEPOSIT_DATE')) {
1774 $libelleproduitservice .= ' ('.dol_print_date($discount->datec, 'day', '', $outputlangs).')';
1775 }
1776 } elseif ($desc == '(EXCESS RECEIVED)' && $object->lines[$i]->fk_remise_except) {
1777 $discount = new DiscountAbsolute($db);
1778 $discount->fetch($object->lines[$i]->fk_remise_except);
1779 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessReceived", $discount->ref_facture_source);
1780 } elseif ($desc == '(EXCESS PAID)' && $object->lines[$i]->fk_remise_except) {
1781 $discount = new DiscountAbsolute($db);
1782 $discount->fetch($object->lines[$i]->fk_remise_except);
1783 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessPaid", $discount->ref_invoice_supplier_source);
1784 } else {
1785 if ($idprod) {
1786 // Check if description must be output
1787 if (!empty($object->element)) {
1788 $tmpkey = 'MAIN_DOCUMENTS_HIDE_DESCRIPTION_FOR_'.strtoupper($object->element);
1789 if (getDolGlobalString($tmpkey)) {
1790 $hidedesc = 1;
1791 }
1792 }
1793 if (empty($hidedesc)) {
1794 if (getDolGlobalString('MAIN_DOCUMENTS_DESCRIPTION_FIRST')) {
1795 $libelleproduitservice = dol_concatdesc($desc, $libelleproduitservice);
1796 } else {
1797 if (getDolGlobalString('HIDE_LABEL_VARIANT_PDF') && $prodser->isVariant()) {
1798 $libelleproduitservice = $desc;
1799 } else {
1800 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1801 }
1802 }
1803 }
1804 } else {
1805 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1806 }
1807 }
1808 }
1809
1810 // We add ref of product (and supplier ref if defined)
1811 $prefix_prodserv = "";
1812 $ref_prodserv = "";
1813 if (getDolGlobalString('PRODUCT_ADD_TYPE_IN_DOCUMENTS')) { // In standard mode, we do not show this
1814 if ($prodser->isService()) {
1815 $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service")." ";
1816 } else {
1817 $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Product")." ";
1818 }
1819 }
1820
1821 if (empty($hideref)) {
1822 if ($issupplierline) {
1823 if (!getDolGlobalString('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES')) { // Common case
1824 $ref_prodserv = $prodser->ref; // Show local ref
1825 if ($ref_supplier) {
1826 $ref_prodserv .= ($prodser->ref ? ' (' : '').$outputlangs->transnoentitiesnoconv("SupplierRef").' '.$ref_supplier.($prodser->ref ? ')' : '');
1827 }
1828 } elseif (getDolGlobalInt('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES') == 1) {
1829 $ref_prodserv = $ref_supplier;
1830 } elseif (getDolGlobalInt('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES') == 2) {
1831 $ref_prodserv = $ref_supplier.' ('.$outputlangs->transnoentitiesnoconv("InternalRef").' '.$prodser->ref.')';
1832 }
1833 } else {
1834 $ref_prodserv = $prodser->ref; // Show local ref only
1835
1836 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1837 $productCustomerPriceStatic = new ProductCustomerPrice($db);
1838 $filter = array('fk_product' => (string) $idprod, 'fk_soc' => (string) $object->socid);
1839
1840 $nbCustomerPrices = $productCustomerPriceStatic->fetchAll('', '', 1, 0, $filter);
1841
1842 if ($nbCustomerPrices > 0) {
1843 $productCustomerPrice = null;
1844 if (count($productCustomerPriceStatic->lines) > 0) {
1845 $date_now = (int) floor(dol_now() / 86400) * 86400; // date without hours
1846 foreach ($productCustomerPriceStatic->lines as $k => $custprice_line) {
1847 if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
1848 $productCustomerPrice = $custprice_line;
1849 break;
1850 }
1851 }
1852 }
1853
1854 if (isset($productCustomerPrice) && !empty($productCustomerPrice->ref_customer)) {
1855 $idcustprice = getDolGlobalInt('PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE');
1856 switch ($idcustprice) {
1857 case 1:
1858 $ref_prodserv = $productCustomerPrice->ref_customer;
1859 break;
1860
1861 case 2:
1862 $ref_prodserv = $productCustomerPrice->ref_customer . ' (' . $outputlangs->transnoentitiesnoconv('InternalRef') . ' ' . $ref_prodserv . ')';
1863 break;
1864
1865 default:
1866 $ref_prodserv = $ref_prodserv . ' (' . $outputlangs->transnoentitiesnoconv('RefCustomer') . ' ' . $productCustomerPrice->ref_customer . ')';
1867 }
1868 }
1869 }
1870 }
1871 }
1872
1873 if (!empty($libelleproduitservice) && !empty($ref_prodserv)) {
1874 $ref_prodserv .= " - ";
1875 }
1876 }
1877
1878 if (!empty($ref_prodserv) && getDolGlobalString('PDF_BOLD_PRODUCT_REF_AND_PERIOD')) {
1879 if (!dol_textishtml($libelleproduitservice)) {
1880 $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1881 }
1882 $ref_prodserv = '<b>'.$ref_prodserv.'</b>';
1883 // $prefix_prodserv and $ref_prodser are not HTML var
1884 }
1885 $libelleproduitservice = $prefix_prodserv.$ref_prodserv.$libelleproduitservice;
1886
1887 // Add an additional description for the category products
1888 if (getDolGlobalString('CATEGORY_ADD_DESC_INTO_DOC') && $idprod && isModEnabled('category')) {
1889 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1890 $categstatic = new Categorie($db);
1891 // recovering the list of all the categories linked to product
1892 $tblcateg = $categstatic->containing($idprod, Categorie::TYPE_PRODUCT);
1893 foreach ($tblcateg as $cate) {
1894 // Adding the descriptions if they are filled
1895 $desccateg = $cate->description;
1896 if ($desccateg) {
1897 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desccateg);
1898 }
1899 }
1900 }
1901
1902 if (!empty($object->lines[$i]->date_start) || !empty($object->lines[$i]->date_end)) {
1903 $format = 'day';
1904 $period = '';
1905 // Show duration if exists
1906 if ($object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1907 $period = '('.$outputlangs->transnoentitiesnoconv('DateFromTo', dol_print_date($object->lines[$i]->date_start, $format, false, $outputlangs), dol_print_date($object->lines[$i]->date_end, $format, false, $outputlangs)).')';
1908 }
1909 if ($object->lines[$i]->date_start && !$object->lines[$i]->date_end) {
1910 $period = '('.$outputlangs->transnoentitiesnoconv('DateFrom', dol_print_date($object->lines[$i]->date_start, $format, false, $outputlangs)).')';
1911 }
1912 if (!$object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1913 $period = '('.$outputlangs->transnoentitiesnoconv('DateUntil', dol_print_date($object->lines[$i]->date_end, $format, false, $outputlangs)).')';
1914 }
1915 //print '>'.$outputlangs->charset_output.','.$period;
1916 if (getDolGlobalString('PDF_BOLD_PRODUCT_REF_AND_PERIOD')) {
1917 if (!dol_textishtml($libelleproduitservice)) {
1918 $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1919 }
1920 $libelleproduitservice .= '<br><b style="color:#333666;" ><em>'.$period.'</em></b>';
1921 } else {
1922 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $period);
1923 }
1924 //print $libelleproduitservice;
1925 }
1926
1927 // Show information for lot
1928 if (!empty($dbatch)) {
1929 // $object is a shipment.
1930 //var_dump($object->lines[$i]->details_entrepot); // array from llx_expeditiondet (we can have several lines for one fk_origin_line)
1931 //var_dump($object->lines[$i]->detail_batch); // array from llx_expeditiondet_batch (each line with a lot is linked to llx_expeditiondet)
1932
1933 include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
1934 include_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
1935 $tmpwarehouse = new Entrepot($db);
1936 $tmpproductbatch = new Productbatch($db);
1937
1938 $format = 'day';
1939 foreach ($dbatch as $detail) {
1940 $dte = array();
1941 if ($detail->eatby) {
1942 $dte[] = $outputlangs->transnoentitiesnoconv('printEatby', dol_print_date($detail->eatby, $format, false, $outputlangs));
1943 }
1944 if ($detail->sellby) {
1945 $dte[] = $outputlangs->transnoentitiesnoconv('printSellby', dol_print_date($detail->sellby, $format, false, $outputlangs));
1946 }
1947 if ($detail->batch) {
1948 $dte[] = $outputlangs->transnoentitiesnoconv('printBatch', $detail->batch);
1949 }
1950 if ($detail->qty) {
1951 $dte[] = $outputlangs->transnoentitiesnoconv('printQty', (string) $detail->qty);
1952 }
1953
1954 // Add also info of planned warehouse for lot
1955 if ($object->element == 'shipping' && $detail->fk_origin_stock > 0 && getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1956 $resproductbatch = $tmpproductbatch->fetch($detail->fk_origin_stock);
1957 if ($resproductbatch > 0) {
1958 $reswarehouse = $tmpwarehouse->fetch($tmpproductbatch->warehouseid);
1959 if ($reswarehouse > 0) {
1960 $dte[] = $tmpwarehouse->ref;
1961 }
1962 }
1963 }
1964
1965 $libelleproduitservice .= "__N__ ".implode(" - ", $dte);
1966 }
1967 } else {
1968 if (getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1969 // TODO Show warehouse for shipment line without batch
1970 }
1971 }
1972
1973 // Now we convert \n into br
1974 if (dol_textishtml($libelleproduitservice)) {
1975 $libelleproduitservice = preg_replace('/__N__/', '<br>', $libelleproduitservice);
1976 } else {
1977 $libelleproduitservice = preg_replace('/__N__/', "\n", $libelleproduitservice);
1978 }
1979 $libelleproduitservice = dol_htmlentitiesbr($libelleproduitservice, 1);
1980
1981 return $libelleproduitservice;
1982}
1983
1993function pdf_getlinenum($object, $i, $outputlangs, $hidedetails = 0)
1994{
1995 global $hookmanager;
1996
1997 $reshook = 0;
1998 $result = '';
1999 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2000 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2001 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2002 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2003 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2004 }
2005 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2006 $action = '';
2007 $reshook = $hookmanager->executeHooks('pdf_getlinenum', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2008 $result .= $hookmanager->resPrint;
2009 }
2010 if (empty($reshook)) {
2011 $result .= dol_htmlentitiesbr($object->lines[$i]->num);
2012 }
2013 return $result;
2014}
2015
2016
2026function pdf_getlineref($object, $i, $outputlangs, $hidedetails = 0)
2027{
2028 global $hookmanager;
2029
2030 $reshook = 0;
2031 $result = '';
2032 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2033 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2034 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2035 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2036 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2037 }
2038 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2039 $action = '';
2040 $reshook = $hookmanager->executeHooks('pdf_getlineref', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2041 $result .= $hookmanager->resPrint;
2042 }
2043 if (empty($reshook)) {
2044 $result .= dol_htmlentitiesbr($object->lines[$i]->product_ref);
2045 }
2046 return $result;
2047}
2048
2049
2059function pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails = 0)
2060{
2061 global $hookmanager;
2062
2063 $reshook = 0;
2064 $result = '';
2065 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2066 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2067 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2068 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2069 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2070 }
2071 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2072 $action = '';
2073 $reshook = $hookmanager->executeHooks('pdf_getlineref_supplier', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2074 $result .= $hookmanager->resPrint;
2075 }
2076 if (empty($reshook)) {
2077 $result .= dol_htmlentitiesbr($object->lines[$i]->ref_supplier);
2078 }
2079 return $result;
2080}
2081
2091function pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails = 0)
2092{
2093 global $conf, $hookmanager, $mysoc;
2094
2095 $result = '';
2096 $reshook = 0;
2097 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2098 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2099 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2100 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2101 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2102 }
2103 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2104 $action = '';
2105 $reshook = $hookmanager->executeHooks('pdf_getlinevatrate', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2106
2107 if (!empty($hookmanager->resPrint)) {
2108 $result .= $hookmanager->resPrint;
2109 }
2110 }
2111 if (empty($reshook)) {
2112 if (empty($hidedetails) || $hidedetails > 1) {
2113 $tmpresult = '';
2114
2115 $tmpresult .= vatrate($object->lines[$i]->tva_tx, false, $object->lines[$i]->info_bits, -1);
2116 if (!getDolGlobalString('MAIN_PDF_MAIN_HIDE_SECOND_TAX')) {
2117 if (price2num($object->lines[$i]->localtax1_tx)) {
2118 if (preg_replace('/[\s0%]/', '', $tmpresult)) {
2119 $tmpresult .= '/';
2120 } else {
2121 $tmpresult = '';
2122 }
2123 $tmpresult .= vatrate((string) abs($object->lines[$i]->localtax1_tx), false);
2124 }
2125 }
2126 if (!getDolGlobalString('MAIN_PDF_MAIN_HIDE_THIRD_TAX')) {
2127 if (price2num($object->lines[$i]->localtax2_tx)) {
2128 if (preg_replace('/[\s0%]/', '', $tmpresult)) {
2129 $tmpresult .= '/';
2130 } else {
2131 $tmpresult = '';
2132 }
2133 $tmpresult .= vatrate((string) abs($object->lines[$i]->localtax2_tx), false);
2134 }
2135 }
2136 $tmpresult .= '%';
2137
2138 $result .= $tmpresult;
2139 }
2140 }
2141 return $result;
2142}
2143
2153function pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails = 0)
2154{
2155 global $hookmanager;
2156
2157 $sign = 1;
2158 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2159 $sign = -1;
2160 }
2161
2162 $result = '';
2163 $reshook = 0;
2164 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2165 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2166 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2167 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2168 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2169 }
2170 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2171 $action = '';
2172 $reshook = $hookmanager->executeHooks('pdf_getlineupexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2173
2174 if (!empty($hookmanager->resPrint)) {
2175 $result .= $hookmanager->resPrint;
2176 }
2177 }
2178 if (empty($reshook)) {
2179 if (empty($hidedetails) || $hidedetails > 1) {
2180 $subprice = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice);
2181 $result .= price($sign * $subprice, 0, $outputlangs);
2182 }
2183 }
2184 return $result;
2185}
2186
2196function pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails = 0)
2197{
2198 global $hookmanager;
2199
2200 $sign = 1;
2201 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2202 $sign = -1;
2203 }
2204
2205 $result = '';
2206 $reshook = 0;
2207 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2208 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2209 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2210 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2211 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2212 }
2213 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2214 $action = '';
2215 $reshook = $hookmanager->executeHooks('pdf_getlineupwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2216
2217 if (!empty($hookmanager->resPrint)) {
2218 $result .= $hookmanager->resPrint;
2219 }
2220 }
2221 if (empty($reshook)) {
2222 if (empty($hidedetails) || $hidedetails > 1) {
2223 $result .= price($sign * (($object->lines[$i]->subprice) + ($object->lines[$i]->subprice) * ($object->lines[$i]->tva_tx) / 100), 0, $outputlangs);
2224 }
2225 }
2226 return $result;
2227}
2228
2238function pdf_getlineqty($object, $i, $outputlangs, $hidedetails = 0)
2239{
2240 global $hookmanager;
2241
2242 $result = '';
2243 $reshook = 0;
2244 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2245 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2246 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2247 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2248 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2249 }
2250 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2251 $action = '';
2252 $reshook = $hookmanager->executeHooks('pdf_getlineqty', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2253
2254 if (!empty($hookmanager->resPrint)) {
2255 $result = $hookmanager->resPrint;
2256 }
2257 }
2258 if (empty($reshook)) {
2259 if ($object->lines[$i]->special_code == 3) {
2260 return '';
2261 }
2262 if (empty($hidedetails) || $hidedetails > 1) {
2263 $result .= $object->lines[$i]->qty;
2264 }
2265 }
2266 return $result;
2267}
2268
2278function pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails = 0)
2279{
2280 global $hookmanager;
2281
2282 $reshook = 0;
2283 $result = '';
2284 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2285 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2286 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2287 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2288 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2289 }
2290 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2291 $action = '';
2292 $reshook = $hookmanager->executeHooks('pdf_getlineqty_asked', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2293
2294 if (!empty($hookmanager->resPrint)) {
2295 $result .= $hookmanager->resPrint;
2296 }
2297 }
2298 if (empty($reshook)) {
2299 if ($object->lines[$i]->special_code == 3) {
2300 return '';
2301 }
2302 if (empty($hidedetails) || $hidedetails > 1) {
2303 $result .= $object->lines[$i]->qty_asked;
2304 }
2305 }
2306 return $result;
2307}
2308
2318function pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails = 0)
2319{
2320 global $hookmanager;
2321
2322 $reshook = 0;
2323 $result = '';
2324 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2325 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2326 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2327 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2328 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2329 }
2330 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2331 $action = '';
2332 $reshook = $hookmanager->executeHooks('pdf_getlineqty_shipped', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2333
2334 if (!empty($hookmanager->resPrint)) {
2335 $result .= $hookmanager->resPrint;
2336 }
2337 }
2338 if (empty($reshook)) {
2339 if ($object->lines[$i]->special_code == 3) {
2340 return '';
2341 }
2342 if (empty($hidedetails) || $hidedetails > 1) {
2343 $result .= $object->lines[$i]->qty_shipped;
2344 }
2345 }
2346 return $result;
2347}
2348
2358function pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails = 0)
2359{
2360 global $hookmanager;
2361
2362 $reshook = 0;
2363 $result = '';
2364 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2365 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2366 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2367 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) { // @phan-suppress-current-line PhanUndeclaredProperty
2368 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2369 }
2370 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2371 $action = '';
2372 $reshook = $hookmanager->executeHooks('pdf_getlineqty_keeptoship', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2373
2374 if (!empty($hookmanager->resPrint)) {
2375 $result .= $hookmanager->resPrint;
2376 }
2377 }
2378 if (empty($reshook)) {
2379 if ($object->lines[$i]->special_code == 3) {
2380 return '';
2381 }
2382 if (empty($hidedetails) || $hidedetails > 1) {
2383 $result .= ($object->lines[$i]->qty_asked - $object->lines[$i]->qty_shipped);
2384 }
2385 }
2386 return $result;
2387}
2388
2398function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0)
2399{
2400 global $hookmanager;
2401
2402 $reshook = 0;
2403 $result = '';
2404 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2405 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2406 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2407 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2408 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2409 }
2410 $parameters = array(
2411 'i' => $i,
2412 'outputlangs' => $outputlangs,
2413 'hidedetails' => $hidedetails,
2414 'special_code' => $special_code
2415 );
2416 $action = '';
2417 $reshook = $hookmanager->executeHooks('pdf_getlineunit', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2418
2419 if (!empty($hookmanager->resPrint)) {
2420 $result .= $hookmanager->resPrint;
2421 }
2422 }
2423 if (empty($reshook)) {
2424 if (empty($hidedetails) || $hidedetails > 1) {
2425 $result .= $object->lines[$i]->getLabelOfUnit('short', $outputlangs, 1);
2426 }
2427 }
2428 return $result;
2429}
2430
2431
2441function pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails = 0)
2442{
2443 global $hookmanager;
2444
2445 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
2446
2447 $reshook = 0;
2448 $result = '';
2449 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2450 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2451 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2452 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2453 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2454 }
2455 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2456 $action = '';
2457 $reshook = $hookmanager->executeHooks('pdf_getlineremisepercent', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2458
2459 if (!empty($hookmanager->resPrint)) {
2460 $result .= $hookmanager->resPrint;
2461 }
2462 }
2463 if (empty($reshook)) {
2464 if ($object->lines[$i]->special_code == 3) {
2465 return '';
2466 }
2467 if (empty($hidedetails) || $hidedetails > 1) {
2468 $result .= dol_print_reduction($object->lines[$i]->remise_percent, $outputlangs);
2469 }
2470 }
2471 return $result;
2472}
2473
2484function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = null)
2485{
2486 if (empty($hookmanager)) {
2487 global $hookmanager;
2488 }
2489
2490 $reshook = 0;
2491 $result = '';
2492 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2493 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2494 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2495 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2496 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2497 }
2498 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2499 $action = '';
2500 $reshook = $hookmanager->executeHooks('pdf_getlineprogress', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2501
2502 if (!empty($hookmanager->resPrint)) {
2503 return $hookmanager->resPrint;
2504 }
2505 }
2506 if (empty($reshook)) {
2507 if ($object->lines[$i]->special_code == 3) {
2508 return '';
2509 }
2510 if (empty($hidedetails) || $hidedetails > 1) {
2511 // 2 = situation_percent is non-cumulative (delta of current situation)
2512 // 1 = (old mode): situation_percent is cumulative (state at situation)
2513 $isCumulative = getDolGlobalInt('INVOICE_USE_SITUATION') === 1;
2514 $showDelta = (bool) getDolGlobalInt('SITUATION_DISPLAY_DIFF_ON_PDF');
2515
2516 if ($isCumulative xor $showDelta) {
2517 // Either:
2518 // - old mode and we want to show a total or
2519 // - new mode and we want to show a delta
2520 $result = $object->lines[$i]->situation_percent;
2521 } else {
2522 // Either:
2523 // - old mode but we want to show a delta or
2524 // - new mode but we want to show a total
2525 $prev_progress = 0;
2526 if (method_exists($object->lines[$i], 'get_prev_progress')) {
2527 $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2528 }
2529 $result = $isCumulative ?
2530 // old mode: we need to compute the delta (total - sum of previous)
2531 $object->lines[$i]->situation_percent - $prev_progress :
2532 // new mode: we need to compute the total (sum of previous + delta)
2533 $prev_progress + $object->lines[$i]->situation_percent;
2534 }
2535 $result = round($result, 1).'%';
2536 }
2537 }
2538 return $result;
2539}
2540
2550function pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails = 0)
2551{
2552 global $hookmanager;
2553
2554 $sign = 1;
2555 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2556 $sign = -1;
2557 }
2558
2559 $reshook = 0;
2560 $result = '';
2561 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2562 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2563 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2564 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2565 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2566 }
2567 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code, 'sign' => $sign);
2568 $action = '';
2569 $reshook = $hookmanager->executeHooks('pdf_getlinetotalexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2570
2571 if (!empty($hookmanager->resPrint)) {
2572 $result .= $hookmanager->resPrint;
2573 }
2574 }
2575 if (empty($reshook)) {
2576 if (!empty($object->lines[$i]) && $object->lines[$i]->special_code == 3) {
2577 $result .= $outputlangs->transnoentities("Option");
2578 } elseif (empty($hidedetails) || $hidedetails > 1) {
2579 $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
2580 if (!empty($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
2581 if (method_exists($object->lines[$i], 'getSituationRatio')) {
2582 $total_ht *= $object->lines[$i]->getSituationRatio();
2583 }
2584 }
2585 $result .= price($sign * $total_ht, 0, $outputlangs);
2586 }
2587 }
2588 return $result;
2589}
2590
2600function pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails = 0)
2601{
2602 global $hookmanager;
2603
2604 $sign = 1;
2605 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2606 $sign = -1;
2607 }
2608
2609 $reshook = 0;
2610 $result = '';
2611 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2612 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2613 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2614 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2615 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2616 }
2617 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2618 $action = '';
2619 $reshook = $hookmanager->executeHooks('pdf_getlinetotalwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2620
2621 if (!empty($hookmanager->resPrint)) {
2622 $result .= $hookmanager->resPrint;
2623 }
2624 }
2625 if (empty($reshook)) {
2626 if ($object->lines[$i]->special_code == 3) {
2627 $result .= $outputlangs->transnoentities("Option");
2628 } elseif (empty($hidedetails) || $hidedetails > 1) {
2629 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ttc : $object->lines[$i]->total_ttc);
2630 if (isset($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
2631 $total_ttc *= $object->lines[$i]->getSituationRatio();
2632 }
2633 $result .= price($sign * $total_ttc, 0, $outputlangs);
2634 }
2635 }
2636 return $result;
2637}
2638
2649function canDisplayLinkedObjectInPDF($object, $elementobject)
2650{
2651 $objectSocId = getObjectSocId($object);
2652 $elementSocId = getObjectSocId($elementobject);
2653
2654 if (getDolGlobalBool("PDF_ALLOW_DISPLAY_LINKED_OBJECT_FOR_OTHER_SOC")) {
2655 return true;
2656 }
2657
2658 if (!empty($objectSocId) && !empty($elementSocId) && $objectSocId != $elementSocId) {
2659 return false;
2660 }
2661
2662 return true;
2663}
2664
2673function pdf_getLinkedObjects(&$object, $outputlangs)
2674{
2675 global $db, $hookmanager;
2676
2677 $linkedobjects = array();
2678
2679 $object->fetchObjectLinked();
2680
2681 foreach ($object->linkedObjects as $objecttype => $objects) {
2682 if ($objecttype == 'facture') {
2683 // For invoice, we don't want to have a reference line on document. Image we are using recurring invoice, we will have a line longer than document width.
2684 } elseif ($objecttype == 'propal' || $objecttype == 'supplier_proposal') {
2685 '@phan-var-force array<Propal|SupplierProposal> $objects';
2687 $outputlangs->load('propal');
2688
2689 foreach ($objects as $elementobject) {
2690 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefProposal");
2691 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2692 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DatePropal");
2693 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2694 }
2695 } elseif ($objecttype == 'commande' || $objecttype == 'supplier_order' || $objecttype == 'order_supplier') {
2696 $optiontohidelinkedorders = "PDF_HIDE_LINKED_ORDERS_ON_SAME_THIRDPARTY";
2697 if ($objecttype == 'supplier_order' || $objecttype == 'order_supplier') {
2698 $optiontohidelinkedorders = "PDF_HIDE_LINKED_PURCHASE_ORDERS_ON_SAME_THIRDPARTY";
2699 }
2700 '@phan-var-force array<Commande|CommandeFournisseur> $objects';
2701 $outputlangs->load('orders');
2702
2703 if (count($objects) > 1 && count($objects) <= getDolGlobalInt("MAXREFONDOC", 10) && !getDolGlobalString($optiontohidelinkedorders)) {
2704 if (empty($object->context['DolPublicNoteAppendedGetLinkedObjects'])) { // Check if already appended before add to avoid repeat data
2705 $outputList = '';
2706 foreach ($objects as $elementobject) {
2707 if (canDisplayLinkedObjectInPDF($object, $elementobject)) {
2708 $outputList = dol_concatdesc($outputList, $outputlangs->transnoentities($elementobject->ref) . (empty($elementobject->ref_client) ? '' : ' (' . $elementobject->ref_client . ')') . (empty($elementobject->ref_supplier) ? '' : ' (' . $elementobject->ref_supplier . ')') . ' ');
2709 $outputList = dol_concatdesc($outputList, $outputlangs->transnoentities("OrderDate") . ' : ' . dol_print_date($elementobject->date, 'day', '', $outputlangs));
2710 }
2711 }
2712
2713 if (!empty($outputList)) {
2714 $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("RefOrder").' :');
2715 $object->note_public = dol_concatdesc($object->note_public, $outputList);
2716 }
2717 }
2718 } elseif (count($objects) == 1 && !getDolGlobalString($optiontohidelinkedorders)) {
2719 $elementobject = array_shift($objects);
2720 if (canDisplayLinkedObjectInPDF($object, $elementobject)) {
2721 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder");
2722 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref).(!empty($elementobject->ref_client) ? ' ('.$elementobject->ref_client.')' : '').(!empty($elementobject->ref_supplier) ? ' ('.$elementobject->ref_supplier.')' : '');
2723 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("OrderDate");
2724 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2725 }
2726 }
2727 } elseif ($objecttype == 'contrat') {
2728 '@phan-var-force Contrat[] $objects';
2729 $outputlangs->load('contracts');
2730 foreach ($objects as $elementobject) {
2731 if (canDisplayLinkedObjectInPDF($object, $elementobject)) {
2732 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefContract");
2733 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2734 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DateContract");
2735 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date_contrat, 'day', '', $outputlangs);
2736 }
2737 }
2738 } elseif ($objecttype == 'fichinter') {
2739 '@phan-var-force Fichinter[] $objects';
2740 $outputlangs->load('interventions');
2741 foreach ($objects as $elementobject) {
2742 if (canDisplayLinkedObjectInPDF($object, $elementobject)) {
2743 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("InterRef");
2744 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2745 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("InterDate");
2746 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->datec, 'day', '', $outputlangs);
2747 }
2748 }
2749 } elseif ($objecttype == 'shipping') {
2750 '@phan-var-force Expedition[] $objects';
2751 $outputlangs->loadLangs(array("orders", "sendings"));
2752
2753 if (count($objects) > 1) {
2754 $order = null;
2755
2756 $refListsTxt = '';
2757 if (empty($object->linkedObjects['commande']) && $object->element != 'commande') {
2758 $refListsTxt .= $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending").' :';
2759 } else {
2760 $refListsTxt .= $outputlangs->transnoentities("RefSending").' :';
2761 }
2762 // We concat this record info into fields xxx_value. title is overwrote.
2763 foreach ($objects as $elementobject) {
2764 if (empty($object->linkedObjects['commande']) && $object->element != 'commande') { // There is not already a link to order and object is not the order, so we show also info with order
2765 $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2766 if (!empty($elementobject->linkedObjectsIds['commande'])) {
2767 include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2768 $order = new Commande($db);
2769 $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2770 if ($ret < 1) {
2771 $order = null;
2772 }
2773 }
2774 }
2775 $refListsTxt .= (!empty($refListsTxt) ? ' ' : '');
2776 if (! is_object($order)) {
2777 $refListsTxt .= $outputlangs->transnoentities($elementobject->ref);
2778 } else {
2779 $refListsTxt .= $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
2780 $refListsTxt .= ' / '.$outputlangs->transnoentities($elementobject->ref);
2781 }
2782 }
2783
2784 if (empty($object->context['DolPublicNoteAppendedGetLinkedObjects']) && !getDolGlobalString("PDF_HIDE_LINKED_OBJECT_IN_PUBLIC_NOTE")) { // Check if already appended before add to avoid repeat data
2785 $object->note_public = dol_concatdesc($object->note_public, $refListsTxt);
2786 }
2787 } elseif (count($objects) == 1) {
2788 $elementobject = array_shift($objects);
2789 $order = null;
2790 // We concat this record info into fields xxx_value. title is overwrote.
2791 if (empty($object->linkedObjects['commande']) && $object->element != 'commande') { // There is not already a link to order and object is not the order, so we show also info with order
2792 $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2793 if (!empty($elementobject->linkedObjectsIds['commande'])) {
2794 include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2795 $order = new Commande($db);
2796 $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2797 if ($ret < 1) {
2798 $order = null;
2799 }
2800 }
2801 }
2802
2803 if (! is_object($order)) {
2804 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefSending");
2805 if (empty($linkedobjects[$objecttype]['ref_value'])) {
2806 $linkedobjects[$objecttype]['ref_value'] = '';
2807 } else {
2808 $linkedobjects[$objecttype]['ref_value'] .= ' / ';
2809 }
2810 $linkedobjects[$objecttype]['ref_value'] .= $outputlangs->transnoentities($elementobject->ref);
2811 $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
2812 } else {
2813 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending");
2814 if (empty($linkedobjects[$objecttype]['ref_value'])) {
2815 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
2816 }
2817 $linkedobjects[$objecttype]['ref_value'] .= ' / '.$outputlangs->transnoentities($elementobject->ref);
2818 $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
2819 }
2820 }
2821 }
2822 }
2823
2824 $object->context['DolPublicNoteAppendedGetLinkedObjects'] = 1;
2825
2826 // For add external linked objects
2827 if (is_object($hookmanager)) {
2828 $parameters = array('linkedobjects' => $linkedobjects, 'outputlangs' => $outputlangs);
2829 $action = '';
2830 $reshook = $hookmanager->executeHooks('pdf_getLinkedObjects', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2831 if (empty($reshook)) {
2832 $linkedobjects = array_replace($linkedobjects, $hookmanager->resArray); // array_replace is used to preserve keys
2833 } elseif ($reshook > 0) {
2834 // The array must be reinserted even if it is empty because clearing the array could be one of the actions performed by the hook.
2835 $linkedobjects = $hookmanager->resArray;
2836 }
2837 }
2838
2839 return $linkedobjects;
2840}
2841
2849function pdf_getSizeForImage($realpath)
2850{
2851 $maxwidth = getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20);
2852 $maxheight = getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT', 32);
2853
2854 include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
2855 $tmp = dol_getImageSize($realpath);
2856 $width = 0;
2857 $height = 0;
2858 if ($tmp['height']) {
2859 $width = (int) round($maxheight * $tmp['width'] / $tmp['height']); // I try to use maxheight
2860 if ($width > $maxwidth) { // Pb with maxheight, so i use maxwidth
2861 $width = $maxwidth;
2862 $height = (int) round($maxwidth * $tmp['height'] / $tmp['width']);
2863 } else { // No pb with maxheight
2864 $height = $maxheight;
2865 }
2866 }
2867 return array('width' => $width, 'height' => $height);
2868}
2869
2881function pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails = 0, $multicurrency = 0)
2882{
2883 global $hookmanager;
2884
2885 $sign = 1;
2886 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2887 $sign = -1;
2888 }
2889 if ($object->lines[$i]->special_code == 3) {
2890 // If option
2891 return $outputlangs->transnoentities("Option");
2892 } else {
2893 if (is_object($hookmanager)) {
2894 $special_code = $object->lines[$i]->special_code;
2895 if (!empty($object->lines[$i]->fk_parent_line)) {
2896 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2897 }
2898
2899 $parameters = array(
2900 'i' => $i,
2901 'outputlangs' => $outputlangs,
2902 'hidedetails' => $hidedetails,
2903 'special_code' => $special_code,
2904 'multicurrency' => $multicurrency
2905 );
2906
2907 $action = '';
2908
2909 if ($hookmanager->executeHooks('getlinetotalremise', $parameters, $object, $action) > 0) { // Note that $action and $object may have been modified by some hooks
2910 if (isset($hookmanager->resArray['linetotalremise'])) {
2911 return (float) $hookmanager->resArray['linetotalremise'];
2912 } else {
2913 return (float) $hookmanager->resPrint; // For backward compatibility
2914 }
2915 }
2916 }
2917
2918 if (empty($hidedetails) || $hidedetails > 1) {
2919 if (empty($multicurrency)) {
2920 return (float) price2num($sign * (($object->lines[$i]->subprice * (float) $object->lines[$i]->qty) - $object->lines[$i]->total_ht), 'MT', 1);
2921 } else {
2922 return (float) price2num($sign * (($object->lines[$i]->multicurrency_subprice * (float) $object->lines[$i]->qty) - $object->lines[$i]->multicurrency_total_ht), 'MT', 1);
2923 }
2924 }
2925 }
2926 return 0;
2927}
2928
2936function pdfExtractMetadata($file, $field = 'Keywords')
2937{
2938 if (!dol_is_file($file)) {
2939 return "ERROR: FILE NOT FOUND OR NOT VALID";
2940 }
2941
2942 // Get content of PDF file
2943 $content = file_get_contents(dol_osencode($file));
2944
2945 // Use a regex to capture the metadata
2946 if ($content) {
2947 $matches = array();
2948
2949 // Remove non printablecaracters
2950 $content = preg_replace('/[^(\x20-\x7F)]*/', '', $content);
2951 if (preg_match('/\/' . preg_quote($field, '/') . '\s*\‍((.*?)\‍)/', $content, $matches)) {
2952 return trim($matches[1]);
2953 }
2954 return "ERROR: NOT FOUND";
2955 } else {
2956 return "ERROR: FAILED TO READ PDF";
2957 }
2958}
2959
2978 TCPDF $pdf,
2979 CommonDocGenerator $generator,
2980 float $curY,
2982 int $i,
2983 Translate $outputlangs,
2984 int $hideref,
2985 int $hidedesc,
2986 array $bgColor,
2987 bool $isSubtotal = false,
2988 bool $applySubtotalLogic = true
2989) {
2990 $savePage = $pdf->getPage();
2991 $saveX = $pdf->GetX();
2992 $prevAlign = $generator->cols['desc']['content']['align'];
2993
2994 if ($isSubtotal && $applySubtotalLogic && $object->lines[$i]->qty < 0) {
2995 $outputlangs->load("subtotals");
2996 $object->lines[$i]->desc = $outputlangs->trans("SubtotalOf", $object->lines[$i]->desc);
2997 $generator->cols['desc']['content']['align'] = ($prevAlign === 'L') ? 'R' : 'L';
2998 }
2999
3000 $pdf->startTransaction();
3001 $pdf->SetXY($saveX, $curY);
3002 $generator->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc);
3003 $pageAfter = $pdf->getPage();
3004 $yAfter = $pdf->GetY();
3005 $pdf->rollbackTransaction(true);
3006
3007 $pdf->SetFillColor($bgColor[0], $bgColor[1], $bgColor[2]);
3008 $width = $generator->page_largeur - $generator->marge_droite - $generator->marge_gauche;
3009
3010 $pdf->SetXY($generator->marge_gauche, $curY);
3011 if ($pageAfter === $savePage) {
3012 $pdf->MultiCell($width, max(0, $yAfter - $curY), '', 0, '', true);
3013 } else {
3014 $pdf->MultiCell($width, $pdf->getPageHeight() - $pdf->getBreakMargin() - $curY, '', 0, '', true);
3015
3016 $pdf->setPage($pageAfter);
3017 $pdf->SetXY($generator->marge_gauche, $pdf->getMargins()['top']);
3018 $pdf->MultiCell($width, max(0, $yAfter - $pdf->getMargins()['top']), '', 0, '', true);
3019
3020 $pdf->setPage($savePage);
3021 }
3022
3023 $pdf->SetTextColor(colorIsLight(implode(',', $bgColor)));
3024 $pdf->SetXY($saveX, $curY);
3025 $generator->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc);
3026 $generator->setAfterColsLinePositionsData('desc', $pdf->GetY(), $pdf->getPage());
3027
3028 $generator->cols['desc']['content']['align'] = $prevAlign;
3029}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
pdfCertifMentionblockedLog(&$pdf, $outputlangs, $seller, $default_font_size, &$posy, $pdftemplate)
Add legal mention.
isALNERunningVersion($blockedlogtestalreadydone=0)
Return if the application is executed with the LNE requirements on.
Class to manage categories.
Class to manage customers orders.
Parent class for documents (PDF, ODT, ...) generators.
printColDescContent($pdf, &$curY, $colKey, $object, $i, $outputlangs, $hideref=0, $hidedesc=0, $issupplierline=0)
print description column content
setAfterColsLinePositionsData(string $colId, float $y, int $pageNumb)
Used for to set afterColsLinePositions var in a pdf draw line loop.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Class to manage contact/addresses.
Class to manage absolute discounts.
Class to manage warehouses.
static getIBANLabel(Account $account)
Returns the name of the Iban label.
File of class to manage predefined price products or services by customer.
Class to manage predefined suppliers products.
Class to manage products or services.
Manage record for batch number management.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
getState($id, $withcode='0', $dbtouse=null, $withregion=0, $outputlangs=null, $entconv=1)
Return state translated from an id.
getFormeJuridiqueLabel($code)
Return the name translated of juridical status.
global $mysoc
dol_is_file($pathoffile)
Return if path is a file.
dol_print_reduction($reduction, $langs)
Returns formatted reduction.
dol_getDefaultFormat($outputlangs=null)
Try to guess default paper format according to language into $langs.
dol_html_entity_decode($a, $b, $c='UTF-8', $keepsomeentities=0)
Replace html_entity_decode functions to manage errors.
dol_now($mode='gmt')
Return date for now.
getDolGlobalFloat($key, $default=0)
Return a Dolibarr global constant float value.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
dol_format_address($object, $withcountry=0, $sep="\n", $outputlangs=null, $mode=0, $extralangcode='')
Return a formatted address (part address/zip/town/state) according to country rules.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
getObjectSocId($obj)
Get the socid of an object, supporting legacy attribute names.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
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.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
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...
getDolCurrency()
Return the main currency ('EUR', 'USD', ...)
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_textishtml($msg, $option=0)
Return if a text is a html content.
colorIsLight($stringcolor)
Return true if the color is light.
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).
getDolGlobalBool($key, $default=false)
Return a Dolibarr global constant boolean value.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode='add', $filterorigmodule='')
Complete or removed entries into a head array (used to build tabs).
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.
isModEnabled($module)
Is Dolibarr module enabled.
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)
dol_getImageSize($file, $url=false)
Return size of image file on disk (Supported extensions are gif, jpg, png, bmp and webp)
pdf_getSizeForImage($realpath)
Return dimensions to use for images onto PDF checking that width and height are not higher than maxim...
Definition pdf.lib.php:2849
pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref=0, $hidedesc=0, $issupplierline=0, $align='J')
Output line description into PDF.
Definition pdf.lib.php:1535
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition pdf.lib.php:2550
pdf_getlinedesc($object, $i, $outputlangs, $hideref=0, $hidedesc=0, $issupplierline=0)
Return line description translated in outputlangs and encoded into htmlentities and with
Definition pdf.lib.php:1592
pdf_getFormat($outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition pdf.lib.php:87
pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails=0, $multicurrency=0)
Return line total amount discount.
Definition pdf.lib.php:2881
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:289
pdfExtractMetadata($file, $field='Keywords')
Function to extract metadata from a PDF file by doing a binary parsing of the PDF file.
Definition pdf.lib.php:2936
pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails=0)
Return line quantity shipped.
Definition pdf.lib.php:2318
pdf_getlinenum($object, $i, $outputlangs, $hidedetails=0)
Return line num.
Definition pdf.lib.php:1993
pdf_getEncryption($pathoffile)
Return if pdf file is protected/encrypted.
Definition pdf.lib.php:235
pdfCertifMention(&$pdf, $outputlangs, $seller, $default_font_size, &$posy, $pdftemplate)
Add legal certificate mention.
Definition pdf.lib.php:908
pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price including tax.
Definition pdf.lib.php:2196
pdfWriteBlockedLogSignature(&$pdf, $outputlangs, $page_height, $object, &$w, &$posx, &$posy)
Show header of page for PDF generation.
Definition pdf.lib.php:780
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:312
pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails=0)
Return line ref_supplier.
Definition pdf.lib.php:2059
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition pdf.lib.php:2600
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:1110
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition pdf.lib.php:2153
pdf_getlineprogress($object, $i, $outputlangs, $hidedetails=0, $hookmanager=null)
Return line percent.
Definition pdf.lib.php:2484
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition pdf.lib.php:2091
pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition pdf.lib.php:337
pdf_admin_prepare_head()
Return array head with list of tabs to view object information.
Definition pdf.lib.php:49
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:742
canDisplayLinkedObjectInPDF($object, $elementobject)
Check if a linked object can be displayed based on third-party privacy rules.
Definition pdf.lib.php:2649
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1497
pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank information for PDF generation.
Definition pdf.lib.php:928
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:268
pdf_render_subtotals(TCPDF $pdf, CommonDocGenerator $generator, float $curY, CommonObject $object, int $i, Translate $outputlangs, int $hideref, int $hidedesc, array $bgColor, bool $isSubtotal=false, bool $applySubtotalLogic=true)
Render subtotals line with a colored background and adapted text color .
Definition pdf.lib.php:2977
pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails=0)
Return line keep to ship quantity.
Definition pdf.lib.php:2358
pdf_getlineref($object, $i, $outputlangs, $hidedetails=0)
Return line product ref.
Definition pdf.lib.php:2026
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:433
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition pdf.lib.php:2398
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition pdf.lib.php:2441
pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails=0)
Return line quantity asked.
Definition pdf.lib.php:2278
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition pdf.lib.php:2238
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:824
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:388
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition pdf.lib.php:844