dolibarr 21.0.0-beta
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($conf->global->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($conf->global->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
338function pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
339{
340 // store current object
341 $pdf->startTransaction();
342 // store starting values
343 $start_y = $pdf->GetY();
344 //var_dump($start_y);
345 $start_page = $pdf->getPage();
346 // call printing functions with content
347 $pdf->writeHTMLCell(0, 0, 0, $start_y, $htmlcontent, 0, 1, false, true, 'J', true);
348 // get the new Y
349 $end_y = $pdf->GetY();
350 $end_page = $pdf->getPage();
351 // calculate height
352 $height = 0;
353 if ($end_page == $start_page) {
354 $height = $end_y - $start_y;
355 } else {
356 for ($page = $start_page; $page <= $end_page; ++$page) {
357 $pdf->setPage($page);
358 $tmpm = $pdf->getMargins();
359 $tMargin = $tmpm['top'];
360 if ($page == $start_page) {
361 // first page
362 $height = $pdf->getPageHeight() - $start_y - $pdf->getBreakMargin();
363 } elseif ($page == $end_page) {
364 // last page
365 $height = $end_y - $tMargin;
366 } else {
367 $height = $pdf->getPageHeight() - $tMargin - $pdf->getBreakMargin();
368 }
369 }
370 }
371 // restore previous object
372 $pdf = $pdf->rollbackTransaction();
373
374 return $height;
375}
376
377
386function pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias = 0)
387{
388 global $conf;
389
390 // Recipient name
391 $socname = '';
392
393 if ($thirdparty instanceof Societe) {
394 $socname = $thirdparty->name;
395 if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->name_alias)) {
396 if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
397 $socname = $thirdparty->name_alias." - ".$thirdparty->name;
398 } else {
399 $socname = $thirdparty->name." - ".$thirdparty->name_alias;
400 }
401 }
402 } elseif ($thirdparty instanceof Contact) {
403 if ($thirdparty->socid > 0) {
404 $thirdparty->fetch_thirdparty();
405 $socname = $thirdparty->thirdparty->name;
406 if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->thirdparty->name_alias)) {
407 if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
408 $socname = $thirdparty->thirdparty->name_alias." - ".$thirdparty->thirdparty->name;
409 } else {
410 $socname = $thirdparty->thirdparty->name." - ".$thirdparty->thirdparty->name_alias;
411 }
412 }
413 }
414 } else {
415 throw new InvalidArgumentException('Parameter 1 $thirdparty is not a Societe nor Contact');
416 }
417
418 return $outputlangs->convToOutputCharset($socname);
419}
420
421
434function pdf_build_address($outputlangs, $sourcecompany, $targetcompany = '', $targetcontact = '', $usecontact = 0, $mode = 'source', $object = null)
435{
436 global $hookmanager;
437
438 if ($mode == 'source' && !is_object($sourcecompany)) {
439 return -1;
440 }
441 if ($mode == 'target' && !is_object($targetcompany)) {
442 return -1;
443 }
444
445 if (!empty($sourcecompany->state_id) && empty($sourcecompany->state)) {
446 $sourcecompany->state = getState($sourcecompany->state_id);
447 }
448 if (!empty($targetcompany->state_id) && empty($targetcompany->state)) {
449 $targetcompany->state = getState($targetcompany->state_id);
450 }
451
452 $reshook = 0;
453 $stringaddress = '';
454 if (is_object($hookmanager)) {
455 $parameters = array('sourcecompany' => &$sourcecompany, 'targetcompany' => &$targetcompany, 'targetcontact' => &$targetcontact, 'outputlangs' => $outputlangs, 'mode' => $mode, 'usecontact' => $usecontact);
456 $action = '';
457 $reshook = $hookmanager->executeHooks('pdf_build_address', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
458 $stringaddress .= $hookmanager->resPrint;
459 }
460 if (empty($reshook)) {
461 if ($mode == 'source') {
462 $withCountry = 0;
463 if (isset($targetcompany->country_code) && !empty($sourcecompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
464 $withCountry = 1;
465 }
466
467 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($sourcecompany, $withCountry, "\n", $outputlangs))."\n";
468
469 if (!getDolGlobalString('MAIN_PDF_DISABLESOURCEDETAILS')) {
470 // Phone
471 if ($sourcecompany->phone) {
472 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("PhoneShort").": ".$outputlangs->convToOutputCharset($sourcecompany->phone);
473 }
474 // Fax
475 if ($sourcecompany->fax) {
476 $stringaddress .= ($stringaddress ? ($sourcecompany->phone ? " - " : "\n") : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($sourcecompany->fax);
477 }
478 // EMail
479 if ($sourcecompany->email) {
480 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($sourcecompany->email);
481 }
482 // Web
483 if ($sourcecompany->url) {
484 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($sourcecompany->url);
485 }
486 }
487 // Intra VAT
488 if (getDolGlobalString('MAIN_TVAINTRA_IN_SOURCE_ADDRESS')) {
489 if ($sourcecompany->tva_intra) {
490 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($sourcecompany->tva_intra);
491 }
492 }
493 // Professional Ids
494 $reg = array();
495 if (getDolGlobalString('MAIN_PROFID1_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof1)) {
496 $tmp = $outputlangs->transcountrynoentities("ProfId1", $sourcecompany->country_code);
497 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
498 $tmp = $reg[1];
499 }
500 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof1);
501 }
502 if (getDolGlobalString('MAIN_PROFID2_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof2)) {
503 $tmp = $outputlangs->transcountrynoentities("ProfId2", $sourcecompany->country_code);
504 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
505 $tmp = $reg[1];
506 }
507 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof2);
508 }
509 if (getDolGlobalString('MAIN_PROFID3_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof3)) {
510 $tmp = $outputlangs->transcountrynoentities("ProfId3", $sourcecompany->country_code);
511 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
512 $tmp = $reg[1];
513 }
514 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof3);
515 }
516 if (getDolGlobalString('MAIN_PROFID4_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof4)) {
517 $tmp = $outputlangs->transcountrynoentities("ProfId4", $sourcecompany->country_code);
518 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
519 $tmp = $reg[1];
520 }
521 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof4);
522 }
523 if (getDolGlobalString('MAIN_PROFID5_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof5)) {
524 $tmp = $outputlangs->transcountrynoentities("ProfId5", $sourcecompany->country_code);
525 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
526 $tmp = $reg[1];
527 }
528 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof5);
529 }
530 if (getDolGlobalString('MAIN_PROFID6_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof6)) {
531 $tmp = $outputlangs->transcountrynoentities("ProfId6", $sourcecompany->country_code);
532 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
533 $tmp = $reg[1];
534 }
535 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof6);
536 }
537 if (getDolGlobalString('PDF_ADD_MORE_AFTER_SOURCE_ADDRESS')) {
538 $stringaddress .= ($stringaddress ? "\n" : '') . getDolGlobalString('PDF_ADD_MORE_AFTER_SOURCE_ADDRESS');
539 }
540 }
541
542 if ($mode == 'target' || preg_match('/targetwithdetails/', $mode)) {
543 if ($usecontact && (is_object($targetcontact))) {
544 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($targetcontact->getFullName($outputlangs, 1));
545
546 if (!empty($targetcontact->address)) {
547 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcontact))."\n";
548 } else {
549 $companytouseforaddress = $targetcompany;
550
551 // Contact on a thirdparty that is a different thirdparty than the thirdparty of object
552 if ($targetcontact->socid > 0 && $targetcontact->socid != $targetcompany->id) {
553 $targetcontact->fetch_thirdparty();
554 $companytouseforaddress = $targetcontact->thirdparty;
555 }
556
557 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($companytouseforaddress))."\n";
558 }
559 // Country
560 if (!empty($targetcontact->country_code) && $targetcontact->country_code != $sourcecompany->country_code) {
561 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcontact->country_code));
562 } elseif (empty($targetcontact->country_code) && !empty($targetcompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
563 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
564 }
565
566 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || preg_match('/targetwithdetails/', $mode)) {
567 // Phone
568 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
569 if (!empty($targetcontact->phone_pro) || !empty($targetcontact->phone_mobile)) {
570 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
571 }
572 if (!empty($targetcontact->phone_pro)) {
573 $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_pro);
574 }
575 if (!empty($targetcontact->phone_pro) && !empty($targetcontact->phone_mobile)) {
576 $stringaddress .= " / ";
577 }
578 if (!empty($targetcontact->phone_mobile)) {
579 $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_mobile);
580 }
581 }
582 // Fax
583 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
584 if ($targetcontact->fax) {
585 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcontact->fax);
586 }
587 }
588 // EMail
589 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
590 if ($targetcontact->email) {
591 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcontact->email);
592 }
593 }
594 // Web
595 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
596 if ($targetcontact->url) {
597 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcontact->url);
598 }
599 }
600 }
601 } else {
602 if (is_object($targetcompany)) {
603 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcompany));
604 // Country
605 if (!empty($targetcompany->country_code) && $targetcompany->country_code != $sourcecompany->country_code) {
606 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
607 } else {
608 $stringaddress .= ($stringaddress ? "\n" : '');
609 }
610
611 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || preg_match('/targetwithdetails/', $mode)) {
612 // Phone
613 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
614 if (!empty($targetcompany->phone)) {
615 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
616 }
617 if (!empty($targetcompany->phone)) {
618 $stringaddress .= $outputlangs->convToOutputCharset($targetcompany->phone);
619 }
620 }
621 // Fax
622 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
623 if ($targetcompany->fax) {
624 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcompany->fax);
625 }
626 }
627 // EMail
628 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
629 if ($targetcompany->email) {
630 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcompany->email);
631 }
632 }
633 // Web
634 if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
635 if ($targetcompany->url) {
636 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcompany->url);
637 }
638 }
639 }
640 }
641 }
642
643 // Intra VAT
644 if (!getDolGlobalString('MAIN_TVAINTRA_NOT_IN_ADDRESS')) {
645 if ($usecontact && is_object($targetcontact) && getDolGlobalInt('MAIN_USE_COMPANY_NAME_OF_CONTACT')) {
646 $targetcontact->fetch_thirdparty();
647 if (!empty($targetcontact->thirdparty->id) && $targetcontact->thirdparty->tva_intra) {
648 $stringaddress .= ($stringaddress ? "\n" : '') . $outputlangs->transnoentities("VATIntraShort") . ': ' . $outputlangs->convToOutputCharset($targetcontact->thirdparty->tva_intra);
649 }
650 } elseif (!empty($targetcompany->tva_intra)) {
651 $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($targetcompany->tva_intra);
652 }
653 }
654
655 // Legal form
656 if (getDolGlobalString('MAIN_LEGALFORM_IN_ADDRESS') && !empty($targetcompany->forme_juridique_code)) {
657 $tmp = getFormeJuridiqueLabel((string) $targetcompany->forme_juridique_code);
658 $stringaddress .= ($stringaddress ? "\n" : '').$tmp;
659 }
660
661 // Professional Ids
662 if (getDolGlobalString('MAIN_PROFID1_IN_ADDRESS') && !empty($targetcompany->idprof1)) {
663 $tmp = $outputlangs->transcountrynoentities("ProfId1", $targetcompany->country_code);
664 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
665 $tmp = $reg[1];
666 }
667 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof1);
668 }
669 if (getDolGlobalString('MAIN_PROFID2_IN_ADDRESS') && !empty($targetcompany->idprof2)) {
670 $tmp = $outputlangs->transcountrynoentities("ProfId2", $targetcompany->country_code);
671 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
672 $tmp = $reg[1];
673 }
674 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof2);
675 }
676 if (getDolGlobalString('MAIN_PROFID3_IN_ADDRESS') && !empty($targetcompany->idprof3)) {
677 $tmp = $outputlangs->transcountrynoentities("ProfId3", $targetcompany->country_code);
678 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
679 $tmp = $reg[1];
680 }
681 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof3);
682 }
683 if (getDolGlobalString('MAIN_PROFID4_IN_ADDRESS') && !empty($targetcompany->idprof4)) {
684 $tmp = $outputlangs->transcountrynoentities("ProfId4", $targetcompany->country_code);
685 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
686 $tmp = $reg[1];
687 }
688 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof4);
689 }
690 if (getDolGlobalString('MAIN_PROFID5_IN_ADDRESS') && !empty($targetcompany->idprof5)) {
691 $tmp = $outputlangs->transcountrynoentities("ProfId5", $targetcompany->country_code);
692 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
693 $tmp = $reg[1];
694 }
695 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof5);
696 }
697 if (getDolGlobalString('MAIN_PROFID6_IN_ADDRESS') && !empty($targetcompany->idprof6)) {
698 $tmp = $outputlangs->transcountrynoentities("ProfId6", $targetcompany->country_code);
699 if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
700 $tmp = $reg[1];
701 }
702 $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof6);
703 }
704
705 // Public note
706 if (getDolGlobalString('MAIN_PUBLIC_NOTE_IN_ADDRESS')) {
707 if ($mode == 'source' && !empty($sourcecompany->note_public)) {
708 $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($sourcecompany->note_public);
709 }
710 if (($mode == 'target' || preg_match('/targetwithdetails/', $mode)) && !empty($targetcompany->note_public)) {
711 $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($targetcompany->note_public);
712 }
713 }
714 }
715 }
716
717 return $stringaddress;
718}
719
720
729function pdf_pagehead(&$pdf, $outputlangs, $page_height)
730{
731 global $conf;
732
733 // Add a background image on document only if good setup of const
734 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
735 $filepath = $conf->mycompany->dir_output.'/logos/' . getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF');
736 if (file_exists($filepath)) {
737 $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak before adding image
738 if (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF_ALPHA')) {
739 $pdf->SetAlpha(getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_ALPHA'));
740 } // Option for change opacity of background
741 $pdf->Image($filepath, getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_X'), getDolGlobalFloat('MAIN_USE_BACKGROUND_ON_PDF_Y'), 0, $page_height);
742 if (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF_ALPHA')) {
743 $pdf->SetAlpha(1);
744 }
745 $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
746 $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
747 }
748 }
749 if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND') && getDolGlobalString('MAIN_ADD_PDF_BACKGROUND') != '-1') {
750 $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
751 }
752}
753
754
765function pdf_getSubstitutionArray($outputlangs, $exclude = null, $object = null, $onlykey = 0, $include = null)
766{
767 $substitutionarray = getCommonSubstitutionArray($outputlangs, $onlykey, $exclude, $object, $include);
768 $substitutionarray['__FROM_NAME__'] = '__FROM_NAME__';
769 $substitutionarray['__FROM_EMAIL__'] = '__FROM_EMAIL__';
770 return $substitutionarray;
771}
772
773
785function pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
786{
787 // Print Draft Watermark
788 if ($unit == 'pt') {
789 $k = 1;
790 } elseif ($unit == 'mm') {
791 $k = 72 / 25.4;
792 } elseif ($unit == 'cm') {
793 $k = 72 / 2.54;
794 } elseif ($unit == 'in') {
795 $k = 72;
796 } else {
797 $k = 1;
798 dol_print_error(null, 'Unexpected unit "'.$unit.'" for pdf_watermark');
799 }
800
801 // Make substitution
802 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, null);
803 complete_substitutions_array($substitutionarray, $outputlangs, null);
804 $text = make_substitutions($text, $substitutionarray, $outputlangs);
805 $text = $outputlangs->convToOutputCharset($text);
806
807 $savx = $pdf->getX();
808 $savy = $pdf->getY();
809
810 $watermark_angle = atan($h / $w) / 2;
811 $watermark_x_pos = 0;
812 $watermark_y_pos = $h / 3;
813 $watermark_x = $w / 2;
814 $watermark_y = $h / 3;
815 $pdf->SetFont('', 'B', 40);
816 $pdf->SetTextColor(255, 0, 0);
817
818 // rotate
819 $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));
820 // print watermark
821 $pdf->SetAlpha(0.5);
822 $pdf->SetXY($watermark_x_pos, $watermark_y_pos);
823
824 // set alpha to semi-transparency
825 $pdf->SetAlpha(0.3);
826 $pdf->Cell($w - 20, 25, $outputlangs->convToOutputCharset($text), "", 2, "C", 0);
827
828 // antirotate
829 $pdf->_out('Q');
830
831 $pdf->SetXY($savx, $savy);
832
833 // Restore alpha
834 $pdf->SetAlpha(1);
835}
836
837
850function pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber = 0, $default_font_size = 10)
851{
852 global $mysoc, $conf;
853
854 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbank.class.php';
855
856 $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
857 $diffsizecontent = getDolGlobalInt('PDF_DIFFSIZE_CONTENT', 4);
858 $pdf->SetXY($curx, $cury);
859
860 if (empty($onlynumber)) {
861 $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
862 $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByTransferOnThisBankAccount').':', 0, 'L', 0);
863 $cury += 4;
864 }
865
866 $outputlangs->load("banks");
867
868 // Use correct name of bank id according to country
869 $bickey = "BICNumber";
870 if ($account->getCountryCode() == 'IN') {
871 $bickey = "SWIFT";
872 }
873
874 // Get format of bank account according to its country
875 $usedetailedbban = $account->useDetailedBBAN();
876
877 //$onlynumber=0; $usedetailedbban=1; // For tests
878 if ($usedetailedbban) {
879 $savcurx = $curx;
880
881 if (empty($onlynumber)) {
882 $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
883 $pdf->SetXY($curx, $cury);
884 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
885 $cury += 3;
886 }
887
888 if (!getDolGlobalString('PDF_BANK_HIDE_NUMBER_SHOW_ONLY_BICIBAN')) { // Note that some countries still need bank number, BIC/IBAN not enough for them
889 // Note:
890 // bank = code_banque (FR), sort code (GB, IR. Example: 12-34-56)
891 // desk = code guichet (FR), used only when $usedetailedbban = 1
892 // number = account number
893 // key = check control key used only when $usedetailedbban = 1
894 if (empty($onlynumber)) {
895 $pdf->line($curx + 1, $cury + 1, $curx + 1, $cury + 6);
896 }
897
898
899 foreach ($account->getFieldsToShow() as $val) {
900 $pdf->SetXY($curx, $cury + 4);
901 $pdf->SetFont('', '', $default_font_size - 3);
902
903 if ($val == 'BankCode') {
904 // Bank code
905 $tmplength = 18;
906 $content = $account->code_banque;
907 } elseif ($val == 'DeskCode') {
908 // Desk
909 $tmplength = 18;
910 $content = $account->code_guichet;
911 } elseif ($val == 'BankAccountNumber') {
912 // Number
913 $tmplength = 24;
914 $content = $account->number;
915 } elseif ($val == 'BankAccountNumberKey') {
916 // Key
917 $tmplength = 15;
918 $content = $account->cle_rib;
919 } elseif ($val == 'IBAN' || $val == 'BIC') {
920 // Key
921 $tmplength = 0;
922 $content = '';
923 } else {
924 dol_print_error($account->db, 'Unexpected value for getFieldsToShow: '.$val);
925 break;
926 }
927
928 $pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($content), 0, 'C', 0);
929 $pdf->SetXY($curx, $cury + 1);
930 $curx += $tmplength;
931 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
932 $pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities($val), 0, 'C', 0);
933 if (empty($onlynumber)) {
934 $pdf->line($curx, $cury + 1, $curx, $cury + 7);
935 }
936 }
937
938 $curx = $savcurx;
939 $cury += 8;
940 }
941 } elseif (!empty($account->number)) {
942 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
943 $pdf->SetXY($curx, $cury);
944 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
945 $cury += 3;
946
947 $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
948 $pdf->SetXY($curx, $cury);
949 $pdf->MultiCell(100, 3, $outputlangs->transnoentities("BankAccountNumber").': '.$outputlangs->convToOutputCharset($account->number), 0, 'L', 0);
950 $cury += 3;
951
952 if ($diffsizecontent <= 2) {
953 $cury += 1;
954 }
955 }
956
957 $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
958
959 if (empty($onlynumber) && !empty($account->address)) {
960 $pdf->SetXY($curx, $cury);
961 $val = $outputlangs->transnoentities("Residence").': '.$outputlangs->convToOutputCharset($account->address);
962 $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
963 //$nboflines=dol_nboflines_bis($val,120);
964 //$cury+=($nboflines*3)+2;
965 $tmpy = $pdf->getStringHeight(100, $val);
966 $cury += $tmpy;
967 }
968
969 if (!empty($account->owner_name)) {
970 $pdf->SetXY($curx, $cury);
971 $val = $outputlangs->transnoentities("BankAccountOwner").': '.$outputlangs->convToOutputCharset($account->owner_name);
972 $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
973 $tmpy = $pdf->getStringHeight(100, $val);
974 $cury += $tmpy;
975 } elseif (!$usedetailedbban) {
976 $cury += 1;
977 }
978
979 // Use correct name of bank id according to country
980 $ibankey = FormBank::getIBANLabel($account);
981
982 if (!empty($account->iban)) {
983 //Remove whitespaces to ensure we are dealing with the format we expect
984 $ibanDisplay_temp = str_replace(' ', '', $outputlangs->convToOutputCharset($account->iban));
985 $ibanDisplay = "";
986
987 $nbIbanDisplay_temp = dol_strlen($ibanDisplay_temp);
988 for ($i = 0; $i < $nbIbanDisplay_temp; $i++) {
989 $ibanDisplay .= $ibanDisplay_temp[$i];
990 if ($i % 4 == 3 && $i > 0) {
991 $ibanDisplay .= " ";
992 }
993 }
994
995 $pdf->SetFont('', 'B', $default_font_size - 3);
996 $pdf->SetXY($curx, $cury);
997 $pdf->MultiCell(100, 3, $outputlangs->transnoentities($ibankey).': '.$ibanDisplay, 0, 'L', 0);
998 $cury += 3;
999 }
1000
1001 if (!empty($account->bic)) {
1002 $pdf->SetFont('', 'B', $default_font_size - 3);
1003 $pdf->SetXY($curx, $cury);
1004 $pdf->MultiCell(100, 3, $outputlangs->transnoentities($bickey).': '.$outputlangs->convToOutputCharset($account->bic), 0, 'L', 0);
1005 }
1006
1007 return $pdf->getY();
1008}
1009
1027function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails = 0, $hidefreetext = 0, $page_largeur = 0, $watermark = '')
1028{
1029 global $conf, $hookmanager;
1030
1031 $outputlangs->load("dict");
1032 $line = '';
1033 $reg = array();
1034 $marginwithfooter = 0; // Return value
1035
1036 $dims = $pdf->getPageDimensions();
1037
1038 // Line of free text
1039 if (empty($hidefreetext) && getDolGlobalString($paramfreetext)) {
1040 $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
1041 // More substitution keys
1042 if (is_object($fromcompany)) {
1043 $substitutionarray['__FROM_NAME__'] = $fromcompany->name;
1044 $substitutionarray['__FROM_EMAIL__'] = $fromcompany->email;
1045 }
1046 complete_substitutions_array($substitutionarray, $outputlangs, $object);
1047 $newfreetext = make_substitutions(getDolGlobalString($paramfreetext), $substitutionarray, $outputlangs);
1048
1049 // Make a change into HTML code to allow to include images from medias directory.
1050 // <img alt="" src="/dolibarr_dev/htdocs/viewimage.php?modulepart=medias&amp;entity=1&amp;file=image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1051 // become
1052 // <img alt="" src="'.DOL_DATA_ROOT.'/medias/image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1053 $newfreetext = preg_replace('/(<img.*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)("[^\/]*\/>)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $newfreetext);
1054
1055 $line .= $outputlangs->convToOutputCharset($newfreetext);
1056 }
1057
1058 // First line of company infos
1059 $line1 = "";
1060 $line2 = "";
1061 $line3 = "";
1062 $line4 = "";
1063
1064 if (is_object($fromcompany) && in_array($showdetails, array(1, 3))) {
1065 // Company name
1066 if ($fromcompany->name) {
1067 $line1 .= ($line1 ? " - " : "").$outputlangs->transnoentities("RegisteredOffice").": ".$fromcompany->name;
1068 }
1069 // Address
1070 if ($fromcompany->address) {
1071 $line1 .= ($line1 ? " - " : "").str_replace("\n", ", ", $fromcompany->address);
1072 }
1073 // Zip code
1074 if ($fromcompany->zip) {
1075 $line1 .= ($line1 ? " - " : "").$fromcompany->zip;
1076 }
1077 // Town
1078 if ($fromcompany->town) {
1079 $line1 .= ($line1 ? " " : "").$fromcompany->town;
1080 }
1081 // Country
1082 if ($fromcompany->country) {
1083 $line1 .= ($line1 ? ", " : "").$fromcompany->country;
1084 }
1085 // Phone
1086 if ($fromcompany->phone) {
1087 $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Phone").": ".$fromcompany->phone;
1088 }
1089 // Fax
1090 if ($fromcompany->fax) {
1091 $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Fax").": ".$fromcompany->fax;
1092 }
1093
1094 // URL
1095 if ($fromcompany->url) {
1096 $line2 .= ($line2 ? " - " : "").$fromcompany->url;
1097 }
1098 // Email
1099 if ($fromcompany->email) {
1100 $line2 .= ($line2 ? " - " : "").$fromcompany->email;
1101 }
1102 }
1103 if ($showdetails == 2 || $showdetails == 3 || (!empty($fromcompany->country_code) && $fromcompany->country_code == 'DE')) {
1104 // Managers
1105 if ($fromcompany->managers) {
1106 $line2 .= ($line2 ? " - " : "").$fromcompany->managers;
1107 }
1108 }
1109
1110 // Line 3 of company infos
1111 // Juridical status
1112 if (!empty($fromcompany->forme_juridique_code) && $fromcompany->forme_juridique_code) {
1113 $line3 .= ($line3 ? " - " : "").$outputlangs->convToOutputCharset(getFormeJuridiqueLabel((string) $fromcompany->forme_juridique_code));
1114 }
1115 // Capital
1116 if (!empty($fromcompany->capital)) {
1117 $tmpamounttoshow = price2num($fromcompany->capital); // This field is a free string or a float
1118 if (is_numeric($tmpamounttoshow) && $tmpamounttoshow > 0) {
1119 $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", price($tmpamounttoshow, 0, $outputlangs, 0, 0, 0, $conf->currency));
1120 } elseif (!empty($fromcompany->capital)) {
1121 $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", $fromcompany->capital, $outputlangs);
1122 }
1123 }
1124 // Prof Id 1
1125 if (!empty($fromcompany->idprof1) && $fromcompany->idprof1 && ($fromcompany->country_code != 'FR' || !$fromcompany->idprof2)) {
1126 $field = $outputlangs->transcountrynoentities("ProfId1", $fromcompany->country_code);
1127 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1128 $field = $reg[1];
1129 }
1130 $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof1);
1131 }
1132 // Prof Id 2
1133 if (!empty($fromcompany->idprof2) && $fromcompany->idprof2) {
1134 $field = $outputlangs->transcountrynoentities("ProfId2", $fromcompany->country_code);
1135 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1136 $field = $reg[1];
1137 }
1138 $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof2);
1139 }
1140
1141 // Line 4 of company infos
1142 // Prof Id 3
1143 if (!empty($fromcompany->idprof3) && $fromcompany->idprof3) {
1144 $field = $outputlangs->transcountrynoentities("ProfId3", $fromcompany->country_code);
1145 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1146 $field = $reg[1];
1147 }
1148 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof3);
1149 }
1150 // Prof Id 4
1151 if (!empty($fromcompany->idprof4) && $fromcompany->idprof4) {
1152 $field = $outputlangs->transcountrynoentities("ProfId4", $fromcompany->country_code);
1153 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1154 $field = $reg[1];
1155 }
1156 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof4);
1157 }
1158 // Prof Id 5
1159 if (!empty($fromcompany->idprof5) && $fromcompany->idprof5) {
1160 $field = $outputlangs->transcountrynoentities("ProfId5", $fromcompany->country_code);
1161 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1162 $field = $reg[1];
1163 }
1164 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof5);
1165 }
1166 // Prof Id 6
1167 if (!empty($fromcompany->idprof6) && $fromcompany->idprof6) {
1168 $field = $outputlangs->transcountrynoentities("ProfId6", $fromcompany->country_code);
1169 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1170 $field = $reg[1];
1171 }
1172 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof6);
1173 }
1174 // Prof Id 7
1175 if (!empty($fromcompany->idprof7) && $fromcompany->idprof7) {
1176 $field = $outputlangs->transcountrynoentities("ProfId7", $fromcompany->country_code);
1177 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1178 $field = $reg[1];
1179 }
1180 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof7);
1181 }
1182 // Prof Id 8
1183 if (!empty($fromcompany->idprof8) && $fromcompany->idprof8) {
1184 $field = $outputlangs->transcountrynoentities("ProfId8", $fromcompany->country_code);
1185 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1186 $field = $reg[1];
1187 }
1188 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof8);
1189 }
1190 // Prof Id 9
1191 if (!empty($fromcompany->idprof9) && $fromcompany->idprof9) {
1192 $field = $outputlangs->transcountrynoentities("ProfId9", $fromcompany->country_code);
1193 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1194 $field = $reg[1];
1195 }
1196 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof9);
1197 }
1198 // Prof Id 10
1199 if (!empty($fromcompany->idprof10) && $fromcompany->idprof10) {
1200 $field = $outputlangs->transcountrynoentities("ProfId10", $fromcompany->country_code);
1201 if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1202 $field = $reg[1];
1203 }
1204 $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof10);
1205 }
1206 // IntraCommunautary VAT
1207 if (!empty($fromcompany->tva_intra) && $fromcompany->tva_intra != '') {
1208 $line4 .= ($line4 ? " - " : "").$outputlangs->transnoentities("VATIntraShort").": ".$outputlangs->convToOutputCharset($fromcompany->tva_intra);
1209 }
1210
1211 $pdf->SetFont('', '', 7);
1212 $pdf->SetDrawColor(224, 224, 224);
1213 // Option for footer text color
1214 if (getDolGlobalString('PDF_FOOTER_TEXT_COLOR')) {
1215 list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_TEXT_COLOR, '%d, %d, %d');
1216 $pdf->SetTextColor($r, $g, $b);
1217 }
1218
1219 // The start of the bottom of this page footer is positioned according to # of lines
1220 $freetextheight = 0;
1221 $align = null;
1222 if ($line) { // Free text
1223 //$line="sample text<br>\nfd<strong>sf</strong>sdf<br>\nghfghg<br>";
1224 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) {
1225 $width = 20000;
1226 $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.
1227 if (getDolGlobalString('MAIN_USE_AUTOWRAP_ON_FREETEXT')) {
1228 $width = 200;
1229 $align = 'C';
1230 }
1231 $freetextheight = $pdf->getStringHeight($width, $line);
1232 } else {
1233 $freetextheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($line, 1, 'UTF-8', 0)); // New method (works for HTML content)
1234 //print '<br>'.$freetextheight;exit;
1235 }
1236 }
1237
1238 $posy = 0;
1239 // For customized footer
1240 if (is_object($hookmanager)) {
1241 $parameters = array('line1' => $line1, 'line2' => $line2, 'line3' => $line3, 'line4' => $line4, 'outputlangs' => $outputlangs);
1242 $action = '';
1243 $hookmanager->executeHooks('pdf_pagefoot', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1244 if (!empty($hookmanager->resPrint) && $hidefreetext == 0) {
1245 $mycustomfooter = $hookmanager->resPrint;
1246 $mycustomfooterheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1247
1248 $marginwithfooter = $marge_basse + $freetextheight + $mycustomfooterheight;
1249 $posy = (float) $marginwithfooter;
1250
1251 // Option for footer background color (without freetext zone)
1252 if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1253 list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
1254 $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
1255 $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', array(), $fill_color = array($r, $g, $b));
1256 $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
1257 }
1258
1259 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1260 $pdf->SetAutoPageBreak(0, 0);
1261 } // Option for disable auto pagebreak
1262 if ($line) { // Free text
1263 $pdf->SetXY($dims['lm'], -$posy);
1264 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1265 $pdf->MultiCell(0, 3, $line, 0, $align, 0);
1266 } else {
1267 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1268 }
1269 $posy -= $freetextheight;
1270 }
1271 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1272 $pdf->SetAutoPageBreak(1, 0);
1273 } // Restore pagebreak
1274
1275 $pdf->SetY(-$posy);
1276
1277 // Hide footer line if footer background color is set
1278 if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1279 $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1280 }
1281
1282 // Option for set top margin height of footer after freetext
1283 if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1284 $posy -= (float) getDolGlobalString('PDF_FOOTER_TOP_MARGIN');
1285 } else {
1286 $posy--;
1287 }
1288
1289 if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) {
1290 $pdf->SetAutoPageBreak(0, 0);
1291 } // Option for disable auto pagebreak
1292 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $mycustomfooterheight, $dims['lm'], $dims['hk'] - $posy, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1293 if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) {
1294 $pdf->SetAutoPageBreak(1, 0);
1295 } // Restore pagebreak
1296
1297 $posy -= $mycustomfooterheight - 3;
1298 } else {
1299 // Else default footer
1300 $marginwithfooter = $marge_basse + $freetextheight + (!empty($line1) ? 3 : 0) + (!empty($line2) ? 3 : 0) + (!empty($line3) ? 3 : 0) + (!empty($line4) ? 3 : 0);
1301 $posy = (float) $marginwithfooter;
1302
1303 // Option for footer background color (without freetext zone)
1304 if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1305 list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
1306 $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
1307 $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', array(), $fill_color = array($r, $g, $b));
1308 $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
1309 }
1310
1311 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1312 $pdf->SetAutoPageBreak(0, 0);
1313 } // Option for disable auto pagebreak
1314 if ($line) { // Free text
1315 $pdf->SetXY($dims['lm'], -$posy);
1316 if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1317 $pdf->MultiCell(0, 3, $line, 0, $align, 0);
1318 } else {
1319 $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1320 }
1321 $posy -= $freetextheight;
1322 }
1323 if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1324 $pdf->SetAutoPageBreak(1, 0);
1325 } // Restore pagebreak
1326
1327 $pdf->SetY(-$posy);
1328
1329 // Option for hide all footer (page number will no hidden)
1330 if (!getDolGlobalInt('PDF_FOOTER_HIDDEN')) {
1331 // Hide footer line if footer background color is set
1332 if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1333 $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1334 }
1335
1336 // Option for set top margin height of footer after freetext
1337 if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1338 $posy -= (float) getDolGlobalString('PDF_FOOTER_TOP_MARGIN');
1339 } else {
1340 $posy--;
1341 }
1342
1343 if (!empty($line1)) {
1344 $pdf->SetFont('', 'B', 7);
1345 $pdf->SetXY($dims['lm'], -$posy);
1346 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line1, 0, 'C', 0);
1347 $posy -= 3;
1348 $pdf->SetFont('', '', 7);
1349 }
1350
1351 if (!empty($line2)) {
1352 $pdf->SetFont('', 'B', 7);
1353 $pdf->SetXY($dims['lm'], -$posy);
1354 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line2, 0, 'C', 0);
1355 $posy -= 3;
1356 $pdf->SetFont('', '', 7);
1357 }
1358
1359 if (!empty($line3)) {
1360 $pdf->SetXY($dims['lm'], -$posy);
1361 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line3, 0, 'C', 0);
1362 }
1363
1364 if (!empty($line4)) {
1365 $posy -= 3;
1366 $pdf->SetXY($dims['lm'], -$posy);
1367 $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line4, 0, 'C', 0);
1368 }
1369 }
1370 }
1371 }
1372
1373 // Show page nb and apply correction for some font.
1374 $pdf->SetXY($dims['wk'] - $dims['rm'] - 18 - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_X', 0), -$posy - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_Y', 0));
1375
1376 $pagination = $pdf->PageNo().' / '.$pdf->getAliasNbPages();
1377 $fontRenderCorrection = 0;
1378 if (in_array(pdf_getPDFFont($outputlangs), array('freemono', 'DejaVuSans'))) {
1379 $fontRenderCorrection = 10;
1380 }
1381 $pdf->MultiCell(18 + $fontRenderCorrection, 2, $pagination, 0, 'R', 0);
1382
1383 // Show Draft Watermark
1384 if (!empty($watermark)) {
1385 pdf_watermark($pdf, $outputlangs, $page_hauteur, $page_largeur, 'mm', $watermark);
1386 }
1387
1388 return $marginwithfooter;
1389}
1390
1405function pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
1406{
1407 $linkedobjects = pdf_getLinkedObjects($object, $outputlangs);
1408 if (!empty($linkedobjects)) {
1409 foreach ($linkedobjects as $linkedobject) {
1410 $reftoshow = $linkedobject["ref_title"].' : '.$linkedobject["ref_value"];
1411 if (!empty($linkedobject["date_value"])) {
1412 $reftoshow .= ' / '.$linkedobject["date_value"];
1413 }
1414
1415 $posy += 3;
1416 $pdf->SetXY($posx, $posy);
1417 $pdf->SetFont('', '', (float) $default_font_size - 2);
1418 $pdf->MultiCell($w, $h, $reftoshow, '', $align);
1419 }
1420 }
1421
1422 return $pdf->getY();
1423}
1424
1442function pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref = 0, $hidedesc = 0, $issupplierline = 0, $align = 'J')
1443{
1444 global $db, $conf, $langs, $hookmanager;
1445
1446 $reshook = 0;
1447 $result = '';
1448 //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) ) )
1449 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
1450 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1451 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1452 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1453 }
1454 $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);
1455 $action = '';
1456 $reshook = $hookmanager->executeHooks('pdf_writelinedesc', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1457
1458 if (!empty($hookmanager->resPrint)) {
1459 $result .= $hookmanager->resPrint;
1460 }
1461 }
1462 if (empty($reshook)) {
1463 $labelproductservice = pdf_getlinedesc($object, $i, $outputlangs, $hideref, $hidedesc, $issupplierline);
1464 $labelproductservice = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $labelproductservice, -1, $nbrep);
1465
1466 //var_dump($labelproductservice);exit;
1467
1468 // 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"
1469 // We make the reverse, so PDF generation has the real URL.
1470 $nbrep = 0;
1471 $labelproductservice = preg_replace('/(<img[^>]*src=")([^"]*)(&amp;)([^"]*")/', '\1\2&\4', $labelproductservice, -1, $nbrep);
1472
1473 if (getDolGlobalString('MARGIN_TOP_ZERO_UL')) {
1474 $pdf->setListIndentWidth(5);
1475 $TMarginList = ['ul' => [['h' => 0.1, ],['h' => 0.1, ]], 'li' => [['h' => 0.1, ],],];
1476 $pdf->setHtmlVSpace($TMarginList);
1477 }
1478
1479 // Description
1480 $pdf->writeHTMLCell($w, $h, $posx, $posy, $outputlangs->convToOutputCharset($labelproductservice), 0, 1, false, true, $align, true);
1481 $result .= $labelproductservice;
1482 }
1483 return $result;
1484}
1485
1497function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
1498{
1499 global $db, $conf, $langs;
1500
1501 $idprod = (!empty($object->lines[$i]->fk_product) ? $object->lines[$i]->fk_product : false);
1502 $label = (!empty($object->lines[$i]->label) ? $object->lines[$i]->label : (!empty($object->lines[$i]->product_label) ? $object->lines[$i]->product_label : ''));
1503 $product_barcode = (!empty($object->lines[$i]->product_barcode) ? $object->lines[$i]->product_barcode : "");
1504 $desc = (!empty($object->lines[$i]->desc) ? $object->lines[$i]->desc : (!empty($object->lines[$i]->description) ? $object->lines[$i]->description : ''));
1505 $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
1506 $note = (!empty($object->lines[$i]->note) ? $object->lines[$i]->note : '');
1507 $dbatch = (!empty($object->lines[$i]->detail_batch) ? $object->lines[$i]->detail_batch : false);
1508
1509 if ($issupplierline) {
1510 include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
1511 $prodser = new ProductFournisseur($db);
1512 } else {
1513 include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
1514 $prodser = new Product($db);
1515
1516 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1517 include_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
1518 }
1519 }
1520
1521 if ($idprod) {
1522 $prodser->fetch($idprod);
1523 // If a predefined product and multilang and on other lang, we renamed label with label translated
1524 if (getDolGlobalInt('MAIN_MULTILANGS') && ($outputlangs->defaultlang != $langs->defaultlang)) {
1525 $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)
1526
1527 // 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
1528 // ($textwasnotmodified is replaced with $textwasmodifiedorcompleted and we add completion).
1529
1530 // Set label
1531 // 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.
1532 //var_dump($outputlangs->defaultlang.' - '.$langs->defaultlang.' - '.$label.' - '.$prodser->label);exit;
1533 $textwasnotmodified = ($label == $prodser->label);
1534 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1535 $label = $prodser->multilangs[$outputlangs->defaultlang]["label"];
1536 }
1537
1538 // Set desc
1539 // Manage HTML entities description test because $prodser->description is store with htmlentities but $desc no
1540 $textwasnotmodified = false;
1541 if (!empty($desc) && dol_textishtml($desc) && !empty($prodser->description) && dol_textishtml($prodser->description)) {
1542 $textwasnotmodified = (strpos(dol_html_entity_decode($desc, ENT_QUOTES | ENT_HTML5), dol_html_entity_decode($prodser->description, ENT_QUOTES | ENT_HTML5)) !== false);
1543 } else {
1544 $textwasnotmodified = ($desc == $prodser->description);
1545 }
1546 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["description"])) {
1547 if ($textwasnotmodified) {
1548 $desc = str_replace($prodser->description, $prodser->multilangs[$outputlangs->defaultlang]["description"], $desc);
1549 } elseif ($translatealsoifmodified) {
1550 $desc = $prodser->multilangs[$outputlangs->defaultlang]["description"];
1551 }
1552 }
1553
1554 // Set note
1555 $textwasnotmodified = ($note == $prodser->note_public);
1556 if (!empty($prodser->multilangs[$outputlangs->defaultlang]["other"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1557 $note = $prodser->multilangs[$outputlangs->defaultlang]["other"];
1558 }
1559 }
1560 } 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
1561 $desc = str_replace('(DEPOSIT)', $outputlangs->trans('Deposit'), $desc);
1562 }
1563
1564 $libelleproduitservice = ''; // Default value
1565 if (!getDolGlobalString('PDF_HIDE_PRODUCT_LABEL_IN_SUPPLIER_LINES')) {
1566 // Description short of product line
1567 $libelleproduitservice = $label;
1568 if (!empty($libelleproduitservice) && getDolGlobalString('PDF_BOLD_PRODUCT_LABEL')) {
1569 // Adding <b> may convert the original string into a HTML string. So we have to first
1570 // convert \n into <br> we text is not already HTML.
1571 if (!dol_textishtml($libelleproduitservice)) {
1572 $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1573 }
1574 $libelleproduitservice = '<b>'.$libelleproduitservice.'</b>';
1575 }
1576 }
1577
1578
1579 // Add ref of subproducts
1580 if (getDolGlobalString('SHOW_SUBPRODUCT_REF_IN_PDF')) {
1581 $prodser->get_sousproduits_arbo();
1582 if (!empty($prodser->sousprods) && is_array($prodser->sousprods) && count($prodser->sousprods)) {
1583 $outputlangs->load('mrp');
1584 $tmparrayofsubproducts = reset($prodser->sousprods);
1585
1586 $qtyText = null;
1587 if (isset($object->lines[$i]->qty) && !empty($object->lines[$i]->qty)) {
1588 $qtyText = $object->lines[$i]->qty;
1589 } elseif (isset($object->lines[$i]->qty_shipped) && !empty($object->lines[$i]->qty_shipped)) {
1590 $qtyText = $object->lines[$i]->qty;
1591 }
1592
1593 if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF')) {
1594 foreach ($tmparrayofsubproducts as $subprodval) {
1595 $libelleproduitservice = dol_concatdesc(
1596 dol_concatdesc($libelleproduitservice, " * ".$subprodval[3]),
1597 (!empty($qtyText) ?
1598 $outputlangs->trans('Qty').':'.$qtyText.' x '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1].'= '.$outputlangs->trans('QtyTot').':'.$subprodval[1] * $qtyText :
1599 $outputlangs->trans('Qty').' '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1])
1600 );
1601 }
1602 } else {
1603 foreach ($tmparrayofsubproducts as $subprodval) {
1604 $libelleproduitservice = dol_concatdesc(
1605 dol_concatdesc($libelleproduitservice, " * ".$subprodval[5].(($subprodval[5] && $subprodval[3]) ? ' - ' : '').$subprodval[3]),
1606 (!empty($qtyText) ?
1607 $outputlangs->trans('Qty').':'.$qtyText.' x '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1].'= '.$outputlangs->trans('QtyTot').':'.$subprodval[1] * $qtyText :
1608 $outputlangs->trans('Qty').' '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1])
1609 );
1610 }
1611 }
1612 }
1613 }
1614
1615 if (isModEnabled('barcode') && getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_PRODUCT_BARCODE') && !empty($product_barcode)) {
1616 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $outputlangs->trans("BarCode")." ".$product_barcode);
1617 }
1618
1619 // Description long of product line
1620 if (!empty($desc) && ($desc != $label)) {
1621 if ($desc == '(CREDIT_NOTE)' && $object->lines[$i]->fk_remise_except) {
1622 $discount = new DiscountAbsolute($db);
1623 $discount->fetch($object->lines[$i]->fk_remise_except);
1624 $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1625 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromCreditNote", $sourceref);
1626 } elseif ($desc == '(DEPOSIT)' && $object->lines[$i]->fk_remise_except) {
1627 $discount = new DiscountAbsolute($db);
1628 $discount->fetch($object->lines[$i]->fk_remise_except);
1629 $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1630 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromDeposit", $sourceref);
1631 // Add date of deposit
1632 if (getDolGlobalString('INVOICE_ADD_DEPOSIT_DATE')) {
1633 $libelleproduitservice .= ' ('.dol_print_date($discount->datec, 'day', '', $outputlangs).')';
1634 }
1635 } elseif ($desc == '(EXCESS RECEIVED)' && $object->lines[$i]->fk_remise_except) {
1636 $discount = new DiscountAbsolute($db);
1637 $discount->fetch($object->lines[$i]->fk_remise_except);
1638 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessReceived", $discount->ref_facture_source);
1639 } elseif ($desc == '(EXCESS PAID)' && $object->lines[$i]->fk_remise_except) {
1640 $discount = new DiscountAbsolute($db);
1641 $discount->fetch($object->lines[$i]->fk_remise_except);
1642 $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessPaid", $discount->ref_invoice_supplier_source);
1643 } else {
1644 if ($idprod) {
1645 // Check if description must be output
1646 if (!empty($object->element)) {
1647 $tmpkey = 'MAIN_DOCUMENTS_HIDE_DESCRIPTION_FOR_'.strtoupper($object->element);
1648 if (getDolGlobalString($tmpkey)) {
1649 $hidedesc = 1;
1650 }
1651 }
1652 if (empty($hidedesc)) {
1653 if (getDolGlobalString('MAIN_DOCUMENTS_DESCRIPTION_FIRST')) {
1654 $libelleproduitservice = dol_concatdesc($desc, $libelleproduitservice);
1655 } else {
1656 if (getDolGlobalString('HIDE_LABEL_VARIANT_PDF') && $prodser->isVariant()) {
1657 $libelleproduitservice = $desc;
1658 } else {
1659 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1660 }
1661 }
1662 }
1663 } else {
1664 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1665 }
1666 }
1667 }
1668
1669 // We add ref of product (and supplier ref if defined)
1670 $prefix_prodserv = "";
1671 $ref_prodserv = "";
1672 if (getDolGlobalString('PRODUCT_ADD_TYPE_IN_DOCUMENTS')) { // In standard mode, we do not show this
1673 if ($prodser->isService()) {
1674 $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service")." ";
1675 } else {
1676 $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Product")." ";
1677 }
1678 }
1679
1680 if (empty($hideref)) {
1681 if ($issupplierline) {
1682 if (!getDolGlobalString('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES')) { // Common case
1683 $ref_prodserv = $prodser->ref; // Show local ref
1684 if ($ref_supplier) {
1685 $ref_prodserv .= ($prodser->ref ? ' (' : '').$outputlangs->transnoentitiesnoconv("SupplierRef").' '.$ref_supplier.($prodser->ref ? ')' : '');
1686 }
1687 } elseif (getDolGlobalInt('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES') == 1) {
1688 $ref_prodserv = $ref_supplier;
1689 } elseif (getDolGlobalInt('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES') == 2) {
1690 $ref_prodserv = $ref_supplier.' ('.$outputlangs->transnoentitiesnoconv("InternalRef").' '.$prodser->ref.')';
1691 }
1692 } else {
1693 $ref_prodserv = $prodser->ref; // Show local ref only
1694
1695 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1696 $productCustomerPriceStatic = new ProductCustomerPrice($db);
1697 $filter = array('fk_product' => $idprod, 'fk_soc' => $object->socid);
1698
1699 $nbCustomerPrices = $productCustomerPriceStatic->fetchAll('', '', 1, 0, $filter);
1700
1701 if ($nbCustomerPrices > 0) {
1702 $productCustomerPrice = $productCustomerPriceStatic->lines[0];
1703
1704 if (!empty($productCustomerPrice->ref_customer)) {
1705 switch ($conf->global->PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE) {
1706 case 1:
1707 $ref_prodserv = $productCustomerPrice->ref_customer;
1708 break;
1709
1710 case 2:
1711 $ref_prodserv = $productCustomerPrice->ref_customer . ' (' . $outputlangs->transnoentitiesnoconv('InternalRef') . ' ' . $ref_prodserv . ')';
1712 break;
1713
1714 default:
1715 $ref_prodserv = $ref_prodserv . ' (' . $outputlangs->transnoentitiesnoconv('RefCustomer') . ' ' . $productCustomerPrice->ref_customer . ')';
1716 }
1717 }
1718 }
1719 }
1720 }
1721
1722 if (!empty($libelleproduitservice) && !empty($ref_prodserv)) {
1723 $ref_prodserv .= " - ";
1724 }
1725 }
1726
1727 if (!empty($ref_prodserv) && getDolGlobalString('PDF_BOLD_PRODUCT_REF_AND_PERIOD')) {
1728 if (!dol_textishtml($libelleproduitservice)) {
1729 $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1730 }
1731 $ref_prodserv = '<b>'.$ref_prodserv.'</b>';
1732 // $prefix_prodserv and $ref_prodser are not HTML var
1733 }
1734 $libelleproduitservice = $prefix_prodserv.$ref_prodserv.$libelleproduitservice;
1735
1736 // Add an additional description for the category products
1737 if (getDolGlobalString('CATEGORY_ADD_DESC_INTO_DOC') && $idprod && isModEnabled('category')) {
1738 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1739 $categstatic = new Categorie($db);
1740 // recovering the list of all the categories linked to product
1741 $tblcateg = $categstatic->containing($idprod, Categorie::TYPE_PRODUCT);
1742 foreach ($tblcateg as $cate) {
1743 // Adding the descriptions if they are filled
1744 $desccateg = $cate->description;
1745 if ($desccateg) {
1746 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desccateg);
1747 }
1748 }
1749 }
1750
1751 if (!empty($object->lines[$i]->date_start) || !empty($object->lines[$i]->date_end)) {
1752 $format = 'day';
1753 $period = '';
1754 // Show duration if exists
1755 if ($object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1756 $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)).')';
1757 }
1758 if ($object->lines[$i]->date_start && !$object->lines[$i]->date_end) {
1759 $period = '('.$outputlangs->transnoentitiesnoconv('DateFrom', dol_print_date($object->lines[$i]->date_start, $format, false, $outputlangs)).')';
1760 }
1761 if (!$object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1762 $period = '('.$outputlangs->transnoentitiesnoconv('DateUntil', dol_print_date($object->lines[$i]->date_end, $format, false, $outputlangs)).')';
1763 }
1764 //print '>'.$outputlangs->charset_output.','.$period;
1765 if (getDolGlobalString('PDF_BOLD_PRODUCT_REF_AND_PERIOD')) {
1766 if (!dol_textishtml($libelleproduitservice)) {
1767 $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1768 }
1769 $libelleproduitservice .= '<br><b style="color:#333666;" ><em>'.$period.'</em></b>';
1770 } else {
1771 $libelleproduitservice = dol_concatdesc($libelleproduitservice, $period);
1772 }
1773 //print $libelleproduitservice;
1774 }
1775
1776 // Show information for lot
1777 if (!empty($dbatch)) {
1778 // $object is a shipment.
1779 //var_dump($object->lines[$i]->details_entrepot); // array from llx_expeditiondet (we can have several lines for one fk_origin_line)
1780 //var_dump($object->lines[$i]->detail_batch); // array from llx_expeditiondet_batch (each line with a lot is linked to llx_expeditiondet)
1781
1782 include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
1783 include_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
1784 $tmpwarehouse = new Entrepot($db);
1785 $tmpproductbatch = new Productbatch($db);
1786
1787 $format = 'day';
1788 foreach ($dbatch as $detail) {
1789 $dte = array();
1790 if ($detail->eatby) {
1791 $dte[] = $outputlangs->transnoentitiesnoconv('printEatby', dol_print_date($detail->eatby, $format, false, $outputlangs));
1792 }
1793 if ($detail->sellby) {
1794 $dte[] = $outputlangs->transnoentitiesnoconv('printSellby', dol_print_date($detail->sellby, $format, false, $outputlangs));
1795 }
1796 if ($detail->batch) {
1797 $dte[] = $outputlangs->transnoentitiesnoconv('printBatch', $detail->batch);
1798 }
1799 $dte[] = $outputlangs->transnoentitiesnoconv('printQty', $detail->qty);
1800
1801 // Add also info of planned warehouse for lot
1802 if ($object->element == 'shipping' && $detail->fk_origin_stock > 0 && getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1803 $resproductbatch = $tmpproductbatch->fetch($detail->fk_origin_stock);
1804 if ($resproductbatch > 0) {
1805 $reswarehouse = $tmpwarehouse->fetch($tmpproductbatch->warehouseid);
1806 if ($reswarehouse > 0) {
1807 $dte[] = $tmpwarehouse->ref;
1808 }
1809 }
1810 }
1811
1812 $libelleproduitservice .= "__N__ ".implode(" - ", $dte);
1813 }
1814 } else {
1815 if (getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1816 // TODO Show warehouse for shipment line without batch
1817 }
1818 }
1819
1820 // Now we convert \n into br
1821 if (dol_textishtml($libelleproduitservice)) {
1822 $libelleproduitservice = preg_replace('/__N__/', '<br>', $libelleproduitservice);
1823 } else {
1824 $libelleproduitservice = preg_replace('/__N__/', "\n", $libelleproduitservice);
1825 }
1826 $libelleproduitservice = dol_htmlentitiesbr($libelleproduitservice, 1);
1827
1828 return $libelleproduitservice;
1829}
1830
1840function pdf_getlinenum($object, $i, $outputlangs, $hidedetails = 0)
1841{
1842 global $hookmanager;
1843
1844 $reshook = 0;
1845 $result = '';
1846 //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) ) )
1847 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
1848 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1849 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1850 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1851 }
1852 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1853 $action = '';
1854 $reshook = $hookmanager->executeHooks('pdf_getlinenum', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1855 $result .= $hookmanager->resPrint;
1856 }
1857 if (empty($reshook)) {
1858 $result .= dol_htmlentitiesbr($object->lines[$i]->num);
1859 }
1860 return $result;
1861}
1862
1863
1873function pdf_getlineref($object, $i, $outputlangs, $hidedetails = 0)
1874{
1875 global $hookmanager;
1876
1877 $reshook = 0;
1878 $result = '';
1879 //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) ) )
1880 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
1881 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1882 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1883 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1884 }
1885 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1886 $action = '';
1887 $reshook = $hookmanager->executeHooks('pdf_getlineref', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1888 $result .= $hookmanager->resPrint;
1889 }
1890 if (empty($reshook)) {
1891 $result .= dol_htmlentitiesbr($object->lines[$i]->product_ref);
1892 }
1893 return $result;
1894}
1895
1896
1906function pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails = 0)
1907{
1908 global $hookmanager;
1909
1910 $reshook = 0;
1911 $result = '';
1912 //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) ) )
1913 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
1914 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1915 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1916 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1917 }
1918 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1919 $action = '';
1920 $reshook = $hookmanager->executeHooks('pdf_getlineref_supplier', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1921 $result .= $hookmanager->resPrint;
1922 }
1923 if (empty($reshook)) {
1924 $result .= dol_htmlentitiesbr($object->lines[$i]->ref_supplier);
1925 }
1926 return $result;
1927}
1928
1938function pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails = 0)
1939{
1940 global $conf, $hookmanager, $mysoc;
1941
1942 $result = '';
1943 $reshook = 0;
1944 //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) ) )
1945 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
1946 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1947 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1948 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1949 }
1950 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1951 $action = '';
1952 $reshook = $hookmanager->executeHooks('pdf_getlinevatrate', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1953
1954 if (!empty($hookmanager->resPrint)) {
1955 $result .= $hookmanager->resPrint;
1956 }
1957 }
1958 if (empty($reshook)) {
1959 if (empty($hidedetails) || $hidedetails > 1) {
1960 $tmpresult = '';
1961
1962 $tmpresult .= vatrate($object->lines[$i]->tva_tx, 0, $object->lines[$i]->info_bits, -1);
1963 if (!getDolGlobalString('MAIN_PDF_MAIN_HIDE_SECOND_TAX')) {
1964 if ($object->lines[$i]->total_localtax1 != 0) {
1965 if (preg_replace('/[\s0%]/', '', $tmpresult)) {
1966 $tmpresult .= '/';
1967 } else {
1968 $tmpresult = '';
1969 }
1970 $tmpresult .= vatrate((string) abs($object->lines[$i]->localtax1_tx), 0);
1971 }
1972 }
1973 if (!getDolGlobalString('MAIN_PDF_MAIN_HIDE_THIRD_TAX')) {
1974 if ($object->lines[$i]->total_localtax2 != 0) {
1975 if (preg_replace('/[\s0%]/', '', $tmpresult)) {
1976 $tmpresult .= '/';
1977 } else {
1978 $tmpresult = '';
1979 }
1980 $tmpresult .= vatrate((string) abs($object->lines[$i]->localtax2_tx), 0);
1981 }
1982 }
1983 $tmpresult .= '%';
1984
1985 $result .= $tmpresult;
1986 }
1987 }
1988 return $result;
1989}
1990
2000function pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails = 0)
2001{
2002 global $conf, $hookmanager;
2003
2004 $sign = 1;
2005 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2006 $sign = -1;
2007 }
2008
2009 $result = '';
2010 $reshook = 0;
2011 //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) ) )
2012 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
2013 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2014 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2015 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2016 }
2017 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2018 $action = '';
2019 $reshook = $hookmanager->executeHooks('pdf_getlineupexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2020
2021 if (!empty($hookmanager->resPrint)) {
2022 $result .= $hookmanager->resPrint;
2023 }
2024 }
2025 if (empty($reshook)) {
2026 if (empty($hidedetails) || $hidedetails > 1) {
2027 $subprice = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice);
2028 $result .= price($sign * $subprice, 0, $outputlangs);
2029 }
2030 }
2031 return $result;
2032}
2033
2043function pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails = 0)
2044{
2045 global $hookmanager, $conf;
2046
2047 $sign = 1;
2048 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2049 $sign = -1;
2050 }
2051
2052 $result = '';
2053 $reshook = 0;
2054 //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) ) )
2055 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
2056 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2057 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2058 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2059 }
2060 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2061 $action = '';
2062 $reshook = $hookmanager->executeHooks('pdf_getlineupwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2063
2064 if (!empty($hookmanager->resPrint)) {
2065 $result .= $hookmanager->resPrint;
2066 }
2067 }
2068 if (empty($reshook)) {
2069 if (empty($hidedetails) || $hidedetails > 1) {
2070 $result .= price($sign * (($object->lines[$i]->subprice) + ($object->lines[$i]->subprice) * ($object->lines[$i]->tva_tx) / 100), 0, $outputlangs);
2071 }
2072 }
2073 return $result;
2074}
2075
2085function pdf_getlineqty($object, $i, $outputlangs, $hidedetails = 0)
2086{
2087 global $hookmanager;
2088
2089 $result = '';
2090 $reshook = 0;
2091 //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) ) )
2092 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
2093 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2094 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2095 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2096 }
2097 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2098 $action = '';
2099 $reshook = $hookmanager->executeHooks('pdf_getlineqty', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2100
2101 if (!empty($hookmanager->resPrint)) {
2102 $result = $hookmanager->resPrint;
2103 }
2104 }
2105 if (empty($reshook)) {
2106 if ($object->lines[$i]->special_code == 3) {
2107 return '';
2108 }
2109 if (empty($hidedetails) || $hidedetails > 1) {
2110 $result .= $object->lines[$i]->qty;
2111 }
2112 }
2113 return $result;
2114}
2115
2125function pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails = 0)
2126{
2127 global $hookmanager;
2128
2129 $reshook = 0;
2130 $result = '';
2131 //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) ) )
2132 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
2133 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2134 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2135 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2136 }
2137 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2138 $action = '';
2139 $reshook = $hookmanager->executeHooks('pdf_getlineqty_asked', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2140
2141 if (!empty($hookmanager->resPrint)) {
2142 $result .= $hookmanager->resPrint;
2143 }
2144 }
2145 if (empty($reshook)) {
2146 if ($object->lines[$i]->special_code == 3) {
2147 return '';
2148 }
2149 if (empty($hidedetails) || $hidedetails > 1) {
2150 $result .= $object->lines[$i]->qty_asked;
2151 }
2152 }
2153 return $result;
2154}
2155
2165function pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails = 0)
2166{
2167 global $hookmanager;
2168
2169 $reshook = 0;
2170 $result = '';
2171 //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) ) )
2172 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
2173 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2174 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2175 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2176 }
2177 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2178 $action = '';
2179 $reshook = $hookmanager->executeHooks('pdf_getlineqty_shipped', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2180
2181 if (!empty($hookmanager->resPrint)) {
2182 $result .= $hookmanager->resPrint;
2183 }
2184 }
2185 if (empty($reshook)) {
2186 if ($object->lines[$i]->special_code == 3) {
2187 return '';
2188 }
2189 if (empty($hidedetails) || $hidedetails > 1) {
2190 $result .= $object->lines[$i]->qty_shipped;
2191 }
2192 }
2193 return $result;
2194}
2195
2205function pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails = 0)
2206{
2207 global $hookmanager;
2208
2209 $reshook = 0;
2210 $result = '';
2211 //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) ) )
2212 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
2213 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2214 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) { // @phan-suppress-current-line PhanUndeclaredProperty
2215 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2216 }
2217 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2218 $action = '';
2219 $reshook = $hookmanager->executeHooks('pdf_getlineqty_keeptoship', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2220
2221 if (!empty($hookmanager->resPrint)) {
2222 $result .= $hookmanager->resPrint;
2223 }
2224 }
2225 if (empty($reshook)) {
2226 if ($object->lines[$i]->special_code == 3) {
2227 return '';
2228 }
2229 if (empty($hidedetails) || $hidedetails > 1) {
2230 $result .= ($object->lines[$i]->qty_asked - $object->lines[$i]->qty_shipped);
2231 }
2232 }
2233 return $result;
2234}
2235
2245function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0)
2246{
2247 global $hookmanager, $langs;
2248
2249 $reshook = 0;
2250 $result = '';
2251 //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) ) )
2252 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
2253 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2254 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2255 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2256 }
2257 $parameters = array(
2258 'i' => $i,
2259 'outputlangs' => $outputlangs,
2260 'hidedetails' => $hidedetails,
2261 'special_code' => $special_code
2262 );
2263 $action = '';
2264 $reshook = $hookmanager->executeHooks('pdf_getlineunit', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2265
2266 if (!empty($hookmanager->resPrint)) {
2267 $result .= $hookmanager->resPrint;
2268 }
2269 }
2270 if (empty($reshook)) {
2271 if (empty($hidedetails) || $hidedetails > 1) {
2272 $result .= $langs->transnoentitiesnoconv($object->lines[$i]->getLabelOfUnit('short'));
2273 }
2274 }
2275 return $result;
2276}
2277
2278
2288function pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails = 0)
2289{
2290 global $hookmanager;
2291
2292 include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
2293
2294 $reshook = 0;
2295 $result = '';
2296 //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) ) )
2297 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
2298 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2299 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2300 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2301 }
2302 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2303 $action = '';
2304 $reshook = $hookmanager->executeHooks('pdf_getlineremisepercent', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2305
2306 if (!empty($hookmanager->resPrint)) {
2307 $result .= $hookmanager->resPrint;
2308 }
2309 }
2310 if (empty($reshook)) {
2311 if ($object->lines[$i]->special_code == 3) {
2312 return '';
2313 }
2314 if (empty($hidedetails) || $hidedetails > 1) {
2315 $result .= dol_print_reduction($object->lines[$i]->remise_percent, $outputlangs);
2316 }
2317 }
2318 return $result;
2319}
2320
2331function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = null)
2332{
2333 if (empty($hookmanager)) {
2334 global $hookmanager;
2335 }
2336 global $conf;
2337
2338 $reshook = 0;
2339 $result = '';
2340 //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) ) )
2341 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
2342 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2343 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2344 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2345 }
2346 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2347 $action = '';
2348 $reshook = $hookmanager->executeHooks('pdf_getlineprogress', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2349
2350 if (!empty($hookmanager->resPrint)) {
2351 return $hookmanager->resPrint;
2352 }
2353 }
2354 if (empty($reshook)) {
2355 if ($object->lines[$i]->special_code == 3) {
2356 return '';
2357 }
2358 if (empty($hidedetails) || $hidedetails > 1) {
2359 if (getDolGlobalString('SITUATION_DISPLAY_DIFF_ON_PDF')) {
2360 $prev_progress = 0;
2361 if (method_exists($object->lines[$i], 'get_prev_progress')) {
2362 $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2363 }
2364 $result = round($object->lines[$i]->situation_percent - $prev_progress, 1).'%';
2365 } else {
2366 $result = round($object->lines[$i]->situation_percent, 1).'%';
2367 }
2368 }
2369 }
2370 return $result;
2371}
2372
2382function pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails = 0)
2383{
2384 global $conf, $hookmanager;
2385
2386 $sign = 1;
2387 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2388 $sign = -1;
2389 }
2390
2391 $reshook = 0;
2392 $result = '';
2393 //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) ) )
2394 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
2395 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2396 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2397 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2398 }
2399 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code, 'sign' => $sign);
2400 $action = '';
2401 $reshook = $hookmanager->executeHooks('pdf_getlinetotalexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2402
2403 if (!empty($hookmanager->resPrint)) {
2404 $result .= $hookmanager->resPrint;
2405 }
2406 }
2407 if (empty($reshook)) {
2408 if (!empty($object->lines[$i]) && $object->lines[$i]->special_code == 3) {
2409 $result .= $outputlangs->transnoentities("Option");
2410 } elseif (empty($hidedetails) || $hidedetails > 1) {
2411 $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
2412 if (!empty($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
2413 // TODO Remove this. The total should be saved correctly in database instead of being modified here.
2414 $prev_progress = 0;
2415 $progress = 1;
2416 if (method_exists($object->lines[$i], 'get_prev_progress')) {
2417 $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2418 $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
2419 }
2420 $result .= price($sign * ($total_ht / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
2421 } else {
2422 $result .= price($sign * $total_ht, 0, $outputlangs);
2423 }
2424 }
2425 }
2426 return $result;
2427}
2428
2438function pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails = 0)
2439{
2440 global $hookmanager, $conf;
2441
2442 $sign = 1;
2443 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2444 $sign = -1;
2445 }
2446
2447 $reshook = 0;
2448 $result = '';
2449 //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2450 if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduce this test in the pdf_xxx function if you don't want your hook to run
2451 $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2452 if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2453 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2454 }
2455 $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2456 $action = '';
2457 $reshook = $hookmanager->executeHooks('pdf_getlinetotalwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2458
2459 if (!empty($hookmanager->resPrint)) {
2460 $result .= $hookmanager->resPrint;
2461 }
2462 }
2463 if (empty($reshook)) {
2464 if ($object->lines[$i]->special_code == 3) {
2465 $result .= $outputlangs->transnoentities("Option");
2466 } elseif (empty($hidedetails) || $hidedetails > 1) {
2467 $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ttc : $object->lines[$i]->total_ttc);
2468 if (isset($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
2469 // TODO Remove this. The total should be saved correctly in database instead of being modified here.
2470 $prev_progress = 0;
2471 $progress = 1;
2472 if (method_exists($object->lines[$i], 'get_prev_progress')) {
2473 $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2474 $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
2475 }
2476 $result .= price($sign * ($total_ttc / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
2477 } else {
2478 $result .= price($sign * $total_ttc, 0, $outputlangs);
2479 }
2480 }
2481 }
2482 return $result;
2483}
2484
2493function pdf_getLinkedObjects(&$object, $outputlangs)
2494{
2495 global $db, $hookmanager;
2496
2497 $linkedobjects = array();
2498
2499 $object->fetchObjectLinked();
2500
2501 foreach ($object->linkedObjects as $objecttype => $objects) {
2502 if ($objecttype == 'facture') {
2503 // 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.
2504 } elseif ($objecttype == 'propal' || $objecttype == 'supplier_proposal') {
2505 '@phan-var-force array<Propal|SupplierProposal> $objects';
2506 $outputlangs->load('propal');
2507
2508 foreach ($objects as $elementobject) {
2509 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefProposal");
2510 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2511 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DatePropal");
2512 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2513 }
2514 } elseif ($objecttype == 'commande' || $objecttype == 'supplier_order') {
2515 '@phan-var-force array<Commande|CommandeFournisseur> $objects';
2516 $outputlangs->load('orders');
2517
2518 if (count($objects) > 1 && count($objects) <= (getDolGlobalInt("MAXREFONDOC") ? getDolGlobalInt("MAXREFONDOC") : 10)) {
2519 if (empty($object->context['DolPublicNoteAppendedGetLinkedObjects'])) { // Check if already appended before add to avoid repeat data
2520 $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("RefOrder").' :');
2521 foreach ($objects as $elementobject) {
2522 $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.')').' ');
2523 $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("OrderDate").' : '.dol_print_date($elementobject->date, 'day', '', $outputlangs));
2524 }
2525 }
2526 } elseif (count($objects) == 1) {
2527 $elementobject = array_shift($objects);
2528 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder");
2529 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref).(!empty($elementobject->ref_client) ? ' ('.$elementobject->ref_client.')' : '').(!empty($elementobject->ref_supplier) ? ' ('.$elementobject->ref_supplier.')' : '');
2530 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("OrderDate");
2531 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2532 }
2533 } elseif ($objecttype == 'contrat') {
2534 '@phan-var-force Contrat[] $objects';
2535 $outputlangs->load('contracts');
2536 foreach ($objects as $elementobject) {
2537 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefContract");
2538 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2539 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DateContract");
2540 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date_contrat, 'day', '', $outputlangs);
2541 }
2542 } elseif ($objecttype == 'fichinter') {
2543 '@phan-var-force Fichinter[] $objects';
2544 $outputlangs->load('interventions');
2545 foreach ($objects as $elementobject) {
2546 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("InterRef");
2547 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2548 $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("InterDate");
2549 $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->datec, 'day', '', $outputlangs);
2550 }
2551 } elseif ($objecttype == 'shipping') {
2552 '@phan-var-force Expedition[] $objects';
2553 $outputlangs->loadLangs(array("orders", "sendings"));
2554
2555 if (count($objects) > 1) {
2556 $order = null;
2557
2558 $refListsTxt = '';
2559 if (empty($object->linkedObjects['commande']) && $object->element != 'commande') {
2560 $refListsTxt .= $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending").' :';
2561 } else {
2562 $refListsTxt .= $outputlangs->transnoentities("RefSending").' :';
2563 }
2564 // We concat this record info into fields xxx_value. title is overwrote.
2565 foreach ($objects as $elementobject) {
2566 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
2567 $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2568 if (!empty($elementobject->linkedObjectsIds['commande'])) {
2569 include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2570 $order = new Commande($db);
2571 $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2572 if ($ret < 1) {
2573 $order = null;
2574 }
2575 }
2576 }
2577 $refListsTxt .= (!empty($refListsTxt) ? ' ' : '');
2578 if (! is_object($order)) {
2579 $refListsTxt .= $outputlangs->transnoentities($elementobject->ref);
2580 } else {
2581 $refListsTxt .= $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
2582 $refListsTxt .= ' / '.$outputlangs->transnoentities($elementobject->ref);
2583 }
2584 }
2585
2586 if (empty($object->context['DolPublicNoteAppendedGetLinkedObjects'])) { // Check if already appended before add to avoid repeat data
2587 $object->note_public = dol_concatdesc($object->note_public, $refListsTxt);
2588 }
2589 } elseif (count($objects) == 1) {
2590 $elementobject = array_shift($objects);
2591 $order = null;
2592 // We concat this record info into fields xxx_value. title is overwrote.
2593 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
2594 $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2595 if (!empty($elementobject->linkedObjectsIds['commande'])) {
2596 include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2597 $order = new Commande($db);
2598 $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2599 if ($ret < 1) {
2600 $order = null;
2601 }
2602 }
2603 }
2604
2605 if (! is_object($order)) {
2606 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefSending");
2607 if (empty($linkedobjects[$objecttype]['ref_value'])) {
2608 $linkedobjects[$objecttype]['ref_value'] = '';
2609 } else {
2610 $linkedobjects[$objecttype]['ref_value'] .= ' / ';
2611 }
2612 $linkedobjects[$objecttype]['ref_value'] .= $outputlangs->transnoentities($elementobject->ref);
2613 $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
2614 } else {
2615 $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending");
2616 if (empty($linkedobjects[$objecttype]['ref_value'])) {
2617 $linkedobjects[$objecttype]['ref_value'] = $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
2618 }
2619 $linkedobjects[$objecttype]['ref_value'] .= ' / '.$outputlangs->transnoentities($elementobject->ref);
2620 $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
2621 }
2622 }
2623 }
2624 }
2625
2626 $object->context['DolPublicNoteAppendedGetLinkedObjects'] = 1;
2627
2628 // For add external linked objects
2629 if (is_object($hookmanager)) {
2630 $parameters = array('linkedobjects' => $linkedobjects, 'outputlangs' => $outputlangs);
2631 $action = '';
2632 $hookmanager->executeHooks('pdf_getLinkedObjects', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2633 if (!empty($hookmanager->resArray)) {
2634 $linkedobjects = $hookmanager->resArray;
2635 }
2636 }
2637
2638 return $linkedobjects;
2639}
2640
2648function pdf_getSizeForImage($realpath)
2649{
2650 $maxwidth = getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20);
2651 $maxheight = getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT', 32);
2652
2653 include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
2654 $tmp = dol_getImageSize($realpath);
2655 $width = 0;
2656 $height = 0;
2657 if ($tmp['height']) {
2658 $width = (int) round($maxheight * $tmp['width'] / $tmp['height']); // I try to use maxheight
2659 if ($width > $maxwidth) { // Pb with maxheight, so i use maxwidth
2660 $width = $maxwidth;
2661 $height = (int) round($maxwidth * $tmp['height'] / $tmp['width']);
2662 } else { // No pb with maxheight
2663 $height = $maxheight;
2664 }
2665 }
2666 return array('width' => $width, 'height' => $height);
2667}
2668
2678function pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails = 0)
2679{
2680 global $hookmanager;
2681
2682 $sign = 1;
2683 if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2684 $sign = -1;
2685 }
2686 if ($object->lines[$i]->special_code == 3) {
2687 // If option
2688 return $outputlangs->transnoentities("Option");
2689 } else {
2690 if (is_object($hookmanager)) {
2691 $special_code = $object->lines[$i]->special_code;
2692 if (!empty($object->lines[$i]->fk_parent_line)) {
2693 $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2694 }
2695
2696 $parameters = array(
2697 'i' => $i,
2698 'outputlangs' => $outputlangs,
2699 'hidedetails' => $hidedetails,
2700 'special_code' => $special_code
2701 );
2702
2703 $action = '';
2704
2705 if ($hookmanager->executeHooks('getlinetotalremise', $parameters, $object, $action) > 0) { // Note that $action and $object may have been modified by some hooks
2706 if (isset($hookmanager->resArray['linetotalremise'])) {
2707 return (float) $hookmanager->resArray['linetotalremise'];
2708 } else {
2709 return (float) $hookmanager->resPrint; // For backward compatibility
2710 }
2711 }
2712 }
2713
2714 if (empty($hidedetails) || $hidedetails > 1) {
2715 return (float) price2num($sign * (($object->lines[$i]->subprice * (float) $object->lines[$i]->qty) - $object->lines[$i]->total_ht), 'MT', 1);
2716 }
2717 }
2718 return 0;
2719}
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:2648
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:1442
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition pdf.lib.php:2382
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:1497
pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails=0)
Return line total amount discount.
Definition pdf.lib.php:2678
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:2165
pdf_getlinenum($object, $i, $outputlangs, $hidedetails=0)
Return line num.
Definition pdf.lib.php:1840
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:2043
pdf_getLinkedObjects(&$object, $outputlangs)
Return linked objects to use for document generation.
Definition pdf.lib.php:2493
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:1906
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition pdf.lib.php:2438
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:1027
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition pdf.lib.php:2000
pdf_getlineprogress($object, $i, $outputlangs, $hidedetails=0, $hookmanager=null)
Return line percent.
Definition pdf.lib.php:2331
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition pdf.lib.php:1938
pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition pdf.lib.php:338
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:729
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1405
pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank information for PDF generation.
Definition pdf.lib.php:850
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:2205
pdf_getlineref($object, $i, $outputlangs, $hidedetails=0)
Return line product ref.
Definition pdf.lib.php:1873
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:434
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition pdf.lib.php:2245
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition pdf.lib.php:2288
pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails=0)
Return line quantity asked.
Definition pdf.lib.php:2125
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition pdf.lib.php:2085
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:765
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:386
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition pdf.lib.php:785