Passed
Push — master ( 2ca18e...4f0b12 )
by Julito
10:55
created

generateSettingsForm()   F

Complexity

Conditions 58
Paths > 20000

Size

Total Lines 369
Code Lines 256

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 58
eloc 256
nc 34026
nop 2
dl 0
loc 369
rs 0
c 0
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
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
5
use Chamilo\CoreBundle\Entity\SystemTemplate;
6
use ChamiloSession as Session;
7
use Symfony\Component\Filesystem\Filesystem;
8
9
/**
10
 * Library of the settings.php file.
11
 *
12
 * @author Julio Montoya <[email protected]>
13
 * @author Guillaume Viguier <[email protected]>
14
 *
15
 * @since Chamilo 1.8.7
16
 */
17
define('CSS_UPLOAD_PATH', api_get_path(SYS_PATH).'Resources/public/css/themes/');
18
19
/**
20
 * This function allows easy activating and inactivating of regions.
21
 *
22
 * @author Julio Montoya <[email protected]> Beeznest 2012
23
 */
24
function handleRegions()
25
{
26
    if (isset($_POST['submit_plugins'])) {
27
        storeRegions();
28
        // Add event to the system log.
29
        $user_id = api_get_user_id();
30
        $category = $_GET['category'];
31
        Event::addEvent(
0 ignored issues
show
Bug introduced by
The method addEvent() does not exist on Event. ( Ignorable by Annotation )

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

31
        Event::/** @scrutinizer ignore-call */ 
32
               addEvent(

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
32
            LOG_CONFIGURATION_SETTINGS_CHANGE,
33
            LOG_CONFIGURATION_SETTINGS_CATEGORY,
34
            $category,
35
            api_get_utc_datetime(),
36
            $user_id
37
        );
38
        echo Display::return_message(get_lang('The settings have been stored'), 'confirmation');
39
    }
40
41
    $plugin_obj = new AppPlugin();
42
    $installed_plugins = $plugin_obj->getInstalledPlugins();
43
44
    echo '<form name="plugins" method="post" action="'.api_get_self().'?category='.Security::remove_XSS($_GET['category']).'">';
0 ignored issues
show
Bug introduced by
Are you sure Security::remove_XSS($_GET['category']) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

44
    echo '<form name="plugins" method="post" action="'.api_get_self().'?category='./** @scrutinizer ignore-type */ Security::remove_XSS($_GET['category']).'">';
Loading history...
45
    echo '<table class="data_table">';
46
    echo '<tr>';
47
    echo '<th width="400px">';
48
    echo get_lang('Plugin');
49
    echo '</th><th>';
50
    echo get_lang('Regions');
51
    echo '</th>';
52
    echo '</th>';
53
    echo '</tr>';
54
55
    /* We display all the possible plugins and the checkboxes */
56
    $plugin_region_list = [];
57
    $my_plugin_list = $plugin_obj->getPluginRegions();
58
    foreach ($my_plugin_list as $plugin_item) {
59
        $plugin_region_list[$plugin_item] = $plugin_item;
60
    }
61
62
    // Removing course tool
63
    unset($plugin_region_list['course_tool_plugin']);
64
65
    foreach ($installed_plugins as $pluginName) {
66
        $plugin_info_file = api_get_path(SYS_PLUGIN_PATH).$pluginName.'/plugin.php';
67
68
        if (file_exists($plugin_info_file)) {
69
            $plugin_info = [];
70
            require $plugin_info_file;
71
            if (isset($_GET['name']) && $_GET['name'] === $pluginName) {
72
                echo '<tr class="row_selected">';
73
            } else {
74
                echo '<tr>';
75
            }
76
            echo '<td>';
77
            echo '<h4>'.$plugin_info['title'].' <small>v'.$plugin_info['version'].'</small></h4>';
78
            echo '<p>'.$plugin_info['comment'].'</p>';
79
            echo '</td><td>';
80
            $selected_plugins = $plugin_obj->get_areas_by_plugin($pluginName);
81
            $region_list = [];
82
            $isAdminPlugin = isset($plugin_info['is_admin_plugin']) && $plugin_info['is_admin_plugin'];
83
            $isCoursePlugin = isset($plugin_info['is_course_plugin']) && $plugin_info['is_course_plugin'];
84
85
            if (!$isAdminPlugin && !$isCoursePlugin) {
86
                $region_list = $plugin_region_list;
87
            } else {
88
                if ($isAdminPlugin) {
89
                    $region_list['menu_administrator'] = 'menu_administrator';
90
                }
91
                if ($isCoursePlugin) {
92
                    $region_list['course_tool_plugin'] = 'course_tool_plugin';
93
                }
94
            }
95
96
            echo Display::select(
97
                'plugin_'.$pluginName.'[]',
98
                $region_list,
99
                $selected_plugins,
100
                ['multiple' => 'multiple', 'style' => 'width:500px'],
101
                true,
102
                get_lang('none')
103
            );
104
            echo '</td></tr>';
105
        }
106
    }
107
    echo '</table>';
108
    echo '<br />';
109
    echo '<button class="btn btn-success" type="submit" name="submit_plugins">'.get_lang('Enable the selected plugins').'</button></form>';
110
}
111
112
function handleExtensions()
113
{
114
    echo Display::page_subheader(get_lang('Configure extensions'));
115
    echo '<a class="btn btn-success" href="configure_extensions.php?display=ppt2lp" role="button">'.get_lang('Chamilo RAPID').'</a>';
116
}
117
118
/**
119
 * This function allows easy activating and inactivating of plugins.
120
 *
121
 * @todo: a similar function needs to be written to activate or inactivate additional tools.
122
 *
123
 * @author Patrick Cool <[email protected]>, Ghent University
124
 * @author Julio Montoya <[email protected]> Beeznest 2012
125
 */
126
function handlePlugins()
127
{
128
    Session::erase('plugin_data');
129
    $plugin_obj = new AppPlugin();
130
    $token = Security::get_token();
131
    if (isset($_POST['submit_plugins'])) {
132
        storePlugins();
133
        // Add event to the system log.
134
        $user_id = api_get_user_id();
135
        $category = $_GET['category'];
136
        Event::addEvent(
137
            LOG_CONFIGURATION_SETTINGS_CHANGE,
138
            LOG_CONFIGURATION_SETTINGS_CATEGORY,
139
            $category,
140
            api_get_utc_datetime(),
141
            $user_id
142
        );
143
        echo Display::return_message(get_lang('The settings have been stored'), 'confirmation');
144
    }
145
146
    $all_plugins = $plugin_obj->read_plugins_from_path();
147
    $installed_plugins = $plugin_obj->getInstalledPlugins();
148
149
    // Plugins NOT installed
150
    echo Display::page_subheader(get_lang('Plugins'));
151
    echo '<form class="form-horizontal" name="plugins" method="post" action="'.api_get_self().'?category='.Security::remove_XSS($_GET['category']).'&sec_token='.$token.'">';
0 ignored issues
show
Bug introduced by
Are you sure Security::remove_XSS($_GET['category']) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

151
    echo '<form class="form-horizontal" name="plugins" method="post" action="'.api_get_self().'?category='./** @scrutinizer ignore-type */ Security::remove_XSS($_GET['category']).'&sec_token='.$token.'">';
Loading history...
152
    echo '<table class="table table-hover table-striped table-bordered">';
153
    echo '<tr>';
154
    echo '<th width="20px">';
155
    echo get_lang('Action');
156
    echo '</th><th>';
157
    echo get_lang('Description');
158
    echo '</th>';
159
    echo '</tr>';
160
161
    /*$plugin_list = array();
162
    $my_plugin_list = $plugin_obj->get_plugin_regions();
163
    foreach($my_plugin_list as $plugin_item) {
164
        $plugin_list[$plugin_item] = $plugin_item;
165
    }*/
166
    $installed = '';
167
    $notInstalled = '';
168
    foreach ($all_plugins as $pluginName) {
169
        $plugin_info_file = api_get_path(SYS_PLUGIN_PATH).$pluginName.'/plugin.php';
170
        if (file_exists($plugin_info_file)) {
171
            $plugin_info = [];
172
            require $plugin_info_file;
173
174
            $pluginRow = '';
175
176
            if (in_array($pluginName, $installed_plugins)) {
177
                $pluginRow .= '<tr class="row_selected">';
178
            } else {
179
                $pluginRow .= '<tr>';
180
            }
181
            $pluginRow .= '<td>';
182
            // Checkbox
183
            if (in_array($pluginName, $installed_plugins)) {
184
                $pluginRow .= '<input type="checkbox" name="plugin_'.$pluginName.'[]" checked="checked">';
185
            } else {
186
                $pluginRow .= '<input type="checkbox" name="plugin_'.$pluginName.'[]">';
187
            }
188
            $pluginRow .= '</td><td>';
189
            $pluginRow .= '<h4>'.$plugin_info['title'].' <small>v '.$plugin_info['version'].'</small></h4>';
190
            $pluginRow .= '<p>'.$plugin_info['comment'].'</p>';
191
            $pluginRow .= '<p>'.get_lang('Author').': '.$plugin_info['author'].'</p>';
192
193
            $pluginRow .= '<div class="btn-group btn-group-sm">';
194
            if (in_array($pluginName, $installed_plugins)) {
195
                $pluginRow .= Display::url(
196
                    '<em class="fa fa-cogs"></em> '.get_lang('Configure'),
197
                    'configure_plugin.php?name='.$pluginName,
198
                    ['class' => 'btn btn-primary']
199
                );
200
                $pluginRow .= Display::url(
201
                    '<em class="fa fa-th-large"></em> '.get_lang('Regions'),
202
                    'settings.php?category=Regions&name='.$pluginName,
203
                    ['class' => 'btn btn-primary']
204
                );
205
            }
206
207
            if (file_exists(api_get_path(SYS_PLUGIN_PATH).$pluginName.'/readme.txt')) {
208
                $pluginRow .= Display::url(
209
                    "<em class='fa fa-file-text-o'></em> readme.txt",
210
                    api_get_path(WEB_PLUGIN_PATH).$pluginName."/readme.txt",
211
                    [
212
                        'class' => 'btn btn-primary ajax',
213
                        'data-title' => $plugin_info['title'],
214
                        'data-size' => 'lg',
215
                        '_target' => '_blank',
216
                    ]
217
                );
218
            }
219
220
            $readmeFile = api_get_path(SYS_PLUGIN_PATH).$pluginName.'/README.md';
221
            if (file_exists($readmeFile)) {
222
                $pluginRow .= Display::url(
223
                    "<em class='fa fa-file-text-o'></em> README.md",
224
                    api_get_path(WEB_AJAX_PATH).'plugin.ajax.php?a=md_to_html&plugin='.$pluginName,
225
                    [
226
                        'class' => 'btn btn-primary ajax',
227
                        'data-title' => $plugin_info['title'],
228
                        'data-size' => 'lg',
229
                        '_target' => '_blank',
230
                    ]
231
                );
232
            }
233
234
            $pluginRow .= '</div>';
235
            $pluginRow .= '</td></tr>';
236
237
            if (in_array($pluginName, $installed_plugins)) {
238
                $installed .= $pluginRow;
239
            } else {
240
                $notInstalled .= $pluginRow;
241
            }
242
        }
243
    }
244
245
    echo $installed;
246
    echo $notInstalled;
247
    echo '</table>';
248
249
    echo '<div class="form-actions bottom_actions">';
250
    echo '<button class="btn btn-primary" type="submit" name="submit_plugins">';
251
    echo '<i class="fa fa-check" aria-hidden="true"></i> ';
252
    echo get_lang('Enable the selected plugins').'</button>';
253
    echo '</div>';
254
    echo '</form>';
255
}
256
257
/**
258
 * This function allows the platform admin to choose the default stylesheet.
259
 *
260
 * @author Patrick Cool <[email protected]>, Ghent University
261
 * @author Julio Montoya <[email protected]>, Chamilo
262
 */
263
function handleStylesheets()
264
{
265
    $is_style_changeable = isStyleChangeable();
266
    $allowedFileTypes = ['png'];
267
268
    $form = new FormValidator(
269
        'stylesheet_upload',
270
        'post',
271
        'settings.php?category=Stylesheets#tabs-3'
272
    );
273
    $form->addElement(
274
        'text',
275
        'name_stylesheet',
276
        get_lang('Name of the stylesheet'),
277
        ['size' => '40', 'maxlength' => '40']
278
    );
279
    $form->addRule(
280
        'name_stylesheet',
281
        get_lang('Required field'),
282
        'required'
283
    );
284
    $form->addElement(
285
        'file',
286
        'new_stylesheet',
287
        get_lang('New stylesheet file')
288
    );
289
    $allowed_file_types = getAllowedFileTypes();
290
291
    $form->addRule(
292
        'new_stylesheet',
293
        get_lang('Invalid extension').' ('.implode(',', $allowed_file_types).')',
294
        'filetype',
295
        $allowed_file_types
296
    );
297
    $form->addRule(
298
        'new_stylesheet',
299
        get_lang('Required field'),
300
        'required'
301
    );
302
    $form->addButtonUpload(get_lang('Upload'), 'stylesheet_upload');
303
304
    $show_upload_form = false;
305
    $urlId = api_get_current_access_url_id();
306
307
    if (!is_writable(CSS_UPLOAD_PATH)) {
308
        echo Display::return_message(
309
            CSS_UPLOAD_PATH.get_lang('is not writeable'),
310
            'error',
311
            false
312
        );
313
    } else {
314
        // Uploading a new stylesheet.
315
        if (1 == $urlId) {
316
            $show_upload_form = true;
317
        } else {
318
            if ($is_style_changeable) {
319
                $show_upload_form = true;
320
            }
321
        }
322
    }
323
324
    // Stylesheet upload.
325
    if (isset($_POST['stylesheet_upload'])) {
326
        if ($form->validate()) {
327
            $values = $form->exportValues();
328
            $picture_element = $form->getElement('new_stylesheet');
329
            $picture = $picture_element->getValue();
330
            $result = uploadStylesheet($values, $picture);
331
332
            // Add event to the system log.
333
            $user_id = api_get_user_id();
334
            $category = $_GET['category'];
335
            Event::addEvent(
336
                LOG_CONFIGURATION_SETTINGS_CHANGE,
337
                LOG_CONFIGURATION_SETTINGS_CATEGORY,
338
                $category,
339
                api_get_utc_datetime(),
340
                $user_id
341
            );
342
343
            if ($result) {
344
                echo Display::return_message(get_lang('The stylesheet has been added'));
345
            }
346
        }
347
    }
348
349
    // Current style.
350
    $selected = $currentStyle = api_get_setting('stylesheets');
351
    $styleFromDatabase = api_get_settings_params_simple(
352
        ['variable = ? AND access_url = ?' => ['stylesheets', api_get_current_access_url_id()]]
353
    );
354
    if ($styleFromDatabase) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $styleFromDatabase of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
355
        $selected = $currentStyle = $styleFromDatabase['selected_value'];
356
    }
357
358
    if (isset($_POST['preview'])) {
359
        $selected = $currentStyle = Security::remove_XSS($_POST['style']);
360
    }
361
362
    $themeDir = Template::getThemeDir($selected);
363
    $dir = api_get_path(SYS_PUBLIC_PATH).'css/'.$themeDir.'/images/';
364
    $url = api_get_path(WEB_CSS_PATH).'/'.$themeDir.'/images/';
365
    $logoFileName = 'header-logo.png';
366
    $newLogoFileName = 'header-logo-custom'.api_get_current_access_url_id().'.png';
367
    $webPlatformLogoPath = ChamiloApi::getPlatformLogoPath($selected);
368
369
    $logoForm = new FormValidator(
370
        'logo_upload',
371
        'post',
372
        'settings.php?category=Stylesheets#tabs-2'
373
    );
374
375
    $logoForm->addHtml(
376
        Display::return_message(
377
            sprintf(
378
                get_lang('The logo must be of %s px in size and in %s format'),
379
                '250 x 70',
380
                'PNG'
381
            ),
382
            'info'
383
        )
384
    );
385
386
    if (null !== $webPlatformLogoPath) {
387
        $logoForm->addLabel(
388
            get_lang('Current logo'),
389
            '<img id="header-logo-custom" src="'.$webPlatformLogoPath.'?'.time().'">'
390
        );
391
    }
392
    $logoForm->addFile('new_logo', get_lang('Update logo'));
393
    if ($is_style_changeable) {
394
        $logoGroup = [
395
            $logoForm->addButtonUpload(get_lang('Upload'), 'logo_upload', true),
396
            $logoForm->addButtonCancel(get_lang('Reset'), 'logo_reset', true),
397
        ];
398
399
        $logoForm->addGroup($logoGroup);
400
    }
401
402
    if (isset($_POST['logo_reset'])) {
403
        if (is_file($dir.$newLogoFileName)) {
404
            unlink($dir.$newLogoFileName);
405
            echo Display::return_message(get_lang('Original logo recovered'));
406
            echo '<script>'
407
                .'$("#header-logo").attr("src","'.$url.$logoFileName.'");'
408
            .'</script>';
409
        }
410
    } elseif (isset($_POST['logo_upload'])) {
411
        $logoForm->addRule(
412
            'new_logo',
413
            get_lang('Invalid extension').' ('.implode(',', $allowedFileTypes).')',
414
            'filetype',
415
            $allowedFileTypes
416
        );
417
        $logoForm->addRule(
418
            'new_logo',
419
            get_lang('Required field'),
420
            'required'
421
        );
422
423
        if ($logoForm->validate()) {
424
            $imageInfo = getimagesize($_FILES['new_logo']['tmp_name']);
425
            $width = $imageInfo[0];
426
            $height = $imageInfo[1];
427
            if ($width <= 250 && $height <= 70) {
428
                if (is_file($dir.$newLogoFileName)) {
429
                    unlink($dir.$newLogoFileName);
430
                }
431
432
                $status = move_uploaded_file(
433
                    $_FILES['new_logo']['tmp_name'],
434
                    $dir.$newLogoFileName
435
                );
436
437
                if ($status) {
438
                    echo Display::return_message(get_lang('New logo uploaded'));
439
                    echo '<script>'
440
                         .'$("#header-logo").attr("src","'.$url.$newLogoFileName.'");'
441
                         .'</script>';
442
                } else {
443
                    echo Display::return_message('Error - '.get_lang('No file was uploaded.'), 'error');
444
                }
445
            } else {
446
                Display::return_message('Error - '.get_lang('Image dimensions do not match the requirements. Please check the suggestions next to the image field.'), 'error');
447
            }
448
        }
449
    }
450
451
    if (isset($_POST['download'])) {
452
        generateCSSDownloadLink($selected);
453
    }
454
455
    $form_change = new FormValidator(
456
        'stylesheet_upload',
457
        'post',
458
        api_get_self().'?category=Stylesheets',
459
        null,
460
        ['id' => 'stylesheets_id']
461
    );
462
463
    $styles = $form_change->addElement(
464
        'selectTheme',
465
        'style',
466
        get_lang('Name of the stylesheet')
467
    );
468
    $styles->setSelected($currentStyle);
469
470
    if ($is_style_changeable) {
471
        $group = [
472
            $form_change->addButtonSave(get_lang('Save settings'), 'save', true),
473
            $form_change->addButtonPreview(get_lang('Preview'), 'preview', true),
474
            $form_change->addButtonDownload(get_lang('Download'), 'download', true),
475
        ];
476
477
        $form_change->addGroup($group);
478
479
        if ($show_upload_form) {
480
            echo Display::tabs(
481
                [get_lang('Update'), get_lang('Update logo'), get_lang('New stylesheet file')],
482
                [$form_change->returnForm(), $logoForm->returnForm(), $form->returnForm()]
483
            );
484
        } else {
485
            $form_change->display();
486
        }
487
488
        // Little hack to update the logo image in update form when submiting
489
        if (isset($_POST['logo_reset'])) {
490
            echo '<script>'
491
                    .'$("#header-logo-custom").attr("src","'.$url.$logoFileName.'");'
492
                .'</script>';
493
        } elseif (isset($_POST['logo_upload']) && is_file($dir.$newLogoFileName)) {
494
            echo '<script>'
495
                    .'$("#header-logo-custom").attr("src","'.$url.$newLogoFileName.'");'
496
                .'</script>';
497
        }
498
    } else {
499
        $form_change->freeze();
500
    }
501
}
502
503
/**
504
 * Creates the folder (if needed) and uploads the stylesheet in it.
505
 *
506
 * @param array $values  the values of the form
507
 * @param array $picture the values of the uploaded file
508
 *
509
 * @return bool
510
 *
511
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
512
 *
513
 * @version May 2008
514
 *
515
 * @since v1.8.5
516
 */
