Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
namespace mod_bigbluebuttonbn;
17
 
18
use cache;
19
use cm_info;
20
use mod_bigbluebuttonbn\local\extension\action_url_addons;
21
use mod_bigbluebuttonbn\local\extension\custom_completion_addons;
22
use mod_bigbluebuttonbn\local\extension\mod_form_addons;
23
use mod_bigbluebuttonbn\local\extension\mod_instance_helper;
24
use stdClass;
25
use core_plugin_manager;
26
 
27
/**
28
 * Generic subplugin management helper
29
 *
30
 * @package   mod_bigbluebuttonbn
31
 * @copyright 2023 onwards, Blindside Networks Inc
32
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33
 * @author    Laurent David (laurent@call-learning.fr)
34
 */
35
class extension {
36
    /**
37
     * Plugin name for extension
38
     */
39
    const BBB_EXTENSION_PLUGIN_NAME = 'bbbext';
40
 
41
    /**
42
     * Invoke a subplugin hook that will return additional parameters
43
     *
44
     * @param string $action
45
     * @param array $data
46
     * @param array $metadata
47
     * @param int|null $instanceid
48
     * @return array associative array with the additional data and metadata (indexed by 'data' and
49
     * 'metadata' keys).
50
     */
51
    public static function action_url_addons(
52
        string $action = '',
53
        array $data = [],
54
        array $metadata = [],
55
        ?int $instanceid = null
56
    ): array {
57
        $allmutationclass = self::get_instances_implementing(action_url_addons::class);
58
        $additionaldata = [];
59
        $additionalmetadata = [];
60
        foreach ($allmutationclass as $mutationclass) {
61
            // Here we intentionally just pass data and metadata and not the result as we
62
            // do not want subplugin to assume that another subplugin is doing a modification.
63
            ['data' => $newdata, 'metadata' => $newmetadata] = $mutationclass->execute($action, $data, $metadata, $instanceid);
64
            $additionaldata = array_merge($additionaldata, $newdata ?? []);
65
            $additionalmetadata = array_merge($additionalmetadata, $newmetadata ?? []);
66
        }
67
        return [
68
            'data' => $additionaldata,
69
            'metadata' => $additionalmetadata
70
        ];
71
    }
72
 
73
    /**
74
     * Get new instance of classes that are named on the base of this classname and implementing this class
75
     *
76
     * @param string $classname
77
     * @param array|null $newparameters additional parameters for the constructor.
78
     * @return array
79
     */
80
    protected static function get_instances_implementing(string $classname, ?array $newparameters = []): array {
81
        $classes = self::get_classes_implementing($classname);
82
        sort($classes); // Make sure all extension classes are returned in the same order. This is arbitrarily in
83
        // alphabetical order and depends on the classname but this one way to ensure consistency across calls.
84
        return array_map(function($targetclassname) use ($newparameters) {
85
            // If $newparameters is null, the constructor will be called without parameters.
86
            return new $targetclassname(...$newparameters);
87
        }, $classes);
88
    }
89
 
90
    /**
91
     * Get classes are named on the base of this classname and implementing this class
92
     *
93
     * @param string $classname
94
     * @return array
95
     */
96
    protected static function get_classes_implementing(string $classname): array {
97
        // Get the class basename without Reflection API.
98
        $classnamecomponents = explode("\\", $classname);
99
        $classbasename = end($classnamecomponents);
100
        $allsubs = core_plugin_manager::instance()->get_plugins_of_type(self::BBB_EXTENSION_PLUGIN_NAME);
101
        $extensionclasses = [];
102
        foreach ($allsubs as $sub) {
103
            if (!$sub->is_enabled()) {
104
                continue;
105
            }
106
            $targetclassname = "\\bbbext_{$sub->name}\\bigbluebuttonbn\\$classbasename";
107
            if (!class_exists($targetclassname)) {
108
                continue;
109
            }
110
            if (!is_subclass_of($targetclassname, $classname)) {
111
                debugging("The class $targetclassname should extend $classname in the subplugin {$sub->name}. Ignoring.");
112
                continue;
113
            }
114
            $extensionclasses[] = $targetclassname;
115
        }
116
        return $extensionclasses;
117
    }
118
 
119
    /**
120
     * Get all custom_completion addons classes.
121
     *
122
     * @return array of custom completion addon classes.
123
     */
124
    public static function custom_completion_addons_classes(): array {
125
        return self::get_classes_implementing(custom_completion_addons::class);
126
    }
127
 
128
    /**
129
     * Get all custom_completion addons classes instances.
130
     *
131
     * @param cm_info $cm
132
     * @param int $userid
133
     * @param array|null $completionstate
134
     * @return array of custom completion addon instances.
135
     */
136
    public static function custom_completion_addons_instances(cm_info $cm, int $userid, ?array $completionstate = null): array {
137
        return self::get_instances_implementing(custom_completion_addons::class, [$cm, $userid, $completionstate]);
138
    }
139
 
140
    /**
141
     * Get all mod_form addons classes instances
142
     *
143
     * @param \MoodleQuickForm $mform
144
     * @param stdClass|null $bigbluebuttondata
145
     * @param string|null $suffix
146
     * @return array of custom completion addon classes instances
147
     */
148
    public static function mod_form_addons_instances(\MoodleQuickForm $mform, ?stdClass $bigbluebuttondata = null,
149
        string $suffix = null): array {
150
        return self::get_instances_implementing(mod_form_addons::class, [$mform, $bigbluebuttondata, $suffix]);
151
    }
152
 
153
    /**
154
     * Get additional join tables for instance when extension activated
155
     *
156
     * @return array of additional tables names. They all have a field called bigbluebuttonbnid that identifies the bbb instance.
157
     */
158
    public static function get_join_tables(): array {
159
        global $DB;
160
        // We use cache here as it will be called very often.
161
        $cache = cache::make('mod_bigbluebuttonbn', 'subplugins');
162
        if ($cache->get('additionaltables')) {
163
            return $cache->get('additionaltables');
164
        }
165
        $additionaltablesclasses = self::get_instances_implementing(mod_instance_helper::class);
166
        $tables = [];
167
        foreach ($additionaltablesclasses as $tableclass) {
168
            $tables = array_merge($tables, $tableclass->get_join_tables() ?? []);
169
        }
170
        // Warning and removal for tables that do not have the bigbluebuttonid field.
171
        foreach ($tables as $index => $table) {
172
            $columns = $DB->get_columns($table);
173
            if (empty($columns['bigbluebuttonbnid'])) {
174
                debugging("get_instance_additional_tables: $table should have a column named bigbluebuttonid");
175
                unset($tables[$index]);
176
            }
177
        }
178
        $cache->set('additionaltables', $tables);
179
        return $tables;
180
    }
181
 
182
    /**
183
     * Add instance processing
184
     *
185
     * @param stdClass $data data to persist
186
     * @return void
187
     */
188
    public static function add_instance(stdClass $data): void {
189
        $formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class);
190
        foreach ($formmanagersclasses as $fmclass) {
191
            $fmclass->add_instance($data);
192
        }
193
    }
194
 
195
    /**
196
     * Update instance processing
197
     *
198
     * @param stdClass $data data to persist
199
     * @return void
200
     */
201
    public static function update_instance(stdClass $data): void {
202
        $formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class);
203
        foreach ($formmanagersclasses as $fmclass) {
204
            $fmclass->update_instance($data);
205
        }
206
    }
207
 
208
    /**
209
     * Delete instance processing
210
     *
211
     * @param int $id instance id
212
     * @return void
213
     */
214
    public static function delete_instance(int $id): void {
215
        $formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class);
216
        foreach ($formmanagersclasses as $fmclass) {
217
            $fmclass->delete_instance($id);
218
        }
219
    }
220
}