dolibarr  19.0.0-dev
pdf_storm.modules.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2005-2014 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
5  * Copyright (C) 2008 Chiptronik
6  * Copyright (C) 2011-2021 Philippe Grand <philippe.grand@atoo-net.com>
7  * Copyright (C) 2015 Marcos GarcĂ­a <marcosgdf@gmail.com>
8  * Copyright (C) 2020 John BOTELLA
9 
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <https://www.gnu.org/licenses/>.
22  * or see https://www.gnu.org/
23  */
24 
31 require_once DOL_DOCUMENT_ROOT.'/core/modules/delivery/modules_delivery.php';
32 require_once DOL_DOCUMENT_ROOT.'/delivery/class/delivery.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
35 
36 
41 {
45  public $db;
46 
50  public $name;
51 
55  public $description;
56 
60  public $update_main_doc_field;
61 
65  public $type;
66 
71  public $version = 'dolibarr';
72 
76  public $page_largeur;
77 
81  public $page_hauteur;
82 
86  public $format;
87 
91  public $marge_gauche;
92 
96  public $marge_droite;
97 
101  public $marge_haute;
102 
106  public $marge_basse;
107 
112  public $emetteur;
113 
119  public function __construct($db)
120  {
121  global $conf, $langs, $mysoc;
122 
123  // Translations
124  $langs->loadLangs(array("main", "bills", "sendings", "companies"));
125 
126  $this->db = $db;
127  $this->name = "Storm";
128  $this->description = $langs->trans("DocumentModelStorm");
129  $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
130 
131  // Page size for A4 format
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 FAC_PDF_LOGO
143  $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION
144 
145  // Get source company
146  $this->emetteur = $mysoc;
147  if (empty($this->emetteur->country_code)) {
148  $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
149  }
150 
151  $this->tva = array();
152  $this->tva_array = array();
153  $this->localtax1 = array();
154  $this->localtax2 = array();
155  $this->atleastoneratenotnull = 0;
156  $this->atleastonediscount = 0;
157  }
158 
159 
160  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
172  public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
173  {
174  // phpcs:enable
175  global $user, $langs, $conf, $mysoc, $hookmanager;
176 
177  if (!is_object($outputlangs)) {
178  $outputlangs = $langs;
179  }
180  // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
181  if (!empty($conf->global->MAIN_USE_FPDF)) {
182  $outputlangs->charset_output = 'ISO-8859-1';
183  }
184 
185  // Load translation files required by the page
186  $outputlangs->loadLangs(array("main", "dict", "companies", "bills", "products", "sendings", "deliveries"));
187 
188  if ($conf->expedition->dir_output) {
189  $object->fetch_thirdparty();
190 
191  // Definition of $dir and $file
192  if ($object->specimen) {
193  $dir = $conf->expedition->dir_output."/receipt";
194  $file = $dir."/SPECIMEN.pdf";
195  } else {
196  $objectref = dol_sanitizeFileName($object->ref);
197  $dir = $conf->expedition->dir_output."/receipt/".$objectref;
198  $file = $dir."/".$objectref.".pdf";
199  }
200 
201  if (!file_exists($dir)) {
202  if (dol_mkdir($dir) < 0) {
203  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
204  return 0;
205  }
206  }
207 
208  if (file_exists($dir)) {
209  // Add pdfgeneration hook
210  if (!is_object($hookmanager)) {
211  include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
212  $hookmanager = new HookManager($this->db);
213  }
214  $hookmanager->initHooks(array('pdfgeneration'));
215  $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
216  global $action;
217  $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
218 
219  $nblines = count($object->lines);
220 
221 
222  // Loop on each lines to detect if there is at least one image to show
223  $realpatharray = array();
224  $this->atleastonephoto = false;
225  if (!empty($conf->global->MAIN_GENERATE_DELIVERY_WITH_PICTURE)) {
226  $objphoto = new Product($this->db);
227 
228  for ($i = 0; $i < $nblines; $i++) {
229  if (empty($object->lines[$i]->fk_product)) {
230  continue;
231  }
232 
233  $objphoto->fetch($object->lines[$i]->fk_product);
234 
235  if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
236  $pdir[0] = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$objphoto->id."/photos/";
237  $pdir[1] = get_exdir(0, 0, 0, 0, $objphoto, 'product').dol_sanitizeFileName($objphoto->ref).'/';
238  } else {
239  $pdir[0] = get_exdir(0, 0, 0, 0, $objphoto, 'product'); // default
240  $pdir[1] = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$objphoto->id."/photos/"; // alternative
241  }
242 
243  $arephoto = false;
244  foreach ($pdir as $midir) {
245  if (!$arephoto) {
246  $dir = $conf->product->dir_output.'/'.$midir;
247 
248  foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) {
249  if (!getDolGlobalInt('CAT_HIGH_QUALITY_IMAGES')) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo
250  if ($obj['photo_vignette']) {
251  $filename = $obj['photo_vignette'];
252  } else {
253  $filename = $obj['photo'];
254  }
255  } else {
256  $filename = $obj['photo'];
257  }
258 
259  $realpath = $dir.$filename;
260  $arephoto = true;
261  $this->atleastonephoto = true;
262  }
263  }
264  }
265 
266  if ($realpath && $arephoto) {
267  $realpatharray[$i] = $realpath;
268  }
269  }
270  }
271 
272  if (count($realpatharray) == 0) {
273  $this->posxpicture = $this->posxweightvol;
274  }
275 
276 
277 
278  // Create pdf instance
279  $pdf = pdf_getInstance($this->format);
280  $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
281  $heightforinfotot = 30; // Height reserved to output the info and total part
282  $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
283  $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
284  if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS)) {
285  $heightforfooter += 6;
286  }
287  $pdf->SetAutoPageBreak(1, 0);
288 
289  if (class_exists('TCPDF')) {
290  $pdf->setPrintHeader(false);
291  $pdf->setPrintFooter(false);
292  }
293  $pdf->SetFont(pdf_getPDFFont($outputlangs));
294  // Set path to the background PDF File
295  if (!empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
296  $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND);
297  $tplidx = $pdf->importPage(1);
298  }
299 
300  // We get the shipment that is the origin of delivery receipt
301  $expedition = new Expedition($this->db);
302  $result = $expedition->fetch($object->origin_id);
303  // Now we get the order that is origin of shipment
304  $commande = new Commande($this->db);
305  if ($expedition->origin == 'commande') {
306  $commande->fetch($expedition->origin_id);
307  }
308  $object->commande = $commande; // We set order of shipment onto delivery.
309  $object->commande->loadExpeditions();
310 
311 
312  $pdf->Open();
313  $pagenb = 0;
314  $pdf->SetDrawColor(128, 128, 128);
315 
316  $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
317  $pdf->SetSubject($outputlangs->transnoentities("DeliveryOrder"));
318  $pdf->SetCreator("Dolibarr ".DOL_VERSION);
319  $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
320  $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("DeliveryOrder"));
321  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
322  $pdf->SetCompression(false);
323  }
324 
325  $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
326 
327 
328  // New page
329  $pdf->AddPage();
330  if (!empty($tplidx)) {
331  $pdf->useTemplate($tplidx);
332  }
333  $pagenb++;
334  $this->_pagehead($pdf, $object, 1, $outputlangs);
335  $pdf->SetFont('', '', $default_font_size - 1);
336  $pdf->MultiCell(0, 3, ''); // Set interline to 3
337  $pdf->SetTextColor(0, 0, 0);
338 
339  $tab_top = 90;
340  $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 : 10);
341 
342  $tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext;
343 
344  $this->posxdesc = $this->marge_gauche + 1;
345 
346  // Incoterm
347  $height_incoterms = 0;
348  if (isModEnabled('incoterm')) {
349  $desc_incoterms = $object->getIncotermsForPDF();
350  if ($desc_incoterms) {
351  $tab_top -= 2;
352 
353  $pdf->SetFont('', '', $default_font_size - 1);
354  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
355  $nexY = $pdf->GetY();
356  $height_incoterms = $nexY - $tab_top;
357 
358  // Rect takes a length in 3rd parameter
359  $pdf->SetDrawColor(192, 192, 192);
360  $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_incoterms + 1);
361 
362  $tab_top = $nexY + 6;
363  $height_incoterms += 4;
364  }
365  }
366 
367  // display note
368  $notetoshow = empty($object->note_public) ? '' : $object->note_public;
369 
370  // Extrafields in note
371  $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
372  if (!empty($extranote)) {
373  $notetoshow = dol_concatdesc($notetoshow, $extranote);
374  }
375 
376  if (!empty($notetoshow)) {
377  $tab_top = 88 + $height_incoterms;
378 
379  $pdf->SetFont('', '', $default_font_size - 1);
380  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
381  $nexY = $pdf->GetY();
382  $height_note = $nexY - $tab_top;
383 
384  // Rect takes a length in 3rd parameter
385  $pdf->SetDrawColor(192, 192, 192);
386  $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1);
387 
388  $tab_height = $tab_height - $height_note;
389  $tab_top = $nexY + 6;
390  } else {
391  $height_note = 0;
392  }
393 
394  // Use new auto column system
395  $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
396 
397  // Table simulation to know the height of the title line
398  $pdf->startTransaction();
399  $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, 0);
400  $pdf->rollbackTransaction(true);
401 
402  $iniY = $tab_top + $this->tabTitleHeight + 2;
403  $curY = $tab_top + $this->tabTitleHeight + 2;
404  $nexY = $tab_top + $this->tabTitleHeight + 2;
405 
406  // Loop on each lines
407  for ($i = 0; $i < $nblines; $i++) {
408  // Fetch optionals
409  if (empty($object->lines[$i]->array_options)) {
410  $object->lines[$i]->fetch_optionals();
411  }
412 
413  $curY = $nexY;
414  $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
415  $pdf->SetTextColor(0, 0, 0);
416 
417  // Define size of image if we need it
418  $imglinesize = array();
419  if (!empty($realpatharray[$i])) {
420  $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
421  }
422 
423 
424  $pdf->setTopMargin($tab_top_newpage);
425  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
426  $pageposbefore = $pdf->getPage();
427 
428  // Description of product line
429  $curX = $this->posxdesc - 1;
430 
431  $showpricebeforepagebreak = 1;
432 
433  $posYAfterImage = 0;
434  $posYAfterDescription = 0;
435  if ($this->getColumnStatus('photo')) {
436  // We start with Photo of product line
437  if (isset($imglinesize['width']) && isset($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // If photo too high, we moved completely on new page
438  $pdf->AddPage('', '', true);
439  if (!empty($tplidx)) {
440  $pdf->useTemplate($tplidx);
441  }
442  //if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
443  $pdf->setPage($pageposbefore + 1);
444 
445  $curY = $tab_top_newpage;
446 
447  // Allows data in the first page if description is long enough to break in multiples pages
448  if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
449  $showpricebeforepagebreak = 1;
450  } else {
451  $showpricebeforepagebreak = 0;
452  }
453  }
454 
455 
456  if (!empty($this->cols['photo']) && isset($imglinesize['width']) && isset($imglinesize['height'])) {
457  $pdf->Image($realpatharray[$i], $this->getColumnContentXStart('photo'), $curY + 1, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
458  // $pdf->Image does not increase value return by getY, so we save it manually
459  $posYAfterImage = $curY + $imglinesize['height'];
460  }
461  }
462 
463 
464  // Description of product line
465  if ($this->getColumnStatus('desc')) {
466  $pdf->startTransaction();
467  pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->getColumnContentWidth('desc'), 3, $this->getColumnContentXStart('desc'), $curY, $hideref, $hidedesc);
468  $pageposafter = $pdf->getPage();
469  if ($pageposafter > $pageposbefore) { // There is a pagebreak
470  $pdf->rollbackTransaction(true);
471  $pageposafter = $pageposbefore;
472  //print $pageposafter.'-'.$pageposbefore;exit;
473  $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
474  pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->getColumnContentWidth('desc'), 4, $this->getColumnContentXStart('desc'), $curY, $hideref, $hidedesc);
475  $posyafter = $pdf->GetY();
476  if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
477  if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
478  $pdf->AddPage('', '', true);
479  if (!empty($tplidx)) {
480  $pdf->useTemplate($tplidx);
481  }
482  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
483  $this->_pagehead($pdf, $object, 0, $outputlangs);
484  }
485  $pdf->setPage($pageposafter + 1);
486  }
487  } else {
488  // We found a page break
489  // Allows data in the first page if description is long enough to break in multiples pages
490  if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
491  $showpricebeforepagebreak = 1;
492  } else {
493  $showpricebeforepagebreak = 0;
494  }
495  }
496  } else // No pagebreak
497  {
498  $pdf->commitTransaction();
499  }
500 
501  $posYAfterDescription = $pdf->GetY();
502  }
503 
504  $nexY = $pdf->GetY();
505  $pageposafter = $pdf->getPage();
506  $pdf->setPage($pageposbefore);
507  $pdf->setTopMargin($this->marge_haute);
508  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
509 
510  // We suppose that a too long description is moved completely on next page
511  if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
512  $pdf->setPage($pageposafter);
513  $curY = $tab_top_newpage;
514  }
515 
516  $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par defaut
517 
518 
519  // Quantity
520  if ($this->getColumnStatus('qty_shipped')) {
521  $this->printStdColumnContent($pdf, $curY, 'qty_shipped', $object->lines[$i]->qty_shipped);
522  $nexY = max($pdf->GetY(), $nexY);
523  }
524 
525  // Remaining to ship
526  if ($this->getColumnStatus('qty_remaining')) {
527  $qtyRemaining = $object->lines[$i]->qty_asked - $object->commande->expeditions[$object->lines[$i]->fk_origin_line];
528  $this->printStdColumnContent($pdf, $curY, 'qty_remaining', $qtyRemaining);
529  $nexY = max($pdf->GetY(), $nexY);
530  }
531 
532  $nexY = max($nexY, $posYAfterImage);
533 
534  // Extrafields
535  if (!empty($object->lines[$i]->array_options)) {
536  foreach ($object->lines[$i]->array_options as $extrafieldColKey => $extrafieldValue) {
537  if ($this->getColumnStatus($extrafieldColKey)) {
538  $extrafieldValue = $this->getExtrafieldContent($object->lines[$i], $extrafieldColKey, $outputlangs);
539  $this->printStdColumnContent($pdf, $curY, $extrafieldColKey, $extrafieldValue);
540  $nexY = max($pdf->GetY(), $nexY);
541  }
542  }
543  }
544 
545  // Add line
546  if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) {
547  $pdf->setPage($pageposafter);
548  $pdf->SetLineStyle(array('dash'=>'1,1', 'color'=>array(80, 80, 80)));
549  //$pdf->SetDrawColor(190,190,200);
550  $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1);
551  $pdf->SetLineStyle(array('dash'=>0));
552  }
553 
554  $nexY += 2; // Add space between lines
555 
556  // Detect if some page were added automatically and output _tableau for past pages
557  while ($pagenb < $pageposafter) {
558  $pdf->setPage($pagenb);
559  if ($pagenb == 1) {
560  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1);
561  } else {
562  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
563  }
564  $this->_pagefoot($pdf, $object, $outputlangs, 1);
565  $pagenb++;
566  $pdf->setPage($pagenb);
567  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
568  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
569  $this->_pagehead($pdf, $object, 0, $outputlangs);
570  }
571  if (!empty($tplidx)) {
572  $pdf->useTemplate($tplidx);
573  }
574  }
575  if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) {
576  if ($pagenb == 1) {
577  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1);
578  } else {
579  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
580  }
581  $this->_pagefoot($pdf, $object, $outputlangs, 1);
582  // New page
583  $pdf->AddPage();
584  if (!empty($tplidx)) {
585  $pdf->useTemplate($tplidx);
586  }
587  $pagenb++;
588  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
589  $this->_pagehead($pdf, $object, 0, $outputlangs);
590  }
591  }
592  }
593 
594  // Show square
595  if ($pagenb == 1) {
596  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0);
597  $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
598  } else {
599  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0);
600  $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
601  }
602 
603  // Affiche zone infos
604  $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
605 
606  // Pied de page
607  $this->_pagefoot($pdf, $object, $outputlangs);
608 
609  if (method_exists($pdf, 'AliasNbPages')) {
610  $pdf->AliasNbPages();
611  }
612 
613  $pdf->Close();
614 
615  $pdf->Output($file, 'F');
616 
617  // Add pdfgeneration hook
618  if (!is_object($hookmanager)) {
619  include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
620  $hookmanager = new HookManager($this->db);
621  }
622  $hookmanager->initHooks(array('pdfgeneration'));
623  $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
624  global $action;
625  $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
626  if ($reshook < 0) {
627  $this->error = $hookmanager->error;
628  $this->errors = $hookmanager->errors;
629  }
630 
631  dolChmod($file);
632 
633  $this->result = array('fullpath'=>$file);
634 
635  return 1; // No error
636  } else {
637  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
638  return 0;
639  }
640  }
641 
642  $this->error = $langs->transnoentities("ErrorConstantNotDefined", "LIVRAISON_OUTPUTDIR");
643  return 0;
644  }
645 
646  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
647  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
657  protected function _tableau_info(&$pdf, $object, $posy, $outputlangs)
658  {
659  // phpcs:enable
660  global $conf, $mysoc;
661  $default_font_size = pdf_getPDFFontSize($outputlangs);
662 
663  $pdf->SetFont('', '', $default_font_size);
664  $pdf->SetXY($this->marge_gauche, $posy);
665 
666  $larg_sign = ($this->page_largeur - $this->marge_gauche - $this->marge_droite) / 3;
667  $pdf->Rect($this->marge_gauche, $posy + 1, $larg_sign, 25);
668  $pdf->SetXY($this->marge_gauche + 2, $posy + 2);
669  $pdf->MultiCell($larg_sign, 2, $outputlangs->trans("For").' '.$outputlangs->convToOutputCharset($mysoc->name).":", '', 'L');
670 
671  $pdf->Rect(2 * $larg_sign + $this->marge_gauche, $posy + 1, $larg_sign, 25);
672  $pdf->SetXY(2 * $larg_sign + $this->marge_gauche + 2, $posy + 2);
673  $pdf->MultiCell($larg_sign, 2, $outputlangs->trans("ForCustomer").':', '', 'L');
674  }
675 
676 
677  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
690  protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0)
691  {
692  global $conf;
693 
694  // Force to disable hidetop and hidebottom
695  $hidebottom = 0;
696  if ($hidetop) {
697  $hidetop = -1;
698  }
699 
700  $currency = !empty($currency) ? $currency : $conf->currency;
701  $default_font_size = pdf_getPDFFontSize($outputlangs);
702 
703  // Amount in (at tab_top - 1)
704  $pdf->SetTextColor(0, 0, 0);
705  $pdf->SetFont('', '', $default_font_size - 2);
706 
707  if (empty($hidetop)) {
708  //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
709  if (!empty($conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)) {
710  $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, 5, 'F', null, explode(',', $conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR));
711  }
712  }
713 
714  $pdf->SetDrawColor(128, 128, 128);
715  $pdf->SetFont('', '', $default_font_size - 1);
716 
717  // Output Rect
718  $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
719 
720 
721  $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
722 
723  if (empty($hidetop)) {
724  $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
725  }
726  }
727 
728  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
738  protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
739  {
740  global $conf, $langs, $hookmanager;
741 
742  $default_font_size = pdf_getPDFFontSize($outputlangs);
743 
744  pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
745 
746  // Show Draft Watermark
747  if ($object->statut == 0 && getDolGlobalString('COMMANDE_DRAFT_WATERMARK')) {
748  pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', getDolGlobalString('COMMANDE_DRAFT_WATERMARK'));
749  }
750 
751  $pdf->SetTextColor(0, 0, 60);
752  $pdf->SetFont('', 'B', $default_font_size + 3);
753 
754  $posy = $this->marge_haute;
755  $posx = $this->page_largeur - $this->marge_droite - 100;
756 
757  $pdf->SetXY($this->marge_gauche, $posy);
758 
759  // Logo
760  $logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
761  if ($this->emetteur->logo) {
762  if (is_readable($logo)) {
763  $height = pdf_getHeightForLogo($logo);
764  $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
765  } else {
766  $pdf->SetTextColor(200, 0, 0);
767  $pdf->SetFont('', 'B', $default_font_size - 2);
768  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
769  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
770  }
771  } else {
772  $pdf->MultiCell(100, 4, $this->emetteur->name, 0, 'L');
773  }
774 
775  $pdf->SetFont('', 'B', $default_font_size + 2);
776  $pdf->SetXY($posx, $posy);
777  $pdf->SetTextColor(0, 0, 60);
778  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("DeliveryOrder")." ".$outputlangs->convToOutputCharset($object->ref), '', 'R');
779 
780  $pdf->SetFont('', '', $default_font_size + 2);
781 
782  $posy += 5;
783  $pdf->SetXY($posx, $posy);
784  $pdf->SetTextColor(0, 0, 60);
785  if ($object->date_valid) {
786  $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date_delivery, "%d %b %Y", false, $outputlangs, true), '', 'R');
787  } else {
788  $pdf->SetTextColor(255, 0, 0);
789  $pdf->MultiCell(100, 4, $outputlangs->transnoentities("DeliveryNotValidated"), '', 'R');
790  $pdf->SetTextColor(0, 0, 60);
791  }
792 
793  if ($object->thirdparty->code_client) {
794  $posy += 5;
795  $pdf->SetXY($posx, $posy);
796  $pdf->SetTextColor(0, 0, 60);
797  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R');
798  }
799 
800  $pdf->SetTextColor(0, 0, 60);
801 
802  $posy += 2;
803 
804  // Show list of linked objects
805  $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
806 
807  if ($showaddress) {
808  // Sender properties
809  $carac_emetteur = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
810 
811  // Show sender
812  $posy = 42;
813  $posx = $this->marge_gauche;
814  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
815  $posx = $this->page_largeur - $this->marge_droite - 80;
816  }
817  $hautcadre = 40;
818 
819  // Show sender frame
820  $pdf->SetTextColor(0, 0, 0);
821  $pdf->SetFont('', '', $default_font_size - 2);
822  $pdf->SetXY($posx, $posy - 5);
823  $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, 'L');
824  $pdf->SetXY($posx, $posy);
825  $pdf->SetFillColor(230, 230, 230);
826  $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1);
827  $pdf->SetTextColor(0, 0, 60);
828 
829  // Show sender name
830  $pdf->SetXY($posx + 2, $posy + 3);
831  $pdf->SetFont('', 'B', $default_font_size);
832  $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L');
833  $posy = $pdf->getY();
834 
835  // Show sender information
836  $pdf->SetXY($posx + 2, $posy);
837  $pdf->SetFont('', '', $default_font_size - 1);
838  $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L');
839 
840  // Client destinataire
841  $posy = 42;
842  $posx = 102;
843  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
844  $posx = $this->marge_gauche;
845  }
846  $pdf->SetTextColor(0, 0, 0);
847  $pdf->SetFont('', '', $default_font_size - 2);
848  $pdf->SetXY($posx, $posy - 5);
849  $pdf->MultiCell(80, 5, $outputlangs->transnoentities("DeliveryAddress"), 0, 'L');
850 
851  // If SHIPPING contact defined on order, we use it
852  $usecontact = false;
853  $arrayidcontact = $object->commande->getIdContact('external', 'SHIPPING');
854  if (count($arrayidcontact) > 0) {
855  $usecontact = true;
856  $result = $object->fetch_contact($arrayidcontact[0]);
857  }
858 
859  // Recipient name
860  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)))) {
861  $thirdparty = $object->contact;
862  } else {
863  $thirdparty = $object->thirdparty;
864  }
865 
866  $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
867 
868  $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), $usecontact, 'target', $object);
869 
870  // Show recipient
871  $widthrecbox = 100;
872  if ($this->page_largeur < 210) {
873  $widthrecbox = 84; // To work with US executive format
874  }
875  $posy = 42;
876  $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
877  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
878  $posx = $this->marge_gauche;
879  }
880 
881  // Show recipient frame
882  $pdf->SetTextColor(0, 0, 0);
883  $pdf->SetFont('', '', $default_font_size - 2);
884  $pdf->SetXY($posx + 2, $posy - 5);
885  //$pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":",0,'L');
886  $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
887 
888  // Show recipient name
889  $pdf->SetXY($posx + 2, $posy + 3);
890  $pdf->SetFont('', 'B', $default_font_size);
891  $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, 'L');
892 
893  $posy = $pdf->getY();
894 
895  // Show recipient information
896  $pdf->SetFont('', '', $default_font_size - 1);
897  $pdf->SetXY($posx + 2, $posy);
898  $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L');
899  }
900 
901  $pdf->SetTextColor(0, 0, 60);
902  }
903 
904  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
914  protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
915  {
916  $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
917  return pdf_pagefoot($pdf, $outputlangs, 'DELIVERY_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext);
918  }
919 
920 
921 
932  public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
933  {
934  global $conf, $hookmanager;
935 
936  // Default field style for content
937  $this->defaultContentsFieldsStyle = array(
938  'align' => 'R', // R,C,L
939  'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
940  );
941 
942  // Default field style for content
943  $this->defaultTitlesFieldsStyle = array(
944  'align' => 'C', // R,C,L
945  'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
946  );
947 
948  /*
949  * For exemple
950  $this->cols['theColKey'] = array(
951  'rank' => $rank, // int : use for ordering columns
952  'width' => 20, // the column width in mm
953  'title' => array(
954  'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
955  'label' => ' ', // the final label : used fore final generated text
956  'align' => 'L', // text alignement : R,C,L
957  'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
958  ),
959  'content' => array(
960  'align' => 'L', // text alignement : R,C,L
961  'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
962  ),
963  );
964  */
965 
966  $rank = 0; // do not use negative rank
967  $this->cols['desc'] = array(
968  'rank' => $rank,
969  'width' => false, // only for desc
970  'status' => true,
971  'title' => array(
972  'textkey' => 'Designation', // use lang key is usefull in somme case with module
973  'align' => 'L',
974  // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
975  // 'label' => ' ', // the final label
976  'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
977  ),
978  'content' => array(
979  'align' => 'L',
980  ),
981  );
982 
983  $rank = $rank + 10;
984  $this->cols['photo'] = array(
985  'rank' => $rank,
986  'width' => (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH), // in mm
987  'status' => false,
988  'title' => array(
989  'textkey' => 'Photo',
990  'label' => ' '
991  ),
992  'content' => array(
993  'padding' => array(0, 0, 0, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
994  ),
995  'border-left' => false, // remove left line separator
996  );
997 
998  if (!empty($conf->global->MAIN_GENERATE_DELIVERY_WITH_PICTURE) && !empty($this->atleastonephoto)) {
999  $this->cols['photo']['status'] = true;
1000  }
1001 
1002 
1003  $rank = $rank + 10;
1004  $this->cols['Comments'] = array(
1005  'rank' => $rank,
1006  'width' => 50, // in mm
1007  'status' => true,
1008  'title' => array(
1009  'textkey' => 'Comments'
1010  ),
1011  'border-left' => true, // add left line separator
1012  );
1013 
1014  // $rank = $rank + 10;
1015  // $this->cols['weight'] = array(
1016  // 'rank' => $rank,
1017  // 'width' => 30, // in mm
1018  // 'status' => false,
1019  // 'title' => array(
1020  // 'textkey' => 'WeightVolShort'
1021  // ),
1022  // 'border-left' => true, // add left line separator
1023  // );
1024 
1025  $rank = $rank + 10;
1026  $this->cols['qty_shipped'] = array(
1027  'rank' => $rank,
1028  'width' => 20, // in mm
1029  'status' => true,
1030  'title' => array(
1031  'textkey' => 'QtyShippedShort'
1032  ),
1033  'border-left' => true, // add left line separator
1034  );
1035 
1036  $rank = $rank + 10;
1037  $this->cols['qty_remaining'] = array(
1038  'rank' => $rank,
1039  'width' => 20, // in mm
1040  'status' => 1,
1041  'title' => array(
1042  'textkey' => 'KeepToShipShort'
1043  ),
1044  'border-left' => true, // add left line separator
1045  );
1046 
1047 
1048  // Add extrafields cols
1049  if (!empty($object->lines)) {
1050  $line = reset($object->lines);
1051  $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
1052  }
1053 
1054  $parameters = array(
1055  'object' => $object,
1056  'outputlangs' => $outputlangs,
1057  'hidedetails' => $hidedetails,
1058  'hidedesc' => $hidedesc,
1059  'hideref' => $hideref
1060  );
1061 
1062  $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
1063  if ($reshook < 0) {
1064  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1065  } elseif (empty($reshook)) {
1066  $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
1067  } else {
1068  $this->cols = $hookmanager->resArray;
1069  }
1070  }
1071 }
Class to manage customers orders.
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.
getColumnContentXStart($colKey)
get column content X (abscissa) left position from column key
printRect($pdf, $x, $y, $l, $h, $hidetop=0, $hidebottom=0)
Rect pdf.
getColumnContentWidth($colKey)
get column content width from column key
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 shipments.
Class to manage hooks.
Classe mere des modeles de bon de livraison.
Class to manage products or services.
Class to build Delivery Order documents with storm model.
defineColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Define Array Column Field.
_tableau_info(&$pdf, $object, $posy, $outputlangs)
Show miscellaneous information (payment mode, payment term, ...)
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0)
Show table for lines.
__construct($db)
Constructor.
_pagehead(&$pdf, $object, $showaddress, $outputlangs)
Show top header of page.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
print *****$script_file(".$version.") pid cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
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.
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...
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_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref=0, $hidedesc=0, $issupplierline=0)
Output line description into PDF.
Definition: pdf.lib.php:1369
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_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition: pdf.lib.php:1333
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_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
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition: pdf.lib.php:773
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