Completed
Push — master ( c9546d...95f607 )
by Julito
09:41
created

public/main/admin/settings.lib.php (4 issues)

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(
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']).'">';
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.'">';
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) {
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);
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
    require_once api_get_path(LIBRARY_PATH).'specific_fields_manager.lib.php';
751
    $search_enabled = api_get_setting('search_enabled');
752
753
    $form = new FormValidator(
754
        'search-options',
755
        'post',
756
        api_get_self().'?category=Search'
757
    );
758
    $values = api_get_settings_options('search_enabled');
759
    $form->addElement('header', null, get_lang('Fulltext search'));
760
761
    $group = formGenerateElementsGroup($form, $values, 'search_enabled');
762
763
    // SearchEnabledComment
764
    $form->addGroup(
765
        $group,
766
        'search_enabled',
767
        [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.')],
768
        null,
769
        false
770
    );
771
772
    $search_enabled = api_get_setting('search_enabled');
773
774
    if ($form->validate()) {
775
        $formValues = $form->exportValues();
776
        setConfigurationSettingsInDatabase($formValues, $_configuration['access_url']);
777
        $search_enabled = $formValues['search_enabled'];
778
        echo Display::return_message($SettingsStored, 'confirm');
779
    }
780
    $specific_fields = get_specific_field_list();
781
782
    if ('true' == $search_enabled) {
783
        $values = api_get_settings_options('search_show_unlinked_results');
784
        $group = formGenerateElementsGroup(
785
            $form,
786
            $values,
787
            'search_show_unlinked_results'
788
        );
789
        $form->addGroup(
790
            $group,
791
            'search_show_unlinked_results',
792
            [
793
                get_lang('Full-text search: show unlinked results'),
794
                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?'),
795
            ],
796
            null,
797
            false
798
        );
799
        $default_values['search_show_unlinked_results'] = api_get_setting('search_show_unlinked_results');
800
801
        $sf_values = [];
802
        foreach ($specific_fields as $sf) {
803
            $sf_values[$sf['code']] = $sf['name'];
804
        }
805
        $url = Display::div(
806
            Display::url(
807
                get_lang('Add a specific search field'),
808
                'specific_fields.php'
809
            ),
810
            ['class' => 'sectioncomment']
811
        );
812
        if (empty($sf_values)) {
813
            $form->addElement('label', [get_lang('Specific Field for prefilter'), $url]);
814
        } else {
815
            $form->addElement(
816
                'select',
817
                'search_prefilter_prefix',
818
                [get_lang('Specific Field for prefilter'), $url],
819
                $sf_values,
820
                ''
821
            );
822
            $default_values['search_prefilter_prefix'] = api_get_setting('search_prefilter_prefix');
823
        }
824
    }
825
826
    $default_values['search_enabled'] = $search_enabled;
827
828
    $form->addButtonSave(get_lang('Save'));
829
    $form->setDefaults($default_values);
830
831
    echo '<div id="search-options-form">';
832
    $form->display();
833
    echo '</div>';
834
835
    if ('true' == $search_enabled) {
836
        $xapianPath = api_get_path(SYS_UPLOAD_PATH).'plugins/xapian/searchdb';
837
838
        /*
839
        @todo Test the Xapian connection
840
        if (extension_loaded('xapian')) {
841
            require_once 'xapian.php';
842
            try {
843
                $db = new XapianDatabase($xapianPath.'/');
844
            } catch (Exception $e) {
845
                var_dump($e->getMessage());
846
            }
847
848
            require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
849
            require_once api_get_path(LIBRARY_PATH) . 'search/IndexableChunk.class.php';
850
            require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
851
852
            $indexable = new IndexableChunk();
853
            $indexable->addValue("content", 'Test');
854
855
            $di = new ChamiloIndexer();
856
            $di->connectDb(NULL, NULL, 'english');
857
            $di->addChunk($indexable);
858
            $did = $di->index();
859
        }
860
        */
861
862
        $xapianLoaded = Display::return_icon('bullet_green.png', get_lang('Validate'));
863
        $dir_exists = Display::return_icon('bullet_green.png', get_lang('Validate'));
864
        $dir_is_writable = Display::return_icon('bullet_green.png', get_lang('Validate'));
865
        $specific_fields_exists = Display::return_icon('bullet_green.png', get_lang('Validate'));
866
867
        //Testing specific fields
868
        if (empty($specific_fields)) {
869
            $specific_fields_exists = Display::return_icon(
870
                'bullet_red.png',
871
                get_lang('Add a specific search field')
872
            );
873
        }
874
        //Testing xapian extension
875
        if (!extension_loaded('xapian')) {
876
            $xapianLoaded = Display::return_icon('bullet_red.png', get_lang('Error'));
877
        }
878
        //Testing xapian searchdb path
879
        if (!is_dir($xapianPath)) {
880
            $dir_exists = Display::return_icon('bullet_red.png', get_lang('Error'));
881
        }
882
        //Testing xapian searchdb path is writable
883
        if (!is_writable($xapianPath)) {
884
            $dir_is_writable = Display::return_icon('bullet_red.png', get_lang('Error'));
885
        }
886
887
        $data = [];
888
        $data[] = [get_lang('Xapian module installed'), $xapianLoaded];
889
        $data[] = [get_lang('The directory exists').' - '.$xapianPath, $dir_exists];
890
        $data[] = [get_lang('Is writable').' - '.$xapianPath, $dir_is_writable];
891
        $data[] = [get_lang('Available custom search fields'), $specific_fields_exists];
892
893
        showSearchSettingsTable($data);
894
        showSearchToolsStatusTable();
895
    }
896
}
897
898
/**
899
 * Wrapper for the templates.
900
 *
901
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
902
 * @author Julio Montoya.
903
 *
904
 * @version August 2008
905
 *
906
 * @since v1.8.6
907
 */
