dolibarr  13.0.2
card.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (c) 2004-2019 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
6  * Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
7  * Copyright (C) 2019 Thibault FOUCART <support@ptibogxiv.net>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  */
22 
29 require '../../main.inc.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
31 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
32 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
36 
37 $WIDTH = DolGraph::getDefaultGraphSizeForStats('width', 380);
38 $HEIGHT = DolGraph::getDefaultGraphSizeForStats('height', 160);
39 
40 // Load translation files required by the page
41 $langs->loadLangs(array('companies', 'products', 'stocks', 'bills', 'other'));
42 
43 $id = GETPOST('id', 'int'); // For this page, id can also be 'all'
44 $ref = GETPOST('ref', 'alpha');
45 $mode = (GETPOST('mode', 'alpha') ? GETPOST('mode', 'alpha') : 'byunit');
46 $search_year = GETPOST('search_year', 'int');
47 $search_categ = GETPOST('search_categ', 'int');
48 
49 $error = 0;
50 $mesg = '';
51 $graphfiles = array();
52 
53 $socid = '';
54 if (!empty($user->socid)) $socid = $user->socid;
55 
56 // Security check
57 $fieldvalue = (!empty($id) ? $id : $ref);
58 $fieldtype = (!empty($ref) ? 'ref' : 'rowid');
59 $result = restrictedArea($user, 'produit|service', $fieldvalue, 'product&product', '', '', $fieldtype);
60 
61 $tmp = dol_getdate(dol_now());
62 $currentyear = $tmp['year'];
63 if (empty($search_year)) $search_year = $currentyear;
64 
65 
66 /*
67  * Actions
68  */
69 
70 // None
71 
72 
73 /*
74  * View
75  */
76 
77 $form = new Form($db);
78 $htmlother = new FormOther($db);
79 $object = new Product($db);
80 
81 if (!$id && empty($ref)) {
82  llxHeader("", $langs->trans("ProductStatistics"));
83 
84  $type = GETPOST('type', 'int');
85 
86  $helpurl = '';
87  if ($type == '0') {
88  $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
89  //$title=$langs->trans("StatisticsOfProducts");
90  $title = $langs->trans("Statistics");
91  } elseif ($type == '1') {
92  $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
93  //$title=$langs->trans("StatisticsOfServices");
94  $title = $langs->trans("Statistics");
95  } else {
96  $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
97  //$title=$langs->trans("StatisticsOfProductsOrServices");
98  $title = $langs->trans("Statistics");
99  }
100 
101  $picto = 'product';
102  if ($type == 1) $picto = 'service';
103 
104  print load_fiche_titre($title, $mesg, $picto);
105 } else {
106  $result = $object->fetch($id, $ref);
107 
108  $title = $langs->trans('ProductServiceCard');
109  $helpurl = '';
110  $shortlabel = dol_trunc($object->label, 16);
111  if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) {
112  $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('Statistics');
113  $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
114  }
115  if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) {
116  $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('Statistics');
117  $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
118  }
119 
120  llxHeader('', $title, $helpurl);
121 }
122 
123 
124 if ($result && (!empty($id) || !empty($ref))) {
125  $head = product_prepare_head($object);
126  $titre = $langs->trans("CardProduct".$object->type);
127  $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product');
128 
129  print dol_get_fiche_head($head, 'stats', $titre, -1, $picto);
130 
131  $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
132 
133  dol_banner_tab($object, 'ref', $linkback, ($user->socid ? 0 : 1), 'ref', '', '', '', 0, '', '', 1);
134 
136 }
137 if (empty($id) && empty($ref)) {
138  $h = 0;
139  $head = array();
140 
141  $head[$h][0] = DOL_URL_ROOT.'/product/stats/card.php'.($type != '' ? '?type='.$type : '');
142  $head[$h][1] = $langs->trans("Chart");
143  $head[$h][2] = 'chart';
144  $h++;
145 
146  $title = $langs->trans("ListProductServiceByPopularity");
147  if ((string) $type == '1') {
148  $title = $langs->trans("ListServiceByPopularity");
149  }
150  if ((string) $type == '0') {
151  $title = $langs->trans("ListProductByPopularity");
152  }
153 
154  $head[$h][0] = DOL_URL_ROOT.'/product/popuprop.php'.($type != '' ? '?type='.$type : '');
155  $head[$h][1] = $langs->trans("ProductsPerPopularity");
156  $head[$h][2] = 'popularity';
157  $h++;
158 
159  print dol_get_fiche_head($head, 'chart', $langs->trans("Statistics"), -1);
160 }
161 
162 
163 if ($result || empty($id)) {
164  print '<form name="stats" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
165  print '<input type="hidden" name="token" value="'.newToken().'">';
166  print '<input type="hidden" name="id" value="'.$id.'">';
167 
168  print '<table class="noborder centpercent">';
169  print '<tr class="liste_titre"><td class="liste_titre" colspan="2">'.$langs->trans("Filter").'</td></tr>';
170 
171  if (empty($id)) {
172  // Type
173  print '<tr><td class="titlefield">'.$langs->trans("ProductsAndServices").'</td><td>';
174  $array = array('-1'=>'&nbsp;', '0'=>$langs->trans('Product'), '1'=>$langs->trans('Service'));
175  print $form->selectarray('type', $array, $type);
176  print '</td></tr>';
177 
178  // Tag
179  if ($conf->categorie->enabled) {
180  print '<tr><td class="titlefield">'.$langs->trans("Categories").'</td><td>';
181  //$moreforfilter.='<div class="divsearchfield">';
182  $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1);
183  //$moreforfilter.='</div>';
184  print $moreforfilter;
185  print '</td></tr>';
186  }
187  }
188 
189  // Year
190  print '<tr><td class="titlefield">'.$langs->trans("Year").'</td><td>';
191  $arrayyears = array();
192  for ($year = $currentyear - 25; $year < $currentyear; $year++)
193  {
194  $arrayyears[$year] = $year;
195  }
196  if (!in_array($year, $arrayyears)) $arrayyears[$year] = $year;
197  if (!in_array($currentyear, $arrayyears)) $arrayyears[$currentyear] = $currentyear;
198  arsort($arrayyears);
199  print $form->selectarray('search_year', $arrayyears, $search_year, 1);
200  print '</td></tr>';
201  print '</table>';
202  print '<div class="center"><input type="submit" name="submit" class="button" value="'.$langs->trans("Refresh").'"></div>';
203  print '</form>';
204 
205  print '<br>';
206 
207 
208  // Choice of stats mode (byunit or bynumber)
209  if (!empty($conf->dol_use_jmobile)) print "\n".'<div class="fichecenter"><div class="nowrap">'."\n";
210 
211  if ($mode == 'bynumber') print '<a class="a-mesure-disabled" href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id') ?GETPOST('id') : $object->id).($type != '' ? '&type='.$type : '').'&mode=byunit&search_year='.$search_year.'">';
212  else print '<span class="a-mesure">';
213  print $langs->trans("StatsByNumberOfUnits");
214  if ($mode == 'bynumber') print '</a>';
215  else print '</span>';
216 
217  if (!empty($conf->dol_use_jmobile)) print '</div>'."\n".'<div class="nowrap">'."\n";
218  else print ' &nbsp; ';
219 
220  if ($mode == 'byunit') print '<a class="a-mesure-disabled" href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id') ?GETPOST('id') : $object->id).($type != '' ? '&type='.$type : '').'&mode=bynumber&search_year='.$search_year.'">';
221  else print '<span class="a-mesure">';
222  print $langs->trans("StatsByNumberOfEntities");
223  if ($mode == 'byunit') print '</a>';
224  else print '</span>';
225 
226  if (!empty($conf->dol_use_jmobile)) print '</div></div>';
227  else print '<br>';
228  print '<br>';
229 
230  //print '<table width="100%">';
231 
232  // Generation des graphs
233  $dir = (!empty($conf->product->multidir_temp[$object->entity]) ? $conf->product->multidir_temp[$object->entity] : $conf->service->multidir_temp[$object->entity]);
234  if ($object->id > 0) { // We are on statistics for a dedicated product
235  if (!file_exists($dir.'/'.$object->id)) {
236  if (dol_mkdir($dir.'/'.$object->id) < 0) {
237  $mesg = $langs->trans("ErrorCanNotCreateDir", $dir);
238  $error++;
239  }
240  }
241  }
242 
243  if ($conf->propal->enabled) {
244  $graphfiles['propal'] = array('modulepart'=>'productstats_proposals',
245  'file' => $object->id.'/propal12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
246  'label' => ($mode == 'byunit' ? $langs->transnoentitiesnoconv("NumberOfUnitsProposals") : $langs->transnoentitiesnoconv("NumberOfProposals")));
247  }
248 
249  if ($conf->supplier_proposal->enabled) {
250  $graphfiles['proposalssuppliers'] = array('modulepart'=>'productstats_proposalssuppliers',
251  'file' => $object->id.'/proposalssuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
252  'label' => ($mode == 'byunit' ? $langs->transnoentitiesnoconv("NumberOfUnitsSupplierProposals") : $langs->transnoentitiesnoconv("NumberOfSupplierProposals")));
253  }
254 
255  if ($conf->order->enabled) {
256  $graphfiles['orders'] = array('modulepart'=>'productstats_orders',
257  'file' => $object->id.'/orders12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
258  'label' => ($mode == 'byunit' ? $langs->transnoentitiesnoconv("NumberOfUnitsCustomerOrders") : $langs->transnoentitiesnoconv("NumberOfCustomerOrders")));
259  }
260 
261  if ($conf->supplier_order->enabled) {
262  $graphfiles['orderssuppliers'] = array('modulepart'=>'productstats_orderssuppliers',
263  'file' => $object->id.'/orderssuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
264  'label' => ($mode == 'byunit' ? $langs->transnoentitiesnoconv("NumberOfUnitsSupplierOrders") : $langs->transnoentitiesnoconv("NumberOfSupplierOrders")));
265  }
266 
267  if ($conf->facture->enabled) {
268  $graphfiles['invoices'] = array('modulepart'=>'productstats_invoices',
269  'file' => $object->id.'/invoices12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
270  'label' => ($mode == 'byunit' ? $langs->transnoentitiesnoconv("NumberOfUnitsCustomerInvoices") : $langs->transnoentitiesnoconv("NumberOfCustomerInvoices")));
271  }
272 
273  if ($conf->supplier_invoice->enabled) {
274  $graphfiles['invoicessuppliers'] = array('modulepart'=>'productstats_invoicessuppliers',
275  'file' => $object->id.'/invoicessuppliers12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
276  'label' => ($mode == 'byunit' ? $langs->transnoentitiesnoconv("NumberOfUnitsSupplierInvoices") : $langs->transnoentitiesnoconv("NumberOfSupplierInvoices")));
277  }
278 
279  if ($conf->contrat->enabled) {
280  $graphfiles['contracts'] = array('modulepart'=>'productstats_contracts',
281  'file' => $object->id.'/contracts12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
282  'label' => ($mode == 'byunit' ? $langs->transnoentitiesnoconv("NumberOfUnitsContracts") : $langs->transnoentitiesnoconv("NumberOfContracts")));
283  }
284 
285  if ($conf->mrp->enabled) {
286  $graphfiles['mrp'] = array('modulepart'=>'productstats_mrp',
287  'file' => $object->id.'/mos12m'.((string) $type != '' ? '_type'.$type : '').'_'.$mode.($search_year > 0 ? '_year'.$search_year : '').'.png',
288  'label' => ($mode == 'byunit' ? $langs->transnoentitiesnoconv("NumberOfUnitsMos") : $langs->transnoentitiesnoconv("NumberOfMos")));
289  }
290 
291  $px = new DolGraph();
292 
293  if (!$error && count($graphfiles) > 0) {
294  $mesg = $px->isGraphKo();
295  if (!$mesg) {
296  foreach ($graphfiles as $key => $val) {
297  if (!$graphfiles[$key]['file']) continue;
298 
299  $graph_data = array();
300 
301  if (dol_is_file($dir.'/'.$graphfiles[$key]['file'])) {
302  // TODO Load cachefile $graphfiles[$key]['file']
303  } else {
304  $morefilters = '';
305  if ($search_categ > 0) {
306  $categ = new Categorie($db);
307  $categ->fetch($search_categ);
308  $listofprodids = $categ->getObjectsInCateg('product', 1);
309  $morefilters = ' AND d.fk_product IN ('.((is_array($listofprodids) && count($listofprodids)) ? join(',', $listofprodids) : '0').')';
310  }
311  if ($search_categ == -2) {
312  $morefilters = ' AND d.fk_product NOT IN (SELECT cp.fk_product from '.MAIN_DB_PREFIX.'categorie_product as cp)';
313  }
314 
315  if ($key == 'propal') $graph_data = $object->get_nb_propal($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
316  if ($key == 'orders') $graph_data = $object->get_nb_order($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
317  if ($key == 'invoices') $graph_data = $object->get_nb_vente($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
318  if ($key == 'proposalssuppliers') $graph_data = $object->get_nb_propalsupplier($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
319  if ($key == 'invoicessuppliers') $graph_data = $object->get_nb_achat($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
320  if ($key == 'orderssuppliers') $graph_data = $object->get_nb_ordersupplier($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
321  if ($key == 'contracts') $graph_data = $object->get_nb_contract($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
322  if ($key == 'mrp') $graph_data = $object->get_nb_mos($socid, $mode, ((string) $type != '' ? $type : -1), $search_year, $morefilters);
323 
324  // TODO Save cachefile $graphfiles[$key]['file']
325  }
326 
327  if (is_array($graph_data)) {
328  $px->SetData($graph_data);
329  $px->SetYLabel($graphfiles[$key]['label']);
330  $px->SetMaxValue($px->GetCeilMaxValue() < 0 ? 0 : $px->GetCeilMaxValue());
331  $px->SetMinValue($px->GetFloorMinValue() > 0 ? 0 : $px->GetFloorMinValue());
332  $px->setShowLegend(0);
333  $px->SetWidth($WIDTH);
334  $px->SetHeight($HEIGHT);
335  $px->SetHorizTickIncrement(1);
336  $px->SetShading(3);
337  //print 'x '.$key.' '.$graphfiles[$key]['file'];
338 
339  $url = DOL_URL_ROOT.'/viewimage.php?modulepart='.$graphfiles[$key]['modulepart'].'&entity='.$object->entity.'&file='.urlencode($graphfiles[$key]['file']);
340  $px->draw($dir."/".$graphfiles[$key]['file'], $url);
341 
342  $graphfiles[$key]['total'] = $px->total();
343  $graphfiles[$key]['output'] = $px->show();
344  } else {
345  dol_print_error($db, 'Error for calculating graph on key='.$key.' - '.$object->error);
346  }
347  }
348 
349  //setEventMessages($langs->trans("ChartGenerated"), null, 'mesgs');
350  }
351  }
352 
353  // Show graphs
354  $i = 0;
355  if (count($graphfiles) > 0) {
356  foreach ($graphfiles as $key => $val) {
357  if (!$graphfiles[$key]['file']) continue;
358 
359  if ($graphfiles == 'propal' && !$user->rights->propale->lire) continue;
360  if ($graphfiles == 'order' && !$user->rights->commande->lire) continue;
361  if ($graphfiles == 'invoices' && !$user->rights->facture->lire) continue;
362  if ($graphfiles == 'proposals_suppliers' && !$user->rights->supplier_proposal->lire) continue;
363  if ($graphfiles == 'invoices_suppliers' && !$user->rights->fournisseur->facture->lire) continue;
364  if ($graphfiles == 'orders_suppliers' && !$user->rights->fournisseur->commande->lire) continue;
365  if ($graphfiles == 'mrp' && empty($user->rights->mrp->mo->read)) continue;
366 
367 
368  if ($i % 2 == 0) {
369  print "\n".'<div class="fichecenter"><div class="fichehalfleft">'."\n";
370  } else {
371  print "\n".'<div class="fichehalfright"><div class="ficheaddleft">'."\n";
372  }
373 
374  // Date generation
375  if ($graphfiles[$key]['output'] && !$px->isGraphKo()) {
376  if (file_exists($dir."/".$graphfiles[$key]['file']) && filemtime($dir."/".$graphfiles[$key]['file'])) $dategenerated = $langs->trans("GeneratedOn", dol_print_date(filemtime($dir."/".$graphfiles[$key]['file']), "dayhour"));
377  else $dategenerated = $langs->trans("GeneratedOn", dol_print_date(dol_now(), "dayhour"));
378  } else {
379  $dategenerated = ($mesg ? '<font class="error">'.$mesg.'</font>' : $langs->trans("ChartNotGenerated"));
380  }
381  $linktoregenerate = '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.(GETPOST('id') ?GETPOST('id') : $object->id).((string) $type != '' ? '&type='.$type : '').'&action=recalcul&mode='.$mode.'&search_year='.$search_year.'&search_categ='.$search_categ.'">'.img_picto($langs->trans("ReCalculate").' ('.$dategenerated.')', 'refresh').'</a>';
382 
383  // Show graph
384  print '<table class="noborder centpercent">';
385  // Label
386  print '<tr class="liste_titre"><td>';
387  print $graphfiles[$key]['label'];
388  print ' <span class="opacitymedium">('.$graphfiles[$key]['total'].')</span></td>';
389  print '<td align="right">'.$linktoregenerate.'</td>';
390  print '</tr>';
391  // Image
392  print '<tr class="impair"><td colspan="2" class="nohover" align="center">';
393  print $graphfiles[$key]['output'];
394  print '</td></tr>';
395  print '</table>';
396 
397  if ($i % 2 == 0) {
398  print "\n".'</div>'."\n";
399  } else {
400  print "\n".'</div></div></div>';
401  print '<div class="clear"><div class="fichecenter"><br></div></div>'."\n";
402  }
403 
404  $i++;
405  }
406  }
407  // div not closed
408  if ($i % 2 == 1) {
409  print "\n".'<div class="fichehalfright"><div class="ficheaddleft">'."\n";
410  print "\n".'</div></div></div>';
411  print '<div class="clear"><div class="fichecenter"><br></div></div>'."\n";
412  }
413 }
414 
415 if (!$id) {
417 }
418 
419 // End of page
420 llxFooter();
421 $db->close();
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Class to manage products or services.
dol_now($mode= 'auto')
Return date for now.
const TYPE_SERVICE
Service.
const TYPE_PRODUCT
Regular product.
llxHeader()
Empty header.
Definition: wrapper.php:45
Class to manage generation of HTML components Only common components must be here.
Class to manage categories.
load_fiche_titre($titre, $morehtmlright= '', $picto= 'generic', $pictoisfullpath=0, $id= '', $morecssontable= '', $morehtmlcenter= '')
Load a title with picto.
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
Classe permettant la generation de composants html autre Only common components are here...
dol_getdate($timestamp, $fast=false, $forcetimezone= '')
Return an array with locale date info.
restrictedArea($user, $features, $objectid=0, $tableandshare= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid', $isdraft=0)
Check permissions of a user to show a page and an object.
dol_is_file($pathoffile)
Return if path is a file.
Definition: files.lib.php:457
dol_get_fiche_head($links=array(), $active= '', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tabs of a record.
print
Draft customers invoices.
Definition: index.php:89
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
Class to build graphs.
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_get_fiche_end($notab=0)
Return tab footer of a card.
static getDefaultGraphSizeForStats($direction, $defaultsize= '')
getDefaultGraphSizeForStats
dol_trunc($string, $size=40, $trunc= 'right', $stringencoding= 'UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding &#39;...&#39; if string larger than length.
dol_banner_tab($object, $paramid, $morehtml= '', $shownav=1, $fieldid= 'rowid', $fieldref= 'ref', $morehtmlref= '', $moreparam= '', $nodbprefix=0, $morehtmlleft= '', $morehtmlstatus= '', $onlybanner=0, $morehtmlright= '')
Show tab footer of a card.
llxFooter()
Empty footer.
Definition: wrapper.php:59
product_prepare_head($object)
Prepare array with list of tabs.
Definition: product.lib.php:35
dol_mkdir($dir, $dataroot= '', $newmask=null)
Creation of a directory (this can create recursive subdir)