517
function uploadStylesheet($values, $picture)
518
{
519
    $result = false;
520
    // Valid name for the stylesheet folder.
521
    $style_name = api_preg_replace('/[^A-Za-z0-9]/', '', $values['name_stylesheet']);
522
    if (empty($style_name) || is_array($style_name)) {
523
        // The name of the uploaded stylesheet doesn't have the expected format
524
        return $result;
525
    }
526
    $cssToUpload = CSS_UPLOAD_PATH;
527
528
    // Check if a virtual instance vchamilo is used
529
    $virtualInstanceTheme = api_get_configuration_value('virtual_css_theme_folder');
530
    if (!empty($virtualInstanceTheme)) {
531
        $cssToUpload = $cssToUpload.$virtualInstanceTheme.'/';
532
    }
533
534
    // Create the folder if needed.
535
    if (!is_dir($cssToUpload.$style_name.'/')) {
536
        mkdir($cssToUpload.$style_name.'/', api_get_permissions_for_new_directories());
537
    }
538
539
    $info = pathinfo($picture['name']);
540
541
    if ('zip' == $info['extension']) {
542
        // Try to open the file and extract it in the theme.
543
        $zip = new ZipArchive();
544
        if ($zip->open($picture['tmp_name'])) {
545
            // Make sure all files inside the zip are images or css.
546
            $num_files = $zip->numFiles;
547
            $valid = true;
548
            $single_directory = true;
549
            $invalid_files = [];
550
551
            $allowedFiles = getAllowedFileTypes();
552
553
            for ($i = 0; $i < $num_files; $i++) {
554
                $file = $zip->statIndex($i);
555
                if ('/' != substr($file['name'], -1)) {
556
                    $path_parts = pathinfo($file['name']);
557
                    if (!in_array($path_parts['extension'], $allowedFiles)) {
558
                        $valid = false;
559
                        $invalid_files[] = $file['name'];
560
                    }
561
                }
562
563
                if (false === strpos($file['name'], '/')) {
564
                    $single_directory = false;
565
                }
566
            }
567
            if (!$valid) {
568
                $error_string = '<ul>';
569
                foreach ($invalid_files as $invalid_file) {
570
                    $error_string .= '<li>'.$invalid_file.'</li>';
571
                }
572
                $error_string .= '</ul>';
573
                echo Display::return_message(
574
                    get_lang('The only accepted extensions in the ZIP file are .jp(e)g, .png, .gif and .css.').$error_string,
575
                    'error',
576
                    false
577
                );
578
            } else {
579
                // If the zip does not contain a single directory, extract it.
580
                if (!$single_directory) {
581
                    // Extract zip file.
582
                    $zip->extractTo($cssToUpload.$style_name.'/');
583
                    $result = true;
584
                } else {
585
                    $extraction_path = $cssToUpload.$style_name.'/';
586
                    $mode = api_get_permissions_for_new_directories();
587
                    for ($i = 0; $i < $num_files; $i++) {
588
                        $entry = $zip->getNameIndex($i);
589
                        if ('/' == substr($entry, -1)) {
590
                            continue;
591
                        }
592
593
                        $pos_slash = strpos($entry, '/');
594
                        $entry_without_first_dir = substr($entry, $pos_slash + 1);
595
                        // If there is still a slash, we need to make sure the directories are created.
596
                        if (false !== strpos($entry_without_first_dir, '/')) {
597
                            if (!is_dir($extraction_path.dirname($entry_without_first_dir))) {
598
                                // Create it.
599
                                @mkdir($extraction_path.dirname($entry_without_first_dir), $mode, true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mkdir(). 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

599
                                /** @scrutinizer ignore-unhandled */ @mkdir($extraction_path.dirname($entry_without_first_dir), $mode, true);

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...
600
                            }
601
                        }
602
603
                        $fp = $zip->getStream($entry);
604
                        $ofp = fopen($extraction_path.dirname($entry_without_first_dir).'/'.basename($entry), 'w');
605
606
                        while (!feof($fp)) {
607
                            fwrite($ofp, fread($fp, 8192));
608
                        }
609
610
                        fclose($fp);
611
                        fclose($ofp);
612
                    }
613
                    $result = true;
614
                }
615
            }
616
            $zip->close();
617
        } else {
618
            echo Display::return_message(get_lang('Error reading ZIP file').$info['extension'], 'error', false);
619
        }
620
    } else {
621
        // Simply move the file.
622
        move_uploaded_file($picture['tmp_name'], $cssToUpload.$style_name.'/'.$picture['name']);
623
        $result = true;
624
    }
625
626
    if ($result) {
627
        $fs = new Filesystem();
628
        $fs->mirror(
629
            CSS_UPLOAD_PATH,
630
            api_get_path(SYS_PATH).'web/css/themes/',
631
            null,
632
            ['override' => true]
633
        );
634
    }
635
636
    return $result;
637
}
638
639
/**
640
 * Store plugin regions.
641
 */
642
function storeRegions()
643
{
644
    $plugin_obj = new AppPlugin();
645
646
    // Get a list of all current 'Plugins' settings
647
    $installed_plugins = $plugin_obj->getInstalledPlugins();
648
    $shortlist_installed = [];
649
    if (!empty($installed_plugins)) {
650
        foreach ($installed_plugins as $plugin) {
651
            if (isset($plugin['subkey'])) {
652
                $shortlist_installed[] = $plugin['subkey'];
653
            }
654
        }
655
    }
656
657
    $plugin_list = $plugin_obj->read_plugins_from_path();
658
659
    foreach ($plugin_list as $plugin) {
660
        if (isset($_POST['plugin_'.$plugin])) {
661
            $areas_to_installed = $_POST['plugin_'.$plugin];
662
            if (!empty($areas_to_installed)) {
663
                $plugin_obj->removeAllRegions($plugin);
664
                foreach ($areas_to_installed as $region) {
665
                    if (!empty($region) && '-1' != $region) {
666
                        $plugin_obj->add_to_region($plugin, $region);
667
                    }
668
                }
669
            }
670
        }
671
    }
672
}
673
674
/**
675
 * This function allows easy activating and inactivating of plugins.
676
 *
677
 * @author Patrick Cool <[email protected]>, Ghent University
678
 */
679
function storePlugins()
680
{
681
    $appPlugin = new AppPlugin();
682
    // Get a list of all current 'Plugins' settings
683
    $plugin_list = $appPlugin->read_plugins_from_path();
684
    $installed_plugins = [];
685
686
    foreach ($plugin_list as $plugin) {
687
        if (isset($_POST['plugin_'.$plugin])) {
688
            $appPlugin->install($plugin);
689
            $installed_plugins[] = $plugin;
690
        }
691
    }
692
693
    if (!empty($installed_plugins)) {
694
        $remove_plugins = array_diff($plugin_list, $installed_plugins);
695
    } else {
696
        $remove_plugins = $plugin_list;
697
    }
698
699
    foreach ($remove_plugins as $plugin) {
700
        $appPlugin->uninstall($plugin);
701
    }
702
}
703
704
/**
705
 * This function allows the platform admin to choose which should be the default stylesheet.
706
 *
707
 * @author Patrick Cool <[email protected]>, Ghent University
708
 */
709
function storeStylesheets()
710
{
711
    // Insert the stylesheet.
712
    if (isStyle($_POST['style'])) {
713
        api_set_setting(
714
            'stylesheets',
715
            $_POST['style'],
716
            null,
717
            'stylesheets',
718
            api_get_current_access_url_id()
719
        );
720
    }
721
722
    return true;
723
}
724
725
/**
726
 * This function checks if the given style is a recognize style that exists in the css directory as
727
 * a standalone directory.
728
 *
729
 * @param string $style
730
 *
731
 * @return bool True if this style is recognized, false otherwise
732
 */
733
function isStyle($style)
734
{
735
    $themeList = api_get_themes();
736
737
    return in_array($style, array_keys($themeList));
738
}
739
740
/**
741
 * Search options
742
 * TODO: support for multiple site. aka $_configuration['access_url'] == 1.
743
 *
744
 * @author Marco Villegas <[email protected]>
745
 */
746
function handleSearch()
747
{
748
    global $SettingsStored, $_configuration;
749
750
    $search_enabled = api_get_setting('search_enabled');
751
752
    $form = new FormValidator(
753
        'search-options',
754
        'post',
755
        api_get_self().'?category=Search'
756
    );
757
    $values = api_get_settings_options('search_enabled');
758
    $form->addElement('header', null, get_lang('Fulltext search'));
759
760
    $group = formGenerateElementsGroup($form, $values, 'search_enabled');
761
762
    // SearchEnabledComment
763
    $form->addGroup(
764
        $group,
765
        'search_enabled',
766
        [get_lang('Fulltext search'), get_lang('This feature allows you to index most of the documents uploaded to your portal, then provide a search feature for users.<br />This feature will not index documents that have already been uploaded, so it is important to enable (if wanted) at the beginning of your implementation.<br />Once enabled, a search box will appear in the courses list of every user. Searching for a specific term will bring a list of corresponding documents, exercises or forum topics, filtered depending on the availability of these contents to the user.')],
767
        null,
768
        false
769
    );
770
771
    $search_enabled = api_get_setting('search_enabled');
772
773
    if ($form->validate()) {
774
        $formValues = $form->exportValues();
775
        setConfigurationSettingsInDatabase($formValues, $_configuration['access_url']);
776
        $search_enabled = $formValues['search_enabled'];
777
        echo Display::return_message($SettingsStored, 'confirm');
778
    }
779
    $specific_fields = get_specific_field_list();
780
781
    if ('true' == $search_enabled) {
782
        $values = api_get_settings_options('search_show_unlinked_results');
783
        $group = formGenerateElementsGroup(
784
            $form,
785
            $values,
786
            'search_show_unlinked_results'
787
        );
788
        $form->addGroup(
789
            $group,
790
            'search_show_unlinked_results',
791
            [
792
                get_lang('Full-text search: show unlinked results'),
793
                get_lang('When showing the results of a full-text search, what should be done with the results that are not accessible to the current user?'),
794
            ],
795
            null,
796
            false
797
        );
798
        $default_values['search_show_unlinked_results'] = api_get_setting('search_show_unlinked_results');
0 ignored issues
show
Comprehensibility Best Practice introduced by
$default_values was never initialized. Although not strictly required by PHP, it is generally a good practice to add $default_values = array(); before regardless.
Loading history...
799
800
        $sf_values = [];
801
        foreach ($specific_fields as $sf) {
802
            $sf_values[$sf['code']] = $sf['name'];
803
        }
804
        $url = Display::div(
805
            Display::url(
806
                get_lang('Add a specific search field'),
807
                'specific_fields.php'
808
            ),
809
            ['class' => 'sectioncomment']
810
        );
811
        if (empty($sf_values)) {
812
            $form->addElement('label', [get_lang('Specific Field for prefilter'), $url]);
813
        } else {
814
            $form->addElement(
815
                'select',
816
                'search_prefilter_prefix',
817
                [get_lang('Specific Field for prefilter'), $url],
818
                $sf_values,
819
                ''
820
            );
821
            $default_values['search_prefilter_prefix'] = api_get_setting('search_prefilter_prefix');
822
        }
823
    }
824
825
    $default_values['search_enabled'] = $search_enabled;
826
827
    $form->addButtonSave(get_lang('Save'));
828
    $form->setDefaults($default_values);
829
830
    echo '<div id="search-options-form">';
831
    $form->display();
832
    echo '</div>';
833
834
    if ('true' == $search_enabled) {
835
        //$xapianPath = api_get_path(SYS_UPLOAD_PATH).'plugins/xapian/searchdb';
836
837
        /*
838
        @todo Test the Xapian connection
839
        if (extension_loaded('xapian')) {
840
            require_once 'xapian.php';
841
            try {
842
                $db = new XapianDatabase($xapianPath.'/');
843
            } catch (Exception $e) {
844
                var_dump($e->getMessage());
845
            }
846
847
            require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
848
            require_once api_get_path(LIBRARY_PATH) . 'search/IndexableChunk.class.php';
849
            require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
850
851
            $indexable = new IndexableChunk();
852
            $indexable->addValue("content", 'Test');
853
854
            $di = new ChamiloIndexer();
855
            $di->connectDb(NULL, NULL, 'english');
856
            $di->addChunk($indexable);
857
            $did = $di->index();
858
        }
859
        */
860
861
        $xapianLoaded = Display::return_icon('bullet_green.png', get_lang('Validate'));
862
        $dir_exists = Display::return_icon('bullet_green.png', get_lang('Validate'));
863
        $dir_is_writable = Display::return_icon('bullet_green.png', get_lang('Validate'));
864
        $specific_fields_exists = Display::return_icon('bullet_green.png', get_lang('Validate'));
865
866
        //Testing specific fields
867
        if (empty($specific_fields)) {
868
            $specific_fields_exists = Display::return_icon(
869
                'bullet_red.png',
870
                get_lang('Add a specific search field')
871
            );
872
        }
873
        //Testing xapian extension
874
        if (!extension_loaded('xapian')) {
875
            $xapianLoaded = Display::return_icon('bullet_red.png', get_lang('Error'));
876
        }
877
        //Testing xapian searchdb path
878
        if (!is_dir($xapianPath)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $xapianPath seems to be never defined.
Loading history...
879
            $dir_exists = Display::return_icon('bullet_red.png', get_lang('Error'));
880
        }
881
        //Testing xapian searchdb path is writable
882
        if (!is_writable($xapianPath)) {
883
            $dir_is_writable = Display::return_icon('bullet_red.png', get_lang('Error'));
884
        }
885
886
        $data = [];
887
        $data[] = [get_lang('Xapian module installed'), $xapianLoaded];
888
        $data[] = [get_lang('The directory exists').' - '.$xapianPath, $dir_exists];
889
        $data[] = [get_lang('Is writable').' - '.$xapianPath, $dir_is_writable];
890
        $data[] = [get_lang('Available custom search fields'), $specific_fields_exists];
891
892
        showSearchSettingsTable($data);
893
        showSearchToolsStatusTable();
894
    }
895
}
896
897
/**
898
 * Wrapper for the templates.
899
 *
900
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
901
 * @author Julio Montoya.
902
 *
903
 * @version August 2008
904
 *
905
 * @since v1.8.6
906
 */
907
function handleTemplates()
908
{
909
    /* Drive-by fix to avoid undefined var warnings, without repeating
910
     * isset() combos all over the place. */
911
    $action = isset($_GET['action']) ? $_GET['action'] : "invalid";
912
913
    if ('add' != $action) {
914
        echo '<div class="actions" style="margin-left: 1px;">';
915
        echo '<a href="settings.php?category=Templates&action=add">'.
916
                Display::return_icon('new_template.png', get_lang('Add a template'), '', ICON_SIZE_MEDIUM).'</a>';
917
        echo '</div>';
918
    }
919
920
    if ('add' == $action || ('edit' == $action && is_numeric($_GET['id']))) {
921
        addEditTemplate();
922
923
        // Add event to the system log.
924
        $user_id = api_get_user_id();
925
        $category = $_GET['category'];
926
        Event::addEvent(
927
            LOG_CONFIGURATION_SETTINGS_CHANGE,
928
            LOG_CONFIGURATION_SETTINGS_CATEGORY,
929
            $category,
930
            api_get_utc_datetime(),
931
            $user_id
932
        );
933
    } else {
934
        if ('delete' == $action && is_numeric($_GET['id'])) {
935
            deleteTemplate($_GET['id']);
936
937
            // Add event to the system log
938
            $user_id = api_get_user_id();
939
            $category = $_GET['category'];
940
            Event::addEvent(
941
                LOG_CONFIGURATION_SETTINGS_CHANGE,
942
                LOG_CONFIGURATION_SETTINGS_CATEGORY,
943
                $category,
944
                api_get_utc_datetime(),
945
                $user_id
946
            );
947
        }
948
        displayTemplates();
949
    }
950
}
951
952
/**
953
 * Display a sortable table with all the templates that the platform administrator has defined.
954
 *
955
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
956
 *
957
 * @version August 2008
958
 *
959
 * @since v1.8.6
960
 */
961
function displayTemplates()
962
{
963
    $table = new SortableTable(
964
        'templates',
965
        'getNumberOfTemplates',
966
        'getTemplateData',
967
        1
968
    );
969
    $table->set_additional_parameters(
970
        ['category' => Security::remove_XSS($_GET['category'])]
971
    );
972
    $table->set_header(0, get_lang('Image'), true, ['style' => 'width: 101px;']);
973
    $table->set_header(1, get_lang('Title'));
974
    $table->set_header(2, get_lang('Detail'), false, ['style' => 'width:50px;']);
975
    $table->set_column_filter(2, 'actionsFilter');
976
    $table->set_column_filter(0, 'searchImageFilter');
977
    $table->display();
978
}
979
980
/**
981
 * Gets the number of templates that are defined by the platform admin.
982
 *
983
 * @return int
984
 *
985
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
986
 *
987
 * @version August 2008
988
 *
989
 * @since v1.8.6
990
 */
991
function getNumberOfTemplates()
992
{
993
    // Database table definition.
994
    $table = Database::get_main_table('system_template');
995
996
    // The sql statement.
997
    $sql = "SELECT COUNT(id) AS total FROM $table";
998
    $result = Database::query($sql);
999
    $row = Database::fetch_array($result);
1000
1001
    // Returning the number of templates.
1002
    return $row['total'];
1003
}
1004
1005
/**
1006
 * Gets all the template data for the sortable table.
1007
 *
1008
 * @param int    $from            the start of the limit statement
1009
 * @param int    $number_of_items the number of elements that have to be retrieved from the database
1010
 * @param int    $column          the column that is
1011
 * @param string $direction       the sorting direction (ASC or DESC)
1012
 *
1013
 * @return array
1014
 *
1015
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1016
 *
1017
 * @version August 2008
1018
 *
1019
 * @since v1.8.6
1020
 */
1021
function getTemplateData($from, $number_of_items, $column, $direction)
1022
{
1023
    // Database table definition.
1024
    $table_system_template = Database::get_main_table('system_template');
1025
1026
    $from = (int) $from;
1027
    $number_of_items = (int) $number_of_items;
1028
    $column = (int) $column;
1029
    $direction = !in_array(strtolower(trim($direction)), ['asc', 'desc']) ? 'asc' : $direction;
1030
    // The sql statement.
1031
    $sql = "SELECT image as col0, title as col1, id as col2 FROM $table_system_template";
1032
    $sql .= " ORDER BY col$column $direction ";
1033
    $sql .= " LIMIT $from,$number_of_items";
1034
    $result = Database::query($sql);
1035
    $return = [];
1036
    while ($row = Database::fetch_array($result)) {
1037
        $row['1'] = get_lang($row['1']);
1038
        $return[] = $row;
1039
    }
1040
    // Returning all the information for the sortable table.
1041
    return $return;
1042
}
1043
1044
/**
1045
 * display the edit and delete icons in the sortable table.
1046
 *
1047
 * @param int $id the id of the template
1048
 *
1049
 * @return string code for the link to edit and delete the template
1050
 *
1051
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1052
 *
1053
 * @version August 2008
1054
 *
1055
 * @since v1.8.6
1056
 */
1057
function actionsFilter($id)
1058
{
1059
    $return = '<a href="settings.php?category=Templates&action=edit&id='.Security::remove_XSS($id).'">'.Display::return_icon('edit.png', get_lang('Edit'), '', ICON_SIZE_SMALL).'</a>';
0 ignored issues
show
Bug introduced by
Are you sure Security::remove_XSS($id) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

1059
    $return = '<a href="settings.php?category=Templates&action=edit&id='./** @scrutinizer ignore-type */ Security::remove_XSS($id).'">'.Display::return_icon('edit.png', get_lang('Edit'), '', ICON_SIZE_SMALL).'</a>';
Loading history...
1060
    $return .= '<a href="settings.php?category=Templates&action=delete&id='.Security::remove_XSS($id).'" onClick="javascript:if(!confirm('."'".get_lang('Please confirm your choice')."'".')) return false;">'.Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>';
1061
1062
    return $return;
1063
}
1064
1065
/**
1066
 * Display the image of the template in the sortable table.
1067
 *
1068
 * @param string $image the image
1069
 *
1070
 * @return string code for the image
1071
 *
1072
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1073
 *
1074
 * @version August 2008
1075
 *
1076
 * @since v1.8.6
1077
 */
1078
function searchImageFilter($image)
1079
{
1080
    if (!empty($image)) {
1081
        return '<img src="'.api_get_path(WEB_PUBLIC_PATH).'img/template_thumb/'.$image.'" alt="'.get_lang('Template preview').'"/>';
1082
    } else {
1083
        return '<img src="'.api_get_path(WEB_PUBLIC_PATH).'img/template_thumb/noimage.gif" alt="'.get_lang('NoTemplate preview').'"/>';
1084
    }
1085
}
1086
1087
/**
1088
 * Add (or edit) a template. This function displays the form and also takes
1089
 * care of uploading the image and storing the information in the database.
1090
 *
1091
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1092
 *
1093
 * @version August 2008
1094
 *
1095
 * @since v1.8.6
1096
 */
1097
function addEditTemplate()
1098
{
1099
    $em = Database::getManager();
1100
    $id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
1101
1102
    /** @var SystemTemplate $template */
1103
    $template = $id ? $em->find('ChamiloCoreBundle:SystemTemplate', $id) : new SystemTemplate();
1104
1105
    $form = new FormValidator(
1106
        'template',
1107
        'post',
1108
        'settings.php?category=Templates&action='.Security::remove_XSS($_GET['action']).'&id='.$id
0 ignored issues
show
Bug introduced by
Are you sure Security::remove_XSS($_GET['action']) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

1108
        'settings.php?category=Templates&action='./** @scrutinizer ignore-type */ Security::remove_XSS($_GET['action']).'&id='.$id
Loading history...
1109
    );
1110
1111
    // Setting the form elements: the header.
1112
    if ('add' == $_GET['action']) {
1113
        $title = get_lang('Add a template');
1114
    } else {
1115
        $title = get_lang('Template edition');
1116
    }
1117
    $form->addElement('header', '', $title);
1118
1119
    // Setting the form elements: the title of the template.
1120
    $form->addText('title', get_lang('Title'), false);
1121
    $form->addText('comment', get_lang('Description'), false);
1122
1123
    // Setting the form elements: the content of the template (wysiwyg editor).
1124
    $form->addHtmlEditor(
1125
        'template_text',
1126
        get_lang('Text'),
1127
        true,
1128
        true,
1129
        ['ToolbarSet' => 'Documents', 'Width' => '100%', 'Height' => '400']
1130
    );
1131
1132
    // Setting the form elements: the form to upload an image to be used with the template.
1133
    if (empty($template->getImage())) {
1134
        $form->addElement('file', 'template_image', get_lang('Image'), '');
1135
    }
1136
1137
    // Setting the form elements: a little bit information about the template image.
1138
    $form->addElement('static', 'file_comment', '', get_lang('This image will represent the template in the templates list. It should be no larger than 100x70 pixels'));
1139
1140
    // Getting all the information of the template when editing a template.
1141
    if ('edit' == $_GET['action']) {
1142
        $defaults['template_id'] = $id;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$defaults was never initialized. Although not strictly required by PHP, it is generally a good practice to add $defaults = array(); before regardless.
Loading history...
1143
        $defaults['template_text'] = $template->getContent();
1144
        // Forcing get_lang().
1145
        $defaults['title'] = $template->getTitle();
1146
        $defaults['comment'] = $template->getComment();
1147
1148
        // Adding an extra field: a hidden field with the id of the template we are editing.
1149
        $form->addElement('hidden', 'template_id');
1150
1151
        // Adding an extra field: a preview of the image that is currently used.
1152
1153
        if (!empty($template->getImage())) {
1154
            $form->addElement(
1155
                'static',
1156
                'template_image_preview',
1157
                '',
1158
                '<img src="'.api_get_path(WEB_PUBLIC_PATH).'img/template_thumb/'.$template->getImage()
1159
                    .'" alt="'.get_lang('Template preview')
1160
                    .'"/>'
1161
            );
1162
            $form->addCheckBox('delete_image', null, get_lang('Delete picture'));
1163
        } else {
1164
            $form->addElement(
1165
                'static',
1166
                'template_image_preview',
1167
                '',
1168
                '<img src="'.api_get_path(WEB_PUBLIC_PATH).'img/template_thumb/noimage.gif" alt="'.get_lang('NoTemplate preview').'"/>'
1169
            );
1170
        }
1171
1172
        // Setting the information of the template that we are editing.
1173
        $form->setDefaults($defaults);
1174
    }
1175
    // Setting the form elements: the submit button.
1176
    $form->addButtonSave(get_lang('Validate'), 'submit');
1177
1178
    // Setting the rules: the required fields.
1179
    if (empty($template->getImage())) {
1180
        $form->addRule(
1181
            'template_image',
1182
            get_lang('Required field'),
1183
            'required'
1184
        );
1185
        $form->addRule('title', get_lang('Required field'), 'required');
1186
    }
1187
1188
    // if the form validates (complies to all rules) we save the information,
1189
    // else we display the form again (with error message if needed)
1190
    if ($form->validate()) {
1191
        $check = Security::check_token('post');
1192
1193
        if ($check) {
1194
            // Exporting the values.
1195
            $values = $form->exportValues();
1196
            $isDelete = null;
1197
            if (isset($values['delete_image'])) {
1198
                $isDelete = $values['delete_image'];
1199
            }
1200
1201
            // Upload the file.
1202
            if (!empty($_FILES['template_image']['name'])) {
1203
                $upload_ok = process_uploaded_file($_FILES['template_image']);
1204
1205
                if ($upload_ok) {
1206
                    // Try to add an extension to the file if it hasn't one.
1207
                    $new_file_name = add_ext_on_mime(stripslashes($_FILES['template_image']['name']), $_FILES['template_image']['type']);
1208
1209
                    // The upload directory.
1210
                    // todo
1211
1212
                    $upload_dir = api_get_path(SYS_PATH).'home/default_platform_document/template_thumb/';
1213
1214
                    // Create the directory if it does not exist.
1215
                    if (!is_dir($upload_dir)) {
1216
                        mkdir($upload_dir, api_get_permissions_for_new_directories());
1217
                    }
1218
1219
                    // Resize the preview image to max default and upload.
1220
                    $temp = new Image($_FILES['template_image']['tmp_name']);
1221
                    $picture_info = $temp->get_image_info();
1222
1223
                    $max_width_for_picture = 100;
1224
                    if ($picture_info['width'] > $max_width_for_picture) {
1225
                        $temp->resize($max_width_for_picture);
1226
                    }
1227
                    $temp->send_image($upload_dir.$new_file_name);
1228
                }
1229
            }
1230
1231
            // Store the information in the database (as insert or as update).
1232
            $bootstrap = api_get_bootstrap_and_font_awesome();
1233
            $viewport = '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
1234
1235
            if ('add' == $_GET['action']) {
1236
                $templateContent = '<head>'.$viewport.'<title>'.$values['title'].'</title>'.$bootstrap.'</head>'
1237
                    .$values['template_text'];
1238
                $template
1239
                    ->setTitle($values['title'])
1240
                    ->setComment(Security::remove_XSS($values['comment']))
1241
                    ->setContent(Security::remove_XSS($templateContent, COURSEMANAGERLOWSECURITY))
1242
                    ->setImage($new_file_name);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $new_file_name does not seem to be defined for all execution paths leading up to this point.
Loading history...
1243
                $em->persist($template);
1244
                $em->flush();
1245
1246
                // Display a feedback message.
1247
                echo Display::return_message(
1248
                    get_lang('Template added'),
1249
                    'confirm'
1250
                );
1251
                echo '<a href="settings.php?category=Templates&action=add">'.
1252
                    Display::return_icon('new_template.png', get_lang('Add a template'), '', ICON_SIZE_MEDIUM).
1253
                    '</a>';
1254
            } else {
1255
                $templateContent = '<head>'.$viewport.'<title>'.$values['title'].'</title>'.$bootstrap.'</head>'
1256
                    .$values['template_text'];
1257
1258
                $template
1259
                    ->setTitle($values['title'])
1260
                    ->setContent(Security::remove_XSS($templateContent, COURSEMANAGERLOWSECURITY));
1261
1262
                if (!empty($new_file_name)) {
1263
                    $template->setImage($new_file_name);
1264
                }
1265
1266
                $em->persist($template);
1267
                $em->flush();
1268
1269
                // Display a feedback message.
1270
                echo Display::return_message(get_lang('Template edited'), 'confirm');
1271
            }
1272
        }
1273
        Security::clear_token();
1274
        displayTemplates();
1275
    } else {
1276
        $token = Security::get_token();
1277
        $form->addElement('hidden', 'sec_token');
1278
        $form->setConstants(['sec_token' => $token]);
1279
        // Display the form.
1280
        $form->display();
1281
    }
1282
}
1283
1284
/**
1285
 * Delete a template.
1286
 *
1287
 * @param int $id the id of the template that has to be deleted
1288
 *
1289
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1290
 *
1291
 * @version August 2008
1292
 *
1293
 * @since v1.8.6
1294
 */
1295
function deleteTemplate($id)
1296
{
1297
    $id = intval($id);
1298
    // First we remove the image.
1299
    $table = Database::get_main_table('system_template');
1300
    $sql = "SELECT * FROM $table WHERE id = $id";
1301
    $result = Database::query($sql);
1302
    $row = Database::fetch_array($result);
1303
    if (!empty($row['image'])) {
1304
        @unlink(api_get_path(SYS_APP_PATH).'home/default_platform_document/template_thumb/'.$row['image']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). 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

1304
        /** @scrutinizer ignore-unhandled */ @unlink(api_get_path(SYS_APP_PATH).'home/default_platform_document/template_thumb/'.$row['image']);

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
The constant SYS_APP_PATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1305
    }
1306
1307
    // Now we remove it from the database.
1308
    $sql = "DELETE FROM $table WHERE id = $id";
1309
    Database::query($sql);
1310
1311
    // Display a feedback message.
1312
    echo Display::return_message(get_lang('Template deleted'), 'confirm');
1313
}
1314
1315
/**
1316
 * @param array $settings
1317
 * @param array $settings_by_access_list
1318
 *
1319
 * @throws \Doctrine\ORM\ORMException
1320
 * @throws \Doctrine\ORM\OptimisticLockException
1321
 * @throws \Doctrine\ORM\TransactionRequiredException
1322
 *
1323
 * @return FormValidator
1324
 */
1325
function generateSettingsForm($settings, $settings_by_access_list)
1326
{
1327
    global $_configuration, $settings_to_avoid, $convert_byte_to_mega_list;
1328
    $em = Database::getManager();
1329
    $table_settings_current = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1330
1331
    $form = new FormValidator(
1332
        'settings',
1333
        'post',
1334
        'settings.php?category='.Security::remove_XSS($_GET['category'])
0 ignored issues
show
Bug introduced by
Are you sure Security::remove_XSS($_GET['category']) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

1334
        'settings.php?category='./** @scrutinizer ignore-type */ Security::remove_XSS($_GET['category'])
Loading history...
1335
    );
1336
1337
    $form->addElement(
1338
        'hidden',
1339
        'search_field',
1340
        (!empty($_GET['search_field']) ? Security::remove_XSS($_GET['search_field']) : null)
1341
    );
1342
1343
    $url_id = api_get_current_access_url_id();
1344
    /*
1345
    if (!empty($_configuration['multiple_access_urls']) && api_is_global_platform_admin() && $url_id == 1) {
1346
        $group = array();
1347
        $group[] = $form->createElement('button', 'mark_all', get_lang('Select all'));
1348
        $group[] = $form->createElement('button', 'unmark_all', get_lang('Unselect all'));
1349
        $form->addGroup($group, 'buttons_in_action_right');
1350
    }*/
1351
1352
    $default_values = [];
1353
    $url_info = api_get_access_url($url_id);
1354
    $i = 0;
1355
    $addedSettings = [];
1356
    foreach ($settings as $row) {
1357
        if (in_array($row['variable'], array_keys($settings_to_avoid))) {
1358
            continue;
1359
        }
1360
1361
        if (in_array($row['variable'], $addedSettings)) {
1362
            continue;
1363
        }
1364
1365
        $addedSettings[] = $row['variable'];
1366
1367
        if (!empty($_configuration['multiple_access_urls'])) {
1368
            if (api_is_global_platform_admin()) {
1369
                if (0 == $row['access_url_locked']) {
1370
                    if (1 == $url_id) {
1371
                        if ('1' == $row['access_url_changeable']) {
1372
                            $form->addElement(
1373
                                'html',
1374
                                '<div class="float-right"><a class="share_this_setting" data_status = "0"  data_to_send = "'.$row['variable'].'" href="javascript:void(0);">'.
1375
                                Display::return_icon('shared_setting.png', get_lang('Change setting visibility for the other portals'), null, ICON_SIZE_MEDIUM).'</a></div>'
1376
                            );
1377
                        } else {
1378
                            $form->addElement(
1379
                                'html',
1380
                                '<div class="float-right"><a class="share_this_setting" data_status = "1" data_to_send = "'.$row['variable'].'" href="javascript:void(0);">'.
1381
                                Display::return_icon('shared_setting_na.png', get_lang('Change setting visibility for the other portals'), null, ICON_SIZE_MEDIUM).'</a></div>'
1382
                            );
1383
                        }
1384
                    } else {
1385
                        if ('1' == $row['access_url_changeable']) {
1386
                            $form->addElement(
1387
                                'html',
1388
                                '<div class="float-right">'.
1389
                                Display::return_icon('shared_setting.png', get_lang('Change setting visibility for the other portals'), null, ICON_SIZE_MEDIUM).'</div>'
1390
                            );
1391
                        } else {
1392
                            $form->addElement(
1393
                                'html',
1394
                                '<div class="float-right">'.
1395
                                Display::return_icon('shared_setting_na.png', get_lang('Change setting visibility for the other portals'), null, ICON_SIZE_MEDIUM).'</div>'
1396
                            );
1397
                        }
1398
                    }
1399
                }
1400
            }
1401
        }
1402
1403
        $hideme = [];
1404
        $hide_element = false;
1405
1406
        if (1 != $_configuration['access_url']) {
1407
            if (0 == $row['access_url_changeable']) {
1408
                // We hide the element in other cases (checkbox, radiobutton) we 'freeze' the element.
1409
                $hide_element = true;
1410
                $hideme = ['disabled'];
1411
            } elseif (1 == $url_info['active']) {
1412
                // We show the elements.
1413
                if (empty($row['variable'])) {
1414
                    $row['variable'] = 0;
1415
                }
1416
                if (empty($row['subkey'])) {
1417
                    $row['subkey'] = 0;
1418
                }
1419
                if (empty($row['category'])) {
1420
                    $row['category'] = 0;
1421
                }
1422
                if (isset($settings_by_access_list[$row['variable']]) &&
1423
                    isset($settings_by_access_list[$row['variable']][$row['subkey']]) &&
1424
                    is_array($settings_by_access_list[$row['variable']][$row['subkey']][$row['category']])
1425
                ) {
1426
                    // We are sure that the other site have a selected value.
1427
                    if ('' != $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']]['selected_value']) {
1428
                        $row['selected_value'] = $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']]['selected_value'];
1429
                    }
1430
                }
1431
                // There is no else{} statement because we load the default $row['selected_value'] of the main Chamilo site.
1432
            }
1433
        }
1434
1435
        switch ($row['type']) {
1436
            case 'textfield':
1437
                if (in_array($row['variable'], $convert_byte_to_mega_list)) {
1438
                    $form->addElement(
1439
                        'text',
1440
                        $row['variable'],
1441
                        [
1442
                            get_lang($row['title']),
1443
                            get_lang($row['comment']),
1444
                            get_lang('MB'),
1445
                        ],
1446
                        ['maxlength' => '8', 'aria-label' => get_lang($row['title'])]
1447
                    );
1448
                    $form->applyFilter($row['variable'], 'html_filter');
1449
                    $default_values[$row['variable']] = round($row['selected_value'] / 1024 / 1024, 1);
1450
                } elseif ('account_valid_duration' == $row['variable']) {
1451
                    $form->addElement(
1452
                        'text',
1453
                        $row['variable'],
1454
                        [
1455
                            get_lang($row['title']),
1456
                            get_lang($row['comment']),
1457
                        ],
1458
                        ['maxlength' => '5', 'aria-label' => get_lang($row['title'])]
1459
                    );
1460
                    $form->applyFilter($row['variable'], 'html_filter');
1461
1462
                    // For platform character set selection:
1463
                    // Conversion of the textfield to a select box with valid values.
1464
                    $default_values[$row['variable']] = $row['selected_value'];
1465
                } elseif ('platform_charset' == $row['variable']) {
1466
                    break;
1467
                } else {
1468
                    $hideme['class'] = 'col-md-4';
1469
                    $hideme['aria-label'] = get_lang($row['title']);
1470
                    $form->addElement(
1471
                        'text',
1472
                        $row['variable'],
1473
                        [
1474
                            get_lang($row['title']),
1475
                            get_lang($row['comment']),
1476
                        ],
1477
                        $hideme
1478
                    );
1479
                    $form->applyFilter($row['variable'], 'html_filter');
1480
                    $default_values[$row['variable']] = $row['selected_value'];
1481
                }
1482
                break;
1483
            case 'textarea':
1484
                if ('header_extra_content' == $row['variable']) {
1485
                    $file = api_get_home_path().'header_extra_content.txt';
0 ignored issues
show
Bug introduced by
The function api_get_home_path was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

1485
                    $file = /** @scrutinizer ignore-call */ api_get_home_path().'header_extra_content.txt';
Loading history...
1486
                    $value = '';
1487
                    if (file_exists($file)) {
1488
                        $value = file_get_contents($file);
1489
                    }
1490
                    $form->addElement(
1491
                        'textarea',
1492
                        $row['variable'],
1493
                        [get_lang($row['title']), get_lang($row['comment'])],
1494
                        ['rows' => '10', 'id' => $row['variable']],
1495
                        $hideme
1496
                    );
1497
                    $default_values[$row['variable']] = $value;
1498
                } elseif ('footer_extra_content' == $row['variable']) {
1499
                    $file = api_get_home_path().'footer_extra_content.txt';
1500
                    $value = '';
1501
                    if (file_exists($file)) {
1502
                        $value = file_get_contents($file);
1503
                    }
1504
                    $form->addElement(
1505
                        'textarea',
1506
                        $row['variable'],
1507
                        [get_lang($row['title']), get_lang($row['comment'])],
1508
                        ['rows' => '10', 'id' => $row['variable']],
1509
                        $hideme
1510
                    );
1511
                    $default_values[$row['variable']] = $value;
1512
                } else {
1513
                    $form->addElement(
1514
                        'textarea',
1515
                        $row['variable'],
1516
                        [get_lang($row['title']),
1517
                        get_lang($row['comment']), ],
1518
                        ['rows' => '10', 'id' => $row['variable']],
1519
                        $hideme
1520
                    );
1521
                    $default_values[$row['variable']] = $row['selected_value'];
1522
                }
1523
                break;
1524
            case 'radio':
1525
                $values = api_get_settings_options($row['variable']);
1526
                $group = [];
1527
                if (is_array($values)) {
1528
                    foreach ($values as $key => $value) {
1529
                        $element = &$form->createElement(
1530
                            'radio',
1531
                            $row['variable'],
1532
                            '',
1533
                            get_lang($value['display_text']),
1534
                            $value['value']
1535
                        );
1536
                        if ($hide_element) {
1537
                            $element->freeze();
1538
                        }
1539
                        $group[] = $element;
1540
                    }
1541
                }
1542
                $form->addGroup(
1543
                    $group,
1544
                    $row['variable'],
1545
                    [get_lang($row['title']), get_lang($row['comment'])],
1546
                    null,
1547
                    false
1548
                );
1549
                $default_values[$row['variable']] = $row['selected_value'];
1550
                break;
1551
            case 'checkbox':
1552
                // 1. We collect all the options of this variable.
1553
                $sql = "SELECT * FROM $table_settings_current
1554
                        WHERE variable='".$row['variable']."' AND access_url =  1";
1555
1556
                $result = Database::query($sql);
1557
                $group = [];
1558
                while ($rowkeys = Database::fetch_array($result)) {
1559
                    // Profile tab option should be hidden when the social tool is enabled.
1560
                    if ('true' == api_get_setting('allow_social_tool')) {
1561
                        if ('show_tabs' === $rowkeys['variable'] && 'my_profile' === $rowkeys['subkey']) {
1562
                            continue;
1563
                        }
1564
                    }
1565
1566
                    // Hiding the gradebook option.
1567
                    if ('show_tabs' === $rowkeys['variable'] && 'my_gradebook' === $rowkeys['subkey']) {
1568
                        continue;
1569
                    }
1570
1571
                    $element = &$form->createElement(
1572
                        'checkbox',
1573
                        $rowkeys['subkey'],
1574
                        '',
1575
                        get_lang($rowkeys['subkeytext'])
1576
                    );
1577
1578
                    if (1 == $row['access_url_changeable']) {
1579
                        // 2. We look into the DB if there is a setting for a specific access_url.
1580
                        $access_url = $_configuration['access_url'];
1581
                        if (empty($access_url)) {
1582
                            $access_url = 1;
1583
                        }
1584
                        $sql = "SELECT selected_value FROM $table_settings_current
1585
                                WHERE
1586
                                    variable='".$rowkeys['variable']."' AND
1587
                                    subkey='".$rowkeys['subkey']."' AND
1588
                                    subkeytext='".$rowkeys['subkeytext']."' AND
1589
                                    access_url =  $access_url";
1590
                        $result_access = Database::query($sql);
1591
                        $row_access = Database::fetch_array($result_access);
1592
                        if ('true' === $row_access['selected_value'] && !$form->isSubmitted()) {
1593
                            $element->setChecked(true);
1594
                        }
1595
                    } else {
1596
                        if ('true' === $rowkeys['selected_value'] && !$form->isSubmitted()) {
1597
                            $element->setChecked(true);
1598
                        }
1599
                    }
1600
                    if ($hide_element) {
1601
                        $element->freeze();
1602
                    }
1603
                    $group[] = $element;
1604
                }
1605
                $form->addGroup(
1606
                    $group,
1607
                    $row['variable'],
1608
                    [get_lang($row['title']), get_lang($row['comment'])],
1609
                    null
1610
                );
1611
                break;
1612
            case 'link':
1613
                $form->addElement(
1614
                    'static',
1615
                    null,
1616
                    [get_lang($row['title']), get_lang($row['comment'])],
1617
                    get_lang('current value').' : '.$row['selected_value'],
1618
                    $hideme
1619
                );
1620
                break;
1621
            case 'select':
1622
                /*
1623
                * To populate the list of options, the select type dynamically calls a function that must be called select_ + the name of the variable being displayed.
1624
                * The functions being called must be added to the file settings.lib.php.
1625
                */
1626
                $form->addElement(
1627
                    'select',
1628
                    $row['variable'],
1629
                    [get_lang($row['title']), get_lang($row['comment'])],
1630
                    call_user_func('select_'.$row['variable']),
1631
                    $hideme
1632
                );
1633
                $default_values[$row['variable']] = $row['selected_value'];
1634
                break;
1635
            case 'custom':
1636
                break;
1637
            case 'select_course':
1638
                $courseSelectOptions = [];
1639
1640
                if (!empty($row['selected_value'])) {
1641
                    $course = $em->find('ChamiloCoreBundle:Course', $row['selected_value']);
1642
1643
                    $courseSelectOptions[$course->getId()] = $course->getTitle();
1644
                }
1645
1646
                $form->addElement(
1647
                    'select_ajax',
1648
                    $row['variable'],
1649
                    [get_lang($row['title']), get_lang($row['comment'])],
1650
                    $courseSelectOptions,
1651
                    ['url' => api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=search_course']
1652
                );
1653
                $default_values[$row['variable']] = $row['selected_value'];
1654
                break;
1655
        }
1656
1657
        switch ($row['variable']) {
1658
            case 'pdf_export_watermark_enable':
1659
                $url = PDF::get_watermark(null);
1660
1661
                if (false != $url) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $url of type string to the boolean false. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
1662
                    $delete_url = '<a href="?delete_watermark">'.get_lang('Remove picture').' '.Display::return_icon('delete.png', get_lang('Remove picture')).'</a>';
1663
                    $form->addElement('html', '<div style="max-height:100px; max-width:100px; margin-left:162px; margin-bottom:10px; clear:both;"><img src="'.$url.'" style="margin-bottom:10px;" />'.$delete_url.'</div>');
1664
                }
1665
1666
                $form->addElement('file', 'pdf_export_watermark_path', get_lang('Upload a watermark image'));
1667
                $allowed_picture_types = ['jpg', 'jpeg', 'png', 'gif'];
1668
                $form->addRule(
1669
                    'pdf_export_watermark_path',
1670
                    get_lang('Only PNG, JPG or GIF images allowed').' ('.implode(',', $allowed_picture_types).')',
1671
                    'filetype',
1672
                    $allowed_picture_types
1673
                );
1674
1675
                break;
1676
            case 'timezone_value':
1677
                $timezone = $row['selected_value'];
1678
                if (empty($timezone)) {
1679
                    $timezone = api_get_timezone();
1680
                }
1681
                $form->addLabel('', sprintf(get_lang('The local time in the portal timezone (%s) is %s'), $timezone, api_get_local_time()));
1682
                break;
1683
        }
1684
    } // end for
1685
1686
    if (!empty($settings)) {
1687
        $form->setDefaults($default_values);
1688
    }
1689
    $form->addHtml('<div class="bottom_actions">');
1690
    $form->addButtonSave(get_lang('Save settings'));
1691
    $form->addHtml('</div>');
1692
1693
    return $form;
1694
}
1695
1696
/**
1697
 * Searches a platform setting in all categories except from the Plugins category.
1698
 *
1699
 * @param string $search
1700
 *
1701
 * @return array
1702
 */
1703
function searchSetting($search)
1704
{
1705
    if (empty($search)) {
1706
        return [];
1707
    }
1708
    $table_settings_current = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1709
    $sql = "SELECT * FROM $table_settings_current
1710
            WHERE category <> 'Plugins' ORDER BY id ASC ";
1711
    $result = Database::store_result(Database::query($sql), 'ASSOC');
1712
    $settings = [];
1713
1714
    $search = api_strtolower($search);
1715
1716
    if (!empty($result)) {
1717
        foreach ($result as $setting) {
1718
            $found = false;
1719
1720
            $title = api_strtolower(get_lang($setting['title']));
1721
            // try the title
1722
            if (false === strpos($title, $search)) {
1723
                $comment = api_strtolower(get_lang($setting['comment']));
1724
                //Try the comment
1725
                if (false === strpos($comment, $search)) {
1726
                    //Try the variable name
1727
                    if (false === strpos($setting['variable'], $search)) {
1728
                        continue;
1729
                    } else {
1730
                        $found = true;
1731
                    }
1732
                } else {
1733
                    $found = true;
1734
                }
1735
            } else {
1736
                $found = true;
1737
            }
1738
            if ($found) {
1739
                $settings[] = $setting;
1740
            }
1741
        }
1742
    }
1743
1744
    return $settings;
1745
}
1746
/**
1747
 * Helper function to generates a form elements group.
1748
 *
1749
 * @param object $form   The form where the elements group has to be added
1750
 * @param array  $values Values to browse through
1751
 *
1752
 * @return array
1753
 */
1754
function formGenerateElementsGroup($form, $values = [], $elementName)
1755
{
1756
    $group = [];
1757
    if (is_array($values)) {
1758
        foreach ($values as $key => $value) {
1759
            $element = &$form->createElement('radio', $elementName, '', get_lang($value['display_text']), $value['value']);
1760
            $group[] = $element;
1761
        }
1762
    }
1763
1764
    return $group;
1765
}
1766
/**
1767
 * Helper function with allowed file types for CSS.
1768
 *
1769
 * @return array Array of file types (no indexes)
1770
 */
1771
function getAllowedFileTypes()
1772
{
1773
    $allowedFiles = [
1774
        'css',
1775
        'zip',
1776
        'jpeg',
1777
        'jpg',
1778
        'png',
1779
        'gif',
1780
        'ico',
1781
        'psd',
1782
        'xcf',
1783
        'svg',
1784
        'webp',
1785
        'woff',
1786
        'woff2',
1787
    ];
1788
1789
    return $allowedFiles;
1790
}
1791
/**
1792
 * Helper function to set settings in the database.
1793
 *
1794
 * @param array $parameters List of values
1795
 * @param int   $accessUrl  The current access URL
1796
 */
1797
function setConfigurationSettingsInDatabase($parameters, $accessUrl)
1798
{
1799
    api_set_settings_category('Search', 'false', $accessUrl);
1800
    // Save the settings.
1801
    foreach ($parameters as $key => $value) {
1802
        api_set_setting($key, $value, null, null);
1803
    }
1804
}
1805
1806
/**
1807
 * Helper function to show the status of the search settings table.
1808
 *
1809
 * @param array $data Data to show
1810
 */
1811
function showSearchSettingsTable($data)
1812
{
1813
    echo Display::tag('h3', get_lang('Settings'));
1814
    $table = new SortableTableFromArray($data);
1815
    $table->set_header(0, get_lang('Setting'), false);
1816
    $table->set_header(1, get_lang('Status'), false);
1817
    echo $table->display();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $table->display() targeting SortableTable::display() 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...
1818
}
1819
/**
1820
 * Helper function to show status table for each command line tool installed.
1821
 */
1822
function showSearchToolsStatusTable()
1823
{
1824
    //@todo windows support
1825
    if (false == api_is_windows_os()) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1826
        $list_of_programs = ['pdftotext', 'ps2pdf', 'catdoc', 'html2text', 'unrtf', 'catppt', 'xls2csv'];
1827
        foreach ($list_of_programs as $program) {
1828
            $output = [];
1829
            $ret_val = null;
1830
            exec("which $program", $output, $ret_val);
1831
1832
            if (!$output) {
1833
                $output[] = '';
1834
            }
1835
1836
            $icon = Display::return_icon('bullet_red.png', get_lang('Not installed'));
1837
            if (!empty($output[0])) {
1838
                $icon = Display::return_icon('bullet_green.png', get_lang('Installed'));
1839
            }
1840
            $data2[] = [$program, $output[0], $icon];
1841
        }
1842
        echo Display::tag('h3', get_lang('Course Program</a>. If your course has no code, whatever the reason, invent one. For instance <i>INNOVATION</i> if the course is about Innovation Managements needed to convert files'));
1843
        $table = new SortableTableFromArray($data2);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $data2 seems to be defined by a foreach iteration on line 1827. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1844
        $table->set_header(0, get_lang('Course Program</a>. If your course has no code, whatever the reason, invent one. For instance <i>INNOVATION</i> if the course is about Innovation Management'), false);
1845
        $table->set_header(1, get_lang('Path'), false);
1846
        $table->set_header(2, get_lang('Status'), false);
1847
        echo $table->display();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $table->display() targeting SortableTable::display() 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...
1848
    } else {
1849
        echo Display::return_message(
1850
            get_lang('You are using Chamilo in a Windows platform, sadly you can\'t convert documents in order to search the content using this tool'),
1851
            'warning'
1852
        );
1853
    }
1854
}
1855
/**
1856
 * Helper function to generate and show CSS Zip download message.
1857
 *
1858
 * @param string $style Style path
1859
 */
