Passed
Push — main ( d8f8f2...7eb3b3 )
by Rafael
47:22
created

BlockedLogAdminListController::blockedlog_list()   F

Complexity

Conditions 46
Paths > 20000

Size

Total Lines 273
Code Lines 194

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 46
eloc 194
nc 2670592
nop 1
dl 0
loc 273
rs 0
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* Copyright (C) 2017       ATM Consulting          <[email protected]>
4
 * Copyright (C) 2017-2018  Laurent Destailleur     <[email protected]>
5
 * Copyright (C) 2018       Frédéric France         <[email protected]>
6
 * Copyright (C) 2024       Rafael San José         <[email protected]>
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
 */
21
22
namespace DoliModules\BlockedLog\Controller;
23
24
global $conf;
25
global $db;
26
global $user;
27
global $hookmanager;
28
global $user;
29
global $menumanager;
30
global $langs;
31
global $mysoc;
32
33
/**
34
 *    \file       htdocs/blockedlog/admin/blockedlog_list.php
35
 *    \ingroup    blockedlog
36
 *    \brief      Page setup for blockedlog module
37
 */
38
39
use DoliCore\Base\DolibarrController;
40
use DoliModules\BlockedLog\Model\BlockedLog;
41
use DoliModules\BlockedLog\Model\BlockedLogAuthority;
42
43
// Load Dolibarr environment
44
require BASE_PATH . '/main.inc.php';
45
require_once BASE_PATH . '/../Dolibarr/Modules/BlockedLog/Lib/BlockedLog.php';
46
require_once BASE_PATH . '/../Dolibarr/Lib/Admin.php';
47
require_once BASE_PATH . '/../Dolibarr/Lib/Date.php';
48
49
class BlockedLogAdminListController extends DolibarrController
50
{
51
    public function blockedlog_list(bool $executeActions = true): bool
52
    {
53
        global $conf;
54
        global $db;
55
        global $user;
56
        global $hookmanager;
57
        global $user;
58
        global $menumanager;
59
        global $langs;
60
61
// Load translation files required by the page
62
        $langs->loadLangs(['admin', 'bills', 'blockedlog', 'other']);
63
64
// Access Control
65
        if ((!$user->admin && !$user->hasRight('blockedlog', 'read')) || empty($conf->blockedlog->enabled)) {
66
            accessforbidden();
67
        }
68
69
// Get Parameters
70
        $action = GETPOST('action', 'aZ09');
71
        $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'blockedloglist'; // To manage different context of search
72
        $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
73
        $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
74
75
        $search_showonlyerrors = GETPOSTINT('search_showonlyerrors');
76
        if ($search_showonlyerrors < 0) {
77
            $search_showonlyerrors = 0;
78
        }
79
80
        $search_startyear = GETPOSTINT('search_startyear');
81
        $search_startmonth = GETPOSTINT('search_startmonth');
82
        $search_startday = GETPOSTINT('search_startday');
83
        $search_endyear = GETPOSTINT('search_endyear');
84
        $search_endmonth = GETPOSTINT('search_endmonth');
85
        $search_endday = GETPOSTINT('search_endday');
86
        $search_id = GETPOST('search_id', 'alpha');
87
        $search_fk_user = GETPOST('search_fk_user', 'intcomma');
88
        $search_start = -1;
89
        if ($search_startyear != '') {
90
            $search_start = dol_mktime(0, 0, 0, $search_startmonth, $search_startday, $search_startyear);
91
        }
92
        $search_end = -1;
93
        if (GETPOST('search_endyear') != '') {
94
            $search_end = dol_mktime(23, 59, 59, GETPOST('search_endmonth'), GETPOST('search_endday'), GETPOST('search_endyear'));
95
        }
96
        $search_code = GETPOST('search_code', 'alpha');
97
        $search_ref = GETPOST('search_ref', 'alpha');
98
        $search_amount = GETPOST('search_amount', 'alpha');
99
100
        if (($search_start == -1 || empty($search_start)) && !GETPOSTISSET('search_startmonth') && !GETPOSTISSET('begin')) {
101
            $search_start = dol_time_plus_duree(dol_now(), '-1', 'w');
102
            $tmparray = dol_getdate($search_start);
103
            $search_startday = $tmparray['mday'];
104
            $search_startmonth = $tmparray['mon'];
105
            $search_startyear = $tmparray['year'];
106
        }
107
108
// Load variable for pagination
109
        $limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
110
        $sortfield = GETPOST('sortfield', 'aZ09comma');
111
        $sortorder = GETPOST('sortorder', 'aZ09comma');
112
        $page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
113
        if (empty($page) || $page == -1) {
114
            $page = 0;
115
        }     // If $page is not defined, or '' or -1
116
        $offset = $limit * $page;
117
        $pageprev = $page - 1;
118
        $pagenext = $page + 1;
119
120
        if (empty($sortfield)) {
121
            $sortfield = 'rowid';
122
        }
123
        if (empty($sortorder)) {
124
            $sortorder = 'DESC';
125
        }
126
127
        $block_static = new BlockedLog($db);
128
        $block_static->loadTrackedEvents();
129
130
        $result = restrictedArea($user, 'blockedlog', 0, '');
131
132
// Execution Time
133
        $max_execution_time_for_importexport = (!getDolGlobalString('EXPORT_MAX_EXECUTION_TIME') ? 300 : $conf->global->EXPORT_MAX_EXECUTION_TIME); // 5mn if not defined
134
        $max_time = @ini_get("max_execution_time");
135
        if ($max_time && $max_time < $max_execution_time_for_importexport) {
136
            dol_syslog("max_execution_time=" . $max_time . " is lower than max_execution_time_for_importexport=" . $max_execution_time_for_importexport . ". We try to increase it dynamically.");
137
            @ini_set("max_execution_time", $max_execution_time_for_importexport); // This work only if safe mode is off. also web servers has timeout of 300
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ini_set(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

137
            /** @scrutinizer ignore-unhandled */ @ini_set("max_execution_time", $max_execution_time_for_importexport); // This work only if safe mode is off. also web servers has timeout of 300

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
138
        }
139
140
141
        /*
142
         * Actions
143
         */
144
145
// Purge search criteria
146
        if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
147
            $search_id = '';
148
            $search_fk_user = '';
149
            $search_start = -1;
150
            $search_end = -1;
151
            $search_code = '';
152
            $search_ref = '';
153
            $search_amount = '';
154
            $search_showonlyerrors = 0;
155
            $search_startyear = '';
156
            $search_startmonth = '';
157
            $search_startday = '';
158
            $search_endyear = '';
159
            $search_endmonth = '';
160
            $search_endday = '';
161
            $toselect = [];
162
            $search_array_options = [];
163
        }
164
165
        if ($action === 'downloadblockchain') {
166
            $auth = new BlockedLogAuthority($db);
167
168
            $bc = $auth->getLocalBlockChain();
169
170
            header('Content-Type: application/octet-stream');
171
            header("Content-Transfer-Encoding: Binary");
172
            header("Content-disposition: attachment; filename=\"" . $auth->signature . ".certif\"");
173
174
            echo $bc;
175
176
            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
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...
177
        } elseif (GETPOST('downloadcsv', 'alpha')) {
178
            $error = 0;
179
180
            $previoushash = '';
181
            $firstid = '';
182
183
            if (!$error) {
184
                // Get ID of first line
185
                $sql = "SELECT rowid,date_creation,tms,user_fullname,action,amounts,element,fk_object,date_object,ref_object,signature,fk_user,object_data";
186
                $sql .= " FROM " . MAIN_DB_PREFIX . "blockedlog";
187
                $sql .= " WHERE entity = " . $conf->entity;
188
                if (GETPOSTINT('monthtoexport') > 0 || GETPOSTINT('yeartoexport') > 0) {
189
                    $dates = dol_get_first_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 1);
190
                    $datee = dol_get_last_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 12);
191
                    $sql .= " AND date_creation BETWEEN '" . $db->idate($dates) . "' AND '" . $db->idate($datee) . "'";
192
                }
193
                $sql .= " ORDER BY rowid ASC"; // Required so we get the first one
194
                $sql .= $db->plimit(1);
195
196
                $res = $db->query($sql);
197
                if ($res) {
198
                    // Make the first fetch to get first line
199
                    $obj = $db->fetch_object($res);
200
                    if ($obj) {
201
                        $previoushash = $block_static->getPreviousHash(0, $obj->rowid);
202
                        $firstid = $obj->rowid;
203
                    } else {    // If not data found for filter, we do not need previoushash neither firstid
204
                        $previoushash = 'nodata';
205
                        $firstid = '';
206
                    }
207
                } else {
208
                    $error++;
209
                    setEventMessages($db->lasterror, null, 'errors');
210
                }
211
            }
212
213
            if (!$error) {
214
                // Now restart request with all data = no limit(1) in sql request
215
                $sql = "SELECT rowid, date_creation, tms, user_fullname, action, amounts, element, fk_object, date_object, ref_object, signature, fk_user, object_data, object_version";
216
                $sql .= " FROM " . MAIN_DB_PREFIX . "blockedlog";
217
                $sql .= " WHERE entity = " . ((int) $conf->entity);
218
                if (GETPOSTINT('monthtoexport') > 0 || GETPOSTINT('yeartoexport') > 0) {
219
                    $dates = dol_get_first_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 1);
220
                    $datee = dol_get_last_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 12);
221
                    $sql .= " AND date_creation BETWEEN '" . $db->idate($dates) . "' AND '" . $db->idate($datee) . "'";
222
                }
