dolibarr  13.0.2
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  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program. If not, see <https://www.gnu.org/licenses/>.
28  * or see https://www.gnu.org/
29  */
30 
45 function pdf_getFormat(Translate $outputlangs = null, $mode = 'setup')
46 {
47  global $conf, $db, $langs;
48 
49  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'));
50 
51  // Default value if setup was not done and/or entry into c_paper_format not defined
52  $width = 210; $height = 297; $unit = 'mm';
53 
54  if ($mode == 'auto' || empty($conf->global->MAIN_PDF_FORMAT) || $conf->global->MAIN_PDF_FORMAT == 'auto')
55  {
56  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
57  $pdfformat = dol_getDefaultFormat($outputlangs);
58  } else {
59  $pdfformat = $conf->global->MAIN_PDF_FORMAT;
60  }
61 
62  $sql = "SELECT code, label, width, height, unit FROM ".MAIN_DB_PREFIX."c_paper_format";
63  $sql .= " WHERE code = '".$db->escape($pdfformat)."'";
64  $resql = $db->query($sql);
65  if ($resql)
66  {
67  $obj = $db->fetch_object($resql);
68  if ($obj)
69  {
70  $width = (int) $obj->width;
71  $height = (int) $obj->height;
72  $unit = $obj->unit;
73  }
74  }
75 
76  //print "pdfformat=".$pdfformat." width=".$width." height=".$height." unit=".$unit;
77  return array('width'=>$width, 'height'=>$height, 'unit'=>$unit);
78 }
79 
88 function pdf_getInstance($format = '', $metric = 'mm', $pagetype = 'P')
89 {
90  global $conf;
91 
92  // Define constant for TCPDF
93  if (!defined('K_TCPDF_EXTERNAL_CONFIG'))
94  {
95  define('K_TCPDF_EXTERNAL_CONFIG', 1); // this avoid using tcpdf_config file
96  define('K_PATH_CACHE', DOL_DATA_ROOT.'/admin/temp/');
97  define('K_PATH_URL_CACHE', DOL_DATA_ROOT.'/admin/temp/');
98  dol_mkdir(K_PATH_CACHE);
99  define('K_BLANK_IMAGE', '_blank.png');
100  define('PDF_PAGE_FORMAT', 'A4');
101  define('PDF_PAGE_ORIENTATION', 'P');
102  define('PDF_CREATOR', 'TCPDF');
103  define('PDF_AUTHOR', 'TCPDF');
104  define('PDF_HEADER_TITLE', 'TCPDF Example');
105  define('PDF_HEADER_STRING', "by Dolibarr ERP CRM");
106  define('PDF_UNIT', 'mm');
107  define('PDF_MARGIN_HEADER', 5);
108  define('PDF_MARGIN_FOOTER', 10);
109  define('PDF_MARGIN_TOP', 27);
110  define('PDF_MARGIN_BOTTOM', 25);
111  define('PDF_MARGIN_LEFT', 15);
112  define('PDF_MARGIN_RIGHT', 15);
113  define('PDF_FONT_NAME_MAIN', 'helvetica');
114  define('PDF_FONT_SIZE_MAIN', 10);
115  define('PDF_FONT_NAME_DATA', 'helvetica');
116  define('PDF_FONT_SIZE_DATA', 8);
117  define('PDF_FONT_MONOSPACED', 'courier');
118  define('PDF_IMAGE_SCALE_RATIO', 1.25);
119  define('HEAD_MAGNIFICATION', 1.1);
120  define('K_CELL_HEIGHT_RATIO', 1.25);
121  define('K_TITLE_MAGNIFICATION', 1.3);
122  define('K_SMALL_RATIO', 2 / 3);
123  define('K_THAI_TOPCHARS', true);
124  define('K_TCPDF_CALLS_IN_HTML', true);
125  if (!empty($conf->global->TCPDF_THROW_ERRORS_INSTEAD_OF_DIE)) {
126  define('K_TCPDF_THROW_EXCEPTION_ERROR', true);
127  } else {
128  define('K_TCPDF_THROW_EXCEPTION_ERROR', false);
129  }
130  }
131 
132  // Load TCPDF
133  require_once TCPDF_PATH.'tcpdf.php';
134 
135  // We need to instantiate tcpdi object (instead of tcpdf) to use merging features. But we can disable it (this will break all merge features).
136  if (empty($conf->global->MAIN_DISABLE_TCPDI)) require_once TCPDI_PATH.'tcpdi.php';
137 
138  //$arrayformat=pdf_getFormat();
139  //$format=array($arrayformat['width'],$arrayformat['height']);
140  //$metric=$arrayformat['unit'];
141 
142  $pdfa = false; // PDF-1.3
143  if (!empty($conf->global->PDF_USE_1A)) $pdfa = true; // PDF1/A
144 
145  if (class_exists('TCPDI')) $pdf = new TCPDI($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
146  else $pdf = new TCPDF($pagetype, $metric, $format, true, 'UTF-8', false, $pdfa);
147 
148  // Protection and encryption of pdf
149  if (!empty($conf->global->PDF_SECURITY_ENCRYPTION))
150  {
151  /* Permission supported by TCPDF
152  - print : Print the document;
153  - modify : Modify the contents of the document by operations other than those controlled by 'fill-forms', 'extract' and 'assemble';
154  - copy : Copy or otherwise extract text and graphics from the document;
155  - 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);
156  - fill-forms : Fill in existing interactive form fields (including signature fields), even if 'annot-forms' is not specified;
157  - extract : Extract text and graphics (in support of accessibility to users with disabilities or for other purposes);
158  - assemble : Assemble the document (insert, rotate, or delete pages and create bookmarks or thumbnail images), even if 'modify' is not set;
159  - 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.
160  - owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions.
161  */
162 
163  // For TCPDF, we specify permission we want to block
164  $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
165 
166  // Password for the end user
167  $pdfuserpass = (!empty($conf->global->PDF_SECURITY_ENCRYPTION_USERPASS) ? $conf->global->PDF_SECURITY_ENCRYPTION_USERPASS : '');
168 
169  // Password of the owner, created randomly if not defined
170  $pdfownerpass = (!empty($conf->global->PDF_SECURITY_ENCRYPTION_OWNERPASS) ? $conf->global->PDF_SECURITY_ENCRYPTION_OWNERPASS : null);
171 
172  // For encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit
173  $encstrength = (!empty($conf->global->PDF_SECURITY_ENCRYPTION_STRENGTH) ? $conf->global->PDF_SECURITY_ENCRYPTION_STRENGTH : 0);
174 
175  // Array of recipients containing public-key certificates ('c') and permissions ('p').
176  // For example: array(array('c' => 'file://../examples/data/cert/tcpdf.crt', 'p' => array('print')))
177  $pubkeys = (!empty($conf->global->PDF_SECURITY_ENCRYPTION_PUBKEYS) ?json_decode($conf->global->PDF_SECURITY_ENCRYPTION_PUBKEYS, true) : null); // Json format in llx_const
178 
179  $pdf->SetProtection($pdfrights, $pdfuserpass, $pdfownerpass, $encstrength, $pubkeys);
180  }
181 
182  return $pdf;
183 }
184 
191 function pdf_getEncryption($pathoffile)
192 {
193  require_once TCPDF_PATH.'tcpdf_parser.php';
194 
195  $isencrypted = false;
196 
197  $content = file_get_contents($pathoffile);
198 
199  //ob_start();
200  @($parser = new \TCPDF_PARSER(ltrim($content)));
201  list($xref, $data) = $parser->getParsedData();
202  unset($parser);
203  //ob_end_clean();
204 
205  if (isset($xref['trailer']['encrypt'])) {
206  $isencrypted = true; // Secured pdf file are currently not supported
207  }
208 
209  if (empty($data)) {
210  $isencrypted = true; // Object list not found. Possible secured file
211  }
212 
213  return $isencrypted;
214 }
215 
222 function pdf_getPDFFont($outputlangs)
223 {
224  global $conf;
225 
226  if (!empty($conf->global->MAIN_PDF_FORCE_FONT)) return $conf->global->MAIN_PDF_FORCE_FONT;
227 
228  $font = 'Helvetica'; // By default, for FPDI, or ISO language on TCPDF
229  if (class_exists('TCPDF')) // If TCPDF on, we can use an UTF8 one like DejaVuSans if required (slower)
230  {
231  if ($outputlangs->trans('FONTFORPDF') != 'FONTFORPDF')
232  {
233  $font = $outputlangs->trans('FONTFORPDF');
234  }
235  }
236  return $font;
237 }
238 
245 function pdf_getPDFFontSize($outputlangs)
246 {
247  global $conf;
248 
249  $size = 10; // By default, for FPDI or ISO language on TCPDF
250  if (class_exists('TCPDF')) // If TCPDF on, we can use an UTF8 font like DejaVuSans if required (slower)
251  {
252  if ($outputlangs->trans('FONTSIZEFORPDF') != 'FONTSIZEFORPDF')
253  {
254  $size = (int) $outputlangs->trans('FONTSIZEFORPDF');
255  }
256  }
257  if (!empty($conf->global->MAIN_PDF_FORCE_FONT_SIZE)) $size = $conf->global->MAIN_PDF_FORCE_FONT_SIZE;
258 
259  return $size;
260 }
261 
262 
270 function pdf_getHeightForLogo($logo, $url = false)
271 {
272  global $conf;
273  $height = (empty($conf->global->MAIN_DOCUMENTS_LOGO_HEIGHT) ? 20 : $conf->global->MAIN_DOCUMENTS_LOGO_HEIGHT);
274  $maxwidth = 130;
275  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
276  $tmp = dol_getImageSize($logo, $url);
277  if ($tmp['height'])
278  {
279  $width = round($height * $tmp['width'] / $tmp['height']);
280  if ($width > $maxwidth) $height = $height * $maxwidth / $width;
281  }
282  //print $tmp['width'].' '.$tmp['height'].' '.$width; exit;
283  return $height;
284 }
285 
294 function pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
295 {
296  // store current object
297  $pdf->startTransaction();
298  // store starting values
299  $start_y = $pdf->GetY();
300  //var_dump($start_y);
301  $start_page = $pdf->getPage();
302  // call printing functions with content
303  $pdf->writeHTMLCell(0, 0, 0, $start_y, $htmlcontent, 0, 1, false, true, 'J', true);
304  // get the new Y
305  $end_y = $pdf->GetY();
306  $end_page = $pdf->getPage();
307  // calculate height
308  $height = 0;
309  if ($end_page == $start_page) {
310  $height = $end_y - $start_y;
311  } else {
312  for ($page = $start_page; $page <= $end_page; ++$page) {
313  $pdf->setPage($page);
314  $tmpm = $pdf->getMargins();
315  $tMargin = $tmpm['top'];
316  if ($page == $start_page) {
317  // first page
318  $height = $pdf->getPageHeight() - $start_y - $pdf->getBreakMargin();
319  } elseif ($page == $end_page) {
320  // last page
321  $height = $end_y - $tMargin;
322  } else {
323  $height = $pdf->getPageHeight() - $tMargin - $pdf->getBreakMargin();
324  }
325  }
326  }
327  // restore previous object
328  $pdf = $pdf->rollbackTransaction();
329 
330  return $height;
331 }
332 
333 
342 function pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias = 0)
343 {
344  global $conf;
345 
346  // Recipient name
347  $socname = '';
348 
349  if ($thirdparty instanceof Societe) {
350  $socname .= $thirdparty->name;
351  if (($includealias || !empty($conf->global->PDF_INCLUDE_ALIAS_IN_THIRDPARTY_NAME)) && !empty($thirdparty->name_alias)) {
352  $socname .= " - ".$thirdparty->name_alias;
353  }
354  } elseif ($thirdparty instanceof Contact) {
355  $socname = $thirdparty->socname;
356  } else {
357  throw new InvalidArgumentException('Parameter 1 $thirdparty is not a Societe nor Contact');
358  }
359 
360  return $outputlangs->convToOutputCharset($socname);
361 }
362 
363 
376 function pdf_build_address($outputlangs, $sourcecompany, $targetcompany = '', $targetcontact = '', $usecontact = 0, $mode = 'source', $object = null)
377 {
378  global $conf, $hookmanager;
379 
380  if ($mode == 'source' && !is_object($sourcecompany)) return -1;
381  if ($mode == 'target' && !is_object($targetcompany)) return -1;
382 
383  if (!empty($sourcecompany->state_id) && empty($sourcecompany->state)) $sourcecompany->state = getState($sourcecompany->state_id);
384  if (!empty($targetcompany->state_id) && empty($targetcompany->state)) $targetcompany->state = getState($targetcompany->state_id);
385 
386  $reshook = 0;
387  $stringaddress = '';
388  if (is_object($hookmanager))
389  {
390  $parameters = array('sourcecompany' => &$sourcecompany, 'targetcompany' => &$targetcompany, 'targetcontact' => &$targetcontact, 'outputlangs' => $outputlangs, 'mode' => $mode, 'usecontact' => $usecontact);
391  $action = '';
392  $reshook = $hookmanager->executeHooks('pdf_build_address', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
393  $stringaddress .= $hookmanager->resPrint;
394  }
395  if (empty($reshook))
396  {
397  if ($mode == 'source')
398  {
399  $withCountry = 0;
400  if (!empty($sourcecompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) $withCountry = 1;
401 
402  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($sourcecompany, $withCountry, "\n", $outputlangs))."\n";
403 
404  if (empty($conf->global->MAIN_PDF_DISABLESOURCEDETAILS))
405  {
406  // Phone
407  if ($sourcecompany->phone) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("PhoneShort").": ".$outputlangs->convToOutputCharset($sourcecompany->phone);
408  // Fax
409  if ($sourcecompany->fax) $stringaddress .= ($stringaddress ? ($sourcecompany->phone ? " - " : "\n") : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($sourcecompany->fax);
410  // EMail
411  if ($sourcecompany->email) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($sourcecompany->email);
412  // Web
413  if ($sourcecompany->url) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($sourcecompany->url);
414  }
415  // Intra VAT
416  if (!empty($conf->global->MAIN_TVAINTRA_IN_SOURCE_ADDRESS))
417  {
418  if ($sourcecompany->tva_intra) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($sourcecompany->tva_intra);
419  }
420  // Professionnal Ids
421  $reg = array();
422  if (!empty($conf->global->MAIN_PROFID1_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof1))
423  {
424  $tmp = $outputlangs->transcountrynoentities("ProfId1", $sourcecompany->country_code);
425  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
426  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof1);
427  }
428  if (!empty($conf->global->MAIN_PROFID2_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof2))
429  {
430  $tmp = $outputlangs->transcountrynoentities("ProfId2", $sourcecompany->country_code);
431  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
432  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof2);
433  }
434  if (!empty($conf->global->MAIN_PROFID3_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof3))
435  {
436  $tmp = $outputlangs->transcountrynoentities("ProfId3", $sourcecompany->country_code);
437  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
438  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof3);
439  }
440  if (!empty($conf->global->MAIN_PROFID4_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof4))
441  {
442  $tmp = $outputlangs->transcountrynoentities("ProfId4", $sourcecompany->country_code);
443  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
444  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof4);
445  }
446  if (!empty($conf->global->MAIN_PROFID5_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof5))
447  {
448  $tmp = $outputlangs->transcountrynoentities("ProfId5", $sourcecompany->country_code);
449  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
450  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof5);
451  }
452  if (!empty($conf->global->MAIN_PROFID6_IN_SOURCE_ADDRESS) && !empty($sourcecompany->idprof6))
453  {
454  $tmp = $outputlangs->transcountrynoentities("ProfId6", $sourcecompany->country_code);
455  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
456  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($sourcecompany->idprof6);
457  }
458  if (!empty($conf->global->PDF_ADD_MORE_AFTER_SOURCE_ADDRESS)) {
459  $stringaddress .= ($stringaddress ? "\n" : '').$conf->global->PDF_ADD_MORE_AFTER_SOURCE_ADDRESS;
460  }
461  }
462 
463  if ($mode == 'target' || preg_match('/targetwithdetails/', $mode))
464  {
465  if ($usecontact)
466  {
467  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($targetcontact->getFullName($outputlangs, 1));
468 
469  if (!empty($targetcontact->address)) {
470  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcontact));
471  } else {
472  $companytouseforaddress = $targetcompany;
473 
474  // Contact on a thirdparty that is a different thirdparty than the thirdparty of object
475  if ($targetcontact->socid > 0 && $targetcontact->socid != $targetcompany->id)
476  {
477  $targetcontact->fetch_thirdparty();
478  $companytouseforaddress = $targetcontact->thirdparty;
479  }
480 
481  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($companytouseforaddress));
482  }
483  // Country
484  if (!empty($targetcontact->country_code) && $targetcontact->country_code != $sourcecompany->country_code) {
485  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcontact->country_code));
486  } elseif (empty($targetcontact->country_code) && !empty($targetcompany->country_code) && ($targetcompany->country_code != $sourcecompany->country_code)) {
487  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
488  }
489 
490  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || preg_match('/targetwithdetails/', $mode))
491  {
492  // Phone
493  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode))
494  {
495  if (!empty($targetcontact->phone_pro) || !empty($targetcontact->phone_mobile)) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
496  if (!empty($targetcontact->phone_pro)) $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_pro);
497  if (!empty($targetcontact->phone_pro) && !empty($targetcontact->phone_mobile)) $stringaddress .= " / ";
498  if (!empty($targetcontact->phone_mobile)) $stringaddress .= $outputlangs->convToOutputCharset($targetcontact->phone_mobile);
499  }
500  // Fax
501  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode))
502  {
503  if ($targetcontact->fax) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcontact->fax);
504  }
505  // EMail
506  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode))
507  {
508  if ($targetcontact->email) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcontact->email);
509  }
510  // Web
511  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode))
512  {
513  if ($targetcontact->url) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcontact->url);
514  }
515  }
516  } else {
517  $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset(dol_format_address($targetcompany));
518  // Country
519  if (!empty($targetcompany->country_code) && $targetcompany->country_code != $sourcecompany->country_code) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$targetcompany->country_code));
520 
521  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || preg_match('/targetwithdetails/', $mode))
522  {
523  // Phone
524  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_phone/', $mode))
525  {
526  if (!empty($targetcompany->phone) || !empty($targetcompany->phone_mobile)) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Phone").": ";
527  if (!empty($targetcompany->phone)) $stringaddress .= $outputlangs->convToOutputCharset($targetcompany->phone);
528  if (!empty($targetcompany->phone) && !empty($targetcompany->phone_mobile)) $stringaddress .= " / ";
529  if (!empty($targetcompany->phone_mobile)) $stringaddress .= $outputlangs->convToOutputCharset($targetcompany->phone_mobile);
530  }
531  // Fax
532  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_fax/', $mode))
533  {
534  if ($targetcompany->fax) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Fax").": ".$outputlangs->convToOutputCharset($targetcompany->fax);
535  }
536  // EMail
537  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_email/', $mode))
538  {
539  if ($targetcompany->email) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Email").": ".$outputlangs->convToOutputCharset($targetcompany->email);
540  }
541  // Web
542  if (!empty($conf->global->MAIN_PDF_ADDALSOTARGETDETAILS) || $mode == 'targetwithdetails' || preg_match('/targetwithdetails_url/', $mode))
543  {
544  if ($targetcompany->url) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("Web").": ".$outputlangs->convToOutputCharset($targetcompany->url);
545  }
546  }
547  }
548 
549  // Intra VAT
550  if (empty($conf->global->MAIN_TVAINTRA_NOT_IN_ADDRESS))
551  {
552  if ($targetcompany->tva_intra) $stringaddress .= ($stringaddress ? "\n" : '').$outputlangs->transnoentities("VATIntraShort").': '.$outputlangs->convToOutputCharset($targetcompany->tva_intra);
553  }
554 
555  // Professionnal Ids
556  if (!empty($conf->global->MAIN_PROFID1_IN_ADDRESS) && !empty($targetcompany->idprof1))
557  {
558  $tmp = $outputlangs->transcountrynoentities("ProfId1", $targetcompany->country_code);
559  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
560  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof1);
561  }
562  if (!empty($conf->global->MAIN_PROFID2_IN_ADDRESS) && !empty($targetcompany->idprof2))
563  {
564  $tmp = $outputlangs->transcountrynoentities("ProfId2", $targetcompany->country_code);
565  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
566  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof2);
567  }
568  if (!empty($conf->global->MAIN_PROFID3_IN_ADDRESS) && !empty($targetcompany->idprof3))
569  {
570  $tmp = $outputlangs->transcountrynoentities("ProfId3", $targetcompany->country_code);
571  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
572  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof3);
573  }
574  if (!empty($conf->global->MAIN_PROFID4_IN_ADDRESS) && !empty($targetcompany->idprof4))
575  {
576  $tmp = $outputlangs->transcountrynoentities("ProfId4", $targetcompany->country_code);
577  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
578  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof4);
579  }
580  if (!empty($conf->global->MAIN_PROFID5_IN_ADDRESS) && !empty($targetcompany->idprof5))
581  {
582  $tmp = $outputlangs->transcountrynoentities("ProfId5", $targetcompany->country_code);
583  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
584  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof5);
585  }
586  if (!empty($conf->global->MAIN_PROFID6_IN_ADDRESS) && !empty($targetcompany->idprof6))
587  {
588  $tmp = $outputlangs->transcountrynoentities("ProfId6", $targetcompany->country_code);
589  if (preg_match('/\((.+)\)/', $tmp, $reg)) $tmp = $reg[1];
590  $stringaddress .= ($stringaddress ? "\n" : '').$tmp.': '.$outputlangs->convToOutputCharset($targetcompany->idprof6);
591  }
592 
593  // Public note
594  if (!empty($conf->global->MAIN_PUBLIC_NOTE_IN_ADDRESS))
595  {
596  if ($mode == 'source' && !empty($sourcecompany->note_public))
597  {
598  $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($sourcecompany->note_public);
599  }
600  if (($mode == 'target' || preg_match('/targetwithdetails/', $mode)) && !empty($targetcompany->note_public))
601  {
602  $stringaddress .= ($stringaddress ? "\n" : '').dol_string_nohtmltag($targetcompany->note_public);
603  }
604  }
605  }
606  }
607 
608  return $stringaddress;
609 }
610 
611 
620 function pdf_pagehead(&$pdf, $outputlangs, $page_height)
621 {
622  global $conf;
623 
624  // Add a background image on document
625  if (!empty($conf->global->MAIN_USE_BACKGROUND_ON_PDF)) // Warning, this option make TCPDF generation being crazy and some content disappeared behind the image
626  {
627  $pdf->SetAutoPageBreak(0, 0); // Disable auto pagebreak before adding image
628  $pdf->Image($conf->mycompany->dir_output.'/logos/'.$conf->global->MAIN_USE_BACKGROUND_ON_PDF, (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);
629  $pdf->SetAutoPageBreak(1, 0); // Restore pagebreak
630  }
631 }
632 
633 
643 function pdf_getSubstitutionArray($outputlangs, $exclude = null, $object = null, $onlykey = 0)
644 {
645  $substitutionarray = getCommonSubstitutionArray($outputlangs, $onlykey, $exclude, $object);
646  $substitutionarray['__FROM_NAME__'] = '__FROM_NAME__';
647  $substitutionarray['__FROM_EMAIL__'] = '__FROM_EMAIL__';
648  return $substitutionarray;
649 }
650 
651 
663 function pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
664 {
665  global $langs, $mysoc, $user;
666 
667  // Print Draft Watermark
668  if ($unit == 'pt') $k = 1;
669  elseif ($unit == 'mm') $k = 72 / 25.4;
670  elseif ($unit == 'cm') $k = 72 / 2.54;
671  elseif ($unit == 'in') $k = 72;
672 
673  // Make substitution
674  $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, null);
675  complete_substitutions_array($substitutionarray, $outputlangs, null);
676  $text = make_substitutions($text, $substitutionarray, $outputlangs);
677  $text = $outputlangs->convToOutputCharset($text);
678 
679  $savx = $pdf->getX(); $savy = $pdf->getY();
680 
681  $watermark_angle = atan($h / $w) / 2;
682  $watermark_x_pos = 0;
683  $watermark_y_pos = $h / 3;
684  $watermark_x = $w / 2;
685  $watermark_y = $h / 3;
686  $pdf->SetFont('', 'B', 40);
687  $pdf->SetTextColor(255, 192, 203);
688  //rotate
689  $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));
690  //print watermark
691  $pdf->SetXY($watermark_x_pos, $watermark_y_pos);
692  $pdf->Cell($w - 20, 25, $outputlangs->convToOutputCharset($text), "", 2, "C", 0);
693  //antirotate
694  $pdf->_out('Q');
695 
696  $pdf->SetXY($savx, $savy);
697 }
698 
699 
712 function pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber = 0, $default_font_size = 10)
713 {
714  global $mysoc, $conf;
715 
716  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbank.class.php';
717 
718  $diffsizetitle = (empty($conf->global->PDF_DIFFSIZE_TITLE) ? 3 : $conf->global->PDF_DIFFSIZE_TITLE);
719  $diffsizecontent = (empty($conf->global->PDF_DIFFSIZE_CONTENT) ? 4 : $conf->global->PDF_DIFFSIZE_CONTENT);
720  $pdf->SetXY($curx, $cury);
721 
722  if (empty($onlynumber))
723  {
724  $pdf->SetFont('', 'B', $default_font_size - $diffsizetitle);
725  $pdf->MultiCell(100, 3, $outputlangs->transnoentities('PaymentByTransferOnThisBankAccount').':', 0, 'L', 0);
726  $cury += 4;
727  }
728 
729  $outputlangs->load("banks");
730 
731  // Use correct name of bank id according to country
732  $bickey = "BICNumber";
733  if ($account->getCountryCode() == 'IN') $bickey = "SWIFT";
734 
735  // Get format of bank account according to its country
736  $usedetailedbban = $account->useDetailedBBAN();
737 
738  //$onlynumber=0; $usedetailedbban=1; // For tests
739  if ($usedetailedbban)
740  {
741  $savcurx = $curx;
742 
743  if (empty($onlynumber))
744  {
745  $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
746  $pdf->SetXY($curx, $cury);
747  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
748  $cury += 3;
749  }
750 
751  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
752  {
753  // Note:
754  // bank = code_banque (FR), sort code (GB, IR. Example: 12-34-56)
755  // desk = code guichet (FR), used only when $usedetailedbban = 1
756  // number = account number
757  // key = check control key used only when $usedetailedbban = 1
758  if (empty($onlynumber)) $pdf->line($curx + 1, $cury + 1, $curx + 1, $cury + 6);
759 
760 
761  foreach ($account->getFieldsToShow() as $val)
762  {
763  $pdf->SetXY($curx, $cury + 4);
764  $pdf->SetFont('', '', $default_font_size - 3);
765 
766  if ($val == 'BankCode') {
767  // Bank code
768  $tmplength = 18;
769  $content = $account->code_banque;
770  } elseif ($val == 'DeskCode') {
771  // Desk
772  $tmplength = 18;
773  $content = $account->code_guichet;
774  } elseif ($val == 'BankAccountNumber') {
775  // Number
776  $tmplength = 24;
777  $content = $account->number;
778  } elseif ($val == 'BankAccountNumberKey') {
779  // Key
780  $tmplength = 15;
781  $content = $account->cle_rib;
782  } elseif ($val == 'IBAN' || $val == 'BIC') {
783  // Key
784  $tmplength = 0;
785  $content = '';
786  } else {
787  dol_print_error($account->db, 'Unexpected value for getFieldsToShow: '.$val);
788  break;
789  }
790 
791  $pdf->MultiCell($tmplength, 3, $outputlangs->convToOutputCharset($content), 0, 'C', 0);
792  $pdf->SetXY($curx, $cury + 1);
793  $curx += $tmplength;
794  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
795  $pdf->MultiCell($tmplength, 3, $outputlangs->transnoentities($val), 0, 'C', 0);
796  if (empty($onlynumber)) {
797  $pdf->line($curx, $cury + 1, $curx, $cury + 7);
798  }
799  }
800 
801  $curx = $savcurx;
802  $cury += 8;
803  }
804  } else {
805  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
806  $pdf->SetXY($curx, $cury);
807  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("Bank").': '.$outputlangs->convToOutputCharset($account->bank), 0, 'L', 0);
808  $cury += 3;
809 
810  $pdf->SetFont('', 'B', $default_font_size - $diffsizecontent);
811  $pdf->SetXY($curx, $cury);
812  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("BankAccountNumber").': '.$outputlangs->convToOutputCharset($account->number), 0, 'L', 0);
813  $cury += 3;
814 
815  if ($diffsizecontent <= 2) $cury += 1;
816  }
817 
818  $pdf->SetFont('', '', $default_font_size - $diffsizecontent);
819 
820  if (empty($onlynumber) && !empty($account->domiciliation)) {
821  $pdf->SetXY($curx, $cury);
822  $val = $outputlangs->transnoentities("Residence").': '.$outputlangs->convToOutputCharset($account->domiciliation);
823  $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
824  //$nboflines=dol_nboflines_bis($val,120);
825  //$cury+=($nboflines*3)+2;
826  $tmpy = $pdf->getStringHeight(100, $val);
827  $cury += $tmpy;
828  }
829 
830  if (!empty($account->proprio)) {
831  $pdf->SetXY($curx, $cury);
832  $val = $outputlangs->transnoentities("BankAccountOwner").': '.$outputlangs->convToOutputCharset($account->proprio);
833  $pdf->MultiCell(100, 3, $val, 0, 'L', 0);
834  $tmpy = $pdf->getStringHeight(100, $val);
835  $cury += $tmpy;
836  } elseif (!$usedetailedbban) {
837  $cury += 1;
838  }
839 
840  // Use correct name of bank id according to country
841  $ibankey = FormBank::getIBANLabel($account);
842 
843  if (!empty($account->iban))
844  {
845  //Remove whitespaces to ensure we are dealing with the format we expect
846  $ibanDisplay_temp = str_replace(' ', '', $outputlangs->convToOutputCharset($account->iban));
847  $ibanDisplay = "";
848 
849  $nbIbanDisplay_temp = dol_strlen($ibanDisplay_temp);
850  for ($i = 0; $i < $nbIbanDisplay_temp; $i++)
851  {
852  $ibanDisplay .= $ibanDisplay_temp[$i];
853  if ($i % 4 == 3 && $i > 0) $ibanDisplay .= " ";
854  }
855 
856  $pdf->SetFont('', 'B', $default_font_size - 3);
857  $pdf->SetXY($curx, $cury);
858  $pdf->MultiCell(100, 3, $outputlangs->transnoentities($ibankey).': '.$ibanDisplay, 0, 'L', 0);
859  $cury += 3;
860  }
861 
862  if (!empty($account->bic))
863  {
864  $pdf->SetFont('', 'B', $default_font_size - 3);
865  $pdf->SetXY($curx, $cury);
866  $pdf->MultiCell(100, 3, $outputlangs->transnoentities($bickey).': '.$outputlangs->convToOutputCharset($account->bic), 0, 'L', 0);
867  }
868 
869  return $pdf->getY();
870 }
871 
887 function pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails = 0, $hidefreetext = 0)
888 {
889  global $conf, $user, $mysoc;
890 
891  $outputlangs->load("dict");
892  $line = '';
893 
894  $dims = $pdf->getPageDimensions();
895 
896  // Line of free text
897  if (empty($hidefreetext) && !empty($conf->global->$paramfreetext))
898  {
899  $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
900  // More substitution keys
901  $substitutionarray['__FROM_NAME__'] = $fromcompany->name;
902  $substitutionarray['__FROM_EMAIL__'] = $fromcompany->email;
903  complete_substitutions_array($substitutionarray, $outputlangs, $object);
904  $newfreetext = make_substitutions($conf->global->$paramfreetext, $substitutionarray, $outputlangs);
905 
906  // Make a change into HTML code to allow to include images from medias directory.
907  // <img alt="" src="/dolibarr_dev/htdocs/viewimage.php?modulepart=medias&amp;entity=1&amp;file=image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
908  // become
909  // <img alt="" src="'.DOL_DATA_ROOT.'/medias/image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
910  $newfreetext = preg_replace('/(<img.*src=")[^\"]*viewimage\.php[^\"]*modulepart=medias[^\"]*file=([^\"]*)("[^\/]*\/>)/', '\1file:/'.DOL_DATA_ROOT.'/medias/\2\3', $newfreetext);
911 
912  $line .= $outputlangs->convToOutputCharset($newfreetext);
913  }
914 
915  // First line of company infos
916  $line1 = ""; $line2 = ""; $line3 = ""; $line4 = "";
917 
918  if ($showdetails == 1 || $showdetails == 3)
919  {
920  // Company name
921  if ($fromcompany->name)
922  {
923  $line1 .= ($line1 ? " - " : "").$outputlangs->transnoentities("RegisteredOffice").": ".$fromcompany->name;
924  }
925  // Address
926  if ($fromcompany->address)
927  {
928  $line1 .= ($line1 ? " - " : "").str_replace("\n", ", ", $fromcompany->address);
929  }
930  // Zip code
931  if ($fromcompany->zip)
932  {
933  $line1 .= ($line1 ? " - " : "").$fromcompany->zip;
934  }
935  // Town
936  if ($fromcompany->town)
937  {
938  $line1 .= ($line1 ? " " : "").$fromcompany->town;
939  }
940  // Country
941  if ($fromcompany->country)
942  {
943  $line1 .= ($line1 ? ", " : "").$fromcompany->country;
944  }
945  // Phone
946  if ($fromcompany->phone)
947  {
948  $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Phone").": ".$fromcompany->phone;
949  }
950  // Fax
951  if ($fromcompany->fax)
952  {
953  $line2 .= ($line2 ? " - " : "").$outputlangs->transnoentities("Fax").": ".$fromcompany->fax;
954  }
955 
956  // URL
957  if ($fromcompany->url)
958  {
959  $line2 .= ($line2 ? " - " : "").$fromcompany->url;
960  }
961  // Email
962  if ($fromcompany->email)
963  {
964  $line2 .= ($line2 ? " - " : "").$fromcompany->email;
965  }
966  }
967  if ($showdetails == 2 || $showdetails == 3 || ($fromcompany->country_code == 'DE'))
968  {
969  // Managers
970  if ($fromcompany->managers)
971  {
972  $line2 .= ($line2 ? " - " : "").$fromcompany->managers;
973  }
974  }
975 
976  // Line 3 of company infos
977  // Juridical status
978  if ($fromcompany->forme_juridique_code)
979  {
980  $line3 .= ($line3 ? " - " : "").$outputlangs->convToOutputCharset(getFormeJuridiqueLabel($fromcompany->forme_juridique_code));
981  }
982  // Capital
983  if ($fromcompany->capital)
984  {
985  $tmpamounttoshow = price2num($fromcompany->capital); // This field is a free string
986  if (is_numeric($tmpamounttoshow) && $tmpamounttoshow > 0) $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", price($tmpamounttoshow, 0, $outputlangs, 0, 0, 0, $conf->currency));
987  else $line3 .= ($line3 ? " - " : "").$outputlangs->transnoentities("CapitalOf", $tmpamounttoshow, $outputlangs);
988  }
989  // Prof Id 1
990  if ($fromcompany->idprof1 && ($fromcompany->country_code != 'FR' || !$fromcompany->idprof2))
991  {
992  $field = $outputlangs->transcountrynoentities("ProfId1", $fromcompany->country_code);
993  if (preg_match('/\((.*)\)/i', $field, $reg)) $field = $reg[1];
994  $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof1);
995  }
996  // Prof Id 2
997  if ($fromcompany->idprof2)
998  {
999  $field = $outputlangs->transcountrynoentities("ProfId2", $fromcompany->country_code);
1000  if (preg_match('/\((.*)\)/i', $field, $reg)) $field = $reg[1];
1001  $line3 .= ($line3 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof2);
1002  }
1003 
1004  // Line 4 of company infos
1005  // Prof Id 3
1006  if ($fromcompany->idprof3)
1007  {
1008  $field = $outputlangs->transcountrynoentities("ProfId3", $fromcompany->country_code);
1009  if (preg_match('/\((.*)\)/i', $field, $reg)) $field = $reg[1];
1010  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof3);
1011  }
1012  // Prof Id 4
1013  if ($fromcompany->idprof4)
1014  {
1015  $field = $outputlangs->transcountrynoentities("ProfId4", $fromcompany->country_code);
1016  if (preg_match('/\((.*)\)/i', $field, $reg)) $field = $reg[1];
1017  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof4);
1018  }
1019  // Prof Id 5
1020  if ($fromcompany->idprof5)
1021  {
1022  $field = $outputlangs->transcountrynoentities("ProfId5", $fromcompany->country_code);
1023  if (preg_match('/\((.*)\)/i', $field, $reg)) $field = $reg[1];
1024  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof5);
1025  }
1026  // Prof Id 6
1027  if ($fromcompany->idprof6)
1028  {
1029  $field = $outputlangs->transcountrynoentities("ProfId6", $fromcompany->country_code);
1030  if (preg_match('/\((.*)\)/i', $field, $reg)) $field = $reg[1];
1031  $line4 .= ($line4 ? " - " : "").$field.": ".$outputlangs->convToOutputCharset($fromcompany->idprof6);
1032  }
1033  // IntraCommunautary VAT
1034  if ($fromcompany->tva_intra != '')
1035  {
1036  $line4 .= ($line4 ? " - " : "").$outputlangs->transnoentities("VATIntraShort").": ".$outputlangs->convToOutputCharset($fromcompany->tva_intra);
1037  }
1038 
1039  $pdf->SetFont('', '', 7);
1040  $pdf->SetDrawColor(224, 224, 224);
1041 
1042  // The start of the bottom of this page footer is positioned according to # of lines
1043  $freetextheight = 0;
1044  if ($line) // Free text
1045  {
1046  //$line="sample text<br>\nfd<strong>sf</strong>sdf<br>\nghfghg<br>";
1047  if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT))
1048  {
1049  $width = 20000; $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.
1050  if (!empty($conf->global->MAIN_USE_AUTOWRAP_ON_FREETEXT)) {
1051  $width = 200; $align = 'C';
1052  }
1053  $freetextheight = $pdf->getStringHeight($width, $line);
1054  } else {
1055  $freetextheight = pdfGetHeightForHtmlContent($pdf, dol_htmlentitiesbr($line, 1, 'UTF-8', 0)); // New method (works for HTML content)
1056  //print '<br>'.$freetextheight;exit;
1057  }
1058  }
1059 
1060  $marginwithfooter = $marge_basse + $freetextheight + (!empty($line1) ? 3 : 0) + (!empty($line2) ? 3 : 0) + (!empty($line3) ? 3 : 0) + (!empty($line4) ? 3 : 0);
1061  $posy = $marginwithfooter + 0;
1062 
1063  if ($line) // Free text
1064  {
1065  $pdf->SetXY($dims['lm'], -$posy);
1066  if (empty($conf->global->PDF_ALLOW_HTML_FOR_FREE_TEXT)) // by default
1067  {
1068  $pdf->MultiCell(0, 3, $line, 0, $align, 0);
1069  } else {
1070  $pdf->writeHTMLCell($pdf->page_largeur - $pdf->margin_left - $pdf->margin_right, $freetextheight, $dims['lm'], $dims['hk'] - $marginwithfooter, dol_htmlentitiesbr($line, 1, 'UTF-8', 0));
1071  }
1072  $posy -= $freetextheight;
1073  }
1074 
1075  $pdf->SetY(-$posy);
1076  $pdf->line($dims['lm'], $dims['hk'] - $posy, $dims['wk'] - $dims['rm'], $dims['hk'] - $posy);
1077  $posy--;
1078 
1079  if (!empty($line1))
1080  {
1081  $pdf->SetFont('', 'B', 7);
1082  $pdf->SetXY($dims['lm'], -$posy);
1083  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line1, 0, 'C', 0);
1084  $posy -= 3;
1085  $pdf->SetFont('', '', 7);
1086  }
1087 
1088  if (!empty($line2))
1089  {
1090  $pdf->SetFont('', 'B', 7);
1091  $pdf->SetXY($dims['lm'], -$posy);
1092  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line2, 0, 'C', 0);
1093  $posy -= 3;
1094  $pdf->SetFont('', '', 7);
1095  }
1096 
1097  if (!empty($line3))
1098  {
1099  $pdf->SetXY($dims['lm'], -$posy);
1100  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line3, 0, 'C', 0);
1101  }
1102 
1103  if (!empty($line4))
1104  {
1105  $posy -= 3;
1106  $pdf->SetXY($dims['lm'], -$posy);
1107  $pdf->MultiCell($dims['wk'] - $dims['rm'] - $dims['lm'], 2, $line4, 0, 'C', 0);
1108  }
1109 
1110  // Show page nb only on iso languages (so default Helvetica font)
1111  if (strtolower(pdf_getPDFFont($outputlangs)) == 'helvetica')
1112  {
1113  $pdf->SetXY($dims['wk'] - $dims['rm'] - 15, -$posy);
1114  //print 'xxx'.$pdf->PageNo().'-'.$pdf->getAliasNbPages().'-'.$pdf->getAliasNumPage();exit;
1115  $pdf->MultiCell(15, 2, $pdf->PageNo().'/'.$pdf->getAliasNbPages(), 0, 'R', 0);
1116  }
1117 
1118  return $marginwithfooter;
1119 }
1120 
1135 function pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
1136 {
1137  $linkedobjects = pdf_getLinkedObjects($object, $outputlangs);
1138  if (!empty($linkedobjects))
1139  {
1140  foreach ($linkedobjects as $linkedobject)
1141  {
1142  $reftoshow = $linkedobject["ref_title"].' : '.$linkedobject["ref_value"];
1143  if (!empty($linkedobject["date_value"]))
1144  {
1145  $reftoshow .= ' / '.$linkedobject["date_value"];
1146  }
1147 
1148  $posy += 3;
1149  $pdf->SetXY($posx, $posy);
1150  $pdf->SetFont('', '', $default_font_size - 2);
1151  $pdf->MultiCell($w, $h, $reftoshow, '', $align);
1152  }
1153  }
1154 
1155  return $pdf->getY();
1156 }
1157 
1174 function pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
1175 {
1176  global $db, $conf, $langs, $hookmanager;
1177 
1178  $reshook = 0;
1179  $result = '';
1180  //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) ) )
1181  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
1182  {
1183  $special_code = empty($object->lines[$i]->special_code) ? '' : $object->lines[$i]->special_code;
1184  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1185  $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);
1186  $action = '';
1187  $reshook = $hookmanager->executeHooks('pdf_writelinedesc', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1188 
1189  if (!empty($hookmanager->resPrint)) $result .= $hookmanager->resPrint;
1190  }
1191  if (empty($reshook))
1192  {
1193  $labelproductservice = pdf_getlinedesc($object, $i, $outputlangs, $hideref, $hidedesc, $issupplierline);
1194 
1195  //var_dump($labelproductservice);exit;
1196 
1197  // 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"
1198  // We make the reverse, so PDF generation has the real URL.
1199  $labelproductservice = preg_replace('/(<img[^>]*src=")([^"]*)(&amp;)([^"]*")/', '\1\2&\4', $labelproductservice, -1, $nbrep);
1200 
1201  //var_dump($labelproductservice);exit;
1202 
1203  // Description
1204  $pdf->writeHTMLCell($w, $h, $posx, $posy, $outputlangs->convToOutputCharset($labelproductservice), 0, 1, false, true, 'J', true);
1205  $result .= $labelproductservice;
1206  }
1207  return $result;
1208 }
1209 
1221 function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0, $issupplierline = 0)
1222 {
1223  global $db, $conf, $langs;
1224 
1225  $idprod = (!empty($object->lines[$i]->fk_product) ? $object->lines[$i]->fk_product : false);
1226  $label = (!empty($object->lines[$i]->label) ? $object->lines[$i]->label : (!empty($object->lines[$i]->product_label) ? $object->lines[$i]->product_label : ''));
1227  $desc = (!empty($object->lines[$i]->desc) ? $object->lines[$i]->desc : (!empty($object->lines[$i]->description) ? $object->lines[$i]->description : ''));
1228  $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
1229  $note = (!empty($object->lines[$i]->note) ? $object->lines[$i]->note : '');
1230  $dbatch = (!empty($object->lines[$i]->detail_batch) ? $object->lines[$i]->detail_batch : false);
1231 
1232  if ($issupplierline)
1233  {
1234  include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
1235  $prodser = new ProductFournisseur($db);
1236  } else {
1237  include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
1238  $prodser = new Product($db);
1239  }
1240 
1241  if ($idprod)
1242  {
1243  $prodser->fetch($idprod);
1244  // If a predefined product and multilang and on other lang, we renamed label with label translated
1245  if (!empty($conf->global->MAIN_MULTILANGS) && ($outputlangs->defaultlang != $langs->defaultlang))
1246  {
1247  $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)
1248 
1249  // 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
1250  // ($textwasmodified is replaced with $textwasmodifiedorcompleted and we add completion).
1251 
1252  // Set label
1253  // If we want another language, and if label is same than default language (we did force it to a specific value), we can use translation.
1254  //var_dump($outputlangs->defaultlang.' - '.$langs->defaultlang.' - '.$label.' - '.$prodser->label);exit;
1255  $textwasmodified = ($label == $prodser->label);
1256  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["label"]) && ($textwasmodified || $translatealsoifmodified)) {
1257  $label = $prodser->multilangs[$outputlangs->defaultlang]["label"];
1258  }
1259 
1260  // Set desc
1261  // Manage HTML entities description test because $prodser->description is store with htmlentities but $desc no
1262  $textwasmodified = false;
1263  if (!empty($desc) && dol_textishtml($desc) && !empty($prodser->description) && dol_textishtml($prodser->description)) {
1264  $textwasmodified = (strpos(dol_html_entity_decode($desc, ENT_QUOTES | ENT_HTML5), dol_html_entity_decode($prodser->description, ENT_QUOTES | ENT_HTML5)) !== false);
1265  } else {
1266  $textwasmodified = ($desc == $prodser->description);
1267  }
1268  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["description"]) && ($textwasmodified || $translatealsoifmodified)) $desc = $prodser->multilangs[$outputlangs->defaultlang]["description"];
1269 
1270  // Set note
1271  $textwasmodified = ($note == $prodser->note);
1272  if (!empty($prodser->multilangs[$outputlangs->defaultlang]["note"]) && ($textwasmodified || $translatealsoifmodified)) $note = $prodser->multilangs[$outputlangs->defaultlang]["note"];
1273  }
1274  } elseif ($object->element == 'facture' || $object->element == 'facturefourn') {
1275  if ($object->type == $object::TYPE_DEPOSIT) {
1276  $desc = str_replace('(DEPOSIT)', $outputlangs->trans('Deposit'), $desc);
1277  }
1278  }
1279 
1280  // Description short of product line
1281  $libelleproduitservice = $label;
1282  if (!empty($libelleproduitservice) && !empty($conf->global->PDF_BOLD_PRODUCT_LABEL)) {
1283  $libelleproduitservice = '<b>'.$libelleproduitservice.'</b>';
1284  }
1285 
1286  // Add ref of subproducts
1287  if (!empty($conf->global->SHOW_SUBPRODUCT_REF_IN_PDF)) {
1288  $prodser->get_sousproduits_arbo();
1289  if (!empty($prodser->sousprods) && is_array($prodser->sousprods) && count($prodser->sousprods)) {
1290  $tmparrayofsubproducts = reset($prodser->sousprods);
1291  foreach ($tmparrayofsubproducts as $subprodval) {
1292  $libelleproduitservice .= "\n * ".$subprodval[5].(($subprodval[5] && $subprodval[3]) ? ' - ' : '').$subprodval[3].' ('.$subprodval[1].')';
1293  }
1294  }
1295  }
1296 
1297  // Description long of product line
1298  if (!empty($desc) && ($desc != $label))
1299  {
1300  if ($libelleproduitservice && empty($hidedesc))
1301  {
1302  $libelleproduitservice .= '__N__';
1303  }
1304 
1305  if ($desc == '(CREDIT_NOTE)' && $object->lines[$i]->fk_remise_except)
1306  {
1307  $discount = new DiscountAbsolute($db);
1308  $discount->fetch($object->lines[$i]->fk_remise_except);
1309  $sourceref = !empty($discount->discount_type) ? $discount->ref_invoive_supplier_source : $discount->ref_facture_source;
1310  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromCreditNote", $sourceref);
1311  } elseif ($desc == '(DEPOSIT)' && $object->lines[$i]->fk_remise_except)
1312  {
1313  $discount = new DiscountAbsolute($db);
1314  $discount->fetch($object->lines[$i]->fk_remise_except);
1315  $sourceref = !empty($discount->discount_type) ? $discount->ref_invoive_supplier_source : $discount->ref_facture_source;
1316  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromDeposit", $sourceref);
1317  // Add date of deposit
1318  if (!empty($conf->global->INVOICE_ADD_DEPOSIT_DATE)) $libelleproduitservice .= ' ('.dol_print_date($discount->datec, 'day', '', $outputlangs).')';
1319  } elseif ($desc == '(EXCESS RECEIVED)' && $object->lines[$i]->fk_remise_except)
1320  {
1321  $discount = new DiscountAbsolute($db);
1322  $discount->fetch($object->lines[$i]->fk_remise_except);
1323  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessReceived", $discount->ref_facture_source);
1324  } elseif ($desc == '(EXCESS PAID)' && $object->lines[$i]->fk_remise_except)
1325  {
1326  $discount = new DiscountAbsolute($db);
1327  $discount->fetch($object->lines[$i]->fk_remise_except);
1328  $libelleproduitservice = $outputlangs->transnoentitiesnoconv("DiscountFromExcessPaid", $discount->ref_invoice_supplier_source);
1329  } else {
1330  if ($idprod) {
1331  // Check if description must be output
1332  if (!empty($object->element)) {
1333  $tmpkey = 'MAIN_DOCUMENTS_HIDE_DESCRIPTION_FOR_'.strtoupper($object->element);
1334  if (!empty($conf->global->$tmpkey)) {
1335  $hidedesc = 1;
1336  }
1337  }
1338  if (empty($hidedesc)) {
1339  if (!empty($conf->global->MAIN_DOCUMENTS_DESCRIPTION_FIRST)) {
1340  $libelleproduitservice = $desc."\n".$libelleproduitservice;
1341  } else {
1342  if (!empty($conf->global->HIDE_LABEL_VARIANT_PDF) && $prodser->isVariant()) {
1343  $libelleproduitservice = $desc;
1344  } else {
1345  $libelleproduitservice .= $desc;
1346  }
1347  }
1348  }
1349  } else {
1350  $libelleproduitservice .= $desc;
1351  }
1352  }
1353  }
1354 
1355  // We add ref of product (and supplier ref if defined)
1356  $prefix_prodserv = "";
1357  $ref_prodserv = "";
1358  if (!empty($conf->global->PRODUCT_ADD_TYPE_IN_DOCUMENTS)) { // In standard mode, we do not show this
1359  if ($prodser->isService()) {
1360  $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Service")." ";
1361  } else {
1362  $prefix_prodserv = $outputlangs->transnoentitiesnoconv("Product")." ";
1363  }
1364  }
1365 
1366  if (empty($hideref)) {
1367  if ($issupplierline) {
1368  if (empty($conf->global->PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES)) { // Common case
1369  $ref_prodserv = $prodser->ref; // Show local ref
1370  if ($ref_supplier) $ref_prodserv .= ($prodser->ref ? ' (' : '').$outputlangs->transnoentitiesnoconv("SupplierRef").' '.$ref_supplier.($prodser->ref ? ')' : '');
1371  } elseif ($conf->global->PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES == 1) {
1372  $ref_prodserv = $ref_supplier;
1373  } elseif ($conf->global->PDF_HIDE_PRODUCT_REF_IN_SUPPLIER_LINES == 2) {
1374  $ref_prodserv = $ref_supplier.' ('.$outputlangs->transnoentitiesnoconv("InternalRef").' '.$prodser->ref.')';
1375  }
1376  } else {
1377  $ref_prodserv = $prodser->ref; // Show local ref only
1378  }
1379 
1380  if (!empty($libelleproduitservice) && !empty($ref_prodserv)) $ref_prodserv .= " - ";
1381  }
1382 
1383  if (!empty($ref_prodserv) && !empty($conf->global->PDF_BOLD_PRODUCT_REF_AND_PERIOD)) { $ref_prodserv = '<b>'.$ref_prodserv.'</b>'; }
1384  $libelleproduitservice = $prefix_prodserv.$ref_prodserv.$libelleproduitservice;
1385 
1386  // Add an additional description for the category products
1387  if (!empty($conf->global->CATEGORY_ADD_DESC_INTO_DOC) && $idprod && !empty($conf->categorie->enabled))
1388  {
1389  include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1390  $categstatic = new Categorie($db);
1391  // recovering the list of all the categories linked to product
1392  $tblcateg = $categstatic->containing($idprod, Categorie::TYPE_PRODUCT);
1393  foreach ($tblcateg as $cate)
1394  {
1395  // Adding the descriptions if they are filled
1396  $desccateg = $cate->description;
1397  if ($desccateg)
1398  $libelleproduitservice .= '__N__'.$desccateg;
1399  }
1400  }
1401 
1402  if (!empty($object->lines[$i]->date_start) || !empty($object->lines[$i]->date_end))
1403  {
1404  $format = 'day';
1405  $period = '';
1406  // Show duration if exists
1407  if ($object->lines[$i]->date_start && $object->lines[$i]->date_end)
1408  {
1409  $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)).')';
1410  }
1411  if ($object->lines[$i]->date_start && !$object->lines[$i]->date_end)
1412  {
1413  $period = '('.$outputlangs->transnoentitiesnoconv('DateFrom', dol_print_date($object->lines[$i]->date_start, $format, false, $outputlangs)).')';
1414  }
1415  if (!$object->lines[$i]->date_start && $object->lines[$i]->date_end)
1416  {
1417  $period = '('.$outputlangs->transnoentitiesnoconv('DateUntil', dol_print_date($object->lines[$i]->date_end, $format, false, $outputlangs)).')';
1418  }
1419  //print '>'.$outputlangs->charset_output.','.$period;
1420  if (!empty($conf->global->PDF_BOLD_PRODUCT_REF_AND_PERIOD)) {
1421  $libelleproduitservice .= '<b style="color:#333666;" ><em>'."__N__</b> ".$period.'</em>';
1422  } else {
1423  $libelleproduitservice .= "__N__".$period;
1424  }
1425  //print $libelleproduitservice;
1426  }
1427 
1428  if ($dbatch)
1429  {
1430  $format = 'day';
1431  foreach ($dbatch as $detail)
1432  {
1433  $dte = array();
1434  if ($detail->eatby) $dte[] = $outputlangs->transnoentitiesnoconv('printEatby', dol_print_date($detail->eatby, $format, false, $outputlangs));
1435  if ($detail->sellby) $dte[] = $outputlangs->transnoentitiesnoconv('printSellby', dol_print_date($detail->sellby, $format, false, $outputlangs));
1436  if ($detail->batch) $dte[] = $outputlangs->transnoentitiesnoconv('printBatch', $detail->batch);
1437  $dte[] = $outputlangs->transnoentitiesnoconv('printQty', $detail->qty);
1438  $libelleproduitservice .= "__N__ ".implode(" - ", $dte);
1439  }
1440  }
1441 
1442  // Now we convert \n into br
1443  if (dol_textishtml($libelleproduitservice)) $libelleproduitservice = preg_replace('/__N__/', '<br>', $libelleproduitservice);
1444  else $libelleproduitservice = preg_replace('/__N__/', "\n", $libelleproduitservice);
1445  $libelleproduitservice = dol_htmlentitiesbr($libelleproduitservice, 1);
1446 
1447  return $libelleproduitservice;
1448 }
1449 
1459 function pdf_getlinenum($object, $i, $outputlangs, $hidedetails = 0)
1460 {
1461  global $hookmanager;
1462 
1463  $reshook = 0;
1464  $result = '';
1465  //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) ) )
1466  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
1467  {
1468  $special_code = $object->lines[$i]->special_code;
1469  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1470  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1471  $action = '';
1472  $reshook = $hookmanager->executeHooks('pdf_getlinenum', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1473  $result .= $hookmanager->resPrint;
1474  }
1475  if (empty($reshook))
1476  {
1477  $result .= dol_htmlentitiesbr($object->lines[$i]->num);
1478  }
1479  return $result;
1480 }
1481 
1482 
1492 function pdf_getlineref($object, $i, $outputlangs, $hidedetails = 0)
1493 {
1494  global $hookmanager;
1495 
1496  $reshook = 0;
1497  $result = '';
1498  //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) ) )
1499  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
1500  {
1501  $special_code = $object->lines[$i]->special_code;
1502  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1503  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1504  $action = '';
1505  $reshook = $hookmanager->executeHooks('pdf_getlineref', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1506  $result .= $hookmanager->resPrint;
1507  }
1508  if (empty($reshook))
1509  {
1510  $result .= dol_htmlentitiesbr($object->lines[$i]->product_ref);
1511  }
1512  return $result;
1513 }
1514 
1524 function pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails = 0)
1525 {
1526  global $hookmanager;
1527 
1528  $reshook = 0;
1529  $result = '';
1530  //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) ) )
1531  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
1532  {
1533  $special_code = $object->lines[$i]->special_code;
1534  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1535  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1536  $action = '';
1537  $reshook = $hookmanager->executeHooks('pdf_getlineref_supplier', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1538  $result .= $hookmanager->resPrint;
1539  }
1540  if (empty($reshook))
1541  {
1542  $result .= dol_htmlentitiesbr($object->lines[$i]->ref_supplier);
1543  }
1544  return $result;
1545 }
1546 
1556 function pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails = 0)
1557 {
1558  global $conf, $hookmanager, $mysoc;
1559 
1560  $result = '';
1561  $reshook = 0;
1562  //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) ) )
1563  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
1564  {
1565  $special_code = $object->lines[$i]->special_code;
1566  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1567  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1568  $action = '';
1569  $reshook = $hookmanager->executeHooks('pdf_getlinevatrate', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1570 
1571  if (!empty($hookmanager->resPrint)) $result .= $hookmanager->resPrint;
1572  }
1573  if (empty($reshook))
1574  {
1575  if (empty($hidedetails) || $hidedetails > 1)
1576  {
1577  $tmpresult = '';
1578 
1579  $tmpresult .= vatrate($object->lines[$i]->tva_tx, 0, $object->lines[$i]->info_bits, -1);
1580  if (empty($conf->global->MAIN_PDF_MAIN_HIDE_SECOND_TAX))
1581  {
1582  if ($object->lines[$i]->total_localtax1 != 0)
1583  {
1584  if (preg_replace('/[\s0%]/', '', $tmpresult)) $tmpresult .= '/';
1585  else $tmpresult = '';
1586  $tmpresult .= vatrate(abs($object->lines[$i]->localtax1_tx), 0);
1587  }
1588  }
1589  if (empty($conf->global->MAIN_PDF_MAIN_HIDE_THIRD_TAX))
1590  {
1591  if ($object->lines[$i]->total_localtax2 != 0)
1592  {
1593  if (preg_replace('/[\s0%]/', '', $tmpresult)) $tmpresult .= '/';
1594  else $tmpresult = '';
1595  $tmpresult .= vatrate(abs($object->lines[$i]->localtax2_tx), 0);
1596  }
1597  }
1598  $tmpresult .= '%';
1599 
1600  $result .= $tmpresult;
1601  }
1602  }
1603  return $result;
1604 }
1605 
1615 function pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails = 0)
1616 {
1617  global $conf, $hookmanager;
1618 
1619  $sign = 1;
1620  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign = -1;
1621 
1622  $result = '';
1623  $reshook = 0;
1624  //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) ) )
1625  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
1626  {
1627  $special_code = $object->lines[$i]->special_code;
1628  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1629  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1630  $action = '';
1631  $reshook = $hookmanager->executeHooks('pdf_getlineupexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1632 
1633  if (!empty($hookmanager->resPrint)) $result .= $hookmanager->resPrint;
1634  }
1635  if (empty($reshook))
1636  {
1637  if (empty($hidedetails) || $hidedetails > 1)
1638  {
1639  $subprice = (!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_subprice : $object->lines[$i]->subprice);
1640  $result .= price($sign * $subprice, 0, $outputlangs);
1641  }
1642  }
1643  return $result;
1644 }
1645 
1655 function pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails = 0)
1656 {
1657  global $hookmanager, $conf;
1658 
1659  $sign = 1;
1660  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign = -1;
1661 
1662  $result = '';
1663  $reshook = 0;
1664  //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) ) )
1665  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
1666  {
1667  $special_code = $object->lines[$i]->special_code;
1668  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1669  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1670  $action = '';
1671  $reshook = $hookmanager->executeHooks('pdf_getlineupwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1672 
1673  if (!empty($hookmanager->resPrint)) $result .= $hookmanager->resPrint;
1674  }
1675  if (empty($reshook))
1676  {
1677  if (empty($hidedetails) || $hidedetails > 1) $result .= price($sign * (($object->lines[$i]->subprice) + ($object->lines[$i]->subprice) * ($object->lines[$i]->tva_tx) / 100), 0, $outputlangs);
1678  }
1679  return $result;
1680 }
1681 
1691 function pdf_getlineqty($object, $i, $outputlangs, $hidedetails = 0)
1692 {
1693  global $hookmanager;
1694 
1695  $result = '';
1696  $reshook = 0;
1697  //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) ) )
1698  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
1699  {
1700  $special_code = $object->lines[$i]->special_code;
1701  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1702  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1703  $action = '';
1704  $reshook = $hookmanager->executeHooks('pdf_getlineqty', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1705 
1706  if (!empty($hookmanager->resPrint)) $result = $hookmanager->resPrint;
1707  }
1708  if (empty($reshook))
1709  {
1710  if ($object->lines[$i]->special_code == 3) return '';
1711  if (empty($hidedetails) || $hidedetails > 1) $result .= $object->lines[$i]->qty;
1712  }
1713  return $result;
1714 }
1715 
1725 function pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails = 0)
1726 {
1727  global $hookmanager;
1728 
1729  $reshook = 0;
1730  $result = '';
1731  //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) ) )
1732  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
1733  {
1734  $special_code = $object->lines[$i]->special_code;
1735  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1736  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1737  $action = '';
1738  $reshook = $hookmanager->executeHooks('pdf_getlineqty_asked', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1739 
1740  if (!empty($hookmanager->resPrint)) $result .= $hookmanager->resPrint;
1741  }
1742  if (empty($reshook))
1743  {
1744  if ($object->lines[$i]->special_code == 3) return '';
1745  if (empty($hidedetails) || $hidedetails > 1) $result .= $object->lines[$i]->qty_asked;
1746  }
1747  return $result;
1748 }
1749 
1759 function pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails = 0)
1760 {
1761  global $hookmanager;
1762 
1763  $reshook = 0;
1764  $result = '';
1765  //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) ) )
1766  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
1767  {
1768  $special_code = $object->lines[$i]->special_code;
1769  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1770  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1771  $action = '';
1772  $reshook = $hookmanager->executeHooks('pdf_getlineqty_shipped', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1773 
1774  if (!empty($hookmanager->resPrint)) $result .= $hookmanager->resPrint;
1775  }
1776  if (empty($reshook))
1777  {
1778  if ($object->lines[$i]->special_code == 3) return '';
1779  if (empty($hidedetails) || $hidedetails > 1) $result .= $object->lines[$i]->qty_shipped;
1780  }
1781  return $result;
1782 }
1783 
1793 function pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails = 0)
1794 {
1795  global $hookmanager;
1796 
1797  $reshook = 0;
1798  $result = '';
1799  //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) ) )
1800  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
1801  {
1802  $special_code = $object->lines[$i]->special_code;
1803  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1804  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1805  $action = '';
1806  $reshook = $hookmanager->executeHooks('pdf_getlineqty_keeptoship', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1807 
1808  if (!empty($hookmanager->resPrint)) $result .= $hookmanager->resPrint;
1809  }
1810  if (empty($reshook))
1811  {
1812  if ($object->lines[$i]->special_code == 3) return '';
1813  if (empty($hidedetails) || $hidedetails > 1) $result .= ($object->lines[$i]->qty_asked - $object->lines[$i]->qty_shipped);
1814  }
1815  return $result;
1816 }
1817 
1828 function pdf_getlineunit($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = false)
1829 {
1830  global $langs;
1831 
1832  $reshook = 0;
1833  $result = '';
1834  //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) ) )
1835  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
1836  {
1837  $special_code = $object->lines[$i]->special_code;
1838  if (!empty($object->lines[$i]->fk_parent_line)) {
1839  $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1840  }
1841  $parameters = array(
1842  'i' => $i,
1843  'outputlangs' => $outputlangs,
1844  'hidedetails' => $hidedetails,
1845  'special_code' => $special_code
1846  );
1847  $action = '';
1848  $reshook = $hookmanager->executeHooks('pdf_getlineunit', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1849 
1850  if (!empty($hookmanager->resPrint)) $result .= $hookmanager->resPrint;
1851  }
1852  if (empty($reshook))
1853  {
1854  if (empty($hidedetails) || $hidedetails > 1) $result .= $langs->transnoentitiesnoconv($object->lines[$i]->getLabelOfUnit('short'));
1855  }
1856  return $result;
1857 }
1858 
1859 
1869 function pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails = 0)
1870 {
1871  global $hookmanager;
1872 
1873  include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1874 
1875  $reshook = 0;
1876  $result = '';
1877  //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) ) )
1878  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
1879  {
1880  $special_code = $object->lines[$i]->special_code;
1881  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1882  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
1883  $action = '';
1884  $reshook = $hookmanager->executeHooks('pdf_getlineremisepercent', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1885 
1886  if (!empty($hookmanager->resPrint)) $result .= $hookmanager->resPrint;
1887  }
1888  if (empty($reshook))
1889  {
1890  if ($object->lines[$i]->special_code == 3) return '';
1891  if (empty($hidedetails) || $hidedetails > 1) $result .= dol_print_reduction($object->lines[$i]->remise_percent, $outputlangs);
1892  }
1893  return $result;
1894 }
1895 
1906 function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookmanager = null)
1907 {
1908  if (empty($hookmanager)) global $hookmanager;
1909  global $conf;
1910 
1911  $reshook = 0;
1912  $result = '';
1913  //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) ) )
1914  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
1915  {
1916  $special_code = $object->lines[$i]->special_code;
1917  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1918  $parameters = array('i' => $i, 'outputlangs' => $outputlangs, 'hidedetails' => $hidedetails, 'special_code' => $special_code);
1919  $action = '';
1920  $reshook = $hookmanager->executeHooks('pdf_getlineprogress', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1921 
1922  if (!empty($hookmanager->resPrint)) return $hookmanager->resPrint;
1923  }
1924  if (empty($reshook))
1925  {
1926  if ($object->lines[$i]->special_code == 3) return '';
1927  if (empty($hidedetails) || $hidedetails > 1)
1928  {
1929  if ($conf->global->SITUATION_DISPLAY_DIFF_ON_PDF)
1930  {
1931  $prev_progress = 0;
1932  if (method_exists($object, 'get_prev_progress'))
1933  {
1934  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
1935  }
1936  $result = ($object->lines[$i]->situation_percent - $prev_progress).'%';
1937  } else $result = $object->lines[$i]->situation_percent.'%';
1938  }
1939  }
1940  return $result;
1941 }
1942 
1952 function pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails = 0)
1953 {
1954  global $conf, $hookmanager;
1955 
1956  $sign = 1;
1957  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign = -1;
1958 
1959  $reshook = 0;
1960  $result = '';
1961  //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) ) )
1962  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
1963  {
1964  $special_code = $object->lines[$i]->special_code;
1965  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
1966  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code, 'sign'=>$sign);
1967  $action = '';
1968  $reshook = $hookmanager->executeHooks('pdf_getlinetotalexcltax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1969 
1970  if (!empty($hookmanager->resPrint)) $result .= $hookmanager->resPrint;
1971  }
1972  if (empty($reshook))
1973  {
1974  if ($object->lines[$i]->special_code == 3)
1975  {
1976  $result .= $outputlangs->transnoentities("Option");
1977  }
1978  elseif (empty($hidedetails) || $hidedetails > 1)
1979  {
1980  $total_ht = (!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
1981  if (!empty($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0)
1982  {
1983  // TODO Remove this. The total should be saved correctly in database instead of being modified here.
1984  $prev_progress = 0;
1985  $progress = 1;
1986  if (method_exists($object->lines[$i], 'get_prev_progress'))
1987  {
1988  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
1989  $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
1990  }
1991  $result .= price($sign * ($total_ht / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
1992  } else {
1993  $result .= price($sign * $total_ht, 0, $outputlangs);
1994  }
1995  }
1996  }
1997  return $result;
1998 }
1999 
2009 function pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails = 0)
2010 {
2011  global $hookmanager, $conf;
2012 
2013  $sign = 1;
2014  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign = -1;
2015 
2016  $reshook = 0;
2017  $result = '';
2018  //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) ) )
2019  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
2020  {
2021  $special_code = $object->lines[$i]->special_code;
2022  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2023  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2024  $action = '';
2025  $reshook = $hookmanager->executeHooks('pdf_getlinetotalwithtax', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2026 
2027  if (!empty($hookmanager->resPrint)) $result .= $hookmanager->resPrint;
2028  }
2029  if (empty($reshook))
2030  {
2031  if ($object->lines[$i]->special_code == 3)
2032  {
2033  $result .= $outputlangs->transnoentities("Option");
2034  }
2035  elseif (empty($hidedetails) || $hidedetails > 1)
2036  {
2037  $total_ttc = (!empty($conf->multicurrency->enabled) && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ttc : $object->lines[$i]->total_ttc);
2038  if ($object->lines[$i]->situation_percent > 0)
2039  {
2040  // TODO Remove this. The total should be saved correctly in database instead of being modified here.
2041  $prev_progress = 0;
2042  $progress = 1;
2043  if (method_exists($object->lines[$i], 'get_prev_progress'))
2044  {
2045  $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
2046  $progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
2047  }
2048  $result .= price($sign * ($total_ttc / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
2049  } else {
2050  $result .= price($sign * $total_ttc, 0, $outputlangs);
2051  }
2052  }
2053  }
2054  return $result;
2055 }
2056 
2066 function pdf_getTotalQty($object, $type, $outputlangs)
2067 {
2068  global $hookmanager;
2069 
2070  $total = 0;
2071  $nblines = count($object->lines);
2072 
2073  // Loop on each lines
2074  for ($i = 0; $i < $nblines; $i++)
2075  {
2076  if ($object->lines[$i]->special_code != 3)
2077  {
2078  if ($type == 'all')
2079  {
2080  $total += $object->lines[$i]->qty;
2081  } elseif ($type == 9 && is_object($hookmanager) && (($object->lines[$i]->product_type == 9 && !empty($object->lines[$i]->special_code)) || !empty($object->lines[$i]->fk_parent_line)))
2082  {
2083  $special_code = $object->lines[$i]->special_code;
2084  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2085  $parameters = array('i'=>$i, 'outputlangs'=>$outputlangs, 'hidedetails'=>$hidedetails, 'special_code'=>$special_code);
2086  $action = '';
2087  $reshook = $hookmanager->executeHooks('pdf_getTotalQty', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2088  return $hookmanager->resPrint;
2089  } elseif ($type == 0 && $object->lines[$i]->product_type == 0)
2090  {
2091  $total += $object->lines[$i]->qty;
2092  } elseif ($type == 1 && $object->lines[$i]->product_type == 1)
2093  {
2094  $total += $object->lines[$i]->qty;
2095  }
2096  }
2097  }
2098 
2099  return $total;
2100 }
2101 
2110 function pdf_getLinkedObjects($object, $outputlangs)
2111 {
2112  global $db, $hookmanager;
2113 
2114  $linkedobjects = array();
2115 
2116  $object->fetchObjectLinked();
2117 
2118  foreach ($object->linkedObjects as $objecttype => $objects)
2119  {
2120  if ($objecttype == 'facture')
2121  {
2122  // 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.
2123  } elseif ($objecttype == 'propal' || $objecttype == 'supplier_proposal')
2124  {
2125  $outputlangs->load('propal');
2126 
2127  foreach ($objects as $elementobject)
2128  {
2129  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefProposal");
2130  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2131  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DatePropal");
2132  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2133  }
2134  } elseif ($objecttype == 'commande' || $objecttype == 'supplier_order')
2135  {
2136  $outputlangs->load('orders');
2137  foreach ($objects as $elementobject)
2138  {
2139  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder");
2140  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref).($elementobject->ref_client ? ' ('.$elementobject->ref_client.')' : '').($elementobject->ref_supplier ? ' ('.$elementobject->ref_supplier.')' : '');
2141  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("OrderDate");
2142  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date, 'day', '', $outputlangs);
2143  }
2144  } elseif ($objecttype == 'contrat')
2145  {
2146  $outputlangs->load('contracts');
2147  foreach ($objects as $elementobject)
2148  {
2149  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefContract");
2150  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2151  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DateContract");
2152  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->date_contrat, 'day', '', $outputlangs);
2153  }
2154  } elseif ($objecttype == 'fichinter')
2155  {
2156  $outputlangs->load('interventions');
2157  foreach ($objects as $elementobject)
2158  {
2159  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("InterRef");
2160  $linkedobjects[$objecttype]['ref_value'] = $outputlangs->transnoentities($elementobject->ref);
2161  $linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("InterDate");
2162  $linkedobjects[$objecttype]['date_value'] = dol_print_date($elementobject->datec, 'day', '', $outputlangs);
2163  }
2164  } elseif ($objecttype == 'shipping')
2165  {
2166  $outputlangs->loadLangs(array("orders", "sendings"));
2167 
2168  foreach ($objects as $x => $elementobject)
2169  {
2170  $order = null;
2171  // We concat this record info into fields xxx_value. title is overwrote.
2172  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
2173  {
2174  $elementobject->fetchObjectLinked(null, '', null, '', 'OR', 1, 'sourcetype', 0);
2175  if (!empty($elementobject->linkedObjectsIds['commande'])) {
2176  include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
2177  $order = new Commande($db);
2178  $ret = $order->fetch(reset($elementobject->linkedObjectsIds['commande']));
2179  if ($ret < 1) { $order = null; }
2180  }
2181  }
2182  if (!is_object($order))
2183  {
2184  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefSending");
2185  if (!empty($linkedobjects[$objecttype]['ref_value'])) $linkedobjects[$objecttype]['ref_value'] .= ' / ';
2186  $linkedobjects[$objecttype]['ref_value'] .= $outputlangs->transnoentities($elementobject->ref);
2187  //$linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("DateShipment");
2188  //if (! empty($linkedobjects[$objecttype]['date_value'])) $linkedobjects[$objecttype]['date_value'].=' / ';
2189  //$linkedobjects[$objecttype]['date_value'].= dol_print_date($elementobject->date_delivery,'day','',$outputlangs);
2190  } else {
2191  $linkedobjects[$objecttype]['ref_title'] = $outputlangs->transnoentities("RefOrder").' / '.$outputlangs->transnoentities("RefSending");
2192  if (empty($linkedobjects[$objecttype]['ref_value'])) $linkedobjects[$objecttype]['ref_value'] = $outputlangs->convToOutputCharset($order->ref).($order->ref_client ? ' ('.$order->ref_client.')' : '');
2193  $linkedobjects[$objecttype]['ref_value'] .= ' / '.$outputlangs->transnoentities($elementobject->ref);
2194  //$linkedobjects[$objecttype]['date_title'] = $outputlangs->transnoentities("OrderDate") . ($elementobject->date_delivery ? ' / ' . $outputlangs->transnoentities("DateShipment") : '');
2195  //if (empty($linkedobjects[$objecttype]['date_value'])) $linkedobjects[$objecttype]['date_value'] = dol_print_date($order->date,'day','',$outputlangs);
2196  //$linkedobjects[$objecttype]['date_value'].= ($elementobject->date_delivery ? ' / ' . dol_print_date($elementobject->date_delivery,'day','',$outputlangs) : '');
2197  }
2198  }
2199  }
2200  }
2201 
2202  // For add external linked objects
2203  if (is_object($hookmanager))
2204  {
2205  $parameters = array('linkedobjects' => $linkedobjects, 'outputlangs'=>$outputlangs);
2206  $action = '';
2207  $hookmanager->executeHooks('pdf_getLinkedObjects', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2208  if (!empty($hookmanager->resArray)) $linkedobjects = $hookmanager->resArray;
2209  }
2210 
2211  return $linkedobjects;
2212 }
2213 
2221 function pdf_getSizeForImage($realpath)
2222 {
2223  global $conf;
2224 
2225  $maxwidth = (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH);
2226  $maxheight = (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT) ? 32 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_HEIGHT);
2227  include_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
2228  $tmp = dol_getImageSize($realpath);
2229  if ($tmp['height'])
2230  {
2231  $width = (int) round($maxheight * $tmp['width'] / $tmp['height']); // I try to use maxheight
2232  if ($width > $maxwidth) // Pb with maxheight, so i use maxwidth
2233  {
2234  $width = $maxwidth;
2235  $height = (int) round($maxwidth * $tmp['height'] / $tmp['width']);
2236  } else // No pb with maxheight
2237  {
2238  $height = $maxheight;
2239  }
2240  }
2241  return array('width'=>$width, 'height'=>$height);
2242 }
2243 
2253 function pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails = 0)
2254 {
2255  global $conf, $hookmanager;
2256  $sign = 1;
2257  if (isset($object->type) && $object->type == 2 && !empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE)) $sign = -1;
2258  if ($object->lines[$i]->special_code == 3)
2259  {
2260  return $outputlangs->transnoentities("Option");
2261  } else {
2262  if (is_object($hookmanager))
2263  {
2264  $special_code = $object->lines[$i]->special_code;
2265  if (!empty($object->lines[$i]->fk_parent_line)) $special_code = $object->getSpecialCode($object->lines[$i]->fk_parent_line);
2266 
2267  $parameters = array(
2268  'i'=>$i,
2269  'outputlangs'=>$outputlangs,
2270  'hidedetails'=>$hidedetails,
2271  'special_code'=>$special_code
2272  );
2273 
2274  $action = '';
2275 
2276  if ($hookmanager->executeHooks('getlinetotalremise', $parameters, $object, $action) > 0)
2277  {
2278  return $hookmanager->resPrint; // Note that $action and $object may have been modified by some hooks
2279  }
2280  }
2281 
2282  if (empty($hidedetails) || $hidedetails > 1) return $sign * (($object->lines[$i]->subprice * $object->lines[$i]->qty) - $object->lines[$i]->total_ht);
2283  }
2284  return '';
2285 }
pdf_getFormat(Translate $outputlangs=null, $mode= 'setup')
Return array with format properties of default PDF format.
Definition: pdf.lib.php:45
convToOutputCharset($str, $pagecodefrom= 'UTF-8')
Convert a string into output charset (this-&gt;charset_output that should be defined to conf-&gt;file-&gt;char...
pdf_bank(&$pdf, $outputlangs, $curx, $cury, $account, $onlynumber=0, $default_font_size=10)
Show bank informations for PDF generation.
Definition: pdf.lib.php:712
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto= 'UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition: pdf.lib.php:342
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition: pdf.lib.php:620
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition: pdf.lib.php:663
dol_getImageSize($file, $url=false)
Return size of image file on disk (Supported extensions are gif, jpg, png and bmp) ...
Definition: images.lib.php:86
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_print_reduction($reduction, $langs)
Returns formated reduction.
Class to manage contact/addresses.
pdf_getLinkedObjects($object, $outputlangs)
Return linked objects to use for document generation.
Definition: pdf.lib.php:2110
pdf_getlineqty_keeptoship($object, $i, $outputlangs, $hidedetails=0)
Return line keep to ship quantity.
Definition: pdf.lib.php:1793
pdf_getTotalQty($object, $type, $outputlangs)
Return total quantity of products and/or services.
Definition: pdf.lib.php:2066
dol_html_entity_decode($a, $b, $c= 'UTF-8', $keepsomeentities=0)
Replace html_entity_decode functions to manage errors.
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition: pdf.lib.php:245
Class to manage products or services.
pdf_getlinenum($object, $i, $outputlangs, $hidedetails=0)
Return line num.
Definition: pdf.lib.php:1459
pdf_getlineqty_asked($object, $i, $outputlangs, $hidedetails=0)
Return line quantity asked.
Definition: pdf.lib.php:1725
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...
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition: pdf.lib.php:222
pdf_getEncryption($pathoffile)
Return if pdf file is protected/encrypted.
Definition: pdf.lib.php:191
pdf_getlineunit($object, $i, $outputlangs, $hidedetails=0, $hookmanager=false)
Return line unit.
Definition: pdf.lib.php:1828
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...
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null)
Return array of possible common substitutions.
pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line total excluding tax.
Definition: pdf.lib.php:1952
static getIBANLabel(Account $account)
Returns the name of the Iban label.
pdf_getlinevatrate($object, $i, $outputlangs, $hidedetails=0)
Return line vat rate.
Definition: pdf.lib.php:1556
Class to manage third parties objects (customers, suppliers, prospects...)
pdf_getlineqty($object, $i, $outputlangs, $hidedetails=0)
Return line quantity.
Definition: pdf.lib.php:1691
getFormeJuridiqueLabel($code)
Retourne le nom traduit de la forme juridique.
Class to manage categories.
pdf_getlineqty_shipped($object, $i, $outputlangs, $hidedetails=0)
Return line quantity shipped.
Definition: pdf.lib.php:1759
pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0)
Show footer of page for PDF generation.
Definition: pdf.lib.php:887
dol_strlen($string, $stringencoding= 'UTF-8')
Make a strlen call.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
pdf_getlineupexcltax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price excluding tax.
Definition: pdf.lib.php:1615
pdfGetHeightForHtmlContent(&$pdf, $htmlcontent)
Function to try to calculate height of a HTML Content.
Definition: pdf.lib.php:294
Class to manage customers orders.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
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:2221
pdfGetLineTotalDiscountAmount($object, $i, $outputlangs, $hidedetails=0)
Return line total amount discount.
Definition: pdf.lib.php:2253
dol_getDefaultFormat(Translate $outputlangs=null)
Try to guess default paper format according to language into $langs.
Class to manage translations.
pdf_getlineupwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line unit price including tax.
Definition: pdf.lib.php:1655
getState($id, $withcode= '', $dbtouse=0, $withregion=0, $outputlangs= '', $entconv=1)
Return state translated from an id.
pdf_getlineremisepercent($object, $i, $outputlangs, $hidedetails=0)
Return line remise percent.
Definition: pdf.lib.php:1869
pdf_getlineprogress($object, $i, $outputlangs, $hidedetails=0, $hookmanager=null)
Return line percent.
Definition: pdf.lib.php:1906
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition: pdf.lib.php:270
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0)
Return a string with VAT rate label formated for view output Used into pdf and HTML pages...
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition: pdf.lib.php:1135
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:643
pdf_getInstance($format= '', $metric= 'mm', $pagetype= 'P')
Return a PDF instance object.
Definition: pdf.lib.php:88
pdf_getlineref($object, $i, $outputlangs, $hidedetails=0)
Return line product ref.
Definition: pdf.lib.php:1492
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:376
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
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:1174
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Class to manage absolute discounts.
make_substitutions($text, $substitutionarray, $outputlangs=null)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=&gt;newva...
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:1221
Class to manage predefined suppliers products.
dol_mkdir($dir, $dataroot= '', $newmask=null)
Creation of a directory (this can create recursive subdir)
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 &quot;subst...
pdf_getlineref_supplier($object, $i, $outputlangs, $hidedetails=0)
Return line ref_supplier.
Definition: pdf.lib.php:1524
dol_textishtml($msg, $option=0)
Return if a text is a html content.
pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails=0)
Return line total including tax.
Definition: pdf.lib.php:2009