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