display_dashboard_plugin_checkboxes()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 1
dl 0
loc 16
rs 9.9332
c 0
b 0
f 0
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * DashboardManager can be used to manage dashboard
6
 * author Christian Fasanando <[email protected]>.
7
 *
8
 * @package chamilo.dashboard
9
 */
10
class DashboardManager
11
{
12
    /**
13
     * Constructor.
14
     */
15
    public function __construct()
16
    {
17
    }
18
19
    /**
20
     * This function allows easy activating and inactivating of dashboard plugins.
21
     */
22
    public static function handle_dashboard_plugins()
23
    {
24
        $token = Security::get_existing_token();
25
        $tokenCondition = '&sec_token='.$token;
26
27
        /* We scan the plugin directory. Each folder is a potential plugin. */
28
        $dashboard_pluginpath = api_get_path(SYS_PLUGIN_PATH).'dashboard/';
29
        $possiblePlugins = self::getPossibleDashboardPluginsPath();
30
31
        $table_cols = ['name', 'version', 'description'];
32
        echo Display::page_subheader(get_lang('DashboardPlugins'));
33
        echo '<form name="plugins" method="post" action="'.api_get_self().'?category='.Security::remove_XSS($_GET['category']).$tokenCondition.'">';
34
        echo '<table class="table table-hover table-striped data_table">';
35
        echo '<tr>';
36
        echo '<th width="50px">'.get_lang('Enabled').'</th>';
37
        echo '<th width="250px">'.get_lang('Name').'</th>';
38
        echo '<th width="100px">'.get_lang('Version').'</th>';
39
        echo '<th>'.get_lang('Description').'</th>';
40
        echo '</tr>';
41
42
        $disabled_blocks_data = self::get_block_data_without_plugin();
43
44
        // We display all the possible enabled or disabled plugins
45
        foreach ($possiblePlugins as $testplugin) {
46
            $plugin_info_file = $dashboard_pluginpath.$testplugin."/$testplugin.info";
47
            if (file_exists($plugin_info_file) && is_readable($plugin_info_file)) {
48
                $plugin_info = api_parse_info_file($plugin_info_file);
49
50
                // change index to lower case
51
                $plugin_info = array_change_key_case($plugin_info);
52
53
                echo '<tr>';
54
                self::display_dashboard_plugin_checkboxes($testplugin);
55
                for ($i = 0; $i < count($table_cols); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
56
                    if (isset($plugin_info[strtolower($table_cols[$i])])) {
57
                        echo '<td>';
58
                        echo $plugin_info[$table_cols[$i]];
59
                        echo '</td>';
60
                    } else {
61
                        echo '<td></td>';
62
                    }
63
                }
64
                echo '</tr>';
65
            } else {
66
                if ($testplugin != 'css') {
67
                    echo Display::tag(
68
                        'tr',
69
                        Display::tag(
70
                            'td',
71
                            get_lang('CheckFilePermissions').' '.Security::remove_XSS($plugin_info_file),
72
                            ['colspan' => '3']
73
                        )
74
                    );
75
                }
76
            }
77
        }
78
79
        // display all disabled block data
80
        if (count($disabled_blocks_data) > 0) {
81
            foreach ($disabled_blocks_data as $disabled_block) {
82
                echo '<tr style="background-color:#eee">';
83
                echo '<td><center><input type="checkbox" name="disabled_block" value="true" checked disabled /></center>';
84
                for ($j = 0; $j < count($table_cols); $j++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
85
                    if (isset($disabled_block[strtolower($table_cols[$j])])) {
86
                        if ($j == 2) {
87
                            echo '<td>';
88
                            echo '<font color="#aaa">'.$disabled_block[$table_cols[$j]].'</font><br />';
89
                            echo '<font color="red">'.get_lang('ThisPluginHasbeenDeletedFromDashboardPluginDirectory').'</font>';
90
                            echo '</td>';
91
                        } else {
92
                            echo '<td>';
93
                            echo '<font color="#aaa">'.$disabled_block[$table_cols[$j]].'</font>';
94
                            echo '</td>';
95
                        }
96
                    } else {
97
                        echo '<td>&nbsp;</td>';
98
                    }
99
                }
100
                echo '</tr>';
101
            }
102
        }
103
104
        echo '</table>';
105
        echo '<br />';
106
        echo '<button class="btn btn-default" type="submit" name="submit_dashboard_plugins" value="'.get_lang('EnableDashboardPlugins').'">'.
107
            get_lang('EnableDashboardPlugins').'</button></form>';
108
    }
109
110
    /**
111
     * display checkboxes for dashboard plugin list.
112
     *
113
     * @param string $plugin_path
114
     */
115
    public static function display_dashboard_plugin_checkboxes($plugin_path)
116
    {
117
        $tbl_block = Database::get_main_table(TABLE_MAIN_BLOCK);
118
119
        $sql = "SELECT * FROM $tbl_block
120
                WHERE path = '".Database::escape_string($plugin_path)."' AND active = 1";
121
        $rs = Database::query($sql);
122
123
        $checked = '';
124
        if (Database::num_rows($rs) > 0) {
125
            $checked = "checked";
126
        }
127
128
        echo "<td align=\"center\">";
129
        echo '<input type="checkbox" name="'.$plugin_path.'" value="true" '.$checked.'/>';
130
        echo "</td>";
131
    }
132
133
    /**
134
     * This function allows easy activating and inactivating
135
     * of plugins and save them inside db.
136
     *
137
     * @param array $plugin_paths dashboard plugin paths
138
     *                            return int affected rows
139
     */
140
    public static function store_dashboard_plugins($plugin_paths)
141
    {
142
        $tbl_block = Database::get_main_table(TABLE_MAIN_BLOCK);
143
        $affected_rows = 0;
144
145
        // get all plugins path inside plugin directory
146
        $dashboard_pluginpath = api_get_path(SYS_PLUGIN_PATH).'dashboard/';
147
        $possiblePlugins = self::getPossibleDashboardPluginsPath();
148
149
        if (count($possiblePlugins) > 0) {
150
            $selected_plugins = array_intersect(array_keys($plugin_paths), $possiblePlugins);
151
            $not_selected_plugins = array_diff($possiblePlugins, array_keys($plugin_paths));
152
153
            // get blocks id from not selected path
154
            $not_selected_blocks_id = [];
155
            foreach ($not_selected_plugins as $plugin) {
156
                $block_data = self::get_enabled_dashboard_blocks($plugin);
157
                if (!empty($block_data[$plugin])) {
158
                    $not_selected_blocks_id[] = $block_data[$plugin]['id'];
159
                }
160
            }
161
162
            /* clean not selected plugins for extra user data and block data */
163
            // clean from extra user data
164
            $field_variable = 'dashboard';
165
            $extra_user_data = UserManager::get_extra_user_data_by_field_variable($field_variable);
166
            if (!empty($extra_user_data) && count($extra_user_data) > 0) {
167
                foreach ($extra_user_data as $key => $user_data) {
168
                    $user_id = $key;
169
                    $user_block_data = self::get_user_block_data($user_id);
170
                    $user_block_id = array_keys($user_block_data);
171
172
                    // clean disabled block data
173
                    foreach ($user_block_id as $block_id) {
174
                        if (in_array($block_id, $not_selected_blocks_id)) {
175
                            unset($user_block_data[$block_id]);
176
                        }
177
                    }
178
179
                    // get columns and blocks id for updating extra user data
180
                    $columns = [];
181
                    $user_blocks_id = [];
182
                    foreach ($user_block_data as $data) {
183
                        $user_blocks_id[$data['block_id']] = true;
184
                        $columns[$data['block_id']] = $data['column'];
185
                    }
186
187
                    // update extra user blocks data
188
                    self::store_user_blocks($user_id, $user_blocks_id, $columns);
189
                }
190
            }
191
            // clean from block data
192
            if (!empty($not_selected_blocks_id)) {
193
                $sql_check = "SELECT id FROM $tbl_block
194
                              WHERE id IN(".implode(',', $not_selected_blocks_id).")";
195
                $rs_check = Database::query($sql_check);
196
                if (Database::num_rows($rs_check) > 0) {
197
                    $del = "DELETE FROM $tbl_block WHERE id IN(".implode(',', $not_selected_blocks_id).")";
198
                    Database::query($del);
199
                }
200
            }
201
202
            // store selected plugins
203
            if (!empty($selected_plugins) && count($selected_plugins) > 0) {
204
                foreach ($selected_plugins as $testplugin) {
205
                    $selected_path = Database::escape_string($testplugin);
206
207
                    // check if the path already stored inside block table for updating or adding it
208
                    $sql = "SELECT path FROM $tbl_block WHERE path = '$selected_path'";
209
                    $rs = Database::query($sql);
210
                    if (Database::num_rows($rs) > 0) {
211
                        // update
212
                        $upd = "UPDATE $tbl_block SET active = 1 WHERE path = '$selected_path'";
213
                        $result = Database::query($upd);
214
                        $affected_rows = Database::affected_rows($result);
215
                    } else {
216
                        // insert
217
                        $plugin_info_file = $dashboard_pluginpath.$testplugin."/$testplugin.info";
218
                        $plugin_info = [];
219
                        if (file_exists($plugin_info_file)) {
220
                            $plugin_info = api_parse_info_file($plugin_info_file);
221
                        }
222
223
                        // change keys to lower case
224
                        $plugin_info = array_change_key_case($plugin_info);
225
226
                        // setting variables
227
                        $plugin_name = $testplugin;
228
                        $plugin_description = '';
229
                        $plugin_controller = '';
230
                        $plugin_path = $testplugin;
231
232
                        if (isset($plugin_info['name'])) {
233
                            $plugin_name = Database::escape_string($plugin_info['name']);
234
                        }
235
                        if (isset($plugin_info['description'])) {
236
                            $plugin_description = Database::escape_string($plugin_info['description']);
237
                        }
238
                        if (isset($plugin_info['controller'])) {
239
                            $plugin_controller = Database::escape_string($plugin_info['controller']);
240
                        }
241
242
                        $ins = "INSERT INTO $tbl_block(name, description, path, controller)
243
                            VALUES ('$plugin_name', '$plugin_description', '$plugin_path', '$plugin_controller')";
244
                        $result = Database::query($ins);
245
                        $affected_rows = Database::affected_rows($result);
246
                    }
247
                }
248
            }
249
        }
250
251
        return $affected_rows;
252
    }
253
254
    /**
255
     * Get all plugins path inside dashboard directory.
256
     *
257
     * @return array name plugins directories
258
     */
259
    public static function getPossibleDashboardPluginsPath()
260
    {
261
        // get all plugins path inside plugin directory
262
        /* We scan the plugin directory. Each folder is a potential plugin. */
263
        $possiblePlugins = [];
264
        $dashboard_pluginpath = api_get_path(SYS_PLUGIN_PATH).'dashboard/';
265
        $handle = @opendir($dashboard_pluginpath);
266
        while (false !== ($file = readdir($handle))) {
267
            if ($file != '.' && $file != '..' && is_dir($dashboard_pluginpath.$file)) {
268
                $possiblePlugins[] = $file;
269
            }
270
        }
271
        @closedir($handle);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for closedir(). 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

271
        /** @scrutinizer ignore-unhandled */ @closedir($handle);

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...
Bug introduced by
Are you sure the usage of closedir($handle) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
272
273
        return $possiblePlugins;
274
    }
275
276
    /**
277
     * Get all blocks data without plugin directory.
278
     *
279
     * @return array Block data
280
     */
281
    public static function get_block_data_without_plugin()
282
    {
283
        $tbl_block = Database::get_main_table(TABLE_MAIN_BLOCK);
284
        $possiblePlugins = self::getPossibleDashboardPluginsPath();
285
286
        // We check if plugin exists inside directory for updating active field
287
        $sql = "SELECT * FROM $tbl_block";
288
        $rs = Database::query($sql);
289
        if (Database::num_rows($rs) > 0) {
290
            while ($row = Database::fetch_array($rs)) {
291
                if (!in_array($row['path'], $possiblePlugins)) {
292
                    $active = 0;
293
                } else {
294
                    $active = 1;
295
                }
296
                // update active
297
                $upd = "UPDATE $tbl_block SET active = '$active'
298
                        WHERE path = '".$row['path']."'";
299
                Database::query($upd);
300
            }
301
        }
302
303
        // get disabled block data
304
        $block_data = [];
305
        $sql = "SELECT * FROM $tbl_block WHERE active = 0";
306
        $rs_block = Database::query($sql);
307
        if (Database::num_rows($rs_block) > 0) {
308
            while ($row_block = Database::fetch_array($rs_block)) {
309
                $block_data[] = $row_block;
310
            }
311
        }
312
313
        return $block_data;
314
    }
315
316
    /**
317
     * get data about enabled dashboard block (stored insise block table).
318
     *
319
     * @param string $path plugin path
320
     *
321
     * @return array data
322
     */
323
    public static function get_enabled_dashboard_blocks($path = '')
324
    {
325
        $tbl_block = Database::get_main_table(TABLE_MAIN_BLOCK);
326
        $condition_path = '';
327
        if (!empty($path)) {
328
            $path = Database::escape_string($path);
329
            $condition_path = ' AND path = "'.$path.'" ';
330
        }
331
332
        $sql = "SELECT * FROM $tbl_block WHERE active = 1 $condition_path ";
333
        $rs = Database::query($sql);
334
        $block_data = [];
335
        if (Database::num_rows($rs) > 0) {
336
            while ($row = Database::fetch_array($rs)) {
337
                $block_data[$row['path']] = $row;
338
            }
339
        }
340
341
        return $block_data;
342
    }
343
344
    /**
345
     * display user dashboard list.
346
     *
347
     * @param int  User id
348
     */
349
    public static function display_user_dashboard_list($user_id)
350
    {
351
        $enabled_dashboard_plugins = self::get_enabled_dashboard_blocks();
352
        $user_block_data = self::get_user_block_data($user_id);
353
        $html = '';
354
        if (count($enabled_dashboard_plugins) > 0) {
355
            $html .= '<div style="margin-top:20px">';
356
            $html .= '<div><strong>'.get_lang('SelectBlockForDisplayingInsideBlocksDashboardView').'</strong></div><br />';
357
            $html .= '<form name="dashboard_list" method="post" action="index.php?action=store_user_block">';
358
            $html .= '<table class="table table-hover table-striped data_table">';
359
            $html .= '<tr>';
360
            $html .= '<th width="5%">';
361
            $html .= get_lang('Enabled');
362
            $html .= '</th>';
363
            $html .= '<th width="30%">';
364
            $html .= get_lang('Name');
365
            $html .= '</th>';
366
            $html .= '<th width="40%">';
367
            $html .= get_lang('Description');
368
            $html .= '</th>';
369
            $html .= '<th>';
370
            $html .= get_lang('ColumnPosition');
371
            $html .= '</th>';
372
            $html .= '</tr>';
373
374
            // We display all enabled plugins and the checkboxes
375
            foreach ($enabled_dashboard_plugins as $block) {
376
                $path = $block['path'];
377
                $controller_class = $block['controller'];
378
                $filename_controller = $path.'.class.php';
379
                $dashboard_plugin_path = api_get_path(SYS_PLUGIN_PATH).'dashboard/'.$path.'/';
380
                require_once $dashboard_plugin_path.$filename_controller;
381
                if (class_exists($controller_class)) {
382
                    $obj_block = new $controller_class($user_id);
383
384
                    // check if user is allowed to see the block
385
                    if (method_exists($obj_block, 'is_block_visible_for_user')) {
386
                        $is_block_visible_for_user = $obj_block->is_block_visible_for_user($user_id);
387
                        if (!$is_block_visible_for_user) {
388
                            continue;
389
                        }
390
                    }
391
392
                    $html .= '<tr>';
393
                    // checkboxes
394
                    $html .= self::display_user_dashboard_list_checkboxes($user_id, $block['id']);
395
                    $html .= '<td>'.$block['name'].'</td>';
396
                    $html .= '<td>'.$block['description'].'</td>';
397
                    $html .= '<td>
398
                            <select class="selectpicker form-control" name="columns['.$block['id'].']">
399
                            <option value="1" '.(isset($user_block_data[$block['id']]) && $user_block_data[$block['id']]['column'] == 1 ? 'selected' : '').' >1</option>
400
                            <option value="2" '.(isset($user_block_data[$block['id']]) && $user_block_data[$block['id']]['column'] == 2 ? 'selected' : '').' >2</option>
401
                            </select>
402
                          </td>';
403
                    $html .= '</tr>';
404
                } else {
405
                    $html .= Display::tag('tr', Display::tag('td', get_lang('Error').' '.$controller_class, ['colspan' => '3']));
406
                }
407
            }
408
409
            $html .= '</table>';
410
            $html .= '<div class="row"><div class="col-md-12">';
411
            $html .= '<button class="btn btn-default" type="submit" name="submit_dashboard_list" value="'.get_lang('EnableDashboardBlock').'"><em class="fa fa-check-square"></em> '.
412
                get_lang('EnableDashboardBlock').'</button></form>';
413
            $html .= '</div></div>';
414
        } else {
415
            $html .= '<div style="margin-top:20px">'.get_lang('ThereAreNoEnabledDashboardPlugins').'</div>';
416
            if (api_is_platform_admin()) {
417
                $html .= '<a class="btn btn-default" href="'.api_get_path(WEB_CODE_PATH).'admin/settings.php?category=Plugins">'.
418
                    get_lang('ConfigureDashboardPlugin').'</a>';
419
            }
420
        }
421
422
        return $html;
423
    }
424
425
    /**
426
     * display checkboxes for user dashboard list.
427
     *
428
     * @param int    User id
429
     * @param int    Block id
430
     */
431
    public static function display_user_dashboard_list_checkboxes($user_id, $block_id)
432
    {
433
        $user_id = intval($user_id);
434
        $user_block_data = self::get_user_block_data($user_id);
435
        $enabled_blocks_id = array_keys($user_block_data);
436
437
        $checked = '';
438
        if (in_array($block_id, $enabled_blocks_id)) {
439
            $checked = "checked";
440
        }
441
442
        $html = "<td align=\"center\">";
443
        $html .= '<input type="checkbox" name="enabled_blocks['.$block_id.']" value="true" '.$checked.'/>';
444
        $html .= "</td>";
445
446
        return $html;
447
    }
448
449
    /**
450
     * This function store enabled blocks id with its column position (block_id1:colum;block_id2:colum; ...)
451
     * inside extra user fields.
452
     *
453
     * @param int   $user_id        User id
454
     * @param array $enabled_blocks selected blocks
455
     * @param array $columns        columns position
456
     *
457
     * @return bool
458
     */
459
    public static function store_user_blocks($user_id, $enabled_blocks, $columns)
460
    {
461
        $selected_blocks_id = [];
462
        if (is_array($enabled_blocks) && count($enabled_blocks) > 0) {
463
            $selected_blocks_id = array_keys($enabled_blocks);
464
        }
465
466
        // build data for storing inside extra user field
467
        $fname = 'dashboard';
468
        $fvalue = [];
469
        foreach ($selected_blocks_id as $block_id) {
470
            $fvalue[] = $block_id.':'.$columns[$block_id];
471
        }
472
        $upd_extra_field = UserManager::update_extra_field_value(
473
            $user_id,
474
            $fname,
475
            $fvalue
476
        );
477
478
        return $upd_extra_field;
479
    }
480
481
    /**
482
     * This function get user block data (block id with its number of column) from extra user data.
483
     *
484
     * @param int        User id
485
     *
486
     * @return array data (block_id,column)
487
     */
488
    public static function get_user_block_data($user_id)
489
    {
490
        $user_id = intval($user_id);
491
        $field_variable = 'dashboard';
492
        $extra_user_data = UserManager::get_extra_user_data_by_field($user_id, $field_variable);
493
494
        if (!isset($extra_user_data[$field_variable])) {
495
            return [];
496
        }
497
498
        $extra_user_data = explode(';', $extra_user_data[$field_variable]);
499
        $data = [];
500
        foreach ($extra_user_data as $extra) {
501
            $split_extra = explode(':', $extra);
502
            if (!empty($split_extra)) {
503
                $block_id = $split_extra[0];
504
                $column = isset($split_extra[1]) ? $split_extra[1] : null;
505
                $data[$block_id] = ['block_id' => $block_id, 'column' => $column];
506
            }
507
        }
508
509
        return $data;
510
    }
511
512
    /**
513
     * This function update extra user blocks data after closing a dashboard block.
514
     *
515
     * @param int $user_id User id
516
     * @param string    plugin path
517
     *
518
     * @return bool
519
     */
520
    public static function close_user_block($user_id, $path)
521
    {
522
        $enabled_dashboard_blocks = self::get_enabled_dashboard_blocks($path);
523
        $user_block_data = self::get_user_block_data($user_id);
524
525
        foreach ($enabled_dashboard_blocks as $enabled_block) {
526
            unset($user_block_data[$enabled_block['id']]);
527
        }
528
529
        // get columns and blocks id for updating extra user data
530
        $columns = [];
531
        $user_blocks_id = [];
532
        foreach ($user_block_data as $data) {
533
            $user_blocks_id[$data['block_id']] = true;
534
            $columns[$data['block_id']] = $data['column'];
535
        }
536
537
        // update extra user blocks data
538
        $upd_extra_field = self::store_user_blocks($user_id, $user_blocks_id, $columns);
539
540
        return $upd_extra_field;
541
    }
542
543
    /**
544
     * get links for styles from dashboard plugins.
545
     *
546
     * @return string links
547
     */
548
    public static function getStyleSheet()
549
    {
550
        return '<link rel="stylesheet" href="'.api_get_path(WEB_PLUGIN_PATH).'dashboard/css/default.css" type="text/css" />'.PHP_EOL;
551
    }
552
}
553