dolibarr  20.0.0-alpha
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 
40 include_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 
86 function pdf_getFormat(Translate $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 
128 function 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-1.3
184  if (getDolGlobalString('PDF_USE_A')) {
185  $pdfa = getDolGlobalString('PDF_USE_A'); // PDF/A-1 ou PDF/A-3
186  }
187 
188  if (!getDolGlobalString('MAIN_DISABLE_TCPDI') && class_exists('TCPDI')) {
189  $pdf = new TCPDI($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
190  } else {
191  $pdf = new TCPDF($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
192  }
193 
194  // Protection and encryption of pdf
195  if (getDolGlobalString('PDF_SECURITY_ENCRYPTION')) {
196  /* Permission supported by TCPDF
197  - print : Print the document;
198  - modify : Modify the contents of the document by operations other than those controlled by 'fill-forms', 'extract' and 'assemble';
199  - copy : Copy or otherwise extract text and graphics from the document;
200  - 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);
201  - fill-forms : Fill in existing interactive form fields (including signature fields), even if 'annot-forms' is not specified;
202  - extract : Extract text and graphics (in support of accessibility to users with disabilities or for other purposes);
203  - assemble : Assemble the document (insert, rotate, or delete pages and create bookmarks or thumbnail images), even if 'modify' is not set;
204  - 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.
205  - owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions.
206  */
207 
208  // For TCPDF, we specify permission we want to block
209  $pdfrights = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_RIGHTS') ? json_decode($conf->global->PDF_SECURITY_ENCRYPTION_RIGHTS, true) : array('modify', 'copy')); // Json format in llx_const
210 
211  // Password for the end user
212  $pdfuserpass = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_USERPASS') ? $conf->global->PDF_SECURITY_ENCRYPTION_USERPASS : '');
213 
214  // Password of the owner, created randomly if not defined
215  $pdfownerpass = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_OWNERPASS') ? $conf->global->PDF_SECURITY_ENCRYPTION_OWNERPASS : null);
216 
217  // For encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit
218  $encstrength = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_STRENGTH') ? $conf->global->PDF_SECURITY_ENCRYPTION_STRENGTH : 0);
219 
220  // Array of recipients containing public-key certificates ('c') and permissions ('p').
221  // For example: array(array('c' => 'file://../examples/data/cert/tcpdf.crt', 'p' => array('print')))
222  $pubkeys = (getDolGlobalString('PDF_SECURITY_ENCRYPTION_PUBKEYS') ? json_decode($conf->global->PDF_SECURITY_ENCRYPTION_PUBKEYS, true) : null); // Json format in llx_const
223 
224  $pdf->SetProtection($pdfrights, $pdfuserpass, $pdfownerpass, $encstrength, $pubkeys);
225  }
226 
227  return $pdf;
228 }
229 
236 function pdf_getEncryption($pathoffile)
237 {
238  require_once TCPDF_PATH.'tcpdf_parser.php';
239 
240  $isencrypted = false;
241 
242  $content = file_get_contents($pathoffile);
243 
244  //ob_start();
245  @($parser = new TCPDF_PARSER(ltrim($content)));
246  list($xref, $data) = $parser->getParsedData();
247  unset($parser);
248  //ob_end_clean();
249 
250  if (isset($xref['trailer']['encrypt'])) {
251  $isencrypted = true; // Secured pdf file are currently not supported
252  }
253 
254  if (empty($data)) {
255  $isencrypted = true; // Object list not found. Possible secured file
256  }
257 
258  return $isencrypted;
259 }
260 
267 function pdf_getPDFFont($outputlangs)
268 {
269  global $conf;
270 
271  if (getDolGlobalString('MAIN_PDF_FORCE_FONT')) {
272  return $conf->global->MAIN_PDF_FORCE_FONT;
273  }
274 
275  $font = 'Helvetica'; // By default, for FPDI, or ISO language on TCPDF
276  if (class_exists('TCPDF')) { // If TCPDF on, we can use an UTF8 one like DejaVuSans if required (slower)
277  if ($outputlangs->trans('FONTFORPDF') != 'FONTFORPDF') {
278  $font = $outputlangs->trans('FONTFORPDF');
279  }
280  }
281  return $font;
282 }
283 
290 function pdf_getPDFFontSize($outputlangs)
291 {
292  global $conf;
293 
294  $size = 10; // By default, for FPDI or ISO language on TCPDF
295  if (class_exists('TCPDF')) { // If TCPDF on, we can use an UTF8 font like DejaVuSans if required (slower)
296  if ($outputlangs->trans('FONTSIZEFORPDF') != 'FONTSIZEFORPDF') {
297  $size = (int) $outputlangs->trans('FONTSIZEFORPDF');
298  }
299  }
300  if (getDolGlobalString('MAIN_PDF_FORCE_FONT_SIZE')) {
301  $size = getDolGlobalString('MAIN_PDF_FORCE_FONT_SIZE');
302  }
303 
304  return $size;
305 }
306 
307 
315 function pdf_getHeightForLogo($logo, $url = false)
316 {
317  global $conf;
318  $height = (!getDolGlobalString('MAIN_DOCUMENTS_LOGO_HEIGHT') ? 20 : $conf->global->MAIN_DOCUMENTS_LOGO_HEIGHT);
319  $maxwidth = 130;
320  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
321  $tmp = dol_getImageSize($logo, $url);
322  if ($tmp['height']) {
323  $width = round($height * $tmp['width'] / $tmp['height']);
324  if ($width > $maxwidth) {
325  $height = $height * $maxwidth / $width;
326  }
327  }
328  //print $tmp['width'].' '.$tmp['height'].' '.$width; exit;
329  return $height;
330 }
331 
340 function pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
341 {
342  // store current object
343  $pdf->startTransaction();
344  // store starting values
345  $start_y = $pdf->GetY();
346  //var_dump($start_y);
347  $start_page = $pdf->getPage();
348  // call printing functions with content
349  $pdf->writeHTMLCell(0, 0, 0, $start_y, $htmlcontent, 0, 1, false, true, 'J', true);
350  // get the new Y
351  $end_y = $pdf->GetY();
352  $end_page = $pdf->getPage();
353  // calculate height
354  $height = 0;
355  if ($end_page == $start_page) {
356  $height = $end_y - $start_y;
357  } else {
358  for ($page = $start_page; $page <= $end_page; ++$page) {
359  $pdf->setPage($page);
360  $tmpm = $pdf->getMargins();
361  $tMargin = $tmpm['top'];
362  if ($page == $start_page) {
363  // first page
364  $height = $pdf->getPageHeight() - $start_y - $pdf->getBreakMargin();
365  } elseif ($page == $end_page) {
366  // last page
367  $height = $end_y - $tMargin;
368  } else {
369  $height = $pdf->getPageHeight() - $tMargin - $pdf->getBreakMargin();
370  }
371  }
372  }
373  // restore previous object
374  $pdf = $pdf->rollbackTransaction();
375 
376  return $height;
377 }
378 
379 
388 function pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias = 0)
389 {
390  global $conf;
391 
392  // Recipient name
393  $socname = '';
394 
395  if ($thirdparty instanceof Societe) {
396  $socname = $thirdparty->name;
397  if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->name_alias)) {
398  if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
399  $socname = $thirdparty->name_alias." - ".$thirdparty->name;
400  } else {
401  $socname = $thirdparty->name." - ".$thirdparty->name_alias;
402  }
403  }
404  } elseif ($thirdparty instanceof Contact) {
405  if ($thirdparty->socid > 0) {
406  $thirdparty->fetch_thirdparty();
407  $socname = $thirdparty->thirdparty->name;
408  if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->thirdparty->name_alias)) {
409  if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
410  $socname = $thirdparty->thirdparty->name_alias." - ".$thirdparty->thirdparty->name;
411  } else {
412  $socname = $thirdparty->thirdparty->name." - ".$thirdparty->thirdparty->name_alias;
413  }
414  }
415  }
416  } else {
417  throw new InvalidArgumentException('Parameter 1 $thirdparty is not a Societe nor Contact');
418  }
419 
420  return $outputlangs->convToOutputCharset($socname);
421 }
422 
423 
436 function pdf_build_address($outputlangs, $sourcecompany, $targetcompany = '', $targetcontact = '', $usecontact = 0, $mode = 'source', $object = null)
437 {
438  global $conf, $hookmanager;
439 
440  if ($mode == 'source' && !is_object($sourcecompany)) {
441  return -1;
442  }
443  if ($mode == 'target' && !is_object($targetcompany)) {
444  return -1;
445  }
446 
447  if (!empty($sourcecompany->state_id) && empty($sourcecompany->state)) {
448  $sourcecompany->state = getState($sourcecompany->state_id);
449  }
450  if (!empty($targetcompany->state_id) && empty($targetcompany->state)) {
451  $targetcompany->state = getState($targetcompany->state_id);
452  }
453 
454  $reshook = 0;
455  $stringaddress = '';
456  if (is_object($hookmanager)) {
457  $parameters = array('sourcecompany' => &$sourcecompany, 'targetcompany' => &$targetcompany, 'targetcontact' => &$targetcontact, 'outputlangs' => $outputlangs, 'mode' => $mode, 'usecontact' => $usecontact);
458  $action = '';
459  $reshook = $hookmanager->executeHooks('pdf_build_address', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
460  $stringaddress .= $hookmanager->resPrint;
461  }
462  if (empty($reshook)) {
463  if ($mode == 'source') {
464  $withCountry = 0;
465  if (isset($targetcompany->country_code) && !empty($sourcecompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
466  $withCountry = 1;
467  }
468 
469  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($sourcecompany, $withCountry, "\n", $outputlangs))."\n";
470 
471  if (!getDolGlobalString('MAIN_PDF_DISABLESOURCEDETAILS')) {
472  // Phone
473  if ($sourcecompany->phone) {
474  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("PhoneShort").": ".$outputlangs->convToOutputCharset($sourcecompany->phone);
475  }
476  // Fax
477  if ($sourcecompany->fax) {
478  $stringaddress .= ($stringaddress ? ($sourcecompany->phone ? " - " : "\n") : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($sourcecompany->fax);
479  }
480  // EMail
481  if ($sourcecompany->email) {
482  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($sourcecompany->email);
483  }
484  // Web
485  if ($sourcecompany->url) {
486  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($sourcecompany->url);
487  }
488  }
489  // Intra VAT
490  if (getDolGlobalString('MAIN_TVAINTRA_IN_SOURCE_ADDRESS')) {
491  if ($sourcecompany->tva_intra) {
492  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($sourcecompany->tva_intra);
493  }
494  }
495  // Professional Ids
496  $reg = array();
497  if (getDolGlobalString('MAIN_PROFID1_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof1)) {
498  $tmp = $outputlangs->transcountrynoentities("ProfId1", $sourcecompany->country_code);
499  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
500  $tmp = $reg[1];
501  }
502  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof1);
503  }
504  if (getDolGlobalString('MAIN_PROFID2_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof2)) {
505  $tmp = $outputlangs->transcountrynoentities("ProfId2", $sourcecompany->country_code);
506  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
507  $tmp = $reg[1];
508  }
509  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof2);
510  }
511  if (getDolGlobalString('MAIN_PROFID3_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof3)) {
512  $tmp = $outputlangs->transcountrynoentities("ProfId3", $sourcecompany->country_code);
513  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
514  $tmp = $reg[1];
515  }
516  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof3);
517  }
518  if (getDolGlobalString('MAIN_PROFID4_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof4)) {
519  $tmp = $outputlangs->transcountrynoentities("ProfId4", $sourcecompany->country_code);
520  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
521  $tmp = $reg[1];
522  }
523  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof4);
524  }
525  if (getDolGlobalString('MAIN_PROFID5_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof5)) {
526  $tmp = $outputlangs->transcountrynoentities("ProfId5", $sourcecompany->country_code);
527  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
528  $tmp = $reg[1];
529  }
530  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof5);
531  }
532  if (getDolGlobalString('MAIN_PROFID6_IN_SOURCE_ADDRESS') && !empty($sourcecompany->idprof6)) {
533  $tmp = $outputlangs->transcountrynoentities("ProfId6", $sourcecompany->country_code);
534  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
535  $tmp = $reg[1];
536  }
537  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof6);
538  }
539  if (getDolGlobalString('PDF_ADD_MORE_AFTER_SOURCE_ADDRESS')) {
540  $stringaddress .= ($stringaddress ? "\n" : '') . getDolGlobalString('PDF_ADD_MORE_AFTER_SOURCE_ADDRESS');
541  }
542  }
543 
544  if ($mode == 'target' || preg_match('/targetwithdetails/', $mode)) {
545  if ($usecontact) {
546  if (is_object($targetcontact)) {
547  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($targetcontact->getFullName($outputlangs, 1));
548 
549  if (!empty($targetcontact->address)) {
550  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcontact))."\n";
551  } else {
552  $companytouseforaddress = $targetcompany;
553 
554  // Contact on a thirdparty that is a different thirdparty than the thirdparty of object
555  if ($targetcontact->socid > 0 && $targetcontact->socid != $targetcompany->id) {
556  $targetcontact->fetch_thirdparty();
557  $companytouseforaddress = $targetcontact->thirdparty;
558  }
559 
560  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($companytouseforaddress))."\n";
561  }
562  // Country
563  if (!empty($targetcontact->country_code) && $targetcontact->country_code != $sourcecompany->country_code) {
564  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcontact->country_code));
565  } elseif (empty($targetcontact->country_code) && !empty($targetcompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
566  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
567  }
568 
569  if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || preg_match('/targetwithdetails/', $mode)) {
570  // Phone
571  if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
572  if (!empty($targetcontact->phone_pro) || !empty($targetcontact->phone_mobile)) {
573  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
574  }
575  if (!empty($targetcontact->phone_pro)) {
576  $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_pro);
577  }
578  if (!empty($targetcontact->phone_pro) && !empty($targetcontact->phone_mobile)) {
579  $stringaddress .= " / ";
580  }
581  if (!empty($targetcontact->phone_mobile)) {
582  $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_mobile);
583  }
584  }
585  // Fax
586  if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
587  if ($targetcontact->fax) {
588  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcontact->fax);
589  }
590  }
591  // EMail
592  if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
593  if ($targetcontact->email) {
594  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcontact->email);
595  }
596  }
597  // Web
598  if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
599  if ($targetcontact->url) {
600  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcontact->url);
601  }
602  }
603  }
604  }
605  } else {
606  if (is_object($targetcompany)) {
607  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcompany));
608  // Country
609  if (!empty($targetcompany->country_code) && $targetcompany->country_code != $sourcecompany->country_code) {
610  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
611  } else {
612  $stringaddress .= ($stringaddress ? "\n" : '');
613  }
614 
615  if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || preg_match('/targetwithdetails/', $mode)) {
616  // Phone
617  if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
618  if (!empty($targetcompany->phone)) {
619  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
620  }
621  if (!empty($targetcompany->phone)) {
622  $stringaddress .= $outputlangs->convToOutputCharset($targetcompany->phone);
623  }
624  }
625  // Fax
626  if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
627  if ($targetcompany->fax) {
628  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcompany->fax);
629  }
630  }
631  // EMail
632  if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
633  if ($targetcompany->email) {
634  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcompany->email);
635  }
636  }
637  // Web
638  if (getDolGlobalString('MAIN_PDF_ADDALSOTARGETDETAILS') || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
639  if ($targetcompany->url) {
640  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcompany->url);
641  }
642  }
643  }
644  }
645  }
646 
647  // Intra VAT
648  if (!getDolGlobalString('MAIN_TVAINTRA_NOT_IN_ADDRESS')) {
649  if ($usecontact && is_object($targetcontact) && getDolGlobalInt('MAIN_USE_COMPANY_NAME_OF_CONTACT')) {
650  $targetcontact->fetch_thirdparty();
651  if (!empty($targetcontact->thirdparty->id) && $targetcontact->thirdparty->tva_intra) {
652  $stringaddress .= ($stringaddress ? "\n" : '') . $outputlangs->transnoentities("VATIntraShort") . ': ' . $outputlangs->convToOutputCharset($targetcontact->thirdparty->tva_intra);
653  }
654  } elseif ($targetcompany->tva_intra) {
655  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($targetcompany->tva_intra);
656  }
657  }
658 
659  // Professional Ids
660  if (getDolGlobalString('MAIN_PROFID1_IN_ADDRESS') && !empty($targetcompany->idprof1)) {
661  $tmp = $outputlangs->transcountrynoentities("ProfId1", $targetcompany->country_code);
662  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
663  $tmp = $reg[1];
664  }
665  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof1);
666  }
667  if (getDolGlobalString('MAIN_PROFID2_IN_ADDRESS') && !empty($targetcompany->idprof2)) {
668  $tmp = $outputlangs->transcountrynoentities("ProfId2", $targetcompany->country_code);
669  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
670  $tmp = $reg[1];
671  }
672  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof2);
673  }
674  if (getDolGlobalString('MAIN_PROFID3_IN_ADDRESS') && !empty($targetcompany->idprof3)) {
675  $tmp = $outputlangs->transcountrynoentities("ProfId3", $targetcompany->country_code);
676  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
677  $tmp = $reg[1];
678  }
679  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof3);
680  }
681  if (getDolGlobalString('MAIN_PROFID4_IN_ADDRESS') && !empty($targetcompany->idprof4)) {
682  $tmp = $outputlangs->transcountrynoentities("ProfId4", $targetcompany->country_code);
683  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
684  $tmp = $reg[1];
685  }
686  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof4);
687  }
688  if (getDolGlobalString('MAIN_PROFID5_IN_ADDRESS') && !empty($targetcompany->idprof5)) {
689  $tmp = $outputlangs->transcountrynoentities("ProfId5", $targetcompany->country_code);
690  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
691  $tmp = $reg[1];
692  }
693  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof5);
694  }
695  if (getDolGlobalString('MAIN_PROFID6_IN_ADDRESS') && !empty($targetcompany->idprof6)) {
696  $tmp = $outputlangs->transcountrynoentities("ProfId6", $targetcompany->country_code);
697  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
698  $tmp = $reg[1];
699  }
700  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof6);
701  }
702 
703  // Public note
704  if (getDolGlobalString('MAIN_PUBLIC_NOTE_IN_ADDRESS')) {
705  if ($mode == 'source' && !empty($sourcecompany->note_public)) {
706  $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($sourcecompany->note_public);
707  }
708  if (($mode == 'target' || preg_match('/targetwithdetails/', $mode)) && !empty($targetcompany->note_public)) {
709  $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($targetcompany->note_public);
710  }
711  }
712  }
713  }
714 
715  return $stringaddress;
716 }
717 
718 
727 function pdf_pagehead(&$pdf, $outputlangs, $page_height)
728 {
729  global $conf;
730 
731  // Add a background image on document only if good setup of const
732  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
733  $filepath = $conf->mycompany->dir_output.'/logos/' . getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF');
734  if (file_exists($filepath)) {
735  $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak before adding image
736  if (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF_ALPHA')) {
737  $pdf->SetAlpha($conf->global->MAIN_USE_BACKGROUND_ON_PDF_ALPHA);
738  } // Option for change opacity of background
739  $pdf->Image($filepath, (isset($conf->global->MAIN_USE_BACKGROUND_ON_PDF_X) ? $conf->global->MAIN_USE_BACKGROUND_ON_PDF_X : 0), (isset($conf->global->MAIN_USE_BACKGROUND_ON_PDF_Y) ? $conf->global->MAIN_USE_BACKGROUND_ON_PDF_Y : 0), 0, $page_height);
740  if (getDolGlobalString('MAIN_USE_BACKGROUND_ON_PDF_ALPHA')) {
741  $pdf->SetAlpha(1);
742  }
743  $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
744  $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
745  }
746  }
747  if (getDolGlobalString('MAIN_ADD_PDF_BACKGROUND') && getDolGlobalString('MAIN_ADD_PDF_BACKGROUND') != '-1') {
748  $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
749  }
750 }
751 
752 
763 function pdf_getSubstitutionArray($outputlangs, $exclude = null, $object = null, $onlykey = 0, $include = null)
764 {
765  $substitutionarray = getCommonSubstitutionArray($outputlangs, $onlykey, $exclude, $object, $include);
766  $substitutionarray['__FROM_NAME__'] = '__FROM_NAME__';
767  $substitutionarray['__FROM_EMAIL__'] = '__FROM_EMAIL__';
768  return $substitutionarray;
769 }
770 
771 
783 function pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
784 {
785  // Print Draft Watermark
786  if ($unit == 'pt') {
787  $k = 1;
788  } elseif ($unit == 'mm') {
789  $k = 72 / 25.4;
790  } elseif ($unit == 'cm') {
791  $k = 72 / 2.54;
792  } elseif ($unit == 'in') {
793  $k = 72;
794  }
795 
796  // Make substitution
797  $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, null);
798  complete_substitutions_array($substitutionarray, $outputlangs, null);
799  $text = make_substitutions($text, $substitutionarray, $outputlangs);
800  $text = $outputlangs->convToOutputCharset($text);
801 
802  $savx = $pdf->getX();
803  $savy = $pdf->getY();
804 
805  $watermark_angle = atan($h / $w) / 2;
806  $watermark_x_pos = 0;
807  $watermark_y_pos = $h / 3;
808  $watermark_x = $w / 2;
809  $watermark_y = $h / 3;
810  $pdf->SetFont('', 'B', 40);
811  $pdf->SetTextColor(255, 192, 203);
812 
813  //rotate
814  $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));
815  //print watermark
816  $pdf->SetXY($watermark_x_pos, $watermark_y_pos);
817  $pdf->Cell($w - 20, 25, $outputlangs->convToOutputCharset($text), "", 2, "C", 0);
818  //antirotate
819  $pdf->_out('Q');
820 
821  $pdf->SetXY($savx, $savy);
822 }
823 
824 
837 function pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber = 0, $default_font_size = 10)
838 {
839  global $mysoc, $conf;
840 
841  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbank.class.php';
842 
843  $diffsizetitle = getDolGlobalInt('PDF_DIFFSIZE_TITLE', 3);
844  $diffsizecontent = getDolGlobalInt('PDF_DIFFSIZE_CONTENT', 4);
845  $pdf->SetXY($curx, $cury);
846 
847  if (empty($onlynumber)) {
848  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
849  $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByTransferOnThisBankAccount').':', 0, 'L', 0);
850  $cury += 4;
851  }
852 
853  $outputlangs->load("banks");
854 
855  // Use correct name of bank id according to country
856  $bickey = "BICNumber";
857  if ($account->getCountryCode() == 'IN') {
858  $bickey = "SWIFT";
859  }
860 
861  // Get format of bank account according to its country
862  $usedetailedbban = $account->useDetailedBBAN();
863 
864  //$onlynumber=0; $usedetailedbban=1; // For tests
865  if ($usedetailedbban) {
866  $savcurx = $curx;
867 
868  if (empty($onlynumber)) {
869  $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
870  $pdf->SetXY($curx, $cury);
871  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
872  $cury += 3;
873  }
874 
875  if (!getDolGlobalString('PDF_BANK_HIDE_NUMBER_SHOW_ONLY_BICIBAN')) { // Note that some countries still need bank number, BIC/IBAN not enough for them
876  // Note:
877  // bank = code_banque (FR), sort code (GB, IR. Example: 12-34-56)
878  // desk = code guichet (FR), used only when $usedetailedbban = 1
879  // number = account number
880  // key = check control key used only when $usedetailedbban = 1
881  if (empty($onlynumber)) {
882  $pdf->line($curx + 1, $cury + 1, $curx + 1, $cury + 6);
883  }
884 
885 
886  foreach ($account->getFieldsToShow() as $val) {
887  $pdf->SetXY($curx, $cury + 4);
888  $pdf->SetFont('', '', $default_font_size - 3);
889 
890  if ($val == 'BankCode') {
891  // Bank code
892  $tmplength = 18;
893  $content = $account->code_banque;
894  } elseif ($val == 'DeskCode') {
895  // Desk
896  $tmplength = 18;
897  $content = $account->code_guichet;
898  } elseif ($val == 'BankAccountNumber') {
899  // Number
900  $tmplength = 24;
901  $content = $account->number;
902  } elseif ($val == 'BankAccountNumberKey') {
903  // Key
904  $tmplength = 15;
905  $content = $account->cle_rib;
906  } elseif ($val == 'IBAN' || $val == 'BIC') {
907  // Key
908  $tmplength = 0;
909  $content = '';
910  } else {
911  dol_print_error($account->db, 'Unexpected value for getFieldsToShow: '.$val);
912  break;
913  }
914 
915  $pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($content), 0, 'C', 0);
916  $pdf->SetXY($curx, $cury + 1);
917  $curx += $tmplength;
918  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
919  $pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities($val), 0, 'C', 0);
920  if (empty($onlynumber)) {
921  $pdf->line($curx, $cury + 1, $curx, $cury + 7);
922  }
923  }
924 
925  $curx = $savcurx;
926  $cury += 8;
927  }
928  } elseif (!empty($account->number)) {
929  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
930  $pdf->SetXY($curx, $cury);
931  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
932  $cury += 3;
933 
934  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
935  $pdf->SetXY($curx, $cury);
936  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("BankAccountNumber").': '.$outputlangs->convToOutputCharset($account->number), 0, 'L', 0);
937  $cury += 3;
938 
939  if ($diffsizecontent <= 2) {
940  $cury += 1;
941  }
942  }
943 
944  $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
945 
946  if (empty($onlynumber) && (!empty($account->domiciliation) || !empty($account->address))) {
947  $pdf->SetXY($curx, $cury);
948  $val = $outputlangs->transnoentities("Residence").': '.$outputlangs->convToOutputCharset(empty($account->address) ? $account->domiciliation : $account->address);
949  $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
950  //$nboflines=dol_nboflines_bis($val,120);
951  //$cury+=($nboflines*3)+2;
952  $tmpy = $pdf->getStringHeight(100, $val);
953  $cury += $tmpy;
954  }
955 
956  if (!empty($account->owner_name)) {
957  $pdf->SetXY($curx, $cury);
958  $val = $outputlangs->transnoentities("BankAccountOwner").': '.$outputlangs->convToOutputCharset($account->owner_name);
959  $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
960  $tmpy = $pdf->getStringHeight(100, $val);
961  $cury += $tmpy;
962  } elseif (!$usedetailedbban) {
963  $cury += 1;
964  }
965 
966  // Use correct name of bank id according to country
967  $ibankey = FormBank::getIBANLabel($account);
968 
969  if (!empty($account->iban)) {
970  //Remove whitespaces to ensure we are dealing with the format we expect
971  $ibanDisplay_temp = str_replace(' ', '', $outputlangs->convToOutputCharset($account->iban));
972  $ibanDisplay = "";
973 
974  $nbIbanDisplay_temp = dol_strlen($ibanDisplay_temp);
975  for ($i = 0; $i < $nbIbanDisplay_temp; $i++) {
976  $ibanDisplay .= $ibanDisplay_temp[$i];
977  if ($i % 4 == 3 && $i > 0) {
978  $ibanDisplay .= " ";
979  }
980  }
981 
982  $pdf->SetFont('', 'B', $default_font_size - 3);
983  $pdf->SetXY($curx, $cury);
984  $pdf->MultiCell(100, 3, $outputlangs->transnoentities($ibankey).': '.$ibanDisplay, 0, 'L', 0);
985  $cury += 3;
986  }
987 
988  if (!empty($account->bic)) {
989  $pdf->SetFont('', 'B', $default_font_size - 3);
990  $pdf->SetXY($curx, $cury);
991  $pdf->MultiCell(100, 3, $outputlangs->transnoentities($bickey).': '.$outputlangs->convToOutputCharset($account->bic), 0, 'L', 0);
992  }
993 
994  return $pdf->getY();
995 }
996 
1014 function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails = 0, $hidefreetext = 0, $page_largeur = 0, $watermark = '')
1015 {
1016  global $conf, $hookmanager;
1017 
1018  $outputlangs->load("dict");
1019  $line = '';
1020  $reg = array();
1021  $marginwithfooter = 0; // Return value
1022 
1023  $dims = $pdf->getPageDimensions();
1024 
1025  // Line of free text
1026  if (empty($hidefreetext) && !empty($conf->global->$paramfreetext)) {
1027  $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
1028  // More substitution keys
1029  $substitutionarray['__FROM_NAME__'] = $fromcompany->name;
1030  $substitutionarray['__FROM_EMAIL__'] = $fromcompany->email;
1031  complete_substitutions_array($substitutionarray, $outputlangs, $object);
1032  $newfreetext = make_substitutions(getDolGlobalString($paramfreetext), $substitutionarray, $outputlangs);
1033 
1034  // Make a change into HTML code to allow to include images from medias directory.
1035  // <img alt="" src="/dolibarr_dev/htdocs/viewimage.php?modulepart=medias&amp;entity=1&amp;file=image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1036  // become
1037  // <img alt="" src="'.DOL_DATA_ROOT.'/medias/image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1038  $newfreetext = preg_replace('/(<img.*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)("[^\/]*\/>)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $newfreetext);
1039 
1040  $line .= $outputlangs->convToOutputCharset($newfreetext);
1041  }
1042 
1043  // First line of company infos
1044  $line1 = "";
1045  $line2 = "";
1046  $line3 = "";
1047  $line4 = "";
1048 
1049  if ($showdetails == 1 || $showdetails == 3) {
1050  // Company name
1051  if ($fromcompany->name) {
1052  $line1 .= ($line1 ? " - " : "").$outputlangs->transnoentities("RegisteredOffice").": ".$fromcompany->name;
1053  }
1054  // Address
1055  if ($fromcompany->address) {
1056  $line1 .= ($line1 ? " - " : "").str_replace("\n", ", ", $fromcompany->address);
1057  }
1058  // Zip code
1059  if ($fromcompany->zip) {
1060  $line1 .= ($line1 ? " - " : "").$fromcompany->zip;
1061  }
1062  // Town
1063  if ($fromcompany->town) {
1064  $line1 .= ($line1 ? " " : "").$fromcompany->town;
1065  }
1066  // Country
1067  if ($fromcompany->country) {
1068  $line1 .= ($line1 ? ", " : "").$fromcompany->country;
1069  }
1070  // Phone
1071  if ($fromcompany->phone) {
1072  $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Phone").": ".$fromcompany->phone;
1073  }
1074  // Fax
1075  if ($fromcompany->fax) {
1076  $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Fax").": ".$fromcompany->fax;
1077  }
1078 
1079  // URL
1080  if ($fromcompany->url) {
1081  $line2 .= ($line2 ? " - " : "").$fromcompany->url;
1082  }
1083  // Email
1084  if ($fromcompany->email) {
1085  $line2 .= ($line2 ? " - " : "").$fromcompany->email;
1086  }
1087  }
1088  if ($showdetails == 2 || $showdetails == 3 || (!empty($fromcompany->country_code) && $fromcompany->country_code == 'DE')) {
1089  // Managers
1090  if ($fromcompany->managers) {
1091  $line2 .= ($line2 ? " - " : "").$fromcompany->managers;
1092  }
1093  }
1094 
1095  // Line 3 of company infos
1096  // Juridical status
1097  if (!empty($fromcompany->forme_juridique_code) && $fromcompany->forme_juridique_code) {
1098  $line3 .= ($line3 ? " - " : "").$outputlangs->convToOutputCharset(getFormeJuridiqueLabel($fromcompany->forme_juridique_code));
1099  }
1100  // Capital
1101  if (!empty($fromcompany->capital)) {
1102  $tmpamounttoshow = price2num($fromcompany->capital); // This field is a free string or a float
1103  if (is_numeric($tmpamounttoshow) && $tmpamounttoshow > 0) {
1104  $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", price($tmpamounttoshow, 0, $outputlangs, 0, 0, 0, $conf->currency));
1105  } elseif (!empty($fromcompany->capital)) {
1106  $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", $fromcompany->capital, $outputlangs);
1107  }
1108  }
1109  // Prof Id 1
1110  if (!empty($fromcompany->idprof1) && $fromcompany->idprof1 && ($fromcompany->country_code != 'FR' || !$fromcompany->idprof2)) {
1111  $field = $outputlangs->transcountrynoentities("ProfId1", $fromcompany->country_code);
1112  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1113  $field = $reg[1];
1114  }
1115  $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof1);
1116  }
1117  // Prof Id 2
1118  if (!empty($fromcompany->idprof2) && $fromcompany->idprof2) {
1119  $field = $outputlangs->transcountrynoentities("ProfId2", $fromcompany->country_code);
1120  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1121  $field = $reg[1];
1122  }
1123  $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof2);
1124  }
1125 
1126  // Line 4 of company infos
1127  // Prof Id 3
1128  if (!empty($fromcompany->idprof3) && $fromcompany->idprof3) {
1129  $field = $outputlangs->transcountrynoentities("ProfId3", $fromcompany->country_code);
1130  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1131  $field = $reg[1];
1132  }
1133  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof3);
1134  }
1135  // Prof Id 4
1136  if (!empty($fromcompany->idprof4) && $fromcompany->idprof4) {
1137  $field = $outputlangs->transcountrynoentities("ProfId4", $fromcompany->country_code);
1138  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1139  $field = $reg[1];
1140  }
1141  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof4);
1142  }
1143  // Prof Id 5
1144  if (!empty($fromcompany->idprof5) && $fromcompany->idprof5) {
1145  $field = $outputlangs->transcountrynoentities("ProfId5", $fromcompany->country_code);
1146  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1147  $field = $reg[1];
1148  }
1149  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof5);
1150  }
1151  // Prof Id 6
1152  if (!empty($fromcompany->idprof6) && $fromcompany->idprof6) {
1153  $field = $outputlangs->transcountrynoentities("ProfId6", $fromcompany->country_code);
1154  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1155  $field = $reg[1];
1156  }
1157  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof6);
1158  }
1159  // Prof Id 7
1160  if (!empty($fromcompany->idprof7) && $fromcompany->idprof7) {
1161  $field = $outputlangs->transcountrynoentities("ProfId7", $fromcompany->country_code);
1162  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1163  $field = $reg[1];
1164  }
1165  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof7);
1166  }
1167  // Prof Id 8
1168  if (!empty($fromcompany->idprof8) && $fromcompany->idprof8) {
1169  $field = $outputlangs->transcountrynoentities("ProfId8", $fromcompany->country_code);
1170  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1171  $field = $reg[1];
1172  }
1173  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof8);
1174  }
1175  // Prof Id 9
1176  if (!empty($fromcompany->idprof9) && $fromcompany->idprof9) {
1177  $field = $outputlangs->transcountrynoentities("ProfId9", $fromcompany->country_code);
1178  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1179  $field = $reg[1];
1180  }
1181  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof9);
1182  }
1183  // Prof Id 10
1184  if (!empty($fromcompany->idprof10) && $fromcompany->idprof10) {
1185  $field = $outputlangs->transcountrynoentities("ProfId10", $fromcompany->country_code);
1186  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1187  $field = $reg[1];
1188  }
1189  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof10);
1190  }
1191  // IntraCommunautary VAT
1192  if (!empty($fromcompany->tva_intra) && $fromcompany->tva_intra != '') {
1193  $line4 .= ($line4 ? " - " : "").$outputlangs->transnoentities("VATIntraShort").": ".$outputlangs->convToOutputCharset($fromcompany->tva_intra);
1194  }
1195 
1196  $pdf->SetFont('', '', 7);
1197  $pdf->SetDrawColor(224, 224, 224);
1198  // Option for footer text color
1199  if (getDolGlobalString('PDF_FOOTER_TEXT_COLOR')) {
1200  list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_TEXT_COLOR, '%d, %d, %d');
1201  $pdf->SetTextColor($r, $g, $b);
1202  }
1203 
1204  // The start of the bottom of this page footer is positioned according to # of lines
1205  $freetextheight = 0;
1206  if ($line) { // Free text
1207  //$line="sample text<br>\nfd<strong>sf</strong>sdf<br>\nghfghg<br>";
1208  if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) {
1209  $width = 20000;
1210  $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.
1211  if (getDolGlobalString('MAIN_USE_AUTOWRAP_ON_FREETEXT')) {
1212  $width = 200;
1213  $align = 'C';
1214  }
1215  $freetextheight = $pdf->getStringHeight($width, $line);
1216  } else {
1217  $freetextheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($line, 1, 'UTF-8', 0)); // New method (works for HTML content)
1218  //print '<br>'.$freetextheight;exit;
1219  }
1220  }
1221 
1222  // For customize footer
1223  if (is_object($hookmanager)) {
1224  $parameters = array('line1' => $line1, 'line2' => $line2, 'line3' => $line3, 'line4' => $line4, 'outputlangs' => $outputlangs);
1225  $action = '';
1226  $hookmanager->executeHooks('pdf_pagefoot', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1227  if (!empty($hookmanager->resPrint) && $hidefreetext == 0) {
1228  $mycustomfooter = $hookmanager->resPrint;
1229  $mycustomfooterheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1230 
1231  $marginwithfooter = $marge_basse + $freetextheight + $mycustomfooterheight;
1232  $posy = (float) $marginwithfooter;
1233 
1234  // Option for footer background color (without freetext zone)
1235  if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1236  list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
1237  $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
1238  $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', '', $fill_color = array($r, $g, $b));
1239  $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
1240  }
1241 
1242  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1243  $pdf->SetAutoPageBreak(0, 0);
1244  } // Option for disable auto pagebreak
1245  if ($line) { // Free text
1246  $pdf->SetXY($dims['lm'], -$posy);
1247  if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1248  $pdf->MultiCell(0, 3, $line, 0, $align, 0);
1249  } else {
1250  $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1251  }
1252  $posy -= $freetextheight;
1253  }
1254  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1255  $pdf->SetAutoPageBreak(1, 0);
1256  } // Restore pagebreak
1257 
1258  $pdf->SetY(-$posy);
1259 
1260  // Hide footer line if footer background color is set
1261  if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1262  $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1263  }
1264 
1265  // Option for set top margin height of footer after freetext
1266  if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1267  $posy -= (float) getDolGlobalString('PDF_FOOTER_TOP_MARGIN');
1268  } else {
1269  $posy--;
1270  }
1271 
1272  if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) {
1273  $pdf->SetAutoPageBreak(0, 0);
1274  } // Option for disable auto pagebreak
1275  $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $mycustomfooterheight, $dims['lm'], $dims['hk'] - $posy, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1276  if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) {
1277  $pdf->SetAutoPageBreak(1, 0);
1278  } // Restore pagebreak
1279 
1280  $posy -= $mycustomfooterheight - 3;
1281  } else {
1282  // Else default footer
1283  $marginwithfooter = $marge_basse + $freetextheight + (!empty($line1) ? 3 : 0) + (!empty($line2) ? 3 : 0) + (!empty($line3) ? 3 : 0) + (!empty($line4) ? 3 : 0);
1284  $posy = (float) $marginwithfooter;
1285 
1286  // Option for footer background color (without freetext zone)
1287  if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1288  list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
1289  $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
1290  $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', '', $fill_color = array($r, $g, $b));
1291  $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
1292  }
1293 
1294  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1295  $pdf->SetAutoPageBreak(0, 0);
1296  } // Option for disable auto pagebreak
1297  if ($line) { // Free text
1298  $pdf->SetXY($dims['lm'], -$posy);
1299  if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1300  $pdf->MultiCell(0, 3, $line, 0, $align, 0);
1301  } else {
1302  $pdf->writeHTMLCell($dims['wk'] - $dims['lm'] - $dims['rm'], $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1303  }
1304  $posy -= $freetextheight;
1305  }
1306  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) {
1307  $pdf->SetAutoPageBreak(1, 0);
1308  } // Restore pagebreak
1309 
1310  $pdf->SetY(-$posy);
1311 
1312  // Option for hide all footer (page number will no hidden)
1313  if (!getDolGlobalInt('PDF_FOOTER_HIDDEN')) {
1314  // Hide footer line if footer background color is set
1315  if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1316  $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1317  }
1318 
1319  // Option for set top margin height of footer after freetext
1320  if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1321  $posy -= (float) getDolGlobalString('PDF_FOOTER_TOP_MARGIN');
1322  } else {
1323  $posy--;
1324  }
1325 
1326  if (!empty($line1)) {
1327  $pdf->SetFont('', 'B', 7);
1328  $pdf->SetXY($dims['lm'], -$posy);
1329  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line1, 0, 'C', 0);
1330  $posy -= 3;
1331  $pdf->SetFont('', '', 7);
1332  }
1333 
1334  if (!empty($line2)) {
1335  $pdf->SetFont('', 'B', 7);
1336  $pdf->SetXY($dims['lm'], -$posy);
1337  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line2, 0, 'C', 0);
1338  $posy -= 3;
1339  $pdf->SetFont('', '', 7);
1340  }
1341 
1342  if (!empty($line3)) {
1343  $pdf->SetXY($dims['lm'], -$posy);
1344  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line3, 0, 'C', 0);
1345  }
1346 
1347  if (!empty($line4)) {
1348  $posy -= 3;
1349  $pdf->SetXY($dims['lm'], -$posy);
1350  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line4, 0, 'C', 0);
1351  }
1352  }
1353  }
1354  }
1355 
1356  // Show page nb and apply correction for some font.
1357  $pdf->SetXY($dims['wk'] - $dims['rm'] - 18 - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_X', 0), -$posy - getDolGlobalInt('PDF_FOOTER_PAGE_NUMBER_Y', 0));
1358 
1359  $pagination = $pdf->PageNo().' / '.$pdf->getAliasNbPages();
1360  $fontRenderCorrection = 0;
1361  if (in_array(pdf_getPDFFont($outputlangs), array('freemono', 'DejaVuSans'))) {
1362  $fontRenderCorrection = 10;
1363  }
1364  $pdf->MultiCell(18 + $fontRenderCorrection, 2, $pagination, 0, 'R', 0);
1365 
1366  // Show Draft Watermark
1367  if (!empty($watermark)) {
1368  pdf_watermark($pdf, $outputlangs, $page_hauteur, $page_largeur, 'mm', $watermark);
1369  }
1370 
1371  return $marginwithfooter;
1372 }
1373 
1388 function pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
1389 {
1390  $linkedobjects = pdf_getLinkedObjects($object, $outputlangs);
1391  if (!empty($linkedobjects)) {
1392  foreach ($linkedobjects as $linkedobject) {
1393  $reftoshow = $linkedobject["ref_title"].' : '.$linkedobject["ref_value"];
1394  if (!empty($linkedobject["date_value"])) {
1395  $reftoshow .= ' / '.$linkedobject["date_value"];
1396  }
1397 
1398  $posy += 3;
1399  $pdf->SetXY($posx, $posy);
1400  $pdf->SetFont('', '', $default_font_size - 2);
1401  $pdf->MultiCell($w, $h, $reftoshow, '', $align);
1402  }
1403  }
1404 
1405  return $pdf->getY();
1406 }
1407 
1425 function pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref = 0, $hidedesc = 0, $issupplierline = 0, $align = 'J')
1426 {
1427  global $db, $conf, $langs, $hookmanager;
1428 
1429  $reshook = 0;
1430  $result = '';
1431  //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) ) )
1432  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
1433  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1434  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1435  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1436  }
1437  $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);
1438  $action = '';
1439  $reshook = $hookmanager->executeHooks('pdf_writelinedesc', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1440 
1441  if (!empty($hookmanager->resPrint)) {
1442  $result .= $hookmanager->resPrint;
1443  }
1444  }
1445  if (empty($reshook)) {
1446  $labelproductservice = pdf_getlinedesc($object, $i, $outputlangs, $hideref, $hidedesc, $issupplierline);
1447  $labelproductservice = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $labelproductservice, -1, $nbrep);
1448 
1449  //var_dump($labelproductservice);exit;
1450 
1451  // 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"
1452  // We make the reverse, so PDF generation has the real URL.
1453  $nbrep = 0;
1454  $labelproductservice = preg_replace('/(<img[^>]*src=")([^"]*)(&amp;)([^"]*")/', '\1\2&\4', $labelproductservice, -1, $nbrep);
1455 
1456  //var_dump($labelproductservice);exit;
1457 
1458  // Description
1459  $pdf->writeHTMLCell($w, $h, $posx, $posy, $outputlangs->convToOutputCharset($labelproductservice), 0, 1, false, true, $align, true);
1460  $result .= $labelproductservice;
1461  }
1462  return $result;
1463 }
1464 
1476 function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
1477 {
1478  global $db, $conf, $langs;
1479 
1480  $idprod = (!empty($object->lines[$i]->fk_product) ? $object->lines[$i]->fk_product : false);
1481  $label = (!empty($object->lines[$i]->label) ? $object->lines[$i]->label : (!empty($object->lines[$i]->product_label) ? $object->lines[$i]->product_label : ''));
1482  $product_barcode = (!empty($object->lines[$i]->product_barcode) ? $object->lines[$i]->product_barcode : "");
1483  $desc = (!empty($object->lines[$i]->desc) ? $object->lines[$i]->desc : (!empty($object->lines[$i]->description) ? $object->lines[$i]->description : ''));
1484  $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
1485  $note = (!empty($object->lines[$i]->note) ? $object->lines[$i]->note : '');
1486  $dbatch = (!empty($object->lines[$i]->detail_batch) ? $object->lines[$i]->detail_batch : false);
1487 
1488  if ($issupplierline) {
1489  include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
1490  $prodser = new ProductFournisseur($db);
1491  } else {
1492  include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
1493  $prodser = new Product($db);
1494 
1495  if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
1496  include_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
1497  }
1498  }
1499 
1500  if ($idprod) {
1501  $prodser->fetch($idprod);
1502  // If a predefined product and multilang and on other lang, we renamed label with label translated
1503  if (getDolGlobalInt('MAIN_MULTILANGS') && ($outputlangs->defaultlang != $langs->defaultlang)) {
1504  $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)
1505 
1506  // 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
1507  // ($textwasnotmodified is replaced with $textwasmodifiedorcompleted and we add completion).
1508 
1509  // Set label
1510  // 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.
1511  //var_dump($outputlangs->defaultlang.' - '.$langs->defaultlang.' - '.$label.' - '.$prodser->label);exit;
1512  $textwasnotmodified = ($label == $prodser->label);
1513  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1514  $label = $prodser->multilangs[$outputlangs->defaultlang]["label"];
1515  }
1516 
1517  // Set desc
1518  // Manage HTML entities description test because $prodser->description is store with htmlentities but $desc no
1519  $textwasnotmodified = false;
1520  if (!empty($desc) && dol_textishtml($desc) && !empty($prodser->description) && dol_textishtml($prodser->description)) {
1521  $textwasnotmodified = (strpos(dol_html_entity_decode($desc, ENT_QUOTES | ENT_HTML5), dol_html_entity_decode($prodser->description, ENT_QUOTES | ENT_HTML5)) !== false);
1522  } else {
1523  $textwasnotmodified = ($desc == $prodser->description);
1524  }
1525  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["description"])) {
1526  if ($textwasnotmodified) {
1527  $desc = str_replace($prodser->description, $prodser->multilangs[$outputlangs->defaultlang]["description"], $desc);
1528  } elseif ($translatealsoifmodified) {
1529  $desc = $prodser->multilangs[$outputlangs->defaultlang]["description"];
1530  }
1531  }
1532 
1533  // Set note
1534  $textwasnotmodified = ($note == $prodser->note_public);
1535  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["other"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1536  $note = $prodser->multilangs[$outputlangs->defaultlang]["other"];
1537  }
1538  }
1539  } 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
1540  $desc = str_replace('(DEPOSIT)', $outputlangs->trans('Deposit'), $desc);
1541  }
1542 
1543  if (!getDolGlobalString('PDF_HIDE_PRODUCT_LABEL_IN_SUPPLIER_LINES')) {
1544  // Description short of product line
1545  $libelleproduitservice = $label;
1546  if (!empty($libelleproduitservice) && getDolGlobalString('PDF_BOLD_PRODUCT_LABEL')) {
1547  // Adding <b> may convert the original string into a HTML string. So we have to first
1548  // convert \n into <br> we text is not already HTML.
1549  if (!dol_textishtml($libelleproduitservice)) {
1550  $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1551  }
1552  $libelleproduitservice = '<b>'.$libelleproduitservice.'</b>';
1553  }
1554  }
1555 
1556 
1557  // Add ref of subproducts
1558  if (getDolGlobalString('SHOW_SUBPRODUCT_REF_IN_PDF')) {
1559  $prodser->get_sousproduits_arbo();
1560  if (!empty($prodser->sousprods) && is_array($prodser->sousprods) && count($prodser->sousprods)) {
1561  $outputlangs->load('mrp');
1562  $tmparrayofsubproducts = reset($prodser->sousprods);
1563 
1564  $qtyText = null;
1565  if (isset($object->lines[$i]->qty) && !empty($object->lines[$i]->qty)) {
1566  $qtyText = $object->lines[$i]->qty;
1567  } elseif (isset($object->lines[$i]->qty_shipped) && !empty($object->lines[$i]->qty_shipped)) {
1568  $qtyText = $object->lines[$i]->qty;
1569  }
1570 
1571  if (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF')) {
1572  foreach ($tmparrayofsubproducts as $subprodval) {
1573  $libelleproduitservice = dol_concatdesc(
1574  dol_concatdesc($libelleproduitservice, " * ".$subprodval[3]),
1575  (!empty($qtyText) ?
1576  $outputlangs->trans('Qty').':'.$qtyText.' x '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1].'= '.$outputlangs->trans('QtyTot').':'.$subprodval[1] * $qtyText :
1577  $outputlangs->trans('Qty').' '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1])
1578  );
1579  }
1580  } else {
1581  foreach ($tmparrayofsubproducts as $subprodval) {
1582  $libelleproduitservice = dol_concatdesc(
1583  dol_concatdesc($libelleproduitservice, " * ".$subprodval[5].(($subprodval[5] && $subprodval[3]) ? ' - ' : '').$subprodval[3]),
1584  (!empty($qtyText) ?
1585  $outputlangs->trans('Qty').':'.$qtyText.' x '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1].'= '.$outputlangs->trans('QtyTot').':'.$subprodval[1] * $qtyText :
1586  $outputlangs->trans('Qty').' '.$outputlangs->trans('AssociatedProducts').':'.$subprodval[1])
1587  );
1588  }
1589  }
1590  }
1591  }
1592 
1593  if (isModEnabled('barcode') && getDolGlobalString('MAIN_GENERATE_DOCUMENTS_SHOW_PRODUCT_BARCODE') && !empty($product_barcode)) {
1594  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $outputlangs->trans("BarCode")." ".$product_barcode);
1595  }
1596 
1597  // Description long of product line
1598  if (!empty($desc) && ($desc != $label)) {
1599  if ($desc == '(CREDIT_NOTE)' && $object->lines[$i]->fk_remise_except) {
1600  $discount = new DiscountAbsolute($db);
1601  $discount->fetch($object->lines[$i]->fk_remise_except);
1602  $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1603  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromCreditNote", $sourceref);
1604  } elseif ($desc == '(DEPOSIT)' && $object->lines[$i]->fk_remise_except) {
1605  $discount = new DiscountAbsolute($db);
1606  $discount->fetch($object->lines[$i]->fk_remise_except);
1607  $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1608  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromDeposit", $sourceref);
1609  // Add date of deposit
1610  if (getDolGlobalString('INVOICE_ADD_DEPOSIT_DATE')) {
1611  $libelleproduitservice .= ' ('.dol_print_date($discount->datec, 'day', '', $outputlangs).')';
1612  }
1613  } elseif ($desc == '(EXCESS RECEIVED)' && $object->lines[$i]->fk_remise_except) {
1614  $discount = new DiscountAbsolute($db);
1615  $discount->fetch($object->lines[$i]->fk_remise_except);
1616  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessReceived", $discount->ref_facture_source);
1617  } elseif ($desc == '(EXCESS PAID)' && $object->lines[$i]->fk_remise_except) {
1618  $discount = new DiscountAbsolute($db);
1619  $discount->fetch($object->lines[$i]->fk_remise_except);
1620  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessPaid", $discount->ref_invoice_supplier_source);
1621  } else {
1622  if ($idprod) {
1623  // Check if description must be output
1624  if (!empty($object->element)) {
1625  $tmpkey = 'MAIN_DOCUMENTS_HIDE_DESCRIPTION_FOR_'.strtoupper($object->element);
1626  if (!empty($conf->global->$tmpkey)) {
1627  $hidedesc = 1;
1628  }
1629  }
1630  if (empty($hidedesc)) {
1631  if (getDolGlobalString('MAIN_DOCUMENTS_DESCRIPTION_FIRST')) {
1632  $libelleproduitservice = dol_concatdesc($desc, $libelleproduitservice);
1633  } else {
1634  if (getDolGlobalString('HIDE_LABEL_VARIANT_PDF') && $prodser->isVariant()) {
1635  $libelleproduitservice = $desc;
1636  } else {
1637  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1638  }
1639  }
1640  }
1641  } else {
1642  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1643  }
1644  }
1645  }
1646 
1647  // We add ref of product (and supplier ref if defined)
1648  $prefix_prodserv = "";
1649  $ref_prodserv = "";
1650  if (getDolGlobalString('PRODUCT_ADD_TYPE_IN_DOCUMENTS')) { // In standard mode, we do not show this
1651  if ($prodser->isService()) {
1652  $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service")." ";
1653  } else {
1654  $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Product")." ";
1655  }
1656  }
1657 
1658  if (empty($hideref)) {
1659  if ($issupplierline) {
1660  if (!getDolGlobalString('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES')) { // Common case
1661  $ref_prodserv = $prodser->ref; // Show local ref
1662  if ($ref_supplier) {
1663  $ref_prodserv .= ($prodser->ref ? ' (' : '').$outputlangs->transnoentitiesnoconv("SupplierRef").' '.$ref_supplier.($prodser->ref ? ')' : '');
1664  }
1665  } elseif (getDolGlobalInt('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES') == 1) {
1666  $ref_prodserv = $ref_supplier;
1667  } elseif (getDolGlobalInt('PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES') == 2) {
1668  $ref_prodserv = $ref_supplier.' ('.$outputlangs->transnoentitiesnoconv("InternalRef").' '.$prodser->ref.')';
1669  }
1670  } else {
1671  $ref_prodserv = $prodser->ref; // Show local ref only
1672 
1673  if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
1674  $productCustomerPriceStatic = new ProductCustomerPrice($db);
1675  $filter = array('fk_product' => $idprod, 'fk_soc' => $object->socid);
1676 
1677  $nbCustomerPrices = $productCustomerPriceStatic->fetchAll('', '', 1, 0, $filter);
1678 
1679  if ($nbCustomerPrices > 0) {
1680  $productCustomerPrice = $productCustomerPriceStatic->lines[0];
1681 
1682  if (!empty($productCustomerPrice->ref_customer)) {
1683  switch ($conf->global->PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE) {
1684  case 1:
1685  $ref_prodserv = $productCustomerPrice->ref_customer;
1686  break;
1687 
1688  case 2:
1689  $ref_prodserv = $productCustomerPrice->ref_customer . ' (' . $outputlangs->transnoentitiesnoconv('InternalRef') . ' ' . $ref_prodserv . ')';
1690  break;
1691 
1692  default:
1693  $ref_prodserv = $ref_prodserv . ' (' . $outputlangs->transnoentitiesnoconv('RefCustomer') . ' ' . $productCustomerPrice->ref_customer . ')';
1694  }
1695  }
1696  }
1697  }
1698  }
1699 
1700  if (!empty($libelleproduitservice) && !empty($ref_prodserv)) {
1701  $ref_prodserv .= " - ";
1702  }
1703  }
1704 
1705  if (!empty($ref_prodserv) && getDolGlobalString('PDF_BOLD_PRODUCT_REF_AND_PERIOD')) {
1706  if (!dol_textishtml($libelleproduitservice)) {
1707  $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1708  }
1709  $ref_prodserv = '<b>'.$ref_prodserv.'</b>';
1710  // $prefix_prodserv and $ref_prodser are not HTML var
1711  }
1712  $libelleproduitservice = $prefix_prodserv.$ref_prodserv.$libelleproduitservice;
1713 
1714  // Add an additional description for the category products
1715  if (getDolGlobalString('CATEGORY_ADD_DESC_INTO_DOC') && $idprod && isModEnabled('category')) {
1716  include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1717  $categstatic = new Categorie($db);
1718  // recovering the list of all the categories linked to product
1719  $tblcateg = $categstatic->containing($idprod, Categorie::TYPE_PRODUCT);
1720  foreach ($tblcateg as $cate) {
1721  // Adding the descriptions if they are filled
1722  $desccateg = $cate->description;
1723  if ($desccateg) {
1724  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desccateg);
1725  }
1726  }
1727  }
1728 
1729  if (!empty($object->lines[$i]->date_start) || !empty($object->lines[$i]->date_end)) {
1730  $format = 'day';
1731  $period = '';
1732  // Show duration if exists
1733  if ($object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1734  $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)).')';
1735  }
1736  if ($object->lines[$i]->date_start && !$object->lines[$i]->date_end) {
1737  $period = '('.$outputlangs->transnoentitiesnoconv('DateFrom', dol_print_date($object->lines[$i]->date_start, $format, false, $outputlangs)).')';
1738  }
1739  if (!$object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1740  $period = '('.$outputlangs->transnoentitiesnoconv('DateUntil', dol_print_date($object->lines[$i]->date_end, $format, false, $outputlangs)).')';
1741  }
1742  //print '>'.$outputlangs->charset_output.','.$period;
1743  if (getDolGlobalString('PDF_BOLD_PRODUCT_REF_AND_PERIOD')) {
1744  if (!dol_textishtml($libelleproduitservice)) {
1745  $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1746  }
1747  $libelleproduitservice .= '<br><b style="color:#333666;" ><em>'.$period.'</em></b>';
1748  } else {
1749  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $period);
1750  }
1751  //print $libelleproduitservice;
1752  }
1753 
1754  // Show information for lot
1755  if (!empty($dbatch)) {
1756  // $object is a shipment.
1757  //var_dump($object->lines[$i]->details_entrepot); // array from llx_expeditiondet (we can have several lines for one fk_origin_line)
1758  //var_dump($object->lines[$i]->detail_batch); // array from llx_expeditiondet_batch (each line with a lot is linked to llx_expeditiondet)
1759 
1760  include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
1761  include_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
1762  $tmpwarehouse = new Entrepot($db);
1763  $tmpproductbatch = new Productbatch($db);
1764 
1765  $format = 'day';
1766  foreach ($dbatch as $detail) {
1767  $dte = array();
1768  if ($detail->eatby) {
1769  $dte[] = $outputlangs->transnoentitiesnoconv('printEatby', dol_print_date($detail->eatby, $format, false, $outputlangs));
1770  }
1771  if ($detail->sellby) {
1772  $dte[] = $outputlangs->transnoentitiesnoconv('printSellby', dol_print_date($detail->sellby, $format, false, $outputlangs));
1773  }
1774  if ($detail->batch) {
1775  $dte[] = $outputlangs->transnoentitiesnoconv('printBatch', $detail->batch);
1776  }
1777  $dte[] = $outputlangs->transnoentitiesnoconv('printQty', $detail->qty);
1778 
1779  // Add also info of planned warehouse for lot
1780  if ($object->element == 'shipping' && $detail->fk_origin_stock > 0 && getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1781  $resproductbatch = $tmpproductbatch->fetch($detail->fk_origin_stock);
1782  if ($resproductbatch > 0) {
1783  $reswarehouse = $tmpwarehouse->fetch($tmpproductbatch->warehouseid);
1784  if ($reswarehouse > 0) {
1785  $dte[] = $tmpwarehouse->ref;
1786  }
1787  }
1788  }
1789 
1790  $libelleproduitservice .= "__N__ ".implode(" - ", $dte);
1791  }
1792  } else {
1793  if (getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1794  // TODO Show warehouse for shipment line without batch
1795  }
1796  }
1797 
1798  // Now we convert \n into br
1799  if (dol_textishtml($libelleproduitservice)) {
1800  $libelleproduitservice = preg_replace('/__N__/', '<br>', $libelleproduitservice);
1801  } else {
1802  $libelleproduitservice = preg_replace('/__N__/', "\n", $libelleproduitservice);
1803  }
1804  $libelleproduitservice = dol_htmlentitiesbr($libelleproduitservice, 1);
1805 
1806  return $libelleproduitservice;
1807 }
1808 
1818 function pdf_getlinenum($object, $i, $outputlangs, $hidedetails = 0)
1819 {
1820  global $hookmanager;
1821 
1822  $reshook = 0;
1823  $result = '';
1824  //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) ) )
1825  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
1826  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1827  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1828  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1829  }
1830  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1831  $action = '';
1832  $reshook = $hookmanager->executeHooks('pdf_getlinenum', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1833  $result .= $hookmanager->resPrint;
1834  }
1835  if (empty($reshook)) {
1836  $result .= dol_htmlentitiesbr($object->lines[$i]->num);
1837  }
1838  return $result;
1839 }
1840 
1841 
1851 function pdf_getlineref($object, $i, $outputlangs, $hidedetails = 0)
1852 {
1853  global $hookmanager;
1854 
1855  $reshook = 0;
1856  $result = '';
1857  //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) ) )
1858  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
1859  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1860  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1861  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1862  }
1863  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1864  $action = '';
1865  $reshook = $hookmanager->executeHooks('pdf_getlineref', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1866  $result .= $hookmanager->resPrint;
1867  }
1868  if (empty($reshook)) {
1869  $result .= dol_htmlentitiesbr($object->lines[$i]->product_ref);
1870  }
1871  return $result;
1872 }
1873 
1883 function pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails = 0)
1884 {
1885  global $hookmanager;
1886 
1887  $reshook = 0;
1888  $result = '';
1889  //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) ) )
1890  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
1891  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1892  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1893  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1894  }
1895  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1896  $action = '';
1897  $reshook = $hookmanager->executeHooks('pdf_getlineref_supplier', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1898  $result .= $hookmanager->resPrint;
1899  }
1900  if (empty($reshook)) {
1901  $result .= dol_htmlentitiesbr($object->lines[$i]->ref_supplier);
1902  }
1903  return $result;
1904 }
1905 
1915 function pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails = 0)
1916 {
1917  global $conf, $hookmanager, $mysoc;
1918 
1919  $result = '';
1920  $reshook = 0;
1921  //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) ) )
1922  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
1923  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1924  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1925  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1926  }
1927  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1928  $action = '';
1929  $reshook = $hookmanager->executeHooks('pdf_getlinevatrate', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1930 
1931  if (!empty($hookmanager->resPrint)) {
1932  $result .= $hookmanager->resPrint;
1933  }
1934  }
1935  if (empty($reshook)) {
1936  if (empty($hidedetails) || $hidedetails > 1) {
1937  $tmpresult = '';
1938 
1939  $tmpresult .= vatrate($object->lines[$i]->tva_tx, 0, $object->lines[$i]->info_bits, -1);
1940  if (!getDolGlobalString('MAIN_PDF_MAIN_HIDE_SECOND_TAX')) {
1941  if ($object->lines[$i]->total_localtax1 != 0) {
1942  if (preg_replace('/[\s0%]/', '', $tmpresult)) {
1943  $tmpresult .= '/';
1944  } else {
1945  $tmpresult = '';
1946  }
1947  $tmpresult .= vatrate(abs($object->lines[$i]->localtax1_tx), 0);
1948  }
1949  }
1950  if (!getDolGlobalString('MAIN_PDF_MAIN_HIDE_THIRD_TAX')) {
1951  if ($object->lines[$i]->total_localtax2 != 0) {
1952  if (preg_replace('/[\s0%]/', '', $tmpresult)) {
1953  $tmpresult .= '/';
1954  } else {
1955  $tmpresult = '';
1956  }
1957  $tmpresult .= vatrate(abs($object->lines[$i]->localtax2_tx), 0);
1958  }
1959  }
1960  $tmpresult .= '%';
1961 
1962  $result .= $tmpresult;
1963  }
1964  }
1965  return $result;
1966 }
1967 
1977 function pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails = 0)
1978 {
1979  global $conf, $hookmanager;
1980 
1981  $sign = 1;
1982  if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
1983  $sign = -1;
1984  }
1985 
1986  $result = '';
1987  $reshook = 0;
1988  //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) ) )
1989  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
1990  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1991  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1992  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1993  }
1994  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1995  $action = '';
1996  $reshook = $hookmanager->executeHooks('pdf_getlineupexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1997 
1998  if (!empty($hookmanager->resPrint)) {
1999  $result .= $hookmanager->resPrint;
2000  }
2001  }
2002  if (empty($reshook)) {
2003  if (empty($hidedetails) || $hidedetails > 1) {
2004  $subprice = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice);
2005  $result .= price($sign * $subprice, 0, $outputlangs);
2006  }
2007  }
2008  return $result;
2009 }
2010 
2020 function pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails = 0)
2021 {
2022  global $hookmanager, $conf;
2023 
2024  $sign = 1;
2025  if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2026  $sign = -1;
2027  }
2028 
2029  $result = '';
2030  $reshook = 0;
2031  //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) ) )
2032  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
2033  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2034  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2035  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2036  }
2037  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2038  $action = '';
2039  $reshook = $hookmanager->executeHooks('pdf_getlineupwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2040 
2041  if (!empty($hookmanager->resPrint)) {
2042  $result .= $hookmanager->resPrint;
2043  }
2044  }
2045  if (empty($reshook)) {
2046  if (empty($hidedetails) || $hidedetails > 1) {
2047  $result .= price($sign * (($object->lines[$i]->subprice) + ($object->lines[$i]->subprice) * ($object->lines[$i]->tva_tx) / 100), 0, $outputlangs);
2048  }
2049  }
2050  return $result;
2051 }
2052 
2062 function pdf_getlineqty($object, $i, $outputlangs, $hidedetails = 0)
2063 {
2064  global $hookmanager;
2065 
2066  $result = '';
2067  $reshook = 0;
2068  //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) ) )
2069  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
2070  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2071  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2072  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2073  }
2074  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2075  $action = '';
2076  $reshook = $hookmanager->executeHooks('pdf_getlineqty', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2077 
2078  if (!empty($hookmanager->resPrint)) {
2079  $result = $hookmanager->resPrint;
2080  }
2081  }
2082  if (empty($reshook)) {
2083  if ($object->lines[$i]->special_code == 3) {
2084  return '';
2085  }
2086  if (empty($hidedetails) || $hidedetails > 1) {
2087  $result .= $object->lines[$i]->qty;
2088  }
2089  }
2090  return $result;
2091 }
2092 
2102 function pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails = 0)
2103 {
2104  global $hookmanager;
2105 
2106  $reshook = 0;
2107  $result = '';
2108  //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2109  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
2110  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2111  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2112  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2113  }
2114  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2115  $action = '';
2116  $reshook = $hookmanager->executeHooks('pdf_getlineqty_asked', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2117 
2118  if (!empty($hookmanager->resPrint)) {
2119  $result .= $hookmanager->resPrint;
2120  }
2121  }
2122  if (empty($reshook)) {
2123  if ($object->lines[$i]->special_code == 3) {
2124  return '';
2125  }
2126  if (empty($hidedetails) || $hidedetails > 1) {
2127  $result .= $object->lines[$i]->qty_asked;
2128  }
2129  }
2130  return $result;
2131 }
2132 
2142 function pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails = 0)
2143 {
2144  global $hookmanager;
2145 
2146  $reshook = 0;
2147  $result = '';
2148  //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) ) )
2149  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
2150  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2151  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2152  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2153  }
2154  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2155  $action = '';
2156  $reshook = $hookmanager->executeHooks('pdf_getlineqty_shipped', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2157 
2158  if (!empty($hookmanager->resPrint)) {
2159  $result .= $hookmanager->resPrint;
2160  }
2161  }
2162  if (empty($reshook)) {
2163  if ($object->lines[$i]->special_code == 3) {
2164  return '';
2165  }
2166  if (empty($hidedetails) || $hidedetails > 1) {
2167  $result .= $object->lines[$i]->qty_shipped;
2168  }
2169  }
2170  return $result;
2171 }
2172 
2182 function pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails = 0)
2183 {
2184  global $hookmanager;
2185 
2186  $reshook = 0;
2187  $result = '';
2188  //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) ) )
2189  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
2190  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2191  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2192  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2193  }
2194  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2195  $action = '';
2196  $reshook = $hookmanager->executeHooks('pdf_getlineqty_keeptoship', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2197 
2198  if (!empty($hookmanager->resPrint)) {
2199  $result .= $hookmanager->resPrint;
2200  }
2201  }
2202  if (empty($reshook)) {
2203  if ($object->lines[$i]->special_code == 3) {
2204  return '';
2205  }
2206  if (empty($hidedetails) || $hidedetails > 1) {
2207  $result .= ($object->lines[$i]->qty_asked - $object->lines[$i]->qty_shipped);
2208  }
2209  }
2210  return $result;
2211 }
2212 
2222 function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0)
2223 {
2224  global $hookmanager, $langs;
2225 
2226  $reshook = 0;
2227  $result = '';
2228  //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) ) )
2229  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
2230  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2231  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2232  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2233  }
2234  $parameters = array(
2235  'i' => $i,
2236  'outputlangs' => $outputlangs,
2237  'hidedetails' => $hidedetails,
2238  'special_code' => $special_code
2239  );
2240  $action = '';
2241  $reshook = $hookmanager->executeHooks('pdf_getlineunit', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2242 
2243  if (!empty($hookmanager->resPrint)) {
2244  $result .= $hookmanager->resPrint;
2245  }
2246  }
2247  if (empty($reshook)) {
2248  if (empty($hidedetails) || $hidedetails > 1) {
2249  $result .= $langs->transnoentitiesnoconv($object->lines[$i]->getLabelOfUnit('short'));
2250  }
2251  }
2252  return $result;
2253 }
2254 
2255 
2265 function pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails = 0)
2266 {
2267  global $hookmanager;
2268 
2269  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
2270 
2271  $reshook = 0;
2272  $result = '';
2273  //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) ) )
2274  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
2275  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2276  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2277  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2278  }
2279  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2280  $action = '';
2281  $reshook = $hookmanager->executeHooks('pdf_getlineremisepercent', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2282 
2283  if (!empty($hookmanager->resPrint)) {
2284  $result .= $hookmanager->resPrint;
2285  }
2286  }
2287  if (empty($reshook)) {
2288  if ($object->lines[$i]->special_code == 3) {
2289  return '';
2290  }
2291  if (empty($hidedetails) || $hidedetails > 1) {
2292  $result .= dol_print_reduction($object->lines[$i]->remise_percent, $outputlangs);
2293  }
2294  }
2295  return $result;
2296 }
2297 
2308 function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = null)
2309 {
2310  if (empty($hookmanager)) {
2311  global $hookmanager;
2312  }
2313  global $conf;
2314 
2315  $reshook = 0;
2316  $result = '';
2317  //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) ) )
2318  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
2319  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2320  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2321  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2322  }
2323  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2324  $action = '';
2325  $reshook = $hookmanager->executeHooks('pdf_getlineprogress', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2326 
2327  if (!empty($hookmanager->resPrint)) {
2328  return $hookmanager->resPrint;
2329  }
2330  }
2331  if (empty($reshook)) {
2332  if ($object->lines[$i]->special_code == 3) {
2333  return '';
2334  }
2335  if (empty($hidedetails) || $hidedetails > 1) {
2336  if (getDolGlobalString('SITUATION_DISPLAY_DIFF_ON_PDF')) {
2337  $prev_progress = 0;
2338  if (method_exists($object->lines[$i], 'get_prev_progress')) {
2339  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2340  }
2341  $result = round($object->lines[$i]->situation_percent - $prev_progress, 1).'%';
2342  } else {
2343  $result = round($object->lines[$i]->situation_percent, 1).'%';
2344  }
2345  }
2346  }
2347  return $result;
2348 }
2349 
2359 function pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails = 0)
2360 {
2361  global $conf, $hookmanager;
2362 
2363  $sign = 1;
2364  if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2365  $sign = -1;
2366  }
2367 
2368  $reshook = 0;
2369  $result = '';
2370  //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) ) )
2371  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
2372  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2373  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2374  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2375  }
2376  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code, 'sign' => $sign);
2377  $action = '';
2378  $reshook = $hookmanager->executeHooks('pdf_getlinetotalexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2379 
2380  if (!empty($hookmanager->resPrint)) {
2381  $result .= $hookmanager->resPrint;
2382  }
2383  }
2384  if (empty($reshook)) {
2385  if (!empty($object->lines[$i]) && $object->lines[$i]->special_code == 3) {
2386  $result .= $outputlangs->transnoentities("Option");
2387  } elseif (empty($hidedetails) || $hidedetails > 1) {
2388  $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
2389  if (!empty($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
2390  // TODO Remove this. The total should be saved correctly in database instead of being modified here.
2391  $prev_progress = 0;
2392  $progress = 1;
2393  if (method_exists($object->lines[$i], 'get_prev_progress')) {
2394  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2395  $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
2396  }
2397  $result .= price($sign * ($total_ht / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
2398  } else {
2399  $result .= price($sign * $total_ht, 0, $outputlangs);
2400  }
2401  }
2402  }
2403  return $result;
2404 }
2405 
2415 function pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails = 0)
2416 {
2417  global $hookmanager, $conf;
2418 
2419  $sign = 1;
2420  if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2421  $sign = -1;
2422  }
2423 
2424  $reshook = 0;
2425  $result = '';
2426  //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) ) )
2427  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
2428  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
2429  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2430  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2431  }
2432  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2433  $action = '';
2434  $reshook = $hookmanager->executeHooks('pdf_getlinetotalwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2435 
2436  if (!empty($hookmanager->resPrint)) {
2437  $result .= $hookmanager->resPrint;
2438  }
2439  }
2440  if (empty($reshook)) {
2441  if ($object->lines[$i]->special_code == 3) {
2442  $result .= $outputlangs->transnoentities("Option");
2443  } elseif (empty($hidedetails) || $hidedetails > 1) {
2444  $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ttc : $object->lines[$i]->total_ttc);
2445  if ($object->lines[$i]->situation_percent > 0) {
2446  // TODO Remove this. The total should be saved correctly in database instead of being modified here.
2447  $prev_progress = 0;
2448  $progress = 1;
2449  if (method_exists($object->lines[$i], 'get_prev_progress')) {
2450  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2451  $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
2452  }
2453  $result .= price($sign * ($total_ttc / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
2454  } else {
2455  $result .= price($sign * $total_ttc, 0, $outputlangs);
2456  }
2457  }
2458  }
2459  return $result;
2460 }
2461 
2470 function pdf_getLinkedObjects(&$object, $outputlangs)
2471 {
2472  global $db, $hookmanager;
2473 
2474  $linkedobjects = array();
2475 
2476  $object->fetchObjectLinked();
2477 
2478  foreach ($object->linkedObjects as $objecttype => $objects) {
2479  if ($objecttype == 'facture') {
2480  // 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.
2481  } elseif ($objecttype == 'propal' || $objecttype == 'supplier_proposal') {
2482  $outputlangs->load('propal');
2483 
2484  foreach ($objects as $elementobject) {
2485  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefProposal");
2486  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2487  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DatePropal");
2488  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2489  }
2490  } elseif ($objecttype == 'commande' || $objecttype == 'supplier_order') {
2491  $outputlangs->load('orders');
2492 
2493  if (count($objects) > 1 && count($objects) <= (getDolGlobalInt("MAXREFONDOC") ? getDolGlobalInt("MAXREFONDOC") : 10)) {
2494  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("RefOrder").' :');
2495  foreach ($objects as $elementobject) {
2496  $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.')').' ');
2497  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("OrderDate").' : '.dol_print_date($elementobject->date, 'day', '', $outputlangs));
2498  }
2499  } elseif (count($objects) == 1) {
2500  $elementobject = array_shift($objects);
2501  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder");
2502  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref).(!empty($elementobject->ref_client) ? ' ('.$elementobject->ref_client.')' : '').(!empty($elementobject->ref_supplier) ? ' ('.$elementobject->ref_supplier.')' : '');
2503  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("OrderDate");
2504  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2505  }
2506  } elseif ($objecttype == 'contrat') {
2507  $outputlangs->load('contracts');
2508  foreach ($objects as $elementobject) {
2509  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefContract");
2510  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2511  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DateContract");
2512  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date_contrat, 'day', '', $outputlangs);
2513  }
2514  } elseif ($objecttype == 'fichinter') {
2515  $outputlangs->load('interventions');
2516  foreach ($objects as $elementobject) {
2517  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("InterRef");
2518  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2519  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("InterDate");
2520  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->datec, 'day', '', $outputlangs);
2521  }
2522  } elseif ($objecttype == 'shipping') {
2523  $outputlangs->loadLangs(array("orders", "sendings"));
2524 
2525  if (count($objects) > 1) {
2526  $order = null;
2527  if (empty($object->linkedObjects['commande']) && $object->element != 'commande') {
2528  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending").' :');
2529  } else {
2530  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("RefSending").' :');
2531  }
2532  // We concat this record info into fields xxx_value. title is overwrote.
2533  foreach ($objects as $elementobject) {
2534  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
2535  $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2536  if (!empty($elementobject->linkedObjectsIds['commande'])) {
2537  include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2538  $order = new Commande($db);
2539  $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2540  if ($ret < 1) {
2541  $order = null;
2542  }
2543  }
2544  }
2545 
2546  if (! is_object($order)) {
2547  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities($elementobject->ref));
2548  } else {
2549  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : ''));
2550  $object->note_public = dol_concatdesc($object->note_public, ' / '.$outputlangs->transnoentities($elementobject->ref));
2551  }
2552  }
2553  } elseif (count($objects) == 1) {
2554  $elementobject = array_shift($objects);
2555  $order = null;
2556  // We concat this record info into fields xxx_value. title is overwrote.
2557  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
2558  $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2559  if (!empty($elementobject->linkedObjectsIds['commande'])) {
2560  include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2561  $order = new Commande($db);
2562  $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2563  if ($ret < 1) {
2564  $order = null;
2565  }
2566  }
2567  }
2568 
2569  if (! is_object($order)) {
2570  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefSending");
2571  if (empty($linkedobjects[$objecttype]['ref_value'])) {
2572  $linkedobjects[$objecttype]['ref_value'] = '';
2573  } else {
2574  $linkedobjects[$objecttype]['ref_value'] .= ' / ';
2575  }
2576  $linkedobjects[$objecttype]['ref_value'] .= $outputlangs->transnoentities($elementobject->ref);
2577  $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
2578  } else {
2579  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending");
2580  if (empty($linkedobjects[$objecttype]['ref_value'])) {
2581  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
2582  }
2583  $linkedobjects[$objecttype]['ref_value'] .= ' / '.$outputlangs->transnoentities($elementobject->ref);
2584  $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
2585  }
2586  }
2587  }
2588  }
2589 
2590  // For add external linked objects
2591  if (is_object($hookmanager)) {
2592  $parameters = array('linkedobjects' => $linkedobjects, 'outputlangs' => $outputlangs);
2593  $action = '';
2594  $hookmanager->executeHooks('pdf_getLinkedObjects', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2595  if (!empty($hookmanager->resArray)) {
2596  $linkedobjects = $hookmanager->resArray;
2597  }
2598  }
2599 
2600  return $linkedobjects;
2601 }
2602 
2610 function pdf_getSizeForImage($realpath)
2611 {
2612  global $conf;
2613 
2614  $maxwidth = getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_WIDTH', 20);
2615  $maxheight = getDolGlobalInt('MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT', 32);
2616  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
2617  $tmp = dol_getImageSize($realpath);
2618  $width = 0;
2619  $height = 0;
2620  if ($tmp['height']) {
2621  $width = (int) round($maxheight * $tmp['width'] / $tmp['height']); // I try to use maxheight
2622  if ($width > $maxwidth) { // Pb with maxheight, so i use maxwidth
2623  $width = $maxwidth;
2624  $height = (int) round($maxwidth * $tmp['height'] / $tmp['width']);
2625  } else { // No pb with maxheight
2626  $height = $maxheight;
2627  }
2628  }
2629  return array('width' => $width, 'height' => $height);
2630 }
2631 
2641 function pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails = 0)
2642 {
2643  global $conf, $hookmanager;
2644 
2645  $sign = 1;
2646  if (isset($object->type) && $object->type == 2 && getDolGlobalString('INVOICE_POSITIVE_CREDIT_NOTE')) {
2647  $sign = -1;
2648  }
2649  if ($object->lines[$i]->special_code == 3) {
2650  return $outputlangs->transnoentities("Option");
2651  } else {
2652  if (is_object($hookmanager)) {
2653  $special_code = $object->lines[$i]->special_code;
2654  if (!empty($object->lines[$i]->fk_parent_line)) {
2655  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2656  }
2657 
2658  $parameters = array(
2659  'i' => $i,
2660  'outputlangs' => $outputlangs,
2661  'hidedetails' => $hidedetails,
2662  'special_code' => $special_code
2663  );
2664 
2665  $action = '';
2666 
2667  if ($hookmanager->executeHooks('getlinetotalremise', $parameters, $object, $action) > 0) { // Note that $action and $object may have been modified by some hooks
2668  if (isset($hookmanager->resArray['linetotalremise'])) {
2669  return $hookmanager->resArray['linetotalremise'];
2670  } else {
2671  return (float) $hookmanager->resPrint; // For backward compatibility
2672  }
2673  }
2674  }
2675 
2676  if (empty($hidedetails) || $hidedetails > 1) {
2677  return $sign * (($object->lines[$i]->subprice * (float) $object->lines[$i]->qty) - $object->lines[$i]->total_ht);
2678  }
2679  }
2680  return 0;
2681 }
if($user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition: card.php:58
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='', $dbtouse=null, $withregion=0, $outputlangs=null, $entconv=1)
Return state translated from an id.
getFormeJuridiqueLabel($code)
Return the name translated of juridical status.
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:744
dol_print_reduction($reduction, $langs)
Returns formatted reduction.
dol_getDefaultFormat(Translate $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.
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 dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
dol_getImageSize($file, $url=false)
Return size of image file on disk (Supported extensions are gif, jpg, png, bmp and webp)
Definition: images.lib.php:144
div float
Buy price without taxes.
Definition: style.css.php:959
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:2610
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:1425
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition: pdf.lib.php:2359
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:1476
pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails=0)
Return line total amount discount.
Definition: pdf.lib.php:2641
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition: pdf.lib.php:290
pdf_getFormat(Translate $outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition: pdf.lib.php:86
pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails=0)
Return line quantity shipped.
Definition: pdf.lib.php:2142
pdf_getlinenum($object, $i, $outputlangs, $hidedetails=0)
Return line num.
Definition: pdf.lib.php:1818
pdf_getEncryption($pathoffile)
Return if pdf file is protected/encrypted.
Definition: pdf.lib.php:236
pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price including tax.
Definition: pdf.lib.php:2020
pdf_getLinkedObjects(&$object, $outputlangs)
Return linked objects to use for document generation.
Definition: pdf.lib.php:2470
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition: pdf.lib.php:315
pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails=0)
Return line ref_supplier.
Definition: pdf.lib.php:1883
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition: pdf.lib.php:2415
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:1014
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition: pdf.lib.php:1977
pdf_getlineprogress($object, $i, $outputlangs, $hidedetails=0, $hookmanager=null)
Return line percent.
Definition: pdf.lib.php:2308
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition: pdf.lib.php:1915
pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition: pdf.lib.php:340
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:727
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition: pdf.lib.php:1388
pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank information for PDF generation.
Definition: pdf.lib.php:837
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition: pdf.lib.php:267
pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails=0)
Return line keep to ship quantity.
Definition: pdf.lib.php:2182
pdf_getlineref($object, $i, $outputlangs, $hidedetails=0)
Return line product ref.
Definition: pdf.lib.php:1851
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formatted for output on documents.
Definition: pdf.lib.php:436
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0)
Return line unit.
Definition: pdf.lib.php:2222
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition: pdf.lib.php:2265
pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails=0)
Return line quantity asked.
Definition: pdf.lib.php:2102
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition: pdf.lib.php:2062
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:763
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:388
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition: pdf.lib.php:783