dolibarr 20.0.0
modules_boxes.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2013 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
5 * Copyright (C) 2015 Frederic France <frederic.france@free.fr>
6 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 * or see https://www.gnu.org/
21 */
22
35class ModeleBoxes // Can't be abstract as it is instantiated to build "empty" boxes
36{
40 public $db;
41
45 public $param;
46
50 public $info_box_head = array();
51
55 public $info_box_contents = array();
56
60 public $error = '';
61
65 public $max = 5;
66
70 public $enabled = 1;
71
75 public $hidden = false;
76
80 public $rowid;
81
86 public $id;
87
91 public $position;
92
96 public $box_order;
97
101 public $fk_user;
102
106 public $sourcefile;
107
111 public $class;
112
116 public $box_id;
117
121 public $boxcode;
122
126 public $note;
127
131 public $widgettype = '';
132
133
140 public function __construct($db, $param = '')
141 {
142 $this->db = $db;
143 }
144
150 public function error()
151 {
152 return $this->error;
153 }
154
155
163 public function fetch($rowid)
164 {
165 global $conf;
166
167 // Recupere liste des boites d'un user si ce dernier a sa propre liste
168 $sql = "SELECT b.rowid as id, b.box_id, b.position, b.box_order, b.fk_user";
169 $sql .= " FROM ".MAIN_DB_PREFIX."boxes as b";
170 $sql .= " WHERE b.entity = ".$conf->entity;
171 $sql .= " AND b.rowid = ".((int) $rowid);
172
173 dol_syslog(get_class($this)."::fetch rowid=".((int) $rowid));
174
175 $resql = $this->db->query($sql);
176 if ($resql) {
177 $obj = $this->db->fetch_object($resql);
178 if ($obj) {
179 $this->id = $obj->id;
180 $this->rowid = $obj->id; // For backward compatibility
181 $this->box_id = $obj->box_id;
182 $this->position = $obj->position;
183 $this->box_order = $obj->box_order;
184 $this->fk_user = $obj->fk_user;
185 return 1;
186 } else {
187 return -1;
188 }
189 } else {
190 return -1;
191 }
192 }
193
202 public function showBox($head, $contents, $nooutput = 0)
203 {
204 global $langs, $user, $conf;
205
206 if (!empty($this->hidden)) {
207 return "\n<!-- Box ".get_class($this)." hidden -->\n"; // Nothing done if hidden (for example when user has no permission)
208 }
209
210 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
211
212 $MAXLENGTHBOX = 60; // When set to 0: no length limit
213
214 $cachetime = 900; // 900 : 15mn
215 $cachedir = DOL_DATA_ROOT.'/users/temp/widgets';
216 $fileid = get_class($this).'id-'.$this->box_id.'-e'.$conf->entity.'-u'.$user->id.'-s'.$user->socid.'.cache';
217 $filename = '/box-'.$fileid;
218 $refresh = dol_cache_refresh($cachedir, $filename, $cachetime);
219 $out = '';
220
221 if ($refresh) {
222 dol_syslog(get_class($this).'::showBox');
223
224 // Define nbcol and nblines of the box to show
225 $nbcol = 0;
226 if (isset($contents[0])) {
227 $nbcol = count($contents[0]);
228 }
229 $nblines = count($contents);
230
231 $out .= "\n<!-- Box ".get_class($this)." start -->\n";
232
233 $out .= '<div class="box divboxtable boxdraggable" id="boxto_'.$this->box_id.'">'."\n";
234 if (!empty($head['text']) || !empty($head['sublink']) || !empty($head['subpicto']) || $nblines) {
235 $out .= '<table summary="boxtable'.$this->box_id.'" class="noborder boxtable centpercent">'."\n";
236 }
237
238 // Show box title
239 if (!empty($head['text']) || !empty($head['sublink']) || !empty($head['subpicto'])) {
240 $out .= '<tr class="liste_titre box_titre">';
241 $out .= '<th';
242 if (!empty($head['nbcol'])) {
243 $nbcol = $head['nbcol'];
244 }
245 if ($nbcol > 1) {
246 $out .= ' colspan="'.$nbcol.'"';
247 }
248 $out .= '>';
249 if (!empty($conf->use_javascript_ajax)) {
250 //$out.= '<table summary="" class="nobordernopadding" width="100%"><tr><td class="tdoverflowmax150 maxwidth150onsmartphone">';
251 $out .= '<div class="tdoverflowmax400 maxwidth250onsmartphone float">';
252 }
253 if (!empty($head['text'])) {
254 $s = dol_trunc($head['text'], isset($head['limit']) ? $head['limit'] : $MAXLENGTHBOX);
255 $out .= $s;
256 }
257 if (!empty($conf->use_javascript_ajax)) {
258 $out .= '</div>';
259 }
260 //$out.= '</td>';
261
262 if (!empty($conf->use_javascript_ajax)) {
263 $sublink = '';
264 if (!empty($head['sublink'])) {
265 $sublink .= '<a href="'.$head['sublink'].'"'.(empty($head['target']) ? '' : ' target="'.$head['target'].'"').'>';
266 }
267 if (!empty($head['subpicto'])) {
268 $sublink .= img_picto($head['subtext'], $head['subpicto'], 'class="opacitymedium marginleftonly '.(empty($head['subclass']) ? '' : $head['subclass']).'" id="idsubimg'.$this->boxcode.'"');
269 }
270 if (!empty($head['sublink'])) {
271 $sublink .= '</a>';
272 }
273
274 //$out.= '<td class="nocellnopadd boxclose right nowraponall">';
275 $out .= '<div class="nocellnopadd boxclose floatright nowraponall">';
276 $out .= $sublink;
277 // The image must have the class 'boxhandle' because it's value used in DOM draggable objects to define the area used to catch the full object
278 $out .= img_picto($langs->trans("MoveBox", $this->box_id), 'grip_title', 'class="opacitymedium boxhandle hideonsmartphone cursormove marginleftonly"');
279 $out .= img_picto($langs->trans("CloseBox", $this->box_id), 'close_title', 'class="opacitymedium boxclose cursorpointer marginleftonly" rel="x:y" id="imgclose'.$this->box_id.'"');
280 $label = $head['text'];
281 //if (!empty($head['graph'])) $label.=' ('.$langs->trans("Graph").')';
282 if (!empty($head['graph'])) {
283 $label .= ' <span class="opacitymedium fas fa-chart-bar"></span>';
284 }
285 $out .= '<input type="hidden" id="boxlabelentry'.$this->box_id.'" value="'.dol_escape_htmltag($label).'">';
286 //$out.= '</td></tr></table>';
287 $out .= '</div>';
288 }
289
290 $out .= "</th>";
291 $out .= "</tr>\n";
292 }
293
294 // Show box lines
295 if ($nblines) {
296 // Loop on each record
297 foreach (array_keys($contents) as $i) {
298 if (isset($contents[$i]) && is_array($contents[$i])) {
299 // TR
300 if (isset($contents[$i][0]['tr'])) {
301 $out .= '<tr '.$contents[$i][0]['tr'].'>';
302 } else {
303 $out .= '<tr class="oddeven">';
304 }
305
306 // Loop on each TD
307 $nbcolthisline = count($contents[$i]);
308 foreach (array_keys($contents[$i]) as $j) {
309 // Define tdparam
310 $tdparam = '';
311 if (!empty($contents[$i][$j]['td'])) {
312 $tdparam .= ' '.$contents[$i][$j]['td'];
313 }
314
315 $text = isset($contents[$i][$j]['text']) ? $contents[$i][$j]['text'] : '';
316 $textwithnotags = preg_replace('/<([^>]+)>/i', '', $text);
317 $text2 = isset($contents[$i][$j]['text2']) ? $contents[$i][$j]['text2'] : '';
318 $text2withnotags = preg_replace('/<([^>]+)>/i', '', $text2);
319
320 $textnoformat = isset($contents[$i][$j]['textnoformat']) ? $contents[$i][$j]['textnoformat'] : '';
321 //$out.= "xxx $textwithnotags y";
322 if (empty($contents[$i][$j]['tooltip'])) {
323 $contents[$i][$j]['tooltip'] = "";
324 }
325 $tooltip = isset($contents[$i][$j]['tooltip']) ? $contents[$i][$j]['tooltip'] : '';
326
327 $out .= '<td'.$tdparam.'>'."\n";
328
329 // Url
330 if (!empty($contents[$i][$j]['url']) && empty($contents[$i][$j]['logo'])) {
331 $out .= '<a href="'.$contents[$i][$j]['url'].'"';
332 if (!empty($tooltip)) {
333 $out .= ' title="'.dol_escape_htmltag($langs->trans("Show").' '.$tooltip, 1).'" class="classfortooltip"';
334 }
335 //$out.= ' alt="'.$textwithnotags.'"'; // Pas de alt sur un "<a href>"
336 $out .= isset($contents[$i][$j]['target']) ? ' target="'.$contents[$i][$j]['target'].'"' : '';
337 $out .= '>';
338 }
339
340 // Logo
341 if (!empty($contents[$i][$j]['logo'])) {
342 $logo = preg_replace("/^object_/i", "", $contents[$i][$j]['logo']);
343 $out .= '<a href="'.$contents[$i][$j]['url'].'">';
344 $out .= img_object($langs->trans("Show").' '.$tooltip, $logo, 'class="classfortooltip"');
345 }
346
347 $maxlength = $MAXLENGTHBOX;
348 if (isset($contents[$i][$j]['maxlength'])) {
349 $maxlength = $contents[$i][$j]['maxlength'];
350 }
351
352 if ($maxlength) {
353 $textwithnotags = dol_trunc($textwithnotags, $maxlength);
354 }
355 if (preg_match('/^<(img|div|span)/i', $text) || !empty($contents[$i][$j]['asis'])) {
356 $out .= $text; // show text with no html cleaning
357 } else {
358 $out .= $textwithnotags; // show text with html cleaning
359 }
360
361 // End Url
362 if (!empty($contents[$i][$j]['url'])) {
363 $out .= '</a>';
364 }
365
366 if (preg_match('/^<(img|div|span)/i', $text2) || !empty($contents[$i][$j]['asis2'])) {
367 $out .= $text2; // show text with no html cleaning
368 } else {
369 $out .= $text2withnotags; // show text with html cleaning
370 }
371
372 if (!empty($textnoformat)) {
373 $out .= "\n".$textnoformat."\n";
374 }
375
376 $out .= "</td>\n";
377 }
378
379 $out .= "</tr>\n";
380 }
381 }
382 }
383
384 if (!empty($head['text']) || !empty($head['sublink']) || !empty($head['subpicto']) || $nblines) {
385 $out .= "</table>\n";
386 }
387
388 // If invisible box with no contents
389 if (empty($head['text']) && empty($head['sublink']) && empty($head['subpicto']) && !$nblines) {
390 $out .= "<br>\n";
391 }
392
393 $out .= "</div>\n";
394
395 $out .= "<!-- Box ".get_class($this)." end -->\n\n";
396 if (getDolGlobalString('MAIN_ACTIVATE_FILECACHE')) {
397 dol_filecache($cachedir, $filename, $out);
398 }
399 } else {
400 dol_syslog(get_class($this).'::showBoxCached');
401 $out = "<!-- Box ".get_class($this)." from cache -->";
402 $out .= dol_readcachefile($cachedir, $filename);
403 }
404
405 if ($nooutput) {
406 return $out;
407 } else {
408 print $out;
409 }
410
411 return '';
412 }
413
414
422 public static function getWidgetsList($forcedirwidget = null)
423 {
424 global $langs, $db;
425
426 $files = array();
427 $fullpath = array();
428 $relpath = array();
429 $iscoreorexternal = array();
430 $modules = array();
431 $orders = array();
432 $i = 0;
433
434 //$dirwidget=array_merge(array('/core/boxes/'), $conf->modules_parts['widgets']);
435 $dirwidget = array('/core/boxes/'); // $conf->modules_parts['widgets'] is not required
436 if (is_array($forcedirwidget)) {
437 $dirwidget = $forcedirwidget;
438 }
439
440 foreach ($dirwidget as $reldir) {
441 $dir = dol_buildpath($reldir, 0);
442 $newdir = dol_osencode($dir);
443
444 // Check if directory exists (we do not use dol_is_dir to avoid loading files.lib.php at each call)
445 if (!is_dir($newdir)) {
446 continue;
447 }
448
449 $handle = opendir($newdir);
450 if (is_resource($handle)) {
451 while (($file = readdir($handle)) !== false) {
452 $reg = array();
453 if (is_readable($newdir.'/'.$file) && preg_match('/^(.+)\.php/', $file, $reg)) {
454 if (preg_match('/\.back$/', $file) || preg_match('/^(.+)\.disabled\.php/', $file)) {
455 continue;
456 }
457
458 $part1 = $reg[1];
459
460 $modName = ucfirst($reg[1]);
461 //print "file=$file"; print "modName=$modName"; exit;
462 if (in_array($modName, $modules)) {
463 $langs->load("errors");
464 print '<div class="error">'.$langs->trans("Error").' : '.$langs->trans("ErrorDuplicateWidget", $modName, "").'</div>';
465 } else {
466 try {
467 include_once $newdir.'/'.$file;
468 } catch (Exception $e) {
469 print $e->getMessage();
470 }
471 }
472
473 $files[$i] = $file;
474 $fullpath[$i] = $dir.'/'.$file;
475 $relpath[$i] = preg_replace('/^\//', '', $reldir).'/'.$file;
476 $iscoreorexternal[$i] = ($reldir == '/core/boxes/' ? 'internal' : 'external');
477 $modules[$i] = $modName;
478 $orders[$i] = $part1; // Set sort criteria value
479
480 $i++;
481 }
482 }
483 closedir($handle);
484 }
485 }
486 //echo "<pre>";print_r($modules);echo "</pre>";
487
488 asort($orders);
489
490 $widget = array();
491 $j = 0;
492
493 // Loop on each widget
494 foreach ($orders as $key => $value) {
495 $modName = $modules[$key];
496 if (empty($modName)) {
497 continue;
498 }
499
500 if (!class_exists($modName)) {
501 print 'Error: A widget file was found but its class "'.$modName.'" was not found.'."<br>\n";
502 continue;
503 }
504
505 $objMod = new $modName($db);
506 if (is_object($objMod)) {
507 // Define disabledbyname and disabledbymodule
508 $disabledbyname = 0;
509 $disabledbymodule = 0; // TODO Set to 2 if module is not enabled
510 $module = '';
511
512 // Check if widget file is disabled by name
513 if (preg_match('/NORUN$/i', $files[$key])) {
514 $disabledbyname = 1;
515 }
516
517 // We set info of modules
518 $widget[$j]['picto'] = (empty($objMod->picto) ? (empty($objMod->boximg) ? img_object('', 'generic') : $objMod->boximg) : img_object('', $objMod->picto));
519 $widget[$j]['file'] = $files[$key];
520 $widget[$j]['fullpath'] = $fullpath[$key];
521 $widget[$j]['relpath'] = $relpath[$key];
522 $widget[$j]['iscoreorexternal'] = $iscoreorexternal[$key];
523 $widget[$j]['version'] = empty($objMod->version) ? '' : $objMod->version;
524 $widget[$j]['status'] = img_picto($langs->trans("Active"), 'tick');
525 if ($disabledbyname > 0 || $disabledbymodule > 1) {
526 $widget[$j]['status'] = '';
527 }
528
529 $text = '<b>'.$langs->trans("Description").':</b><br>';
530 $text .= $objMod->boxlabel.'<br>';
531 $text .= '<br><b>'.$langs->trans("Status").':</b><br>';
532 if ($disabledbymodule == 2) {
533 $text .= $langs->trans("WidgetDisabledAsModuleDisabled", $module).'<br>';
534 }
535
536 $widget[$j]['info'] = $text;
537 }
538 $j++;
539 }
540
541 return $widget;
542 }
543}
print $object position
Definition edit.php:195
Class ModeleBoxes.
showBox($head, $contents, $nooutput=0)
Standard method to show a box (usage by boxes not mandatory, a box can still use its own showBox func...
fetch($rowid)
Load a box line from its rowid.
error()
Return last error message.
__construct($db, $param='')
Constructor.
static getWidgetsList($forcedirwidget=null)
Return list of widget.
dol_filecache($directory, $filename, $object)
Store object in file.
dol_readcachefile($directory, $filename)
Read object from cachefile.
dol_cache_refresh($directory, $filename, $cachetime)
Test if Refresh needed.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
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.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
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...
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall TAKEPOS_SHOW_SUBPRICE right right right takeposterminal SELECT e rowid
Definition invoice.php:1991