908
function handleTemplates()
909
{
910
    /* Drive-by fix to avoid undefined var warnings, without repeating
911
     * isset() combos all over the place. */
912
    $action = isset($_GET['action']) ? $_GET['action'] : "invalid";
913
914
    if ('add' != $action) {
915
        echo '<div class="actions" style="margin-left: 1px;">';
916
        echo '<a href="settings.php?category=Templates&action=add">'.
917
                Display::return_icon('new_template.png', get_lang('Add a template'), '', ICON_SIZE_MEDIUM).'</a>';
918
        echo '</div>';
919
    }
920
921
    if ('add' == $action || ('edit' == $action && is_numeric($_GET['id']))) {
922
        addEditTemplate();
923
924
        // Add event to the system log.
925
        $user_id = api_get_user_id();
926
        $category = $_GET['category'];
927
        Event::addEvent(
928
            LOG_CONFIGURATION_SETTINGS_CHANGE,
929
            LOG_CONFIGURATION_SETTINGS_CATEGORY,
930
            $category,
931
            api_get_utc_datetime(),
932
            $user_id
933
        );
934
    } else {
935
        if ('delete' == $action && is_numeric($_GET['id'])) {
936
            deleteTemplate($_GET['id']);
937
938
            // Add event to the system log
939
            $user_id = api_get_user_id();
940
            $category = $_GET['category'];
941
            Event::addEvent(
942
                LOG_CONFIGURATION_SETTINGS_CHANGE,
943
                LOG_CONFIGURATION_SETTINGS_CATEGORY,
944
                $category,
945
                api_get_utc_datetime(),
946
                $user_id
947
            );
948
        }
949
        displayTemplates();
950
    }
951
}
952
953
/**
954
 * Display a sortable table with all the templates that the platform administrator has defined.
955
 *
956
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
957
 *
958
 * @version August 2008
959
 *
960
 * @since v1.8.6
961
 */
962
function displayTemplates()
963
{
964
    $table = new SortableTable(
965
        'templates',
966
        'getNumberOfTemplates',
967
        'getTemplateData',
968
        1
969
    );
970
    $table->set_additional_parameters(
971
        ['category' => Security::remove_XSS($_GET['category'])]
972
    );
973
    $table->set_header(0, get_lang('Image'), true, ['style' => 'width: 101px;']);
974
    $table->set_header(1, get_lang('Title'));
975
    $table->set_header(2, get_lang('Detail'), false, ['style' => 'width:50px;']);
976
    $table->set_column_filter(2, 'actionsFilter');
977
    $table->set_column_filter(0, 'searchImageFilter');
978
    $table->display();
979
}
980
981
/**
982
 * Gets the number of templates that are defined by the platform admin.
983
 *
984
 * @return int
985
 *
986
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
987
 *
988
 * @version August 2008
989
 *
990
 * @since v1.8.6
991
 */
992
function getNumberOfTemplates()
993
{
994
    // Database table definition.
995
    $table = Database::get_main_table('system_template');
996
997
    // The sql statement.
998
    $sql = "SELECT COUNT(id) AS total FROM $table";
999
    $result = Database::query($sql);
1000
    $row = Database::fetch_array($result);
1001
1002
    // Returning the number of templates.
1003
    return $row['total'];
1004
}
1005
1006
/**
1007
 * Gets all the template data for the sortable table.
1008
 *
1009
 * @param int    $from            the start of the limit statement
1010
 * @param int    $number_of_items the number of elements that have to be retrieved from the database
1011
 * @param int    $column          the column that is
1012
 * @param string $direction       the sorting direction (ASC or DESC)
1013
 *
1014
 * @return array
1015
 *
1016
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1017
 *
1018
 * @version August 2008
1019
 *
1020
 * @since v1.8.6
1021
 */
1022
function getTemplateData($from, $number_of_items, $column, $direction)
1023
{
1024
    // Database table definition.
1025
    $table_system_template = Database::get_main_table('system_template');
1026
1027
    // The sql statement.
1028
    $sql = "SELECT image as col0, title as col1, id as col2 FROM $table_system_template";
1029
    $sql .= " ORDER BY col$column $direction ";
1030
    $sql .= " LIMIT $from,$number_of_items";
1031
    $result = Database::query($sql);
1032
    $return = [];
1033
    while ($row = Database::fetch_array($result)) {
1034
        $row['1'] = get_lang($row['1']);
1035
        $return[] = $row;
1036
    }
1037
    // Returning all the information for the sortable table.
1038
    return $return;
1039
}
1040
1041
/**
1042
 * display the edit and delete icons in the sortable table.
1043
 *
1044
 * @param int $id the id of the template
1045
 *
1046
 * @return string code for the link to edit and delete the template
1047
 *
1048
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1049
 *
1050
 * @version August 2008
1051
 *
1052
 * @since v1.8.6
1053
 */
1054
function actionsFilter($id)
1055
{
1056
    $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>';
1057
    $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>';
1058
1059
    return $return;
1060
}
1061
1062
/**
1063
 * Display the image of the template in the sortable table.
1064
 *
1065
 * @param string $image the image
1066
 *
1067
 * @return string code for the image
1068
 *
1069
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1070
 *
1071
 * @version August 2008
1072
 *
1073
 * @since v1.8.6
1074
 */
1075
function searchImageFilter($image)
1076
{
1077
    if (!empty($image)) {
1078
        return '<img src="'.api_get_path(WEB_PUBLIC_PATH).'img/template_thumb/'.$image.'" alt="'.get_lang('Template preview').'"/>';
1079
    } else {
1080
        return '<img src="'.api_get_path(WEB_PUBLIC_PATH).'img/template_thumb/noimage.gif" alt="'.get_lang('NoTemplate preview').'"/>';
1081
    }
1082
}
1083
1084
/**
1085
 * Add (or edit) a template. This function displays the form and also takes
1086
 * care of uploading the image and storing the information in the database.
1087
 *
1088
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1089
 *
1090
 * @version August 2008
1091
 *
1092
 * @since v1.8.6
1093
 */
