dolibarr  17.0.4
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  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program. If not, see <https://www.gnu.org/licenses/>.
29  * or see https://www.gnu.org/
30  */
31 
38 include_once DOL_DOCUMENT_ROOT.'/core/lib/signature.lib.php';
39 
40 
47 {
48  global $langs, $conf, $user;
49 
50  $h = 0;
51  $head = array();
52 
53  $head[$h][0] = DOL_URL_ROOT.'/admin/pdf.php';
54  $head[$h][1] = $langs->trans("Parameters");
55  $head[$h][2] = 'general';
56  $h++;
57 
58  // Show more tabs from modules
59  // Entries must be declared in modules descriptor with line
60  // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
61  // $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab
62  complete_head_from_modules($conf, $langs, null, $head, $h, 'pdf_admin');
63 
64  if (isModEnabled("propal")) {
65  $head[$h][0] = DOL_URL_ROOT.'/admin/pdf_other.php';
66  $head[$h][1] = $langs->trans("Other");
67  $head[$h][2] = 'other';
68  $h++;
69  }
70 
71  complete_head_from_modules($conf, $langs, null, $head, $h, 'pdf_admin', 'remove');
72 
73  return $head;
74 }
75 
76 
84 function pdf_getFormat(Translate $outputlangs = null, $mode = 'setup')
85 {
86  global $conf, $db, $langs;
87 
88  dol_syslog("pdf_getFormat Get paper format with mode=".$mode." MAIN_PDF_FORMAT=".(empty($conf->global->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'));
89 
90  // Default value if setup was not done and/or entry into c_paper_format not defined
91  $width = 210;
92  $height = 297;
93  $unit = 'mm';
94 
95  if ($mode == 'auto' || empty($conf->global->MAIN_PDF_FORMAT) || $conf->global->MAIN_PDF_FORMAT == 'auto') {
96  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
97  $pdfformat = dol_getDefaultFormat($outputlangs);
98  } else {
99  $pdfformat = $conf->global->MAIN_PDF_FORMAT;
100  }
101 
102  $sql = "SELECT code, label, width, height, unit FROM ".MAIN_DB_PREFIX."c_paper_format";
103  $sql .= " WHERE code = '".$db->escape($pdfformat)."'";
104  $resql = $db->query($sql);
105  if ($resql) {
106  $obj = $db->fetch_object($resql);
107  if ($obj) {
108  $width = (int) $obj->width;
109  $height = (int) $obj->height;
110  $unit = $obj->unit;
111  }
112  }
113 
114  //print "pdfformat=".$pdfformat." width=".$width." height=".$height." unit=".$unit;
115  return array('width'=>$width, 'height'=>$height, 'unit'=>$unit);
116 }
117 
126 function pdf_getInstance($format = '', $metric = 'mm', $pagetype = 'P')
127 {
128  global $conf;
129 
130  // Define constant for TCPDF
131  if (!defined('K_TCPDF_EXTERNAL_CONFIG')) {
132  define('K_TCPDF_EXTERNAL_CONFIG', 1); // this avoid using tcpdf_config file
133  define('K_PATH_CACHE', DOL_DATA_ROOT.'/admin/temp/');
134  define('K_PATH_URL_CACHE', DOL_DATA_ROOT.'/admin/temp/');
135  dol_mkdir(K_PATH_CACHE);
136  define('K_BLANK_IMAGE', '_blank.png');
137  define('PDF_PAGE_FORMAT', 'A4');
138  define('PDF_PAGE_ORIENTATION', 'P');
139  define('PDF_CREATOR', 'TCPDF');
140  define('PDF_AUTHOR', 'TCPDF');
141  define('PDF_HEADER_TITLE', 'TCPDF Example');
142  define('PDF_HEADER_STRING', "by Dolibarr ERP CRM");
143  define('PDF_UNIT', 'mm');
144  define('PDF_MARGIN_HEADER', 5);
145  define('PDF_MARGIN_FOOTER', 10);
146  define('PDF_MARGIN_TOP', 27);
147  define('PDF_MARGIN_BOTTOM', 25);
148  define('PDF_MARGIN_LEFT', 15);
149  define('PDF_MARGIN_RIGHT', 15);
150  define('PDF_FONT_NAME_MAIN', 'helvetica');
151  define('PDF_FONT_SIZE_MAIN', 10);
152  define('PDF_FONT_NAME_DATA', 'helvetica');
153  define('PDF_FONT_SIZE_DATA', 8);
154  define('PDF_FONT_MONOSPACED', 'courier');
155  define('PDF_IMAGE_SCALE_RATIO', 1.25);
156  define('HEAD_MAGNIFICATION', 1.1);
157  define('K_CELL_HEIGHT_RATIO', 1.25);
158  define('K_TITLE_MAGNIFICATION', 1.3);
159  define('K_SMALL_RATIO', 2 / 3);
160  define('K_THAI_TOPCHARS', true);
161  define('K_TCPDF_CALLS_IN_HTML', true);
162  if (!empty($conf->global->TCPDF_THROW_ERRORS_INSTEAD_OF_DIE)) {
163  define('K_TCPDF_THROW_EXCEPTION_ERROR', true);
164  } else {
165  define('K_TCPDF_THROW_EXCEPTION_ERROR', false);
166  }
167  }
168 
169  // Load TCPDF
170  require_once TCPDF_PATH.'tcpdf.php';
171 
172  // We need to instantiate tcpdi object (instead of tcpdf) to use merging features. But we can disable it (this will break all merge features).
173  if (empty($conf->global->MAIN_DISABLE_TCPDI)) {
174  require_once TCPDI_PATH.'tcpdi.php';
175  }
176 
177  //$arrayformat=pdf_getFormat();
178  //$format=array($arrayformat['width'],$arrayformat['height']);
179  //$metric=$arrayformat['unit'];
180 
181  $pdfa = false; // PDF-1.3
182  if (!empty($conf->global->PDF_USE_A)) {
183  $pdfa = $conf->global->PDF_USE_A; // PDF/A-1 ou PDF/A-3
184  }
185 
186  if (class_exists('TCPDI')) {
187  $pdf = new TCPDI($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
188  } else {
189  $pdf = new TCPDF($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
190  }
191 
192  // Protection and encryption of pdf
193  if (!empty($conf->global->PDF_SECURITY_ENCRYPTION)) {
194  /* Permission supported by TCPDF
195  - print : Print the document;
196  - modify : Modify the contents of the document by operations other than those controlled by 'fill-forms', 'extract' and 'assemble';
197  - copy : Copy or otherwise extract text and graphics from the document;
198  - annot-forms : Add or modify text annotations, fill in interactive form fields, and, if 'modify' is also set, create or modify interactive form fields (including signature fields);
199  - fill-forms : Fill in existing interactive form fields (including signature fields), even if 'annot-forms' is not specified;
200  - extract : Extract text and graphics (in support of accessibility to users with disabilities or for other purposes);
201  - assemble : Assemble the document (insert, rotate, or delete pages and create bookmarks or thumbnail images), even if 'modify' is not set;
202  - print-high : Print the document to a representation from which a faithful digital copy of the PDF content could be generated. When this is not set, printing is limited to a low-level representation of the appearance, possibly of degraded quality.
203  - owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions.
204  */
205 
206  // For TCPDF, we specify permission we want to block
207  $pdfrights = (!empty($conf->global->PDF_SECURITY_ENCRYPTION_RIGHTS) ?json_decode($conf->global->PDF_SECURITY_ENCRYPTION_RIGHTS, true) : array('modify', 'copy')); // Json format in llx_const
208 
209  // Password for the end user
210  $pdfuserpass = (!empty($conf->global->PDF_SECURITY_ENCRYPTION_USERPASS) ? $conf->global->PDF_SECURITY_ENCRYPTION_USERPASS : '');
211 
212  // Password of the owner, created randomly if not defined
213  $pdfownerpass = (!empty($conf->global->PDF_SECURITY_ENCRYPTION_OWNERPASS) ? $conf->global->PDF_SECURITY_ENCRYPTION_OWNERPASS : null);
214 
215  // For encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit
216  $encstrength = (!empty($conf->global->PDF_SECURITY_ENCRYPTION_STRENGTH) ? $conf->global->PDF_SECURITY_ENCRYPTION_STRENGTH : 0);
217 
218  // Array of recipients containing public-key certificates ('c') and permissions ('p').
219  // For example: array(array('c' => 'file://../examples/data/cert/tcpdf.crt', 'p' => array('print')))
220  $pubkeys = (!empty($conf->global->PDF_SECURITY_ENCRYPTION_PUBKEYS) ?json_decode($conf->global->PDF_SECURITY_ENCRYPTION_PUBKEYS, true) : null); // Json format in llx_const
221 
222  $pdf->SetProtection($pdfrights, $pdfuserpass, $pdfownerpass, $encstrength, $pubkeys);
223  }
224 
225  return $pdf;
226 }
227 
234 function pdf_getEncryption($pathoffile)
235 {
236  require_once TCPDF_PATH.'tcpdf_parser.php';
237 
238  $isencrypted = false;
239 
240  $content = file_get_contents($pathoffile);
241 
242  //ob_start();
243  @($parser = new \TCPDF_PARSER(ltrim($content)));
244  list($xref, $data) = $parser->getParsedData();
245  unset($parser);
246  //ob_end_clean();
247 
248  if (isset($xref['trailer']['encrypt'])) {
249  $isencrypted = true; // Secured pdf file are currently not supported
250  }
251 
252  if (empty($data)) {
253  $isencrypted = true; // Object list not found. Possible secured file
254  }
255 
256  return $isencrypted;
257 }
258 
265 function pdf_getPDFFont($outputlangs)
266 {
267  global $conf;
268 
269  if (!empty($conf->global->MAIN_PDF_FORCE_FONT)) {
270  return $conf->global->MAIN_PDF_FORCE_FONT;
271  }
272 
273  $font = 'Helvetica'; // By default, for FPDI, or ISO language on TCPDF
274  if (class_exists('TCPDF')) { // If TCPDF on, we can use an UTF8 one like DejaVuSans if required (slower)
275  if ($outputlangs->trans('FONTFORPDF') != 'FONTFORPDF') {
276  $font = $outputlangs->trans('FONTFORPDF');
277  }
278  }
279  return $font;
280 }
281 
288 function pdf_getPDFFontSize($outputlangs)
289 {
290  global $conf;
291 
292  $size = 10; // By default, for FPDI or ISO language on TCPDF
293  if (class_exists('TCPDF')) { // If TCPDF on, we can use an UTF8 font like DejaVuSans if required (slower)
294  if ($outputlangs->trans('FONTSIZEFORPDF') != 'FONTSIZEFORPDF') {
295  $size = (int) $outputlangs->trans('FONTSIZEFORPDF');
296  }
297  }
298  if (!empty($conf->global->MAIN_PDF_FORCE_FONT_SIZE)) {
299  $size = $conf->global->MAIN_PDF_FORCE_FONT_SIZE;
300  }
301 
302  return $size;
303 }
304 
305 
313 function pdf_getHeightForLogo($logo, $url = false)
314 {
315  global $conf;
316  $height = (empty($conf->global->MAIN_DOCUMENTS_LOGO_HEIGHT) ? 20 : $conf->global->MAIN_DOCUMENTS_LOGO_HEIGHT);
317  $maxwidth = 130;
318  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
319  $tmp = dol_getImageSize($logo, $url);
320  if ($tmp['height']) {
321  $width = round($height * $tmp['width'] / $tmp['height']);
322  if ($width > $maxwidth) {
323  $height = $height * $maxwidth / $width;
324  }
325  }
326  //print $tmp['width'].' '.$tmp['height'].' '.$width; exit;
327  return $height;
328 }
329 
338 function pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
339 {
340  // store current object
341  $pdf->startTransaction();
342  // store starting values
343  $start_y = $pdf->GetY();
344  //var_dump($start_y);
345  $start_page = $pdf->getPage();
346  // call printing functions with content
347  $pdf->writeHTMLCell(0, 0, 0, $start_y, $htmlcontent, 0, 1, false, true, 'J', true);
348  // get the new Y
349  $end_y = $pdf->GetY();
350  $end_page = $pdf->getPage();
351  // calculate height
352  $height = 0;
353  if ($end_page == $start_page) {
354  $height = $end_y - $start_y;
355  } else {
356  for ($page = $start_page; $page <= $end_page; ++$page) {
357  $pdf->setPage($page);
358  $tmpm = $pdf->getMargins();
359  $tMargin = $tmpm['top'];
360  if ($page == $start_page) {
361  // first page
362  $height = $pdf->getPageHeight() - $start_y - $pdf->getBreakMargin();
363  } elseif ($page == $end_page) {
364  // last page
365  $height = $end_y - $tMargin;
366  } else {
367  $height = $pdf->getPageHeight() - $tMargin - $pdf->getBreakMargin();
368  }
369  }
370  }
371  // restore previous object
372  $pdf = $pdf->rollbackTransaction();
373 
374  return $height;
375 }
376 
377 
386 function pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias = 0)
387 {
388  global $conf;
389 
390  // Recipient name
391  $socname = '';
392 
393  if ($thirdparty instanceof Societe) {
394  $socname = $thirdparty->name;
395  if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->name_alias)) {
396  if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
397  $socname = $thirdparty->name_alias." - ".$thirdparty->name;
398  } else {
399  $socname = $thirdparty->name." - ".$thirdparty->name_alias;
400  }
401  }
402  } elseif ($thirdparty instanceof Contact) {
403  if ($thirdparty->socid > 0) {
404  $thirdparty->fetch_thirdparty();
405  $socname = $thirdparty->thirdparty->name;
406  if (($includealias || getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME')) && !empty($thirdparty->thirdparty->name_alias)) {
407  if (getDolGlobalInt('PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME') == 2) {
408  $socname = $thirdparty->thirdparty->name_alias." - ".$thirdparty->thirdparty->name;
409  } else {
410  $socname = $thirdparty->thirdparty->name." - ".$thirdparty->thirdparty->name_alias;
411  }
412  }
413  }
414  } else {
415  throw new InvalidArgumentException('Parameter 1 $thirdparty is not a Societe nor Contact');
416  }
417 
418  return $outputlangs->convToOutputCharset($socname);
419 }
420 
421 
434 function pdf_build_address($outputlangs, $sourcecompany, $targetcompany = '', $targetcontact = '', $usecontact = 0, $mode = 'source', $object = null)
435 {
436  global $conf, $hookmanager;
437 
438  if ($mode == 'source' && !is_object($sourcecompany)) {
439  return -1;
440  }
441  if ($mode == 'target' && !is_object($targetcompany)) {
442  return -1;
443  }
444 
445  if (!empty($sourcecompany->state_id) && empty($sourcecompany->state)) {
446  $sourcecompany->state = getState($sourcecompany->state_id);
447  }
448  if (!empty($targetcompany->state_id) && empty($targetcompany->state)) {
449  $targetcompany->state = getState($targetcompany->state_id);
450  }
451 
452  $reshook = 0;
453  $stringaddress = '';
454  if (is_object($hookmanager)) {
455  $parameters = array('sourcecompany' => &$sourcecompany, 'targetcompany' => &$targetcompany, 'targetcontact' => &$targetcontact, 'outputlangs' => $outputlangs, 'mode' => $mode, 'usecontact' => $usecontact);
456  $action = '';
457  $reshook = $hookmanager->executeHooks('pdf_build_address', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
458  $stringaddress .= $hookmanager->resPrint;
459  }
460  if (empty($reshook)) {
461  if ($mode == 'source') {
462  $withCountry = 0;
463  if (isset($targetcompany->country_code) && !empty($sourcecompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
464  $withCountry = 1;
465  }
466 
467  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($sourcecompany, $withCountry, "\n", $outputlangs))."\n";
468 
469  if (empty($conf->global->MAIN_PDF_DISABLESOURCEDETAILS)) {
470  // Phone
471  if ($sourcecompany->phone) {
472  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("PhoneShort").": ".$outputlangs->convToOutputCharset($sourcecompany->phone);
473  }
474  // Fax
475  if ($sourcecompany->fax) {
476  $stringaddress .= ($stringaddress ? ($sourcecompany->phone ? " - " : "\n") : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($sourcecompany->fax);
477  }
478  // EMail
479  if ($sourcecompany->email) {
480  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($sourcecompany->email);
481  }
482  // Web
483  if ($sourcecompany->url) {
484  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($sourcecompany->url);
485  }
486  }
487  // Intra VAT
488  if (!empty($conf->global->MAIN_TVAINTRA_IN_SOURCE_ADDRESS)) {
489  if ($sourcecompany->tva_intra) {
490  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($sourcecompany->tva_intra);
491  }
492  }
493  // Professionnal Ids
494  $reg = array();
495  if (!empty($conf->global->MAIN_PROFID1_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof1)) {
496  $tmp = $outputlangs->transcountrynoentities("ProfId1", $sourcecompany->country_code);
497  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
498  $tmp = $reg[1];
499  }
500  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof1);
501  }
502  if (!empty($conf->global->MAIN_PROFID2_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof2)) {
503  $tmp = $outputlangs->transcountrynoentities("ProfId2", $sourcecompany->country_code);
504  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
505  $tmp = $reg[1];
506  }
507  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof2);
508  }
509  if (!empty($conf->global->MAIN_PROFID3_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof3)) {
510  $tmp = $outputlangs->transcountrynoentities("ProfId3", $sourcecompany->country_code);
511  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
512  $tmp = $reg[1];
513  }
514  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof3);
515  }
516  if (!empty($conf->global->MAIN_PROFID4_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof4)) {
517  $tmp = $outputlangs->transcountrynoentities("ProfId4", $sourcecompany->country_code);
518  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
519  $tmp = $reg[1];
520  }
521  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof4);
522  }
523  if (!empty($conf->global->MAIN_PROFID5_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof5)) {
524  $tmp = $outputlangs->transcountrynoentities("ProfId5", $sourcecompany->country_code);
525  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
526  $tmp = $reg[1];
527  }
528  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof5);
529  }
530  if (!empty($conf->global->MAIN_PROFID6_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof6)) {
531  $tmp = $outputlangs->transcountrynoentities("ProfId6", $sourcecompany->country_code);
532  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
533  $tmp = $reg[1];
534  }
535  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof6);
536  }
537  if (!empty($conf->global->PDF_ADD_MORE_AFTER_SOURCE_ADDRESS)) {
538  $stringaddress .= ($stringaddress ? "\n" : '').$conf->global->PDF_ADD_MORE_AFTER_SOURCE_ADDRESS;
539  }
540  }
541 
542  if ($mode == 'target' || preg_match('/targetwithdetails/', $mode)) {
543  if ($usecontact) {
544  if (is_object($targetcontact)) {
545  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($targetcontact->getFullName($outputlangs, 1));
546 
547  if (!empty($targetcontact->address)) {
548  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcontact))."\n";
549  } else {
550  $companytouseforaddress = $targetcompany;
551 
552  // Contact on a thirdparty that is a different thirdparty than the thirdparty of object
553  if ($targetcontact->socid > 0 && $targetcontact->socid != $targetcompany->id) {
554  $targetcontact->fetch_thirdparty();
555  $companytouseforaddress = $targetcontact->thirdparty;
556  }
557 
558  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($companytouseforaddress))."\n";
559  }
560  // Country
561  if (!empty($targetcontact->country_code) && $targetcontact->country_code != $sourcecompany->country_code) {
562  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcontact->country_code));
563  } elseif (empty($targetcontact->country_code) && !empty($targetcompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
564  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
565  }
566 
567  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || preg_match('/targetwithdetails/', $mode)) {
568  // Phone
569  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
570  if (!empty($targetcontact->phone_pro) || !empty($targetcontact->phone_mobile)) {
571  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
572  }
573  if (!empty($targetcontact->phone_pro)) {
574  $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_pro);
575  }
576  if (!empty($targetcontact->phone_pro) && !empty($targetcontact->phone_mobile)) {
577  $stringaddress .= " / ";
578  }
579  if (!empty($targetcontact->phone_mobile)) {
580  $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_mobile);
581  }
582  }
583  // Fax
584  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
585  if ($targetcontact->fax) {
586  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcontact->fax);
587  }
588  }
589  // EMail
590  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
591  if ($targetcontact->email) {
592  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcontact->email);
593  }
594  }
595  // Web
596  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
597  if ($targetcontact->url) {
598  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcontact->url);
599  }
600  }
601  }
602  }
603  } else {
604  if (is_object($targetcompany)) {
605  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcompany))."\n";
606  // Country
607  if (!empty($targetcompany->country_code) && $targetcompany->country_code != $sourcecompany->country_code) {
608  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
609  }
610 
611  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || preg_match('/targetwithdetails/', $mode)) {
612  // Phone
613  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode)) {
614  if (!empty($targetcompany->phone)) {
615  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
616  }
617  if (!empty($targetcompany->phone)) {
618  $stringaddress .= $outputlangs->convToOutputCharset($targetcompany->phone);
619  }
620  }
621  // Fax
622  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode)) {
623  if ($targetcompany->fax) {
624  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcompany->fax);
625  }
626  }
627  // EMail
628  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode)) {
629  if ($targetcompany->email) {
630  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcompany->email);
631  }
632  }
633  // Web
634  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode)) {
635  if ($targetcompany->url) {
636  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcompany->url);
637  }
638  }
639  }
640  }
641  }
642 
643  // Intra VAT
644  if (empty($conf->global->MAIN_TVAINTRA_NOT_IN_ADDRESS)) {
645  if ($usecontact && is_object($targetcontact) && getDolGlobalInt('MAIN_USE_COMPANY_NAME_OF_CONTACT')) {
646  $targetcontact->fetch_thirdparty();
647  if (!empty($targetcontact->thirdparty->id) && $targetcontact->thirdparty->tva_intra) {
648  $stringaddress .= ($stringaddress ? "\n" : '') . $outputlangs->transnoentities("VATIntraShort") . ': ' . $outputlangs->convToOutputCharset($targetcontact->thirdparty->tva_intra);
649  }
650  } elseif ($targetcompany->tva_intra) {
651  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($targetcompany->tva_intra);
652  }
653  }
654 
655  // Professionnal Ids
656  if (!empty($conf->global->MAIN_PROFID1_IN_ADDRESS) && !empty($targetcompany->idprof1)) {
657  $tmp = $outputlangs->transcountrynoentities("ProfId1", $targetcompany->country_code);
658  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
659  $tmp = $reg[1];
660  }
661  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof1);
662  }
663  if (!empty($conf->global->MAIN_PROFID2_IN_ADDRESS) && !empty($targetcompany->idprof2)) {
664  $tmp = $outputlangs->transcountrynoentities("ProfId2", $targetcompany->country_code);
665  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
666  $tmp = $reg[1];
667  }
668  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof2);
669  }
670  if (!empty($conf->global->MAIN_PROFID3_IN_ADDRESS) && !empty($targetcompany->idprof3)) {
671  $tmp = $outputlangs->transcountrynoentities("ProfId3", $targetcompany->country_code);
672  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
673  $tmp = $reg[1];
674  }
675  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof3);
676  }
677  if (!empty($conf->global->MAIN_PROFID4_IN_ADDRESS) && !empty($targetcompany->idprof4)) {
678  $tmp = $outputlangs->transcountrynoentities("ProfId4", $targetcompany->country_code);
679  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
680  $tmp = $reg[1];
681  }
682  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof4);
683  }
684  if (!empty($conf->global->MAIN_PROFID5_IN_ADDRESS) && !empty($targetcompany->idprof5)) {
685  $tmp = $outputlangs->transcountrynoentities("ProfId5", $targetcompany->country_code);
686  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
687  $tmp = $reg[1];
688  }
689  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof5);
690  }
691  if (!empty($conf->global->MAIN_PROFID6_IN_ADDRESS) && !empty($targetcompany->idprof6)) {
692  $tmp = $outputlangs->transcountrynoentities("ProfId6", $targetcompany->country_code);
693  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
694  $tmp = $reg[1];
695  }
696  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof6);
697  }
698 
699  // Public note
700  if (!empty($conf->global->MAIN_PUBLIC_NOTE_IN_ADDRESS)) {
701  if ($mode == 'source' && !empty($sourcecompany->note_public)) {
702  $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($sourcecompany->note_public);
703  }
704  if (($mode == 'target' || preg_match('/targetwithdetails/', $mode)) && !empty($targetcompany->note_public)) {
705  $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($targetcompany->note_public);
706  }
707  }
708  }
709  }
710 
711  return $stringaddress;
712 }
713 
714 
723 function pdf_pagehead(&$pdf, $outputlangs, $page_height)
724 {
725  global $conf;
726 
727  // Add a background image on document only if good setup of const
728  if (!empty($conf->global->MAIN_USE_BACKGROUND_ON_PDF) && ($conf->global->MAIN_USE_BACKGROUND_ON_PDF != '-1')) { // Warning, this option make TCPDF generation being crazy and some content disappeared behind the image
729  $filepath = $conf->mycompany->dir_output.'/logos/'.$conf->global->MAIN_USE_BACKGROUND_ON_PDF;
730  if (file_exists($filepath)) {
731  $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak before adding image
732  $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);
733  $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
734  $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
735  }
736  }
737 }
738 
739 
749 function pdf_getSubstitutionArray($outputlangs, $exclude = null, $object = null, $onlykey = 0)
750 {
751  $substitutionarray = getCommonSubstitutionArray($outputlangs, $onlykey, $exclude, $object);
752  $substitutionarray['__FROM_NAME__'] = '__FROM_NAME__';
753  $substitutionarray['__FROM_EMAIL__'] = '__FROM_EMAIL__';
754  return $substitutionarray;
755 }
756 
757 
769 function pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
770 {
771  global $langs, $mysoc, $user;
772 
773  // Print Draft Watermark
774  if ($unit == 'pt') {
775  $k = 1;
776  } elseif ($unit == 'mm') {
777  $k = 72 / 25.4;
778  } elseif ($unit == 'cm') {
779  $k = 72 / 2.54;
780  } elseif ($unit == 'in') {
781  $k = 72;
782  }
783 
784  // Make substitution
785  $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, null);
786  complete_substitutions_array($substitutionarray, $outputlangs, null);
787  $text = make_substitutions($text, $substitutionarray, $outputlangs);
788  $text = $outputlangs->convToOutputCharset($text);
789 
790  $savx = $pdf->getX();
791  $savy = $pdf->getY();
792 
793  $watermark_angle = atan($h / $w) / 2;
794  $watermark_x_pos = 0;
795  $watermark_y_pos = $h / 3;
796  $watermark_x = $w / 2;
797  $watermark_y = $h / 3;
798  $pdf->SetFont('', 'B', 40);
799  $pdf->SetTextColor(255, 192, 203);
800  //rotate
801  $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));
802  //print watermark
803  $pdf->SetXY($watermark_x_pos, $watermark_y_pos);
804  $pdf->Cell($w - 20, 25, $outputlangs->convToOutputCharset($text), "", 2, "C", 0);
805  //antirotate
806  $pdf->_out('Q');
807 
808  $pdf->SetXY($savx, $savy);
809 }
810 
811 
824 function pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber = 0, $default_font_size = 10)
825 {
826  global $mysoc, $conf;
827 
828  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbank.class.php';
829 
830  $diffsizetitle = (empty($conf->global->PDF_DIFFSIZE_TITLE) ? 3 : $conf->global->PDF_DIFFSIZE_TITLE);
831  $diffsizecontent = (empty($conf->global->PDF_DIFFSIZE_CONTENT) ? 4 : $conf->global->PDF_DIFFSIZE_CONTENT);
832  $pdf->SetXY($curx, $cury);
833 
834  if (empty($onlynumber)) {
835  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
836  $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByTransferOnThisBankAccount').':', 0, 'L', 0);
837  $cury += 4;
838  }
839 
840  $outputlangs->load("banks");
841 
842  // Use correct name of bank id according to country
843  $bickey = "BICNumber";
844  if ($account->getCountryCode() == 'IN') {
845  $bickey = "SWIFT";
846  }
847 
848  // Get format of bank account according to its country
849  $usedetailedbban = $account->useDetailedBBAN();
850 
851  //$onlynumber=0; $usedetailedbban=1; // For tests
852  if ($usedetailedbban) {
853  $savcurx = $curx;
854 
855  if (empty($onlynumber)) {
856  $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
857  $pdf->SetXY($curx, $cury);
858  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
859  $cury += 3;
860  }
861 
862  if (empty($conf->global->PDF_BANK_HIDE_NUMBER_SHOW_ONLY_BICIBAN)) { // Note that some countries still need bank number, BIC/IBAN not enougth for them
863  // Note:
864  // bank = code_banque (FR), sort code (GB, IR. Example: 12-34-56)
865  // desk = code guichet (FR), used only when $usedetailedbban = 1
866  // number = account number
867  // key = check control key used only when $usedetailedbban = 1
868  if (empty($onlynumber)) {
869  $pdf->line($curx + 1, $cury + 1, $curx + 1, $cury + 6);
870  }
871 
872 
873  foreach ($account->getFieldsToShow() as $val) {
874  $pdf->SetXY($curx, $cury + 4);
875  $pdf->SetFont('', '', $default_font_size - 3);
876 
877  if ($val == 'BankCode') {
878  // Bank code
879  $tmplength = 18;
880  $content = $account->code_banque;
881  } elseif ($val == 'DeskCode') {
882  // Desk
883  $tmplength = 18;
884  $content = $account->code_guichet;
885  } elseif ($val == 'BankAccountNumber') {
886  // Number
887  $tmplength = 24;
888  $content = $account->number;
889  } elseif ($val == 'BankAccountNumberKey') {
890  // Key
891  $tmplength = 15;
892  $content = $account->cle_rib;
893  } elseif ($val == 'IBAN' || $val == 'BIC') {
894  // Key
895  $tmplength = 0;
896  $content = '';
897  } else {
898  dol_print_error($account->db, 'Unexpected value for getFieldsToShow: '.$val);
899  break;
900  }
901 
902  $pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($content), 0, 'C', 0);
903  $pdf->SetXY($curx, $cury + 1);
904  $curx += $tmplength;
905  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
906  $pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities($val), 0, 'C', 0);
907  if (empty($onlynumber)) {
908  $pdf->line($curx, $cury + 1, $curx, $cury + 7);
909  }
910  }
911 
912  $curx = $savcurx;
913  $cury += 8;
914  }
915  } else {
916  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
917  $pdf->SetXY($curx, $cury);
918  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
919  $cury += 3;
920 
921  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
922  $pdf->SetXY($curx, $cury);
923  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("BankAccountNumber").': '.$outputlangs->convToOutputCharset($account->number), 0, 'L', 0);
924  $cury += 3;
925 
926  if ($diffsizecontent <= 2) {
927  $cury += 1;
928  }
929  }
930 
931  $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
932 
933  if (empty($onlynumber) && !empty($account->domiciliation)) {
934  $pdf->SetXY($curx, $cury);
935  $val = $outputlangs->transnoentities("Residence").': '.$outputlangs->convToOutputCharset($account->domiciliation);
936  $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
937  //$nboflines=dol_nboflines_bis($val,120);
938  //$cury+=($nboflines*3)+2;
939  $tmpy = $pdf->getStringHeight(100, $val);
940  $cury += $tmpy;
941  }
942 
943  if (!empty($account->proprio)) {
944  $pdf->SetXY($curx, $cury);
945  $val = $outputlangs->transnoentities("BankAccountOwner").': '.$outputlangs->convToOutputCharset($account->proprio);
946  $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
947  $tmpy = $pdf->getStringHeight(100, $val);
948  $cury += $tmpy;
949  } elseif (!$usedetailedbban) {
950  $cury += 1;
951  }
952 
953  // Use correct name of bank id according to country
954  $ibankey = FormBank::getIBANLabel($account);
955 
956  if (!empty($account->iban)) {
957  //Remove whitespaces to ensure we are dealing with the format we expect
958  $ibanDisplay_temp = str_replace(' ', '', $outputlangs->convToOutputCharset($account->iban));
959  $ibanDisplay = "";
960 
961  $nbIbanDisplay_temp = dol_strlen($ibanDisplay_temp);
962  for ($i = 0; $i < $nbIbanDisplay_temp; $i++) {
963  $ibanDisplay .= $ibanDisplay_temp[$i];
964  if ($i % 4 == 3 && $i > 0) {
965  $ibanDisplay .= " ";
966  }
967  }
968 
969  $pdf->SetFont('', 'B', $default_font_size - 3);
970  $pdf->SetXY($curx, $cury);
971  $pdf->MultiCell(100, 3, $outputlangs->transnoentities($ibankey).': '.$ibanDisplay, 0, 'L', 0);
972  $cury += 3;
973  }
974 
975  if (!empty($account->bic)) {
976  $pdf->SetFont('', 'B', $default_font_size - 3);
977  $pdf->SetXY($curx, $cury);
978  $pdf->MultiCell(100, 3, $outputlangs->transnoentities($bickey).': '.$outputlangs->convToOutputCharset($account->bic), 0, 'L', 0);
979  }
980 
981  return $pdf->getY();
982 }
983 
1001 function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails = 0, $hidefreetext = 0, $page_largeur = 0, $watermark = '')
1002 {
1003  global $conf, $user, $mysoc, $hookmanager;
1004 
1005  $outputlangs->load("dict");
1006  $line = '';
1007  $reg = array();
1008 
1009  $dims = $pdf->getPageDimensions();
1010 
1011  // Line of free text
1012  if (empty($hidefreetext) && !empty($conf->global->$paramfreetext)) {
1013  $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
1014  // More substitution keys
1015  $substitutionarray['__FROM_NAME__'] = $fromcompany->name;
1016  $substitutionarray['__FROM_EMAIL__'] = $fromcompany->email;
1017  complete_substitutions_array($substitutionarray, $outputlangs, $object);
1018  $newfreetext = make_substitutions($conf->global->$paramfreetext, $substitutionarray, $outputlangs);
1019 
1020  // Make a change into HTML code to allow to include images from medias directory.
1021  // <img alt="" src="/dolibarr_dev/htdocs/viewimage.php?modulepart=medias&amp;entity=1&amp;file=image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1022  // become
1023  // <img alt="" src="'.DOL_DATA_ROOT.'/medias/image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1024  $newfreetext = preg_replace('/(<img.*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)("[^\/]*\/>)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $newfreetext);
1025 
1026  $line .= $outputlangs->convToOutputCharset($newfreetext);
1027  }
1028 
1029  // First line of company infos
1030  $line1 = "";
1031  $line2 = "";
1032  $line3 = "";
1033  $line4 = "";
1034 
1035  if ($showdetails == 1 || $showdetails == 3) {
1036  // Company name
1037  if ($fromcompany->name) {
1038  $line1 .= ($line1 ? " - " : "").$outputlangs->transnoentities("RegisteredOffice").": ".$fromcompany->name;
1039  }
1040  // Address
1041  if ($fromcompany->address) {
1042  $line1 .= ($line1 ? " - " : "").str_replace("\n", ", ", $fromcompany->address);
1043  }
1044  // Zip code
1045  if ($fromcompany->zip) {
1046  $line1 .= ($line1 ? " - " : "").$fromcompany->zip;
1047  }
1048  // Town
1049  if ($fromcompany->town) {
1050  $line1 .= ($line1 ? " " : "").$fromcompany->town;
1051  }
1052  // Country
1053  if ($fromcompany->country) {
1054  $line1 .= ($line1 ? ", " : "").$fromcompany->country;
1055  }
1056  // Phone
1057  if ($fromcompany->phone) {
1058  $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Phone").": ".$fromcompany->phone;
1059  }
1060  // Fax
1061  if ($fromcompany->fax) {
1062  $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Fax").": ".$fromcompany->fax;
1063  }
1064 
1065  // URL
1066  if ($fromcompany->url) {
1067  $line2 .= ($line2 ? " - " : "").$fromcompany->url;
1068  }
1069  // Email
1070  if ($fromcompany->email) {
1071  $line2 .= ($line2 ? " - " : "").$fromcompany->email;
1072  }
1073  }
1074  if ($showdetails == 2 || $showdetails == 3 || (!empty($fromcompany->country_code) && $fromcompany->country_code == 'DE')) {
1075  // Managers
1076  if ($fromcompany->managers) {
1077  $line2 .= ($line2 ? " - " : "").$fromcompany->managers;
1078  }
1079  }
1080 
1081  // Line 3 of company infos
1082  // Juridical status
1083  if (!empty($fromcompany->forme_juridique_code) && $fromcompany->forme_juridique_code) {
1084  $line3 .= ($line3 ? " - " : "").$outputlangs->convToOutputCharset(getFormeJuridiqueLabel($fromcompany->forme_juridique_code));
1085  }
1086  // Capital
1087  if (!empty($fromcompany->capital)) {
1088  $tmpamounttoshow = price2num($fromcompany->capital); // This field is a free string or a float
1089  if (is_numeric($tmpamounttoshow) && $tmpamounttoshow > 0) {
1090  $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", price($tmpamounttoshow, 0, $outputlangs, 0, 0, 0, $conf->currency));
1091  } elseif (!empty($fromcompany->capital)) {
1092  $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", $fromcompany->capital, $outputlangs);
1093  }
1094  }
1095  // Prof Id 1
1096  if (!empty($fromcompany->idprof1) && $fromcompany->idprof1 && ($fromcompany->country_code != 'FR' || !$fromcompany->idprof2)) {
1097  $field = $outputlangs->transcountrynoentities("ProfId1", $fromcompany->country_code);
1098  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1099  $field = $reg[1];
1100  }
1101  $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof1);
1102  }
1103  // Prof Id 2
1104  if (!empty($fromcompany->idprof2) && $fromcompany->idprof2) {
1105  $field = $outputlangs->transcountrynoentities("ProfId2", $fromcompany->country_code);
1106  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1107  $field = $reg[1];
1108  }
1109  $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof2);
1110  }
1111 
1112  // Line 4 of company infos
1113  // Prof Id 3
1114  if (!empty($fromcompany->idprof3) && $fromcompany->idprof3) {
1115  $field = $outputlangs->transcountrynoentities("ProfId3", $fromcompany->country_code);
1116  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1117  $field = $reg[1];
1118  }
1119  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof3);
1120  }
1121  // Prof Id 4
1122  if (!empty($fromcompany->idprof4) && $fromcompany->idprof4) {
1123  $field = $outputlangs->transcountrynoentities("ProfId4", $fromcompany->country_code);
1124  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1125  $field = $reg[1];
1126  }
1127  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof4);
1128  }
1129  // Prof Id 5
1130  if (!empty($fromcompany->idprof5) && $fromcompany->idprof5) {
1131  $field = $outputlangs->transcountrynoentities("ProfId5", $fromcompany->country_code);
1132  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1133  $field = $reg[1];
1134  }
1135  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof5);
1136  }
1137  // Prof Id 6
1138  if (!empty($fromcompany->idprof6) && $fromcompany->idprof6) {
1139  $field = $outputlangs->transcountrynoentities("ProfId6", $fromcompany->country_code);
1140  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1141  $field = $reg[1];
1142  }
1143  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof6);
1144  }
1145  // IntraCommunautary VAT
1146  if (!empty($fromcompany->tva_intra) && $fromcompany->tva_intra != '') {
1147  $line4 .= ($line4 ? " - " : "").$outputlangs->transnoentities("VATIntraShort").": ".$outputlangs->convToOutputCharset($fromcompany->tva_intra);
1148  }
1149 
1150  $pdf->SetFont('', '', 7);
1151  $pdf->SetDrawColor(224, 224, 224);
1152  // Option for footer text color
1153  if (!empty($conf->global->PDF_FOOTER_TEXT_COLOR)) {
1154  list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_TEXT_COLOR, '%d, %d, %d');
1155  $pdf->SetTextColor($r, $g, $b);
1156  }
1157 
1158  // The start of the bottom of this page footer is positioned according to # of lines
1159  $freetextheight = 0;
1160  if ($line) { // Free text
1161  //$line="sample text<br>\nfd<strong>sf</strong>sdf<br>\nghfghg<br>";
1162  if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT)) {
1163  $width = 20000;
1164  $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.
1165  if (!empty($conf->global->MAIN_USE_AUTOWRAP_ON_FREETEXT)) {
1166  $width = 200;
1167  $align = 'C';
1168  }
1169  $freetextheight = $pdf->getStringHeight($width, $line);
1170  } else {
1171  $freetextheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($line, 1, 'UTF-8', 0)); // New method (works for HTML content)
1172  //print '<br>'.$freetextheight;exit;
1173  }
1174  }
1175 
1176  // For customize footer
1177  if (is_object($hookmanager)) {
1178  $parameters = array('line1' => $line1, 'line2' => $line2, 'line3' => $line3, 'line4' => $line4, 'outputlangs'=>$outputlangs);
1179  $action = '';
1180  $hookmanager->executeHooks('pdf_pagefoot', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1181  if (!empty($hookmanager->resPrint) && $hidefreetext == 0) {
1182  $mycustomfooter = $hookmanager->resPrint;
1183  $mycustomfooterheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1184 
1185  $marginwithfooter = $marge_basse + $freetextheight + $mycustomfooterheight;
1186  $posy = $marginwithfooter + 0;
1187 
1188  // Option for footer background color (without freetext zone)
1189  if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1190  list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
1191  $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
1192  $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', '', $fill_color = array($r, $g, $b));
1193  $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
1194  }
1195 
1196  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(0, 0); } // Option for disable auto pagebreak
1197  if ($line) { // Free text
1198  $pdf->SetXY($dims['lm'], -$posy);
1199  if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1200  $pdf->MultiCell(0, 3, $line, 0, $align, 0);
1201  } else {
1202  $pdf->writeHTMLCell($pdf->page_largeur - $pdf->margin_left - $pdf->margin_right, $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1203  }
1204  $posy -= $freetextheight;
1205  }
1206  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(1, 0); } // Restore pagebreak
1207 
1208  $pdf->SetY(-$posy);
1209 
1210  // Hide footer line if footer background color is set
1211  if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1212  $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1213  }
1214 
1215  // Option for set top margin height of footer after freetext
1216  if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1217  $posy -= floatval(getDolGlobalString('PDF_FOOTER_TOP_MARGIN'));
1218  } else {
1219  $posy--;
1220  }
1221 
1222  if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(0, 0); } // Option for disable auto pagebreak
1223  $pdf->writeHTMLCell($pdf->page_largeur - $pdf->margin_left - $pdf->margin_right, $mycustomfooterheight, $dims['lm'], $dims['hk'] - $posy, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1224  if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(1, 0); } // Restore pagebreak
1225 
1226  $posy -= $mycustomfooterheight - 3;
1227  } else {
1228  // Else default footer
1229  $marginwithfooter = $marge_basse + $freetextheight + (!empty($line1) ? 3 : 0) + (!empty($line2) ? 3 : 0) + (!empty($line3) ? 3 : 0) + (!empty($line4) ? 3 : 0);
1230  $posy = $marginwithfooter + 0;
1231 
1232  // Option for footer background color (without freetext zone)
1233  if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1234  list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
1235  $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
1236  $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', '', $fill_color = array($r, $g, $b));
1237  $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
1238  }
1239 
1240  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(0, 0); } // Option for disable auto pagebreak
1241  if ($line) { // Free text
1242  $pdf->SetXY($dims['lm'], -$posy);
1243  if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1244  $pdf->MultiCell(0, 3, $line, 0, $align, 0);
1245  } else {
1246  $pdf->writeHTMLCell($pdf->page_largeur - $pdf->margin_left - $pdf->margin_right, $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1247  }
1248  $posy -= $freetextheight;
1249  }
1250  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(1, 0); } // Restore pagebreak
1251 
1252  $pdf->SetY(-$posy);
1253 
1254  // Hide footer line if footer background color is set
1255  if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1256  $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1257  }
1258 
1259  // Option for set top margin height of footer after freetext
1260  if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1261  $posy -= floatval(getDolGlobalString('PDF_FOOTER_TOP_MARGIN'));
1262  } else {
1263  $posy--;
1264  }
1265 
1266  if (!empty($line1)) {
1267  $pdf->SetFont('', 'B', 7);
1268  $pdf->SetXY($dims['lm'], -$posy);
1269  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line1, 0, 'C', 0);
1270  $posy -= 3;
1271  $pdf->SetFont('', '', 7);
1272  }
1273 
1274  if (!empty($line2)) {
1275  $pdf->SetFont('', 'B', 7);
1276  $pdf->SetXY($dims['lm'], -$posy);
1277  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line2, 0, 'C', 0);
1278  $posy -= 3;
1279  $pdf->SetFont('', '', 7);
1280  }
1281 
1282  if (!empty($line3)) {
1283  $pdf->SetXY($dims['lm'], -$posy);
1284  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line3, 0, 'C', 0);
1285  }
1286 
1287  if (!empty($line4)) {
1288  $posy -= 3;
1289  $pdf->SetXY($dims['lm'], -$posy);
1290  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line4, 0, 'C', 0);
1291  }
1292  }
1293  }
1294  // Show page nb only on iso languages (so default Helvetica font)
1295  if (strtolower(pdf_getPDFFont($outputlangs)) == 'helvetica') {
1296  $pdf->SetXY($dims['wk'] - $dims['rm'] - 18, -$posy);
1297  //$pdf->MultiCell(18, 2, $pdf->getPageNumGroupAlias().' / '.$pdf->getPageGroupAlias(), 0, 'R', 0);
1298  $pdf->MultiCell(18, 2, $pdf->PageNo().' / '.$pdf->getAliasNbPages(), 0, 'R', 0);
1299  }
1300 
1301  // Show Draft Watermark
1302  if (!empty($watermark)) {
1303  pdf_watermark($pdf, $outputlangs, $page_hauteur, $page_largeur, 'mm', $watermark);
1304  }
1305 
1306  return $marginwithfooter;
1307 }
1308 
1323 function pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
1324 {
1325  $linkedobjects = pdf_getLinkedObjects($object, $outputlangs);
1326  if (!empty($linkedobjects)) {
1327  foreach ($linkedobjects as $linkedobject) {
1328  $reftoshow = $linkedobject["ref_title"].' : '.$linkedobject["ref_value"];
1329  if (!empty($linkedobject["date_value"])) {
1330  $reftoshow .= ' / '.$linkedobject["date_value"];
1331  }
1332 
1333  $posy += 3;
1334  $pdf->SetXY($posx, $posy);
1335  $pdf->SetFont('', '', $default_font_size - 2);
1336  $pdf->MultiCell($w, $h, $reftoshow, '', $align);
1337  }
1338  }
1339 
1340  return $pdf->getY();
1341 }
1342 
1359 function pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
1360 {
1361  global $db, $conf, $langs, $hookmanager;
1362 
1363  $reshook = 0;
1364  $result = '';
1365  //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) ) )
1366  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
1367  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1368  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1369  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1370  }
1371  $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);
1372  $action = '';
1373  $reshook = $hookmanager->executeHooks('pdf_writelinedesc', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1374 
1375  if (!empty($hookmanager->resPrint)) {
1376  $result .= $hookmanager->resPrint;
1377  }
1378  }
1379  if (empty($reshook)) {
1380  $labelproductservice = pdf_getlinedesc($object, $i, $outputlangs, $hideref, $hidedesc, $issupplierline);
1381 
1382  //var_dump($labelproductservice);exit;
1383 
1384  // 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"
1385  // We make the reverse, so PDF generation has the real URL.
1386  $nbrep = 0;
1387  $labelproductservice = preg_replace('/(<img[^>]*src=")([^"]*)(&amp;)([^"]*")/', '\1\2&\4', $labelproductservice, -1, $nbrep);
1388 
1389  //var_dump($labelproductservice);exit;
1390 
1391  // Description
1392  $pdf->writeHTMLCell($w, $h, $posx, $posy, $outputlangs->convToOutputCharset($labelproductservice), 0, 1, false, true, 'J', true);
1393  $result .= $labelproductservice;
1394  }
1395  return $result;
1396 }
1397 
1409 function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
1410 {
1411  global $db, $conf, $langs;
1412 
1413  $idprod = (!empty($object->lines[$i]->fk_product) ? $object->lines[$i]->fk_product : false);
1414  $label = (!empty($object->lines[$i]->label) ? $object->lines[$i]->label : (!empty($object->lines[$i]->product_label) ? $object->lines[$i]->product_label : ''));
1415  $desc = (!empty($object->lines[$i]->desc) ? $object->lines[$i]->desc : (!empty($object->lines[$i]->description) ? $object->lines[$i]->description : ''));
1416  $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
1417  $note = (!empty($object->lines[$i]->note) ? $object->lines[$i]->note : '');
1418  $dbatch = (!empty($object->lines[$i]->detail_batch) ? $object->lines[$i]->detail_batch : false);
1419 
1420  if ($issupplierline) {
1421  include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
1422  $prodser = new ProductFournisseur($db);
1423  } else {
1424  include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
1425  $prodser = new Product($db);
1426 
1427  if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
1428  include_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
1429  }
1430  }
1431 
1432  if ($idprod) {
1433  $prodser->fetch($idprod);
1434  // If a predefined product and multilang and on other lang, we renamed label with label translated
1435  if (getDolGlobalInt('MAIN_MULTILANGS') && ($outputlangs->defaultlang != $langs->defaultlang)) {
1436  $translatealsoifmodified = (!empty($conf->global->MAIN_MULTILANG_TRANSLATE_EVEN_IF_MODIFIED)); // By default if value was modified manually, we keep it (no translation because we don't have it)
1437 
1438  // 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
1439  // ($textwasnotmodified is replaced with $textwasmodifiedorcompleted and we add completion).
1440 
1441  // Set label
1442  // 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.
1443  //var_dump($outputlangs->defaultlang.' - '.$langs->defaultlang.' - '.$label.' - '.$prodser->label);exit;
1444  $textwasnotmodified = ($label == $prodser->label);
1445  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1446  $label = $prodser->multilangs[$outputlangs->defaultlang]["label"];
1447  }
1448 
1449  // Set desc
1450  // Manage HTML entities description test because $prodser->description is store with htmlentities but $desc no
1451  $textwasnotmodified = false;
1452  if (!empty($desc) && dol_textishtml($desc) && !empty($prodser->description) && dol_textishtml($prodser->description)) {
1453  $textwasnotmodified = (strpos(dol_html_entity_decode($desc, ENT_QUOTES | ENT_HTML5), dol_html_entity_decode($prodser->description, ENT_QUOTES | ENT_HTML5)) !== false);
1454  } else {
1455  $textwasnotmodified = ($desc == $prodser->description);
1456  }
1457  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["description"])) {
1458  if ($textwasnotmodified) {
1459  $desc = str_replace($prodser->description, $prodser->multilangs[$outputlangs->defaultlang]["description"], $desc);
1460  } elseif ($translatealsoifmodified) {
1461  $desc = $prodser->multilangs[$outputlangs->defaultlang]["description"];
1462  }
1463  }
1464 
1465  // Set note
1466  $textwasnotmodified = ($note == $prodser->note_public);
1467  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["other"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1468  $note = $prodser->multilangs[$outputlangs->defaultlang]["other"];
1469  }
1470  }
1471  } 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
1472  $desc = str_replace('(DEPOSIT)', $outputlangs->trans('Deposit'), $desc);
1473  }
1474 
1475  if (empty($conf->global->PDF_HIDE_PRODUCT_LABEL_IN_SUPPLIER_LINES)) {
1476  // Description short of product line
1477  $libelleproduitservice = $label;
1478  if (!empty($libelleproduitservice) && !empty($conf->global->PDF_BOLD_PRODUCT_LABEL)) {
1479  // Adding <b> may convert the original string into a HTML string. Sowe have to first
1480  // convert \n into <br> we text is not already HTML.
1481  if (!dol_textishtml($libelleproduitservice)) {
1482  $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1483  }
1484  $libelleproduitservice = '<b>'.$libelleproduitservice.'</b>';
1485  }
1486  }
1487 
1488 
1489  // Add ref of subproducts
1490  if (!empty($conf->global->SHOW_SUBPRODUCT_REF_IN_PDF)) {
1491  $prodser->get_sousproduits_arbo();
1492  if (!empty($prodser->sousprods) && is_array($prodser->sousprods) && count($prodser->sousprods)) {
1493  $tmparrayofsubproducts = reset($prodser->sousprods);
1494  if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF)) {
1495  foreach ($tmparrayofsubproducts as $subprodval) {
1496  $libelleproduitservice = dol_concatdesc($libelleproduitservice, " * ".$subprodval[3].' ('.$subprodval[1].')');
1497  }
1498  } else {
1499  foreach ($tmparrayofsubproducts as $subprodval) {
1500  $libelleproduitservice = dol_concatdesc($libelleproduitservice, " * ".$subprodval[5].(($subprodval[5] && $subprodval[3]) ? ' - ' : '').$subprodval[3].' ('.$subprodval[1].')');
1501  }
1502  }
1503  }
1504  }
1505 
1506  // Description long of product line
1507  if (!empty($desc) && ($desc != $label)) {
1508  if ($desc == '(CREDIT_NOTE)' && $object->lines[$i]->fk_remise_except) {
1509  $discount = new DiscountAbsolute($db);
1510  $discount->fetch($object->lines[$i]->fk_remise_except);
1511  $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1512  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromCreditNote", $sourceref);
1513  } elseif ($desc == '(DEPOSIT)' && $object->lines[$i]->fk_remise_except) {
1514  $discount = new DiscountAbsolute($db);
1515  $discount->fetch($object->lines[$i]->fk_remise_except);
1516  $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1517  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromDeposit", $sourceref);
1518  // Add date of deposit
1519  if (!empty($conf->global->INVOICE_ADD_DEPOSIT_DATE)) {
1520  $libelleproduitservice .= ' ('.dol_print_date($discount->datec, 'day', '', $outputlangs).')';
1521  }
1522  } elseif ($desc == '(EXCESS RECEIVED)' && $object->lines[$i]->fk_remise_except) {
1523  $discount = new DiscountAbsolute($db);
1524  $discount->fetch($object->lines[$i]->fk_remise_except);
1525  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessReceived", $discount->ref_facture_source);
1526  } elseif ($desc == '(EXCESS PAID)' && $object->lines[$i]->fk_remise_except) {
1527  $discount = new DiscountAbsolute($db);
1528  $discount->fetch($object->lines[$i]->fk_remise_except);
1529  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessPaid", $discount->ref_invoice_supplier_source);
1530  } else {
1531  if ($idprod) {
1532  // Check if description must be output
1533  if (!empty($object->element)) {
1534  $tmpkey = 'MAIN_DOCUMENTS_HIDE_DESCRIPTION_FOR_'.strtoupper($object->element);
1535  if (!empty($conf->global->$tmpkey)) {
1536  $hidedesc = 1;
1537  }
1538  }
1539  if (empty($hidedesc)) {
1540  if (!empty($conf->global->MAIN_DOCUMENTS_DESCRIPTION_FIRST)) {
1541  $libelleproduitservice = dol_concatdesc($desc, $libelleproduitservice);
1542  } else {
1543  if (!empty($conf->global->HIDE_LABEL_VARIANT_PDF) && $prodser->isVariant()) {
1544  $libelleproduitservice = $desc;
1545  } else {
1546  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1547  }
1548  }
1549  }
1550  } else {
1551  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1552  }
1553  }
1554  }
1555 
1556  // We add ref of product (and supplier ref if defined)
1557  $prefix_prodserv = "";
1558  $ref_prodserv = "";
1559  if (!empty($conf->global->PRODUCT_ADD_TYPE_IN_DOCUMENTS)) { // In standard mode, we do not show this
1560  if ($prodser->isService()) {
1561  $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service")." ";
1562  } else {
1563  $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Product")." ";
1564  }
1565  }
1566 
1567  if (empty($hideref)) {
1568  if ($issupplierline) {
1569  if (empty($conf->global->PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES)) { // Common case
1570  $ref_prodserv = $prodser->ref; // Show local ref
1571  if ($ref_supplier) {
1572  $ref_prodserv .= ($prodser->ref ? ' (' : '').$outputlangs->transnoentitiesnoconv("SupplierRef").' '.$ref_supplier.($prodser->ref ? ')' : '');
1573  }
1574  } elseif ($conf->global->PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES == 1) {
1575  $ref_prodserv = $ref_supplier;
1576  } elseif ($conf->global->PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES == 2) {
1577  $ref_prodserv = $ref_supplier.' ('.$outputlangs->transnoentitiesnoconv("InternalRef").' '.$prodser->ref.')';
1578  }
1579  } else {
1580  $ref_prodserv = $prodser->ref; // Show local ref only
1581 
1582  if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
1583  $productCustomerPriceStatic = new Productcustomerprice($db);
1584  $filter = array('fk_product' => $idprod, 'fk_soc' => $object->socid);
1585 
1586  $nbCustomerPrices = $productCustomerPriceStatic->fetchAll('', '', 1, 0, $filter);
1587 
1588  if ($nbCustomerPrices > 0) {
1589  $productCustomerPrice = $productCustomerPriceStatic->lines[0];
1590 
1591  if (!empty($productCustomerPrice->ref_customer)) {
1592  switch ($conf->global->PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE) {
1593  case 1:
1594  $ref_prodserv = $productCustomerPrice->ref_customer;
1595  break;
1596 
1597  case 2:
1598  $ref_prodserv = $productCustomerPrice->ref_customer . ' (' . $outputlangs->transnoentitiesnoconv('InternalRef') . ' ' . $ref_prodserv . ')';
1599  break;
1600 
1601  default:
1602  $ref_prodserv = $ref_prodserv . ' (' . $outputlangs->transnoentitiesnoconv('RefCustomer') . ' ' . $productCustomerPrice->ref_customer . ')';
1603  }
1604  }
1605  }
1606  }
1607  }
1608 
1609  if (!empty($libelleproduitservice) && !empty($ref_prodserv)) {
1610  $ref_prodserv .= " - ";
1611  }
1612  }
1613 
1614  if (!empty($ref_prodserv) && !empty($conf->global->PDF_BOLD_PRODUCT_REF_AND_PERIOD)) {
1615  if (!dol_textishtml($libelleproduitservice)) {
1616  $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1617  }
1618  $ref_prodserv = '<b>'.$ref_prodserv.'</b>';
1619  // $prefix_prodserv and $ref_prodser are not HTML var
1620  }
1621  $libelleproduitservice = $prefix_prodserv.$ref_prodserv.$libelleproduitservice;
1622 
1623  // Add an additional description for the category products
1624  if (!empty($conf->global->CATEGORY_ADD_DESC_INTO_DOC) && $idprod && isModEnabled('categorie')) {
1625  include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1626  $categstatic = new Categorie($db);
1627  // recovering the list of all the categories linked to product
1628  $tblcateg = $categstatic->containing($idprod, Categorie::TYPE_PRODUCT);
1629  foreach ($tblcateg as $cate) {
1630  // Adding the descriptions if they are filled
1631  $desccateg = $cate->description;
1632  if ($desccateg) {
1633  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desccateg);
1634  }
1635  }
1636  }
1637 
1638  if (!empty($object->lines[$i]->date_start) || !empty($object->lines[$i]->date_end)) {
1639  $format = 'day';
1640  $period = '';
1641  // Show duration if exists
1642  if ($object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1643  $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)).')';
1644  }
1645  if ($object->lines[$i]->date_start && !$object->lines[$i]->date_end) {
1646  $period = '('.$outputlangs->transnoentitiesnoconv('DateFrom', dol_print_date($object->lines[$i]->date_start, $format, false, $outputlangs)).')';
1647  }
1648  if (!$object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1649  $period = '('.$outputlangs->transnoentitiesnoconv('DateUntil', dol_print_date($object->lines[$i]->date_end, $format, false, $outputlangs)).')';
1650  }
1651  //print '>'.$outputlangs->charset_output.','.$period;
1652  if (!empty($conf->global->PDF_BOLD_PRODUCT_REF_AND_PERIOD)) {
1653  if (!dol_textishtml($libelleproduitservice)) {
1654  $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1655  }
1656  $libelleproduitservice .= '<br><b style="color:#333666;" ><em>'.$period.'</em></b>';
1657  } else {
1658  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $period);
1659  }
1660  //print $libelleproduitservice;
1661  }
1662 
1663  // Show information for lot
1664  if ($dbatch) {
1665  // $object is a shipment.
1666  //var_dump($object->lines[$i]->details_entrepot); // array from llx_expeditiondet (we can have seral lines for one fk_origin_line)
1667  //var_dump($object->lines[$i]->detail_batch); // array from llx_expeditiondet_batch (each line with a lot is linked to llx_expeditiondet)
1668 
1669  include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
1670  include_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
1671  $tmpwarehouse = new Entrepot($db);
1672  $tmpproductbatch = new Productbatch($db);
1673 
1674  $format = 'day';
1675  foreach ($dbatch as $detail) {
1676  $dte = array();
1677  if ($detail->eatby) {
1678  $dte[] = $outputlangs->transnoentitiesnoconv('printEatby', dol_print_date($detail->eatby, $format, false, $outputlangs));
1679  }
1680  if ($detail->sellby) {
1681  $dte[] = $outputlangs->transnoentitiesnoconv('printSellby', dol_print_date($detail->sellby, $format, false, $outputlangs));
1682  }
1683  if ($detail->batch) {
1684  $dte[] = $outputlangs->transnoentitiesnoconv('printBatch', $detail->batch);
1685  }
1686  $dte[] = $outputlangs->transnoentitiesnoconv('printQty', $detail->qty);
1687 
1688  // Add also info of planned warehouse for lot
1689  if ($object->element == 'shipping' && $detail->fk_origin_stock > 0 && getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1690  $resproductbatch = $tmpproductbatch->fetch($detail->fk_origin_stock);
1691  if ($resproductbatch > 0) {
1692  $reswarehouse = $tmpwarehouse->fetch($tmpproductbatch->warehouseid);
1693  if ($reswarehouse > 0) {
1694  $dte[] = $tmpwarehouse->ref;
1695  }
1696  }
1697  }
1698 
1699  $libelleproduitservice .= "__N__ ".implode(" - ", $dte);
1700  }
1701  } else {
1702  if (getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1703  // TODO Show warehouse for shipment line without batch
1704  }
1705  }
1706 
1707  // Now we convert \n into br
1708  if (dol_textishtml($libelleproduitservice)) {
1709  $libelleproduitservice = preg_replace('/__N__/', '<br>', $libelleproduitservice);
1710  } else {
1711  $libelleproduitservice = preg_replace('/__N__/', "\n", $libelleproduitservice);
1712  }
1713  $libelleproduitservice = dol_htmlentitiesbr($libelleproduitservice, 1);
1714 
1715  return $libelleproduitservice;
1716 }
1717 
1727 function pdf_getlinenum($object, $i, $outputlangs, $hidedetails = 0)
1728 {
1729  global $hookmanager;
1730 
1731  $reshook = 0;
1732  $result = '';
1733  //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) ) )
1734  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
1735  $special_code = $object->lines[$i]->special_code;
1736  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1737  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1738  }
1739  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1740  $action = '';
1741  $reshook = $hookmanager->executeHooks('pdf_getlinenum', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1742  $result .= $hookmanager->resPrint;
1743  }
1744  if (empty($reshook)) {
1745  $result .= dol_htmlentitiesbr($object->lines[$i]->num);
1746  }
1747  return $result;
1748 }
1749 
1750 
1760 function pdf_getlineref($object, $i, $outputlangs, $hidedetails = 0)
1761 {
1762  global $hookmanager;
1763 
1764  $reshook = 0;
1765  $result = '';
1766  //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) ) )
1767  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
1768  $special_code = $object->lines[$i]->special_code;
1769  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1770  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1771  }
1772  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1773  $action = '';
1774  $reshook = $hookmanager->executeHooks('pdf_getlineref', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1775  $result .= $hookmanager->resPrint;
1776  }
1777  if (empty($reshook)) {
1778  $result .= dol_htmlentitiesbr($object->lines[$i]->product_ref);
1779  }
1780  return $result;
1781 }
1782 
1792 function pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails = 0)
1793 {
1794  global $hookmanager;
1795 
1796  $reshook = 0;
1797  $result = '';
1798  //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) ) )
1799  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
1800  $special_code = $object->lines[$i]->special_code;
1801  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1802  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1803  }
1804  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1805  $action = '';
1806  $reshook = $hookmanager->executeHooks('pdf_getlineref_supplier', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1807  $result .= $hookmanager->resPrint;
1808  }
1809  if (empty($reshook)) {
1810  $result .= dol_htmlentitiesbr($object->lines[$i]->ref_supplier);
1811  }
1812  return $result;
1813 }
1814 
1824 function pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails = 0)
1825 {
1826  global $conf, $hookmanager, $mysoc;
1827 
1828  $result = '';
1829  $reshook = 0;
1830  //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) ) )
1831  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
1832  $special_code = empty($object->lines[$i]) ? '' : $object->lines[$i]->special_code;
1833  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1834  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1835  }
1836  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1837  $action = '';
1838  $reshook = $hookmanager->executeHooks('pdf_getlinevatrate', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1839 
1840  if (!empty($hookmanager->resPrint)) {
1841  $result .= $hookmanager->resPrint;
1842  }
1843  }
1844  if (empty($reshook)) {
1845  if (empty($hidedetails) || $hidedetails > 1) {
1846  $tmpresult = '';
1847 
1848  $tmpresult .= vatrate($object->lines[$i]->tva_tx, 0, $object->lines[$i]->info_bits, -1);
1849  if (empty($conf->global->MAIN_PDF_MAIN_HIDE_SECOND_TAX)) {
1850  if ($object->lines[$i]->total_localtax1 != 0) {
1851  if (preg_replace('/[\s0%]/', '', $tmpresult)) {
1852  $tmpresult .= '/';
1853  } else {
1854  $tmpresult = '';
1855  }
1856  $tmpresult .= vatrate(abs($object->lines[$i]->localtax1_tx), 0);
1857  }
1858  }
1859  if (empty($conf->global->MAIN_PDF_MAIN_HIDE_THIRD_TAX)) {
1860  if ($object->lines[$i]->total_localtax2 != 0) {
1861  if (preg_replace('/[\s0%]/', '', $tmpresult)) {
1862  $tmpresult .= '/';
1863  } else {
1864  $tmpresult = '';
1865  }
1866  $tmpresult .= vatrate(abs($object->lines[$i]->localtax2_tx), 0);
1867  }
1868  }
1869  $tmpresult .= '%';
1870 
1871  $result .= $tmpresult;
1872  }
1873  }
1874  return $result;
1875 }
1876 
1886 function pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails = 0)
1887 {
1888  global $conf, $hookmanager;
1889 
1890  $sign = 1;
1891  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) {
1892  $sign = -1;
1893  }
1894 
1895  $result = '';
1896  $reshook = 0;
1897  //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
1898  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
1899  $special_code = empty($object->lines[$i]) ? '' : $object->lines[$i]->special_code;
1900  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1901  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1902  }
1903  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1904  $action = '';
1905  $reshook = $hookmanager->executeHooks('pdf_getlineupexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1906 
1907  if (!empty($hookmanager->resPrint)) {
1908  $result .= $hookmanager->resPrint;
1909  }
1910  }
1911  if (empty($reshook)) {
1912  if (empty($hidedetails) || $hidedetails > 1) {
1913  $subprice = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice);
1914  $result .= price($sign * $subprice, 0, $outputlangs);
1915  }
1916  }
1917  return $result;
1918 }
1919 
1929 function pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails = 0)
1930 {
1931  global $hookmanager, $conf;
1932 
1933  $sign = 1;
1934  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) {
1935  $sign = -1;
1936  }
1937 
1938  $result = '';
1939  $reshook = 0;
1940  //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) ) )
1941  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
1942  $special_code = $object->lines[$i]->special_code;
1943  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1944  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1945  }
1946  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1947  $action = '';
1948  $reshook = $hookmanager->executeHooks('pdf_getlineupwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1949 
1950  if (!empty($hookmanager->resPrint)) {
1951  $result .= $hookmanager->resPrint;
1952  }
1953  }
1954  if (empty($reshook)) {
1955  if (empty($hidedetails) || $hidedetails > 1) {
1956  $result .= price($sign * (($object->lines[$i]->subprice) + ($object->lines[$i]->subprice) * ($object->lines[$i]->tva_tx) / 100), 0, $outputlangs);
1957  }
1958  }
1959  return $result;
1960 }
1961 
1971 function pdf_getlineqty($object, $i, $outputlangs, $hidedetails = 0)
1972 {
1973  global $hookmanager;
1974 
1975  $result = '';
1976  $reshook = 0;
1977  //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) ) )
1978  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
1979  $special_code = empty($object->lines[$i]) ? '' : $object->lines[$i]->special_code;
1980  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
1981  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1982  }
1983  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1984  $action = '';
1985  $reshook = $hookmanager->executeHooks('pdf_getlineqty', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1986 
1987  if (!empty($hookmanager->resPrint)) {
1988  $result = $hookmanager->resPrint;
1989  }
1990  }
1991  if (empty($reshook)) {
1992  if ($object->lines[$i]->special_code == 3) {
1993  return '';
1994  }
1995  if (empty($hidedetails) || $hidedetails > 1) {
1996  $result .= $object->lines[$i]->qty;
1997  }
1998  }
1999  return $result;
2000 }
2001 
2011 function pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails = 0)
2012 {
2013  global $hookmanager;
2014 
2015  $reshook = 0;
2016  $result = '';
2017  //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) ) )
2018  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
2019  $special_code = $object->lines[$i]->special_code;
2020  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2021  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2022  }
2023  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2024  $action = '';
2025  $reshook = $hookmanager->executeHooks('pdf_getlineqty_asked', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2026 
2027  if (!empty($hookmanager->resPrint)) {
2028  $result .= $hookmanager->resPrint;
2029  }
2030  }
2031  if (empty($reshook)) {
2032  if ($object->lines[$i]->special_code == 3) {
2033  return '';
2034  }
2035  if (empty($hidedetails) || $hidedetails > 1) {
2036  $result .= $object->lines[$i]->qty_asked;
2037  }
2038  }
2039  return $result;
2040 }
2041 
2051 function pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails = 0)
2052 {
2053  global $hookmanager;
2054 
2055  $reshook = 0;
2056  $result = '';
2057  //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) ) )
2058  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
2059  $special_code = $object->lines[$i]->special_code;
2060  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2061  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2062  }
2063  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2064  $action = '';
2065  $reshook = $hookmanager->executeHooks('pdf_getlineqty_shipped', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2066 
2067  if (!empty($hookmanager->resPrint)) {
2068  $result .= $hookmanager->resPrint;
2069  }
2070  }
2071  if (empty($reshook)) {
2072  if ($object->lines[$i]->special_code == 3) {
2073  return '';
2074  }
2075  if (empty($hidedetails) || $hidedetails > 1) {
2076  $result .= $object->lines[$i]->qty_shipped;
2077  }
2078  }
2079  return $result;
2080 }
2081 
2091 function pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails = 0)
2092 {
2093  global $hookmanager;
2094 
2095  $reshook = 0;
2096  $result = '';
2097  //if (is_object($hookmanager) && ( (isset($object->lines[$i]->product_type) && $object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line) ) )
2098  if (is_object($hookmanager)) { // Old code is commented on preceding line. Reproduct this test in the pdf_xxx function if you don't want your hook to run
2099  $special_code = $object->lines[$i]->special_code;
2100  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2101  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2102  }
2103  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2104  $action = '';
2105  $reshook = $hookmanager->executeHooks('pdf_getlineqty_keeptoship', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2106 
2107  if (!empty($hookmanager->resPrint)) {
2108  $result .= $hookmanager->resPrint;
2109  }
2110  }
2111  if (empty($reshook)) {
2112  if ($object->lines[$i]->special_code == 3) {
2113  return '';
2114  }
2115  if (empty($hidedetails) || $hidedetails > 1) {
2116  $result .= ($object->lines[$i]->qty_asked - $object->lines[$i]->qty_shipped);
2117  }
2118  }
2119  return $result;
2120 }
2121 
2132 function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = false)
2133 {
2134  global $langs;
2135 
2136  $reshook = 0;
2137  $result = '';
2138  //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) ) )
2139  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
2140  $special_code = $object->lines[$i]->special_code;
2141  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2142  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2143  }
2144  $parameters = array(
2145  'i' => $i,
2146  'outputlangs' => $outputlangs,
2147  'hidedetails' => $hidedetails,
2148  'special_code' => $special_code
2149  );
2150  $action = '';
2151  $reshook = $hookmanager->executeHooks('pdf_getlineunit', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2152 
2153  if (!empty($hookmanager->resPrint)) {
2154  $result .= $hookmanager->resPrint;
2155  }
2156  }
2157  if (empty($reshook)) {
2158  if (empty($hidedetails) || $hidedetails > 1) {
2159  $result .= $langs->transnoentitiesnoconv($object->lines[$i]->getLabelOfUnit('short'));
2160  }
2161  }
2162  return $result;
2163 }
2164 
2165 
2175 function pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails = 0)
2176 {
2177  global $hookmanager;
2178 
2179  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
2180 
2181  $reshook = 0;
2182  $result = '';
2183  //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) ) )
2184  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
2185  $special_code = $object->lines[$i]->special_code;
2186  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2187  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2188  }
2189  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2190  $action = '';
2191  $reshook = $hookmanager->executeHooks('pdf_getlineremisepercent', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2192 
2193  if (!empty($hookmanager->resPrint)) {
2194  $result .= $hookmanager->resPrint;
2195  }
2196  }
2197  if (empty($reshook)) {
2198  if ($object->lines[$i]->special_code == 3) {
2199  return '';
2200  }
2201  if (empty($hidedetails) || $hidedetails > 1) {
2202  $result .= dol_print_reduction($object->lines[$i]->remise_percent, $outputlangs);
2203  }
2204  }
2205  return $result;
2206 }
2207 
2218 function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = null)
2219 {
2220  if (empty($hookmanager)) {
2221  global $hookmanager;
2222  }
2223  global $conf;
2224 
2225  $reshook = 0;
2226  $result = '';
2227  //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) ) )
2228  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
2229  $special_code = $object->lines[$i]->special_code;
2230  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2231  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2232  }
2233  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2234  $action = '';
2235  $reshook = $hookmanager->executeHooks('pdf_getlineprogress', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2236 
2237  if (!empty($hookmanager->resPrint)) {
2238  return $hookmanager->resPrint;
2239  }
2240  }
2241  if (empty($reshook)) {
2242  if ($object->lines[$i]->special_code == 3) {
2243  return '';
2244  }
2245  if (empty($hidedetails) || $hidedetails > 1) {
2246  if (!empty($conf->global->SITUATION_DISPLAY_DIFF_ON_PDF)) {
2247  $prev_progress = 0;
2248  if (method_exists($object->lines[$i], 'get_prev_progress')) {
2249  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2250  }
2251  $result = round($object->lines[$i]->situation_percent - $prev_progress, 1).'%';
2252  } else {
2253  $result = round($object->lines[$i]->situation_percent, 1).'%';
2254  }
2255  }
2256  }
2257  return $result;
2258 }
2259 
2269 function pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails = 0)
2270 {
2271  global $conf, $hookmanager;
2272 
2273  $sign = 1;
2274  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) {
2275  $sign = -1;
2276  }
2277 
2278  $reshook = 0;
2279  $result = '';
2280  //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) ) )
2281  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
2282  $special_code = empty($object->lines[$i]) ? '' : $object->lines[$i]->special_code;
2283  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2284  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2285  }
2286  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code, 'sign'=>$sign);
2287  $action = '';
2288  $reshook = $hookmanager->executeHooks('pdf_getlinetotalexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2289 
2290  if (!empty($hookmanager->resPrint)) {
2291  $result .= $hookmanager->resPrint;
2292  }
2293  }
2294  if (empty($reshook)) {
2295  if (!empty($object->lines[$i]) && $object->lines[$i]->special_code == 3) {
2296  $result .= $outputlangs->transnoentities("Option");
2297  } elseif (empty($hidedetails) || $hidedetails > 1) {
2298  $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
2299  if (!empty($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
2300  // TODO Remove this. The total should be saved correctly in database instead of being modified here.
2301  $prev_progress = 0;
2302  $progress = 1;
2303  if (method_exists($object->lines[$i], 'get_prev_progress')) {
2304  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2305  $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
2306  }
2307  $result .= price($sign * ($total_ht / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
2308  } else {
2309  $result .= price($sign * $total_ht, 0, $outputlangs);
2310  }
2311  }
2312  }
2313  return $result;
2314 }
2315 
2325 function pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails = 0)
2326 {
2327  global $hookmanager, $conf;
2328 
2329  $sign = 1;
2330  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) {
2331  $sign = -1;
2332  }
2333 
2334  $reshook = 0;
2335  $result = '';
2336  //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) ) )
2337  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
2338  $special_code = $object->lines[$i]->special_code;
2339  if (!empty($object->lines[$i]->fk_parent_line) && $object->lines[$i]->fk_parent_line > 0) {
2340  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2341  }
2342  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2343  $action = '';
2344  $reshook = $hookmanager->executeHooks('pdf_getlinetotalwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2345 
2346  if (!empty($hookmanager->resPrint)) {
2347  $result .= $hookmanager->resPrint;
2348  }
2349  }
2350  if (empty($reshook)) {
2351  if ($object->lines[$i]->special_code == 3) {
2352  $result .= $outputlangs->transnoentities("Option");
2353  } elseif (empty($hidedetails) || $hidedetails > 1) {
2354  $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ttc : $object->lines[$i]->total_ttc);
2355  if ($object->lines[$i]->situation_percent > 0) {
2356  // TODO Remove this. The total should be saved correctly in database instead of being modified here.
2357  $prev_progress = 0;
2358  $progress = 1;
2359  if (method_exists($object->lines[$i], 'get_prev_progress')) {
2360  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2361  $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
2362  }
2363  $result .= price($sign * ($total_ttc / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
2364  } else {
2365  $result .= price($sign * $total_ttc, 0, $outputlangs);
2366  }
2367  }
2368  }
2369  return $result;
2370 }
2371 
2380 function pdf_getLinkedObjects(&$object, $outputlangs)
2381 {
2382  global $db, $hookmanager;
2383 
2384  $linkedobjects = array();
2385 
2386  $object->fetchObjectLinked();
2387 
2388  foreach ($object->linkedObjects as $objecttype => $objects) {
2389  if ($objecttype == 'facture') {
2390  // For invoice, we don't want to have a reference line on document. Image we are using recuring invoice, we will have a line longer than document width.
2391  } elseif ($objecttype == 'propal' || $objecttype == 'supplier_proposal') {
2392  $outputlangs->load('propal');
2393 
2394  foreach ($objects as $elementobject) {
2395  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefProposal");
2396  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2397  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DatePropal");
2398  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2399  }
2400  } elseif ($objecttype == 'commande' || $objecttype == 'supplier_order') {
2401  $outputlangs->load('orders');
2402 
2403  if (count($objects) > 1 && count($objects) <= (getDolGlobalInt("MAXREFONDOC") ? getDolGlobalInt("MAXREFONDOC") : 10)) {
2404  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("RefOrder").' :');
2405  foreach ($objects as $elementobject) {
2406  $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.')').' ');
2407  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("OrderDate").' : '.dol_print_date($elementobject->date, 'day', '', $outputlangs));
2408  }
2409  } elseif (count($objects) == 1) {
2410  $elementobject = array_shift($objects);
2411  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder");
2412  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref).(!empty($elementobject->ref_client) ? ' ('.$elementobject->ref_client.')' : '').(!empty($elementobject->ref_supplier) ? ' ('.$elementobject->ref_supplier.')' : '');
2413  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("OrderDate");
2414  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2415  }
2416  } elseif ($objecttype == 'contrat') {
2417  $outputlangs->load('contracts');
2418  foreach ($objects as $elementobject) {
2419  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefContract");
2420  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2421  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DateContract");
2422  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date_contrat, 'day', '', $outputlangs);
2423  }
2424  } elseif ($objecttype == 'fichinter') {
2425  $outputlangs->load('interventions');
2426  foreach ($objects as $elementobject) {
2427  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("InterRef");
2428  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2429  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("InterDate");
2430  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->datec, 'day', '', $outputlangs);
2431  }
2432  } elseif ($objecttype == 'shipping') {
2433  $outputlangs->loadLangs(array("orders", "sendings"));
2434 
2435  if (count($objects) > 1) {
2436  $order = null;
2437  if (empty($object->linkedObjects['commande']) && $object->element != 'commande') {
2438  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending").' :');
2439  } else {
2440  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("RefSending").' :');
2441  }
2442  // We concat this record info into fields xxx_value. title is overwrote.
2443  foreach ($objects as $elementobject) {
2444  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
2445  $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2446  if (!empty($elementobject->linkedObjectsIds['commande'])) {
2447  include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2448  $order = new Commande($db);
2449  $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2450  if ($ret < 1) {
2451  $order = null;
2452  }
2453  }
2454  }
2455 
2456  if (! is_object($order)) {
2457  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities($elementobject->ref));
2458  } else {
2459  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : ''));
2460  $object->note_public = dol_concatdesc($object->note_public, ' / '.$outputlangs->transnoentities($elementobject->ref));
2461  }
2462  }
2463  } elseif (count($objects) == 1) {
2464  $elementobject = array_shift($objects);
2465  $order = null;
2466  // We concat this record info into fields xxx_value. title is overwrote.
2467  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
2468  $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2469  if (!empty($elementobject->linkedObjectsIds['commande'])) {
2470  include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2471  $order = new Commande($db);
2472  $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2473  if ($ret < 1) {
2474  $order = null;
2475  }
2476  }
2477  }
2478 
2479  if (! is_object($order)) {
2480  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefSending");
2481  if (!empty($linkedobjects[$objecttype]['ref_value'])) $linkedobjects[$objecttype]['ref_value'] .= ' / ';
2482  $linkedobjects[$objecttype]['ref_value'] .= $outputlangs->transnoentities($elementobject->ref);
2483  $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
2484  } else {
2485  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending");
2486  if (empty($linkedobjects[$objecttype]['ref_value'])) $linkedobjects[$objecttype]['ref_value'] = $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
2487  $linkedobjects[$objecttype]['ref_value'] .= ' / '.$outputlangs->transnoentities($elementobject->ref);
2488  $linkedobjects[$objecttype]['date_value'] = dol_print_date(empty($elementobject->date_shipping) ? $elementobject->date_delivery : $elementobject->date_shipping, 'day', '', $outputlangs);
2489  }
2490  }
2491  }
2492  }
2493 
2494  // For add external linked objects
2495  if (is_object($hookmanager)) {
2496  $parameters = array('linkedobjects' => $linkedobjects, 'outputlangs'=>$outputlangs);
2497  $action = '';
2498  $hookmanager->executeHooks('pdf_getLinkedObjects', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2499  if (!empty($hookmanager->resArray)) {
2500  $linkedobjects = $hookmanager->resArray;
2501  }
2502  }
2503 
2504  return $linkedobjects;
2505 }
2506 
2514 function pdf_getSizeForImage($realpath)
2515 {
2516  global $conf;
2517 
2518  $maxwidth = (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH);
2519  $maxheight = (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT) ? 32 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT);
2520  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
2521  $tmp = dol_getImageSize($realpath);
2522  $width = 0;
2523  $height = 0;
2524  if ($tmp['height']) {
2525  $width = (int) round($maxheight * $tmp['width'] / $tmp['height']); // I try to use maxheight
2526  if ($width > $maxwidth) { // Pb with maxheight, so i use maxwidth
2527  $width = $maxwidth;
2528  $height = (int) round($maxwidth * $tmp['height'] / $tmp['width']);
2529  } else // No pb with maxheight
2530  {
2531  $height = $maxheight;
2532  }
2533  }
2534  return array('width'=>$width, 'height'=>$height);
2535 }
2536 
2546 function pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails = 0)
2547 {
2548  global $conf, $hookmanager;
2549  $sign = 1;
2550  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) {
2551  $sign = -1;
2552  }
2553  if ($object->lines[$i]->special_code == 3) {
2554  return $outputlangs->transnoentities("Option");
2555  } else {
2556  if (is_object($hookmanager)) {
2557  $special_code = $object->lines[$i]->special_code;
2558  if (!empty($object->lines[$i]->fk_parent_line)) {
2559  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2560  }
2561 
2562  $parameters = array(
2563  'i'=>$i,
2564  'outputlangs'=>$outputlangs,
2565  'hidedetails'=>$hidedetails,
2566  'special_code'=>$special_code
2567  );
2568 
2569  $action = '';
2570 
2571  if ($hookmanager->executeHooks('getlinetotalremise', $parameters, $object, $action) > 0) {
2572  return $hookmanager->resPrint; // Note that $action and $object may have been modified by some hooks
2573  }
2574  }
2575 
2576  if (empty($hidedetails) || $hidedetails > 1) {
2577  return $sign * (($object->lines[$i]->subprice * $object->lines[$i]->qty) - $object->lines[$i]->total_ht);
2578  }
2579  }
2580  return '';
2581 }
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.
Class to manage predefined suppliers products.
Class to manage products or services.
Manage record for batch number management.
File of class to manage predefined price products or services by customer.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
convToOutputCharset($str, $pagecodefrom='UTF-8')
Convert a string into output charset (this->charset_output that should be defined to conf->file->char...
getState($id, $withcode='', $dbtouse=0, $withregion=0, $outputlangs='', $entconv=1)
Return state translated from an id.
getFormeJuridiqueLabel($code)
Retourne le nom traduit de la forme juridique.
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:745
dol_print_reduction($reduction, $langs)
Returns formated 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 formated for view output Used into pdf and HTML pages.
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_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_format_address($object, $withcountry=0, $sep="\n", $outputlangs='', $mode=0, $extralangcode='')
Return a formated address (part address/zip/town/state) according to country rules.
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
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.
if(!function_exists('utf8_encode')) if(!function_exists('utf8_decode')) getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null)
Return array of possible common substitutions.
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...
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:140
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:2514
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition: pdf.lib.php:2269
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:1409
pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails=0)
Return line total amount discount.
Definition: pdf.lib.php:2546
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition: pdf.lib.php:288
pdf_getFormat(Translate $outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition: pdf.lib.php:84
pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails=0)
Return line quantity shipped.
Definition: pdf.lib.php:2051
pdf_getlinenum($object, $i, $outputlangs, $hidedetails=0)
Return line num.
Definition: pdf.lib.php:1727
pdf_getEncryption($pathoffile)
Return if pdf file is protected/encrypted.
Definition: pdf.lib.php:234
pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price including tax.
Definition: pdf.lib.php:1929
pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref=0, $hidedesc=0, $issupplierline=0)
Output line description into PDF.
Definition: pdf.lib.php:1359
pdf_getLinkedObjects(&$object, $outputlangs)
Return linked objects to use for document generation.
Definition: pdf.lib.php:2380
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition: pdf.lib.php:313
pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails=0)
Return line ref_supplier.
Definition: pdf.lib.php:1792
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition: pdf.lib.php:2325
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:1001
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition: pdf.lib.php:1886
pdf_getlineprogress($object, $i, $outputlangs, $hidedetails=0, $hookmanager=null)
Return line percent.
Definition: pdf.lib.php:2218
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition: pdf.lib.php:1824
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0, $hookmanager=false)
Return line unit.
Definition: pdf.lib.php:2132
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition: pdf.lib.php:749
pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition: pdf.lib.php:338
pdf_admin_prepare_head()
Return array head with list of tabs to view object informations.
Definition: pdf.lib.php:46
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition: pdf.lib.php:723
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition: pdf.lib.php:1323
pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank informations for PDF generation.
Definition: pdf.lib.php:824
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition: pdf.lib.php:265
pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails=0)
Return line keep to ship quantity.
Definition: pdf.lib.php:2091
pdf_getlineref($object, $i, $outputlangs, $hidedetails=0)
Return line product ref.
Definition: pdf.lib.php:1760
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formated for output on documents.
Definition: pdf.lib.php:434
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition: pdf.lib.php:2175
pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails=0)
Return line quantity asked.
Definition: pdf.lib.php:2011
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition: pdf.lib.php:1971
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition: pdf.lib.php:126
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition: pdf.lib.php:386
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition: pdf.lib.php:769