dolibarr  20.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 
35 class 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.'" width="100%" class="noborder boxtable">'."\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.
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:744
print *****$script_file(".$version.") pid c cd cd cd description as p label as s rowid
dol_filecache($directory, $filename, $object)
Store object in file.
Definition: files.lib.php:3435
dol_readcachefile($directory, $filename)
Read object from cachefile.
Definition: files.lib.php:3468
dol_cache_refresh($directory, $filename, $cachetime)
Test if Refresh needed.
Definition: files.lib.php:3453
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...