1094
function addEditTemplate()
1095
{
1096
    $em = Database::getManager();
1097
    $id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
1098
1099
    /** @var SystemTemplate $template */
1100
    $template = $id ? $em->find('ChamiloCoreBundle:SystemTemplate', $id) : new SystemTemplate();
1101
1102
    $form = new FormValidator(
1103
        'template',
1104
        'post',
1105
        'settings.php?category=Templates&action='.Security::remove_XSS($_GET['action']).'&id='.$id
1106
    );
1107
1108
    // Setting the form elements: the header.
1109
    if ('add' == $_GET['action']) {
1110
        $title = get_lang('Add a template');
1111
    } else {
1112
        $title = get_lang('Template edition');
1113
    }
1114
    $form->addElement('header', '', $title);
1115
1116
    // Setting the form elements: the title of the template.
1117
    $form->addText('title', get_lang('Title'), false);
1118
    $form->addText('comment', get_lang('Description'), false);
1119
1120
    // Setting the form elements: the content of the template (wysiwyg editor).
1121
    $form->addHtmlEditor(
1122
        'template_text',
1123
        get_lang('Text'),
1124
        true,
1125
        true,
1126
        ['ToolbarSet' => 'Documents', 'Width' => '100%', 'Height' => '400']
1127
    );
1128
1129
    // Setting the form elements: the form to upload an image to be used with the template.
1130
    if (empty($template->getImage())) {
1131
        $form->addElement('file', 'template_image', get_lang('Image'), '');
1132
    }
1133
1134
    // Setting the form elements: a little bit information about the template image.
1135
    $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'));
1136
1137
    // Getting all the information of the template when editing a template.
1138
    if ('edit' == $_GET['action']) {
1139
        $defaults['template_id'] = $id;
1140
        $defaults['template_text'] = $template->getContent();
1141
        // Forcing get_lang().
1142
        $defaults['title'] = $template->getTitle();
1143
        $defaults['comment'] = $template->getComment();
1144
1145
        // Adding an extra field: a hidden field with the id of the template we are editing.
1146
        $form->addElement('hidden', 'template_id');
1147
1148
        // Adding an extra field: a preview of the image that is currently used.
1149
1150
        if (!empty($template->getImage())) {
1151
            $form->addElement(
1152
                'static',
1153
                'template_image_preview',
1154
                '',
1155
                '<img src="'.api_get_path(WEB_PUBLIC_PATH).'img/template_thumb/'.$template->getImage()
1156
                    .'" alt="'.get_lang('Template preview')
1157
                    .'"/>'
1158
            );
1159
            $form->addCheckBox('delete_image', null, get_lang('Delete picture'));
1160
        } else {
1161
            $form->addElement(
1162
                'static',
1163
                'template_image_preview',
1164
                '',
1165
                '<img src="'.api_get_path(WEB_PUBLIC_PATH).'img/template_thumb/noimage.gif" alt="'.get_lang('NoTemplate preview').'"/>'
1166
            );
1167
        }
1168
1169
        // Setting the information of the template that we are editing.
1170
        $form->setDefaults($defaults);
1171
    }
1172
    // Setting the form elements: the submit button.
1173
    $form->addButtonSave(get_lang('Validate'), 'submit');
1174
1175
    // Setting the rules: the required fields.
1176
    if (empty($template->getImage())) {
1177
        $form->addRule(
1178
            'template_image',
1179
            get_lang('Required field'),
1180
            'required'
1181
        );
1182
        $form->addRule('title', get_lang('Required field'), 'required');
1183
    }
1184
1185
    // if the form validates (complies to all rules) we save the information,
1186
    // else we display the form again (with error message if needed)
1187
    if ($form->validate()) {
1188
        $check = Security::check_token('post');
1189
1190
        if ($check) {
1191
            // Exporting the values.
1192
            $values = $form->exportValues();
1193
            $isDelete = null;
1194
            if (isset($values['delete_image'])) {
1195
                $isDelete = $values['delete_image'];
1196
            }
1197
1198
            // Upload the file.
1199
            if (!empty($_FILES['template_image']['name'])) {
1200
                $upload_ok = process_uploaded_file($_FILES['template_image']);
1201
1202
                if ($upload_ok) {
1203
                    // Try to add an extension to the file if it hasn't one.
1204
                    $new_file_name = add_ext_on_mime(stripslashes($_FILES['template_image']['name']), $_FILES['template_image']['type']);
1205
1206
                    // The upload directory.
1207
                    // todo
1208
1209
                    $upload_dir = api_get_path(SYS_PATH).'home/default_platform_document/template_thumb/';
1210
1211
                    // Create the directory if it does not exist.
1212
                    if (!is_dir($upload_dir)) {
1213
                        mkdir($upload_dir, api_get_permissions_for_new_directories());
1214
                    }
1215
1216
                    // Resize the preview image to max default and upload.
1217
                    $temp = new Image($_FILES['template_image']['tmp_name']);
1218
                    $picture_info = $temp->get_image_info();
1219
1220
                    $max_width_for_picture = 100;
1221
                    if ($picture_info['width'] > $max_width_for_picture) {
1222
                        $temp->resize($max_width_for_picture);
1223
                    }
1224
                    $temp->send_image($upload_dir.$new_file_name);
1225
                }
1226
            }
1227
1228
            // Store the information in the database (as insert or as update).
1229
            $bootstrap = api_get_bootstrap_and_font_awesome();
1230
            $viewport = '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
1231
1232
            if ('add' == $_GET['action']) {
1233
                $templateContent = '<head>'.$viewport.'<title>'.$values['title'].'</title>'.$bootstrap.'</head>'
1234
                    .$values['template_text'];
1235
                $template
1236
                    ->setTitle($values['title'])
1237
                    ->setComment(Security::remove_XSS($values['comment']))
1238
                    ->setContent(Security::remove_XSS($templateContent, COURSEMANAGERLOWSECURITY))
1239
                    ->setImage($new_file_name);
1240
                $em->persist($template);
1241
                $em->flush();
1242
1243
                // Display a feedback message.
1244
                echo Display::return_message(
1245
                    get_lang('Template added'),
1246
                    'confirm'
1247
                );
1248
                echo '<a href="settings.php?category=Templates&action=add">'.
1249
                    Display::return_icon('new_template.png', get_lang('Add a template'), '', ICON_SIZE_MEDIUM).
1250
                    '</a>';
1251
            } else {
1252
                $templateContent = '<head>'.$viewport.'<title>'.$values['title'].'</title>'.$bootstrap.'</head>'
1253
                    .$values['template_text'];
1254
1255
                $template
1256
                    ->setTitle($values['title'])
1257
                    ->setContent(Security::remove_XSS($templateContent, COURSEMANAGERLOWSECURITY));
1258
1259
                if (!empty($new_file_name)) {
1260
                    $template->setImage($new_file_name);
1261
                }
1262
1263
                $em->persist($template);
1264
                $em->flush();
1265
1266
                // Display a feedback message.
1267
                echo Display::return_message(get_lang('Template edited'), 'confirm');
1268
            }
1269
        }
1270
        Security::clear_token();
1271
        displayTemplates();
1272
    } else {
1273
        $token = Security::get_token();
1274
        $form->addElement('hidden', 'sec_token');
1275
        $form->setConstants(['sec_token' => $token]);
1276
        // Display the form.
1277
        $form->display();
1278
    }
1279
}
1280
1281
/**
1282
 * Delete a template.
1283
 *
1284
 * @param int $id the id of the template that has to be deleted
1285
 *
1286
 * @author Patrick Cool <[email protected]>, Ghent University, Belgium
1287
 *
1288
 * @version August 2008
1289
 *
1290
 * @since v1.8.6
1291
 */
