dolibarr  x.y.z
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") || isModEnabled('facture') || isModEnabled('reception')) {
65  $head[$h][0] = DOL_URL_ROOT.'/admin/pdf_other.php';
66  $head[$h][1] = $langs->trans("Others");
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 ($targetcompany->tva_intra) {
646  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($targetcompany->tva_intra);
647  }
648  }
649 
650  // Professionnal Ids
651  if (!empty($conf->global->MAIN_PROFID1_IN_ADDRESS) && !empty($targetcompany->idprof1)) {
652  $tmp = $outputlangs->transcountrynoentities("ProfId1", $targetcompany->country_code);
653  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
654  $tmp = $reg[1];
655  }
656  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof1);
657  }
658  if (!empty($conf->global->MAIN_PROFID2_IN_ADDRESS) && !empty($targetcompany->idprof2)) {
659  $tmp = $outputlangs->transcountrynoentities("ProfId2", $targetcompany->country_code);
660  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
661  $tmp = $reg[1];
662  }
663  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof2);
664  }
665  if (!empty($conf->global->MAIN_PROFID3_IN_ADDRESS) && !empty($targetcompany->idprof3)) {
666  $tmp = $outputlangs->transcountrynoentities("ProfId3", $targetcompany->country_code);
667  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
668  $tmp = $reg[1];
669  }
670  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof3);
671  }
672  if (!empty($conf->global->MAIN_PROFID4_IN_ADDRESS) && !empty($targetcompany->idprof4)) {
673  $tmp = $outputlangs->transcountrynoentities("ProfId4", $targetcompany->country_code);
674  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
675  $tmp = $reg[1];
676  }
677  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof4);
678  }
679  if (!empty($conf->global->MAIN_PROFID5_IN_ADDRESS) && !empty($targetcompany->idprof5)) {
680  $tmp = $outputlangs->transcountrynoentities("ProfId5", $targetcompany->country_code);
681  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
682  $tmp = $reg[1];
683  }
684  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof5);
685  }
686  if (!empty($conf->global->MAIN_PROFID6_IN_ADDRESS) && !empty($targetcompany->idprof6)) {
687  $tmp = $outputlangs->transcountrynoentities("ProfId6", $targetcompany->country_code);
688  if (preg_match('/\‍((.+)\‍)/', $tmp, $reg)) {
689  $tmp = $reg[1];
690  }
691  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof6);
692  }
693 
694  // Public note
695  if (!empty($conf->global->MAIN_PUBLIC_NOTE_IN_ADDRESS)) {
696  if ($mode == 'source' && !empty($sourcecompany->note_public)) {
697  $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($sourcecompany->note_public);
698  }
699  if (($mode == 'target' || preg_match('/targetwithdetails/', $mode)) && !empty($targetcompany->note_public)) {
700  $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($targetcompany->note_public);
701  }
702  }
703  }
704  }
705 
706  return $stringaddress;
707 }
708 
709 
718 function pdf_pagehead(&$pdf, $outputlangs, $page_height)
719 {
720  global $conf;
721 
722  // Add a background image on document only if good setup of const
723  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
724  $filepath = $conf->mycompany->dir_output.'/logos/'.$conf->global->MAIN_USE_BACKGROUND_ON_PDF;
725  if (file_exists($filepath)) {
726  $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak before adding image
727  $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);
728  $pdf->SetPageMark(); // This option avoid to have the images missing on some pages
729  $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
730  }
731  }
732 }
733 
734 
744 function pdf_getSubstitutionArray($outputlangs, $exclude = null, $object = null, $onlykey = 0)
745 {
746  $substitutionarray = getCommonSubstitutionArray($outputlangs, $onlykey, $exclude, $object);
747  $substitutionarray['__FROM_NAME__'] = '__FROM_NAME__';
748  $substitutionarray['__FROM_EMAIL__'] = '__FROM_EMAIL__';
749  return $substitutionarray;
750 }
751 
752 
764 function pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
765 {
766  global $langs, $mysoc, $user;
767 
768  // Print Draft Watermark
769  if ($unit == 'pt') {
770  $k = 1;
771  } elseif ($unit == 'mm') {
772  $k = 72 / 25.4;
773  } elseif ($unit == 'cm') {
774  $k = 72 / 2.54;
775  } elseif ($unit == 'in') {
776  $k = 72;
777  }
778 
779  // Make substitution
780  $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, null);
781  complete_substitutions_array($substitutionarray, $outputlangs, null);
782  $text = make_substitutions($text, $substitutionarray, $outputlangs);
783  $text = $outputlangs->convToOutputCharset($text);
784 
785  $savx = $pdf->getX();
786  $savy = $pdf->getY();
787 
788  $watermark_angle = atan($h / $w) / 2;
789  $watermark_x_pos = 0;
790  $watermark_y_pos = $h / 3;
791  $watermark_x = $w / 2;
792  $watermark_y = $h / 3;
793  $pdf->SetFont('', 'B', 40);
794  $pdf->SetTextColor(255, 192, 203);
795  //rotate
796  $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));
797  //print watermark
798  $pdf->SetXY($watermark_x_pos, $watermark_y_pos);
799  $pdf->Cell($w - 20, 25, $outputlangs->convToOutputCharset($text), "", 2, "C", 0);
800  //antirotate
801  $pdf->_out('Q');
802 
803  $pdf->SetXY($savx, $savy);
804 }
805 
806 
819 function pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber = 0, $default_font_size = 10)
820 {
821  global $mysoc, $conf;
822 
823  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbank.class.php';
824 
825  $diffsizetitle = (empty($conf->global->PDF_DIFFSIZE_TITLE) ? 3 : $conf->global->PDF_DIFFSIZE_TITLE);
826  $diffsizecontent = (empty($conf->global->PDF_DIFFSIZE_CONTENT) ? 4 : $conf->global->PDF_DIFFSIZE_CONTENT);
827  $pdf->SetXY($curx, $cury);
828 
829  if (empty($onlynumber)) {
830  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
831  $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByTransferOnThisBankAccount').':', 0, 'L', 0);
832  $cury += 4;
833  }
834 
835  $outputlangs->load("banks");
836 
837  // Use correct name of bank id according to country
838  $bickey = "BICNumber";
839  if ($account->getCountryCode() == 'IN') {
840  $bickey = "SWIFT";
841  }
842 
843  // Get format of bank account according to its country
844  $usedetailedbban = $account->useDetailedBBAN();
845 
846  //$onlynumber=0; $usedetailedbban=1; // For tests
847  if ($usedetailedbban) {
848  $savcurx = $curx;
849 
850  if (empty($onlynumber)) {
851  $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
852  $pdf->SetXY($curx, $cury);
853  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
854  $cury += 3;
855  }
856 
857  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
858  // Note:
859  // bank = code_banque (FR), sort code (GB, IR. Example: 12-34-56)
860  // desk = code guichet (FR), used only when $usedetailedbban = 1
861  // number = account number
862  // key = check control key used only when $usedetailedbban = 1
863  if (empty($onlynumber)) {
864  $pdf->line($curx + 1, $cury + 1, $curx + 1, $cury + 6);
865  }
866 
867 
868  foreach ($account->getFieldsToShow() as $val) {
869  $pdf->SetXY($curx, $cury + 4);
870  $pdf->SetFont('', '', $default_font_size - 3);
871 
872  if ($val == 'BankCode') {
873  // Bank code
874  $tmplength = 18;
875  $content = $account->code_banque;
876  } elseif ($val == 'DeskCode') {
877  // Desk
878  $tmplength = 18;
879  $content = $account->code_guichet;
880  } elseif ($val == 'BankAccountNumber') {
881  // Number
882  $tmplength = 24;
883  $content = $account->number;
884  } elseif ($val == 'BankAccountNumberKey') {
885  // Key
886  $tmplength = 15;
887  $content = $account->cle_rib;
888  } elseif ($val == 'IBAN' || $val == 'BIC') {
889  // Key
890  $tmplength = 0;
891  $content = '';
892  } else {
893  dol_print_error($account->db, 'Unexpected value for getFieldsToShow: '.$val);
894  break;
895  }
896 
897  $pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($content), 0, 'C', 0);
898  $pdf->SetXY($curx, $cury + 1);
899  $curx += $tmplength;
900  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
901  $pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities($val), 0, 'C', 0);
902  if (empty($onlynumber)) {
903  $pdf->line($curx, $cury + 1, $curx, $cury + 7);
904  }
905  }
906 
907  $curx = $savcurx;
908  $cury += 8;
909  }
910  } else {
911  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
912  $pdf->SetXY($curx, $cury);
913  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
914  $cury += 3;
915 
916  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
917  $pdf->SetXY($curx, $cury);
918  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("BankAccountNumber").': '.$outputlangs->convToOutputCharset($account->number), 0, 'L', 0);
919  $cury += 3;
920 
921  if ($diffsizecontent <= 2) {
922  $cury += 1;
923  }
924  }
925 
926  $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
927 
928  if (empty($onlynumber) && !empty($account->domiciliation)) {
929  $pdf->SetXY($curx, $cury);
930  $val = $outputlangs->transnoentities("Residence").': '.$outputlangs->convToOutputCharset($account->domiciliation);
931  $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
932  //$nboflines=dol_nboflines_bis($val,120);
933  //$cury+=($nboflines*3)+2;
934  $tmpy = $pdf->getStringHeight(100, $val);
935  $cury += $tmpy;
936  }
937 
938  if (!empty($account->proprio)) {
939  $pdf->SetXY($curx, $cury);
940  $val = $outputlangs->transnoentities("BankAccountOwner").': '.$outputlangs->convToOutputCharset($account->proprio);
941  $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
942  $tmpy = $pdf->getStringHeight(100, $val);
943  $cury += $tmpy;
944  } elseif (!$usedetailedbban) {
945  $cury += 1;
946  }
947 
948  // Use correct name of bank id according to country
949  $ibankey = FormBank::getIBANLabel($account);
950 
951  if (!empty($account->iban)) {
952  //Remove whitespaces to ensure we are dealing with the format we expect
953  $ibanDisplay_temp = str_replace(' ', '', $outputlangs->convToOutputCharset($account->iban));
954  $ibanDisplay = "";
955 
956  $nbIbanDisplay_temp = dol_strlen($ibanDisplay_temp);
957  for ($i = 0; $i < $nbIbanDisplay_temp; $i++) {
958  $ibanDisplay .= $ibanDisplay_temp[$i];
959  if ($i % 4 == 3 && $i > 0) {
960  $ibanDisplay .= " ";
961  }
962  }
963 
964  $pdf->SetFont('', 'B', $default_font_size - 3);
965  $pdf->SetXY($curx, $cury);
966  $pdf->MultiCell(100, 3, $outputlangs->transnoentities($ibankey).': '.$ibanDisplay, 0, 'L', 0);
967  $cury += 3;
968  }
969 
970  if (!empty($account->bic)) {
971  $pdf->SetFont('', 'B', $default_font_size - 3);
972  $pdf->SetXY($curx, $cury);
973  $pdf->MultiCell(100, 3, $outputlangs->transnoentities($bickey).': '.$outputlangs->convToOutputCharset($account->bic), 0, 'L', 0);
974  }
975 
976  return $pdf->getY();
977 }
978 
996 function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails = 0, $hidefreetext = 0, $page_largeur = 0, $watermark = '')
997 {
998  global $conf, $user, $mysoc, $hookmanager;
999 
1000  $outputlangs->load("dict");
1001  $line = '';
1002  $reg = array();
1003 
1004  $dims = $pdf->getPageDimensions();
1005 
1006  // Line of free text
1007  if (empty($hidefreetext) && !empty($conf->global->$paramfreetext)) {
1008  $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
1009  // More substitution keys
1010  $substitutionarray['__FROM_NAME__'] = $fromcompany->name;
1011  $substitutionarray['__FROM_EMAIL__'] = $fromcompany->email;
1012  complete_substitutions_array($substitutionarray, $outputlangs, $object);
1013  $newfreetext = make_substitutions($conf->global->$paramfreetext, $substitutionarray, $outputlangs);
1014 
1015  // Make a change into HTML code to allow to include images from medias directory.
1016  // <img alt="" src="/dolibarr_dev/htdocs/viewimage.php?modulepart=medias&amp;entity=1&amp;file=image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1017  // become
1018  // <img alt="" src="'.DOL_DATA_ROOT.'/medias/image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
1019  $newfreetext = preg_replace('/(<img.*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)("[^\/]*\/>)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $newfreetext);
1020 
1021  $line .= $outputlangs->convToOutputCharset($newfreetext);
1022  }
1023 
1024  // First line of company infos
1025  $line1 = "";
1026  $line2 = "";
1027  $line3 = "";
1028  $line4 = "";
1029 
1030  if ($showdetails == 1 || $showdetails == 3) {
1031  // Company name
1032  if ($fromcompany->name) {
1033  $line1 .= ($line1 ? " - " : "").$outputlangs->transnoentities("RegisteredOffice").": ".$fromcompany->name;
1034  }
1035  // Address
1036  if ($fromcompany->address) {
1037  $line1 .= ($line1 ? " - " : "").str_replace("\n", ", ", $fromcompany->address);
1038  }
1039  // Zip code
1040  if ($fromcompany->zip) {
1041  $line1 .= ($line1 ? " - " : "").$fromcompany->zip;
1042  }
1043  // Town
1044  if ($fromcompany->town) {
1045  $line1 .= ($line1 ? " " : "").$fromcompany->town;
1046  }
1047  // Country
1048  if ($fromcompany->country) {
1049  $line1 .= ($line1 ? ", " : "").$fromcompany->country;
1050  }
1051  // Phone
1052  if ($fromcompany->phone) {
1053  $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Phone").": ".$fromcompany->phone;
1054  }
1055  // Fax
1056  if ($fromcompany->fax) {
1057  $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Fax").": ".$fromcompany->fax;
1058  }
1059 
1060  // URL
1061  if ($fromcompany->url) {
1062  $line2 .= ($line2 ? " - " : "").$fromcompany->url;
1063  }
1064  // Email
1065  if ($fromcompany->email) {
1066  $line2 .= ($line2 ? " - " : "").$fromcompany->email;
1067  }
1068  }
1069  if ($showdetails == 2 || $showdetails == 3 || (!empty($fromcompany->country_code) && $fromcompany->country_code == 'DE')) {
1070  // Managers
1071  if ($fromcompany->managers) {
1072  $line2 .= ($line2 ? " - " : "").$fromcompany->managers;
1073  }
1074  }
1075 
1076  // Line 3 of company infos
1077  // Juridical status
1078  if (!empty($fromcompany->forme_juridique_code) && $fromcompany->forme_juridique_code) {
1079  $line3 .= ($line3 ? " - " : "").$outputlangs->convToOutputCharset(getFormeJuridiqueLabel($fromcompany->forme_juridique_code));
1080  }
1081  // Capital
1082  if (!empty($fromcompany->capital)) {
1083  $tmpamounttoshow = price2num($fromcompany->capital); // This field is a free string or a float
1084  if (is_numeric($tmpamounttoshow) && $tmpamounttoshow > 0) {
1085  $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", price($tmpamounttoshow, 0, $outputlangs, 0, 0, 0, $conf->currency));
1086  } elseif (!empty($fromcompany->capital)) {
1087  $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", $fromcompany->capital, $outputlangs);
1088  }
1089  }
1090  // Prof Id 1
1091  if (!empty($fromcompany->idprof1) && $fromcompany->idprof1 && ($fromcompany->country_code != 'FR' || !$fromcompany->idprof2)) {
1092  $field = $outputlangs->transcountrynoentities("ProfId1", $fromcompany->country_code);
1093  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1094  $field = $reg[1];
1095  }
1096  $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof1);
1097  }
1098  // Prof Id 2
1099  if (!empty($fromcompany->idprof2) && $fromcompany->idprof2) {
1100  $field = $outputlangs->transcountrynoentities("ProfId2", $fromcompany->country_code);
1101  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1102  $field = $reg[1];
1103  }
1104  $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof2);
1105  }
1106 
1107  // Line 4 of company infos
1108  // Prof Id 3
1109  if (!empty($fromcompany->idprof3) && $fromcompany->idprof3) {
1110  $field = $outputlangs->transcountrynoentities("ProfId3", $fromcompany->country_code);
1111  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1112  $field = $reg[1];
1113  }
1114  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof3);
1115  }
1116  // Prof Id 4
1117  if (!empty($fromcompany->idprof4) && $fromcompany->idprof4) {
1118  $field = $outputlangs->transcountrynoentities("ProfId4", $fromcompany->country_code);
1119  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1120  $field = $reg[1];
1121  }
1122  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof4);
1123  }
1124  // Prof Id 5
1125  if (!empty($fromcompany->idprof5) && $fromcompany->idprof5) {
1126  $field = $outputlangs->transcountrynoentities("ProfId5", $fromcompany->country_code);
1127  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1128  $field = $reg[1];
1129  }
1130  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof5);
1131  }
1132  // Prof Id 6
1133  if (!empty($fromcompany->idprof6) && $fromcompany->idprof6) {
1134  $field = $outputlangs->transcountrynoentities("ProfId6", $fromcompany->country_code);
1135  if (preg_match('/\‍((.*)\‍)/i', $field, $reg)) {
1136  $field = $reg[1];
1137  }
1138  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof6);
1139  }
1140  // IntraCommunautary VAT
1141  if (!empty($fromcompany->tva_intra) && $fromcompany->tva_intra != '') {
1142  $line4 .= ($line4 ? " - " : "").$outputlangs->transnoentities("VATIntraShort").": ".$outputlangs->convToOutputCharset($fromcompany->tva_intra);
1143  }
1144 
1145  $pdf->SetFont('', '', 7);
1146  $pdf->SetDrawColor(224, 224, 224);
1147  // Option for footer text color
1148  if (!empty($conf->global->PDF_FOOTER_TEXT_COLOR)) {
1149  list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_TEXT_COLOR, '%d, %d, %d');
1150  $pdf->SetTextColor($r, $g, $b);
1151  }
1152 
1153  // The start of the bottom of this page footer is positioned according to # of lines
1154  $freetextheight = 0;
1155  if ($line) { // Free text
1156  //$line="sample text<br>\nfd<strong>sf</strong>sdf<br>\nghfghg<br>";
1157  if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT)) {
1158  $width = 20000;
1159  $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.
1160  if (!empty($conf->global->MAIN_USE_AUTOWRAP_ON_FREETEXT)) {
1161  $width = 200;
1162  $align = 'C';
1163  }
1164  $freetextheight = $pdf->getStringHeight($width, $line);
1165  } else {
1166  $freetextheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($line, 1, 'UTF-8', 0)); // New method (works for HTML content)
1167  //print '<br>'.$freetextheight;exit;
1168  }
1169  }
1170 
1171  // For customize footer
1172  if (is_object($hookmanager)) {
1173  $parameters = array('line1' => $line1, 'line2' => $line2, 'line3' => $line3, 'line4' => $line4, 'outputlangs'=>$outputlangs);
1174  $action = '';
1175  $hookmanager->executeHooks('pdf_pagefoot', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1176  if (!empty($hookmanager->resPrint) && $hidefreetext == 0) {
1177  $mycustomfooter = $hookmanager->resPrint;
1178  $mycustomfooterheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1179 
1180  $marginwithfooter = $marge_basse + $freetextheight + $mycustomfooterheight;
1181  $posy = (float) $marginwithfooter;
1182 
1183  // Option for footer background color (without freetext zone)
1184  if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1185  list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
1186  $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
1187  $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', '', $fill_color = array($r, $g, $b));
1188  $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
1189  }
1190 
1191  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(0, 0); } // Option for disable auto pagebreak
1192  if ($line) { // Free text
1193  $pdf->SetXY($dims['lm'], -$posy);
1194  if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1195  $pdf->MultiCell(0, 3, $line, 0, $align, 0);
1196  } else {
1197  $pdf->writeHTMLCell($pdf->page_largeur - $pdf->margin_left - $pdf->margin_right, $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1198  }
1199  $posy -= $freetextheight;
1200  }
1201  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(1, 0); } // Restore pagebreak
1202 
1203  $pdf->SetY(-$posy);
1204 
1205  // Hide footer line if footer background color is set
1206  if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1207  $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1208  }
1209 
1210  // Option for set top margin height of footer after freetext
1211  if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1212  $posy -= floatval(getDolGlobalString('PDF_FOOTER_TOP_MARGIN'));
1213  } else {
1214  $posy--;
1215  }
1216 
1217  if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(0, 0); } // Option for disable auto pagebreak
1218  $pdf->writeHTMLCell($pdf->page_largeur - $pdf->margin_left - $pdf->margin_right, $mycustomfooterheight, $dims['lm'], $dims['hk'] - $posy, dol_htmlentitiesbr($mycustomfooter, 1, 'UTF-8', 0));
1219  if (getDolGlobalInt('PDF_FOOTER_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(1, 0); } // Restore pagebreak
1220 
1221  $posy -= $mycustomfooterheight - 3;
1222  } else {
1223  // Else default footer
1224  $marginwithfooter = $marge_basse + $freetextheight + (!empty($line1) ? 3 : 0) + (!empty($line2) ? 3 : 0) + (!empty($line3) ? 3 : 0) + (!empty($line4) ? 3 : 0);
1225  $posy = (float) $marginwithfooter;
1226 
1227  // Option for footer background color (without freetext zone)
1228  if (getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1229  list($r, $g, $b) = sscanf($conf->global->PDF_FOOTER_BACKGROUND_COLOR, '%d, %d, %d');
1230  $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak
1231  $pdf->Rect(0, $dims['hk'] - $posy + $freetextheight, $dims['wk'] + 1, $marginwithfooter + 1, 'F', '', $fill_color = array($r, $g, $b));
1232  $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
1233  }
1234 
1235  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(0, 0); } // Option for disable auto pagebreak
1236  if ($line) { // Free text
1237  $pdf->SetXY($dims['lm'], -$posy);
1238  if (!getDolGlobalString('PDF_ALLOW_HTML_FOR_FREE_TEXT')) { // by default
1239  $pdf->MultiCell(0, 3, $line, 0, $align, 0);
1240  } else {
1241  $pdf->writeHTMLCell($pdf->page_largeur - $pdf->margin_left - $pdf->margin_right, $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1242  }
1243  $posy -= $freetextheight;
1244  }
1245  if (getDolGlobalInt('PDF_FREETEXT_DISABLE_PAGEBREAK') === 1) { $pdf->SetAutoPageBreak(1, 0); } // Restore pagebreak
1246 
1247  $pdf->SetY(-$posy);
1248 
1249  // Hide footer line if footer background color is set
1250  if (!getDolGlobalString('PDF_FOOTER_BACKGROUND_COLOR')) {
1251  $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1252  }
1253 
1254  // Option for set top margin height of footer after freetext
1255  if (getDolGlobalString('PDF_FOOTER_TOP_MARGIN') || getDolGlobalInt('PDF_FOOTER_TOP_MARGIN') === 0) {
1256  $posy -= floatval(getDolGlobalString('PDF_FOOTER_TOP_MARGIN'));
1257  } else {
1258  $posy--;
1259  }
1260 
1261  if (!empty($line1)) {
1262  $pdf->SetFont('', 'B', 7);
1263  $pdf->SetXY($dims['lm'], -$posy);
1264  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line1, 0, 'C', 0);
1265  $posy -= 3;
1266  $pdf->SetFont('', '', 7);
1267  }
1268 
1269  if (!empty($line2)) {
1270  $pdf->SetFont('', 'B', 7);
1271  $pdf->SetXY($dims['lm'], -$posy);
1272  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line2, 0, 'C', 0);
1273  $posy -= 3;
1274  $pdf->SetFont('', '', 7);
1275  }
1276 
1277  if (!empty($line3)) {
1278  $pdf->SetXY($dims['lm'], -$posy);
1279  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line3, 0, 'C', 0);
1280  }
1281 
1282  if (!empty($line4)) {
1283  $posy -= 3;
1284  $pdf->SetXY($dims['lm'], -$posy);
1285  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line4, 0, 'C', 0);
1286  }
1287  }
1288  }
1289  // Show page nb only on iso languages (so default Helvetica font)
1290  if (strtolower(pdf_getPDFFont($outputlangs)) == 'helvetica') {
1291  $pdf->SetXY($dims['wk'] - $dims['rm'] - 18, -$posy);
1292  //$pdf->MultiCell(18, 2, $pdf->getPageNumGroupAlias().' / '.$pdf->getPageGroupAlias(), 0, 'R', 0);
1293  $pdf->MultiCell(18, 2, $pdf->PageNo().' / '.$pdf->getAliasNbPages(), 0, 'R', 0);
1294  }
1295 
1296  // Show Draft Watermark
1297  if (!empty($watermark)) {
1298  pdf_watermark($pdf, $outputlangs, $page_hauteur, $page_largeur, 'mm', $watermark);
1299  }
1300 
1301  return $marginwithfooter;
1302 }
1303 
1318 function pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
1319 {
1320  $linkedobjects = pdf_getLinkedObjects($object, $outputlangs);
1321  if (!empty($linkedobjects)) {
1322  foreach ($linkedobjects as $linkedobject) {
1323  $reftoshow = $linkedobject["ref_title"].' : '.$linkedobject["ref_value"];
1324  if (!empty($linkedobject["date_value"])) {
1325  $reftoshow .= ' / '.$linkedobject["date_value"];
1326  }
1327 
1328  $posy += 3;
1329  $pdf->SetXY($posx, $posy);
1330  $pdf->SetFont('', '', $default_font_size - 2);
1331  $pdf->MultiCell($w, $h, $reftoshow, '', $align);
1332  }
1333  }
1334 
1335  return $pdf->getY();
1336 }
1337 
1354 function pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
1355 {
1356  global $db, $conf, $langs, $hookmanager;
1357 
1358  $reshook = 0;
1359  $result = '';
1360  //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) ) )
1361  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
1362  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1363  if (!empty($object->lines[$i]->fk_parent_line)) {
1364  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1365  }
1366  $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);
1367  $action = '';
1368  $reshook = $hookmanager->executeHooks('pdf_writelinedesc', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1369 
1370  if (!empty($hookmanager->resPrint)) {
1371  $result .= $hookmanager->resPrint;
1372  }
1373  }
1374  if (empty($reshook)) {
1375  $labelproductservice = pdf_getlinedesc($object, $i, $outputlangs, $hideref, $hidedesc, $issupplierline);
1376 
1377  //var_dump($labelproductservice);exit;
1378 
1379  // 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"
1380  // We make the reverse, so PDF generation has the real URL.
1381  $nbrep = 0;
1382  $labelproductservice = preg_replace('/(<img[^>]*src=")([^"]*)(&amp;)([^"]*")/', '\1\2&\4', $labelproductservice, -1, $nbrep);
1383 
1384  //var_dump($labelproductservice);exit;
1385 
1386  // Description
1387  $pdf->writeHTMLCell($w, $h, $posx, $posy, $outputlangs->convToOutputCharset($labelproductservice), 0, 1, false, true, 'J', true);
1388  $result .= $labelproductservice;
1389  }
1390  return $result;
1391 }
1392 
1404 function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
1405 {
1406  global $db, $conf, $langs;
1407 
1408  $idprod = (!empty($object->lines[$i]->fk_product) ? $object->lines[$i]->fk_product : false);
1409  $label = (!empty($object->lines[$i]->label) ? $object->lines[$i]->label : (!empty($object->lines[$i]->product_label) ? $object->lines[$i]->product_label : ''));
1410  $desc = (!empty($object->lines[$i]->desc) ? $object->lines[$i]->desc : (!empty($object->lines[$i]->description) ? $object->lines[$i]->description : ''));
1411  $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
1412  $note = (!empty($object->lines[$i]->note) ? $object->lines[$i]->note : '');
1413  $dbatch = (!empty($object->lines[$i]->detail_batch) ? $object->lines[$i]->detail_batch : false);
1414 
1415  if ($issupplierline) {
1416  include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
1417  $prodser = new ProductFournisseur($db);
1418  } else {
1419  include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
1420  $prodser = new Product($db);
1421 
1422  if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
1423  include_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
1424  }
1425  }
1426 
1427  if ($idprod) {
1428  $prodser->fetch($idprod);
1429  // If a predefined product and multilang and on other lang, we renamed label with label translated
1430  if (getDolGlobalInt('MAIN_MULTILANGS') && ($outputlangs->defaultlang != $langs->defaultlang)) {
1431  $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)
1432 
1433  // 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
1434  // ($textwasnotmodified is replaced with $textwasmodifiedorcompleted and we add completion).
1435 
1436  // Set label
1437  // 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.
1438  //var_dump($outputlangs->defaultlang.' - '.$langs->defaultlang.' - '.$label.' - '.$prodser->label);exit;
1439  $textwasnotmodified = ($label == $prodser->label);
1440  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1441  $label = $prodser->multilangs[$outputlangs->defaultlang]["label"];
1442  }
1443 
1444  // Set desc
1445  // Manage HTML entities description test because $prodser->description is store with htmlentities but $desc no
1446  $textwasnotmodified = false;
1447  if (!empty($desc) && dol_textishtml($desc) && !empty($prodser->description) && dol_textishtml($prodser->description)) {
1448  $textwasnotmodified = (strpos(dol_html_entity_decode($desc, ENT_QUOTES | ENT_HTML5), dol_html_entity_decode($prodser->description, ENT_QUOTES | ENT_HTML5)) !== false);
1449  } else {
1450  $textwasnotmodified = ($desc == $prodser->description);
1451  }
1452  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["description"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1453  $desc = $prodser->multilangs[$outputlangs->defaultlang]["description"];
1454  }
1455 
1456  // Set note
1457  $textwasnotmodified = ($note == $prodser->note_public);
1458  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["other"]) && ($textwasnotmodified || $translatealsoifmodified)) {
1459  $note = $prodser->multilangs[$outputlangs->defaultlang]["other"];
1460  }
1461  }
1462  } 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
1463  $desc = str_replace('(DEPOSIT)', $outputlangs->trans('Deposit'), $desc);
1464  }
1465 
1466  if (empty($conf->global->PDF_HIDE_PRODUCT_LABEL_IN_SUPPLIER_LINES)) {
1467  // Description short of product line
1468  $libelleproduitservice = $label;
1469  if (!empty($libelleproduitservice) && !empty($conf->global->PDF_BOLD_PRODUCT_LABEL)) {
1470  // Adding <b> may convert the original string into a HTML string. Sowe have to first
1471  // convert \n into <br> we text is not already HTML.
1472  if (!dol_textishtml($libelleproduitservice)) {
1473  $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1474  }
1475  $libelleproduitservice = '<b>'.$libelleproduitservice.'</b>';
1476  }
1477  }
1478 
1479 
1480  // Add ref of subproducts
1481  if (!empty($conf->global->SHOW_SUBPRODUCT_REF_IN_PDF)) {
1482  $prodser->get_sousproduits_arbo();
1483  if (!empty($prodser->sousprods) && is_array($prodser->sousprods) && count($prodser->sousprods)) {
1484  $tmparrayofsubproducts = reset($prodser->sousprods);
1485  if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF)) {
1486  foreach ($tmparrayofsubproducts as $subprodval) {
1487  $libelleproduitservice = dol_concatdesc($libelleproduitservice, " * ".$subprodval[3].' ('.$subprodval[1].')');
1488  }
1489  } else {
1490  foreach ($tmparrayofsubproducts as $subprodval) {
1491  $libelleproduitservice = dol_concatdesc($libelleproduitservice, " * ".$subprodval[5].(($subprodval[5] && $subprodval[3]) ? ' - ' : '').$subprodval[3].' ('.$subprodval[1].')');
1492  }
1493  }
1494  }
1495  }
1496 
1497  // Description long of product line
1498  if (!empty($desc) && ($desc != $label)) {
1499  if ($desc == '(CREDIT_NOTE)' && $object->lines[$i]->fk_remise_except) {
1500  $discount = new DiscountAbsolute($db);
1501  $discount->fetch($object->lines[$i]->fk_remise_except);
1502  $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1503  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromCreditNote", $sourceref);
1504  } elseif ($desc == '(DEPOSIT)' && $object->lines[$i]->fk_remise_except) {
1505  $discount = new DiscountAbsolute($db);
1506  $discount->fetch($object->lines[$i]->fk_remise_except);
1507  $sourceref = !empty($discount->discount_type) ? $discount->ref_invoice_supplier_source : $discount->ref_facture_source;
1508  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromDeposit", $sourceref);
1509  // Add date of deposit
1510  if (!empty($conf->global->INVOICE_ADD_DEPOSIT_DATE)) {
1511  $libelleproduitservice .= ' ('.dol_print_date($discount->datec, 'day', '', $outputlangs).')';
1512  }
1513  } elseif ($desc == '(EXCESS RECEIVED)' && $object->lines[$i]->fk_remise_except) {
1514  $discount = new DiscountAbsolute($db);
1515  $discount->fetch($object->lines[$i]->fk_remise_except);
1516  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessReceived", $discount->ref_facture_source);
1517  } elseif ($desc == '(EXCESS PAID)' && $object->lines[$i]->fk_remise_except) {
1518  $discount = new DiscountAbsolute($db);
1519  $discount->fetch($object->lines[$i]->fk_remise_except);
1520  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessPaid", $discount->ref_invoice_supplier_source);
1521  } else {
1522  if ($idprod) {
1523  // Check if description must be output
1524  if (!empty($object->element)) {
1525  $tmpkey = 'MAIN_DOCUMENTS_HIDE_DESCRIPTION_FOR_'.strtoupper($object->element);
1526  if (!empty($conf->global->$tmpkey)) {
1527  $hidedesc = 1;
1528  }
1529  }
1530  if (empty($hidedesc)) {
1531  if (!empty($conf->global->MAIN_DOCUMENTS_DESCRIPTION_FIRST)) {
1532  $libelleproduitservice = dol_concatdesc($desc, $libelleproduitservice);
1533  } else {
1534  if (!empty($conf->global->HIDE_LABEL_VARIANT_PDF) && $prodser->isVariant()) {
1535  $libelleproduitservice = $desc;
1536  } else {
1537  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1538  }
1539  }
1540  }
1541  } else {
1542  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desc);
1543  }
1544  }
1545  }
1546 
1547  // We add ref of product (and supplier ref if defined)
1548  $prefix_prodserv = "";
1549  $ref_prodserv = "";
1550  if (!empty($conf->global->PRODUCT_ADD_TYPE_IN_DOCUMENTS)) { // In standard mode, we do not show this
1551  if ($prodser->isService()) {
1552  $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service")." ";
1553  } else {
1554  $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Product")." ";
1555  }
1556  }
1557 
1558  if (empty($hideref)) {
1559  if ($issupplierline) {
1560  if (empty($conf->global->PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES)) { // Common case
1561  $ref_prodserv = $prodser->ref; // Show local ref
1562  if ($ref_supplier) {
1563  $ref_prodserv .= ($prodser->ref ? ' (' : '').$outputlangs->transnoentitiesnoconv("SupplierRef").' '.$ref_supplier.($prodser->ref ? ')' : '');
1564  }
1565  } elseif ($conf->global->PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES == 1) {
1566  $ref_prodserv = $ref_supplier;
1567  } elseif ($conf->global->PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES == 2) {
1568  $ref_prodserv = $ref_supplier.' ('.$outputlangs->transnoentitiesnoconv("InternalRef").' '.$prodser->ref.')';
1569  }
1570  } else {
1571  $ref_prodserv = $prodser->ref; // Show local ref only
1572 
1573  if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
1574  $productCustomerPriceStatic = new Productcustomerprice($db);
1575  $filter = array('fk_product' => $idprod, 'fk_soc' => $object->socid);
1576 
1577  $nbCustomerPrices = $productCustomerPriceStatic->fetchAll('', '', 1, 0, $filter);
1578 
1579  if ($nbCustomerPrices > 0) {
1580  $productCustomerPrice = $productCustomerPriceStatic->lines[0];
1581 
1582  if (!empty($productCustomerPrice->ref_customer)) {
1583  switch ($conf->global->PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE) {
1584  case 1:
1585  $ref_prodserv = $productCustomerPrice->ref_customer;
1586  break;
1587 
1588  case 2:
1589  $ref_prodserv = $productCustomerPrice->ref_customer . ' (' . $outputlangs->transnoentitiesnoconv('InternalRef') . ' ' . $ref_prodserv . ')';
1590  break;
1591 
1592  default:
1593  $ref_prodserv = $ref_prodserv . ' (' . $outputlangs->transnoentitiesnoconv('RefCustomer') . ' ' . $productCustomerPrice->ref_customer . ')';
1594  }
1595  }
1596  }
1597  }
1598  }
1599 
1600  if (!empty($libelleproduitservice) && !empty($ref_prodserv)) {
1601  $ref_prodserv .= " - ";
1602  }
1603  }
1604 
1605  if (!empty($ref_prodserv) && !empty($conf->global->PDF_BOLD_PRODUCT_REF_AND_PERIOD)) {
1606  if (!dol_textishtml($libelleproduitservice)) {
1607  $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1608  }
1609  $ref_prodserv = '<b>'.$ref_prodserv.'</b>';
1610  // $prefix_prodserv and $ref_prodser are not HTML var
1611  }
1612  $libelleproduitservice = $prefix_prodserv.$ref_prodserv.$libelleproduitservice;
1613 
1614  // Add an additional description for the category products
1615  if (!empty($conf->global->CATEGORY_ADD_DESC_INTO_DOC) && $idprod && isModEnabled('categorie')) {
1616  include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1617  $categstatic = new Categorie($db);
1618  // recovering the list of all the categories linked to product
1619  $tblcateg = $categstatic->containing($idprod, Categorie::TYPE_PRODUCT);
1620  foreach ($tblcateg as $cate) {
1621  // Adding the descriptions if they are filled
1622  $desccateg = $cate->description;
1623  if ($desccateg) {
1624  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $desccateg);
1625  }
1626  }
1627  }
1628 
1629  if (!empty($object->lines[$i]->date_start) || !empty($object->lines[$i]->date_end)) {
1630  $format = 'day';
1631  $period = '';
1632  // Show duration if exists
1633  if ($object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1634  $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)).')';
1635  }
1636  if ($object->lines[$i]->date_start && !$object->lines[$i]->date_end) {
1637  $period = '('.$outputlangs->transnoentitiesnoconv('DateFrom', dol_print_date($object->lines[$i]->date_start, $format, false, $outputlangs)).')';
1638  }
1639  if (!$object->lines[$i]->date_start && $object->lines[$i]->date_end) {
1640  $period = '('.$outputlangs->transnoentitiesnoconv('DateUntil', dol_print_date($object->lines[$i]->date_end, $format, false, $outputlangs)).')';
1641  }
1642  //print '>'.$outputlangs->charset_output.','.$period;
1643  if (!empty($conf->global->PDF_BOLD_PRODUCT_REF_AND_PERIOD)) {
1644  if (!dol_textishtml($libelleproduitservice)) {
1645  $libelleproduitservice = str_replace("\n", '<br>', $libelleproduitservice);
1646  }
1647  $libelleproduitservice .= '<br><b style="color:#333666;" ><em>'.$period.'</em></b>';
1648  } else {
1649  $libelleproduitservice = dol_concatdesc($libelleproduitservice, $period);
1650  }
1651  //print $libelleproduitservice;
1652  }
1653 
1654  // Show information for lot
1655  if (!empty($dbatch)) {
1656  // $object is a shipment.
1657  //var_dump($object->lines[$i]->details_entrepot); // array from llx_expeditiondet (we can have seral lines for one fk_origin_line)
1658  //var_dump($object->lines[$i]->detail_batch); // array from llx_expeditiondet_batch (each line with a lot is linked to llx_expeditiondet)
1659 
1660  include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
1661  include_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
1662  $tmpwarehouse = new Entrepot($db);
1663  $tmpproductbatch = new Productbatch($db);
1664 
1665  $format = 'day';
1666  foreach ($dbatch as $detail) {
1667  $dte = array();
1668  if ($detail->eatby) {
1669  $dte[] = $outputlangs->transnoentitiesnoconv('printEatby', dol_print_date($detail->eatby, $format, false, $outputlangs));
1670  }
1671  if ($detail->sellby) {
1672  $dte[] = $outputlangs->transnoentitiesnoconv('printSellby', dol_print_date($detail->sellby, $format, false, $outputlangs));
1673  }
1674  if ($detail->batch) {
1675  $dte[] = $outputlangs->transnoentitiesnoconv('printBatch', $detail->batch);
1676  }
1677  $dte[] = $outputlangs->transnoentitiesnoconv('printQty', $detail->qty);
1678 
1679  // Add also info of planned warehouse for lot
1680  if ($object->element == 'shipping' && $detail->fk_origin_stock > 0 && getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1681  $resproductbatch = $tmpproductbatch->fetch($detail->fk_origin_stock);
1682  if ($resproductbatch > 0) {
1683  $reswarehouse = $tmpwarehouse->fetch($tmpproductbatch->warehouseid);
1684  if ($reswarehouse > 0) {
1685  $dte[] = $tmpwarehouse->ref;
1686  }
1687  }
1688  }
1689 
1690  $libelleproduitservice .= "__N__ ".implode(" - ", $dte);
1691  }
1692  } else {
1693  if (getDolGlobalInt('PRODUCTBATCH_SHOW_WAREHOUSE_ON_SHIPMENT')) {
1694  // TODO Show warehouse for shipment line without batch
1695  }
1696  }
1697 
1698  // Now we convert \n into br
1699  if (dol_textishtml($libelleproduitservice)) {
1700  $libelleproduitservice = preg_replace('/__N__/', '<br>', $libelleproduitservice);
1701  } else {
1702  $libelleproduitservice = preg_replace('/__N__/', "\n", $libelleproduitservice);
1703  }
1704  $libelleproduitservice = dol_htmlentitiesbr($libelleproduitservice, 1);
1705 
1706  return $libelleproduitservice;
1707 }
1708 
1718 function pdf_getlinenum($object, $i, $outputlangs, $hidedetails = 0)
1719 {
1720  global $hookmanager;
1721 
1722  $reshook = 0;
1723  $result = '';
1724  //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) ) )
1725  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
1726  $special_code = $object->lines[$i]->special_code;
1727  if (!empty($object->lines[$i]->fk_parent_line)) {
1728  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1729  }
1730  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1731  $action = '';
1732  $reshook = $hookmanager->executeHooks('pdf_getlinenum', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1733  $result .= $hookmanager->resPrint;
1734  }
1735  if (empty($reshook)) {
1736  $result .= dol_htmlentitiesbr($object->lines[$i]->num);
1737  }
1738  return $result;
1739 }
1740 
1741 
1751 function pdf_getlineref($object, $i, $outputlangs, $hidedetails = 0)
1752 {
1753  global $hookmanager;
1754 
1755  $reshook = 0;
1756  $result = '';
1757  //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) ) )
1758  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
1759  $special_code = $object->lines[$i]->special_code;
1760  if (!empty($object->lines[$i]->fk_parent_line)) {
1761  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1762  }
1763  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1764  $action = '';
1765  $reshook = $hookmanager->executeHooks('pdf_getlineref', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1766  $result .= $hookmanager->resPrint;
1767  }
1768  if (empty($reshook)) {
1769  $result .= dol_htmlentitiesbr($object->lines[$i]->product_ref);
1770  }
1771  return $result;
1772 }
1773 
1783 function pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails = 0)
1784 {
1785  global $hookmanager;
1786 
1787  $reshook = 0;
1788  $result = '';
1789  //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) ) )
1790  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
1791  $special_code = $object->lines[$i]->special_code;
1792  if (!empty($object->lines[$i]->fk_parent_line)) {
1793  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1794  }
1795  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1796  $action = '';
1797  $reshook = $hookmanager->executeHooks('pdf_getlineref_supplier', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1798  $result .= $hookmanager->resPrint;
1799  }
1800  if (empty($reshook)) {
1801  $result .= dol_htmlentitiesbr($object->lines[$i]->ref_supplier);
1802  }
1803  return $result;
1804 }
1805 
1815 function pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails = 0)
1816 {
1817  global $conf, $hookmanager, $mysoc;
1818 
1819  $result = '';
1820  $reshook = 0;
1821  //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) ) )
1822  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
1823  $special_code = $object->lines[$i]->special_code;
1824  if (!empty($object->lines[$i]->fk_parent_line)) {
1825  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1826  }
1827  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1828  $action = '';
1829  $reshook = $hookmanager->executeHooks('pdf_getlinevatrate', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1830 
1831  if (!empty($hookmanager->resPrint)) {
1832  $result .= $hookmanager->resPrint;
1833  }
1834  }
1835  if (empty($reshook)) {
1836  if (empty($hidedetails) || $hidedetails > 1) {
1837  $tmpresult = '';
1838 
1839  $tmpresult .= vatrate($object->lines[$i]->tva_tx, 0, $object->lines[$i]->info_bits, -1);
1840  if (empty($conf->global->MAIN_PDF_MAIN_HIDE_SECOND_TAX)) {
1841  if ($object->lines[$i]->total_localtax1 != 0) {
1842  if (preg_replace('/[\s0%]/', '', $tmpresult)) {
1843  $tmpresult .= '/';
1844  } else {
1845  $tmpresult = '';
1846  }
1847  $tmpresult .= vatrate(abs($object->lines[$i]->localtax1_tx), 0);
1848  }
1849  }
1850  if (empty($conf->global->MAIN_PDF_MAIN_HIDE_THIRD_TAX)) {
1851  if ($object->lines[$i]->total_localtax2 != 0) {
1852  if (preg_replace('/[\s0%]/', '', $tmpresult)) {
1853  $tmpresult .= '/';
1854  } else {
1855  $tmpresult = '';
1856  }
1857  $tmpresult .= vatrate(abs($object->lines[$i]->localtax2_tx), 0);
1858  }
1859  }
1860  $tmpresult .= '%';
1861 
1862  $result .= $tmpresult;
1863  }
1864  }
1865  return $result;
1866 }
1867 
1877 function pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails = 0)
1878 {
1879  global $conf, $hookmanager;
1880 
1881  $sign = 1;
1882  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) {
1883  $sign = -1;
1884  }
1885 
1886  $result = '';
1887  $reshook = 0;
1888  //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) ) )
1889  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
1890  $special_code = $object->lines[$i]->special_code;
1891  if (!empty($object->lines[$i]->fk_parent_line)) {
1892  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1893  }
1894  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1895  $action = '';
1896  $reshook = $hookmanager->executeHooks('pdf_getlineupexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1897 
1898  if (!empty($hookmanager->resPrint)) {
1899  $result .= $hookmanager->resPrint;
1900  }
1901  }
1902  if (empty($reshook)) {
1903  if (empty($hidedetails) || $hidedetails > 1) {
1904  $subprice = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice);
1905  $result .= price($sign * $subprice, 0, $outputlangs);
1906  }
1907  }
1908  return $result;
1909 }
1910 
1920 function pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails = 0)
1921 {
1922  global $hookmanager, $conf;
1923 
1924  $sign = 1;
1925  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) {
1926  $sign = -1;
1927  }
1928 
1929  $result = '';
1930  $reshook = 0;
1931  //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) ) )
1932  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
1933  $special_code = $object->lines[$i]->special_code;
1934  if (!empty($object->lines[$i]->fk_parent_line)) {
1935  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1936  }
1937  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1938  $action = '';
1939  $reshook = $hookmanager->executeHooks('pdf_getlineupwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1940 
1941  if (!empty($hookmanager->resPrint)) {
1942  $result .= $hookmanager->resPrint;
1943  }
1944  }
1945  if (empty($reshook)) {
1946  if (empty($hidedetails) || $hidedetails > 1) {
1947  $result .= price($sign * (($object->lines[$i]->subprice) + ($object->lines[$i]->subprice) * ($object->lines[$i]->tva_tx) / 100), 0, $outputlangs);
1948  }
1949  }
1950  return $result;
1951 }
1952 
1962 function pdf_getlineqty($object, $i, $outputlangs, $hidedetails = 0)
1963 {
1964  global $hookmanager;
1965 
1966  $result = '';
1967  $reshook = 0;
1968  //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) ) )
1969  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
1970  $special_code = $object->lines[$i]->special_code;
1971  if (!empty($object->lines[$i]->fk_parent_line)) {
1972  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1973  }
1974  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1975  $action = '';
1976  $reshook = $hookmanager->executeHooks('pdf_getlineqty', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1977 
1978  if (!empty($hookmanager->resPrint)) {
1979  $result = $hookmanager->resPrint;
1980  }
1981  }
1982  if (empty($reshook)) {
1983  if ($object->lines[$i]->special_code == 3) {
1984  return '';
1985  }
1986  if (empty($hidedetails) || $hidedetails > 1) {
1987  $result .= $object->lines[$i]->qty;
1988  }
1989  }
1990  return $result;
1991 }
1992 
2002 function pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails = 0)
2003 {
2004  global $hookmanager;
2005 
2006  $reshook = 0;
2007  $result = '';
2008  //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) ) )
2009  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
2010  $special_code = $object->lines[$i]->special_code;
2011  if (!empty($object->lines[$i]->fk_parent_line)) {
2012  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2013  }
2014  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2015  $action = '';
2016  $reshook = $hookmanager->executeHooks('pdf_getlineqty_asked', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2017 
2018  if (!empty($hookmanager->resPrint)) {
2019  $result .= $hookmanager->resPrint;
2020  }
2021  }
2022  if (empty($reshook)) {
2023  if ($object->lines[$i]->special_code == 3) {
2024  return '';
2025  }
2026  if (empty($hidedetails) || $hidedetails > 1) {
2027  $result .= $object->lines[$i]->qty_asked;
2028  }
2029  }
2030  return $result;
2031 }
2032 
2042 function pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails = 0)
2043 {
2044  global $hookmanager;
2045 
2046  $reshook = 0;
2047  $result = '';
2048  //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) ) )
2049  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
2050  $special_code = $object->lines[$i]->special_code;
2051  if (!empty($object->lines[$i]->fk_parent_line)) {
2052  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2053  }
2054  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2055  $action = '';
2056  $reshook = $hookmanager->executeHooks('pdf_getlineqty_shipped', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2057 
2058  if (!empty($hookmanager->resPrint)) {
2059  $result .= $hookmanager->resPrint;
2060  }
2061  }
2062  if (empty($reshook)) {
2063  if ($object->lines[$i]->special_code == 3) {
2064  return '';
2065  }
2066  if (empty($hidedetails) || $hidedetails > 1) {
2067  $result .= $object->lines[$i]->qty_shipped;
2068  }
2069  }
2070  return $result;
2071 }
2072 
2082 function pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails = 0)
2083 {
2084  global $hookmanager;
2085 
2086  $reshook = 0;
2087  $result = '';
2088  //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) ) )
2089  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
2090  $special_code = $object->lines[$i]->special_code;
2091  if (!empty($object->lines[$i]->fk_parent_line)) {
2092  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2093  }
2094  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2095  $action = '';
2096  $reshook = $hookmanager->executeHooks('pdf_getlineqty_keeptoship', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2097 
2098  if (!empty($hookmanager->resPrint)) {
2099  $result .= $hookmanager->resPrint;
2100  }
2101  }
2102  if (empty($reshook)) {
2103  if ($object->lines[$i]->special_code == 3) {
2104  return '';
2105  }
2106  if (empty($hidedetails) || $hidedetails > 1) {
2107  $result .= ($object->lines[$i]->qty_asked - $object->lines[$i]->qty_shipped);
2108  }
2109  }
2110  return $result;
2111 }
2112 
2123 function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = false)
2124 {
2125  global $langs;
2126 
2127  $reshook = 0;
2128  $result = '';
2129  //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) ) )
2130  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
2131  $special_code = $object->lines[$i]->special_code;
2132  if (!empty($object->lines[$i]->fk_parent_line)) {
2133  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2134  }
2135  $parameters = array(
2136  'i' => $i,
2137  'outputlangs' => $outputlangs,
2138  'hidedetails' => $hidedetails,
2139  'special_code' => $special_code
2140  );
2141  $action = '';
2142  $reshook = $hookmanager->executeHooks('pdf_getlineunit', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2143 
2144  if (!empty($hookmanager->resPrint)) {
2145  $result .= $hookmanager->resPrint;
2146  }
2147  }
2148  if (empty($reshook)) {
2149  if (empty($hidedetails) || $hidedetails > 1) {
2150  $result .= $langs->transnoentitiesnoconv($object->lines[$i]->getLabelOfUnit('short'));
2151  }
2152  }
2153  return $result;
2154 }
2155 
2156 
2166 function pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails = 0)
2167 {
2168  global $hookmanager;
2169 
2170  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
2171 
2172  $reshook = 0;
2173  $result = '';
2174  //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) ) )
2175  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
2176  $special_code = $object->lines[$i]->special_code;
2177  if (!empty($object->lines[$i]->fk_parent_line)) {
2178  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2179  }
2180  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2181  $action = '';
2182  $reshook = $hookmanager->executeHooks('pdf_getlineremisepercent', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2183 
2184  if (!empty($hookmanager->resPrint)) {
2185  $result .= $hookmanager->resPrint;
2186  }
2187  }
2188  if (empty($reshook)) {
2189  if ($object->lines[$i]->special_code == 3) {
2190  return '';
2191  }
2192  if (empty($hidedetails) || $hidedetails > 1) {
2193  $result .= dol_print_reduction($object->lines[$i]->remise_percent, $outputlangs);
2194  }
2195  }
2196  return $result;
2197 }
2198 
2209 function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = null)
2210 {
2211  if (empty($hookmanager)) {
2212  global $hookmanager;
2213  }
2214  global $conf;
2215 
2216  $reshook = 0;
2217  $result = '';
2218  //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) ) )
2219  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
2220  $special_code = $object->lines[$i]->special_code;
2221  if (!empty($object->lines[$i]->fk_parent_line)) {
2222  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2223  }
2224  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
2225  $action = '';
2226  $reshook = $hookmanager->executeHooks('pdf_getlineprogress', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2227 
2228  if (!empty($hookmanager->resPrint)) {
2229  return $hookmanager->resPrint;
2230  }
2231  }
2232  if (empty($reshook)) {
2233  if ($object->lines[$i]->special_code == 3) {
2234  return '';
2235  }
2236  if (empty($hidedetails) || $hidedetails > 1) {
2237  if (!empty($conf->global->SITUATION_DISPLAY_DIFF_ON_PDF)) {
2238  $prev_progress = 0;
2239  if (method_exists($object->lines[$i], 'get_prev_progress')) {
2240  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2241  }
2242  $result = round($object->lines[$i]->situation_percent - $prev_progress, 1).'%';
2243  } else {
2244  $result = round($object->lines[$i]->situation_percent, 1).'%';
2245  }
2246  }
2247  }
2248  return $result;
2249 }
2250 
2260 function pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails = 0)
2261 {
2262  global $conf, $hookmanager;
2263 
2264  $sign = 1;
2265  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) {
2266  $sign = -1;
2267  }
2268 
2269  $reshook = 0;
2270  $result = '';
2271  //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) ) )
2272  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
2273  $special_code = $object->lines[$i]->special_code;
2274  if (!empty($object->lines[$i]->fk_parent_line)) {
2275  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2276  }
2277  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code, 'sign'=>$sign);
2278  $action = '';
2279  $reshook = $hookmanager->executeHooks('pdf_getlinetotalexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2280 
2281  if (!empty($hookmanager->resPrint)) {
2282  $result .= $hookmanager->resPrint;
2283  }
2284  }
2285  if (empty($reshook)) {
2286  if ($object->lines[$i]->special_code == 3) {
2287  $result .= $outputlangs->transnoentities("Option");
2288  } elseif (empty($hidedetails) || $hidedetails > 1) {
2289  $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
2290  if (!empty($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
2291  // TODO Remove this. The total should be saved correctly in database instead of being modified here.
2292  $prev_progress = 0;
2293  $progress = 1;
2294  if (method_exists($object->lines[$i], 'get_prev_progress')) {
2295  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2296  $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
2297  }
2298  $result .= price($sign * ($total_ht / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
2299  } else {
2300  $result .= price($sign * $total_ht, 0, $outputlangs);
2301  }
2302  }
2303  }
2304  return $result;
2305 }
2306 
2316 function pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails = 0)
2317 {
2318  global $hookmanager, $conf;
2319 
2320  $sign = 1;
2321  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) {
2322  $sign = -1;
2323  }
2324 
2325  $reshook = 0;
2326  $result = '';
2327  //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) ) )
2328  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
2329  $special_code = $object->lines[$i]->special_code;
2330  if (!empty($object->lines[$i]->fk_parent_line)) {
2331  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2332  }
2333  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2334  $action = '';
2335  $reshook = $hookmanager->executeHooks('pdf_getlinetotalwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2336 
2337  if (!empty($hookmanager->resPrint)) {
2338  $result .= $hookmanager->resPrint;
2339  }
2340  }
2341  if (empty($reshook)) {
2342  if ($object->lines[$i]->special_code == 3) {
2343  $result .= $outputlangs->transnoentities("Option");
2344  } elseif (empty($hidedetails) || $hidedetails > 1) {
2345  $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ttc : $object->lines[$i]->total_ttc);
2346  if ($object->lines[$i]->situation_percent > 0) {
2347  // TODO Remove this. The total should be saved correctly in database instead of being modified here.
2348  $prev_progress = 0;
2349  $progress = 1;
2350  if (method_exists($object->lines[$i], 'get_prev_progress')) {
2351  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2352  $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
2353  }
2354  $result .= price($sign * ($total_ttc / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
2355  } else {
2356  $result .= price($sign * $total_ttc, 0, $outputlangs);
2357  }
2358  }
2359  }
2360  return $result;
2361 }
2362 
2371 function pdf_getLinkedObjects(&$object, $outputlangs)
2372 {
2373  global $db, $hookmanager;
2374 
2375  $linkedobjects = array();
2376 
2377  $object->fetchObjectLinked();
2378 
2379  foreach ($object->linkedObjects as $objecttype => $objects) {
2380  if ($objecttype == 'facture') {
2381  // 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.
2382  } elseif ($objecttype == 'propal' || $objecttype == 'supplier_proposal') {
2383  $outputlangs->load('propal');
2384 
2385  foreach ($objects as $elementobject) {
2386  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefProposal");
2387  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2388  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DatePropal");
2389  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2390  }
2391  } elseif ($objecttype == 'commande' || $objecttype == 'supplier_order') {
2392  $outputlangs->load('orders');
2393 
2394  if (count($objects) > 1 && count($objects) <= (getDolGlobalInt("MAXREFONDOC") ? getDolGlobalInt("MAXREFONDOC") : 10)) {
2395  $object->note_public = dol_concatdesc($object->note_public, '<br>'.$outputlangs->transnoentities("RefOrder").' : <br>');
2396  foreach ($objects as $elementobject) {
2397  $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.')' : '').' ');
2398  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities("OrderDate").' : '.dol_print_date($elementobject->date, 'day', '', $outputlangs).'<br>');
2399  }
2400  } elseif (count($objects) == 1) {
2401  $elementobject = array_shift($objects);
2402  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder");
2403  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref).(!empty($elementobject->ref_client) ? ' ('.$elementobject->ref_client.')' : '').(!empty($elementobject->ref_supplier) ? ' ('.$elementobject->ref_supplier.')' : '');
2404  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("OrderDate");
2405  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2406  }
2407  } elseif ($objecttype == 'contrat') {
2408  $outputlangs->load('contracts');
2409  foreach ($objects as $elementobject) {
2410  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefContract");
2411  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2412  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DateContract");
2413  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date_contrat, 'day', '', $outputlangs);
2414  }
2415  } elseif ($objecttype == 'fichinter') {
2416  $outputlangs->load('interventions');
2417  foreach ($objects as $elementobject) {
2418  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("InterRef");
2419  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2420  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("InterDate");
2421  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->datec, 'day', '', $outputlangs);
2422  }
2423  } elseif ($objecttype == 'shipping') {
2424  $outputlangs->loadLangs(array("orders", "sendings"));
2425 
2426  if (count($objects) > 1) {
2427  $order = null;
2428  if (empty($object->linkedObjects['commande']) && $object->element != 'commande') {
2429  $object->note_public = dol_concatdesc($object->note_public, '<br>'.$outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending").' : <br>');
2430  } else {
2431  $object->note_public = dol_concatdesc($object->note_public, '<br>'.$outputlangs->transnoentities("RefSending").' : <br>');
2432  }
2433  // We concat this record info into fields xxx_value. title is overwrote.
2434  foreach ($objects as $elementobject) {
2435  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
2436  $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2437  if (!empty($elementobject->linkedObjectsIds['commande'])) {
2438  include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2439  $order = new Commande($db);
2440  $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2441  if ($ret < 1) {
2442  $order = null;
2443  }
2444  }
2445  }
2446 
2447  if (! is_object($order)) {
2448  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->transnoentities($elementobject->ref));
2449  $object->note_public = dol_concatdesc($object->note_public, '<br>');
2450  } else {
2451  $object->note_public = dol_concatdesc($object->note_public, $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : ''));
2452  $object->note_public = dol_concatdesc($object->note_public, ' / '.$outputlangs->transnoentities($elementobject->ref));
2453  $object->note_public = dol_concatdesc($object->note_public, '<br>');
2454  }
2455  }
2456  } elseif (count($objects) == 1) {
2457  $elementobject = array_shift($objects);
2458  $order = null;
2459  // We concat this record info into fields xxx_value. title is overwrote.
2460  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
2461  $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2462  if (!empty($elementobject->linkedObjectsIds['commande'])) {
2463  include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2464  $order = new Commande($db);
2465  $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2466  if ($ret < 1) {
2467  $order = null;
2468  }
2469  }
2470  }
2471 
2472  if (! is_object($order)) {
2473  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefSending");
2474  if (!empty($linkedobjects[$objecttype]['ref_value'])) $linkedobjects[$objecttype]['ref_value'] .= ' / ';
2475  $linkedobjects[$objecttype]['ref_value'] .= $outputlangs->transnoentities($elementobject->ref);
2476  } else {
2477  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending");
2478  if (empty($linkedobjects[$objecttype]['ref_value'])) $linkedobjects[$objecttype]['ref_value'] = $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
2479  $linkedobjects[$objecttype]['ref_value'] .= ' / '.$outputlangs->transnoentities($elementobject->ref);
2480  }
2481  }
2482  }
2483  }
2484 
2485  // For add external linked objects
2486  if (is_object($hookmanager)) {
2487  $parameters = array('linkedobjects' => $linkedobjects, 'outputlangs'=>$outputlangs);
2488  $action = '';
2489  $hookmanager->executeHooks('pdf_getLinkedObjects', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2490  if (!empty($hookmanager->resArray)) {
2491  $linkedobjects = $hookmanager->resArray;
2492  }
2493  }
2494 
2495  return $linkedobjects;
2496 }
2497 
2505 function pdf_getSizeForImage($realpath)
2506 {
2507  global $conf;
2508 
2509  $maxwidth = (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH);
2510  $maxheight = (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT) ? 32 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT);
2511  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
2512  $tmp = dol_getImageSize($realpath);
2513  if ($tmp['height']) {
2514  $width = (int) round($maxheight * $tmp['width'] / $tmp['height']); // I try to use maxheight
2515  if ($width > $maxwidth) { // Pb with maxheight, so i use maxwidth
2516  $width = $maxwidth;
2517  $height = (int) round($maxwidth * $tmp['height'] / $tmp['width']);
2518  } else // No pb with maxheight
2519  {
2520  $height = $maxheight;
2521  }
2522  }
2523  return array('width'=>$width, 'height'=>$height);
2524 }
2525 
2535 function pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails = 0)
2536 {
2537  global $conf, $hookmanager;
2538  $sign = 1;
2539  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) {
2540  $sign = -1;
2541  }
2542  if ($object->lines[$i]->special_code == 3) {
2543  return $outputlangs->transnoentities("Option");
2544  } else {
2545  if (is_object($hookmanager)) {
2546  $special_code = $object->lines[$i]->special_code;
2547  if (!empty($object->lines[$i]->fk_parent_line)) {
2548  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2549  }
2550 
2551  $parameters = array(
2552  'i'=>$i,
2553  'outputlangs'=>$outputlangs,
2554  'hidedetails'=>$hidedetails,
2555  'special_code'=>$special_code
2556  );
2557 
2558  $action = '';
2559 
2560  if ($hookmanager->executeHooks('getlinetotalremise', $parameters, $object, $action) > 0) {
2561  return $hookmanager->resPrint; // Note that $action and $object may have been modified by some hooks
2562  }
2563  }
2564 
2565  if (empty($hidedetails) || $hidedetails > 1) {
2566  return $sign * (($object->lines[$i]->subprice * $object->lines[$i]->qty) - $object->lines[$i]->total_ht);
2567  }
2568  }
2569  return '';
2570 }
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:118
div float
Buy price without taxes.
Definition: style.css.php:913
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:2505
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition: pdf.lib.php:2260
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:1404
pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails=0)
Return line total amount discount.
Definition: pdf.lib.php:2535
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:2042
pdf_getlinenum($object, $i, $outputlangs, $hidedetails=0)
Return line num.
Definition: pdf.lib.php:1718
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:1920
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:1354
pdf_getLinkedObjects(&$object, $outputlangs)
Return linked objects to use for document generation.
Definition: pdf.lib.php:2371
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:1783
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition: pdf.lib.php:2316
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:996
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition: pdf.lib.php:1877
pdf_getlineprogress($object, $i, $outputlangs, $hidedetails=0, $hookmanager=null)
Return line percent.
Definition: pdf.lib.php:2209
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition: pdf.lib.php:1815
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0, $hookmanager=false)
Return line unit.
Definition: pdf.lib.php:2123
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:744
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:718
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition: pdf.lib.php:1318
pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank informations for PDF generation.
Definition: pdf.lib.php:819
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:2082
pdf_getlineref($object, $i, $outputlangs, $hidedetails=0)
Return line product ref.
Definition: pdf.lib.php:1751
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:2166
pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails=0)
Return line quantity asked.
Definition: pdf.lib.php:2002
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition: pdf.lib.php:1962
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:764