dolibarr 25.0.0-alpha
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-2026 Frédéric France <frederic.france@free.fr>
18 * Copyright (C) 2024-2026 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 // Default: throw exceptions on TCPDF/TCPDI errors instead of die().
166 // A die() in a PDF library produces white pages on web requests and kills
167 // batch jobs on the first bad PDF. Exceptions can be caught and surfaced as
168 // normal Dolibarr errors. Users can opt out by setting
169 // TCPDF_THROW_ERRORS_INSTEAD_OF_DIE = 0 to restore the legacy die() behavior.
170 if (getDolGlobalString('TCPDF_THROW_ERRORS_INSTEAD_OF_DIE', '1')) {
171 define('K_TCPDF_THROW_EXCEPTION_ERROR', true);
172 } else {
173 define('K_TCPDF_THROW_EXCEPTION_ERROR', false);
174 }
175 }
176
177 // Load TCPDF
178 require_once TCPDF_PATH.'tcpdf.php';
179
180 // We need to instantiate tcpdi object (instead of tcpdf) to use merging features. But we can disable it (this will break all merge features).
181 if (!getDolGlobalString('MAIN_DISABLE_TCPDI')) {
182 require_once TCPDI_PATH.'tcpdi.php';
183 }
184
185 //$arrayformat=pdf_getFormat();
186 //$format=array($arrayformat['width'],$arrayformat['height']);
187 //$metric=$arrayformat['unit'];
188
189 //$pdfa = false; // PDF default version
190 $pdfa = getDolGlobalInt('PDF_USE_A', 0); // 0=PDF 1.7, 1=PDF 1.4/A-1b ou 3=PDF 1.7/A-3b
191
192 if (!getDolGlobalString('MAIN_DISABLE_TCPDI') && class_exists('TCPDI')) {
193 $pdf = new TCPDI($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
194 } else {
195 $pdf = new TCPDF($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
196 }
197 // Allow "file://..." image src values (used to embed local server paths translated from a public URL)
198 $pdf->setAllowLocalFiles(true);
199
200 // Protection and encryption of pdf
201 if (getDolGlobalString('PDF_SECURITY_ENCRYPTION')) {
202 /* Permission supported by TCPDF
203 - print : Print the document;
204 - modify : Modify the contents of the document by operations other than those controlled by 'fill-forms', 'extract' and 'assemble';
205 - copy : Copy or otherwise extract text and graphics from the document;
206 - 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);
207 - fill-forms : Fill in existing interactive form fields (including signature fields), even if 'annot-forms' is not specified;
208 - extract : Extract text and graphics (in support of accessibility to users with disabilities or for other purposes);
209 - assemble : Assemble the document (insert, rotate, or delete pages and create bookmarks or thumbnail images), even if 'modify' is not set;
210 - 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.
211 - owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions.
212 */
213
214 // For TCPDF, we specify permission we want to block
215 $pdfrights = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_RIGHTS') ? json_decode(getDolGlobalString('PDF_SECURITY_ENCRYPTION_RIGHTS'), true) : array('modify', 'copy')); // Json format in llx_const
216
217 // Password for the end user
218 $pdfuserpass = getDolGlobalString('PDF_SECURITY_ENCRYPTION_USERPASS');
219
220 // Password of the owner, created randomly if not defined
221 $pdfownerpass = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_OWNERPASS') ? getDolGlobalString('PDF_SECURITY_ENCRYPTION_OWNERPASS') : null);
222
223 // For encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit
224 $encstrength = getDolGlobalInt('PDF_SECURITY_ENCRYPTION_STRENGTH', 0);
225
226 // Array of recipients containing public-key certificates ('c') and permissions ('p').
227 // For example: array(array('c' => 'file://../examples/data/cert/tcpdf.crt', 'p' => array('print')))
228 $pubkeys = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_PUBKEYS') ? json_decode(getDolGlobalString('PDF_SECURITY_ENCRYPTION_PUBKEYS'), true) : null); // Json format in llx_const
229
230 $pdf->SetProtection($pdfrights, $pdfuserpass, $pdfownerpass, $encstrength, $pubkeys);
231 }
232
233 return $pdf;
234}
235
242function pdf_getEncryption($pathoffile)
243{
244 require_once TCPDF_PATH.'tcpdf_parser.php';
245
246 $isencrypted = false;
247
248 $content = file_get_contents($pathoffile);
249
250 //ob_start();
251 @($parser = new TCPDF_PARSER(ltrim($content)));
252 $tmp = $parser->getParsedData();
253 $xref = $tmp[0];
254 $data = $tmp[1] ?? null;
255 unset($parser);
256 //ob_end_clean();
257
258 if (isset($xref['trailer']['encrypt'])) {
259 $isencrypted = true; // Secured pdf file are currently not supported
260 }
261
262 if (empty($data)) {
263 $isencrypted = true; // Object list not found. Possible secured file
264 }
265
266 return $isencrypted;
267}
268
275function pdf_getPDFFont($outputlangs)
276{
277 if (getDolGlobalString('MAIN_PDF_FORCE_FONT')) {
278 return getDolGlobalString('MAIN_PDF_FORCE_FONT');
279 }
280
281 $font = 'Helvetica'; // By default, for FPDI, or ISO language on TCPDF
282 if (class_exists('TCPDF')) { // If TCPDF on, we can use an UTF8 one like DejaVuSans if required (slower)
283 if ($outputlangs->trans('FONTFORPDF') != 'FONTFORPDF') {
284 $font = $outputlangs->trans('FONTFORPDF');
285 }
286 }
287 return $font;
288}
289
296function pdf_getPDFFontSize($outputlangs)
297{
298 $size = 10; // By default, for FPDI or ISO language on TCPDF
299 if (class_exists('TCPDF')) { // If TCPDF on, we can use an UTF8 font like DejaVuSans if required (slower)
300 if ($outputlangs->trans('FONTSIZEFORPDF') != 'FONTSIZEFORPDF') {
301 $size = (int) $outputlangs->trans('FONTSIZEFORPDF');
302 }
303 }
304 if (getDolGlobalString('MAIN_PDF_FORCE_FONT_SIZE')) {
305 $size = getDolGlobalString('MAIN_PDF_FORCE_FONT_SIZE');
306 }
307
308 return $size;
309}
310
311
319function pdf_getHeightForLogo($logo, $url = false)
320{
321 $height = getDolGlobalFloat('MAIN_DOCUMENTS_LOGO_HEIGHT', 20);
322 $maxwidth = 130;
323 include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
324 $tmp = dol_getImageSize($logo, $url);
325 if ($tmp['height']) {
326 $width = round($height * $tmp['width'] / $tmp['height']);
327 if ($width > $maxwidth) {
328 $height = $height * $maxwidth / $width;
329 }
330 }
331
332 return $height;
333}
334
351function pdf_writeLogoOrCompanyName($pdf, $outputlangs, $emetteur, $logodir, $posx, $posy, $w, $default_font_size, $align)
352{
353 if (!getDolGlobalInt('PDF_DISABLE_MYCOMPANY_LOGO')) {
354 if ($emetteur->logo) {
355 if (!getDolGlobalInt('MAIN_PDF_USE_LARGE_LOGO')) {
356 $logo = $logodir.'/logos/thumbs/'.$emetteur->logo_small;
357 } else {
358 $logo = $logodir.'/logos/'.$emetteur->logo;
359 }
360 if (is_readable($logo)) {
361 $height = pdf_getHeightForLogo($logo);
362 $pdf->Image($logo, $posx, $posy, 0, $height); // width=0 (auto)
363 } else {
364 $pdf->SetTextColor(200, 0, 0);
365 $pdf->SetFont('', 'B', $default_font_size - 2);
366 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
367 $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
368 }
369 } else {
370 $text = (string) $emetteur->name;
371 $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, $align);
372 }
373 }
374}
375
385function pdfGetHeightForHtmlContent($pdf, $htmlcontent)
386{
387 // store current object
388 $pdf->startTransaction();
389 // 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
390 // Another solution would be to do the test on another PDF instance with samefont, width...
391 $pdf->setY(0);
392 // store starting values
393 $start_y = $pdf->GetY();
394 //var_dump($start_y);
395 $start_page = $pdf->getPage();
396 // call printing functions with content
397 $pdf->writeHTMLCell(0, 0, 0, $start_y, $htmlcontent, 0, 1, false, true, 'J', true);
398 // get the new Y
399 $end_y = $pdf->GetY();
400 $end_page = $pdf->getPage();
401 // calculate height
402 $height = 0;
403 if ($end_page == $start_page) {
404 $height = $end_y - $start_y;
405 } else {
406 for ($page = $start_page; $page <= $end_page; ++$page) {
407 $pdf->setPage($page);
408 $tmpm = $pdf->getMargins();
409 $tMargin = $tmpm['top'];
410 if ($page == $start_page) {
411 // first page
412 $height = $pdf->getPageHeight() - $start_y - $pdf->getBreakMargin();
413 } elseif ($page == $end_page) {
414 // last page
415 $height = $end_y - $tMargin;
416 } else {
417 $height = $pdf->getPageHeight() - $tMargin - $pdf->getBreakMargin();
418 }
419 }
420 }
421 // restore previous object state
422 $pdf->rollbackTransaction(true);
423
424 return $height;
425}
426
427
436function pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias = 0)
437{
438 // Recipient name
439 $socname = '';
440
441 if ($thirdparty instanceof Societe) {
442 $socname = $thirdparty->name;
443 if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->name_alias)) {
444 if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
445 $socname = $thirdparty->name_alias." - ".$thirdparty->name;
446 } else {
447 $socname = $thirdparty->name." - ".$thirdparty->name_alias;
448 }
449 }
450 } elseif ($thirdparty instanceof Contact) {
451 if ($thirdparty->socid > 0) {
452 $thirdparty->fetch_thirdparty();
453 $socname = $thirdparty->thirdparty->name;
454 if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->thirdparty->name_alias)) {
455 if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
456 $socname = $thirdparty->thirdparty->name_alias." - ".$thirdparty->thirdparty->name;
457 } else {
458 $socname = $thirdparty->thirdparty->name." - ".$thirdparty->thirdparty->name_alias;
459 }
460 }
461 }
462 } else {
463 throw new InvalidArgumentException('Parameter 1 $thirdparty is not a Societe nor Contact');
464 }
465
466 return $outputlangs->convToOutputCharset((string) $socname);
467}
468
481function pdf_build_address($outputlangs, $sourcecompany, $targetcompany = '', $targetcontact = '', $usecontact = 0, $mode = 'source', $object = null)
482{
483 global $hookmanager;
484
485 if ($mode == 'source' && !is_object($sourcecompany)) {
486 return -1;
487 }
488 if (($mode == 'target' || $mode == 'targetshipping') && !is_object($targetcompany)) {
489 return -1;
490 }
491
492 if (!empty($sourcecompany->state_id) && empty($sourcecompany->state)) {
493 $sourcecompany->state = getState($sourcecompany->state_id);
494 }
495 if (!empty($targetcompany->state_id) && empty($targetcompany->state)) {
496 $targetcompany->state = getState($targetcompany->state_id);
497 }
498
499 $reshook = 0;
500 $stringaddress = '';
501 if (is_object($hookmanager)) {
502 $parameters = array('sourcecompany' => &$sourcecompany, 'targetcompany' => &$targetcompany, 'targetcontact' => &$targetcontact, 'outputlangs' => $outputlangs, 'mode' => $mode, 'usecontact' => $usecontact);
503 $action = '';
504 // @phan-suppress-next-line PhanTypeMismatchArgumentNullable
505 $reshook = $hookmanager->executeHooks('pdf_build_address', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
506 $stringaddress .= $hookmanager->resPrint;
507 }
508 if (empty($reshook)) {
509 if ($mode == 'source') {
510 $withCountry = 0;
511 if (isset($targetcompany->country_code) && !empty($sourcecompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
512 $withCountry = 1;
513 }
514
515 $fulladdress = dol_format_address($sourcecompany, $withCountry, "\n", $outputlangs);
516 if ($fulladdress) {
517 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($fulladdress)."\n";
518 }
519
520 if (!getDolGlobalString('MAIN_PDF_DISABLESOURCEDETAILS')) {
521 // Phone
522 if ($sourcecompany->phone) {
523 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("PhoneShort").": ".$outputlangs->convToOutputCharset($sourcecompany->phone);
524 }
525 // Phone mobile
526 if ($sourcecompany->phone_mobile && getDolGlobalString('MAIN_PDF_SHOW_SOURCE_PHONE_MOBILE')) {
527 $stringaddress .= ($stringaddress ? ($sourcecompany->phone ? " - " : "\n") : '').$outputlangs->transnoentities("PhoneShort").": ".$outputlangs->convToOutputCharset($sourcecompany->phone_mobile);
528 }
529 // Fax
530 if ($sourcecompany->fax) {
531 $stringaddress .= ($stringaddress ? ($sourcecompany->phone ? " - " : "\n") : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($sourcecompany->fax);
532 }
533 // EMail
534 if ($sourcecompany->email) {
535 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($sourcecompany->email);
536 }
537 // Web
538 if ($sourcecompany->url) {
539 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($sourcecompany->url);
540 }
541 }
542 // Intra VAT
543 if (getDolGlobalString('MAIN_TVAINTRA_IN_SOURCE_ADDRESS')) {
544 if ($sourcecompany->tva_intra) {
545 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($sourcecompany->tva_intra);
546 }
547 }
548 // Professional Ids
549 $reg = array();
550 if (getDolGlobalString('MAIN_PROFID1_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof1)) {
551 $tmp = $outputlangs->transcountrynoentities("ProfId1", $sourcecompany->country_code);
552 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
553 $tmp = $reg[1];
554 }
555 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof1);
556 }
557 if (getDolGlobalString('MAIN_PROFID2_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof2)) {
558 $tmp = $outputlangs->transcountrynoentities("ProfId2", $sourcecompany->country_code);
559 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
560 $tmp = $reg[1];
561 }
562 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof2);
563 }
564 if (getDolGlobalString('MAIN_PROFID3_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof3)) {
565 $tmp = $outputlangs->transcountrynoentities("ProfId3", $sourcecompany->country_code);
566 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
567 $tmp = $reg[1];
568 }
569 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof3);
570 }
571 if (getDolGlobalString('MAIN_PROFID4_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof4)) {
572 $tmp = $outputlangs->transcountrynoentities("ProfId4", $sourcecompany->country_code);
573 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
574 $tmp = $reg[1];
575 }
576 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof4);
577 }
578 if (getDolGlobalString('MAIN_PROFID5_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof5)) {
579 $tmp = $outputlangs->transcountrynoentities("ProfId5", $sourcecompany->country_code);
580 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
581 $tmp = $reg[1];
582 }
583 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof5);
584 }
585 if (getDolGlobalString('MAIN_PROFID6_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof6)) {
586 $tmp = $outputlangs->transcountrynoentities("ProfId6", $sourcecompany->country_code);
587 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
588 $tmp = $reg[1];
589 }
590 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof6);
591 }
592 if (getDolGlobalString('PDF_ADD_MORE_AFTER_SOURCE_ADDRESS')) {
593 $stringaddress .= ($stringaddress ? "\n" : '') . getDolGlobalString('PDF_ADD_MORE_AFTER_SOURCE_ADDRESS');
594 }
595 }
596
597 if ($mode == 'target' || $mode == 'targetshipping' || preg_match('/targetwithdetails/', $mode)) {
598 if ($usecontact && (is_object($targetcontact))) {
599 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($targetcontact->getFullName($outputlangs, 1));
600
601 if (!empty($targetcontact->address)) {
602 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcontact))."\n";
603 } elseif (is_object($targetcompany)) {
604 $companytouseforaddress = $targetcompany;
605
606 // Contact on a thirdparty that is a different thirdparty than the thirdparty of object
607 if ($targetcontact->socid > 0 && $targetcontact->socid != $targetcompany->id) {
608 $targetcontact->fetch_thirdparty();
609 $companytouseforaddress = $targetcontact->thirdparty;
610 }
611
612 if (is_object($companytouseforaddress)) {
613 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($companytouseforaddress))."\n";
614 }
615 }
616 // Country
617 if (!empty($targetcontact->country_code) && $targetcontact->country_code != $sourcecompany->country_code) {
618 $stringaddress .= (($stringaddress && !getDolGlobalString('MAIN_PDF_REMOVE_BREAK_BEFORE_COUNTRY')) ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcontact->country_code));
619 } elseif (empty($targetcontact->country_code) && !empty($targetcompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
620 $stringaddress .= (($stringaddress && !getDolGlobalString('MAIN_PDF_REMOVE_BREAK_BEFORE_COUNTRY')) ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
621 }
622
623 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || preg_match('/targetwithdetails/', $mode)) {
624 // Phone
625 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
626 if (!empty($targetcontact->phone_pro) || !empty($targetcontact->phone_mobile)) {
627 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
628 }
629 if (!empty($targetcontact->phone_pro)) {
630 $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_pro);
631 }
632 if (!empty($targetcontact->phone_pro) && !empty($targetcontact->phone_mobile)) {
633 $stringaddress .= " / ";
634 }
635 if (!empty($targetcontact->phone_mobile)) {
636 $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_mobile);
637 }
638 }
639 // Fax
640 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
641 if ($targetcontact->fax) {
642 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcontact->fax);
643 }
644 }
645 // EMail
646 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
647 if ($targetcontact->email) {
648 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcontact->email);
649 }
650 }
651 // Web
652 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
653 if ($targetcontact->url) {
654 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset((string) $targetcontact->url);
655 }
656 }
657 }
658 } else {
659 if (is_object($targetcompany)) {
660 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcompany));
661 // Country
662 if (!empty($targetcompany->country_code) && $targetcompany->country_code != $sourcecompany->country_code) {
663 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
664 } else {
665 $stringaddress .= ($stringaddress ? "\n" : '');
666 }
667
668 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || preg_match('/targetwithdetails/', $mode)) {
669 // Phone
670 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
671 if (!empty($targetcompany->phone) || !empty($targetcompany->phone_mobile)) {
672 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
673 }
674 if (!empty($targetcompany->phone)) {
675 $stringaddress .= $outputlangs->convToOutputCharset($targetcompany->phone);
676 }
677 if (!empty($targetcompany->phone) && !empty($targetcompany->phone_mobile)) {
678 $stringaddress .= " / ";
679 }
680 if (!empty($targetcompany->phone_mobile)) {
681 $stringaddress .= $outputlangs->convToOutputCharset($targetcompany->phone_mobile);
682 }
683 }
684 // Fax
685 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
686 if ($targetcompany->fax) {
687 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcompany->fax);
688 }
689 }
690 // EMail
691 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
692 if ($targetcompany->email) {
693 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcompany->email);
694 }
695 }
696 // Web
697 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
698 if ($targetcompany->url) {
699 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcompany->url);
700 }
701 }
702 }
703 }
704 }
705
706 // Intra VAT
707 if (!getDolGlobalString('MAIN_TVAINTRA_NOT_IN_ADDRESS')) {
708 if ($usecontact && is_object($targetcontact) && getDolGlobalInt('MAIN_USE_COMPANY_NAME_OF_CONTACT')) {
709 $targetcontact->fetch_thirdparty();
710 if (!empty($targetcontact->thirdparty->id) && $targetcontact->thirdparty->tva_intra) {
711 $stringaddress .= ($stringaddress ? "\n" : '') . $outputlangs->transnoentities("VATIntraShort") . ': ' . $outputlangs->convToOutputCharset($targetcontact->thirdparty->tva_intra);
712 }
713 } elseif (!empty($targetcompany->tva_intra)) {
714 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($targetcompany->tva_intra);
715 }
716 }
717
718 // Legal form
719 if (getDolGlobalString('MAIN_LEGALFORM_IN_ADDRESS') && !empty($targetcompany->forme_juridique_code)) {
720 $tmp = getFormeJuridiqueLabel((string) $targetcompany->forme_juridique_code);
721 $stringaddress .= ($stringaddress ? "\n" : '').$tmp;
722 }
723
724 // Professional Ids
725 if (getDolGlobalString('MAIN_PROFID1_IN_ADDRESS') && !empty($targetcompany->idprof1)) {
726 $tmp = $outputlangs->transcountrynoentities("ProfId1", $targetcompany->country_code);
727 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
728 $tmp = $reg[1];
729 }
730 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof1);
731 }
732 if (getDolGlobalString('MAIN_PROFID2_IN_ADDRESS') && !empty($targetcompany->idprof2)) {
733 $tmp = $outputlangs->transcountrynoentities("ProfId2", $targetcompany->country_code);
734 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
735 $tmp = $reg[1];
736 }
737 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof2);
738 }
739 if (getDolGlobalString('MAIN_PROFID3_IN_ADDRESS') && !empty($targetcompany->idprof3)) {
740 $tmp = $outputlangs->transcountrynoentities("ProfId3", $targetcompany->country_code);
741 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
742 $tmp = $reg[1];
743 }
744 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof3);
745 }
746 if (getDolGlobalString('MAIN_PROFID4_IN_ADDRESS') && !empty($targetcompany->idprof4)) {
747 $tmp = $outputlangs->transcountrynoentities("ProfId4", $targetcompany->country_code);
748 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
749 $tmp = $reg[1];
750 }
751 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof4);
752 }
753 if (getDolGlobalString('MAIN_PROFID5_IN_ADDRESS') && !empty($targetcompany->idprof5)) {
754 $tmp = $outputlangs->transcountrynoentities("ProfId5", $targetcompany->country_code);
755 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
756 $tmp = $reg[1];
757 }
758 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof5);
759 }
760 if (getDolGlobalString('MAIN_PROFID6_IN_ADDRESS') && !empty($targetcompany->idprof6)) {
761 $tmp = $outputlangs->transcountrynoentities("ProfId6", $targetcompany->country_code);
762 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
763 $tmp = $reg[1];
764 }
765 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof6);
766 }
767
768 // Public note
769 if (getDolGlobalString('MAIN_PUBLIC_NOTE_IN_ADDRESS')) {
770 if ($mode == 'source' && !empty($sourcecompany->note_public)) {
771 $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($sourcecompany->note_public);
772 }
773 if (($mode == 'target' || $mode == 'targetshipping' || preg_match('/targetwithdetails/', $mode)) && !empty($targetcompany->note_public)) {
774 $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($targetcompany->note_public);
775 }
776 }
777 }
778 }
779
780 return $stringaddress;
781}
782
783
792function pdf_pagehead($pdf, $outputlangs, $page_height)
793{
794 global $conf;
795
796 // Add a background image on document only if good setup of const
797 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
798 $filepath = $conf->mycompany->dir_output.'/logos/' . getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF');
799 if (file_exists($filepath)) {
800 $pdf->setAutoPageBreak(false, 0); // Disable auto pagebreak before adding image
801 if (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF_ALPHA')) {
802 $pdf->SetAlpha(getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_ALPHA'));
803 } // Option for change opacity of background
804 $pdf->Image($filepath, getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_X'), getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_Y'), 0, $page_height);
805 if (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF_ALPHA')) {
806 $pdf->SetAlpha(1);
807 }
808 $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
809 $pdf->setAutoPageBreak(true, 0); // Restore pagebreak
810 }
811 }
812 if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND') && getDolGlobalString('MAIN_ADD_PDF_BACKGROUND') != '-1') {
813 $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
814 }
815}
816
817
830function pdfWriteAdditionnalTitle($pdf, $outputlangs, $page_height, $object, &$w, &$posx, &$posy)
831{
832 // Transaction/Signature ID + Duplicate or Temporary info
833 include_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
834
835 pdfWriteBlockedLogSignature($pdf, $outputlangs, $page_height, $object, $w, $posx, $posy);
836}
837
838
855function pdfWriteVATArray($docgenerator, &$index, $pdf, $outputlangs, $outputlangsbis, $object, $col1x, $col2x, $largcol2, $tab2_top, $tab2_hl)
856{
857 global $mysoc;
858
859 $tmpatleastoneratenotnull = 0;
860
861 // Local tax 1 before VAT
862 foreach ($docgenerator->localtax1 as $localtax_type => $localtax_rate) {
863 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
864 continue;
865 }
866
867 foreach ($localtax_rate as $tvakey => $tvaval) {
868 if ($tvakey != 0 || getDolGlobalString('INVOICE_SHOW_ALSO_LOCALTAX1_LINE_IF_ZERO')) {
869 //$tmpatleastoneratenotnull++;
870
871 $index++;
872 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
873
874 $tvacompl = '';
875 if (preg_match('/\*/', (string) $tvakey)) {
876 $tvakey = str_replace('*', '', (string) $tvakey);
877 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
878 }
879
880 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
881 $totalvat .= ' ';
882
883 if (getDolGlobalString('PDF_LOCALTAX1_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
884 $totalvat .= $tvacompl;
885 } else {
886 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
887 }
888
889 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
890
891 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
892
893 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
894 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
895 }
896 }
897 }
898
899 // Local tax 2 before VAT
900 foreach ($docgenerator->localtax2 as $localtax_type => $localtax_rate) {
901 if (in_array((string) $localtax_type, array('1', '3', '5'))) {
902 continue;
903 }
904
905 foreach ($localtax_rate as $tvakey => $tvaval) {
906 if ($tvakey != 0 || getDolGlobalString('INVOICE_SHOW_ALSO_LOCALTAX2_LINE_IF_ZERO')) {
907 //$tmpatleastoneratenotnull++;
908
909 $index++;
910 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
911
912 $tvacompl = '';
913 if (preg_match('/\*/', (string) $tvakey)) {
914 $tvakey = str_replace('*', '', (string) $tvakey);
915 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
916 }
917 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
918 $totalvat .= ' ';
919
920 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
921 $totalvat .= $tvacompl;
922 } else {
923 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
924 }
925
926 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
927
928 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
929
930 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
931 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
932 }
933 }
934 }
935
936 // Situations totals might be wrong on huge amounts with old mode 1
937 if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1 && $object->situation_cycle_ref && $object->situation_counter > 1) {
938 $sum_pdf_tva = 0;
939 foreach ($docgenerator->tva as $tvakey => $tvaval) {
940 $sum_pdf_tva += $tvaval; // sum VAT amounts to compare to object
941 }
942
943 if ($sum_pdf_tva != $object->total_tva) { // apply coef to recover the VAT object amount (the good one)
944 if (!empty($sum_pdf_tva)) {
945 $coef_fix_tva = $object->total_tva / $sum_pdf_tva;
946 } else {
947 $coef_fix_tva = 1;
948 }
949
950
951 foreach ($docgenerator->tva as $tvakey => $tvaval) {
952 $docgenerator->tva[$tvakey] = $tvaval * $coef_fix_tva;
953 }
954 foreach ($docgenerator->tva_array as $tvakey => $tvaval) {
955 $docgenerator->tva_array[$tvakey]['amount'] = $tvaval['amount'] * $coef_fix_tva;
956 }
957 }
958 }
959
960 if (!getDolGlobalInt('PDF_INVOICE_SHOW_VAT_ANALYSIS')) { // by default, we show detail of vat here
961 // VAT
962 foreach ($docgenerator->tva_array as $tvakey => $tvaval) {
963 if ($tvakey != 0 || getDolGlobalString('INVOICE_SHOW_ALSO_VAT_LINE_IF_ZERO')) {
964 $tmpatleastoneratenotnull++;
965
966 $index++;
967 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
968
969 $tvacompl = '';
970 if (preg_match('/\*/', $tvakey)) {
971 $tvakey = str_replace('*', '', $tvakey);
972 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
973 }
974 $totalvat = $outputlangs->transcountrynoentities("TotalVAT", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalVAT", $mysoc->country_code) : '');
975 $totalvat .= ' ';
976 if (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'rateonly') {
977 $totalvat .= vatrate((string) $tvaval['vatrate'], true).$tvacompl;
978 } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'codeonly') {
979 $totalvat .= $tvaval['vatcode'].$tvacompl;
980 } elseif (getDolGlobalString('PDF_VAT_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
981 $totalvat .= $tvacompl;
982 } else {
983 $totalvat .= vatrate((string) $tvaval['vatrate'], true).($tvaval['vatcode'] ? ' ('.$tvaval['vatcode'].')' : '').$tvacompl;
984 }
985
986 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
987
988 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
989
990 $pdf->MultiCell($largcol2, $tab2_hl, price(price2num($tvaval['amount'], 'MT'), 0, $outputlangs), 0, 'R', true);
991 }
992 }
993 }
994
995 // Local tax 1 after VAT
996 foreach ($docgenerator->localtax1 as $localtax_type => $localtax_rate) {
997 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
998 continue;
999 }
1000
1001 foreach ($localtax_rate as $tvakey => $tvaval) {
1002 if ($tvakey != 0 || getDolGlobalString('INVOICE_SHOW_ALSO_LOCALTAX1_LINE_IF_ZERO')) {
1003 //$tmpatleastoneratenotnull++;
1004
1005 $index++;
1006 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1007
1008 $tvacompl = '';
1009 if (preg_match('/\*/', (string) $tvakey)) {
1010 $tvakey = str_replace('*', '', (string) $tvakey);
1011 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1012 }
1013 $totalvat = $outputlangs->transcountrynoentities("TotalLT1", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT1", $mysoc->country_code) : '');
1014 $totalvat .= ' ';
1015
1016 if (getDolGlobalString('PDF_LOCALTAX1_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1017 $totalvat .= $tvacompl;
1018 } else {
1019 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1020 }
1021
1022 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1023
1024 $total_localtax = ((isModEnabled("multicurrency") && isset($object->multicurrency_tx) && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1025
1026 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1027 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1028 }
1029 }
1030 }
1031
1032 // Local tax 2 after VAT
1033 foreach ($docgenerator->localtax2 as $localtax_type => $localtax_rate) {
1034 if (in_array((string) $localtax_type, array('2', '4', '6'))) {
1035 continue;
1036 }
1037
1038 foreach ($localtax_rate as $tvakey => $tvaval) {
1039 // retrieve global local tax
1040 if ($tvakey != 0 || getDolGlobalString('INVOICE_SHOW_ALSO_LOCALTAX2_LINE_IF_ZERO')) {
1041 //$tmpatleastoneratenotnull++;
1042
1043 $index++;
1044 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1045
1046 $tvacompl = '';
1047 if (preg_match('/\*/', (string) $tvakey)) {
1048 $tvakey = str_replace('*', '', (string) $tvakey);
1049 $tvacompl = " (".$outputlangs->transnoentities("NonPercuRecuperable").")";
1050 }
1051 $totalvat = $outputlangs->transcountrynoentities("TotalLT2", $mysoc->country_code).(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transcountrynoentities("TotalLT2", $mysoc->country_code) : '');
1052 $totalvat .= ' ';
1053
1054 if (getDolGlobalString('PDF_LOCALTAX2_LABEL_IS_CODE_OR_RATE') == 'nocodenorate') {
1055 $totalvat .= $tvacompl;
1056 } else {
1057 $totalvat .= vatrate((string) abs((float) $tvakey), true).$tvacompl;
1058 }
1059
1060 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $totalvat, 0, 'L', true);
1061
1062 $total_localtax = ((isModEnabled("multicurrency") && $object->multicurrency_tx != 1) ? price2num($tvaval * $object->multicurrency_tx, 'MT') : $tvaval);
1063
1064 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1065 $pdf->MultiCell($largcol2, $tab2_hl, price($total_localtax, 0, $outputlangs), 0, 'R', true);
1066 }
1067 }
1068 }
1069
1070 $docgenerator->atleastoneratenotnull = $tmpatleastoneratenotnull;
1071}
1072
1073
1095function pdfWriteAlreadyPaid($docgenerator, &$index, $pdf, $outputlangs, $outputlangsbis, $object, $col1x, $col2x, $largcol2, $tab2_top, $tab2_hl, $deja_regle, $creditnoteamount, $depositsamount, $resteapayer, $resteapayer_origin)
1096{
1097 global $mysoc;
1098
1099 $useborder = 0;
1100
1101 if ((($deja_regle > 0 || $creditnoteamount > 0 || $depositsamount > 0) && !getDolGlobalString('INVOICE_NO_PAYMENT_DETAILS'))
1102 || isALNERunningVersion()) {
1103 // Already paid + Deposits
1104 $index++;
1105 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1106 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("Paid").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("Paid") : ''), 0, 'L', false);
1107 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1108 //if (!isModEnabled("multicurrency") || $object->multicurrency_tx == 1 || getDolGlobalInt('MULTICURRENCY_SHOW_ALSO_MAIN_CURRENCY_ON_PDF') == 0) {
1109 $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle + $depositsamount, 0, $outputlangs), 0, 'R', false);
1110 //} else {
1111 // $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle + $depositsamount, 0, $outputlangs), 0, 'R', false);
1112 //
1113 // $index++;
1114 // $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1115 // $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("Paid").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("Paid") : '').' ('.$outputlangs->getCurrencySymbol($mysoc->currency_code).')', $useborder, 'L', true);
1116
1117 // $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1118 // $pdf->MultiCell($largcol2, $tab2_hl, price($deja_regle_origin + $depositsamount_origin, 0, $outputlangs, 1, -1, -1, $mysoc->currency_code), $useborder, 'L', true);
1119 //}
1120
1121 // Credit note
1122 if ($creditnoteamount) {
1123 $labeltouse = ($outputlangs->transnoentities("CreditNotesOrExcessReceived") != "CreditNotesOrExcessReceived") ? $outputlangs->transnoentities("CreditNotesOrExcessReceived") : $outputlangs->transnoentities("CreditNotes");
1124 $labeltouse .= (is_object($outputlangsbis) ? (' / '.(($outputlangsbis->transnoentities("CreditNotesOrExcessReceived") != "CreditNotesOrExcessReceived") ? $outputlangsbis->transnoentities("CreditNotesOrExcessReceived") : $outputlangsbis->transnoentities("CreditNotes"))) : '');
1125 $index++;
1126 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1127 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $labeltouse, 0, 'L', false);
1128 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1129 $pdf->MultiCell($largcol2, $tab2_hl, price($creditnoteamount, 0, $outputlangs), 0, 'R', false);
1130 }
1131
1132 if ($object->close_code == Facture::CLOSECODE_DISCOUNTVAT) {
1133 $index++;
1134 $pdf->SetFillColor(255, 255, 255);
1135
1136 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1137 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("EscompteOfferedShort").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("EscompteOfferedShort") : ''), $useborder, 'L', true);
1138 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1139 $pdf->MultiCell($largcol2, $tab2_hl, price(price2num($object->total_ttc - $deja_regle - $creditnoteamount - $depositsamount, 'MT'), 0, $outputlangs), $useborder, 'R', true);
1140
1141 $resteapayer = 0;
1142 $resteapayer_origin = 0;
1143 }
1144
1145 $index++;
1146 $pdf->SetTextColor(0, 0, 60);
1147 $pdf->SetFillColor(224, 224, 224);
1148 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1149 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("RemainderToPay") : ''), $useborder, 'L', true);
1150 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1151 if (!isModEnabled("multicurrency") || $object->multicurrency_tx == 1 || getDolGlobalInt('MULTICURRENCY_SHOW_ALSO_MAIN_CURRENCY_ON_PDF') == 0) {
1152 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', true);
1153 } else {
1154 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer, 0, $outputlangs), $useborder, 'R', true);
1155
1156 //$pdf->MultiCell($largcol2, $tab2_hl, '('.price($resteapayer_origin, 0, $outputlangs, 1, -1, 'MT', $mysoc->currency_code).') '.price($resteapayer, 0, $outputlangs), 0, 'R', true);
1157 $index++;
1158 $pdf->SetXY($col1x, $tab2_top + $tab2_hl * $index);
1159 $pdf->SetTextColor(0, 0, 60);
1160 $pdf->SetFillColor(224, 224, 224);
1161 $pdf->MultiCell($col2x - $col1x, $tab2_hl, $outputlangs->transnoentities("RemainderToPay").(is_object($outputlangsbis) ? ' / '.$outputlangsbis->transnoentities("RemainderToPay") : '').' ('.$outputlangs->getCurrencySymbol($mysoc->currency_code).')', $useborder, 'L', true);
1162
1163 $pdf->SetXY($col2x, $tab2_top + $tab2_hl * $index);
1164 $pdf->MultiCell($largcol2, $tab2_hl, price($resteapayer_origin, 0, $outputlangs, 1, -1, -1, $mysoc->currency_code), $useborder, 'L', true);
1165 }
1166 }
1167}
1168
1169
1180function pdf_getSubstitutionArray($outputlangs, $exclude = null, $object = null, $onlykey = 0, $include = null)
1181{
1182 $substitutionarray = getCommonSubstitutionArray($outputlangs, $onlykey, $exclude, $object, $include);
1183 $substitutionarray['__FROM_NAME__'] = '__FROM_NAME__';
1184 $substitutionarray['__FROM_EMAIL__'] = '__FROM_EMAIL__';
1185 return $substitutionarray;
1186}
1187
1188
1200function pdf_watermark($pdf, $outputlangs, $h, $w, $unit, $text)
1201{
1202 // Print Draft Watermark
1203 if ($unit == 'pt') {
1204 $k = 1;
1205 } elseif ($unit == 'mm') {
1206 $k = 72 / 25.4;
1207 } elseif ($unit == 'cm') {
1208 $k = 72 / 2.54;
1209 } elseif ($unit == 'in') {
1210 $k = 72;
1211 } else {
1212 $k = 1;
1213 dol_print_error(null, 'Unexpected unit "'.$unit.'" for pdf_watermark');
1214 }
1215
1216 // Make substitution
1217 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, null);
1218 complete_substitutions_array($substitutionarray, $outputlangs, null);
1219 $text = make_substitutions($text, $substitutionarray, $outputlangs);
1220 $text = $outputlangs->convToOutputCharset($text);
1221
1222 $savx = $pdf->getX();
1223 $savy = $pdf->getY();
1224
1225 $watermark_angle = atan($h / $w) / 2;
1226 $watermark_x_pos = 0;
1227 $watermark_y_pos = $h / 3;
1228 $watermark_x = $w / 2;
1229 $watermark_y = $h / 3;
1230 $pdf->SetFont('', 'B', 40);
1231 $pdf->SetTextColor(255, 0, 0);
1232
1233 // rotate
1234 $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));
1235 // print watermark
1236 $pdf->SetAlpha(0.5);
1237 $pdf->SetXY($watermark_x_pos, $watermark_y_pos);
1238
1239 // set alpha to semi-transparency
1240 $pdf->SetAlpha(0.3);
1241 $pdf->Cell($w - 20, 25, $outputlangs->convToOutputCharset($text), "", 2, "C", false);
1242
1243 // antirotate
1244 $pdf->_out('Q');
1245
1246 $pdf->SetXY($savx, $savy);
1247
1248 // Restore alpha
1249 $pdf->SetAlpha(1);
1250}
1251
1252
1264function pdfCertifMention($pdf, $outputlangs, $seller, $default_font_size, &$posy, $pdftemplate)
1265{
1266 include_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
1267
1268 return pdfCertifMentionblockedLog($pdf, $outputlangs, $seller, $default_font_size, $posy, $pdftemplate);
1269}
1270
1271
1284function pdf_bank($pdf, $outputlangs, $curx, $cury, $account, $onlynumber = 0, $default_font_size = 10)
1285{
1286 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbank.class.php';
1287
1288 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
1289 $diffsizecontent = getDolGlobalInt('PDF_DIFFSIZE_CONTENT', 4);
1290 $pdf->SetXY($curx, $cury);
1291
1292 if (empty($onlynumber)) {
1293 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
1294 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByTransferOnThisBankAccount').':', 0, 'L', false);
1295 $cury += 4;
1296 }
1297
1298 $outputlangs->load("banks");
1299
1300 // Use correct name of bank id according to country
1301 $bickey = "BICNumber";
1302 if ($account->getCountryCode() == 'IN') {
1303 $bickey = "SWIFT";
1304 }
1305
1306 // Get format of bank account according to its country
1307 $usedetailedbban = $account->useDetailedBBAN();
1308
1309 //$onlynumber=0; $usedetailedbban=1; // For tests
1310 if ($usedetailedbban) {
1311 $savcurx = $curx;
1312
1313 if (empty($onlynumber)) {
1314 $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
1315 $pdf->SetXY($curx, $cury);
1316 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', false);
1317 $cury += 3;
1318 }
1319
1320 if (!getDolGlobalString('PDF_BANK_HIDE_NUMBER_SHOW_ONLY_BICIBAN')) { // Note that some countries still need bank number, BIC/IBAN not enough for them
1321 // Note:
1322 // bank = code_banque (FR), sort code (GB, IR. Example: 12-34-56)
1323 // desk = code guichet (FR), used only when $usedetailedbban = 1
1324 // number = account number
1325 // key = check control key used only when $usedetailedbban = 1
1326 if (empty($onlynumber)) {
1327 $pdf->line($curx + 1, $cury + 1, $curx + 1, $cury + 6);
1328 }
1329
1330 $bank_number_length = 0;
1331 foreach ($account->getFieldsToShow() as $val) {
1332 $pdf->SetXY($curx, $cury + 4);
1333 $pdf->SetFont('', '', $default_font_size - 3);
1334
1335 if ($val == 'BankCode') {
1336 // Bank code
1337 $tmplength = 18;
1338 $content = $account->code_banque;
1339 } elseif ($val == 'DeskCode') {
1340 // Desk
1341 $tmplength = 18;
1342 $content = $account->code_guichet;
1343 } elseif ($val == 'BankAccountNumber') {
1344 // Number
1345 $tmplength = 24;
1346 $content = $account->number;
1347 } elseif ($val == 'BankAccountNumberKey') {
1348 // Key
1349 $tmplength = 15;
1350 $content = $account->cle_rib;
1351 } elseif ($val == 'IBAN' || $val == 'BIC') {
1352 // Key
1353 $tmplength = 0;
1354 $content = '';
1355 } else {
1356 dol_print_error($account->db, 'Unexpected value for getFieldsToShow: '.$val);
1357 break;
1358 }
1359
1360 if ($content == '') {
1361 continue;
1362 }
1363
1364 $pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($content), 0, 'C', false);
1365 $pdf->SetXY($curx, $cury + 1);
1366 $curx += $tmplength;
1367 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
1368 $pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities($val), 0, 'C', false);
1369 if (empty($onlynumber)) {
1370 $pdf->line($curx, $cury + 1, $curx, $cury + 7);
1371 }
1372
1373 // Only set this variable when table was printed
1374 $bank_number_length = 8;
1375 }
1376
1377 $curx = $savcurx;
1378 $cury += $bank_number_length;
1379 }
1380 } elseif (!empty($account->number)) {
1381 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
1382 $pdf->SetXY($curx, $cury);
1383 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', false);
1384 $cury += 3;
1385
1386 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
1387 $pdf->SetXY($curx, $cury);
1388 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("BankAccountNumber").': '.$outputlangs->convToOutputCharset($account->number), 0, 'L', false);
1389 $cury += 3;
1390
1391 if ($diffsizecontent <= 2) {
1392 $cury += 1;
1393 }
1394 }
1395
1396 $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
1397
1398 if (empty($onlynumber) && !empty($account->address)) {
1399 $pdf->SetXY($curx, $cury);
1400 $val = $outputlangs->transnoentities("Residence").': '.$outputlangs->convToOutputCharset($account->address);
1401 $pdf->MultiCell(100, 3, $val, 0, 'L', false);
1402 //$nboflines=dol_nboflines_bis($val,120);
1403 //$cury+=($nboflines*3)+2;
1404 $tmpy = $pdf->getStringHeight(100, $val);
1405 $cury += $tmpy;
1406 }
1407
1408 if (!empty($account->owner_name)) {
1409 $pdf->SetXY($curx, $cury);
1410 $val = $outputlangs->transnoentities("BankAccountOwner").': '.$outputlangs->convToOutputCharset($account->owner_name);
1411 $pdf->MultiCell(100, 3, $val, 0, 'L', false);
1412 $tmpy = $pdf->getStringHeight(100, $val);
1413 $cury += $tmpy;
1414 } elseif (!$usedetailedbban) {
1415 $cury += 1;
1416 }
1417
1418 // Use correct name of bank id according to country
1419 $ibankey = FormBank::getIBANLabel($account);
1420
1421 if (!empty($account->iban)) {
1422 //Remove whitespaces to ensure we are dealing with the format we expect
1423 $ibanDisplay_temp = str_replace(' ', '', $outputlangs->convToOutputCharset($account->iban));
1424 $ibanDisplay = "";
1425
1426 $nbIbanDisplay_temp = dol_strlen($ibanDisplay_temp);
1427 for ($i = 0; $i < $nbIbanDisplay_temp; $i++) {
1428 $ibanDisplay .= $ibanDisplay_temp[$i];
1429 if ($i % 4 == 3 && $i > 0) {
1430 $ibanDisplay .= " ";
1431 }
1432 }
1433
1434 $pdf->SetFont('', 'B', $default_font_size - 3);
1435 $pdf->SetXY($curx, $cury);
1436 $pdf->MultiCell(100, 3, $outputlangs->transnoentities($ibankey).': '.$ibanDisplay, 0, 'L', false);
1437 $cury += 3;
1438 }
1439
1440 if (!empty($account->bic)) {
1441 $pdf->SetFont('', 'B', $default_font_size - 3);
1442 $pdf->SetXY($curx, $cury);
1443 $pdf->MultiCell(100, 3, $outputlangs->transnoentities($bickey).': '.$outputlangs->convToOutputCharset($account->bic), 0, 'L', false);
1444 }
1445
1446 return $pdf->getY();
1447}
1448
1466function pdf_pagefoot($pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails = 0, $hidefreetext = 0, $page_largeur = 0, $watermark = '')
1467{
1468 global $conf, $hookmanager;
1469
1470 $outputlangs->load("dict");
1471 $line = '';
1472 $reg = array();
1473 $marginwithfooter = 0; // Return value
1474
1475 $dims = $pdf->getPageDimensions();
1476
1477 // Line of free text
1478 if (empty($hidefreetext) && getDolGlobalString($paramfreetext)) {
1479 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
1480 // More substitution keys
1481 if (is_object($fromcompany)) {
1482 $substitutionarray['__FROM_NAME__'] = $fromcompany->name;
1483 $substitutionarray['__FROM_EMAIL__'] = $fromcompany->email;
1484 }
1485 complete_substitutions_array($substitutionarray, $outputlangs, $object);
1486 $newfreetext = make_substitutions(getDolGlobalString($paramfreetext), $substitutionarray, $outputlangs);
1487
1488 // Make a change into HTML code to allow to include images from medias directory.
1489 // <img alt="" src="/dolibarr_dev/htdocs/viewimage.php?modulepart=medias&amp;entity=1&amp;file=image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1490 // become
1491 // <img alt="" src="'.DOL_DATA_ROOT.'/medias/image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1492 $newfreetext = preg_replace('/(<img.*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)("[^\/]*\/>)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $newfreetext);
1493
1494 $line .= $outputlangs->convToOutputCharset($newfreetext);
1495 }
1496
1497 // First line of company infos
1498 $line1 = "";
1499 $line2 = "";
1500 $line3 = "";
1501 $line4 = "";
1502
1503 if (is_object($fromcompany) && in_array($showdetails, array(1, 3))) {
1504 // Company name
1505 if ($fromcompany->name) {
1506 $line1 .= ($line1 ? " - " : "").$outputlangs->transnoentities("RegisteredOffice").": ".$fromcompany->name;
1507 }
1508 // Address
1509 if ($fromcompany->address) {
1510 $line1 .= ($line1 ? " - " : "").str_replace("\n", ", ", $fromcompany->address);
1511 }
1512 // Zip code
1513 if ($fromcompany->zip) {
1514 $line1 .= ($line1 ? " - " : "").$fromcompany->zip;
1515 }
1516 // Town
1517 if ($fromcompany->town) {
1518 $line1 .= ($line1 ? " " : "").$fromcompany->town;
1519 }
1520 // Country
1521 if ($fromcompany->country) {
1522 $line1 .= ($line1 ? ", " : "").$fromcompany->country;
1523 }
1524 // Phone
1525 if ($fromcompany->phone) {
1526 $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Phone").": ".$fromcompany->phone;
1527 }
1528 // Fax
1529 if ($fromcompany->fax) {
1530 $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Fax").": ".$fromcompany->fax;
1531 }
1532
1533 // URL
1534 if ($fromcompany->url) {
1535 $line2 .= ($line2 ? " - " : "").$fromcompany->url;
1536 }
1537 // Email
1538 if ($fromcompany->email) {
1539 $line2 .= ($line2 ? " - " : "").$fromcompany->email;
1540 }
1541 }
1542 if ($showdetails == 2 || $showdetails == 3 || (!empty($fromcompany->country_code) && $fromcompany->country_code == 'DE')) {
1543 // Managers
1544 if ($fromcompany->managers) {
1545 $line2 .= ($line2 ? " - " : "").$fromcompany->managers;
1546 }
1547 }
1548
1549 // Line 3 of company infos
1550 // Juridical status
1551 if (!empty($fromcompany->forme_juridique_code)) {
1552 $line3 .= ($line3 ? " - " : "").$outputlangs->convToOutputCharset(getFormeJuridiqueLabel((string) $fromcompany->forme_juridique_code));
1553 }
1554 // Capital
1555 if (!empty($fromcompany->capital)) {
1556 $tmpamounttoshow = price2num($fromcompany->capital); // This field is a free string or a float
1557 if (is_numeric($tmpamounttoshow) && $tmpamounttoshow > 0) {
1558 $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", price($tmpamounttoshow, 0, $outputlangs, 0, 0, 0, getDolCurrency()));
1559 } elseif (!empty($fromcompany->capital)) {
1560 $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", (string) $fromcompany->capital);
1561 }
1562 }
1563 // Prof Id 1
1564 if (!empty($fromcompany->idprof1) && ($fromcompany->country_code != 'FR' || (empty($fromcompany->idprof2) || strpos($fromcompany->idprof2, $fromcompany->idprof1) !== 0))) {
1565 $field = $outputlangs->transcountrynoentities("ProfId1", $fromcompany->country_code);
1566 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1567 $field = $reg[1];
1568 }
1569 $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof1);
1570 }
1571 // Prof Id 2
1572 if (!empty($fromcompany->idprof2)) {
1573 $field = $outputlangs->transcountrynoentities("ProfId2", $fromcompany->country_code);
1574 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1575 $field = $reg[1];
1576 }
1577 $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof2);
1578 }
1579
1580 // Line 4 of company infos
1581 // Prof Id 3
1582 if (!empty($fromcompany->idprof3)) {
1583 $field = $outputlangs->transcountrynoentities("ProfId3", $fromcompany->country_code);
1584 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1585 $field = $reg[1];
1586 }
1587 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof3);
1588 }
1589 // Prof Id 4
1590 if (!empty($fromcompany->idprof4)) {
1591 $field = $outputlangs->transcountrynoentities("ProfId4", $fromcompany->country_code);
1592 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1593 $field = $reg[1];
1594 }
1595 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof4);
1596 }
1597 // Prof Id 5
1598 if (!empty($fromcompany->idprof5)) {
1599 $field = $outputlangs->transcountrynoentities("ProfId5", $fromcompany->country_code);
1600 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1601 $field = $reg[1];
1602 }
1603 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof5);
1604 }
1605 // Prof Id 6
1606 if (!empty($fromcompany->idprof6)) {
1607 $field = $outputlangs->transcountrynoentities("ProfId6", $fromcompany->country_code);
1608 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1609 $field = $reg[1];
1610 }
1611 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof6);
1612 }
1613 // Prof Id 7
1614 if (!empty($fromcompany->idprof7)) {
1615 $field = $outputlangs->transcountrynoentities("ProfId7", $fromcompany->country_code);
1616 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1617 $field = $reg[1];
1618 }
1619 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof7);
1620 }
1621 // Prof Id 8
1622 if (!empty($fromcompany->idprof8)) {
1623 $field = $outputlangs->transcountrynoentities("ProfId8", $fromcompany->country_code);
1624 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1625 $field = $reg[1];
1626 }
1627 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof8);
1628 }
1629 // Prof Id 9
1630 if (!empty($fromcompany->idprof9)) {
1631 $field = $outputlangs->transcountrynoentities("ProfId9", $fromcompany->country_code);
1632 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1633 $field = $reg[1];
1634 }
1635 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof9);
1636 }
1637 // Prof Id 10
1638 if (!empty($fromcompany->idprof10)) {
1639 $field = $outputlangs->transcountrynoentities("ProfId10", $fromcompany->country_code);
1640 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1641 $field = $reg[1];
1642 }
1643 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof10);
1644 }
1645 // IntraCommunautary VAT
1646 if (!empty($fromcompany->tva_intra) && $fromcompany->tva_intra != '') {
1647 $line4 .= ($line4 ? " - " : "").$outputlangs->transnoentities("VATIntraShort").": ".$outputlangs->convToOutputCharset($fromcompany->tva_intra);
1648 }
1649
1650 $pdf->SetFont('', '', 7);
1651 $pdf->SetDrawColor(224, 224, 224);
1652 // Option for footer text color
1653 if (getDolGlobalString('PDF_FOOTER_TEXT_COLOR')) {
1654 $tmparray = sscanf(getDolGlobalString('PDF_FOOTER_TEXT_COLOR'), '%d, %d, %d');
1655 $r = $tmparray[0];
1656 $g = $tmparray[1];
1657 $b = $tmparray[2];
1658 $pdf->SetTextColor($r, $g, $b);
1659 }
1660
1661 // The start of the bottom of this page footer is positioned according to # of lines
1662 $freetextheight = 0;
1663 $align = '';
1664 if ($line) { // Free text
1665 //$line="sample text<br>\nfd<strong>sf</strong>sdf<br>\nghfghg<br>";
1666 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) {
1667 $width = 20000;
1668 $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.
1669 if (getDolGlobalString('MAIN_USE_AUTOWRAP_ON_FREETEXT')) {
1670 $width = 200;
1671 $align = 'C';
1672 }
1673 $freetextheight = $pdf->getStringHeight($width, $line);
1674 } else {
1675 $freetextheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($line, 1, 'UTF-8', 0)); // New method (works for HTML content)
1676 //print '<br>'.$freetextheight;
1677 }
1678 }
1679
1680 $posy = 0;
1681 // For customized footer
1682 if (is_object($hookmanager)) {
1683 $parameters = array('line1' => $line1, 'line2' => $line2, 'line3' => $line3, 'line4' => $line4, 'outputlangs' => $outputlangs);
1684 $action = '';
1685 $hookmanager->executeHooks('pdf_pagefoot', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1686 if (!empty($hookmanager->resPrint) && $hidefreetext == 0) {
1687 $mycustomfooter = $hookmanager->resPrint;
1688 $mycustomfooterheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1689
1690 $marginwithfooter = $marge_basse + $freetextheight + $mycustomfooterheight;
1691 $posy = (float) $marginwithfooter;
1692
1693 // Option for footer background color (without freetext zone)
1694 if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1695 $tmparray = sscanf(getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR'), '%d, %d, %d');
1696 $r = $tmparray[0];
1697 $g = $tmparray[1];
1698 $b = $tmparray[2];
1699 $pdf->setAutoPageBreak(false, 0); // Disable auto pagebreak
1700 $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', array(), $fill_color = array($r, $g, $b));
1701 $pdf->setAutoPageBreak(true, 0); // Restore pagebreak
1702 }
1703
1704 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1705 $pdf->setAutoPageBreak(false, 0);
1706 } // Option for disable auto pagebreak
1707 if ($line) { // Free text
1708 $pdf->SetXY($dims['lm'], -$posy);
1709 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1710 $pdf->MultiCell(0, 3, $line, 0, $align, false);
1711 } else {
1712 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1713 }
1714 $posy -= $freetextheight;
1715 }
1716 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1717 $pdf->setAutoPageBreak(true, 0);
1718 } // Restore pagebreak
1719
1720 $pdf->SetY(-$posy);
1721
1722 // Hide footer line if footer background color is set
1723 if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1724 $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1725 }
1726
1727 // Option for set top margin height of footer after freetext
1728 if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1729 $posy -= (float) getDolGlobalString('PDF_FOOTER_TOP_MARGIN');
1730 } else {
1731 $posy--;
1732 }
1733
1734 if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) {
1735 $pdf->setAutoPageBreak(false, 0);
1736 } // Option for disable auto pagebreak
1737 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $mycustomfooterheight, $dims['lm'], $dims['hk'] - $posy, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1738 if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) {
1739 $pdf->setAutoPageBreak(true, 0);
1740 } // Restore pagebreak
1741
1742 $posy -= $mycustomfooterheight - 3;
1743 } else {
1744 // Else default footer
1745 $marginwithfooter = $marge_basse + $freetextheight + (!empty($line1) ? 3 : 0) + (!empty($line2) ? 3 : 0) + (!empty($line3) ? 3 : 0) + (!empty($line4) ? 3 : 0);
1746 $posy = (float) $marginwithfooter;
1747
1748 // Option for footer background color (without freetext zone)
1749 if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1750 $tmparray = sscanf(getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR'), '%d, %d, %d');
1751 $r = $tmparray[0];
1752 $g = $tmparray[1];
1753 $b = $tmparray[2];
1754 $pdf->setAutoPageBreak(false, 0); // Disable auto pagebreak
1755 $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', array(), $fill_color = array($r, $g, $b));
1756 $pdf->setAutoPageBreak(true, 0); // Restore pagebreak
1757 }
1758
1759 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1760 $pdf->setAutoPageBreak(false, 0);
1761 } // Option for disable auto pagebreak
1762 if ($line) { // Free text
1763 $pdf->SetXY($dims['lm'], -$posy);
1764 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1765 $pdf->MultiCell(0, 3, $line, 0, $align, false);
1766 } else {
1767 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1768 }
1769 $posy -= $freetextheight;
1770 }
1771 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1772 $pdf->setAutoPageBreak(true, 0);
1773 } // Restore pagebreak
1774
1775 $pdf->SetY(-$posy);
1776
1777 // Option for hide all footer (page number will no hidden)
1778 if (!getDolGlobalInt('PDF_FOOTER_HIDDEN')) {
1779 // Hide footer line if footer background color is set
1780 if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1781 $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1782 }
1783
1784 // Option for set top margin height of footer after freetext
1785 if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1786 $posy -= (float) getDolGlobalString('PDF_FOOTER_TOP_MARGIN');
1787 } else {
1788 $posy--;
1789 }
1790
1791 if (!empty($line1)) {
1792 $pdf->SetFont('', 'B', 7);
1793 $pdf->SetXY($dims['lm'], -$posy);
1794 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line1, 0, 'C', false);
1795 $posy -= 3;
1796 $pdf->SetFont('', '', 7);
1797 }
1798
1799 if (!empty($line2)) {
1800 $pdf->SetFont('', 'B', 7);
1801 $pdf->SetXY($dims['lm'], -$posy);
1802 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line2, 0, 'C', false);
1803 $posy -= 3;
1804 $pdf->SetFont('', '', 7);
1805 }
1806
1807 if (!empty($line3)) {
1808 $pdf->SetXY($dims['lm'], -$posy);
1809 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line3, 0, 'C', false);
1810 }
1811
1812 if (!empty($line4)) {
1813 $posy -= 3;
1814 $pdf->SetXY($dims['lm'], -$posy);
1815 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line4, 0, 'C', false);
1816 }
1817 }
1818 }
1819 }
1820
1821 // Show page nb and apply correction for some font.
1822 $pdf->SetXY($dims['wk'] - $dims['rm'] - 18 - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_X', 0), -$posy - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_Y', 0));
1823
1824 $pagination = $pdf->PageNo().' / '.$pdf->getAliasNbPages();
1825 $fontRenderCorrection = 0;
1826 if (in_array(pdf_getPDFFont($outputlangs), array('freemono', 'DejaVuSans'))) {
1827 $fontRenderCorrection = 10;
1828 }
1829 $pdf->MultiCell(18 + $fontRenderCorrection, 2, $pagination, 0, 'R', false);
1830
1831 // Show Draft Watermark
1832 if (!empty($watermark)) {
1833 pdf_watermark($pdf, $outputlangs, $page_hauteur, $page_largeur, 'mm', $watermark);
1834 }
1835
1836 return $marginwithfooter;
1837}
1838
1853function pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
1854{
1855 $linkedobjects = pdf_getLinkedObjects($object, $outputlangs); // May update $object->note_public
1856
1857 if (!empty($linkedobjects)) {
1858 foreach ($linkedobjects as $linkedobject) {
1859 $reftoshow = $linkedobject["ref_title"].' : '.$linkedobject["ref_value"];
1860 if (!empty($linkedobject["date_value"])) {
1861 $reftoshow .= ' / '.$linkedobject["date_value"];
1862 }
1863
1864 $posy += 3;
1865 $pdf->SetXY($posx, $posy);
1866 $pdf->SetFont('', '', (float) $default_font_size - 2);
1867 $pdf->MultiCell($w, $h, $reftoshow, '', $align);
1868 }
1869 }
1870
1871 return $pdf->getY();
1872}
1873
1891function pdf_writelinedesc($pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref = 0, $hidedesc = 0, $issupplierline = 0, $align = 'J')
1892{
1893 global $hookmanager;
1894
1895 $reshook = 0;
1896 $result = '';
1897 //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) ) )
1898 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
1899 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1900 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1901 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1902 }
1903 $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);
1904 $action = '';
1905 // WARNING: A hook must not close/open the PDF transaction. Doing this generates a lot of trouble.
1906 // Test to know if content added by the hooks is already done by the main caller of pdf_writelinedesc
1907 $reshook = $hookmanager->executeHooks('pdf_writelinedesc', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1908
1909 if (!empty($hookmanager->resPrint)) {
1910 $result .= $hookmanager->resPrint;
1911 }
1912 }
1913 if (empty($reshook)) {
1914 $labelproductservice = pdf_getlinedesc($object, $i, $outputlangs, $hideref, $hidedesc, $issupplierline);
1915 $labelproductservice = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $labelproductservice, -1, $nbrep);
1916
1917 //var_dump($labelproductservice);exit;
1918
1919 // 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"
1920 // We make the reverse, so PDF generation has the real URL.
1921 $nbrep = 0;
1922 $labelproductservice = preg_replace('/(<img[^>]*src=")([^"]*)(&amp;)([^"]*")/', '\1\2&\4', $labelproductservice, -1, $nbrep);
1923
1924 if (getDolGlobalString('MARGIN_TOP_ZERO_UL')) {
1925 $pdf->setListIndentWidth(5);
1926 $TMarginList = ['ul' => [['h' => 0.1, ],['h' => 0.1, ]], 'li' => [['h' => 0.1, ],],];
1927 $pdf->setHtmlVSpace($TMarginList);
1928 }
1929
1930 // Description
1931 $pdf->writeHTMLCell($w, $h, $posx, $posy, $outputlangs->convToOutputCharset($labelproductservice), 0, 1, false, true, $align, true);
1932 $result .= $labelproductservice;
1933 }
1934 return $result;
1935}
1936
1948function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
1949{
1950 global $db, $conf, $langs;
1951
1952 $idprod = (!empty($object->lines[$i]->fk_product) ? $object->lines[$i]->fk_product : false);
1953 $label = (!empty($object->lines[$i]->label) ? $object->lines[$i]->label : (!empty($object->lines[$i]->product_label) ? $object->lines[$i]->product_label : ''));
1954 $product_barcode = (!empty($object->lines[$i]->product_barcode) ? $object->lines[$i]->product_barcode : "");
1955 $desc = (!empty($object->lines[$i]->desc) ? $object->lines[$i]->desc : (!empty($object->lines[$i]->description) ? $object->lines[$i]->description : ''));
1956 $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
1957 $note = (!empty($object->lines[$i]->note) ? $object->lines[$i]->note : '');
1958 $dbatch = (!empty($object->lines[$i]->detail_batch) ? $object->lines[$i]->detail_batch : false);
1959
1960 $multilangsactive = getDolGlobalInt('MAIN_MULTILANGS');
1961
1962 if ($issupplierline) {
1963 include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
1964 $prodser = new ProductFournisseur($db);
1965 } else {
1966 include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
1967 $prodser = new Product($db);
1968
1969 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1970 include_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
1971 }
1972 }
1973
1974 //id
1975 $idprod = (!empty($object->lines[$i]->fk_product) ? $object->lines[$i]->fk_product : false);
1976 if ($idprod) {
1977 $prodser->fetch($idprod);
1978 //load multilangs
1979 if ($multilangsactive) {
1980 $prodser->getMultiLangs();
1981 $object->lines[$i]->multilangs = $prodser->multilangs;
1982 }
1983 }
1984 //label
1985 if (!empty($object->lines[$i]->label)) {
1986 $label = $object->lines[$i]->label;
1987 } else {
1988 if (!empty($object->lines[$i]->multilangs[$outputlangs->defaultlang]['label']) && $multilangsactive) {
1989 $label = $object->lines[$i]->multilangs[$outputlangs->defaultlang]['label'];
1990 } else {
1991 if (!empty($object->lines[$i]->product_label)) {
1992 $label = $object->lines[$i]->product_label;
1993 } else {
1994 $label = '';
1995 }
1996 }
1997 }
1998 //description
1999 if (!empty($object->lines[$i]->desc)) {
2000 $desc = $object->lines[$i]->desc;
2001 } else {
2002 if (!empty($object->lines[$i]->multilangs[$outputlangs->defaultlang]['description']) && $multilangsactive) {
2003 $desc = $object->lines[$i]->multilangs[$outputlangs->defaultlang]['description'];
2004 } else {
2005 if (!empty($object->lines[$i]->description)) {
2006 $desc = $object->lines[$i]->description;
2007 } else {
2008 $desc = '';
2009 }
2010 }
2011 }
2012 //ref supplier
2013 $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
2014 //note
2015 $note = (!empty($object->lines[$i]->note) ? $object->lines[$i]->note : '');
2016 //dbatch
2017 $dbatch = (!empty($object->lines[$i]->detail_batch) ? $object->lines[$i]->detail_batch : false);
2018
2019 if ($idprod) {
2020 // If a predefined product and multilang and on other lang, we renamed label with label translated
2021 if ($multilangsactive && ($outputlangs->defaultlang != $langs->defaultlang)) {
2022 $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)
2023
2024 // 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
2025 // ($textwasnotmodified is replaced with $textwasmodifiedorcompleted and we add completion).
2026
2027 // Set label
2028 // 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.
2029 //var_dump($outputlangs->defaultlang.' - '.$langs->defaultlang.' - '.$label.' - '.$prodser->label);exit;
2030 $textwasnotmodified = ($label == $prodser->label);
2031 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && ($textwasnotmodified || $translatealsoifmodified)) {
2032 $label = $prodser->multilangs[$outputlangs->defaultlang]["label"];
2033 }
2034
2035 // Set desc
2036 // Manage HTML entities description test because $prodser->description is store with htmlentities but $desc no
2037 $textwasnotmodified = false;
2038 $textdiffersonlybymarkup = false;
2039 if (!empty($desc) && dol_textishtml($desc) && !empty($prodser->description) && dol_textishtml($prodser->description)) {
2040 $textwasnotmodified = (strpos(dol_html_entity_decode($desc, ENT_QUOTES | ENT_HTML5), dol_html_entity_decode($prodser->description, ENT_QUOTES | ENT_HTML5)) !== false);
2041 } elseif (!empty($desc) && !empty($prodser->description) && dol_textishtml($desc) != dol_textishtml($prodser->description)) {
2042 // One side is HTML and the other is not. This happens as soon as a line is saved while the
2043 // WYSIWYG editor is enabled on line details: the plain product description becomes "<p>...</p>".
2044 // Comparing the raw strings would then report a manual change and silently drop the translation,
2045 // so compare the text content instead.
2046 $desctextonly = trim(dol_html_entity_decode(dol_string_nohtmltag($desc, 1), ENT_QUOTES | ENT_HTML5));
2047 $prodtextonly = trim(dol_html_entity_decode(dol_string_nohtmltag($prodser->description, 1), ENT_QUOTES | ENT_HTML5));
2048 $textwasnotmodified = ($prodtextonly !== '' && strpos($desctextonly, $prodtextonly) !== false);
2049 $textdiffersonlybymarkup = ($textwasnotmodified && $desctextonly === $prodtextonly);
2050 } else {
2051 $textwasnotmodified = ($desc == $prodser->description);
2052 }
2053 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["description"])) {
2054 if ($textwasnotmodified) {
2055 if ($textdiffersonlybymarkup && strpos($desc, $prodser->description) === false) {
2056 // Same text, but wrapped in tags or written with HTML entities: the product description
2057 // is not present verbatim, so the str_replace below would find nothing to replace.
2058 $desc = $prodser->multilangs[$outputlangs->defaultlang]["description"];
2059 } else {
2060 $desc = str_replace($prodser->description, $prodser->multilangs[$outputlangs->defaultlang]["description"], $desc);
2061 }
2062 } elseif ($translatealsoifmodified) {
2063 $desc = $prodser->multilangs[$outputlangs->defaultlang]["description"];
2064 }
2065 }
2066
2067 // Set note
2068 $textwasnotmodified = ($note == $prodser->note_public);
2069 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["other"]) && ($textwasnotmodified || $translatealsoifmodified)) {
2070 $note = $prodser->multilangs[$outputlangs->defaultlang]["other"];
2071 }
2072 }
2073 } 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
2074 $desc = str_replace('(DEPOSIT)', $outputlangs->trans('Deposit'), $desc);
2075 }
2076
2077 $labelproductservice = ''; // Default value
2078 if (!getDolGlobalString('PDF_HIDE_PRODUCT_LABEL_IN_SUPPLIER_LINES')) {
2079 // Description short of product line
2080 $labelproductservice = $label;
2081 if (!empty($labelproductservice) && getDolGlobalString('PDF_BOLD_PRODUCT_LABEL')) {
2082 // Adding <b> may convert the original string into a HTML string. So we have to first
2083 // convert \n into <br> we text is not already HTML.
2084 if (!dol_textishtml($labelproductservice)) {
2085 $labelproductservice = str_replace("\n", '<br>', $labelproductservice);
2086 }
2087 $labelproductservice = '<b>'.$labelproductservice.'</b>';
2088 }
2089 }
2090
2091
2092 // Add ref of subproducts
2093 if (getDolGlobalString('SHOW_SUBPRODUCT_REF_IN_PDF')) {
2094 $prodser->get_sousproduits_arbo();
2095 if (!empty($prodser->sousprods) && is_array($prodser->sousprods) && count($prodser->sousprods)) {
2096 $outputlangs->load('mrp');
2097 $tmparrayofsubproducts = reset($prodser->sousprods);
2098
2099 $qtyText = null;
2100 if (isset($object->lines[$i]->qty) && !empty($object->lines[$i]->qty)) {
2101 $qtyText = $object->lines[$i]->qty;
2102 } elseif (isset($object->lines[$i]->qty_shipped) && !empty($object->lines[$i]->qty_shipped)) {
2103 $qtyText = $object->lines[$i]->qty;
2104 }
2105
2106 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF')) {
2107 foreach ($tmparrayofsubproducts as $subprodval) {
2108 $labelproductservice = dol_concatdesc(
2109 dol_concatdesc($labelproductservice, " * ".$subprodval[3]),
2110 (!empty($qtyText) ?
2111 $outputlangs->trans('Qty').':'.$qtyText.' x '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1].'= '.$outputlangs->trans('QtyTot').':'.$subprodval[1] * $qtyText :
2112 $outputlangs->trans('Qty').' '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1])
2113 );
2114 }
2115 } else {
2116 foreach ($tmparrayofsubproducts as $subprodval) {
2117 $labelproductservice = dol_concatdesc(
2118 dol_concatdesc($labelproductservice, " * ".$subprodval[5].(($subprodval[5] && $subprodval[3]) ? ' - ' : '').$subprodval[3]),
2119 (!empty($qtyText) ?
2120 $outputlangs->trans('Qty').':'.$qtyText.' x '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1].'= '.$outputlangs->trans('QtyTot').':'.$subprodval[1] * $qtyText :
2121 $outputlangs->trans('Qty').' '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1])
2122 );
2123 }
2124 }
2125 }
2126 }
2127
2128 if (isModEnabled('barcode') && getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_PRODUCT_BARCODE') && !empty($product_barcode)) {
2129 $labelproductservice = dol_concatdesc($labelproductservice, $outputlangs->trans("BarCode")." ".$product_barcode);
2130 }
2131
2132 // Description long of product line
2133 if (!empty($desc) && ($desc != $label)) {
2134 if ($desc == '(CREDIT_NOTE)' && $object->lines[$i]->fk_remise_except) {
2135 $discount = new DiscountAbsolute($db);
2136 $discount->fetch($object->lines[$i]->fk_remise_except);
2137 $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
2138 $labelproductservice = $outputlangs->transnoentitiesnoconv("DiscountFromCreditNote", $sourceref);
2139 } elseif ($desc == '(DEPOSIT)' && $object->lines[$i]->fk_remise_except) {
2140 $discount = new DiscountAbsolute($db);
2141 $discount->fetch($object->lines[$i]->fk_remise_except);
2142 $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
2143 $labelproductservice = $outputlangs->transnoentitiesnoconv("DiscountFromDeposit", $sourceref);
2144 // Add date of deposit
2145 if (getDolGlobalString('INVOICE_ADD_DEPOSIT_DATE')) {
2146 $labelproductservice .= ' ('.dol_print_date($discount->datec, 'day', '', $outputlangs).')';
2147 }
2148 } elseif ($desc == '(EXCESS RECEIVED)' && $object->lines[$i]->fk_remise_except) {
2149 $discount = new DiscountAbsolute($db);
2150 $discount->fetch($object->lines[$i]->fk_remise_except);
2151 $labelproductservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessReceived", $discount->ref_facture_source);
2152 } elseif ($desc == '(EXCESS PAID)' && $object->lines[$i]->fk_remise_except) {
2153 $discount = new DiscountAbsolute($db);
2154 $discount->fetch($object->lines[$i]->fk_remise_except);
2155 $labelproductservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessPaid", $discount->ref_invoice_supplier_source);
2156 } else {
2157 if ($idprod) {
2158 // Check if description must be output
2159 if (!empty($object->element)) {
2160 $tmpkey = 'MAIN_DOCUMENTS_HIDE_DESCRIPTION_FOR_'.strtoupper($object->element);
2161 if (getDolGlobalString($tmpkey)) {
2162 $hidedesc = 1;
2163 }
2164 }
2165 if (empty($hidedesc)) {
2166 if (getDolGlobalString('MAIN_DOCUMENTS_DESCRIPTION_FIRST')) {
2167 $labelproductservice = dol_concatdesc($desc, $labelproductservice);
2168 } else {
2169 if (getDolGlobalString('HIDE_LABEL_VARIANT_PDF') && $prodser->isVariant()) {
2170 $labelproductservice = $desc;
2171 } else {
2172 $labelproductservice = dol_concatdesc($labelproductservice, $desc);
2173 }
2174 }
2175 }
2176 } else {
2177 $labelproductservice = dol_concatdesc($labelproductservice, $desc);
2178 }
2179 }
2180 }
2181
2182 // We add ref of product (and supplier ref if defined)
2183 $prefix_prodserv = "";
2184 $ref_prodserv = "";
2185 if (getDolGlobalString('PRODUCT_ADD_TYPE_IN_DOCUMENTS')) { // In standard mode, we do not show this
2186 if ($prodser->isService()) {
2187 $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service")." ";
2188 } else {
2189 $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Product")." ";
2190 }
2191 }
2192
2193 if (empty($hideref)) {
2194 if ($issupplierline) {
2195 if (!getDolGlobalString('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES')) { // Common case
2196 $ref_prodserv = $prodser->ref; // Show local ref
2197 if ($ref_supplier) {
2198 $ref_prodserv .= ($prodser->ref ? ' (' : '').$outputlangs->transnoentitiesnoconv("SupplierRef").' '.$ref_supplier.($prodser->ref ? ')' : '');
2199 }
2200 } elseif (getDolGlobalInt('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES') == 1) {
2201 $ref_prodserv = $ref_supplier;
2202 } elseif (getDolGlobalInt('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES') == 2) {
2203 $ref_prodserv = $ref_supplier.' ('.$outputlangs->transnoentitiesnoconv("InternalRef").' '.$prodser->ref.')';
2204 }
2205 } else {
2206 $ref_prodserv = $prodser->ref; // Show local ref only
2207
2208 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
2209 $productCustomerPriceStatic = new ProductCustomerPrice($db);
2210 $filter = array('fk_product' => (string) $idprod, 'fk_soc' => (string) $object->socid);
2211
2212 $nbCustomerPrices = $productCustomerPriceStatic->fetchAll('', '', 1, 0, $filter);
2213
2214 if ($nbCustomerPrices > 0) {
2215 $productCustomerPrice = null;
2216 if (count($productCustomerPriceStatic->lines) > 0) {
2217 $date_now = (int) floor(dol_now() / 86400) * 86400; // date without hours
2218 foreach ($productCustomerPriceStatic->lines as $k => $custprice_line) {
2219 if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
2220 $productCustomerPrice = $custprice_line;
2221 break;
2222 }
2223 }
2224 }
2225
2226 if (isset($productCustomerPrice) && !empty($productCustomerPrice->ref_customer)) {
2227 $idcustprice = getDolGlobalInt('PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE');
2228 switch ($idcustprice) {
2229 case 1:
2230 $ref_prodserv = $productCustomerPrice->ref_customer;
2231 break;
2232
2233 case 2:
2234 $ref_prodserv = $productCustomerPrice->ref_customer . ' (' . $outputlangs->transnoentitiesnoconv('InternalRef') . ' ' . $ref_prodserv . ')';
2235 break;
2236
2237 default:
2238 $ref_prodserv = $ref_prodserv . ' (' . $outputlangs->transnoentitiesnoconv('RefCustomer') . ' ' . $productCustomerPrice->ref_customer . ')';
2239 }
2240 }
2241 }
2242 }
2243 }
2244
2245 if (!empty($labelproductservice) && !empty($ref_prodserv)) {
2246 $ref_prodserv .= " - ";
2247 }
2248 }
2249
2250 if (!empty($ref_prodserv) && getDolGlobalString('PDF_BOLD_PRODUCT_REF_AND_PERIOD')) {
2251 if (!dol_textishtml($labelproductservice)) {
2252 $labelproductservice = str_replace("\n", '<br>', $labelproductservice);
2253 }
2254 $ref_prodserv = '<b>'.$ref_prodserv.'</b>';
2255 // $prefix_prodserv and $ref_prodser are not HTML var
2256 }
2257 $labelproductservice = $prefix_prodserv.$ref_prodserv.$labelproductservice;
2258
2259 // Add an additional description for the category products
2260 if (getDolGlobalString('CATEGORY_ADD_DESC_INTO_DOC') && $idprod && isModEnabled('category')) {
2261 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
2262 $categstatic = new Categorie($db);
2263 // recovering the list of all the categories linked to product
2264 $tblcateg = $categstatic->containing($idprod, Categorie::TYPE_PRODUCT);
2265 foreach ($tblcateg as $cate) {
2266 // Adding the descriptions if they are filled
2267 $desccateg = $cate->description;
2268 if ($desccateg) {
2269 $labelproductservice = dol_concatdesc($labelproductservice, $desccateg);
2270 }
2271 }
2272 }
2273
2274 if (!empty($object->lines[$i]->date_start) || !empty($object->lines[$i]->date_end)) {
2275 $format = 'day';
2276 $period = '';
2277 // Show duration if exists
2278 if ($object->lines[$i]->date_start && $object->lines[$i]->date_end) {
2279 $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)).')';
2280 }
2281 if ($object->lines[$i]->date_start && !$object->lines[$i]->date_end) {
2282 $period = '('.$outputlangs->transnoentitiesnoconv('DateFrom', dol_print_date($object->lines[$i]->date_start, $format, false, $outputlangs)).')';
2283 }
2284 if (!$object->lines[$i]->date_start && $object->lines[$i]->date_end) {
2285 $period = '('.$outputlangs->transnoentitiesnoconv('DateUntil', dol_print_date($object->lines[$i]->date_end, $format, false, $outputlangs)).')';
2286 }
2287 //print '>'.$outputlangs->charset_output.','.$period;
2288 if (getDolGlobalString('PDF_BOLD_PRODUCT_REF_AND_PERIOD')) {
2289 if (!dol_textishtml($labelproductservice)) {
2290 $labelproductservice = str_replace("\n", '<br>', $labelproductservice);
2291 }
2292 $labelproductservice .= '<br><b style="color:#333666;" ><em>'.$period.'</em></b>';
2293 } else {
2294 $labelproductservice = dol_concatdesc($labelproductservice, $period);
2295 }
2296 //print $labelproductservice;
2297 }
2298
2299 // Show information for lot
2300 if (!empty($dbatch)) {
2301 // $object is a shipment.
2302 //var_dump($object->lines[$i]->details_entrepot); // array from llx_expeditiondet (we can have several lines for one fk_origin_line)
2303 //var_dump($object->lines[$i]->detail_batch); // array from llx_expeditiondet_batch (each line with a lot is linked to llx_expeditiondet)
2304
2305 include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
2306 include_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
2307 $tmpwarehouse = new Entrepot($db);
2308 $tmpproductbatch = new Productbatch($db);
2309
2310 $format = 'day';
2311 foreach ($dbatch as $detail) {
2312 $dte = array();
2313 if ($detail->eatby) {
2314 $dte[] = $outputlangs->transnoentitiesnoconv('printEatby', dol_print_date($detail->eatby, $format, false, $outputlangs));
2315 }
2316 if ($detail->sellby) {
2317 $dte[] = $outputlangs->transnoentitiesnoconv('printSellby', dol_print_date($detail->sellby, $format, false, $outputlangs));
2318 }
2319 if ($detail->batch) {
2320 $dte[] = $outputlangs->transnoentitiesnoconv('printBatch', $detail->batch);
2321 }
2322 if ($detail->qty) {
2323 $dte[] = $outputlangs->transnoentitiesnoconv('printQty', (string) $detail->qty);
2324 }
2325
2326 // Add also info of planned warehouse for lot
2327 if ($object->element == 'shipping' && $detail->fk_origin_stock > 0 && getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
2328 $resproductbatch = $tmpproductbatch->fetch($detail->fk_origin_stock);
2329 if ($resproductbatch > 0) {
2330 $reswarehouse = $tmpwarehouse->fetch($tmpproductbatch->warehouseid);
2331 if ($reswarehouse > 0) {
2332 $dte[] = $tmpwarehouse->ref;
2333 }
2334 }
2335 }
2336
2337 $labelproductservice .= "__N__ ".implode(" - ", $dte);
2338 }
2339 } else {
2340 if (getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
2341 // TODO Show warehouse for shipment line without batch
2342 }
2343 }
2344
2345 // Now we convert \n into br
2346 if (dol_textishtml($labelproductservice)) {
2347 $labelproductservice = preg_replace('/__N__/', '<br>', $labelproductservice);
2348 } else {
2349 $labelproductservice = preg_replace('/__N__/', "\n", $labelproductservice);
2350 }
2351 $labelproductservice = dol_htmlentitiesbr($labelproductservice, 1);
2352
2353 return $labelproductservice;
2354}
2355
2365function pdf_getlinenum($object, $i, $outputlangs, $hidedetails = 0)
2366{
2367 global $hookmanager;
2368
2369 $reshook = 0;
2370 $result = '';
2371 //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) ) )
2372 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
2373 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2374 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2375 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2376 }
2377 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2378 $action = '';
2379 $reshook = $hookmanager->executeHooks('pdf_getlinenum', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2380 $result .= $hookmanager->resPrint;
2381 }
2382 if (empty($reshook)) {
2383 $result .= dol_htmlentitiesbr($object->lines[$i]->num);
2384 }
2385 return $result;
2386}
2387
2388
2398function pdf_getlineref($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('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2411 $action = '';
2412 $reshook = $hookmanager->executeHooks('pdf_getlineref', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2413 $result .= $hookmanager->resPrint;
2414 }
2415 if (empty($reshook)) {
2416 $result .= dol_htmlentitiesbr($object->lines[$i]->product_ref);
2417 }
2418 return $result;
2419}
2420
2421
2431function pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails = 0)
2432{
2433 global $hookmanager;
2434
2435 $reshook = 0;
2436 $result = '';
2437 //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) ) )
2438 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
2439 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2440 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2441 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2442 }
2443 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2444 $action = '';
2445 $reshook = $hookmanager->executeHooks('pdf_getlineref_supplier', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2446 $result .= $hookmanager->resPrint;
2447 }
2448 if (empty($reshook)) {
2449 $result .= dol_htmlentitiesbr($object->lines[$i]->ref_supplier);
2450 }
2451 return $result;
2452}
2453
2463function pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails = 0)
2464{
2465 global $conf, $hookmanager, $mysoc;
2466
2467 $result = '';
2468 $reshook = 0;
2469 //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) ) )
2470 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
2471 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2472 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2473 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2474 }
2475 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2476 $action = '';
2477 $reshook = $hookmanager->executeHooks('pdf_getlinevatrate', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2478
2479 if (!empty($hookmanager->resPrint)) {
2480 $result .= $hookmanager->resPrint;
2481 }
2482 }
2483 if (empty($reshook)) {
2484 if (empty($hidedetails) || $hidedetails > 1) {
2485 $tmpresult = '';
2486
2487 $tmpresult .= vatrate($object->lines[$i]->tva_tx, false, $object->lines[$i]->info_bits, -1);
2488 if (!getDolGlobalString('MAIN_PDF_MAIN_HIDE_SECOND_TAX')) {
2489 if (price2num($object->lines[$i]->localtax1_tx)) {
2490 if (preg_replace('/[\s0%]/', '', $tmpresult)) {
2491 $tmpresult .= '/';
2492 } else {
2493 $tmpresult = '';
2494 }
2495 $tmpresult .= vatrate((string) abs($object->lines[$i]->localtax1_tx), false);
2496 }
2497 }
2498 if (!getDolGlobalString('MAIN_PDF_MAIN_HIDE_THIRD_TAX')) {
2499 if (price2num($object->lines[$i]->localtax2_tx)) {
2500 if (preg_replace('/[\s0%]/', '', $tmpresult)) {
2501 $tmpresult .= '/';
2502 } else {
2503 $tmpresult = '';
2504 }
2505 $tmpresult .= vatrate((string) abs($object->lines[$i]->localtax2_tx), false);
2506 }
2507 }
2508 $tmpresult .= '%';
2509
2510 $result .= $tmpresult;
2511 }
2512 }
2513 return $result;
2514}
2515
2525function pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails = 0)
2526{
2527 global $hookmanager;
2528
2529 $sign = 1;
2530 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2531 $sign = -1;
2532 }
2533
2534 $result = '';
2535 $reshook = 0;
2536 //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) ) )
2537 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
2538 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2539 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2540 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2541 }
2542 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2543 $action = '';
2544 $reshook = $hookmanager->executeHooks('pdf_getlineupexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2545
2546 if (!empty($hookmanager->resPrint)) {
2547 $result .= $hookmanager->resPrint;
2548 }
2549 }
2550 if (empty($reshook)) {
2551 if (empty($hidedetails) || $hidedetails > 1) {
2552 $subprice = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice);
2553 $result .= price($sign * $subprice, 0, $outputlangs);
2554 }
2555 }
2556 return $result;
2557}
2558
2568function pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails = 0)
2569{
2570 global $hookmanager;
2571
2572 $sign = 1;
2573 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2574 $sign = -1;
2575 }
2576
2577 $result = '';
2578 $reshook = 0;
2579 //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) ) )
2580 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
2581 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2582 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2583 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2584 }
2585 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2586 $action = '';
2587 $reshook = $hookmanager->executeHooks('pdf_getlineupwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2588
2589 if (!empty($hookmanager->resPrint)) {
2590 $result .= $hookmanager->resPrint;
2591 }
2592 }
2593 if (empty($reshook)) {
2594 if (empty($hidedetails) || $hidedetails > 1) {
2595 $result .= price($sign * (($object->lines[$i]->subprice) + ($object->lines[$i]->subprice) * ($object->lines[$i]->tva_tx) / 100), 0, $outputlangs);
2596 }
2597 }
2598 return $result;
2599}
2600
2610function pdf_getlineqty($object, $i, $outputlangs, $hidedetails = 0)
2611{
2612 global $hookmanager;
2613
2614 $result = '';
2615 $reshook = 0;
2616 //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) ) )
2617 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
2618 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2619 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2620 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2621 }
2622 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2623 $action = '';
2624 $reshook = $hookmanager->executeHooks('pdf_getlineqty', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2625
2626 if (!empty($hookmanager->resPrint)) {
2627 $result = $hookmanager->resPrint;
2628 }
2629 }
2630 if (empty($reshook)) {
2631 if ($object->lines[$i]->special_code == 3) {
2632 return '';
2633 }
2634 if (empty($hidedetails) || $hidedetails > 1) {
2635 $result .= $object->lines[$i]->qty;
2636 }
2637 }
2638 return $result;
2639}
2640
2650function pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails = 0)
2651{
2652 global $hookmanager;
2653
2654 $reshook = 0;
2655 $result = '';
2656 //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) ) )
2657 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
2658 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2659 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2660 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2661 }
2662 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2663 $action = '';
2664 $reshook = $hookmanager->executeHooks('pdf_getlineqty_asked', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2665
2666 if (!empty($hookmanager->resPrint)) {
2667 $result .= $hookmanager->resPrint;
2668 }
2669 }
2670 if (empty($reshook)) {
2671 if ($object->lines[$i]->special_code == 3) {
2672 return '';
2673 }
2674 if (empty($hidedetails) || $hidedetails > 1) {
2675 $result .= $object->lines[$i]->qty_asked;
2676 }
2677 }
2678 return $result;
2679}
2680
2690function pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails = 0)
2691{
2692 global $hookmanager;
2693
2694 $reshook = 0;
2695 $result = '';
2696 //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) ) )
2697 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
2698 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2699 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2700 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2701 }
2702 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2703 $action = '';
2704 $reshook = $hookmanager->executeHooks('pdf_getlineqty_shipped', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2705
2706 if (!empty($hookmanager->resPrint)) {
2707 $result .= $hookmanager->resPrint;
2708 }
2709 }
2710 if (empty($reshook)) {
2711 if ($object->lines[$i]->special_code == 3) {
2712 return '';
2713 }
2714 if (empty($hidedetails) || $hidedetails > 1) {
2715 $result .= $object->lines[$i]->qty_shipped;
2716 }
2717 }
2718 return $result;
2719}
2720
2730function pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails = 0)
2731{
2732 global $hookmanager;
2733
2734 $reshook = 0;
2735 $result = '';
2736 //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) ) )
2737 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
2738 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2739 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) { // @phan-suppress-current-line PhanUndeclaredProperty
2740 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2741 }
2742 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2743 $action = '';
2744 $reshook = $hookmanager->executeHooks('pdf_getlineqty_keeptoship', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2745
2746 if (!empty($hookmanager->resPrint)) {
2747 $result .= $hookmanager->resPrint;
2748 }
2749 }
2750 if (empty($reshook)) {
2751 if ($object->lines[$i]->special_code == 3) {
2752 return '';
2753 }
2754 if (empty($hidedetails) || $hidedetails > 1) {
2755 $result .= ($object->lines[$i]->qty_asked - $object->lines[$i]->qty_shipped);
2756 }
2757 }
2758 return $result;
2759}
2760
2770function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0)
2771{
2772 global $hookmanager;
2773
2774 $reshook = 0;
2775 $result = '';
2776 //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) ) )
2777 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
2778 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2779 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2780 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2781 }
2782 $parameters = array(
2783 'i' => $i,
2784 'outputlangs' => $outputlangs,
2785 'hidedetails' => $hidedetails,
2786 'special_code' => $special_code
2787 );
2788 $action = '';
2789 $reshook = $hookmanager->executeHooks('pdf_getlineunit', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2790
2791 if (!empty($hookmanager->resPrint)) {
2792 $result .= $hookmanager->resPrint;
2793 }
2794 }
2795 if (empty($reshook)) {
2796 if (empty($hidedetails) || $hidedetails > 1) {
2797 $result .= $object->lines[$i]->getLabelOfUnit('short', $outputlangs, 1);
2798 }
2799 }
2800 return $result;
2801}
2802
2803
2813function pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails = 0)
2814{
2815 global $hookmanager;
2816
2817 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
2818
2819 $reshook = 0;
2820 $result = '';
2821 //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) ) )
2822 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
2823 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2824 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2825 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2826 }
2827 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2828 $action = '';
2829 $reshook = $hookmanager->executeHooks('pdf_getlineremisepercent', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2830
2831 if (!empty($hookmanager->resPrint)) {
2832 $result .= $hookmanager->resPrint;
2833 }
2834 }
2835 if (empty($reshook)) {
2836 if ($object->lines[$i]->special_code == 3) {
2837 return '';
2838 }
2839 if (empty($hidedetails) || $hidedetails > 1) {
2840 $result .= dol_print_reduction($object->lines[$i]->remise_percent, $outputlangs);
2841 }
2842 }
2843 return $result;
2844}
2845
2856function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = null)
2857{
2858 if (empty($hookmanager)) {
2859 global $hookmanager;
2860 }
2861
2862 $reshook = 0;
2863 $result = '';
2864 //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) ) )
2865 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
2866 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2867 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2868 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2869 }
2870 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2871 $action = '';
2872 $reshook = $hookmanager->executeHooks('pdf_getlineprogress', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2873
2874 if (!empty($hookmanager->resPrint)) {
2875 return $hookmanager->resPrint;
2876 }
2877 }
2878 if (empty($reshook)) {
2879 if ($object->lines[$i]->special_code == 3) {
2880 return '';
2881 }
2882 if (empty($hidedetails) || $hidedetails > 1) {
2883 // 2 = situation_percent is non-cumulative (delta of current situation)
2884 // 1 = (old mode): situation_percent is cumulative (state at situation)
2885 $isCumulative = getDolGlobalInt('INVOICE_USE_SITUATION') === 1;
2886 $showDelta = (bool) getDolGlobalInt('SITUATION_DISPLAY_DIFF_ON_PDF');
2887
2888 if ($isCumulative xor $showDelta) {
2889 // Either:
2890 // - old mode and we want to show a total or
2891 // - new mode and we want to show a delta
2892 $result = $object->lines[$i]->situation_percent;
2893 } else {
2894 // Either:
2895 // - old mode but we want to show a delta or
2896 // - new mode but we want to show a total
2897 $prev_progress = 0;
2898 if ($isCumulative) {
2899 // old mode: the previous line already holds the running total
2900 if (method_exists($object->lines[$i], 'get_prev_progress')) {
2901 $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2902 }
2903 } else {
2904 // new mode: each line holds its own delta, so we must sum every previous one.
2905 // get_prev_progress() only reads the line pointed by fk_prev_id, which is the last
2906 // delta and not the accumulated progress, so it under-reports from the third
2907 // situation on. getAllPrevProgress() walks the whole fk_prev_id chain, and it is
2908 // what the screen uses to compute the same value.
2909 if (method_exists($object->lines[$i], 'getAllPrevProgress')) {
2910 $prev_progress = $object->lines[$i]->getAllPrevProgress($object->id);
2911 } elseif (method_exists($object->lines[$i], 'get_prev_progress')) {
2912 $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2913 }
2914 }
2915 $result = $isCumulative ?
2916 // old mode: we need to compute the delta (total - sum of previous)
2917 $object->lines[$i]->situation_percent - $prev_progress :
2918 // new mode: we need to compute the total (sum of previous + delta)
2919 $prev_progress + $object->lines[$i]->situation_percent;
2920 }
2921 $result = round($result, 1).'%';
2922 }
2923 }
2924 return $result;
2925}
2926
2936function pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails = 0)
2937{
2938 global $hookmanager;
2939
2940 $sign = 1;
2941 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2942 $sign = -1;
2943 }
2944
2945 $reshook = 0;
2946 $result = '';
2947 //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) ) )
2948 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
2949 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2950 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2951 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2952 }
2953 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code, 'sign' => $sign);
2954 $action = '';
2955 $reshook = $hookmanager->executeHooks('pdf_getlinetotalexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2956
2957 if (!empty($hookmanager->resPrint)) {
2958 $result .= $hookmanager->resPrint;
2959 }
2960 }
2961 if (empty($reshook)) {
2962 if (!empty($object->lines[$i]) && $object->lines[$i]->special_code == 3) {
2963 $result .= $outputlangs->transnoentities("Option");
2964 } elseif (empty($hidedetails) || $hidedetails > 1) {
2965 $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
2966 if (!empty($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
2967 if (method_exists($object->lines[$i], 'getSituationRatio')) {
2968 $total_ht *= $object->lines[$i]->getSituationRatio();
2969 }
2970 }
2971 $result .= price($sign * $total_ht, 0, $outputlangs);
2972 }
2973 }
2974 return $result;
2975}
2976
2986function pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails = 0)
2987{
2988 global $hookmanager;
2989
2990 $sign = 1;
2991 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2992 $sign = -1;
2993 }
2994
2995 $reshook = 0;
2996 $result = '';
2997 //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) ) )
2998 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
2999 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
3000 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
3001 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
3002 }
3003 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
3004 $action = '';
3005 $reshook = $hookmanager->executeHooks('pdf_getlinetotalwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
3006
3007 if (!empty($hookmanager->resPrint)) {
3008 $result .= $hookmanager->resPrint;
3009 }
3010 }
3011 if (empty($reshook)) {
3012 if ($object->lines[$i]->special_code == 3) {
3013 $result .= $outputlangs->transnoentities("Option");
3014 } elseif (empty($hidedetails) || $hidedetails > 1) {
3015 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ttc : $object->lines[$i]->total_ttc);
3016 if (isset($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
3017 $total_ttc *= $object->lines[$i]->getSituationRatio();
3018 }
3019 $result .= price($sign * $total_ttc, 0, $outputlangs);
3020 }
3021 }
3022 return $result;
3023}
3024
3035function canDisplayLinkedObjectInPDF($object, $elementobject)
3036{
3037 $objectSocId = getObjectSocId($object);
3038 $elementSocId = getObjectSocId($elementobject);
3039
3040 if (getDolGlobalBool("PDF_ALLOW_DISPLAY_LINKED_OBJECT_FOR_OTHER_SOC")) {
3041 return true;
3042 }
3043
3044 if (!empty($objectSocId) && !empty($elementSocId) && $objectSocId != $elementSocId) {
3045 return false;
3046 }
3047
3048 return true;
3049}
3050
3059function pdf_getLinkedObjects($object, $outputlangs)
3060{
3061 global $db, $hookmanager;
3062
3063 $linkedobjects = array();
3064
3065 $object->fetchObjectLinked();
3066
3067 foreach ($object->linkedObjects as $objecttype => $objects) {
3068 if ($objecttype == 'facture') {
3069 // 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.
3070 } elseif ($objecttype == 'propal' || $objecttype == 'supplier_proposal') {
3071 '@phan-var-force array<Propal|SupplierProposal> $objects';
3073 $outputlangs->load('propal');
3074
3075 foreach ($objects as $elementobject) {
3076 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefProposal");
3077 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
3078 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DatePropal");
3079 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
3080 }
3081 } elseif ($objecttype == 'commande' || $objecttype == 'supplier_order' || $objecttype == 'order_supplier') {
3082 $optiontohidelinkedorders = "PDF_HIDE_LINKED_ORDERS_ON_SAME_THIRDPARTY";
3083 if ($objecttype == 'supplier_order' || $objecttype == 'order_supplier') {
3084 $optiontohidelinkedorders = "PDF_HIDE_LINKED_PURCHASE_ORDERS_ON_SAME_THIRDPARTY";
3085 }
3086 '@phan-var-force array<Commande|CommandeFournisseur> $objects';
3087 $outputlangs->load('orders');
3088
3089 if (count($objects) > 1 && count($objects) <= getDolGlobalInt("MAXREFONDOC", 10) && !getDolGlobalString($optiontohidelinkedorders)) {
3090 if (empty($object->context['DolPublicNoteAppendedGetLinkedObjects'])) { // Check if already appended before add to avoid repeat data
3091 $outputList = '';
3092 foreach ($objects as $elementobject) {
3093 if (canDisplayLinkedObjectInPDF($object, $elementobject)) {
3094 $outputList = dol_concatdesc($outputList, $outputlangs->transnoentities($elementobject->ref) . (empty($elementobject->ref_client) ? '' : ' (' . $elementobject->ref_client . ')') . (empty($elementobject->ref_supplier) ? '' : ' (' . $elementobject->ref_supplier . ')') . ' ');
3095 $outputList = dol_concatdesc($outputList, $outputlangs->transnoentities("OrderDate") . ' : ' . dol_print_date($elementobject->date, 'day', '', $outputlangs));
3096 }
3097 }
3098
3099 if (!empty($outputList)) {
3100 $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("RefOrder").' :');
3101 $object->note_public = dol_concatdesc($object->note_public, $outputList);
3102 }
3103 }
3104 } elseif (count($objects) == 1 && !getDolGlobalString($optiontohidelinkedorders)) {
3105 $elementobject = array_shift($objects);
3106 if (canDisplayLinkedObjectInPDF($object, $elementobject)) {
3107 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder");
3108 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref).(!empty($elementobject->ref_client) ? ' ('.$elementobject->ref_client.')' : '').(!empty($elementobject->ref_supplier) ? ' ('.$elementobject->ref_supplier.')' : '');
3109 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("OrderDate");
3110 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
3111 }
3112 }
3113 } elseif ($objecttype == 'contrat') {
3114 '@phan-var-force Contrat[] $objects';
3115 $outputlangs->load('contracts');
3116 foreach ($objects as $elementobject) {
3117 if (canDisplayLinkedObjectInPDF($object, $elementobject)) {
3118 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefContract");
3119 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
3120 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DateContract");
3121 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date_contrat, 'day', '', $outputlangs);
3122 }
3123 }
3124 } elseif ($objecttype == 'fichinter') {
3125 '@phan-var-force Fichinter[] $objects';
3126 $outputlangs->load('interventions');
3127 foreach ($objects as $elementobject) {
3128 if (canDisplayLinkedObjectInPDF($object, $elementobject)) {
3129 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("InterRef");
3130 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
3131 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("InterDate");
3132 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->datec, 'day', '', $outputlangs);
3133 }
3134 }
3135 } elseif ($objecttype == 'shipping') {
3136 '@phan-var-force Expedition[] $objects';
3137 $outputlangs->loadLangs(array("orders", "sendings"));
3138
3139 if (count($objects) > 1) {
3140 $order = null;
3141
3142 $refListsTxt = '';
3143 if (empty($object->linkedObjects['commande']) && $object->element != 'commande') {
3144 $refListsTxt .= $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending").' :';
3145 } else {
3146 $refListsTxt .= $outputlangs->transnoentities("RefSending").' :';
3147 }
3148 // We concat this record info into fields xxx_value. title is overwrote.
3149 foreach ($objects as $elementobject) {
3150 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
3151 $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
3152 if (!empty($elementobject->linkedObjectsIds['commande'])) {
3153 include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
3154 $order = new Commande($db);
3155 $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
3156 if ($ret < 1) {
3157 $order = null;
3158 }
3159 }
3160 }
3161 $refListsTxt .= (!empty($refListsTxt) ? ' ' : '');
3162 if (! is_object($order)) {
3163 $refListsTxt .= $outputlangs->transnoentities($elementobject->ref);
3164 } else {
3165 $refListsTxt .= $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
3166 $refListsTxt .= ' / '.$outputlangs->transnoentities($elementobject->ref);
3167 }
3168 }
3169
3170 if (empty($object->context['DolPublicNoteAppendedGetLinkedObjects']) && !getDolGlobalString("PDF_HIDE_LINKED_OBJECT_IN_PUBLIC_NOTE")) { // Check if already appended before add to avoid repeat data
3171 $object->note_public = dol_concatdesc($object->note_public, $refListsTxt);
3172 }
3173 } elseif (count($objects) == 1) {
3174 $elementobject = array_shift($objects);
3175 $order = null;
3176 // We concat this record info into fields xxx_value. title is overwrote.
3177 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
3178 $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
3179 if (!empty($elementobject->linkedObjectsIds['commande'])) {
3180 include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
3181 $order = new Commande($db);
3182 $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
3183 if ($ret < 1) {
3184 $order = null;
3185 }
3186 }
3187 }
3188
3189 if (! is_object($order)) {
3190 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefSending");
3191 if (empty($linkedobjects[$objecttype]['ref_value'])) {
3192 $linkedobjects[$objecttype]['ref_value'] = '';
3193 } else {
3194 $linkedobjects[$objecttype]['ref_value'] .= ' / ';
3195 }
3196 $linkedobjects[$objecttype]['ref_value'] .= $outputlangs->transnoentities($elementobject->ref);
3197 $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
3198 } else {
3199 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending");
3200 if (empty($linkedobjects[$objecttype]['ref_value'])) {
3201 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
3202 }
3203 $linkedobjects[$objecttype]['ref_value'] .= ' / '.$outputlangs->transnoentities($elementobject->ref);
3204 $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
3205 }
3206 }
3207 }
3208 }
3209
3210 $object->context['DolPublicNoteAppendedGetLinkedObjects'] = 1;
3211
3212 // For add external linked objects
3213 if (is_object($hookmanager)) {
3214 $parameters = array('linkedobjects' => $linkedobjects, 'outputlangs' => $outputlangs);
3215 $action = '';
3216 $reshook = $hookmanager->executeHooks('pdf_getLinkedObjects', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
3217 if (empty($reshook)) {
3218 $linkedobjects = array_replace($linkedobjects, $hookmanager->resArray); // array_replace is used to preserve keys
3219 } elseif ($reshook > 0) {
3220 // The array must be reinserted even if it is empty because clearing the array could be one of the actions performed by the hook.
3221 $linkedobjects = $hookmanager->resArray;
3222 }
3223 }
3224
3225 return $linkedobjects;
3226}
3227
3235function pdf_getSizeForImage($realpath)
3236{
3237 $maxwidth = getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20);
3238 $maxheight = getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT', 32);
3239
3240 include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
3241 $tmp = dol_getImageSize($realpath);
3242 $width = 0;
3243 $height = 0;
3244 if ($tmp['height']) {
3245 $width = (int) round($maxheight * $tmp['width'] / $tmp['height']); // I try to use maxheight
3246 if ($width > $maxwidth) { // Pb with maxheight, so i use maxwidth
3247 $width = $maxwidth;
3248 $height = (int) round($maxwidth * $tmp['height'] / $tmp['width']);
3249 } else { // No pb with maxheight
3250 $height = $maxheight;
3251 }
3252 }
3253 return array('width' => $width, 'height' => $height);
3254}
3255
3267function pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails = 0, $multicurrency = 0)
3268{
3269 global $hookmanager;
3270
3271 $sign = 1;
3272 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
3273 $sign = -1;
3274 }
3275 if ($object->lines[$i]->special_code == 3) {
3276 // If option
3277 return $outputlangs->transnoentities("Option");
3278 } else {
3279 if (is_object($hookmanager)) {
3280 $special_code = $object->lines[$i]->special_code;
3281 if (!empty($object->lines[$i]->fk_parent_line)) {
3282 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
3283 }
3284
3285 $parameters = array(
3286 'i' => $i,
3287 'outputlangs' => $outputlangs,
3288 'hidedetails' => $hidedetails,
3289 'special_code' => $special_code,
3290 'multicurrency' => $multicurrency
3291 );
3292
3293 $action = '';
3294
3295 if ($hookmanager->executeHooks('getlinetotalremise', $parameters, $object, $action) > 0) { // Note that $action and $object may have been modified by some hooks
3296 if (isset($hookmanager->resArray['linetotalremise'])) {
3297 return (float) $hookmanager->resArray['linetotalremise'];
3298 } else {
3299 return (float) $hookmanager->resPrint; // For backward compatibility
3300 }
3301 }
3302 }
3303
3304 if (empty($hidedetails) || $hidedetails > 1) {
3305 if (empty($multicurrency)) {
3306 $diff = (float) price2num($sign * $object->lines[$i]->subprice * (float) $object->lines[$i]->qty, 'MT', 1) - $object->lines[$i]->total_ht;
3307 return (float) price2num($diff, 'MT', 1);
3308 } else {
3309 $diff = (float) price2num($sign * $object->lines[$i]->multicurrency_subprice * (float) $object->lines[$i]->qty, 'MT', 1) - $object->lines[$i]->multicurrency_total_ht;
3310 return (float) price2num($diff, 'MT', 1);
3311 }
3312 }
3313 }
3314 return 0;
3315}
3316
3324function pdfExtractMetadata($file, $field = 'Keywords')
3325{
3326 if (!dol_is_file($file)) {
3327 return "ERROR: FILE NOT FOUND OR NOT VALID";
3328 }
3329
3330 // Get content of PDF file
3331 $content = file_get_contents(dol_osencode($file));
3332
3333 // Use a regex to capture the metadata
3334 if ($content) {
3335 $matches = array();
3336
3337 // Remove non printablecaracters
3338 $content = preg_replace('/[^(\x20-\x7F)]*/', '', $content);
3339 if (preg_match('/\/' . preg_quote($field, '/') . '\s*\‍((.*?)\‍)/', $content, $matches)) {
3340 return trim($matches[1]);
3341 }
3342 return "ERROR: NOT FOUND";
3343 } else {
3344 return "ERROR: FAILED TO READ PDF";
3345 }
3346}
3347
3366 TCPDF $pdf,
3367 CommonDocGenerator $generator,
3368 float $curY,
3370 int $i,
3371 Translate $outputlangs,
3372 int $hideref,
3373 int $hidedesc,
3374 array $bgColor,
3375 bool $isSubtotal = false,
3376 bool $applySubtotalLogic = true
3377) {
3378 $savePage = $pdf->getPage();
3379 $saveX = $pdf->GetX();
3380 $prevAlign = $generator->cols['desc']['content']['align'];
3381
3382 if ($isSubtotal && $applySubtotalLogic && $object->lines[$i]->qty < 0) {
3383 $outputlangs->load("subtotals");
3384 $object->lines[$i]->desc = getDolGlobalString("SUBTOTAL_LINE_TEXT_DOES_NOT_INCLUDE_TITLE_TEXT") ? $outputlangs->trans("SubTotal") : $outputlangs->trans("SubtotalOf", $object->lines[$i]->desc);
3385 $generator->cols['desc']['content']['align'] = ($prevAlign === 'L') ? 'R' : 'L';
3386 }
3387
3388 $pdf->startTransaction();
3389 $pdf->SetXY($saveX, $curY);
3390 $generator->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc);
3391 $pageAfter = $pdf->getPage();
3392 $yAfter = $pdf->GetY();
3393 $pdf->rollbackTransaction(true);
3394
3395 $pdf->SetFillColor($bgColor[0], $bgColor[1], $bgColor[2]);
3396 $width = $generator->page_largeur - $generator->marge_droite - $generator->marge_gauche;
3397
3398 $pdf->SetXY($generator->marge_gauche, $curY);
3399 if ($pageAfter === $savePage) {
3400 $pdf->MultiCell($width, max(0, $yAfter - $curY), '', 0, '', true);
3401 } else {
3402 $pdf->MultiCell($width, $pdf->getPageHeight() - $pdf->getBreakMargin() - $curY, '', 0, '', true);
3403
3404 // The page reached by the measuring pass above was discarded along with
3405 // the transaction, and the MultiCell only recreates it when some room was
3406 // left to fill. A line starting below the break margin leaves none, so
3407 // the page must be added before it can be selected.
3408 while ($pdf->getNumPages() < $pageAfter) {
3409 $pdf->AddPage();
3410 }
3411 $pdf->setPage($pageAfter);
3412 $pdf->SetXY($generator->marge_gauche, $pdf->getMargins()['top']);
3413 $pdf->MultiCell($width, max(0, $yAfter - $pdf->getMargins()['top']), '', 0, '', true);
3414
3415 $pdf->setPage($savePage);
3416 }
3417
3418 $pdf->SetTextColor(colorIsLight(implode(',', $bgColor)));
3419 $pdf->SetXY($saveX, $curY);
3420 $generator->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc);
3421 $generator->setAfterColsLinePositionsData('desc', $pdf->GetY(), $pdf->getPage());
3422
3423 $generator->cols['desc']['content']['align'] = $prevAlign;
3424}
3425
3426
3437function pdf_truncate_text($pdf, $text, $max_width, $ellipsis_pos = 1, $ellipsis = "\u{2026}")
3438{
3439 if ($ellipsis_pos == 0) {
3440 $ellipsis = '';
3441 }
3442 if ($ellipsis_pos == 'left') {
3443 // Keep left part of the string
3444 $ellipsis_pos = 1;
3445 }
3446 if ($ellipsis_pos == 'right') {
3447 // Keep right part of the string
3448 $ellipsis_pos = 0;
3449 }
3450
3451 $ellipsis_width = $pdf->GetStringWidth($ellipsis);
3452 $available_width = $max_width - $ellipsis_width;
3453
3454 if ($available_width <= 0) {
3455 return ($ellipsis_pos <= 0) ? $ellipsis : '';
3456 }
3457
3458 $text_width = $pdf->GetStringWidth($text);
3459 if ($text_width <= $max_width) {
3460 return $text;
3461 }
3462
3463 if ($ellipsis_pos < 0) {
3464 // Ellipsis at start: truncate from the beginning
3465 $low = 0;
3466 $high = dol_strlen($text, 'UTF-8');
3467 $best = $high;
3468
3469 while ($low <= $high) {
3470 $mid = (int) (($low + $high) / 2);
3471 $substring = dol_substr($text, $mid, null, 'UTF-8');
3472 $substring_width = $pdf->GetStringWidth($substring);
3473
3474 if ($substring_width <= $available_width) {
3475 $best = $mid;
3476 $high = $mid - 1;
3477 } else {
3478 $low = $mid + 1;
3479 }
3480 }
3481
3482 return $ellipsis . dol_substr($text, $best, null, 'UTF-8');
3483 } else {
3484 // Ellipsis at end (default)
3485 $low = 0;
3486 $high = dol_strlen($text, 'UTF-8');
3487 $best = 0;
3488
3489 while ($low <= $high) {
3490 $mid = (int) (($low + $high) / 2);
3491 $substring = dol_substr($text, 0, $mid, 'UTF-8');
3492 $substring_width = $pdf->GetStringWidth($substring);
3493
3494 if ($substring_width <= $available_width) {
3495 $best = $mid;
3496 $low = $mid + 1;
3497 } else {
3498 $high = $mid - 1;
3499 }
3500 }
3501
3502 return dol_substr($text, 0, $best, 'UTF-8') . $ellipsis;
3503 }
3504}
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
pdfWriteBlockedLogSignature(&$pdf, $outputlangs, $page_height, $object, &$w, &$posx, &$posy)
Add some information from the blockedlog module.
pdfCertifMentionblockedLog(&$pdf, $outputlangs, $seller, $default_font_size, &$posy, $pdftemplate)
Add legal mention.
isALNERunningVersion($blockedlogusagealreadychecked=0, $blockedlogmoduleonalreadychecked=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.
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
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
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...
dol_substr($string, $start, $length=null, $stringencoding='', $trunconbytes=0)
Make a substring.
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.
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:3235
pdf_watermark($pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition pdf.lib.php:1200
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition pdf.lib.php:2936
pdfCertifMention($pdf, $outputlangs, $seller, $default_font_size, &$posy, $pdftemplate)
Add legal certificate mention.
Definition pdf.lib.php:1264
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:1948
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:3267
pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1853
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:296
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:3324
pdf_bank($pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank information for PDF generation.
Definition pdf.lib.php:1284
pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails=0)
Return line quantity shipped.
Definition pdf.lib.php:2690
pdf_getlinenum($object, $i, $outputlangs, $hidedetails=0)
Return line num.
Definition pdf.lib.php:2365
pdf_getEncryption($pathoffile)
Return if pdf file is protected/encrypted.
Definition pdf.lib.php:242
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:1891
pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price including tax.
Definition pdf.lib.php:2568
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:319
pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails=0)
Return line ref_supplier.
Definition pdf.lib.php:2431
pdfWriteVATArray($docgenerator, &$index, $pdf, $outputlangs, $outputlangsbis, $object, $col1x, $col2x, $largcol2, $tab2_top, $tab2_hl)
Add some information from the blockedlog module.
Definition pdf.lib.php:855
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition pdf.lib.php:2986
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition pdf.lib.php:2525
pdf_getlineprogress($object, $i, $outputlangs, $hidedetails=0, $hookmanager=null)
Return line percent.
Definition pdf.lib.php:2856
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition pdf.lib.php:2463
pdf_admin_prepare_head()
Return array head with list of tabs to view object information.
Definition pdf.lib.php:49
canDisplayLinkedObjectInPDF($object, $elementobject)
Check if a linked object can be displayed based on third-party privacy rules.
Definition pdf.lib.php:3035
pdf_pagehead($pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:792
pdfGetHeightForHtmlContent($pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition pdf.lib.php:385
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:1466
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:275
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:3365
pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails=0)
Return line keep to ship quantity.
Definition pdf.lib.php:2730
pdf_truncate_text($pdf, $text, $max_width, $ellipsis_pos=1, $ellipsis="\u{2026}")
Truncates text to fit a specified width in TCPDF, with configurable ellipsis position.
Definition pdf.lib.php:3437
pdf_getlineref($object, $i, $outputlangs, $hidedetails=0)
Return line product ref.
Definition pdf.lib.php:2398
pdfWriteAdditionnalTitle($pdf, $outputlangs, $page_height, $object, &$w, &$posx, &$posy)
Add some information from the blockedlog module.
Definition pdf.lib.php:830
pdfWriteAlreadyPaid($docgenerator, &$index, $pdf, $outputlangs, $outputlangsbis, $object, $col1x, $col2x, $largcol2, $tab2_top, $tab2_hl, $deja_regle, $creditnoteamount, $depositsamount, $resteapayer, $resteapayer_origin)
Add some information from the blockedlog module.
Definition pdf.lib.php:1095
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:481
pdf_writeLogoOrCompanyName($pdf, $outputlangs, $emetteur, $logodir, $posx, $posy, $w, $default_font_size, $align)
Output company logo on top-left of a PDF page header, or the company name as fallback text if no logo...
Definition pdf.lib.php:351
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition pdf.lib.php:2770
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition pdf.lib.php:2813
pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails=0)
Return line quantity asked.
Definition pdf.lib.php:2650
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition pdf.lib.php:2610
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:1180
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:436