1292
function deleteTemplate($id)
1293
{
1294
    $id = intval($id);
1295
    // First we remove the image.
1296
    $table = Database::get_main_table('system_template');
1297
    $sql = "SELECT * FROM $table WHERE id = $id";
1298
    $result = Database::query($sql);
1299
    $row = Database::fetch_array($result);
1300
    if (!empty($row['image'])) {
1301
        @unlink(api_get_path(SYS_APP_PATH).'home/default_platform_document/template_thumb/'.$row['image']);
1302
    }
1303
1304
    // Now we remove it from the database.
1305
    $sql = "DELETE FROM $table WHERE id = $id";
1306
    Database::query($sql);
1307
1308
    // Display a feedback message.
1309
    echo Display::return_message(get_lang('Template deleted'), 'confirm');
1310
}
1311
1312
/**
1313
 * Returns the list of timezone identifiers used to populate the select
1314
 * This function is called through a call_user_func() in the generate_settings_form function.
1315
 *
1316
 * @return array List of timezone identifiers
1317
 *
1318
 * @author Guillaume Viguier <[email protected]>
1319
 *
1320
 * @since Chamilo 1.8.7
1321
 */
1322
function select_timezone_value()
1323
{
1324
    return api_get_timezones();
1325
}
1326
1327
/**
1328
 * Returns an array containing the list of options used to populate the gradebook_number_decimals variable
1329
 * This function is called through a call_user_func() in the generate_settings_form function.
1330
 *
1331
 * @return array List of gradebook_number_decimals options
1332
 *
1333
 * @author Guillaume Viguier <[email protected]>
1334
 */
1335
function select_gradebook_number_decimals()
1336
{
1337
    return ['0', '1', '2'];
1338
}
1339
1340
/**
1341
 * Get the options for a select element to select gradebook default grade model.
1342
 *
1343
 * @return array
1344
 */
1345
function select_gradebook_default_grade_model_id()
1346
{
1347
    $grade_model = new GradeModel();
1348
    $models = $grade_model->get_all();
1349
    $options = [];
1350
    $options[-1] = get_lang('none');
1351
1352
    if (!empty($models)) {
1353
        foreach ($models as $model) {
1354
            $options[$model['id']] = $model['name'];
1355
        }
1356
    }
1357
1358
    return $options;
1359
}
1360
1361
/**
1362
 * @param array $settings
1363
 * @param array $settings_by_access_list
1364
 *
1365
 * @throws \Doctrine\ORM\ORMException
1366
 * @throws \Doctrine\ORM\OptimisticLockException
1367
 * @throws \Doctrine\ORM\TransactionRequiredException
1368
 *
1369
 * @return FormValidator
1370
 */
