Passed
Pull Request — master (#6703)
by
unknown
08:09
created

Plugin::get()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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