dolibarr  9.0.0
product.lib.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2006-2015 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
4  * Copyright (C) 2009-2010 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
6  * Copyright (C) 2015-2016 Marcos García <marcosgdf@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  * or see http://www.gnu.org/
21  */
22 
35 function product_prepare_head($object)
36 {
37  global $db, $langs, $conf, $user;
38  $langs->load("products");
39 
40  $h = 0;
41  $head = array();
42 
43  $head[$h][0] = DOL_URL_ROOT."/product/card.php?id=".$object->id;
44  $head[$h][1] = $langs->trans("Card");
45  $head[$h][2] = 'card';
46  $h++;
47 
48  if (! empty($object->status))
49  {
50  $head[$h][0] = DOL_URL_ROOT."/product/price.php?id=".$object->id;
51  $head[$h][1] = $langs->trans("SellingPrices");
52  $head[$h][2] = 'price';
53  $h++;
54  }
55 
56  if (! empty($object->status_buy) || (! empty($conf->margin->enabled) && ! empty($object->status))) // If margin is on and product on sell, we may need the cost price even if product os not on purchase
57  {
58  if ((! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->lire)
59  || (! empty($conf->margin->enabled) && $user->rights->margin->liretous)
60  )
61  {
62  $head[$h][0] = DOL_URL_ROOT."/product/fournisseurs.php?id=".$object->id;
63  $head[$h][1] = $langs->trans("BuyingPrices");
64  $head[$h][2] = 'suppliers';
65  $h++;
66  }
67  }
68 
69  // Multilangs
70  if (! empty($conf->global->MAIN_MULTILANGS))
71  {
72  $head[$h][0] = DOL_URL_ROOT."/product/traduction.php?id=".$object->id;
73  $head[$h][1] = $langs->trans("Translation");
74  $head[$h][2] = 'translation';
75  $h++;
76  }
77 
78  // Sub products
79  if (! empty($conf->global->PRODUIT_SOUSPRODUITS))
80  {
81  $head[$h][0] = DOL_URL_ROOT."/product/composition/card.php?id=".$object->id;
82  $head[$h][1] = $langs->trans('AssociatedProducts');
83 
84  $nbFatherAndChild = $object->hasFatherOrChild();
85  if ($nbFatherAndChild > 0) $head[$h][1].= ' <span class="badge">'.$nbFatherAndChild.'</span>';
86  $head[$h][2] = 'subproduct';
87  $h++;
88  }
89 
90  $head[$h][0] = DOL_URL_ROOT."/product/stats/card.php?id=".$object->id;
91  $head[$h][1] = $langs->trans('Statistics');
92  $head[$h][2] = 'stats';
93  $h++;
94 
95  $head[$h][0] = DOL_URL_ROOT."/product/stats/facture.php?showmessage=1&id=".$object->id;
96  $head[$h][1] = $langs->trans('Referers');
97  $head[$h][2] = 'referers';
98  $h++;
99 
100  if (!empty($conf->variants->enabled) && ($object->isProduct() || $object->isService())) {
101 
102  global $db;
103 
104  require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
105 
106  $prodcomb = new ProductCombination($db);
107 
108  if ($prodcomb->fetchByFkProductChild($object->id) == -1)
109  {
110  $head[$h][0] = DOL_URL_ROOT."/variants/combinations.php?id=".$object->id;
111  $head[$h][1] = $langs->trans('ProductCombinations');
112  $head[$h][2] = 'combinations';
113  $nbVariant = $prodcomb->countNbOfCombinationForFkProductParent($object->id);
114  if ($nbVariant > 0) $head[$h][1].= ' <span class="badge">'.$nbVariant.'</span>';
115  }
116 
117  $h++;
118  }
119 
120  if ($object->isProduct() || ($object->isService() && ! empty($conf->global->STOCK_SUPPORTS_SERVICES))) // If physical product we can stock (or service with option)
121  {
122  if (! empty($conf->stock->enabled) && $user->rights->stock->lire)
123  {
124  $head[$h][0] = DOL_URL_ROOT."/product/stock/product.php?id=".$object->id;
125  $head[$h][1] = $langs->trans("Stock");
126  $head[$h][2] = 'stock';
127  $h++;
128  }
129  }
130 
131  // Show more tabs from modules
132  // Entries must be declared in modules descriptor with line
133  // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
134  // $this->tabs = array('entity:-tabname); to remove a tab
135  complete_head_from_modules($conf,$langs,$object,$head,$h,'product');
136 
137  // Notes
138  if (empty($conf->global->MAIN_DISABLE_NOTES_TAB))
139  {
140  $nbNote = 0;
141  if(!empty($object->note_private)) $nbNote++;
142  if(!empty($object->note_public)) $nbNote++;
143  $head[$h][0] = DOL_URL_ROOT.'/product/note.php?id='.$object->id;
144  $head[$h][1] = $langs->trans('Notes');
145  if ($nbNote > 0) $head[$h][1].= ' <span class="badge">'.$nbNote.'</span>';
146  $head[$h][2] = 'note';
147  $h++;
148  }
149 
150  // Attachments
151  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
152  require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
153  if (! empty($conf->product->enabled) && ($object->type==Product::TYPE_PRODUCT)) $upload_dir = $conf->product->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
154  if (! empty($conf->service->enabled) && ($object->type==Product::TYPE_SERVICE)) $upload_dir = $conf->service->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
155  $nbFiles = count(dol_dir_list($upload_dir,'files',0,'','(\.meta|_preview.*\.png)$'));
156  if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) {
157  if (! empty($conf->product->enabled) && ($object->type==Product::TYPE_PRODUCT)) $upload_dir = $conf->produit->multidir_output[$object->entity].'/'.get_exdir($object->id,2,0,0,$object,'product').$object->id.'/photos';
158  if (! empty($conf->service->enabled) && ($object->type==Product::TYPE_SERVICE)) $upload_dir = $conf->service->multidir_output[$object->entity].'/'.get_exdir($object->id,2,0,0,$object,'product').$object->id.'/photos';
159  $nbFiles += count(dol_dir_list($upload_dir,'files',0,'','(\.meta|_preview.*\.png)$'));
160  }
161  $nbLinks=Link::count($db, $object->element, $object->id);
162  $head[$h][0] = DOL_URL_ROOT.'/product/document.php?id='.$object->id;
163  $head[$h][1] = $langs->trans('Documents');
164  if (($nbFiles+$nbLinks) > 0) $head[$h][1].= ' <span class="badge">'.($nbFiles+$nbLinks).'</span>';
165  $head[$h][2] = 'documents';
166  $h++;
167 
168  complete_head_from_modules($conf,$langs,$object,$head,$h,'product', 'remove');
169 
170  // Log
171  $head[$h][0] = DOL_URL_ROOT.'/product/agenda.php?id='.$object->id;
172  $head[$h][1] = $langs->trans("Events");
173  if (! empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read) ))
174  {
175  $head[$h][1].= '/';
176  $head[$h][1].= $langs->trans("Agenda");
177  }
178  $head[$h][2] = 'agenda';
179  $h++;
180 
181  return $head;
182 }
183 
190 function productlot_prepare_head($object)
191 {
192  global $db, $langs, $conf, $user;
193 
194  // Load translation files required by the page
195  $langs->loadLangs(array("products","productbatch"));
196 
197  $h = 0;
198  $head = array();
199 
200  $head[$h][0] = DOL_URL_ROOT."/product/stock/productlot_card.php?id=".$object->id;
201  $head[$h][1] = $langs->trans("Card");
202  $head[$h][2] = 'card';
203  $h++;
204 
205  // Attachments
206  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
207  require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
208  $upload_dir = $conf->productbatch->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
209  $nbFiles = count(dol_dir_list($upload_dir,'files',0,'','(\.meta|_preview.*\.png)$'));
210  $nbLinks=Link::count($db, $object->element, $object->id);
211  $head[$h][0] = DOL_URL_ROOT."/product/stock/productlot_document.php?id=".$object->id;
212  $head[$h][1] = $langs->trans("Documents");
213  if (($nbFiles+$nbLinks) > 0) $head[$h][1].= ' <span class="badge">'.($nbFiles+$nbLinks).'</span>';
214  $head[$h][2] = 'documents';
215  $h++;
216 
217  // Show more tabs from modules
218  // Entries must be declared in modules descriptor with line
219  // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
220  // $this->tabs = array('entity:-tabname); to remove a tab
221  complete_head_from_modules($conf,$langs,$object,$head,$h,'productlot');
222 
223  complete_head_from_modules($conf,$langs,$object,$head,$h,'productlot', 'remove');
224 
225  // Log
226  /*
227  $head[$h][0] = DOL_URL_ROOT.'/product/info.php?id='.$object->id;
228  $head[$h][1] = $langs->trans("Info");
229  $head[$h][2] = 'info';
230  $h++;
231  */
232 
233  return $head;
234 }
235 
236 
237 
244 {
245  global $langs, $conf, $user;
246 
247  $h = 0;
248  $head = array();
249 
250  $head[$h][0] = DOL_URL_ROOT."/product/admin/product.php";
251  $head[$h][1] = $langs->trans('Parameters');
252  $head[$h][2] = 'general';
253  $h++;
254 
255  if (!empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($conf->global->PRODUIT_MULTIPRICES_ALLOW_AUTOCALC_PRICELEVEL))
256  {
257  $head[$h] = array(
258  0 => DOL_URL_ROOT."/product/admin/price_rules.php",
259  1 => $langs->trans('MultipriceRules'),
260  2 => 'generator'
261  );
262  $h++;
263  }
264 
265  // Show more tabs from modules
266  // Entries must be declared in modules descriptor with line
267  // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
268  // $this->tabs = array('entity:-tabname); to remove a tab
269  complete_head_from_modules($conf,$langs,null,$head,$h,'product_admin');
270 
271  $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_extrafields.php';
272  $head[$h][1] = $langs->trans("ExtraFields");
273  $head[$h][2] = 'attributes';
274  $h++;
275 
276  complete_head_from_modules($conf,$langs,null,$head,$h,'product_admin','remove');
277 
278  return $head;
279 }
280 
281 
282 
289 {
290  global $langs, $conf, $user;
291 
292  $h = 0;
293  $head = array();
294 
295  // Show more tabs from modules
296  // Entries must be declared in modules descriptor with line
297  // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
298  // $this->tabs = array('entity:-tabname); to remove a tab
299  complete_head_from_modules($conf,$langs,null,$head,$h,'product_lot_admin');
300 
301  $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_lot_extrafields.php';
302  $head[$h][1] = $langs->trans("ExtraFields");
303  $head[$h][2] = 'attributes';
304  $h++;
305 
306  complete_head_from_modules($conf,$langs,null,$head,$h,'product_lot_admin','remove');
307 
308  return $head;
309 }
310 
311 
312 
320 function show_stats_for_company($product,$socid)
321 {
322  global $conf,$langs,$user,$db;
323 
324  $nblines = 0;
325 
326  print '<tr class="liste_titre">';
327  print '<td align="left" width="25%">'.$langs->trans("Referers").'</td>';
328  print '<td align="right" width="25%">'.$langs->trans("NbOfThirdParties").'</td>';
329  print '<td align="right" width="25%">'.$langs->trans("NbOfObjectReferers").'</td>';
330  print '<td align="right" width="25%">'.$langs->trans("TotalQuantity").'</td>';
331  print '</tr>';
332 
333  // Customer proposals
334  if (! empty($conf->propal->enabled) && $user->rights->propale->lire)
335  {
336  $nblines++;
337  $ret=$product->load_stats_propale($socid);
338  if ($ret < 0) dol_print_error($db);
339  $langs->load("propal");
340  print '<tr><td>';
341  print '<a href="propal.php?id='.$product->id.'">'.img_object('','propal').' '.$langs->trans("Proposals").'</a>';
342  print '</td><td align="right">';
343  print $product->stats_propale['customers'];
344  print '</td><td align="right">';
345  print $product->stats_propale['nb'];
346  print '</td><td align="right">';
347  print $product->stats_propale['qty'];
348  print '</td>';
349  print '</tr>';
350  }
351  // Supplier proposals
352  if (! empty($conf->supplier_proposal->enabled) && $user->rights->supplier_proposal->lire)
353  {
354  $nblines++;
355  $ret=$product->load_stats_proposal_supplier($socid);
356  if ($ret < 0) dol_print_error($db);
357  $langs->load("propal");
358  print '<tr><td>';
359  print '<a href="supplier_proposal.php?id='.$product->id.'">'.img_object('','propal').' '.$langs->trans("SupplierProposals").'</a>';
360  print '</td><td align="right">';
361  print $product->stats_proposal_supplier['suppliers'];
362  print '</td><td align="right">';
363  print $product->stats_proposal_supplier['nb'];
364  print '</td><td align="right">';
365  print $product->stats_proposal_supplier['qty'];
366  print '</td>';
367  print '</tr>';
368  }
369  // Customer orders
370  if (! empty($conf->commande->enabled) && $user->rights->commande->lire)
371  {
372  $nblines++;
373  $ret=$product->load_stats_commande($socid);
374  if ($ret < 0) dol_print_error($db);
375  $langs->load("orders");
376  print '<tr><td>';
377  print '<a href="commande.php?id='.$product->id.'">'.img_object('','order').' '.$langs->trans("CustomersOrders").'</a>';
378  print '</td><td align="right">';
379  print $product->stats_commande['customers'];
380  print '</td><td align="right">';
381  print $product->stats_commande['nb'];
382  print '</td><td align="right">';
383  print $product->stats_commande['qty'];
384  print '</td>';
385  print '</tr>';
386  }
387  // Supplier orders
388  if (! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->commande->lire)
389  {
390  $nblines++;
391  $ret=$product->load_stats_commande_fournisseur($socid);
392  if ($ret < 0) dol_print_error($db);
393  $langs->load("orders");
394  print '<tr><td>';
395  print '<a href="commande_fournisseur.php?id='.$product->id.'">'.img_object('','order').' '.$langs->trans("SuppliersOrders").'</a>';
396  print '</td><td align="right">';
397  print $product->stats_commande_fournisseur['suppliers'];
398  print '</td><td align="right">';
399  print $product->stats_commande_fournisseur['nb'];
400  print '</td><td align="right">';
401  print $product->stats_commande_fournisseur['qty'];
402  print '</td>';
403  print '</tr>';
404  }
405  // Customer invoices
406  if (! empty($conf->facture->enabled) && $user->rights->facture->lire)
407  {
408  $nblines++;
409  $ret=$product->load_stats_facture($socid);
410  if ($ret < 0) dol_print_error($db);
411  $langs->load("bills");
412  print '<tr><td>';
413  print '<a href="facture.php?id='.$product->id.'">'.img_object('','bill').' '.$langs->trans("CustomersInvoices").'</a>';
414  print '</td><td align="right">';
415  print $product->stats_facture['customers'];
416  print '</td><td align="right">';
417  print $product->stats_facture['nb'];
418  print '</td><td align="right">';
419  print $product->stats_facture['qty'];
420  print '</td>';
421  print '</tr>';
422  }
423  // Supplier invoices
424  if (! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire)
425  {
426  $nblines++;
427  $ret=$product->load_stats_facture_fournisseur($socid);
428  if ($ret < 0) dol_print_error($db);
429  $langs->load("bills");
430  print '<tr><td>';
431  print '<a href="facture_fournisseur.php?id='.$product->id.'">'.img_object('','bill').' '.$langs->trans("SuppliersInvoices").'</a>';
432  print '</td><td align="right">';
433  print $product->stats_facture_fournisseur['suppliers'];
434  print '</td><td align="right">';
435  print $product->stats_facture_fournisseur['nb'];
436  print '</td><td align="right">';
437  print $product->stats_facture_fournisseur['qty'];
438  print '</td>';
439  print '</tr>';
440  }
441 
442  // Contracts
443  if (! empty($conf->contrat->enabled) && $user->rights->contrat->lire)
444  {
445  $nblines++;
446  $ret=$product->load_stats_contrat($socid);
447  if ($ret < 0) dol_print_error($db);
448  $langs->load("contracts");
449  print '<tr><td>';
450  print '<a href="contrat.php?id='.$product->id.'">'.img_object('','contract').' '.$langs->trans("Contracts").'</a>';
451  print '</td><td align="right">';
452  print $product->stats_contrat['customers'];
453  print '</td><td align="right">';
454  print $product->stats_contrat['nb'];
455  print '</td><td align="right">';
456  print $product->stats_contrat['qty'];
457  print '</td>';
458  print '</tr>';
459  }
460 
461  return $nblines++;
462 }
463 
464 
473 function measuring_units_string($unit,$measuring_style='')
474 {
475  global $langs;
476 
477  $measuring_units=array();
478  if ($measuring_style == 'weight')
479  {
480  $measuring_units[3] = $langs->transnoentitiesnoconv("WeightUnitton");
481  $measuring_units[0] = $langs->transnoentitiesnoconv("WeightUnitkg");
482  $measuring_units[-3] = $langs->transnoentitiesnoconv("WeightUnitg");
483  $measuring_units[-6] = $langs->transnoentitiesnoconv("WeightUnitmg");
484  $measuring_units[98] = $langs->transnoentitiesnoconv("WeightUnitounce");
485  $measuring_units[99] = $langs->transnoentitiesnoconv("WeightUnitpound");
486  }
487  else if ($measuring_style == 'size')
488  {
489  $measuring_units[0] = $langs->transnoentitiesnoconv("SizeUnitm");
490  $measuring_units[-1] = $langs->transnoentitiesnoconv("SizeUnitdm");
491  $measuring_units[-2] = $langs->transnoentitiesnoconv("SizeUnitcm");
492  $measuring_units[-3] = $langs->transnoentitiesnoconv("SizeUnitmm");
493  $measuring_units[98] = $langs->transnoentitiesnoconv("SizeUnitfoot");
494  $measuring_units[99] = $langs->transnoentitiesnoconv("SizeUnitinch");
495  }
496  else if ($measuring_style == 'surface')
497  {
498  $measuring_units[0] = $langs->transnoentitiesnoconv("SurfaceUnitm2");
499  $measuring_units[-2] = $langs->transnoentitiesnoconv("SurfaceUnitdm2");
500  $measuring_units[-4] = $langs->transnoentitiesnoconv("SurfaceUnitcm2");
501  $measuring_units[-6] = $langs->transnoentitiesnoconv("SurfaceUnitmm2");
502  $measuring_units[98] = $langs->transnoentitiesnoconv("SurfaceUnitfoot2");
503  $measuring_units[99] = $langs->transnoentitiesnoconv("SurfaceUnitinch2");
504  }
505  else if ($measuring_style == 'volume')
506  {
507  $measuring_units[0] = $langs->transnoentitiesnoconv("VolumeUnitm3");
508  $measuring_units[-3] = $langs->transnoentitiesnoconv("VolumeUnitdm3");
509  $measuring_units[-6] = $langs->transnoentitiesnoconv("VolumeUnitcm3");
510  $measuring_units[-9] = $langs->transnoentitiesnoconv("VolumeUnitmm3");
511  $measuring_units[88] = $langs->transnoentitiesnoconv("VolumeUnitfoot3");
512  $measuring_units[89] = $langs->transnoentitiesnoconv("VolumeUnitinch3");
513  $measuring_units[97] = $langs->transnoentitiesnoconv("VolumeUnitounce");
514  $measuring_units[98] = $langs->transnoentitiesnoconv("VolumeUnitlitre");
515  $measuring_units[99] = $langs->transnoentitiesnoconv("VolumeUnitgallon");
516  }
517 
518  return $measuring_units[$unit];
519 }
520 
528 function measuring_units_squared($unit)
529 {
530  $measuring_units=array();
531  $measuring_units[0] = 0; // m -> m3
532  $measuring_units[-1] = -2; // dm-> dm2
533  $measuring_units[-2] = -4; // cm -> cm2
534  $measuring_units[-3] = -6; // mm -> mm2
535  $measuring_units[98] = 98; // foot -> foot2
536  $measuring_units[99] = 99; // inch -> inch2
537  return $measuring_units[$unit];
538 }
539 
540 
548 function measuring_units_cubed($unit)
549 {
550  $measuring_units=array();
551  $measuring_units[0] = 0; // m -> m2
552  $measuring_units[-1] = -3; // dm-> dm3
553  $measuring_units[-2] = -6; // cm -> cm3
554  $measuring_units[-3] = -9; // mm -> mm3
555  $measuring_units[98] = 88; // foot -> foot3
556  $measuring_units[99] = 89; // inch -> inch3
557  return $measuring_units[$unit];
558 }
print
Draft customers invoices.
Definition: index.php:91
product_lot_admin_prepare_head()
Return array head with list of tabs to view object informations.
productlot_prepare_head($object)
Prepare array with list of tabs.
complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode='add')
Complete or removed entries into a head array (used to build tabs).
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart)
Return a path to have a the directory according to object where files are stored. ...
const TYPE_SERVICE
Service.
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
const TYPE_PRODUCT
Regular product.
show_stats_for_company($product, $socid)
Show stats for company.
measuring_units_squared($unit)
Transform a given unit into the square of that unit, if known.
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:59
Class ProductCombination Used to represent a product combination.
measuring_units_cubed($unit)
Transform a given unit into the cube of that unit, if known.
product_admin_prepare_head()
Return array head with list of tabs to view object informations.
measuring_units_string($unit, $measuring_style='')
Return translation label of a unit key.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
product_prepare_head($object)
Prepare array with list of tabs.
Definition: product.lib.php:35