Completed
Push — master ( 996ef7...cc3037 )
by Julito
29:27
created

AppPlugin::__construct()   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
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/* See license terms in /license.txt */
3
4
/**
5
 * Class AppPlugin
6
 */
7
class AppPlugin
8
{
9
    public $plugin_regions = array(
10
        'main_top',
11
        'main_bottom',
12
        'login_top',
13
        'login_bottom',
14
        'menu_top',
15
        'menu_bottom',
16
        'content_top',
17
        'content_bottom',
18
        'header_main',
19
        'header_center',
20
        'header_left',
21
        'header_right',
22
        'pre_footer',
23
        'footer_left',
24
        'footer_center',
25
        'footer_right',
26
        'menu_administrator',
27
        'course_tool_plugin'
28
    );
29
30
    public $installedPluginListName = array();
31
    public $installedPluginListObject = array();
32
33
    /**
34
     * Constructor
35
     */
36
    public function __construct()
37
    {
38
    }
39
40
    /**
41
     * Read plugin from path
42
     * @return array
43
     */
44
    public function read_plugins_from_path()
45
    {
46
        /* We scan the plugin directory. Each folder is a potential plugin. */
47
        $pluginPath = api_get_path(SYS_PLUGIN_PATH);
48
        $plugins = array();
49
        $handle = @opendir($pluginPath);
50
        while (false !== ($file = readdir($handle))) {
51
            if ($file != '.' && $file != '..' && is_dir(api_get_path(SYS_PLUGIN_PATH).$file)) {
52
                $plugins[] = $file;
53
            }
54
        }
55
        @closedir($handle);
56
        sort($plugins);
57
58
        return $plugins;
59
    }
60
61
    /**
62
     * @return array
63
     */
64 View Code Duplication
    public function get_installed_plugins_by_region()
65
    {
66
        $plugins = array();
67
        /* We retrieve all the active plugins. */
68
        $result = api_get_settings('Plugins');
69
        if (!empty($result)) {
70
            foreach ($result as $row) {
71
                $plugins[$row['variable']][] = $row['selected_value'];
72
            }
73
        }
74
75
        return $plugins;
76
    }
77
78
    /**
79
     * @return array
80
     */
81
    public function getInstalledPluginListName()
82
    {
83
        if (empty($this->installedPluginListName)) {
84
            $this->installedPluginListName = $this->get_installed_plugins();
85
        }
86
87
        return $this->installedPluginListName;
88
    }
89
90
    /**
91
     * @return array List of Plugin
92
     */
93
    public function getInstalledPluginListObject()
94
    {
95
        if (empty($this->installedPluginListObject)) {
96
            $this->setInstalledPluginListObject();
97
        }
98
99
        return $this->installedPluginListObject;
100
    }
101
102
    /**
103
     * @return array
104
     */
105
    public function setInstalledPluginListObject()
106
    {
107
        $pluginListName = $this->getInstalledPluginListName();
108
        $pluginList = array();
109
        if (!empty($pluginListName)) {
110
            foreach ($pluginListName as $pluginName) {
111
                $pluginInfo = $this->getPluginInfo($pluginName);
112
                if (isset($pluginInfo['plugin_class'])) {
113
                    $pluginList[] = $pluginInfo['plugin_class']::create();
114
                }
115
            }
116
        }
117
        $this->installedPluginListObject = $pluginList;
118
    }
119
120
    /**
121
     * @return array
122
     */
123
    public function get_installed_plugins()
124
    {
125
        $installedPlugins = array();
126
        $plugins = api_get_settings_params(
127
            array(
128
                "variable = ? AND selected_value = ? AND category = ? " => array('status', 'installed', 'Plugins')
129
            )
130
        );
131
132
        if (!empty($plugins)) {
133
            foreach ($plugins as $row) {
134
                $installedPlugins[$row['subkey']] = true;
135
            }
136
            $installedPlugins = array_keys($installedPlugins);
137
        }
138
139
        return $installedPlugins;
140
    }
141
142
    /**
143
     * @param string $pluginName
144
     * @param int    $urlId
145
     */
146
    public function install($pluginName, $urlId = null)
147
    {
148
        if (empty($urlId)) {
149
            $urlId = api_get_current_access_url_id();
150
        } else {
151
            $urlId = intval($urlId);
152
        }
153
154
        api_add_setting(
155
            'installed',
156
            'status',
157
            $pluginName,
158
            'setting',
159
            'Plugins',
160
            $pluginName,
161
            null,
162
            null,
163
            null,
164
            $urlId,
165
            1
166
        );
167
168
        $pluginPath = api_get_path(SYS_PLUGIN_PATH).$pluginName.'/install.php';
169
170
        if (is_file($pluginPath) && is_readable($pluginPath)) {
171
            // Execute the install procedure.
172
173
            require $pluginPath;
174
        }
175
    }
176
177
    /**
178
    * @param string $pluginName
179
    * @param int    $urlId
180
    */
181
    public function uninstall($pluginName, $urlId = null)
182
    {
183
        if (empty($urlId)) {
184
            $urlId = api_get_current_access_url_id();
185
        } else {
186
            $urlId = intval($urlId);
187
        }
188
189
        // First call the custom uninstall to allow full access to global settings
190
        $pluginPath = api_get_path(SYS_PLUGIN_PATH).$pluginName.'/uninstall.php';
191
        if (is_file($pluginPath) && is_readable($pluginPath)) {
192
            // Execute the uninstall procedure.
193
194
            require $pluginPath;
195
        }
196
        // Second remove all remaining global settings
197
        api_delete_settings_params(
198
            array('category = ? AND access_url = ? AND subkey = ? ' => array('Plugins', $urlId, $pluginName))
199
        );
200
    }
201
202
    /**
203
     * @param string $pluginName
204
     *
205
     * @return array
206
     */
207 View Code Duplication
    public function get_areas_by_plugin($pluginName)
208
    {
209
        $result = api_get_settings('Plugins');
210
        $areas = array();
211
        foreach ($result as $row) {
212
            if ($pluginName == $row['selected_value']) {
213
                $areas[] = $row['variable'];
214
            }
215
        }
216
217
        return $areas;
218
    }
219
220
    /**
221
     * @param string $location
222
     *
223
     * @return bool
224
     */
225
    public function is_valid_plugin_location($location)
226
    {
227
        return in_array($location, $this->plugin_list);
228
    }
229
230
    /**
231
     * @param string $pluginName
232
     *
233
     * @return bool
234
     */
235
    public function is_valid_plugin($pluginName)
236
    {
237
        if (is_dir(api_get_path(SYS_PLUGIN_PATH).$pluginName)) {
238
            if (is_file(api_get_path(SYS_PLUGIN_PATH).$pluginName.'/index.php')) {
239
                return true;
240
            }
241
        }
242
243
        return false;
244
    }
245
246
    /**
247
     * @return array
248
     */
249
    public function get_plugin_regions()
250
    {
251
        sort($this->plugin_regions);
252
253
        return $this->plugin_regions;
254
    }
255
256
    /**
257
    * @param string $region
258
    * @param string $template
259
    * @param bool   $forced
260
    *
261
    * @return null|string
262
    */
263
    public function load_region($region, $template, $_plugins, $forced = false)
264
    {
265
        if ($region == 'course_tool_plugin') {
266
            return '';
267
        }
268
269
        ob_start();
270
        $this->get_all_plugin_contents_by_region($region, $template, $_plugins, $forced);
271
        $content = ob_get_contents();
272
        ob_end_clean();
273
274
        return $content;
275
    }
276
277
    /**
278
     * Loads the translation files inside a plugin if exists.
279
     * It loads by default english see the hello world plugin
280
     *
281
     * @param string $plugin_name
282
     *
283
     * @todo add caching
284
     */
285
    public function load_plugin_lang_variables($plugin_name)
286
    {
287
        $root = api_get_path(SYS_PLUGIN_PATH);
288
        $strings = null;
289
290
        // 1. Loading english if exists
291
        $english_path = $root.$plugin_name."/lang/english.php";
292
293
        if (is_readable($english_path)) {
294
            include $english_path;
295
296
            foreach ($strings as $key => $string) {
0 ignored issues
show
Bug introduced by
The expression $strings of type null is not traversable.
Loading history...
297
                $GLOBALS[$key] = $string;
298
            }
299
        }
300
301
        // 2. Loading the system language
302
        /*
303
        if ($language_interface != 'english') {
304
            $path = $root.$plugin_name."/lang/$language_interface.php";
305
306
            if (is_readable($path)) {
307
                include $path;
308
                if (!empty($strings)) {
309
                    foreach ($strings as $key => $string) {
310
                        $GLOBALS[$key] = $string;
311
                    }
312
                }
313
            } else {
314
                $interfaceLanguageId = api_get_language_id($language_interface);
315
                $interfaceLanguageInfo = api_get_language_info($interfaceLanguageId);
316
                $languageParentId = intval($interfaceLanguageInfo['parent_id']);
317
318
                if ($languageParentId > 0) {
319
                    $languageParentInfo = api_get_language_info($languageParentId);
320
                    $languageParentFolder = $languageParentInfo['dokeos_folder'];
321
322
                    $parentPath = "{$root}{$plugin_name}/lang/{$languageParentFolder}.php";
323
                    if (is_readable($parentPath)) {
324
                        include $parentPath;
325
                        if (!empty($strings)) {
326
                            foreach ($strings as $key => $string) {
327
                                $this->strings[$key] = $string;
328
                            }
329
                        }
330
                    }
331
                }
332
            }
333
        }*/
334
    }
335
336
    /**
337
     * @param string $region
338
     * @param Template $template
339
     * @param bool $forced
340
     *
341
     * @return bool
342
     *
343
     * @todo improve this function
344
     */
345
    public function get_all_plugin_contents_by_region($region, $template, $_plugins, $forced = false)
346
    {
347
        if (isset($_plugins[$region]) && is_array($_plugins[$region])) {
348
            // Load the plugin information
349
            foreach ($_plugins[$region] as $plugin_name) {
350
351
                // The plugin_info variable is available inside the plugin index
352
                $plugin_info = $this->getPluginInfo($plugin_name, $forced);
353
354
                // We also know where the plugin is
355
                $plugin_info['current_region'] = $region;
356
357
                // Loading the plugin/XXX/index.php file
358
                $plugin_file = api_get_path(SYS_PLUGIN_PATH)."$plugin_name/index.php";
359
360
                if (file_exists($plugin_file)) {
361
362
                    //Loading the lang variables of the plugin if exists
363
                    self::load_plugin_lang_variables($plugin_name);
364
365
                    // Printing the plugin index.php file
366
                    require $plugin_file;
367
368
                    // If the variable $_template is set we assign those values to be accessible in Twig
369
                    if (isset($_template)) {
370
                        $_template['plugin_info'] = $plugin_info;
371
                    } else {
372
                        $_template = array();
373
                        $_template['plugin_info'] = $plugin_info;
374
                    }
375
376
                    // Setting the plugin info available in the template if exists.
377
                    $template->addGlobal($plugin_name, $_template);
378
379
                    // Loading the Twig template plugin files if exists
380
                    $template_list = array();
381
                    if (isset($plugin_info) && isset($plugin_info['templates'])) {
382
                        $template_list = $plugin_info['templates'];
383
                    }
384
385
                    if (!empty($template_list)) {
386
                        foreach ($template_list as $plugin_tpl) {
0 ignored issues
show
Bug introduced by
The expression $template_list of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
387
                            if (!empty($plugin_tpl)) {
388
                                $template_plugin_file = "$plugin_name/$plugin_tpl"; // for twig
389
                                $template->display($template_plugin_file, false);
390
                            }
391
                        }
392
                    }
393
                }
394
            }
395
        }
396
397
        return true;
398
    }
399
400
    /**
401
     * Loads plugin info
402
     *
403
     * @staticvar array $plugin_data
404
     * @param string    $plugin_name
405
     * @param bool      $forced load from DB or from the static array
406
     *
407
     * @return array
408
     * @todo filter setting_form
409
     */
410
    public function getPluginInfo($plugin_name, $forced = false)
411
    {
412
        static $plugin_data = array();
413
414
        if (isset($plugin_data[$plugin_name]) && $forced == false) {
415
            return $plugin_data[$plugin_name];
416
        } else {
417
            $plugin_file = api_get_path(SYS_PLUGIN_PATH)."$plugin_name/plugin.php";
418
419
            $plugin_info = array();
420
            if (file_exists($plugin_file)) {
421
422
                require $plugin_file;
423
            }
424
425
            // Extra options
426
            $plugin_settings = api_get_settings_params(
427
                array(
428
                    "subkey = ? AND category = ? AND type = ? " => array($plugin_name, 'Plugins','setting')
429
                )
430
            );
431
432
            $settings_filtered = array();
433
            foreach ($plugin_settings as $item) {
434
                $settings_filtered[$item['variable']] = $item['selected_value'];
435
            }
436
            $plugin_info['settings'] = $settings_filtered;
437
            $plugin_data[$plugin_name] = $plugin_info;
438
439
            return $plugin_info;
440
        }
441
    }
442
443
    /**
444
     * Get the template list
445
     * @param  string $pluginName
446
     *
447
     * @return bool
448
     */
449
    public function get_templates_list($pluginName)
450
    {
451
        $plugin_info = $this->getPluginInfo($pluginName);
452
        if (isset($plugin_info) && isset($plugin_info['templates'])) {
453
            return $plugin_info['templates'];
454
        } else {
455
            return false;
456
        }
457
    }
458
459
    /**
460
     * Remove all regions of an specific plugin
461
     */
462
    public function remove_all_regions($plugin)
463
    {
464
        $access_url_id = api_get_current_access_url_id();
465
        if (!empty($plugin)) {
466
            api_delete_settings_params(
467
                array(
468
                    'category = ? AND type = ? AND access_url = ? AND subkey = ? ' => array('Plugins', 'region', $access_url_id, $plugin)
469
                )
470
            );
471
        }
472
    }
473
474
    /**
475
     * Add a plugin to a region
476
     * @param string $plugin
477
     * @param string $region
478
     */
479
    public function add_to_region($plugin, $region)
480
    {
481
        $access_url_id = api_get_current_access_url_id();
482
        api_add_setting(
483
            $plugin,
484
            $region,
485
            $plugin,
486
            'region',
487
            'Plugins',
488
            $plugin,
489
            null,
490
            null,
491
            null,
492
            $access_url_id,
493
            1
494
        );
495
    }
496
497
    /**
498
     * @param int $courseId
499
     */
500
    public function install_course_plugins($courseId)
501
    {
502
        $pluginList = $this->getInstalledPluginListObject();
503
504
        if (!empty($pluginList)) {
505
            /** @var Plugin $obj */
506
            foreach ($pluginList as $obj) {
507
                $pluginName = $obj->get_name();
508
                $plugin_path = api_get_path(SYS_PLUGIN_PATH).$pluginName.'/plugin.php';
509
510
                if (file_exists($plugin_path)) {
511
                    require $plugin_path;
512
                    if (isset($plugin_info) && isset($plugin_info['plugin_class']) && $obj->isCoursePlugin) {
513
                        $obj->course_install($courseId);
514
                    }
515
                }
516
            }
517
        }
518
    }
519
520
    /**
521
     * Add the course settings to the course settings form
522
     * @param FormValidator $form
523
     */
524
    public function add_course_settings_form($form)
525
    {
526
        $pluginList = $this->getInstalledPluginListObject();
527
        /** @var Plugin $obj */
528
        foreach ($pluginList as $obj) {
529
            $plugin_name = $obj->get_name();
530
            $pluginTitle = $obj->get_title();
531
            if (!empty($obj->course_settings)) {
532
                if (is_file(api_get_path(SYS_CODE_PATH).'img/icons/'.ICON_SIZE_SMALL.'/'.$plugin_name.'.png')) {
533
                    $icon = Display::return_icon(
534
                        $plugin_name . '.png',
535
                        Security::remove_XSS($pluginTitle),
536
                        '',
537
                        ICON_SIZE_SMALL
538
                    );
539
                } else {
540
                    $icon = Display::return_icon(
541
                        'plugins.png',
542
                        Security::remove_XSS($pluginTitle),
543
                        '',
544
                        ICON_SIZE_SMALL
545
                    );
546
                }
547
548
                $form->addHtml('<div class="panel panel-default">');
549
                $form->addHtml('
550
                    <div class="panel-heading" role="tab" id="heading-' . $plugin_name . '-settings">
551
                        <h4 class="panel-title">
552
                            <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse-' . $plugin_name . '-settings" aria-expanded="false" aria-controls="collapse-' . $plugin_name . '-settings">
553
                ');
554
                $form->addHtml($icon . ' ' . $pluginTitle);
555
                $form->addHtml('
556
                            </a>
557
                        </h4>
558
                    </div>
559
                ');
560
                $form->addHtml('
561
                    <div id="collapse-' . $plugin_name . '-settings" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading-' . $plugin_name . '-settings">
562
                        <div class="panel-body">
563
                ');
564
565
                $groups = array();
566
                foreach ($obj->course_settings as $setting) {
567
                    if ($obj->validateCourseSetting($setting['name']) === false) {
568
                        continue;
569
                    }
570
                    if ($setting['type'] != 'checkbox') {
571
                        $form->addElement($setting['type'], $setting['name'], $obj->get_lang($setting['name']));
572
                    } else {
573
                        $element = & $form->createElement(
574
                            $setting['type'],
575
                            $setting['name'],
576
                            '',
577
                            $obj->get_lang($setting['name'])
578
                        );
579
                        if (isset($setting['init_value']) && $setting['init_value'] == 1) {
580
                            $element->setChecked(true);
581
                        }
582
                        $form->addElement($element);
583
584
                        if (isset($setting['group'])) {
585
                            $groups[$setting['group']][] = $element;
586
                        }
587
                    }
588
                }
589
                foreach ($groups as $k => $v) {
590
                    $form->addGroup($groups[$k], $k, array($obj->get_lang($k)));
591
                }
592
                $form->addButtonSave(get_lang('SaveSettings'));
593
                $form->addHtml('
594
                        </div>
595
                    </div>
596
                ');
597
                $form->addHtml('</div>');
598
            }
599
        }
600
    }
601
602
    /**
603
     * Get all course settings from all installed plugins.
604
     * @return array
605
     */
606
    public function getAllPluginCourseSettings()
607
    {
608
        $pluginList = $this->getInstalledPluginListObject();
609
        /** @var Plugin $obj */
610
        $courseSettings = array();
611
        if (!empty($pluginList)) {
612
            foreach ($pluginList as $obj) {
613
                $pluginCourseSetting = $obj->getCourseSettings();
614
                $courseSettings = array_merge($courseSettings, $pluginCourseSetting);
615
            }
616
        }
617
618
        return $courseSettings;
619
    }
620
621
    /**
622
     * When saving the plugin values in the course settings, check whether
623
     * a callback method should be called and send it the updated settings
624
     * @param array $values The new settings the user just saved
625
     * @return void
626
     */
627
    public function saveCourseSettingsHook($values)
628
    {
629
        $pluginList = $this->getInstalledPluginListObject();
630
631
        /** @var Plugin $obj */
632
        foreach ($pluginList as $obj) {
633
            $settings = $obj->getCourseSettings();
634
635
            $subValues = array();
636
            if (!empty($settings)) {
637
                foreach ($settings as $v) {
638
                    if (isset($values[$v])) {
639
                        $subValues[$v] = $values[$v];
640
                    }
641
                }
642
            }
643
644
            if (!empty($subValues)) {
645
                $obj->course_settings_updated($subValues);
646
            }
647
        }
648
    }
649
650
    /**
651
     * Get first SMS plugin name
652
     * @return string|boolean
653
     */
654
    public function getSMSPluginName()
655
    {
656
        $installedPluginsList = $this->getInstalledPluginListObject();
657
        foreach ($installedPluginsList as $installedPlugin) {
658
            if ($installedPlugin->isMailPlugin) {
659
                return get_class($installedPlugin);
660
            }
661
        }
662
663
        return false;
664
    }
665
666
    /**
667
     * @return SmsPluginLibraryInterface
668
     */
669
    public function getSMSPluginLibrary()
670
    {
671
        $className = $this->getSMSPluginName();
672
        $className = str_replace('Plugin', '', $className);
673
674
        if (class_exists($className)) {
675
            return new $className;
676
        }
677
678
        return false;
679
    }
680
}
681