Passed
Push — master ( 888f66...5c6945 )
by Angel Fernando Quiroz
08:42 queued 14s
created

Plugin::getFieldNames()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Entity\ResourceLink;
5
use Chamilo\CoreBundle\Entity\Tool;
6
use Chamilo\CoreBundle\Framework\Container;
7
use Chamilo\CourseBundle\Entity\CTool;
8
use Doctrine\ORM\Exception\NotSupported;
9
use Doctrine\ORM\Exception\ORMException;
10
use Doctrine\ORM\OptimisticLockException;
11
12
/**
13
 * Class Plugin
14
 * Base class for plugins.
15
 *
16
 * This class has to be extended by every plugin. It defines basic methods
17
 * to install/uninstall and get information about a plugin
18
 *
19
 * @author    Julio Montoya <[email protected]>
20
 * @author    Yannick Warnier <[email protected]>
21
 * @author    Laurent Opprecht    <[email protected]>
22
 * @copyright 2012 University of Geneva
23
 * @license   GNU General Public License - http://www.gnu.org/copyleft/gpl.html
24
 */
25
class Plugin
26
{
27
    const TAB_FILTER_NO_STUDENT = '::no-student';
28
    const TAB_FILTER_ONLY_STUDENT = '::only-student';
29
    public $isCoursePlugin = false;
30
    public $isAdminPlugin = false;
31
    public $isMailPlugin = false;
32
    // Adds icon in the course home
33
    public $addCourseTool = true;
34
    public $hasPersonalEvents = false;
35
36
    /**
37
     * When creating a new course, these settings are added to the course, in
38
     * the course_info/infocours.php
39
     * To show the plugin course icons you need to add these icons:
40
     * main/img/icons/22/plugin_name.png
41
     * main/img/icons/64/plugin_name.png
42
     * main/img/icons/64/plugin_name_na.png.
43
     *
44
     * @example
45
     * $course_settings = array(
46
    array('name' => 'big_blue_button_welcome_message',  'type' => 'text'),
47
    array('name' => 'big_blue_button_record_and_store', 'type' => 'checkbox')
48
    );
49
     */
50
    public $course_settings = [];
51
    /**
52
     * This indicates whether changing the setting should execute the callback
53
     * function.
54
     */
55
    public $course_settings_callback = false;
56
57
    protected $version = '';
58
    protected $author = '';
59
    protected $fields = [];
60
    private $settings = [];
61
    // Translation strings.
62
    private $strings = null;
63
64
    /**
65
     * Default constructor for the plugin class. By default, it only sets
66
     * a few attributes of the object.
67
     *
68
     * @param string $version  of this plugin
69
     * @param string $author   of this plugin
70
     * @param array  $settings settings to be proposed to configure the plugin
71
     */
72
    protected function __construct($version, $author, $settings = [])
73
    {
74
        $this->version = $version;
75
        $this->author = $author;
76
        $this->fields = $settings;
77
78
        global $language_files;
79
        $language_files[] = 'plugin_'.$this->get_name();
80
    }
81
82
    /**
83
     * Gets an array of information about this plugin (name, version, ...).
84
     *
85
     * @return array Array of information elements about this plugin
86
     */
87
    public function get_info()
88
    {
89
        $pluginRepo = Container::getPluginRepository();
90
91
        $result = [];
92
        $result['obj'] = $this;
93
        $result['title'] = $this->get_title();
94
        $result['comment'] = $this->get_comment();
95
        $result['version'] = $this->get_version();
96
        $result['author'] = $this->get_author();
97
        $result['plugin_class'] = get_class($this);
98
        $result['is_course_plugin'] = $this->isCoursePlugin;
99
        $result['is_admin_plugin'] = $this->isAdminPlugin;
100
        $result['is_mail_plugin'] = $this->isMailPlugin;
101
        $result['entity'] = $pluginRepo->findOneByTitle($this->get_title());
102
103
        if ($form = $this->getSettingsForm()) {
104
            $result['settings_form'] = $form;
105
106
            foreach ($this->fields as $name => $type) {
107
                $value = $this->get($name);
108
109
                if (is_array($type)) {
110
                    $value = $type['options'];
111
                }
112
                $result[$name] = $value;
113
            }
114
        }
115
116
        return $result;
117
    }
118
119
    /**
120
     * Returns the "system" name of the plugin in lowercase letters.
121
     *
122
     * @return string
123
     */
124
    public function get_name()
125
    {
126
        $result = get_class($this);
127
        $result = str_replace('Plugin', '', $result);
128
        $result = strtolower($result);
129
130
        return $result;
131
    }
132
133
    /**
134
     * @return string
135
     */
136
    public function getCamelCaseName()
137
    {
138
        $result = get_class($this);
139
140
        return str_replace('Plugin', '', $result);
141
    }
142
143
    /**
144
     * Returns the title of the plugin.
145
     *
146
     * @return string
147
     */
148
    public function get_title()
149
    {
150
        return $this->get_lang('plugin_title');
151
    }
152
153
    /**
154
     * Returns the description of the plugin.
155
     *
156
     * @return string
157
     */
158
    public function get_comment()
159
    {
160
        return $this->get_lang('plugin_comment');
161
    }
162
163
    /**
164
     * Returns the version of the plugin.
165
     *
166
     * @return string
167
     */
168
    public function get_version()
169
    {
170
        return $this->version;
171
    }
172
173
    /**
174
     * Returns the author of the plugin.
175
     *
176
     * @return string
177
     */
178
    public function get_author()
179
    {
180
        return $this->author;
181
    }
182
183
    /**
184
     * Returns the contents of the CSS defined by the plugin.
185
     *
186
     * @return string
187
     */
188
    public function get_css()
189
    {
190
        $name = $this->get_name();
191
        $path = api_get_path(SYS_PLUGIN_PATH)."$name/resources/$name.css";
192
        if (!is_readable($path)) {
193
            return '';
194
        }
195
        $css = [];
196
        $css[] = file_get_contents($path);
197
        $result = implode($css);
198
199
        return $result;
200
    }
201
202
    /**
203
     * Returns an HTML form (generated by FormValidator) of the plugin settings.
204
     *
205
     * @return FormValidator FormValidator-generated form
206
     */
207
    public function getSettingsForm()
208
    {
209
        $result = new FormValidator($this->get_name());
210
211
        $defaults = [];
212
        $checkboxGroup = [];
213
        $checkboxCollection = [];
214
215
        if ($checkboxNames = array_keys($this->fields, 'checkbox')) {
216
            $pluginInfoCollection = api_get_settings('Plugins');
217
            foreach ($pluginInfoCollection as $pluginInfo) {
218
                if (false !== array_search($pluginInfo['title'], $checkboxNames)) {
219
                    $checkboxCollection[$pluginInfo['title']] = $pluginInfo;
220
                }
221
            }
222
        }
223
224
        foreach ($this->fields as $name => $type) {
225
            $options = null;
226
            if (is_array($type) && isset($type['type']) && 'select' === $type['type']) {
227
                $attributes = isset($type['attributes']) ? $type['attributes'] : [];
228
                if (!empty($type['options']) && isset($type['translate_options']) && $type['translate_options']) {
229
                    foreach ($type['options'] as $key => &$optionName) {
230
                        $optionName = $this->get_lang($optionName);
231
                    }
232
                }
233
                $options = $type['options'];
234
                $type = $type['type'];
235
            }
236
237
            $value = $this->get($name);
238
            $defaults[$name] = $value;
239
            $type = isset($type) ? $type : 'text';
240
241
            $help = null;
242
            if ($this->get_lang_plugin_exists($name.'_help')) {
243
                $help = $this->get_lang($name.'_help');
244
                if ("show_main_menu_tab" === $name) {
245
                    $pluginName = strtolower(str_replace('Plugin', '', get_class($this)));
246
                    $pluginUrl = api_get_path(WEB_PATH)."plugin/$pluginName/index.php";
247
                    $pluginUrl = "<a href=$pluginUrl>$pluginUrl</a>";
248
                    $help = sprintf($help, $pluginUrl);
249
                }
250
            }
251
252
            switch ($type) {
253
                case 'html':
254
                    $result->addHtml($this->get_lang($name));
255
                    break;
256
                case 'wysiwyg':
257
                    $result->addHtmlEditor($name, $this->get_lang($name), false);
258
                    break;
259
                case 'text':
260
                    $result->addElement($type, $name, [$this->get_lang($name), $help]);
261
                    break;
262
                case 'boolean':
263
                    $group = [];
264
                    $group[] = $result->createElement(
265
                        'radio',
266
                        $name,
267
                        '',
268
                        get_lang('Yes'),
269
                        'true'
270
                    );
271
                    $group[] = $result->createElement(
272
                        'radio',
273
                        $name,
274
                        '',
275
                        get_lang('No'),
276
                        'false'
277
                    );
278
                    $result->addGroup($group, null, [$this->get_lang($name), $help]);
279
                    break;
280
                case 'checkbox':
281
                    $selectedValue = null;
282
                    if (isset($checkboxCollection[$name])) {
283
                        if ('true' === $checkboxCollection[$name]['selected_value']) {
284
                            $selectedValue = 'checked';
285
                        }
286
                    }
287
288
                    $element = $result->createElement(
289
                        $type,
290
                        $name,
291
                        '',
292
                        $this->get_lang($name),
293
                        $selectedValue
294
                    );
295
                    $element->_attributes['value'] = 'true';
296
                    $checkboxGroup[] = $element;
297
                    break;
298
                case 'select':
299
                    $result->addElement(
300
                        $type,
301
                        $name,
302
                        [$this->get_lang($name), $help],
303
                        $options,
304
                        $attributes
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $attributes does not seem to be defined for all execution paths leading up to this point.
Loading history...
305
                    );
306
                    break;
307
                case 'user':
308
                    $options = [];
309
                    if (!empty($value)) {
310
                        $userInfo = api_get_user_info($value);
311
                        if ($userInfo) {
312
                            $options[$value] = $userInfo['complete_name'];
313
                        }
314
                    }
315
                    $result->addSelectAjax(
316
                        $name,
317
                        [$this->get_lang($name), $help],
318
                        $options,
319
                        ['url' => api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php?a=get_user_like']
320
                    );
321
                    break;
322
            }
323
        }
324
325
        if (!empty($checkboxGroup)) {
326
            $result->addGroup(
327
                $checkboxGroup,
328
                null,
329
                ['', $help]
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $help seems to be defined by a foreach iteration on line 224. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
330
            );
331
        }
332
        $result->setDefaults($defaults);
333
        $result->addButtonSave($this->get_lang('Save'), 'submit_button');
334
335
        return $result;
336
    }
337
338
    /**
339
     * Returns the value of a given plugin global setting.
340
     *
341
     * @param string $name of the plugin setting
342
     *
343
     * @return string Value of the plugin setting
344
     *
345
     * @throws Exception
346
     */
347
    public function get($name)
348
    {
349
        $settings = $this->get_settings();
350
        foreach ($settings as $setting) {
351
            if (isset($setting[$name])) {
352
                return $setting[$name];
353
            }
354
        }
355
356
        return false;
357
    }
358
359
    /**
360
     * Returns an array with the global settings for this plugin.
361
     *
362
     * @param bool $forceFromDB Optional. Force get settings from the database
363
     *
364
     * @return array Plugin settings as an array
365
     *
366
     * @throws Exception
367
     */
368
    public function get_settings(bool $forceFromDB = false): array
369
    {
370
        $plugin = Container::getPluginRepository()->findOneByTitle($this->get_name());
371
372
        if ($plugin && empty($this->settings) || $forceFromDB) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ($plugin && empty($this-...tings)) || $forceFromDB, Probably Intended Meaning: $plugin && (empty($this-...tings) || $forceFromDB)
Loading history...
373
            $configByUrl = $plugin->getConfigurationsByAccessUrl(
374
                Container::getAccessUrlHelper()->getCurrent()
375
            );
376
377
            $this->settings = $configByUrl?->getConfiguration() ?? [];
378
        }
379
380
        return $this->settings;
381
    }
382
383
    /**
384
     * Tells whether language variables are defined for this plugin or not.
385
     *
386
     * @param string $name System name of the plugin
387
     *
388
     * @return bool True if the plugin has language variables defined, false otherwise
389
     */
390
    public function get_lang_plugin_exists($name)
391
    {
392
        return isset($this->strings[$name]);
393
    }
394
395
    /**
396
     * Hook for the get_lang() function to check for plugin-defined language terms.
397
     *
398
     * @param string $name of the language variable we are looking for
399
     *
400
     * @return string The translated language term of the plugin
401
     */
402
    public function get_lang($name)
403
    {
404
        // Check whether the language strings for the plugin have already been
405
        // loaded. If so, no need to load them again.
406
        if (is_null($this->strings)) {
407
            $language_interface = api_get_language_isocode();
408
            $root = api_get_path(SYS_PLUGIN_PATH);
409
            $plugin_name = $this->get_name();
410
411
            $interfaceLanguageId = api_get_language_id($language_interface);
412
            if (empty($interfaceLanguageId)) {
413
                $language_interface = api_get_setting('platformLanguage');
414
                $interfaceLanguageId = api_get_language_id($language_interface);
415
            }
416
            $interfaceLanguageInfo = api_get_language_info($interfaceLanguageId);
417
            $languageParentId = !empty($interfaceLanguageInfo['parent_id']) ? (int) $interfaceLanguageInfo['parent_id'] : 0;
418
419
            // 1. Loading english if exists
420
            $english_path = $root.$plugin_name."/lang/english.php";
421
422
            if (is_readable($english_path)) {
423
                $strings = [];
424
                include $english_path;
425
                $this->strings = $strings;
426
            }
427
428
            $path = $root.$plugin_name."/lang/$language_interface.php";
429
            // 2. Loading the system language
430
            if (is_readable($path)) {
431
                include $path;
432
                if (!empty($strings)) {
433
                    foreach ($strings as $key => $string) {
434
                        $this->strings[$key] = $string;
435
                    }
436
                }
437
            } elseif ($languageParentId > 0) {
438
                $languageParentInfo = api_get_language_info($languageParentId);
439
                $languageParentFolder = $languageParentInfo['english_name'];
440
441
                $parentPath = "{$root}{$plugin_name}/lang/{$languageParentFolder}.php";
442
                if (is_readable($parentPath)) {
443
                    include $parentPath;
444
                    if (!empty($strings)) {
445
                        foreach ($strings as $key => $string) {
446
                            $this->strings[$key] = $string;
447
                        }
448
                    }
449
                }
450
            }
451
        }
452
        if (isset($this->strings[$name])) {
453
            return $this->strings[$name];
454
        }
455
456
        return get_lang($name);
457
    }
458
459
    /**
460
     * @param string $variable
461
     * @param string $language
462
     *
463
     * @return string
464
     */
465
    public function getLangFromFile($variable, $language)
466
    {
467
        static $langStrings = [];
468
469
        if (empty($langStrings[$language])) {
470
            $root = api_get_path(SYS_PLUGIN_PATH);
471
            $pluginName = $this->get_name();
472
473
            $englishPath = "$root$pluginName/lang/$language.php";
474
475
            if (is_readable($englishPath)) {
476
                $strings = [];
477
                include $englishPath;
478
479
                $langStrings[$language] = $strings;
480
            }
481
        }
482
483
        if (isset($langStrings[$language][$variable])) {
484
            return $langStrings[$language][$variable];
485
        }
486
487
        return $this->get_lang($variable);
488
    }
489
490
    /**
491
     * Caller for the install_course_fields() function.
492
     *
493
     * @param int  $courseId
494
     * @param bool $addToolLink Whether to add a tool link on the course homepage
495
     */
496
    public function course_install($courseId, $addToolLink = true)
497
    {
498
        $this->install_course_fields($courseId, $addToolLink);
499
    }
500
501
    /**
502
     * Add course settings and, if not asked otherwise, add a tool link on the course homepage.
503
     *
504
     * @param int  $courseId      Course integer ID
505
     * @param bool $add_tool_link Whether to add a tool link or not
506
     *                            (some tools might just offer a configuration section and act on the backend)
507
     *
508
     * @return bool|null False on error, null otherwise
509
     */
510
    public function install_course_fields($courseId, $add_tool_link = true)
511
    {
512
        $plugin_name = $this->get_name();
513
        $t_course = Database::get_course_table(TABLE_COURSE_SETTING);
514
        $courseId = (int) $courseId;
515
516
        if (empty($courseId)) {
517
            return false;
518
        }
519
520
        // Adding course settings.
521
        if (!empty($this->course_settings)) {
522
            foreach ($this->course_settings as $setting) {
523
                $variable = $setting['name'];
524
                $value = '';
525
                if (isset($setting['init_value'])) {
526
                    $value = $setting['init_value'];
527
                }
528
529
                $pluginGlobalValue = api_get_plugin_setting($plugin_name, $variable);
530
                if (null !== $pluginGlobalValue) {
531
                    $value = 1;
532
                }
533
534
                $type = 'textfield';
535
                if (isset($setting['type'])) {
536
                    $type = $setting['type'];
537
                }
538
539
                if (isset($setting['group'])) {
540
                    $group = $setting['group'];
541
                    $sql = "SELECT value
542
                            FROM $t_course
543
                            WHERE
544
                                c_id = $courseId AND
545
                                variable = '".Database::escape_string($group)."' AND
546
                                subkey = '".Database::escape_string($variable)."'
547
                            ";
548
                    $result = Database::query($sql);
549
                    if (!Database::num_rows($result)) {
550
                        $params = [
551
                            'c_id' => $courseId,
552
                            'variable' => $group,
553
                            'subkey' => $variable,
554
                            'value' => $value,
555
                            'category' => 'plugins',
556
                            'type' => $type,
557
                            'title' => '',
558
                        ];
559
                        Database::insert($t_course, $params);
560
                    }
561
                } else {
562
                    $sql = "SELECT value FROM $t_course
563
                            WHERE c_id = $courseId AND variable = '$variable' ";
564
                    $result = Database::query($sql);
565
                    if (!Database::num_rows($result)) {
566
                        $params = [
567
                            'c_id' => $courseId,
568
                            'variable' => $variable,
569
                            'subkey' => $plugin_name,
570
                            'value' => $value,
571
                            'category' => 'plugins',
572
                            'type' => $type,
573
                            'title' => '',
574
                        ];
575
                        Database::insert($t_course, $params);
576
                    }
577
                }
578
            }
579
        }
580
581
        // Stop here if we don't want a tool link on the course homepage
582
        if (!$add_tool_link || false == $this->addCourseTool) {
583
            return true;
584
        }
585
586
        // Add an icon in the table tool list
587
        $this->createLinkToCourseTool($plugin_name, $courseId);
588
    }
589
590
    /**
591
     * Delete the fields added to the course settings page and the link to the
592
     * tool on the course's homepage.
593
     *
594
     * @param int $courseId
595
     *
596
     * @return false|null
597
     */
598
    public function uninstall_course_fields($courseId)
599
    {
600
        $courseId = (int) $courseId;
601
602
        if (empty($courseId)) {
603
            return false;
604
        }
605
        $pluginName = $this->get_name();
606
607
        $t_course = Database::get_course_table(TABLE_COURSE_SETTING);
608
        $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
609
610
        if (!empty($this->course_settings)) {
611
            foreach ($this->course_settings as $setting) {
612
                $variable = Database::escape_string($setting['name']);
613
                if (!empty($setting['group'])) {
614
                    $variable = Database::escape_string($setting['group']);
615
                }
616
                if (empty($variable)) {
617
                    continue;
618
                }
619
                $sql = "DELETE FROM $t_course
620
                        WHERE c_id = $courseId AND variable = '$variable'";
621
                Database::query($sql);
622
            }
623
        }
624
625
        $pluginName = Database::escape_string($pluginName);
626
        $sql = "DELETE FROM $t_tool
627
                WHERE c_id = $courseId AND
628
                (
629
                  title = '$pluginName' OR
630
                  title = '$pluginName:student' OR
631
                  title = '$pluginName:teacher'
632
                )";
633
        Database::query($sql);
634
    }
635
636
    /**
637
     * Install the course fields and tool link of this plugin in all courses.
638
     *
639
     * @param bool $add_tool_link Whether we want to add a plugin link on the course homepage
640
     */
641
    public function install_course_fields_in_all_courses($add_tool_link = true)
642
    {
643
        // Update existing courses to add plugin settings
644
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
645
        $sql = "SELECT id FROM $table ORDER BY id";
646
        $res = Database::query($sql);
647
        while ($row = Database::fetch_assoc($res)) {
648
            $this->install_course_fields($row['id'], $add_tool_link);
649
        }
650
    }
651
652
    /**
653
     * Uninstall the plugin settings fields from all courses.
654
     */
655
    public function uninstall_course_fields_in_all_courses()
656
    {
657
        // Update existing courses to add conference settings
658
        $table = Database::get_main_table(TABLE_MAIN_COURSE);
659
        $sql = "SELECT id FROM $table
660
                ORDER BY id";
661
        $res = Database::query($sql);
662
        while ($row = Database::fetch_assoc($res)) {
663
            $this->uninstall_course_fields($row['id']);
664
        }
665
    }
666
667
    /**
668
     * @return array
669
     */
670
    public function getCourseSettings()
671
    {
672
        $settings = [];
673
        if (is_array($this->course_settings)) {
674
            foreach ($this->course_settings as $item) {
675
                // Skip html type
676
                if ('html' === $item['type']) {
677
                    continue;
678
                }
679
                if (isset($item['group'])) {
680
                    if (!in_array($item['group'], $settings)) {
681
                        $settings[] = $item['group'];
682
                    }
683
                } else {
684
                    $settings[] = $item['name'];
685
                }
686
            }
687
        }
688
689
        return $settings;
690
    }
691
692
    /**
693
     * Method to be extended when changing the setting in the course
694
     * configuration should trigger the use of a callback method.
695
     *
696
     * @param array $values sent back from the course configuration script
697
     */
698
    public function course_settings_updated($values = [])
699
    {
700
    }
701
702
    /**
703
     * Add a tab to platform.
704
     *
705
     * @param string $tabName
706
     * @param string $url
707
     * @param string $userFilter Optional. Filter tab type
708
     *
709
     * @return false|string
710
     */
711
    public function addTab($tabName, $url, $userFilter = null)
712
    {
713
        $table = Database::get_main_table(TABLE_MAIN_SETTINGS);
714
        $sql = "SELECT *
715
                FROM $table
716
                WHERE
717
                    variable = 'show_tabs' AND
718
                    subkey LIKE 'custom_tab_%'";
719
        $result = Database::query($sql);
720
        $customTabsNum = Database::num_rows($result);
721
722
        $tabNum = $customTabsNum + 1;
723
724
        // Avoid Tab Name Spaces
725
        $tabNameNoSpaces = preg_replace('/\s+/', '', $tabName);
726
        $subkeytext = "Tabs".$tabNameNoSpaces;
727
728
        // Check if it is already added
729
        $checkCondition = [
730
            'where' => [
731
                    "variable = 'show_tabs' AND subkeytext = ?" => [
732
                        $subkeytext,
733
                    ],
734
                ],
735
        ];
736
737
        $checkDuplicate = Database::select('*', 'settings_current', $checkCondition);
738
        if (!empty($checkDuplicate)) {
739
            return false;
740
        }
741
742
        // End Check
743
        $subkey = 'custom_tab_'.$tabNum;
744
745
        if (!empty($userFilter)) {
746
            switch ($userFilter) {
747
                case self::TAB_FILTER_NO_STUDENT:
748
                case self::TAB_FILTER_ONLY_STUDENT:
749
                    $subkey .= $userFilter;
750
                    break;
751
            }
752
        }
753
754
        $currentUrlId = api_get_current_access_url_id();
755
        $attributes = [
756
            'variable' => 'show_tabs',
757
            'subkey' => $subkey,
758
            'type' => 'checkbox',
759
            'category' => 'Platform',
760
            'selected_value' => 'true',
761
            'title' => $tabName,
762
            'comment' => $url,
763
            'subkeytext' => $subkeytext,
764
            'access_url' => $currentUrlId,
765
            'access_url_changeable' => 1,
766
            'access_url_locked' => 0,
767
        ];
768
        $resp = Database::insert('settings_current', $attributes);
769
770
        // Save the id
771
        $settings = $this->get_settings();
772
        $setData = [
773
            'comment' => $subkey,
774
        ];
775
        $whereCondition = [
776
            'id = ?' => key($settings),
777
        ];
778
        Database::update('settings_current', $setData, $whereCondition);
779
780
        return $resp;
781
    }
782
783
    /**
784
     * Delete a tab to chamilo's platform.
785
     *
786
     * @param string $key
787
     *
788
     * @return bool $resp Transaction response
789
     */
790
    public function deleteTab($key)
791
    {
792
        $table = Database::get_main_table(TABLE_MAIN_SETTINGS);
793
        $sql = "SELECT *
794
                FROM $table
795
                WHERE variable = 'show_tabs'
796
                AND subkey <> '$key'
797
                AND subkey like 'custom_tab_%'
798
                ";
799
        $resp = $result = Database::query($sql);
800
        $customTabsNum = Database::num_rows($result);
801
802
        if (!empty($key)) {
803
            $whereCondition = [
804
                'variable = ? AND subkey = ?' => ['show_tabs', $key],
805
            ];
806
            $resp = Database::delete('settings_current', $whereCondition);
807
808
            //if there is more than one tab
809
            //re enumerate them
810
            if (!empty($customTabsNum) && $customTabsNum > 0) {
811
                $tabs = Database::store_result($result, 'ASSOC');
812
                $i = 1;
813
                foreach ($tabs as $row) {
814
                    $newSubKey = "custom_tab_$i";
815
816
                    if (false !== strpos($row['subkey'], self::TAB_FILTER_NO_STUDENT)) {
817
                        $newSubKey .= self::TAB_FILTER_NO_STUDENT;
818
                    } elseif (false !== strpos($row['subkey'], self::TAB_FILTER_ONLY_STUDENT)) {
819
                        $newSubKey .= self::TAB_FILTER_ONLY_STUDENT;
820
                    }
821
822
                    $attributes = ['subkey' => $newSubKey];
823
                    $this->updateTab($row['subkey'], $attributes);
824
                    $i++;
825
                }
826
            }
827
        }
828
829
        return $resp;
830
    }
831
832
    /**
833
     * Update the tabs attributes.
834
     *
835
     * @param string $key
836
     * @param array  $attributes
837
     *
838
     * @return bool
839
     */
840
    public function updateTab($key, $attributes)
841
    {
842
        $whereCondition = [
843
            'variable = ? AND subkey = ?' => ['show_tabs', $key],
844
        ];
845
        $resp = Database::update('settings_current', $attributes, $whereCondition);
846
847
        return $resp;
848
    }
849
850
    /**
851
     * This method shows or hides plugin's tab.
852
     *
853
     * @param bool   $showTab  Shows or hides the main menu plugin tab
854
     * @param string $filePath Plugin starter file path
855
     */
856
    public function manageTab($showTab, $filePath = 'index.php')
857
    {
858
        $langString = str_replace('Plugin', '', get_class($this));
859
        $pluginName = strtolower($langString);
860
        $pluginUrl = 'plugin/'.$pluginName.'/'.$filePath;
861
862
        if ('true' === $showTab) {
863
            $tabAdded = $this->addTab($langString, $pluginUrl);
864
            if ($tabAdded) {
865
                // The page must be refreshed to show the recently created tab
866
                echo "<script>location.href = '".Security::remove_XSS($_SERVER['REQUEST_URI'])."';</script>";
867
            }
868
        } else {
869
            $settingsCurrentTable = Database::get_main_table(TABLE_MAIN_SETTINGS);
870
            $conditions = [
871
                'where' => [
872
                    "variable = 'show_tabs' AND title = ? AND comment = ? " => [
873
                        $langString,
874
                        $pluginUrl,
875
                    ],
876
                ],
877
            ];
878
            $result = Database::select('subkey', $settingsCurrentTable, $conditions);
879
            if (!empty($result)) {
880
                $this->deleteTab($result[0]['subkey']);
881
            }
882
        }
883
    }
884
885
    /**
886
     * @param string $variable
887
     *
888
     * @return bool
889
     */
890
    public function validateCourseSetting($variable)
891
    {
892
        return true;
893
    }
894
895
    /**
896
     * @param string $region
897
     *
898
     * @return string
899
     */
900
    public function renderRegion($region)
901
    {
902
        return '';
903
    }
904
905
    /**
906
     * Returns true if the plugin is installed, false otherwise.
907
     *
908
     * @param bool $checkEnabled Also check if enabled (instead of only installed)
909
     *
910
     * @return bool True if plugin is installed/enabled, false otherwise
911
     */
912
    public function isEnabled($checkEnabled = false)
913
    {
914
        $settings = api_get_settings_params_simple(
915
            [
916
                "subkey = ? AND category = ? AND type = ? AND variable = 'status' " => [
917
                    $this->get_name(),
918
                    'Plugins',
919
                    'setting',
920
                ],
921
            ]
922
        );
923
        if (is_array($settings) && isset($settings['selected_value']) && 'installed' == $settings['selected_value']) {
924
            // The plugin is installed
925
            // If we need a check on whether it is enabled, also check for
926
            // *plugin*_tool_enable and make sure it is *NOT* false
927
            if ($checkEnabled) {
928
                $enabled = api_get_settings_params_simple(
929
                    [
930
                        "variable = ? AND subkey = ? AND category = 'Plugins' " => [
931
                            $this->get_name().'_tool_enable',
932
                            $this->get_name(),
933
                        ],
934
                    ]
935
                );
936
                if (is_array($enabled) && isset($enabled['selected_value']) && 'false' == $enabled['selected_value']) {
937
                    // Only return false if the setting exists and it is
938
                    // *specifically* set to false
939
                    return false;
940
                }
941
            }
942
943
            return true;
944
        }
945
946
        return false;
947
    }
948
949
    /**
950
     * Allow make some actions after configure the plugin parameters
951
     * This function is called from main/admin/configure_plugin.php page
952
     * when saving the plugin parameters.
953
     *
954
     * @return \Plugin
955
     */
956
    public function performActionsAfterConfigure()
957
    {
958
        return $this;
959
    }
960
961
    /**
962
     * This function allows to change the visibility of the icon inside a course
963
     * :student tool will be visible only for students
964
     * :teacher tool will be visible only for teachers
965
     * If nothing it's set then tool will be visible for both as a normal icon.
966
     *
967
     * @return string
968
     */
969
    public function getToolIconVisibilityPerUserStatus()
970
    {
971
        return '';
972
    }
973
974
    /**
975
     * Default tool icon visibility.
976
     *
977
     * @return bool
978
     */
979
    public function isIconVisibleByDefault()
980
    {
981
        return true;
982
    }
983
984
    /**
985
     * Get the admin URL for the plugin if Plugin::isAdminPlugin is true.
986
     *
987
     * @return string
988
     */
989
    public function getAdminUrl()
990
    {
991
        if (!$this->isAdminPlugin) {
992
            return '';
993
        }
994
995
        $name = $this->get_name();
996
        $sysPath = api_get_path(SYS_PLUGIN_PATH).$name;
997
        $webPath = api_get_path(WEB_PLUGIN_PATH).$name;
998
999
        if (file_exists("$sysPath/admin.php")) {
1000
            return "$webPath/admin.php";
1001
        }
1002
1003
        if (file_exists("$sysPath/start.php")) {
1004
            return "$webPath/start.php";
1005
        }
1006
1007
        return '';
1008
    }
1009
1010
    /**
1011
     * @param bool $value
1012
     */
1013
    public function setHasPersonalEvents($value)
1014
    {
1015
        $this->hasPersonalEvents = $value;
1016
    }
1017
1018
    /**
1019
     * Overwrite to perform some actions when deleting a user.
1020
     *
1021
     * @param int $userId
1022
     */
1023
    public function doWhenDeletingUser($userId)
1024
    {
1025
    }
1026
1027
    /**
1028
     * Overwrite to perform some actions when deleting a course.
1029
     *
1030
     * @param int $courseId
1031
     */
1032
    public function doWhenDeletingCourse($courseId)
1033
    {
1034
    }
1035
1036
    /**
1037
     * Overwrite to perform some actions when deleting a session.
1038
     *
1039
     * @param int $sessionId
1040
     */
1041
    public function doWhenDeletingSession($sessionId)
1042
    {
1043
    }
1044
1045
    /**
1046
     * Add a link for a course tool.
1047
     *
1048
     * @param string      $name     The tool name
1049
     * @param int         $courseId The course ID
1050
     *
1051
     * @throws NotSupported
1052
     * @throws ORMException
1053
     * @throws OptimisticLockException
1054
     */
1055
    protected function createLinkToCourseTool(string $name, int $courseId): ?CTool
1056
    {
1057
        if (!$this->addCourseTool) {
1058
            return null;
1059
        }
1060
1061
        $visibilityPerStatus = $this->getToolIconVisibilityPerUserStatus();
1062
        $visibility = $this->isIconVisibleByDefault();
1063
1064
        $course = api_get_course_entity($courseId);
1065
        $user = api_get_user_entity();
1066
1067
        $em = Database::getManager();
1068
1069
        $toolRepo = $em->getRepository(Tool::class);
1070
        $cToolRepo = $em->getRepository(CTool::class);
1071
1072
        /** @var CTool $cTool */
1073
        $cTool = $cToolRepo->findOneBy([
1074
            'title' => $name.$visibilityPerStatus,
1075
            'course' => $course,
1076
        ]);
1077
1078
        if (!$cTool) {
0 ignored issues
show
introduced by
$cTool is of type Chamilo\CourseBundle\Entity\CTool, thus it always evaluated to true.
Loading history...
1079
            $tool = $toolRepo->findOneBy(['title' => $name]);
1080
1081
            if (!$tool) {
1082
                $tool = new Tool();
1083
                $tool->setTitle($name);
1084
1085
                $em->persist($tool);
1086
                $em->flush();
1087
            }
1088
1089
            $cTool = new CTool();
1090
            $cTool
1091
                ->setTool($tool)
1092
                ->setTitle($name.$visibilityPerStatus)
1093
                ->setVisibility($visibility)
1094
                ->setParent($course)
1095
                ->setCreator($user)
1096
                ->addCourseLink(
1097
                    $course,
1098
                    null,
1099
                    null,
1100
                    $visibility ? ResourceLink::VISIBILITY_PUBLISHED : ResourceLink::VISIBILITY_DRAFT
1101
                )
1102
            ;
1103
1104
            $course->addTool($cTool);
1105
1106
            $em->persist($cTool);
1107
            $em->flush();
1108
        }
1109
1110
        return $cTool;
1111
    }
1112
1113
    public function getFieldNames(): array
1114
    {
1115
        return array_keys($this->fields);
1116
    }
1117
}
1118