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 mod_bigbluebuttonbn\local\extension\action_url_addons; 20 use mod_bigbluebuttonbn\local\extension\mod_form_addons; 21 use mod_bigbluebuttonbn\local\extension\mod_instance_helper; 22 use stdClass; 23 use core_plugin_manager; 24 25 /** 26 * Generic subplugin management helper 27 * 28 * @package mod_bigbluebuttonbn 29 * @copyright 2023 onwards, Blindside Networks Inc 30 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 31 * @author Laurent David (laurent@call-learning.fr) 32 */ 33 class extension { 34 /** 35 * Plugin name for extension 36 */ 37 const BBB_EXTENSION_PLUGIN_NAME = 'bbbext'; 38 39 /** 40 * Invoke a subplugin hook that will return additional parameters 41 * 42 * @param string $action 43 * @param array $data 44 * @param array $metadata 45 * @param int|null $instanceid 46 * @return array associative array with the additional data and metadata (indexed by 'data' and 47 * 'metadata' keys). 48 */ 49 public static function action_url_addons( 50 string $action = '', 51 array $data = [], 52 array $metadata = [], 53 ?int $instanceid = null 54 ): array { 55 $allmutationclass = self::get_instances_implementing(action_url_addons::class); 56 $additionaldata = []; 57 $additionalmetadata = []; 58 foreach ($allmutationclass as $mutationclass) { 59 // Here we intentionally just pass data and metadata and not the result as we 60 // do not want subplugin to assume that another subplugin is doing a modification. 61 ['data' => $newdata, 'metadata' => $newmetadata] = $mutationclass->execute($action, $data, $metadata, $instanceid); 62 $additionaldata = array_merge($additionaldata, $newdata ?? []); 63 $additionalmetadata = array_merge($additionalmetadata, $newmetadata ?? []); 64 } 65 return [ 66 'data' => $additionaldata, 67 'metadata' => $additionalmetadata 68 ]; 69 } 70 71 /** 72 * Get new instance of classes that are named on the base of this classname and implementing this class 73 * 74 * @param string $classname 75 * @param array|null $newparameters additional parameters for the constructor. 76 * @return array 77 */ 78 protected static function get_instances_implementing(string $classname, ?array $newparameters = []): array { 79 $classes = self::get_classes_implementing($classname); 80 sort($classes); // Make sure all extension classes are returned in the same order. This is arbitrarily in 81 // alphabetical order and depends on the classname but this one way to ensure consistency across calls. 82 return array_map(function($targetclassname) use ($newparameters) { 83 // If $newparameters is null, the constructor will be called without parameters. 84 return new $targetclassname(...$newparameters); 85 }, $classes); 86 } 87 88 /** 89 * Get classes are named on the base of this classname and implementing this class 90 * 91 * @param string $classname 92 * @return array 93 */ 94 protected static function get_classes_implementing(string $classname): array { 95 // Get the class basename without Reflection API. 96 $classnamecomponents = explode("\\", $classname); 97 $classbasename = end($classnamecomponents); 98 $allsubs = core_plugin_manager::instance()->get_plugins_of_type(self::BBB_EXTENSION_PLUGIN_NAME); 99 $extensionclasses = []; 100 foreach ($allsubs as $sub) { 101 if (!$sub->is_enabled()) { 102 continue; 103 } 104 $targetclassname = "\\bbbext_{$sub->name}\\bigbluebuttonbn\\$classbasename"; 105 if (!class_exists($targetclassname)) { 106 continue; 107 } 108 if (!is_subclass_of($targetclassname, $classname)) { 109 debugging("The class $targetclassname should extend $classname in the subplugin {$sub->name}. Ignoring."); 110 continue; 111 } 112 $extensionclasses[] = $targetclassname; 113 } 114 return $extensionclasses; 115 } 116 117 /** 118 * Get all mod_form addons classes instances 119 * 120 * @param \MoodleQuickForm $mform 121 * @param stdClass|null $bigbluebuttondata 122 * @param string|null $suffix 123 * @return array of custom completion addon classes instances 124 */ 125 public static function mod_form_addons_instances(\MoodleQuickForm $mform, ?stdClass $bigbluebuttondata = null, 126 string $suffix = null): array { 127 return self::get_instances_implementing(mod_form_addons::class, [$mform, $bigbluebuttondata, $suffix]); 128 } 129 130 /** 131 * Get additional join tables for instance when extension activated 132 * 133 * @return array of additional tables names. They all have a field called bigbluebuttonbnid that identifies the bbb instance. 134 */ 135 public static function get_join_tables(): array { 136 global $DB; 137 // We use cache here as it will be called very often. 138 $cache = cache::make('mod_bigbluebuttonbn', 'subplugins'); 139 if ($cache->get('additionaltables')) { 140 return $cache->get('additionaltables'); 141 } 142 $additionaltablesclasses = self::get_instances_implementing(mod_instance_helper::class); 143 $tables = []; 144 foreach ($additionaltablesclasses as $tableclass) { 145 $tables = array_merge($tables, $tableclass->get_join_tables() ?? []); 146 } 147 // Warning and removal for tables that do not have the bigbluebuttonid field. 148 foreach ($tables as $index => $table) { 149 $columns = $DB->get_columns($table); 150 if (empty($columns['bigbluebuttonbnid'])) { 151 debugging("get_instance_additional_tables: $table should have a column named bigbluebuttonid"); 152 unset($tables[$index]); 153 } 154 } 155 $cache->set('additionaltables', $tables); 156 return $tables; 157 } 158 159 /** 160 * Add instance processing 161 * 162 * @param stdClass $data data to persist 163 * @return void 164 */ 165 public static function add_instance(stdClass $data): void { 166 $formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class); 167 foreach ($formmanagersclasses as $fmclass) { 168 $fmclass->add_instance($data); 169 } 170 } 171 172 /** 173 * Update instance processing 174 * 175 * @param stdClass $data data to persist 176 * @return void 177 */ 178 public static function update_instance(stdClass $data): void { 179 $formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class); 180 foreach ($formmanagersclasses as $fmclass) { 181 $fmclass->update_instance($data); 182 } 183 } 184 185 /** 186 * Delete instance processing 187 * 188 * @param int $id instance id 189 * @return void 190 */ 191 public static function delete_instance(int $id): void { 192 $formmanagersclasses = self::get_instances_implementing(mod_instance_helper::class); 193 foreach ($formmanagersclasses as $fmclass) { 194 $fmclass->delete_instance($id); 195 } 196 } 197 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body