dolibarr 20.0.0
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
33require_once DOL_DOCUMENT_ROOT.'/core/modules/delivery/modules_delivery.php';
34require_once DOL_DOCUMENT_ROOT.'/delivery/class/delivery.class.php';
35require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
36require_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 $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.
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.
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:137
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:140