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