dolibarr 21.0.0-alpha
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
47 public $version;
48
52 public $param;
53
57 public $info_box_head = array();
58
62 public $info_box_contents = array();
63
67 public $error = '';
68
72 public $max = 5;
73
77 public $enabled = 1;
78
82 public $hidden = false;
83
87 public $rowid;
88
93 public $id;
94
98 public $position;
99
103 public $box_order;
104
108 public $fk_user;
109
113 public $sourcefile;
114
118 public $class;
119
123 public $box_id;
124
128 public $boxcode;
129
133 public $note;
134
138 public $widgettype = '';
139
140
142
147 public $boximg;
151 public $boxlabel;
155 public $depends;
156
157
158
165 public function __construct($db, $param = '')
166 {
167 $this->db = $db;
168 }
169
175 public function error()
176 {
177 return $this->error;
178 }
179
180
188 public function fetch($rowid)
189 {
190 global $conf;
191
192 // Recupere liste des boites d'un user si ce dernier a sa propre liste
193 $sql = "SELECT b.rowid as id, b.box_id, b.position, b.box_order, b.fk_user";
194 $sql .= " FROM ".MAIN_DB_PREFIX."boxes as b";
195 $sql .= " WHERE b.entity = ".$conf->entity;
196 $sql .= " AND b.rowid = ".((int) $rowid);
197
198 dol_syslog(get_class($this)."::fetch rowid=".((int) $rowid));
199
200 $resql = $this->db->query($sql);
201 if ($resql) {
202 $obj = $this->db->fetch_object($resql);
203 if ($obj) {
204 $this->id = $obj->id;
205 $this->rowid = $obj->id; // For backward compatibility
206 $this->box_id = $obj->box_id;
207 $this->position = $obj->position;
208 $this->box_order = $obj->box_order;
209 $this->fk_user = $obj->fk_user;
210 return 1;
211 } else {
212 return -1;
213 }
214 } else {
215 return -1;
216 }
217 }
218
227 public function showBox($head = null, $contents = null, $nooutput = 0)
228 {
229 global $langs, $user, $conf;
230
231 if (!empty($this->hidden)) {
232 return "\n<!-- Box ".get_class($this)." hidden -->\n"; // Nothing done if hidden (for example when user has no permission)
233 }
234
235 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
236
237 $MAXLENGTHBOX = 60; // When set to 0: no length limit
238
239 $cachetime = 900; // 900 : 15mn
240 $cachedir = DOL_DATA_ROOT.'/users/temp/widgets';
241 $fileid = get_class($this).'id-'.$this->box_id.'-e'.$conf->entity.'-u'.$user->id.'-s'.$user->socid.'.cache';
242 $filename = '/box-'.$fileid;
243 $refresh = dol_cache_refresh($cachedir, $filename, $cachetime);
244 $out = '';
245
246 if ($contents === null) {
247 $contents = array();
248 }
249
250 if ($refresh) {
251 dol_syslog(get_class($this).'::showBox');
252
253 // Define nbcol and nblines of the box to show
254 $nbcol = 0;
255 if (isset($contents[0])) {
256 $nbcol = count($contents[0]);
257 }
258 $nblines = count($contents);
259
260 $out .= "\n<!-- Box ".get_class($this)." start -->\n";
261
262 $out .= '<div class="box divboxtable boxdraggable" id="boxto_'.$this->box_id.'">'."\n";
263 if (!empty($head['text']) || !empty($head['sublink']) || !empty($head['subpicto']) || $nblines) {
264 $out .= '<table summary="boxtable'.$this->box_id.'" width="100%" class="noborder boxtable">'."\n";
265 }
266
267 // Show box title
268 if (!empty($head['text']) || !empty($head['sublink']) || !empty($head['subpicto'])) {
269 $out .= '<tr class="liste_titre box_titre">';
270 $out .= '<th';
271 if (!empty($head['nbcol'])) {
272 $nbcol = $head['nbcol'];
273 }
274 if ($nbcol > 1) {
275 $out .= ' colspan="'.$nbcol.'"';
276 }
277 $out .= '>';
278 if (!empty($conf->use_javascript_ajax)) {
279 //$out.= '<table summary="" class="nobordernopadding" width="100%"><tr><td class="tdoverflowmax150 maxwidth150onsmartphone">';
280 $out .= '<div class="tdoverflowmax400 maxwidth250onsmartphone float">';
281 }
282 if (!empty($head['text'])) {
283 $s = dol_trunc($head['text'], isset($head['limit']) ? $head['limit'] : $MAXLENGTHBOX);
284 $out .= $s;
285 }
286 if (!empty($conf->use_javascript_ajax)) {
287 $out .= '</div>';
288 }
289 //$out.= '</td>';
290
291 if (!empty($conf->use_javascript_ajax)) {
292 $sublink = '';
293 if (!empty($head['sublink'])) {
294 $sublink .= '<a href="'.$head['sublink'].'"'.(empty($head['target']) ? '' : ' target="'.$head['target'].'"').'>';
295 }
296 if (!empty($head['subpicto'])) {
297 $sublink .= img_picto($head['subtext'], $head['subpicto'], 'class="opacitymedium marginleftonly '.(empty($head['subclass']) ? '' : $head['subclass']).'" id="idsubimg'.$this->boxcode.'"');
298 }
299 if (!empty($head['sublink'])) {
300 $sublink .= '</a>';
301 }
302
303 //$out.= '<td class="nocellnopadd boxclose right nowraponall">';
304 $out .= '<div class="nocellnopadd boxclose floatright nowraponall">';
305 $out .= $sublink;
306 // 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
307 $out .= img_picto($langs->trans("MoveBox", $this->box_id), 'grip_title', 'class="opacitymedium boxhandle hideonsmartphone cursormove marginleftonly"');
308 $out .= img_picto($langs->trans("CloseBox", $this->box_id), 'close_title', 'class="opacitymedium boxclose cursorpointer marginleftonly" rel="x:y" id="imgclose'.$this->box_id.'"');
309 $label = $head['text'];
310 //if (!empty($head['graph'])) $label.=' ('.$langs->trans("Graph").')';
311 if (!empty($head['graph'])) {
312 $label .= ' <span class="opacitymedium fas fa-chart-bar"></span>';
313 }
314 $out .= '<input type="hidden" id="boxlabelentry'.$this->box_id.'" value="'.dol_escape_htmltag($label).'">';
315 //$out.= '</td></tr></table>';
316 $out .= '</div>';
317 }
318
319 $out .= "</th>";
320 $out .= "</tr>\n";
321 }
322
323 // Show box lines
324 if ($nblines) {
325 // Loop on each record
326 foreach (array_keys($contents) as $i) {
327 if (isset($contents[$i]) && is_array($contents[$i])) {
328 // TR
329 if (isset($contents[$i][0]['tr'])) {
330 $out .= '<tr '.$contents[$i][0]['tr'].'>';
331 } else {
332 $out .= '<tr class="oddeven">';
333 }
334
335 // Loop on each TD
336 $nbcolthisline = count($contents[$i]);
337 foreach (array_keys($contents[$i]) as $j) {
338 // Define tdparam
339 $tdparam = '';
340 if (!empty($contents[$i][$j]['td'])) {
341 $tdparam .= ' '.$contents[$i][$j]['td'];
342 }
343
344 $text = isset($contents[$i][$j]['text']) ? $contents[$i][$j]['text'] : '';
345 $textwithnotags = preg_replace('/<([^>]+)>/i', '', $text);
346 $text2 = isset($contents[$i][$j]['text2']) ? $contents[$i][$j]['text2'] : '';
347 $text2withnotags = preg_replace('/<([^>]+)>/i', '', $text2);
348
349 $textnoformat = isset($contents[$i][$j]['textnoformat']) ? $contents[$i][$j]['textnoformat'] : '';
350 //$out.= "xxx $textwithnotags y";
351 if (empty($contents[$i][$j]['tooltip'])) {
352 $contents[$i][$j]['tooltip'] = "";
353 }
354 $tooltip = isset($contents[$i][$j]['tooltip']) ? $contents[$i][$j]['tooltip'] : '';
355
356 $out .= '<td'.$tdparam.'>'."\n";
357
358 // Url
359 if (!empty($contents[$i][$j]['url']) && empty($contents[$i][$j]['logo'])) {
360 $out .= '<a href="'.$contents[$i][$j]['url'].'"';
361 if (!empty($tooltip)) {
362 $out .= ' title="'.dol_escape_htmltag($langs->trans("Show").' '.$tooltip, 1).'" class="classfortooltip"';
363 }
364 //$out.= ' alt="'.$textwithnotags.'"'; // Pas de alt sur un "<a href>"
365 $out .= isset($contents[$i][$j]['target']) ? ' target="'.$contents[$i][$j]['target'].'"' : '';
366 $out .= '>';
367 }
368
369 // Logo
370 if (!empty($contents[$i][$j]['logo'])) {
371 $logo = preg_replace("/^object_/i", "", $contents[$i][$j]['logo']);
372 $out .= '<a href="'.$contents[$i][$j]['url'].'">';
373 $out .= img_object($langs->trans("Show").' '.$tooltip, $logo, 'class="classfortooltip"');
374 }
375
376 $maxlength = $MAXLENGTHBOX;
377 if (isset($contents[$i][$j]['maxlength'])) {
378 $maxlength = $contents[$i][$j]['maxlength'];
379 }
380
381 if ($maxlength) {
382 $textwithnotags = dol_trunc($textwithnotags, $maxlength);
383 }
384 if (preg_match('/^<(img|div|span)/i', $text) || !empty($contents[$i][$j]['asis'])) {
385 $out .= $text; // show text with no html cleaning
386 } else {
387 $out .= $textwithnotags; // show text with html cleaning
388 }
389
390 // End Url
391 if (!empty($contents[$i][$j]['url'])) {
392 $out .= '</a>';
393 }
394
395 if (preg_match('/^<(img|div|span)/i', $text2) || !empty($contents[$i][$j]['asis2'])) {
396 $out .= $text2; // show text with no html cleaning
397 } else {
398 $out .= $text2withnotags; // show text with html cleaning
399 }
400
401 if (!empty($textnoformat)) {
402 $out .= "\n".$textnoformat."\n";
403 }
404
405 $out .= "</td>\n";
406 }
407
408 $out .= "</tr>\n";
409 }
410 }
411 }
412
413 if (!empty($head['text']) || !empty($head['sublink']) || !empty($head['subpicto']) || $nblines) {
414 $out .= "</table>\n";
415 }
416
417 // If invisible box with no contents
418 if (empty($head['text']) && empty($head['sublink']) && empty($head['subpicto']) && !$nblines) {
419 $out .= "<br>\n";
420 }
421
422 $out .= "</div>\n";
423
424 $out .= "<!-- Box ".get_class($this)." end -->\n\n";
425 if (getDolGlobalString('MAIN_ACTIVATE_FILECACHE')) {
426 dol_filecache($cachedir, $filename, $out);
427 }
428 } else {
429 dol_syslog(get_class($this).'::showBoxCached');
430 $out = "<!-- Box ".get_class($this)." from cache -->";
431 $out .= dol_readcachefile($cachedir, $filename);
432 }
433
434 if ($nooutput) {
435 return $out;
436 } else {
437 print $out;
438 }
439
440 return '';
441 }
442
443
452 public static function getWidgetsList($forcedirwidget = null)
453 {
454 global $langs, $db;
455
456 $files = array();
457 $fullpath = array();
458 $relpath = array();
459 $iscoreorexternal = array();
460 $modules = array();
461 $orders = array();
462 $i = 0;
463
464 //$dirwidget=array_merge(array('/core/boxes/'), $conf->modules_parts['widgets']);
465 $dirwidget = array('/core/boxes/'); // $conf->modules_parts['widgets'] is not required
466 if (is_array($forcedirwidget)) {
467 $dirwidget = $forcedirwidget;
468 }
469
470 foreach ($dirwidget as $reldir) {
471 $dir = dol_buildpath($reldir, 0);
472 $newdir = dol_osencode($dir);
473
474 // Check if directory exists (we do not use dol_is_dir to avoid loading files.lib.php at each call)
475 if (!is_dir($newdir)) {
476 continue;
477 }
478
479 $handle = opendir($newdir);
480 if (is_resource($handle)) {
481 while (($file = readdir($handle)) !== false) {
482 $reg = array();
483 if (is_readable($newdir.'/'.$file) && preg_match('/^(.+)\.php/', $file, $reg)) {
484 if (preg_match('/\.back$/', $file) || preg_match('/^(.+)\.disabled\.php/', $file)) {
485 continue;
486 }
487
488 $part1 = $reg[1];
489
490 $modName = ucfirst($reg[1]);
491 //print "file=$file"; print "modName=$modName"; exit;
492 if (in_array($modName, $modules)) {
493 $langs->load("errors");
494 print '<div class="error">'.$langs->trans("Error").' : '.$langs->trans("ErrorDuplicateWidget", $modName, "").'</div>';
495 } else {
496 try {
497 include_once $newdir.'/'.$file;
498 } catch (Exception $e) {
499 print $e->getMessage();
500 }
501 }
502
503 $files[$i] = $file;
504 $fullpath[$i] = $dir.'/'.$file;
505 $relpath[$i] = preg_replace('/^\//', '', $reldir).'/'.$file;
506 $iscoreorexternal[$i] = ($reldir == '/core/boxes/' ? 'internal' : 'external');
507 $modules[$i] = $modName;
508 $orders[$i] = $part1; // Set sort criteria value
509
510 $i++;
511 }
512 }
513 closedir($handle);
514 }
515 }
516 //echo "<pre>";print_r($modules);echo "</pre>";
517
518 asort($orders);
519
520 $widget = array();
521 $j = 0;
522
523 // Loop on each widget
524 foreach ($orders as $key => $value) {
525 $modName = $modules[$key];
526 if (empty($modName)) {
527 continue;
528 }
529
530 if (!class_exists($modName)) {
531 print 'Error: A widget file was found but its class "'.$modName.'" was not found.'."<br>\n";
532 continue;
533 }
534
535 $objMod = new $modName($db);
536 '@phan-var-force ModeleBoxes $objMod';
537 if (is_object($objMod)) {
538 // Define disabledbyname and disabledbymodule
539 $disabledbyname = 0;
540 $disabledbymodule = 0; // TODO Set to 2 if module is not enabled
541 $module = '';
542
543 // Check if widget file is disabled by name
544 if (preg_match('/NORUN$/i', $files[$key])) {
545 $disabledbyname = 1;
546 }
547
548 // We set info of modules @phan-suppress-next-line PhanUndeclaredProperty
549 $widget[$j]['picto'] = ((!property_exists($objMod, 'picto') || empty($objMod->picto)) ? (empty($objMod->boximg) ? img_object('', 'generic') : $objMod->boximg) : img_object('', $objMod->picto));
550 $widget[$j]['file'] = $files[$key];
551 $widget[$j]['fullpath'] = $fullpath[$key];
552 $widget[$j]['relpath'] = $relpath[$key];
553 $widget[$j]['iscoreorexternal'] = $iscoreorexternal[$key];
554 $widget[$j]['version'] = empty($objMod->version) ? '' : $objMod->version;
555 $widget[$j]['status'] = img_picto($langs->trans("Active"), 'tick');
556 if ($disabledbyname > 0 || $disabledbymodule > 1) {
557 $widget[$j]['status'] = '';
558 }
559
560 $text = '<b>'.$langs->trans("Description").':</b><br>';
561 $text .= $objMod->boxlabel.'<br>';
562 $text .= '<br><b>'.$langs->trans("Status").':</b><br>';
563 if ($disabledbymodule == 2) {
564 $text .= $langs->trans("WidgetDisabledAsModuleDisabled", $module).'<br>';
565 }
566
567 $widget[$j]['info'] = $text;
568 }
569 $j++;
570 }
571
572 return $widget;
573 }
574}
print $object position
Definition edit.php:195
Class ModeleBoxes.
showBox($head=null, $contents=null, $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 a 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:2001