1371
function generateSettingsForm($settings, $settings_by_access_list)
1372
{
1373
    global $_configuration, $settings_to_avoid, $convert_byte_to_mega_list;
1374
    $em = Database::getManager();
1375
    $table_settings_current = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1376
1377
    $form = new FormValidator(
1378
        'settings',
1379
        'post',
1380
        'settings.php?category='.Security::remove_XSS($_GET['category'])
1381
    );
1382
1383
    $form->addElement(
1384
        'hidden',
1385
        'search_field',
1386
        (!empty($_GET['search_field']) ? Security::remove_XSS($_GET['search_field']) : null)
1387
    );
1388
1389
    $url_id = api_get_current_access_url_id();
1390
    /*
1391
    if (!empty($_configuration['multiple_access_urls']) && api_is_global_platform_admin() && $url_id == 1) {
1392
        $group = array();
1393
        $group[] = $form->createElement('button', 'mark_all', get_lang('Select all'));
1394
        $group[] = $form->createElement('button', 'unmark_all', get_lang('Unselect all'));
1395
        $form->addGroup($group, 'buttons_in_action_right');
1396
    }*/
1397
1398
    $default_values = [];
1399
    $url_info = api_get_access_url($url_id);
1400
    $i = 0;
1401
    $addedSettings = [];
1402
    foreach ($settings as $row) {
1403
        if (in_array($row['variable'], array_keys($settings_to_avoid))) {
1404
            continue;
1405
        }
1406
1407
        if (in_array($row['variable'], $addedSettings)) {
1408
            continue;
1409
        }
1410
1411
        $addedSettings[] = $row['variable'];
1412
1413
        if (!empty($_configuration['multiple_access_urls'])) {
1414
            if (api_is_global_platform_admin()) {
1415
                if (0 == $row['access_url_locked']) {
1416
                    if (1 == $url_id) {
1417
                        if ('1' == $row['access_url_changeable']) {
1418
                            $form->addElement(
1419
                                'html',
1420
                                '<div class="float-right"><a class="share_this_setting" data_status = "0"  data_to_send = "'.$row['variable'].'" href="javascript:void(0);">'.
1421
                                Display::return_icon('shared_setting.png', get_lang('Change setting visibility for the other portals'), null, ICON_SIZE_MEDIUM).'</a></div>'
1422
                            );
1423
                        } else {
1424
                            $form->addElement(
1425
                                'html',
1426
                                '<div class="float-right"><a class="share_this_setting" data_status = "1" data_to_send = "'.$row['variable'].'" href="javascript:void(0);">'.
1427
                                Display::return_icon('shared_setting_na.png', get_lang('Change setting visibility for the other portals'), null, ICON_SIZE_MEDIUM).'</a></div>'
1428
                            );
1429
                        }
1430
                    } else {
1431
                        if ('1' == $row['access_url_changeable']) {
1432
                            $form->addElement(
1433
                                'html',
1434
                                '<div class="float-right">'.
1435
                                Display::return_icon('shared_setting.png', get_lang('Change setting visibility for the other portals'), null, ICON_SIZE_MEDIUM).'</div>'
1436
                            );
1437
                        } else {
1438
                            $form->addElement(
1439
                                'html',
1440
                                '<div class="float-right">'.
1441
                                Display::return_icon('shared_setting_na.png', get_lang('Change setting visibility for the other portals'), null, ICON_SIZE_MEDIUM).'</div>'
1442
                            );
1443
                        }
1444
                    }
1445
                }
1446
            }
1447
        }
1448
1449
        $hideme = [];
1450
        $hide_element = false;
1451
1452
        if (1 != $_configuration['access_url']) {
1453
            if (0 == $row['access_url_changeable']) {
1454
                // We hide the element in other cases (checkbox, radiobutton) we 'freeze' the element.
1455
                $hide_element = true;
1456
                $hideme = ['disabled'];
1457
            } elseif (1 == $url_info['active']) {
1458
                // We show the elements.
1459
                if (empty($row['variable'])) {
1460
                    $row['variable'] = 0;
1461
                }
1462
                if (empty($row['subkey'])) {
1463
                    $row['subkey'] = 0;
1464
                }
1465
                if (empty($row['category'])) {
1466
                    $row['category'] = 0;
1467
                }
1468
                if (isset($settings_by_access_list[$row['variable']]) &&
1469
                    isset($settings_by_access_list[$row['variable']][$row['subkey']]) &&
1470
                    is_array($settings_by_access_list[$row['variable']][$row['subkey']][$row['category']])
1471
                ) {
1472
                    // We are sure that the other site have a selected value.
1473
                    if ('' != $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']]['selected_value']) {
1474
                        $row['selected_value'] = $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']]['selected_value'];
1475
                    }
1476
                }
1477
                // There is no else{} statement because we load the default $row['selected_value'] of the main Chamilo site.
1478
            }
1479
        }
1480
1481
        switch ($row['type']) {
1482
            case 'textfield':
1483
                if (in_array($row['variable'], $convert_byte_to_mega_list)) {
1484
                    $form->addElement(
1485
                        'text',
1486
                        $row['variable'],
1487
                        [
1488
                            get_lang($row['title']),
1489
                            get_lang($row['comment']),
1490
                            get_lang('MB'),
1491
                        ],
1492
                        ['maxlength' => '8', 'aria-label' => get_lang($row['title'])]
1493
                    );
1494
                    $form->applyFilter($row['variable'], 'html_filter');
1495
                    $default_values[$row['variable']] = round($row['selected_value'] / 1024 / 1024, 1);
1496
                } elseif ('account_valid_duration' == $row['variable']) {
1497
                    $form->addElement(
1498
                        'text',
1499
                        $row['variable'],
1500
                        [
1501
                            get_lang($row['title']),
1502
                            get_lang($row['comment']),
1503
                        ],
1504
                        ['maxlength' => '5', 'aria-label' => get_lang($row['title'])]
1505
                    );
1506
                    $form->applyFilter($row['variable'], 'html_filter');
1507
1508
                    // For platform character set selection:
1509
                    // Conversion of the textfield to a select box with valid values.
1510
                    $default_values[$row['variable']] = $row['selected_value'];
1511
                } elseif ('platform_charset' == $row['variable']) {
1512
                    break;
1513
                } else {
1514
                    $hideme['class'] = 'col-md-4';
1515
                    $hideme['aria-label'] = get_lang($row['title']);
1516
                    $form->addElement(
1517
                        'text',
1518
                        $row['variable'],
1519
                        [
1520
                            get_lang($row['title']),
1521
                            get_lang($row['comment']),
1522
                        ],
1523
                        $hideme
1524
                    );
1525
                    $form->applyFilter($row['variable'], 'html_filter');
1526
                    $default_values[$row['variable']] = $row['selected_value'];
1527
                }
1528
                break;
1529
            case 'textarea':
1530
                if ('header_extra_content' == $row['variable']) {
1531
                    $file = api_get_home_path().'header_extra_content.txt';
1532
                    $value = '';
1533
                    if (file_exists($file)) {
1534
                        $value = file_get_contents($file);
1535
                    }
1536
                    $form->addElement(
1537
                        'textarea',
1538
                        $row['variable'],
1539
                        [get_lang($row['title']), get_lang($row['comment'])],
1540
                        ['rows' => '10', 'id' => $row['variable']],
1541
                        $hideme
1542
                    );
1543
                    $default_values[$row['variable']] = $value;
1544
                } elseif ('footer_extra_content' == $row['variable']) {
1545
                    $file = api_get_home_path().'footer_extra_content.txt';
1546
                    $value = '';
1547
                    if (file_exists($file)) {
1548
                        $value = file_get_contents($file);
1549
                    }
1550
                    $form->addElement(
1551
                        'textarea',
1552
                        $row['variable'],
1553
                        [get_lang($row['title']), get_lang($row['comment'])],
1554
                        ['rows' => '10', 'id' => $row['variable']],
1555
                        $hideme
1556
                    );
1557
                    $default_values[$row['variable']] = $value;
1558
                } else {
1559
                    $form->addElement(
1560
                        'textarea',
1561
                        $row['variable'],
1562
                        [get_lang($row['title']),
1563
                        get_lang($row['comment']), ],
1564
                        ['rows' => '10', 'id' => $row['variable']],
1565
                        $hideme
1566
                    );
1567
                    $default_values[$row['variable']] = $row['selected_value'];
1568
                }
1569
                break;
1570
            case 'radio':
1571
                $values = api_get_settings_options($row['variable']);
1572
                $group = [];
1573
                if (is_array($values)) {
1574
                    foreach ($values as $key => $value) {
1575
                        $element = &$form->createElement(
1576
                            'radio',
1577
                            $row['variable'],
1578
                            '',
1579
                            get_lang($value['display_text']),
1580
                            $value['value']
1581
                        );
1582
                        if ($hide_element) {
1583
                            $element->freeze();
1584
                        }
1585
                        $group[] = $element;
1586
                    }
1587
                }
1588
                $form->addGroup(
1589
                    $group,
1590
                    $row['variable'],
1591
                    [get_lang($row['title']), get_lang($row['comment'])],
1592
                    null,
1593
                    false
1594
                );
1595
                $default_values[$row['variable']] = $row['selected_value'];
1596
                break;
1597
            case 'checkbox':
1598
                // 1. We collect all the options of this variable.
1599
                $sql = "SELECT * FROM $table_settings_current
1600
                        WHERE variable='".$row['variable']."' AND access_url =  1";
1601
1602
                $result = Database::query($sql);
1603
                $group = [];
1604
                while ($rowkeys = Database::fetch_array($result)) {
1605
                    // Profile tab option should be hidden when the social tool is enabled.
1606
                    if ('true' == api_get_setting('allow_social_tool')) {
1607
                        if ('show_tabs' === $rowkeys['variable'] && 'my_profile' === $rowkeys['subkey']) {
1608
                            continue;
1609
                        }
1610
                    }
1611
1612
                    // Hiding the gradebook option.
1613
                    if ('show_tabs' === $rowkeys['variable'] && 'my_gradebook' === $rowkeys['subkey']) {
1614
                        continue;
1615
                    }
1616
1617
                    $element = &$form->createElement(
1618
                        'checkbox',
1619
                        $rowkeys['subkey'],
1620
                        '',
1621
                        get_lang($rowkeys['subkeytext'])
1622
                    );
1623
1624
                    if (1 == $row['access_url_changeable']) {
1625
                        // 2. We look into the DB if there is a setting for a specific access_url.
1626
                        $access_url = $_configuration['access_url'];
1627
                        if (empty($access_url)) {
1628
                            $access_url = 1;
1629
                        }
1630
                        $sql = "SELECT selected_value FROM $table_settings_current
1631
                                WHERE
1632
                                    variable='".$rowkeys['variable']."' AND
1633
                                    subkey='".$rowkeys['subkey']."' AND
1634
                                    subkeytext='".$rowkeys['subkeytext']."' AND
1635
                                    access_url =  $access_url";
1636
                        $result_access = Database::query($sql);
1637
                        $row_access = Database::fetch_array($result_access);
1638
                        if ('true' === $row_access['selected_value'] && !$form->isSubmitted()) {
1639
                            $element->setChecked(true);
1640
                        }
1641
                    } else {
1642
                        if ('true' === $rowkeys['selected_value'] && !$form->isSubmitted()) {
1643
                            $element->setChecked(true);
1644
                        }
1645
                    }
1646
                    if ($hide_element) {
1647
                        $element->freeze();
1648
                    }
1649
                    $group[] = $element;
1650
                }
1651
                $form->addGroup(
1652
                    $group,
1653
                    $row['variable'],
1654
                    [get_lang($row['title']), get_lang($row['comment'])],
1655
                    null
1656
                );
1657
                break;
1658
            case 'link':
1659
                $form->addElement(
1660
                    'static',
1661
                    null,
1662
                    [get_lang($row['title']), get_lang($row['comment'])],
1663
                    get_lang('current value').' : '.$row['selected_value'],
1664
                    $hideme
1665
                );
1666
                break;
1667
            case 'select':
1668
                /*
1669
                * 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.
1670
                * The functions being called must be added to the file settings.lib.php.
1671
                */
1672
                $form->addElement(
1673
                    'select',
1674
                    $row['variable'],
1675
                    [get_lang($row['title']), get_lang($row['comment'])],
1676
                    call_user_func('select_'.$row['variable']),
1677
                    $hideme
1678
                );
1679
                $default_values[$row['variable']] = $row['selected_value'];
1680
                break;
1681
            case 'custom':
1682
                break;
1683
            case 'select_course':
1684
                $courseSelectOptions = [];
1685
1686
                if (!empty($row['selected_value'])) {
1687
                    $course = $em->find('ChamiloCoreBundle:Course', $row['selected_value']);
1688
1689
                    $courseSelectOptions[$course->getId()] = $course->getTitle();
1690
                }
1691
1692
                $form->addElement(
1693
                    'select_ajax',
1694
                    $row['variable'],
1695
                    [get_lang($row['title']), get_lang($row['comment'])],
1696
                    $courseSelectOptions,
1697
                    ['url' => api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=search_course']
1698
                );
1699
                $default_values[$row['variable']] = $row['selected_value'];
1700
                break;
1701
        }
1702
1703
        switch ($row['variable']) {
1704
            case 'pdf_export_watermark_enable':
1705
                $url = PDF::get_watermark(null);
1706
1707
                if (false != $url) {
1708
                    $delete_url = '<a href="?delete_watermark">'.get_lang('Remove picture').' '.Display::return_icon('delete.png', get_lang('Remove picture')).'</a>';
1709
                    $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>');
1710
                }
1711
1712
                $form->addElement('file', 'pdf_export_watermark_path', get_lang('Upload a watermark image'));
1713
                $allowed_picture_types = ['jpg', 'jpeg', 'png', 'gif'];
1714
                $form->addRule(
1715
                    'pdf_export_watermark_path',
1716
                    get_lang('Only PNG, JPG or GIF images allowed').' ('.implode(',', $allowed_picture_types).')',
1717
                    'filetype',
1718
                    $allowed_picture_types
1719
                );
1720
1721
                break;
1722
            case 'timezone_value':
1723
                $timezone = $row['selected_value'];
1724
                if (empty($timezone)) {
1725
                    $timezone = api_get_timezone();
1726
                }
1727
                $form->addLabel('', sprintf(get_lang('The local time in the portal timezone (%s) is %s'), $timezone, api_get_local_time()));
1728
                break;
1729
        }
1730
    } // end for
1731
1732
    if (!empty($settings)) {
1733
        $form->setDefaults($default_values);
1734
    }
1735
    $form->addHtml('<div class="bottom_actions">');
1736
    $form->addButtonSave(get_lang('Save settings'));
1737
    $form->addHtml('</div>');
1738
1739
    return $form;
1740
}
1741
1742
/**
1743
 * Searches a platform setting in all categories except from the Plugins category.
1744
 *
1745
 * @param string $search
1746
 *
1747
 * @return array
1748
 */
1749
function searchSetting($search)
1750
{
1751
    if (empty($search)) {
1752
        return [];
1753
    }
1754
    $table_settings_current = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
1755
    $sql = "SELECT * FROM $table_settings_current
1756
            WHERE category <> 'Plugins' ORDER BY id ASC ";
1757
    $result = Database::store_result(Database::query($sql), 'ASSOC');
1758
    $settings = [];
1759
1760
    $search = api_strtolower($search);
1761
1762
    if (!empty($result)) {
1763
        foreach ($result as $setting) {
1764
            $found = false;
1765
1766
            $title = api_strtolower(get_lang($setting['title']));
1767
            // try the title
1768
            if (false === strpos($title, $search)) {
1769
                $comment = api_strtolower(get_lang($setting['comment']));
1770
                //Try the comment
1771
                if (false === strpos($comment, $search)) {
1772
                    //Try the variable name
1773
                    if (false === strpos($setting['variable'], $search)) {
1774
                        continue;
1775
                    } else {
1776
                        $found = true;
1777
                    }
1778
                } else {
1779
                    $found = true;
1780
                }
1781
            } else {
1782
                $found = true;
1783
            }
1784
            if ($found) {
1785
                $settings[] = $setting;
1786
            }
1787
        }
1788
    }
1789
1790
    return $settings;
1791
}
1792
/**
1793
 * Helper function to generates a form elements group.
1794
 *
1795
 * @param object $form   The form where the elements group has to be added
1796
 * @param array  $values Values to browse through
1797
 *
1798
 * @return array
1799
 */
1800
function formGenerateElementsGroup($form, $values = [], $elementName)
1801
{
1802
    $group = [];
1803
    if (is_array($values)) {
1804
        foreach ($values as $key => $value) {
1805
            $element = &$form->createElement('radio', $elementName, '', get_lang($value['display_text']), $value['value']);
1806
            $group[] = $element;
1807
        }
1808
    }
1809
1810
    return $group;
1811
}
1812
/**
1813
 * Helper function with allowed file types for CSS.
1814
 *
1815
 * @return array Array of file types (no indexes)
1816
 */
1817
function getAllowedFileTypes()
1818
{
1819
    $allowedFiles = [
1820
        'css',
1821
        'zip',
1822
        'jpeg',
1823
        'jpg',
1824
        'png',
1825
        'gif',
1826
        'ico',
1827
        'psd',
1828
        'xcf',
1829
        'svg',
1830
        'webp',
1831
        'woff',
1832
        'woff2',
1833
    ];
1834
1835
    return $allowedFiles;
1836
}
1837
/**
1838
 * Helper function to set settings in the database.
1839
 *
1840
 * @param array $parameters List of values
1841
 * @param int   $accessUrl  The current access URL
1842
 */
1843
function setConfigurationSettingsInDatabase($parameters, $accessUrl)
1844
{
1845
    api_set_settings_category('Search', 'false', $accessUrl);
1846
    // Save the settings.
1847
    foreach ($parameters as $key => $value) {
1848
        api_set_setting($key, $value, null, null);
1849
    }
1850
}
1851
1852
/**
1853
 * Helper function to show the status of the search settings table.
1854
 *
1855
 * @param array $data Data to show
1856
 */
1857
function showSearchSettingsTable($data)
1858
{
1859
    echo Display::tag('h3', get_lang('Settings'));
1860
    $table = new SortableTableFromArray($data);
1861
    $table->set_header(0, get_lang('Setting'), false);
1862
    $table->set_header(1, get_lang('Status'), false);
1863
    echo $table->display();
0 ignored issues
show
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...
1864
}
1865
/**
1866
 * Helper function to show status table for each command line tool installed.
1867
 */
1868
function showSearchToolsStatusTable()
1869
{
1870
    //@todo windows support
1871
    if (false == api_is_windows_os()) {
1872
        $list_of_programs = ['pdftotext', 'ps2pdf', 'catdoc', 'html2text', 'unrtf', 'catppt', 'xls2csv'];
1873
        foreach ($list_of_programs as $program) {
1874
            $output = [];
1875
            $ret_val = null;
1876
            exec("which $program", $output, $ret_val);
1877
1878
            if (!$output) {
1879
                $output[] = '';
1880
            }
1881
1882
            $icon = Display::return_icon('bullet_red.png', get_lang('Not installed'));
1883
            if (!empty($output[0])) {
1884
                $icon = Display::return_icon('bullet_green.png', get_lang('Installed'));
1885
            }
1886
            $data2[] = [$program, $output[0], $icon];
1887
        }
1888
        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'));
1889
        $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 1873. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
1890
        $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);
1891
        $table->set_header(1, get_lang('Path'), false);
1892
        $table->set_header(2, get_lang('Status'), false);
1893
        echo $table->display();
0 ignored issues
show
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...
1894
    } else {
1895
        echo Display::return_message(
1896
            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'),
1897
            'warning'
1898
        );
1899
    }
1900
}
1901
/**
1902
 * Helper function to generate and show CSS Zip download message.
1903
 *
1904
 * @param string $style Style path
1905
 */
