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