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