1906
function generateCSSDownloadLink($style)
1907
{
1908
    $arch = api_get_path(SYS_ARCHIVE_PATH).$style.'.zip';
1909
    $themeDir = Template::getThemeDir($style);
1910
    $dir = api_get_path(SYS_CSS_PATH).$themeDir;
1911
    $check = Security::check_abs_path(
1912
        $dir,
1913
        api_get_path(SYS_CSS_PATH).'themes'
1914
    );
1915
    if (is_dir($dir) && $check) {
1916
        $zip = new PclZip($arch);
1917
        // Remove path prefix except the style name and put file on disk
1918
        $zip->create($dir, PCLZIP_OPT_REMOVE_PATH, substr($dir, 0, -strlen($style)));
1919
        $url = api_get_path(WEB_CODE_PATH).'course_info/download.php?archive_path=&archive='.str_replace(api_get_path(SYS_ARCHIVE_PATH), '', $arch);
1920
1921
        //@TODO: use more generic script to download.
1922
        $str = '<a class="btn btn-primary btn-large" href="'.$url.'">'.get_lang('Download the file').'</a>';
1923
        echo Display::return_message($str, 'normal', false);
1924
    } else {
1925
        echo Display::return_message(get_lang('The file was not found'), 'warning');
1926
    }
1927
}
1928
1929
/**
1930
 * Helper function to tell if the style is changeable in the current URL.
1931
 *
1932
 * @return bool $changeable Whether the style can be changed in this URL or not
1933
 */
