dolibarr  18.0.0
customreports.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2020-2023 Laurent Destailleur <eldy@users.sourceforge.net>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16  *
17  * Note: This tool can be included into a list page with :
18  * define('USE_CUSTOM_REPORT_AS_INCLUDE', 1);
19  * include DOL_DOCUMENT_ROOT.'/core/customreports.php';
20  */
21 
28 if (!defined('USE_CUSTOM_REPORT_AS_INCLUDE')) {
29  require '../main.inc.php';
30 
31  // Get parameters
32  $action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ...
33  $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
34 
35  $mode = GETPOST('mode', 'alpha') ? GETPOST('mode', 'alpha') : 'graph';
36  $objecttype = GETPOST('objecttype', 'aZ09');
37  $tabfamily = GETPOST('tabfamily', 'aZ09');
38 
39  if (empty($objecttype)) {
40  $objecttype = 'thirdparty';
41  }
42 
43  $search_measures = GETPOST('search_measures', 'array');
44 
45  //$search_xaxis = GETPOST('search_xaxis', 'array');
46  if (GETPOST('search_xaxis', 'alpha') && GETPOST('search_xaxis', 'alpha') != '-1') {
47  $search_xaxis = array(GETPOST('search_xaxis', 'alpha'));
48  } else {
49  $search_xaxis = array();
50  }
51  //$search_groupby = GETPOST('search_groupby', 'array');
52  if (GETPOST('search_groupby', 'alpha') && GETPOST('search_groupby', 'alpha') != '-1') {
53  $search_groupby = array(GETPOST('search_groupby', 'alpha'));
54  } else {
55  $search_groupby = array();
56  }
57 
58  $search_yaxis = GETPOST('search_yaxis', 'array');
59  $search_graph = GETPOST('search_graph', 'restricthtml');
60 
61  // Load variable for pagination
62  $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
63  $sortfield = GETPOST('sortfield', 'aZ09comma');
64  $sortorder = GETPOST('sortorder', 'aZ09comma');
65  $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
66  if (empty($page) || $page == -1 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) {
67  $page = 0;
68  } // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action
69  $offset = $limit * $page;
70  $pageprev = $page - 1;
71  $pagenext = $page + 1;
72 
73  $diroutputmassaction = $conf->user->dir_temp.'/'.$user->id.'/customreport';
74 }
75 
76 require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php";
77 require_once DOL_DOCUMENT_ROOT."/core/lib/company.lib.php";
78 require_once DOL_DOCUMENT_ROOT."/core/class/dolgraph.class.php";
79 require_once DOL_DOCUMENT_ROOT."/core/class/doleditor.class.php";
80 require_once DOL_DOCUMENT_ROOT."/core/class/html.formother.class.php";
81 
82 // Load traductions files requiredby by page
83 $langs->loadLangs(array("companies", "other", "exports", "sendings"));
84 
85 $extrafields = new ExtraFields($db);
86 
87 $hookmanager->initHooks(array('customreport')); // Note that conf->hooks_modules contains array
88 
89 $title = '';
90 $picto = '';
91 $head = array();
92 $object = null;
93 $ObjectClassName = '';
94 // Objects available by default
95 $arrayoftype = array(
96  'thirdparty' => array('langs'=>'companies', 'label' => 'ThirdParties', 'picto'=>'company', 'ObjectClassName' => 'Societe', 'enabled' => isModEnabled('societe'), 'ClassPath' => "/societe/class/societe.class.php"),
97  'contact' => array('label' => 'Contacts', 'picto'=>'contact', 'ObjectClassName' => 'Contact', 'enabled' => isModEnabled('societ'), 'ClassPath' => "/contact/class/contact.class.php"),
98  'proposal' => array('label' => 'Proposals', 'picto'=>'proposal', 'ObjectClassName' => 'Propal', 'enabled' => isModEnabled('propal'), 'ClassPath' => "/comm/propal/class/propal.class.php"),
99  'order' => array('label' => 'Orders', 'picto'=>'order', 'ObjectClassName' => 'Commande', 'enabled' => isModEnabled('commande'), 'ClassPath' => "/commande/class/commande.class.php"),
100  'invoice' => array('langs'=>'facture', 'label' => 'Invoices', 'picto'=>'bill', 'ObjectClassName' => 'Facture', 'enabled' => isModEnabled('facture'), 'ClassPath' => "/compta/facture/class/facture.class.php"),
101  'invoice_template'=>array('label' => 'PredefinedInvoices', 'picto'=>'bill', 'ObjectClassName' => 'FactureRec', 'enabled' => isModEnabled('facture'), 'ClassPath' => "/compta/class/facturerec.class.php", 'langs'=>'bills'),
102  'contract' => array('label' => 'Contracts', 'picto'=>'contract', 'ObjectClassName' => 'Contrat', 'enabled' => isModEnabled('contrat'), 'ClassPath' => "/contrat/class/contrat.class.php", 'langs'=>'contracts'),
103  'contractdet' => array('label' => 'ContractLines', 'picto'=>'contract', 'ObjectClassName' => 'ContratLigne', 'enabled' => isModEnabled('contrat'), 'ClassPath' => "/contrat/class/contrat.class.php", 'langs'=>'contracts'),
104  'bom' => array('label' => 'BOM', 'picto'=>'bom', 'ObjectClassName' => 'Bom', 'enabled' => isModEnabled('bom')),
105  'mo' => array('label' => 'MO', 'picto'=>'mrp', 'ObjectClassName' => 'Mo', 'enabled' => isModEnabled('mrp'), 'ClassPath' => "/mrp/class/mo.class.php"),
106  'ticket' => array('label' => 'Ticket', 'picto'=>'ticket', 'ObjectClassName' => 'Ticket', 'enabled' => isModEnabled('ticket')),
107  'member' => array('label' => 'Adherent', 'picto'=>'member', 'ObjectClassName' => 'Adherent', 'enabled' => isModEnabled('adherent'), 'ClassPath' => "/adherents/class/adherent.class.php", 'langs'=>'members'),
108  'cotisation' => array('label' => 'Subscriptions', 'picto'=>'member', 'ObjectClassName' => 'Subscription', 'enabled' => isModEnabled('adherent'), 'ClassPath' => "/adherents/class/subscription.class.php", 'langs'=>'members'),
109 );
110 
111 // Complete $arrayoftype by external modules
112 $parameters = array('objecttype'=>$objecttype, 'tabfamily'=>$tabfamily);
113 $reshook = $hookmanager->executeHooks('loadDataForCustomReports', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
114 if ($reshook < 0) {
115  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
116 } elseif (is_array($hookmanager->resArray)) {
117  if (!empty($hookmanager->resArray['title'])) { // Add entries for tabs
118  $title = $hookmanager->resArray['title'];
119  }
120  if (!empty($hookmanager->resArray['picto'])) { // Add entries for tabs
121  $picto = $hookmanager->resArray['picto'];
122  }
123  if (!empty($hookmanager->resArray['head'])) { // Add entries for tabs
124  $head = array_merge($head, $hookmanager->resArray['head']);
125  }
126  if (!empty($hookmanager->resArray['arrayoftype'])) { // Add entries from hook
127  foreach ($hookmanager->resArray['arrayoftype'] as $key => $val) {
128  $arrayoftype[$key] = $val;
129  }
130  }
131 }
132 
133 if ($objecttype) {
134  try {
135  if (!empty($arrayoftype[$objecttype]['ClassPath'])) {
136  dol_include_once($arrayoftype[$objecttype]['ClassPath']);
137  } else {
138  dol_include_once("/".$objecttype."/class/".$objecttype.".class.php");
139  }
140  $ObjectClassName = $arrayoftype[$objecttype]['ObjectClassName'];
141  $object = new $ObjectClassName($db);
142  } catch (Exception $e) {
143  print 'Failed to load class for type '.$objecttype;
144  }
145 }
146 
147 // Security check
148 $socid = 0;
149 if ($user->socid > 0) { // Protection if external user
150  //$socid = $user->socid;
151  accessforbidden();
152 }
153 
154 // Fetch optionals attributes and labels
155 $extrafields->fetch_name_optionals_label('all'); // We load all extrafields definitions for all objects
156 //$extrafields->fetch_name_optionals_label($object->table_element_line);
157 
158 $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
159 
160 $search_component_params = array('');
161 $search_component_params_hidden = GETPOST('search_component_params_hidden', 'alphanohtml');
162 
163 // For the case we enter a criteria manually, the search_component_params_input will be defined and must be used in priority
164 if (GETPOST('search_component_params_input', 'alphanohtml')) {
165  $search_component_params_hidden = GETPOST('search_component_params_input', 'alphanohtml');
166 }
167 
168 $MAXUNIQUEVALFORGROUP = 20;
169 $MAXMEASURESINBARGRAPH = 20;
170 
171 $YYYY = substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1);
172 $MM = substr($langs->trans("Month"), 0, 1).substr($langs->trans("Month"), 0, 1);
173 $DD = substr($langs->trans("Day"), 0, 1).substr($langs->trans("Day"), 0, 1);
174 $HH = substr($langs->trans("Hour"), 0, 1).substr($langs->trans("Hour"), 0, 1);
175 $MI = substr($langs->trans("Minute"), 0, 1).substr($langs->trans("Minute"), 0, 1);
176 $SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1);
177 
178 $arrayofmesures = array();
179 $arrayofxaxis = array();
180 $arrayofgroupby = array();
181 $arrayofyaxis = array();
182 $arrayofvaluesforgroupby = array();
183 
184 $features = $object->element;
185 if (!empty($object->element_for_permission)) {
186  $features = $object->element_for_permission;
187 }
188 
189 restrictedArea($user, $features, 0, '');
190 
191 $error = 0;
192 
193 
194 /*
195  * Actions
196  */
197 
198 // None
199 
200 
201 
202 /*
203  * View
204  */
205 
206 $form = new Form($db);
207 $formother = new FormOther($db);
208 
209 if (!defined('USE_CUSTOM_REPORT_AS_INCLUDE')) {
210  llxHeader('', $langs->transnoentitiesnoconv('CustomReports'), '');
211 
212  print dol_get_fiche_head($head, 'customreports', $title, -1, $picto);
213 }
214 
215 $newarrayoftype = array();
216 foreach ($arrayoftype as $key => $val) {
217  if (dol_eval($val['enabled'], 1, 1, '1')) {
218  $newarrayoftype[$key] = $arrayoftype[$key];
219  }
220  if (!empty($val['langs'])) {
221  $langs->load($val['langs']);
222  }
223 }
224 
225 $count = 0;
226 $arrayofmesures = fillArrayOfMeasures($object, 't', $langs->trans($newarrayoftype[$objecttype]['label']), $arrayofmesures, 0, $count);
227 $arrayofmesures = dol_sort_array($arrayofmesures, 'position', 'asc', 0, 0, 1);
228 
229 $count = 0;
230 $arrayofxaxis = fillArrayOfXAxis($object, 't', $langs->trans($newarrayoftype[$objecttype]['label']), $arrayofxaxis, 0, $count);
231 $arrayofxaxis = dol_sort_array($arrayofxaxis, 'position', 'asc', 0, 0, 1);
232 
233 $count = 0;
234 $arrayofgroupby = fillArrayOfGroupBy($object, 't', $langs->trans($newarrayoftype[$objecttype]['label']), $arrayofgroupby, 0, $count);
235 $arrayofgroupby = dol_sort_array($arrayofgroupby, 'position', 'asc', 0, 0, 1);
236 
237 
238 // Check parameters
239 if ($action == 'viewgraph') {
240  if (!count($search_measures)) {
241  setEventMessages($langs->trans("AtLeastOneMeasureIsRequired"), null, 'warnings');
242  } elseif ($mode == 'graph' && count($search_xaxis) > 1) {
243  setEventMessages($langs->trans("OnlyOneFieldForXAxisIsPossible"), null, 'warnings');
244  $search_xaxis = array(0 => $search_xaxis[0]);
245  }
246  if (count($search_groupby) >= 2) {
247  setEventMessages($langs->trans("ErrorOnlyOneFieldForGroupByIsPossible"), null, 'warnings');
248  $search_groupby = array(0 => $search_groupby[0]);
249  }
250  if (!count($search_xaxis)) {
251  setEventMessages($langs->trans("AtLeastOneXAxisIsRequired"), null, 'warnings');
252  } elseif ($mode == 'graph' && $search_graph == 'bars' && count($search_measures) > $MAXMEASURESINBARGRAPH) {
253  $langs->load("errors");
254  setEventMessages($langs->trans("GraphInBarsAreLimitedToNMeasures", $MAXMEASURESINBARGRAPH), null, 'warnings');
255  $search_graph = 'lines';
256  }
257 }
258 
259 // Get all possible values of fields when a 'group by' is set, and save this into $arrayofvaluesforgroupby
260 // $arrayofvaluesforgroupby will be used to forge lael of each grouped series
261 if (is_array($search_groupby) && count($search_groupby)) {
262  foreach ($search_groupby as $gkey => $gval) {
263  $gvalwithoutprefix = preg_replace('/^[a-z]+\./', '', $gval);
264 
265  if (preg_match('/\-year$/', $search_groupby[$gkey])) {
266  $tmpval = preg_replace('/\-year$/', '', $search_groupby[$gkey]);
267  $fieldtocount .= 'DATE_FORMAT('.$tmpval.", '%Y')";
268  } elseif (preg_match('/\-month$/', $search_groupby[$gkey])) {
269  $tmpval = preg_replace('/\-month$/', '', $search_groupby[$gkey]);
270  $fieldtocount .= 'DATE_FORMAT('.$tmpval.", '%Y-%m')";
271  } elseif (preg_match('/\-day$/', $search_groupby[$gkey])) {
272  $tmpval = preg_replace('/\-day$/', '', $search_groupby[$gkey]);
273  $fieldtocount .= 'DATE_FORMAT('.$tmpval.", '%Y-%m-%d')";
274  } else {
275  $fieldtocount = $search_groupby[$gkey];
276  }
277 
278  $sql = "SELECT DISTINCT ".$fieldtocount." as val";
279 
280  if (strpos($fieldtocount, 'te') === 0) {
281  $tabletouse = $object->table_element;
282  $tablealiastouse = 'te';
283  if (!empty($arrayofgroupby[$gval])) {
284  $tmpval = explode('.', $gval);
285  $tabletouse = $arrayofgroupby[$gval]['table'];
286  $tablealiastouse = $tmpval[0];
287  }
288  //var_dump($tablealiastouse);exit;
289 
290  //$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element."_extrafields as te";
291  $sql .= " FROM ".MAIN_DB_PREFIX.$tabletouse."_extrafields as ".$tablealiastouse;
292  } else {
293  $tabletouse = $object->table_element;
294  $tablealiastouse = 't';
295  if (!empty($arrayofgroupby[$gval])) {
296  $tmpval = explode('.', $gval);
297  $tabletouse = $arrayofgroupby[$gval]['table'];
298  $tablealiastouse = $tmpval[0];
299  }
300  $sql .= " FROM ".MAIN_DB_PREFIX.$tabletouse." as ".$tablealiastouse;
301  }
302 
303  // Add a where here keeping only the citeria on $tabletouse
304  // TODO
305  /*$sqlfilters = ... GETPOST('search_component_params_hidden', 'alphanohtml');
306  if ($sqlfilters) {
307  $errormessage = '';
308  $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
309  }*/
310 
311  $sql .= " LIMIT ".((int) ($MAXUNIQUEVALFORGROUP + 1));
312 
313  //print $sql;
314  $resql = $db->query($sql);
315  if (!$resql) {
316  dol_print_error($db);
317  }
318 
319  while ($obj = $db->fetch_object($resql)) {
320  if (is_null($obj->val)) {
321  $keytouse = '__NULL__';
322  $valuetranslated = $langs->transnoentitiesnoconv("NotDefined");
323  } elseif ($obj->val === '') {
324  $keytouse = '';
325  $valuetranslated = $langs->transnoentitiesnoconv("Empty");
326  } else {
327  $keytouse = (string) $obj->val;
328  $valuetranslated = $obj->val;
329  }
330 
331  $regs = array();
332  if (!empty($object->fields[$gvalwithoutprefix]['arrayofkeyval'])) {
333  $valuetranslated = $object->fields[$gvalwithoutprefix]['arrayofkeyval'][$obj->val];
334  if (is_null($valuetranslated)) {
335  $valuetranslated = $langs->transnoentitiesnoconv("UndefinedKey");
336  }
337  $valuetranslated = $langs->trans($valuetranslated);
338  } elseif (preg_match('/integer:([^:]+):([^:]+)$/', $object->fields[$gvalwithoutprefix]['type'], $regs)) {
339  $classname = $regs[1];
340  $classpath = $regs[2];
341  dol_include_once($classpath);
342  if (class_exists($classname)) {
343  $tmpobject = new $classname($db);
344  $tmpobject->fetch($obj->val);
345  foreach ($tmpobject->fields as $fieldkey => $field) {
346  if ($field['showoncombobox']) {
347  $valuetranslated = $tmpobject->$fieldkey;
348  //if ($valuetranslated == '-') $valuetranslated = $langs->transnoentitiesnoconv("Unknown")
349  break;
350  }
351  }
352  //$valuetranslated = $tmpobject->ref.'eee';
353  }
354  }
355 
356  $arrayofvaluesforgroupby['g_'.$gkey][$keytouse] = $valuetranslated;
357  }
358  // Add also the possible NULL value if field is a parent field that is not a strict join
359  $tmpfield = explode('.', $gval);
360  if ($tmpfield[0] != 't' || (is_array($object->fields[$tmpfield[1]]) && empty($object->fields[$tmpfield[1]]['notnull']))) {
361  dol_syslog("The group by field ".$gval." may be null (because field is null or it is a left join), so we add __NULL__ entry in list of possible values");
362  //var_dump($gval); var_dump($object->fields);
363  $arrayofvaluesforgroupby['g_'.$gkey]['__NULL__'] = $langs->transnoentitiesnoconv("NotDefined");
364  }
365 
366  asort($arrayofvaluesforgroupby['g_'.$gkey]);
367 
368  // Add a protection/error to refuse the request if number of differentr values for the group by is higher than $MAXUNIQUEVALFORGROUP
369  if (count($arrayofvaluesforgroupby['g_'.$gkey]) > $MAXUNIQUEVALFORGROUP) {
370  $langs->load("errors");
371 
372  if (strpos($fieldtocount, 'te') === 0) { // This is a field of an extrafield
373  //if (!empty($extrafields->attributes[$object->table_element]['langfile'][$gvalwithoutprefix])) {
374  // $langs->load($extrafields->attributes[$object->table_element]['langfile'][$gvalwithoutprefix]);
375  //}
376  $keyforlabeloffield = $extrafields->attributes[$object->table_element]['label'][$gvalwithoutprefix];
377  $labeloffield = $langs->transnoentitiesnoconv($keyforlabeloffield);
378  } elseif (strpos($fieldtocount, 't__') === 0) { // This is a field of a foreign key
379  $reg = array();
380  if (preg_match('/^(.*)\.(.*)/', $gvalwithoutprefix, $reg)) {
381  /*
382  $gvalwithoutprefix = preg_replace('/\..*$/', '', $gvalwithoutprefix);
383  $gvalwithoutprefix = preg_replace('/^t__/', '', $gvalwithoutprefix);
384  $keyforlabeloffield = $object->fields[$gvalwithoutprefix]['label'];
385  $labeloffield = $langs->transnoentitiesnoconv($keyforlabeloffield).'-'.$reg[2];
386  */
387  $labeloffield = $arrayofgroupby[$fieldtocount]['labelnohtml'];
388  } else {
389  $labeloffield = $langs->transnoentitiesnoconv($keyforlabeloffield);
390  }
391  } else { // This is a common field
392  $reg = array();
393  if (preg_match('/^(.*)\-(year|month|day)/', $gvalwithoutprefix, $reg)) {
394  $gvalwithoutprefix = preg_replace('/\-(year|month|day)/', '', $gvalwithoutprefix);
395  $keyforlabeloffield = $object->fields[$gvalwithoutprefix]['label'];
396  $labeloffield = $langs->transnoentitiesnoconv($keyforlabeloffield).'-'.$reg[2];
397  } else {
398  $keyforlabeloffield = $object->fields[$gvalwithoutprefix]['label'];
399  $labeloffield = $langs->transnoentitiesnoconv($keyforlabeloffield);
400  }
401  }
402  //var_dump($object->fields);
403  setEventMessages($langs->trans("ErrorTooManyDifferentValueForSelectedGroupBy", $MAXUNIQUEVALFORGROUP, $labeloffield), null, 'warnings');
404  $search_groupby = array();
405  }
406 
407  $db->free($resql);
408  }
409 }
410 //var_dump($arrayofvaluesforgroupby);exit;
411 
412 
413 $tmparray = dol_getdate(dol_now());
414 $endyear = $tmparray['year'];
415 $endmonth = $tmparray['mon'];
416 $datelastday = dol_get_last_day($endyear, $endmonth, 1);
417 $startyear = $endyear - 2;
418 
419 $param = '';
420 
421 print '<form method="post" action="'.$_SERVER['PHP_SELF'].'" autocomplete="off">';
422 print '<input type="hidden" name="token" value="'.newToken().'">';
423 print '<input type="hidden" name="action" value="viewgraph">';
424 print '<input type="hidden" name="tabfamily" value="'.$tabfamily.'">';
425 
426 $viewmode = '';
427 
428 $viewmode .= '<div class="divadvancedsearchfield">';
429 $arrayofgraphs = array('bars' => 'Bars', 'lines' => 'Lines'); // also 'pies'
430 $viewmode .= '<div class="inline-block opacitymedium"><span class="fas fa-chart-area paddingright" title="'.$langs->trans("Graph").'"></span>'.$langs->trans("Graph").'</div> ';
431 $viewmode .= $form->selectarray('search_graph', $arrayofgraphs, $search_graph, 0, 0, 0, '', 1, 0, 0, '', 'graphtype width100');
432 $viewmode .= '</div>';
433 
434 $num = 0;
435 $massactionbutton = '';
436 $nav = '';
437 $newcardbutton = '';
438 $limit = 0;
439 
440 print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, -1, 'object_action', 0, $nav.'<span class="marginleftonly"></span>'.$newcardbutton, '', $limit, 1, 0, 1, $viewmode);
441 
442 
443 foreach ($newarrayoftype as $tmpkey => $tmpval) {
444  $newarrayoftype[$tmpkey]['label'] = img_picto('', $tmpval['picto'], 'class="pictofixedwidth"').$langs->trans($tmpval['label']);
445 }
446 
447 print '<div class="liste_titre liste_titre_bydiv liste_titre_bydiv_inlineblock centpercent">';
448 
449 // Select object
450 print '<div class="divadvancedsearchfield center floatnone">';
451 print '<div class="inline-block"><span class="opacitymedium">'.$langs->trans("StatisticsOn").'</span></div> ';
452 print $form->selectarray('objecttype', $newarrayoftype, $objecttype, 0, 0, 0, '', 1, 0, 0, '', 'minwidth200', 1, '', 0, 1);
453 if (empty($conf->use_javascript_ajax)) {
454  print '<input type="submit" class="button buttongen button-save nomargintop" name="changeobjecttype" value="'.$langs->trans("Refresh").'">';
455 } else {
456  print '<!-- js code to reload page with good object type -->
457  <script nonce="'.getNonce().'" type="text/javascript">
458  jQuery(document).ready(function() {
459  jQuery("#objecttype").change(function() {
460  console.log("Reload for "+jQuery("#objecttype").val());
461  location.href = "'.$_SERVER["PHP_SELF"].'?objecttype="+jQuery("#objecttype").val()+"'.($tabfamily ? '&tabfamily='.urlencode($tabfamily) : '').(GETPOST('show_search_component_params_hidden', 'int') ? '&show_search_component_params_hidden='.((int) GETPOST('show_search_component_params_hidden', 'int')) : '').'";
462  });
463  });
464  </script>';
465 }
466 print '</div><div class="clearboth"></div>';
467 
468 // Filter (you can use param &show_search_component_params_hidden=1 for debug)
469 print '<div class="divadvancedsearchfield quatrevingtpercent">';
470 print $form->searchComponent(array($object->element => $object->fields), $search_component_params, array(), $search_component_params_hidden);
471 print '</div>';
472 
473 // YAxis (add measures into array)
474 $count = 0;
475 //var_dump($arrayofmesures);
476 print '<div class="divadvancedsearchfield clearboth">';
477 print '<div class="inline-block"><span class="fas fa-ruler-combined paddingright pictofixedwidth" title="'.dol_escape_htmltag($langs->trans("Measures")).'"></span><span class="fas fa-caret-left caretleftaxis" title="'.dol_escape_htmltag($langs->trans("Measures")).'"></span></div>';
478 $simplearrayofmesures = array();
479 foreach ($arrayofmesures as $key => $val) {
480  $simplearrayofmesures[$key] = $arrayofmesures[$key]['label'];
481 }
482 print $form->multiselectarray('search_measures', $simplearrayofmesures, $search_measures, 0, 0, 'minwidth300', 1, 0, '', '', $langs->trans("Measures")); // Fill the array $arrayofmeasures with possible fields
483 print '</div>';
484 
485 // XAxis
486 $count = 0;
487 print '<div class="divadvancedsearchfield">';
488 print '<div class="inline-block"><span class="fas fa-ruler-combined paddingright pictofixedwidth" title="'.dol_escape_htmltag($langs->trans("XAxis")).'"></span><span class="fas fa-caret-down caretdownaxis" title="'.dol_escape_htmltag($langs->trans("XAxis")).'"></span></div>';
489 //var_dump($arrayofxaxis);
490 print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis, $langs->trans("XAxis"), 'minwidth300 maxwidth400'); // Fill the array $arrayofxaxis with possible fields
491 print '</div>';
492 
493 // Group by
494 $count = 0;
495 print '<div class="divadvancedsearchfield">';
496 print '<div class="inline-block opacitymedium"><span class="fas fa-ruler-horizontal paddingright pictofixedwidth" title="'.dol_escape_htmltag($langs->trans("GroupBy")).'"></span></div>';
497 print $formother->selectGroupByField($object, $search_groupby, $arrayofgroupby, 'minwidth250 maxwidth300', $langs->trans("GroupBy")); // Fill the array $arrayofgroupby with possible fields
498 print '</div>';
499 
500 
501 if ($mode == 'grid') {
502  // YAxis
503  print '<div class="divadvancedsearchfield">';
504  foreach ($object->fields as $key => $val) {
505  if (empty($val['measure']) && (!isset($val['enabled']) || dol_eval($val['enabled'], 1, 1, '1'))) {
506  if (in_array($key, array('id', 'rowid', 'entity', 'last_main_doc', 'extraparams'))) {
507  continue;
508  }
509  if (preg_match('/^fk_/', $key)) {
510  continue;
511  }
512  if (in_array($val['type'], array('html', 'text'))) {
513  continue;
514  }
515  if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) {
516  $arrayofyaxis['t.'.$key.'-year'] = array(
517  'label' => $langs->trans($val['label']).' ('.$YYYY.')',
518  'position' => $val['position'],
519  'table' => $object->table_element
520  );
521  $arrayofyaxis['t.'.$key.'-month'] = array(
522  'label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.')',
523  'position' => $val['position'],
524  'table' => $object->table_element
525  );
526  $arrayofyaxis['t.'.$key.'-day'] = array(
527  'label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.'-'.$DD.')',
528  'position' => $val['position'],
529  'table' => $object->table_element
530  );
531  } else {
532  $arrayofyaxis['t.'.$key] = array(
533  'label' => $val['label'],
534  'position' => (int) $val['position'],
535  'table' => $object->table_element
536  );
537  }
538  }
539  }
540  // Add measure from extrafields
541  if ($object->isextrafieldmanaged) {
542  foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
543  if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key]) && (!isset($extrafields->attributes[$object->table_element]['enabled'][$key]) || dol_eval($extrafields->attributes[$object->table_element]['enabled'][$key], 1, 1, '1'))) {
544  $arrayofyaxis['te.'.$key] = array(
545  'label' => $extrafields->attributes[$object->table_element]['label'][$key],
546  'position' => (int) $extrafields->attributes[$object->table_element]['pos'][$key],
547  'table' => $object->table_element
548  );
549  }
550  }
551  }
552  $arrayofyaxis = dol_sort_array($arrayofyaxis, 'position');
553  $arrayofyaxislabel = array();
554  foreach ($arrayofyaxis as $key => $val) {
555  $arrayofyaxislabel[$key] = $val['label'];
556  }
557  print '<div class="inline-block opacitymedium"><span class="fas fa-ruler-vertical paddingright" title="'.$langs->trans("YAxis").'"></span>'.$langs->trans("YAxis").'</div> ';
558  print $form->multiselectarray('search_yaxis', $arrayofyaxislabel, $search_yaxis, 0, 0, 'minwidth100', 1);
559  print '</div>';
560 }
561 
562 if ($mode == 'graph') {
563  //
564 }
565 
566 print '<div class="divadvancedsearchfield">';
567 print '<input type="submit" class="button buttongen button-save nomargintop" value="'.$langs->trans("Refresh").'">';
568 print '</div>';
569 print '</div>';
570 print '</form>';
571 
572 // Generate the SQL request
573 $sql = '';
574 if (!empty($search_measures) && !empty($search_xaxis)) {
575  $errormessage = '';
576 
577  $fieldid = 'rowid';
578 
579  $sql = "SELECT ";
580  foreach ($search_xaxis as $key => $val) {
581  if (preg_match('/\-year$/', $val)) {
582  $tmpval = preg_replace('/\-year$/', '', $val);
583  $sql .= "DATE_FORMAT(".$tmpval.", '%Y') as x_".$key.', ';
584  } elseif (preg_match('/\-month$/', $val)) {
585  $tmpval = preg_replace('/\-month$/', '', $val);
586  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m') as x_".$key.', ';
587  } elseif (preg_match('/\-day$/', $val)) {
588  $tmpval = preg_replace('/\-day$/', '', $val);
589  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d') as x_".$key.', ';
590  } else {
591  $sql .= $val." as x_".$key.", ";
592  }
593  }
594  foreach ($search_groupby as $key => $val) {
595  if (preg_match('/\-year$/', $val)) {
596  $tmpval = preg_replace('/\-year$/', '', $val);
597  $sql .= "DATE_FORMAT(".$tmpval.", '%Y') as g_".$key.', ';
598  } elseif (preg_match('/\-month$/', $val)) {
599  $tmpval = preg_replace('/\-month$/', '', $val);
600  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m') as g_".$key.', ';
601  } elseif (preg_match('/\-day$/', $val)) {
602  $tmpval = preg_replace('/\-day$/', '', $val);
603  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d') as g_".$key.', ';
604  } else {
605  $sql .= $val." as g_".$key.", ";
606  }
607  }
608  foreach ($search_measures as $key => $val) {
609  if ($val == 't.count') {
610  $sql .= "COUNT(t.".$fieldid.") as y_".$key.', ';
611  } elseif (preg_match('/\-sum$/', $val)) {
612  $tmpval = preg_replace('/\-sum$/', '', $val);
613  $sql .= "SUM(".$db->ifsql($tmpval.' IS NULL', '0', $tmpval).") as y_".$key.", ";
614  } elseif (preg_match('/\-average$/', $val)) {
615  $tmpval = preg_replace('/\-average$/', '', $val);
616  $sql .= "AVG(".$db->ifsql($tmpval.' IS NULL', '0', $tmpval).") as y_".$key.", ";
617  } elseif (preg_match('/\-min$/', $val)) {
618  $tmpval = preg_replace('/\-min$/', '', $val);
619  $sql .= "MIN(".$db->ifsql($tmpval.' IS NULL', '0', $tmpval).") as y_".$key.", ";
620  } elseif (preg_match('/\-max$/', $val)) {
621  $tmpval = preg_replace('/\-max$/', '', $val);
622  $sql .= "MAX(".$db->ifsql($tmpval.' IS NULL', '0', $tmpval).") as y_".$key.", ";
623  }
624  }
625  $sql = preg_replace('/,\s*$/', '', $sql);
626  $sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t";
627  // Add measure from extrafields
628  if ($object->isextrafieldmanaged) {
629  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as te ON te.fk_object = t.".$fieldid;
630  }
631  // Add table for link on multientity
632  if ($object->ismultientitymanaged) { // 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table
633  if ($object->ismultientitymanaged == 1) {
634  // No table to add here
635  } else {
636  $tmparray = explode('@', $object->ismultientitymanaged);
637  $sql .= " INNER JOIN ".MAIN_DB_PREFIX.$tmparray[1]." as parenttableforentity ON t.".$tmparray[0]." = parenttableforentity.rowid";
638  $sql .= " AND parenttableforentity.entity IN (".getEntity($tmparray[1]).")";
639  }
640  }
641 
642  // Init the list of tables added. We include by default always the main table.
643  $listoftablesalreadyadded = array($object->table_element => $object->table_element);
644 
645  // Add LEFT JOIN for all parent tables mentionned into the Xaxis
646  //var_dump($arrayofxaxis); var_dump($search_xaxis);
647  foreach ($search_xaxis as $key => $val) {
648  if (!empty($arrayofxaxis[$val])) {
649  $tmpval = explode('.', $val);
650  //var_dump($arrayofgroupby);
651  $tmpforloop = dolExplodeIntoArray($arrayofxaxis[$val]['tablefromt'], ',');
652  foreach ($tmpforloop as $tmptable => $tmptablealias) {
653  if (! in_array($tmptable, $listoftablesalreadyadded)) { // We do not add join for main table and tables already added
654  $tmpforexplode = explode('__', $tmptablealias);
655  $endpart = end($tmpforexplode);
656  $parenttableandfield = preg_replace('/__'.$endpart.'$/', '', $tmptablealias).'.'.$endpart;
657 
658  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$tmptable." as ".$db->sanitize($tmptablealias)." ON ".$db->sanitize($parenttableandfield)." = ".$db->sanitize($tmptablealias).".rowid";
659  $listoftablesalreadyadded[$tmptable] = $tmptable;
660 
661  if (preg_match('/^te/', $tmpval[0]) && preg_replace('/^t_/', 'te_', $tmptablealias) == $tmpval[0]) {
662  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$tmptable."_extrafields as ".$db->sanitize($tmpval[0])." ON ".$db->sanitize($tmpval[0]).".fk_object = ".$db->sanitize($tmptablealias).".rowid";
663  $listoftablesalreadyadded[$tmptable] = $tmptable;
664  }
665  }
666  }
667  } else {
668  $errormessage = 'Found a key into search_xaxis not found into arrayofxaxis';
669  }
670  }
671 
672  // Add LEFT JOIN for all parent tables mentionned into the Group by
673  //var_dump($arrayofgroupby); var_dump($search_groupby);
674  foreach ($search_groupby as $key => $val) {
675  if (!empty($arrayofgroupby[$val])) {
676  $tmpval = explode('.', $val);
677  //var_dump($arrayofgroupby[$val]); var_dump($tmpval);
678  $tmpforloop = dolExplodeIntoArray($arrayofgroupby[$val]['tablefromt'], ',');
679  foreach ($tmpforloop as $tmptable => $tmptablealias) {
680  if (! in_array($tmptable, $listoftablesalreadyadded)) { // We do not add join for main table and tables already added
681  $tmpforexplode = explode('__', $tmptablealias);
682  $endpart = end($tmpforexplode);
683  $parenttableandfield = preg_replace('/__'.$endpart.'$/', '', $tmptablealias).'.'.$endpart;
684 
685  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$tmptable." as ".$db->sanitize($tmptablealias)." ON ".$db->sanitize($parenttableandfield)." = ".$db->sanitize($tmptablealias).".rowid";
686  $listoftablesalreadyadded[$tmptable] = $tmptable;
687 
688  if (preg_match('/^te/', $tmpval[0]) && preg_replace('/^t_/', 'te_', $tmptablealias) == $tmpval[0]) {
689  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$tmptable."_extrafields as ".$db->sanitize($tmpval[0])." ON ".$db->sanitize($tmpval[0]).".fk_object = ".$db->sanitize($tmptablealias).".rowid";
690  $listoftablesalreadyadded[$tmptable] = $tmptable;
691  }
692  }
693  }
694  } else {
695  $errormessage = 'Found a key into search_groupby not found into arrayofgroupby';
696  }
697  }
698 
699  // Add LEFT JOIN for all parent tables mentionned into the Yaxis
700  //var_dump($arrayofgroupby); var_dump($search_groupby);
701  foreach ($search_measures as $key => $val) {
702  if (!empty($arrayofmesures[$val])) {
703  $tmpval = explode('.', $val);
704  //var_dump($arrayofgroupby);
705  $tmpforloop = dolExplodeIntoArray($arrayofmesures[$val]['tablefromt'], ',');
706  foreach ($tmpforloop as $tmptable => $tmptablealias) {
707  if (! in_array($tmptable, $listoftablesalreadyadded)) { // We do not add join for main table and tables already added
708  $tmpforexplode = explode('__', $tmptablealias);
709  $endpart = end($tmpforexplode);
710  $parenttableandfield = preg_replace('/__'.$endpart.'$/', '', $tmptablealias).'.'.$endpart;
711 
712  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$tmptable." as ".$db->sanitize($tmptablealias)." ON ".$db->sanitize($parenttableandfield)." = ".$db->sanitize($tmptablealias).".rowid";
713  $listoftablesalreadyadded[$tmptable] = $tmptable;
714 
715  if (preg_match('/^te/', $tmpval[0]) && preg_replace('/^t_/', 'te_', $tmptablealias) == $tmpval[0]) {
716  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$tmptable."_extrafields as ".$db->sanitize($tmpval[0])." ON ".$db->sanitize($tmpval[0]).".fk_object = ".$db->sanitize($tmptablealias).".rowid";
717  $listoftablesalreadyadded[$tmptable] = $tmptable;
718  }
719  }
720  }
721  } else {
722  $errormessage = 'Found a key into search_measures not found into arrayofmesures';
723  }
724  }
725 
726  $sql .= " WHERE 1 = 1";
727  if ($object->ismultientitymanaged == 1) { // 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table
728  $sql .= " AND t.entity IN (".getEntity($object->element).")";
729  }
730  // Add the where here
731  $sqlfilters = $search_component_params_hidden;
732  if ($sqlfilters) {
733  $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage, 0, 0, 1);
734  }
735  $sql .= " GROUP BY ";
736  foreach ($search_xaxis as $key => $val) {
737  if (preg_match('/\-year$/', $val)) {
738  $tmpval = preg_replace('/\-year$/', '', $val);
739  $sql .= "DATE_FORMAT(".$tmpval.", '%Y'), ";
740  } elseif (preg_match('/\-month$/', $val)) {
741  $tmpval = preg_replace('/\-month$/', '', $val);
742  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m'), ";
743  } elseif (preg_match('/\-day$/', $val)) {
744  $tmpval = preg_replace('/\-day$/', '', $val);
745  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d'), ";
746  } else {
747  $sql .= $val.", ";
748  }
749  }
750  foreach ($search_groupby as $key => $val) {
751  if (preg_match('/\-year$/', $val)) {
752  $tmpval = preg_replace('/\-year$/', '', $val);
753  $sql .= "DATE_FORMAT(".$tmpval.", '%Y'), ";
754  } elseif (preg_match('/\-month$/', $val)) {
755  $tmpval = preg_replace('/\-month$/', '', $val);
756  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m'), ";
757  } elseif (preg_match('/\-day$/', $val)) {
758  $tmpval = preg_replace('/\-day$/', '', $val);
759  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d'), ";
760  } else {
761  $sql .= $val.', ';
762  }
763  }
764  $sql = preg_replace('/,\s*$/', '', $sql);
765  $sql .= ' ORDER BY ';
766  foreach ($search_xaxis as $key => $val) {
767  if (preg_match('/\-year$/', $val)) {
768  $tmpval = preg_replace('/\-year$/', '', $val);
769  $sql .= "DATE_FORMAT(".$tmpval.", '%Y'), ";
770  } elseif (preg_match('/\-month$/', $val)) {
771  $tmpval = preg_replace('/\-month$/', '', $val);
772  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m'), ";
773  } elseif (preg_match('/\-day$/', $val)) {
774  $tmpval = preg_replace('/\-day$/', '', $val);
775  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d'), ";
776  } else {
777  $sql .= $val.', ';
778  }
779  }
780  foreach ($search_groupby as $key => $val) {
781  if (preg_match('/\-year$/', $val)) {
782  $tmpval = preg_replace('/\-year$/', '', $val);
783  $sql .= "DATE_FORMAT(".$tmpval.", '%Y'), ";
784  } elseif (preg_match('/\-month$/', $val)) {
785  $tmpval = preg_replace('/\-month$/', '', $val);
786  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m'), ";
787  } elseif (preg_match('/\-day$/', $val)) {
788  $tmpval = preg_replace('/\-day$/', '', $val);
789  $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d'), ";
790  } else {
791  $sql .= $val.', ';
792  }
793  }
794  $sql = preg_replace('/,\s*$/', '', $sql);
795 }
796 //print $sql;
797 
798 if ($errormessage) {
799  print dol_escape_htmltag($errormessage);
800  $sql = '';
801 }
802 
803 $legend = array();
804 foreach ($search_measures as $key => $val) {
805  $legend[] = $langs->trans($arrayofmesures[$val]['label']);
806 }
807 
808 $useagroupby = (is_array($search_groupby) && count($search_groupby));
809 //var_dump($useagroupby);
810 //var_dump($arrayofvaluesforgroupby);
811 
812 // Execute the SQL request
813 $totalnbofrecord = 0;
814 $data = array();
815 if ($sql) {
816  $resql = $db->query($sql);
817  if (!$resql) {
818  dol_print_error($db);
819  }
820 
821  $ifetch = 0;
822  $xi = 0;
823  $oldlabeltouse = '';
824  while ($obj = $db->fetch_object($resql)) {
825  $ifetch++;
826  if ($useagroupby) {
827  $xval = $search_xaxis[0];
828  $fieldforxkey = 'x_0';
829  $xlabel = $obj->$fieldforxkey;
830  $xvalwithoutprefix = preg_replace('/^[a-z]+\./', '', $xval);
831 
832  // Define $xlabel
833  if (!empty($object->fields[$xvalwithoutprefix]['arrayofkeyval'])) {
834  $xlabel = $object->fields[$xvalwithoutprefix]['arrayofkeyval'][$obj->$fieldforxkey];
835  }
836  $labeltouse = (($xlabel || $xlabel == '0') ? dol_trunc($xlabel, 20, 'middle') : ($xlabel === '' ? $langs->transnoentitiesnoconv("Empty") : $langs->transnoentitiesnoconv("NotDefined")));
837 
838  if ($oldlabeltouse && ($labeltouse != $oldlabeltouse)) {
839  $xi++; // Increase $xi
840  }
841  //var_dump($labeltouse.' '.$oldlabeltouse.' '.$xi);
842  $oldlabeltouse = $labeltouse;
843 
844  /* Example of value for $arrayofvaluesforgroupby
845  * array (size=1)
846  * 'g_0' =>
847  * array (size=6)
848  * 0 => string '0' (length=1)
849  * '' => string 'Empty' (length=5)
850  * '__NULL__' => string 'Not defined' (length=11)
851  * 'done' => string 'done' (length=4)
852  * 'processing' => string 'processing' (length=10)
853  * 'undeployed' => string 'undeployed' (length=10)
854  */
855  foreach ($search_measures as $key => $val) {
856  $gi = 0;
857  foreach ($search_groupby as $gkey) {
858  //var_dump('*** Fetch #'.$ifetch.' for labeltouse='.$labeltouse.' measure number '.$key.' and group g_'.$gi);
859  //var_dump($arrayofvaluesforgroupby);
860  foreach ($arrayofvaluesforgroupby['g_'.$gi] as $gvaluepossiblekey => $gvaluepossiblelabel) {
861  $ykeysuffix = $gvaluepossiblelabel;
862  $gvalwithoutprefix = preg_replace('/^[a-z]+\./', '', $gval);
863 
864  $fieldfory = 'y_'.$key;
865  $fieldforg = 'g_'.$gi;
866  $fieldforybis = 'y_'.$key.'_'.$ykeysuffix;
867  //var_dump('gvaluepossiblekey='.$gvaluepossiblekey.' gvaluepossiblelabel='.$gvaluepossiblelabel.' ykeysuffix='.$ykeysuffix.' gval='.$gval.' gvalwithoutsuffix='.$gvalwithoutprefix);
868  //var_dump('fieldforg='.$fieldforg.' obj->$fieldforg='.$obj->$fieldforg.' fieldfory='.$fieldfory.' obj->$fieldfory='.$obj->$fieldfory.' fieldforybis='.$fieldforybis);
869 
870  if (!is_array($data[$xi])) {
871  $data[$xi] = array();
872  }
873 
874  if (!array_key_exists('label', $data[$xi])) {
875  $data[$xi] = array();
876  $data[$xi]['label'] = $labeltouse;
877  }
878 
879  $objfieldforg = $obj->$fieldforg;
880  if (is_null($objfieldforg)) {
881  $objfieldforg = '__NULL__';
882  }
883 
884  if ($gvaluepossiblekey == '0') { // $gvaluepossiblekey can have type int or string. So we create a special if, used when value is '0'
885  //var_dump($objfieldforg.' == \'0\' -> '.($objfieldforg == '0'));
886  if ($objfieldforg == '0') {
887  // The record we fetch is for this group
888  $data[$xi][$fieldforybis] = $obj->$fieldfory;
889  } elseif (!isset($data[$xi][$fieldforybis])) {
890  // The record we fetch is not for this group
891  $data[$xi][$fieldforybis] = '0';
892  }
893  } else {
894  //var_dump((string) $objfieldforg.' === '.(string) $gvaluepossiblekey.' -> '.((string) $objfieldforg === (string) $gvaluepossiblekey));
895  if ((string) $objfieldforg === (string) $gvaluepossiblekey) {
896  // The record we fetch is for this group
897  $data[$xi][$fieldforybis] = $obj->$fieldfory;
898  } elseif (!isset($data[$xi][$fieldforybis])) {
899  // The record we fetch is not for this group
900  $data[$xi][$fieldforybis] = '0';
901  }
902  }
903  }
904  //var_dump($data[$xi]);
905  $gi++;
906  }
907  }
908  } else { // No group by
909  $xval = $search_xaxis[0];
910  $fieldforxkey = 'x_0';
911  $xlabel = $obj->$fieldforxkey;
912  $xvalwithoutprefix = preg_replace('/^[a-z]+\./', '', $xval);
913 
914  // Define $xlabel
915  if (!empty($object->fields[$xvalwithoutprefix]['arrayofkeyval'])) {
916  $xlabel = $object->fields[$xvalwithoutprefix]['arrayofkeyval'][$obj->$fieldforxkey];
917  }
918 
919  $labeltouse = (($xlabel || $xlabel == '0') ? dol_trunc($xlabel, 20, 'middle') : ($xlabel === '' ? $langs->transnoentitiesnoconv("Empty") : $langs->transnoentitiesnoconv("NotDefined")));
920  $xarrayforallseries = array('label' => $labeltouse);
921  foreach ($search_measures as $key => $val) {
922  $fieldfory = 'y_'.$key;
923  $xarrayforallseries[$fieldfory] = $obj->$fieldfory;
924  }
925  $data[$xi] = $xarrayforallseries;
926  $xi++;
927  }
928  }
929 
930  $totalnbofrecord = count($data);
931 }
932 //var_dump($data);
933 
934 
935 print '<div class="customreportsoutput'.($totalnbofrecord ? '' : ' customreportsoutputnotdata').'">';
936 
937 
938 if ($mode == 'grid') {
939  // TODO
940 }
941 
942 if ($mode == 'graph') {
943  $WIDTH = '80%';
944  $HEIGHT = (empty($_SESSION['dol_screenheight']) ? 400 : $_SESSION['dol_screenheight'] - 500);
945 
946  // Show graph
947  $px1 = new DolGraph();
948  $mesg = $px1->isGraphKo();
949  if (!$mesg) {
950  //var_dump($legend);
951  //var_dump($data);
952  $px1->SetData($data);
953  unset($data);
954 
955  $arrayoftypes = array();
956  foreach ($search_measures as $key => $val) {
957  $arrayoftypes[] = $search_graph;
958  }
959 
960  $px1->SetLegend($legend);
961  $px1->SetMinValue($px1->GetFloorMinValue());
962  $px1->SetMaxValue($px1->GetCeilMaxValue());
963  $px1->SetWidth($WIDTH);
964  $px1->SetHeight($HEIGHT);
965  $px1->SetYLabel($langs->trans("Y"));
966  $px1->SetShading(3);
967  $px1->SetHorizTickIncrement(1);
968  $px1->SetCssPrefix("cssboxes");
969  $px1->SetType($arrayoftypes);
970  $px1->mode = 'depth';
971  $px1->SetTitle('');
972 
973  $dir = $conf->user->dir_temp;
974  dol_mkdir($dir);
975  $filenamenb = $dir.'/customreport_'.$object->element.'.png';
976  $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=user&file=customreport_'.$object->element.'.png';
977 
978  $px1->draw($filenamenb, $fileurlnb);
979 
980  $texttoshow = $langs->trans("NoRecordFound");
981  if (!GETPOSTISSET('search_measures') || !GETPOSTISSET('search_xaxis')) {
982  $texttoshow = $langs->trans("SelectYourGraphOptionsFirst");
983  }
984 
985  print $px1->show($totalnbofrecord ? 0 : $texttoshow);
986  }
987 }
988 
989 if ($sql) {
990  // Show admin info
991  print '<br>'.info_admin($langs->trans("SQLUsedForExport").':<br> '.$sql, 0, 0, 1, '', 'TechnicalInformation');
992 }
993 
994 print '<div>';
995 
996 if (!defined('USE_CUSTOM_REPORT_AS_INCLUDE')) {
997  print dol_get_fiche_end();
998 }
999 
1000 // End of page
1001 llxFooter();
1002 
1003 $db->close();
1004 
1005 
1006 
1007 
1020 function fillArrayOfMeasures($object, $tablealias, $labelofobject, &$arrayofmesures, $level = 0, &$count = 0, &$tablepath = '')
1021 {
1022  global $langs, $extrafields, $db;
1023 
1024  if ($level > 10) { // Protection against infinite loop
1025  return $arrayofmesures;
1026  }
1027 
1028  if (empty($tablepath)) {
1029  $tablepath = $object->table_element.'='.$tablealias;
1030  } else {
1031  $tablepath .= ','.$object->table_element.'='.$tablealias;
1032  }
1033 
1034  if ($level == 0) {
1035  // Add the count of record only for the main/first level object. Parents are necessarly unique for each record.
1036  $arrayofmesures[$tablealias.'.count'] = array(
1037  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': Count',
1038  'labelnohtml' => $labelofobject.': Count',
1039  'position' => 0,
1040  'table' => $object->table_element,
1041  'tablefromt' => $tablepath
1042  );
1043  }
1044 
1045  // Note: here $tablealias can be 't' or 't__fk_contract' or 't_fk_contract_fk_soc'
1046 
1047  // Add main fields of object
1048  foreach ($object->fields as $key => $val) {
1049  if (!empty($val['isameasure']) && (!isset($val['enabled']) || dol_eval($val['enabled'], 1, 1, '1'))) {
1050  $position = (empty($val['position']) ? 0 : intVal($val['position']));
1051  $arrayofmesures[$tablealias.'.'.$key.'-sum'] = array(
1052  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$langs->trans("Sum").')</span>',
1053  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1054  'position' => ($position + ($count * 100000)).'.1',
1055  'table' => $object->table_element,
1056  'tablefromt' => $tablepath
1057  );
1058  $arrayofmesures[$tablealias.'.'.$key.'-average'] = array(
1059  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$langs->trans("Average").')</span>',
1060  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1061  'position' => ($position + ($count * 100000)).'.2',
1062  'table' => $object->table_element,
1063  'tablefromt' => $tablepath
1064  );
1065  $arrayofmesures[$tablealias.'.'.$key.'-min'] = array(
1066  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$langs->trans("Minimum").')</span>',
1067  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1068  'position' => ($position + ($count * 100000)).'.3',
1069  'table' => $object->table_element,
1070  'tablefromt' => $tablepath
1071  );
1072  $arrayofmesures[$tablealias.'.'.$key.'-max'] = array(
1073  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$langs->trans("Maximum").')</span>',
1074  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1075  'position' => ($position + ($count * 100000)).'.4',
1076  'table' => $object->table_element,
1077  'tablefromt' => $tablepath
1078  );
1079  }
1080  }
1081  // Add extrafields to Measures
1082  if (!empty($object->isextrafieldmanaged)) {
1083  foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
1084  if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key]) && (!isset($extrafields->attributes[$object->table_element]['enabled'][$key]) || dol_eval($extrafields->attributes[$object->table_element]['enabled'][$key], 1, 1, '1'))) {
1085  $position = (!empty($val['position']) ? $val['position'] : 0);
1086  $arrayofmesures[preg_replace('/^t/', 'te', $tablealias).'.'.$key.'-sum'] = array(
1087  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' <span class="opacitymedium">('.$langs->trans("Sum").')</span>',
1088  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1089  'position' => ($position+($count * 100000)).'.1',
1090  'table' => $object->table_element,
1091  'tablefromt' => $tablepath
1092  );
1093  $arrayofmesures[preg_replace('/^t/', 'te', $tablealias).'.'.$key.'-average'] = array(
1094  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' <span class="opacitymedium">('.$langs->trans("Average").')</span>',
1095  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1096  'position' => ($position+($count * 100000)).'.2',
1097  'table' => $object->table_element,
1098  'tablefromt' => $tablepath
1099  );
1100  $arrayofmesures[preg_replace('/^t/', 'te', $tablealias).'.'.$key.'-min'] = array(
1101  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' <span class="opacitymedium">('.$langs->trans("Minimum").')</span>',
1102  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1103  'position' => ($position+($count * 100000)).'.3',
1104  'table' => $object->table_element,
1105  'tablefromt' => $tablepath
1106  );
1107  $arrayofmesures[preg_replace('/^t/', 'te', $tablealias).'.'.$key.'-max'] = array(
1108  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' <span class="opacitymedium">('.$langs->trans("Maximum").')</span>',
1109  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1110  'position' => ($position+($count * 100000)).'.4',
1111  'table' => $object->table_element,
1112  'tablefromt' => $tablepath
1113  );
1114  }
1115  }
1116  }
1117  // Add fields for parent objects
1118  foreach ($object->fields as $key => $val) {
1119  if (preg_match('/^[^:]+:[^:]+:/', $val['type'])) {
1120  $tmptype = explode(':', $val['type'], 4);
1121  if ($tmptype[0] == 'integer' && !empty($tmptype[1]) && !empty($tmptype[2])) {
1122  $newobject = $tmptype[1];
1123  dol_include_once($tmptype[2]);
1124  if (class_exists($newobject)) {
1125  $tmpobject = new $newobject($db);
1126  //var_dump($key); var_dump($tmpobject->element); var_dump($val['label']); var_dump($tmptype); var_dump('t-'.$key);
1127  $count++;
1128  $arrayofmesures = fillArrayOfMeasures($tmpobject, $tablealias.'__'.$key, $langs->trans($val['label']), $arrayofmesures, $level + 1, $count, $tablepath);
1129  } else {
1130  print 'For property '.$object->element.'->'.$key.', type="'.$val['type'].'": Failed to find class '.$newobject." in file ".$tmptype[2]."<br>\n";
1131  }
1132  }
1133  }
1134  }
1135 
1136  return $arrayofmesures;
1137 }
1138 
1139 
1152 function fillArrayOfXAxis($object, $tablealias, $labelofobject, &$arrayofxaxis, $level = 0, &$count = 0, &$tablepath = '')
1153 {
1154  global $langs, $extrafields, $db;
1155 
1156  if ($level >= 3) { // Limit scan on 2 levels max
1157  return $arrayofxaxis;
1158  }
1159 
1160  if (empty($tablepath)) {
1161  $tablepath = $object->table_element.'='.$tablealias;
1162  } else {
1163  $tablepath .= ','.$object->table_element.'='.$tablealias;
1164  }
1165 
1166  $YYYY = substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1);
1167  $MM = substr($langs->trans("Month"), 0, 1).substr($langs->trans("Month"), 0, 1);
1168  $DD = substr($langs->trans("Day"), 0, 1).substr($langs->trans("Day"), 0, 1);
1169  $HH = substr($langs->trans("Hour"), 0, 1).substr($langs->trans("Hour"), 0, 1);
1170  $MI = substr($langs->trans("Minute"), 0, 1).substr($langs->trans("Minute"), 0, 1);
1171  $SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1);
1172 
1173  /*if ($level > 0) {
1174  var_dump($object->element.' '.$object->isextrafieldmanaged);
1175  }*/
1176 
1177  // Note: here $tablealias can be 't' or 't__fk_contract' or 't_fk_contract_fk_soc'
1178 
1179  // Add main fields of object
1180  foreach ($object->fields as $key => $val) {
1181  if (empty($val['measure'])) {
1182  if (in_array($key, array(
1183  'id', 'ref_ext', 'rowid', 'entity', 'last_main_doc', 'logo', 'logo_squarred', 'extraparams',
1184  'parent', 'photo', 'socialnetworks', 'webservices_url', 'webservices_key'))) {
1185  continue;
1186  }
1187  if (isset($val['enabled']) && !dol_eval($val['enabled'], 1, 1, '1')) {
1188  continue;
1189  }
1190  if (isset($val['visible']) && !dol_eval($val['visible'], 1, 1, '1')) {
1191  continue;
1192  }
1193  if (preg_match('/^fk_/', $key) && !preg_match('/^fk_statu/', $key)) {
1194  continue;
1195  }
1196  if (preg_match('/^pass/', $key)) {
1197  continue;
1198  }
1199  if (in_array($val['type'], array('html', 'text'))) {
1200  continue;
1201  }
1202  if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) {
1203  $position = (empty($val['position']) ? 0 : intVal($val['position']));
1204  $arrayofxaxis[$tablealias.'.'.$key.'-year'] = array(
1205  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.')</span>',
1206  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1207  'position' => ($position + ($count * 100000)).'.1',
1208  'table' => $object->table_element,
1209  'tablefromt' => $tablepath
1210  );
1211  $arrayofxaxis[$tablealias.'.'.$key.'-month'] = array(
1212  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.'-'.$MM.')</span>',
1213  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1214  'position' => ($position + ($count * 100000)).'.2',
1215  'table' => $object->table_element,
1216  'tablefromt' => $tablepath
1217  );
1218  $arrayofxaxis[$tablealias.'.'.$key.'-day'] = array(
1219  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.'-'.$MM.'-'.$DD.')</span>',
1220  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1221  'position' => ($position + ($count * 100000)).'.3',
1222  'table' => $object->table_element,
1223  'tablefromt' => $tablepath
1224  );
1225  } else {
1226  $position = (empty($val['position']) ? 0 : intVal($val['position']));
1227  $arrayofxaxis[$tablealias.'.'.$key] = array(
1228  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']),
1229  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1230  'position' => ($position + ($count * 100000)),
1231  'table' => $object->table_element,
1232  'tablefromt' => $tablepath
1233  );
1234  }
1235  }
1236  }
1237 
1238  // Add extrafields to X-Axis
1239  if (!empty($object->isextrafieldmanaged)) {
1240  foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
1241  if ($extrafields->attributes[$object->table_element]['type'][$key] == 'separate') {
1242  continue;
1243  }
1244  if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key])) {
1245  continue;
1246  }
1247 
1248  if (in_array($extrafields->attributes[$object->table_element]['type'][$key], array('timestamp', 'date', 'datetime'))) {
1249  $position = (empty($extrafields->attributes[$object->table_element]['pos'][$key]) ? 0 : intVal($extrafields->attributes[$object->table_element]['pos'][$key]));
1250  $arrayofxaxis[preg_replace('/^t/', 'te', $tablealias).'.'.$key.'-year'] = array(
1251  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val).' <span class="opacitymedium">('.$YYYY.')</span>',
1252  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1253  'position' => ($position + ($count * 100000)).'.1',
1254  'table' => $object->table_element,
1255  'tablefromt' => $tablepath
1256  );
1257  $arrayofxaxis[preg_replace('/^t/', 'te', $tablealias).'.'.$key.'-month'] = array(
1258  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val).' <span class="opacitymedium">('.$YYYY.'-'.$MM.')</span>',
1259  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1260  'position' => ($position + ($count * 100000)).'.2',
1261  'table' => $object->table_element,
1262  'tablefromt' => $tablepath
1263  );
1264  $arrayofxaxis[preg_replace('/^t/', 'te', $tablealias).'.'.$key.'-day'] = array(
1265  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val).' <span class="opacitymedium">('.$YYYY.'-'.$MM.'-'.$DD.')</span>',
1266  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1267  'position' => ($position + ($count * 100000)).'.3',
1268  'table' => $object->table_element,
1269  'tablefromt' => $tablepath
1270  );
1271  } else {
1272  $arrayofxaxis[preg_replace('/^t/', 'te', $tablealias).'.'.$key] = array(
1273  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val),
1274  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1275  'position' => 1000 + (int) $extrafields->attributes[$object->table_element]['pos'][$key] + ($count * 100000),
1276  'table' => $object->table_element,
1277  'tablefromt' => $tablepath
1278  );
1279  }
1280  }
1281  }
1282 
1283  // Add fields for parent objects
1284  foreach ($object->fields as $key => $val) {
1285  if (preg_match('/^[^:]+:[^:]+:/', $val['type'])) {
1286  $tmptype = explode(':', $val['type'], 4);
1287  if ($tmptype[0] == 'integer' && $tmptype[1] && $tmptype[2]) {
1288  $newobject = $tmptype[1];
1289  dol_include_once($tmptype[2]);
1290  if (class_exists($newobject)) {
1291  $tmpobject = new $newobject($db);
1292  //var_dump($key); var_dump($tmpobject->element); var_dump($val['label']); var_dump($tmptype); var_dump('t-'.$key);
1293  $count++;
1294  $arrayofxaxis = fillArrayOfXAxis($tmpobject, $tablealias.'__'.$key, $langs->trans($val['label']), $arrayofxaxis, $level + 1, $count, $tablepath);
1295  } else {
1296  print 'For property '.$object->element.'->'.$key.', type="'.$val['type'].'": Failed to find class '.$newobject." in file ".$tmptype[2]."<br>\n";
1297  }
1298  }
1299  }
1300  }
1301 
1302  return $arrayofxaxis;
1303 }
1304 
1305 
1318 function fillArrayOfGroupBy($object, $tablealias, $labelofobject, &$arrayofgroupby, $level = 0, &$count = 0, &$tablepath = '')
1319 {
1320  global $langs, $extrafields, $db;
1321 
1322  if ($level >= 3) {
1323  return $arrayofgroupby;
1324  }
1325 
1326  if (empty($tablepath)) {
1327  $tablepath = $object->table_element.'='.$tablealias;
1328  } else {
1329  $tablepath .= ','.$object->table_element.'='.$tablealias;
1330  }
1331 
1332  $YYYY = substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1).substr($langs->trans("Year"), 0, 1);
1333  $MM = substr($langs->trans("Month"), 0, 1).substr($langs->trans("Month"), 0, 1);
1334  $DD = substr($langs->trans("Day"), 0, 1).substr($langs->trans("Day"), 0, 1);
1335  $HH = substr($langs->trans("Hour"), 0, 1).substr($langs->trans("Hour"), 0, 1);
1336  $MI = substr($langs->trans("Minute"), 0, 1).substr($langs->trans("Minute"), 0, 1);
1337  $SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1);
1338 
1339  // Note: here $tablealias can be 't' or 't__fk_contract' or 't_fk_contract_fk_soc'
1340 
1341  // Add main fields of object
1342  foreach ($object->fields as $key => $val) {
1343  if (empty($val['isameasure'])) {
1344  if (in_array($key, array(
1345  'id', 'ref_ext', 'rowid', 'entity', 'last_main_doc', 'logo', 'logo_squarred', 'extraparams',
1346  'parent', 'photo', 'socialnetworks', 'webservices_url', 'webservices_key'))) {
1347  continue;
1348  }
1349  if (isset($val['enabled']) && !dol_eval($val['enabled'], 1, 1, '1')) {
1350  continue;
1351  }
1352  if (isset($val['visible']) && !dol_eval($val['visible'], 1, 1, '1')) {
1353  continue;
1354  }
1355  if (preg_match('/^fk_/', $key) && !preg_match('/^fk_statu/', $key)) {
1356  continue;
1357  }
1358  if (preg_match('/^pass/', $key)) {
1359  continue;
1360  }
1361  if (in_array($val['type'], array('html', 'text'))) {
1362  continue;
1363  }
1364  if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) {
1365  $position = (empty($val['position']) ? 0 : intVal($val['position']));
1366  $arrayofgroupby[$tablealias.'.'.$key.'-year'] = array(
1367  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.')</span>',
1368  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1369  'position' => ($position + ($count * 100000)).'.1',
1370  'table' => $object->table_element,
1371  'tablefromt' => $tablepath
1372  );
1373  $arrayofgroupby[$tablealias.'.'.$key.'-month'] = array(
1374  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.'-'.$MM.')</span>',
1375  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1376  'position' => ($position + ($count * 100000)).'.2',
1377  'table' => $object->table_element,
1378  'tablefromt' => $tablepath
1379  );
1380  $arrayofgroupby[$tablealias.'.'.$key.'-day'] = array(
1381  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.'-'.$MM.'-'.$DD.')</span>',
1382  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1383  'position' => ($position + ($count * 100000)).'.3',
1384  'table' => $object->table_element,
1385  'tablefromt' => $tablepath
1386  );
1387  } else {
1388  $position = (empty($val['position']) ? 0 : intVal($val['position']));
1389  $arrayofgroupby[$tablealias.'.'.$key] = array(
1390  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']),
1391  'labelnohtml' => $labelofobject.': '.$langs->trans($val['label']),
1392  'position' => ($position + ($count * 100000)),
1393  'table' => $object->table_element,
1394  'tablefromt' => $tablepath
1395  );
1396  }
1397  }
1398  }
1399 
1400  // Add extrafields to Group by
1401  if (!empty($object->isextrafieldmanaged)) {
1402  foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
1403  if ($extrafields->attributes[$object->table_element]['type'][$key] == 'separate') {
1404  continue;
1405  }
1406  if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key])) {
1407  continue;
1408  }
1409 
1410  if (in_array($extrafields->attributes[$object->table_element]['type'][$key], array('timestamp', 'date', 'datetime'))) {
1411  $position = (empty($extrafields->attributes[$object->table_element]['pos'][$key]) ? 0 : intVal($extrafields->attributes[$object->table_element]['pos'][$key]));
1412  $arrayofgroupby[preg_replace('/^t/', 'te', $tablealias).'.'.$key.'-year'] = array(
1413  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val).' <span class="opacitymedium">('.$YYYY.')</span>',
1414  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1415  'position' => ($position + ($count * 100000)).'.1',
1416  'table' => $object->table_element,
1417  'tablefromt' => $tablepath
1418  );
1419  $arrayofgroupby[preg_replace('/^t/', 'te', $tablealias).'.'.$key.'-month'] = array(
1420  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val).' <span class="opacitymedium">('.$YYYY.'-'.$MM.')</span>',
1421  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1422  'position' => ($position + ($count * 100000)).'.2',
1423  'table' => $object->table_element,
1424  'tablefromt' => $tablepath
1425  );
1426  $arrayofgroupby[preg_replace('/^t/', 'te', $tablealias).'.'.$key.'-day'] = array(
1427  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val).' <span class="opacitymedium">('.$YYYY.'-'.$MM.'-'.$DD.')</span>',
1428  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1429  'position' => ($position + ($count * 100000)).'.3',
1430  'table' => $object->table_element,
1431  'tablefromt' => $tablepath
1432  );
1433  } else {
1434  $arrayofgroupby[preg_replace('/^t/', 'te', $tablealias).'.'.$key] = array(
1435  'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val),
1436  'labelnohtml' => $labelofobject.': '.$langs->trans($val),
1437  'position' => 1000 + (int) $extrafields->attributes[$object->table_element]['pos'][$key] + ($count * 100000),
1438  'table' => $object->table_element,
1439  'tablefromt' => $tablepath
1440  );
1441  }
1442  }
1443  }
1444 
1445  // Add fields for parent objects
1446  foreach ($object->fields as $key => $val) {
1447  if (preg_match('/^[^:]+:[^:]+:/', $val['type'])) {
1448  $tmptype = explode(':', $val['type'], 4);
1449  if ($tmptype[0] == 'integer' && $tmptype[1] && $tmptype[2]) {
1450  $newobject = $tmptype[1];
1451  dol_include_once($tmptype[2]);
1452  if (class_exists($newobject)) {
1453  $tmpobject = new $newobject($db);
1454  //var_dump($key); var_dump($tmpobject->element); var_dump($val['label']); var_dump($tmptype); var_dump('t-'.$key);
1455  $count++;
1456  $arrayofgroupby = fillArrayOfGroupBy($tmpobject, $tablealias.'__'.$key, $langs->trans($val['label']), $arrayofgroupby, $level + 1, $count, $tablepath);
1457  } else {
1458  print 'For property '.$object->element.'->'.$key.', type="'.$val['type'].'": Failed to find class '.$newobject." in file ".$tmptype[2]."<br>\n";
1459  }
1460  }
1461  }
1462  }
1463 
1464  return $arrayofgroupby;
1465 }
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
Class to build graphs.
Class to manage standard extra fields.
Class to manage generation of HTML components Only common components must be here.
Classe permettant la generation de composants html autre Only common components are here.
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
fillArrayOfGroupBy($object, $tablealias, $labelofobject, &$arrayofgroupby, $level=0, &$count=0, &$tablepath='')
Fill arrayofgrupby for an object.
fillArrayOfMeasures($object, $tablealias, $labelofobject, &$arrayofmesures, $level=0, &$count=0, &$tablepath='')
Fill arrayofmesures for an object.
fillArrayOfXAxis($object, $tablealias, $labelofobject, &$arrayofxaxis, $level=0, &$count=0, &$tablepath='')
Fill arrayofmesures for an object.
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition: date.lib.php:595
dolExplodeIntoArray($string, $delimiter=';', $kv='=')
Split a string with 2 keys into key array.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
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.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
dol_now($mode='auto')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by second index function, which produces ascending (default) or descending output...
dol_eval($s, $returnvalue=0, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.