Differences Between: [Versions 400 and 402] [Versions 401 and 402]
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 17 /** 18 * BBB Library tests class trait. 19 * 20 * @package mod_bigbluebuttonbn 21 * @copyright 2018 - present, Blindside Networks Inc 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 * @author Laurent David (laurent@call-learning.fr) 24 */ 25 namespace mod_bigbluebuttonbn\test; 26 27 use context_module; 28 use mod_bigbluebuttonbn\instance; 29 use mod_bigbluebuttonbn\local\proxy\recording_proxy; 30 use mod_bigbluebuttonbn\meeting; 31 use stdClass; 32 use testing_data_generator; 33 use core\plugininfo\mod; 34 35 trait testcase_helper_trait { 36 /** @var testing_data_generator|null */ 37 protected $generator = null; 38 39 /** @var object|null */ 40 protected $course = null; 41 42 /** 43 * Convenience function to create an instance of a bigbluebuttonactivty. 44 * 45 * @param stdClass|null $course course to add the module to 46 * @param array $params Array of parameters to pass to the generator 47 * @param array $options Array of options to pass to the generator 48 * @return array($context, $cm, $instance) Testable wrapper around the assign class. 49 */ 50 protected function create_instance(?stdClass $course = null, array $params = [], array $options = []): array { 51 // Prior to creating the instance, make sure that the BigBlueButton module is enabled. 52 $modules = \core_plugin_manager::instance()->get_plugins_of_type('mod'); 53 if (!$modules['bigbluebuttonbn']->is_enabled()) { 54 mod::enable_plugin('bigbluebuttonbn', true); 55 } 56 57 if (!$course) { 58 $course = $this->get_course(); 59 } 60 $params['course'] = $course->id; 61 $options['visible'] = 1; 62 $instance = $this->getDataGenerator()->create_module('bigbluebuttonbn', $params, $options); 63 list($course, $cm) = get_course_and_cm_from_instance($instance, 'bigbluebuttonbn'); 64 $context = context_module::instance($cm->id); 65 66 return [$context, $cm, $instance]; 67 } 68 69 /** 70 * Get the matching form data 71 * 72 * @param stdClass $bbactivity the current bigbluebutton activity 73 * @param stdClass|null $course the course or null (taken from $this->get_course() if null) 74 * @return mixed 75 */ 76 protected function get_form_data_from_instance(stdClass $bbactivity, ?stdClass $course = null): object { 77 global $USER; 78 79 if (!$course) { 80 $course = $this->get_course(); 81 } 82 $this->setAdminUser(); 83 $bbactivitycm = get_coursemodule_from_instance('bigbluebuttonbn', $bbactivity->id); 84 list($cm, $context, $module, $data, $cw) = get_moduleinfo_data($bbactivitycm, $course); 85 $this->setUser($USER); 86 return $data; 87 } 88 89 /** 90 * Get or create course if it does not exist 91 * 92 * @return stdClass|null 93 */ 94 protected function get_course(): stdClass { 95 if (!$this->course) { 96 $this->course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]); 97 } 98 return $this->course; 99 } 100 101 /** 102 * Generate a course, several students and several groups 103 * 104 * @param stdClass $courserecord 105 * @param int $numstudents 106 * @param int $numteachers 107 * @param int $groupsnum 108 * @return array 109 */ 110 protected function setup_course_students_teachers(stdClass $courserecord, int $numstudents, int $numteachers, 111 int $groupsnum): array { 112 global $DB; 113 $generator = $this->getDataGenerator(); 114 $course = $generator->create_course($courserecord); 115 $groups = []; 116 for ($i = 0; $i < $groupsnum; $i++) { 117 $groups[] = $generator->create_group(['courseid' => $course->id]); 118 } 119 $generator->create_group(['courseid' => $course->id]); 120 $generator->create_group(['courseid' => $course->id]); 121 122 $roleids = $DB->get_records_menu('role', null, '', 'shortname, id'); 123 124 $students = []; 125 for ($i = 0; $i < $numstudents; $i++) { 126 $student = $generator->create_user(); 127 $generator->enrol_user($student->id, $course->id, $roleids['student']); 128 $groupid = $groups[$i % $groupsnum]->id; 129 groups_add_member($groupid, $student->id); 130 $students[] = $student; 131 } 132 133 $teachers = []; 134 for ($i = 0; $i < $numteachers; $i++) { 135 $teacher = $generator->create_user(); 136 $generator->enrol_user($teacher->id, $course->id, $roleids['teacher']); 137 $groupid = $groups[$i % $groupsnum]->id; 138 groups_add_member($groupid, $teacher->id); 139 $teachers[] = $teacher; 140 } 141 $bbactivity = $generator->create_module( 142 'bigbluebuttonbn', 143 ['course' => $course->id], 144 ['visible' => true]); 145 146 get_fast_modinfo(0, 0, true); 147 return [$course, $groups, $students, $teachers, $bbactivity, $roleids]; 148 } 149 150 /** 151 * This test requires mock server to be present. 152 */ 153 protected function initialise_mock_server(): void { 154 if (!defined('TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER')) { 155 $this->markTestSkipped( 156 'The TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER constant must be defined to run mod_bigbluebuttonbn tests' 157 ); 158 } 159 try { 160 $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn')->reset_mock(); 161 } catch (\moodle_exception $e) { 162 $this->markTestSkipped( 163 'Cannot connect to the mock server for this test. Make sure that TEST_MOD_BIGBLUEBUTTONBN_MOCK_SERVER points 164 to an active Mock server' 165 ); 166 } 167 } 168 169 /** 170 * Create an return an array of recordings 171 * 172 * @param instance $instance 173 * @param array $recordingdata array of recording information 174 * @param array $additionalmeetingdata 175 * @return array 176 */ 177 protected function create_recordings_for_instance(instance $instance, array $recordingdata = [], 178 $additionalmeetingdata = []): array { 179 $recordings = []; 180 $bbbgenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn'); 181 // Create the meetings on the mock server, so like this we can find the recordings. 182 $meeting = new meeting($instance); 183 $meeting->update_cache(); // The meeting has just been created but we need to force fetch info from the server. 184 if (!$meeting->is_running()) { 185 $additionalmeetingdata = array_merge([ 186 'instanceid' => $instance->get_instance_id(), 187 'groupid' => $instance->get_group_id() 188 ], $additionalmeetingdata); 189 $bbbgenerator->create_meeting($additionalmeetingdata); 190 } 191 foreach ($recordingdata as $rindex => $data) { 192 $recordings[] = $bbbgenerator->create_recording( 193 array_merge([ 194 'bigbluebuttonbnid' => $instance->get_instance_id(), 195 'groupid' => $instance->get_group_id() 196 ], $data) 197 ); 198 } 199 return $recordings; 200 } 201 202 /** 203 * Create an activity which includes a set of recordings. 204 * 205 * @param stdClass $course 206 * @param int $type 207 * @param array $recordingdata array of recording information 208 * @param int $groupid 209 * @return array 210 */ 211 protected function create_activity_with_recordings(stdClass $course, int $type, array $recordingdata, int $groupid = 0): array { 212 $generator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn'); 213 214 $activity = $generator->create_instance([ 215 'course' => $course->id, 216 'type' => $type 217 ]); 218 219 $instance = instance::get_from_instanceid($activity->id); 220 $instance->set_group_id($groupid); 221 $recordings = $this->create_recordings_for_instance($instance, $recordingdata); 222 return [ 223 'course' => $course, 224 'activity' => $activity, 225 'recordings' => $recordings, 226 ]; 227 } 228 229 /** 230 * Create a course, users and recording from dataset given in an array form 231 * 232 * @param array $dataset 233 * @return mixed 234 */ 235 protected function create_from_dataset(array $dataset) { 236 list('type' => $type, 'recordingsdata' => $recordingsdata, 'groups' => $groups, 237 'users' => $users) = $dataset; 238 $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn'); 239 240 $coursedata = empty($groups) ? [] : ['groupmodeforce' => true, 'groupmode' => $dataset['coursemode'] ?? VISIBLEGROUPS]; 241 $this->course = $this->getDataGenerator()->create_course($coursedata); 242 243 foreach ($users as $userdata) { 244 $this->getDataGenerator()->create_and_enrol($this->course, $userdata['role'], ['username' => $userdata['username']]); 245 } 246 247 if ($groups) { 248 foreach ($groups as $groupname => $students) { 249 $group = $this->getDataGenerator()->create_group(['name' => $groupname, 'courseid' => $this->course->id]); 250 foreach ($students as $username) { 251 $user = \core_user::get_user_by_username($username); 252 $this->getDataGenerator()->create_group_member(['userid' => $user->id, 'groupid' => $group->id]); 253 } 254 } 255 } 256 $instancesettings = [ 257 'course' => $this->course->id, 258 'type' => $type, 259 'name' => 'Example', 260 ]; 261 if (!empty($dataset['additionalsettings'])) { 262 $instancesettings = array_merge($instancesettings, $dataset['additionalsettings']); 263 } 264 $activity = $plugingenerator->create_instance($instancesettings); 265 $instance = instance::get_from_instanceid($activity->id); 266 foreach ($recordingsdata as $groupname => $recordings) { 267 if ($groups) { 268 $groupid = groups_get_group_by_name($this->course->id, $groupname); 269 $instance->set_group_id($groupid); 270 } 271 $this->create_recordings_for_instance($instance, $recordings); 272 } 273 return $activity->id; 274 } 275 276 /** 277 * Create the legacy log entries for this task. 278 * 279 * @param instance $instance 280 * @param int $userid 281 * @param int $count 282 * @param bool $importedrecordings 283 * @param bool $withremoterecordings create recording on the mock server ? 284 * @return array 285 */ 286 protected function create_log_entries( 287 instance $instance, 288 int $userid, 289 int $count = 30, 290 bool $importedrecordings = false, 291 bool $withremoterecordings = true 292 ): array { 293 // Create log entries for each (30 for the ungrouped, 30 for the grouped). 294 $baselogdata = [ 295 'courseid' => $instance->get_course_id(), 296 'userid' => $userid, 297 'log' => $importedrecordings ? 'Import' : 'Create', 298 'meta' => json_encode(['record' => true]), 299 'imported' => $importedrecordings, 300 ]; 301 $plugingenerator = $this->getDataGenerator()->get_plugin_generator('mod_bigbluebuttonbn'); 302 for ($i = 0; $i < $count; $i++) { 303 if ($withremoterecordings) { 304 // Create a recording. 305 $starttime = time() - random_int(HOURSECS, WEEKSECS); 306 $recording = $plugingenerator->create_recording([ 307 'bigbluebuttonbnid' => $instance->get_instance_id(), 308 'groupid' => $instance->get_group_id(), 309 'starttime' => $starttime, 310 'endtime' => $starttime + HOURSECS, 311 ], true); // Create them on the server only. 312 313 $baselogdata['meetingid'] = $instance->get_meeting_id(); 314 if ($importedrecordings) { 315 // Fetch the data. 316 $data = recording_proxy::fetch_recordings([$recording->recordingid]); 317 $data = end($data); 318 if ($data) { 319 $metaonly = array_filter($data, function($key) { 320 return strstr($key, 'meta_'); 321 }, ARRAY_FILTER_USE_KEY); 322 } else { 323 $data = []; 324 } 325 $baselogdata['meta'] = json_encode(array_merge([ 326 'recording' => array_diff_key($data, $metaonly), 327 ], $metaonly)); 328 329 } else { 330 $baselogdata['meta'] = json_encode((object) ['record' => true]); 331 } 332 } 333 // Insert the legacy log entry. 334 $logs[] = $plugingenerator->create_log(array_merge($baselogdata, [ 335 'bigbluebuttonbnid' => $instance->get_instance_id(), 336 'timecreated' => time() - random_int(HOURSECS, WEEKSECS) + (HOURSECS * $i), 337 ])); 338 } 339 340 return $logs; 341 } 342 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body