Should be used in the KAF hosted module
'); + $adminsetting->plugin = KALTURA_PLUGIN_NAME; + $settings->add($adminsetting); + + $url = new moodle_url('/local/kaltura/download_log.php'); + $adminsetting = new admin_setting_configcheckbox('enable_logging', get_string('trace_log', 'local_kaltura'), get_string('trace_log_desc', 'local_kaltura', $url->out()), 0); + $adminsetting->plugin = KALTURA_PLUGIN_NAME; + $settings->add($adminsetting); + + $adminsetting = new admin_setting_configcheckbox('enable_submission', get_string('enable_submission', 'local_kaltura'), get_string('enable_submission_desc', 'local_kaltura'), 0); + $adminsetting->plugin = KALTURA_PLUGIN_NAME; + $settings->add($adminsetting); + + $settings->hide_if(KALTURA_PLUGIN_NAME.'/adminsecret', KALTURA_PLUGIN_NAME .'/lti_version', 'eq', LTI_VERSION_1P3); + $settings->hide_if(KALTURA_PLUGIN_NAME.'/client_id', KALTURA_PLUGIN_NAME. '/lti_version', 'eq', LTI_VERSION_1); + + if (isset($configsettings->migration_yes) && $configsettings->migration_yes == 1) { + $url = new moodle_url('/local/kaltura/migration.php'); + + $adminsetting = new admin_setting_heading('migration_url_heading', get_string('migration_notice', 'local_kaltura', $url->out()), ''); + $adminsetting->plugin = KALTURA_PLUGIN_NAME; + $settings->add($adminsetting); + } +} + diff --git a/local/kaltura/styles.css b/local/kaltura/styles.css new file mode 100644 index 0000000000000..420652c8b1185 --- /dev/null +++ b/local/kaltura/styles.css @@ -0,0 +1,33 @@ +/* stylelint-disable declaration-no-important */ + +#contentframe { + border-style: none; +} + +#panelcontentframecontainer { + overflow: scroll; + -webkit-overflow-scrolling: touch; + height: 100%; + width: 100%; +} + +@media (max-width: 767px) { + .kaltura-player-container { + width: 100%; + position: relative; + /* aspect ratio - 16:9 */ + padding-top: 56.25%; + /* player's control bar */ + padding-bottom: 30px; + } + + .kaltura-player-iframe { + position: absolute; + width: 100% !important; + height: 100% !important; + top: 0; + left: 0; + right: 0; + bottom: 0; + } +} \ No newline at end of file diff --git a/local/kaltura/test.php b/local/kaltura/test.php new file mode 100644 index 0000000000000..faa03e5325084 --- /dev/null +++ b/local/kaltura/test.php @@ -0,0 +1,27 @@ +set_url($url); +$PAGE->set_context($context); + +echo $OUTPUT->header(); + +require_capability('moodle/site:config', $context); + +$session = local_kaltura_login(true, '', 2); + +if ($session) { + echo 'Connection successful'; +} else { + echo 'Connection not successful'; +} diff --git a/local/kaltura/tests/locallib_test.php b/local/kaltura/tests/locallib_test.php new file mode 100644 index 0000000000000..70682990b1fda --- /dev/null +++ b/local/kaltura/tests/locallib_test.php @@ -0,0 +1,1261 @@ +. + +/** + * Kaltura local library phpunit tests. + * + * @package local_kaltura + * @author Remote-Learner.net Inc + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright (C) 2014 Remote Learner.net Inc http://www.remote-learner.net + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot.'/local/kaltura/locallib.php'); +require_once($CFG->dirroot.'/local/kaltura/API/KalturaTypes.php'); + +/** + * @group local_kaltura + */ +class local_kaltura_locallib_testcase extends advanced_testcase { + /** + * A Dataprovider method, providing invalid data. + */ + public function mymedia_test_required_param_fail() { + $data = array( + array( + array( + // 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MYMEDIA_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + // 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MYMEDIA_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + // 'width' => 100, + 'height' => 100, + 'module' => KAF_MYMEDIA_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ), + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + // 'height' => 100, + 'module' => KAF_MYMEDIA_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + // 'module' => '', + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MYMEDIA_MODULE, + // 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MYMEDIA_MODULE, + 'course' => new stdClass(), + // 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MYMEDIA_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + // 'custom_publishdata' => '', + ) + ), + array( + array( + // Non-numeric. + 'id' => 'string', + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MYMEDIA_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + // Non-numeric. + 'width' => 'string', + 'height' => 100, + 'module' => KAF_MYMEDIA_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + // Non-numeric. + 'height' => 'string', + 'module' => KAF_MYMEDIA_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MYMEDIA_MODULE, + // Not an object. + 'course' => 'string', + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MYMEDIA_MODULE, + 'course' => new stdClass(), + // Non-numeric. + 'cmid' => 'string', + 'custom_publishdata' => '', + ) + ), + ); + return $data; + } + + /** + * This function tests whether the parameters contain all required fields. + * @param array $data An array of parameters that are invalid. + * @dataProvider mymedia_test_required_param_fail + */ + public function test_local_kaltura_validate_mymedia_required_params_fail($data) { + $this->resetAfterTest(true); + $result = local_kaltura_validate_mymedia_required_params($data); + $this->assertFalse($result); + } + + /** + * A Dataprovider method, providing invalid data. + */ + public function mediagallery_test_required_param_fail() { + $data = array( + array( + array( + // 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + // 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + // 'width' => 100, + 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ), + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + // 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + // 'module' => '', + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + // 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + 'course' => new stdClass(), + // 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + // 'custom_publishdata' => '', + ) + ), + array( + array( + // Non-numeric. + 'id' => 'string', + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + // Non-numeric. + 'width' => 'string', + 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + // Non-numeric. + 'height' => 'string', + 'module' => KAF_MEDIAGALLERY_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + // Not an object. + 'course' => 'string', + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + 'course' => new stdClass(), + // Non-numeric. + 'cmid' => 'string', + 'custom_publishdata' => '', + ) + ), + ); + return $data; + } + + /** + * This function tests whether the parameters contain all required fields. + * @param array $data An array of parameters that are invalid. + * @dataProvider mediagallery_test_required_param_fail + */ + public function test_local_kaltura_validate_coursegallery_required_params_fail($data) { + $this->resetAfterTest(true); + $result = local_kaltura_validate_mediagallery_required_params($data); + $this->assertFalse($result); + } + + /** + * This function tests whether the parameters contain all required fields. + */ + public function test_local_kaltura_validate_coursegallery_required_params() { + $this->resetAfterTest(true); + $data = array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_MEDIAGALLERY_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '' + ); + + $result = local_kaltura_validate_mediagallery_required_params($data); + $this->assertTrue($result); + } + + /** + * A Dataprovider method, providing invalid data. + */ + public function browseembed_test_required_param_fail() { + $data = array( + array( + array( + // 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + // 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + // 'width' => 100, + 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ), + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + // 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + // 'module' => '', + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + // 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + 'course' => new stdClass(), + // 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + // 'custom_publishdata' => '', + ) + ), + array( + array( + // Non-numeric. + 'id' => 'string', + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + // Non-numeric. + 'width' => 'string', + 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + // Non-numeric. + 'height' => 'string', + 'module' => KAF_BROWSE_EMBED_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + // Not an object. + 'course' => 'string', + 'cmid' => 0, + 'custom_publishdata' => '', + ) + ), + array( + array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + 'course' => new stdClass(), + // Non-numeric. + 'cmid' => 'string', + 'custom_publishdata' => '', + ) + ), + ); + return $data; + } + + /** + * This function tests whether the parameters contain all required fields. + * @param array $data An array of parameters that are invalid. + * @dataProvider browseembed_test_required_param_fail + */ + public function test_local_kaltura_validate_browseembed_required_params_fail($data) { + $result = local_kaltura_validate_browseembed_required_params($data); + $this->assertFalse($result); + } + + /** + * This function tests whether the parameters contain all required fields. + */ + public function test_local_kaltura_validate_browseembed_required_params() { + $data = array( + 'id' => 1, + 'title' => 'title', + 'width' => 100, + 'height' => 100, + 'module' => KAF_BROWSE_EMBED_MODULE, + 'course' => new stdClass(), + 'cmid' => 0, + 'custom_publishdata' => '' + ); + + $result = local_kaltura_validate_browseembed_required_params($data); + $this->assertTrue($result); + } + + /** + * This function tests the return values for @see local_kaltura_get_lti_launch_container(). + */ + public function test_local_kaltura_get_lti_launch_container() { + global $CFG; + + $this->resetAfterTest(true); + $result = local_kaltura_get_lti_launch_container(true); + $this->assertEquals(LTI_LAUNCH_CONTAINER_EMBED, $result); + + $result = local_kaltura_get_lti_launch_container(false); + $this->assertEquals(LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS, $result); + } + + /** + * Data provider for different KAF service names. + */ + public function module_name_test_fail() { + $data = array( + array('nothing'), + array(''), + array(1234) + ); + return $data; + } + + /** + * Test validating available KAF services. + * @param array $data An array of parameters that are invalid. + * @dataProvider module_name_test_fail + */ + public function test_local_kaltura_validate_kaf_module_request_fail($data) { + $this->resetAfterTest(true); + $result = local_kaltura_validate_kaf_module_request($data); + $this->assertFalse($result); + } + + /** + * Data provider for different KAF service names. + */ + public function module_name_test() { + $data = array( + array('mymedia'), + array('coursegallery'), + ); + return $data; + } + + /** + * Test validating available KAF services. + * @param array $data An array of parameters that is valid. + * @dataProvider module_name_test + */ + public function test_local_kaltura_validate_kaf_module_request($data) { + $this->resetAfterTest(true); + $result = local_kaltura_validate_kaf_module_request($data); + $this->assertTrue($result); + } + + /** + * Test that the correct end point is returned. + */ + public function test_local_kaltura_get_endpoint() { + $this->resetAfterTest(true); + $result = local_kaltura_get_endpoint(KAF_MYMEDIA_MODULE); + $this->assertEquals(KAF_MYMEDIA_ENDPOINT, $result); + $result = local_kaltura_get_endpoint(KAF_MEDIAGALLERY_MODULE); + $this->assertEquals(KAF_MEDIAGALLERY_ENDPOINT, $result); + $result = local_kaltura_get_endpoint(KAF_BROWSE_EMBED_MODULE); + $this->assertEquals(KAF_BROWSE_EMBED_ENDPOINT, $result); + } + + /** + * This functions tests properties of the mod_lti object returned by local_kaltura_format_lti_instance_object(). + */ + public function test_local_kaltura_format_lti_instance_object() { + $this->resetAfterTest(true); + + set_config('partner_id', 12345, 'local_kaltura'); + set_config('adminsecret', 54321, 'local_kaltura'); + set_config('kaf_uri', 'http://phpunit.tests/local_kaltura/tests/', 'local_kaltura'); + $expecteduri = 'phpunit.tests/local_kaltura/tests'; + + $configsettings = get_config('local_kaltura'); + + $course = new stdClass(); + $course->id = 1; + $param = array( + 'id' => 1, + 'module' => 'mymedia', + 'course' => $course, + 'title' => 'phpunit test', + 'width' => 100, + 'height' => 100, + 'cmid' => 0, + 'intro' => 'phpunitintro', + ); + + $expected = new stdClass(); + + $result = local_kaltura_format_lti_instance_object($param); + + $this->assertObjectHasAttribute('course', $result); + $this->assertObjectHasAttribute('id', $result); + $this->assertObjectHasAttribute('name', $result); + $this->assertObjectHasAttribute('intro', $result); + $this->assertObjectHasAttribute('instructorchoicesendname', $result); + $this->assertObjectHasAttribute('instructorchoicesendemailaddr', $result); + $this->assertObjectHasAttribute('instructorcustomparameters', $result); + $this->assertObjectHasAttribute('instructorchoiceacceptgrades', $result); + $this->assertObjectHasAttribute('instructorchoiceallowroster', $result); + $this->assertObjectHasAttribute('resourcekey', $result); + $this->assertObjectHasAttribute('password', $result); + $this->assertObjectHasAttribute('toolurl', $result); + $this->assertObjectHasAttribute('securetool', $result); + $this->assertObjectHasAttribute('forcessl', $result); + $this->assertObjectHasAttribute('cmid', $result); + + $this->assertEquals(1, $result->course); + $this->assertEquals(1, $result->id); + $this->assertEquals('phpunit test', $result->name); + $this->assertEquals('phpunitintro', $result->intro); + $this->assertEquals(LTI_SETTING_ALWAYS, $result->instructorchoicesendname); + $this->assertEquals(LTI_SETTING_ALWAYS, $result->instructorchoicesendemailaddr); + $this->assertEquals('', $result->instructorcustomparameters); + $this->assertEquals(LTI_SETTING_NEVER, $result->instructorchoiceacceptgrades); + $this->assertEquals(LTI_SETTING_NEVER, $result->instructorchoiceallowroster); + $this->assertEquals($configsettings->partner_id, $result->resourcekey); + $this->assertEquals($configsettings->adminsecret, $result->password); + $this->assertEquals('http://phpunit.tests/local_kaltura/tests/'.KAF_MYMEDIA_ENDPOINT, $result->toolurl); + $this->assertEquals('https://phpunit.tests/local_kaltura/tests/'.KAF_MYMEDIA_ENDPOINT, $result->securetool); + $this->assertEquals(0, $result->cmid); + } + + /** + * Test the formatting of an array to be used by mod_lti. + */ + public function test_local_kaltura_format_typeconfig() { + $this->resetAfterTest(true); + + $param = new stdClass(); + $param->instructorchoicesendname = 0; + $param->instructorchoicesendemailaddr = 'a@a.com'; + $param->instructorcustomparameters = ''; + $param->instructorchoiceacceptgrades = 0; + $param->instructorchoiceallowroster = 3; + + $expected = array( + 'sendname' => 0, + 'sendemailaddr' => 'a@a.com', + 'customparameters' => '', + 'acceptgrades' => 0, + 'allowroster' => 3, + 'launchcontainer' => 2, + ); + + $result = local_kaltura_format_typeconfig($param); + + ksort($result); + ksort($expected); + $this->assertEquals($expected, $result); + + // call function specifying no blocks to be displayed + $expected['launchcontainer'] = 3; + $result = local_kaltura_format_typeconfig($param, false); + $this->assertEquals($expected, $result); + } + + /** + * Data provider for different KAF service names. + */ + public function invalid_logging_data() { + $data = array( + array( + 'string' + ), + array( + 1 + ), + array( + new stdClass() + ) + ); + return $data; + } + + /** + * Test logging. + * @param array $data Sample data from data provider method. + * @dataProvider module_name_test + */ + public function test_local_kaltura_log_data_invalid_logging_data($data) { + $this->resetAfterTest(true); + + $result = local_kaltura_log_data('mymedia', 'http://localhost', $data, true); + $this->assertFalse($result); + } + + /** + * Test logging. + */ + public function test_local_kaltura_log_data_invalid_module() { + $this->resetAfterTest(true); + + $json = '{"courses":[{"courseId":123,"courseName":"something","roles":"ltirole1,ltirole2"},{"courseId":456,"courseName":"else","roles":"ltirole3,ltirole4"}]'; + $data = array(); + $data['test1'] = 'test2'; + $data['test3'] = 'test4'; + $data['json'] = $json; + + $result = local_kaltura_log_data('invalidmodule', 'http://localhost', $data, true); + $this->assertFalse($result); + } + + /** + * Test logging. + */ + public function test_local_kaltura_log_data_logging_request_data() { + global $DB; + + $this->resetAfterTest(true); + + $json = '{"courses":[{"courseId":123,"courseName":"something","roles":"ltirole1,ltirole2"},{"courseId":456,"courseName":"else","roles":"ltirole3,ltirole4"}]'; + $data = array(); + $data['test1'] = 'test2'; + $data['test3'] = 'test4'; + $data['json'] = $json; + + $result = local_kaltura_log_data(KAF_MYMEDIA_MODULE, 'http://localhost', $data, true); + $this->assertTrue($result); + $record = $DB->get_record('local_kaltura_log', array('module'=> 'mymedia')); + + $this->assertObjectHasAttribute('id', $record); + + $this->assertObjectHasAttribute('module', $record); + $this->assertEquals(KAF_MYMEDIA_MODULE, $record->module); + + $this->assertObjectHasAttribute('type', $record); + $this->assertEquals(KALTURA_LOG_REQUEST, $record->type); + + $this->assertObjectHasAttribute('endpoint', $record); + $this->assertEquals('http://localhost', $record->endpoint); + + $this->assertObjectHasAttribute('data', $record); + $this->assertEquals(serialize($data), $record->data); + + $this->assertObjectHasAttribute('timecreated', $record); + $this->assertNotEquals(0, $record); + + $result = local_kaltura_log_data(KAF_MEDIAGALLERY_MODULE, 'http://localhost', $data, true); + $this->assertTrue($result); + + $record = $DB->get_record('local_kaltura_log', array('module'=> 'coursegallery')); + + $this->assertObjectHasAttribute('id', $record); + + $this->assertObjectHasAttribute('module', $record); + $this->assertEquals(KAF_MEDIAGALLERY_MODULE, $record->module); + + $this->assertObjectHasAttribute('type', $record); + $this->assertEquals(KALTURA_LOG_REQUEST, $record->type); + + $this->assertObjectHasAttribute('endpoint', $record); + $this->assertEquals('http://localhost', $record->endpoint); + + $this->assertObjectHasAttribute('data', $record); + $this->assertEquals(serialize($data), $record->data); + + $this->assertObjectHasAttribute('timecreated', $record); + $this->assertNotEquals(0, $record); + } + + /** + * Test logging. + */ + public function test_local_kaltura_log_data_logging_response_data() { + global $DB; + + $this->resetAfterTest(true); + + $json = '{"courses":[{"courseId":123,"courseName":"something","roles":"ltirole1,ltirole2"},{"courseId":456,"courseName":"else","roles":"ltirole3,ltirole4"}]'; + $data = array(); + $data['test1'] = 'test2'; + $data['test3'] = 'test4'; + $data['json'] = $json; + + $result = local_kaltura_log_data('phpunit response', 'http://localhost', $data, false); + $this->assertTrue($result); + + $record = $DB->get_record('local_kaltura_log', array('module'=> 'phpunit response')); + + $this->assertObjectHasAttribute('id', $record); + + $this->assertObjectHasAttribute('module', $record); + $this->assertEquals('phpunit response', $record->module); + + $this->assertObjectHasAttribute('type', $record); + $this->assertEquals(KALTURA_LOG_RESPONSE, $record->type); + + $this->assertObjectHasAttribute('endpoint', $record); + $this->assertEquals('http://localhost', $record->endpoint); + + $this->assertObjectHasAttribute('data', $record); + $this->assertEquals(serialize($data), $record->data); + + $this->assertObjectHasAttribute('timecreated', $record); + $this->assertNotEquals(0, $record); + } + + /** + * Data provider for test_local_kaltura_format_uri(). + */ + public function uri_format_test() { + return array( + array('http://phpunit.tests/local_kaltura/tests'), + array('http://phpunit.tests/local_kaltura/tests/'), + array('https://phpunit.tests/local_kaltura/tests'), + array('https://phpunit.tests/local_kaltura/tests/'), + array('https://www.phpunit.tests/local_kaltura/tests/'), + ); + } + + /** + * Test local_kaltura_format_uri(). + * @param string $url differnt URI formats. + * @dataProvider uri_format_test + */ + public function test_local_kaltura_format_uri($uri) { + $result = local_kaltura_format_uri($uri); + $this->assertEquals('phpunit.tests/local_kaltura/tests', $result); + } + + /** + * Test local_kaltura_get_kaf_publishing_data(). This test creates 4 coures. Enrolls the user as an editing teacher in coures 1 and 4, + * then enrolls the user as a student in course 2. + */ + public function test_local_kaltura_get_kaf_publishing_data_for_non_admin() { + global $DB; + + $this->resetAfterTest(true); + + // Get the roles. + $sql = "SELECT shortname,id + FROM {role}"; + $role = (array) $DB->get_records_sql($sql); + // Create a test user. + $user = $this->getDataGenerator()->create_user(); + + // Create test courses and assign the user roles. + $coursedata = array( + 'fullname' => 'Test 1', + 'shortname' => 'T1' + ); + $courseone = $this->getDataGenerator()->create_course($coursedata); + + $this->getDataGenerator()->enrol_user($user->id, $courseone->id, $role['editingteacher']->id, 'manual'); + + $coursedata = array( + 'fullname' => 'Test 2', + 'shortname' => 'T2' + ); + $coursetwo = $this->getDataGenerator()->create_course($coursedata); + + $this->getDataGenerator()->enrol_user($user->id, $coursetwo->id, $role['student']->id, 'manual'); + + $coursedata = array( + 'fullname' => 'Test 3', + 'shortname' => 'T3' + ); + $coursethree = $this->getDataGenerator()->create_course($coursedata); + + $coursedata = array( + 'fullname' => 'Test 4', + 'shortname' => 'T4' + ); + $coursefour = $this->getDataGenerator()->create_course($coursedata); + + $this->getDataGenerator()->enrol_user($user->id, $coursefour->id, $role['editingteacher']->id, 'manual'); + + // Set the current user to the test user. + advanced_testcase::setuser($user->id); + + $result = local_kaltura_get_kaf_publishing_data(); + + $json = '{"courses":[{"courseId":"'.$courseone->id.'","courseName":"'.$courseone->fullname.'","courseShortName":"'.$courseone->shortname.'","roles":"Instructor"}'; + $json .= ',{"courseId":"'.$coursetwo->id.'","courseName":"'.$coursetwo->fullname.'","courseShortName":"'.$coursetwo->shortname.'","roles":"Learner"}'; + $json .= ',{"courseId":"'.$coursefour->id.'","courseName":"'.$coursefour->fullname.'","courseShortName":"'.$coursefour->shortname.'","roles":"Instructor"}]}'; + + $this->assertEquals(base64_encode($json), $result); + } + + /** + * Test local_kaltura_get_kaf_publishing_data(). This test creates 4 coures. Enrolls the user as an editing teacher in coures 1 and 4, + * then enrolls the user as a student in course 2. + */ + public function test_local_kaltura_get_kaf_publishing_data_for_admin() { + $this->resetAfterTest(true); + + // Create test courses and assign the user roles. + $coursedata = array( + 'fullname' => 'Test 1', + 'shortname' => 'T1' + ); + $courseone = $this->getDataGenerator()->create_course($coursedata); + + $coursedata = array( + 'fullname' => 'Test 2', + 'shortname' => 'T2' + ); + $coursetwo = $this->getDataGenerator()->create_course($coursedata); + + $coursedata = array( + 'fullname' => 'Test 3', + 'shortname' => 'T3' + ); + $coursethree = $this->getDataGenerator()->create_course($coursedata); + + $coursedata = array( + 'fullname' => 'Test 4', + 'shortname' => 'T4' + ); + $coursefour = $this->getDataGenerator()->create_course($coursedata); + + advanced_testcase::setAdminUser(); + + $result = local_kaltura_get_kaf_publishing_data(); + + $json = '{"courses":[{"courseId":"'.$courseone->id.'","courseName":"'.$courseone->fullname.'","courseShortName":"'.$courseone->shortname.'","roles":"urn:lti:sysrole:ims\/lis\/Administrator"}'; + $json .= ',{"courseId":"'.$coursetwo->id.'","courseName":"'.$coursetwo->fullname.'","courseShortName":"'.$coursetwo->shortname.'","roles":"urn:lti:sysrole:ims\/lis\/Administrator"}'; + $json .= ',{"courseId":"'.$coursethree->id.'","courseName":"'.$coursethree->fullname.'","courseShortName":"'.$coursethree->shortname.'","roles":"urn:lti:sysrole:ims\/lis\/Administrator"}'; + $json .= ',{"courseId":"'.$coursefour->id.'","courseName":"'.$coursefour->fullname.'","courseShortName":"'.$coursefour->shortname.'","roles":"urn:lti:sysrole:ims\/lis\/Administrator"}]}'; + + $this->assertEquals(base64_encode($json), $result); + } + + /** + * Data provider for test_local_kaltura_url_contains_configured_hostname_fail(). + */ + public function uri_hostname_tests_invalid() { + return array( + array('http://phpunit1.tests/local_kaltura/tests'), + array('http://phpunit.2tests/local_kaltura/tests/'), + array('http://tests.phpunit/local_kaltura/tests/'), + ); + } + + /** + * Test test_local_kaltura_url_contains_configured_hostname_fail(). + * @param string $url differnt URI formats. + * @dataProvider uri_hostname_tests_invalid + */ + public function test_local_kaltura_url_contains_configured_hostname_fail($url) { + $this->resetAfterTest(true); + + set_config('kaf_uri', 'phpunit.tests', 'local_kaltura'); + + $result = local_kaltura_url_contains_configured_hostname($url); + $this->assertFalse($result); + } + + /** + * Data provider for test_local_kaltura_url_contains_configured_hostname(). + */ + public function uri_hostname_tests_valid() { + return array( + array('http://phpunit.tests/local_kaltura/'), + array('https://phpunit.tests/local_kaltura/tests/'), + ); + } + + /** + * Test test_local_kaltura_url_contains_configured_hostname(). + * @param string $url differnt URI formats. + * @dataProvider uri_hostname_tests_valid + */ + public function test_local_kaltura_url_contains_configured_hostname($url) { + $this->resetAfterTest(true); + + set_config('kaf_uri', 'phpunit.tests', 'local_kaltura'); + + $result = local_kaltura_url_contains_configured_hostname($url); + $this->assertTrue($result); + } + + /** + * Test local_kaltura_add_protocol_to_url(). + */ + public function test_local_kaltura_add_protocol_to_url() { + $expected = 'http://example.com'; + $url = local_kaltura_add_protocol_to_url($expected); + $this->assertEquals($expected, $url); + + $expected = 'https://example.com'; + $url = local_kaltura_add_protocol_to_url($expected); + $this->assertEquals($expected, $url); + + $expected = 'http://example.com'; + $url = local_kaltura_add_protocol_to_url('example.com'); + $this->assertEquals($expected, $url); + + $url = local_kaltura_add_protocol_to_url('htdddtp://example.com'); + $this->assertEmpty($url); + } + + /** + * Test local_kaltura_add_kaf_uri_token(). + */ + public function test_local_kaltura_add_kaf_uri_token() { + $this->resetAfterTest(true); + + // Set KAF URI to HTTP. + $url = 'http://this-is-a-test-with-phpunit.com'; + set_config('kaf_uri', $url, 'local_kaltura'); + + $path = '/phpunit/testing/test1/'; + $expected = $url.$path; + + // Test HTTP returns with the confgirued URL in HTTP. + $actual = 'http://'.KALTURA_URI_TOKEN.$path; + $result = local_kaltura_add_kaf_uri_token($actual); + + $this->assertEquals($expected, $result); + + // Test HTTPS returns with the configured URL in HTTP. + $actual = 'https://'.KALTURA_URI_TOKEN.$path; + $result = local_kaltura_add_kaf_uri_token($actual); + + $this->assertEquals($expected, $result); + + // Set KAF URI to HTTPS. + $url = 'https://this-is-a-test-with-phpunit.com'; + set_config('kaf_uri', $url, 'local_kaltura'); + $expected = $url.$path; + + // Test HTTP returns with the confgirued URL in HTTPS. + $actual = 'http://'.KALTURA_URI_TOKEN.$path; + $result = local_kaltura_add_kaf_uri_token($actual); + + $this->assertEquals($expected, $result); + + // Test HTTPS returns with the confgirued URL in HTTPS. + $actual = 'https://'.KALTURA_URI_TOKEN.$path; + $result = local_kaltura_add_kaf_uri_token($actual); + + $this->assertEquals($expected, $result); + } + + /** + * Test local_kaltura_encode_object_for_storage() + */ + public function test_local_kaltura_encode_object_for_storage() { + $data = array(); + $result = local_kaltura_encode_object_for_storage($data); + $this->assertEquals('', $result); + + $data = new stdClass(); + $result = local_kaltura_encode_object_for_storage($data); + $this->assertEquals('', $result); + + $data = 'hello'; + $result = local_kaltura_encode_object_for_storage($data); + $this->assertEquals('', $result); + + $data = ''; + $result = local_kaltura_encode_object_for_storage($data); + $this->assertEquals('', $result); + + $data = new stdClass(); + $data->one = 'abc'; + $data->two = 'def'; + $result = local_kaltura_encode_object_for_storage($data); + $expected = base64_encode(serialize($data)); + $this->assertEquals($expected, $result); + + $data = array('one' => 'abc', 'two' => 'def'); + $result = local_kaltura_encode_object_for_storage($data); + $expected = base64_encode(serialize($data)); + $this->assertEquals($expected, $result); + } + + /** + * Test local_kaltura_decode_object_for_storage() + */ + public function test_local_kaltura_decode_object_for_storage() { + $result = local_kaltura_decode_object_for_storage(''); + $this->assertEquals('', $result); + + $expected = new stdClass(); + $expected->one = 'abc'; + $expected->two = 'def'; + $data = base64_encode(serialize($expected)); + $result = local_kaltura_decode_object_for_storage($data); + $this->assertEquals($expected, $result); + + $expected = array('one' => 'abc', 'two' => 'def'); + $data = base64_encode(serialize($expected)); + $result = local_kaltura_decode_object_for_storage($data); + $this->assertEquals($expected, $result); + } + + /** + * Test local_kaltura_convert_kaltura_base_entry_object() + */ + public function test_local_kaltura_convert_kaltura_base_entry_object() { + $result = local_kaltura_convert_kaltura_base_entry_object(new stdclass()); + $this->assertFalse($result); + + // Test converting a video entry. + $time = time(); + $base = new KalturaMediaEntry(); + $base->dataUrl = 'http:/phpunittest.com'; + $base->width = 100; + $base->height = 200; + $base->id = 'phpunit'; + $base->name = 'phpunit title'; + $base->thumbnailUrl = 'http://phpunittest.com/thumb'; + $base->duration = 300; + $base->description = 'phpunit description'; + $base->createdAt = $time; + $base->creatorId = 'phpunit user'; + $base->tags = ''; + + $expected = new stdClass(); + $expected->url = ''; + $expected->dataurl = 'http:/phpunittest.com'; + $expected->width = 100; + $expected->height = 200; + $expected->entryid = 'phpunit'; + $expected->title = 'phpunit title'; + $expected->thumbnailurl = 'http://phpunittest.com/thumb'; + $expected->duration = 300; + $expected->description = 'phpunit description'; + $expected->createdat = $time; + $expected->owner = 'phpunit user'; + $expected->tags = ''; + $expected->showtitle = 'on'; + $expected->showdescription = 'on'; + $expected->showowner = 'on'; + $expected->player = ''; + $expected->size = ''; + + $result = local_kaltura_convert_kaltura_base_entry_object($base); + $this->assertEquals($expected, $result); + } +} diff --git a/local/kaltura/tests/migrationlib_test.php b/local/kaltura/tests/migrationlib_test.php new file mode 100644 index 0000000000000..787db66afa10a --- /dev/null +++ b/local/kaltura/tests/migrationlib_test.php @@ -0,0 +1,194 @@ +. + +/** + * Kaltura local_kaltura_migration_progress class phpunit tests. + * + * @package local_kaltura + * @author Remote-Learner.net Inc + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright (C) 2014 Remote Learner.net Inc http://www.remote-learner.net + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot.'/local/kaltura/locallib.php'); +require_once($CFG->dirroot.'/local/kaltura/migrationlib.php'); + +/** + * @group local_kaltura + */ +class local_kaltura_migrationlib_testcase extends advanced_testcase { + /** + * Test initialization of config values. + */ + public function test_initialization_of_config_values() { + $this->resetAfterTest(true); + + $result = new local_kaltura_migration_progress(); + $result = null; + + $configsettings = get_config(KALTURA_PLUGIN_NAME); + + $this->assertObjectHasAttribute('migrationstarted', $configsettings); + $this->assertObjectHasAttribute('existingcategoryrun', $configsettings); + $this->assertObjectHasAttribute('sharedcategoryrun', $configsettings); + $this->assertObjectHasAttribute('categoriescreated', $configsettings); + $this->assertObjectHasAttribute('entriesmigrated', $configsettings); + $this->assertObjectHasAttribute('kafcategoryrootid', $configsettings); + $this->assertEquals(0, $configsettings->migrationstarted); + $this->assertEquals(0, $configsettings->existingcategoryrun); + $this->assertEquals(0, $configsettings->sharedcategoryrun); + $this->assertEquals(0, $configsettings->categoriescreated); + $this->assertEquals(0, $configsettings->entriesmigrated); + $this->assertEquals(0, $configsettings->kafcategoryrootid); + } + + /** + * Test existingcategory accessor functions. + */ + public function test_existingcategoryrun() { + $this->resetAfterTest(true); + + $result = new local_kaltura_migration_progress(); + local_kaltura_migration_progress::set_existingcategoryrun(11); + $value = local_kaltura_migration_progress::get_existingcategoryrun(); + + $this->assertEquals(11, $value); + + $result = null; + $value = get_config(KALTURA_PLUGIN_NAME, 'existingcategoryrun'); + + $this->assertEquals(11, $value); + } + + /** + * Test sharedcategoryrun accessor functions. + */ + public function test_sharedcategoryrun() { + $this->resetAfterTest(true); + + $result = new local_kaltura_migration_progress(); + local_kaltura_migration_progress::set_sharedcategoryrun(11); + $value = local_kaltura_migration_progress::get_sharedcategoryrun(); + + $this->assertEquals(11, $value); + + $result = null; + $value = get_config(KALTURA_PLUGIN_NAME, 'sharedcategoryrun'); + + $this->assertEquals(11, $value); + } + + /** + * Test kafcategoryrootid functions. + */ + public function test_kafcategoryrootid() { + $this->resetAfterTest(true); + + $result = new local_kaltura_migration_progress(); + local_kaltura_migration_progress::set_kafcategoryrootid(11); + $value = local_kaltura_migration_progress::get_kafcategoryrootid(); + + $this->assertEquals(11, $value); + + $result = null; + $value = get_config(KALTURA_PLUGIN_NAME, 'kafcategoryrootid'); + + $this->assertEquals(11, $value); + } + + /** + * Test categoriescreated functions. + */ + public function test_categoriescreated() { + $this->resetAfterTest(true); + + $result = new local_kaltura_migration_progress(); + local_kaltura_migration_progress::increment_categoriescreated(); + $value = local_kaltura_migration_progress::get_categoriescreated(); + + $this->assertEquals(1, $value); + + $result = null; + $value = get_config(KALTURA_PLUGIN_NAME, 'categoriescreated'); + + $this->assertEquals(1, $value); + } + + /** + * Test entriesmigrated functions. + */ + public function test_entriesmigrated() { + $this->resetAfterTest(true); + + $result = new local_kaltura_migration_progress(); + local_kaltura_migration_progress::increment_entriesmigrated(); + $value = local_kaltura_migration_progress::get_entriesmigrated(); + + $this->assertEquals(1, $value); + + $result = null; + $value = get_config(KALTURA_PLUGIN_NAME, 'entriesmigrated'); + + $this->assertEquals(1, $value); + } + + /** + * Test migrationstarted functions. + */ + public function test_migrationstarted() { + $this->resetAfterTest(true); + + $result = new local_kaltura_migration_progress(); + local_kaltura_migration_progress::init_migrationstarted(); + $value = local_kaltura_migration_progress::get_migrationstarted(); + + $this->assertNotEquals(0, $value); + + $result = null; + $value = get_config(KALTURA_PLUGIN_NAME, 'migrationstarted'); + + $this->assertNotEquals(0, $value); + } + + /** + * Test resetting all migration progress properties functions. + */ + public function test_resetall() { + $this->resetAfterTest(true); + + $result = new local_kaltura_migration_progress(); + local_kaltura_migration_progress::set_existingcategoryrun(11); + local_kaltura_migration_progress::set_sharedcategoryrun(11); + local_kaltura_migration_progress::increment_categoriescreated(); + local_kaltura_migration_progress::increment_entriesmigrated(); + local_kaltura_migration_progress::init_migrationstarted(); + local_kaltura_migration_progress::set_kafcategoryrootid(11); + local_kaltura_migration_progress::reset_all(); + + $result = null; + + $configsettings = get_config(KALTURA_PLUGIN_NAME); + $this->assertEquals(0, $configsettings->migrationstarted); + $this->assertEquals(0, $configsettings->existingcategoryrun); + $this->assertEquals(0, $configsettings->sharedcategoryrun); + $this->assertEquals(0, $configsettings->categoriescreated); + $this->assertEquals(0, $configsettings->entriesmigrated); + $this->assertEquals(0, $configsettings->kafcategoryrootid); + } +} \ No newline at end of file diff --git a/local/kaltura/version.php b/local/kaltura/version.php new file mode 100644 index 0000000000000..05dc484b3fcae --- /dev/null +++ b/local/kaltura/version.php @@ -0,0 +1,62 @@ +. + +/** + * Kaltura version file. + * + * @package local_kaltura + * @author Remote-Learner.net Inc + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL + * @copyright (C) 2014 Remote Learner.net Inc http://www.remote-learner.net + */ + +if (!defined('MOODLE_INTERNAL')) { + die('Direct access to this script is forbidden.'); +} + +$plugin->version = 2024100702; +$plugin->component = 'local_kaltura'; +$plugin->release = 'Kaltura release 4.5.1'; +$plugin->requires = 2024042200; +$plugin->maturity = MATURITY_STABLE; + +try { + global $DB; + + $localKalturaPluginVersionRecord = $DB->get_records_select('config_plugins', "plugin = 'local_kaltura' AND name = 'version'"); + + $kalturaPluginVersion = ""; + if ($localKalturaPluginVersionRecord) { + $localKalturaPluginVersionRecordValue = array_pop($localKalturaPluginVersionRecord); + $kalturaPluginVersion = $localKalturaPluginVersionRecordValue->value; + } + + $updatedVersion = null; + if ($kalturaPluginVersion == 20210620311) { + $updatedVersion = 2021051700; + } else if ($kalturaPluginVersion == 20201215310 || $kalturaPluginVersion == 20210620310) { + $updatedVersion = 2020110900; + } else if ($kalturaPluginVersion == 2020070539 || $kalturaPluginVersion == 2020121539 || $kalturaPluginVersion == 2021062039) { + $updatedVersion = 2020061500; + } + + if (!empty($updatedVersion)) { + $pluginsRecords = $DB->get_records_select('config_plugins', "plugin in ('local_kaltura', 'local_kalturamediagallery', 'local_mymedia', 'atto_kalturamedia','block_kalturamediagallery','filter_kaltura','tinymce_kalturamedia','mod_kalvidassign','mod_kalvidres', 'tiny_kalturamedia') AND name = 'version' AND value = '$kalturaPluginVersion'"); + + foreach ($pluginsRecords as $record) { + $record->value = $updatedVersion; + $DB->update_record('config_plugins', $record); + } + } +} catch (Exception $e) {} diff --git a/local/kaltura/yui/build/moodle-local_kaltura-lticontainer/moodle-local_kaltura-lticontainer-debug.js b/local/kaltura/yui/build/moodle-local_kaltura-lticontainer/moodle-local_kaltura-lticontainer-debug.js new file mode 100644 index 0000000000000..4479d14bca651 --- /dev/null +++ b/local/kaltura/yui/build/moodle-local_kaltura-lticontainer/moodle-local_kaltura-lticontainer-debug.js @@ -0,0 +1,203 @@ +YUI.add('moodle-local_kaltura-lticontainer', function (Y, NAME) { + +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see'; + if ($teacher) { + echo $this->output->user_picture($teacher); + } + echo ' | '; + echo '';
+ echo ' ';
+ if ($teacher) {
+ echo ' ';
+ echo ''.fullname($teacher).' ';
+ }
+ echo ''.userdate($gradedate).' ';
+ echo ' | ';
+ echo '
'; + echo ' | ';
+ echo ' ';
+ echo get_string("grade").': '.$grade->str_long_grade;
+ echo ' ';
+ echo '';
+
+ echo '';
+ echo $grade->str_feedback;
+ echo ' ';
+ echo ' |