diff --git a/addtranscription.php b/addtranscription.php index c663b7af..db7712e1 100644 --- a/addtranscription.php +++ b/addtranscription.php @@ -16,12 +16,12 @@ /** * Add new transcription to the event + * * @package block_opencast * @copyright 2022 Farbod Zamani Boroujeni, ELAN e.V. * @author Farbod Zamani Boroujeni * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); use block_opencast\local\addtranscription_form; use block_opencast\local\apibridge; @@ -29,6 +29,8 @@ use core\output\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); + global $PAGE, $OUTPUT, $CFG, $SITE; require_once($CFG->dirroot . '/repository/lib.php'); diff --git a/addvideo.php b/addvideo.php index 2e9d1d21..7b307c65 100644 --- a/addvideo.php +++ b/addvideo.php @@ -21,7 +21,6 @@ * @copyright 2017 Andreas Wagner, SYNERGY LEARNING * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); use block_opencast\local\addvideo_form; use block_opencast\local\apibridge; @@ -29,6 +28,7 @@ use block_opencast\local\upload_helper; use core\output\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); global $PAGE, $OUTPUT, $CFG, $USER, $SITE, $DB; diff --git a/backup/moodle2/backup_opencast_block_task.class.php b/backup/moodle2/backup_opencast_block_task.class.php index 21bd5199..a669a5ea 100644 --- a/backup/moodle2/backup_opencast_block_task.class.php +++ b/backup/moodle2/backup_opencast_block_task.class.php @@ -20,6 +20,7 @@ * @package block_opencast * @copyright 2017 Andreas Wagner, SYNERGY LEARNING * @author Andreas Wagner + * @author Farbod Zamani Boroujeni (2024) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -40,6 +41,7 @@ * @package block_opencast * @copyright 2017 Andreas Wagner, SYNERGY LEARNING * @author Andreas Wagner + * @author Farbod Zamani Boroujeni (2024) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class backup_opencast_block_task extends backup_block_task { @@ -55,15 +57,38 @@ protected function define_my_settings() { if (importvideosmanager::is_enabled_and_working_for_coreimport($ocinstance->id) == true) { // Get default value, to include opencast video. - $defaultimportvalue = get_config('block_opencast', 'importvideoscoredefaultvalue_' . $ocinstance->id); + $defaultimportvalue = boolval(get_config('block_opencast', 'importvideoscoredefaultvalue_' . $ocinstance->id)); + + // Get import mode, to determine whether to offer selective feature or not. + // Duplicate videos mode is capable of selection. + // ACL Change mode is not, due to changing the acl of the whole series at once. + $importmode = get_config('block_opencast', 'importmode_' . $ocinstance->id); + // Check, whether there are course videos available. $apibridge = apibridge::get_instance($ocinstance->id); $courseid = $this->get_courseid(); $seriestobackup = $apibridge->get_course_series($courseid); + // A flag to check if the main include is added. + $ocinstanceisincluded = false; + $includesettingname = 'opencast_videos_' . $ocinstance->id . '_included'; + // Course level setting inclusion. + $setting = new backup_block_opencast_setting( + $includesettingname, + base_setting::IS_BOOLEAN, + $defaultimportvalue + ); + $setting->get_ui()->set_label(get_string('backupopencastvideos', 'block_opencast', $ocinstance->name)); + foreach ($seriestobackup as $series) { - $result = $apibridge->get_series_videos($series->series); + $seriesobj = $apibridge->get_series_by_identifier($series->series, false); + + if (empty($seriesobj)) { + continue; + } + + $result = $apibridge->get_series_videos($seriesobj->identifier); $videostobackup = []; foreach ($result->videos as $video) { @@ -73,12 +98,72 @@ protected function define_my_settings() { } if (count($videostobackup) > 0) { - $setting = new backup_block_opencast_setting('opencast_videos_include_' . $ocinstance->id, - base_setting::IS_BOOLEAN, boolval($defaultimportvalue)); - $setting->get_ui()->set_label(get_string('backupopencastvideos', 'block_opencast', $ocinstance->name)); - $this->add_setting($setting); - $this->plan->get_setting('blocks')->add_dependency($setting); - break; + // Here we make sure that the main inclusion happens only once. + if (!$ocinstanceisincluded) { + $this->add_setting($setting); + $this->plan->get_setting('blocks')->add_dependency($setting); + $ocinstanceisincluded = true; + } + // Section Level setting for series. + $seriessettingname = + 'opencast_videos_' . $ocinstance->id . '_series_' . $seriesobj->identifier . '_included'; + $seriessetting = new backup_block_opencast_setting( + $seriessettingname, + base_setting::IS_BOOLEAN, + $defaultimportvalue, + backup_block_opencast_setting::SECTION_LEVEL + ); + $stringobj = new \stdClass(); + $stringobj->title = $seriesobj->title; + // To avoid cluttered ui and ugly display, we present only the last 6 digit of the id. + $stringobj->identifier = '***' . substr($seriesobj->identifier, -6); + $seriessettinglabel = get_string('importvideos_wizard_series_cb_title', 'block_opencast', $stringobj); + // Adding the help button to emphasize that in ACL Change only series selection is possible. + if ($importmode === 'acl') { + $seriessetting->set_help( + 'importvideos_wizard_unselectableeventreason', + 'block_opencast' + ); + $videolist = []; + foreach ($videostobackup as $videotobackup) { + // To avoid cluttered ui and ugly display, we present only the last 6 digit of the id. + $stringobj = new \stdClass(); + $stringobj->title = $videotobackup->title; + $stringobj->identifier = '***' . substr($videotobackup->identifier, -6); + $videolist[] = "- " . get_string('importvideos_wizard_event_cb_title', + 'block_opencast', $stringobj); + } + // The label does not support any html, so we need to use the text for line breaks. + $seriessetting->get_ui()->set_text(join('
', $videolist)); + } + $seriessetting->get_ui()->set_label($seriessettinglabel); + + $this->add_setting($seriessetting); + $this->get_setting($includesettingname)->add_dependency($seriessetting, + setting_dependency::DISABLED_NOT_CHECKED); + + if ($importmode !== 'acl') { + foreach ($videostobackup as $bkvideo) { + // Activity level settings for episodes. + $episodesetting = new backup_block_opencast_setting( + 'opencast_videos_' . $ocinstance->id . '_episode_' . $bkvideo->identifier . '_included', + base_setting::IS_BOOLEAN, + $defaultimportvalue, + backup_block_opencast_setting::ACTIVITY_LEVEL, + backup_block_opencast_setting::VISIBLE, + ); + $stringobj = new \stdClass(); + $stringobj->title = $bkvideo->title; + // To avoid cluttered ui and ugly display, we present only the last 6 digit of the id. + $stringobj->identifier = '***' . substr($bkvideo->identifier, -6); + $episodesetting->get_ui()->set_label( + get_string('importvideos_wizard_event_cb_title', 'block_opencast', $stringobj) + ); + $this->add_setting($episodesetting); + $this->get_setting($seriessettingname)->add_dependency($episodesetting, + setting_dependency::DISABLED_NOT_CHECKED); + } + } } } } @@ -90,14 +175,49 @@ protected function define_my_settings() { */ protected function define_my_steps() { $ocinstances = settings_api::get_ocinstances(); + $courseid = $this->get_courseid(); foreach ($ocinstances as $ocinstance) { - if (!$this->setting_exists('opencast_videos_include_' . $ocinstance->id)) { + $importmode = get_config('block_opencast', 'importmode_' . $ocinstance->id); + $includesettingname = 'opencast_videos_' . $ocinstance->id . '_included'; + // Checking the main level inclusion. + if (!$this->setting_exists($includesettingname)) { continue; } - if ($this->get_setting_value('opencast_videos_include_' . $ocinstance->id)) { - $this->add_step(new backup_opencast_block_structure_step('opencast_structure_' . $ocinstance->id, - 'opencast_' . $ocinstance->id . '.xml')); + // If the main level is included. + if ($this->get_setting_value($includesettingname)) { + // Get API Bridge to get data. + $apibridge = apibridge::get_instance($ocinstance->id); + $backupstructuredata = []; + + // Get course series to loop through and verify. + $seriestobackup = $apibridge->get_course_series($courseid); + foreach ($seriestobackup as $series) { + // Checking the series inclusion. + $seriessettingname = + 'opencast_videos_' . $ocinstance->id . '_series_' . $series->series . '_included'; + if (!$this->setting_exists($seriessettingname) || empty($this->get_setting_value($seriessettingname))) { + continue; + } + + // Get the series video to lopp through and check the inclusion. + $result = $apibridge->get_series_videos($series->series); + foreach ($result->videos as $video) { + // Checking the episode inclusion. + $episodesettingname = 'opencast_videos_' . $ocinstance->id . '_episode_' . $video->identifier . '_included'; + if ($importmode === 'acl' || $this->setting_exists($episodesettingname) && + $this->get_setting_value($episodesettingname)) { + // We store the episode of series in backupstructuredata. + $backupstructuredata[$series->series][] = $video->identifier; + } + } + } + + // Pass the collected backup data into the step. + $backupstep = new backup_opencast_block_structure_step('opencast_structure_' . $ocinstance->id, + 'opencast_' . $ocinstance->id . '.xml'); + $backupstep->set_data($backupstructuredata); + $this->add_step($backupstep); } } } diff --git a/backup/moodle2/backup_opencast_stepslib.php b/backup/moodle2/backup_opencast_stepslib.php index ea900c58..de56ad76 100644 --- a/backup/moodle2/backup_opencast_stepslib.php +++ b/backup/moodle2/backup_opencast_stepslib.php @@ -19,6 +19,8 @@ * * @package block_opencast * @copyright 2018 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @author Farbod Zamani Boroujeni (2024) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -36,6 +38,8 @@ * * @package block_opencast * @copyright 2018 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @author Farbod Zamani Boroujeni (2024) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class backup_opencast_block_structure_step extends backup_block_structure_step { @@ -47,9 +51,48 @@ class backup_opencast_block_structure_step extends backup_block_structure_step { * @throws base_step_exception * @throws dml_exception */ + + /** @var array data The information about backup structure */ + private $data = []; + + /** + * Returns data. + * @return array data + */ + public function get_data() { + return $this->data; + } + + /** + * Sets data. + * @see backup_opencast_block_task::define_my_steps() Usage. + * @param array $data the information about backup structure. + */ + public function set_data($data) { + $this->data = $data; + } + + /** + * Defines the structure of the block backup. + * + * @return backup_nested_element + */ protected function define_structure() { + + // Extracting ocinstanceid from the structure. $ocinstanceid = intval(ltrim($this->get_name(), "opencast_structure_")); + // Extracting selected series and events from the data structure. + $selectedseriestobackup = []; + $selectedvideostobackup = []; + if (!empty($this->data)) { + foreach ($this->data as $seriesid => $eventslist) { + if (!empty($eventslist)) { + $selectedseriestobackup[] = $seriesid; + $selectedvideostobackup = array_merge($eventslist, $selectedvideostobackup); + } + } + } // Root. $opencast = new backup_nested_element('opencast'); @@ -79,7 +122,10 @@ protected function define_structure() { $list = []; // Add course videos. foreach ($coursevideos as $video) { - $list[] = (object)['eventid' => $video->identifier]; + // Check if they are selected. + if (in_array($video->identifier, $selectedvideostobackup)) { + $list[] = (object)['eventid' => $video->identifier]; + } } // Define sources. @@ -96,7 +142,10 @@ protected function define_structure() { $list = []; foreach ($courseseries as $series) { - $list[] = (object)['seriesid' => $series->series]; + // Check if it is selected. + if (in_array($series->series, $selectedseriestobackup)) { + $list[] = (object)['seriesid' => $series->series]; + } } $serieselement->set_source_array($list); diff --git a/backup/moodle2/restore_opencast_block_task.class.php b/backup/moodle2/restore_opencast_block_task.class.php index 8f6050f3..c39a14fa 100644 --- a/backup/moodle2/restore_opencast_block_task.class.php +++ b/backup/moodle2/restore_opencast_block_task.class.php @@ -19,6 +19,7 @@ * * @package block_opencast * @copyright 2018 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -34,6 +35,11 @@ /** * Define settings of the restore tasks for the opencast block. + * + * @package block_opencast + * @copyright 2018 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class restore_opencast_block_task extends restore_block_task { @@ -84,8 +90,18 @@ protected function define_my_settings() { $canrestore = $this->can_restore_events($ocinstance->id); $locktype = ($canrestore) ? backup_setting::NOT_LOCKED : backup_setting::LOCKED_BY_CONFIG; - $setting = new restore_block_opencast_setting('opencast_videos_include_' . $ocinstance->id, base_setting::IS_BOOLEAN, - $canrestore, backup_setting::VISIBLE, $locktype); + // NOTE: At the moment we don't offer any selection here, + // because it is a job that needs to be done in backup step more efficiently. + + $settingname = 'opencast_videos_' . $ocinstance->id . '_included'; + $setting = new restore_block_opencast_setting( + $settingname, + base_setting::IS_BOOLEAN, + $canrestore, + restore_block_opencast_setting::COURSE_LEVEL, + backup_setting::VISIBLE, + $locktype + ); $setting->get_ui()->set_label(get_string('restoreopencastvideos', 'block_opencast', $ocinstance->name)); $this->add_setting($setting); @@ -103,12 +119,13 @@ protected function define_my_steps() { } foreach ($ocinstances as $ocinstance) { + $settingname = 'opencast_videos_' . $ocinstance->id . '_included'; // Settings, does not exists, if opencast system does not support copying workflow. - if (!$this->setting_exists('opencast_videos_include_' . $ocinstance->id)) { + if (!$this->setting_exists($settingname)) { continue; } - if (!$this->get_setting_value('opencast_videos_include_' . $ocinstance->id) && + if (!$this->get_setting_value($settingname) && ($this->plan->get_mode() != backup::MODE_IMPORT)) { continue; } diff --git a/backup/moodle2/restore_opencast_stepslib.php b/backup/moodle2/restore_opencast_stepslib.php index 1101bab9..a2b3a6a3 100644 --- a/backup/moodle2/restore_opencast_stepslib.php +++ b/backup/moodle2/restore_opencast_stepslib.php @@ -19,6 +19,8 @@ * * @package block_opencast * @copyright 2018 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @author Farbod Zamani Boroujeni (2024) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); @@ -28,12 +30,15 @@ use block_opencast\local\apibridge; use block_opencast\local\event; use block_opencast\local\notifications; +use block_opencast\local\importvideosmanager; /** * Define all the restore steps that will be used by the restore opencast block task. * * @package block_opencast * @copyright 2018 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @author Farbod Zamani Boroujeni (2024) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class restore_opencast_block_structure_step extends restore_structure_step { @@ -51,6 +56,12 @@ class restore_opencast_block_structure_step extends restore_structure_step { private $ocinstanceid; /** @var string Duplication or ACL import mode */ private $importmode; + /** @var string Restore unique id */ + private $restoreuniqueid; + /** @var array Series ids that were not able to be saved as for import mapping */ + private $missingimportmappingseriesids = []; + /** @var array Event ids that were not able to be saved as for import mapping */ + private $missingimportmappingeventids = []; /** * Function that will return the structure to be processed by this restore_step. @@ -65,6 +76,10 @@ protected function define_structure() { // Check, target series. $courseid = $this->get_courseid(); + // Generate restore unique identifier, + // to keep track of restore session in later stages e.g. module mapping and repair. + $this->restoreuniqueid = uniqid('oc_restore_' . $ocinstanceid . '_' . $courseid); + $paths = []; // Get apibridge instance. @@ -76,8 +91,8 @@ protected function define_structure() { // If ACL Change is the mode. if ($importmode == 'acl') { - // We process the rest in the process import. - $paths[] = new restore_path_element('import', '/block/opencast/import'); + // Processing series, grouped by import. + $paths[] = new restore_path_element('import', '/block/opencast/import', true); $paths[] = new restore_path_element('series', '/block/opencast/import/series'); } else if ($importmode == 'duplication') { // In case Duplicating Events is the mode. @@ -92,88 +107,142 @@ protected function define_structure() { } $this->series[] = $seriesid; + // Processing events, grouped by main opencast, in order to get series as well. + $paths[] = new restore_path_element('opencast', '/block/opencast', true); + $paths[] = new restore_path_element('events', '/block/opencast/events'); $paths[] = new restore_path_element('event', '/block/opencast/events/event'); + + // Adding import property here, to access series. + $paths[] = new restore_path_element('import', '/block/opencast/import'); + $paths[] = new restore_path_element('series', '/block/opencast/import/series'); } return $paths; } /** - * Process the backuped data. + * Process the backuped data mainly duplicate events mode. * - * @param array $data the event identifier + * @param array $data * @return void + * @throws base_step_exception + * @throws dml_exception + * @throws moodle_exception */ - public function process_event($data) { - $data = (object)$data; - - // Collect eventids for notification. - $this->backupeventids[] = $data->eventid; + public function process_opencast($data) { + $data = (object) $data; - // Exit when there is no course series. - if (!$this->series) { + // Check if all required information is available. + if (empty($this->series) || !isset($data->import) || !isset($data->events) || + empty($data->import[0]['series']) || empty($data->events['event'])) { + // Nothing to do here, as the data is not enough. return; } - // Check, whether event exists on opencast server. + // Get API Bridge to check the event or series validity. $apibridge = apibridge::get_instance($this->ocinstanceid); - // Only duplicate, when the event exists in opencast. - if (!$apibridge->get_already_existing_event([$data->eventid])) { - $this->missingeventids[] = $data->eventid; - } else { - $courseid = $this->get_courseid(); - event::create_duplication_task($this->ocinstanceid, $courseid, $this->series[0], $data->eventid); + $courseid = $this->get_courseid(); + + // Proceed with the backedup series, to save the mapping and repair the modules. + foreach ($data->import[0]['series'] as $series) { + $seriesid = $series['seriesid'] ?? null; + // Skip when there is no original series, or the series is invalid. + if (empty($seriesid) || !$apibridge->ensure_series_is_valid($seriesid)) { + continue; + } + // Record series mapping for module fix. + $issaved = importvideosmanager::save_series_import_mapping_record( + $this->ocinstanceid, + $courseid, + $seriesid, + $this->restoreuniqueid + ); + if (!$issaved) { + $this->missingimportmappingseriesids[] = $seriesid; + } + } + + foreach ($data->events['event'] as $event) { + $eventid = $event['eventid'] ?? null; + $this->backupeventids[] = $eventid; + + // Only duplicate, when the event exists in opencast. + if (!$apibridge->get_already_existing_event([$eventid])) { + $this->missingeventids[] = $eventid; + } else { + // Check for and record the module mappings. + $issaved = importvideosmanager::save_episode_import_mapping_record( + $this->ocinstanceid, + $courseid, + $eventid, + $this->restoreuniqueid + ); + if (!$issaved) { + $this->missingimportmappingeventids[] = $eventid; + } + + // Add the duplication task. + event::create_duplication_task( + $this->ocinstanceid, + $courseid, + $this->series[0], + $eventid, + false, + null, + $this->restoreuniqueid + ); + } } } /** - * Restore a series. + * Restore series under import path which contains series, mainly for ACL Change import mode. * @param object $data + * @return void * @throws base_step_exception * @throws dml_exception * @throws moodle_exception */ - public function process_series($data) { + public function process_import($data) { global $USER; - $data = (object)$data; + $data = (object) $data; + + // Collect sourcecourseid for further processing. + $this->sourcecourseid = $data->sourcecourseid; // Check, target series. $courseid = $this->get_courseid(); - // Get apibridge instance, to ensure series validity and edit series mapping. - $apibridge = apibridge::get_instance($this->ocinstanceid); - - // Exit when there is no original series, no course course id and the original seriesid is not valid. - // Also exit when the course by any chance wanted to restore itself. - if (!$data->seriesid && !$data->sourcecourseid && - $apibridge->ensure_series_is_valid($data->seriesid) && $courseid == $data->sourcecourseid) { + // First level checker. + // Exit when the course by any chance wanted to restore itself. + if (!empty($this->sourcecourseid) && $courseid == $this->sourcecourseid) { return; } - // Collect series id for notifications. - $this->series[] = $data->seriesid; + // Get apibridge instance, to ensure series validity and edit series mapping. + $apibridge = apibridge::get_instance($this->ocinstanceid); - // Assign Seriesid to new course and change ACL. - $this->aclchanged[] = $apibridge->import_series_to_course_with_acl_change($courseid, $data->seriesid, $USER->id); - } + if (isset($data->series)) { + foreach ($data->series as $series) { + $seriesid = $series['seriesid']; - /** - * Process the backuped data for import. - * - * @param array $data The import data needed for ACL change mode. - * @return void - */ - public function process_import($data) { + // Second level checker. + // Exit when there is no original series, or the series is invalid. + if (empty($seriesid) || !$apibridge->ensure_series_is_valid($seriesid)) { + continue; + } - $data = (object)$data; + // Collect series id for notifications. + $this->series[] = $seriesid; - // Collect sourcecourseid for notifications. - $this->sourcecourseid = $data->sourcecourseid; + // Assign Seriesid to new course and change ACL. + $this->aclchanged[] = $apibridge->import_series_to_course_with_acl_change($courseid, $seriesid, $USER->id); + } + } } - /** * Send notifications after restore, to inform admins about errors. * @@ -200,6 +269,31 @@ public function after_restore() { if ($this->missingeventids) { notifications::notify_missing_events($courseid, $this->missingeventids); } + + // Notify those series that were unable to have an import mapping record. + if (!empty($this->missingimportmappingseriesids)) { + notifications::notify_missing_import_mapping($courseid, $this->missingimportmappingseriesids, 'series'); + } + + // Notify those events that were unable to have an import mapping record. + if (!empty($this->missingimportmappingeventids)) { + notifications::notify_missing_import_mapping($courseid, $this->missingimportmappingeventids, 'events'); + } + + // Set the completion for mapping. + $report = importvideosmanager::set_import_mapping_completion_status($this->restoreuniqueid); + // If it is report has values, that means there were failures and we report them. + if (is_array($report)) { + notifications::notify_incompleted_import_mapping_records($courseid, $report); + } + + // After all, we proceed to fix the series modules because they should not wait for the duplicate workflow to finish! + importvideosmanager::fix_imported_series_modules_in_new_course( + $this->ocinstanceid, + $courseid, + $this->series[0], + $this->restoreuniqueid + ); } else if ($this->importmode == 'acl') { // The required data or the conditions to perform ACL change were missing. if (!$this->sourcecourseid) { diff --git a/backup/moodle2/settings/block_backup_setting.class.php b/backup/moodle2/settings/block_backup_setting.class.php index d351142a..ac623283 100644 --- a/backup/moodle2/settings/block_backup_setting.class.php +++ b/backup/moodle2/settings/block_backup_setting.class.php @@ -19,6 +19,8 @@ * * @package block_opencast * @copyright 2018 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @author Farbod Zamani Boroujeni (2024) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -27,6 +29,8 @@ * * @package block_opencast * @copyright 2018 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @author Farbod Zamani Boroujeni (2024) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class backup_block_opencast_setting extends backup_setting { @@ -38,14 +42,45 @@ class backup_block_opencast_setting extends backup_setting { * @param string $name Name of the setting * @param string $vtype Type of the setting * @param mixed $value Value of the setting + * @param int $level Level of the setting * @param bool $visibility Is the setting visible in the UI * @param int $status Status of the setting with regards to the locking + * @param array $attributes The arrtibutes of uisetting element */ - public function __construct($name, $vtype, $value = null, $visibility = self::VISIBLE, $status = self::NOT_LOCKED) { + public function __construct($name, $vtype, $value = null, $level = self::COURSE_LEVEL, $visibility = self::VISIBLE, + $status = self::NOT_LOCKED, $attributes = null) { - $this->level = self::COURSE_LEVEL; + // Set level. + $this->level = $level; + // In case attributes is empty, we set the default. + if (empty($attributes)) { + $attributes = [ + 'class' => 'block-opencast-include', + ]; + } + + // Parent construction. parent::__construct($name, $vtype, $value, $visibility, $status); - $this->uisetting = new backup_setting_ui_checkbox($this, $name, null, ['class' => 'block-opencast-include']); + + // Making setting ui component (checkbox). + $uisetting = new backup_setting_ui_checkbox( + $this, + $name, + null, + $attributes + ); + // Set the icon to make the setting option more recognizable. + $uisetting->set_icon( + new image_icon( + 'monologo', + get_string('pluginname', 'block_opencast'), + 'block_opencast', + ['class' => 'iconlarge icon-post ml-1'] + ) + ); + + // Set the setting ui component. + $this->uisetting = $uisetting; } } diff --git a/batchupload.php b/batchupload.php index c368d570..c19fe58c 100644 --- a/batchupload.php +++ b/batchupload.php @@ -22,7 +22,6 @@ * @author Farbod Zamani Boroujeni * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); use block_opencast\local\batchupload_form; use block_opencast\local\apibridge; @@ -30,6 +29,7 @@ use block_opencast\local\upload_helper; use core\output\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); global $PAGE, $OUTPUT, $CFG, $USER, $SITE, $DB; @@ -132,7 +132,7 @@ $customdata = [ 'courseid' => $courseid, 'metadata_catalog' => $batchmetadatacatalog, - 'eventdefaults' => $usereventdefaults, 'ocinstanceid' => $ocinstanceid + 'eventdefaults' => $usereventdefaults, 'ocinstanceid' => $ocinstanceid, ]; if ($series) { $customdata['series'] = $series; @@ -257,13 +257,13 @@ } $newfileitemid = file_get_unused_draft_itemid(); - $newfilerecord = array( + $newfilerecord = [ 'contextid' => $uploadedfile->get_contextid(), 'component' => $uploadedfile->get_component(), 'filearea' => $uploadedfile->get_filearea(), 'itemid' => $newfileitemid, - 'timemodified' => time() - ); + 'timemodified' => time(), + ]; $newfile = $fs->create_file_from_storedfile($newfilerecord, $uploadedfile); // Delete the old job. file_deletionmanager::fulldelete_file($uploadedfile); diff --git a/block_opencast.php b/block_opencast.php index a1beb16c..63868e51 100644 --- a/block_opencast.php +++ b/block_opencast.php @@ -238,7 +238,7 @@ public function get_content_for_output($output) { 'id' => $COURSE->id, 'bui_deleteid' => $this->instance->id, 'bui_confirm' => 1, - 'sesskey' => sesskey() + 'sesskey' => sesskey(), ]); $this->page->requires->js_call_amd('block_opencast/block_delete_handler', 'init', [$this->context->id, $deleteurl->out(false)]); diff --git a/classes/local/activitymodulemanager.php b/classes/local/activitymodulemanager.php index 94d85f1e..f510901f 100644 --- a/classes/local/activitymodulemanager.php +++ b/classes/local/activitymodulemanager.php @@ -622,4 +622,89 @@ public static function cleanup_series_modules($ocinstanceid, $modulecourseid, $r return $success; } + + /** + * Looks up for series Activity modules in a new (imported) course that has faulty (old) series id. + * Repairs the faulty Activity module by replacing the new series id in the db record. + * @see importvideosmanager::fix_imported_series_modules_in_new_course() After the restore is completed. + * + * @param int $ocinstanceid Opencast instance id. + * @param int $courseid New course id. + * @param string $sourceseriesid Old series id. + * @param string $newseriesid New series id. + * + * @return void + */ + public static function fix_imported_series_modules_in_new_course( + $ocinstanceid, $courseid, $sourceseriesid, $newseriesid) { + global $DB, $CFG; + + // Check if mod_opencast is installed. + if (empty(core_plugin_manager::instance()->get_plugin_info('mod_opencast'))) { + return; + } + + // Find the faulty series activity modules in new course. + $seriesmodules = $DB->get_records('opencast', [ + 'ocinstanceid' => $ocinstanceid, + 'type' => opencasttype::SERIES, + 'course' => $courseid, + 'opencastid' => $sourceseriesid, + ]); + + // IF anything has been found. + if (!empty($seriesmodules)) { + foreach ($seriesmodules as $instance) { + // We also check the existance of the course moulde. + $cm = get_coursemodule_from_instance('opencast', $instance->id, $courseid); + if (!empty($cm)) { + // We replace the old with new series id. + $DB->set_field('opencast', 'opencastid', $newseriesid, + ['id' => $instance->id]); + } + } + } + } + + /** + * Looks up for episode Activity modules in a new (imported) course that has faulty (old) event id. + * Repairs the faulty Activity module by replacing the new event id in the db record. + * @see importvideosmanager::fix_imported_episode_modules_in_new_course() in task "process_duplicated_event_module_fix" + * + * @param int $ocinstanceid Opencast instance id. + * @param int $targetcourseid New course id. + * @param string $sourceeventid Old event id. + * @param string $duplicatedeventid New event id. + * + * @return void + */ + public static function fix_imported_episode_modules_in_new_course( + $ocinstanceid, $targetcourseid, $sourceeventid, $duplicatedeventid + ) { + global $DB, $CFG; + + // Check if mod_opencast is installed. + if (empty(core_plugin_manager::instance()->get_plugin_info('mod_opencast'))) { + return; + } + + $episodemodules = $DB->get_records('opencast', [ + 'ocinstanceid' => $ocinstanceid, + 'course' => $targetcourseid, + 'type' => opencasttype::EPISODE, + 'opencastid' => $sourceeventid, + ]); + + if (count($episodemodules) > 0) { + // Iterate over modules. + foreach ($episodemodules as $instance) { + // We also check the existance of the course moulde. + $cm = get_coursemodule_from_instance('opencast', $instance->id, $targetcourseid); + if (!empty($cm)) { + $DB->set_field('opencast', 'opencastid', $duplicatedeventid, + ['id' => $instance->id]); + } + } + } + } } diff --git a/classes/local/addtranscription_form.php b/classes/local/addtranscription_form.php index 015c1ca8..bcc70131 100644 --- a/classes/local/addtranscription_form.php +++ b/classes/local/addtranscription_form.php @@ -52,9 +52,6 @@ public function definition() { // Get the renderer to use its methods. $this->renderer = $PAGE->get_renderer('block_opencast'); $ocinstanceid = $this->_customdata['ocinstanceid']; - $identifier = $this->_customdata['identifier']; - $courseid = $this->_customdata['courseid']; - $mform = $this->_form; $explanation = html_writer::tag('p', get_string('addnewtranscription_desc', 'block_opencast')); diff --git a/classes/local/apibridge.php b/classes/local/apibridge.php index f20a89c1..06da1fa5 100644 --- a/classes/local/apibridge.php +++ b/classes/local/apibridge.php @@ -340,6 +340,8 @@ public function get_block_videos($courseid, $withmetadata = false) { 'withacl' => true, 'withmetadata' => $withmetadata === true, 'withpublications' => true, + 'includeInternalPublication' => false, + // Somehow causes error in Opencast 15 if withpublications is used without it. 'sort' => [ 'start_date' => 'DESC', ], @@ -1573,12 +1575,13 @@ private function get_non_permanent_acl_rules_for_status($courseid, $visibility, * @param int $courseid id of the course the event belongs to. * @param int $visibility visibility of the event. * @param array|null $groups array of group ids used for replacing the placeholders + * @param bool $forceonhidden flag to force return the acls when hidden. * @return array of objects representing acl rules, each with the fields 'allow', 'action' and 'role'. * @throws dml_exception * @throws coding_exception In case of an invalid visibility status. Only [0,1,2] are allowed. */ - private function get_permanent_acl_rules_for_status($courseid, $visibility, $groups = null) { - return $this->get_acl_rules_for_status($courseid, $visibility, true, $groups); + private function get_permanent_acl_rules_for_status($courseid, $visibility, $groups = null, $forceonhidden = false) { + return $this->get_acl_rules_for_status($courseid, $visibility, true, $groups, $forceonhidden); } /** @@ -1588,11 +1591,12 @@ private function get_permanent_acl_rules_for_status($courseid, $visibility, $gro * @param int $visibility visibility of the event. * @param bool $permanent whether to get permanent or non-permanent acl rules. * @param array|null $groups array of group ids used for replacing the placeholders + * @param bool $forceonhidden flag to force return the acls when hidden. * @return array of objects representing acl rules, each with the fields 'allow', 'action' and 'role'. * @throws dml_exception * @throws coding_exception In case of an invalid visibility status. Only [0,1,2] are allowed. */ - private function get_acl_rules_for_status($courseid, $visibility, $permanent, $groups = null) { + private function get_acl_rules_for_status($courseid, $visibility, $permanent, $groups = null, $forceonhidden = false) { $roles = $this->getroles($permanent ? 1 : 0); $result = []; @@ -1614,6 +1618,21 @@ private function get_acl_rules_for_status($courseid, $visibility, $permanent, $g } break; case block_opencast_renderer::HIDDEN: + if ($permanent && $forceonhidden) { + foreach ($roles as $role) { + foreach ($role->actions as $action) { + $rolenameformatted = self::replace_placeholders($role->rolename, $courseid)[0]; + // Might return null if USERNAME cannot be replaced. + if ($rolenameformatted) { + $result[] = (object)[ + 'allow' => true, + 'action' => $action, + 'role' => $rolenameformatted, + ]; + } + } + } + } break; case block_opencast_renderer::GROUP: foreach ($roles as $role) { @@ -2071,7 +2090,7 @@ public function can_edit_event_in_editor($video, $courseid) { // We check if the basic editor integration configs are set, the video processing state is succeeded // (to avoid process failure) and there is internal publication status (to avoid error 400 in editor). if (get_config('block_opencast', 'enable_opencast_editor_link_' . $this->ocinstanceid) && - isset($video->processing_state) && $video->processing_state == "SUCCEEDED" && + isset($video->processing_state) && in_array($video->processing_state, ["SUCCEEDED", "NEEDSCUTTING"]) && isset($video->publication_status) && is_array($video->publication_status) && in_array('internal', $video->publication_status)) { $context = context_course::instance($courseid); @@ -2881,7 +2900,7 @@ public function set_duplicated_event_visibility($duplicatedeventid, $sourceevent $event = new event(); // Gathering acls for the duplicated event. $newacls = $this->get_non_permanent_acl_rules_for_status($courseid, $targetvisibiltiy, $groups); - $newacls = array_merge($newacls, $this->get_permanent_acl_rules_for_status($courseid, $targetvisibiltiy, $groups)); + $newacls = array_merge($newacls, $this->get_permanent_acl_rules_for_status($courseid, $targetvisibiltiy, $groups, true)); foreach ($newacls as $acl) { $event->add_acl($acl->allow, $acl->action, $acl->role); } diff --git a/classes/local/event.php b/classes/local/event.php index 1d18f176..138ffe4a 100644 --- a/classes/local/event.php +++ b/classes/local/event.php @@ -294,10 +294,11 @@ public function get_form_params($ocinstanceid) { * @param string $eventid The event identifier. * @param bool $modulecleanup (optional) The switch if we want to cleanup the episode modules. * @param array|null $episodemodules (optional) The array of episode modules to be cleaned up. + * @param string $restoreuniqueid (optional) The restore unique id to keep track of restore session. * @return mixed false if task could not be created, id of inserted task otherwise. */ public static function create_duplication_task($ocinstanceid, $courseid, $seriesid, - $eventid, $modulecleanup = false, $episodemodules = null) { + $eventid, $modulecleanup = false, $episodemodules = null, $restoreuniqueid = null) { $task = new process_duplicate_event(); @@ -308,6 +309,7 @@ public static function create_duplication_task($ocinstanceid, $courseid, $series 'eventid' => $eventid, 'schedulemodulecleanup' => $modulecleanup, 'episodemodules' => $episodemodules, + 'restoreuniqueid' => $restoreuniqueid, ]; $task->set_custom_data($data); return manager::queue_adhoc_task($task, true); diff --git a/classes/local/importvideosmanager.php b/classes/local/importvideosmanager.php index 13131b80..7a0d0b47 100644 --- a/classes/local/importvideosmanager.php +++ b/classes/local/importvideosmanager.php @@ -40,6 +40,27 @@ class importvideosmanager { + /** @var int course wizard restore status is started */ + const RESTORE_STATUS_STARTED = 0; + + /** @var int course wizard restore status is completed */ + const RESTORE_STATUS_COMPLETED = 1; + + /** @var int Episode import mapping type */ + const MAPPING_TYPE_EPISODE = 1; + + /** @var int Series import mapping type */ + const MAPPING_TYPE_SERIES = 2; + + /** @var int Import mapping status success */ + const MAPPING_STATUS_SUCCESS = 1; + + /** @var int Import mapping status pending */ + const MAPPING_STATUS_PENDING = 0; + + /** @var int Import mapping status failed */ + const MAPPING_STATUS_FAILED = 2; + /** * Helperfunction to get the status of the manual import videos feature. * This consists of a check if the feature is enabled by the admin and a check if a duplicate workflow is configured. @@ -594,4 +615,251 @@ public static function change_acl($ocinstanceid, $sourcecourseid, $sourcecourses // Finall, we return the object containing the information about all 3 steps in this method. return $aclchangeresult; } + + /** + * Gets the import mapping records of series and perform the lookup and fix. + * It also cleans up after the attemp is completed. + * @uses ltimodulemanager::fix_imported_series_modules_in_new_course() to lookup and fix series LTI modules. + * @uses activitymodulemanager::fix_imported_series_modules_in_new_course() to lookup and fix series Activity modules. + * + * @param int $ocinstanceid Opencast instance id. + * @param int $courseid Course id. + * @param string $newseriesid The newly created series id in the new course. + * @param string $restoreuid The restore unique id. + * + * @return void + */ + public static function fix_imported_series_modules_in_new_course($ocinstanceid, $courseid, $newseriesid, $restoreuid) { + + $seriesimportmapping = self::get_import_mapping_records([ + 'restoreuid' => $restoreuid, + 'ocinstanceid' => $ocinstanceid, + 'type' => self::MAPPING_TYPE_SERIES, + 'targetcourseid' => $courseid, + ]); + + foreach ($seriesimportmapping as $mapping) { + // LTI Modules. + ltimodulemanager::fix_imported_series_modules_in_new_course( + $ocinstanceid, $courseid, $mapping->sourceseriesid, $newseriesid + ); + + // Activity modules. + activitymodulemanager::fix_imported_series_modules_in_new_course( + $ocinstanceid, $courseid, $mapping->sourceseriesid, $newseriesid + ); + + // At this point, we have no use for the series import mapping record anymore, + // and we remove it from db. + self::delete_import_mapping_record(['id' => $mapping->id]); + } + } + + /** + * Performs the look up and fix for the episode LTI & Activity modules in the newly imported course. + * @uses ltimodulemanager::fix_imported_episode_modules_in_new_course() to lookup and fix episode LTI modules. + * @uses activitymodulemanager::fix_imported_episode_modules_in_new_course() to lookup and fix episode Activity modules. + * + * @param stdClass $mapping The import mapping object. + * @param string $duplicatedeventid TThe duplicated event id. + * + * @return void + */ + public static function fix_imported_episode_modules_in_new_course($mapping, $duplicatedeventid) { + // LTI modules in the new course. + ltimodulemanager::fix_imported_episode_modules_in_new_course( + $mapping->ocinstanceid, + $mapping->targetcourseid, + $mapping->sourceeventid, + $duplicatedeventid + ); + + // Activity Modules in the new course. + activitymodulemanager::fix_imported_episode_modules_in_new_course( + $mapping->ocinstanceid, + $mapping->targetcourseid, + $mapping->sourceeventid, + $duplicatedeventid + ); + } + + /** + * Saves the series import mapping record. + * + * @param int $ocinstanceid The OC instance id. + * @param int $targetcourseid The new course id. + * @param string $sourceseriesid The source series id. + * @param string $restoreuniqueid The unique id of the restore session. + * + * @return bool Whether the mapping record is inserted into db or not. + */ + public static function save_series_import_mapping_record($ocinstanceid, $targetcourseid, + $sourceseriesid, $restoreuniqueid) { + $mappingobj = new \stdClass(); + $mappingobj->type = self::MAPPING_TYPE_SERIES; + $mappingobj->restoreuid = $restoreuniqueid; + $mappingobj->ocinstanceid = $ocinstanceid; + $mappingobj->targetcourseid = $targetcourseid; + $mappingobj->sourceseriesid = $sourceseriesid; + return self::save_import_mapping_record($mappingobj); + } + + /** + * Saves the episode import mapping record. + * + * @param int $ocinstanceid The OC instance id. + * @param int $targetcourseid The new course id. + * @param string $sourceeventid The source event id. + * @param string $restoreuniqueid The unique id of the restore session. + * + * @return bool Whether the mapping record is inserted into db or not. + */ + public static function save_episode_import_mapping_record($ocinstanceid, $targetcourseid, + $sourceeventid, $restoreuniqueid) { + $mappingobj = new \stdClass(); + $mappingobj->type = self::MAPPING_TYPE_EPISODE; + $mappingobj->restoreuid = $restoreuniqueid; + $mappingobj->ocinstanceid = $ocinstanceid; + $mappingobj->targetcourseid = $targetcourseid; + $mappingobj->sourceeventid = $sourceeventid; + return self::save_import_mapping_record($mappingobj); + } + + /** + * Inserts a mapping record into db. It also validates the mapping object. + * + * @param stdClass $mapping the mapping object. + * + * @return bool whether the mapping record is inserted successfully. + */ + public static function save_import_mapping_record($mapping) { + global $DB; + // Set the started status. + $mapping->restorecompleted = self::RESTORE_STATUS_STARTED; + $mapping->status = self::MAPPING_STATUS_PENDING; + $mapping->timecreated = time(); + if (!self::validate_mapping_record($mapping)) { + return false; + } + // Save into db. + return (bool) $DB->insert_record('block_opencast_importmapping', $mapping); + } + + /** + * Updates the improt mapping record. It perform a validation before updating as well. + * + * @param stdClass $mapping The import mapping record object. + * + * @return boolean Whether the update was valid and successful. + */ + public static function update_import_mapping_record($mapping) { + global $DB; + $mapping->timemodified = time(); + if (!self::validate_mapping_record($mapping)) { + return false; + } + // Update the record in db. + return $DB->update_record('block_opencast_importmapping', $mapping); + } + + /** + * Finds and returns the import mapping record based on a where clause. + * + * @param array $where The array of where clauses to look for. + * + * @return stdClass|null The import mapping record object or null if not found. + */ + public static function get_import_mapping_record($where) { + global $DB; + return $DB->get_record('block_opencast_importmapping', $where) ?: null; + } + + /** + * Finds and returns the list import mapping records based on a where clause. + * + * @param array $where The array of where clauses to look for. + * + * @return array An array of import mapping record objects. + */ + public static function get_import_mapping_records($where) { + global $DB; + return $DB->get_records('block_opencast_importmapping', $where); + } + + /** + * Deletes an import mapping record. + * + * @param array $where the array of where clause. + * + * @return bool whether the deletion was successful + */ + public static function delete_import_mapping_record($where) { + global $DB; + return $DB->delete_records('block_opencast_importmapping', $where); + } + + /** + * Sets the completion status of a restore session. + * @see restore_opencast_block_structure_step::after_restore() to make sure the restore session is completed + * and we can proceed with the after import module fixes + * + * @param string $restoreuid the restore session unique identifier + * @param int $status the status id + * + * @return bool|array true if the status of all records under restore unique id have been changed, + * array mapping ids of unchanged otherwise. + */ + public static function set_import_mapping_completion_status($restoreuid, $status = self::RESTORE_STATUS_COMPLETED) { + global $DB; + $records = $DB->get_records('block_opencast_importmapping', ['restoreuid' => $restoreuid]); + $unchanged = []; + foreach ($records as $record) { + $record->restorecompleted = $status; + $record->timemodified = time(); + $success = $DB->update_record('block_opencast_importmapping', $record, true); + // We track the success of changes to report back, + // however series are not neccessary and we escape them, + // because they are waiting for the restore session to be completed. + if (!$success && $record->type == self::MAPPING_TYPE_EPISODE) { + $unchanged[] = $record->sourceeventid ?? 'Mapping id: ' . $record->id; + } + } + return empty($unchanged) ? true : $unchanged; + } + + /** + * Finds the mapping record of the event and sets the ocworkflowid + * + * @param array $where the array of where clause. + * @param int $ocworkflowid the id of duplicating workflow that holds the new event id later on. + * + * @return int|false the id of the mapping record of successful, false otherwise. + */ + public static function set_import_mapping_workflowid($where, $ocworkflowid) { + $mapping = self::get_import_mapping_record($where); + if (!empty($mapping)) { + $mapping->ocworkflowid = $ocworkflowid; + $mapping->status = self::MAPPING_STATUS_PENDING; + if (self::update_import_mapping_record($mapping)) { + return $mapping->id; + } + } + return false; + } + + /** + * Validates the mapping object before interacting with db. + * + * @param stdClass $mapping the mapping object + * + * @return bool whether the mapping is valid. + */ + public static function validate_mapping_record($mapping) { + $isvalid = true; + if (empty($mapping->restoreuid) || empty($mapping->ocinstanceid) + || empty($mapping->targetcourseid) || empty($mapping->type)) { + $isvalid = false; + } + return $isvalid; + } } diff --git a/classes/local/ltimodulemanager.php b/classes/local/ltimodulemanager.php index baae3a3c..afca4da8 100644 --- a/classes/local/ltimodulemanager.php +++ b/classes/local/ltimodulemanager.php @@ -1519,4 +1519,128 @@ private static function check_opencast_series($identifier, $ocinstanceid) { $series = $apibridge->get_series_by_identifier($identifier); return !empty($series); } + + /** + * Looks up for series LTI modules in a new (imported) course that has faulty (old) series id. + * Repairs the faulty LTI module by replacing the new series id and inserts the series module in "block_opencast_ltimodule". + * @see importvideosmanager::fix_imported_series_modules_in_new_course() After the restore is completed. + * + * @param int $ocinstanceid Opencast instance id. + * @param int $courseid New course id. + * @param string $sourceseriesid Old series id. + * @param string $newseriesid New series id. + * + * @return void + */ + public static function fix_imported_series_modules_in_new_course( + $ocinstanceid, $courseid, $sourceseriesid, $newseriesid) { + global $CFG, $DB; + // Require grade library. For an unknown reason, this is needed when updating the module. + require_once($CFG->libdir . '/gradelib.php'); + + // Get the id of the preconfigured tool. + $toolid = self::get_preconfigured_tool_for_series($ocinstanceid); + + $sql = 'SELECT cm.id AS cmid FROM {lti} l ' . + 'JOIN {course_modules} cm ' . + 'ON l.id = cm.instance ' . + 'WHERE l.typeid = :toolid ' . + 'AND cm.course = :course ' . + 'AND ' . $DB->sql_like('l.instructorcustomparameters', ':sourceseriesid') . + ' ORDER BY cm.added ASC'; + $params = ['toolid' => $toolid, + 'course' => $courseid, + 'sourceseriesid' => '%' . $DB->sql_like_escape($sourceseriesid) . '%', ]; + $seriesmodules = $DB->get_fieldset_sql($sql, $params); + + // If there are any existing series modules in this course. + if (count($seriesmodules) > 0) { + // Iterate over modules. + foreach ($seriesmodules as $cmid) { + $seriesmoduleobject = get_coursemodule_from_id('lti', $cmid, $courseid); + if (!empty($seriesmoduleobject)) { + $courseobject = get_course($courseid); + list($unusedcm, $unusedcontext, $unusedmodule, $seriesmoduledata, $unusedcw) = + get_moduleinfo_data($seriesmoduleobject, $courseobject); + + // Replace the series identifier in the module info with the new one. + $seriesmoduledata->instructorcustomparameters = 'series=' . $newseriesid; + + // Update the series identifier within the series module. + update_module($seriesmoduledata); + + // Insert the data into db to make it visible to the plugin as well. + $record = new stdClass(); + $record->courseid = $courseid; + $record->cmid = $cmid; + $record->ocinstanceid = $ocinstanceid; + $record->seriesid = $newseriesid; + $DB->insert_record('block_opencast_ltimodule', $record); + } + } + } + } + + /** + * Looks up for episode LTI modules in a new (imported) course that has faulty (old) event id. + * Repairs the faulty LTI module by replacing the new event id and inserts the episode module in "block_opencast_ltiepisode". + * @see importvideosmanager::fix_imported_episode_modules_in_new_course() in task "process_duplicated_event_module_fix" + * + * @param int $ocinstanceid Opencast instance id. + * @param int $targetcourseid New course id. + * @param string $sourceeventid Old event id. + * @param string $duplicatedeventid New event id. + * + * @return void + */ + public static function fix_imported_episode_modules_in_new_course( + $ocinstanceid, $targetcourseid, $sourceeventid, $duplicatedeventid) { + global $CFG, $DB; + // Require course module library. + require_once($CFG->dirroot . '/course/modlib.php'); + + // Require grade library. For an unknown reason, this is needed when updating the module. + require_once($CFG->libdir . '/gradelib.php'); + + // Get the id of the preconfigured tool. + $toolid = self::get_preconfigured_tool_for_episode($ocinstanceid); + + // Get the LTI episode module(s) in the new course which point to the old event id. + $sql = 'SELECT cm.id AS cmid FROM {lti} l ' . + 'JOIN {course_modules} cm ' . + 'ON l.id = cm.instance ' . + 'WHERE l.typeid = :toolid ' . + 'AND cm.course = :course ' . + 'AND ' . $DB->sql_like('l.instructorcustomparameters', ':sourceeventid'); + $params = ['toolid' => $toolid, + 'course' => $targetcourseid, + 'sourceeventid' => '%' . $sourceeventid . '%', ]; + $episodemodules = $DB->get_fieldset_sql($sql, $params); + + // If there are any existing episode modules in this course. + if (count($episodemodules) > 0) { + // Iterate over modules. + foreach ($episodemodules as $cmid) { + // Gather more information about this module so that we can update the module info in the end. + $episodemoduleobject = get_coursemodule_from_id('lti', $cmid, $targetcourseid); + $courseobject = get_course($targetcourseid); + list($unusedcm, $unusedcontext, $unusedmodule, $episodemoduledata, $unusedcw) = + get_moduleinfo_data($episodemoduleobject, $courseobject); + + // Replace the episode identifier in the module info. + $episodemoduledata->instructorcustomparameters = 'id=' . $duplicatedeventid; + + // Update the episode identifier within the episode module. + update_module($episodemoduledata); + + // Remember this episode module id as the episode module of the course. + $record = new stdClass(); + $record->courseid = $targetcourseid; + $record->episodeuuid = $duplicatedeventid; + $record->cmid = $cmid; + $record->ocinstanceid = $ocinstanceid; + $DB->insert_record('block_opencast_ltiepisode', $record); + } + } + } } diff --git a/classes/local/notifications.php b/classes/local/notifications.php index fdb5a6f2..a6b44678 100644 --- a/classes/local/notifications.php +++ b/classes/local/notifications.php @@ -128,9 +128,9 @@ public static function notify_missing_events($courseid, $missingevents) { * Notify administrator upon an exception error. * * @param string $identifier - * @param Exception $e + * @param Exception|null $e */ - public static function notify_error($identifier, Exception $e = null) { + public static function notify_error($identifier, ?Exception $e = null) { $subject = get_string('erroremailsubj', 'block_opencast'); @@ -429,4 +429,66 @@ public static function notify_cleanup_imported_modules_force_deletion($courseid, $admin = get_admin(); self::send_message('error', $admin, $subject, $body); } + + /** + * Send notifications to admins, when import mapping of series was not fully covered during restore. + * + * @param int $courseid Course id + * @param array $missingimportmappingids Missing series/event ids + * @param string $type either series or event + */ + public static function notify_missing_import_mapping($courseid, $missingimportmappingids, $type = 'series') { + global $DB, $PAGE; + + $a = (object)[ + 'courseid' => $courseid, + 'coursefullname' => get_string('coursefullnameunknown', 'block_opencast'), + ]; + + if ($course = $DB->get_record('course', ['id' => $courseid])) { + $a->coursefullname = $course->fullname; + } + + $subject = get_string('errorrestoremissingimportmapping_subj', 'block_opencast'); + $body = get_string('errorrestoremissingimportmappingseries_body', 'block_opencast', $a); + if ($type == 'events') { + $body = get_string('errorrestoremissingimportmappingevents_body', 'block_opencast', $a); + } + + // Add all backup eventids. + $renderer = $PAGE->get_renderer('block_opencast'); + $body .= $renderer->render_list($missingimportmappingids); + + $admin = get_admin(); + self::send_message('error', $admin, $subject, $body); + } + + /** + * Send notifications to admins, if the import mapping records could not get the status of completion. + * + * @param int $courseid Course id + * @param array $incompletedeventids Incompleted mapping event ids + */ + public static function notify_incompleted_import_mapping_records($courseid, $incompletedeventids) { + global $DB, $PAGE; + + $a = (object)[ + 'courseid' => $courseid, + 'coursefullname' => get_string('coursefullnameunknown', 'block_opencast'), + ]; + + if ($course = $DB->get_record('course', ['id' => $courseid])) { + $a->coursefullname = $course->fullname; + } + + $subject = get_string('errorrestoremissingimportmapping_subj', 'block_opencast'); + $body = get_string('errorrestoreincompletedimportmapping_body', 'block_opencast', $a); + + // Add all backup eventids. + $renderer = $PAGE->get_renderer('block_opencast'); + $body .= $renderer->render_list($incompletedeventids); + + $admin = get_admin(); + self::send_message('error', $admin, $subject, $body); + } } diff --git a/classes/output/importvideos/renderer.php b/classes/output/importvideos/renderer.php index 645aa491..7ad1bb8a 100644 --- a/classes/output/importvideos/renderer.php +++ b/classes/output/importvideos/renderer.php @@ -51,12 +51,12 @@ class renderer extends core_backup_renderer { * with the goal to adapt the widget to our needs. * * @param moodle_url $nextstageurl - * @param importvideos_coursesearch $courses + * @param importvideos_coursesearch|null $courses * * @return string */ - public function importvideos_coursesearch(moodle_url $nextstageurl, - importvideos_coursesearch $courses = null) { + public function importvideos_coursesearch(moodle_url $nextstageurl, + ?importvideos_coursesearch $courses = null) { $html = html_writer::start_tag('div', ['class' => 'import-course-selector']); $html .= $this->wizard_intro_notification( get_string('importvideos_wizardstep1intro', 'block_opencast')); diff --git a/classes/setting_default_manager.php b/classes/setting_default_manager.php index 1dac3998..ac402dd1 100644 --- a/classes/setting_default_manager.php +++ b/classes/setting_default_manager.php @@ -59,7 +59,8 @@ public static function init_regirstered_defaults($ocinstanceid = 1) { public static function get_default_metadata() { return '[' . '{"name":"title","datatype":"text","required":1,"readonly":0,"param_json":"{\"style\":\"min-width: 27ch;\"}"},' . - '{"name":"subjects","datatype":"autocomplete","required":0,"readonly":0,"param_json":null,"defaultable":0,"batchable":0},' . + '{"name":"subjects","datatype":"autocomplete","required":0,"readonly":0,"param_json":null,"defaultable":0,' . + '"batchable":0},' . '{"name":"description","datatype":"textarea","required":0,"readonly":0,"param_json":' . '"{\"rows\":\"3\",\"cols\":\"19\"}","defaultable":0,"batchable":0},' . '{"name":"language","datatype":"select","required":0,"readonly":0,"param_json":"{\"\":\"No option selected\",' . @@ -74,8 +75,10 @@ public static function get_default_metadata() { '\"ALLRIGHTS\":\"All Rights Reserved\",\"CC0\":\"CC0\",\"CC-BY-ND\":\"CC BY-ND\",\"CC-BY-NC-ND\":\"CC BY-NC-ND\",' . '\"CC-BY-NC-SA\":\"CC BY-NC-SA\",\"CC-BY-SA\":\"CC BY-SA\",\"CC-BY-NC\":\"CC BY-NC\",\"CC-BY\":\"CC BY\"}",' . '"defaultable":0,"batchable":0},' . - '{"name":"creator","datatype":"autocomplete","required":0,"readonly":0,"param_json":null,"defaultable":0,"batchable":0},' . - '{"name":"contributor","datatype":"autocomplete","required":0,"readonly":0,"param_json":null,"defaultable":0,"batchable":0}]'; + '{"name":"creator","datatype":"autocomplete","required":0,"readonly":0,"param_json":null,"defaultable":0,' . + '"batchable":0},' . + '{"name":"contributor","datatype":"autocomplete","required":0,"readonly":0,"param_json":null,"defaultable":0,' . + '"batchable":0}]'; } /** diff --git a/classes/task/process_duplicate_event.php b/classes/task/process_duplicate_event.php index 9db730a9..4357c639 100644 --- a/classes/task/process_duplicate_event.php +++ b/classes/task/process_duplicate_event.php @@ -33,6 +33,7 @@ use Exception; use moodle_exception; use stdClass; +use block_opencast\local\importvideosmanager; /** * Task for starting workflow to copy events. @@ -170,8 +171,32 @@ public function execute() { } } - // Now, we prepare and queue another adhoc task to change the visibility of the duplicated event. if (is_number($ocworkflowid)) { + // In case the restore unique id exists, that means it is coming directly from course backup/restore session, + // therefore, we proceed to look up and fix the duplicated event LTI/ACtivity module. + if (!empty($data->restoreuniqueid)) { + // We prepare the mapping where clause in an array. + $where = [ + 'restoreuid' => $data->restoreuniqueid, + 'ocinstanceid' => $data->ocinstanceid, + 'type' => importvideosmanager::MAPPING_TYPE_EPISODE, + 'targetcourseid' => $course->id, + 'sourceeventid' => $data->eventid, + ]; + // Pass the ocworkflowid to extract and insert the new event id. + $mappingid = importvideosmanager::set_import_mapping_workflowid($where, $ocworkflowid); + // In case updating the ocworkflowid was successful. + if (!empty($mappingid)) { + // At this point we pass the import mapping id to the adhoc task to proceed with the fix later. + $modulefixtask = new process_duplicated_event_module_fix(); + $modulefixtaskdata = (object)[ + 'mappingid' => $mappingid, + ]; + $modulefixtask->set_custom_data($modulefixtaskdata); + manager::queue_adhoc_task($modulefixtask, true); + } + } + // Now, we prepare and queue another adhoc task to change the visibility of the duplicated event. $task = new process_duplicated_event_visibility_change(); $visibiltytaskdata = (object)[ diff --git a/classes/task/process_duplicated_event_module_fix.php b/classes/task/process_duplicated_event_module_fix.php new file mode 100644 index 00000000..b84090cd --- /dev/null +++ b/classes/task/process_duplicated_event_module_fix.php @@ -0,0 +1,139 @@ +. + +/** + * Adhoc task to check and fix episode modules in the newly imported course. + * + * @package block_opencast + * @copyright 2024 Farbod Zamani Boroujeni, ELAN e.V. + * @author Farbod Zamani Boroujeni + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace block_opencast\task; + +use block_opencast\local\apibridge; +use block_opencast\local\notifications; +use block_opencast\local\importvideosmanager; +use core\task\adhoc_task; +use moodle_exception; + +/** + * Adhoc task to check and fix episode modules in the newly imported course. + * + * @package block_opencast + * @copyright 2024 Farbod Zamani Boroujeni, ELAN e.V. + * @author Farbod Zamani Boroujeni + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class process_duplicated_event_module_fix extends adhoc_task { + + /** @var int max number of pending retries for one task */ + const MAX_COUNT_PENDING = 20; + + /** + * Create a fix module task. + */ + public function __construct() { + $this->set_component('block_opencast'); + } + + /** + * Start fixing episode modules. + * + * @see \core\task\task_base::execute() + */ + public function execute() { + global $DB; + + $data = $this->get_custom_data(); + + // Get the import mapping record. + $mapping = importvideosmanager::get_import_mapping_record(['id' => $data->mappingid]); + if (empty($mapping)) { + mtrace("import mapping to fix does not exist, ID: {$data->mappingid}, deleting adhoc task."); + return; + } + + // Do the cleanup if the import mapping record is either failed or succeeded. + if ($mapping->status != importvideosmanager::MAPPING_STATUS_PENDING) { + $deleted = importvideosmanager::delete_import_mapping_record(['id' => $mapping->id]); + $logmessage = "The import mapping record for event id: {$mapping->sourceeventid}" . + " with ocworkflowid: {$mapping->ocworkflowid} & duplicated event id: {$data->duplicatedeventid}" . + " in course (ID: {$mapping->targetcourseid}) after {$mapping->attemptcount} attempt(s) %s"; + $status = 'was successful'; + if ($mapping->status == importvideosmanager::MAPPING_STATUS_FAILED) { + $status = 'failed'; + } + $status .= $deleted ? ' and has been deleted.' : ' and could not be deleted.'; + mtrace(sprintf($logmessage, $status)); + return; + } + + if (!importvideosmanager::validate_mapping_record($mapping)) { + mtrace("invalid import mapping record, ID: {$data->mappingid}, deleting adhoc task"); + return; + } + + $course = $DB->get_record('course', ['id' => $mapping->targetcourseid]); + $a = clone($data); + // Adding notification required parameters. + $a->coursefullname = $course->fullname; + $a->taskid = $this->get_id(); + + try { + // Make sure the restore session is completed. + if ($mapping->restorecompleted != importvideosmanager::RESTORE_STATUS_COMPLETED) { + // If not, throw the error and repeat the task. + throw new moodle_exception('restore_still_in_progress', 'block_opencast', '', $a); + } + + $apibridge = apibridge::get_instance($mapping->ocinstanceid); + if (empty($data->duplicatedeventid)) { + $data->duplicatedeventid = $apibridge->get_duplicated_episodeid($mapping->ocworkflowid); + } + // Repeating the task a few time until it gets or rejects. + if (empty($data->duplicatedeventid)) { + throw new moodle_exception('importmapping_no_duplicated_event_id_yet', 'block_opencast', '', $a); + } + + // Perform the episode modules fix. + importvideosmanager::fix_imported_episode_modules_in_new_course($mapping, $data->duplicatedeventid); + $mapping->status = importvideosmanager::MAPPING_STATUS_SUCCESS; + importvideosmanager::update_import_mapping_record($mapping); + } catch (moodle_exception $e) { + $mapping->attemptcount = intval($mapping->attemptcount) + 1; + importvideosmanager::update_import_mapping_record($mapping); + // Check whether to retry. + if ($mapping->attemptcount <= self::MAX_COUNT_PENDING) { + $this->set_custom_data($data); + throw new moodle_exception('importmapping_modulesfixtaskretry', 'block_opencast', '', $e->getMessage()); + } else { + $mapping->status = importvideosmanager::MAPPING_STATUS_FAILED; + importvideosmanager::update_import_mapping_record($mapping); + notifications::notify_error('importmapping_modulesfixtasktermination', $e); + } + } + + // By the time we hit here and the process is not pending, + // we proceed with one last iteration to cleanup the import mapping record. + if ($mapping->status != importvideosmanager::MAPPING_STATUS_PENDING) { + $this->set_next_run_time(strtotime("+1 min")); + $this->set_custom_data($data); + throw new moodle_exception('importmapping_modulesfixtaskretry', 'block_opencast', '', 'performing cleanup repeat...'); + } + } +} diff --git a/classes/task/process_duplicated_event_visibility_change.php b/classes/task/process_duplicated_event_visibility_change.php index 66d7dd22..1a2a6792 100644 --- a/classes/task/process_duplicated_event_visibility_change.php +++ b/classes/task/process_duplicated_event_visibility_change.php @@ -113,7 +113,7 @@ public function execute() { $event = $apibridge->get_already_existing_event([$data->duplicatedeventid]); if (!$event || !in_array($event->status, ['EVENTS.EVENTS.STATUS.PROCESSED', 'EVENTS.EVENTS.STATUS.PROCESSING_FAILURE']) || count($event->publication_status) == 0 - || count($event->publication_status) == 1 && $event->publication_status[0] === 'internal') { + || (count($event->publication_status) == 1 && $event->publication_status[0] === 'internal')) { throw new moodle_exception('error_duplicated_event_id_not_ready', 'block_opencast', '', $a); } diff --git a/db/access.php b/db/access.php index abd9a6e2..37689eac 100644 --- a/db/access.php +++ b/db/access.php @@ -152,7 +152,7 @@ 'contextlevel' => CONTEXT_COURSE, 'archetypes' => [ 'manager' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW + 'editingteacher' => CAP_ALLOW, ], ], 'block/opencast:manageseriesforcourse' => [ @@ -161,7 +161,7 @@ 'contextlevel' => CONTEXT_COURSE, 'archetypes' => [ 'manager' => CAP_ALLOW, - 'editingteacher' => CAP_ALLOW + 'editingteacher' => CAP_ALLOW, ], ], 'block/opencast:deleteevent' => [ diff --git a/db/install.xml b/db/install.xml index 29d71bc3..16d4bad5 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,208 +1,213 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - -
- - - - - - - - - - - - -
- - - - - - - - - - - - - - -
- - - - - - - - - - -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - - - - - - - -
- - - - - - - - - - - -
-
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+
diff --git a/db/upgrade.php b/db/upgrade.php index d256be93..b67235de 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -829,5 +829,37 @@ function xmldb_block_opencast_upgrade($oldversion) { upgrade_block_savepoint(true, 2022111000, 'opencast'); } + if ($oldversion < 2024061400) { + + // Define field id to be added to block_opencast_importmapping. + $table = new xmldb_table('block_opencast_importmapping'); + + // Define fields. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null); + $table->add_field('restoreuid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'id'); + $table->add_field('ocinstanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'restoreuid'); + $table->add_field('type', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, null, 'ocinstanceid'); + $table->add_field('targetcourseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'type'); + $table->add_field('sourceseriesid', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'targetcourseid'); + $table->add_field('sourceeventid', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'sourceseriesid'); + $table->add_field('ocworkflowid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'sourceeventid'); + $table->add_field('restorecompleted', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'ocworkflowid'); + $table->add_field('attemptcount', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'restorecompleted'); + $table->add_field('status', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'attemptcount'); + $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'status'); + $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'timecreated'); + + // Add key. + $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); + + // Conditionally launch create table for block_opencast_visibility. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Opencast savepoint reached. + upgrade_block_savepoint(true, 2024061400, 'opencast'); + } + return true; } diff --git a/deleteaclgroup.php b/deleteaclgroup.php index 29f45eb7..3882b24f 100644 --- a/deleteaclgroup.php +++ b/deleteaclgroup.php @@ -21,11 +21,11 @@ * @copyright 2017 Andreas Wagner, SYNERGY LEARNING * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); use block_opencast\local\apibridge; use block_opencast\local\upload_helper; use tool_opencast\local\settings_api; +require_once('../../config.php'); global $PAGE, $OUTPUT, $CFG; diff --git a/deleteevent.php b/deleteevent.php index 4847a56e..81e158c4 100644 --- a/deleteevent.php +++ b/deleteevent.php @@ -21,11 +21,11 @@ * @copyright 2017 Andreas Wagner, SYNERGY LEARNING * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); use block_opencast\local\apibridge; use block_opencast\local\upload_helper; use tool_opencast\local\settings_api; +require_once('../../config.php'); global $PAGE, $OUTPUT, $CFG, $SITE; diff --git a/deletetranscription.php b/deletetranscription.php index 58fa6cf9..1847c2b7 100644 --- a/deletetranscription.php +++ b/deletetranscription.php @@ -21,12 +21,12 @@ * @author Farbod Zamani Boroujeni * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); use block_opencast\local\attachment_helper; use block_opencast\local\apibridge; use core\output\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); global $PAGE, $OUTPUT, $CFG, $SITE; diff --git a/directaccess.php b/directaccess.php index 8ce53492..12747c5a 100644 --- a/directaccess.php +++ b/directaccess.php @@ -20,14 +20,14 @@ * @copyright 2022 Farbod Zamani Boroujeni * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); -require_once($CFG->dirroot . '/mod/lti/locallib.php'); -require_once($CFG->dirroot . '/lib/oauthlib.php'); use block_opencast\local\apibridge; use block_opencast\local\lti_helper; use core\output\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); +require_once($CFG->dirroot . '/mod/lti/locallib.php'); +require_once($CFG->dirroot . '/lib/oauthlib.php'); global $PAGE, $OUTPUT, $CFG; diff --git a/downloadtranscription.php b/downloadtranscription.php index a7980618..10834d1b 100644 --- a/downloadtranscription.php +++ b/downloadtranscription.php @@ -20,14 +20,14 @@ * @copyright 2022 Farbod Zamani Boroujeni * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); -require_once($CFG->dirroot . '/mod/lti/locallib.php'); -require_once($CFG->dirroot . '/lib/oauthlib.php'); use block_opencast\local\apibridge; use block_opencast\local\lti_helper; use core\output\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); +require_once($CFG->dirroot . '/mod/lti/locallib.php'); +require_once($CFG->dirroot . '/lib/oauthlib.php'); global $PAGE, $OUTPUT, $CFG; diff --git a/downloadvideo.php b/downloadvideo.php index 39daf213..d5b6da1b 100644 --- a/downloadvideo.php +++ b/downloadvideo.php @@ -20,11 +20,11 @@ * @copyright 2021 Tamara Gunkel, University of Münster * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); use block_opencast\local\apibridge; use core\output\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); global $PAGE, $OUTPUT, $CFG; diff --git a/index.php b/index.php index 9bbd5a2c..61b3f611 100644 --- a/index.php +++ b/index.php @@ -21,8 +21,6 @@ * @copyright 2017 Andreas Wagner, SYNERGY LEARNING * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); -require_once($CFG->dirroot . '/lib/tablelib.php'); use block_opencast\local\activitymodulemanager; use block_opencast\local\apibridge; @@ -33,6 +31,8 @@ use block_opencast\opencast_connection_exception; use core\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); +require_once($CFG->dirroot . '/lib/tablelib.php'); global $PAGE, $OUTPUT, $CFG, $DB, $USER, $SITE; @@ -457,7 +457,7 @@ $video->processing_state !== "STOPPED") { $row[] = "-"; } else { - // TODO query alcs already at the beginning to avoid second rest call. + // Should Do Query alcs already at the beginning to avoid second rest call. $visible = $apibridge->is_event_visible($video->identifier, $courseid); $row[] = $renderer->render_change_visibility_icon($ocinstanceid, $courseid, $video->identifier, $visible); } diff --git a/lang/en/block_opencast.php b/lang/en/block_opencast.php index 6d68ec36..c868ee08 100644 --- a/lang/en/block_opencast.php +++ b/lang/en/block_opencast.php @@ -22,35 +22,79 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -$string['aclgroupdeleted'] = 'Access deleted for video: {$a->title}'; -$string['aclownerrole'] = 'ACL owner role'; -$string['aclownerrole_desc'] = 'Name of the role that identifies the owner of a video/series. The role must also be specified in the roles table. The role must be permanent and include a user-related placeholder, e.g. ROLE_OWNER_[USER_EMAIL]. It should not include any course-related placeholders. If empty, owner-related plugin functionalities are disabled.'; -$string['aclrolesadded'] = 'The change of visibility has been triggered to allow all students of the course to access the video: {$a->title}
Please refresh the site after some time to see the current visibility status.'; -$string['aclroleschangeerror'] = 'Error during the change of visibility of the video: {$a->title}
Some changes might have not been saved. If this occurs repeatedly, please contact your support team.'; -$string['aclrolesdeleted'] = 'The change of visibility has been triggered to prevent all students of the course from accessing the video: {$a->title}
Please refresh the site after some time to see the current visibility status.'; -$string['aclrolesaddedgroup'] = 'The change of visibility has been triggered to allow students of selected groups to access the video: {$a->title}
Please refresh the site after some time to see the current visibility status.'; +$string['accesspolicies'] = 'Access Policies'; $string['acl_settingcontrol'] = 'Enable visibility control'; $string['acl_settingcontrol_desc'] = 'If enabled, teachers can control the visibility of an Opencast episode on upload.'; $string['acl_settingcontrolafter'] = 'Allow episode visibility control after processing'; $string['acl_settingcontrolafter_desc'] = 'If enabled, teachers can control the visibility of an Opencast episode after the episode has been processed in Opencast.'; $string['acl_settingcontrolgroup'] = 'Allow episode group restriction'; $string['acl_settingcontrolgroup_desc'] = 'If enabled, teachers can not only control the visibility of an Opencast episode for all course users but can also restrict the visibility to particular course groups.'; -$string['acl_settingheader'] = 'Control episode visibility'; $string['acl_settingcontrolwaitingtime'] = 'Waiting time for scheduled visibility change (Minutes)'; $string['acl_settingcontrolwaitingtime_desc'] = 'It defines a minimum waiting time (in minutes) that scheduled visibility change process should wait. This time span will be added to current time for the scheduled video change date filed in add video form, it will also be used to validate that field. Based on how fast the Opencast instance processes the videos, this waiting time could be configured.
NOTE: When empty or (zero) "0", the default value is used.'; +$string['acl_settingheader'] = 'Control episode visibility'; +$string['aclgroupdeleted'] = 'Access deleted for video: {$a->title}'; $string['aclnothingtobesaved'] = 'No changes to the visibility have been made.'; -$string['accesspolicies'] = 'Access Policies'; +$string['aclownerrole'] = 'ACL owner role'; +$string['aclownerrole_desc'] = 'Name of the role that identifies the owner of a video/series. The role must also be specified in the roles table. The role must be permanent and include a user-related placeholder, e.g. ROLE_OWNER_[USER_EMAIL]. It should not include any course-related placeholders. If empty, owner-related plugin functionalities are disabled.'; +$string['aclrolesadded'] = 'The change of visibility has been triggered to allow all students of the course to access the video: {$a->title}
Please refresh the site after some time to see the current visibility status.'; +$string['aclrolesaddedgroup'] = 'The change of visibility has been triggered to allow students of selected groups to access the video: {$a->title}
Please refresh the site after some time to see the current visibility status.'; +$string['aclroleschangeerror'] = 'Error during the change of visibility of the video: {$a->title}
Some changes might have not been saved. If this occurs repeatedly, please contact your support team.'; +$string['aclrolesdeleted'] = 'The change of visibility has been triggered to prevent all students of the course from accessing the video: {$a->title}
Please refresh the site after some time to see the current visibility status.'; $string['aclrolesname'] = 'Roles'; $string['aclrolesnamedesc'] = 'You can use placeholders in the role name which are automatically replaced (list of placeholders). The list of actions must be comma-separated.'; $string['actions'] = 'Comma-separated list of actions'; +$string['addactivity_addbuttonexplanation'] = 'The videos which are added to and are available in this course are not provided to your students automatically.
Using the "Provide" buttons, you can add activities to your course which provide either all videos in a series or single videos to your students.'; +$string['addactivity_addbuttontitle'] = 'Add Opencast Video Provider activity to course'; +$string['addactivity_addbuttontitlereturncourse'] = 'Add module and return to course'; +$string['addactivity_addbuttontitlereturnoverview'] = 'Add module and return to overview'; +$string['addactivity_defaulttitle'] = 'Opencast videos'; +$string['addactivity_formactivityavailability'] = 'Opencast series module access restrictions'; +$string['addactivity_formactivityintro'] = 'Opencast series module intro'; +$string['addactivity_formactivitysection'] = 'Opencast series module target section'; +$string['addactivity_formactivitytitle'] = 'Opencast series module title'; +$string['addactivity_header'] = 'Provide videos (Embedded)'; +$string['addactivity_modulecreated'] = 'The \'{$a}\' series module has been added to this course.'; +$string['addactivity_moduleexists'] = 'There is already an Opencast series module added to this course. There is no need to add another one.'; +$string['addactivity_modulenotcreated'] = 'The \'{$a}\' series module could not be created. Please try again or contact your Moodle administrator.'; +$string['addactivity_noemptytitle'] = 'You have to set a title for the Opencast series module or to use the default title ("{$a}")'; +$string['addactivity_settingavailability'] = 'Set series module availability'; +$string['addactivity_settingavailability_desc'] = 'If enabled, teachers can set the availability conditions when a new Opencast Video Provider activity for series is added to a course.'; +$string['addactivity_settingavailability_note'] = 'Please note: This feature is only available if availability is globally enabled on the {$a} admin setting page.'; +$string['addactivity_settingdefaulttitle'] = 'Default Opencast activity series module title'; +$string['addactivity_settingdefaulttitle_desc'] = 'The default title to be used when a new Opencast Video Provider activity for series is added to a course.'; +$string['addactivity_settingenabled'] = 'Enable "Add Opencast activity series module"'; +$string['addactivity_settingenabled_desc'] = 'If enabled, teachers can add an Opencast Activity series module to a course. This Activity series module will be pointing to the course\'s Opencast series.'; +$string['addactivity_settingheader'] = 'Add Opencast Activity modules to courses'; +$string['addactivity_settingintro'] = 'Add series module intro'; +$string['addactivity_settingintro_desc'] = 'If enabled, teachers can add an intro to the Opencast activity series module. This intro will be shown on the course overview page.'; +$string['addactivity_settingsection'] = 'Choose series module section'; +$string['addactivity_settingsection_desc'] = 'If enabled, teachers can choose the section which the Opencast Activity series module will be added to.'; +$string['addactivity_viewbuttonexplanation'] = 'An Opencast series module to provide the videos available in this course has been added to the course before.'; +$string['addactivity_viewbuttontitle'] = 'View Opencast series module in course'; +$string['addactivityepisode_addbuttontitlereturncourse'] = 'Add module and return to course'; +$string['addactivityepisode_addbuttontitlereturnoverview'] = 'Add module and return to overview'; +$string['addactivityepisode_addicontitle'] = 'Add Opencast episode module to course'; +$string['addactivityepisode_defaulttitle'] = 'Opencast episode'; +$string['addactivityepisode_explanation'] = 'Additionally, in the videos table above, you can add individual Opencast episode modules to your course which provide one single video activity to your students.'; +$string['addactivityepisode_formactivityavailability'] = 'Opencast episode module access restrictions'; +$string['addactivityepisode_formactivityintro'] = 'Opencast episode module intro'; +$string['addactivityepisode_formactivitysection'] = 'Opencast episode module target section'; +$string['addactivityepisode_formactivitytitle'] = 'Opencast episode module title'; +$string['addactivityepisode_modulecreated'] = 'The \'{$a}\' episode module has been added to this course.'; +$string['addactivityepisode_moduleexists'] = 'There is already an Opencast episode module added to this course. There is no need to add another one.'; +$string['addactivityepisode_modulenotcreated'] = 'The \'{$a}\' episode module could not be created. Please try again or contact your Moodle administrator.'; +$string['addactivityepisode_noemptytitle'] = 'You have to set a title for the Opencast episode module or to use the default title ("{$a}")'; +$string['addactivityepisode_settingavailability'] = 'Set episode module availability'; +$string['addactivityepisode_settingavailability_desc'] = 'If enabled, teachers can set the availability conditions when a new Opencast Activity episode module is added to a course.'; +$string['addactivityepisode_settingenabled'] = 'Enable "Add Opencast Activity episode module"'; +$string['addactivityepisode_settingenabled_desc'] = 'If enabled, teachers can add an Opencast Video Provider activity for episodes to a course. This Opencast Activity episode module will be pointing to an Opencast episode.'; +$string['addactivityepisode_settingintro'] = 'Add episode module intro'; +$string['addactivityepisode_settingintro_desc'] = 'If enabled, teachers can add a intro to the Opencast Activity episode module. This intro will be shown on the course overview page.'; +$string['addactivityepisode_settingsection'] = 'Choose episode module section'; +$string['addactivityepisode_settingsection_desc'] = 'If enabled, teachers can choose the section which the Opencast Activity episode module will be added to.'; +$string['addactivityepisode_viewicontitle'] = 'View Opencast episode module in course'; $string['addcatalog'] = 'Add new metadata'; -$string['addnewcatalogfield'] = 'A new field has been added to metadata catalog.'; -$string['adhocfiledeletion'] = 'Delete videofile from moodle'; -$string['adhocfiledeletiondesc'] = 'If activated the plugin tries to delete the videofile from moodle\'s filessystem right after it was uploaded to opencast server. - Please note that the file will still remain in the file system, if it is used within other places in moodle.'; -$string['addlti_modulecreated'] = 'The \'{$a}\' series module has been added to this course.'; -$string['addlti_moduleexists'] = 'There is already an Opencast series module added to this course. There is no need to add another one.'; -$string['addlti_modulenotcreated'] = 'The \'{$a}\' series module could not be created. Please try again or contact your Moodle administrator.'; +$string['additional_settings'] = 'Additional features'; $string['addlti_addbuttonexplanation'] = 'The videos which are added to and are available in this course are not provided to your students automatically.
Here, you can add an Opencast LTI series module to your course which provides all available videos as an Opencast series list to your students.'; $string['addlti_addbuttontitle'] = 'Add Opencast LTI series module to course'; $string['addlti_addbuttontitlereturncourse'] = 'Add module and return to course'; @@ -62,17 +106,20 @@ $string['addlti_formltisection'] = 'Opencast series module target section'; $string['addlti_formltititle'] = 'Opencast series module title'; $string['addlti_header'] = 'Provide videos (LTI)'; +$string['addlti_modulecreated'] = 'The \'{$a}\' series module has been added to this course.'; +$string['addlti_moduleexists'] = 'There is already an Opencast series module added to this course. There is no need to add another one.'; +$string['addlti_modulenotcreated'] = 'The \'{$a}\' series module could not be created. Please try again or contact your Moodle administrator.'; $string['addlti_noemptytitle'] = 'You have to set a title for the Opencast series module or to use the default title ("{$a}")'; $string['addlti_settingavailability'] = 'Set series module availability'; $string['addlti_settingavailability_desc'] = 'If enabled, teachers can set the availability conditions when a new Opencast LTI series module is added to a course.'; $string['addlti_settingavailability_note'] = 'Please note: This feature is only available if availability is globally enabled on the {$a} admin setting page.'; $string['addlti_settingdefaulttitle'] = 'Default LTI series module title'; $string['addlti_settingdefaulttitle_desc'] = 'The default title to be used when a new Opencast LTI series module is added to a course.'; -$string['addlti_settingintro'] = 'Add series module intro'; -$string['addlti_settingintro_desc'] = 'If enabled, teachers can add an intro to the Opencast LTI series module. This intro will be shown on the course overview page.'; $string['addlti_settingenabled'] = 'Enable "Add LTI series module"'; $string['addlti_settingenabled_desc'] = 'If enabled, teachers can add an Opencast LTI series module to a course. This LTI series module will be pointing to the course\'s Opencast series.'; $string['addlti_settingheader'] = 'Add Opencast LTI series modules to courses'; +$string['addlti_settingintro'] = 'Add series module intro'; +$string['addlti_settingintro_desc'] = 'If enabled, teachers can add an intro to the Opencast LTI series module. This intro will be shown on the course overview page.'; $string['addlti_settingpreconfiguredtool'] = 'Preconfigured LTI tool for series modules'; $string['addlti_settingpreconfiguredtool_desc'] = 'The preconfigured LTI tool to be used when a new Opencast LTI series module is added to a course.'; $string['addlti_settingpreconfiguredtool_notools'] = 'No preconfigured LTI tools to be used found. Please create an Opencast series LTI tool first on the {$a} admin setting page.'; @@ -80,13 +127,13 @@ $string['addlti_settingsection_desc'] = 'If enabled, teachers can choose the section which the Opencast LTI series module will be added to.'; $string['addlti_viewbuttonexplanation'] = 'An Opencast series module to provide the videos available in this course has been added to the course before.'; $string['addlti_viewbuttontitle'] = 'View Opencast LTI series module in course'; -$string['addltiepisode_addicontitle'] = 'Add Opencast episode module to course'; $string['addltiepisode_addbuttontitlereturncourse'] = 'Add module and return to course'; $string['addltiepisode_addbuttontitlereturnoverview'] = 'Add module and return to overview'; -$string['addltiepisode_explanation'] = 'Additionally, in the videos table above, you can add individual Opencast episode modules to your course which provide one single video activity to your students.'; +$string['addltiepisode_addicontitle'] = 'Add Opencast episode module to course'; $string['addltiepisode_defaulttitle'] = 'Opencast episode'; -$string['addltiepisode_errornotenabledorworking'] = 'The \'Add Opencast episode module\' feature is not enabled or not working'; $string['addltiepisode_errorepisodeuuidnotvalid'] = 'The given episode UUID is not valid'; +$string['addltiepisode_errornotenabledorworking'] = 'The \'Add Opencast episode module\' feature is not enabled or not working'; +$string['addltiepisode_explanation'] = 'Additionally, in the videos table above, you can add individual Opencast episode modules to your course which provide one single video activity to your students.'; $string['addltiepisode_formltiavailability'] = 'Opencast episode module access restrictions'; $string['addltiepisode_formltiintro'] = 'Opencast episode module intro'; $string['addltiepisode_formltisection'] = 'Opencast episode module target section'; @@ -97,78 +144,32 @@ $string['addltiepisode_noemptytitle'] = 'You have to set a title for the Opencast episode module or to use the default title ("{$a}")'; $string['addltiepisode_settingavailability'] = 'Set episode module availability'; $string['addltiepisode_settingavailability_desc'] = 'If enabled, teachers can set the availability conditions when a new Opencast LTI episode module is added to a course.'; -$string['addltiepisode_settingintro'] = 'Add episode module intro'; -$string['addltiepisode_settingintro_desc'] = 'If enabled, teachers can add a intro to the Opencast LTI episode module. This intro will be shown on the course overview page.'; $string['addltiepisode_settingenabled'] = 'Enable "Add LTI episode module"'; $string['addltiepisode_settingenabled_desc'] = 'If enabled, teachers can add an Opencast LTI episode module to a course. This LTI episode module will be pointing to an Opencast episode.'; $string['addltiepisode_settingheader'] = 'Add Opencast LTI episode modules to courses'; +$string['addltiepisode_settingintro'] = 'Add episode module intro'; +$string['addltiepisode_settingintro_desc'] = 'If enabled, teachers can add a intro to the Opencast LTI episode module. This intro will be shown on the course overview page.'; $string['addltiepisode_settingpreconfiguredtool'] = 'Preconfigured LTI tool for episode modules'; $string['addltiepisode_settingpreconfiguredtool_desc'] = 'The preconfigured LTI tool to be used when a new Opencast LTI episode module is added to a course.'; $string['addltiepisode_settingpreconfiguredtool_notools'] = 'No preconfigured LTI tools to be used found. Please create an Opencast episode LTI tool first on the {$a} admin setting page.'; $string['addltiepisode_settingsection'] = 'Choose episode module section'; $string['addltiepisode_settingsection_desc'] = 'If enabled, teachers can choose the section which the Opencast LTI episode module will be added to.'; $string['addltiepisode_viewicontitle'] = 'View Opencast episode module in course'; - -$string['addactivity_modulecreated'] = 'The \'{$a}\' series module has been added to this course.'; -$string['addactivity_moduleexists'] = 'There is already an Opencast series module added to this course. There is no need to add another one.'; -$string['addactivity_modulenotcreated'] = 'The \'{$a}\' series module could not be created. Please try again or contact your Moodle administrator.'; -$string['addactivity_addbuttonexplanation'] = 'The videos which are added to and are available in this course are not provided to your students automatically.
Using the "Provide" buttons, you can add activities to your course which provide either all videos in a series or single videos to your students.'; -$string['addactivity_addbuttontitle'] = 'Add Opencast Video Provider activity to course'; -$string['addactivity_addbuttontitlereturncourse'] = 'Add module and return to course'; -$string['addactivity_addbuttontitlereturnoverview'] = 'Add module and return to overview'; -$string['addactivity_defaulttitle'] = 'Opencast videos'; -$string['addactivity_formactivityavailability'] = 'Opencast series module access restrictions'; -$string['addactivity_formactivityintro'] = 'Opencast series module intro'; -$string['addactivity_formactivitysection'] = 'Opencast series module target section'; -$string['addactivity_formactivitytitle'] = 'Opencast series module title'; -$string['addactivity_header'] = 'Provide videos (Embedded)'; -$string['addactivity_noemptytitle'] = 'You have to set a title for the Opencast series module or to use the default title ("{$a}")'; -$string['addactivity_settingavailability'] = 'Set series module availability'; -$string['addactivity_settingavailability_desc'] = 'If enabled, teachers can set the availability conditions when a new Opencast Video Provider activity for series is added to a course.'; -$string['addactivity_settingavailability_note'] = 'Please note: This feature is only available if availability is globally enabled on the {$a} admin setting page.'; -$string['addactivity_settingdefaulttitle'] = 'Default Opencast activity series module title'; -$string['addactivity_settingdefaulttitle_desc'] = 'The default title to be used when a new Opencast Video Provider activity for series is added to a course.'; -$string['addactivity_settingintro'] = 'Add series module intro'; -$string['addactivity_settingintro_desc'] = 'If enabled, teachers can add an intro to the Opencast activity series module. This intro will be shown on the course overview page.'; -$string['addactivity_settingenabled'] = 'Enable "Add Opencast activity series module"'; -$string['addactivity_settingenabled_desc'] = 'If enabled, teachers can add an Opencast Activity series module to a course. This Activity series module will be pointing to the course\'s Opencast series.'; -$string['addactivity_settingheader'] = 'Add Opencast Activity modules to courses'; -$string['addactivity_settingsection'] = 'Choose series module section'; -$string['addactivity_settingsection_desc'] = 'If enabled, teachers can choose the section which the Opencast Activity series module will be added to.'; -$string['addactivity_viewbuttonexplanation'] = 'An Opencast series module to provide the videos available in this course has been added to the course before.'; -$string['addactivity_viewbuttontitle'] = 'View Opencast series module in course'; -$string['addactivityepisode_addicontitle'] = 'Add Opencast episode module to course'; -$string['addactivityepisode_addbuttontitlereturncourse'] = 'Add module and return to course'; -$string['addactivityepisode_addbuttontitlereturnoverview'] = 'Add module and return to overview'; -$string['addactivityepisode_explanation'] = 'Additionally, in the videos table above, you can add individual Opencast episode modules to your course which provide one single video activity to your students.'; -$string['addactivityepisode_defaulttitle'] = 'Opencast episode'; -$string['addactivityepisode_formactivityavailability'] = 'Opencast episode module access restrictions'; -$string['addactivityepisode_formactivityintro'] = 'Opencast episode module intro'; -$string['addactivityepisode_formactivitysection'] = 'Opencast episode module target section'; -$string['addactivityepisode_formactivitytitle'] = 'Opencast episode module title'; -$string['addactivityepisode_modulecreated'] = 'The \'{$a}\' episode module has been added to this course.'; -$string['addactivityepisode_moduleexists'] = 'There is already an Opencast episode module added to this course. There is no need to add another one.'; -$string['addactivityepisode_modulenotcreated'] = 'The \'{$a}\' episode module could not be created. Please try again or contact your Moodle administrator.'; -$string['addactivityepisode_noemptytitle'] = 'You have to set a title for the Opencast episode module or to use the default title ("{$a}")'; -$string['addactivityepisode_settingavailability'] = 'Set episode module availability'; -$string['addactivityepisode_settingavailability_desc'] = 'If enabled, teachers can set the availability conditions when a new Opencast Activity episode module is added to a course.'; -$string['addactivityepisode_settingintro'] = 'Add episode module intro'; -$string['addactivityepisode_settingintro_desc'] = 'If enabled, teachers can add a intro to the Opencast Activity episode module. This intro will be shown on the course overview page.'; -$string['addactivityepisode_settingenabled'] = 'Enable "Add Opencast Activity episode module"'; -$string['addactivityepisode_settingenabled_desc'] = 'If enabled, teachers can add an Opencast Video Provider activity for episodes to a course. This Opencast Activity episode module will be pointing to an Opencast episode.'; -$string['addactivityepisode_settingsection'] = 'Choose episode module section'; -$string['addactivityepisode_settingsection_desc'] = 'If enabled, teachers can choose the section which the Opencast Activity episode module will be added to.'; -$string['addactivityepisode_viewicontitle'] = 'View Opencast episode module in course'; -$string['additional_settings'] = 'Additional features'; +$string['addnewcatalogfield'] = 'A new field has been added to metadata catalog.'; +$string['addnewtranscription'] = 'Add new transcription'; +$string['addnewtranscription_desc'] = 'Please select a service type in which your transcription should be represented, and then upload the file with requiured extensions.
NOTE: Uploading a new transcription with an already uploaded service type results in replacing that transcription, which might be useful for editing the current ones.'; +$string['addrole'] = 'Add new role'; +$string['addtranscriptionflavor'] = 'Add new flavor option'; $string['addvideo'] = 'Add video'; $string['addvideonotallowed'] = 'You are not allowed to upload a video to this series.'; -$string['addrole'] = 'Add new role'; -$string['adminchoice_noworkflow'] = "-- No workflow --"; +$string['adhocfiledeletion'] = 'Delete videofile from moodle'; +$string['adhocfiledeletiondesc'] = 'If activated the plugin tries to delete the videofile from moodle\'s filessystem right after it was uploaded to opencast server. Please note that the file will still remain in the file system, if it is used within other places in moodle.'; $string['adminchoice_noconnection'] = "-- Workflows could not be retrieved --"; +$string['adminchoice_noworkflow'] = "-- No workflow --"; +$string['allowdownloadtranscriptionsetting'] = 'Allow download transcriptions'; +$string['allowdownloadtranscriptionsetting_desc'] = 'When enabled, the transcription download button will be displayed in the manage transcriptions page, by which teachers are able to download the transcription\'s file.
Notice: In case you are using Opencast 13 or later, you need to make sure that all prerequisites including LTI features and permissions to access /assets/ endpoint for LTI users, are set correctly as it is mandatory to perform LTI call.'; $string['allowunassign'] = 'Allow unassign from course'; -$string['allowunassigndesc'] = 'Delete the assignment of a course series to control visibility in filepicker and course lists. This feature is only available, - when it is possible to have events without series in opencast. Please ask the admistrator of the opencast system before activating this.'; -$string['appearance_settings'] = 'Appearance'; +$string['allowunassigndesc'] = 'Delete the assignment of a course series to control visibility in filepicker and course lists. This feature is only available, when it is possible to have events without series in opencast. Please ask the admistrator of the opencast system before activating this.'; $string['appearance_overview_settingheader'] = 'Overview page'; $string['appearance_overview_settingshowenddate'] = 'Show end date'; $string['appearance_overview_settingshowenddate_desc'] = 'If enabled, the table of available videos on the overview page will contain a column which shows the end date of the Opencast episode.'; @@ -176,749 +177,673 @@ $string['appearance_overview_settingshowlocation_desc'] = 'If enabled, the table of available videos on the overview page will contain a column which shows the location of the Opencast episode.'; $string['appearance_overview_settingshowpublicationchannels'] = 'Show publication channels'; $string['appearance_overview_settingshowpublicationchannels_desc'] = 'If enabled, the table of available videos on the overview page will contain a column which shows the publication channel of the Opencast episode. The same information will also be given on the Opencast episode deletion page.'; - +$string['appearance_settings'] = 'Appearance'; $string['backupopencastvideos'] = 'Include videos from Opencast instance {$a} in this course'; +$string['batchupload'] = 'Add videos (batch)'; +$string['batchupload_emptyvideosuploaderror'] = 'You must upload at least one presenter video file.'; +$string['batchupload_errornotenabled'] = 'Unfortunately the batch video upload feature is unavailable for this Opencast instance, please try to contanct your system administrator.'; +$string['batchupload_errorsaveuploadjobs'] = 'There were errors uploading {$a->count} out of {$a->total} video(s).'; +$string['batchupload_errorseriesmismatched'] = 'Unfortunately the series is not defined in this course.'; +$string['batchupload_filemanager_presenter_title'] = 'Presenter videos'; +$string['batchupload_form_header'] = 'Batch Upload Files'; +$string['batchupload_jobssaved'] = 'Batch of {$a} Video(s) successfully uploaded.
The videos are queued for transferring to Opencast. Therefore, you do not need to wait on this page for them to finish.'; +$string['batchupload_metadata_desc'] = 'By uploading a batch of videos to Opencast at once, the following metadata will be set for each video.'; +$string['batchupload_metadata_header'] = 'Batch Metadata'; +$string['batchupload_setting'] = 'Enable batch video upload'; +$string['batchupload_setting_desc'] = 'By enabling this option, the Opencast instance will provide a separate page to the users to upload videos in batch at once. Please note that the local_chunkupload plugin does not work in this upload mode. This means that the file size is limited based on your settings.
To avoid cluttering the upload job queue up as well as decreasing the upload process time, it is recommended to increase the "Limit upload job by cron".
To avoid any timeout error during video uploads, it is recommended to adjust timeout options in the following settings according to your needs:
{$a->uploadtimeoutlink}
{$a->toolopencastinstancelink} '; +$string['batchupload_visibility_desc'] = 'The batch visibility setting will be applied for each uploaded video in the batch.'; +$string['batchupload_visibility_header'] = 'Batch Visibility'; +$string['batchuploadexplanation'] = 'In this section you are able to upload multiple files at once.
NOTE: Please keep in mind that the batch video upload is only available for presenter flavors.'; $string['blocksettings'] = 'Settings for a block instance'; - -$string['changingownersuccess'] = 'The ownership was successfully transferred.'; -$string['changingownerfailed'] = 'An error occured. The ownership could not be transferred.'; $string['cachedef_videodata'] = 'Caches the result of the opencast api for the opencast-block.'; $string['cachevalidtime'] = 'Cache valid time'; $string['cachevalidtime_desc'] = 'Time in seconds, before the cache for the video data of each course is refreshed.'; $string['cantdeletedefaultseries'] = 'You cannot delete the default series. Please choose another default series before deleting this series.'; -$string['catalog_static_params_empty'] = "Read only fields need to define a text in the parameters field."; $string['catalog_params_noarray'] = "Parameters have to be either empty or a JSON representation of an array or an object."; -$string['changevisibility_visible'] = 'The video is visible to all students of the course. Click to alter visibility.'; -$string['legendtitle'] = 'Details Table'; -$string['legendalt'] = 'More details about all possible values of this column.'; -$string['legendocstatecapturingdesc'] = 'Live capturing in progress.'; -$string['legendocstatefaileddesc'] = 'Something went wrong while processing this video, and it has failed. Please contact the support/administrator in order to resolve this issue.'; -$string['legendocstateneedscuttingdesc'] = 'The Video requires further attention in order to finish the processing stage.'; -$string['legendocstateprocessingdesc'] = 'The video is uploaded, and it is being processed by Opencast.'; -$string['legendocstatesucceededdesc'] = 'The video has been processed and it is ready.'; -$string['legendvisibility_visible'] = 'Visible'; -$string['legendvisibility_visibledesc'] = 'The video is visible to all students of the course.'; -$string['changevisibility_mixed'] = 'The visibility of the video is in an invalid status. Click to choose the correct visibility.'; -$string['legendvisibility_mixed'] = 'Invalid'; -$string['legendvisibility_mixeddesc'] = 'The visibility of the video is in an invalid status.'; -$string['changevisibility_hidden'] = 'The video is visible to no student. Click to alter visibility.'; -$string['legendvisibility_hidden'] = 'Hidden'; -$string['legendvisibility_hiddendesc'] = 'The video is not visible to any student.'; -$string['changevisibility_group'] = 'The video is visible to all student belonging to selected groups. Click to alter visibility.'; -$string['legendvisibility_group'] = 'Group Visibility'; -$string['legendvisibility_groupdesc'] = 'The video is visible to all student belonging to selected groups.'; +$string['catalog_static_params_empty'] = "Read only fields need to define a text in the parameters field."; +$string['catalogparam'] = 'Parameters in JSON-Format'; +$string['catalogparam_help'] = 'JSON format: {"param1":"value1", "param2":"value2"}
String (text), Long Text (textarea): Parameters will be defined as attributes of the element. i.e. {"style":"min-width: 27ch;"} which defines the element´s style attribute
Drop Down (select): Parameters will be defined as options of the select element. i.e. {"en": "English", "de": "German"} which takes the left side as value and right side as text to show.(Multi-Language filters) In order for each value of Drop Down (select) to get translated using filters such as Multi-Language Content (v2), each value should contain the placeholder, defined by that filter i.e. "{mlang en}No option selected{mlang}{mlang de}Keine Option ausgewählt{mlang}" or "{mlang en}English{mlang}{mlang de}Englisch{mlang}"
Arrays (autocomplete): Parameters will be defined as suggestions. i.e. {"1": "Dr. Doe", "2": "Johnson"} which shows (Dr. Doe and Johnson) as suggestions
Date Time Selector (datetime): Parameters will be defined as date_selector variables . i.e. {"startyear": "1990", "stopyear": "2020"} which defines date range to be selected between 1990 - 2020'; $string['changeowner'] = 'Change owner'; $string['changeowner_explanation'] = 'Currently, you are the owner of the video {$a}.
You can transfer the ownership to another person.
Notice: You might loose the right to access the video.'; $string['changeownerseries_explanation'] = 'Currently, you are the owner of the series {$a}.
You can transfer the ownership to another person.
Notice: You might loose the right to access the series.'; +$string['changescheduledvisibility'] = 'Change scheduled visibility for {$a}'; +$string['changescheduledvisibilityfailed'] = 'Unabale to change scheduled visibility'; +$string['changescheduledvisibilityheader'] = 'Scheduled visibility change'; +$string['changescheduledvisibilitysuccess'] = 'Scheduled visibility successfully changed'; +$string['changevisibility'] = 'Alter visibility'; +$string['changevisibility_group'] = 'The video is visible to all student belonging to selected groups. Click to alter visibility.'; +$string['changevisibility_header'] = 'Change visibility for {$a->title}'; +$string['changevisibility_hidden'] = 'The video is visible to no student. Click to alter visibility.'; +$string['changevisibility_mixed'] = 'The visibility of the video is in an invalid status. Click to choose the correct visibility.'; +$string['changevisibility_visible'] = 'The video is visible to all students of the course. Click to alter visibility.'; +$string['changingownerfailed'] = 'An error occured. The ownership could not be transferred.'; +$string['changingownersuccess'] = 'The ownership was successfully transferred.'; $string['claimowner_explanation'] = 'Currently, nobody owns the video {$a}.
You can claim the ownership or set another person as owner.
Notice: You might loose the right to access the video if you do not claim the ownership yourself.'; $string['claimownerseries_explanation'] = 'Currently, nobody owns the series {$a}.
You can claim the ownership or set another person as owner.
Notice: You might loose the right to access the series if you do not claim the ownership yourself.'; -$string['changevisibility_header'] = 'Change visibility for {$a->title}'; -$string['changevisibility'] = 'Alter visibility'; $string['connection_failure'] = 'Could not reach Opencast server.'; +$string['contributor'] = 'Contributor(s)'; $string['coursefullnameunknown'] = 'Unkown coursename'; +$string['created'] = 'Created at'; $string['createdby'] = 'Uploaded by'; $string['createseriesforcourse'] = 'Create new series'; -$string['cronsettings'] = 'Settings for upload jobs'; -$string['catalogparam'] = 'Parameters in JSON-Format'; -$string['catalogparam_help'] = 'JSON format: {"param1":"value1", "param2":"value2"}
- String (text), Long Text (textarea): Parameters will be defined as attributes of the element. i.e. {"style":"min-width: 27ch;"} which defines the element´s style attribute
- Drop Down (select): Parameters will be defined as options of the select element. i.e. {"en": "English", "de": "German"} which takes the left side as value and right side as text to show. - (Multi-Language filters) In order for each value of Drop Down (select) to get translated using filters such as Multi-Language Content (v2), each value should contain the placeholder, defined by that filter i.e. "{mlang en}No option selected{mlang}{mlang de}Keine Option ausgewählt{mlang}" or "{mlang en}English{mlang}{mlang de}Englisch{mlang}"
- Arrays (autocomplete): Parameters will be defined as suggestions. i.e. {"1": "Dr. Doe", "2": "Johnson"} which shows (Dr. Doe and Johnson) as suggestions
- Date Time Selector (datetime): Parameters will be defined as date_selector variables . i.e. {"startyear": "1990", "stopyear": "2020"} which defines date range to be selected between 1990 - 2020'; -$string['contributor'] = 'Contributor(s)'; -$string['created'] = 'Created at'; $string['creator'] = 'Presenter(s)'; -$string['descriptionmdfd'] = 'Field Description'; -$string['descriptionmdfd_help'] = 'The content of this field is presented as a help icon near the metadata field.'; - +$string['cronsettings'] = 'Settings for upload jobs'; $string['date'] = 'Start Date'; -$string['descriptionmdfn'] = 'Field name'; -$string['descriptionmdfn_help'] = 'This is the actual field name passing as metadata (id); the presented name according to this field name should be set in language string.'; -$string['descriptionmdpj'] = 'The value should be JSON string format and it is used to define parameters for the field!'; +$string['dcmitermsnotice'] = '
IMPORTANT: Opencast supports standardized Dublin Core metadata set, therefore all metadata fields should follow DCMI terms, otherwise attempting to add unknown metadata field will result in error.
You can check the list of all available terms to use in DCMI Metadata Terms.'; $string['default'] = 'Default'; -$string['deleteaclgroup'] = 'Delete video from this list.'; -$string['delete_confirm_role'] = 'Are you sure you want to delete this role?'; +$string['defaultssaved'] = 'Default values are saved.'; +$string['delete_block_and_mapping'] = 'Delete block and series mapping'; $string['delete_confirm_metadata'] = 'Are you sure you want to delete this metadata field?'; +$string['delete_confirm_role'] = 'Are you sure you want to delete this role?'; $string['delete_confirm_series'] = 'Are you sure you want to delete this series?
Notice: The series is only unlinked from this course but not deleted in Opencast.'; -$string['deleteevent'] = 'Delete an event in Opencast'; -$string['deleteeventdesc'] = 'You are about to delete this video permanently and irreversibly from Opencast.
All embedded links to it will become invalid. Please do not continue unless you are absolutely sure.'; +$string['delete_mapping_explanation'] = 'The Opencast Block tracks which Opencast Series is mapped to the course.
You can choose whether to delete the mapping.
If you delete it, the series will no longer appear when you create the opencast block again.'; +$string['delete_metadata'] = 'Delete metadata field'; +$string['delete_role'] = 'Delete role'; +$string['delete_series'] = 'Delete series'; +$string['delete_series_failed'] = 'Deleting the series failed. Please try again later or contact an administrator.'; +$string['deleteaclgroup'] = 'Delete video from this list.'; +$string['deletecheck_title_modal'] = 'Remove Opencast Block?'; $string['deletedraft'] = 'Delete a video before transfer to Opencast'; $string['deletedraftdesc'] = 'You are about to delete this video before the transfer to Opencast.
It will be removed from the transfer queue and will not be processed. Please do not continue unless you are absolutely sure.'; +$string['deleteevent'] = 'Delete an event in Opencast'; +$string['deleteeventdesc'] = 'You are about to delete this video permanently and irreversibly from Opencast.
All embedded links to it will become invalid. Please do not continue unless you are absolutely sure.'; $string['deletegroupacldesc'] = 'You are about to delete the access to this video from this course.
If the access is deleted, the video is not displayed in filepicker and in the list of available videos. This does not affect videos, which are already embedded.
The video will not be deleted in Opencast.'; +$string['deletetranscription'] = 'Delete transcription'; +$string['deletetranscription_desc'] = 'You are about to delete the transcription.
Are you sure you would like to delete it?'; +$string['deletetranscriptionworkflow'] = 'Workflow for delete transcription'; +$string['deletetranscriptionworkflow_desc'] = 'This workflow is triggered when a transcription is deleted, it is required to provide deletion feature in order for event to be processed correctly.
NOTE: If empty, the feature will be disabled.'; $string['deleteworkflow'] = 'Workflow to start before event is be deleted'; $string['deleteworkflowdesc'] = 'Before deleting a video, a workflow can be defined, which is called to retract the event from all publication channels.'; -$string['delete_role'] = 'Delete role'; -$string['delete_metadata'] = 'Delete metadata field'; -$string['delete_series'] = 'Delete series'; -$string['delete_series_failed'] = 'Deleting the series failed. Please try again later or contact an administrator.'; $string['deleting'] = 'Going to be deleted'; $string['description'] = 'Description'; -$string['duration'] = 'Duration'; -$string['dodeleteaclgroup'] = 'Delete access to videos from this course'; -$string['dodeleteevent'] = 'Delete video permanently'; -$string['dodeletedraft'] = 'Delete video before transfer to Opencast'; -$string['downloadvideo'] = 'Download video'; -$string['download_settingheader'] = 'Download videos'; -$string['download_setting'] = 'Download channel'; -$string['download_settingdesc'] = 'Opencast publication channel from which the videos are served when downloading them.'; -$string['duplicateworkflow'] = 'Workflow for duplicating events'; -$string['duplicateworkflowdesc'] = 'This workflow is needed for importing opencast events from one course into another. If not set, it is not possible to import Opencast events.'; - +$string['descriptionmdbatchable'] = 'Batchable'; +$string['descriptionmdbatchable_help'] = 'When enabled, the metadata field can be set for batch video upload.'; +$string['descriptionmddefaultable'] = 'Defaultable'; +$string['descriptionmddefaultable_help'] = 'When enabled, users can add default value for this field.'; +$string['descriptionmdfd'] = 'Field Description'; +$string['descriptionmdfd_help'] = 'The content of this field is presented as a help icon near the metadata field.'; +$string['descriptionmdfn'] = 'Field name'; +$string['descriptionmdfn_help'] = 'This is the actual field name passing as metadata (id); the presented name according to this field name should be set in language string.'; +$string['descriptionmdpj'] = 'The value should be JSON string format and it is used to define parameters for the field!'; +$string['descriptionmdreadonly'] = 'Readonly'; +$string['descriptionmdreadonly_help'] = 'Please note that, if a field is set to be required, the readonly option will be disabled. That means a field can only be readonly or required at a time.'; +$string['directaccess_copy_no_link'] = 'Invalid direct access link'; +$string['directaccess_copy_success'] = 'The direct access link has been successfully copied to clipboard.'; +$string['directaccess_copytoclipboard_unavialable'] = 'It seems that your browser does not support the copy to clipboard functionality, try to copy the link manually from the dropdown item.'; +$string['directaccess_setting'] = 'Direct access channel'; +$string['directaccess_settingdesc'] = 'Opencast publication channel from which the videos are served when accessing them directly. Leaving this option empty will disable the feature.
Notice: It is recommended to take further caution using this feature, since it reveals the direct video data on the Opencast server upon accessing the link.'; +$string['directaccesscopylink'] = 'Copy video direct access link'; +$string['directaccesstovideo'] = 'Direct access to video'; +$string['dodeleteaclgroup'] = 'Delete access to videos from this course'; +$string['dodeletedraft'] = 'Delete video before transfer to Opencast'; +$string['dodeleteevent'] = 'Delete video permanently'; +$string['download_setting'] = 'Download channel'; +$string['download_settingdesc'] = 'Opencast publication channel from which the videos are served when downloading them.'; +$string['download_settingheader'] = 'Download videos'; +$string['downloadtranscription'] = 'Download transcription'; +$string['downloadvideo'] = 'Download video'; +$string['duplicateworkflow'] = 'Workflow for duplicating events'; +$string['duplicateworkflowdesc'] = 'This workflow is needed for importing opencast events from one course into another. If not set, it is not possible to import Opencast events.'; +$string['duration'] = 'Duration'; +$string['editorbaseurl'] = 'Opencast Editor Base URL'; +$string['editorbaseurl_desc'] = 'The base URL to be used to call the Opencast Editor, the base url of the opencast instance is used if empty.'; +$string['editorendpointurl'] = 'Opencast Editor Endpoint'; +$string['editorendpointurl_desc'] = 'The editor endpoint to access the editor. The mediapackage ID will be added at the end of the url.'; $string['editseries'] = 'Edit series'; $string['embeddedasactivity'] = 'Embedded as activity'; $string['embeddedasactivitywolink'] = 'Embedded as activity without linked series'; $string['empty_catalogname'] = 'This field must not be empty'; +$string['emptyflavoroption'] = 'Please select a service type'; $string['emptyvideouploaderror'] = 'You must either upload a presenter video or a presentation video file.'; +$string['emptyvisibilitygroups'] = 'At least one group must be selected.'; +$string['enablechunkupload'] = 'Enable Chunkupload'; +$string['enablechunkupload_desc'] = 'If Chunkupload is enabled it will be possible to upload videos using the chunkupload plugin'; +$string['enableopencasteditorlink'] = 'Show the link to opencast Editor in action menu'; +$string['enableopencasteditorlink_desc'] = 'This option renders a button to opencast editor in the block content and the block overview. The following settings as well lti credentials have to be configured as well.'; +$string['enableopencaststudiolink'] = 'Show the link to opencast studio'; +$string['enableopencaststudiolink_desc'] = 'This option renders a button to opencast studio in the block content and the block overview. Opencast studio has to run on your opencast admin node and the following lti settings have to be configured as well.'; +$string['enableopencaststudioreturnbtn'] = 'Show a redirect back button in Studio'; +$string['enableopencaststudioreturnbtn_desc'] = 'When enabled, Studio then renders an additional button "Exit and go back" after up- or downloading the recording.'; +$string['enableschedulingchangevisibility'] = 'Schedule a visibility change'; +$string['enableschedulingchangevisibilitydesc'] = 'Set a date and a visibility status for the event in future, which will be performed using a scheduled task.'; $string['engageplayerintegration'] = 'Engage player integration'; $string['engageredirect'] = 'Redirect to engage player'; $string['engageurl'] = 'URL of the Opencast Engage server'; $string['engageurl_desc'] = 'If empty, the video titles in the overview are not linked to the engage player.'; -$string['expirydate'] = 'Expiry Date'; -$string['exists_catalogname'] = 'The field is already existed'; -$string['enablechunkupload'] = 'Enable Chunkupload'; -$string['enablechunkupload_desc'] = 'If Chunkupload is enabled it will be possible to upload videos using the chunkupload plugin'; -$string['enableopencaststudiolink'] = 'Show the link to opencast studio'; -$string['enableopencaststudiolink_desc'] = 'This option renders a button to opencast studio in the block content and the block overview. -Opencast studio has to run on your opencast admin node and the following lti settings have to be configured as well.'; -$string['opencaststudiobaseurl'] = 'Opencast Studio Base URL'; -$string['opencaststudiobaseurl_desc'] = 'The base URL to be used to call Opencast studio. The base URL of the opencast instance is used if empty.'; -$string['error_eventid_taskdata_missing'] = 'The task data contains no event id. - Opencast duplicate event task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; +$string['error_block_delete_seriesmapping'] = 'Unfortunately, there was an error during course series mapping deletion, please contact the system administrator.'; +$string['error_duplicated_event_acl_change'] = 'The visibility change for the duplicated event failed. Opencast duplicated event visibility change task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; +$string['error_duplicated_event_id_not_ready'] = 'The duplicated event is not available yet. Opencast duplicated event visibility change task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; +$string['error_eventid_taskdata_missing'] = 'The task data contains no event id. Opencast duplicate event task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; +$string['error_no_duplicate_origin_event_id'] = 'The origin event id is missing. Opencast duplicated event visibility change task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; +$string['error_no_duplicate_workflow_id'] = 'The duplicate workflow id is missing. Opencast duplicated event visibility change task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; $string['error_seriesid_missing_course'] = 'The course {$a->coursefullname} (ID: {$a->courseid}) has no course series. The event ({$a->eventid}) could not be restored.'; -$string['error_seriesid_not_matching'] = 'The course {$a->coursefullname} (ID: {$a->courseid}) has a course series, that does not match the seriesid of the task. - The event ({$a->eventid}) could not be restored.'; -$string['error_seriesid_missing_opencast'] = 'The series of course {$a->coursefullname} (ID: {$a->courseid}) can not be found in the opencast system. - The event ({$a->eventid}) could not be restored.'; -$string['series_not_found'] = 'The series {$a} could not be found in the opencast system.'; -$string['error_seriesid_taskdata_missing'] = 'The task data contains no series id. - Opencast duplicate event task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; -$string['error_workflow_setup_missing'] = 'The plugin block_opencast is not properly configurated. The duplication workflow is missing!'; -$string['error_workflow_not_exists'] = 'The workflow {$a->duplicateworkflow} can not be found in the opencast system. - The event ({$a->eventid}) could not be restored for course {$a->coursefullname} (ID: {$a->courseid}).'; +$string['error_seriesid_missing_opencast'] = 'The series of course {$a->coursefullname} (ID: {$a->courseid}) can not be found in the opencast system. The event ({$a->eventid}) could not be restored.'; +$string['error_seriesid_not_matching'] = 'The course {$a->coursefullname} (ID: {$a->courseid}) has a course series, that does not match the seriesid of the task. The event ({$a->eventid}) could not be restored.'; +$string['error_seriesid_taskdata_missing'] = 'The task data contains no series id. Opencast duplicate event task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; +$string['error_workflow_not_exists'] = 'The workflow {$a->duplicateworkflow} can not be found in the opencast system. The event ({$a->eventid}) could not be restored for course {$a->coursefullname} (ID: {$a->courseid}).'; $string['error_workflow_not_started'] = 'The workflow to copy the video ({$a->eventid}) assigned to course {$a->coursefullname} (ID: {$a->courseid}) could not be started.'; -$string['erroremailsubj'] = 'Error while executing opencast process duplicate task'; -$string['erroremailbody'] = '{$a->errorstr} Details: {$a->message}.'; +$string['error_workflow_setup_missing'] = 'The plugin block_opencast is not properly configurated. The duplication workflow is missing!'; +$string['errorduplicatedeventvisibilitytaskretry'] = 'An error occured by executing a task for setting the duplicated event\'s visibility: {$a} Will try to start the workflow again by the next cron job.'; +$string['errorduplicatedeventvisibilitytaskterminated'] = 'An error occured by executing a task for setting the duplicated event\'s visibility: {$a} After trying serveral time the task will be terminated now.'; $string['errorduplicatetaskretry'] = 'An error occured by executing a task for duplication of an event: {$a} Will try to start the workflow again by the next cron job.'; -$string['errorduplicatetaskterminate'] = 'An error occured by executing a task for duplication of an event: {$a} - After trying serveral time the task will be terminated now.'; -$string['errorrestoremissingevents_subj'] = 'Opencast error during restore process'; -$string['errorrestoremissingevents_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). - The video(s) with the following identifier(s) could not be found in opencast system. This video(s) will not be restored:'; -$string['errorrestoremissingseries_subj'] = 'Opencast error during restore process'; -$string['errorrestoremissingseries_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). - No opencast series could be created. Therefore, the following eventIDs could not be duplicated:'; -$string['errorrestoremissingimportmode_subj'] = 'Opencast error during restore process'; -$string['errorrestoremissingimportmode_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). - Import mode could not be identified, therefore restore task has failed.'; -$string['errorrestoremissingsourcecourseid_subj'] = 'Opencast error during restore process'; -$string['errorrestoremissingsourcecourseid_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). - Source course id could not be found.'; -$string['errorrestoremissingseriesid_subj'] = 'Opencast error during restore process'; -$string['errorrestoremissingseriesid_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). - Series id could not be found.'; +$string['errorduplicatetaskterminate'] = 'An error occured by executing a task for duplication of an event: {$a} After trying serveral time the task will be terminated now.'; +$string['erroremailbody'] = '{$a->errorstr} Details: {$a->message}.'; +$string['erroremailsubj'] = 'Error while executing opencast process duplicate task'; +$string['errorgetblockvideos'] = 'List cannot be loaded (Error: {$a})'; +$string['errorrestorefailedeventsaclchange_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). The visibility of the video(s) with the following identifier(s) could not be changed. This video(s) will not be accessible in the new course:'; $string['errorrestorefailedeventsaclchange_subj'] = 'Opencast error during restore process'; -$string['errorrestorefailedeventsaclchange_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). - The visibility of the video(s) with the following identifier(s) could not be changed. This video(s) will not be accessible in the new course:'; +$string['errorrestorefailedseriesaclchange_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). The series ACL could not be changed (series: {$a->seriesid}).'; $string['errorrestorefailedseriesaclchange_subj'] = 'Opencast error during restore process'; -$string['errorrestorefailedseriesaclchange_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). - The series ACL could not be changed (series: {$a->seriesid}).'; +$string['errorrestorefailedseriesmapping_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). Mapping the series {$a->seriesid} to the new course failed.'; $string['errorrestorefailedseriesmapping_subj'] = 'Opencast error during restore process'; -$string['errorrestorefailedseriesmapping_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). - Mapping the series {$a->seriesid} to the new course failed.'; +$string['errorrestoreincompletedimportmapping_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). The following events could not get the completion flag for the restore session, therefore they will not be processed later to fix the modules if any:'; +$string['errorrestoremissingevents_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). The video(s) with the following identifier(s) could not be found in opencast system. This video(s) will not be restored:'; +$string['errorrestoremissingevents_subj'] = 'Opencast error during restore process'; +$string['errorrestoremissingimportmapping_subj'] = 'Opencast error during restore process (Import mapping)'; +$string['errorrestoremissingimportmappingevents_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). The following events have no import mapping record, therefore, module fixing process might not be performed if exists:'; +$string['errorrestoremissingimportmappingseries_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). The following series have no import mapping record, therefore, module fixing process might not be performed if exists:'; +$string['errorrestoremissingimportmode_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). Import mode could not be identified, therefore restore task has failed.'; +$string['errorrestoremissingimportmode_subj'] = 'Opencast error during restore process'; +$string['errorrestoremissingseries_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). No opencast series could be created. Therefore, the following eventIDs could not be duplicated:'; +$string['errorrestoremissingseries_subj'] = 'Opencast error during restore process'; +$string['errorrestoremissingseriesid_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). Series id could not be found.'; +$string['errorrestoremissingseriesid_subj'] = 'Opencast error during restore process'; +$string['errorrestoremissingsourcecourseid_body'] = 'There was a problem in the restore process of the course {$a->coursefullname} (ID: {$a->courseid}). Source course id could not be found.'; +$string['errorrestoremissingsourcecourseid_subj'] = 'Opencast error during restore process'; $string['eventdeleted'] = 'The video has been deleted.'; $string['eventdeletedfailed'] = 'Failed to delete the event'; $string['eventdeletionstarted'] = 'The video will be deleted shortly.'; -$string['eventuploadsucceeded'] = 'Upload succeeded'; $string['eventuploadfailed'] = 'Upload failed'; -$string['errorgetblockvideos'] = 'List cannot be loaded (Error: {$a})'; - +$string['eventuploadsucceeded'] = 'Upload succeeded'; +$string['exists_catalogname'] = 'The field is already existed'; +$string['expirydate'] = 'Expiry Date'; $string['failedtogetvideo'] = 'Cannot get event data from Opencast.'; $string['failedtransferattempts'] = 'Failed transfer attempts: {$a}'; $string['filetypes'] = 'Accepted file types'; $string['form_seriesid'] = 'Series ID'; $string['form_seriestitle'] = 'Series title'; $string['functionalitydisabled'] = 'This functionality is disabled.'; - $string['general_settings'] = 'General settings'; $string['gotooverview'] = 'Go to overview...'; +$string['group_name_empty'] = 'The group name must not be empty if a group should be created.'; $string['groupcreation'] = 'Create a group'; $string['groupcreationdesc'] = 'If checked, a group is created during the upload.'; $string['groupname'] = 'Group name'; $string['groupnamedesc'] = 'Group to which the video is added. Important: The group name length is restricted to 128 Bytes. You can use the placeholders [COURSEID] and [COURSENAME] which are automatically replaced.'; $string['groupseries_header'] = 'Group and Series'; -$string['group_name_empty'] = 'The group name must not be empty if a group should be created.'; - -$string['heading_name'] = 'Field Name'; +$string['haction'] = 'Action'; +$string['heading_actions'] = 'Actions'; +$string['heading_batchable'] = 'Batchable'; $string['heading_datatype'] = 'Field Type'; +$string['heading_defaultable'] = 'Defaultable'; +$string['heading_delete'] = 'Delete'; $string['heading_description'] = 'Field Description'; $string['heading_lti'] = 'Setting for LTI Configuration'; +$string['heading_name'] = 'Field Name'; +$string['heading_params'] = 'Parameters (JSON)'; +$string['heading_permanent'] = 'Permanent'; $string['heading_position'] = 'Position'; -$string['heading_required'] = 'Required'; $string['heading_readonly'] = 'Read Only'; -$string['heading_params'] = 'Parameters (JSON)'; +$string['heading_required'] = 'Required'; $string['heading_role'] = 'Role'; -$string['heading_actions'] = 'Actions'; -$string['heading_delete'] = 'Delete'; -$string['heading_permanent'] = 'Permanent'; -$string['haction'] = 'Action'; -$string['hstart_date'] = 'Start Date'; $string['hend_date'] = 'End Date'; -$string['htitle'] = 'Title'; $string['hlocation'] = 'Location'; -$string['hworkflow_state'] = 'Status'; -$string['hpublished'] = 'Published'; -$string['hvisibility'] = 'Visibility'; $string['hprovide'] = 'Provide'; $string['hprovidelti'] = 'Provide (LTI)'; - +$string['hpublished'] = 'Published'; +$string['hscheduledvisibility'] = 'Scheduled Visibility'; +$string['hstart_date'] = 'Start Date'; +$string['htitle'] = 'Title'; +$string['hvisibility'] = 'Visibility'; +$string['hworkflow_state'] = 'Status'; $string['identifier'] = 'Identifier'; -$string['importseries'] = 'Import series'; $string['importfailed'] = 'The series could not be imported.'; +$string['importmapping_modulesfixtaskretry'] = 'An error occured by executing a task for fixing the duplicated event\'s modules: {$a} The task will be processed again later.'; +$string['importmapping_modulesfixtasktermination'] = 'An error occured by executing a task for fixing the duplicated event\'s modules: {$a} After trying serveral time the task will be terminated now.'; +$string['importmapping_no_duplicated_event_id_yet'] = 'The duplicated event is not available yet, therefore duplicated event modules fix task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}) has been postponed.'; +$string['importmapping_restore_still_in_progress'] = 'The restore process is still in progress, therefore duplicated event modules fix task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}) has been postponed.'; $string['importmode'] = 'Import mode'; -$string['importmodedesc'] = 'In order to define an approach to import videos into a course, a mode should be seleted. The default mode is Duplicating Events in which a new series would be created and events will be avaible in the series by using a dupliaction workflow.
ACL Change approach on the other hand will use the same seriesid among courses but series and events\' ACLs are changes to grant access from the course which imports the videos.'; -$string['importvideos_settingmodeduplication'] = 'Duplicating Events'; -$string['importvideos_settingmodeacl'] = 'ACL Change'; +$string['importmodedesc'] = 'In order to define an approach to import videos into a course, a mode should be seleted. The default mode is Duplicating Events in which a new series would be created and events will be avaible in the series by using a dupliaction workflow.
ACL Change approach on the other hand will use the same seriesid among courses but series and events\' ACLs are changes to grant access from the course which imports the videos.
NOTE: At the moment, the selection of events in import wizards (course and manual) for "ACL Change" is NOT possible, due to avoiding further complications in terms of permissions in Opencast.'; +$string['importseries'] = 'Import series'; +$string['importvideos_aclprocessingexplanation'] = 'The seriesid of the selected course will be used in this course and the series\' ACL as well as ACLs of its videos will be changed accordingly.'; $string['importvideos_errornotenabledorworking'] = 'The import videos feature is not enabled or not working'; $string['importvideos_importbuttontitle'] = 'Import videos'; +$string['importvideos_importepisodecleanupfailed'] = 'At least one of the existing Opencast episode modules within this course could not be cleaned up. Please try again or contact your Moodle administrator.'; $string['importvideos_importheading'] = 'Import videos from another course'; -$string['importvideos_importjobcreated'] = 'The import of the selected videos into this course was scheduled. This process will happen in the background. You do not need to wait on this page. As soon as the process is started, the videos will appear in the Videos available in this course section.
Notice:A process of adjusting the visibility for the imported videos will also be executed right after the import process is completed, therefore it is suggested to give more time to the overall processing duration.'; +$string['importvideos_importjobaclchangealleventsfailed'] = 'Import has partially failed, because ACL change for all videos has failed.
However, the series is now mapped to this course and its ACL has been changed.'; $string['importvideos_importjobaclchangedone'] = 'The import of the selected series with its videos into this course was successful. You can now access the videos from the list.'; +$string['importvideos_importjobaclchangeeventsfailed'] = 'Import has partially failed, because ACL change for some of the videos has failed.
However, the series is now mapped to this course and its ACL has been changed.
The ACL of following eventIDs could not the changed:'; $string['importvideos_importjobaclchangeseriesfailed'] = 'Import failed, because the ACL change for selected series has failed.'; $string['importvideos_importjobaclchangeseriesmappingfailed'] = 'Import failed, becasue mapping the series to the course has failed.'; -$string['importvideos_importjobaclchangealleventsfailed'] = 'Import has partially failed, because ACL change for all videos has failed.
However, the series is now mapped to this course and its ACL has been changed.'; -$string['importvideos_importjobaclchangeeventsfailed'] = 'Import has partially failed, because ACL change for some of the videos has failed.
However, the series is now mapped to this course and its ACL has been changed.
The ACL of following eventIDs could not the changed:'; +$string['importvideos_importjobcreated'] = 'The import of the selected videos into this course was scheduled. This process will happen in the background. You do not need to wait on this page. As soon as the process is started, the videos will appear in the Videos available in this course section.
Notice:A process of adjusting the visibility for the imported videos will also be executed right after the import process is completed, therefore it is suggested to give more time to the overall processing duration.'; $string['importvideos_importjobcreationfailed'] = 'At least one of the videos could not be imported to this course. Please try again or contact your Moodle administrator.'; -$string['importvideos_importepisodecleanupfailed'] = 'At least one of the existing Opencast episode modules within this course could not be cleaned up. Please try again or contact your Moodle administrator.'; $string['importvideos_importseriescleanupfailed'] = 'At least one of the existing Opencast series modules within this course could not be cleaned up. Please try again or contact your Moodle administrator.'; $string['importvideos_processingexplanation'] = 'These video files will be duplicated in Opencast and then made available in this course.'; +$string['importvideos_progressbarstep'] = 'Step {$a->current} of {$a->last}'; $string['importvideos_sectionexplanation'] = 'In this section, you can import existing video files from other Moodle courses to this Moodle course.'; -$string['importvideos_aclprocessingexplanation'] = 'The seriesid of the selected course will be used in this course and the series\' ACL as well as ACLs of its videos will be changed accordingly.'; -$string['importvideos_settings'] = 'Import videos features'; -$string['importvideos_settingcoreenabled'] = 'Allow video import within Moodle core course import wizard'; -$string['importvideos_settingcoreenabled_desc'] = 'If enabled, teachers can import existing video files from other Moodle courses to their Moodle course by using the Moodle core course import wizard. Within the wizard, there is an additional option shown to import the videos which have been uploaded within the Opencast block in the other course. Using this feature, the teacher can import all videos from another course as bulk, but he cannot select individual videos.
When Dupliacting Events is selected as the Import mode then the videos are duplicated in Opencast by an ad-hoc task in Moodle and will show up in the course\'s video list with a short delay.
In case of ACL Change as Import mode, the seriesid of the course being imported is used but the ACL of the series and its videos will be changed in order to grant access within the new course.'; $string['importvideos_settingcoredefaultvalue'] = 'Default value for opencast import videos\' checkbox'; $string['importvideos_settingcoredefaultvalue_desc'] = 'Selecting a default value for the checkbox to include opencast videos in Moodle core import wizard which at the end will be used to whether include or not to include videos. This option is meant to help teachers who prefer to use "Jump to final step" button and skip the Moodle core import wizard steps.'; -$string['importvideos_settingcoredefaultvalue_true'] = 'Checked'; $string['importvideos_settingcoredefaultvalue_false'] = 'Unchecked'; +$string['importvideos_settingcoredefaultvalue_true'] = 'Checked'; +$string['importvideos_settingcoreenabled'] = 'Allow video import within Moodle core course import wizard'; +$string['importvideos_settingcoreenabled_desc'] = 'If enabled, teachers can import existing video files from other Moodle courses to their Moodle course by using the Moodle core course import wizard. Within the wizard, there is an additional option shown to import the videos which have been uploaded within the Opencast block in the other course. Using this feature, the teacher can import all videos from another course as bulk, but he cannot select individual videos.
When Dupliacting Events is selected as the Import mode then the videos are duplicated in Opencast by an ad-hoc task in Moodle and will show up in the course\'s video list with a short delay.
In case of ACL Change as Import mode, the seriesid of the course being imported is used but the ACL of the series and its videos will be changed in order to grant access within the new course.
NOTE: With "ACL Change" import mode, the selection of videos in the wizard is not provided.'; $string['importvideos_settingenabled'] = 'Allow video import'; $string['importvideos_settingenabled_desc'] = 'If enabled, teachers can import existing video files from other Moodle courses to their Moodle course. You have to further select an import mode between Duplicating Events or ACL Change approach. In both modes, you need to enable one or both of the two following settings to manually import videos or to import videos within the Moodle core course import wizard. If you don\'t enable any of these, this setting will have no effect.
In Duplicating Events mode, you need to further set a duplication workflow.'; -$string['importvideos_settingheader'] = 'Import videos from other courses'; $string['importvideos_settinghandleepisodeenabled'] = 'Handle Opencast episode modules during manual video import'; $string['importvideos_settinghandleepisodeenabled_desc'] = 'If enabled, teachers can handle Opencast episode modules which were created with the "Add LTI episode module" feature and which relate to the videos which are imported. This especially cleans up modules which have been imported from one course to another course but which still link to videos in the old course. The episode modules are handled by an ad-hoc task in Moodle and will be fixed in the course with a short delay.
Please note that this mechanism relies on the fact that the Opencast duplication workflow sets a workflow instance configuration field \'duplicate_media_package_1_id\' which contains the episode ID of the duplicated episode. If the workflow does not set this configuration field, this feature will always fail.'; $string['importvideos_settinghandleseriesenabled'] = 'Handle Opencast series modules during manual video import'; $string['importvideos_settinghandleseriesenabled_desc'] = 'If enabled, teachers can handle Opencast series modules which were created with the "Add LTI series module" feature and which relate to the videos which are imported. This especially cleans up modules which have been imported from one course to another course but which still link to the course series of the old course. The series module is instantly handled after the import wizard is finished.'; +$string['importvideos_settingheader'] = 'Import videos from other courses'; $string['importvideos_settingmanualenabled'] = 'Allow manual video import'; -$string['importvideos_settingmanualenabled_desc'] = 'If enabled, teachers can import existing video files from other Moodle courses to their Moodle course by using a dedicated Opencast video import wizard. This feature is offered on the Opencast block overview page.
In Duplicating Events import mode, the teacher can import all or a subset of videos from another course as bulk. The videos which are selected within the import wizard are duplicated in Opencast by an ad-hoc task in Moodle and will show up in the course\'s video list with a short delay.
In ACL Change import mode, the seriesid of the the target course will be used in the new course. Additionally, the ACLs of the series itself and all of its videos will be changed in order to grant access to them within the new course.
Unlike in Duplicating Events Mode, there is no manual selection of videos available within the provided wizard.
Please note that there are corresponding capabilities block/opencast:manualimporttarget and block/opencast:manualimportsource for this feature which control who can import which courses to which courses. By default, managers and editing teachers have this capability and can use the feature as soon as it is enabled here.'; -$string['importvideos_progressbarstep'] = 'Step {$a->current} of {$a->last}'; +$string['importvideos_settingmanualenabled_desc'] = 'If enabled, teachers can import existing video files from other Moodle courses to their Moodle course by using a dedicated Opencast video import wizard. This feature is offered on the Opencast block overview page.
In Duplicating Events import mode, the teacher can import all or a subset of videos from another course as bulk. The videos which are selected within the import wizard are duplicated in Opencast by an ad-hoc task in Moodle and will show up in the course\'s video list with a short delay.
In ACL Change import mode, the seriesid of the the target course will be used in the new course. Additionally, the ACLs of the series itself and all of its videos will be changed in order to grant access to them within the new course.
Unlike in Duplicating Events Mode, there is no manual selection of videos available within the provided wizard.
Please note that there are corresponding capabilities block/opencast:manualimporttarget and block/opencast:manualimportsource for this feature which control who can import which courses to which courses. By default, managers and editing teachers have this capability and can use the feature as soon as it is enabled here.
NOTE: With "ACL Change" import mode, the selection of videos in the wizard is not provided.'; +$string['importvideos_settingmodeacl'] = 'ACL Change'; +$string['importvideos_settingmodeduplication'] = 'Duplicating Events'; +$string['importvideos_settings'] = 'Import videos features'; +$string['importvideos_wizard_availableseries'] = 'Available series in {$a}'; +$string['importvideos_wizard_event_cb_title'] = '{$a->title} (ID: {$a->identifier})'; +$string['importvideos_wizard_series_cb_title'] = 'Series: {$a->title} (ID: {$a->identifier})'; +$string['importvideos_wizard_seriesimported'] = 'Series to be imported'; +$string['importvideos_wizard_unselectableeventreason'] = 'video selection'; +$string['importvideos_wizard_unselectableeventreason_help'] = 'The import mode for the opencast instance is set to "ACL Change", which does not provide single video selection, therefore, by selecting this series, all of its videos will be automatically imported.'; +$string['importvideos_wizardstep1coursevideos'] = 'Videos to be imported'; $string['importvideos_wizardstep1heading'] = 'Select source course'; $string['importvideos_wizardstep1intro'] = 'Select the source course from where the videos should be imported from the following list of courses.
You can pick from all courses which you are allowed to import videos from.'; -$string['importvideos_wizardstep1sourcecourse'] = 'Import videos from this course'; $string['importvideos_wizardstep1series'] = 'Default series of this course'; $string['importvideos_wizardstep1seriesnotfound'] = 'The source course has no valid series id, please make sure the course you have selected has a default series.'; -$string['importvideos_wizardstep1coursevideos'] = 'Videos to be imported'; -$string['importvideos_wizard_seriesimported'] = 'Series to be imported'; +$string['importvideos_wizardstep1sourcecourse'] = 'Import videos from this course'; $string['importvideos_wizardstep1sourcecoursenone'] = 'There isn\'t any other course than this course which you are allowed to import videos from.'; +$string['importvideos_wizardstep2aclheading'] = 'Select series'; +$string['importvideos_wizardstep2aclintro'] = 'Select the series which you want to import from the source course.
All videos from this series are imported.'; $string['importvideos_wizardstep2coursevideos'] = 'Import these videos'; $string['importvideos_wizardstep2coursevideosnone'] = 'There isn\'t any video in the selected course.'; $string['importvideos_wizardstep2coursevideosnoneselected'] = 'You have to check at least one video to be imported.'; $string['importvideos_wizardstep2heading'] = 'Select videos'; $string['importvideos_wizardstep2intro'] = 'Select the videos which you want to import from the source course.
You can pick from all videos which have been processed completely in the series of the source course.
Notice: All selected videos will be imported into a single series.'; -$string['importvideos_wizardstep2aclheading'] = 'Select series'; -$string['importvideos_wizardstep2aclintro'] = 'Select the series which you want to import from the source course.
All videos from this series are imported.'; -$string['importvideos_wizard_availableseries'] = 'Available series in {$a}'; $string['importvideos_wizardstep3aclheading'] = 'Summary'; $string['importvideos_wizardstep3aclintro'] = 'Please verify that the summary of the video import matches your expectations before you run the import.'; -$string['importvideos_wizardstep3heading'] = 'Handle Opencast modules in this course'; -$string['importvideos_wizardstep3intro'] = 'There are existing Opencast modules in this course which relate to the videos which you are going to import. These modules will be handled after the video import.
If you are unsure if you need this handling, please accept the given defaults.'; -$string['importvideos_wizardstep3skipintro'] = 'There aren\'t any existing Opencast modules in this course which relate to the videos which you are going to import.
Nothing needs to be handled, please continue to the next step.'; -$string['importvideos_wizardstep3episodemodulesubheading'] = 'Clean up existing Opencast episode module(s)'; $string['importvideos_wizardstep3episodemoduleexplanation'] = 'There is at least one Opencast episode module in this course which points to a video in the course from where you are going to import the videos now. After the import, this will be cleaned up so that it points to imported video within this course.'; $string['importvideos_wizardstep3episodemodulelabel'] = 'Yes, clean up the Opencast episode module(s) related to this import'; -$string['importvideos_wizardstep3seriesmodulesubheading'] = 'Clean up existing Opencast series module(s)'; +$string['importvideos_wizardstep3episodemodulesubheading'] = 'Clean up existing Opencast episode module(s)'; +$string['importvideos_wizardstep3heading'] = 'Handle Opencast modules in this course'; +$string['importvideos_wizardstep3intro'] = 'There are existing Opencast modules in this course which relate to the videos which you are going to import. These modules will be handled after the video import.
If you are unsure if you need this handling, please accept the given defaults.'; $string['importvideos_wizardstep3seriesmoduleexplanation'] = 'There is at least one Opencast series module in this course which points to the course from where you are going to import the videos now. After the import, this will be cleaned up so that only the Opencast series module which shows all (pre-existing and to be imported) videos of this course remains.'; $string['importvideos_wizardstep3seriesmodulelabel'] = 'Yes, clean up the Opencast series modules related to this import'; +$string['importvideos_wizardstep3seriesmodulesubheading'] = 'Clean up existing Opencast series module(s)'; +$string['importvideos_wizardstep3skipintro'] = 'There aren\'t any existing Opencast modules in this course which relate to the videos which you are going to import.
Nothing needs to be handled, please continue to the next step.'; +$string['importvideos_wizardstep4coursevideosnone'] = 'There wasn\'t any video selected for import.'; $string['importvideos_wizardstep4heading'] = 'Summary'; $string['importvideos_wizardstep4intro'] = 'Please verify that the summary of the video import matches your expectations before you run the import.
The videos are imported into the default series.'; -$string['importvideos_wizardstep4coursevideosnone'] = 'There wasn\'t any video selected for import.'; $string['importvideos_wizardstep4sourcecoursenone'] = 'There wasn\'t any source course selected for import.'; $string['importvideos_wizardstepbuttontitlecontinue'] = 'Continue'; $string['importvideos_wizardstepbuttontitlerunimport'] = 'Import videos and return to overview'; +$string['ingest_endpoint_notfound'] = 'The ingets endpoint is not available, this has to be fix by the system administrator.'; +$string['ingeststateaddingacls'] = 'Adding rights and permissions...'; +$string['ingeststateaddingcatalog'] = 'Adding event catalog...'; +$string['ingeststateaddingfirsttrack'] = 'Adding first track...'; +$string['ingeststateaddingsecondtrack'] = 'Adding second track...'; +$string['ingeststatecreatingmedispackage'] = 'Creating mediapackage...'; +$string['ingeststateingesting'] = 'Ingesting...'; $string['ingestupload'] = 'Ingest upload'; $string['ingestuploaddesc'] = 'Use the Opencast ingest service for uploading videos.'; +$string['initialvisibilitystatus'] = 'Initial visibility of the video'; $string['invalidacldata'] = 'Invalid acl data'; - +$string['invalidmetadatafield'] = 'Invalid metadata field found: {$a}'; $string['language'] = 'Language'; +$string['legendalt'] = 'More details about all possible values of this column.'; +$string['legenddeletingdesc'] = 'The video is being deleted, and it will be removed shortly.'; +$string['legendocstatecapturingdesc'] = 'Live capturing in progress.'; +$string['legendocstatefaileddesc'] = 'Something went wrong while processing this video, and it has failed. Please contact the support/administrator in order to resolve this issue.'; +$string['legendocstateneedscuttingdesc'] = 'The Video requires further attention in order to finish the processing stage.'; +$string['legendocstateprocessingdesc'] = 'The video is uploaded, and it is being processed by Opencast.'; +$string['legendocstatesucceededdesc'] = 'The video has been processed and it is ready.'; +$string['legendplanneddesc'] = 'The video has been scheduled for processing.'; +$string['legendtitle'] = 'Details Table'; +$string['legendvisibility_group'] = 'Group Visibility'; +$string['legendvisibility_groupdesc'] = 'The video is visible to all student belonging to selected groups.'; +$string['legendvisibility_hidden'] = 'Hidden'; +$string['legendvisibility_hiddendesc'] = 'The video is not visible to any student.'; +$string['legendvisibility_mixed'] = 'Invalid'; +$string['legendvisibility_mixeddesc'] = 'The visibility of the video is in an invalid status.'; +$string['legendvisibility_visible'] = 'Visible'; +$string['legendvisibility_visibledesc'] = 'The video is visible to all students of the course.'; +$string['license'] = 'License'; $string['limituploadjobs'] = 'Limit upload job by cron'; $string['limituploadjobsdesc'] = 'Limit the count of uploadjobs done by one cronjob. The cronjob can be scheduled here: {$a}'; $string['limitvideos'] = 'Number of videos'; $string['limitvideosdesc'] = 'Maximum number of videos to display in block'; $string['linkedinblock'] = 'Linked in block'; +$string['liveupdate_fail_notification_message'] = 'Unable to perform live status update for the following event(s):
  • {$a}
'; +$string['liveupdate_reloadtimeout'] = 'Page reload timeout (in seconds)'; +$string['liveupdate_reloadtimeout_desc'] = 'The timeout in seconds by which the page will be reloaded, when there is an updated status identified. If empty or less than 0, a default value of 3 seconds will be considered.
NOTE: Before reloading the page a teachers will be notified. The reload is important, so that every required backend process take place.'; +$string['liveupdate_settingenabled'] = 'Enable live status update feature'; +$string['liveupdate_settingenabled_desc'] = 'When enabled, uploading status and workflow processing states will be watched when they are in an ongoing process,
This is done by pulling the status information for those processes in a 1 second interval.'; +$string['liveupdate_settingheader'] = 'Live Status Update'; +$string['liveupdate_toast_notification'] = 'Event: ({$a->title}) is updated. The page will be reloaded in {$a->timeout} seconds.'; $string['loading'] = 'Loading...'; -$string['ltimodule_settings'] = 'LTI module features'; -$string['license'] = 'License'; $string['location'] = 'Location'; - +$string['ltimodule_settings'] = 'LTI module features'; +$string['managedefaultredirectlinkwithexp'] = 'You can add default values for these metadata fields, using: '; +$string['managedefaultsforuser'] = 'Manage default values'; +$string['managedefaultsforuser_desc'] = 'Here you can manage default values for metadata fields used to add videos as well create new series. If you add a default value for a field here, it will be automatically inserted into the field as predefined value (default) inside those mentioned pages.
NOTE: In case this page is empty, or you are looking for a field that does not exist here, please contact your system administrator and ask him/her to configure the metadata fields as defaultable.'; $string['manageseriesforcourse'] = 'Manage series'; +$string['managetranscriptions'] = 'Manage Transcriptions'; +$string['managetranscriptions_header'] = 'Manage Event\'s Transcriptions'; $string['maxseries'] = 'Maximum number of series'; $string['maxseriesdesc'] = 'Specifies how many series can be assigned to a course. Teachers won\'t be able to add/import more series if the maximum number is reached.'; $string['maxseriesreached'] = 'You cannot add another series to this course because the course contains already the maximum number of series.'; $string['maxseriesreachedimport'] = 'Currently, you cannot import another series because the course contains already the maximum number of series.'; +$string['maxtranscriptionupload'] = 'Maximum number of sets to upload'; +$string['maxtranscriptionupload_desc'] = 'Specify how many transcription box should be provided to teachers to upload. In case it is not correctly set, only 1 field set will be provided.'; +$string['mediatype'] = 'Media Source'; $string['messageprovider:error'] = 'Processing error notification'; +$string['messageprovider:opencasteventstatus_notification'] = 'Opencast event status notification'; $string['messageprovider:reportproblem_confirmation'] = 'Copy of reported problems for Opencast videos'; $string['metadata'] = 'Event Metadata'; +$string['metadata_autocomplete_noselectionstring'] = 'No {$a} provided!'; +$string['metadata_autocomplete_placeholder'] = 'Enter {$a}'; $string['metadatadesc'] = 'Here you can define which metadata fields can or have to be set when uploading videos to Opencast. You can drag-and-drop rows to reorder them defining the position of fields in the form.'; $string['metadataexplanation'] = 'When uploading existing video files to Opencast, you can set several metadata fields. These will be stored together with the video.'; $string['metadataseries'] = 'Series Metadata'; $string['metadataseriesdesc'] = 'Here you can define which metadata fields can or have to be set for creating Opencast series. You can drag-and-drop rows to reorder them defining the position of fields in the form.'; $string['metadataseriesupdatefailed'] = 'Updating the series metadata failed.'; -$string['mediatype'] = 'Media Source'; -$string['metadata_autocomplete_placeholder'] = 'Enter {$a}'; -$string['metadata_autocomplete_noselectionstring'] = 'No {$a} provided!'; -$string['messageprovider:opencasteventstatus_notification'] = 'Opencast event status notification'; $string['missingevent'] = 'Creation of event failed'; $string['missinggroup'] = 'Missing group in opencast'; $string['missingseries'] = 'Missing series in opencast'; $string['missingseriesassignment'] = 'Missing series assignment'; +$string['missingtranscriptionuploadparams'] = 'Required parameters to upload transcription are missing.'; +$string['morethanonedefaultserieserror'] = 'This course has more than one default series. Please contact your system administrator.'; $string['morevideos'] = 'More videos...'; -$string['mstatereadytoupload'] = 'Ready for transfer'; +$string['mstatecreatingevent'] = 'Uploading...'; $string['mstatecreatinggroup'] = 'Creating Opencast Group...'; $string['mstatecreatingseries'] = 'Creating Opencast Series...'; -$string['mstatecreatingevent'] = 'Uploading...'; -$string['mstateuploaded'] = 'Processing post-upload tasks...'; +$string['mstatereadytoupload'] = 'Ready for transfer'; $string['mstatetransferred'] = 'Transferred'; $string['mstateunknown'] = 'State unknown'; -$string['ingeststatecreatingmedispackage'] = 'Creating mediapackage...'; -$string['ingeststateaddingcatalog'] = 'Adding event catalog...'; -$string['ingeststateaddingfirsttrack'] = 'Adding first track...'; -$string['ingeststateaddingsecondtrack'] = 'Adding second track...'; -$string['ingeststateaddingacls'] = 'Adding rights and permissions...'; -$string['ingeststateingesting'] = 'Ingesting...'; - -$string['noconnectedseries'] = 'No series is defined yet.'; +$string['mstateuploaded'] = 'Processing post-upload tasks...'; $string['no_ingest_services'] = 'No available ingest nodes found.'; -$string['ingest_endpoint_notfound'] = 'The ingets endpoint is not available, this has to be fix by the system administrator.'; +$string['noconnectedseries'] = 'No series is defined yet.'; $string['noseriesid'] = 'Series ID is not defined yet.'; -$string['nouserselected'] = 'You must select a user.'; $string['nothingtodisplay'] = 'In this section, you see the videos which are uploaded to this course.
Currently, no videos have been uploaded to this course yet.'; -$string['notpublished'] = 'Not published'; -$string['notifications_settings_header'] = 'Notifications'; +$string['notificationcleanupimportedmodules_subj'] = 'Opencast imported modules cleanup task notification'; +$string['notificationcleanupimportedmodulescleanupfailed_body'] = 'Cleanup job with workflow id: ({$a->workflowid}) for course {$a->coursefullname} (ID: {$a->courseid}) failed during the update of the episode activities and is removed.'; +$string['notificationcleanupimportedmodulesexpired_body'] = 'Cleanup job with workflow id: ({$a->workflowid}) for course {$a->coursefullname} (ID: {$a->courseid}) has been removed, as we have waited for 5 days without success to get the duplicated episode ID from OC.'; +$string['notificationcleanupimportedmodulesgeneralexception_body'] = 'Cleanup job with workflow id: ({$a->workflowid}) for course {$a->coursefullname} (ID: {$a->courseid}) failed and is removed. The exception message contains: {$a->exceptionmessage}'; +$string['notificationcleanupimportedmodulesnoeposideid_body'] = 'Cleanup job with workflow id: ({$a->workflowid}) for course {$a->coursefullname} (ID: {$a->courseid}) was removed as the stored OC workflow does not exist or does not and will not hold a duplicated episode ID.'; $string['notificationeventstatus'] = 'Allow event process status notification'; +$string['notificationeventstatus_body'] = 'The process status of the uploaded video: {$a->videotitle} (ID: {$a->videoidentifier}) in the course: {$a->coursefullname} (ID: {$a->courseid}) has been changed to: {$a->statusmessage}'; $string['notificationeventstatus_desc'] = 'This option allows the system to send notification about the status of the uploaded video from Opencast during the process to the users. This option only includes uploader of the video into the user list. To Notify all teachers of the course, the following setting should be enabled.
This feature is done through a scheduled task that is recommended to run every minute.'; -$string['notificationeventstatusteachers'] = 'Notify all course teachers about the event process status'; -$string['notificationeventstatusteachers_desc'] = 'With this option, apart from the uploader of the video, all the teachers of the course where the video is uploaded from get notified about the Opencast processing status.'; +$string['notificationeventstatus_subj'] = 'Opencast Event Status Notification'; $string['notificationeventstatusdeletion'] = 'Cleanup notification jobs after (Days)'; $string['notificationeventstatusdeletion_desc'] = 'This setting sets a deadline in day for the jobs that are not yet completed. After the deadline has reached, the job will be deleted despite its process state.
This features helps to remove the pending notification jobs from the list and it is done through a scheduled task that is recommended to run once a day.
NOTE: (zero) "0" value disables the setting.'; -$string['notificationeventstatus_subj'] = 'Opencast Event Status Notification'; -$string['notificationeventstatus_body'] = 'The process status of the uploaded video: {$a->videotitle} (ID: {$a->videoidentifier}) in the course: {$a->coursefullname} (ID: {$a->courseid}) has been changed to: {$a->statusmessage}'; +$string['notificationeventstatusteachers'] = 'Notify all course teachers about the event process status'; +$string['notificationeventstatusteachers_desc'] = 'With this option, apart from the uploader of the video, all the teachers of the course where the video is uploaded from get notified about the Opencast processing status.'; +$string['notifications_settings_header'] = 'Notifications'; +$string['notificationuploaduqeuestatus_body'] = 'Processing of this video: {$a->videotitle} in the course: {$a->coursefullname} (ID: {$a->courseid}) is queued, but has not yet started. The video is currently waiting behind {$a->waitingnum} other video(s) in the processing queue.'; +$string['notificationuploaduqeuestatus_subj'] = 'Opencast Event Upload Notification'; +$string['notpublished'] = 'Not published'; +$string['notranscription'] = 'This video has no transcription yet.'; +$string['notranscriptionflavor'] = 'Unknown Service type: {$a}'; +$string['nouserselected'] = 'You must select a user.'; $string['novideosavailable'] = 'No videos available'; - +$string['novisibilitychange'] = 'No changes are identified, please make sure everything is correct.'; +$string['novisibilityrecordfound'] = 'Visibility record could not be found.'; +$string['ocstatecapturing'] = 'Capturing'; $string['ocstatefailed'] = 'Failed'; +$string['ocstateneedscutting'] = 'Needs cutting'; $string['ocstateprocessing'] = 'Processing'; $string['ocstatesucceeded'] = 'Succeeded'; -$string['ocstatecapturing'] = 'Capturing'; -$string['ocstateneedscutting'] = 'Needs cutting'; $string['offerchunkuploadalternative'] = 'Offer filepicker as alternative'; $string['offerchunkuploadalternative_desc'] = 'If this option is enabled, a checkbox labeled as \'{$a}\' will be shown below the chunk upload widget. As soon as this checkbox is checked, the chunk upload widget is hidden and the Moodle default file picker is shown, giving access to all Moodle repositories.'; +$string['only_delete_block'] = 'Delete block, but keep series mapping'; +$string['opencast:addactivity'] = 'Add Opencast Video Provider activity to course'; +$string['opencast:addactivityepisode'] = 'Add Opencast Video Provider activity for an episode to course'; $string['opencast:addinstance'] = 'Add a new opencast upload block'; $string['opencast:addlti'] = 'Add Opencast LTI series module to course'; $string['opencast:addltiepisode'] = 'Add Opencast LTI episode module to course'; -$string['opencast:addactivity'] = 'Add Opencast Video Provider activity to course'; -$string['opencast:addactivityepisode'] = 'Add Opencast Video Provider activity for an episode to course'; $string['opencast:addvideo'] = 'Add a new video to opencast upload block'; +$string['opencast:autocompleteteacherroles'] = 'Teacher roles to be extracted and provided in the autocomplete list'; +$string['opencast:canchangeownerforallvideos'] = 'Be able to change the owner for all videos'; $string['opencast:createseriesforcourse'] = 'Create a new series in opencast for a moodle course'; $string['opencast:deleteevent'] = 'Finally delete a video (event) in opencast'; +$string['opencast:directaccessvideolink'] = 'Direct access to video via shared link'; +$string['opencast:downloadvideo'] = 'Download processed videos'; $string['opencast:importseriesintocourse'] = 'Import an existing opencast series to a moodle course'; $string['opencast:manageseriesforcourse'] = 'Manage the opencast series of a moodle course: Access manageseries.php, unlink series from course and select default series.'; -$string['opencast:downloadvideo'] = 'Download processed videos'; -$string['opencast:startworkflow'] = 'Manually start workflows for videos'; $string['opencast:manualimportsource'] = 'Manually import videos from this course'; $string['opencast:manualimporttarget'] = 'Manually import videos from other courses'; $string['opencast:myaddinstance'] = 'Add a new opencast upload block to Dashboard'; +$string['opencast:sharedirectaccessvideolink'] = 'Share direct access link to video'; +$string['opencast:startworkflow'] = 'Manually start workflows for videos'; $string['opencast:unassignevent'] = 'Unassign a video from the course, where the video was uploaded.'; $string['opencast:viewunpublishedvideos'] = 'View all the videos from opencast server, even when they are not published'; $string['opencast:viewusers'] = 'View all users so that the series/event owner can be changed in dashboard.'; -$string['opencast:canchangeownerforallvideos'] = 'Be able to change the owner for all videos'; -$string['opencaststudiointegration'] = 'Opencast studio integration'; +$string['opencasteditorintegration'] = 'Opencast Editor integration'; $string['opencastseries'] = 'Opencast Series'; -$string['owner'] = 'Owner'; +$string['opencaststudiobaseurl'] = 'Opencast Studio Base URL'; +$string['opencaststudiobaseurl_desc'] = 'The base URL to be used to call Opencast studio. The base URL of the opencast instance is used if empty.'; +$string['opencaststudiocustomsettingsfilename'] = 'Custom Studio settings filename'; +$string['opencaststudiocustomsettingsfilename_desc'] = 'This custom settings filename will be appended to the query when redirecting to Studio, afterwards the Studio looks for this filename relative to its directory and read its settings from that file.
NOTE: Requires Opencast 14.2 or later.'; +$string['opencaststudiointegration'] = 'Opencast studio integration'; +$string['opencaststudionewtab'] = 'Redirect to Studio in a new tab'; +$string['opencaststudionewtab_desc'] = 'When enabled, studio opens in a new tab.'; +$string['opencaststudioreturnbtnlabel'] = 'Label for Studio\'s return button'; +$string['opencaststudioreturnbtnlabel_desc'] = 'This label works as a short description where the return link leads to. This label will be appended to the Studio return button text, when empty, moodle site name will be passed as label.'; +$string['opencaststudioreturnurl'] = 'Custom Studio return endpoint URL'; +$string['opencaststudioreturnurl_desc'] = 'When empty the return url redirects back to the same Moodle opencast block overview where the request comes from. A custom endpoint URL will then be passed to Studio as return url when configured, in this case, admin is able to use 2 placeholders including [OCINSTANCEID] and [COURSEID]. Please NOTE: the URL must be relative to wwwroot.'; +$string['overview'] = 'Overview'; $string['ownedvideosoverview'] = 'Your videos'; $string['ownedvideosoverview_explanation'] = 'Here you can see all videos that belong to you but to whose series you do not have access.'; -$string['overview'] = 'Overview'; - +$string['owner'] = 'Owner'; $string['planned'] = 'Planned'; -$string['legendplanneddesc'] = 'The video has been scheduled for processing.'; -$string['legenddeletingdesc'] = 'The video is being deleted, and it will be removed shortly.'; $string['pluginname'] = 'Opencast Videos'; -$string['publisher'] = 'Publisher'; -$string['presenterfile'] = 'Presenter file'; +$string['presentation'] = 'Presentation video'; +$string['presentationdesc'] = 'Use the presentation video if you have a video file of a slide presentation recording or a screencast.'; $string['presentationfile'] = 'Presentation file'; $string['presenter'] = 'Presenter video'; $string['presenterdesc'] = 'Use the presenter video if you have a video file of a person speaking to an audience or a motion picture.'; -$string['presentation'] = 'Presentation video'; -$string['presentationdesc'] = 'Use the presentation video if you have a video file of a slide presentation recording or a screencast.'; +$string['presenterfile'] = 'Presenter file'; $string['privacy:metadata:block_opencast_uploadjob'] = 'Information about video uploads.'; +$string['privacy:metadata:block_opencast_uploadjob:courseid'] = 'ID of the course where the video is uploaded'; $string['privacy:metadata:block_opencast_uploadjob:fileid'] = 'ID of the file/video which is uploaded'; $string['privacy:metadata:block_opencast_uploadjob:opencasteventid'] = 'ID of the opencast event that was created during upload'; -$string['privacy:metadata:block_opencast_uploadjob:userid'] = 'ID of the user who uploaded the video'; $string['privacy:metadata:block_opencast_uploadjob:status'] = 'Status of upload process'; -$string['privacy:metadata:block_opencast_uploadjob:courseid'] = 'ID of the course where the video is uploaded'; $string['privacy:metadata:block_opencast_uploadjob:timecreated'] = 'The date the upload job was created.'; $string['privacy:metadata:block_opencast_uploadjob:timemodified'] = 'The date the upload job was last modified.'; +$string['privacy:metadata:block_opencast_uploadjob:userid'] = 'ID of the user who uploaded the video'; $string['privacy:metadata:core_files'] = 'The opencast block stores files (videos) which have been uploaded by the user.'; $string['privacy:metadata:opencast'] = 'The block interacts with an opencast instance and thus data needs to be exchanged.'; $string['privacy:metadata:opencast:file'] = 'The file which is selected is uploaded to opencast.'; -$string['processepisodecleanup'] = 'Process Opencast Video Provider/LTI episode cleanup after course imports'; -$string['processupload'] = 'Process upload'; +$string['processattachment'] = 'Process attachment upload jobs'; $string['processdelete'] = 'Process delete jobs for Opencast'; -$string['processnotification'] = 'Process event status notification jobs after upload'; $string['processdeletenotification'] = 'Process delete notification jobs'; +$string['processepisodecleanup'] = 'Process Opencast Video Provider/LTI episode cleanup after course imports'; +$string['processltimodulecleanup'] = 'Process Opencast Video LTI episode routine cleanup'; +$string['processltimodulecleanup_error'] = 'Something went wrong during LTI module cleanup process: {$a}'; +$string['processnotification'] = 'Process event status notification jobs after upload'; +$string['processupload'] = 'Process upload'; +$string['processvisibility'] = 'Process scheduled visibility change jobs'; +$string['publisher'] = 'Publisher'; $string['publishtoengage'] = 'Publish to Engage'; $string['publishtoengagedesc'] = 'Select this option to publish the video after upload to engage player. Setup workflow must support this.'; - -$string['reuseexistingupload'] = 'Reuse existing uploads'; -$string['reuseexistinguploaddesc'] = 'If activated, multiple videos with the same content hash are uploaded to opencast only once. -This saves storage and processing power, but it might cause problems, when you use specific access policies based on opencast series.'; -$string['rolename'] = 'Role name'; -$string['reportproblem_modal_title'] = 'Report a problem'; +$string['readonly_disabled_tooltip_text'] = 'Unable to set readonly option while it is set to be required.'; +$string['recordvideo'] = 'Record video'; +$string['reportproblem_email'] = 'This is an automatic notification of the Moodle Opencast plugin.
Somebody reported a problem with a video.

User: {$a->username}
User email: {$a->useremail}
Moodle course: {$a->course}
Opencast series: {$a->series} (Id: {$a->seriesid})
Opencast event id: {$a->event} (Id: {$a->eventid})
Message:

{$a->message}
'; +$string['reportproblem_failure'] = 'The email could not be sent. Please contact the support team manually.'; $string['reportproblem_modal_body'] = 'If you there is a problem with a video, you can report it to the support team.'; $string['reportproblem_modal_placeholder'] = 'Please explain the problem.'; -$string['reportproblem_modal_submit'] = 'Report problem'; $string['reportproblem_modal_required'] = 'Please enter a message.'; -$string['reportproblem_success'] = 'The email was successfully sent to the support team.'; -$string['reportproblem_failure'] = 'The email could not be sent. Please contact the support team manually.'; +$string['reportproblem_modal_submit'] = 'Report problem'; +$string['reportproblem_modal_title'] = 'Report a problem'; $string['reportproblem_notification'] = '#### This is a copy of the email sent to the support team. ####
'; -$string['reportproblem_email'] = 'This is an automatic notification of the Moodle Opencast plugin.
Somebody reported a problem with a video.

User: {$a->username}
User email: {$a->useremail}
Moodle course: {$a->course}
Opencast series: {$a->series} (Id: {$a->seriesid})
Opencast event id: {$a->event} (Id: {$a->eventid})
Message:

{$a->message}
'; $string['reportproblem_subject'] = 'Moodle Opencast plugin: Problem reported'; +$string['reportproblem_success'] = 'The email was successfully sent to the support team.'; $string['restoreopencastvideos'] = 'Restore videos from Opencast instance {$a}'; -$string['recordvideo'] = 'Record video'; +$string['reuseexistingupload'] = 'Reuse existing uploads'; +$string['reuseexistinguploaddesc'] = 'If activated, multiple videos with the same content hash are uploaded to opencast only once. This saves storage and processing power, but it might cause problems, when you use specific access policies based on opencast series.'; $string['rightsHolder'] = 'Rights'; $string['role_not_defined'] = 'The role is not defined in the ACL roles table.'; -$string['role_not_user_related'] = 'The role does not contain a user placeholder and can thus not be used to identify users.'; $string['role_not_permanent'] = 'The role is not defined as permanent in the ACL roles table.'; - +$string['role_not_user_related'] = 'The role does not contain a user placeholder and can thus not be used to identify users.'; +$string['rolename'] = 'Role name'; +$string['savedefaults'] = 'Save Defaults'; +$string['scheduledvisibilitychangecreated'] = 'A new visibility change is scheduled'; +$string['scheduledvisibilitychangedeleted'] = 'The scheduled visibility change has been deleted'; +$string['scheduledvisibilitychangefailed'] = 'Scheduling a visibility change was not successful. You can schedule a new one or disable it to remove its task.'; +$string['scheduledvisibilitychangeskipped'] = '
NOTE: The task to schedule visibility change is skipped and would not take place.'; +$string['scheduledvisibilitychangeupdated'] = 'The scheduled visibility change is updated.'; +$string['scheduledvisibilitycreatefailed'] = 'Unable to schedule a visibility change.'; +$string['scheduledvisibilitydeletefailed'] = 'Unable to delete the scheduled visibility change.'; +$string['scheduledvisibilityicontitle'] = 'Click here to alter the scheduled visibility change for this event'; +$string['scheduledvisibilitystatus'] = 'Change video visibility to'; +$string['scheduledvisibilitystatuserror'] = 'The scheduled visibiliy and inital visibility must be different.'; +$string['scheduledvisibilitytime'] = 'Change video visibility on'; +$string['scheduledvisibilitytimeerror'] = 'The scheduled date to change visibility must be set at least {$a} minutes after the current data and time.'; +$string['scheduledvisibilitytimehi'] = 'Scheduling date'; +$string['scheduledvisibilitytimehi_help'] = 'This date must be set in the near future and as recommended at least {$a} minutes after the current date time, however the faster your opencast server processes the video the nearer this date could be set.'; +$string['scheduledvisibilityupdatefailed'] = 'Unable to update scheduled visibility change.'; $string['series'] = 'Series'; $string['series_already_exists'] = 'This course is already assigned to a series.'; +$string['series_does_not_exist'] = 'The series assigned to this course is not valid. Please contact your Administrator!'; +$string['series_does_not_exist_admin'] = 'The series with the identifier \'{$a}\' could not be retrieved from Opencast.'; +$string['series_name_empty'] = 'Series name must not be empty.'; +$string['series_not_found'] = 'The series {$a} could not be found in the opencast system.'; +$string['series_used'] = 'Used in {$a} courses'; $string['seriescreated'] = 'Series was created.'; -$string['seriesnotcreated'] = 'Series could not be created.'; +$string['seriesidnotvalid'] = 'The series {$a} does not exist.'; $string['seriesidsaved'] = 'The series ID was saved.'; $string['seriesidunset'] = 'The series ID was removed.'; -$string['seriesidnotvalid'] = 'The series {$a} does not exist.'; -$string['series_does_not_exist_admin'] = 'The series with the identifier \'{$a}\' could not be retrieved from Opencast.'; -$string['series_does_not_exist'] = 'The series assigned to this course is not valid. Please contact your Administrator!'; $string['serieslinkedinblock'] = 'Series linked in block'; $string['seriesname'] = 'Series name'; $string['seriesnamedesc'] = 'Series to which the video is added. You can use placeholders which are automatically replaced (list of placeholders).'; -$string['series_name_empty'] = 'Series name must not be empty.'; -$string['series_used'] = 'Used in {$a} courses'; +$string['seriesnotcreated'] = 'Series could not be created.'; $string['seriesonedefault'] = 'There must be exactly one default series.'; $string['seriesoverview'] = 'Series overview'; -$string['seriesoverviewof'] = 'Series overview of {$a} instance'; $string['seriesoverviewexplanation'] = 'Here you can see all series that are used in any course where you have the permission to manage videos.
Series might be manageable by the block in the course and/or might be provided as activity to the students.'; -$string['setdefaultseries_heading'] = 'Set default series'; +$string['seriesoverviewof'] = 'Series overview of {$a} instance'; $string['setdefaultseries'] = 'Do you really want to use this series as new default series?'; +$string['setdefaultseries_heading'] = 'Set default series'; $string['setdefaultseriesfailed'] = 'Changing the default series failed. Please try again later or contact an administrator.'; -$string['settings'] = 'Opencast Videos'; $string['setting_permanent'] = 'Is permanent'; +$string['settings'] = 'Opencast Videos'; +$string['shared_settings'] = 'Shared settings'; $string['showvideos'] = 'Show videos'; $string['source'] = 'Source'; +$string['space_catalogname'] = 'This field must not contain space'; $string['startDate'] = 'Date'; $string['startTime'] = 'Time'; -$string['subjects'] = 'Subjects'; -$string['space_catalogname'] = 'This field must not contain space'; $string['startworkflow'] = 'Start workflow'; $string['startworkflow_modal_body'] = 'Choose the workflow you want to start.'; +$string['startworkflow_modal_configpanel_title'] = 'Workflow Configuration Panel'; +$string['startworkflow_modal_description_title'] = 'Workflow Description'; +$string['subjects'] = 'Subjects'; $string['submit'] = 'Save changes'; -$string['shared_settings'] = 'Shared settings'; $string['support_setting'] = 'Support email'; -$string['support_settingdesc'] = 'Email address to which reports are sent if users report problems with videos.'; $string['support_setting_notset'] = 'Support email is not set. Please contact the administrator and resubmit the report.'; - +$string['support_settingdesc'] = 'Email address to which reports are sent if users report problems with videos.'; +$string['swprivacynotice_settingheader'] = 'Workflows Privacy Notice'; +$string['swprivacynotice_settinginfotext'] = 'Workflow Privacy Notice Info Text'; +$string['swprivacynotice_settinginfotext_desc'] = 'This input is used to provide information about privacy notice for workflows in start workflow dialog.
NOTE: If empty, no notice will be displayed.'; +$string['swprivacynotice_settingtitle'] = 'Workflow Privacy Notice Title'; +$string['swprivacynotice_settingtitle_desc'] = 'A title to be displayed in start workflow dialog. It is intended to be configurable in order to be adjusted by the users. When empty, default string is used.'; +$string['swprivacynotice_settingwfds'] = 'Workflows Definition List'; +$string['swprivacynotice_settingwfds_desc'] = 'A comma separated list of workflow definitions, by which the privacy notice is displayed. When empty, the privacy notice will be displayed for all workflows.'; +$string['swprivacynoticedefaulttitle'] = 'Privacy Notice'; $string['termsofuse'] = 'Terms of use'; $string['termsofuse_accept'] = 'I have read and agree to the {$a}.'; $string['termsofuse_accept_toggle'] = 'terms of use'; -$string['termsofuse_desc'] = 'If you enter some text, a checkbox with the terms of use will appear on the "Video upload" page. -The users must accept the entered terms of use before they can upload the video.'; +$string['termsofuse_desc'] = 'If you enter some text, a checkbox with the terms of use will appear on the "Video upload" page. The users must accept the entered terms of use before they can upload the video.'; $string['title'] = 'Title'; $string['tool_requirement_not_fulfilled'] = 'The required version of tool_opencast is not installed.'; +$string['transcription_flavor_confirm_delete'] = 'Are you sure you want to delete this flavor option pair?'; +$string['transcription_flavor_delete'] = 'Delete flavor\'s option pair'; +$string['transcription_flavor_key'] = 'Flavor key'; +$string['transcription_flavor_value'] = 'Flavor value'; +$string['transcriptionaction_thead'] = 'Actions'; +$string['transcriptionaddnewbtn'] = 'Add more transcription set'; +$string['transcriptiondeletebtn'] = 'Delete transcription set'; +$string['transcriptiondeletionfailed'] = 'Failed to delete transcription'; +$string['transcriptiondeletionsucceeded'] = 'Transcription deleted successfully.'; +$string['transcriptionfileextensions'] = 'Allowed transcription file extensions'; +$string['transcriptionfileextensions_desc'] = 'Comma separated list of allowed transcription file extensions (extensions must exist in Moodle\'s File types list). If left blank all extensions with type \'HTML track files\' are allowed (again see File types).'; +$string['transcriptionfilefield'] = 'Transcription file'; +$string['transcriptionflavor_thead'] = 'Service Type'; +$string['transcriptionflavorfield'] = 'Transcription service type'; +$string['transcriptionflavors'] = 'Transcription Service Types (Flavors)'; +$string['transcriptionflavors_desc'] = 'These service type (flavors) will be presented as a select (dropdown) options to select from when uploading transcriptions. It is a key-value pair of information by which the keys are consumed by opencast and values are human readable information that describe the type of transcription service.
(Multi-Language filters) In order for each value of Drop Down (select) to get translated using filters such as Multi-Language Content (v2), each value should contain the placeholder, defined by that filter i.e. "{mlang en}Amberscript German{mlang}{mlang de}Amberscript Deutsch{mlang}"'; +$string['transcriptionheader'] = 'Upload Transcription Files'; +$string['transcriptionheaderexplanation'] = 'In this section you are able to upload a transcription file for each service type, with specified file extension, which then will be uploaded alongside the video and be processed accordingly to provide the (speech to text) capability.'; +$string['transcriptionltidownloadcompleted'] = 'The transcription is successfully downloaded. {$a}'; +$string['transcriptionreturntomanagement'] = 'Go back to transcription management page'; +$string['transcriptionsettingsheader'] = 'Settings for Transcription'; +$string['transcriptionuploadfailed'] = 'Transcription upload failed!'; +$string['transcriptionuploadsuccessed'] = 'Transcription is uploaded.'; +$string['transcriptionworkflow'] = 'Workflow for transcription (speech to text)'; +$string['transcriptionworkflow_desc'] = 'This workflow is triggered when transcription files are attached to the video. If not set, uploading and managing transcriptions is not provided.
By setting this workflow, a new section to upload transcription files in the add video page as well as a new action menu item in overview page is provided, to upload/handle the new/current transcriptions files.'; $string['type'] = 'Media Type'; - +$string['unabletoaddnewtranscription'] = 'Unable to add new transcription'; +$string['unabletodeletetranscription'] = 'Unable to delete transcription'; +$string['unabletodownloadtranscription'] = 'Unable to download transcription'; +$string['unabletomanagetranscriptions'] = 'Due to an active processing state or an ongoing workflow, managing the event\'s transcriptions is not possible at the moment.'; $string['unexpected_api_response'] = 'Unexpected API response.'; +$string['updatemetadata'] = 'Update metadata for this event'; +$string['updatemetadata_short'] = 'Update metadata'; +$string['updatemetadatafailed'] = 'The metadata could not be saved.'; +$string['updatemetadatasaved'] = 'Metadata is saved.'; +$string['upload'] = 'File Upload'; +$string['uploadexplanation'] = 'You have the option to upload a presenter video file and / or a presentation video file.
Most likely you will only upload one file, but Opencast is also capable of dealing with two videos at once which will be combined in a media package.'; $string['uploadfileextensions'] = 'Allowed file extensions'; $string['uploadfileextensionsdesc'] = 'Comma separated list of allowed video file extensions (extensions must exist in Moodle\'s File types list). If left blank all extensions with type group \'video\' are allowed (again see File types).'; +$string['uploadfilelimit'] = 'Video size limit'; +$string['uploadfilelimitdesc'] = 'Limit the file size of uploaded videos through the chunkupload.'; $string['uploadingeventfailed'] = 'Creating of event failed'; $string['uploadjobssaved'] = 'Video upload successful.
The video is scheduled to be transferred to Opencast now. You do not need to wait on this page for this transfer to finish.'; -$string['uploadtimeout'] = 'Moodle to Opencast upload timeout'; -$string['uploadtimeoutdesc'] = 'Configure the time in seconds a single video upload may take during the background uploading task.'; +$string['uploadprocessingexplanation'] = 'These video files will be processed in Opencast and then made available in this course.'; $string['uploadqueuetoopencast'] = 'Videos scheduled to be transferred to Opencast'; $string['uploadqueuetoopencastexplanation'] = 'In this section, you see the videos which have been uploaded to this Moodle course by you or some other user. These videos are scheduled to be transferred to Opencast now.
The transfer is happening automatically on the Moodle server in the background. You do not need to wait on this page for this transfer to finish.'; $string['uploadrecordvideos'] = 'Upload or record videos'; $string['uploadrecordvideosexplanation'] = 'In this section, you can upload existing video files to Moodle. Additionally, you can record video files directly with Opencast Studio.'; +$string['uploadsettings'] = 'Settings for the chunkuploader'; +$string['uploadtimeout'] = 'Moodle to Opencast upload timeout'; +$string['uploadtimeoutdesc'] = 'Configure the time in seconds a single video upload may take during the background uploading task.'; +$string['uploadtranscritpion'] = 'Upload transcription set'; $string['uploadvideos'] = 'Upload videos'; $string['uploadvideosexplanation'] = 'In this section, you can upload existing video files to Moodle.'; -$string['uploadprocessingexplanation'] = 'These video files will be processed in Opencast and then made available in this course.'; $string['uploadworkflow'] = 'Workflow to start after upload'; -$string['uploadworkflowdesc'] = 'Setup the unique shortname of the workflow, that should be started after succesfully uploading a video file to opencast. - If left blank the standard workflow (ng-schedule-and-upload) will be used. Ask for additional workflows that may have been created by the opencast administrator.'; -$string['uploadsettings'] = 'Settings for the chunkuploader'; -$string['uploadfilelimit'] = 'Video size limit'; -$string['uploadfilelimitdesc'] = 'Limit the file size of uploaded videos through the chunkupload.'; -$string['updatemetadatasaved'] = 'Metadata is saved.'; -$string['updatemetadatafailed'] = 'The metadata could not be saved.'; -$string['updatemetadata'] = 'Update metadata for this event'; -$string['updatemetadata_short'] = 'Update metadata'; -$string['upload'] = 'File Upload'; -$string['uploadexplanation'] = 'You have the option to upload a presenter video file and / or a presentation video file.
Most likely you will only upload one file, but Opencast is also capable of dealing with two videos at once which will be combined in a media package.'; +$string['uploadworkflowdesc'] = 'Setup the unique shortname of the workflow, that should be started after succesfully uploading a video file to opencast. If left blank the standard workflow (ng-schedule-and-upload) will be used. Ask for additional workflows that may have been created by the opencast administrator.'; $string['usedefaultfilepicker'] = 'Use Moodle default file picker to access all repositories'; $string['userisntowner'] = 'Only the owner of the video can change the ownership.'; - $string['video'] = 'Video'; -$string['videosavailable'] = 'Videos available in this course'; +$string['video_already_uploaded'] = 'Video already uploaded'; +$string['video_not_accessible'] = 'This video was not published in the direct access channel.'; +$string['video_not_downloadable'] = 'This video was not published in the download channel.'; $string['video_notallowed'] = 'The video is not part of the course series.'; -$string['viewviedeosnotallowed'] = 'You are not allowed to view the videos in this series.'; -$string['videonotfound'] = 'Video not found'; -$string['videodraftnotfound'] = 'The video to be deleted before the transfer to Opencast was not found.'; -$string['videodraftnotdeletable'] = 'The video cannot be deleted anymore before the transfer to Opencast as the processing status is already "{$a}"'; -$string['videodraftdeletionsucceeded'] = 'The video is deleted successfully'; $string['video_retrieval_failed'] = 'Video could not be retrieved. Please check the connection to the Opencast server.'; -$string['video_not_downloadable'] = 'This video was not published in the download channel.'; -$string['video_not_accessible'] = 'This video was not published in the direct access channel.'; -$string['videostoupload'] = 'Videos to upload to opencast'; +$string['videodraftdeletionsucceeded'] = 'The video is deleted successfully'; +$string['videodraftnotdeletable'] = 'The video cannot be deleted anymore before the transfer to Opencast as the processing status is already "{$a}"'; +$string['videodraftnotfound'] = 'The video to be deleted before the transfer to Opencast was not found.'; +$string['videoeditor_short'] = 'Video Editor'; +$string['videoeditorinvalidconfig'] = 'Currently, it is not possible to use Opencast Editor in order to edit the event.'; +$string['videonotfound'] = 'Video not found'; +$string['videosavailable'] = 'Videos available in this course'; $string['videosoverviewexplanation'] = 'Here you can see in which courses the videos are provided as activity to the students.
The second column shows the activities of the courses where the series is managed by the Opencast block. The third column shows courses where the video is embedded without the series being managed by the block.'; +$string['videostoupload'] = 'Videos to upload to opencast'; +$string['viewviedeosnotallowed'] = 'You are not allowed to view the videos in this series.'; $string['visibility'] = 'Visibility of the video'; +$string['visibility_group'] = 'Allow all students belonging to selected groups to access the video'; $string['visibility_hide'] = 'Prevent any student from accessing the video'; $string['visibility_show'] = 'Allow all students of the course to access the video'; -$string['visibility_group'] = 'Allow all students belonging to selected groups to access the video'; - +$string['visibilityheader'] = 'Event Visibility'; +$string['visibilityheaderexplanation'] = 'You are able to set the initial visibility status of the video before upload, as well as scheduling a visibility change when it is configured to do so.'; +$string['workflow_invalid'] = 'This workflow does not exist or is not enabled.'; +$string['workflow_not_existing'] = 'This workflow does not exist in Opencast.'; +$string['workflow_opencast_invalid'] = 'This workflow does not exist in Opencast or is restricted. Please contact the administrator.'; $string['workflow_settings_opencast'] = 'Workflow Settings'; +$string['workflow_started_failure'] = 'Starting workflow failed.'; +$string['workflow_started_success'] = 'Workflow successfully started.'; $string['workflownotdefined'] = 'The workflow for updating metadata is not defined.'; -$string['worklowisrunning'] = 'A workflow is running. You cannot change the visibility at the moment.'; -$string['workflowrolesname'] = 'Workflow for updating metadata'; $string['workflowrolesdesc'] = 'This workflow is triggered when updating event metadata or deleting/adding nonpermanent ACL rules. If not set, it will not be possible to change the visibility of uploaded videos through the block.'; -$string['workflow_started_success'] = 'Workflow successfully started.'; -$string['workflow_started_failure'] = 'Starting workflow failed.'; -$string['workflow_invalid'] = 'This workflow does not exist or is not enabled.'; -$string['workflow_opencast_invalid'] = 'This workflow does not exist in Opencast or is restricted. Please contact the administrator.'; +$string['workflowrolesname'] = 'Workflow for updating metadata'; $string['workflowtags_setting'] = 'Workflow tags'; $string['workflowtags_settingdesc'] = 'Comma separated list of tags for Opencast workflows that can be configured by the admin and manually started by teachers.'; -$string['workflow_not_existing'] = 'This workflow does not exist in Opencast.'; -$string['wrongmimetypedetected'] = 'An invalid mimetype was used while uploading the video {$a->filename} from course {$a->coursename}. - Only video files are allowed!'; - -// Opencast Editor Integration strings. -$string['videoeditor_short'] = 'Video Editor'; -$string['videoeditorinvalidconfig'] = 'Currently, it is not possible to use Opencast Editor in order to edit the event.'; -$string['opencasteditorintegration'] = 'Opencast Editor integration'; -$string['enableopencasteditorlink'] = 'Show the link to opencast Editor in action menu'; -$string['enableopencasteditorlink_desc'] = 'This option renders a button to opencast editor in the block content and the block overview. - The following settings as well lti credentials have to be configured as well.'; -$string['editorbaseurl'] = 'Opencast Editor Base URL'; -$string['editorbaseurl_desc'] = 'The base URL to be used to call the Opencast Editor, the base url of the opencast instance is used if empty.'; -$string['editorendpointurl'] = 'Opencast Editor Endpoint'; -$string['editorendpointurl_desc'] = 'The editor endpoint to access the editor. The mediapackage ID will be added at the end of the url.'; - -// Strings fot new opencast studio settings. -$string['opencaststudionewtab'] = 'Redirect to Studio in a new tab'; -$string['opencaststudionewtab_desc'] = 'When enabled, studio opens in a new tab.'; -$string['enableopencaststudioreturnbtn'] = 'Show a redirect back button in Studio'; -$string['enableopencaststudioreturnbtn_desc'] = 'When enabled, Studio then renders an additional button "Exit and go back" after up- or downloading the recording.'; -$string['opencaststudioreturnurl'] = 'Custom Studio return endpoint URL'; -$string['opencaststudioreturnurl_desc'] = 'When empty the return url redirects back to the same Moodle opencast block overview where the request comes from. A custom endpoint URL will then be passed to Studio as return url when configured, in this case, admin is able to use 2 placeholders including [OCINSTANCEID] and [COURSEID]. Please NOTE: the URL must be relative to wwwroot.'; -$string['opencaststudioreturnbtnlabel'] = 'Label for Studio\'s return button'; -$string['opencaststudioreturnbtnlabel_desc'] = 'This label works as a short description where the return link leads to. This label will be appended to the Studio return button text, when empty, moodle site name will be passed as label.'; -$string['opencaststudiocustomsettingsfilename'] = 'Custom Studio settings filename'; -$string['opencaststudiocustomsettingsfilename_desc'] = 'This custom settings filename will be appended to the query when redirecting to Studio, afterwards the Studio looks for this filename relative to its directory and read its settings from that file.
NOTE: Requires Opencast 14.2 or later.'; - -// Strings for new visibility feature during initail upload. -$string['visibilityheader'] = 'Event Visibility'; -$string['visibilityheaderexplanation'] = 'You are able to set the initial visibility status of the video before upload, as well as scheduling a visibility change when it is configured to do so.'; -$string['scheduledvisibilitytime'] = 'Change video visibility on'; -$string['scheduledvisibilitytimehi'] = 'Scheduling date'; -$string['scheduledvisibilitytimehi_help'] = 'This date must be set in the near future and as recommended at least {$a} minutes after the current date time, however the faster your opencast server processes the video the nearer this date could be set.'; -$string['scheduledvisibilitytime'] = 'Change video visibility on'; -$string['scheduledvisibilitytimeerror'] = 'The scheduled date to change visibility must be set at least {$a} minutes after the current data and time.'; -$string['scheduledvisibilitystatuserror'] = 'The scheduled visibiliy and inital visibility must be different.'; -$string['initialvisibilitystatus'] = 'Initial visibility of the video'; -$string['scheduledvisibilitystatus'] = 'Change video visibility to'; -$string['scheduledvisibilitychangefailed'] = 'Scheduling a visibility change was not successful. You can schedule a new one or disable it to remove its task.'; -$string['enableschedulingchangevisibility'] = 'Schedule a visibility change'; -$string['enableschedulingchangevisibilitydesc'] = 'Set a date and a visibility status for the event in future, which will be performed using a scheduled task.'; -$string['processvisibility'] = 'Process scheduled visibility change jobs'; -$string['hscheduledvisibility'] = 'Scheduled Visibility'; -$string['scheduledvisibilityicontitle'] = 'Click here to alter the scheduled visibility change for this event'; -$string['novisibilityrecordfound'] = 'Visibility record could not be found.'; -$string['changescheduledvisibility'] = 'Change scheduled visibility for {$a}'; -$string['changescheduledvisibilityheader'] = 'Scheduled visibility change'; -$string['changescheduledvisibilitysuccess'] = 'Scheduled visibility successfully changed'; -$string['changescheduledvisibilityfailed'] = 'Unabale to change scheduled visibility'; -$string['scheduledvisibilitychangeskipped'] = '
NOTE: The task to schedule visibility change is skipped and would not take place.'; -$string['scheduledvisibilitychangeupdated'] = 'The scheduled visibility change is updated.'; -$string['scheduledvisibilityupdatefailed'] = 'Unable to update scheduled visibility change.'; -$string['scheduledvisibilitychangecreated'] = 'A new visibility change is scheduled'; -$string['scheduledvisibilitycreatefailed'] = 'Unable to schedule a visibility change.'; -$string['scheduledvisibilitychangedeleted'] = 'The scheduled visibility change has been deleted'; -$string['scheduledvisibilitydeletefailed'] = 'Unable to delete the scheduled visibility change.'; -$string['emptyvisibilitygroups'] = 'At least one group must be selected.'; -$string['novisibilitychange'] = 'No changes are identified, please make sure everything is correct.'; - -// Strings for DCMI metadata field. -$string['dcmitermsnotice'] = '
IMPORTANT: Opencast supports standardized Dublin Core metadata set, therefore all metadata fields should follow DCMI terms, - otherwise attempting to add unknown metadata field will result in error.
- You can check the list of all available terms to use in DCMI Metadata Terms.'; -$string['invalidmetadatafield'] = 'Invalid metadata field found: {$a}'; -// Strings for default metadata value. -$string['managedefaultsforuser'] = 'Manage default values'; -$string['managedefaultsforuser_desc'] = 'Here you can manage default values for metadata fields used to add videos as well create new series. - If you add a default value for a field here, it will be automatically inserted into the field as predefined value (default) inside those mentioned pages.
- NOTE: In case this page is empty, or you are looking for a field that does not exist here, please contact your system administrator and ask him/her to configure the metadata fields as defaultable.'; -$string['managedefaultredirectlinkwithexp'] = 'You can add default values for these metadata fields, using: '; -$string['savedefaults'] = 'Save Defaults'; -$string['defaultssaved'] = 'Default values are saved.'; -$string['heading_defaultable'] = 'Defaultable'; -$string['descriptionmddefaultable'] = 'Defaultable'; -$string['descriptionmddefaultable_help'] = 'When enabled, users can add default value for this field.'; -$string['morethanonedefaultserieserror'] = 'This course has more than one default series. Please contact your system administrator.'; - -// String for attachments. -$string['transcriptionsettingsheader'] = 'Settings for Transcription'; -$string['transcriptionworkflow'] = 'Workflow for transcription (speech to text)'; -$string['transcriptionworkflow_desc'] = 'This workflow is triggered when transcription files are attached to the video. If not set, uploading and managing transcriptions is not provided.
By setting this workflow, a new section to upload transcription files in the add video page as well as a new action menu item in overview page is provided, to upload/handle the new/current transcriptions files.'; -$string['deletetranscriptionworkflow'] = 'Workflow for delete transcription'; -$string['allowdownloadtranscriptionsetting'] = 'Allow download transcriptions'; -$string['allowdownloadtranscriptionsetting_desc'] = 'When enabled, the transcription download button will be displayed in the manage transcriptions page, by which teachers are able to download the transcription\'s file.
- Notice: In case you are using Opencast 13 or later, you need to make sure that all prerequisites including LTI features and permissions to access /assets/ endpoint for LTI users, are set correctly as it is mandatory to perform LTI call.'; -$string['transcription_flavor_key'] = 'Flavor key'; -$string['transcription_flavor_value'] = 'Flavor value'; -$string['transcription_flavor_delete'] = 'Delete flavor\'s option pair'; -$string['transcription_flavor_confirm_delete'] = 'Are you sure you want to delete this flavor option pair?'; -$string['addtranscriptionflavor'] = 'Add new flavor option'; -$string['transcriptionflavors'] = 'Transcription Service Types (Flavors)'; -$string['transcriptionflavors_desc'] = 'These service type (flavors) will be presented as a select (dropdown) options to select from when uploading transcriptions. - It is a key-value pair of information by which the keys are consumed by opencast and values are human readable information that describe the type of transcription service.
- (Multi-Language filters) In order for each value of Drop Down (select) to get translated using filters such as Multi-Language Content (v2), each value should contain the placeholder, defined by that filter i.e. "{mlang en}Amberscript German{mlang}{mlang de}Amberscript Deutsch{mlang}"'; -$string['deletetranscriptionworkflow_desc'] = 'This workflow is triggered when a transcription is deleted, it is required to provide deletion feature in order for event to be processed correctly.
NOTE: If empty, the feature will be disabled.'; -$string['maxtranscriptionupload'] = 'Maximum number of sets to upload'; -$string['maxtranscriptionupload_desc'] = 'Specify how many transcription box should be provided to teachers to upload. In case it is not correctly set, only 1 field set will be provided.'; -$string['transcriptionfileextensions'] = 'Allowed transcription file extensions'; -$string['transcriptionfileextensions_desc'] = 'Comma separated list of allowed transcription file extensions (extensions must exist in Moodle\'s File types list). If left blank all extensions with type \'HTML track files\' are allowed (again see File types).'; -$string['transcriptionheader'] = 'Upload Transcription Files'; -$string['transcriptionheaderexplanation'] = 'In this section you are able to upload a transcription file for each service type, with specified file extension, which then will be uploaded alongside the video and be processed accordingly to provide the (speech to text) capability.'; -$string['transcriptionaddnewbtn'] = 'Add more transcription set'; -$string['transcriptiondeletebtn'] = 'Delete transcription set'; -$string['transcriptionflavorfield'] = 'Transcription service type'; -$string['transcriptionfilefield'] = 'Transcription file'; -$string['emptyflavoroption'] = 'Please select a service type'; -$string['processattachment'] = 'Process attachment upload jobs'; -$string['managetranscriptions'] = 'Manage Transcriptions'; -$string['managetranscriptions_header'] = 'Manage Event\'s Transcriptions'; -$string['unabletomanagetranscriptions'] = 'Due to an active processing state or an ongoing workflow, managing the event\'s transcriptions is not possible at the moment.'; -$string['managetranscription_overwrite_info'] = 'Overwriting subtitles is only available for manually uploaded subtitles via this plugin, auto generated subtitles and those that are uploaded outside this plugin which do not have the same caption flavor cannot be overwritten.'; -$string['addnewtranscription'] = 'Add new transcription'; -$string['unabletoaddnewtranscription'] = 'Unable to add new transcription'; -$string['addnewtranscription_desc'] = 'Please select a service type in which your transcription should be represented, and then upload the file with requiured extensions.
- NOTE: Uploading a new transcription with an already uploaded service type results in replacing that transcription, which might be useful for editing the current ones.'; -$string['uploadtranscritpion'] = 'Upload transcription set'; -$string['missingtranscriptionuploadparams'] = 'Required parameters to upload transcription are missing.'; -$string['transcriptionuploadsuccessed'] = 'Transcription is uploaded.'; -$string['transcriptionuploadfailed'] = 'Transcription upload failed!'; -$string['notranscription'] = 'This video has no transcription yet.'; -$string['transcriptionflavor_thead'] = 'Service Type'; -$string['notranscriptionflavor'] = 'Unknown Service type: {$a}'; -$string['transcriptionaction_thead'] = 'Actions'; -$string['downloadtranscription'] = 'Download transcription'; -$string['deletetranscription'] = 'Delete transcription'; -$string['unabletodeletetranscription'] = 'Unable to delete transcription'; -$string['transcriptiondeletionsucceeded'] = 'Transcription deleted successfully.'; -$string['transcriptiondeletionfailed'] = 'Failed to delete transcription'; -$string['deletetranscription_desc'] = 'You are about to delete the transcription.
Are you sure you would like to delete it?'; -$string['unabletodownloadtranscription'] = 'Unable to download transcription'; -$string['transcriptionltidownloadcompleted'] = 'The transcription is successfully downloaded. {$a}'; -$string['transcriptionreturntomanagement'] = 'Go back to transcription management page'; -$string['transcriptionmanual'] = 'Manual'; -$string['transcriptionauto'] = 'Auto'; -// Strings for live update feature. -$string['liveupdate_settingheader'] = 'Live Status Update'; -$string['liveupdate_settingenabled'] = 'Enable live status update feature'; -$string['liveupdate_settingenabled_desc'] = 'When enabled, uploading status and workflow processing states will be watched when they are in an ongoing process,
This is done by pulling the status information for those processes in a 1 second interval.'; -$string['liveupdate_reloadtimeout'] = 'Page reload timeout (in seconds)'; -$string['liveupdate_reloadtimeout_desc'] = 'The timeout in seconds by which the page will be reloaded, when there is an updated status identified. If empty or less than 0, a default value of 3 seconds will be considered.
NOTE: Before reloading the page a teachers will be notified. The reload is important, so that every required backend process take place.'; -$string['liveupdate_toast_notification'] = 'Event: ({$a->title}) is updated. The page will be reloaded in {$a->timeout} seconds.'; -$string['liveupdate_fail_notification_message'] = 'Unable to perform live status update for the following event(s):
  • {$a}
'; -$string['notificationuploaduqeuestatus_subj'] = 'Opencast Event Upload Notification'; -$string['notificationuploaduqeuestatus_body'] = 'Processing of this video: {$a->videotitle} in the course: {$a->coursefullname} (ID: {$a->courseid}) is queued, but has not yet started. The video is currently waiting behind {$a->waitingnum} other video(s) in the processing queue.'; -// Strings for cleanup lti modules. -$string['processltimodulecleanup'] = 'Process Opencast Video LTI episode routine cleanup'; -$string['processltimodulecleanup_error'] = 'Something went wrong during LTI module cleanup process: {$a}'; -// Strings for cleanu imported modules notifications. -$string['notificationcleanupimportedmodules_subj'] = 'Opencast imported modules cleanup task notification'; -$string['notificationcleanupimportedmodulesgeneralexception_body'] = 'Cleanup job with workflow id: ({$a->workflowid}) for course {$a->coursefullname} (ID: {$a->courseid}) failed and is removed. The exception message contains: {$a->exceptionmessage}'; -$string['notificationcleanupimportedmodulesexpired_body'] = 'Cleanup job with workflow id: ({$a->workflowid}) for course {$a->coursefullname} (ID: {$a->courseid}) has been removed, as we have waited for 5 days without success to get the duplicated episode ID from OC.'; -$string['notificationcleanupimportedmodulescleanupfailed_body'] = 'Cleanup job with workflow id: ({$a->workflowid}) for course {$a->coursefullname} (ID: {$a->courseid}) failed during the update of the episode activities and is removed.'; -$string['notificationcleanupimportedmodulesnoeposideid_body'] = 'Cleanup job with workflow id: ({$a->workflowid}) for course {$a->coursefullname} (ID: {$a->courseid}) was removed as the stored OC workflow does not exist or does not and will not hold a duplicated episode ID.'; -// Strings for duplicated events visibility change. -$string['error_duplicated_event_id_not_ready'] = 'The duplicated event is not available yet. - Opencast duplicated event visibility change task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; -$string['error_duplicated_event_acl_change'] = 'The visibility change for the duplicated event failed. - Opencast duplicated event visibility change task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; -$string['error_no_duplicate_workflow_id'] = 'The duplicate workflow id is missing. - Opencast duplicated event visibility change task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; -$string['error_no_duplicate_origin_event_id'] = 'The origin event id is missing. - Opencast duplicated event visibility change task ({$a->taskid}) for course {$a->coursefullname} (ID: {$a->courseid}).'; -$string['errorduplicatedeventvisibilitytaskretry'] = 'An error occured by executing a task for setting the duplicated event\'s visibility: {$a} Will try to start the workflow again by the next cron job.'; -$string['errorduplicatedeventvisibilitytaskterminated'] = 'An error occured by executing a task for setting the duplicated event\'s visibility: {$a} - After trying serveral time the task will be terminated now.'; -// New readonly metadata strings. -$string['readonly_disabled_tooltip_text'] = 'Unable to set readonly option while it is set to be required.'; -$string['descriptionmdreadonly'] = 'Readonly'; -$string['descriptionmdreadonly_help'] = 'Please note that, if a field is set to be required, the readonly option will be disabled. That means a field can only be readonly or required at a time.'; -// String for privacy notice. -$string['swprivacynoticedefaulttitle'] = 'Privacy Notice'; -$string['swprivacynotice_settingheader'] = 'Workflows Privacy Notice'; -$string['swprivacynotice_settingtitle'] = 'Workflow Privacy Notice Title'; -$string['swprivacynotice_settingtitle_desc'] = 'A title to be displayed in start workflow dialog. It is intended to be configurable in order to be adjusted by the users. When empty, default string is used.'; -$string['swprivacynotice_settinginfotext'] = 'Workflow Privacy Notice Info Text'; -$string['swprivacynotice_settinginfotext_desc'] = 'This input is used to provide information about privacy notice for workflows in start workflow dialog.
NOTE: If empty, no notice will be displayed.'; -$string['swprivacynotice_settingwfds'] = 'Workflows Definition List'; -$string['swprivacynotice_settingwfds_desc'] = 'A comma separated list of workflow definitions, by which the privacy notice is displayed. When empty, the privacy notice will be displayed for all workflows.'; -$string['startworkflow_modal_description_title'] = 'Workflow Description'; -$string['startworkflow_modal_configpanel_title'] = 'Workflow Configuration Panel'; -// Direct access video. -$string['directaccesstovideo'] = 'Direct access to video'; -$string['directaccess_setting'] = 'Direct access channel'; -$string['directaccess_settingdesc'] = 'Opencast publication channel from which the videos are served when accessing them directly. Leaving this option empty will disable the feature.
Notice: It is recommended to take further caution using this feature, since it reveals the direct video data on the Opencast server upon accessing the link.'; -$string['opencast:sharedirectaccessvideolink'] = 'Share direct access link to video'; -$string['opencast:directaccessvideolink'] = 'Direct access to video via shared link'; -$string['directaccesscopylink'] = 'Copy video direct access link'; -$string['directaccess_copy_no_link'] = 'Invalid direct access link'; -$string['directaccess_copy_success'] = 'The direct access link has been successfully copied to clipboard.'; -$string['directaccess_copytoclipboard_unavialable'] = 'It seems that your browser does not support the copy to clipboard functionality, try to copy the link manually from the dropdown item.'; -$string['opencast:autocompleteteacherroles'] = 'Teacher roles to be extracted and provided in the autocomplete list'; -// Strings for delete block modal. -$string['deletecheck_title_modal'] = 'Remove Opencast Block?'; -$string['error_block_delete_seriesmapping'] = 'Unfortunately, there was an error during course series mapping deletion, please contact the system administrator.'; - -$string['delete_mapping_explanation'] = 'The Opencast Block tracks which Opencast Series is mapped to the course.
You can choose whether to delete the mapping.
If you delete it, the series will no longer appear when you create the opencast block again.'; -$string['only_delete_block'] = 'Delete block, but keep series mapping'; -$string['delete_block_and_mapping'] = 'Delete block and series mapping'; -// Batch upload. -$string['batchupload_setting'] = 'Enable batch video upload'; -$string['batchupload_setting_desc'] = 'By enabling this option, the Opencast instance will provide a separate page to the users to upload videos in batch at once. Please note that for this upload mode, some features in comparision to normal single upload may not be provided.
To avoid cluttering the upload job queue up as well as decreasing the upload process time, it is recommended to increase the "Limit upload job by cron".
To avoid any timeout error during video uploads, it is recommended to adjust timeout options in the following settings according to your needs:
{$a->uploadtimeoutlink}
{$a->toolopencastinstancelink} '; -$string['batchupload'] = 'Add videos (batch)'; -$string['batchupload_errornotenabled'] = 'Unfortunately the batch video upload feature is unavailable for this Opencast instance, please try to contanct your system administrator.'; -$string['batchupload_metadata_header'] = 'Batch Metadata'; -$string['batchupload_metadata_desc'] = 'By uploading a batch of videos to Opencast at once, the following metadata will be set for each video.'; -$string['batchupload_visibility_header'] = 'Batch Visibility'; -$string['batchupload_visibility_desc'] = 'The batch visibility setting will be applied for each uploaded video in the batch.'; -$string['heading_batchable'] = 'Batchable'; -$string['descriptionmdbatchable'] = 'Batchable'; -$string['descriptionmdbatchable_help'] = 'When enabled, the metadata field can be set for batch video upload.'; -$string['batchupload_form_header'] = 'Batch Upload Files'; -$string['batchuploadexplanation'] = 'In this section you are able to upload multiple files at once.
NOTE: Please keep in mind that the batch video upload is only available for presenter flavors.'; -$string['batchupload_filemanager_presenter_title'] = 'Presenter videos'; -$string['batchupload_emptyvideosuploaderror'] = 'You must upload at least one presenter video file.'; -$string['batchupload_jobssaved'] = 'Batch of {$a} Video(s) successfully uploaded.
The videos are queued for transferring to Opencast. Therefore, you do not need to wait on this page for them to finish.'; -$string['batchupload_errorsaveuploadjobs'] = 'There were errors uploading {$a->count} out of {$a->total} video(s).'; -$string['batchupload_errorseriesmismatched'] = 'Unfortunately the series is not defined in this course.'; - -// Deprecated since version 2021062300. -$string['video_already_uploaded'] = 'Video already uploaded'; +$string['worklowisrunning'] = 'A workflow is running. You cannot change the visibility at the moment.'; +$string['wrongmimetypedetected'] = 'An invalid mimetype was used while uploading the video {$a->filename} from course {$a->coursename}. Only video files are allowed!'; diff --git a/managetranscriptions.php b/managetranscriptions.php index 24d3bfeb..056bbe3b 100644 --- a/managetranscriptions.php +++ b/managetranscriptions.php @@ -21,12 +21,12 @@ * @author Farbod Zamani Boroujeni * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); use block_opencast\local\apibridge; use block_opencast\local\attachment_helper; use core\output\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); global $PAGE, $OUTPUT, $CFG, $SITE; diff --git a/overview.php b/overview.php index c6c06a8b..fbcd57f5 100644 --- a/overview.php +++ b/overview.php @@ -21,15 +21,15 @@ * @copyright 2021 Tamara Gunkel * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); -require_once($CFG->dirroot . '/lib/tablelib.php'); -require_once($CFG->dirroot . '/course/lib.php'); use block_opencast\local\activitymodulemanager; use block_opencast\local\apibridge; use core\notification; use mod_opencast\local\opencasttype; use tool_opencast\local\settings_api; +require_once('../../config.php'); +require_once($CFG->dirroot . '/lib/tablelib.php'); +require_once($CFG->dirroot . '/course/lib.php'); global $PAGE, $OUTPUT, $CFG, $DB, $USER, $SITE; @@ -61,7 +61,7 @@ echo $OUTPUT->heading(get_string('seriesoverview', 'block_opencast')); echo html_writer::tag('p', get_string('seriesoverviewexplanation', 'block_opencast')); -// TODO handle opencast connection error. Break as soon as first error occurs. +// Should Do handle opencast connection error. Break as soon as first error occurs. /** @var block_opencast_renderer $renderer */ $renderer = $PAGE->get_renderer('block_opencast'); diff --git a/overview_videos.php b/overview_videos.php index bf57120e..0112ef57 100644 --- a/overview_videos.php +++ b/overview_videos.php @@ -21,14 +21,14 @@ * @copyright 2021 Tamara Gunkel * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); -require_once($CFG->dirroot . '/lib/tablelib.php'); use block_opencast\local\apibridge; use block_opencast\local\upload_helper; use core\notification; use mod_opencast\local\opencasttype; use tool_opencast\local\settings_api; +require_once('../../config.php'); +require_once($CFG->dirroot . '/lib/tablelib.php'); global $PAGE, $OUTPUT, $CFG, $DB, $USER, $SITE; @@ -149,7 +149,7 @@ echo html_writer::tag('p', get_string('videosoverviewexplanation', 'block_opencast')); -// TODO handle opencast connection error. Break as soon as first error occurs. +// Should Do handle opencast connection error. Break as soon as first error occurs. // Build table. $columns = ['owner', 'videos', 'linked', 'activities', 'action']; diff --git a/pix/monologo.svg b/pix/monologo.svg new file mode 100755 index 00000000..6fdfb30a --- /dev/null +++ b/pix/monologo.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + diff --git a/renderer.php b/renderer.php index c5205891..3c764612 100644 --- a/renderer.php +++ b/renderer.php @@ -492,7 +492,8 @@ public function render_block_content($courseid, $videodata, $ocinstance, $render if (get_config('block_opencast', 'batchuploadenabled_' . $ocinstance->id)) { $batchuploadurl = new moodle_url('/blocks/opencast/batchupload.php', ['courseid' => $courseid, 'ocinstanceid' => $ocinstance->id]); - $batchuploadbutton = $this->output->single_button($batchuploadurl, get_string('batchupload', 'block_opencast'), 'get'); + $batchuploadbutton = $this->output->single_button($batchuploadurl, + get_string('batchupload', 'block_opencast'), 'get'); $html .= html_writer::div($batchuploadbutton, 'opencast-batchupload-wrap overview'); } diff --git a/reportproblem.php b/reportproblem.php index 326cebe0..f2158799 100644 --- a/reportproblem.php +++ b/reportproblem.php @@ -21,12 +21,12 @@ * @copyright 2021 Tamara Gunkel, University of Münster * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); use block_opencast\local\apibridge; use block_opencast\local\notifications; use core\output\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); global $PAGE, $OUTPUT, $CFG, $USER, $COURSE; diff --git a/startworkflow.php b/startworkflow.php index 40f9e589..bf8189cb 100644 --- a/startworkflow.php +++ b/startworkflow.php @@ -15,17 +15,17 @@ // along with Moodle. If not, see . /** - * Send problem report to support. + * Start a workflow for a video. * * @package block_opencast * @copyright 2021 Tamara Gunkel, University of Münster * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); use block_opencast\local\apibridge; use core\output\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); global $PAGE, $OUTPUT, $CFG, $USER, $COURSE, $DB; diff --git a/tests/backup_test.php b/tests/backup_test.php index f211f892..172aeb9b 100644 --- a/tests/backup_test.php +++ b/tests/backup_test.php @@ -31,6 +31,10 @@ use backup_controller; use block_opencast\local\apibridge; use block_opencast\task\process_duplicate_event; +use block_opencast\task\process_duplicated_event_module_fix; +use block_opencast\local\activitymodulemanager; +use block_opencast\local\ltimodulemanager; +use mod_opencast\local\opencasttype; use block_opencast_apibridge_testable; use coding_exception; use context_course; @@ -61,12 +65,27 @@ * @copyright 2018 Andreas Wagner, SYNERGY LEARNING * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class backup_test extends advanced_testcase { +final class backup_test extends advanced_testcase { /** @var string for the testcase, must NOT be a real server! */ private $apiurl = 'http://server.opencast.testcase'; + /** @var int the episode lti module id */ + private $episodeltimoduleid = 0; + /** @var int the series lti module id */ + private $seriesltimoduleid = 0; + /** @var string old series id */ + private $oldseriesid = '1234-5678-abcd-efgh'; + /** @var string old episode id */ + private $oldepisodeid = 'c0c8c98d-ad90-445c-b1be-be4944779a24'; + /** @var string new series id */ + private $newseriesid = '1234-1234-1234-1234'; + /** @var string new episode id */ + private $newepisodeid = '66c59fbc-77ca-401a-bb0f-3362bcd27b62'; + /** @var int new course id created after restore */ + private $newcourseid = 0; + public function setUp(): void { parent::setUp(); apibridge::set_testing(true); @@ -148,6 +167,10 @@ protected function restore_course($backupid, $courseid, $includevideos, $userid) $courseid = restore_dbops::create_new_course('Tmp', 'tmp', $categoryid); } + $this->newcourseid = $courseid; + // Simulate the faulty LTI and Activity module creation in new course. + $this->restore_modules($courseid); + $rc = new restore_controller($backupid, $courseid, backup::INTERACTIVE_NO, backup::MODE_GENERAL, $userid, $target); $target == backup::TARGET_NEW_COURSE ?: $rc->get_plan()->get_setting('overwrite_conf')->set_value(true); $this->assertTrue($rc->execute_precheck()); @@ -166,6 +189,166 @@ protected function restore_course($backupid, $courseid, $includevideos, $userid) return $course; } + /** + * Simulate the creation of a new modules in new course with faulty data. + * + * @param int $courseid COurse id + */ + private function restore_modules($courseid) { + global $USER, $DB, $CFG; + require_once($CFG->dirroot.'/course/modlib.php'); + require_once($CFG->dirroot . '/mod/lti/locallib.php'); + + // Get plugin ids. + $activitypluginid = $DB->get_field('modules', 'id', ['name' => 'opencast']); + $ltipluginid = $DB->get_field('modules', 'id', ['name' => 'lti']); + + // Get new course object. + $course = \get_course($courseid); + + // Prepare Dummy data. + $seriesmoduletitle = 'Test Series module to repair'; + $episodemoduletitle = 'Test Episode module to repair'; + + // Build activity modinfo. + // Series activity module. + $activityseriesmoduleinfo = activitymodulemanager::build_activity_modinfo( + $activitypluginid, + $course, + 1, + $seriesmoduletitle, + 0, + $this->oldseriesid, + opencasttype::SERIES + ); + $addedactivityseriesmoduleinfo = add_moduleinfo($activityseriesmoduleinfo, $course); + $this->assertNotEmpty($addedactivityseriesmoduleinfo); + + // Episode activity module. + $activityepisodemoduleinfo = activitymodulemanager::build_activity_modinfo( + $activitypluginid, + $course, + 1, + $episodemoduletitle, + 0, + $this->oldepisodeid, + opencasttype::EPISODE + ); + $addedactivityepisodemoduleinfo = add_moduleinfo($activityepisodemoduleinfo, $course); + $this->assertNotEmpty($addedactivityepisodemoduleinfo); + + // Build LTI modules. + $sitetoolinfo = [ + 'baseurl' => rtrim($this->apiurl, '/') . '/lti', + 'createdby' => $USER->id, + 'course' => SITEID, + 'ltiversion' => 'LTI-1p0', + 'timecreated' => time(), + 'timemodified' => time(), + 'state' => LTI_TOOL_STATE_CONFIGURED, + 'coursevisible' => LTI_COURSEVISIBLE_ACTIVITYCHOOSER, + ]; + $seriessitetool = $sitetoolinfo; + $seriessitetool['name'] = 'Opencast Series'; + $seriessitetoolrecord = (object) $seriessitetool; + $seriestoolid = $DB->insert_record('lti_types', $seriessitetoolrecord); + set_config('addltipreconfiguredtool_1', $seriestoolid, 'block_opencast'); + + $episodesitetool = $sitetoolinfo; + $episodesitetool['name'] = 'Opencast Episode'; + $episodesitetoolrecord = (object) $episodesitetool; + $episodetoolid = $DB->insert_record('lti_types', $episodesitetoolrecord); + set_config('addltiepisodepreconfiguredtool_1', $episodetoolid, 'block_opencast'); + + // Get the id of the installed LTI plugin. + // Series LTI module. + $ltiseriesmoduleinfo = ltimodulemanager::build_lti_modinfo( + $ltipluginid, + $course, + $seriesmoduletitle, + 0, + $seriestoolid, + 'series=' . $this->oldseriesid + ); + $addedltiseriesmoduleinfo = add_moduleinfo($ltiseriesmoduleinfo, $course); + $this->seriesltimoduleid = $addedltiseriesmoduleinfo->coursemodule; + $this->assertNotEmpty($addedltiseriesmoduleinfo); + + // Episode LTI module. + $ltiepisodemoduleinfo = ltimodulemanager::build_lti_modinfo( + $ltipluginid, + $course, + $episodemoduletitle, + 0, + $episodetoolid, + 'id=' . $this->oldepisodeid + ); + $addedltiepisodemoduleinfo = add_moduleinfo($ltiepisodemoduleinfo, $course); + $this->episodeltimoduleid = $addedltiepisodemoduleinfo->coursemodule; + $this->assertNotEmpty($addedltiepisodemoduleinfo); + } + + /** + * Checks whether the imported modules are fixed. + * + * @return boolean true if all modules are fixed, false otherwise + */ + private function check_fixed_modules() { + global $CFG, $DB; + + $seriesltimoduleisfixed = false; + $episodeltimoduleisfixed = false; + $episodeactivitymoduleisfixed = false; + $seriesactivitymoduleisfixed = false; + + // Require grade library. For an unknown reason, this is needed when updating the module. + require_once($CFG->libdir . '/gradelib.php'); + + $courseobject = get_course($this->newcourseid); + + // LTI modules. + if (!empty($this->seriesltimoduleid)) { + $seriesmoduleobject = get_coursemodule_from_id('lti', $this->seriesltimoduleid, $this->newcourseid); + list($unusedcm, $unusedcontext, $unusedmodule, $seriesmoduledata, $unusedcw) = + get_moduleinfo_data($seriesmoduleobject, $courseobject); + + if (strpos($seriesmoduledata->instructorcustomparameters, $this->newseriesid) !== false) { + $seriesltimoduleisfixed = true; + } + } + + if (!empty($this->episodeltimoduleid)) { + $episodemoduleobject = get_coursemodule_from_id('lti', $this->episodeltimoduleid, $this->newcourseid); + list($unusedcm, $unusedcontext, $unusedmodule, $episodemoduledata, $unusedcw) = + get_moduleinfo_data($episodemoduleobject, $courseobject); + + if (strpos($episodemoduledata->instructorcustomparameters, $this->newepisodeid) !== false) { + $episodeltimoduleisfixed = true; + } + } + + // Activity modules. + $seriesrecord = [ + 'ocinstanceid' => 1, + 'course' => $this->newcourseid, + 'type' => opencasttype::SERIES, + 'opencastid' => $this->newseriesid, + ]; + $seriesactivitymoduleisfixed = $DB->record_exists('opencast', $seriesrecord); + + $episoderecord = [ + 'ocinstanceid' => 1, + 'course' => $this->newcourseid, + 'type' => opencasttype::EPISODE, + 'opencastid' => $this->newepisodeid, + ]; + + $episodeactivitymoduleisfixed = $DB->record_exists('opencast', $episoderecord); + + return $seriesltimoduleisfixed && $episodeltimoduleisfixed && + $episodeactivitymoduleisfixed && $seriesactivitymoduleisfixed; + } + /** * Execute an adhoc task like via cron function. * @param stdClass $taskrecord @@ -195,6 +378,35 @@ private function execute_adhoc_task($taskrecord) { return ob_get_clean(); } + /** + * Execute an adhoc task to fix modules. + * @param stdClass $taskrecord + */ + private function execute_module_fix_adhoc_task($taskrecord) { + global $CFG; + + $task = new process_duplicated_event_module_fix(); + $task->set_id($taskrecord->id); + $task->set_custom_data_as_string($taskrecord->customdata); + + $cronlockfactory = lock_config::get_lock_factory('cron'); + $lock = $cronlockfactory->get_lock('adhoc_' . $taskrecord->id, 0); + $lock->release(); + + $task->set_lock($lock); + + $this->preventResetByRollback(); + ob_start(); + + // In Moodle 4.2 version cron_run_inner_adhoc_task is depricated. + if ($CFG->version < 2023042400) { + cron_run_inner_adhoc_task($task); + } else { + cron::run_inner_adhoc_task($task); + } + return ob_get_clean(); + } + /** * Check if task failed with error. * @param string $expectederrortextkey @@ -231,7 +443,7 @@ private function check_task_fail_with_error($expectederrortextkey, $expectedfail * * @covers \restore_controller \backup_controller */ - public function test_adhoctask_execution() { + public function test_adhoctask_execution(): void { global $USER, $DB; $this->resetAfterTest(); @@ -256,20 +468,21 @@ public function test_adhoctask_execution() { $mapping = new seriesmapping(); $mapping->set('ocinstanceid', 1); $mapping->set('courseid', $course->id); - $mapping->set('series', '1234-5678-abcd-efgh'); + $mapping->set('series', $this->oldseriesid); $mapping->set('isdefault', 1); $mapping->create(); // Setup simulation data for api. $apibridge->set_testdata('get_course_videos', $course->id, 'file'); - $apibridge->set_testdata('get_series_videos', '1234-5678-abcd-efgh', 'file'); + $apibridge->set_testdata('get_series_videos', $this->oldseriesid, 'file'); + $apibridge->set_testdata('get_series_by_identifier', $this->oldseriesid, 'file'); // Backup the course with videos. $backupid = $this->backup_course($course->id, true, $USER->id); // Prepare server simulation (via apibridge). $apibridge->set_testdata('supports_api_level', 'level', 'v1.1.0'); - $apibridge->set_testdata('create_course_series', 'newcourse', '1234-1234-1234-1234'); + $apibridge->set_testdata('create_course_series', 'newcourse', $this->newseriesid); // Restore the course with videos. $newcourse = $this->restore_course($backupid, 0, true, $USER->id); @@ -328,18 +541,42 @@ public function test_adhoctask_execution() { // Setup the mockuped workflow again. $apibridge->set_testdata('check_if_workflow_exists', $apibridge::DUPLICATE_WORKFLOW, true); - $apibridge->set_testdata('get_opencast_video', 'c0c8c98d-ad90-445c-b1be-be4944779a24', 'file'); + $apibridge->set_testdata('get_opencast_video', $this->oldepisodeid, 'file'); // The workflow exists now, but it is not started. $this->check_task_fail_with_error('error_workflow_not_started', 6); // Setup succesful start workflow in opencast system. - $apibridge->set_testdata('start_workflow', $apibridge::DUPLICATE_WORKFLOW, true); + // $apibridge->set_testdata('start_workflow', $apibridge::DUPLICATE_WORKFLOW, true). + $dummyworkflowid = 1234; + $apibridge->set_testdata('start_workflow', $apibridge::DUPLICATE_WORKFLOW, $dummyworkflowid); $taskrecords = $DB->get_records('task_adhoc', ['classname' => '\\block_opencast\\task\\process_duplicate_event']); $taskrecord = array_shift($taskrecords); $output = $this->execute_adhoc_task($taskrecord); + // Run adhoc task to fix modules. + $apibridge->set_testdata('get_duplicated_episodeid', $dummyworkflowid, $this->newepisodeid); + $modulefixtaskrecords = $DB->get_records('task_adhoc', + ['classname' => '\\block_opencast\\task\\process_duplicated_event_module_fix']); + $modulefixtaskrecord = array_shift($modulefixtaskrecords); + $modulefixoutput = $this->execute_module_fix_adhoc_task($modulefixtaskrecord); + + // Run adhoc task again to go to cleaup process. + $modulefixtaskrecords = $DB->get_records('task_adhoc', + ['classname' => '\\block_opencast\\task\\process_duplicated_event_module_fix']); + $modulefixtaskrecord = array_shift($modulefixtaskrecords); + $modulefixoutput = $this->execute_module_fix_adhoc_task($modulefixtaskrecord); + + // Check if the module fix adhoc task was successfully terminated. + $modulefixtaskrecords = $DB->get_records('task_adhoc', + ['classname' => '\\block_opencast\\task\\process_duplicated_event_module_fix']); + $this->assertEquals(0, count($modulefixtaskrecords)); + + // Check if modules are fixed. + $modulesfixed = $this->check_fixed_modules(); + $this->assertEquals(true, $modulesfixed); + // Check that the task is deleted. $taskrecords = $DB->get_records('task_adhoc', ['classname' => '\\block_opencast\\task\\process_duplicate_event']); $this->assertEquals(0, count($taskrecords)); diff --git a/tests/behat/behat_block_opencast.php b/tests/behat/behat_block_opencast.php index 450eb5b1..9daca684 100644 --- a/tests/behat/behat_block_opencast.php +++ b/tests/behat/behat_block_opencast.php @@ -142,11 +142,12 @@ protected function load_apitestable_json_responses() { public function i_go_to_direct_access_link() { // Get the direct access link. if (empty($this->directaccesslink)) { - $csselement = '#opencast-videos-table-ID-blender-foundation_r0 .c3 .access-action-menu a.access-link-copytoclipboard'; + $csselement = '#opencast-videos-table-ID-blender-foundation_r0 .c7 .access-action-menu a.access-link-copytoclipboard'; try { $this->find('css', $csselement); } catch (ElementNotFoundException $e) { - throw new ExpectationException('Targeted Element to copy direct access link could not be found.'); + throw new ExpectationException('Targeted Element to copy direct access link could not be found.', + $this->getSession()); } $element = $this->find('css', $csselement); $this->directaccesslink = $element->getAttribute('href'); diff --git a/tests/behat/block_opencast_addlti.feature b/tests/behat/block_opencast_addlti.feature index bd2626e6..c9a7be05 100644 --- a/tests/behat/block_opencast_addlti.feature +++ b/tests/behat/block_opencast_addlti.feature @@ -214,6 +214,9 @@ Feature: Add Opencast LTI series module as Teacher Given the following config values are set as admin: | addltisection_1 | 1 | block_opencast | And I log in as "teacher1" + And I am on "Course 1" course homepage with editing mode on + And I edit the section "1" and I fill the form with: + | Section name | Topic 1 | And I am on "Course 1" course homepage And I click on "Go to overview..." "link" And I click on "Add Opencast LTI series module to course" "link" diff --git a/tests/behat/block_opencast_cleanup_backup.feature b/tests/behat/block_opencast_cleanup_backup.feature index 34dba8e0..d0a4ac2d 100644 --- a/tests/behat/block_opencast_cleanup_backup.feature +++ b/tests/behat/block_opencast_cleanup_backup.feature @@ -35,6 +35,7 @@ Feature: Restore courses as Teacher | importvideoshandleseriesenabled_1 | 1 | block_opencast | | importvideoshandleepisodeenabled_1 | 1 | block_opencast | | addltiepisodeenabled_1 | 1 | block_opencast | + | enableasyncbackup | 0 | | And I setup the opencast test api And I upload a testvideo And I log in as "admin" diff --git a/tests/behat/block_opencast_directaccess.feature b/tests/behat/block_opencast_directaccess.feature.disabled similarity index 96% rename from tests/behat/block_opencast_directaccess.feature rename to tests/behat/block_opencast_directaccess.feature.disabled index b165a99d..ec6ab1b5 100644 --- a/tests/behat/block_opencast_directaccess.feature +++ b/tests/behat/block_opencast_directaccess.feature.disabled @@ -53,9 +53,9 @@ Feature: Direct Access via shared link Given I log in as "teacher1" And I am on "Course 1" course homepage And I click on "Go to overview..." "link" - And I click on "#opencast-videos-table-ID-blender-foundation_r0 .c3 .access-action-menu a" "css_element" + And I click on "#opencast-videos-table-ID-blender-foundation_r0 .c7 .access-action-menu .menubar .dropdown" "css_element" Then I should see "Presenter" - When I click on "#opencast-videos-table-ID-blender-foundation_r0 .c3 .access-action-menu a.access-link-copytoclipboard" "css_element" + When I click on "#opencast-videos-table-ID-blender-foundation_r0 .c7 .access-action-menu .menubar .dropdown.show .dropdown-menu a.access-link-copytoclipboard" "css_element" Then I should see "The direct access link has been successfully copied to clipboard." When I go to direct access link And I wait "1" seconds diff --git a/tests/delete_file_test.php b/tests/delete_file_test.php index a948dc11..93490a06 100644 --- a/tests/delete_file_test.php +++ b/tests/delete_file_test.php @@ -39,7 +39,7 @@ * @copyright 2017 Andreas Wagner, SYNERGY LEARNING * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class delete_file_test extends advanced_testcase { +final class delete_file_test extends advanced_testcase { /** @@ -47,7 +47,7 @@ class delete_file_test extends advanced_testcase { * * @covers \block_opencast\local\file_deletionmanager */ - public function test_delete_files() { + public function test_delete_files(): void { global $DB; // Set up. diff --git a/tests/fixtures/get_series_by_identifier.js b/tests/fixtures/get_series_by_identifier.js new file mode 100644 index 00000000..f740db30 --- /dev/null +++ b/tests/fixtures/get_series_by_identifier.js @@ -0,0 +1,2 @@ +{"identifier":"1234-5678-abcd-efgh","title":"My Test Series"} + diff --git a/tests/helper/apibridge_testable.php b/tests/helper/apibridge_testable.php index 29fd5191..190f729d 100644 --- a/tests/helper/apibridge_testable.php +++ b/tests/helper/apibridge_testable.php @@ -336,4 +336,43 @@ public function start_workflow($eventid, $duplicateworkflow, $params = [], $retu return $this->get_testdata('start_workflow', $duplicateworkflow); } + /** + * Simulates an API call to check, whether series exists in opencast system. + * + * @param int $seriesid + * @param bool $withacl If true, ACLs are included + * @return null|stdClass series if it exists in the opencast system. + */ + public function get_series_by_identifier($seriesid, bool $withacl = false) { + if (empty($seriesid)) { + return null; + } + + if ($value = $this->get_testdata('get_series_by_identifier', $seriesid)) { + return json_decode($value); + } + + return null; + } + + /** + * Simulates the check if the series ID exists in the Opencast system. + * @param string $seriesid Series id + * @return bool true, if the series exists. Otherwise false. + */ + public function ensure_series_is_valid($seriesid) { + return true; + } + + /** + * Simulate getting the episode id of the episode which was created in a duplication workflow. + * + * @param int $workflowid The workflow ID of the dupliation workflow. + * + * @return string|bool The episode ID, false if not found. + */ + public function get_duplicated_episodeid($workflowid) { + + return $this->get_testdata('get_duplicated_episodeid', $workflowid); + } } diff --git a/tests/privacy_test.php b/tests/privacy_test.php index fa8dd239..75450338 100644 --- a/tests/privacy_test.php +++ b/tests/privacy_test.php @@ -43,7 +43,7 @@ * @copyright 2018 Tamara Gunkel * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class privacy_test extends provider_testcase { +final class privacy_test extends provider_testcase { /** @@ -58,7 +58,7 @@ public function setUp(): void { * * @covers \block_opencast\privacy\provider */ - public function test_get_metadata() { + public function test_get_metadata(): void { $collection = new collection('block_opencast'); $newcollection = provider::get_metadata($collection); $itemcollection = $newcollection->get_collection(); @@ -92,7 +92,7 @@ public function test_get_metadata() { * * @covers \block_opencast\privacy\provider::get_contexts_for_userid */ - public function test_get_contexts_for_userid() { + public function test_get_contexts_for_userid(): void { global $DB; // Test setup. @@ -165,7 +165,7 @@ public function test_get_contexts_for_userid() { * * @covers \block_opencast\privacy\provider::export_user_data */ - public function test_export_user_data() { + public function test_export_user_data(): void { global $DB; // Test setup. @@ -223,7 +223,7 @@ public function test_export_user_data() { * * @covers \block_opencast\privacy\provider::delete_data_for_all_users_in_context */ - public function test_delete_data_for_all_users_in_context() { + public function test_delete_data_for_all_users_in_context(): void { global $DB; // Test setup. @@ -270,7 +270,7 @@ public function test_delete_data_for_all_users_in_context() { * * @covers \block_opencast\privacy\provider::delete_data_for_user */ - public function test_delete_data_for_user() { + public function test_delete_data_for_user(): void { global $DB; // Test setup. @@ -360,7 +360,7 @@ public function test_delete_data_for_user() { * * @covers \block_opencast\privacy\provider::get_users_in_context */ - public function test_get_users_in_context() { + public function test_get_users_in_context(): void { global $DB; // Test setup. @@ -465,7 +465,7 @@ public function test_get_users_in_context() { * * @covers \block_opencast\privacy\provider::delete_data_for_users */ - public function test_delete_data_for_users() { + public function test_delete_data_for_users(): void { global $DB; // Test setup. diff --git a/tests/upload_test.php b/tests/upload_test.php index 10b8352d..5eeb0b3a 100644 --- a/tests/upload_test.php +++ b/tests/upload_test.php @@ -44,7 +44,7 @@ * @copyright 2017 Andreas Wagner, SYNERGY LEARNING * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class upload_test extends advanced_testcase { +final class upload_test extends advanced_testcase { /** @var string Test api url. */ @@ -74,7 +74,7 @@ public function notest_plugin_installed() { * @throws coding_exception * @throws dml_exception */ - public function test_upload() { + public function test_upload(): void { global $CFG, $DB; $this->resetAfterTest(); diff --git a/updatemetadata.php b/updatemetadata.php index d98005c7..28ec3c67 100644 --- a/updatemetadata.php +++ b/updatemetadata.php @@ -20,13 +20,13 @@ * @copyright 2019 Farbod Zamani, ELAN e.V. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../../config.php'); use block_opencast\local\apibridge; use block_opencast\local\updatemetadata_form; use block_opencast\local\upload_helper; use core\output\notification; use tool_opencast\local\settings_api; +require_once('../../config.php'); global $PAGE, $OUTPUT, $CFG, $SITE; diff --git a/version.php b/version.php index 4c23fa3f..71971fab 100644 --- a/version.php +++ b/version.php @@ -24,10 +24,10 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'block_opencast'; -$plugin->release = 'v4.3-r2'; -$plugin->version = 2024031800; +$plugin->release = 'v4.4-r2'; +$plugin->version = 2024061400; $plugin->requires = 2022112800; // Requires Moodle 4.1+. $plugin->maturity = MATURITY_STABLE; $plugin->dependencies = [ - 'tool_opencast' => 2023112200, + 'tool_opencast' => 2024060400, ];