1<?php 2/* Copyright (C) 2003-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org> 3 * Copyright (C) 2004-2013 Laurent Destailleur <eldy@users.sourceforge.net> 4 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com> 5 * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <https://www.gnu.org/licenses/>. 19 */ 20 21/** 22 * \file htdocs/admin/boxes.php 23 * \brief Page to setup boxes 24 */ 25 26require '../main.inc.php'; 27include_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php'; 28require_once DOL_DOCUMENT_ROOT.'/core/class/infobox.class.php'; 29include_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; 30 31// Load translation files required by the page 32$langs->loadLangs(array('admin', 'boxes', 'accountancy')); 33 34if (!$user->admin) { 35 accessforbidden(); 36} 37 38$rowid = GETPOST('rowid', 'int'); 39$action = GETPOST('action', 'aZ09'); 40 41 42// Define possible position of boxes 43$pos_name = InfoBox::getListOfPagesForBoxes(); 44$boxes = array(); 45 46 47/* 48 * Actions 49 */ 50 51if ($action == 'addconst') { 52 dolibarr_set_const($db, "MAIN_BOXES_MAXLINES", $_POST["MAIN_BOXES_MAXLINES"], '', 0, '', $conf->entity); 53 dolibarr_set_const($db, "MAIN_ACTIVATE_FILECACHE", $_POST["MAIN_ACTIVATE_FILECACHE"], 'chaine', 0, '', $conf->entity); 54} 55 56if ($action == 'add') { 57 $error = 0; 58 $boxids = GETPOST('boxid', 'array'); 59 60 $db->begin(); 61 if (is_array($boxids)) { 62 foreach ($boxids as $boxid) { 63 if (is_numeric($boxid['pos']) && $boxid['pos'] >= 0) { // 0=Home, 1=... 64 $pos = $boxid['pos']; 65 66 // Initialize distinct fk_user with all already existing values of fk_user (user that use a personalized view of boxes for page "pos") 67 $distinctfkuser = array(); 68 if (!$error) { 69 $sql = "SELECT fk_user"; 70 $sql .= " FROM ".MAIN_DB_PREFIX."user_param"; 71 $sql .= " WHERE param = 'MAIN_BOXES_".$db->escape($pos)."' AND value = '1'"; 72 $sql .= " AND entity = ".$conf->entity; 73 dol_syslog("boxes.php search fk_user to activate box for", LOG_DEBUG); 74 $resql = $db->query($sql); 75 if ($resql) { 76 $num = $db->num_rows($resql); 77 $i = 0; 78 while ($i < $num) { 79 $obj = $db->fetch_object($resql); 80 $distinctfkuser[$obj->fk_user] = $obj->fk_user; 81 $i++; 82 } 83 } else { 84 setEventMessages($db->lasterror(), null, 'errors'); 85 $error++; 86 } 87 } 88 89 $distinctfkuser['0'] = '0'; // Add entry for fk_user = 0. We must use string as key and val 90 91 foreach ($distinctfkuser as $fk_user) { 92 if (!$error && $fk_user != '') { 93 $arrayofexistingboxid = array(); 94 $nbboxonleft = $nbboxonright = 0; 95 $sql = "SELECT box_id, box_order FROM ".MAIN_DB_PREFIX."boxes"; 96 $sql .= " WHERE position = ".$pos." AND fk_user = ".$fk_user." AND entity = ".$conf->entity; 97 dol_syslog("boxes.php activate box", LOG_DEBUG); 98 $resql = $db->query($sql); 99 if ($resql) { 100 while ($obj = $db->fetch_object($resql)) { 101 $boxorder = $obj->box_order; 102 if (preg_match('/A/', $boxorder)) { 103 $nbboxonleft++; 104 } 105 if (preg_match('/B/', $boxorder)) { 106 $nbboxonright++; 107 } 108 $arrayofexistingboxid[$obj->box_id] = 1; 109 } 110 } else { 111 dol_print_error($db); 112 } 113 114 if (empty($arrayofexistingboxid[$boxid['value']])) { 115 $sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes ("; 116 $sql .= "box_id, position, box_order, fk_user, entity"; 117 $sql .= ") values ("; 118 $sql .= $boxid['value'].", ".$pos.", '".(($nbboxonleft > $nbboxonright) ? 'B01' : 'A01')."', ".$fk_user.", ".$conf->entity; 119 $sql .= ")"; 120 121 dol_syslog("boxes.php activate box", LOG_DEBUG); 122 $resql = $db->query($sql); 123 if (!$resql) { 124 setEventMessages($db->lasterror(), null, 'errors'); 125 $error++; 126 } 127 } else { 128 dol_syslog("boxes.php activate box - already exists in database", LOG_DEBUG); 129 } 130 } 131 } 132 } 133 } 134 } 135 if (!$error) { 136 $db->commit(); 137 $action = ''; 138 } else { 139 $db->rollback(); 140 } 141} 142 143if ($action == 'delete') { 144 $sql = "SELECT box_id FROM ".MAIN_DB_PREFIX."boxes"; 145 $sql .= " WHERE rowid=".((int) $rowid); 146 147 $resql = $db->query($sql); 148 $obj = $db->fetch_object($resql); 149 if (!empty($obj->box_id)) { 150 $db->begin(); 151 152 // Remove all personalized setup when a box is activated or disabled (why removing all ? We removed only removed boxes) 153 // $sql = "DELETE FROM ".MAIN_DB_PREFIX."user_param"; 154 // $sql.= " WHERE param LIKE 'MAIN_BOXES_%'"; 155 // $resql = $db->query($sql); 156 157 $sql = "DELETE FROM ".MAIN_DB_PREFIX."boxes"; 158 $sql .= " WHERE entity = ".$conf->entity; 159 $sql .= " AND box_id=".$obj->box_id; 160 161 $resql = $db->query($sql); 162 163 $db->commit(); 164 } 165} 166 167if ($action == 'switch') { 168 // We switch values of field box_order for the 2 lines of table boxes 169 $db->begin(); 170 171 $objfrom = new ModeleBoxes($db); 172 $objfrom->fetch(GETPOST("switchfrom", 'int')); 173 174 $objto = new ModeleBoxes($db); 175 $objto->fetch(GETPOST('switchto', 'int')); 176 177 $resultupdatefrom = 0; 178 $resultupdateto = 0; 179 if (is_object($objfrom) && is_object($objto)) { 180 $newfirst = $objto->box_order; 181 $newsecond = $objfrom->box_order; 182 if ($newfirst == $newsecond) { 183 $newsecondchar = preg_replace('/[0-9]+/', '', $newsecond); 184 $newsecondnum = preg_replace('/[a-zA-Z]+/', '', $newsecond); 185 $newsecond = sprintf("%s%02d", $newsecondchar ? $newsecondchar : 'A', $newsecondnum + 1); 186 } 187 $sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order='".$db->escape($newfirst)."' WHERE rowid=".((int) $objfrom->rowid); 188 dol_syslog($sql); 189 $resultupdatefrom = $db->query($sql); 190 if (!$resultupdatefrom) { 191 dol_print_error($db); 192 } 193 194 $sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order='".$db->escape($newsecond)."' WHERE rowid=".((int) $objto->rowid); 195 dol_syslog($sql); 196 $resultupdateto = $db->query($sql); 197 if (!$resultupdateto) { 198 dol_print_error($db); 199 } 200 } 201 202 if ($resultupdatefrom && $resultupdateto) { 203 $db->commit(); 204 } else { 205 $db->rollback(); 206 } 207} 208 209 210/* 211 * View 212 */ 213 214$form = new Form($db); 215 216llxHeader('', $langs->trans("Boxes")); 217 218print load_fiche_titre($langs->trans("Boxes"), '', 'title_setup'); 219 220print '<span class="opacitymedium">'.$langs->trans("BoxesDesc")." ".$langs->trans("OnlyActiveElementsAreShown")."</span><br>\n"; 221 222/* 223 * Search for the default active boxes for each possible position 224 * We store the active boxes by default in $boxes[position][id_boite]=1 225 */ 226 227$actives = array(); 228 229$sql = "SELECT b.rowid, b.box_id, b.position, b.box_order,"; 230$sql .= " bd.rowid as boxid"; 231$sql .= " FROM ".MAIN_DB_PREFIX."boxes as b, ".MAIN_DB_PREFIX."boxes_def as bd"; 232$sql .= " WHERE b.box_id = bd.rowid"; 233$sql .= " AND b.entity IN (0,".$conf->entity.")"; 234$sql .= " AND b.fk_user=0"; 235$sql .= " ORDER by b.position, b.box_order"; 236 237dol_syslog("Search available boxes", LOG_DEBUG); 238$resql = $db->query($sql); 239if ($resql) { 240 $num = $db->num_rows($resql); 241 242 // Check record to know if we must recalculate sort order 243 $i = 0; 244 $decalage = 0; 245 while ($i < $num) { 246 $obj = $db->fetch_object($resql); 247 $boxes[$obj->position][$obj->box_id] = 1; 248 $i++; 249 250 array_push($actives, $obj->box_id); 251 252 if ($obj->box_order == '' || $obj->box_order == '0' || $decalage) { 253 $decalage++; 254 } 255 // We renumber the order of the boxes if one of them is in '' 256 // This occurs just after an insert. 257 if ($decalage) { 258 $sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order='".$db->escape($decalage)."' WHERE rowid=".$obj->rowid; 259 $db->query($sql); 260 } 261 } 262 263 if ($decalage) { 264 // If we have renumbered, we correct the field box_order 265 // This occurs just after an insert. 266 $sql = "SELECT box_order"; 267 $sql .= " FROM ".MAIN_DB_PREFIX."boxes"; 268 $sql .= " WHERE entity = ".$conf->entity; 269 $sql .= " AND LENGTH(box_order) <= 2"; 270 271 dol_syslog("Execute requests to renumber box order", LOG_DEBUG); 272 $result = $db->query($sql); 273 if ($result) { 274 while ($record = $db->fetch_array($result)) { 275 if (dol_strlen($record['box_order']) == 1) { 276 if (preg_match("/[13579]{1}/", substr($record['box_order'], -1))) { 277 $box_order = "A0".$record['box_order']; 278 $sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".$conf->entity." AND box_order = '".$db->escape($record['box_order'])."'"; 279 $resql = $db->query($sql); 280 } elseif (preg_match("/[02468]{1}/", substr($record['box_order'], -1))) { 281 $box_order = "B0".$record['box_order']; 282 $sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".$conf->entity." AND box_order = '".$db->escape($record['box_order'])."'"; 283 $resql = $db->query($sql); 284 } 285 } elseif (dol_strlen($record['box_order']) == 2) { 286 if (preg_match("/[13579]{1}/", substr($record['box_order'], -1))) { 287 $box_order = "A".$record['box_order']; 288 $sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".$conf->entity." AND box_order = '".$db->escape($record['box_order'])."'"; 289 $resql = $db->query($sql); 290 } elseif (preg_match("/[02468]{1}/", substr($record['box_order'], -1))) { 291 $box_order = "B".$record['box_order']; 292 $sql = "UPDATE ".MAIN_DB_PREFIX."boxes SET box_order = '".$db->escape($box_order)."' WHERE entity = ".$conf->entity." AND box_order = '".$db->escape($record['box_order'])."'"; 293 $resql = $db->query($sql); 294 } 295 } 296 } 297 } 298 } 299 $db->free($resql); 300} 301 302// Available boxes to activate 303$boxtoadd = InfoBox::listBoxes($db, 'available', -1, null, $actives); 304// Activated boxes 305$boxactivated = InfoBox::listBoxes($db, 'activated', -1, null); 306 307print "<br>\n"; 308print "\n\n".'<!-- Boxes Available -->'."\n"; 309print load_fiche_titre($langs->trans("BoxesAvailable"), '', ''); 310 311print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n"; 312print '<input type="hidden" name="token" value="'.newToken().'">'."\n"; 313print '<input type="hidden" name="action" value="add">'."\n"; 314 315print '<div class="div-table-responsive-no-min">'; 316print '<table class="tagtable liste centpercent">'."\n"; 317 318print '<tr class="liste_titre">'; 319print '<td width="300">'.$langs->trans("Box").'</td>'; 320print '<td>'.$langs->trans("Note").'/'.$langs->trans("Parameters").'</td>'; 321print '<td>'.$langs->trans("SourceFile").'</td>'; 322print '<td width="160" class="center">'.$langs->trans("ActivateOn").'</td>'; 323print "</tr>\n"; 324 325foreach ($boxtoadd as $box) { 326 if (preg_match('/^([^@]+)@([^@]+)$/i', $box->boximg)) { 327 $logo = $box->boximg; 328 } else { 329 $logo = preg_replace("/^object_/i", "", $box->boximg); 330 } 331 332 print "\n".'<!-- Box '.$box->boxcode.' -->'."\n"; 333 print '<tr class="oddeven">'."\n"; 334 print '<td>'.img_object("", $logo, 'height="14px"').' '.$langs->transnoentitiesnoconv($box->boxlabel); 335 if (!empty($box->class) && preg_match('/graph_/', $box->class)) { 336 print ' ('.$langs->trans("Graph").')'; 337 } 338 print '</td>'."\n"; 339 print '<td>'; 340 if ($box->note == '(WarningUsingThisBoxSlowDown)') { 341 $langs->load("errors"); 342 print $langs->trans("WarningUsingThisBoxSlowDown"); 343 } else { 344 print ($box->note ? $box->note : ' '); 345 } 346 print '</td>'."\n"; 347 print '<td>'.$box->sourcefile.'</td>'."\n"; 348 349 // For each possible position, an activation link is displayed if the box is not already active for that position 350 print '<td class="center">'; 351 print $form->selectarray("boxid[".$box->box_id."][pos]", $pos_name, -1, 1, 0, 0, '', 1)."\n"; 352 print '<input type="hidden" name="boxid['.$box->box_id.'][value]" value="'.$box->box_id.'">'."\n"; 353 print '</td>'; 354 355 print '</tr>'."\n"; 356} 357if (!count($boxtoadd) && count($boxactivated)) { 358 print '<tr><td class="opacitymedium" colspan="4">'.$langs->trans("AllWidgetsWereEnabled").'</td></tr>'; 359} 360print '</table>'."\n"; 361print '</div>'; 362 363print '<div class="right">'; 364print '<input type="submit" class="button"'.(count($boxtoadd) ? '' : ' disabled').' value="'.$langs->trans("Activate").'">'; 365print '</div>'."\n"; 366print '</form>'; 367print "\n".'<!-- End Boxes Available -->'."\n"; 368 369 370//var_dump($boxactivated); 371print "<br>\n\n"; 372print load_fiche_titre($langs->trans("BoxesActivated"), '', ''); 373 374print '<div class="div-table-responsive-no-min">'; 375print '<table class="tagtable liste">'."\n"; 376 377print '<tr class="liste_titre">'; 378print '<td width="300">'.$langs->trans("Box").'</td>'; 379print '<td>'.$langs->trans("Note").'/'.$langs->trans("Parameters").'</td>'; 380print '<td class="center" width="160">'.$langs->trans("ActiveOn").'</td>'; 381print '<td class="center" width="60" colspan="2">'.$langs->trans("PositionByDefault").'</td>'; 382print '<td class="center" width="80">'.$langs->trans("Disable").'</td>'; 383print '</tr>'."\n"; 384 385$box_order = 1; 386$foundrupture = 1; 387foreach ($boxactivated as $key => $box) { 388 if (preg_match('/^([^@]+)@([^@]+)$/i', $box->boximg)) { 389 $logo = $box->boximg; 390 } else { 391 $logo = preg_replace("/^object_/i", "", $box->boximg); 392 } 393 394 print "\n".'<!-- Box '.$box->boxcode.' -->'."\n"; 395 print '<tr class="oddeven">'; 396 print '<td>'.img_object("", $logo, 'height="14px"').' '.$langs->transnoentitiesnoconv($box->boxlabel); 397 if (!empty($box->class) && preg_match('/graph_/', $box->class)) { 398 print ' ('.$langs->trans("Graph").')'; 399 } 400 print '</td>'; 401 print '<td>'; 402 if ($box->note == '(WarningUsingThisBoxSlowDown)') { 403 $langs->load("errors"); 404 print img_warning('', 0).' '.$langs->trans("WarningUsingThisBoxSlowDown"); 405 } else { 406 print ($box->note ? $box->note : ' '); 407 } 408 print '</td>'; 409 print '<td class="center">'.(empty($pos_name[$box->position]) ? '' : $langs->trans($pos_name[$box->position])).'</td>'; 410 $hasnext = ($key < (count($boxactivated) - 1)); 411 $hasprevious = ($key != 0); 412 print '<td class="center">'.($key + 1).'</td>'; 413 print '<td class="center">'; 414 print ($hasnext ? '<a href="boxes.php?action=switch&switchfrom='.$box->rowid.'&switchto='.$boxactivated[$key + 1]->rowid.'">'.img_down().'</a> ' : ''); 415 print ($hasprevious ? '<a href="boxes.php?action=switch&switchfrom='.$box->rowid.'&switchto='.$boxactivated[$key - 1]->rowid.'">'.img_up().'</a>' : ''); 416 print '</td>'; 417 print '<td class="center">'; 418 print '<a href="boxes.php?rowid='.$box->rowid.'&action=delete&token='.newToken().'">'.img_delete().'</a>'; 419 print '</td>'; 420 421 print '</tr>'."\n"; 422} 423 424print '</table>'; 425print '</div>'; 426print '<br>'; 427 428 429// Other parameters 430 431print "\n\n".'<!-- Other Const -->'."\n"; 432print load_fiche_titre($langs->trans("Other"), '', ''); 433print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">'; 434print '<input type="hidden" name="token" value="'.newToken().'">'; 435print '<input type="hidden" name="action" value="addconst">'; 436print '<div class="div-table-responsive-no-min">'; 437print '<table class="noborder centpercent">'; 438 439print '<tr class="liste_titre">'; 440print '<td class="liste_titre">'.$langs->trans("Parameter").'</td>'; 441print '<td class="liste_titre">'.$langs->trans("Value").'</td>'; 442print '</tr>'; 443 444print '<tr class="oddeven">'; 445print '<td>'; 446print $langs->trans("MaxNbOfLinesForBoxes"); 447print '</td>'."\n"; 448print '<td>'; 449print '<input type="text" class="flat" size="6" name="MAIN_BOXES_MAXLINES" value="'.$conf->global->MAIN_BOXES_MAXLINES.'">'; 450print '</td>'; 451print '</tr>'; 452 453// Activate FileCache - Developement 454if ($conf->global->MAIN_FEATURES_LEVEL == 2 || !empty($conf->global->MAIN_ACTIVATE_FILECACHE)) { 455 print '<tr class="oddeven"><td width="35%">'.$langs->trans("EnableFileCache").'</td><td>'; 456 print $form->selectyesno('MAIN_ACTIVATE_FILECACHE', $conf->global->MAIN_ACTIVATE_FILECACHE, 1); 457 print '</td>'; 458 print '</tr>'; 459} 460 461print '</table>'; 462print '</div>'; 463 464print '<br>'; 465print '<div class="center"><input type="submit" class="button button-save" value="'.$langs->trans("Save").'" name="Button"></div>'; 466print '<br>'; 467 468print '</form>'; 469print "\n".'<!-- End Other Const -->'."\n"; 470 471// End of page 472llxFooter(); 473$db->close(); 474