Passed
Push — main ( 131f20...c1d479 )
by Rafael
51:37
created

DashboardController   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 816
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 505
c 1
b 0
f 0
dl 0
loc 816
rs 10
wmc 6

3 Methods

Rating   Name   Duplication   Size   Complexity  
B getWeatherStatus() 0 38 6
A showWeather() 0 6 1
B index() 0 814 6
1
<?php
2
3
/* Copyright (C) 2001-2004  Rodolphe Quiedeville    <[email protected]>
4
 * Copyright (C) 2004-2020	Laurent Destailleur		<[email protected]>
5
 * Copyright (C) 2005-2017	Regis Houssin			<[email protected]>
6
 * Copyright (C) 2011-2012	Juanjo Menent			<[email protected]>
7
 * Copyright (C) 2015		Marcos García			<[email protected]>
8
 * Copyright (C) 2021		Frédéric France			<[email protected]>
9
 * Copyright (C) 2024		Rafael San José         <[email protected]>
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
23
 */
24
25
namespace DoliModules\User\Controller;
26
27
global $conf;
28
global $db;
29
global $user;
30
global $hookmanager;
31
global $user;
32
global $menumanager;
33
global $langs;
34
global $mysoc;
35
36
/**
37
 *  \file       htdocs/index.php
38
 *  \brief      Dolibarr home page
39
 */
