dolibarr 18.0.6
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
31require_once DOL_DOCUMENT_ROOT.'/core/modules/delivery/modules_delivery.php';
32require_once DOL_DOCUMENT_ROOT.'/delivery/class/delivery.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
34require_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 $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after 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.
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:2529
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:1374
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:1010
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition pdf.lib.php:726
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition pdf.lib.php:1338
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:778
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