1860
function generateCSSDownloadLink($style)
1861
{
1862
    $arch = api_get_path(SYS_ARCHIVE_PATH).$style.'.zip';
1863
    $themeDir = Template::getThemeDir($style);
1864
    $dir = api_get_path(SYS_CSS_PATH).$themeDir;
1865
    $check = Security::check_abs_path(
1866
        $dir,
1867
        api_get_path(SYS_CSS_PATH).'themes'
1868
    );
1869
    if (is_dir($dir) && $check) {
1870
        $zip = new PclZip($arch);
1871
        // Remove path prefix except the style name and put file on disk
1872
        $zip->create($dir, PCLZIP_OPT_REMOVE_PATH, substr($dir, 0, -strlen($style)));
0 ignored issues
show
Bug introduced by
The constant PCLZIP_OPT_REMOVE_PATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1873
        $url = api_get_path(WEB_CODE_PATH).'course_info/download.php?archive_path=&archive='.str_replace(api_get_path(SYS_ARCHIVE_PATH), '', $arch);
1874
1875
        //@TODO: use more generic script to download.
1876
        $str = '<a class="btn btn-primary btn-large" href="'.$url.'">'.get_lang('Download the file').'</a>';
1877
        echo Display::return_message($str, 'normal', false);
1878
    } else {
1879
        echo Display::return_message(get_lang('The file was not found'), 'warning');
1880
    }
1881
}
1882
1883
/**
1884
 * Helper function to tell if the style is changeable in the current URL.
1885
 *
1886
 * @return bool $changeable Whether the style can be changed in this URL or not
1887
 */
