dolibarr 21.0.3
pdf.lib.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2006-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
4 * Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
5 * Copyright (C) 2010-2012 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2010-2017 Juanjo Menent <jmenent@2byte.es>
7 * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
8 * Copyright (C) 2012 Cédric Salvador <csalvador@gpcsolutions.fr>
9 * Copyright (C) 2012-2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
10 * Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
11 * Copyright (C) 2014 Teddy Andreotti <125155@supinfo.com>
12 * Copyright (C) 2015-2016 Marcos García <marcosgdf@gmail.com>
13 * Copyright (C) 2019 Lenin Rivas <lenin.rivas@servcom-it.com>
14 * Copyright (C) 2020 Nicolas ZABOURI <info@inovea-conseil.com>
15 * Copyright (C) 2021-2022 Anthony Berton <anthony.berton@bb2a.fr>
16 * Copyright (C) 2023-2024 Frédéric France <frederic.france@free.fr>
17 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 3 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program. If not, see <https://www.gnu.org/licenses/>.
31 * or see https://www.gnu.org/
32 */
33
40include_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php';
41
42
49{
50 global $langs, $conf;
51
52 $h = 0;
53 $head = array();
54
55 $head[$h][0] = DOL_URL_ROOT.'/admin/pdf.php';
56 $head[$h][1] = $langs->trans("Parameters");
57 $head[$h][2] = 'general';
58 $h++;
59
60 // Show more tabs from modules
61 // Entries must be declared in modules descriptor with line
62 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
63 // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab
64 complete_head_from_modules($conf, $langs, null, $head, $h, 'pdf_admin');
65
66 if (isModEnabled("propal") || isModEnabled('invoice') || isModEnabled('reception')) {
67 $head[$h][0] = DOL_URL_ROOT.'/admin/pdf_other.php';
68 $head[$h][1] = $langs->trans("Others");
69 $head[$h][2] = 'other';
70 $h++;
71 }
72
73 complete_head_from_modules($conf, $langs, null, $head, $h, 'pdf_admin', 'remove');
74
75 return $head;
76}
77
78
86function pdf_getFormat($outputlangs = null, $mode = 'setup')
87{
88 global $conf, $db, $langs;
89
90 dol_syslog("pdf_getFormat Get paper format with mode=".$mode." MAIN_PDF_FORMAT=".(!getDolGlobalString('MAIN_PDF_FORMAT') ? 'null' : $conf->global->MAIN_PDF_FORMAT)." outputlangs->defaultlang=".(is_object($outputlangs) ? $outputlangs->defaultlang : 'null')." and langs->defaultlang=".(is_object($langs) ? $langs->defaultlang : 'null'));
91
92 // Default value if setup was not done and/or entry into c_paper_format not defined
93 $width = 210;
94 $height = 297;
95 $unit = 'mm';
96
97 if ($mode == 'auto' || !getDolGlobalString('MAIN_PDF_FORMAT') || getDolGlobalString('MAIN_PDF_FORMAT') == 'auto') {
98 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
99 $pdfformat = dol_getDefaultFormat($outputlangs);
100 } else {
101 $pdfformat = getDolGlobalString('MAIN_PDF_FORMAT');
102 }
103
104 $sql = "SELECT code, label, width, height, unit FROM ".MAIN_DB_PREFIX."c_paper_format";
105 $sql .= " WHERE code = '".$db->escape($pdfformat)."'";
106 $resql = $db->query($sql);
107 if ($resql) {
108 $obj = $db->fetch_object($resql);
109 if ($obj) {
110 $width = (int) $obj->width;
111 $height = (int) $obj->height;
112 $unit = $obj->unit;
113 }
114 }
115
116 //print "pdfformat=".$pdfformat." width=".$width." height=".$height." unit=".$unit;
117 return array('width' => $width, 'height' => $height, 'unit' => $unit);
118}
119
128function pdf_getInstance($format = '', $metric = 'mm', $pagetype = 'P')
129{
130 global $conf;
131
132 // Define constant for TCPDF
133 if (!defined('K_TCPDF_EXTERNAL_CONFIG')) {
134 define('K_TCPDF_EXTERNAL_CONFIG', 1); // this avoid using tcpdf_config file
135 define('K_PATH_CACHE', DOL_DATA_ROOT.'/admin/temp/');
136 define('K_PATH_URL_CACHE', DOL_DATA_ROOT.'/admin/temp/');
137 dol_mkdir(K_PATH_CACHE);
138 define('K_BLANK_IMAGE', '_blank.png');
139 define('PDF_PAGE_FORMAT', 'A4');
140 define('PDF_PAGE_ORIENTATION', 'P');
141 define('PDF_CREATOR', 'TCPDF');
142 define('PDF_AUTHOR', 'TCPDF');
143 define('PDF_HEADER_TITLE', 'TCPDF Example');
144 define('PDF_HEADER_STRING', "by Dolibarr ERP CRM");
145 define('PDF_UNIT', 'mm');
146 define('PDF_MARGIN_HEADER', 5);
147 define('PDF_MARGIN_FOOTER', 10);
148 define('PDF_MARGIN_TOP', 27);
149 define('PDF_MARGIN_BOTTOM', 25);
150 define('PDF_MARGIN_LEFT', 15);
151 define('PDF_MARGIN_RIGHT', 15);
152 define('PDF_FONT_NAME_MAIN', 'helvetica');
153 define('PDF_FONT_SIZE_MAIN', 10);
154 define('PDF_FONT_NAME_DATA', 'helvetica');
155 define('PDF_FONT_SIZE_DATA', 8);
156 define('PDF_FONT_MONOSPACED', 'courier');
157 define('PDF_IMAGE_SCALE_RATIO', 1.25);
158 define('HEAD_MAGNIFICATION', 1.1);
159 define('K_CELL_HEIGHT_RATIO', 1.25);
160 define('K_TITLE_MAGNIFICATION', 1.3);
161 define('K_SMALL_RATIO', 2 / 3);
162 define('K_THAI_TOPCHARS', true);
163 define('K_TCPDF_CALLS_IN_HTML', true);
164 if (getDolGlobalString('TCPDF_THROW_ERRORS_INSTEAD_OF_DIE')) {
165 define('K_TCPDF_THROW_EXCEPTION_ERROR', true);
166 } else {
167 define('K_TCPDF_THROW_EXCEPTION_ERROR', false);
168 }
169 }
170
171 // Load TCPDF
172 require_once TCPDF_PATH.'tcpdf.php';
173
174 // We need to instantiate tcpdi object (instead of tcpdf) to use merging features. But we can disable it (this will break all merge features).
175 if (!getDolGlobalString('MAIN_DISABLE_TCPDI')) {
176 require_once TCPDI_PATH.'tcpdi.php';
177 }
178
179 //$arrayformat=pdf_getFormat();
180 //$format=array($arrayformat['width'],$arrayformat['height']);
181 //$metric=$arrayformat['unit'];
182
183 //$pdfa = false; // PDF default version
184 $pdfa = getDolGlobalInt('PDF_USE_A', 0); // PDF/A-1 ou PDF/A-3
185
186 if (!getDolGlobalString('MAIN_DISABLE_TCPDI') && class_exists('TCPDI')) {
187 $pdf = new TCPDI($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
188 } else {
189 $pdf = new TCPDF($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
190 }
191
192 // Protection and encryption of pdf
193 if (getDolGlobalString('PDF_SECURITY_ENCRYPTION')) {
194 /* Permission supported by TCPDF
195 - print : Print the document;
196 - modify : Modify the contents of the document by operations other than those controlled by 'fill-forms', 'extract' and 'assemble';
197 - copy : Copy or otherwise extract text and graphics from the document;
198 - 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);
199 - fill-forms : Fill in existing interactive form fields (including signature fields), even if 'annot-forms' is not specified;
200 - extract : Extract text and graphics (in support of accessibility to users with disabilities or for other purposes);
201 - assemble : Assemble the document (insert, rotate, or delete pages and create bookmarks or thumbnail images), even if 'modify' is not set;
202 - 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.
203 - owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions.
204 */
205
206 // For TCPDF, we specify permission we want to block
207 $pdfrights = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_RIGHTS') ? json_decode(getDolGlobalString('PDF_SECURITY_ENCRYPTION_RIGHTS'), true) : array('modify', 'copy')); // Json format in llx_const
208
209 // Password for the end user
210 $pdfuserpass = getDolGlobalString('PDF_SECURITY_ENCRYPTION_USERPASS');
211
212 // Password of the owner, created randomly if not defined
213 $pdfownerpass = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_OWNERPASS') ? getDolGlobalString('PDF_SECURITY_ENCRYPTION_OWNERPASS') : null);
214
215 // For encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit
216 $encstrength = getDolGlobalInt('PDF_SECURITY_ENCRYPTION_STRENGTH', 0);
217
218 // Array of recipients containing public-key certificates ('c') and permissions ('p').
219 // For example: array(array('c' => 'file://../examples/data/cert/tcpdf.crt', 'p' => array('print')))
220 $pubkeys = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_PUBKEYS') ? json_decode(getDolGlobalString('PDF_SECURITY_ENCRYPTION_PUBKEYS'), true) : null); // Json format in llx_const
221
222 $pdf->SetProtection($pdfrights, $pdfuserpass, $pdfownerpass, $encstrength, $pubkeys);
223 }
224
225 return $pdf;
226}
227
234function pdf_getEncryption($pathoffile)
235{
236 require_once TCPDF_PATH.'tcpdf_parser.php';
237
238 $isencrypted = false;
239
240 $content = file_get_contents($pathoffile);
241
242 //ob_start();
243 @($parser = new TCPDF_PARSER(ltrim($content)));
244 list($xref, $data) = $parser->getParsedData();
245 unset($parser);
246 //ob_end_clean();
247
248 if (isset($xref['trailer']['encrypt'])) {
249 $isencrypted = true; // Secured pdf file are currently not supported
250 }
251
252 if (empty($data)) {
253 $isencrypted = true; // Object list not found. Possible secured file
254 }
255
256 return $isencrypted;
257}
258
265function pdf_getPDFFont($outputlangs)
266{
267 global $conf;
268
269 if (getDolGlobalString('MAIN_PDF_FORCE_FONT')) {
270 return $conf->global->MAIN_PDF_FORCE_FONT;
271 }
272
273 $font = 'Helvetica'; // By default, for FPDI, or ISO language on TCPDF
274 if (class_exists('TCPDF')) { // If TCPDF on, we can use an UTF8 one like DejaVuSans if required (slower)
275 if ($outputlangs->trans('FONTFORPDF') != 'FONTFORPDF') {
276 $font = $outputlangs->trans('FONTFORPDF');
277 }
278 }
279 return $font;
280}
281
288function pdf_getPDFFontSize($outputlangs)
289{
290 global $conf;
291
292 $size = 10; // By default, for FPDI or ISO language on TCPDF
293 if (class_exists('TCPDF')) { // If TCPDF on, we can use an UTF8 font like DejaVuSans if required (slower)
294 if ($outputlangs->trans('FONTSIZEFORPDF') != 'FONTSIZEFORPDF') {
295 $size = (int) $outputlangs->trans('FONTSIZEFORPDF');
296 }
297 }
298 if (getDolGlobalString('MAIN_PDF_FORCE_FONT_SIZE')) {
299 $size = getDolGlobalString('MAIN_PDF_FORCE_FONT_SIZE');
300 }
301
302 return $size;
303}
304
305
313function pdf_getHeightForLogo($logo, $url = false)
314{
315 global $conf;
316 $height = (!getDolGlobalString('MAIN_DOCUMENTS_LOGO_HEIGHT') ? 20 : $conf->global->MAIN_DOCUMENTS_LOGO_HEIGHT);
317 $maxwidth = 130;
318 include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
319 $tmp = dol_getImageSize($logo, $url);
320 if ($tmp['height']) {
321 $width = round($height * $tmp['width'] / $tmp['height']);
322 if ($width > $maxwidth) {
323 $height = $height * $maxwidth / $width;
324 }
325 }
326 //print $tmp['width'].' '.$tmp['height'].' '.$width; exit;
327 return $height;
328}
329
339function pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
340{
341 // store current object
342 $pdf->startTransaction();
343 // 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
344 // Another solution would be to do the test on another PDF instance with samefont, width...
345 $pdf->setY(0);
346 // store starting values
347 $start_y = $pdf->GetY();
348 //var_dump($start_y);
349 $start_page = $pdf->getPage();
350 // call printing functions with content
351 $pdf->writeHTMLCell(0, 0, 0, $start_y, $htmlcontent, 0, 1, false, true, 'J', true);
352 // get the new Y
353 $end_y = $pdf->GetY();
354 $end_page = $pdf->getPage();
355 // calculate height
356 $height = 0;
357 if ($end_page == $start_page) {
358 $height = $end_y - $start_y;
359 } else {
360 for ($page = $start_page; $page <= $end_page; ++$page) {
361 $pdf->setPage($page);
362 $tmpm = $pdf->getMargins();
363 $tMargin = $tmpm['top'];
364 if ($page == $start_page) {
365 // first page
366 $height = $pdf->getPageHeight() - $start_y - $pdf->getBreakMargin();
367 } elseif ($page == $end_page) {
368 // last page
369 $height = $end_y - $tMargin;
370 } else {
371 $height = $pdf->getPageHeight() - $tMargin - $pdf->getBreakMargin();
372 }
373 }
374 }
375 // restore previous object
376 $pdf = $pdf->rollbackTransaction();
377
378 return $height;
379}
380
381
390function pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias = 0)
391{
392 global $conf;
393
394 // Recipient name
395 $socname = '';
396
397 if ($thirdparty instanceof Societe) {
398 $socname = $thirdparty->name;
399 if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->name_alias)) {
400 if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
401 $socname = $thirdparty->name_alias." - ".$thirdparty->name;
402 } else {
403 $socname = $thirdparty->name." - ".$thirdparty->name_alias;
404 }
405 }
406 } elseif ($thirdparty instanceof Contact) {
407 if ($thirdparty->socid > 0) {
408 $thirdparty->fetch_thirdparty();
409 $socname = $thirdparty->thirdparty->name;
410 if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->thirdparty->name_alias)) {
411 if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
412 $socname = $thirdparty->thirdparty->name_alias." - ".$thirdparty->thirdparty->name;
413 } else {
414 $socname = $thirdparty->thirdparty->name." - ".$thirdparty->thirdparty->name_alias;
415 }
416 }
417 }
418 } else {
419 throw new InvalidArgumentException('Parameter 1 $thirdparty is not a Societe nor Contact');
420 }
421
422 return $outputlangs->convToOutputCharset($socname);
423}
424
425
438function pdf_build_address($outputlangs, $sourcecompany, $targetcompany = '', $targetcontact = '', $usecontact = 0, $mode = 'source', $object = null)
439{
440 global $hookmanager;
441
442 if ($mode == 'source' && !is_object($sourcecompany)) {
443 return -1;
444 }
445 if ($mode == 'target' && !is_object($targetcompany)) {
446 return -1;
447 }
448
449 if (!empty($sourcecompany->state_id) && empty($sourcecompany->state)) {
450 $sourcecompany->state = getState($sourcecompany->state_id);
451 }
452 if (!empty($targetcompany->state_id) && empty($targetcompany->state)) {
453 $targetcompany->state = getState($targetcompany->state_id);
454 }
455
456 $reshook = 0;
457 $stringaddress = '';
458 if (is_object($hookmanager)) {
459 $parameters = array('sourcecompany' => &$sourcecompany, 'targetcompany' => &$targetcompany, 'targetcontact' => &$targetcontact, 'outputlangs' => $outputlangs, 'mode' => $mode, 'usecontact' => $usecontact);
460 $action = '';
461 $reshook = $hookmanager->executeHooks('pdf_build_address', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
462 $stringaddress .= $hookmanager->resPrint;
463 }
464 if (empty($reshook)) {
465 if ($mode == 'source') {
466 $withCountry = 0;
467 if (isset($targetcompany->country_code) && !empty($sourcecompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
468 $withCountry = 1;
469 }
470
471 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($sourcecompany, $withCountry, "\n", $outputlangs))."\n";
472
473 if (!getDolGlobalString('MAIN_PDF_DISABLESOURCEDETAILS')) {
474 // Phone
475 if ($sourcecompany->phone) {
476 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("PhoneShort").": ".$outputlangs->convToOutputCharset($sourcecompany->phone);
477 }
478 // Fax
479 if ($sourcecompany->fax) {
480 $stringaddress .= ($stringaddress ? ($sourcecompany->phone ? " - " : "\n") : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($sourcecompany->fax);
481 }
482 // EMail
483 if ($sourcecompany->email) {
484 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($sourcecompany->email);
485 }
486 // Web
487 if ($sourcecompany->url) {
488 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($sourcecompany->url);
489 }
490 }
491 // Intra VAT
492 if (getDolGlobalString('MAIN_TVAINTRA_IN_SOURCE_ADDRESS')) {
493 if ($sourcecompany->tva_intra) {
494 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($sourcecompany->tva_intra);
495 }
496 }
497 // Professional Ids
498 $reg = array();
499 if (getDolGlobalString('MAIN_PROFID1_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof1)) {
500 $tmp = $outputlangs->transcountrynoentities("ProfId1", $sourcecompany->country_code);
501 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
502 $tmp = $reg[1];
503 }
504 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof1);
505 }
506 if (getDolGlobalString('MAIN_PROFID2_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof2)) {
507 $tmp = $outputlangs->transcountrynoentities("ProfId2", $sourcecompany->country_code);
508 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
509 $tmp = $reg[1];
510 }
511 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof2);
512 }
513 if (getDolGlobalString('MAIN_PROFID3_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof3)) {
514 $tmp = $outputlangs->transcountrynoentities("ProfId3", $sourcecompany->country_code);
515 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
516 $tmp = $reg[1];
517 }
518 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof3);
519 }
520 if (getDolGlobalString('MAIN_PROFID4_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof4)) {
521 $tmp = $outputlangs->transcountrynoentities("ProfId4", $sourcecompany->country_code);
522 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
523 $tmp = $reg[1];
524 }
525 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof4);
526 }
527 if (getDolGlobalString('MAIN_PROFID5_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof5)) {
528 $tmp = $outputlangs->transcountrynoentities("ProfId5", $sourcecompany->country_code);
529 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
530 $tmp = $reg[1];
531 }
532 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof5);
533 }
534 if (getDolGlobalString('MAIN_PROFID6_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof6)) {
535 $tmp = $outputlangs->transcountrynoentities("ProfId6", $sourcecompany->country_code);
536 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
537 $tmp = $reg[1];
538 }
539 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof6);
540 }
541 if (getDolGlobalString('PDF_ADD_MORE_AFTER_SOURCE_ADDRESS')) {
542 $stringaddress .= ($stringaddress ? "\n" : '') . getDolGlobalString('PDF_ADD_MORE_AFTER_SOURCE_ADDRESS');
543 }
544 }
545
546 if ($mode == 'target' || preg_match('/targetwithdetails/', $mode)) {
547 if ($usecontact && (is_object($targetcontact))) {
548 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($targetcontact->getFullName($outputlangs, 1));
549
550 if (!empty($targetcontact->address)) {
551 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcontact))."\n";
552 } else {
553 $companytouseforaddress = $targetcompany;
554
555 // Contact on a thirdparty that is a different thirdparty than the thirdparty of object
556 if ($targetcontact->socid > 0 && $targetcontact->socid != $targetcompany->id) {
557 $targetcontact->fetch_thirdparty();
558 $companytouseforaddress = $targetcontact->thirdparty;
559 }
560
561 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($companytouseforaddress))."\n";
562 }
563 // Country
564 if (!empty($targetcontact->country_code) && $targetcontact->country_code != $sourcecompany->country_code) {
565 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcontact->country_code));
566 } elseif (empty($targetcontact->country_code) && !empty($targetcompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
567 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
568 }
569
570 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || preg_match('/targetwithdetails/', $mode)) {
571 // Phone
572 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
573 if (!empty($targetcontact->phone_pro) || !empty($targetcontact->phone_mobile)) {
574 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
575 }
576 if (!empty($targetcontact->phone_pro)) {
577 $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_pro);
578 }
579 if (!empty($targetcontact->phone_pro) && !empty($targetcontact->phone_mobile)) {
580 $stringaddress .= " / ";
581 }
582 if (!empty($targetcontact->phone_mobile)) {
583 $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_mobile);
584 }
585 }
586 // Fax
587 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
588 if ($targetcontact->fax) {
589 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcontact->fax);
590 }
591 }
592 // EMail
593 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
594 if ($targetcontact->email) {
595 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcontact->email);
596 }
597 }
598 // Web
599 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
600 if ($targetcontact->url) {
601 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcontact->url);
602 }
603 }
604 }
605 } else {
606 if (is_object($targetcompany)) {
607 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcompany));
608 // Country
609 if (!empty($targetcompany->country_code) && $targetcompany->country_code != $sourcecompany->country_code) {
610 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
611 } else {
612 $stringaddress .= ($stringaddress ? "\n" : '');
613 }
614
615 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || preg_match('/targetwithdetails/', $mode)) {
616 // Phone
617 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
618 if (!empty($targetcompany->phone)) {
619 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
620 }
621 if (!empty($targetcompany->phone)) {
622 $stringaddress .= $outputlangs->convToOutputCharset($targetcompany->phone);
623 }
624 }
625 // Fax
626 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
627 if ($targetcompany->fax) {
628 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcompany->fax);
629 }
630 }
631 // EMail
632 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
633 if ($targetcompany->email) {
634 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcompany->email);
635 }
636 }
637 // Web
638 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
639 if ($targetcompany->url) {
640 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcompany->url);
641 }
642 }
643 }
644 }
645 }
646
647 // Intra VAT
648 if (!getDolGlobalString('MAIN_TVAINTRA_NOT_IN_ADDRESS')) {
649 if ($usecontact && is_object($targetcontact) && getDolGlobalInt('MAIN_USE_COMPANY_NAME_OF_CONTACT')) {
650 $targetcontact->fetch_thirdparty();
651 if (!empty($targetcontact->thirdparty->id) && $targetcontact->thirdparty->tva_intra) {
652 $stringaddress .= ($stringaddress ? "\n" : '') . $outputlangs->transnoentities("VATIntraShort") . ': ' . $outputlangs->convToOutputCharset($targetcontact->thirdparty->tva_intra);
653 }
654 } elseif (!empty($targetcompany->tva_intra)) {
655 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($targetcompany->tva_intra);
656 }
657 }
658
659 // Legal form
660 if (getDolGlobalString('MAIN_LEGALFORM_IN_ADDRESS') && !empty($targetcompany->forme_juridique_code)) {
661 $tmp = getFormeJuridiqueLabel((string) $targetcompany->forme_juridique_code);
662 $stringaddress .= ($stringaddress ? "\n" : '').$tmp;
663 }
664
665 // Professional Ids
666 if (getDolGlobalString('MAIN_PROFID1_IN_ADDRESS') && !empty($targetcompany->idprof1)) {
667 $tmp = $outputlangs->transcountrynoentities("ProfId1", $targetcompany->country_code);
668 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
669 $tmp = $reg[1];
670 }
671 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof1);
672 }
673 if (getDolGlobalString('MAIN_PROFID2_IN_ADDRESS') && !empty($targetcompany->idprof2)) {
674 $tmp = $outputlangs->transcountrynoentities("ProfId2", $targetcompany->country_code);
675 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
676 $tmp = $reg[1];
677 }
678 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof2);
679 }
680 if (getDolGlobalString('MAIN_PROFID3_IN_ADDRESS') && !empty($targetcompany->idprof3)) {
681 $tmp = $outputlangs->transcountrynoentities("ProfId3", $targetcompany->country_code);
682 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
683 $tmp = $reg[1];
684 }
685 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof3);
686 }
687 if (getDolGlobalString('MAIN_PROFID4_IN_ADDRESS') && !empty($targetcompany->idprof4)) {
688 $tmp = $outputlangs->transcountrynoentities("ProfId4", $targetcompany->country_code);
689 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
690 $tmp = $reg[1];
691 }
692 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof4);
693 }
694 if (getDolGlobalString('MAIN_PROFID5_IN_ADDRESS') && !empty($targetcompany->idprof5)) {
695 $tmp = $outputlangs->transcountrynoentities("ProfId5", $targetcompany->country_code);
696 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
697 $tmp = $reg[1];
698 }
699 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof5);
700 }
701 if (getDolGlobalString('MAIN_PROFID6_IN_ADDRESS') && !empty($targetcompany->idprof6)) {
702 $tmp = $outputlangs->transcountrynoentities("ProfId6", $targetcompany->country_code);
703 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
704 $tmp = $reg[1];
705 }
706 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof6);
707 }
708
709 // Public note
710 if (getDolGlobalString('MAIN_PUBLIC_NOTE_IN_ADDRESS')) {
711 if ($mode == 'source' && !empty($sourcecompany->note_public)) {
712 $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($sourcecompany->note_public);
713 }
714 if (($mode == 'target' || preg_match('/targetwithdetails/', $mode)) && !empty($targetcompany->note_public)) {
715 $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($targetcompany->note_public);
716 }
717 }
718 }
719 }
720
721 return $stringaddress;
722}
723
724
733function pdf_pagehead(&$pdf, $outputlangs, $page_height)
734{
735 global $conf;
736
737 // Add a background image on document only if good setup of const
738 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
739 $filepath = $conf->mycompany->dir_output.'/logos/' . getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF');
740 if (file_exists($filepath)) {
741 $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak before adding image
742 if (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF_ALPHA')) {
743 $pdf->SetAlpha(getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_ALPHA'));
744 } // Option for change opacity of background
745 $pdf->Image($filepath, getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_X'), getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_Y'), 0, $page_height);
746 if (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF_ALPHA')) {
747 $pdf->SetAlpha(1);
748 }
749 $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
750 $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
751 }
752 }
753 if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND') && getDolGlobalString('MAIN_ADD_PDF_BACKGROUND') != '-1') {
754 $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
755 }
756}
757
758
769function pdf_getSubstitutionArray($outputlangs, $exclude = null, $object = null, $onlykey = 0, $include = null)
770{
771 $substitutionarray = getCommonSubstitutionArray($outputlangs, $onlykey, $exclude, $object, $include);
772 $substitutionarray['__FROM_NAME__'] = '__FROM_NAME__';
773 $substitutionarray['__FROM_EMAIL__'] = '__FROM_EMAIL__';
774 return $substitutionarray;
775}
776
777
789function pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
790{
791 // Print Draft Watermark
792 if ($unit == 'pt') {
793 $k = 1;
794 } elseif ($unit == 'mm') {
795 $k = 72 / 25.4;
796 } elseif ($unit == 'cm') {
797 $k = 72 / 2.54;
798 } elseif ($unit == 'in') {
799 $k = 72;
800 } else {
801 $k = 1;
802 dol_print_error(null, 'Unexpected unit "'.$unit.'" for pdf_watermark');
803 }
804
805 // Make substitution
806 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, null);
807 complete_substitutions_array($substitutionarray, $outputlangs, null);
808 $text = make_substitutions($text, $substitutionarray, $outputlangs);
809 $text = $outputlangs->convToOutputCharset($text);
810
811 $savx = $pdf->getX();
812 $savy = $pdf->getY();
813
814 $watermark_angle = atan($h / $w) / 2;
815 $watermark_x_pos = 0;
816 $watermark_y_pos = $h / 3;
817 $watermark_x = $w / 2;
818 $watermark_y = $h / 3;
819 $pdf->SetFont('', 'B', 40);
820 $pdf->SetTextColor(255, 0, 0);
821
822 // rotate
823 $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));
824 // print watermark
825 $pdf->SetAlpha(0.5);
826 $pdf->SetXY($watermark_x_pos, $watermark_y_pos);
827
828 // set alpha to semi-transparency
829 $pdf->SetAlpha(0.3);
830 $pdf->Cell($w - 20, 25, $outputlangs->convToOutputCharset($text), "", 2, "C", 0);
831
832 // antirotate
833 $pdf->_out('Q');
834
835 $pdf->SetXY($savx, $savy);
836
837 // Restore alpha
838 $pdf->SetAlpha(1);
839}
840
841
854function pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber = 0, $default_font_size = 10)
855{
856 global $mysoc, $conf;
857
858 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbank.class.php';
859
860 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
861 $diffsizecontent = getDolGlobalInt('PDF_DIFFSIZE_CONTENT', 4);
862 $pdf->SetXY($curx, $cury);
863
864 if (empty($onlynumber)) {
865 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
866 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByTransferOnThisBankAccount').':', 0, 'L', 0);
867 $cury += 4;
868 }
869
870 $outputlangs->load("banks");
871
872 // Use correct name of bank id according to country
873 $bickey = "BICNumber";
874 if ($account->getCountryCode() == 'IN') {
875 $bickey = "SWIFT";
876 }
877
878 // Get format of bank account according to its country
879 $usedetailedbban = $account->useDetailedBBAN();
880
881 //$onlynumber=0; $usedetailedbban=1; // For tests
882 if ($usedetailedbban) {
883 $savcurx = $curx;
884
885 if (empty($onlynumber)) {
886 $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
887 $pdf->SetXY($curx, $cury);
888 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
889 $cury += 3;
890 }
891
892 if (!getDolGlobalString('PDF_BANK_HIDE_NUMBER_SHOW_ONLY_BICIBAN')) { // Note that some countries still need bank number, BIC/IBAN not enough for them
893 // Note:
894 // bank = code_banque (FR), sort code (GB, IR. Example: 12-34-56)
895 // desk = code guichet (FR), used only when $usedetailedbban = 1
896 // number = account number
897 // key = check control key used only when $usedetailedbban = 1
898 if (empty($onlynumber)) {
899 $pdf->line($curx + 1, $cury + 1, $curx + 1, $cury + 6);
900 }
901
902
903 foreach ($account->getFieldsToShow() as $val) {
904 $pdf->SetXY($curx, $cury + 4);
905 $pdf->SetFont('', '', $default_font_size - 3);
906
907 if ($val == 'BankCode') {
908 // Bank code
909 $tmplength = 18;
910 $content = $account->code_banque;
911 } elseif ($val == 'DeskCode') {
912 // Desk
913 $tmplength = 18;
914 $content = $account->code_guichet;
915 } elseif ($val == 'BankAccountNumber') {
916 // Number
917 $tmplength = 24;
918 $content = $account->number;
919 } elseif ($val == 'BankAccountNumberKey') {
920 // Key
921 $tmplength = 15;
922 $content = $account->cle_rib;
923 } elseif ($val == 'IBAN' || $val == 'BIC') {
924 // Key
925 $tmplength = 0;
926 $content = '';
927 } else {
928 dol_print_error($account->db, 'Unexpected value for getFieldsToShow: '.$val);
929 break;
930 }
931
932 $pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($content), 0, 'C', 0);
933 $pdf->SetXY($curx, $cury + 1);
934 $curx += $tmplength;
935 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
936 $pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities($val), 0, 'C', 0);
937 if (empty($onlynumber)) {
938 $pdf->line($curx, $cury + 1, $curx, $cury + 7);
939 }
940 }
941
942 $curx = $savcurx;
943 $cury += 8;
944 }
945 } elseif (!empty($account->number)) {
946 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
947 $pdf->SetXY($curx, $cury);
948 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
949 $cury += 3;
950
951 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
952 $pdf->SetXY($curx, $cury);
953 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("BankAccountNumber").': '.$outputlangs->convToOutputCharset($account->number), 0, 'L', 0);
954 $cury += 3;
955
956 if ($diffsizecontent <= 2) {
957 $cury += 1;
958 }
959 }
960
961 $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
962
963 if (empty($onlynumber) && !empty($account->address)) {
964 $pdf->SetXY($curx, $cury);
965 $val = $outputlangs->transnoentities("Residence").': '.$outputlangs->convToOutputCharset($account->address);
966 $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
967 //$nboflines=dol_nboflines_bis($val,120);
968 //$cury+=($nboflines*3)+2;
969 $tmpy = $pdf->getStringHeight(100, $val);
970 $cury += $tmpy;
971 }
972
973 if (!empty($account->owner_name)) {
974 $pdf->SetXY($curx, $cury);
975 $val = $outputlangs->transnoentities("BankAccountOwner").': '.$outputlangs->convToOutputCharset($account->owner_name);
976 $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
977 $tmpy = $pdf->getStringHeight(100, $val);
978 $cury += $tmpy;
979 } elseif (!$usedetailedbban) {
980 $cury += 1;
981 }
982
983 // Use correct name of bank id according to country
984 $ibankey = FormBank::getIBANLabel($account);
985
986 if (!empty($account->iban)) {
987 //Remove whitespaces to ensure we are dealing with the format we expect
988 $ibanDisplay_temp = str_replace(' ', '', $outputlangs->convToOutputCharset($account->iban));
989 $ibanDisplay = "";
990
991 $nbIbanDisplay_temp = dol_strlen($ibanDisplay_temp);
992 for ($i = 0; $i < $nbIbanDisplay_temp; $i++) {
993 $ibanDisplay .= $ibanDisplay_temp[$i];
994 if ($i % 4 == 3 && $i > 0) {
995 $ibanDisplay .= " ";
996 }
997 }
998
999 $pdf->SetFont('', 'B', $default_font_size - 3);
1000 $pdf->SetXY($curx, $cury);
1001 $pdf->MultiCell(100, 3, $outputlangs->transnoentities($ibankey).': '.$ibanDisplay, 0, 'L', 0);
1002 $cury += 3;
1003 }
1004
1005 if (!empty($account->bic)) {
1006 $pdf->SetFont('', 'B', $default_font_size - 3);
1007 $pdf->SetXY($curx, $cury);
1008 $pdf->MultiCell(100, 3, $outputlangs->transnoentities($bickey).': '.$outputlangs->convToOutputCharset($account->bic), 0, 'L', 0);
1009 }
1010
1011 return $pdf->getY();
1012}
1013
1031function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails = 0, $hidefreetext = 0, $page_largeur = 0, $watermark = '')
1032{
1033 global $conf, $hookmanager;
1034
1035 $outputlangs->load("dict");
1036 $line = '';
1037 $reg = array();
1038 $marginwithfooter = 0; // Return value
1039
1040 $dims = $pdf->getPageDimensions();
1041
1042 // Line of free text
1043 if (empty($hidefreetext) && getDolGlobalString($paramfreetext)) {
1044 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
1045 // More substitution keys
1046 if (is_object($fromcompany)) {
1047 $substitutionarray['__FROM_NAME__'] = $fromcompany->name;
1048 $substitutionarray['__FROM_EMAIL__'] = $fromcompany->email;
1049 }
1050 complete_substitutions_array($substitutionarray, $outputlangs, $object);
1051 $newfreetext = make_substitutions(getDolGlobalString($paramfreetext), $substitutionarray, $outputlangs);
1052
1053 // Make a change into HTML code to allow to include images from medias directory.
1054 // <img alt="" src="/dolibarr_dev/htdocs/viewimage.php?modulepart=medias&amp;entity=1&amp;file=image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1055 // become
1056 // <img alt="" src="'.DOL_DATA_ROOT.'/medias/image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1057 $newfreetext = preg_replace('/(<img.*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)("[^\/]*\/>)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $newfreetext);
1058
1059 $line .= $outputlangs->convToOutputCharset($newfreetext);
1060 }
1061
1062 // First line of company infos
1063 $line1 = "";
1064 $line2 = "";
1065 $line3 = "";
1066 $line4 = "";
1067
1068 if (is_object($fromcompany) && in_array($showdetails, array(1, 3))) {
1069 // Company name
1070 if ($fromcompany->name) {
1071 $line1 .= ($line1 ? " - " : "").$outputlangs->transnoentities("RegisteredOffice").": ".$fromcompany->name;
1072 }
1073 // Address
1074 if ($fromcompany->address) {
1075 $line1 .= ($line1 ? " - " : "").str_replace("\n", ", ", $fromcompany->address);
1076 }
1077 // Zip code
1078 if ($fromcompany->zip) {
1079 $line1 .= ($line1 ? " - " : "").$fromcompany->zip;
1080 }
1081 // Town
1082 if ($fromcompany->town) {
1083 $line1 .= ($line1 ? " " : "").$fromcompany->town;
1084 }
1085 // Country
1086 if ($fromcompany->country) {
1087 $line1 .= ($line1 ? ", " : "").$fromcompany->country;
1088 }
1089 // Phone
1090 if ($fromcompany->phone) {
1091 $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Phone").": ".$fromcompany->phone;
1092 }
1093 // Fax
1094 if ($fromcompany->fax) {
1095 $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Fax").": ".$fromcompany->fax;
1096 }
1097
1098 // URL
1099 if ($fromcompany->url) {
1100 $line2 .= ($line2 ? " - " : "").$fromcompany->url;
1101 }
1102 // Email
1103 if ($fromcompany->email) {
1104 $line2 .= ($line2 ? " - " : "").$fromcompany->email;
1105 }
1106 }
1107 if ($showdetails == 2 || $showdetails == 3 || (!empty($fromcompany->country_code) && $fromcompany->country_code == 'DE')) {
1108 // Managers
1109 if ($fromcompany->managers) {
1110 $line2 .= ($line2 ? " - " : "").$fromcompany->managers;
1111 }
1112 }
1113
1114 // Line 3 of company infos
1115 // Juridical status
1116 if (!empty($fromcompany->forme_juridique_code) && $fromcompany->forme_juridique_code) {
1117 $line3 .= ($line3 ? " - " : "").$outputlangs->convToOutputCharset(getFormeJuridiqueLabel((string) $fromcompany->forme_juridique_code));
1118 }
1119 // Capital
1120 if (!empty($fromcompany->capital)) {
1121 $tmpamounttoshow = price2num($fromcompany->capital); // This field is a free string or a float
1122 if (is_numeric($tmpamounttoshow) && $tmpamounttoshow > 0) {
1123 $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", price($tmpamounttoshow, 0, $outputlangs, 0, 0, 0, $conf->currency));
1124 } elseif (!empty($fromcompany->capital)) {
1125 $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", $fromcompany->capital, $outputlangs);
1126 }
1127 }
1128 // Prof Id 1
1129 if (!empty($fromcompany->idprof1) && $fromcompany->idprof1 && ($fromcompany->country_code != 'FR' || !$fromcompany->idprof2)) {
1130 $field = $outputlangs->transcountrynoentities("ProfId1", $fromcompany->country_code);
1131 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1132 $field = $reg[1];
1133 }
1134 $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof1);
1135 }
1136 // Prof Id 2
1137 if (!empty($fromcompany->idprof2) && $fromcompany->idprof2) {
1138 $field = $outputlangs->transcountrynoentities("ProfId2", $fromcompany->country_code);
1139 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1140 $field = $reg[1];
1141 }
1142 $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof2);
1143 }
1144
1145 // Line 4 of company infos
1146 // Prof Id 3
1147 if (!empty($fromcompany->idprof3) && $fromcompany->idprof3) {
1148 $field = $outputlangs->transcountrynoentities("ProfId3", $fromcompany->country_code);
1149 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1150 $field = $reg[1];
1151 }
1152 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof3);
1153 }
1154 // Prof Id 4
1155 if (!empty($fromcompany->idprof4) && $fromcompany->idprof4) {
1156 $field = $outputlangs->transcountrynoentities("ProfId4", $fromcompany->country_code);
1157 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1158 $field = $reg[1];
1159 }
1160 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof4);
1161 }
1162 // Prof Id 5
1163 if (!empty($fromcompany->idprof5) && $fromcompany->idprof5) {
1164 $field = $outputlangs->transcountrynoentities("ProfId5", $fromcompany->country_code);
1165 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1166 $field = $reg[1];
1167 }
1168 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof5);
1169 }
1170 // Prof Id 6
1171 if (!empty($fromcompany->idprof6) && $fromcompany->idprof6) {
1172 $field = $outputlangs->transcountrynoentities("ProfId6", $fromcompany->country_code);
1173 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1174 $field = $reg[1];
1175 }
1176 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof6);
1177 }
1178 // Prof Id 7
1179 if (!empty($fromcompany->idprof7) && $fromcompany->idprof7) {
1180 $field = $outputlangs->transcountrynoentities("ProfId7", $fromcompany->country_code);
1181 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1182 $field = $reg[1];
1183 }
1184 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof7);
1185 }
1186 // Prof Id 8
1187 if (!empty($fromcompany->idprof8) && $fromcompany->idprof8) {
1188 $field = $outputlangs->transcountrynoentities("ProfId8", $fromcompany->country_code);
1189 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1190 $field = $reg[1];
1191 }
1192 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof8);
1193 }
1194 // Prof Id 9
1195 if (!empty($fromcompany->idprof9) && $fromcompany->idprof9) {
1196 $field = $outputlangs->transcountrynoentities("ProfId9", $fromcompany->country_code);
1197 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1198 $field = $reg[1];
1199 }
1200 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof9);
1201 }
1202 // Prof Id 10
1203 if (!empty($fromcompany->idprof10) && $fromcompany->idprof10) {
1204 $field = $outputlangs->transcountrynoentities("ProfId10", $fromcompany->country_code);
1205 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1206 $field = $reg[1];
1207 }
1208 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof10);
1209 }
1210 // IntraCommunautary VAT
1211 if (!empty($fromcompany->tva_intra) && $fromcompany->tva_intra != '') {
1212 $line4 .= ($line4 ? " - " : "").$outputlangs->transnoentities("VATIntraShort").": ".$outputlangs->convToOutputCharset($fromcompany->tva_intra);
1213 }
1214
1215 $pdf->SetFont('', '', 7);
1216 $pdf->SetDrawColor(224, 224, 224);
1217 // Option for footer text color
1218 if (getDolGlobalString('PDF_FOOTER_TEXT_COLOR')) {
1219 list($r, $g, $b) = sscanf(getDolGlobalString('PDF_FOOTER_TEXT_COLOR'), '%d, %d, %d');
1220 $pdf->SetTextColor($r, $g, $b);
1221 }
1222
1223 // The start of the bottom of this page footer is positioned according to # of lines
1224 $freetextheight = 0;
1225 $align = null;
1226 if ($line) { // Free text
1227 //$line="sample text<br>\nfd<strong>sf</strong>sdf<br>\nghfghg<br>";
1228 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) {
1229 $width = 20000;
1230 $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.
1231 if (getDolGlobalString('MAIN_USE_AUTOWRAP_ON_FREETEXT')) {
1232 $width = 200;
1233 $align = 'C';
1234 }
1235 $freetextheight = $pdf->getStringHeight($width, $line);
1236 } else {
1237 $freetextheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($line, 1, 'UTF-8', 0)); // New method (works for HTML content)
1238 //print '<br>'.$freetextheight;
1239 }
1240 }
1241
1242 $posy = 0;
1243 // For customized footer
1244 if (is_object($hookmanager)) {
1245 $parameters = array('line1' => $line1, 'line2' => $line2, 'line3' => $line3, 'line4' => $line4, 'outputlangs' => $outputlangs);
1246 $action = '';
1247 $hookmanager->executeHooks('pdf_pagefoot', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1248 if (!empty($hookmanager->resPrint) && $hidefreetext == 0) {
1249 $mycustomfooter = $hookmanager->resPrint;
1250 $mycustomfooterheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1251
1252 $marginwithfooter = $marge_basse + $freetextheight + $mycustomfooterheight;
1253 $posy = (float) $marginwithfooter;
1254
1255 // Option for footer background color (without freetext zone)
1256 if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1257 list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
1258 $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
1259 $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', array(), $fill_color = array($r, $g, $b));
1260 $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
1261 }
1262
1263 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1264 $pdf->SetAutoPageBreak(0, 0);
1265 } // Option for disable auto pagebreak
1266 if ($line) { // Free text
1267 $pdf->SetXY($dims['lm'], -$posy);
1268 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1269 $pdf->MultiCell(0, 3, $line, 0, $align, 0);
1270 } else {
1271 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1272 }
1273 $posy -= $freetextheight;
1274 }
1275 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1276 $pdf->SetAutoPageBreak(1, 0);
1277 } // Restore pagebreak
1278
1279 $pdf->SetY(-$posy);
1280
1281 // Hide footer line if footer background color is set
1282 if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1283 $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1284 }
1285
1286 // Option for set top margin height of footer after freetext
1287 if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1288 $posy -= (float) getDolGlobalString('PDF_FOOTER_TOP_MARGIN');
1289 } else {
1290 $posy--;
1291 }
1292
1293 if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) {
1294 $pdf->SetAutoPageBreak(0, 0);
1295 } // Option for disable auto pagebreak
1296 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $mycustomfooterheight, $dims['lm'], $dims['hk'] - $posy, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1297 if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) {
1298 $pdf->SetAutoPageBreak(1, 0);
1299 } // Restore pagebreak
1300
1301 $posy -= $mycustomfooterheight - 3;
1302 } else {
1303 // Else default footer
1304 $marginwithfooter = $marge_basse + $freetextheight + (!empty($line1) ? 3 : 0) + (!empty($line2) ? 3 : 0) + (!empty($line3) ? 3 : 0) + (!empty($line4) ? 3 : 0);
1305 $posy = (float) $marginwithfooter;
1306
1307 // Option for footer background color (without freetext zone)
1308 if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1309 list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
1310 $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
1311 $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', array(), $fill_color = array($r, $g, $b));
1312 $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
1313 }
1314
1315 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1316 $pdf->SetAutoPageBreak(0, 0);
1317 } // Option for disable auto pagebreak
1318 if ($line) { // Free text
1319 $pdf->SetXY($dims['lm'], -$posy);
1320 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1321 $pdf->MultiCell(0, 3, $line, 0, $align, 0);
1322 } else {
1323 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1324 }
1325 $posy -= $freetextheight;
1326 }
1327 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1328 $pdf->SetAutoPageBreak(1, 0);
1329 } // Restore pagebreak
1330
1331 $pdf->SetY(-$posy);
1332
1333 // Option for hide all footer (page number will no hidden)
1334 if (!getDolGlobalInt('PDF_FOOTER_HIDDEN')) {
1335 // Hide footer line if footer background color is set
1336 if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1337 $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1338 }
1339
1340 // Option for set top margin height of footer after freetext
1341 if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1342 $posy -= (float) getDolGlobalString('PDF_FOOTER_TOP_MARGIN');
1343 } else {
1344 $posy--;
1345 }
1346
1347 if (!empty($line1)) {
1348 $pdf->SetFont('', 'B', 7);
1349 $pdf->SetXY($dims['lm'], -$posy);
1350 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line1, 0, 'C', 0);
1351 $posy -= 3;
1352 $pdf->SetFont('', '', 7);
1353 }
1354
1355 if (!empty($line2)) {
1356 $pdf->SetFont('', 'B', 7);
1357 $pdf->SetXY($dims['lm'], -$posy);
1358 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line2, 0, 'C', 0);
1359 $posy -= 3;
1360 $pdf->SetFont('', '', 7);
1361 }
1362
1363 if (!empty($line3)) {
1364 $pdf->SetXY($dims['lm'], -$posy);
1365 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line3, 0, 'C', 0);
1366 }
1367
1368 if (!empty($line4)) {
1369 $posy -= 3;
1370 $pdf->SetXY($dims['lm'], -$posy);
1371 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line4, 0, 'C', 0);
1372 }
1373 }
1374 }
1375 }
1376
1377 // Show page nb and apply correction for some font.
1378 $pdf->SetXY($dims['wk'] - $dims['rm'] - 18 - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_X', 0), -$posy - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_Y', 0));
1379
1380 $pagination = $pdf->PageNo().' / '.$pdf->getAliasNbPages();
1381 $fontRenderCorrection = 0;
1382 if (in_array(pdf_getPDFFont($outputlangs), array('freemono', 'DejaVuSans'))) {
1383 $fontRenderCorrection = 10;
1384 }
1385 $pdf->MultiCell(18 + $fontRenderCorrection, 2, $pagination, 0, 'R', 0);
1386
1387 // Show Draft Watermark
1388 if (!empty($watermark)) {
1389 pdf_watermark($pdf, $outputlangs, $page_hauteur, $page_largeur, 'mm', $watermark);
1390 }
1391
1392 return $marginwithfooter;
1393}
1394
1409function pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
1410{
1411 $linkedobjects = pdf_getLinkedObjects($object, $outputlangs);
1412 if (!empty($linkedobjects)) {
1413 foreach ($linkedobjects as $linkedobject) {
1414 $reftoshow = $linkedobject["ref_title"].' : '.$linkedobject["ref_value"];
1415 if (!empty($linkedobject["date_value"])) {
1416 $reftoshow .= ' / '.$linkedobject["date_value"];
1417 }
1418
1419 $posy += 3;
1420 $pdf->SetXY($posx, $posy);
1421 $pdf->SetFont('', '', (float) $default_font_size - 2);
1422 $pdf->MultiCell($w, $h, $reftoshow, '', $align);
1423 }
1424 }
1425
1426 return $pdf->getY();
1427}
1428
1446function pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref = 0, $hidedesc = 0, $issupplierline = 0, $align = 'J')
1447{
1448 global $db, $conf, $langs, $hookmanager;
1449
1450 $reshook = 0;
1451 $result = '';
1452 //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) ) )
1453 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
1454 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1455 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1456 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1457 }
1458 $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);
1459 $action = '';
1460 // WARNING: A hook must not close/open the PDF transaction. Doing this generates a lot of trouble.
1461 // Test to know if content added by the hooks is already done by the main caller of pdf_writelinedesc
1462 $reshook = $hookmanager->executeHooks('pdf_writelinedesc', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1463
1464 if (!empty($hookmanager->resPrint)) {
1465 $result .= $hookmanager->resPrint;
1466 }
1467 }
1468 if (empty($reshook)) {
1469 $labelproductservice = pdf_getlinedesc($object, $i, $outputlangs, $hideref, $hidedesc, $issupplierline);
1470 $labelproductservice = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $labelproductservice, -1, $nbrep);
1471
1472 //var_dump($labelproductservice);exit;
1473
1474 // 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"
1475 // We make the reverse, so PDF generation has the real URL.
1476 $nbrep = 0;
1477 $labelproductservice = preg_replace('/(<img[^>]*src=")([^"]*)(&amp;)([^"]*")/', '\1\2&\4', $labelproductservice, -1, $nbrep);
1478
1479 if (getDolGlobalString('MARGIN_TOP_ZERO_UL')) {
1480 $pdf->setListIndentWidth(5);
1481 $TMarginList = ['ul' => [['h' => 0.1, ],['h' => 0.1, ]], 'li' => [['h' => 0.1, ],],];
1482 $pdf->setHtmlVSpace($TMarginList);
1483 }
1484
1485 // Description
1486 $pdf->writeHTMLCell($w, $h, $posx, $posy, $outputlangs->convToOutputCharset($labelproductservice), 0, 1, false, true, $align, true);
1487 $result .= $labelproductservice;
1488 }
1489 return $result;
1490}
1491
1503function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
1504{
1505 global $db, $conf, $langs;
1506
1507 $idprod = (!empty($object->lines[$i]->fk_product) ? $object->lines[$i]->fk_product : false);
1508 $label = (!empty($object->lines[$i]->label) ? $object->lines[$i]->label : (!empty($object->lines[$i]->product_label) ? $object->lines[$i]->product_label : ''));
1509 $product_barcode = (!empty($object->lines[$i]->product_barcode) ? $object->lines[$i]->product_barcode : "");
1510 $desc = (!empty($object->lines[$i]->desc) ? $object->lines[$i]->desc : (!empty($object->lines[$i]->description) ? $object->lines[$i]->description : ''));
1511 $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
1512 $note = (!empty($object->lines[$i]->note) ? $object->lines[$i]->note : '');
1513 $dbatch = (!empty($object->lines[$i]->detail_batch) ? $object->lines[$i]->detail_batch : false);
1514
1515 $multilangsactive = getDolGlobalInt('MAIN_MULTILANGS');
1516
1517 if ($issupplierline) {
1518 include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
1519 $prodser = new ProductFournisseur($db);
1520 } else {
1521 include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
1522 $prodser = new Product($db);
1523
1524 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1525 include_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
1526 }
1527 }
1528
1529 //id
1530 $idprod = (!empty($object->lines[$i]->fk_product) ? $object->lines[$i]->fk_product : false);
1531 if ($idprod) {
1532 $prodser->fetch($idprod);
1533 //load multilangs
1534 if ($multilangsactive) {
1535 $prodser->getMultiLangs();
1536 $object->lines[$i]->multilangs = $prodser->multilangs;
1537 }
1538 }
1539 //label
1540 if (!empty($object->lines[$i]->label)) {
1541 $label = $object->lines[$i]->label;
1542 } else {
1543 if (!empty($object->lines[$i]->multilangs[$outputlangs->defaultlang]['label']) && $multilangsactive) {
1544 $label = $object->lines[$i]->multilangs[$outputlangs->defaultlang]['label'];
1545 } else {
1546 if (!empty($object->lines[$i]->product_label)) {
1547 $label = $object->lines[$i]->product_label;
1548 } else {
1549 $label = '';
1550 }
1551 }
1552 }
1553 //description
1554 if (!empty($object->lines[$i]->desc)) {
1555 $desc = $object->lines[$i]->desc;
1556 } else {
1557 if (!empty($object->lines[$i]->multilangs[$outputlangs->defaultlang]['description']) && $multilangsactive) {
1558 $desc = $object->lines[$i]->multilangs[$outputlangs->defaultlang]['description'];
1559 } else {
1560 if (!empty($object->lines[$i]->description)) {
1561 $desc = $object->lines[$i]->description;
1562 } else {
1563 $desc = '';
1564 }
1565 }
1566 }
1567 //ref supplier
1568 $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
1569 //note
1570 $note = (!empty($object->lines[$i]->note) ? $object->lines[$i]->note : '');
1571 //dbatch
1572 $dbatch = (!empty($object->lines[$i]->detail_batch) ? $object->lines[$i]->detail_batch : false);
1573
1574 if ($idprod) {
1575 // If a predefined product and multilang and on other lang, we renamed label with label translated
1576 if ($multilangsactive && ($outputlangs->defaultlang != $langs->defaultlang)) {
1577 $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)
1578
1579 // 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
1580 // ($textwasnotmodified is replaced with $textwasmodifiedorcompleted and we add completion).
1581
1582 // Set label
1583 // 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.
1584 //var_dump($outputlangs->defaultlang.' - '.$langs->defaultlang.' - '.$label.' - '.$prodser->label);exit;
1585 $textwasnotmodified = ($label == $prodser->label);
1586 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1587 $label = $prodser->multilangs[$outputlangs->defaultlang]["label"];
1588 }
1589
1590 // Set desc
1591 // Manage HTML entities description test because $prodser->description is store with htmlentities but $desc no
1592 $textwasnotmodified = false;
1593 if (!empty($desc) && dol_textishtml($desc) && !empty($prodser->description) && dol_textishtml($prodser->description)) {
1594 $textwasnotmodified = (strpos(dol_html_entity_decode($desc, ENT_QUOTES | ENT_HTML5), dol_html_entity_decode($prodser->description, ENT_QUOTES | ENT_HTML5)) !== false);
1595 } else {
1596 $textwasnotmodified = ($desc == $prodser->description);
1597 }
1598 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["description"])) {
1599 if ($textwasnotmodified) {
1600 $desc = str_replace($prodser->description, $prodser->multilangs[$outputlangs->defaultlang]["description"], $desc);
1601 } elseif ($translatealsoifmodified) {
1602 $desc = $prodser->multilangs[$outputlangs->defaultlang]["description"];
1603 }
1604 }
1605
1606 // Set note
1607 $textwasnotmodified = ($note == $prodser->note_public);
1608 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["other"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1609 $note = $prodser->multilangs[$outputlangs->defaultlang]["other"];
1610 }
1611 }
1612 } 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
1613 $desc = str_replace('(DEPOSIT)', $outputlangs->trans('Deposit'), $desc);
1614 }
1615
1616 $libelleproduitservice = ''; // Default value
1617 if (!getDolGlobalString('PDF_HIDE_PRODUCT_LABEL_IN_SUPPLIER_LINES')) {
1618 // Description short of product line
1619 $libelleproduitservice = $label;
1620 if (!empty($libelleproduitservice) && getDolGlobalString('PDF_BOLD_PRODUCT_LABEL')) {
1621 // Adding <b> may convert the original string into a HTML string. So we have to first
1622 // convert \n into <br> we text is not already HTML.
1623 if (!dol_textishtml($libelleproduitservice)) {
1624 $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1625 }
1626 $libelleproduitservice = '<b>'.$libelleproduitservice.'</b>';
1627 }
1628 }
1629
1630
1631 // Add ref of subproducts
1632 if (getDolGlobalString('SHOW_SUBPRODUCT_REF_IN_PDF')) {
1633 $prodser->get_sousproduits_arbo();
1634 if (!empty($prodser->sousprods) && is_array($prodser->sousprods) && count($prodser->sousprods)) {
1635 $outputlangs->load('mrp');
1636 $tmparrayofsubproducts = reset($prodser->sousprods);
1637
1638 $qtyText = null;
1639 if (isset($object->lines[$i]->qty) && !empty($object->lines[$i]->qty)) {
1640 $qtyText = $object->lines[$i]->qty;
1641 } elseif (isset($object->lines[$i]->qty_shipped) && !empty($object->lines[$i]->qty_shipped)) {
1642 $qtyText = $object->lines[$i]->qty;
1643 }
1644
1645 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF')) {
1646 foreach ($tmparrayofsubproducts as $subprodval) {
1647 $libelleproduitservice = dol_concatdesc(
1648 dol_concatdesc($libelleproduitservice, " * ".$subprodval[3]),
1649 (!empty($qtyText) ?
1650 $outputlangs->trans('Qty').':'.$qtyText.' x '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1].'= '.$outputlangs->trans('QtyTot').':'.$subprodval[1] * $qtyText :
1651 $outputlangs->trans('Qty').' '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1])
1652 );
1653 }
1654 } else {
1655 foreach ($tmparrayofsubproducts as $subprodval) {
1656 $libelleproduitservice = dol_concatdesc(
1657 dol_concatdesc($libelleproduitservice, " * ".$subprodval[5].(($subprodval[5] && $subprodval[3]) ? ' - ' : '').$subprodval[3]),
1658 (!empty($qtyText) ?
1659 $outputlangs->trans('Qty').':'.$qtyText.' x '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1].'= '.$outputlangs->trans('QtyTot').':'.$subprodval[1] * $qtyText :
1660 $outputlangs->trans('Qty').' '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1])
1661 );
1662 }
1663 }
1664 }
1665 }
1666
1667 if (isModEnabled('barcode') && getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_PRODUCT_BARCODE') && !empty($product_barcode)) {
1668 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $outputlangs->trans("BarCode")." ".$product_barcode);
1669 }
1670
1671 // Description long of product line
1672 if (!empty($desc) && ($desc != $label)) {
1673 if ($desc == '(CREDIT_NOTE)' && $object->lines[$i]->fk_remise_except) {
1674 $discount = new DiscountAbsolute($db);
1675 $discount->fetch($object->lines[$i]->fk_remise_except);
1676 $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1677 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromCreditNote", $sourceref);
1678 } elseif ($desc == '(DEPOSIT)' && $object->lines[$i]->fk_remise_except) {
1679 $discount = new DiscountAbsolute($db);
1680 $discount->fetch($object->lines[$i]->fk_remise_except);
1681 $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1682 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromDeposit", $sourceref);
1683 // Add date of deposit
1684 if (getDolGlobalString('INVOICE_ADD_DEPOSIT_DATE')) {
1685 $libelleproduitservice .= ' ('.dol_print_date($discount->datec, 'day', '', $outputlangs).')';
1686 }
1687 } elseif ($desc == '(EXCESS RECEIVED)' && $object->lines[$i]->fk_remise_except) {
1688 $discount = new DiscountAbsolute($db);
1689 $discount->fetch($object->lines[$i]->fk_remise_except);
1690 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessReceived", $discount->ref_facture_source);
1691 } elseif ($desc == '(EXCESS PAID)' && $object->lines[$i]->fk_remise_except) {
1692 $discount = new DiscountAbsolute($db);
1693 $discount->fetch($object->lines[$i]->fk_remise_except);
1694 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessPaid", $discount->ref_invoice_supplier_source);
1695 } else {
1696 if ($idprod) {
1697 // Check if description must be output
1698 if (!empty($object->element)) {
1699 $tmpkey = 'MAIN_DOCUMENTS_HIDE_DESCRIPTION_FOR_'.strtoupper($object->element);
1700 if (getDolGlobalString($tmpkey)) {
1701 $hidedesc = 1;
1702 }
1703 }
1704 if (empty($hidedesc)) {
1705 if (getDolGlobalString('MAIN_DOCUMENTS_DESCRIPTION_FIRST')) {
1706 $libelleproduitservice = dol_concatdesc($desc, $libelleproduitservice);
1707 } else {
1708 if (getDolGlobalString('HIDE_LABEL_VARIANT_PDF') && $prodser->isVariant()) {
1709 $libelleproduitservice = $desc;
1710 } else {
1711 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1712 }
1713 }
1714 }
1715 } else {
1716 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1717 }
1718 }
1719 }
1720
1721 // We add ref of product (and supplier ref if defined)
1722 $prefix_prodserv = "";
1723 $ref_prodserv = "";
1724 if (getDolGlobalString('PRODUCT_ADD_TYPE_IN_DOCUMENTS')) { // In standard mode, we do not show this
1725 if ($prodser->isService()) {
1726 $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service")." ";
1727 } else {
1728 $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Product")." ";
1729 }
1730 }
1731
1732 if (empty($hideref)) {
1733 if ($issupplierline) {
1734 if (!getDolGlobalString('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES')) { // Common case
1735 $ref_prodserv = $prodser->ref; // Show local ref
1736 if ($ref_supplier) {
1737 $ref_prodserv .= ($prodser->ref ? ' (' : '').$outputlangs->transnoentitiesnoconv("SupplierRef").' '.$ref_supplier.($prodser->ref ? ')' : '');
1738 }
1739 } elseif (getDolGlobalInt('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES') == 1) {
1740 $ref_prodserv = $ref_supplier;
1741 } elseif (getDolGlobalInt('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES') == 2) {
1742 $ref_prodserv = $ref_supplier.' ('.$outputlangs->transnoentitiesnoconv("InternalRef").' '.$prodser->ref.')';
1743 }
1744 } else {
1745 $ref_prodserv = $prodser->ref; // Show local ref only
1746
1747 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1748 $productCustomerPriceStatic = new ProductCustomerPrice($db);
1749 $filter = array('fk_product' => $idprod, 'fk_soc' => $object->socid);
1750
1751 $nbCustomerPrices = $productCustomerPriceStatic->fetchAll('', '', 1, 0, $filter);
1752
1753 if ($nbCustomerPrices > 0) {
1754 $productCustomerPrice = $productCustomerPriceStatic->lines[0];
1755
1756 if (!empty($productCustomerPrice->ref_customer)) {
1757 switch ($conf->global->PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE) {
1758 case 1:
1759 $ref_prodserv = $productCustomerPrice->ref_customer;
1760 break;
1761
1762 case 2:
1763 $ref_prodserv = $productCustomerPrice->ref_customer . ' (' . $outputlangs->transnoentitiesnoconv('InternalRef') . ' ' . $ref_prodserv . ')';
1764 break;
1765
1766 default:
1767 $ref_prodserv = $ref_prodserv . ' (' . $outputlangs->transnoentitiesnoconv('RefCustomer') . ' ' . $productCustomerPrice->ref_customer . ')';
1768 }
1769 }
1770 }
1771 }
1772 }
1773
1774 if (!empty($libelleproduitservice) && !empty($ref_prodserv)) {
1775 $ref_prodserv .= " - ";
1776 }
1777 }
1778
1779 if (!empty($ref_prodserv) && getDolGlobalString('PDF_BOLD_PRODUCT_REF_AND_PERIOD')) {
1780 if (!dol_textishtml($libelleproduitservice)) {
1781 $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1782 }
1783 $ref_prodserv = '<b>'.$ref_prodserv.'</b>';
1784 // $prefix_prodserv and $ref_prodser are not HTML var
1785 }
1786 $libelleproduitservice = $prefix_prodserv.$ref_prodserv.$libelleproduitservice;
1787
1788 // Add an additional description for the category products
1789 if (getDolGlobalString('CATEGORY_ADD_DESC_INTO_DOC') && $idprod && isModEnabled('category')) {
1790 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1791 $categstatic = new Categorie($db);
1792 // recovering the list of all the categories linked to product
1793 $tblcateg = $categstatic->containing($idprod, Categorie::TYPE_PRODUCT);
1794 foreach ($tblcateg as $cate) {
1795 // Adding the descriptions if they are filled
1796 $desccateg = $cate->description;
1797 if ($desccateg) {
1798 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desccateg);
1799 }
1800 }
1801 }
1802
1803 if (!empty($object->lines[$i]->date_start) || !empty($object->lines[$i]->date_end)) {
1804 $format = 'day';
1805 $period = '';
1806 // Show duration if exists
1807 if ($object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1808 $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)).')';
1809 }
1810 if ($object->lines[$i]->date_start && !$object->lines[$i]->date_end) {
1811 $period = '('.$outputlangs->transnoentitiesnoconv('DateFrom', dol_print_date($object->lines[$i]->date_start, $format, false, $outputlangs)).')';
1812 }
1813 if (!$object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1814 $period = '('.$outputlangs->transnoentitiesnoconv('DateUntil', dol_print_date($object->lines[$i]->date_end, $format, false, $outputlangs)).')';
1815 }
1816 //print '>'.$outputlangs->charset_output.','.$period;
1817 if (getDolGlobalString('PDF_BOLD_PRODUCT_REF_AND_PERIOD')) {
1818 if (!dol_textishtml($libelleproduitservice)) {
1819 $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1820 }
1821 $libelleproduitservice .= '<br><b style="color:#333666;" ><em>'.$period.'</em></b>';
1822 } else {
1823 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $period);
1824 }
1825 //print $libelleproduitservice;
1826 }
1827
1828 // Show information for lot
1829 if (!empty($dbatch)) {
1830 // $object is a shipment.
1831 //var_dump($object->lines[$i]->details_entrepot); // array from llx_expeditiondet (we can have several lines for one fk_origin_line)
1832 //var_dump($object->lines[$i]->detail_batch); // array from llx_expeditiondet_batch (each line with a lot is linked to llx_expeditiondet)
1833
1834 include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
1835 include_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
1836 $tmpwarehouse = new Entrepot($db);
1837 $tmpproductbatch = new Productbatch($db);
1838
1839 $format = 'day';
1840 foreach ($dbatch as $detail) {
1841 $dte = array();
1842 if ($detail->eatby) {
1843 $dte[] = $outputlangs->transnoentitiesnoconv('printEatby', dol_print_date($detail->eatby, $format, false, $outputlangs));
1844 }
1845 if ($detail->sellby) {
1846 $dte[] = $outputlangs->transnoentitiesnoconv('printSellby', dol_print_date($detail->sellby, $format, false, $outputlangs));
1847 }
1848 if ($detail->batch) {
1849 $dte[] = $outputlangs->transnoentitiesnoconv('printBatch', $detail->batch);
1850 }
1851 if ($detail->qty) {
1852 $dte[] = $outputlangs->transnoentitiesnoconv('printQty', $detail->qty);
1853 }
1854
1855 // Add also info of planned warehouse for lot
1856 if ($object->element == 'shipping' && $detail->fk_origin_stock > 0 && getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1857 $resproductbatch = $tmpproductbatch->fetch($detail->fk_origin_stock);
1858 if ($resproductbatch > 0) {
1859 $reswarehouse = $tmpwarehouse->fetch($tmpproductbatch->warehouseid);
1860 if ($reswarehouse > 0) {
1861 $dte[] = $tmpwarehouse->ref;
1862 }
1863 }
1864 }
1865
1866 $libelleproduitservice .= "__N__ ".implode(" - ", $dte);
1867 }
1868 } else {
1869 if (getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1870 // TODO Show warehouse for shipment line without batch
1871 }
1872 }
1873
1874 // Now we convert \n into br
1875 if (dol_textishtml($libelleproduitservice)) {
1876 $libelleproduitservice = preg_replace('/__N__/', '<br>', $libelleproduitservice);
1877 } else {
1878 $libelleproduitservice = preg_replace('/__N__/', "\n", $libelleproduitservice);
1879 }
1880 $libelleproduitservice = dol_htmlentitiesbr($libelleproduitservice, 1);
1881
1882 return $libelleproduitservice;
1883}
1884
1894function pdf_getlinenum($object, $i, $outputlangs, $hidedetails = 0)
1895{
1896 global $hookmanager;
1897
1898 $reshook = 0;
1899 $result = '';
1900 //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) ) )
1901 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
1902 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1903 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1904 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1905 }
1906 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1907 $action = '';
1908 $reshook = $hookmanager->executeHooks('pdf_getlinenum', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1909 $result .= $hookmanager->resPrint;
1910 }
1911 if (empty($reshook)) {
1912 $result .= dol_htmlentitiesbr($object->lines[$i]->num);
1913 }
1914 return $result;
1915}
1916
1917
1927function pdf_getlineref($object, $i, $outputlangs, $hidedetails = 0)
1928{
1929 global $hookmanager;
1930
1931 $reshook = 0;
1932 $result = '';
1933 //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) ) )
1934 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
1935 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1936 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1937 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1938 }
1939 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1940 $action = '';
1941 $reshook = $hookmanager->executeHooks('pdf_getlineref', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1942 $result .= $hookmanager->resPrint;
1943 }
1944 if (empty($reshook)) {
1945 $result .= dol_htmlentitiesbr($object->lines[$i]->product_ref);
1946 }
1947 return $result;
1948}
1949
1950
1960function pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails = 0)
1961{
1962 global $hookmanager;
1963
1964 $reshook = 0;
1965 $result = '';
1966 //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) ) )
1967 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
1968 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1969 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1970 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1971 }
1972 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1973 $action = '';
1974 $reshook = $hookmanager->executeHooks('pdf_getlineref_supplier', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1975 $result .= $hookmanager->resPrint;
1976 }
1977 if (empty($reshook)) {
1978 $result .= dol_htmlentitiesbr($object->lines[$i]->ref_supplier);
1979 }
1980 return $result;
1981}
1982
1992function pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails = 0)
1993{
1994 global $conf, $hookmanager, $mysoc;
1995
1996 $result = '';
1997 $reshook = 0;
1998 //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) ) )
1999 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
2000 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2001 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2002 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2003 }
2004 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2005 $action = '';
2006 $reshook = $hookmanager->executeHooks('pdf_getlinevatrate', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2007
2008 if (!empty($hookmanager->resPrint)) {
2009 $result .= $hookmanager->resPrint;
2010 }
2011 }
2012 if (empty($reshook)) {
2013 if (empty($hidedetails) || $hidedetails > 1) {
2014 $tmpresult = '';
2015
2016 $tmpresult .= vatrate($object->lines[$i]->tva_tx, 0, $object->lines[$i]->info_bits, -1);
2017 if (!getDolGlobalString('MAIN_PDF_MAIN_HIDE_SECOND_TAX')) {
2018 if (price2num($object->lines[$i]->localtax1_tx)) {
2019 if (preg_replace('/[\s0%]/', '', $tmpresult)) {
2020 $tmpresult .= '/';
2021 } else {
2022 $tmpresult = '';
2023 }
2024 $tmpresult .= vatrate((string) abs($object->lines[$i]->localtax1_tx), 0);
2025 }
2026 }
2027 if (!getDolGlobalString('MAIN_PDF_MAIN_HIDE_THIRD_TAX')) {
2028 if (price2num($object->lines[$i]->localtax2_tx)) {
2029 if (preg_replace('/[\s0%]/', '', $tmpresult)) {
2030 $tmpresult .= '/';
2031 } else {
2032 $tmpresult = '';
2033 }
2034 $tmpresult .= vatrate((string) abs($object->lines[$i]->localtax2_tx), 0);
2035 }
2036 }
2037 $tmpresult .= '%';
2038
2039 $result .= $tmpresult;
2040 }
2041 }
2042 return $result;
2043}
2044
2054function pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails = 0)
2055{
2056 global $conf, $hookmanager;
2057
2058 $sign = 1;
2059 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2060 $sign = -1;
2061 }
2062
2063 $result = '';
2064 $reshook = 0;
2065 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2066 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2067 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2068 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2069 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2070 }
2071 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2072 $action = '';
2073 $reshook = $hookmanager->executeHooks('pdf_getlineupexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2074
2075 if (!empty($hookmanager->resPrint)) {
2076 $result .= $hookmanager->resPrint;
2077 }
2078 }
2079 if (empty($reshook)) {
2080 if (empty($hidedetails) || $hidedetails > 1) {
2081 $subprice = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice);
2082 $result .= price($sign * $subprice, 0, $outputlangs);
2083 }
2084 }
2085 return $result;
2086}
2087
2097function pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails = 0)
2098{
2099 global $hookmanager, $conf;
2100
2101 $sign = 1;
2102 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2103 $sign = -1;
2104 }
2105
2106 $result = '';
2107 $reshook = 0;
2108 //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) ) )
2109 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
2110 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2111 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2112 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2113 }
2114 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2115 $action = '';
2116 $reshook = $hookmanager->executeHooks('pdf_getlineupwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2117
2118 if (!empty($hookmanager->resPrint)) {
2119 $result .= $hookmanager->resPrint;
2120 }
2121 }
2122 if (empty($reshook)) {
2123 if (empty($hidedetails) || $hidedetails > 1) {
2124 $result .= price($sign * (($object->lines[$i]->subprice) + ($object->lines[$i]->subprice) * ($object->lines[$i]->tva_tx) / 100), 0, $outputlangs);
2125 }
2126 }
2127 return $result;
2128}
2129
2139function pdf_getlineqty($object, $i, $outputlangs, $hidedetails = 0)
2140{
2141 global $hookmanager;
2142
2143 $result = '';
2144 $reshook = 0;
2145 //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) ) )
2146 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
2147 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2148 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2149 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2150 }
2151 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2152 $action = '';
2153 $reshook = $hookmanager->executeHooks('pdf_getlineqty', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2154
2155 if (!empty($hookmanager->resPrint)) {
2156 $result = $hookmanager->resPrint;
2157 }
2158 }
2159 if (empty($reshook)) {
2160 if ($object->lines[$i]->special_code == 3) {
2161 return '';
2162 }
2163 if (empty($hidedetails) || $hidedetails > 1) {
2164 $result .= $object->lines[$i]->qty;
2165 }
2166 }
2167 return $result;
2168}
2169
2179function pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails = 0)
2180{
2181 global $hookmanager;
2182
2183 $reshook = 0;
2184 $result = '';
2185 //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) ) )
2186 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
2187 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2188 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2189 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2190 }
2191 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2192 $action = '';
2193 $reshook = $hookmanager->executeHooks('pdf_getlineqty_asked', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2194
2195 if (!empty($hookmanager->resPrint)) {
2196 $result .= $hookmanager->resPrint;
2197 }
2198 }
2199 if (empty($reshook)) {
2200 if ($object->lines[$i]->special_code == 3) {
2201 return '';
2202 }
2203 if (empty($hidedetails) || $hidedetails > 1) {
2204 $result .= $object->lines[$i]->qty_asked;
2205 }
2206 }
2207 return $result;
2208}
2209
2219function pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails = 0)
2220{
2221 global $hookmanager;
2222
2223 $reshook = 0;
2224 $result = '';
2225 //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) ) )
2226 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
2227 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2228 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2229 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2230 }
2231 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2232 $action = '';
2233 $reshook = $hookmanager->executeHooks('pdf_getlineqty_shipped', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2234
2235 if (!empty($hookmanager->resPrint)) {
2236 $result .= $hookmanager->resPrint;
2237 }
2238 }
2239 if (empty($reshook)) {
2240 if ($object->lines[$i]->special_code == 3) {
2241 return '';
2242 }
2243 if (empty($hidedetails) || $hidedetails > 1) {
2244 $result .= $object->lines[$i]->qty_shipped;
2245 }
2246 }
2247 return $result;
2248}
2249
2259function pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails = 0)
2260{
2261 global $hookmanager;
2262
2263 $reshook = 0;
2264 $result = '';
2265 //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) ) )
2266 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
2267 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2268 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) { // @phan-suppress-current-line PhanUndeclaredProperty
2269 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2270 }
2271 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2272 $action = '';
2273 $reshook = $hookmanager->executeHooks('pdf_getlineqty_keeptoship', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2274
2275 if (!empty($hookmanager->resPrint)) {
2276 $result .= $hookmanager->resPrint;
2277 }
2278 }
2279 if (empty($reshook)) {
2280 if ($object->lines[$i]->special_code == 3) {
2281 return '';
2282 }
2283 if (empty($hidedetails) || $hidedetails > 1) {
2284 $result .= ($object->lines[$i]->qty_asked - $object->lines[$i]->qty_shipped);
2285 }
2286 }
2287 return $result;
2288}
2289
2299function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0)
2300{
2301 global $hookmanager, $langs;
2302
2303 $reshook = 0;
2304 $result = '';
2305 //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) ) )
2306 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
2307 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2308 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2309 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2310 }
2311 $parameters = array(
2312 'i' => $i,
2313 'outputlangs' => $outputlangs,
2314 'hidedetails' => $hidedetails,
2315 'special_code' => $special_code
2316 );
2317 $action = '';
2318 $reshook = $hookmanager->executeHooks('pdf_getlineunit', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2319
2320 if (!empty($hookmanager->resPrint)) {
2321 $result .= $hookmanager->resPrint;
2322 }
2323 }
2324 if (empty($reshook)) {
2325 if (empty($hidedetails) || $hidedetails > 1) {
2326 $result .= $langs->transnoentitiesnoconv($object->lines[$i]->getLabelOfUnit('short'));
2327 }
2328 }
2329 return $result;
2330}
2331
2332
2342function pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails = 0)
2343{
2344 global $hookmanager;
2345
2346 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
2347
2348 $reshook = 0;
2349 $result = '';
2350 //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) ) )
2351 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
2352 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2353 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2354 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2355 }
2356 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2357 $action = '';
2358 $reshook = $hookmanager->executeHooks('pdf_getlineremisepercent', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2359
2360 if (!empty($hookmanager->resPrint)) {
2361 $result .= $hookmanager->resPrint;
2362 }
2363 }
2364 if (empty($reshook)) {
2365 if ($object->lines[$i]->special_code == 3) {
2366 return '';
2367 }
2368 if (empty($hidedetails) || $hidedetails > 1) {
2369 $result .= dol_print_reduction($object->lines[$i]->remise_percent, $outputlangs);
2370 }
2371 }
2372 return $result;
2373}
2374
2385function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = null)
2386{
2387 if (empty($hookmanager)) {
2388 global $hookmanager;
2389 }
2390 global $conf;
2391
2392 $reshook = 0;
2393 $result = '';
2394 //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) ) )
2395 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
2396 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2397 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2398 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2399 }
2400 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2401 $action = '';
2402 $reshook = $hookmanager->executeHooks('pdf_getlineprogress', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2403
2404 if (!empty($hookmanager->resPrint)) {
2405 return $hookmanager->resPrint;
2406 }
2407 }
2408 if (empty($reshook)) {
2409 if ($object->lines[$i]->special_code == 3) {
2410 return '';
2411 }
2412 if (empty($hidedetails) || $hidedetails > 1) {
2413 if (getDolGlobalString('SITUATION_DISPLAY_DIFF_ON_PDF')) {
2414 $prev_progress = 0;
2415 if (method_exists($object->lines[$i], 'get_prev_progress')) {
2416 $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2417 }
2418 $result = round($object->lines[$i]->situation_percent - $prev_progress, 1).'%';
2419 } else {
2420 $result = round($object->lines[$i]->situation_percent, 1).'%';
2421 }
2422 }
2423 }
2424 return $result;
2425}
2426
2436function pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails = 0)
2437{
2438 global $conf, $hookmanager;
2439
2440 $sign = 1;
2441 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2442 $sign = -1;
2443 }
2444
2445 $reshook = 0;
2446 $result = '';
2447 //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) ) )
2448 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
2449 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2450 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2451 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2452 }
2453 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code, 'sign' => $sign);
2454 $action = '';
2455 $reshook = $hookmanager->executeHooks('pdf_getlinetotalexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2456
2457 if (!empty($hookmanager->resPrint)) {
2458 $result .= $hookmanager->resPrint;
2459 }
2460 }
2461 if (empty($reshook)) {
2462 if (!empty($object->lines[$i]) && $object->lines[$i]->special_code == 3) {
2463 $result .= $outputlangs->transnoentities("Option");
2464 } elseif (empty($hidedetails) || $hidedetails > 1) {
2465 $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
2466 if (!empty($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
2467 // TODO Remove this. The total should be saved correctly in database instead of being modified here.
2468 $prev_progress = 0;
2469 $progress = 1;
2470 if (method_exists($object->lines[$i], 'get_prev_progress')) {
2471 $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2472 $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
2473 }
2474 $result .= price($sign * ($total_ht / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
2475 } else {
2476 $result .= price($sign * $total_ht, 0, $outputlangs);
2477 }
2478 }
2479 }
2480 return $result;
2481}
2482
2492function pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails = 0)
2493{
2494 global $hookmanager, $conf;
2495
2496 $sign = 1;
2497 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2498 $sign = -1;
2499 }
2500
2501 $reshook = 0;
2502 $result = '';
2503 //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) ) )
2504 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
2505 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2506 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2507 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2508 }
2509 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2510 $action = '';
2511 $reshook = $hookmanager->executeHooks('pdf_getlinetotalwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2512
2513 if (!empty($hookmanager->resPrint)) {
2514 $result .= $hookmanager->resPrint;
2515 }
2516 }
2517 if (empty($reshook)) {
2518 if ($object->lines[$i]->special_code == 3) {
2519 $result .= $outputlangs->transnoentities("Option");
2520 } elseif (empty($hidedetails) || $hidedetails > 1) {
2521 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ttc : $object->lines[$i]->total_ttc);
2522 if (isset($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
2523 // TODO Remove this. The total should be saved correctly in database instead of being modified here.
2524 $prev_progress = 0;
2525 $progress = 1;
2526 if (method_exists($object->lines[$i], 'get_prev_progress')) {
2527 $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2528 $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
2529 }
2530 $result .= price($sign * ($total_ttc / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
2531 } else {
2532 $result .= price($sign * $total_ttc, 0, $outputlangs);
2533 }
2534 }
2535 }
2536 return $result;
2537}
2538
2547function pdf_getLinkedObjects(&$object, $outputlangs)
2548{
2549 global $db, $hookmanager;
2550
2551 $linkedobjects = array();
2552
2553 $object->fetchObjectLinked();
2554
2555 foreach ($object->linkedObjects as $objecttype => $objects) {
2556 if ($objecttype == 'facture') {
2557 // 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.
2558 } elseif ($objecttype == 'propal' || $objecttype == 'supplier_proposal') {
2559 '@phan-var-force array<Propal|SupplierProposal> $objects';
2560 $outputlangs->load('propal');
2561
2562 foreach ($objects as $elementobject) {
2563 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefProposal");
2564 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2565 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DatePropal");
2566 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2567 }
2568 } elseif ($objecttype == 'commande' || $objecttype == 'supplier_order') {
2569 '@phan-var-force array<Commande|CommandeFournisseur> $objects';
2570 $outputlangs->load('orders');
2571
2572 if (count($objects) > 1 && count($objects) <= (getDolGlobalInt("MAXREFONDOC") ? getDolGlobalInt("MAXREFONDOC") : 10)) {
2573 if (empty($object->context['DolPublicNoteAppendedGetLinkedObjects'])) { // Check if already appended before add to avoid repeat data
2574 $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("RefOrder").' :');
2575 foreach ($objects as $elementobject) {
2576 $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities($elementobject->ref).(empty($elementobject->ref_client) ? '' : ' ('.$elementobject->ref_client.')').(empty($elementobject->ref_supplier) ? '' : ' ('.$elementobject->ref_supplier.')').' ');
2577 $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("OrderDate").' : '.dol_print_date($elementobject->date, 'day', '', $outputlangs));
2578 }
2579 }
2580 } elseif (count($objects) == 1) {
2581 $elementobject = array_shift($objects);
2582 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder");
2583 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref).(!empty($elementobject->ref_client) ? ' ('.$elementobject->ref_client.')' : '').(!empty($elementobject->ref_supplier) ? ' ('.$elementobject->ref_supplier.')' : '');
2584 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("OrderDate");
2585 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2586 }
2587 } elseif ($objecttype == 'contrat') {
2588 '@phan-var-force Contrat[] $objects';
2589 $outputlangs->load('contracts');
2590 foreach ($objects as $elementobject) {
2591 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefContract");
2592 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2593 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DateContract");
2594 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date_contrat, 'day', '', $outputlangs);
2595 }
2596 } elseif ($objecttype == 'fichinter') {
2597 '@phan-var-force Fichinter[] $objects';
2598 $outputlangs->load('interventions');
2599 foreach ($objects as $elementobject) {
2600 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("InterRef");
2601 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2602 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("InterDate");
2603 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->datec, 'day', '', $outputlangs);
2604 }
2605 } elseif ($objecttype == 'shipping') {
2606 '@phan-var-force Expedition[] $objects';
2607 $outputlangs->loadLangs(array("orders", "sendings"));
2608
2609 if (count($objects) > 1) {
2610 $order = null;
2611
2612 $refListsTxt = '';
2613 if (empty($object->linkedObjects['commande']) && $object->element != 'commande') {
2614 $refListsTxt .= $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending").' :';
2615 } else {
2616 $refListsTxt .= $outputlangs->transnoentities("RefSending").' :';
2617 }
2618 // We concat this record info into fields xxx_value. title is overwrote.
2619 foreach ($objects as $elementobject) {
2620 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
2621 $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2622 if (!empty($elementobject->linkedObjectsIds['commande'])) {
2623 include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2624 $order = new Commande($db);
2625 $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2626 if ($ret < 1) {
2627 $order = null;
2628 }
2629 }
2630 }
2631 $refListsTxt .= (!empty($refListsTxt) ? ' ' : '');
2632 if (! is_object($order)) {
2633 $refListsTxt .= $outputlangs->transnoentities($elementobject->ref);
2634 } else {
2635 $refListsTxt .= $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
2636 $refListsTxt .= ' / '.$outputlangs->transnoentities($elementobject->ref);
2637 }
2638 }
2639
2640 if (empty($object->context['DolPublicNoteAppendedGetLinkedObjects'])) { // Check if already appended before add to avoid repeat data
2641 $object->note_public = dol_concatdesc($object->note_public, $refListsTxt);
2642 }
2643 } elseif (count($objects) == 1) {
2644 $elementobject = array_shift($objects);
2645 $order = null;
2646 // We concat this record info into fields xxx_value. title is overwrote.
2647 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
2648 $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2649 if (!empty($elementobject->linkedObjectsIds['commande'])) {
2650 include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2651 $order = new Commande($db);
2652 $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2653 if ($ret < 1) {
2654 $order = null;
2655 }
2656 }
2657 }
2658
2659 if (! is_object($order)) {
2660 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefSending");
2661 if (empty($linkedobjects[$objecttype]['ref_value'])) {
2662 $linkedobjects[$objecttype]['ref_value'] = '';
2663 } else {
2664 $linkedobjects[$objecttype]['ref_value'] .= ' / ';
2665 }
2666 $linkedobjects[$objecttype]['ref_value'] .= $outputlangs->transnoentities($elementobject->ref);
2667 $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
2668 } else {
2669 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending");
2670 if (empty($linkedobjects[$objecttype]['ref_value'])) {
2671 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
2672 }
2673 $linkedobjects[$objecttype]['ref_value'] .= ' / '.$outputlangs->transnoentities($elementobject->ref);
2674 $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
2675 }
2676 }
2677 }
2678 }
2679
2680 $object->context['DolPublicNoteAppendedGetLinkedObjects'] = 1;
2681
2682 // For add external linked objects
2683 if (is_object($hookmanager)) {
2684 $parameters = array('linkedobjects' => $linkedobjects, 'outputlangs' => $outputlangs);
2685 $action = '';
2686 $reshook = $hookmanager->executeHooks('pdf_getLinkedObjects', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2687 if (empty($reshook)) {
2688 $linkedobjects = array_replace($linkedobjects, $hookmanager->resArray); // array_replace is used to preserve keys
2689 } elseif ($reshook>0) {
2690 // The array must be reinserted even if it is empty because clearing the array could be one of the actions performed by the hook.
2691 $linkedobjects = $hookmanager->resArray;
2692 }
2693 }
2694
2695 return $linkedobjects;
2696}
2697
2705function pdf_getSizeForImage($realpath)
2706{
2707 $maxwidth = getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20);
2708 $maxheight = getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT', 32);
2709
2710 include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
2711 $tmp = dol_getImageSize($realpath);
2712 $width = 0;
2713 $height = 0;
2714 if ($tmp['height']) {
2715 $width = (int) round($maxheight * $tmp['width'] / $tmp['height']); // I try to use maxheight
2716 if ($width > $maxwidth) { // Pb with maxheight, so i use maxwidth
2717 $width = $maxwidth;
2718 $height = (int) round($maxwidth * $tmp['height'] / $tmp['width']);
2719 } else { // No pb with maxheight
2720 $height = $maxheight;
2721 }
2722 }
2723 return array('width' => $width, 'height' => $height);
2724}
2725
2735function pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails = 0)
2736{
2737 global $hookmanager;
2738
2739 $sign = 1;
2740 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2741 $sign = -1;
2742 }
2743 if ($object->lines[$i]->special_code == 3) {
2744 // If option
2745 return $outputlangs->transnoentities("Option");
2746 } else {
2747 if (is_object($hookmanager)) {
2748 $special_code = $object->lines[$i]->special_code;
2749 if (!empty($object->lines[$i]->fk_parent_line)) {
2750 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2751 }
2752
2753 $parameters = array(
2754 'i' => $i,
2755 'outputlangs' => $outputlangs,
2756 'hidedetails' => $hidedetails,
2757 'special_code' => $special_code
2758 );
2759
2760 $action = '';
2761
2762 if ($hookmanager->executeHooks('getlinetotalremise', $parameters, $object, $action) > 0) { // Note that $action and $object may have been modified by some hooks
2763 if (isset($hookmanager->resArray['linetotalremise'])) {
2764 return (float) $hookmanager->resArray['linetotalremise'];
2765 } else {
2766 return (float) $hookmanager->resPrint; // For backward compatibility
2767 }
2768 }
2769 }
2770
2771 if (empty($hidedetails) || $hidedetails > 1) {
2772 return (float) price2num($sign * (($object->lines[$i]->subprice * (float) $object->lines[$i]->qty) - $object->lines[$i]->total_ht), 'MT', 1);
2773 }
2774 }
2775 return 0;
2776}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
Class to manage categories.
Class to manage customers orders.
Class to manage contact/addresses.
Class to manage absolute discounts.
Class to manage warehouses.
static getIBANLabel(Account $account)
Returns the name of the Iban label.
File of class to manage predefined price products or services by customer.
Class to manage predefined suppliers products.
Class to manage products or services.
Manage record for batch number management.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
getState($id, $withcode='0', $dbtouse=null, $withregion=0, $outputlangs=null, $entconv=1)
Return state translated from an id.
getFormeJuridiqueLabel($code)
Return the name translated of juridical status.
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.
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_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_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
dol_textishtml($msg, $option=0)
Return if a text is a html content.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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...
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null, $include=null)
Return array of possible common substitutions.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
dol_getImageSize($file, $url=false)
Return size of image file on disk (Supported extensions are gif, jpg, png, bmp and webp)
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
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:2705
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:1446
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition pdf.lib.php:2436
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:1503
pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails=0)
Return line total amount discount.
Definition pdf.lib.php:2735
pdf_getFormat($outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition pdf.lib.php:86
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition pdf.lib.php:288
pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails=0)
Return line quantity shipped.
Definition pdf.lib.php:2219
pdf_getlinenum($object, $i, $outputlangs, $hidedetails=0)
Return line num.
Definition pdf.lib.php:1894
pdf_getEncryption($pathoffile)
Return if pdf file is protected/encrypted.
Definition pdf.lib.php:234
pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price including tax.
Definition pdf.lib.php:2097
pdf_getLinkedObjects(&$object, $outputlangs)
Return linked objects to use for document generation.
Definition pdf.lib.php:2547
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition pdf.lib.php:313
pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails=0)
Return line ref_supplier.
Definition pdf.lib.php:1960
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition pdf.lib.php:2492
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:1031
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition pdf.lib.php:2054
pdf_getlineprogress($object, $i, $outputlangs, $hidedetails=0, $hookmanager=null)
Return line percent.
Definition pdf.lib.php:2385
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition pdf.lib.php:1992
pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition pdf.lib.php:339
pdf_admin_prepare_head()
Return array head with list of tabs to view object information.
Definition pdf.lib.php:48
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:733
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1409
pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank information for PDF generation.
Definition pdf.lib.php:854
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition pdf.lib.php:265
pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails=0)
Return line keep to ship quantity.
Definition pdf.lib.php:2259
pdf_getlineref($object, $i, $outputlangs, $hidedetails=0)
Return line product ref.
Definition pdf.lib.php:1927
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formatted for output on PDF documents.
Definition pdf.lib.php:438
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition pdf.lib.php:2299
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition pdf.lib.php:2342
pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails=0)
Return line quantity asked.
Definition pdf.lib.php:2179
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition pdf.lib.php:2139
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:769
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition pdf.lib.php:128
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition pdf.lib.php:390
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition pdf.lib.php:789