customreports.php 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304
  1. <?php
  2. /* Copyright (C) 2020 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. /**
  22. * \file htdocs/core/customreports.php
  23. * \ingroup core
  24. * \brief Page to make custom reports
  25. */
  26. if (!defined('USE_CUSTOM_REPORT_AS_INCLUDE')) {
  27. require '../main.inc.php';
  28. // Get parameters
  29. $action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ...
  30. $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
  31. $mode = GETPOST('mode', 'alpha') ? GETPOST('mode', 'alpha') : 'graph';
  32. $objecttype = GETPOST('objecttype', 'aZ09');
  33. $tabfamily = GETPOST('tabfamily', 'aZ09');
  34. if (empty($objecttype)) {
  35. $objecttype = 'thirdparty';
  36. }
  37. $search_measures = GETPOST('search_measures', 'array');
  38. //$search_xaxis = GETPOST('search_xaxis', 'array');
  39. if (GETPOST('search_xaxis', 'alpha') && GETPOST('search_xaxis', 'alpha') != '-1') {
  40. $search_xaxis = array(GETPOST('search_xaxis', 'alpha'));
  41. } else {
  42. $search_xaxis = array();
  43. }
  44. //$search_groupby = GETPOST('search_groupby', 'array');
  45. if (GETPOST('search_groupby', 'alpha') && GETPOST('search_groupby', 'alpha') != '-1') {
  46. $search_groupby = array(GETPOST('search_groupby', 'alpha'));
  47. } else {
  48. $search_groupby = array();
  49. }
  50. $search_yaxis = GETPOST('search_yaxis', 'array');
  51. $search_graph = GETPOST('search_graph', 'restricthtml');
  52. // Load variable for pagination
  53. $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
  54. $sortfield = GETPOST('sortfield', 'aZ09comma');
  55. $sortorder = GETPOST('sortorder', 'aZ09comma');
  56. $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
  57. if (empty($page) || $page == -1 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha') || (empty($toselect) && $massaction === '0')) {
  58. $page = 0;
  59. } // If $page is not defined, or '' or -1 or if we click on clear filters or if we select empty mass action
  60. $offset = $limit * $page;
  61. $pageprev = $page - 1;
  62. $pagenext = $page + 1;
  63. $diroutputmassaction = $conf->user->dir_temp.'/'.$user->id.'/customreport';
  64. }
  65. require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php";
  66. require_once DOL_DOCUMENT_ROOT."/core/lib/company.lib.php";
  67. require_once DOL_DOCUMENT_ROOT."/core/class/dolgraph.class.php";
  68. require_once DOL_DOCUMENT_ROOT."/core/class/doleditor.class.php";
  69. require_once DOL_DOCUMENT_ROOT."/core/class/html.formother.class.php";
  70. // Load traductions files requiredby by page
  71. $langs->loadLangs(array("companies", "other", "exports", "sendings"));
  72. $extrafields = new ExtraFields($db);
  73. $hookmanager->initHooks(array('customreport')); // Note that conf->hooks_modules contains array
  74. $title = '';
  75. $picto = '';
  76. $head = array();
  77. $object = null;
  78. $ObjectClassName = '';
  79. // Objects available by default
  80. $arrayoftype = array(
  81. 'thirdparty' => array('label' => 'ThirdParties', 'ObjectClassName' => 'Societe', 'enabled' => isModEnabled('societe'), 'ClassPath' => "/societe/class/societe.class.php"),
  82. 'contact' => array('label' => 'Contacts', 'ObjectClassName' => 'Contact', 'enabled' => isModEnabled('societ'), 'ClassPath' => "/contact/class/contact.class.php"),
  83. 'proposal' => array('label' => 'Proposals', 'ObjectClassName' => 'Propal', 'enabled' => isModEnabled('propal'), 'ClassPath' => "/comm/propal/class/propal.class.php"),
  84. 'order' => array('label' => 'Orders', 'ObjectClassName' => 'Commande', 'enabled' => isModEnabled('commande'), 'ClassPath' => "/commande/class/commande.class.php"),
  85. 'invoice' => array('label' => 'Invoices', 'ObjectClassName' => 'Facture', 'enabled' => isModEnabled('facture'), 'ClassPath' => "/compta/facture/class/facture.class.php"),
  86. 'invoice_template'=>array('label' => 'PredefinedInvoices', 'ObjectClassName' => 'FactureRec', 'enabled' => isModEnabled('facture'), 'ClassPath' => "/compta/class/facturerec.class.php", 'langs'=>'bills'),
  87. 'contract' => array('label' => 'Contracts', 'ObjectClassName' => 'Contrat', 'enabled' => isModEnabled('contrat'), 'ClassPath' => "/contrat/class/contrat.class.php", 'langs'=>'contracts'),
  88. 'contractdet' => array('label' => 'ContractLines', 'ObjectClassName' => 'ContratLigne', 'enabled' => isModEnabled('contrat'), 'ClassPath' => "/contrat/class/contrat.class.php", 'langs'=>'contracts'),
  89. 'bom' => array('label' => 'BOM', 'ObjectClassName' => 'Bom', 'enabled' => isModEnabled('bom')),
  90. 'mo' => array('label' => 'MO', 'ObjectClassName' => 'Mo', 'enabled' => isModEnabled('mrp'), 'ClassPath' => "/mrp/class/mo.class.php"),
  91. 'ticket' => array('label' => 'Ticket', 'ObjectClassName' => 'Ticket', 'enabled' => isModEnabled('ticket')),
  92. 'member' => array('label' => 'Adherent', 'ObjectClassName' => 'Adherent', 'enabled' => isModEnabled('adherent'), 'ClassPath' => "/adherents/class/adherent.class.php", 'langs'=>'members'),
  93. 'cotisation' => array('label' => 'Subscriptions', 'ObjectClassName' => 'Subscription', 'enabled' => isModEnabled('adherent'), 'ClassPath' => "/adherents/class/subscription.class.php", 'langs'=>'members'),
  94. );
  95. // Complete $arrayoftype by external modules
  96. $parameters = array('objecttype'=>$objecttype, 'tabfamily'=>$tabfamily);
  97. $reshook = $hookmanager->executeHooks('loadDataForCustomReports', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  98. if ($reshook < 0) {
  99. setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  100. } elseif (is_array($hookmanager->resArray)) {
  101. if (!empty($hookmanager->resArray['title'])) { // Add entries for tabs
  102. $title = $hookmanager->resArray['title'];
  103. }
  104. if (!empty($hookmanager->resArray['picto'])) { // Add entries for tabs
  105. $picto = $hookmanager->resArray['picto'];
  106. }
  107. if (!empty($hookmanager->resArray['head'])) { // Add entries for tabs
  108. $head = array_merge($head, $hookmanager->resArray['head']);
  109. }
  110. if (!empty($hookmanager->resArray['arrayoftype'])) { // Add entries from hook
  111. foreach ($hookmanager->resArray['arrayoftype'] as $key => $val) {
  112. $arrayoftype[$key] = $val;
  113. }
  114. }
  115. }
  116. if ($objecttype) {
  117. try {
  118. if (!empty($arrayoftype[$objecttype]['ClassPath'])) {
  119. dol_include_once($arrayoftype[$objecttype]['ClassPath']);
  120. } else {
  121. dol_include_once("/".$objecttype."/class/".$objecttype.".class.php");
  122. }
  123. $ObjectClassName = $arrayoftype[$objecttype]['ObjectClassName'];
  124. $object = new $ObjectClassName($db);
  125. } catch (Exception $e) {
  126. print 'Failed to load class for type '.$objecttype;
  127. }
  128. }
  129. // Security check
  130. $socid = 0;
  131. if ($user->socid > 0) { // Protection if external user
  132. //$socid = $user->socid;
  133. accessforbidden();
  134. }
  135. // Fetch optionals attributes and labels
  136. $extrafields->fetch_name_optionals_label($object->table_element);
  137. //$extrafields->fetch_name_optionals_label($object->table_element_line);
  138. $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
  139. $search_component_params = array('');
  140. $search_component_params_hidden = GETPOST('search_component_params_hidden', 'alphanohtml');
  141. // For the case we enter a criteria manually, the search_component_params_input will be defined and must be used in priority
  142. if (GETPOST('search_component_params_input', 'alphanohtml')) {
  143. $search_component_params_hidden = GETPOST('search_component_params_input', 'alphanohtml');
  144. }
  145. $MAXUNIQUEVALFORGROUP = 20;
  146. $MAXMEASURESINBARGRAPH = 20;
  147. $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);
  148. $MM = substr($langs->trans("Month"), 0, 1).substr($langs->trans("Month"), 0, 1);
  149. $DD = substr($langs->trans("Day"), 0, 1).substr($langs->trans("Day"), 0, 1);
  150. $HH = substr($langs->trans("Hour"), 0, 1).substr($langs->trans("Hour"), 0, 1);
  151. $MI = substr($langs->trans("Minute"), 0, 1).substr($langs->trans("Minute"), 0, 1);
  152. $SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1);
  153. $arrayofmesures = array();
  154. $arrayofxaxis = array();
  155. $arrayofgroupby = array();
  156. $arrayofyaxis = array();
  157. $arrayofvaluesforgroupby = array();
  158. $features = $object->element;
  159. if (!empty($object->element_for_permission)) {
  160. $features = $object->element_for_permission;
  161. }
  162. restrictedArea($user, $features, 0, '');
  163. $error = 0;
  164. /*
  165. * Actions
  166. */
  167. // None
  168. /*
  169. * View
  170. */
  171. $form = new Form($db);
  172. $formother = new FormOther($db);
  173. if (!defined('USE_CUSTOM_REPORT_AS_INCLUDE')) {
  174. llxHeader('', $langs->transnoentitiesnoconv('CustomReports'), '');
  175. print dol_get_fiche_head($head, 'customreports', $title, -1, $picto);
  176. }
  177. $newarrayoftype = array();
  178. foreach ($arrayoftype as $key => $val) {
  179. if (dol_eval($val['enabled'], 1, 1, '1')) {
  180. $newarrayoftype[$key] = $arrayoftype[$key];
  181. }
  182. if (!empty($val['langs'])) {
  183. $langs->load($val['langs']);
  184. }
  185. }
  186. $count = 0;
  187. $arrayofmesures = fillArrayOfMeasures($object, 't', $langs->trans($newarrayoftype[$objecttype]['label']), $arrayofmesures, 0, $count);
  188. $arrayofmesures = dol_sort_array($arrayofmesures, 'position', 'asc', 0, 0, 1);
  189. $count = 0;
  190. $arrayofxaxis = fillArrayOfXAxis($object, 't', $langs->trans($newarrayoftype[$objecttype]['label']), $arrayofxaxis, 0, $count);
  191. $arrayofxaxis = dol_sort_array($arrayofxaxis, 'position', 'asc', 0, 0, 1);
  192. $count = 0;
  193. $arrayofgroupby = fillArrayOfGroupBy($object, 't', $langs->trans($newarrayoftype[$objecttype]['label']), $arrayofgroupby, 0, $count);
  194. $arrayofgroupby = dol_sort_array($arrayofgroupby, 'position', 'asc', 0, 0, 1);
  195. // Check parameters
  196. if ($action == 'viewgraph') {
  197. if (!count($search_measures)) {
  198. setEventMessages($langs->trans("AtLeastOneMeasureIsRequired"), null, 'warnings');
  199. } elseif ($mode == 'graph' && count($search_xaxis) > 1) {
  200. setEventMessages($langs->trans("OnlyOneFieldForXAxisIsPossible"), null, 'warnings');
  201. $search_xaxis = array(0 => $search_xaxis[0]);
  202. }
  203. if (count($search_groupby) >= 2) {
  204. setEventMessages($langs->trans("ErrorOnlyOneFieldForGroupByIsPossible"), null, 'warnings');
  205. $search_groupby = array(0 => $search_groupby[0]);
  206. }
  207. if (!count($search_xaxis)) {
  208. setEventMessages($langs->trans("AtLeastOneXAxisIsRequired"), null, 'warnings');
  209. } elseif ($mode == 'graph' && $search_graph == 'bars' && count($search_measures) > $MAXMEASURESINBARGRAPH) {
  210. $langs->load("errors");
  211. setEventMessages($langs->trans("GraphInBarsAreLimitedToNMeasures", $MAXMEASURESINBARGRAPH), null, 'warnings');
  212. $search_graph = 'lines';
  213. }
  214. }
  215. // Get all possible values of fields when a 'group by' is set, and save this into $arrayofvaluesforgroupby
  216. // $arrayofvaluesforgroupby will be used to forge lael of each grouped series
  217. if (is_array($search_groupby) && count($search_groupby)) {
  218. foreach ($search_groupby as $gkey => $gval) {
  219. $gvalwithoutprefix = preg_replace('/^[a-z]+\./', '', $gval);
  220. if (preg_match('/\-year$/', $search_groupby[$gkey])) {
  221. $tmpval = preg_replace('/\-year$/', '', $search_groupby[$gkey]);
  222. $fieldtocount .= 'DATE_FORMAT('.$tmpval.", '%Y')";
  223. } elseif (preg_match('/\-month$/', $search_groupby[$gkey])) {
  224. $tmpval = preg_replace('/\-month$/', '', $search_groupby[$gkey]);
  225. $fieldtocount .= 'DATE_FORMAT('.$tmpval.", '%Y-%m')";
  226. } elseif (preg_match('/\-day$/', $search_groupby[$gkey])) {
  227. $tmpval = preg_replace('/\-day$/', '', $search_groupby[$gkey]);
  228. $fieldtocount .= 'DATE_FORMAT('.$tmpval.", '%Y-%m-%d')";
  229. } else {
  230. $fieldtocount = $search_groupby[$gkey];
  231. }
  232. $sql = "SELECT DISTINCT ".$fieldtocount." as val";
  233. if (strpos($fieldtocount, 'te.') === 0) {
  234. $sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element."_extrafields as te";
  235. } else {
  236. $tabletouse = $object->table_element;
  237. $tablealiastouse = 't';
  238. if (!empty($arrayofgroupby[$gval])) {
  239. $tmpval = explode('.', $gval);
  240. $tabletouse = $arrayofgroupby[$gval]['table'];
  241. $tablealiastouse = $tmpval[0];
  242. }
  243. $sql .= " FROM ".MAIN_DB_PREFIX.$tabletouse." as ".$tablealiastouse;
  244. }
  245. // Add the where here
  246. /*
  247. $sqlfilters = GETPOST('search_component_params_hidden', 'alphanohtml');
  248. if ($sqlfilters) {
  249. $errormessage = '';
  250. if (dolCheckFilters($sqlfilters, $errormessage)) {
  251. $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
  252. $sql .= " WHERE (".preg_replace_callback('/'.$regexstring.'/', 'dolForgeCriteriaCallback', $sqlfilters).")";
  253. } else {
  254. print $errormessage;
  255. }
  256. }*/
  257. $sql .= " LIMIT ".((int) ($MAXUNIQUEVALFORGROUP + 1));
  258. //print $sql;
  259. $resql = $db->query($sql);
  260. if (!$resql) {
  261. dol_print_error($db);
  262. }
  263. while ($obj = $db->fetch_object($resql)) {
  264. if (is_null($obj->val)) {
  265. $keytouse = '__NULL__';
  266. $valuetranslated = $langs->transnoentitiesnoconv("NotDefined");
  267. } elseif ($obj->val === '') {
  268. $keytouse = '';
  269. $valuetranslated = $langs->transnoentitiesnoconv("Empty");
  270. } else {
  271. $keytouse = (string) $obj->val;
  272. $valuetranslated = $obj->val;
  273. }
  274. $regs = array();
  275. if (!empty($object->fields[$gvalwithoutprefix]['arrayofkeyval'])) {
  276. $valuetranslated = $object->fields[$gvalwithoutprefix]['arrayofkeyval'][$obj->val];
  277. if (is_null($valuetranslated)) {
  278. $valuetranslated = $langs->transnoentitiesnoconv("UndefinedKey");
  279. }
  280. $valuetranslated = $langs->trans($valuetranslated);
  281. } elseif (preg_match('/integer:([^:]+):([^:]+)$/', $object->fields[$gvalwithoutprefix]['type'], $regs)) {
  282. $classname = $regs[1];
  283. $classpath = $regs[2];
  284. dol_include_once($classpath);
  285. if (class_exists($classname)) {
  286. $tmpobject = new $classname($db);
  287. $tmpobject->fetch($obj->val);
  288. foreach ($tmpobject->fields as $fieldkey => $field) {
  289. if ($field['showoncombobox']) {
  290. $valuetranslated = $tmpobject->$fieldkey;
  291. //if ($valuetranslated == '-') $valuetranslated = $langs->transnoentitiesnoconv("Unknown")
  292. break;
  293. }
  294. }
  295. //$valuetranslated = $tmpobject->ref.'eee';
  296. }
  297. }
  298. $arrayofvaluesforgroupby['g_'.$gkey][$keytouse] = $valuetranslated;
  299. }
  300. // Add also the possible NULL value if field is a parent field that is not a strict join
  301. $tmpfield = explode('.', $gval);
  302. if ($tmpfield[0] != 't' || (is_array($object->fields[$tmpfield[1]]) && empty($object->fields[$tmpfield[1]]['notnull']))) {
  303. 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");
  304. //var_dump($gval); var_dump($object->fields);
  305. $arrayofvaluesforgroupby['g_'.$gkey]['__NULL__'] = $langs->transnoentitiesnoconv("NotDefined");
  306. }
  307. asort($arrayofvaluesforgroupby['g_'.$gkey]);
  308. // Add a protection/error to refuse the request if number of differentr values for the group by is higher than $MAXUNIQUEVALFORGROUP
  309. if (count($arrayofvaluesforgroupby['g_'.$gkey]) > $MAXUNIQUEVALFORGROUP) {
  310. $langs->load("errors");
  311. if (strpos($fieldtocount, 'te.') === 0) { // This is an extrafield
  312. //if (!empty($extrafields->attributes[$object->table_element]['langfile'][$gvalwithoutprefix])) {
  313. // $langs->load($extrafields->attributes[$object->table_element]['langfile'][$gvalwithoutprefix]);
  314. //}
  315. $keyforlabeloffield = $extrafields->attributes[$object->table_element]['label'][$gvalwithoutprefix];
  316. $labeloffield = $langs->transnoentitiesnoconv($keyforlabeloffield);
  317. } elseif (strpos($fieldtocount, 't__') === 0) { // This is a field of a foreign key
  318. $reg = array();
  319. if (preg_match('/^(.*)\.(.*)/', $gvalwithoutprefix, $reg)) {
  320. $gvalwithoutprefix = preg_replace('/\..*$/', '', $gvalwithoutprefix);
  321. $gvalwithoutprefix = preg_replace('/t__/', '', $gvalwithoutprefix);
  322. $keyforlabeloffield = $object->fields[$gvalwithoutprefix]['label'];
  323. $labeloffield = $langs->transnoentitiesnoconv($keyforlabeloffield).'-'.$reg[2];
  324. } else {
  325. $labeloffield = $langs->transnoentitiesnoconv($keyforlabeloffield);
  326. }
  327. } else { // This is a common field
  328. $reg = array();
  329. if (preg_match('/^(.*)\-(year|month|day)/', $gvalwithoutprefix, $reg)) {
  330. $gvalwithoutprefix = preg_replace('/\-(year|month|day)/', '', $gvalwithoutprefix);
  331. $keyforlabeloffield = $object->fields[$gvalwithoutprefix]['label'];
  332. $labeloffield = $langs->transnoentitiesnoconv($keyforlabeloffield).'-'.$reg[2];
  333. } else {
  334. $keyforlabeloffield = $object->fields[$gvalwithoutprefix]['label'];
  335. $labeloffield = $langs->transnoentitiesnoconv($keyforlabeloffield);
  336. }
  337. }
  338. //var_dump($gkey.' '.$gval.' '.$gvalwithoutprefix.' '.$fieldtocount.' '.$keyforlabeloffield);
  339. //var_dump($object->fields);
  340. setEventMessages($langs->trans("ErrorTooManyDifferentValueForSelectedGroupBy", $MAXUNIQUEVALFORGROUP, $labeloffield), null, 'warnings');
  341. $search_groupby = array();
  342. }
  343. $db->free($resql);
  344. }
  345. }
  346. //var_dump($arrayofvaluesforgroupby);exit;
  347. $tmparray = dol_getdate(dol_now());
  348. $endyear = $tmparray['year'];
  349. $endmonth = $tmparray['mon'];
  350. $datelastday = dol_get_last_day($endyear, $endmonth, 1);
  351. $startyear = $endyear - 2;
  352. $param = '';
  353. print '<form method="post" action="'.$_SERVER['PHP_SELF'].'">';
  354. print '<input type="hidden" name="token" value="'.newToken().'">';
  355. print '<input type="hidden" name="action" value="viewgraph">';
  356. print '<input type="hidden" name="tabfamily" value="'.$tabfamily.'">';
  357. $viewmode = '';
  358. $viewmode .= '<div class="divadvancedsearchfield">';
  359. $arrayofgraphs = array('bars' => 'Bars', 'lines' => 'Lines'); // also 'pies'
  360. $viewmode .= '<div class="inline-block opacitymedium"><span class="fas fa-chart-area paddingright" title="'.$langs->trans("Graph").'"></span>'.$langs->trans("Graph").'</div> ';
  361. $viewmode .= $form->selectarray('search_graph', $arrayofgraphs, $search_graph, 0, 0, 0, 'minwidth100', 1);
  362. $viewmode .= '</div>';
  363. $num = 0;
  364. $massactionbutton = '';
  365. $nav = '';
  366. $newcardbutton = '';
  367. $limit = 0;
  368. 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);
  369. print '<div class="liste_titre liste_titre_bydiv centpercent">';
  370. // Select object
  371. print '<div class="divadvancedsearchfield center floatnone">';
  372. print '<div class="inline-block"><span class="opacitymedium">'.$langs->trans("StatisticsOn").'</span></div> ';
  373. print $form->selectarray('objecttype', $newarrayoftype, $objecttype, 0, 0, 0, '', 1, 0, 0, '', 'minwidth200', 1);
  374. if (empty($conf->use_javascript_ajax)) {
  375. print '<input type="submit" class="button buttongen button-save nomargintop" name="changeobjecttype" value="'.$langs->trans("Refresh").'">';
  376. } else {
  377. print '<!-- js code to reload page with good object type -->
  378. <script type="text/javascript">
  379. jQuery(document).ready(function() {
  380. jQuery("#objecttype").change(function() {
  381. console.log("Reload for "+jQuery("#objecttype").val());
  382. 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')) : '').'";
  383. });
  384. });
  385. </script>';
  386. }
  387. print '</div><div class="clearboth"></div>';
  388. // Add Filter (you can use param &show_search_component_params_hidden=1 for debug)
  389. print '<div class="divadvancedsearchfield quatrevingtpercent">';
  390. print $form->searchComponent(array($object->element => $object->fields), $search_component_params, array(), $search_component_params_hidden);
  391. print '</div>';
  392. // Add measures into array
  393. $count = 0;
  394. //var_dump($arrayofmesures);
  395. print '<div class="divadvancedsearchfield clearboth">';
  396. 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>';
  397. $simplearrayofmesures = array();
  398. foreach ($arrayofmesures as $key => $val) {
  399. $simplearrayofmesures[$key] = $arrayofmesures[$key]['label'];
  400. }
  401. print $form->multiselectarray('search_measures', $simplearrayofmesures, $search_measures, 0, 0, 'minwidth300', 1, 0, '', '', $langs->trans("Measures")); // Fill the array $arrayofmeasures with possible fields
  402. print '</div>';
  403. // XAxis
  404. $count = 0;
  405. print '<div class="divadvancedsearchfield">';
  406. 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>';
  407. //var_dump($arrayofxaxis);
  408. print $formother->selectXAxisField($object, $search_xaxis, $arrayofxaxis, $langs->trans("XAxis"), 'minwidth300 maxwidth400'); // Fill the array $arrayofxaxis with possible fields
  409. print '</div>';
  410. // Group by
  411. $count = 0;
  412. print '<div class="divadvancedsearchfield">';
  413. print '<div class="inline-block opacitymedium"><span class="fas fa-ruler-horizontal paddingright pictofixedwidth" title="'.dol_escape_htmltag($langs->trans("GroupBy")).'"></span></div>';
  414. print $formother->selectGroupByField($object, $search_groupby, $arrayofgroupby, 'minwidth250 maxwidth300', $langs->trans("GroupBy")); // Fill the array $arrayofgroupby with possible fields
  415. print '</div>';
  416. if ($mode == 'grid') {
  417. // YAxis
  418. print '<div class="divadvancedsearchfield">';
  419. foreach ($object->fields as $key => $val) {
  420. if (empty($val['measure']) && (!isset($val['enabled']) || dol_eval($val['enabled'], 1, 1, '1'))) {
  421. if (in_array($key, array('id', 'rowid', 'entity', 'last_main_doc', 'extraparams'))) {
  422. continue;
  423. }
  424. if (preg_match('/^fk_/', $key)) {
  425. continue;
  426. }
  427. if (in_array($val['type'], array('html', 'text'))) {
  428. continue;
  429. }
  430. if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) {
  431. $arrayofyaxis['t.'.$key.'-year'] = array(
  432. 'label' => $langs->trans($val['label']).' ('.$YYYY.')',
  433. 'position' => $val['position'],
  434. 'table' => $object->table_element
  435. );
  436. $arrayofyaxis['t.'.$key.'-month'] = array(
  437. 'label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.')',
  438. 'position' => $val['position'],
  439. 'table' => $object->table_element
  440. );
  441. $arrayofyaxis['t.'.$key.'-day'] = array(
  442. 'label' => $langs->trans($val['label']).' ('.$YYYY.'-'.$MM.'-'.$DD.')',
  443. 'position' => $val['position'],
  444. 'table' => $object->table_element
  445. );
  446. } else {
  447. $arrayofyaxis['t.'.$key] = array(
  448. 'label' => $val['label'],
  449. 'position' => (int) $val['position'],
  450. 'table' => $object->table_element
  451. );
  452. }
  453. }
  454. }
  455. // Add measure from extrafields
  456. if ($object->isextrafieldmanaged) {
  457. foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
  458. 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'))) {
  459. $arrayofyaxis['te.'.$key] = array(
  460. 'label' => $extrafields->attributes[$object->table_element]['label'][$key],
  461. 'position' => (int) $extrafields->attributes[$object->table_element]['pos'][$key],
  462. 'table' => $object->table_element
  463. );
  464. }
  465. }
  466. }
  467. $arrayofyaxis = dol_sort_array($arrayofyaxis, 'position');
  468. $arrayofyaxislabel = array();
  469. foreach ($arrayofyaxis as $key => $val) {
  470. $arrayofyaxislabel[$key] = $val['label'];
  471. }
  472. print '<div class="inline-block opacitymedium"><span class="fas fa-ruler-vertical paddingright" title="'.$langs->trans("YAxis").'"></span>'.$langs->trans("YAxis").'</div> ';
  473. print $form->multiselectarray('search_yaxis', $arrayofyaxislabel, $search_yaxis, 0, 0, 'minwidth100', 1);
  474. print '</div>';
  475. }
  476. if ($mode == 'graph') {
  477. //
  478. }
  479. print '<div class="divadvancedsearchfield">';
  480. print '<input type="submit" class="button buttongen button-save nomargintop" value="'.$langs->trans("Refresh").'">';
  481. print '</div>';
  482. print '</div>';
  483. print '</form>';
  484. // Generate the SQL request
  485. $sql = '';
  486. if (!empty($search_measures) && !empty($search_xaxis)) {
  487. $fieldid = 'rowid';
  488. $sql = "SELECT ";
  489. foreach ($search_xaxis as $key => $val) {
  490. if (preg_match('/\-year$/', $val)) {
  491. $tmpval = preg_replace('/\-year$/', '', $val);
  492. $sql .= "DATE_FORMAT(".$tmpval.", '%Y') as x_".$key.', ';
  493. } elseif (preg_match('/\-month$/', $val)) {
  494. $tmpval = preg_replace('/\-month$/', '', $val);
  495. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m') as x_".$key.', ';
  496. } elseif (preg_match('/\-day$/', $val)) {
  497. $tmpval = preg_replace('/\-day$/', '', $val);
  498. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d') as x_".$key.', ';
  499. } else {
  500. $sql .= $val." as x_".$key.", ";
  501. }
  502. }
  503. foreach ($search_groupby as $key => $val) {
  504. if (preg_match('/\-year$/', $val)) {
  505. $tmpval = preg_replace('/\-year$/', '', $val);
  506. $sql .= "DATE_FORMAT(".$tmpval.", '%Y') as g_".$key.', ';
  507. } elseif (preg_match('/\-month$/', $val)) {
  508. $tmpval = preg_replace('/\-month$/', '', $val);
  509. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m') as g_".$key.', ';
  510. } elseif (preg_match('/\-day$/', $val)) {
  511. $tmpval = preg_replace('/\-day$/', '', $val);
  512. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d') as g_".$key.', ';
  513. } else {
  514. $sql .= $val." as g_".$key.", ";
  515. }
  516. }
  517. foreach ($search_measures as $key => $val) {
  518. if ($val == 't.count') {
  519. $sql .= "COUNT(t.".$fieldid.") as y_".$key.', ';
  520. } elseif (preg_match('/\-sum$/', $val)) {
  521. $tmpval = preg_replace('/\-sum$/', '', $val);
  522. $sql .= "SUM(".$db->ifsql($tmpval.' IS NULL', '0', $tmpval).") as y_".$key.", ";
  523. } elseif (preg_match('/\-average$/', $val)) {
  524. $tmpval = preg_replace('/\-average$/', '', $val);
  525. $sql .= "AVG(".$db->ifsql($tmpval.' IS NULL', '0', $tmpval).") as y_".$key.", ";
  526. } elseif (preg_match('/\-min$/', $val)) {
  527. $tmpval = preg_replace('/\-min$/', '', $val);
  528. $sql .= "MIN(".$db->ifsql($tmpval.' IS NULL', '0', $tmpval).") as y_".$key.", ";
  529. } elseif (preg_match('/\-max$/', $val)) {
  530. $tmpval = preg_replace('/\-max$/', '', $val);
  531. $sql .= "MAX(".$db->ifsql($tmpval.' IS NULL', '0', $tmpval).") as y_".$key.", ";
  532. }
  533. }
  534. $sql = preg_replace('/,\s*$/', '', $sql);
  535. $sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t";
  536. // Add measure from extrafields
  537. if ($object->isextrafieldmanaged) {
  538. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as te ON te.fk_object = t.".$fieldid;
  539. }
  540. // Add table for link for multientity
  541. if ($object->ismultientitymanaged) { // 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table
  542. if ($object->ismultientitymanaged == 1) {
  543. // No table to add here
  544. } else {
  545. $tmparray = explode('@', $object->ismultientitymanaged);
  546. $sql .= " INNER JOIN ".MAIN_DB_PREFIX.$tmparray[1]." as parenttableforentity ON t.".$tmparray[0]." = parenttableforentity.rowid";
  547. $sql .= " AND parenttableforentity.entity IN (".getEntity($tmparray[1]).")";
  548. }
  549. }
  550. $listoftablesalreadyadded = array($object->table_element => $object->table_element);
  551. // Add LEFT JOIN for all parent tables mentionned into the Xaxis
  552. //var_dump($arrayofxaxis); var_dump($search_xaxis);
  553. foreach ($search_xaxis as $key => $val) {
  554. if (!empty($arrayofxaxis[$val])) {
  555. $tmpval = explode('.', $val);
  556. //var_dump($arrayofxaxis[$val]['table']);
  557. if (! in_array($arrayofxaxis[$val]['table'], $listoftablesalreadyadded)) { // We do not add join for main table already added
  558. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$arrayofxaxis[$val]['table']." as ".$db->sanitize($tmpval[0])." ON t.".str_replace('t__', '', $db->sanitize($tmpval[0]))." = ".$db->sanitize($tmpval[0]).".rowid";
  559. $listoftablesalreadyadded[$arrayofxaxis[$val]['table']] = $arrayofxaxis[$val]['table'];
  560. }
  561. } else {
  562. dol_print_error($db, 'Found a key into search_xaxis not found into arrayofxaxis');
  563. }
  564. }
  565. // Add LEFT JOIN for all parent tables mentionned into the Group by
  566. //var_dump($arrayofgroupby); var_dump($search_groupby);
  567. foreach ($search_groupby as $key => $val) {
  568. if (!empty($arrayofgroupby[$val])) {
  569. $tmpval = explode('.', $val);
  570. //var_dump($arrayofxaxis[$val]['table']);
  571. if (! in_array($arrayofgroupby[$val]['table'], $listoftablesalreadyadded)) { // We do not add join for main table already added
  572. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$arrayofgroupby[$val]['table']." as ".$tmpval[0]." ON t.".str_replace('t__', '', $tmpval[0])." = ".$tmpval[0].".rowid";
  573. $listoftablesalreadyadded[$arrayofgroupby[$val]['table']] = $arrayofgroupby[$val]['table'];
  574. }
  575. } else {
  576. dol_print_error($db, 'Found a key into search_groupby not found into arrayofgroupby');
  577. }
  578. }
  579. // Add LEFT JOIN for all parent tables mentionned into the Yaxis
  580. //var_dump($arrayofgroupby); var_dump($search_groupby);
  581. foreach ($search_measures as $key => $val) {
  582. if (!empty($arrayofmesures[$val])) {
  583. $tmpval = explode('.', $val);
  584. //var_dump($arrayofxaxis[$val]['table']);
  585. if (! in_array($arrayofmesures[$val]['table'], $listoftablesalreadyadded)) { // We do not add join for main table already added
  586. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$arrayofmesures[$val]['table']." as ".$tmpval[0]." ON t.".str_replace('t__', '', $tmpval[0])." = ".$tmpval[0].".rowid";
  587. $listoftablesalreadyadded[$arrayofmesures[$val]['table']] = $arrayofmesures[$val]['table'];
  588. }
  589. } else {
  590. dol_print_error($db, 'Found a key into search_measures not found into arrayofmesures');
  591. }
  592. }
  593. $sql .= " WHERE 1 = 1";
  594. if ($object->ismultientitymanaged == 1) { // 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table
  595. $sql .= " AND t.entity IN (".getEntity($object->element).")";
  596. }
  597. // Add the where here
  598. $sqlfilters = $search_component_params_hidden;
  599. if ($sqlfilters) {
  600. $errormessage = '';
  601. if (dolCheckFilters($sqlfilters, $errormessage)) {
  602. $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^\(\)]+)\)';
  603. $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'dolForgeCriteriaCallback', $sqlfilters).")";
  604. } else {
  605. print $errormessage;
  606. }
  607. }
  608. $sql .= " GROUP BY ";
  609. foreach ($search_xaxis as $key => $val) {
  610. if (preg_match('/\-year$/', $val)) {
  611. $tmpval = preg_replace('/\-year$/', '', $val);
  612. $sql .= "DATE_FORMAT(".$tmpval.", '%Y'), ";
  613. } elseif (preg_match('/\-month$/', $val)) {
  614. $tmpval = preg_replace('/\-month$/', '', $val);
  615. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m'), ";
  616. } elseif (preg_match('/\-day$/', $val)) {
  617. $tmpval = preg_replace('/\-day$/', '', $val);
  618. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d'), ";
  619. } else {
  620. $sql .= $val.", ";
  621. }
  622. }
  623. foreach ($search_groupby as $key => $val) {
  624. if (preg_match('/\-year$/', $val)) {
  625. $tmpval = preg_replace('/\-year$/', '', $val);
  626. $sql .= "DATE_FORMAT(".$tmpval.", '%Y'), ";
  627. } elseif (preg_match('/\-month$/', $val)) {
  628. $tmpval = preg_replace('/\-month$/', '', $val);
  629. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m'), ";
  630. } elseif (preg_match('/\-day$/', $val)) {
  631. $tmpval = preg_replace('/\-day$/', '', $val);
  632. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d'), ";
  633. } else {
  634. $sql .= $val.', ';
  635. }
  636. }
  637. $sql = preg_replace('/,\s*$/', '', $sql);
  638. $sql .= ' ORDER BY ';
  639. foreach ($search_xaxis as $key => $val) {
  640. if (preg_match('/\-year$/', $val)) {
  641. $tmpval = preg_replace('/\-year$/', '', $val);
  642. $sql .= "DATE_FORMAT(".$tmpval.", '%Y'), ";
  643. } elseif (preg_match('/\-month$/', $val)) {
  644. $tmpval = preg_replace('/\-month$/', '', $val);
  645. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m'), ";
  646. } elseif (preg_match('/\-day$/', $val)) {
  647. $tmpval = preg_replace('/\-day$/', '', $val);
  648. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d'), ";
  649. } else {
  650. $sql .= $val.', ';
  651. }
  652. }
  653. foreach ($search_groupby as $key => $val) {
  654. if (preg_match('/\-year$/', $val)) {
  655. $tmpval = preg_replace('/\-year$/', '', $val);
  656. $sql .= "DATE_FORMAT(".$tmpval.", '%Y'), ";
  657. } elseif (preg_match('/\-month$/', $val)) {
  658. $tmpval = preg_replace('/\-month$/', '', $val);
  659. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m'), ";
  660. } elseif (preg_match('/\-day$/', $val)) {
  661. $tmpval = preg_replace('/\-day$/', '', $val);
  662. $sql .= "DATE_FORMAT(".$tmpval.", '%Y-%m-%d'), ";
  663. } else {
  664. $sql .= $val.', ';
  665. }
  666. }
  667. $sql = preg_replace('/,\s*$/', '', $sql);
  668. }
  669. //print $sql;
  670. $legend = array();
  671. foreach ($search_measures as $key => $val) {
  672. $legend[] = $langs->trans($arrayofmesures[$val]['label']);
  673. }
  674. $useagroupby = (is_array($search_groupby) && count($search_groupby));
  675. //var_dump($useagroupby);
  676. //var_dump($arrayofvaluesforgroupby);
  677. // Execute the SQL request
  678. $totalnbofrecord = 0;
  679. $data = array();
  680. if ($sql) {
  681. $resql = $db->query($sql);
  682. if (!$resql) {
  683. dol_print_error($db);
  684. }
  685. $ifetch = 0;
  686. $xi = 0;
  687. $oldlabeltouse = '';
  688. while ($obj = $db->fetch_object($resql)) {
  689. $ifetch++;
  690. if ($useagroupby) {
  691. $xval = $search_xaxis[0];
  692. $fieldforxkey = 'x_0';
  693. $xlabel = $obj->$fieldforxkey;
  694. $xvalwithoutprefix = preg_replace('/^[a-z]+\./', '', $xval);
  695. // Define $xlabel
  696. if (!empty($object->fields[$xvalwithoutprefix]['arrayofkeyval'])) {
  697. $xlabel = $object->fields[$xvalwithoutprefix]['arrayofkeyval'][$obj->$fieldforxkey];
  698. }
  699. $labeltouse = (($xlabel || $xlabel == '0') ? dol_trunc($xlabel, 20, 'middle') : ($xlabel === '' ? $langs->transnoentitiesnoconv("Empty") : $langs->transnoentitiesnoconv("NotDefined")));
  700. if ($oldlabeltouse && ($labeltouse != $oldlabeltouse)) {
  701. $xi++; // Increase $xi
  702. }
  703. //var_dump($labeltouse.' '.$oldlabeltouse.' '.$xi);
  704. $oldlabeltouse = $labeltouse;
  705. /* Example of value for $arrayofvaluesforgroupby
  706. * array (size=1)
  707. * 'g_0' =>
  708. * array (size=6)
  709. * 0 => string '0' (length=1)
  710. * '' => string 'Empty' (length=5)
  711. * '__NULL__' => string 'Not defined' (length=11)
  712. * 'done' => string 'done' (length=4)
  713. * 'processing' => string 'processing' (length=10)
  714. * 'undeployed' => string 'undeployed' (length=10)
  715. */
  716. foreach ($search_measures as $key => $val) {
  717. $gi = 0;
  718. foreach ($search_groupby as $gkey) {
  719. //var_dump('*** Fetch #'.$ifetch.' for labeltouse='.$labeltouse.' measure number '.$key.' and group g_'.$gi);
  720. //var_dump($arrayofvaluesforgroupby);
  721. foreach ($arrayofvaluesforgroupby['g_'.$gi] as $gvaluepossiblekey => $gvaluepossiblelabel) {
  722. $ykeysuffix = $gvaluepossiblelabel;
  723. $gvalwithoutprefix = preg_replace('/^[a-z]+\./', '', $gval);
  724. $fieldfory = 'y_'.$key;
  725. $fieldforg = 'g_'.$gi;
  726. $fieldforybis = 'y_'.$key.'_'.$ykeysuffix;
  727. //var_dump('gvaluepossiblekey='.$gvaluepossiblekey.' gvaluepossiblelabel='.$gvaluepossiblelabel.' ykeysuffix='.$ykeysuffix.' gval='.$gval.' gvalwithoutsuffix='.$gvalwithoutprefix);
  728. //var_dump('fieldforg='.$fieldforg.' obj->$fieldforg='.$obj->$fieldforg.' fieldfory='.$fieldfory.' obj->$fieldfory='.$obj->$fieldfory.' fieldforybis='.$fieldforybis);
  729. if (!is_array($data[$xi])) {
  730. $data[$xi] = array();
  731. }
  732. if (!array_key_exists('label', $data[$xi])) {
  733. $data[$xi] = array();
  734. $data[$xi]['label'] = $labeltouse;
  735. }
  736. $objfieldforg = $obj->$fieldforg;
  737. if (is_null($objfieldforg)) {
  738. $objfieldforg = '__NULL__';
  739. }
  740. if ($gvaluepossiblekey == '0') { // $gvaluepossiblekey can have type int or string. So we create a special if, used when value is '0'
  741. //var_dump($objfieldforg.' == \'0\' -> '.($objfieldforg == '0'));
  742. if ($objfieldforg == '0') {
  743. // The record we fetch is for this group
  744. $data[$xi][$fieldforybis] = $obj->$fieldfory;
  745. } elseif (!isset($data[$xi][$fieldforybis])) {
  746. // The record we fetch is not for this group
  747. $data[$xi][$fieldforybis] = '0';
  748. }
  749. } else {
  750. //var_dump((string) $objfieldforg.' === '.(string) $gvaluepossiblekey.' -> '.((string) $objfieldforg === (string) $gvaluepossiblekey));
  751. if ((string) $objfieldforg === (string) $gvaluepossiblekey) {
  752. // The record we fetch is for this group
  753. $data[$xi][$fieldforybis] = $obj->$fieldfory;
  754. } elseif (!isset($data[$xi][$fieldforybis])) {
  755. // The record we fetch is not for this group
  756. $data[$xi][$fieldforybis] = '0';
  757. }
  758. }
  759. }
  760. //var_dump($data[$xi]);
  761. $gi++;
  762. }
  763. }
  764. } else { // No group by
  765. $xval = $search_xaxis[0];
  766. $fieldforxkey = 'x_0';
  767. $xlabel = $obj->$fieldforxkey;
  768. $xvalwithoutprefix = preg_replace('/^[a-z]+\./', '', $xval);
  769. // Define $xlabel
  770. if (!empty($object->fields[$xvalwithoutprefix]['arrayofkeyval'])) {
  771. $xlabel = $object->fields[$xvalwithoutprefix]['arrayofkeyval'][$obj->$fieldforxkey];
  772. }
  773. $labeltouse = (($xlabel || $xlabel == '0') ? dol_trunc($xlabel, 20, 'middle') : ($xlabel === '' ? $langs->trans("Empty") : $langs->trans("NotDefined")));
  774. $xarrayforallseries = array('label' => $labeltouse);
  775. foreach ($search_measures as $key => $val) {
  776. $fieldfory = 'y_'.$key;
  777. $xarrayforallseries[$fieldfory] = $obj->$fieldfory;
  778. }
  779. $data[$xi] = $xarrayforallseries;
  780. $xi++;
  781. }
  782. }
  783. $totalnbofrecord = count($data);
  784. }
  785. //var_dump($data);
  786. print '<div class="customreportsoutput'.($totalnbofrecord ? '' : ' customreportsoutputnotdata').'">';
  787. if ($mode == 'grid') {
  788. // TODO
  789. }
  790. if ($mode == 'graph') {
  791. $WIDTH = '80%';
  792. $HEIGHT = 200;
  793. // Show graph
  794. $px1 = new DolGraph();
  795. $mesg = $px1->isGraphKo();
  796. if (!$mesg) {
  797. //var_dump($legend);
  798. //var_dump($data);
  799. $px1->SetData($data);
  800. unset($data);
  801. $arrayoftypes = array();
  802. foreach ($search_measures as $key => $val) {
  803. $arrayoftypes[] = $search_graph;
  804. }
  805. $px1->SetLegend($legend);
  806. $px1->SetMinValue($px1->GetFloorMinValue());
  807. $px1->SetMaxValue($px1->GetCeilMaxValue());
  808. $px1->SetWidth($WIDTH);
  809. $px1->SetHeight($HEIGHT);
  810. $px1->SetYLabel($langs->trans("Y"));
  811. $px1->SetShading(3);
  812. $px1->SetHorizTickIncrement(1);
  813. $px1->SetCssPrefix("cssboxes");
  814. $px1->SetType($arrayoftypes);
  815. $px1->mode = 'depth';
  816. $px1->SetTitle('');
  817. $dir = $conf->user->dir_temp;
  818. dol_mkdir($dir);
  819. $filenamenb = $dir.'/customreport_'.$object->element.'.png';
  820. $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=user&file=customreport_'.$object->element.'.png';
  821. $px1->draw($filenamenb, $fileurlnb);
  822. $texttoshow = $langs->trans("NoRecordFound");
  823. if (!GETPOSTISSET('search_measures') || !GETPOSTISSET('search_xaxis')) {
  824. $texttoshow = $langs->trans("SelectYourGraphOptionsFirst");
  825. }
  826. print $px1->show($totalnbofrecord ? 0 : $texttoshow);
  827. }
  828. }
  829. if ($sql) {
  830. // Show admin info
  831. print '<br>'.info_admin($langs->trans("SQLUsedForExport").':<br> '.$sql, 0, 0, 1, '', 'TechnicalInformation');
  832. }
  833. print '<div>';
  834. if (!defined('USE_CUSTOM_REPORT_AS_INCLUDE')) {
  835. print dol_get_fiche_end();
  836. }
  837. // End of page
  838. llxFooter();
  839. $db->close();
  840. /**
  841. * Fill arrayofmesures for an object
  842. *
  843. * @param mixed $object Any object
  844. * @param string $tablealias Alias of table
  845. * @param string $labelofobject Label of object
  846. * @param array $arrayofmesures Array of mesures already filled
  847. * @param int $level Level
  848. * @param int $count Count
  849. * @return array Array of mesures
  850. */
  851. function fillArrayOfMeasures($object, $tablealias, $labelofobject, &$arrayofmesures, $level = 0, &$count = 0)
  852. {
  853. global $langs, $extrafields, $db;
  854. if ($level > 10) { // Protection against infinite loop
  855. return $arrayofmesures;
  856. }
  857. if ($level == 0) {
  858. // Add the count of record only for the main/first level object. Parents are necessarly unique for each record.
  859. $arrayofmesures[$tablealias.'.count'] = array(
  860. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': Count',
  861. 'position' => 0,
  862. 'table' => $object->table_element
  863. );
  864. }
  865. // Add main fields of object
  866. foreach ($object->fields as $key => $val) {
  867. if (!empty($val['isameasure']) && (!isset($val['enabled']) || dol_eval($val['enabled'], 1, 1, '1'))) {
  868. $position = (empty($val['position']) ? 0 : intVal($val['position']));
  869. $arrayofmesures[$tablealias.'.'.$key.'-sum'] = array(
  870. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$langs->trans("Sum").')</span>',
  871. 'position' => ($position + ($count * 100000)).'.1',
  872. 'table' => $object->table_element
  873. );
  874. $arrayofmesures[$tablealias.'.'.$key.'-average'] = array(
  875. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$langs->trans("Average").')</span>',
  876. 'position' => ($position + ($count * 100000)).'.2',
  877. 'table' => $object->table_element
  878. );
  879. $arrayofmesures[$tablealias.'.'.$key.'-min'] = array(
  880. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$langs->trans("Minimum").')</span>',
  881. 'position' => ($position + ($count * 100000)).'.3',
  882. 'table' => $object->table_element
  883. );
  884. $arrayofmesures[$tablealias.'.'.$key.'-max'] = array(
  885. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$langs->trans("Maximum").')</span>',
  886. 'position' => ($position + ($count * 100000)).'.4',
  887. 'table' => $object->table_element
  888. );
  889. }
  890. }
  891. // Add extrafields to Measures
  892. if (!empty($object->isextrafieldmanaged)) {
  893. foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
  894. 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'))) {
  895. $position = (!empty($val['position']) ? $val['position'] : 0);
  896. $arrayofmesures[$tablealias.'e.'.$key.'-sum'] = array(
  897. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' <span class="opacitymedium">('.$langs->trans("Sum").')</span>',
  898. 'position' => ($position+($count * 100000)).'.1',
  899. 'table' => $object->table_element
  900. );
  901. $arrayofmesures[$tablealias.'e.'.$key.'-average'] = array(
  902. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' <span class="opacitymedium">('.$langs->trans("Average").')</span>',
  903. 'position' => ($position+($count * 100000)).'.2',
  904. 'table' => $object->table_element
  905. );
  906. $arrayofmesures[$tablealias.'e.'.$key.'-min'] = array(
  907. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' <span class="opacitymedium">('.$langs->trans("Minimum").')</span>',
  908. 'position' => ($position+($count * 100000)).'.3',
  909. 'table' => $object->table_element
  910. );
  911. $arrayofmesures[$tablealias.'e.'.$key.'-max'] = array(
  912. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]).' <span class="opacitymedium">('.$langs->trans("Maximum").')</span>',
  913. 'position' => ($position+($count * 100000)).'.4',
  914. 'table' => $object->table_element
  915. );
  916. }
  917. }
  918. }
  919. // Add fields for parent objects
  920. foreach ($object->fields as $key => $val) {
  921. if (preg_match('/^[^:]+:[^:]+:/', $val['type'])) {
  922. $tmptype = explode(':', $val['type'], 4);
  923. if ($tmptype[0] == 'integer' && $tmptype[1] && $tmptype[2]) {
  924. $newobject = $tmptype[1];
  925. dol_include_once($tmptype[2]);
  926. if (class_exists($newobject)) {
  927. $tmpobject = new $newobject($db);
  928. //var_dump($key); var_dump($tmpobject->element); var_dump($val['label']); var_dump($tmptype); var_dump('t-'.$key);
  929. $count++;
  930. $arrayofmesures = fillArrayOfMeasures($tmpobject, $tablealias.'__'.$key, $langs->trans($val['label']), $arrayofmesures, $level + 1, $count);
  931. } else {
  932. print 'For property '.$object->element.'->'.$key.', type="'.$val['type'].'": Failed to find class '.$newobject." in file ".$tmptype[2]."<br>\n";
  933. }
  934. }
  935. }
  936. }
  937. return $arrayofmesures;
  938. }
  939. /**
  940. * Fill arrayofmesures for an object
  941. *
  942. * @param mixed $object Any object
  943. * @param string $tablealias Alias of table ('t' for example)
  944. * @param string $labelofobject Label of object
  945. * @param array $arrayofxaxis Array of xaxis already filled
  946. * @param int $level Level
  947. * @param int $count Count
  948. * @return array Array of xaxis
  949. */
  950. function fillArrayOfXAxis($object, $tablealias, $labelofobject, &$arrayofxaxis, $level = 0, &$count = 0)
  951. {
  952. global $langs, $extrafields, $db;
  953. if ($level > 10) { // Protection against infinite loop
  954. return $arrayofxaxis;
  955. }
  956. if ($level >= 2) {
  957. return $arrayofxaxis;
  958. }
  959. $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);
  960. $MM = substr($langs->trans("Month"), 0, 1).substr($langs->trans("Month"), 0, 1);
  961. $DD = substr($langs->trans("Day"), 0, 1).substr($langs->trans("Day"), 0, 1);
  962. $HH = substr($langs->trans("Hour"), 0, 1).substr($langs->trans("Hour"), 0, 1);
  963. $MI = substr($langs->trans("Minute"), 0, 1).substr($langs->trans("Minute"), 0, 1);
  964. $SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1);
  965. // Add main fields of object
  966. foreach ($object->fields as $key => $val) {
  967. if (empty($val['measure'])) {
  968. if (in_array($key, array(
  969. 'id', 'ref_ext', 'rowid', 'entity', 'last_main_doc', 'logo', 'logo_squarred', 'extraparams',
  970. 'parent', 'photo', 'socialnetworks', 'webservices_url', 'webservices_key'))) {
  971. continue;
  972. }
  973. if (isset($val['enabled']) && !dol_eval($val['enabled'], 1, 1, '1')) {
  974. continue;
  975. }
  976. if (isset($val['visible']) && !dol_eval($val['visible'], 1, 1, '1')) {
  977. continue;
  978. }
  979. if (preg_match('/^fk_/', $key) && !preg_match('/^fk_statu/', $key)) {
  980. continue;
  981. }
  982. if (preg_match('/^pass/', $key)) {
  983. continue;
  984. }
  985. if (in_array($val['type'], array('html', 'text'))) {
  986. continue;
  987. }
  988. if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) {
  989. $position = (empty($val['position']) ? 0 : intVal($val['position']));
  990. $arrayofxaxis[$tablealias.'.'.$key.'-year'] = array(
  991. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.')</span>',
  992. 'position' => ($position + ($count * 100000)).'.1',
  993. 'table' => $object->table_element
  994. );
  995. $arrayofxaxis[$tablealias.'.'.$key.'-month'] = array(
  996. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.'-'.$MM.')</span>',
  997. 'position' => ($position + ($count * 100000)).'.2',
  998. 'table' => $object->table_element
  999. );
  1000. $arrayofxaxis[$tablealias.'.'.$key.'-day'] = array(
  1001. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.'-'.$MM.'-'.$DD.')</span>',
  1002. 'position' => ($position + ($count * 100000)).'.3',
  1003. 'table' => $object->table_element
  1004. );
  1005. } else {
  1006. $position = (empty($val['position']) ? 0 : intVal($val['position']));
  1007. $arrayofxaxis[$tablealias.'.'.$key] = array(
  1008. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']),
  1009. 'position' => ($position + ($count * 100000)),
  1010. 'table' => $object->table_element
  1011. );
  1012. }
  1013. }
  1014. }
  1015. // Add extrafields to X-Axis
  1016. if (!empty($object->isextrafieldmanaged)) {
  1017. foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
  1018. if ($extrafields->attributes[$object->table_element]['type'][$key] == 'separate') {
  1019. continue;
  1020. }
  1021. if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key])) {
  1022. continue;
  1023. }
  1024. $arrayofxaxis[$tablealias.'e.'.$key] = array(
  1025. 'label' => img_picto('', $object->picto, 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]),
  1026. 'position' => 1000 + (int) $extrafields->attributes[$object->table_element]['pos'][$key] + ($count * 100000),
  1027. 'table' => $object->table_element
  1028. );
  1029. }
  1030. }
  1031. // Add fields for parent objects
  1032. foreach ($object->fields as $key => $val) {
  1033. if (preg_match('/^[^:]+:[^:]+:/', $val['type'])) {
  1034. $tmptype = explode(':', $val['type'], 4);
  1035. if ($tmptype[0] == 'integer' && $tmptype[1] && $tmptype[2]) {
  1036. $newobject = $tmptype[1];
  1037. dol_include_once($tmptype[2]);
  1038. if (class_exists($newobject)) {
  1039. $tmpobject = new $newobject($db);
  1040. //var_dump($key); var_dump($tmpobject->element); var_dump($val['label']); var_dump($tmptype); var_dump('t-'.$key);
  1041. $count++;
  1042. $arrayofxaxis = fillArrayOfXAxis($tmpobject, $tablealias.'__'.$key, $langs->trans($val['label']), $arrayofxaxis, $level + 1, $count);
  1043. } else {
  1044. print 'For property '.$object->element.'->'.$key.', type="'.$val['type'].'": Failed to find class '.$newobject." in file ".$tmptype[2]."<br>\n";
  1045. }
  1046. }
  1047. }
  1048. }
  1049. return $arrayofxaxis;
  1050. }
  1051. /**
  1052. * Fill arrayofgrupby for an object
  1053. *
  1054. * @param mixed $object Any object
  1055. * @param string $tablealias Alias of table
  1056. * @param string $labelofobject Label of object
  1057. * @param array $arrayofgroupby Array of groupby already filled
  1058. * @param int $level Level
  1059. * @param int $count Count
  1060. * @return array Array of groupby
  1061. */
  1062. function fillArrayOfGroupBy($object, $tablealias, $labelofobject, &$arrayofgroupby, $level = 0, &$count = 0)
  1063. {
  1064. global $langs, $extrafields, $db;
  1065. if ($level > 10) { // Protection against infinite loop
  1066. return $arrayofgroupby;
  1067. }
  1068. if ($level >= 2) {
  1069. return $arrayofgroupby;
  1070. }
  1071. $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);
  1072. $MM = substr($langs->trans("Month"), 0, 1).substr($langs->trans("Month"), 0, 1);
  1073. $DD = substr($langs->trans("Day"), 0, 1).substr($langs->trans("Day"), 0, 1);
  1074. $HH = substr($langs->trans("Hour"), 0, 1).substr($langs->trans("Hour"), 0, 1);
  1075. $MI = substr($langs->trans("Minute"), 0, 1).substr($langs->trans("Minute"), 0, 1);
  1076. $SS = substr($langs->trans("Second"), 0, 1).substr($langs->trans("Second"), 0, 1);
  1077. // Add main fields of object
  1078. foreach ($object->fields as $key => $val) {
  1079. if (empty($val['isameasure'])) {
  1080. if (in_array($key, array(
  1081. 'id', 'ref_ext', 'rowid', 'entity', 'last_main_doc', 'logo', 'logo_squarred', 'extraparams',
  1082. 'parent', 'photo', 'socialnetworks', 'webservices_url', 'webservices_key'))) {
  1083. continue;
  1084. }
  1085. if (isset($val['enabled']) && !dol_eval($val['enabled'], 1, 1, '1')) {
  1086. continue;
  1087. }
  1088. if (isset($val['visible']) && !dol_eval($val['visible'], 1, 1, '1')) {
  1089. continue;
  1090. }
  1091. if (preg_match('/^fk_/', $key) && !preg_match('/^fk_statu/', $key)) {
  1092. continue;
  1093. }
  1094. if (preg_match('/^pass/', $key)) {
  1095. continue;
  1096. }
  1097. if (in_array($val['type'], array('html', 'text'))) {
  1098. continue;
  1099. }
  1100. if (in_array($val['type'], array('timestamp', 'date', 'datetime'))) {
  1101. $position = (empty($val['position']) ? 0 : intVal($val['position']));
  1102. $arrayofgroupby[$tablealias.'.'.$key.'-year'] = array(
  1103. 'label' => img_picto('', $object->picto,
  1104. 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.')</span>', 'position' => ($position + ($count * 100000)).'.1',
  1105. 'table' => $object->table_element
  1106. );
  1107. $arrayofgroupby[$tablealias.'.'.$key.'-month'] = array(
  1108. 'label' => img_picto('', $object->picto,
  1109. 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.'-'.$MM.')</span>', 'position' => ($position + ($count * 100000)).'.2',
  1110. 'table' => $object->table_element
  1111. );
  1112. $arrayofgroupby[$tablealias.'.'.$key.'-day'] = array(
  1113. 'label' => img_picto('', $object->picto,
  1114. 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']).' <span class="opacitymedium">('.$YYYY.'-'.$MM.'-'.$DD.')</span>', 'position' => ($position + ($count * 100000)).'.3',
  1115. 'table' => $object->table_element
  1116. );
  1117. } else {
  1118. $position = (empty($val['position']) ? 0 : intVal($val['position']));
  1119. $arrayofgroupby[$tablealias.'.'.$key] = array(
  1120. 'label' => img_picto('', $object->picto,
  1121. 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($val['label']), 'position' => ($position + ($count * 100000)),
  1122. 'table' => $object->table_element
  1123. );
  1124. }
  1125. }
  1126. }
  1127. // Add extrafields to Group by
  1128. if (!empty($object->isextrafieldmanaged)) {
  1129. foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
  1130. if ($extrafields->attributes[$object->table_element]['type'][$key] == 'separate') {
  1131. continue;
  1132. }
  1133. if (!empty($extrafields->attributes[$object->table_element]['totalizable'][$key])) {
  1134. continue;
  1135. }
  1136. $arrayofgroupby[$tablealias.'e.'.$key] = array(
  1137. 'label' => img_picto('', $object->picto,
  1138. 'class="pictofixedwidth"').' '.$labelofobject.': '.$langs->trans($extrafields->attributes[$object->table_element]['label'][$key]), 'position' => 1000 + (int) $extrafields->attributes[$object->table_element]['pos'][$key] + ($count * 100000),
  1139. 'table' => $object->table_element
  1140. );
  1141. }
  1142. }
  1143. // Add fields for parent objects
  1144. foreach ($object->fields as $key => $val) {
  1145. if (preg_match('/^[^:]+:[^:]+:/', $val['type'])) {
  1146. $tmptype = explode(':', $val['type'], 4);
  1147. if ($tmptype[0] == 'integer' && $tmptype[1] && $tmptype[2]) {
  1148. $newobject = $tmptype[1];
  1149. dol_include_once($tmptype[2]);
  1150. if (class_exists($newobject)) {
  1151. $tmpobject = new $newobject($db);
  1152. //var_dump($key); var_dump($tmpobject->element); var_dump($val['label']); var_dump($tmptype); var_dump('t-'.$key);
  1153. $count++;
  1154. $arrayofgroupby = fillArrayOfGroupBy($tmpobject, $tablealias.'__'.$key, $langs->trans($val['label']), $arrayofgroupby, $level + 1, $count);
  1155. } else {
  1156. print 'For property '.$object->element.'->'.$key.', type="'.$val['type'].'": Failed to find class '.$newobject." in file ".$tmptype[2]."<br>\n";
  1157. }
  1158. }
  1159. }
  1160. }
  1161. return $arrayofgroupby;
  1162. }