223
                $sql .= " ORDER BY rowid ASC"; // Required so later we can use the parameter $previoushash of checkSignature()
224
225
                $res = $db->query($sql);
226
                if ($res) {
227
                    header('Content-Type: application/octet-stream');
228
                    header("Content-Transfer-Encoding: Binary");
229
                    header("Content-disposition: attachment; filename=\"unalterable-log-archive-" . $dolibarr_main_db_name . "-" . (GETPOSTINT('yeartoexport') > 0 ? GETPOSTINT('yeartoexport') . (GETPOSTINT('monthtoexport') > 0 ? sprintf("%02d", GETPOSTINT('monthtoexport')) : '') . '-' : '') . $previoushash . ".csv\"");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $dolibarr_main_db_name seems to be never defined.
Loading history...
230
231
                    print $langs->transnoentities('Id')
232
                        . ';' . $langs->transnoentities('Date')
233
                        . ';' . $langs->transnoentities('User')
234
                        . ';' . $langs->transnoentities('Action')
235
                        . ';' . $langs->transnoentities('Element')
236
                        . ';' . $langs->transnoentities('Amounts')
237
                        . ';' . $langs->transnoentities('ObjectId')
238
                        . ';' . $langs->transnoentities('Date')
239
                        . ';' . $langs->transnoentities('Ref')
240
                        . ';' . $langs->transnoentities('Fingerprint')
241
                        . ';' . $langs->transnoentities('Status')
242
                        . ';' . $langs->transnoentities('Note')
243
                        . ';' . $langs->transnoentities('Version')
244
                        . ';' . $langs->transnoentities('FullData')
245
                        . "\n";
246
247
                    $loweridinerror = 0;
248
                    $i = 0;
249
250
                    while ($obj = $db->fetch_object($res)) {
251
                        // We set here all data used into signature calculation (see checkSignature method) and more
252
                        // IMPORTANT: We must have here, the same rule for transformation of data than into the fetch method (db->jdate for date, ...)
253
                        $block_static->id = $obj->rowid;
254
                        $block_static->date_creation = $db->jdate($obj->date_creation);
255
                        $block_static->date_modification = $db->jdate($obj->tms);
256
                        $block_static->action = $obj->action;
257
                        $block_static->fk_object = $obj->fk_object;
258
                        $block_static->element = $obj->element;
259
                        $block_static->amounts = (float) $obj->amounts;
260
                        $block_static->ref_object = $obj->ref_object;
261
                        $block_static->date_object = $db->jdate($obj->date_object);
262
                        $block_static->user_fullname = $obj->user_fullname;
263
                        $block_static->fk_user = $obj->fk_user;
264
                        $block_static->signature = $obj->signature;
265
                        $block_static->object_data = $block_static->dolDecodeBlockedData($obj->object_data);
266
                        $block_static->object_version = $obj->object_version;
267
268
                        $checksignature = $block_static->checkSignature($previoushash); // If $previoushash is not defined, checkSignature will search it
269
270
                        if ($checksignature) {
271
                            $statusofrecord = 'Valid';
272
                            if ($loweridinerror > 0) {
273
                                $statusofrecordnote = 'ValidButFoundAPreviousKO';
274
                            } else {
275
                                $statusofrecordnote = '';
276
                            }
277
                        } else {
278
                            $statusofrecord = 'KO';
279
                            $statusofrecordnote = 'LineCorruptedOrNotMatchingPreviousOne';
280
                            $loweridinerror = $obj->rowid;
281
                        }
282
283
                        if ($i == 0) {
284
                            $statusofrecordnote = $langs->trans("PreviousFingerprint") . ': ' . $previoushash . ($statusofrecordnote ? ' - ' . $statusofrecordnote : '');
285
                        }
286
                        print $obj->rowid;
287
                        print ';' . $obj->date_creation;
288
                        print ';"' . str_replace('"', '""', $obj->user_fullname) . '"';
289
                        print ';' . $obj->action;
290
                        print ';' . $obj->element;
291
                        print ';' . $obj->amounts;
292
                        print ';' . $obj->fk_object;
293
                        print ';' . $obj->date_object;
294
                        print ';"' . str_replace('"', '""', $obj->ref_object) . '"';
295
                        print ';' . $obj->signature;
296
                        print ';' . $statusofrecord;
297
                        print ';' . $statusofrecordnote;
298
                        print ';' . $obj->object_version;
299
                        print ';"' . str_replace('"', '""', $obj->object_data) . '"';
300
                        print "\n";
301
302
                        // Set new previous hash for next fetch
303
                        $previoushash = $obj->signature;
304
305
                        $i++;
306
                    }
307
308
                    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
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...
309
                } else {
310
                    setEventMessages($db->lasterror, null, 'errors');
311
                }
312
            }
313
        }
314
315
316
        /*
317
         *	View
318
         */
319
        require_once realpath(BASE_PATH . '/../Dolibarr/Modules/BlockedLog/Views/admin_blocked_log_list.php');
320
321
        $db->close();
322
323
        return true;
324
    }
325
}
326
327