1888
function isStyleChangeable()
1889
{
1890
    $changeable = false;
1891
    $urlId = api_get_current_access_url_id();
1892
    if ($urlId) {
1893
        $style_info = api_get_settings('stylesheets', '', 1, 0);
1894
        $url_info = api_get_access_url($urlId);
1895
        if (1 == $style_info[0]['access_url_changeable'] && 1 == $url_info['active']) {
1896
            $changeable = true;
1897
        }
1898
    } else {
1899
        $changeable = true;
1900
    }
1901
1902
    return $changeable;
1903
}
1904
1905
/**
1906
 * Get all settings of one category prepared for display in admin/settings.php.
1907
 *
1908
 * @param string $category
1909
 *
1910
 * @return array
1911
 */
1912
function getCategorySettings($category = '')
1913
{
1914
    $url_id = api_get_current_access_url_id();
1915
    $settings_by_access_list = [];
1916
1917
    if (1 == $url_id) {
1918
        $settings = api_get_settings($category, 'group', $url_id);
1919
    } else {
1920
        $url_info = api_get_access_url($url_id);
1921
        if (1 == $url_info['active']) {
1922
            $categoryToSearch = $category;
1923
            if ('search_setting' == $category) {
1924
                $categoryToSearch = '';
1925
            }
1926
            // The default settings of Chamilo
1927
            $settings = api_get_settings($categoryToSearch, 'group', 1, 0);
1928
            // The settings that are changeable from a particular site.
1929
            $settings_by_access = api_get_settings($categoryToSearch, 'group', $url_id, 1);
1930
1931
            foreach ($settings_by_access as $row) {
1932
                if (empty($row['variable'])) {
1933
                    $row['variable'] = 0;
1934
                }
1935
                if (empty($row['subkey'])) {
1936
                    $row['subkey'] = 0;
1937
                }
1938
                if (empty($row['category'])) {
1939
                    $row['category'] = 0;
1940
                }
1941
1942
                // One more validation if is changeable.
1943
                if (1 == $row['access_url_changeable']) {
1944
                    $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
1945
                } else {
1946
                    $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = [];
1947
                }
1948
            }
1949
        }
1950
    }
1951
1952
    if (isset($category) && 'search_setting' == $category) {
1953
        if (!empty($_REQUEST['search_field'])) {
1954
            $settings = searchSetting($_REQUEST['search_field']);
1955
        }
1956
    }
1957
1958
    return [
1959
        'settings' => $settings,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $settings does not seem to be defined for all execution paths leading up to this point.
Loading history...
1960
        'settings_by_access_list' => $settings_by_access_list,
1961
    ];
1962
}
1963