1934
function isStyleChangeable()
1935
{
1936
    $changeable = false;
1937
    $urlId = api_get_current_access_url_id();
1938
    if ($urlId) {
1939
        $style_info = api_get_settings('stylesheets', '', 1, 0);
1940
        $url_info = api_get_access_url($urlId);
1941
        if (1 == $style_info[0]['access_url_changeable'] && 1 == $url_info['active']) {
1942
            $changeable = true;
1943
        }
1944
    } else {
1945
        $changeable = true;
1946
    }
1947
1948
    return $changeable;
1949
}
1950
1951
/**
1952
 * Get all settings of one category prepared for display in admin/settings.php.
1953
 *
1954
 * @param string $category
1955
 *
1956
 * @return array
1957
 */
1958
function getCategorySettings($category = '')
1959
{
1960
    $url_id = api_get_current_access_url_id();
1961
    $settings_by_access_list = [];
1962
1963
    if (1 == $url_id) {
1964
        $settings = api_get_settings($category, 'group', $url_id);
1965
    } else {
1966
        $url_info = api_get_access_url($url_id);
1967
        if (1 == $url_info['active']) {
1968
            $categoryToSearch = $category;
1969
            if ('search_setting' == $category) {
1970
                $categoryToSearch = '';
1971
            }
1972
            // The default settings of Chamilo
1973
            $settings = api_get_settings($categoryToSearch, 'group', 1, 0);
1974
            // The settings that are changeable from a particular site.
1975
            $settings_by_access = api_get_settings($categoryToSearch, 'group', $url_id, 1);
1976
1977
            foreach ($settings_by_access as $row) {
1978
                if (empty($row['variable'])) {
1979
                    $row['variable'] = 0;
1980
                }
1981
                if (empty($row['subkey'])) {
1982
                    $row['subkey'] = 0;
1983
                }
1984
                if (empty($row['category'])) {
1985
                    $row['category'] = 0;
1986
                }
1987
1988
                // One more validation if is changeable.
1989
                if (1 == $row['access_url_changeable']) {
1990
                    $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = $row;
1991
                } else {
1992
                    $settings_by_access_list[$row['variable']][$row['subkey']][$row['category']] = [];
1993
                }
1994
            }
1995
        }
1996
    }
1997
1998
    if (isset($category) && 'search_setting' == $category) {
1999
        if (!empty($_REQUEST['search_field'])) {
2000
            $settings = searchSetting($_REQUEST['search_field']);
2001
        }
2002
    }
2003
2004
    return [
2005
        '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...
2006
        'settings_by_access_list' => $settings_by_access_list,
2007
    ];
2008
}
2009