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