40
41
use DoliCore\Base\DolibarrController;
42
use DoliCore\Form\Form;
43
use DoliCore\Form\FormOther;
44
use DoliModules\Accounting\Model\BonPrelevement;
45
use DoliModules\Accounting\Model\RemiseCheque;
46
use DoliModules\Adherent\Model\Adherent;
47
use DoliModules\Agenda\Model\ActionComm;
48
use DoliModules\Bank\Model\Account;
49
use DoliModules\Billing\Model\Commande;
50
use DoliModules\Billing\Model\Facture;
51
use DoliModules\Contract\Model\Contrat;
52
use DoliModules\ExpenseReport\Model\ExpenseReport;
53
use DoliModules\Holiday\Model\Holiday;
54
use DoliModules\Project\Model\Project;
55
use DoliModules\Project\Model\Task;
56
use DoliModules\Proposal\Model\Propal;
57
use DoliModules\Supplier\Model\CommandeFournisseur;
58
use DoliModules\Supplier\Model\FactureFournisseur;
59
use DoliModules\SupplierProposal\Model\SupplierProposal;
60
use DoliModules\Ticket\Model\Ticket;
61
62
class DashboardController extends DolibarrController
63
{
64
    public function index(bool $executeActions = true): bool
65
    {
66
        global $conf;
67
        global $db;
68
        global $user;
69
        global $hookmanager;
70
        global $user;
71
        global $menumanager;
72
        global $langs;
73
74
        define('CSRFCHECK_WITH_TOKEN', 1); // We force need to use a token to login when making a POST
75
76
        require BASE_PATH . '/main.inc.php';
77
78
// If not defined, we select menu "home"
79
        $_GET['mainmenu'] = GETPOST('mainmenu', 'aZ09') ? GETPOST('mainmenu', 'aZ09') : 'home';
80
        $action = GETPOST('action', 'aZ09');
81
82
        $hookmanager->initHooks(array('index'));
83
84
        /*
85
         * Actions
86
         */
87
88
        $nbmodulesnotautoenabled = count($conf->modules);
89
        if (in_array('fckeditor', $conf->modules)) $nbmodulesnotautoenabled--;
90
        if (in_array('export', $conf->modules)) $nbmodulesnotautoenabled--;
91
        if (in_array('import', $conf->modules)) $nbmodulesnotautoenabled--;
92
93
// Check if company name is defined (first install)
94
        if (!isset($conf->global->MAIN_INFO_SOCIETE_NOM) || !getDolGlobalString('MAIN_INFO_SOCIETE_NOM')) {
95
            header("Location: " . DOL_URL_ROOT . "/admin/index.php?mainmenu=home&leftmenu=setup&mesg=setupnotcomplete");
96
            exit;
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return boolean. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
97
        }
98
        if ($nbmodulesnotautoenabled <= getDolGlobalString('MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING', 1)) {  // If only user module enabled
99
            header("Location: " . DOL_URL_ROOT . "/admin/index.php?mainmenu=home&leftmenu=setup&mesg=setupnotcomplete");
100
            exit;
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return boolean. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
101
        }
102
        if (GETPOST('addbox')) {    // Add box (when submit is done from a form when ajax disabled)
103
            require_once DOL_DOCUMENT_ROOT . '/core/class/infobox.class.php';
104
            $zone = GETPOSTINT('areacode');
105
            $userid = GETPOSTINT('userid');
106
            $boxorder = GETPOST('boxorder', 'aZ09');
107
            $boxorder .= GETPOST('boxcombo', 'aZ09');
108
109
            $result = InfoBox::saveboxorder($db, $zone, $boxorder, $userid);
110
            if ($result > 0) {
111
                setEventMessages($langs->trans("BoxAdded"), null);
112
            }
113
        }
114
115
        /*
116
         * View
117
         */
118
119
        if (!isset($form) || !is_object($form)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $form seems to never exist and therefore isset should always be false.
Loading history...
120
            $form = new Form($db);
121
        }
122
123
// Title
124
        $title = $langs->trans("HomeArea") . ' - Dolibarr ' . DOL_VERSION;
125
        if (getDolGlobalString('MAIN_APPLICATION_TITLE')) {
126
            $title = $langs->trans("HomeArea") . ' - ' . getDolGlobalString('MAIN_APPLICATION_TITLE');
127
        }
128
129
        llxHeader('', $title);
130
131
        $resultboxes = FormOther::getBoxesArea($user, "0"); // Load $resultboxes (selectboxlist + boxactivated + boxlista + boxlistb)
132
133
        print load_fiche_titre('&nbsp;', $resultboxes['selectboxlist'], '', 0, '', 'titleforhome');
134
135
        if (getDolGlobalString('MAIN_MOTD')) {
136
            $conf->global->MAIN_MOTD = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>/i', '<br>', getDolGlobalString('MAIN_MOTD'));
137
            if (getDolGlobalString('MAIN_MOTD')) {
138
                $substitutionarray = getCommonSubstitutionArray($langs);
139
                complete_substitutions_array($substitutionarray, $langs);
140
                $texttoshow = make_substitutions(getDolGlobalString('MAIN_MOTD'), $substitutionarray, $langs);
141
142
                print "\n<!-- Start of welcome text -->\n";
143
                print '<table class="centpercent notopnoleftnoright"><tr><td>';
144
                print dol_htmlentitiesbr($texttoshow);
145
                print '</td></tr></table><br>';
146
                print "\n<!-- End of welcome text -->\n";
147
            }
148
        }
149
150
        /*
151
         * Show security warnings
152
         */
153
154
// Security warning if install.lock file is missing or if conf file is writable
155
        if (!getDolGlobalString('MAIN_REMOVE_INSTALL_WARNING')) {
156
            $message = '';
157
158
            // Check if install lock file is present
159
            $lockfile = DOL_DATA_ROOT . '/install.lock';
160
            if (!empty($lockfile) && !file_exists($lockfile) && is_dir(DOL_DOCUMENT_ROOT . "/install")) {
161
                $langs->load("errors");
162
                //if (!empty($message)) $message.='<br>';
163
                $message .= info_admin($langs->transnoentities("WarningLockFileDoesNotExists", DOL_DATA_ROOT) . ' ' . $langs->transnoentities("WarningUntilDirRemoved", DOL_DOCUMENT_ROOT . "/install"), 0, 0, '1', 'clearboth');
164
            }
165
166
            // Conf files must be in read only mode
167
            if (is_writable($conffile)) {   // $conffile is defined into filefunc.inc.php
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $conffile seems to be never defined.
Loading history...
168
                $langs->load("errors");
169
                //$langs->load("other");
170
                //if (!empty($message)) $message.='<br>';
171
                $message .= info_admin($langs->transnoentities("WarningConfFileMustBeReadOnly") . ' ' . $langs->transnoentities("WarningUntilDirRemoved", DOL_DOCUMENT_ROOT . "/install"), 0, 0, '1', 'clearboth');
172
            }
173
174
            $object = new stdClass();
0 ignored issues
show
Bug introduced by
The type DoliModules\User\Controller\stdClass was not found. Did you mean stdClass? If so, make sure to prefix the type with \.
Loading history...
175
            $parameters = array();
176
            $reshook = $hookmanager->executeHooks('infoadmin', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
177
            if ($reshook == 0) {
178
                $message .= $hookmanager->resPrint;
179
            }
180
            if ($message) { // $message is an HTML string.
181
                print dol_string_onlythesehtmltags($message, 1, 0, 0, 0, array('div', 'span', 'b'));
182
                print '<br>';
183
                //print info_admin($langs->trans("WarningUntilDirRemoved",DOL_DOCUMENT_ROOT."/install"));
184
            }
185
        }
186
187
        /*
188
         * Dashboard Dolibarr statistics
189
         * Hidden for external users
190
         */
191
192
        $boxstatItems = array();
193
        $boxstatFromHook = '';
194
195
// Load translation files required by page
196
        $langs->loadLangs(array('commercial', 'bills', 'orders', 'contracts'));
197
198
// Dolibarr Working Board with weather
199
        if (!getDolGlobalString('MAIN_DISABLE_GLOBAL_WORKBOARD') && getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2) {
200
            $showweather = (!getDolGlobalString('MAIN_DISABLE_METEO') || getDolGlobalInt('MAIN_DISABLE_METEO') == 2) ? 1 : 0;
201
202
            //Array that contains all WorkboardResponse classes to process them
203
            $dashboardlines = array();
204
205
            // Number of actions to do (late)
206
            if (isModEnabled('agenda') && !getDolGlobalString('MAIN_DISABLE_BLOCK_AGENDA') && $user->hasRight('agenda', 'myactions', 'read')) {
207
                $board = new ActionComm($db);
208
                $dashboardlines[$board->element] = $board->load_board($user);
209
            }
210
211
            // Number of project opened
212
            if (isModEnabled('project') && !getDolGlobalString('MAIN_DISABLE_BLOCK_PROJECT') && $user->hasRight('projet', 'lire')) {
213
                $board = new Project($db);
214
                $dashboardlines[$board->element] = $board->load_board($user);
215
            }
216
217
            // Number of tasks to do (late)
218
            if (isModEnabled('project') && !getDolGlobalString('MAIN_DISABLE_BLOCK_PROJECT') && !getDolGlobalString('PROJECT_HIDE_TASKS') && $user->hasRight('projet', 'lire')) {
219
                $board = new Task($db);
220
                $dashboardlines[$board->element] = $board->load_board($user);
221
            }
222
223
            // Number of commercial customer proposals open (expired)
224
            if (isModEnabled('propal') && !getDolGlobalString('MAIN_DISABLE_BLOCK_CUSTOMER') && $user->hasRight('propal', 'read')) {
225
                $board = new Propal($db);
226
                $dashboardlines[$board->element . '_opened'] = $board->load_board($user, "opened");
227
                // Number of commercial proposals CLOSED signed (billed)
228
                $dashboardlines[$board->element . '_signed'] = $board->load_board($user, "signed");
229
            }
230
231
            // Number of supplier proposals open (expired)
232
            if (isModEnabled('supplier_proposal') && !getDolGlobalString('MAIN_DISABLE_BLOCK_SUPPLIER') && $user->hasRight('supplier_proposal', 'lire')) {
233
                $langs->load("supplier_proposal");
234
                $board = new SupplierProposal($db);
235
                $dashboardlines[$board->element . '_opened'] = $board->load_board($user, "opened");
236
                // Number of commercial proposals CLOSED signed (billed)
237
                $dashboardlines[$board->element . '_signed'] = $board->load_board($user, "signed");
238
            }
239
240
            // Number of sales orders
241
            if (isModEnabled('order') && !getDolGlobalString('MAIN_DISABLE_BLOCK_CUSTOMER') && $user->hasRight('commande', 'lire')) {
242
                $board = new Commande($db);
0 ignored issues
show
Deprecated Code introduced by
The class DoliModules\Billing\Model\Commande has been deprecated: Use Order instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

242
                $board = /** @scrutinizer ignore-deprecated */ new Commande($db);
Loading history...
243
                // Number of customer orders to be shipped (validated and in progress)
244
                $dashboardlines[$board->element . '_toship'] = $board->load_board($user, 'toship');
245
                // Number of customer orders to be billed (not visible by default, does not match a lot of organization).
246
                if (getDolGlobalInt('ORDER_BILL_AFTER_VALIDATION')) {
247
                    $dashboardlines[$board->element . '_tobill'] = $board->load_board($user, 'tobill');
248
                }
249
                // Number of customer orders to be billed (delivered but not billed)
250
                $dashboardlines[$board->element . '_shippedtobill'] = $board->load_board($user, 'shippedtobill');
251
            }
252
253
            // Number of suppliers orders
254
            if (isModEnabled('supplier_order') && !getDolGlobalString('MAIN_DISABLE_BLOCK_SUPPLIER') && $user->hasRight('fournisseur', 'commande', 'lire')) {
255
                $board = new CommandeFournisseur($db);
256
                $dashboardlines[$board->element . '_opened'] = $board->load_board($user, "opened");
257
                $dashboardlines[$board->element . '_awaiting'] = $board->load_board($user, 'awaiting');
258
            }
259
260
            // Number of contract / services enabled (delayed)
261
            if (isModEnabled('contract') && !getDolGlobalString('MAIN_DISABLE_BLOCK_CONTRACT') && $user->hasRight('contrat', 'lire')) {
262
                $board = new Contrat($db);
263
                $dashboardlines[$board->element . '_inactive'] = $board->load_board($user, "inactive");
264
                // Number of active services (expired)
265
                $dashboardlines[$board->element . '_active'] = $board->load_board($user, "active");
266
            }
267
268
            // Number of tickets open
269
            if (isModEnabled('ticket') && !getDolGlobalString('MAIN_DISABLE_BLOCK_TICKET') && $user->hasRight('ticket', 'read')) {
270
                $board = new Ticket($db);
271
                $dashboardlines[$board->element . '_opened'] = $board->load_board($user, "opened");
272
                // Number of active services (expired)
273
                //$dashboardlines[$board->element.'_active'] = $board->load_board($user, "active");
274
            }
275
276
            // Number of invoices customers (paid)
277
            if (isModEnabled('invoice') && !getDolGlobalString('MAIN_DISABLE_BLOCK_CUSTOMER') && $user->hasRight('facture', 'lire')) {
278
                $board = new Facture($db);
279
                $dashboardlines[$board->element] = $board->load_board($user);
280
            }
281
282
            // Number of supplier invoices (paid)
283
            if (isModEnabled('supplier_invoice') && !getDolGlobalString('MAIN_DISABLE_BLOCK_SUPPLIER') && $user->hasRight('fournisseur', 'facture', 'lire')) {
284
                $board = new FactureFournisseur($db);
285
                $dashboardlines[$board->element] = $board->load_board($user);
286
            }
287
288
            // Number of transactions to conciliate
289
            if (isModEnabled('bank') && !getDolGlobalString('MAIN_DISABLE_BLOCK_BANK') && $user->hasRight('banque', 'lire') && !$user->socid) {
290
                $board = new Account($db);
291
                $nb = $board->countAccountToReconcile(); // Get nb of account to reconciliate
292
                if ($nb > 0) {
293
                    $dashboardlines[$board->element] = $board->load_board($user);
294
                }
295
            }
296
297
298
            // Number of cheque to send
299
            if (isModEnabled('bank') && !getDolGlobalString('MAIN_DISABLE_BLOCK_BANK') && $user->hasRight('banque', 'lire') && !$user->socid) {
300
                if (!getDolGlobalString('BANK_DISABLE_CHECK_DEPOSIT')) {
301
                    include_once DOL_DOCUMENT_ROOT . '/compta/paiement/cheque/class/remisecheque.class.php';
302
                    $board = new RemiseCheque($db);
303
                    $dashboardlines[$board->element] = $board->load_board($user);
304
                }
305
                if (isModEnabled('prelevement')) {
306
                    include_once DOL_DOCUMENT_ROOT . '/compta/prelevement/class/bonprelevement.class.php';
307
                    $board = new BonPrelevement($db);
308
                    $dashboardlines[$board->element . '_direct_debit'] = $board->load_board($user, 'direct_debit');
309
                }
310
                if (isModEnabled('paymentbybanktransfer')) {
311
                    include_once DOL_DOCUMENT_ROOT . '/compta/prelevement/class/bonprelevement.class.php';
312
                    $board = new BonPrelevement($db);
313
                    $dashboardlines[$board->element . '_credit_transfer'] = $board->load_board($user, 'credit_transfer');
314
                }
315
            }
316
317
            // Number of foundation members
318
            if (isModEnabled('member') && !getDolGlobalString('MAIN_DISABLE_BLOCK_ADHERENT') && $user->hasRight('adherent', 'lire') && !$user->socid) {
319
                $board = new Adherent($db);
320
                $dashboardlines[$board->element . '_shift'] = $board->load_board($user, 'shift');
321
                $dashboardlines[$board->element . '_expired'] = $board->load_board($user, 'expired');
322
            }
323
324
            // Number of expense reports to approve
325
            if (isModEnabled('expensereport') && !getDolGlobalString('MAIN_DISABLE_BLOCK_EXPENSEREPORT') && $user->hasRight('expensereport', 'approve')) {
326
                $board = new ExpenseReport($db);
327
                $dashboardlines[$board->element . '_toapprove'] = $board->load_board($user, 'toapprove');
328
            }
329
330
            // Number of expense reports to pay
331
            if (isModEnabled('expensereport') && !getDolGlobalString('MAIN_DISABLE_BLOCK_EXPENSEREPORT') && $user->hasRight('expensereport', 'to_paid')) {
332
                $board = new ExpenseReport($db);
333
                $dashboardlines[$board->element . '_topay'] = $board->load_board($user, 'topay');
334
            }
335
336
            // Number of holidays to approve
337
            if (isModEnabled('holiday') && !getDolGlobalString('MAIN_DISABLE_BLOCK_HOLIDAY') && $user->hasRight('holiday', 'approve')) {
338
                $board = new Holiday($db);
339
                $dashboardlines[$board->element] = $board->load_board($user);
340
            }
341
342
            $object = new stdClass();
343
            $parameters = array();
344
            $action = '';
345
            $reshook = $hookmanager->executeHooks(
346
                'addOpenElementsDashboardLine',
347
                $parameters,
348
                $object,
349
                $action
350
            ); // Note that $action and $object may have been modified by some hooks
351
            if ($reshook == 0) {
352
                $dashboardlines = array_merge($dashboardlines, $hookmanager->resArray);
353
            }
354
355
            /* Open object dashboard */
356
            $dashboardgroup = array(
357
                'action' =>
358
                    array(
359
                        'groupName' => 'Agenda',
360
                        'stats' => array('action'),
361
                    ),
362
                'project' =>
363
                    array(
364
                        'groupName' => 'Projects',
365
                        'globalStatsKey' => 'projects',
366
                        'stats' => array('project', 'project_task'),
367
                    ),
368
                'propal' =>
369
                    array(
370
                        'groupName' => 'Proposals',
371
                        'globalStatsKey' => 'proposals',
372
                        'stats' =>
373
                            array('propal_opened', 'propal_signed'),
374
                    ),
375
                'commande' =>
376
                    array(
377
                        'groupName' => 'Orders',
378
                        'globalStatsKey' => 'orders',
379
                        'stats' =>
380
                            array('commande_toship', 'commande_tobill', 'commande_shippedtobill'),
381
                    ),
382
                'facture' =>
383
                    array(
384
                        'groupName' => 'Invoices',
385
                        'globalStatsKey' => 'invoices',
386
                        'stats' =>
387
                            array('facture'),
388
                    ),
389
                'supplier_proposal' =>
390
                    array(
391
                        'lang' => 'supplier_proposal',
392
                        'groupName' => 'SupplierProposals',
393
                        'globalStatsKey' => 'askprice',
394
                        'stats' =>
395
                            array('supplier_proposal_opened', 'supplier_proposal_signed'),
396
                    ),
397
                'order_supplier' =>
398
                    array(
399
                        'groupName' => 'SuppliersOrders',
400
                        'globalStatsKey' => 'supplier_orders',
401
                        'stats' =>
402
                            array('order_supplier_opened', 'order_supplier_awaiting'),
403
                    ),
404
                'invoice_supplier' =>
405
                    array(
406
                        'groupName' => 'BillsSuppliers',
407
                        'globalStatsKey' => 'supplier_invoices',
408
                        'stats' =>
409
                            array('invoice_supplier'),
410
                    ),
411
                'contrat' =>
412
                    array(
413
                        'groupName' => 'Contracts',
414
                        'globalStatsKey' => 'Contracts',
415
                        'stats' =>
416
                            array('contrat_inactive', 'contrat_active'),
417
                    ),
418
                'ticket' =>
419
                    array(
420
                        'groupName' => 'Tickets',
421
                        'globalStatsKey' => 'ticket',
422
                        'stats' =>
423
                            array('ticket_opened'),
424
                    ),
425
                'bank_account' =>
426
                    array(
427
                        'groupName' => 'BankAccount',
428
                        'stats' =>
429
                            array('bank_account', 'chequereceipt', 'widthdraw_direct_debit', 'widthdraw_credit_transfer'),
430
                    ),
431
                'member' =>
432
                    array(
433
                        'groupName' => 'Members',
434
                        'globalStatsKey' => 'members',
435
                        'stats' =>
436
                            array('member_shift', 'member_expired'),
437
                    ),
438
                'expensereport' =>
439
                    array(
440
                        'groupName' => 'ExpenseReport',
441
                        'globalStatsKey' => 'expensereports',
442
                        'stats' =>
443
                            array('expensereport_toapprove', 'expensereport_topay'),
444
                    ),
445
                'holiday' =>
446
                    array(
447
                        'groupName' => 'Holidays',
448
                        'globalStatsKey' => 'holidays',
449
                        'stats' =>
450
                            array('holiday'),
451
                    ),
452
            );
453
454
            $object = new stdClass();
455
            $parameters = array(
456
                'dashboardgroup' => $dashboardgroup
457
            );
458
            $reshook = $hookmanager->executeHooks('addOpenElementsDashboardGroup', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
459
            if ($reshook == 0) {
460
                $dashboardgroup = array_merge($dashboardgroup, $hookmanager->resArray);
461
            }
462
463
464
            // Calculate total nb of late
465
            $totallate = $totaltodo = 0;
466
467
            //Remove any invalid response
468
            //load_board can return an integer if failed, or WorkboardResponse if OK
469
            $valid_dashboardlines = array();
470
            foreach ($dashboardlines as $workboardid => $tmp) {
471
                if ($tmp instanceof WorkboardResponse) {
472
                    $tmp->id = $workboardid; // Complete the object to add its id into its name
473
                    $valid_dashboardlines[$workboardid] = $tmp;
474
                }
475
            }
476
477
            // We calculate $totallate. Must be defined before start of next loop because it is show in first fetch on next loop
478
            foreach ($valid_dashboardlines as $board) {
479
                if (is_numeric($board->nbtodo) && is_numeric($board->nbtodolate) && $board->nbtodolate > 0) {
480
                    $totaltodo += $board->nbtodo;
481
                    $totallate += $board->nbtodolate;
482
                }
483
            }
484
485
            $openedDashBoardSize = 'info-box-sm'; // use sm by default
486
            foreach ($dashboardgroup as $dashbordelement) {
487
                if (is_array($dashbordelement['stats']) && count($dashbordelement['stats']) > 2) {
488
                    $openedDashBoardSize = ''; // use default info box size : big
489
                    break;
490
                }
491
            }
492
493
            $totalLateNumber = $totallate;
494
            $totallatePercentage = ((!empty($totaltodo)) ? round($totallate / $totaltodo * 100, 2) : 0);
495
            if (getDolGlobalString('MAIN_USE_METEO_WITH_PERCENTAGE')) {
496
                $totallate = $totallatePercentage;
497
            }
498
499
            $boxwork = '';
500
            $boxwork .= '<div class="box">';
501
            $boxwork .= '<table summary="' . dol_escape_htmltag($langs->trans("WorkingBoard")) . '" class="noborder boxtable boxtablenobottom boxworkingboard centpercent">' . "\n";
502
            $boxwork .= '<tr class="liste_titre">';
503
            $boxwork .= '<th class="liste_titre"><div class="inline-block valignmiddle">' . $langs->trans("DolibarrWorkBoard") . '</div>';
504
            if ($showweather) {
505
                if ($totallate > 0) {
506
                    $text = $langs->transnoentitiesnoconv("WarningYouHaveAtLeastOneTaskLate") . ' (' . $langs->transnoentitiesnoconv(
507
                            "NActionsLate",
508
                            $totallate . (getDolGlobalString('MAIN_USE_METEO_WITH_PERCENTAGE') ? '%' : '')
509
                        ) . ')';
510
                } else {
511
                    $text = $langs->transnoentitiesnoconv("NoItemLate");
512
                }
513
                $text .= '. ' . $langs->transnoentitiesnoconv("LateDesc");
514
                //$text.=$form->textwithpicto('',$langs->trans("LateDesc"));
515
                $options = 'height="24px" style="float: right"';
516
                $boxwork .= showWeather($totallate, $text, $options, 'inline-block valignmiddle');
517
            }
518
            $boxwork .= '</th>';
519
            $boxwork .= '</tr>' . "\n";
520
521
            // Show dashboard
522
            $nbworkboardempty = 0;
523
            $isIntopOpenedDashBoard = $globalStatInTopOpenedDashBoard = array();
524
            if (!empty($valid_dashboardlines)) {
525
                $openedDashBoard = '';
526
527
                $boxwork .= '<tr class="nobottom nohover"><td class="tdboxstats nohover flexcontainer centpercent"><div style="display: flex: flex-wrap: wrap">';
528
529
                foreach ($dashboardgroup as $groupKey => $groupElement) {
530
                    $boards = array();
531
532
                    // Scan $groupElement and save the one with 'stats' that must be used for the open objects dashboard
533
                    if (!getDolGlobalString('MAIN_DISABLE_NEW_OPENED_DASH_BOARD')) {
534
                        foreach ($groupElement['stats'] as $infoKey) {
535
                            if (!empty($valid_dashboardlines[$infoKey])) {
536
                                $boards[] = $valid_dashboardlines[$infoKey];
537
                                $isIntopOpenedDashBoard[] = $infoKey;
538
                            }
539
                        }
540
                    }
541
542
                    if (!empty($boards)) {
543
                        if (!empty($groupElement['lang'])) {
544
                            $langs->load($groupElement['lang']);
545
                        }
546
                        $groupName = $langs->trans($groupElement['groupName']);
547
                        $groupKeyLowerCase = strtolower($groupKey);
548
549
                        // global stats
550
                        $globalStatsKey = false;
551
                        if (!empty($groupElement['globalStatsKey']) && empty($groupElement['globalStats'])) { // can be filled by hook
552
                            $globalStatsKey = $groupElement['globalStatsKey'];
553
                            $groupElement['globalStats'] = array();
554
                        }
555
556
                        $openedDashBoard .= '<div class="box-flex-item"><div class="box-flex-item-with-margin">' . "\n";
557
                        $openedDashBoard .= '	<div class="info-box ' . $openedDashBoardSize . '">' . "\n";
558
                        $openedDashBoard .= '		<span class="info-box-icon bg-infobox-' . $groupKeyLowerCase . '">' . "\n";
559
                        $openedDashBoard .= '		<i class="fa fa-dol-' . $groupKeyLowerCase . '"></i>' . "\n";
560
561
                        // Show the span for the total of record. TODO This seems not used.
562
                        if (!empty($groupElement['globalStats'])) {
563
                            $globalStatInTopOpenedDashBoard[] = $globalStatsKey;
564
                            $openedDashBoard .= '<span class="info-box-icon-text" title="' . $groupElement['globalStats']['text'] . '">' . $groupElement['globalStats']['nbTotal'] . '</span>';
565
                        }
566
567
                        $openedDashBoard .= '</span>' . "\n";
568
                        $openedDashBoard .= '<div class="info-box-content">' . "\n";
569
570
                        $openedDashBoard .= '<div class="info-box-title" title="' . strip_tags($groupName) . '">' . $groupName . '</div>' . "\n";
571
                        $openedDashBoard .= '<div class="info-box-lines">' . "\n";
572
573
                        foreach ($boards as $board) {
574
                            $openedDashBoard .= '<div class="info-box-line spanoverflow nowrap">';
575
576
                            if (!empty($board->labelShort)) {
577
                                $infoName = '<div class="marginrightonly inline-block valignmiddle info-box-line-text" title="' . $board->label . '">' . $board->labelShort . '</div>';
578
                            } else {
579
                                $infoName = '<div class="marginrightonly inline-block valignmiddle info-box-line-text">' . $board->label . '</div>';
580
                            }
581
582
                            $textLateTitle = $langs->trans("NActionsLate", $board->nbtodolate);
583
                            $textLateTitle .= ' (' . $langs->trans("Late") . ' = ' . $langs->trans("DateReference") . ' > ' . $langs->trans("DateToday") . ' ' . (ceil(empty($board->warning_delay) ? 0 : $board->warning_delay) >= 0 ? '+' : '') . ceil(empty($board->warning_delay) ? 0 : $board->warning_delay) . ' ' . $langs->trans("days") . ')';
584
585
                            if ($board->id == 'bank_account') {
586
                                $textLateTitle .= '<br><span class="opacitymedium">' . $langs->trans("IfYouDontReconcileDisableProperty", $langs->transnoentitiesnoconv("Conciliable")) . '</span>';
587
                            }
588
589
                            $textLate = '';
590
                            if ($board->nbtodolate > 0) {
591
                                $textLate .= '<span title="' . dol_escape_htmltag($textLateTitle) . '" class="classfortooltip badge badge-warning">';
592
                                $textLate .= '<i class="fa fa-exclamation-triangle"></i> ' . $board->nbtodolate;
593
                                $textLate .= '</span>';
594
                            }
595
596
                            $nbtodClass = '';
597
                            if ($board->nbtodo > 0) {
598
                                $nbtodClass = 'badge badge-info';
599
                            } else {
600
                                $nbtodClass = 'opacitymedium';
601
                            }
602
603
                            // Forge the line to show into the open object box
604
                            $labeltoshow = $board->label . ' (' . $board->nbtodo . ')';
605
                            if ($board->total > 0) {
606
                                $labeltoshow .= ' - ' . price($board->total, 0, $langs, 1, -1, -1, $conf->currency);
607
                            }
608
                            $openedDashBoard .= '<a href="' . $board->url . '" class="info-box-text info-box-text-a">';
609
                            $openedDashBoard .= $infoName;
610
                            $openedDashBoard .= '<div class="inline-block nowraponall">';
611
                            $openedDashBoard .= '<span class="classfortooltip' . ($nbtodClass ? ' ' . $nbtodClass : '') . '" title="' . $labeltoshow . '">';
612
                            $openedDashBoard .= $board->nbtodo;
613
                            if ($board->total > 0 && getDolGlobalString('MAIN_WORKBOARD_SHOW_TOTAL_WO_TAX')) {
614
                                $openedDashBoard .= ' : ' . price($board->total, 0, $langs, 1, -1, -1, $conf->currency);
615
                            }
616
                            $openedDashBoard .= '</span>';
617
618
                            if ($textLate) {
619
                                if ($board->url_late) {
620
                                    $openedDashBoard .= '</div></a>';
621
                                    $openedDashBoard .= ' <div class="inline-block"><a href="' . $board->url_late . '" class="info-box-text info-box-text-a paddingleft">';
622
                                } else {
623
                                    $openedDashBoard .= ' ';
624
                                }
625
                                $openedDashBoard .= $textLate;
626
                            }
627
                            $openedDashBoard .= '</a>' . "\n";
628
                            $openedDashBoard .= '</div>';
629
                            $openedDashBoard .= '</div>' . "\n";
630
                        }
631
632
                        // TODO Add hook here to add more "info-box-line"
633
634
                        $openedDashBoard .= '		</div><!-- /.info-box-lines --></div><!-- /.info-box-content -->' . "\n";
635
                        $openedDashBoard .= '	</div><!-- /.info-box -->' . "\n";
636
                        $openedDashBoard .= '</div><!-- /.box-flex-item-with-margin -->' . "\n";
637
                        $openedDashBoard .= '</div><!-- /.box-flex-item -->' . "\n";
638
                        $openedDashBoard .= "\n";
639
                    }
640
                }
641
642
                if ($showweather && !empty($isIntopOpenedDashBoard)) {
643
                    $appendClass = (getDolGlobalInt('MAIN_DISABLE_METEO') == 2 ? ' hideonsmartphone' : '');
644
                    $weather = getWeatherStatus($totallate);
645
646
                    $text = '';
647
                    if ($totallate > 0) {
648
                        $text = $langs->transnoentitiesnoconv("WarningYouHaveAtLeastOneTaskLate") . ' (' . $langs->transnoentitiesnoconv(
649
                                "NActionsLate",
650
                                $totallate . (getDolGlobalString('MAIN_USE_METEO_WITH_PERCENTAGE') ? '%' : '')
651
                            ) . ')';
652
                    } else {
653
                        $text = $langs->transnoentitiesnoconv("NoItemLate");
654
                    }
655
                    $text .= '. ' . $langs->transnoentitiesnoconv("LateDesc");
656
657
                    $weatherDashBoard = '<div class="box-flex-item ' . $appendClass . '"><div class="box-flex-item-with-margin">' . "\n";
658
                    $weatherDashBoard .= '	<div class="info-box ' . $openedDashBoardSize . ' info-box-weather info-box-weather-level' . $weather->level . '">' . "\n";
659
                    $weatherDashBoard .= '		<span class="info-box-icon">';
660
                    $weatherDashBoard .= img_weather('', $weather->level, '', 0, 'valignmiddle width50');
661
                    $weatherDashBoard .= '       </span>' . "\n";
662
                    $weatherDashBoard .= '		<div class="info-box-content">' . "\n";
663
                    $weatherDashBoard .= '			<div class="info-box-title">' . $langs->trans('GlobalOpenedElemView') . '</div>' . "\n";
664
665
                    if ($totallatePercentage > 0 && getDolGlobalString('MAIN_USE_METEO_WITH_PERCENTAGE')) {
666
                        $weatherDashBoard .= '			<span class="info-box-number">' . $langs->transnoentitiesnoconv(
667
                                "NActionsLate",
668
                                price($totallatePercentage) . '%'
669
                            ) . '</span>' . "\n";
670
                        $weatherDashBoard .= '			<span class="progress-description">' . $langs->trans(
671
                                'NActionsLate',
672
                                $totalLateNumber
673
                            ) . '</span>' . "\n";
674
                    } else {
675
                        $weatherDashBoard .= '			<span class="info-box-number">' . $langs->transnoentitiesnoconv(
676
                                "NActionsLate",
677
                                $totalLateNumber
678
                            ) . '</span>' . "\n";
679
                        if ($totallatePercentage > 0) {
680
                            $weatherDashBoard .= '			<span class="progress-description">' . $langs->trans(
681
                                    'NActionsLate',
682
                                    price($totallatePercentage) . '%'
683
                                ) . '</span>' . "\n";
684
                        }
685
                    }
686
687
                    $weatherDashBoard .= '		</div><!-- /.info-box-content -->' . "\n";
688
                    $weatherDashBoard .= '	</div><!-- /.info-box -->' . "\n";
689
                    $weatherDashBoard .= '</div><!-- /.box-flex-item-with-margin -->' . "\n";
690
                    $weatherDashBoard .= '</div><!-- /.box-flex-item -->' . "\n";
691
                    $weatherDashBoard .= "\n";
692
693
                    $openedDashBoard = $weatherDashBoard . $openedDashBoard;
694
                }
695
696
                if (!empty($isIntopOpenedDashBoard)) {
697
                    for ($i = 1; $i <= 10; $i++) {
698
                        $openedDashBoard .= '<div class="box-flex-item filler"></div>';
699
                    }
700
                }
701
702
                $nbworkboardcount = 0;
703
                foreach ($valid_dashboardlines as $infoKey => $board) {
704
                    if (in_array($infoKey, $isIntopOpenedDashBoard)) {
705
                        // skip if info is present on top
706
                        continue;
707
                    }
708
709
                    if (empty($board->nbtodo)) {
710
                        $nbworkboardempty++;
711
                    }
712
                    $nbworkboardcount++;
713
714
715
                    $textlate = $langs->trans("NActionsLate", $board->nbtodolate);
716
                    $textlate .= ' (' . $langs->trans("Late") . ' = ' . $langs->trans("DateReference") . ' > ' . $langs->trans("DateToday") . ' ' . (ceil($board->warning_delay) >= 0 ? '+' : '') . ceil($board->warning_delay) . ' ' . $langs->trans("days") . ')';
717
718
719
                    $boxwork .= '<div class="boxstatsindicator thumbstat150 nobold nounderline"><div class="boxstats130 boxstatsborder">';
720
                    $boxwork .= '<div class="boxstatscontent">';
721
                    $boxwork .= '<span class="boxstatstext" title="' . dol_escape_htmltag($board->label) . '">' . $board->img . ' <span>' . $board->label . '</span></span><br>';
722
                    $boxwork .= '<a class="valignmiddle dashboardlineindicator" href="' . $board->url . '"><span class="dashboardlineindicator' . (($board->nbtodo == 0) ? ' dashboardlineok' : '') . '">' . $board->nbtodo . '</span></a>';
723
                    if ($board->total > 0 && getDolGlobalString('MAIN_WORKBOARD_SHOW_TOTAL_WO_TAX')) {
724
                        $boxwork .= '&nbsp;/&nbsp;<a class="valignmiddle dashboardlineindicator" href="' . $board->url . '"><span class="dashboardlineindicator' . (($board->nbtodo == 0) ? ' dashboardlineok' : '') . '">' . price($board->total) . '</span></a>';
725
                    }
726
                    $boxwork .= '</div>';
727
                    if ($board->nbtodolate > 0) {
728
                        $boxwork .= '<div class="dashboardlinelatecoin nowrap">';
729
                        $boxwork .= '<a title="' . dol_escape_htmltag($textlate) . '" class="valignmiddle dashboardlineindicatorlate' . ($board->nbtodolate > 0 ? ' dashboardlineko' : ' dashboardlineok') . '" href="' . ((!$board->url_late) ? $board->url : $board->url_late) . '">';
730
                        //$boxwork .= img_picto($textlate, "warning_white", 'class="valigntextbottom"');
731
                        $boxwork .= img_picto(
732
                            $textlate,
733
                            "warning_white",
734
                            'class="inline-block hideonsmartphone valigntextbottom"'
735
                        );
736
                        $boxwork .= '<span class="dashboardlineindicatorlate' . ($board->nbtodolate > 0 ? ' dashboardlineko' : ' dashboardlineok') . '">';
737
                        $boxwork .= $board->nbtodolate;
738
                        $boxwork .= '</span>';
739
                        $boxwork .= '</a>';
740
                        $boxwork .= '</div>';
741
                    }
742
                    $boxwork .= '</div></div>';
743
                    $boxwork .= "\n";
744
                }
745
746
                $boxwork .= '<div class="boxstatsindicator thumbstat150 nobold nounderline"><div class="boxstats150empty"></div></div>';
747
                $boxwork .= '<div class="boxstatsindicator thumbstat150 nobold nounderline"><div class="boxstats150empty"></div></div>';
748
                $boxwork .= '<div class="boxstatsindicator thumbstat150 nobold nounderline"><div class="boxstats150empty"></div></div>';
749
                $boxwork .= '<div class="boxstatsindicator thumbstat150 nobold nounderline"><div class="boxstats150empty"></div></div>';
750
751
                $boxwork .= '</div>';
752
                $boxwork .= '</td></tr>';
753
            } else {
754
                $boxwork .= '<tr class="nohover">';
755
                $boxwork .= '<td class="nohover valignmiddle opacitymedium">';
756
                $boxwork .= $langs->trans("NoOpenedElementToProcess");
757
                $boxwork .= '</td>';
758
                $boxwork .= '</tr>';
759
            }
760
761
            $boxwork .= '</td></tr>';
762
763
            $boxwork .= '</table>'; // End table array of working board
764
            $boxwork .= '</div>';
765
766
            if (!empty($isIntopOpenedDashBoard)) {
767
                print '<div class="fichecenter">';
768
                print '<div class="opened-dash-board-wrap"><div class="box-flex-container">' . $openedDashBoard . '</div></div>';
769
                print '</div>';
770
            }
771
        }
772
773
774
        print '<div class="clearboth"></div>';
775
776
        print '<div class="fichecenter fichecenterbis">';
777
778
779
        /*
780
         * Show widgets (boxes)
781
         */
782
783
        $boxlist = '<div class="twocolumns">';
784
785
        $boxlist .= '<div class="firstcolumn fichehalfleft boxhalfleft" id="boxhalfleft">';
786
        if (!empty($nbworkboardcount)) {
787
            $boxlist .= $boxwork;
788
        }
789
790
        $boxlist .= $resultboxes['boxlista'];
791
792
        $boxlist .= '</div>';
793
794
        $boxlist .= '<div class="secondcolumn fichehalfright boxhalfright" id="boxhalfright">';
795
796
        $boxlist .= $resultboxes['boxlistb'];
797
798
        $boxlist .= '</div>';
799
        $boxlist .= "\n";
800
801
        $boxlist .= '</div>';
802
803
804
        print $boxlist;
805
806
        print '</div>';
807
808
//print 'mem='.memory_get_usage().' - '.memory_get_peak_usage();
809
810
// End of page
811
        llxFooter();
812
        $db->close();
813
814
815
        /**
816
         *  Show weather logo. Logo to show depends on $totallate and values for
817
         *  conf 'MAIN_METEO_LEVELx'
818
         *
819
         * @param int $totallate Nb of element late
820
         * @param string $text Text to show on logo
821
         * @param string $options More parameters on img tag
822
         * @param string $morecss More CSS
823
         * @return     string                  Return img tag of weather
824
         */
825
        function showWeather($totallate, $text, $options, $morecss = '')
826
        {
827
            global $conf;
828
829
            $weather = getWeatherStatus($totallate);
830
            return img_weather($text, $weather->picto, $options, 0, $morecss);
831
        }
832
833
834
        /**
835
         *  get weather status for conf 'MAIN_METEO_LEVELx'
836
         *
837
         * @param int $totallate Nb of element late
838
         * @return     stdClass                Return img tag of weather
839
         */
840
        function getWeatherStatus($totallate)
841
        {
842
            $weather = new stdClass();
843
            $weather->picto = '';
844
845
            $offset = 0;
846
            $factor = 10; // By default
847
848
            $used_conf = (getDolGlobalString('MAIN_USE_METEO_WITH_PERCENTAGE') ? 'MAIN_METEO_PERCENTAGE_LEVEL' : 'MAIN_METEO_LEVEL');
849
850
            $weather->level = 0;
851
            $level0 = $offset;
852
            $level0 = getDolGlobalString($used_conf . '0', $level0);
853
            $level1 = $offset + $factor;
854
            $level1 = getDolGlobalString($used_conf . '1', $level1);
855
            $level2 = $offset + 2 * $factor;
856
            $level2 = getDolGlobalString($used_conf . '2', $level2);
857
            $level3 = $offset + 3 * $factor;
858
            $level3 = getDolGlobalString($used_conf . '3', $level3);
859
860
            if ($totallate <= $level0) {
861
                $weather->picto = 'weather-clear.png';
862
                $weather->level = 0;
863
            } elseif ($totallate <= $level1) {
864
                $weather->picto = 'weather-few-clouds.png';
865
                $weather->level = 1;
866
            } elseif ($totallate <= $level2) {
867
                $weather->picto = 'weather-clouds.png';
868
                $weather->level = 2;
869
            } elseif ($totallate <= $level3) {
870
                $weather->picto = 'weather-many-clouds.png';
871
                $weather->level = 3;
872
            } else {
873
                $weather->picto = 'weather-storm.png';
874
                $weather->level = 4;
875
            }
876
877
            return $weather;
878
        }
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return boolean. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
879
    }
880
}
881
882
883