dolibarr  17.0.4
pdf_storm.modules.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2005-2014 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2007 Franky Van Liedekerke <franky.van.liedekerke@telenet.be>
5  * Copyright (C) 2008 Chiptronik
6  * Copyright (C) 2011-2021 Philippe Grand <philippe.grand@atoo-net.com>
7  * Copyright (C) 2015 Marcos GarcĂ­a <marcosgdf@gmail.com>
8  * Copyright (C) 2020 John BOTELLA
9 
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <https://www.gnu.org/licenses/>.
22  * or see https://www.gnu.org/
23  */
24 
31 require_once DOL_DOCUMENT_ROOT.'/core/modules/delivery/modules_delivery.php';
32 require_once DOL_DOCUMENT_ROOT.'/delivery/class/delivery.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
35 
36 
41 {
45  public $db;
46 
50  public $name;
51 
55  public $description;
56 
60  public $update_main_doc_field;
61 
65  public $type;
66 
71  public $phpmin = array(7, 0);
72 
77  public $version = 'dolibarr';
78 
82  public $page_largeur;
83 
87  public $page_hauteur;
88 
92  public $format;
93 
97  public $marge_gauche;
98 
102  public $marge_droite;
103 
107  public $marge_haute;
108 
112  public $marge_basse;
113 
118  public $emetteur;
119 
125  public function __construct($db)
126  {
127  global $conf, $langs, $mysoc;
128 
129  // Translations
130  $langs->loadLangs(array("main", "bills", "sendings", "companies"));
131 
132  $this->db = $db;
133  $this->name = "Storm";
134  $this->description = $langs->trans("DocumentModelStorm");
135  $this->update_main_doc_field = 1; // Save the name of generated file as the main doc when generating a doc with this template
136 
137  // Page size for A4 format
138  $this->type = 'pdf';
139  $formatarray = pdf_getFormat();
140  $this->page_largeur = $formatarray['width'];
141  $this->page_hauteur = $formatarray['height'];
142  $this->format = array($this->page_largeur, $this->page_hauteur);
143  $this->marge_gauche = getDolGlobalInt('MAIN_PDF_MARGIN_LEFT', 10);
144  $this->marge_droite = getDolGlobalInt('MAIN_PDF_MARGIN_RIGHT', 10);
145  $this->marge_haute = getDolGlobalInt('MAIN_PDF_MARGIN_TOP', 10);
146  $this->marge_basse = getDolGlobalInt('MAIN_PDF_MARGIN_BOTTOM', 10);
147 
148  $this->option_logo = 1; // Display logo FAC_PDF_LOGO
149  $this->option_tva = 1; // Manage the vat option FACTURE_TVAOPTION
150 
151  // Get source company
152  $this->emetteur = $mysoc;
153  if (empty($this->emetteur->country_code)) {
154  $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default, if was not defined
155  }
156 
157  $this->tva = array();
158  $this->tva_array = array();
159  $this->localtax1 = array();
160  $this->localtax2 = array();
161  $this->atleastoneratenotnull = 0;
162  $this->atleastonediscount = 0;
163  }
164 
165 
166  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
178  public function write_file($object, $outputlangs, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
179  {
180  // phpcs:enable
181  global $user, $langs, $conf, $mysoc, $hookmanager;
182 
183  if (!is_object($outputlangs)) {
184  $outputlangs = $langs;
185  }
186  // For backward compatibility with FPDF, force output charset to ISO, because FPDF expect text to be encoded in ISO
187  if (!empty($conf->global->MAIN_USE_FPDF)) {
188  $outputlangs->charset_output = 'ISO-8859-1';
189  }
190 
191  // Load translation files required by the page
192  $outputlangs->loadLangs(array("main", "dict", "companies", "bills", "products", "sendings", "deliveries"));
193 
194  if ($conf->expedition->dir_output) {
195  $object->fetch_thirdparty();
196 
197  // Definition of $dir and $file
198  if ($object->specimen) {
199  $dir = $conf->expedition->dir_output."/receipt";
200  $file = $dir."/SPECIMEN.pdf";
201  } else {
202  $objectref = dol_sanitizeFileName($object->ref);
203  $dir = $conf->expedition->dir_output."/receipt/".$objectref;
204  $file = $dir."/".$objectref.".pdf";
205  }
206 
207  if (!file_exists($dir)) {
208  if (dol_mkdir($dir) < 0) {
209  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
210  return 0;
211  }
212  }
213 
214  if (file_exists($dir)) {
215  // Add pdfgeneration hook
216  if (!is_object($hookmanager)) {
217  include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
218  $hookmanager = new HookManager($this->db);
219  }
220  $hookmanager->initHooks(array('pdfgeneration'));
221  $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
222  global $action;
223  $reshook = $hookmanager->executeHooks('beforePDFCreation', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
224 
225  $nblines = count($object->lines);
226 
227 
228  // Loop on each lines to detect if there is at least one image to show
229  $realpatharray = array();
230  $this->atleastonephoto = false;
231  if (!empty($conf->global->MAIN_GENERATE_DELIVERY_WITH_PICTURE)) {
232  $objphoto = new Product($this->db);
233 
234  for ($i = 0; $i < $nblines; $i++) {
235  if (empty($object->lines[$i]->fk_product)) {
236  continue;
237  }
238 
239  $objphoto->fetch($object->lines[$i]->fk_product);
240 
241  if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
242  $pdir[0] = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$objphoto->id."/photos/";
243  $pdir[1] = get_exdir(0, 0, 0, 0, $objphoto, 'product').dol_sanitizeFileName($objphoto->ref).'/';
244  } else {
245  $pdir[0] = get_exdir(0, 0, 0, 0, $objphoto, 'product'); // default
246  $pdir[1] = get_exdir($objphoto->id, 2, 0, 0, $objphoto, 'product').$objphoto->id."/photos/"; // alternative
247  }
248 
249  $arephoto = false;
250  foreach ($pdir as $midir) {
251  if (!$arephoto) {
252  $dir = $conf->product->dir_output.'/'.$midir;
253 
254  foreach ($objphoto->liste_photos($dir, 1) as $key => $obj) {
255  if (!getDolGlobalInt('CAT_HIGH_QUALITY_IMAGES')) { // If CAT_HIGH_QUALITY_IMAGES not defined, we use thumb if defined and then original photo
256  if ($obj['photo_vignette']) {
257  $filename = $obj['photo_vignette'];
258  } else {
259  $filename = $obj['photo'];
260  }
261  } else {
262  $filename = $obj['photo'];
263  }
264 
265  $realpath = $dir.$filename;
266  $arephoto = true;
267  $this->atleastonephoto = true;
268  }
269  }
270  }
271 
272  if ($realpath && $arephoto) {
273  $realpatharray[$i] = $realpath;
274  }
275  }
276  }
277 
278  if (count($realpatharray) == 0) {
279  $this->posxpicture = $this->posxweightvol;
280  }
281 
282 
283 
284  // Create pdf instance
285  $pdf = pdf_getInstance($this->format);
286  $default_font_size = pdf_getPDFFontSize($outputlangs); // Must be after pdf_getInstance
287  $heightforinfotot = 30; // Height reserved to output the info and total part
288  $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
289  $heightforfooter = $this->marge_basse + 8; // Height reserved to output the footer (value include bottom margin)
290  if (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS)) {
291  $heightforfooter += 6;
292  }
293  $pdf->SetAutoPageBreak(1, 0);
294 
295  if (class_exists('TCPDF')) {
296  $pdf->setPrintHeader(false);
297  $pdf->setPrintFooter(false);
298  }
299  $pdf->SetFont(pdf_getPDFFont($outputlangs));
300  // Set path to the background PDF File
301  if (!empty($conf->global->MAIN_ADD_PDF_BACKGROUND)) {
302  $pagecount = $pdf->setSourceFile($conf->mycompany->dir_output.'/'.$conf->global->MAIN_ADD_PDF_BACKGROUND);
303  $tplidx = $pdf->importPage(1);
304  }
305 
306  // We get the shipment that is the origin of delivery receipt
307  $expedition = new Expedition($this->db);
308  $result = $expedition->fetch($object->origin_id);
309  // Now we get the order that is origin of shipment
310  $commande = new Commande($this->db);
311  if ($expedition->origin == 'commande') {
312  $commande->fetch($expedition->origin_id);
313  }
314  $object->commande = $commande; // We set order of shipment onto delivery.
315  $object->commande->loadExpeditions();
316 
317 
318  $pdf->Open();
319  $pagenb = 0;
320  $pdf->SetDrawColor(128, 128, 128);
321 
322  $pdf->SetTitle($outputlangs->convToOutputCharset($object->ref));
323  $pdf->SetSubject($outputlangs->transnoentities("DeliveryOrder"));
324  $pdf->SetCreator("Dolibarr ".DOL_VERSION);
325  $pdf->SetAuthor($outputlangs->convToOutputCharset($user->getFullName($outputlangs)));
326  $pdf->SetKeyWords($outputlangs->convToOutputCharset($object->ref)." ".$outputlangs->transnoentities("DeliveryOrder"));
327  if (getDolGlobalString('MAIN_DISABLE_PDF_COMPRESSION')) {
328  $pdf->SetCompression(false);
329  }
330 
331  $pdf->SetMargins($this->marge_gauche, $this->marge_haute, $this->marge_droite); // Left, Top, Right
332 
333 
334  // New page
335  $pdf->AddPage();
336  if (!empty($tplidx)) {
337  $pdf->useTemplate($tplidx);
338  }
339  $pagenb++;
340  $this->_pagehead($pdf, $object, 1, $outputlangs);
341  $pdf->SetFont('', '', $default_font_size - 1);
342  $pdf->MultiCell(0, 3, ''); // Set interline to 3
343  $pdf->SetTextColor(0, 0, 0);
344 
345  $tab_top = 90;
346  $tab_top_newpage = (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD') ? 42 : 10);
347 
348  $tab_height = $this->page_hauteur - $tab_top - $heightforfooter - $heightforfreetext;
349 
350  $this->posxdesc = $this->marge_gauche + 1;
351 
352  // Incoterm
353  $height_incoterms = 0;
354  if (isModEnabled('incoterm')) {
355  $desc_incoterms = $object->getIncotermsForPDF();
356  if ($desc_incoterms) {
357  $tab_top -= 2;
358 
359  $pdf->SetFont('', '', $default_font_size - 1);
360  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top - 1, dol_htmlentitiesbr($desc_incoterms), 0, 1);
361  $nexY = $pdf->GetY();
362  $height_incoterms = $nexY - $tab_top;
363 
364  // Rect takes a length in 3rd parameter
365  $pdf->SetDrawColor(192, 192, 192);
366  $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_incoterms + 1);
367 
368  $tab_top = $nexY + 6;
369  $height_incoterms += 4;
370  }
371  }
372 
373  // display note
374  $notetoshow = empty($object->note_public) ? '' : $object->note_public;
375 
376  // Extrafields in note
377  $extranote = $this->getExtrafieldsInHtml($object, $outputlangs);
378  if (!empty($extranote)) {
379  $notetoshow = dol_concatdesc($notetoshow, $extranote);
380  }
381 
382  if (!empty($notetoshow)) {
383  $tab_top = 88 + $height_incoterms;
384 
385  $pdf->SetFont('', '', $default_font_size - 1);
386  $pdf->writeHTMLCell(190, 3, $this->posxdesc - 1, $tab_top, dol_htmlentitiesbr($notetoshow), 0, 1);
387  $nexY = $pdf->GetY();
388  $height_note = $nexY - $tab_top;
389 
390  // Rect takes a length in 3rd parameter
391  $pdf->SetDrawColor(192, 192, 192);
392  $pdf->Rect($this->marge_gauche, $tab_top - 1, $this->page_largeur - $this->marge_gauche - $this->marge_droite, $height_note + 1);
393 
394  $tab_height = $tab_height - $height_note;
395  $tab_top = $nexY + 6;
396  } else {
397  $height_note = 0;
398  }
399 
400  // Use new auto column system
401  $this->prepareArrayColumnField($object, $outputlangs, $hidedetails, $hidedesc, $hideref);
402 
403  // Table simulation to know the height of the title line
404  $pdf->startTransaction();
405  $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, 0);
406  $pdf->rollbackTransaction(true);
407 
408  $iniY = $tab_top + $this->tabTitleHeight + 2;
409  $curY = $tab_top + $this->tabTitleHeight + 2;
410  $nexY = $tab_top + $this->tabTitleHeight + 2;
411 
412  // Loop on each lines
413  for ($i = 0; $i < $nblines; $i++) {
414  // Fetch optionals
415  if (empty($object->lines[$i]->array_options)) {
416  $object->lines[$i]->fetch_optionals();
417  }
418 
419  $curY = $nexY;
420  $pdf->SetFont('', '', $default_font_size - 1); // Into loop to work with multipage
421  $pdf->SetTextColor(0, 0, 0);
422 
423  // Define size of image if we need it
424  $imglinesize = array();
425  if (!empty($realpatharray[$i])) {
426  $imglinesize = pdf_getSizeForImage($realpatharray[$i]);
427  }
428 
429 
430  $pdf->setTopMargin($tab_top_newpage);
431  $pdf->setPageOrientation('', 1, $heightforfooter + $heightforfreetext + $heightforinfotot); // The only function to edit the bottom margin of current page to set it.
432  $pageposbefore = $pdf->getPage();
433 
434  // Description of product line
435  $curX = $this->posxdesc - 1;
436 
437  $showpricebeforepagebreak = 1;
438 
439  $posYAfterImage = 0;
440  $posYAfterDescription = 0;
441  if ($this->getColumnStatus('photo')) {
442  // We start with Photo of product line
443  if (isset($imglinesize['width']) && isset($imglinesize['height']) && ($curY + $imglinesize['height']) > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // If photo too high, we moved completely on new page
444  $pdf->AddPage('', '', true);
445  if (!empty($tplidx)) {
446  $pdf->useTemplate($tplidx);
447  }
448  //if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) $this->_pagehead($pdf, $object, 0, $outputlangs);
449  $pdf->setPage($pageposbefore + 1);
450 
451  $curY = $tab_top_newpage;
452 
453  // Allows data in the first page if description is long enough to break in multiples pages
454  if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
455  $showpricebeforepagebreak = 1;
456  } else {
457  $showpricebeforepagebreak = 0;
458  }
459  }
460 
461 
462  if (!empty($this->cols['photo']) && isset($imglinesize['width']) && isset($imglinesize['height'])) {
463  $pdf->Image($realpatharray[$i], $this->getColumnContentXStart('photo'), $curY + 1, $imglinesize['width'], $imglinesize['height'], '', '', '', 2, 300); // Use 300 dpi
464  // $pdf->Image does not increase value return by getY, so we save it manually
465  $posYAfterImage = $curY + $imglinesize['height'];
466  }
467  }
468 
469 
470  // Description of product line
471  if ($this->getColumnStatus('desc')) {
472  $pdf->startTransaction();
473  pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->getColumnContentWidth('desc'), 3, $this->getColumnContentXStart('desc'), $curY, $hideref, $hidedesc);
474  $pageposafter = $pdf->getPage();
475  if ($pageposafter > $pageposbefore) { // There is a pagebreak
476  $pdf->rollbackTransaction(true);
477  $pageposafter = $pageposbefore;
478  //print $pageposafter.'-'.$pageposbefore;exit;
479  $pdf->setPageOrientation('', 1, $heightforfooter); // The only function to edit the bottom margin of current page to set it.
480  pdf_writelinedesc($pdf, $object, $i, $outputlangs, $this->getColumnContentWidth('desc'), 4, $this->getColumnContentXStart('desc'), $curY, $hideref, $hidedesc);
481  $posyafter = $pdf->GetY();
482  if ($posyafter > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) { // There is no space left for total+free text
483  if ($i == ($nblines - 1)) { // No more lines, and no space left to show total, so we create a new page
484  $pdf->AddPage('', '', true);
485  if (!empty($tplidx)) {
486  $pdf->useTemplate($tplidx);
487  }
488  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
489  $this->_pagehead($pdf, $object, 0, $outputlangs);
490  }
491  $pdf->setPage($pageposafter + 1);
492  }
493  } else {
494  // We found a page break
495  // Allows data in the first page if description is long enough to break in multiples pages
496  if (!empty($conf->global->MAIN_PDF_DATA_ON_FIRST_PAGE)) {
497  $showpricebeforepagebreak = 1;
498  } else {
499  $showpricebeforepagebreak = 0;
500  }
501  }
502  } else // No pagebreak
503  {
504  $pdf->commitTransaction();
505  }
506 
507  $posYAfterDescription = $pdf->GetY();
508  }
509 
510  $nexY = $pdf->GetY();
511  $pageposafter = $pdf->getPage();
512  $pdf->setPage($pageposbefore);
513  $pdf->setTopMargin($this->marge_haute);
514  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
515 
516  // We suppose that a too long description is moved completely on next page
517  if ($pageposafter > $pageposbefore && empty($showpricebeforepagebreak)) {
518  $pdf->setPage($pageposafter);
519  $curY = $tab_top_newpage;
520  }
521 
522  $pdf->SetFont('', '', $default_font_size - 1); // On repositionne la police par defaut
523 
524 
525  // Quantity
526  if ($this->getColumnStatus('qty_shipped')) {
527  $this->printStdColumnContent($pdf, $curY, 'qty_shipped', $object->lines[$i]->qty_shipped);
528  $nexY = max($pdf->GetY(), $nexY);
529  }
530 
531  // Remaining to ship
532  if ($this->getColumnStatus('qty_remaining')) {
533  $qtyRemaining = $object->lines[$i]->qty_asked - $object->commande->expeditions[$object->lines[$i]->fk_origin_line];
534  $this->printStdColumnContent($pdf, $curY, 'qty_remaining', $qtyRemaining);
535  $nexY = max($pdf->GetY(), $nexY);
536  }
537 
538  $nexY = max($nexY, $posYAfterImage);
539 
540  // Extrafields
541  if (!empty($object->lines[$i]->array_options)) {
542  foreach ($object->lines[$i]->array_options as $extrafieldColKey => $extrafieldValue) {
543  if ($this->getColumnStatus($extrafieldColKey)) {
544  $extrafieldValue = $this->getExtrafieldContent($object->lines[$i], $extrafieldColKey, $outputlangs);
545  $this->printStdColumnContent($pdf, $curY, $extrafieldColKey, $extrafieldValue);
546  $nexY = max($pdf->GetY(), $nexY);
547  }
548  }
549  }
550 
551  // Add line
552  if (!empty($conf->global->MAIN_PDF_DASH_BETWEEN_LINES) && $i < ($nblines - 1)) {
553  $pdf->setPage($pageposafter);
554  $pdf->SetLineStyle(array('dash'=>'1,1', 'color'=>array(80, 80, 80)));
555  //$pdf->SetDrawColor(190,190,200);
556  $pdf->line($this->marge_gauche, $nexY + 1, $this->page_largeur - $this->marge_droite, $nexY + 1);
557  $pdf->SetLineStyle(array('dash'=>0));
558  }
559 
560  $nexY += 2; // Add space between lines
561 
562  // Detect if some page were added automatically and output _tableau for past pages
563  while ($pagenb < $pageposafter) {
564  $pdf->setPage($pagenb);
565  if ($pagenb == 1) {
566  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1);
567  } else {
568  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
569  }
570  $this->_pagefoot($pdf, $object, $outputlangs, 1);
571  $pagenb++;
572  $pdf->setPage($pagenb);
573  $pdf->setPageOrientation('', 1, 0); // The only function to edit the bottom margin of current page to set it.
574  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
575  $this->_pagehead($pdf, $object, 0, $outputlangs);
576  }
577  if (!empty($tplidx)) {
578  $pdf->useTemplate($tplidx);
579  }
580  }
581  if (isset($object->lines[$i + 1]->pagebreak) && $object->lines[$i + 1]->pagebreak) {
582  if ($pagenb == 1) {
583  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforfooter, 0, $outputlangs, 0, 1);
584  } else {
585  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforfooter, 0, $outputlangs, 1, 1);
586  }
587  $this->_pagefoot($pdf, $object, $outputlangs, 1);
588  // New page
589  $pdf->AddPage();
590  if (!empty($tplidx)) {
591  $pdf->useTemplate($tplidx);
592  }
593  $pagenb++;
594  if (!getDolGlobalInt('MAIN_PDF_DONOTREPEAT_HEAD')) {
595  $this->_pagehead($pdf, $object, 0, $outputlangs);
596  }
597  }
598  }
599 
600  // Show square
601  if ($pagenb == 1) {
602  $this->_tableau($pdf, $tab_top, $this->page_hauteur - $tab_top - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 0, 0);
603  $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
604  } else {
605  $this->_tableau($pdf, $tab_top_newpage, $this->page_hauteur - $tab_top_newpage - $heightforinfotot - $heightforfreetext - $heightforfooter, 0, $outputlangs, 1, 0);
606  $bottomlasttab = $this->page_hauteur - $heightforinfotot - $heightforfreetext - $heightforfooter + 1;
607  }
608 
609  // Affiche zone infos
610  $this->_tableau_info($pdf, $object, $bottomlasttab, $outputlangs);
611 
612  // Pied de page
613  $this->_pagefoot($pdf, $object, $outputlangs);
614 
615  if (method_exists($pdf, 'AliasNbPages')) {
616  $pdf->AliasNbPages();
617  }
618 
619  $pdf->Close();
620 
621  $pdf->Output($file, 'F');
622 
623  // Add pdfgeneration hook
624  if (!is_object($hookmanager)) {
625  include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
626  $hookmanager = new HookManager($this->db);
627  }
628  $hookmanager->initHooks(array('pdfgeneration'));
629  $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs);
630  global $action;
631  $reshook = $hookmanager->executeHooks('afterPDFCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
632  if ($reshook < 0) {
633  $this->error = $hookmanager->error;
634  $this->errors = $hookmanager->errors;
635  }
636 
637  if (!empty($conf->global->MAIN_UMASK)) {
638  @chmod($file, octdec($conf->global->MAIN_UMASK));
639  }
640 
641  $this->result = array('fullpath'=>$file);
642 
643  return 1; // No error
644  } else {
645  $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir);
646  return 0;
647  }
648  }
649 
650  $this->error = $langs->transnoentities("ErrorConstantNotDefined", "LIVRAISON_OUTPUTDIR");
651  return 0;
652  }
653 
654  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
655  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
665  protected function _tableau_info(&$pdf, $object, $posy, $outputlangs)
666  {
667  // phpcs:enable
668  global $conf, $mysoc;
669  $default_font_size = pdf_getPDFFontSize($outputlangs);
670 
671  $pdf->SetFont('', '', $default_font_size);
672  $pdf->SetXY($this->marge_gauche, $posy);
673 
674  $larg_sign = ($this->page_largeur - $this->marge_gauche - $this->marge_droite) / 3;
675  $pdf->Rect($this->marge_gauche, $posy + 1, $larg_sign, 25);
676  $pdf->SetXY($this->marge_gauche + 2, $posy + 2);
677  $pdf->MultiCell($larg_sign, 2, $outputlangs->trans("For").' '.$outputlangs->convToOutputCharset($mysoc->name).":", '', 'L');
678 
679  $pdf->Rect(2 * $larg_sign + $this->marge_gauche, $posy + 1, $larg_sign, 25);
680  $pdf->SetXY(2 * $larg_sign + $this->marge_gauche + 2, $posy + 2);
681  $pdf->MultiCell($larg_sign, 2, $outputlangs->trans("ForCustomer").':', '', 'L');
682  }
683 
684 
685  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
698  protected function _tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop = 0, $hidebottom = 0)
699  {
700  global $conf;
701 
702  // Force to disable hidetop and hidebottom
703  $hidebottom = 0;
704  if ($hidetop) {
705  $hidetop = -1;
706  }
707 
708  $currency = !empty($currency) ? $currency : $conf->currency;
709  $default_font_size = pdf_getPDFFontSize($outputlangs);
710 
711  // Amount in (at tab_top - 1)
712  $pdf->SetTextColor(0, 0, 0);
713  $pdf->SetFont('', '', $default_font_size - 2);
714 
715  if (empty($hidetop)) {
716  //$conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR='230,230,230';
717  if (!empty($conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR)) {
718  $pdf->Rect($this->marge_gauche, $tab_top, $this->page_largeur - $this->marge_droite - $this->marge_gauche, 5, 'F', null, explode(',', $conf->global->MAIN_PDF_TITLE_BACKGROUND_COLOR));
719  }
720  }
721 
722  $pdf->SetDrawColor(128, 128, 128);
723  $pdf->SetFont('', '', $default_font_size - 1);
724 
725  // Output Rect
726  $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
727 
728 
729  $this->pdfTabTitles($pdf, $tab_top, $tab_height, $outputlangs, $hidetop);
730 
731  if (empty($hidetop)) {
732  $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
733  }
734  }
735 
736  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
746  protected function _pagehead(&$pdf, $object, $showaddress, $outputlangs)
747  {
748  global $conf, $langs, $hookmanager;
749 
750  $default_font_size = pdf_getPDFFontSize($outputlangs);
751 
752  pdf_pagehead($pdf, $outputlangs, $this->page_hauteur);
753 
754  // Show Draft Watermark
755  if ($object->statut == 0 && (!empty($conf->global->COMMANDE_DRAFT_WATERMARK))) {
756  pdf_watermark($pdf, $outputlangs, $this->page_hauteur, $this->page_largeur, 'mm', $conf->global->COMMANDE_DRAFT_WATERMARK);
757  }
758 
759  $pdf->SetTextColor(0, 0, 60);
760  $pdf->SetFont('', 'B', $default_font_size + 3);
761 
762  $posy = $this->marge_haute;
763  $posx = $this->page_largeur - $this->marge_droite - 100;
764 
765  $pdf->SetXY($this->marge_gauche, $posy);
766 
767  // Logo
768  $logo = $conf->mycompany->dir_output.'/logos/'.$this->emetteur->logo;
769  if ($this->emetteur->logo) {
770  if (is_readable($logo)) {
771  $height = pdf_getHeightForLogo($logo);
772  $pdf->Image($logo, $this->marge_gauche, $posy, 0, $height); // width=0 (auto)
773  } else {
774  $pdf->SetTextColor(200, 0, 0);
775  $pdf->SetFont('', 'B', $default_font_size - 2);
776  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorLogoFileNotFound", $logo), 0, 'L');
777  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("ErrorGoToGlobalSetup"), 0, 'L');
778  }
779  } else {
780  $pdf->MultiCell(100, 4, $this->emetteur->name, 0, 'L');
781  }
782 
783  $pdf->SetFont('', 'B', $default_font_size + 2);
784  $pdf->SetXY($posx, $posy);
785  $pdf->SetTextColor(0, 0, 60);
786  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("DeliveryOrder")." ".$outputlangs->convToOutputCharset($object->ref), '', 'R');
787 
788  $pdf->SetFont('', '', $default_font_size + 2);
789 
790  $posy += 5;
791  $pdf->SetXY($posx, $posy);
792  $pdf->SetTextColor(0, 0, 60);
793  if ($object->date_valid) {
794  $pdf->MultiCell(100, 4, $outputlangs->transnoentities("Date")." : ".dol_print_date($object->date_delivery, "%d %b %Y", false, $outputlangs, true), '', 'R');
795  } else {
796  $pdf->SetTextColor(255, 0, 0);
797  $pdf->MultiCell(100, 4, $outputlangs->transnoentities("DeliveryNotValidated"), '', 'R');
798  $pdf->SetTextColor(0, 0, 60);
799  }
800 
801  if ($object->thirdparty->code_client) {
802  $posy += 5;
803  $pdf->SetXY($posx, $posy);
804  $pdf->SetTextColor(0, 0, 60);
805  $pdf->MultiCell(100, 3, $outputlangs->transnoentities("CustomerCode")." : ".$outputlangs->transnoentities($object->thirdparty->code_client), '', 'R');
806  }
807 
808  $pdf->SetTextColor(0, 0, 60);
809 
810  $posy += 2;
811 
812  // Show list of linked objects
813  $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size);
814 
815  if ($showaddress) {
816  // Sender properties
817  $carac_emetteur = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, '', 0, 'source', $object);
818 
819  // Show sender
820  $posy = 42;
821  $posx = $this->marge_gauche;
822  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
823  $posx = $this->page_largeur - $this->marge_droite - 80;
824  }
825  $hautcadre = 40;
826 
827  // Show sender frame
828  $pdf->SetTextColor(0, 0, 0);
829  $pdf->SetFont('', '', $default_font_size - 2);
830  $pdf->SetXY($posx, $posy - 5);
831  $pdf->MultiCell(80, 5, $outputlangs->transnoentities("BillFrom"), 0, 'L');
832  $pdf->SetXY($posx, $posy);
833  $pdf->SetFillColor(230, 230, 230);
834  $pdf->MultiCell(82, $hautcadre, "", 0, 'R', 1);
835  $pdf->SetTextColor(0, 0, 60);
836 
837  // Show sender name
838  $pdf->SetXY($posx + 2, $posy + 3);
839  $pdf->SetFont('', 'B', $default_font_size);
840  $pdf->MultiCell(80, 4, $outputlangs->convToOutputCharset($this->emetteur->name), 0, 'L');
841  $posy = $pdf->getY();
842 
843  // Show sender information
844  $pdf->SetXY($posx + 2, $posy);
845  $pdf->SetFont('', '', $default_font_size - 1);
846  $pdf->MultiCell(80, 4, $carac_emetteur, 0, 'L');
847 
848  // Client destinataire
849  $posy = 42;
850  $posx = 102;
851  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
852  $posx = $this->marge_gauche;
853  }
854  $pdf->SetTextColor(0, 0, 0);
855  $pdf->SetFont('', '', $default_font_size - 2);
856  $pdf->SetXY($posx, $posy - 5);
857  $pdf->MultiCell(80, 5, $outputlangs->transnoentities("DeliveryAddress"), 0, 'L');
858 
859  // If SHIPPING contact defined on order, we use it
860  $usecontact = false;
861  $arrayidcontact = $object->commande->getIdContact('external', 'SHIPPING');
862  if (count($arrayidcontact) > 0) {
863  $usecontact = true;
864  $result = $object->fetch_contact($arrayidcontact[0]);
865  }
866 
867  // Recipient name
868  if ($usecontact && ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT)))) {
869  $thirdparty = $object->contact;
870  } else {
871  $thirdparty = $object->thirdparty;
872  }
873 
874  $carac_client_name = pdfBuildThirdpartyName($thirdparty, $outputlangs);
875 
876  $carac_client = pdf_build_address($outputlangs, $this->emetteur, $object->thirdparty, ($usecontact ? $object->contact : ''), $usecontact, 'target', $object);
877 
878  // Show recipient
879  $widthrecbox = 100;
880  if ($this->page_largeur < 210) {
881  $widthrecbox = 84; // To work with US executive format
882  }
883  $posy = 42;
884  $posx = $this->page_largeur - $this->marge_droite - $widthrecbox;
885  if (!empty($conf->global->MAIN_INVERT_SENDER_RECIPIENT)) {
886  $posx = $this->marge_gauche;
887  }
888 
889  // Show recipient frame
890  $pdf->SetTextColor(0, 0, 0);
891  $pdf->SetFont('', '', $default_font_size - 2);
892  $pdf->SetXY($posx + 2, $posy - 5);
893  //$pdf->MultiCell($widthrecbox, 5, $outputlangs->transnoentities("BillTo").":",0,'L');
894  $pdf->Rect($posx, $posy, $widthrecbox, $hautcadre);
895 
896  // Show recipient name
897  $pdf->SetXY($posx + 2, $posy + 3);
898  $pdf->SetFont('', 'B', $default_font_size);
899  $pdf->MultiCell($widthrecbox, 4, $carac_client_name, 0, 'L');
900 
901  $posy = $pdf->getY();
902 
903  // Show recipient information
904  $pdf->SetFont('', '', $default_font_size - 1);
905  $pdf->SetXY($posx + 2, $posy);
906  $pdf->MultiCell($widthrecbox, 4, $carac_client, 0, 'L');
907  }
908 
909  $pdf->SetTextColor(0, 0, 60);
910  }
911 
912  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
922  protected function _pagefoot(&$pdf, $object, $outputlangs, $hidefreetext = 0)
923  {
924  $showdetails = getDolGlobalInt('MAIN_GENERATE_DOCUMENTS_SHOW_FOOT_DETAILS', 0);
925  return pdf_pagefoot($pdf, $outputlangs, 'DELIVERY_FREE_TEXT', $this->emetteur, $this->marge_basse, $this->marge_gauche, $this->page_hauteur, $object, $showdetails, $hidefreetext);
926  }
927 
928 
929 
940  public function defineColumnField($object, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
941  {
942  global $conf, $hookmanager;
943 
944  // Default field style for content
945  $this->defaultContentsFieldsStyle = array(
946  'align' => 'R', // R,C,L
947  'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
948  );
949 
950  // Default field style for content
951  $this->defaultTitlesFieldsStyle = array(
952  'align' => 'C', // R,C,L
953  'padding' => array(0.5, 0, 0.5, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
954  );
955 
956  /*
957  * For exemple
958  $this->cols['theColKey'] = array(
959  'rank' => $rank, // int : use for ordering columns
960  'width' => 20, // the column width in mm
961  'title' => array(
962  'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
963  'label' => ' ', // the final label : used fore final generated text
964  'align' => 'L', // text alignement : R,C,L
965  'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
966  ),
967  'content' => array(
968  'align' => 'L', // text alignement : R,C,L
969  'padding' => array(0.5,0.5,0.5,0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
970  ),
971  );
972  */
973 
974  $rank = 0; // do not use negative rank
975  $this->cols['desc'] = array(
976  'rank' => $rank,
977  'width' => false, // only for desc
978  'status' => true,
979  'title' => array(
980  'textkey' => 'Designation', // use lang key is usefull in somme case with module
981  'align' => 'L',
982  // 'textkey' => 'yourLangKey', // if there is no label, yourLangKey will be translated to replace label
983  // 'label' => ' ', // the final label
984  'padding' => array(0.5, 0.5, 0.5, 0.5), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
985  ),
986  'content' => array(
987  'align' => 'L',
988  ),
989  );
990 
991  $rank = $rank + 10;
992  $this->cols['photo'] = array(
993  'rank' => $rank,
994  'width' => (empty($conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH) ? 20 : $conf->global->MAIN_DOCUMENTS_WITH_PICTURE_WIDTH), // in mm
995  'status' => false,
996  'title' => array(
997  'textkey' => 'Photo',
998  'label' => ' '
999  ),
1000  'content' => array(
1001  'padding' => array(0, 0, 0, 0), // Like css 0 => top , 1 => right, 2 => bottom, 3 => left
1002  ),
1003  'border-left' => false, // remove left line separator
1004  );
1005 
1006  if (!empty($conf->global->MAIN_GENERATE_DELIVERY_WITH_PICTURE) && !empty($this->atleastonephoto)) {
1007  $this->cols['photo']['status'] = true;
1008  }
1009 
1010 
1011  $rank = $rank + 10;
1012  $this->cols['Comments'] = array(
1013  'rank' => $rank,
1014  'width' => 50, // in mm
1015  'status' => true,
1016  'title' => array(
1017  'textkey' => 'Comments'
1018  ),
1019  'border-left' => true, // add left line separator
1020  );
1021 
1022  // $rank = $rank + 10;
1023  // $this->cols['weight'] = array(
1024  // 'rank' => $rank,
1025  // 'width' => 30, // in mm
1026  // 'status' => false,
1027  // 'title' => array(
1028  // 'textkey' => 'WeightVolShort'
1029  // ),
1030  // 'border-left' => true, // add left line separator
1031  // );
1032 
1033  $rank = $rank + 10;
1034  $this->cols['qty_shipped'] = array(
1035  'rank' => $rank,
1036  'width' => 20, // in mm
1037  'status' => true,
1038  'title' => array(
1039  'textkey' => 'QtyShippedShort'
1040  ),
1041  'border-left' => true, // add left line separator
1042  );
1043 
1044  $rank = $rank + 10;
1045  $this->cols['qty_remaining'] = array(
1046  'rank' => $rank,
1047  'width' => 20, // in mm
1048  'status' => 1,
1049  'title' => array(
1050  'textkey' => 'KeepToShipShort'
1051  ),
1052  'border-left' => true, // add left line separator
1053  );
1054 
1055 
1056  // Add extrafields cols
1057  if (!empty($object->lines)) {
1058  $line = reset($object->lines);
1059  $this->defineColumnExtrafield($line, $outputlangs, $hidedetails);
1060  }
1061 
1062  $parameters = array(
1063  'object' => $object,
1064  'outputlangs' => $outputlangs,
1065  'hidedetails' => $hidedetails,
1066  'hidedesc' => $hidedesc,
1067  'hideref' => $hideref
1068  );
1069 
1070  $reshook = $hookmanager->executeHooks('defineColumnField', $parameters, $this); // Note that $object may have been modified by hook
1071  if ($reshook < 0) {
1072  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1073  } elseif (empty($reshook)) {
1074  $this->cols = array_replace($this->cols, $hookmanager->resArray); // array_replace is used to preserve keys
1075  } else {
1076  $this->cols = $hookmanager->resArray;
1077  }
1078  }
1079 }
Class to manage customers orders.
prepareArrayColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Prepare Array Column Field.
getColumnStatus($colKey)
get column status from column key
printStdColumnContent($pdf, &$curY, $colKey, $columnText='')
print standard column content
pdfTabTitles(&$pdf, $tab_top, $tab_height, $outputlangs, $hidetop=0)
Print standard column content.
getColumnContentXStart($colKey)
get column content X (abscissa) left position from column key
printRect($pdf, $x, $y, $l, $h, $hidetop=0, $hidebottom=0)
Rect pdf.
getColumnContentWidth($colKey)
get column content width from column key
getExtrafieldContent($object, $extrafieldKey, $outputlangs=null)
get extrafield content for pdf writeHtmlCell compatibility usage for PDF line columns and object note...
defineColumnExtrafield($object, $outputlangs, $hidedetails=0)
Define Array Column Field for extrafields.
Class to manage shipments.
Class to manage hooks.
Classe mere des modeles de bon de livraison.
Class to manage products or services.
Class to build Delivery Order documents with storm model.
defineColumnField($object, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0)
Define Array Column Field.
_tableau_info(&$pdf, $object, $posy, $outputlangs)
Show miscellaneous information (payment mode, payment term, ...)
_tableau(&$pdf, $tab_top, $tab_height, $nexY, $outputlangs, $hidetop=0, $hidebottom=0)
Show table for lines.
__construct($db)
Constructor.
_pagehead(&$pdf, $object, $showaddress, $outputlangs)
Show top header of page.
_pagefoot(&$pdf, $object, $outputlangs, $hidefreetext=0)
Show footer of page.
write_file($object, $outputlangs, $srctemplatepath='', $hidedetails=0, $hidedesc=0, $hideref=0)
Function to build pdf onto disk.
print *****$script_file(".$version.") pid cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
if(!function_exists('utf8_encode')) if(!function_exists('utf8_decode')) getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
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...
isModEnabled($module)
Is Dolibarr module enabled.
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:2514
pdf_getPDFFontSize($outputlangs)
Return font size to use for PDF generation.
Definition: pdf.lib.php:288
pdf_getFormat(Translate $outputlangs=null, $mode='setup')
Return array with format properties of default PDF format.
Definition: pdf.lib.php:84
pdf_writelinedesc(&$pdf, $object, $i, $outputlangs, $w, $h, $posx, $posy, $hideref=0, $hidedesc=0, $issupplierline=0)
Output line description into PDF.
Definition: pdf.lib.php:1359
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:1001
pdf_pagehead(&$pdf, $outputlangs, $page_height)
Show header of page for PDF generation.
Definition: pdf.lib.php:723
pdf_writeLinkedObjects(&$pdf, $object, $outputlangs, $posx, $posy, $w, $h, $align, $default_font_size)
Show linked objects for PDF generation.
Definition: pdf.lib.php:1323
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 formated for output on documents.
Definition: pdf.lib.php:434
pdf_getInstance($format='', $metric='mm', $pagetype='P')
Return a PDF instance object.
Definition: pdf.lib.php:126
pdfBuildThirdpartyName($thirdparty, Translate $outputlangs, $includealias=0)
Returns the name of the thirdparty.
Definition: pdf.lib.php:386
pdf_watermark(&$pdf, $outputlangs, $h, $w, $unit, $text)
Add a draft watermark on PDF files.
Definition: pdf.lib.php:769
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:119
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:122
$conf db
API class for accounts.
Definition: inc.php:41