dolibarr  17.0.4
pdf_espadon.modules.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2005-2012 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2014-2015 Marcos García <marcosgdf@gmail.com>
6  * Copyright (C) 2018-2020 Frédéric France <frederic.france@netlogic.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  * or see https://www.gnu.org/
21  */
22 
29 require_once DOL_DOCUMENT_ROOT.'/core/modules/expedition/modules_expedition.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
31 require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
32 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
33 
38 {
42  public $db;
43 
47  public $name;
48 
52  public $description;
53 
57  public $update_main_doc_field;
58 
62  public $type;
63 
68  public $phpmin = array(7, 0);
69 
74  public $version = 'dolibarr';
75 
79  public $page_largeur;
80 
84  public $page_hauteur;
85 
89  public $format;
90 
94  public $marge_gauche;
95 
99  public $marge_droite;
100 
104  public $marge_haute;
105 
109  public $marge_basse;
110 
115  public $emetteur;
116 
117 
123  public function __construct(DoliDB $db)
124  {
125  global $conf, $langs, $mysoc;
126 
127  $this->db = $db;
128  $this->name = "espadon";
129  $this->description = $langs->trans("DocumentModelStandardPDF");
130  $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
131 
132  $this->type = 'pdf';
133  $formatarray = pdf_getFormat();
134  $this->page_largeur = $formatarray['width'];
135  $this->page_hauteur = $formatarray['height'];
136  $this->format = array($this->page_largeur, $this->page_hauteur);
137  $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
138  $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
139  $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
140  $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
141 
142  $this->option_logo = 1; // Display logo
143  $this->option_draft_watermark = 1; // Support add of a watermark on drafts
144  $this->watermark = '';
145 
146  // Get source company
147  $this->emetteur = $mysoc;
148  if (!$this->emetteur->country_code) {
149  $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default if not defined
150  }
151 
152  $this->tabTitleHeight = 5; // default height
153  }
154 
155  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
167  public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
168  {
169  // phpcs:enable
170  global $user, $conf, $langs, $hookmanager;
171 
172  $object->fetch_thirdparty();
173 
174  if (!is_object($outputlangs)) {
175  $outputlangs = $langs;
176  }
177  // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
178  if (!empty($conf->global->MAIN_USE_FPDF)) {
179  $outputlangs->charset_output = 'ISO-8859-1';
180  }
181 
182  // Load traductions files required by page
183  $outputlangs->loadLangs(array("main", "bills", "orders", "products", "dict", "companies", "propal", "deliveries", "sendings", "productbatch"));
184 
185  // Show Draft Watermark
186  if ($object->statut == $object::STATUS_DRAFT && (!empty($conf->global->SHIPPING_DRAFT_WATERMARK))) {
187  $this->watermark = $conf->global->SHIPPING_DRAFT_WATERMARK;
188  }
189 
190  global $outputlangsbis;
191  $outputlangsbis = null;
192  if (!empty($conf->global->PDF_USE_ALSO_LANGUAGE_CODE) && $outputlangs->defaultlang != $conf->global->PDF_USE_ALSO_LANGUAGE_CODE) {
193  $outputlangsbis = new Translate('', $conf);
194  $outputlangsbis->setDefaultLang($conf->global->PDF_USE_ALSO_LANGUAGE_CODE);
195  $outputlangsbis->loadLangs(array("main", "bills", "orders", "products", "dict", "companies", "propal", "deliveries", "sendings", "productbatch"));
196  }
197 
198  $nblines = count($object->lines);
199 
200  // Loop on each lines to detect if there is at least one image to show
201  $realpatharray = array();
202  $this->atleastonephoto = false;
203  if (!empty($conf->global->MAIN_GENERATE_SHIPMENT_WITH_PICTURE)) {
204  $objphoto = new Product($this->db);
205 
206  for ($i = 0; $i < $nblines; $i++) {
207  if (empty($object->lines[$i]->fk_product)) {
208  continue;
209  }
210 
211  $objphoto->fetch($object->lines[$i]->fk_product);
212 
213  if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
214  $pdir = get_exdir($object->lines[$i]->fk_product, 2, 0, 0, $objphoto, 'product').$object->lines[$i]->fk_product."/photos/";
215  $dir = $conf->product->dir_output.'/'.$pdir;
216  } else {
217  $pdir = get_exdir(0, 0, 0, 0, $objphoto, 'product');
218  $dir = $conf->product->dir_output.'/'.$pdir;
219  }
220 
221  $realpath = '';
222 
223  foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) {
224  if (!getDolGlobalInt('CAT_HIGH_QUALITY_IMAGES')) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo
225  if ($obj['photo_vignette']) {
226  $filename = $obj['photo_vignette'];
227  } else {
228  $filename = $obj['photo'];
229  }
230  } else {
231  $filename = $obj['photo'];
232  }
233 
234  $realpath = $dir.$filename;
235  $this->atleastonephoto = true;
236  break;
237  }
238 
239  if ($realpath) {
240  $realpatharray[$i] = $realpath;
241  }
242  }
243  }
244 
245  if (count($realpatharray) == 0) {
246  $this->posxpicture = $this->posxweightvol;
247  }
248 
249  if ($conf->expedition->dir_output) {
250  // Definition of $dir and $file
251  if ($object->specimen) {
252  $dir = $conf->expedition->dir_output."/sending";
253  $file = $dir."/SPECIMEN.pdf";
254  } else {
255  $expref = dol_sanitizeFileName($object->ref);
256  $dir = $conf->expedition->dir_output."/sending/".$expref;
257  $file = $dir."/".$expref.".pdf";
258  }
259 
260  if (!file_exists($dir)) {
261  if (dol_mkdir($dir) < 0) {
262  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
263  return 0;
264  }
265  }
266 
267  if (file_exists($dir)) {
268  // Add pdfgeneration hook
269  if (!is_object($hookmanager)) {
270  include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
271  $hookmanager = new HookManager($this->db);
272  }
273  $hookmanager->initHooks(array('pdfgeneration'));
274  $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
275  global $action;
276  $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
277 
278  // Set nblines with the new facture lines content after hook
279  $nblines = count($object->lines);
280 
281  $pdf = pdf_getInstance($this->format);
282  $default_font_size = pdf_getPDFFontSize($outputlangs);
283  $heightforinfotot = 8; // Height reserved to output the info and total part
284  $heightforfreetext = (isset($conf->global->MAIN_PDF_FREETEXT_HEIGHT) ? $conf->global->MAIN_PDF_FREETEXT_HEIGHT : 5); // Height reserved to output the free text on last page
285  $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
286  if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS)) {
287  $heightforfooter += 6;
288  }
289  $pdf->SetAutoPageBreak(1, 0);
290 
291  if (class_exists('TCPDF')) {
292  $pdf->setPrintHeader(false);
293  $pdf->setPrintFooter(false);
294  }
295  $pdf->SetFont(pdf_getPDFFont($outputlangs));
296  // Set path to the background PDF File
297  if (!empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
298  $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND);
299  $tplidx = $pdf->importPage(1);
300  }
301 
302  $pdf->Open();
303  $pagenb = 0;
304  $pdf->SetDrawColor(128, 128, 128);
305 
306  if (method_exists($pdf, 'AliasNbPages')) {
307  $pdf->AliasNbPages();
308  }
309 
310  $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
311  $pdf->SetSubject($outputlangs->transnoentities("Shipment"));
312  $pdf->SetCreator("Dolibarr ".DOL_VERSION);
313  $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
314  $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("Shipment"));
315  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
316  $pdf->SetCompression(false);
317  }
318 
319  $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
320 
321  // New page
322  $pdf->AddPage();
323  if (!empty($tplidx)) {
324  $pdf->useTemplate($tplidx);
325  }
326  $pagenb++;
327  $top_shift = $this->_pagehead($pdf, $object, 1, $outputlangs);
328  $pdf->SetFont('', '', $default_font_size - 1);
329  $pdf->MultiCell(0, 3, ''); // Set interline to 3
330  $pdf->SetTextColor(0, 0, 0);
331 
332  $tab_top = 90;
333  $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 + $top_shift: 10);
334 
335  $tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext;
336 
337  $this->posxdesc = $this->marge_gauche + 1;
338 
339  // Incoterm
340  $height_incoterms = 0;
341  if (isModEnabled('incoterm')) {
342  $desc_incoterms = $object->getIncotermsForPDF();
343  if ($desc_incoterms) {
344  $tab_top -= 2;
345 
346  $pdf->SetFont('', '', $default_font_size - 1);
347  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
348  $nexY = $pdf->GetY();
349  $height_incoterms = $nexY - $tab_top;
350 
351  // Rect takes a length in 3rd parameter
352  $pdf->SetDrawColor(192, 192, 192);
353  $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_incoterms + 1);
354 
355  $tab_top = $nexY + 6;
356  $height_incoterms += 4;
357  }
358  }
359 
360  // display note
361  $notetoshow = empty($object->note_public) ? '' : $object->note_public;
362 
363  // Extrafields in note
364  $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
365  if (!empty($extranote)) {
366  $notetoshow = dol_concatdesc($notetoshow, $extranote);
367  }
368 
369  if (!empty($notetoshow) || !empty($object->tracking_number)) {
370  $tab_top -= 2;
371  $tab_topbeforetrackingnumber = $tab_top;
372 
373  // Tracking number
374  if (!empty($object->tracking_number)) {
375  $height_trackingnumber = 4;
376 
377  $pdf->SetFont('', 'B', $default_font_size - 2);
378  $pdf->writeHTMLCell(60, $height_trackingnumber, $this->posxdesc - 1, $tab_top - 1, $outputlangs->transnoentities("TrackingNumber") . " : " . $object->tracking_number, 0, 1, false, true, 'L');
379 
380  $tab_top_alt = $pdf->GetY();
381  $object->getUrlTrackingStatus($object->tracking_number);
382  if (!empty($object->tracking_url)) {
383  if ($object->shipping_method_id > 0) {
384  // Get code using getLabelFromKey
385  $code = $outputlangs->getLabelFromKey($this->db, $object->shipping_method_id, 'c_shipment_mode', 'rowid', 'code');
386  $label = '';
387  if ($object->tracking_url != $object->tracking_number) {
388  $label .= $outputlangs->trans("LinkToTrackYourPackage")."<br>";
389  }
390  $label .= $outputlangs->trans("SendingMethod").": ".$outputlangs->trans("SendingMethod".strtoupper($code));
391  //var_dump($object->tracking_url != $object->tracking_number);exit;
392  if ($object->tracking_url != $object->tracking_number) {
393  $label .= " : ";
394  $label .= $object->tracking_url;
395  }
396 
397  $height_trackingnumber += 4;
398  $pdf->SetFont('', 'B', $default_font_size - 2);
399  $pdf->writeHTMLCell(60, $height_trackingnumber, $this->posxdesc - 1, $tab_top_alt, $label, 0, 1, false, true, 'L');
400  }
401  }
402  $tab_top = $pdf->GetY();
403  }
404 
405 
406  // Notes
407  $pagenb = $pdf->getPage();
408  if (!empty($notetoshow) || !empty($object->tracking_number)) {
409  $tab_top -= 1;
410 
411  $tab_width = $this->page_largeur - $this->marge_gauche - $this->marge_droite;
412  $pageposbeforenote = $pagenb;
413 
414  $substitutionarray = pdf_getSubstitutionArray($outputlangs, null, $object);
415  complete_substitutions_array($substitutionarray, $outputlangs, $object);
416  $notetoshow = make_substitutions($notetoshow, $substitutionarray, $outputlangs);
417  $notetoshow = convertBackOfficeMediasLinksToPublicLinks($notetoshow);
418 
419  $pdf->startTransaction();
420 
421  $pdf->SetFont('', '', $default_font_size - 1);
422  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
423  // Description
424  $pageposafternote = $pdf->getPage();
425  $posyafter = $pdf->GetY();
426 
427  if ($pageposafternote > $pageposbeforenote) {
428  $pdf->rollbackTransaction(true);
429 
430  // prepare pages to receive notes
431  while ($pagenb < $pageposafternote) {
432  $pdf->AddPage();
433  $pagenb++;
434  if (!empty($tplidx)) $pdf->useTemplate($tplidx);
435  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
436  // $this->_pagefoot($pdf,$object,$outputlangs,1);
437  $pdf->setTopMargin($tab_top_newpage);
438  // The only function to edit the bottom margin of current page to set it.
439  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
440  }
441 
442  // back to start
443  $pdf->setPage($pageposbeforenote);
444  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
445  $pdf->SetFont('', '', $default_font_size - 1);
446  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
447  $pageposafternote = $pdf->getPage();
448 
449  $posyafter = $pdf->GetY();
450 
451  if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) { // There is no space left for total+free text
452  $pdf->AddPage('', '', true);
453  $pagenb++;
454  $pageposafternote++;
455  $pdf->setPage($pageposafternote);
456  $pdf->setTopMargin($tab_top_newpage);
457  // The only function to edit the bottom margin of current page to set it.
458  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext);
459  //$posyafter = $tab_top_newpage;
460  }
461 
462 
463  // apply note frame to previous pages
464  $i = $pageposbeforenote;
465  while ($i < $pageposafternote) {
466  $pdf->setPage($i);
467 
468 
469  $pdf->SetDrawColor(128, 128, 128);
470  // Draw note frame
471  if ($i > $pageposbeforenote) {
472  if (empty($height_trackingnumber)) {
473  $height_note = $this->page_hauteur - ($tab_top_newpage + $heightforfooter);
474  } else {
475  $height_note = $this->page_hauteur - ($tab_top_newpage + $heightforfooter) + $height_trackingnumber + 1;
476  $tab_top_newpage = $tab_topbeforetrackingnumber;
477  }
478  $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 2);
479  } else {
480  if (empty($height_trackingnumber)) {
481  $height_note = $this->page_hauteur - ($tab_top + $heightforfooter);
482  } else {
483  $height_note = $this->page_hauteur - ($tab_top + $heightforfooter)+ $height_trackingnumber + 1;
484  $tab_top = $tab_topbeforetrackingnumber;
485  }
486  $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 2);
487  }
488 
489  // Add footer
490  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
491  $this->_pagefoot($pdf, $object, $outputlangs, 1);
492 
493  $i++;
494  }
495 
496  // apply note frame to last page
497  $pdf->setPage($pageposafternote);
498  if (!empty($tplidx)) $pdf->useTemplate($tplidx);
499  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
500  $height_note = $posyafter - $tab_top_newpage;
501  $pdf->Rect($this->marge_gauche, $tab_top_newpage - 1, $tab_width, $height_note + 1);
502  } else // No pagebreak
503  {
504  $pdf->commitTransaction();
505  $posyafter = $pdf->GetY();
506  if (empty($height_trackingnumber)) {
507  $height_note = $posyafter - $tab_top + 1;
508  } else {
509  $height_note = $posyafter - $tab_top + $height_trackingnumber + 1;
510  $tab_top = $tab_topbeforetrackingnumber;
511  }
512  $pdf->Rect($this->marge_gauche, $tab_top - 1, $tab_width, $height_note + 2);
513 
514 
515  if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + 20))) {
516  // not enough space, need to add page
517  $pdf->AddPage('', '', true);
518  $pagenb++;
519  $pageposafternote++;
520  $pdf->setPage($pageposafternote);
521  if (!empty($tplidx)) $pdf->useTemplate($tplidx);
522  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
523 
524  $posyafter = $tab_top_newpage;
525  }
526  }
527 
528  $tab_height = $tab_height - $height_note;
529  $tab_top = $posyafter + 6;
530  } else {
531  $height_note = 0;
532  }
533  }
534 
535 
536  // Use new auto column system
537  $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
538 
539  // Table simulation to know the height of the title line
540  $pdf->startTransaction();
541  $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs);
542  $pdf->rollbackTransaction(true);
543 
544 
545  $nexY = $tab_top + $this->tabTitleHeight;
546 
547  // Loop on each lines
548  $pageposbeforeprintlines = $pdf->getPage();
549  $pagenb = $pageposbeforeprintlines;
550  for ($i = 0; $i < $nblines; $i++) {
551  $curY = $nexY;
552  $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
553  $pdf->SetTextColor(0, 0, 0);
554 
555  // Define size of image if we need it
556  $imglinesize = array();
557  if (!empty($realpatharray[$i])) {
558  $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
559  }
560 
561  $pdf->setTopMargin($tab_top_newpage);
562  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
563  $pageposbefore = $pdf->getPage();
564 
565  $showpricebeforepagebreak = 1;
566  $posYAfterImage = 0;
567  $posYAfterDescription = 0;
568 
569  if ($this->getColumnStatus('photo')) {
570  // We start with Photo of product line
571  if (isset($imglinesize['width']) && isset($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot))) { // If photo too high, we moved completely on new page
572  $pdf->AddPage('', '', true);
573  if (!empty($tplidx)) {
574  $pdf->useTemplate($tplidx);
575  }
576  //if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
577  $pdf->setPage($pageposbefore + 1);
578 
579  $curY = $tab_top_newpage;
580 
581  // Allows data in the first page if description is long enough to break in multiples pages
582  if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
583  $showpricebeforepagebreak = 1;
584  } else {
585  $showpricebeforepagebreak = 0;
586  }
587  }
588 
589 
590  if (!empty($this->cols['photo']) && isset($imglinesize['width']) && isset($imglinesize['height'])) {
591  $pdf->Image($realpatharray[$i], $this->getColumnContentXStart('photo'), $curY + 1, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
592  // $pdf->Image does not increase value return by getY, so we save it manually
593  $posYAfterImage = $curY + $imglinesize['height'];
594  }
595  }
596 
597  // Description of product line
598  if ($this->getColumnStatus('desc')) {
599  $pdf->startTransaction();
600 
601  $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc);
602 
603  $pageposafter = $pdf->getPage();
604  if ($pageposafter > $pageposbefore) { // There is a pagebreak
605  $pdf->rollbackTransaction(true);
606 
607  $this->printColDescContent($pdf, $curY, 'desc', $object, $i, $outputlangs, $hideref, $hidedesc);
608 
609  $pageposafter = $pdf->getPage();
610  $posyafter = $pdf->GetY();
611  //var_dump($posyafter); var_dump(($this->page_hauteur - ($heightforfooter+$heightforfreetext+$heightforinfotot))); exit;
612  if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot))) { // There is no space left for total+free text
613  if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
614  $pdf->AddPage('', '', true);
615  if (!empty($tplidx)) {
616  $pdf->useTemplate($tplidx);
617  }
618  //if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
619  $pdf->setPage($pageposafter + 1);
620  }
621  } else {
622  // We found a page break
623  // Allows data in the first page if description is long enough to break in multiples pages
624  if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
625  $showpricebeforepagebreak = 1;
626  } else {
627  $showpricebeforepagebreak = 0;
628  }
629  }
630  } else // No pagebreak
631  {
632  $pdf->commitTransaction();
633  }
634  $posYAfterDescription = $pdf->GetY();
635  }
636 
637  $nexY = max($pdf->GetY(), $posYAfterImage);
638  $pageposafter = $pdf->getPage();
639 
640  $pdf->setPage($pageposbefore);
641  $pdf->setTopMargin($this->marge_haute);
642  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
643 
644  // We suppose that a too long description or photo were moved completely on next page
645  if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
646  $pdf->setPage($pageposafter);
647  $curY = $tab_top_newpage;
648  }
649 
650  // We suppose that a too long description is moved completely on next page
651  if ($pageposafter > $pageposbefore) {
652  $pdf->setPage($pageposafter);
653  $curY = $tab_top_newpage;
654  }
655 
656  $pdf->SetFont('', '', $default_font_size - 1); // We reposition the default font
657 
658  // weight
659 
660  $weighttxt = '';
661  if ($object->lines[$i]->fk_product_type == 0 && $object->lines[$i]->weight) {
662  $weighttxt = round($object->lines[$i]->weight * $object->lines[$i]->qty_shipped, 5).' '.measuringUnitString(0, "weight", $object->lines[$i]->weight_units, 1);
663  }
664  $voltxt = '';
665  if ($object->lines[$i]->fk_product_type == 0 && $object->lines[$i]->volume) {
666  $voltxt = round($object->lines[$i]->volume * $object->lines[$i]->qty_shipped, 5).' '.measuringUnitString(0, "volume", $object->lines[$i]->volume_units ? $object->lines[$i]->volume_units : 0, 1);
667  }
668 
669 
670  if ($this->getColumnStatus('weight')) {
671  $this->printStdColumnContent($pdf, $curY, 'weight', $weighttxt.(($weighttxt && $voltxt) ? '<br>' : '').$voltxt);
672  $nexY = max($pdf->GetY(), $nexY);
673  }
674 
675  if ($this->getColumnStatus('qty_asked')) {
676  $this->printStdColumnContent($pdf, $curY, 'qty_asked', $object->lines[$i]->qty_asked);
677  $nexY = max($pdf->GetY(), $nexY);
678  }
679 
680  if ($this->getColumnStatus('unit_order')) {
681  $this->printStdColumnContent($pdf, $curY, 'unit_order', measuringUnitString($object->lines[$i]->fk_unit));
682  $nexY = max($pdf->GetY(), $nexY);
683  }
684 
685  if ($this->getColumnStatus('qty_shipped')) {
686  $this->printStdColumnContent($pdf, $curY, 'qty_shipped', $object->lines[$i]->qty_shipped);
687  $nexY = max($pdf->GetY(), $nexY);
688  }
689 
690  if ($this->getColumnStatus('subprice')) {
691  $this->printStdColumnContent($pdf, $curY, 'subprice', price($object->lines[$i]->subprice, 0, $outputlangs));
692  $nexY = max($pdf->GetY(), $nexY);
693  }
694 
695  // Extrafields
696  if (!empty($object->lines[$i]->array_options)) {
697  foreach ($object->lines[$i]->array_options as $extrafieldColKey => $extrafieldValue) {
698  if ($this->getColumnStatus($extrafieldColKey)) {
699  $extrafieldValue = $this->getExtrafieldContent($object->lines[$i], $extrafieldColKey, $outputlangs);
700  $this->printStdColumnContent($pdf, $curY, $extrafieldColKey, $extrafieldValue);
701  $nexY = max($pdf->GetY(), $nexY);
702  }
703  }
704  }
705 
706  // Add line
707  if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) {
708  $pdf->setPage($pageposafter);
709  $pdf->SetLineStyle(array('dash'=>'1,1', 'color'=>array(80, 80, 80)));
710  //$pdf->SetDrawColor(190,190,200);
711  $pdf->line($this->marge_gauche, $nexY, $this->page_largeur - $this->marge_droite, $nexY);
712  $pdf->SetLineStyle(array('dash'=>0));
713  }
714 
715  // Detect if some page were added automatically and output _tableau for past pages
716  while ($pagenb < $pageposafter) {
717  $pdf->setPage($pagenb);
718  if ($pagenb == $pageposbeforeprintlines) {
719  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1);
720  } else {
721  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
722  }
723  $this->_pagefoot($pdf, $object, $outputlangs, 1);
724  $pagenb++;
725  $pdf->setPage($pagenb);
726  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
727  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
728  $this->_pagehead($pdf, $object, 0, $outputlangs);
729  }
730  if (!empty($tplidx)) {
731  $pdf->useTemplate($tplidx);
732  }
733  }
734  if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) {
735  if ($pagenb == 1) {
736  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1);
737  } else {
738  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
739  }
740  $this->_pagefoot($pdf, $object, $outputlangs, 1);
741  // New page
742  $pdf->AddPage();
743  if (!empty($tplidx)) {
744  $pdf->useTemplate($tplidx);
745  }
746  $pagenb++;
747  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
748  $this->_pagehead($pdf, $object, 0, $outputlangs);
749  }
750  }
751  }
752 
753  // Show square
754  if ($pagenb == 1) {
755  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0);
756  $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
757  } else {
758  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0);
759  $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
760  }
761 
762  // Display total area
763  $posy = $this->_tableau_tot($pdf, $object, 0, $bottomlasttab, $outputlangs);
764 
765  // Pagefoot
766  $this->_pagefoot($pdf, $object, $outputlangs);
767  if (method_exists($pdf, 'AliasNbPages')) {
768  $pdf->AliasNbPages();
769  }
770 
771  $pdf->Close();
772 
773  $pdf->Output($file, 'F');
774 
775  // Add pdfgeneration hook
776  $hookmanager->initHooks(array('pdfgeneration'));
777  $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
778  global $action;
779  $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
780  if ($reshook < 0) {
781  $this->error = $hookmanager->error;
782  $this->errors = $hookmanager->errors;
783  }
784 
785  if (!empty($conf->global->MAIN_UMASK)) {
786  @chmod($file, octdec($conf->global->MAIN_UMASK));
787  }
788 
789  $this->result = array('fullpath'=>$file);
790 
791  return 1; // No error
792  } else {
793  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
794  return 0;
795  }
796  } else {
797  $this->error = $langs->transnoentities("ErrorConstantNotDefined", "EXP_OUTPUTDIR");
798  return 0;
799  }
800  }
801 
802  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
803  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
814  protected function _tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
815  {
816  // phpcs:enable
817  global $conf, $mysoc;
818 
819  $sign = 1;
820 
821  $default_font_size = pdf_getPDFFontSize($outputlangs);
822 
823  $tab2_top = $posy;
824  $tab2_hl = 4;
825  $pdf->SetFont('', 'B', $default_font_size - 1);
826 
827  // Total table
828  $col1x = $this->posxweightvol - 50;
829  $col2x = $this->posxweightvol;
830  /*if ($this->page_largeur < 210) // To work with US executive format
831  {
832  $col2x-=20;
833  }*/
834  if (empty($conf->global->SHIPPING_PDF_HIDE_ORDERED)) {
835  $largcol2 = ($this->posxqtyordered - $this->posxweightvol);
836  } else {
837  $largcol2 = ($this->posxqtytoship - $this->posxweightvol);
838  }
839 
840  $useborder = 0;
841  $index = 0;
842 
843  $totalWeighttoshow = '';
844  $totalVolumetoshow = '';
845 
846  // Load dim data
847  $tmparray = $object->getTotalWeightVolume();
848  $totalWeight = $tmparray['weight'];
849  $totalVolume = $tmparray['volume'];
850  $totalOrdered = $tmparray['ordered'];
851  $totalToShip = $tmparray['toship'];
852  // Set trueVolume and volume_units not currently stored into database
853  if ($object->trueWidth && $object->trueHeight && $object->trueDepth) {
854  $object->trueVolume = $object->trueWidth * $object->trueHeight * $object->trueDepth;
855  $object->volume_units = $object->size_units * 3;
856  }
857 
858  if ($totalWeight != '') {
859  $totalWeighttoshow = showDimensionInBestUnit($totalWeight, 0, "weight", $outputlangs);
860  }
861  if ($totalVolume != '') {
862  $totalVolumetoshow = showDimensionInBestUnit($totalVolume, 0, "volume", $outputlangs);
863  }
864  if ($object->trueWeight) {
865  $totalWeighttoshow = showDimensionInBestUnit($object->trueWeight, $object->weight_units, "weight", $outputlangs);
866  }
867  if ($object->trueVolume) {
868  if ($object->volume_units < 50) {
869  $totalVolumetoshow = showDimensionInBestUnit($object->trueVolume, $object->volume_units, "volume", $outputlangs);
870  } else {
871  $totalVolumetoshow = price($object->trueVolume, 0, $outputlangs, 0, 0).' '.measuringUnitString(0, "volume", $object->volume_units);
872  }
873  }
874 
875  if ($this->getColumnStatus('desc')) {
876  $this->printStdColumnContent($pdf, $tab2_top, 'desc', $outputlangs->transnoentities("Total"));
877  }
878 
879 
880  if ($this->getColumnStatus('weight')) {
881  if ($totalWeighttoshow) {
882  $this->printStdColumnContent($pdf, $tab2_top, 'weight', $totalWeighttoshow);
883  $index++;
884  }
885 
886  if ($totalVolumetoshow) {
887  $y = $tab2_top + ($tab2_hl * $index);
888  $this->printStdColumnContent($pdf, $y, 'weight', $totalVolumetoshow);
889  }
890  }
891 
892  if ($this->getColumnStatus('qty_asked') && $totalOrdered) {
893  $this->printStdColumnContent($pdf, $tab2_top, 'qty_asked', $totalOrdered);
894  }
895 
896  if ($this->getColumnStatus('qty_shipped') && $totalToShip) {
897  $this->printStdColumnContent($pdf, $tab2_top, 'qty_shipped', $totalToShip);
898  }
899 
900  if ($this->getColumnStatus('subprice')) {
901  $this->printStdColumnContent($pdf, $tab2_top, 'subprice', price($object->total_ht, 0, $outputlangs));
902  }
903 
904  $pdf->SetTextColor(0, 0, 0);
905 
906  return ($tab2_top + ($tab2_hl * $index));
907  }
908 
909  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
922  protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0)
923  {
924  global $conf;
925 
926  // Force to disable hidetop and hidebottom
927  $hidebottom = 0;
928  if ($hidetop) {
929  $hidetop = -1;
930  }
931 
932  $currency = !empty($currency) ? $currency : $conf->currency;
933  $default_font_size = pdf_getPDFFontSize($outputlangs);
934 
935  // Amount in (at tab_top - 1)
936  $pdf->SetTextColor(0, 0, 0);
937  $pdf->SetFont('', '', $default_font_size - 2);
938 
939  if (empty($hidetop)) {
940  //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
941  if (!empty($conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)) {
942  $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, $this->tabTitleHeight, 'F', null, explode(',', $conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR));
943  }
944  }
945 
946  $pdf->SetDrawColor(128, 128, 128);
947  $pdf->SetFont('', '', $default_font_size - 1);
948 
949  // Output Rect
950  $this->printRect($pdf, $this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $tab_height, $hidetop, $hidebottom); // Rect takes a length in 3rd parameter and 4th parameter
951 
952 
953  $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
954 
955  if (empty($hidetop)) {
956  $pdf->line($this->marge_gauche, $tab_top + $this->tabTitleHeight, $this->page_largeur - $this->marge_droite, $tab_top + $this->tabTitleHeight); // line takes a position y in 2nd parameter and 4th parameter
957  }
958  }
959 
960  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
970  protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
971  {
972  global $conf, $langs, $mysoc;
973 
974  $langs->load("orders");
975 
976  $default_font_size = pdf_getPDFFontSize($outputlangs);
977 
978  pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
979 
980  //Prepare next
981  $pdf->SetTextColor(0, 0, 60);
982  $pdf->SetFont('', 'B', $default_font_size + 3);
983 
984  $w = 110;
985 
986  $posy = $this->marge_haute;
987  $posx = $this->page_largeur - $this->marge_droite - $w;
988 
989  $pdf->SetXY($this->marge_gauche, $posy);
990 
991  // Logo
992  if ($this->emetteur->logo) {
993  $logodir = $conf->mycompany->dir_output;
994  if (!empty($conf->mycompany->multidir_output[$object->entity])) {
995  $logodir = $conf->mycompany->multidir_output[$object->entity];
996  }
997  if (empty($conf->global->MAIN_PDF_USE_LARGE_LOGO)) {
998  $logo = $logodir.'/logos/thumbs/'.$this->emetteur->logo_small;
999  } else {
1000  $logo = $logodir.'/logos/'.$this->emetteur->logo;
1001  }
1002  if (is_readable($logo)) {
1003  $height = pdf_getHeightForLogo($logo);
1004  $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
1005  } else {
1006  $pdf->SetTextColor(200, 0, 0);
1007  $pdf->SetFont('', 'B', $default_font_size - 2);
1008  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
1009  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
1010  }
1011  } else {
1012  $text = $this->emetteur->name;
1013  $pdf->MultiCell($w, 4, $outputlangs->convToOutputCharset($text), 0, 'L');
1014  }
1015 
1016  // Show barcode
1017  if (isModEnabled('barcode')) {
1018  $posx = 105;
1019  } else {
1020  $posx = $this->marge_gauche + 3;
1021  }
1022  //$pdf->Rect($this->marge_gauche, $this->marge_haute, $this->page_largeur-$this->marge_gauche-$this->marge_droite, 30);
1023  if (isModEnabled('barcode')) {
1024  // TODO Build code bar with function writeBarCode of barcode module for sending ref $object->ref
1025  //$pdf->SetXY($this->marge_gauche+3, $this->marge_haute+3);
1026  //$pdf->Image($logo,10, 5, 0, 24);
1027  }
1028 
1029  $pdf->SetDrawColor(128, 128, 128);
1030  if (isModEnabled('barcode')) {
1031  // TODO Build code bar with function writeBarCode of barcode module for sending ref $object->ref
1032  //$pdf->SetXY($this->marge_gauche+3, $this->marge_haute+3);
1033  //$pdf->Image($logo,10, 5, 0, 24);
1034  }
1035 
1036 
1037  $posx = $this->page_largeur - $w - $this->marge_droite;
1038  $posy = $this->marge_haute;
1039 
1040  $pdf->SetFont('', 'B', $default_font_size + 2);
1041  $pdf->SetXY($posx, $posy);
1042  $pdf->SetTextColor(0, 0, 60);
1043  $title = $outputlangs->transnoentities("SendingSheet");
1044  $pdf->MultiCell($w, 4, $title, '', 'R');
1045 
1046  $pdf->SetFont('', '', $default_font_size + 1);
1047 
1048  $posy += 5;
1049 
1050  $pdf->SetXY($posx, $posy);
1051  $pdf->SetTextColor(0, 0, 60);
1052  $pdf->MultiCell($w, 4, $outputlangs->transnoentities("RefSending")." : ".$object->ref, '', 'R');
1053 
1054  // Date planned delivery
1055  if (!empty($object->date_delivery)) {
1056  $posy += 4;
1057  $pdf->SetXY($posx, $posy);
1058  $pdf->SetTextColor(0, 0, 60);
1059  $pdf->MultiCell($w, 4, $outputlangs->transnoentities("DateDeliveryPlanned")." : ".dol_print_date($object->date_delivery, "day", false, $outputlangs, true), '', 'R');
1060  }
1061 
1062  if (empty($conf->global->MAIN_PDF_HIDE_CUSTOMER_CODE) && !empty($object->thirdparty->code_client)) {
1063  $posy += 4;
1064  $pdf->SetXY($posx, $posy);
1065  $pdf->SetTextColor(0, 0, 60);
1066  $pdf->MultiCell($w, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R');
1067  }
1068 
1069 
1070  $pdf->SetFont('', '', $default_font_size + 3);
1071  $Yoff = 25;
1072 
1073  // Add list of linked orders
1074  $origin = $object->origin;
1075  $origin_id = $object->origin_id;
1076 
1077  // TODO move to external function
1078  if (!empty($conf->$origin->enabled)) { // commonly $origin='commande'
1079  $outputlangs->load('orders');
1080 
1081  $classname = ucfirst($origin);
1082  $linkedobject = new $classname($this->db);
1083  $result = $linkedobject->fetch($origin_id);
1084  if ($result >= 0) {
1085  //$linkedobject->fetchObjectLinked() Get all linked object to the $linkedobject (commonly order) into $linkedobject->linkedObjects
1086 
1087  $pdf->SetFont('', '', $default_font_size - 2);
1088  $text = $linkedobject->ref;
1089  if ($linkedobject->ref_client) {
1090  $text .= ' ('.$linkedobject->ref_client.')';
1091  }
1092  $Yoff = $Yoff + 8;
1093  $pdf->SetXY($this->page_largeur - $this->marge_droite - $w, $Yoff);
1094  $pdf->MultiCell($w, 2, $outputlangs->transnoentities("RefOrder")." : ".$outputlangs->transnoentities($text), 0, 'R');
1095  $Yoff = $Yoff + 3;
1096  $pdf->SetXY($this->page_largeur - $this->marge_droite - $w, $Yoff);
1097  $pdf->MultiCell($w, 2, $outputlangs->transnoentities("OrderDate")." : ".dol_print_date($linkedobject->date, "day", false, $outputlangs, true), 0, 'R');
1098  }
1099  }
1100 
1101  $top_shift = 0;
1102  // Show list of linked objects
1103  /*$current_y = $pdf->getY();
1104  $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, $w, 3, 'R', $default_font_size);
1105  if ($current_y < $pdf->getY()) {
1106  $top_shift = $pdf->getY() - $current_y;
1107  }*/
1108 
1109  if ($showaddress) {
1110  // Sender properties
1111  $carac_emetteur = '';
1112  // Add internal contact of origin element if defined
1113  $arrayidcontact = array();
1114  if (!empty($origin) && is_object($object->$origin)) {
1115  $arrayidcontact = $object->$origin->getIdContact('internal', 'SALESREPFOLL');
1116  }
1117  if (is_array($arrayidcontact) && count($arrayidcontact) > 0) {
1118  $object->fetch_user(reset($arrayidcontact));
1119  $carac_emetteur .= ($carac_emetteur ? "\n" : '').$outputlangs->transnoentities("Name").": ".$outputlangs->convToOutputCharset($object->user->getFullName($outputlangs))."\n";
1120  }
1121 
1122  $carac_emetteur .= pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
1123 
1124  // Show sender
1125  $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42;
1126  $posx = $this->marge_gauche;
1127  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
1128  $posx = $this->page_largeur - $this->marge_droite - 80;
1129  }
1130 
1131  $hautcadre = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 38 : 40;
1132  $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 82;
1133 
1134  // Show sender frame
1135  if (empty($conf->global->MAIN_PDF_NO_SENDER_FRAME)) {
1136  $pdf->SetTextColor(0, 0, 0);
1137  $pdf->SetFont('', '', $default_font_size - 2);
1138  $pdf->SetXY($posx, $posy - 5);
1139  $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("Sender"), 0, 'L');
1140  $pdf->SetXY($posx, $posy);
1141  $pdf->SetFillColor(230, 230, 230);
1142  $pdf->MultiCell($widthrecbox, $hautcadre, "", 0, 'R', 1);
1143  $pdf->SetTextColor(0, 0, 60);
1144  $pdf->SetFillColor(255, 255, 255);
1145  }
1146 
1147  // Show sender name
1148  if (empty($conf->global->MAIN_PDF_HIDE_SENDER_NAME)) {
1149  $pdf->SetXY($posx + 2, $posy + 3);
1150  $pdf->SetFont('', 'B', $default_font_size);
1151  $pdf->MultiCell($widthrecbox - 2, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L');
1152  $posy = $pdf->getY();
1153  }
1154 
1155  // Show sender information
1156  $pdf->SetXY($posx + 2, $posy);
1157  $pdf->SetFont('', '', $default_font_size - 1);
1158  $pdf->MultiCell($widthrecbox - 2, 4, $carac_emetteur, 0, 'L');
1159 
1160 
1161  // If SHIPPING contact defined, we use it
1162  $usecontact = false;
1163  $arrayidcontact = $object->$origin->getIdContact('external', 'SHIPPING');
1164  if (count($arrayidcontact) > 0) {
1165  $usecontact = true;
1166  $result = $object->fetch_contact($arrayidcontact[0]);
1167  }
1168 
1169  // Recipient name
1170  if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)))) {
1171  $thirdparty = $object->contact;
1172  } else {
1173  $thirdparty = $object->thirdparty;
1174  }
1175 
1176  $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
1177 
1178  $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, (!empty($object->contact) ? $object->contact : null), $usecontact, 'targetwithdetails', $object);
1179 
1180  // Show recipient
1181  $widthrecbox = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 92 : 100;
1182  if ($this->page_largeur < 210) {
1183  $widthrecbox = 84; // To work with US executive format
1184  }
1185  $posy = !empty($conf->global->MAIN_PDF_USE_ISO_LOCATION) ? 40 : 42;
1186  $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
1187  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
1188  $posx = $this->marge_gauche;
1189  }
1190 
1191  // Show recipient frame
1192  if (empty($conf->global->MAIN_PDF_NO_RECIPENT_FRAME)) {
1193  $pdf->SetTextColor(0, 0, 0);
1194  $pdf->SetFont('', '', $default_font_size - 2);
1195  $pdf->SetXY($posx + 2, $posy - 5);
1196  $pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("Recipient"), 0, 'L');
1197  $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
1198  }
1199 
1200  // Show recipient name
1201  $pdf->SetXY($posx + 2, $posy + 3);
1202  $pdf->SetFont('', 'B', $default_font_size);
1203  $pdf->MultiCell($widthrecbox, 2, $carac_client_name, 0, 'L');
1204 
1205  $posy = $pdf->getY();
1206 
1207  // Show recipient information
1208  $pdf->SetFont('', '', $default_font_size - 1);
1209  $pdf->SetXY($posx + 2, $posy);
1210  $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L');
1211  }
1212 
1213  $pdf->SetTextColor(0, 0, 0);
1214  return $top_shift;
1215  }
1216 
1217  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
1227  protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
1228  {
1229  $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
1230  return pdf_pagefoot($pdf, $outputlangs, 'SHIPPING_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext, $this->page_largeur, $this->watermark);
1231  }
1232 
1243  public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
1244  {
1245  global $conf, $hookmanager;
1246 
1247  // Default field style for content
1248  $this->defaultContentsFieldsStyle = array(
1249  'align' => 'R', // R,C,L
1250  'padding' => array(1, 0.5, 1, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1251  );
1252 
1253  // Default field style for content
1254  $this->defaultTitlesFieldsStyle = array(
1255  'align' => 'C', // R,C,L
1256  'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1257  );
1258 
1259  /*
1260  * For exemple
1261  $this->cols['theColKey'] = array(
1262  'rank' => $rank, // int : use for ordering columns
1263  'width' => 20, // the column width in mm
1264  'title' => array(
1265  'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1266  'label' => ' ', // the final label : used fore final generated text
1267  'align' => 'L', // text alignement : R,C,L
1268  'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1269  ),
1270  'content' => array(
1271  'align' => 'L', // text alignement : R,C,L
1272  'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1273  ),
1274  );
1275  */
1276 
1277  $rank = 0; // do not use negative rank
1278  $this->cols['desc'] = array(
1279  'rank' => $rank,
1280  'width' => false, // only for desc
1281  'status' => true,
1282  'title' => array(
1283  'textkey' => 'Designation', // use lang key is usefull in somme case with module
1284  'align' => 'L',
1285  // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
1286  // 'label' => ' ', // the final label
1287  'padding' => array(0.5, 1, 0.5, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1288  ),
1289  'content' => array(
1290  'padding' => array(1, 0.5, 1, 1.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1291  ),
1292  );
1293 
1294  $rank = $rank + 10;
1295  $this->cols['photo'] = array(
1296  'rank' => $rank,
1297  'width' => (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH), // in mm
1298  'status' => false,
1299  'title' => array(
1300  'textkey' => 'Photo',
1301  'label' => ' '
1302  ),
1303  'content' => array(
1304  'padding' => array(0, 0, 0, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1305  ),
1306  'border-left' => false, // remove left line separator
1307  );
1308 
1309  if (!empty($conf->global->MAIN_GENERATE_SHIPMENT_WITH_PICTURE) && !empty($this->atleastonephoto)) {
1310  $this->cols['photo']['status'] = true;
1311  }
1312 
1313  $rank = $rank + 10;
1314  $this->cols['weight'] = array(
1315  'rank' => $rank,
1316  'width' => 30, // in mm
1317  'status' => true,
1318  'title' => array(
1319  'textkey' => 'WeightVolShort'
1320  ),
1321  'border-left' => true, // add left line separator
1322  );
1323 
1324 
1325  $rank = $rank + 10;
1326  $this->cols['subprice'] = array(
1327  'rank' => $rank,
1328  'width' => 19, // in mm
1329  'status' => !empty($conf->global->MAIN_PDF_SHIPPING_DISPLAY_AMOUNT_HT) ? 1 : 0,
1330  'title' => array(
1331  'textkey' => 'PriceUHT'
1332  ),
1333  'border-left' => true, // add left line separator
1334  );
1335 
1336  $rank = $rank + 10;
1337  $this->cols['totalexcltax'] = array(
1338  'rank' => $rank,
1339  'width' => 26, // in mm
1340  'status' => !empty($conf->global->MAIN_PDF_SHIPPING_DISPLAY_AMOUNT_HT) ? 1 : 0,
1341  'title' => array(
1342  'textkey' => 'TotalHT'
1343  ),
1344  'border-left' => true, // add left line separator
1345  );
1346 
1347  $rank = $rank + 10;
1348  $this->cols['qty_asked'] = array(
1349  'rank' => $rank,
1350  'width' => 30, // in mm
1351  'status' => empty($conf->global->SHIPPING_PDF_HIDE_ORDERED) ? 1 : 0,
1352  'title' => array(
1353  'textkey' => 'QtyOrdered'
1354  ),
1355  'border-left' => true, // add left line separator
1356  'content' => array(
1357  'align' => 'C',
1358  ),
1359  );
1360 
1361  $rank = $rank + 10;
1362  $this->cols['unit_order'] = array(
1363  'rank' => $rank,
1364  'width' => 15, // in mm
1365  'status' => empty($conf->global->PRODUCT_USE_UNITS) ? 0 : 1,
1366  'title' => array(
1367  'textkey' => 'Unit'
1368  ),
1369  'border-left' => true, // add left line separator
1370  'content' => array(
1371  'align' => 'C',
1372  ),
1373  );
1374 
1375  $rank = $rank + 10;
1376  $this->cols['qty_shipped'] = array(
1377  'rank' => $rank,
1378  'width' => 30, // in mm
1379  'status' => true,
1380  'title' => array(
1381  'textkey' => 'QtyToShip'
1382  ),
1383  'border-left' => true, // add left line separator
1384  'content' => array(
1385  'align' => 'C',
1386  ),
1387  );
1388 
1389  // Add extrafields cols
1390  if (!empty($object->lines)) {
1391  $line = reset($object->lines);
1392  $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
1393  }
1394 
1395  $parameters = array(
1396  'object' => $object,
1397  'outputlangs' => $outputlangs,
1398  'hidedetails' => $hidedetails,
1399  'hidedesc' => $hidedesc,
1400  'hideref' => $hideref
1401  );
1402 
1403  $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
1404  if ($reshook < 0) {
1405  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1406  } elseif (empty($reshook)) {
1407  $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
1408  } else {
1409  $this->cols = $hookmanager->resArray;
1410  }
1411  }
1412 }
prepareArrayColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Prepare Array Column Field.
getColumnStatus($colKey)
get column status from column key
printStdColumnContent($pdf, &$curY, $colKey, $columnText='')
print standard column content
pdfTabTitles(&$pdf, $tab_top, $tab_height, $outputlangs, $hidetop=0)
Print standard column content.
printColDescContent($pdf, &$curY, $colKey, $object, $i, $outputlangs, $hideref=0, $hidedesc=0, $issupplierline=0)
print description column content
getColumnContentXStart($colKey)
get column content X (abscissa) left position from column key
printRect($pdf, $x, $y, $l, $h, $hidetop=0, $hidebottom=0)
Rect pdf.
getExtrafieldContent($object, $extrafieldKey, $outputlangs=null)
get extrafield content for pdf writeHtmlCell compatibility usage for PDF line columns and object note...
defineColumnExtrafield($object, $outputlangs, $hidedetails=0)
Define Array Column Field for extrafields.
Class to manage Dolibarr database access.
Class to manage hooks.
Parent class of sending receipts models.
Class to manage products or services.
Class to manage translations.
Class to build sending documents with model espadon.
__construct(DoliDB $db)
Constructor.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
_pagehead(&$pdf, $object, $showaddress, $outputlangs)
Show top header of page.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0)
Show table for lines.
_tableau_tot(&$pdf, $object, $deja_regle, $posy, $outputlangs)
Show total to pay.
defineColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Define Array Column Field.
print *****$script_file(".$version.") pid cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
if(!function_exists('dolEscapeXML')) convertBackOfficeMediasLinksToPublicLinks($notetoshow)
Convert links to local wrapper to medias files into a string into a public external URL readable on i...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
if(!function_exists('utf8_encode')) if(!function_exists('utf8_decode')) getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
isModEnabled($module)
Is Dolibarr module enabled.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
pdf_getSizeForImage($realpath)
Return dimensions to use for images onto PDF checking that width and height are not higher than maxim...
Definition: pdf.lib.php:2514
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition: pdf.lib.php:288
pdf_getFormat(Translate $outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition: pdf.lib.php:84
pdf_getHeightForLogo($logo, $url=false)
Return height to use for Logo onto PDF.
Definition: pdf.lib.php:313
pdf_pagefoot(&$pdf, $outputlangs, $paramfreetext, $fromcompany, $marge_basse, $marge_gauche, $page_hauteur, $object, $showdetails=0, $hidefreetext=0, $page_largeur=0, $watermark='')
Show footer of page for PDF generation.
Definition: pdf.lib.php:1001
pdf_getSubstitutionArray($outputlangs, $exclude=null, $object=null, $onlykey=0)
Return array of possible substitutions for PDF content (without external module substitutions).
Definition: pdf.lib.php:749
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition: pdf.lib.php:723
pdf_getPDFFont($outputlangs)
Return font name to use for PDF generation.
Definition: pdf.lib.php:265
pdf_build_address($outputlangs, $sourcecompany, $targetcompany='', $targetcontact='', $usecontact=0, $mode='source', $object=null)
Return a string with full address formated for output on documents.
Definition: pdf.lib.php:434
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition: pdf.lib.php:126
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition: pdf.lib.php:386
measuringUnitString($unit, $measuring_style='', $scale='', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:119
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:122
$conf db
API class for accounts.
Definition: inc.php:41