Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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;
1441 ariadna 21
use mod_bigbluebuttonbn\local\extension\broker_meeting_events_addons;
1 efrain 22
use mod_bigbluebuttonbn\local\extension\custom_completion_addons;
23
use mod_bigbluebuttonbn\local\extension\mod_form_addons;
24
use mod_bigbluebuttonbn\local\extension\mod_instance_helper;
25
use stdClass;
26
use core_plugin_manager;
1441 ariadna 27
use core_component;
1 efrain 28
 
29
/**
30
 * Generic subplugin management helper
31
 *
32
 * @package   mod_bigbluebuttonbn
33
 * @copyright 2023 onwards, Blindside Networks Inc
34
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 * @author    Laurent David (laurent@call-learning.fr)
36
 */
37
class extension {
38
    /**
39
     * Plugin name for extension
40
     */
41
    const BBB_EXTENSION_PLUGIN_NAME = 'bbbext';
42
 
43
    /**
44
     * Invoke a subplugin hook that will return additional parameters
45
     *
46
     * @param string $action
47
     * @param array $data
48
     * @param array $metadata
49
     * @param int|null $instanceid
50
     * @return array associative array with the additional data and metadata (indexed by 'data' and
51
     * 'metadata' keys).
52
     */
53
    public static function action_url_addons(
54
        string $action = '',
55
        array $data = [],
56
        array $metadata = [],
57
        ?int $instanceid = null
58
    ): array {
59
        $allmutationclass = self::get_instances_implementing(action_url_addons::class);
60
        $additionaldata = [];
61
        $additionalmetadata = [];
62
        foreach ($allmutationclass as $mutationclass) {
63
            // Here we intentionally just pass data and metadata and not the result as we
64
            // do not want subplugin to assume that another subplugin is doing a modification.
65
            ['data' => $newdata, 'metadata' => $newmetadata] = $mutationclass->execute($action, $data, $metadata, $instanceid);
66
            $additionaldata = array_merge($additionaldata, $newdata ?? []);
67
            $additionalmetadata = array_merge($additionalmetadata, $newmetadata ?? []);
68
        }
69
        return [
70
            'data' => $additionaldata,
71
            'metadata' => $additionalmetadata
72
        ];
73
    }
74
 
75
    /**
76
     * Get new instance of classes that are named on the base of this classname and implementing this class
77
     *
78
     * @param string $classname
79
     * @param array|null $newparameters additional parameters for the constructor.
80
     * @return array
81
     */
82
    protected static function get_instances_implementing(string $classname, ?array $newparameters = []): array {
83
        $classes = self::get_classes_implementing($classname);
1441 ariadna 84
        ksort($classes); // Make sure all extension classes are returned in the correct order.
1 efrain 85
        return array_map(function($targetclassname) use ($newparameters) {
86
            // If $newparameters is null, the constructor will be called without parameters.
87
            return new $targetclassname(...$newparameters);
88
        }, $classes);
89
    }
90
 
91
    /**
92
     * Get classes are named on the base of this classname and implementing this class
93
     *
94
     * @param string $classname
95
     * @return array
96
     */
97
    protected static function get_classes_implementing(string $classname): array {
98
        // Get the class basename without Reflection API.
99
        $classnamecomponents = explode("\\", $classname);
100
        $classbasename = end($classnamecomponents);
101
        $allsubs = core_plugin_manager::instance()->get_plugins_of_type(self::BBB_EXTENSION_PLUGIN_NAME);
102
        $extensionclasses = [];
1441 ariadna 103
        $names = core_component::get_plugin_list(self::BBB_EXTENSION_PLUGIN_NAME);
104
        $sortedlist = self::get_sorted_plugins_list($names); // Make sure to use the most updated list.
105
        $sortedlist = array_flip($sortedlist);
1 efrain 106
        foreach ($allsubs as $sub) {
107
            if (!$sub->is_enabled()) {
108
                continue;
109
            }
110
            $targetclassname = "\\bbbext_{$sub->name}\\bigbluebuttonbn\\$classbasename";
111
            if (!class_exists($targetclassname)) {
112
                continue;
113
            }
114
            if (!is_subclass_of($targetclassname, $classname)) {
115
                debugging("The class $targetclassname should extend $classname in the subplugin {$sub->name}. Ignoring.");
116
                continue;
117
            }
1441 ariadna 118
            if (!isset($sortedlist[$sub->name])) {
119
                debugging("The class $targetclassname does not belong to an existing subplugin. Ignoring");
120
                continue;
121
            }
122
            // Return all extension classes based on subplugin order on manage extension page.
123
            $sortorder = $sortedlist[$sub->name];
124
            $extensionclasses[$sortorder] = $targetclassname;
1 efrain 125
        }
126
        return $extensionclasses;
127
    }
128
 
129
    /**
1441 ariadna 130
     * Return plugin list sorted according to order from admin extension manager.
131
     * @param array $names Array of plugin names
132
     * @return array The sorted list of plugins
133
     */
134
    public static function get_sorted_plugins_list(array $names): array {
135
        $result = [];
136
        foreach ($names as $name => $path) {
137
            $idx = get_config(self::BBB_EXTENSION_PLUGIN_NAME . '_' . $name, 'sortorder');
138
            if (!$idx) {
139
                $idx = 0;
140
            }
141
            while (array_key_exists($idx, $result)) {
142
                $idx += 1;
143
            }
144
            $result[$idx] = $name;
145
        }
146
        ksort($result);
147
        return $result;
148
    }
149
 
150
    /**
1 efrain 151
     * Get all custom_completion addons classes.
152
     *
153
     * @return array of custom completion addon classes.
154
     */
155
    public static function custom_completion_addons_classes(): array {
156
        return self::get_classes_implementing(custom_completion_addons::class);
157
    }
158
 
159
    /**
160
     * Get all custom_completion addons classes instances.
161
     *
162
     * @param cm_info $cm
163
     * @param int $userid
164
     * @param array|null $completionstate
165
     * @return array of custom completion addon instances.
166
     */
167
    public static function custom_completion_addons_instances(cm_info $cm, int $userid, ?array $completionstate = null): array {
168
        return self::get_instances_implementing(custom_completion_addons::class, [$cm, $userid, $completionstate]);
169
    }
170
 
171
    /**
172
     * Get all mod_form addons classes instances
173
     *
174
     * @param \MoodleQuickForm $mform
175
     * @param stdClass|null $bigbluebuttondata
176
     * @param string|null $suffix
177
     * @return array of custom completion addon classes instances
178
     */
179
    public static function mod_form_addons_instances(\MoodleQuickForm $mform, ?stdClass $bigbluebuttondata = null,
1441 ariadna 180
        ?string $suffix = null): array {
1 efrain 181
        return self::get_instances_implementing(mod_form_addons::class, [$mform, $bigbluebuttondata, $suffix]);
182
    }
183
 
184
    /**
185
     * Get additional join tables for instance when extension activated
186
     *
187
     * @return array of additional tables names. They all have a field called bigbluebuttonbnid that identifies the bbb instance.
188
     */
189
    public static function get_join_tables(): array {
190
        global $DB;
191
        // We use cache here as it will be called very often.
192
        $cache = cache::make('mod_bigbluebuttonbn', 'subplugins');
193
        if ($cache->get('additionaltables')) {
194
            return $cache->get('additionaltables');
195
        }
196
        $additionaltablesclasses = self::get_instances_implementing(mod_instance_helper::class);
197
        $tables = [];
198
        foreach ($additionaltablesclasses as $tableclass) {
199
            $tables = array_merge($tables, $tableclass->get_join_tables() ?? []);
200
        }
201
        // Warning and removal for tables that do not have the bigbluebuttonid field.
202
        foreach ($tables as $index => $table) {
203
            $columns = $DB->get_columns($table);
204
            if (empty($columns['bigbluebuttonbnid'])) {
205
                debugging("get_instance_additional_tables: $table should have a column named bigbluebuttonid");
206
                unset($tables[$index]);
207
            }
208
        }
209
        $cache->set('additionaltables', $tables);
210
        return $tables;
211
    }
212
 
213
    /**
214
     * Add instance processing
215
     *
216
     * @param stdClass $data data to persist
217
     * @return void
218
     */
219
    public static function add_instance(stdClass $data): void {
220
        $formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class);
221
        foreach ($formmanagersclasses as $fmclass) {
222
            $fmclass->add_instance($data);
223
        }
224
    }
225
 
226
    /**
227
     * Update instance processing
228
     *
229
     * @param stdClass $data data to persist
230
     * @return void
231
     */
232
    public static function update_instance(stdClass $data): void {
233
        $formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class);
234
        foreach ($formmanagersclasses as $fmclass) {
235
            $fmclass->update_instance($data);
236
        }
237
    }
238
 
239
    /**
240
     * Delete instance processing
241
     *
242
     * @param int $id instance id
243
     * @return void
244
     */
245
    public static function delete_instance(int $id): void {
246
        $formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class);
247
        foreach ($formmanagersclasses as $fmclass) {
248
            $fmclass->delete_instance($id);
249
        }
250
    }
1441 ariadna 251
 
252
    /**
253
     * Get all broker_meeting_events addons classes instances
254
     *
255
     * @param instance|null $instance
256
     * @param string|null $data
257
     * @return array of custom completion addon classes instances
258
     */
259
    public static function broker_meeting_events_addons_instances(instance $instance, string $data): array {
260
        return self::get_instances_implementing(broker_meeting_events_addons::class, [$instance, $data]);
261
    }
1 efrain 262
}