diff --git a/CHANGES.md b/CHANGES.md index 8d960eab..aafae320 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,10 @@ CHANGELOG ========= +5.2.0 (2026-06-01) +------------------ +* Moodle 5.2 compatible version + 5.1.5 (v5.1-r6, 2026-05-20) --------------------------- * [FEATURE] Introduce new step opencast diff --git a/classes/local/intersectedRecordset.php b/classes/local/intersectedRecordset.php new file mode 100644 index 00000000..29611f2e --- /dev/null +++ b/classes/local/intersectedRecordset.php @@ -0,0 +1,157 @@ +. + +/** + * Helper class which intersects multiple moodle record sets. + * + * @package tool_lifecycle + * @copyright 2025 Michael Schink JKU + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tool_lifecycle\local; + +defined('MOODLE_INTERNAL') || die(); + +class intersectedRecordset implements \Iterator, \Countable { + private $records = []; + private $position = 0; + private $wasFilled = false; + + /** + * Constructor: Inits class & intersects passed recordsets. + * + * @param moodle_recordset|array|null $recordsets + * @param string $key + */ + public function __construct($recordsets = null, string $key = 'id') { + if($recordsets !== null) { + if(is_array($recordsets)) { + // For multiple recordsets + foreach($recordsets as $recordset) { + // If recordset is a chunked recordset + if(is_array($recordset)) { + //mtrace('Chunked recordset'); + // Create new array for chunked recordset + $chunkedRecords = []; + // For each chunked recordset + foreach($recordset as $chunk_recordset) { + // For each record in chunked recordset + foreach($chunk_recordset as $record) { + if(isset($record->$key)) { $chunkedRecords[$record->$key] = $record; } + } + } + // Add all records of chunked recordsets + $this->add($chunkedRecords, $key); + } else { + //mtrace('Normal recordset'); + $this->add($recordset, $key); + } + } + } else { $this->add($recordsets, $key); } + } + } + + /** + * Adds recordset & saves intersection of all recordsets. + * + * @param moodle_recordset $recordset + * @param string $key + */ + public function add($recordset, string $key = 'id'): void { + // Add new records to array with key + $newRecords = []; + foreach($recordset as $record) { + if(isset($record->$key)) { $newRecords[$record->$key] = $record; } + } + //mtrace(' Found '.count($newRecords).' records in recordset'); + //$recordset->close(); + + // Store new records without key, if no records were stored & return + if(empty($this->records) && !$this->wasFilled) { + $this->records = array_values($newRecords); + $this->wasFilled = true; + + return; + } + + // Add existing records to array with key + $existingRecords = []; + foreach($this->records as $record) { + if(isset($record->$key)) { $existingRecords[$record->$key] = $record; } + } + + // Intersect existing & new records by keys + $intersectionKeys = array_intersect_key($existingRecords, $newRecords); + // Clear existing records + $this->records = []; + // Store intersected records by keys + foreach($intersectionKeys as $keyValue => $record) { + $this->records[] = $existingRecords[$keyValue]; + } + //mtrace('Add - Intersected record sets: '.count($this->records)); + } + + /** + * Returns current recordset. + * + * @return mixed + */ + public function current(): mixed { + return $this->records[$this->position]; + } + + /** + * Returns current key (index). + * + * @return int + */ + public function key(): int { + return $this->position; + } + + /** + * Moves internal pointer to next recordset. + */ + public function next(): void { + $this->position++; + } + + /** + * Returns internal pointer to start. + */ + public function rewind(): void { + $this->position = 0; + } + + /** + * Checks if current pointer points to a valid recordset. + * + * @return bool + */ + public function valid(): bool { + return isset($this->records[$this->position]); + } + + /** + * Returns the amount of all recordsets. + * + * @return int + */ + public function count(): int { + return count($this->records); + } +} \ No newline at end of file diff --git a/classes/processor.php b/classes/processor.php index e2e656fd..eba0ca9f 100644 --- a/classes/processor.php +++ b/classes/processor.php @@ -345,6 +345,225 @@ public function process_course_interactive($processid) { * @throws \coding_exception * @throws \dml_exception */ + public function get_course_recordset($triggers, $nositecourse = true, $forcounting = false) { + global $DB, $SESSION; + + // Mike + $where = []; + $whereparams = []; + $recordsets = []; + $workflow = false; + foreach ($triggers as $trigger) { + $where_tmp2 = " TRUE "; + $whereparams_tmp2 = []; + if (!$workflow) { + $workflow = workflow_manager::get_workflow($trigger->workflowid); + $andor = ($workflow->andor ?? 0) == 0 ? 'AND' : 'OR'; + $where_tmp2 = $andor == 'AND' ? 'true ' : 'false '; + } + $lib = lib_manager::get_automatic_trigger_lib($trigger->subpluginname); + // Exclude specificdate trigger when counting. + if (!($forcounting && $lib->default_response() == trigger_response::triggertime())) { + [$sql, $params] = $lib->get_course_recordset_where($trigger->id); + $sql = preg_replace("/{course}/", "c", $sql, 1); + if (!empty($sql)) { + $where_tmp2 .= " $andor " . $sql; + $whereparams[] = array_merge($whereparams_tmp2, $params); + } else { $whereparams[] = []; } + } else { $whereparams[] = []; } + $where[] = $where_tmp2; + } + + $maxparams = 65535; + //$maxparams = 1000; + mtrace(''); + mtrace('Start - MAX params: '.$maxparams.', trigger where parts: '.count($where)/*.' '.print_r($where, true)*/.' & params: '.count($whereparams)/*.' '.print_r($whereparams, true)*/); + foreach($whereparams as $key => $whereparam) { + if(count($whereparam) > $maxparams) { + mtrace('More than '.$maxparams.' params with key '.$key.': '.count($whereparam)); + // Get where part of params array + $wherepart = $where[$key]; + // Get first & last param + $first = ':'.array_key_first($whereparam); + $last = ':'.array_key_last($whereparam); + mtrace(' 1. Get first param '.$first.' & last param '.$last); + // Get where part before first param & after last param (to re-create where part) + $position = strpos($wherepart, $first); + $before = substr($wherepart, 0, $position); + $position = strpos($wherepart, $last); + $after = substr($wherepart, $position + strlen($last)); + mtrace(' 2. Re-create where part: '.$before.' '.$after); + // Remove original where part & params + //unset($where[$key]); + //unset($whereparams[$key]); + $where[$key] = []; + $whereparams[$key] = []; + mtrace(' 3. Remove where part & params with key: '.$key); + // Chunk params + $whereparam_chunks = array_chunk($whereparam, $maxparams, true); + mtrace(' 4. Chunk params: '.count($whereparam_chunks)/*.print_r($whereparam_chunks, true))*/.' ('.count($whereparam).'/'.$maxparams.')'); + // For each chunk of params + $counter = 0; + foreach($whereparam_chunks as $whereparam_chunk) { + $counter++; + // Create param string of chunk params + $whereparam_chunk_string = implode(',', array_map(function($value) { return ':' . $value; }, array_keys($whereparam_chunk))); + // Re-create where part for chunk + $where_chunk = $before.$whereparam_chunk_string.$after; + if(count($whereparam_chunks) > 10 && $counter == 10 ) { mtrace(' ...'); } + if($counter < 5 || $counter >= (count($whereparam_chunks) - 5)) { mtrace(' 5.'.$counter.' Add chunk query: '.(strlen($where_chunk) > 150 ? substr($where_chunk, 0, 150) . '...' : $where_chunk).' & params: '.count($whereparam_chunk)/*.print_r($whereparam_chunk, true)*/); } + // Add where part & params of chunk + if(count($where) && count($whereparams)) { + $where[$key][] = $where_chunk; + $whereparams[$key][] = $whereparam_chunk; + } else { mtrace('ERROR: Amount of where parts & params are not the same!'); } + } + } + } + mtrace('End - MAX params: '.$maxparams.', trigger where parts: '.count($where)/*.' '.print_r($where, true)*/.' & params '.count($whereparams)/*.' '.print_r($whereparams, true)*/); + mtrace(''); + //die(); + + if ($forcounting) { + foreach ($where as $key => $where_tmp) { + $whereparams_tmp = $whereparams[$key]; + // Get course hasprocess and delay with the sql. + $sql = "SELECT c.id, + COALESCE(p.courseid, pe.courseid, 0) as hasprocess, + COALESCE(po.workflowid, peo.workflowid, 0) as hasotherwfprocess, + CASE + WHEN COALESCE(d.delayeduntil, 0) > COALESCE(dw.delayeduntil, 0) THEN d.delayeduntil + WHEN COALESCE(d.delayeduntil, 0) < COALESCE(dw.delayeduntil, 0) THEN dw.delayeduntil + ELSE 0 + END as delaycourse + FROM {course} c + LEFT JOIN {tool_lifecycle_process} p ON c.id = p.courseid AND p.workflowid = $workflow->id + LEFT JOIN {tool_lifecycle_proc_error} pe ON c.id = pe.courseid AND pe.workflowid = $workflow->id + LEFT JOIN {tool_lifecycle_process} po ON c.id = po.courseid AND po.workflowid <> $workflow->id + LEFT JOIN {tool_lifecycle_proc_error} peo ON c.id = peo.courseid AND peo.workflowid <> $workflow->id + LEFT JOIN {tool_lifecycle_delayed} d ON c.id = d.courseid + LEFT JOIN {tool_lifecycle_delayed_workf} dw ON + c.id = dw.courseid AND dw.workflowid = $workflow->id + WHERE "; + if(is_array($where_tmp)) { + //mtrace('Chunked recordset: '.count($where_tmp)/*.' '.print_r($where_tmp, true)*/.', params: '.count($whereparams_tmp)/*.' '.print_r($whereparams_tmp, true)*/); + $tmp = []; + foreach($where_tmp as $chunk_key => $chunk_where_tmp) { + // We include delayed courses here anyway, so we only take the site course into account. + if ($nositecourse) { + $chunk_where_tmp = "($chunk_where_tmp) AND c.id <> 1 "; + } + $sql_tmp = $sql.$chunk_where_tmp; + $debugsql = $sql_tmp; + foreach ($whereparams_tmp as $key => $value) { + $debugsql = str_replace(":".$key, $value, $debugsql); + } + // v5.0-r3 + //$SESSION->debugtriggersql = $debugsql; + // v5.2-r1 + $SESSION->debugprocesssql = $debugsql; + $tmp[] = $DB->get_recordset_sql($sql_tmp, $whereparams_tmp[$chunk_key]); + } + $recordsets[] = $tmp; + } else { + //mtrace('Nomrmal recordset: '.$where_tmp.', params: '.count($whereparams_tmp)/*.' '.print_r($whereparams_tmp, true)*/); + // We include delayed courses here anyway, so we only take the site course into account. + if ($nositecourse) { + $where_tmp = "($where_tmp) AND c.id <> 1 "; + } + $sql_tmp = $sql.$where_tmp; + $debugsql = $sql_tmp; + foreach ($whereparams_tmp as $key => $value) { + $debugsql = str_replace(":".$key, $value, $debugsql); + } + // v5.0-r3 + //$SESSION->debugtriggersql = $debugsql; + // v5.2-r1 + $SESSION->debugprocesssql = $debugsql; + $recordsets[] = $DB->get_recordset_sql($sql_tmp, $whereparams_tmp); + } + } + + //use tool_lifecycle\local\intersectedRecordset; + $recordsets = new \tool_lifecycle\local\intersectedRecordset($recordsets); + //mtrace('Intersected record sets (for counting): '.count($recordsets)); + } else { + foreach ($where as $key => $where_tmp) { + $whereparams_tmp = $whereparams[$key]; + // Get only courses which are not part of an existing process. + $sql = "SELECT c.id from {course} c + LEFT JOIN {tool_lifecycle_process} p ON c.id = p.courseid + LEFT JOIN {tool_lifecycle_proc_error} pe ON c.id = pe.courseid + WHERE p.courseid is null AND pe.courseid IS NULL AND "; + if(is_array($where_tmp)) { + //mtrace('Chunked recordset: '.count($where_tmp)/*.' '.print_r($where_tmp, true)*/.', params: '.count($whereparams_tmp)/*.' '.print_r($whereparams_tmp, true)*/); + $tmp = []; + foreach($where_tmp as $chunk_key => $chunk_where_tmp) { + if ($workflow) { + if (!$workflow->includesitecourse) { + $chunk_where_tmp = "($chunk_where_tmp) AND c.id <> 1 "; + } + if (!$workflow->includedelayedcourses) { + $chunk_where_tmp = "($chunk_where_tmp) AND NOT c.id in (select courseid FROM {tool_lifecycle_delayed_workf} + WHERE delayeduntil > :time1 AND workflowid = :workflowid) + AND NOT c.id in (select courseid FROM {tool_lifecycle_delayed} WHERE delayeduntil > :time2) "; + $inparams = ['time1' => time(), 'time2' => time(), 'workflowid' => $workflow->id]; + $whereparams_tmp = array_merge($whereparams_tmp, $inparams); + } + } + $sql_tmp = $sql.$chunk_where_tmp; + $debugsql = $sql_tmp; + foreach ($whereparams_tmp as $key => $value) { + $debugsql = str_replace(":".$key, $value, $debugsql); + } + // v5.0-r3 + //$SESSION->debugtriggersql = $debugsql; + // v5.2-r1 + $SESSION->debugprocesssql = $debugsql; + $tmp[] = $DB->get_recordset_sql($sql_tmp, $whereparams_tmp[$chunk_key]); + } + $recordsets[] = $tmp; + } else { + //mtrace('Nomrmal recordset: '.$where_tmp.', params: '.count($whereparams_tmp)/*.' '.print_r($whereparams_tmp, true)*/); + if ($workflow) { + if (!$workflow->includesitecourse) { + $where_tmp = "($where_tmp) AND c.id <> 1 "; + } + if (!$workflow->includedelayedcourses) { + $where_tmp = "($where_tmp) AND NOT c.id in (select courseid FROM {tool_lifecycle_delayed_workf} + WHERE delayeduntil > :time1 AND workflowid = :workflowid) + AND NOT c.id in (select courseid FROM {tool_lifecycle_delayed} WHERE delayeduntil > :time2) "; + $inparams = ['time1' => time(), 'time2' => time(), 'workflowid' => $workflow->id]; + $whereparams_tmp = array_merge($whereparams_tmp, $inparams); + } + } + $sql_tmp = $sql.$where_tmp; + $debugsql = $sql_tmp; + foreach ($whereparams_tmp as $key => $value) { + $debugsql = str_replace(":".$key, $value, $debugsql); + } + // v5.0-r3 + //$SESSION->debugtriggersql = $debugsql; + // v5.2-r1 + $SESSION->debugprocesssql = $debugsql; + $recordsets[] = $DB->get_recordset_sql($sql_tmp, $whereparams_tmp); + } + } + + //use tool_lifecycle\local\intersectedRecordset; + $recordsets = new \tool_lifecycle\local\intersectedRecordset($recordsets); + //mtrace('Intersected record sets: '.count($recordsets)); + } + + mtrace(''); + mtrace('FINAL recordsets: '.$recordsets->count()/*.' '.print_r($recordsets, true)*/); + mtrace(''); + //die(); + + return $recordsets; + } + + /* public function get_course_recordset($triggers, $nositecourse = true, $forcounting = false) { global $DB, $SESSION; @@ -419,6 +638,7 @@ public function get_course_recordset($triggers, $nositecourse = true, $forcounti return $DB->get_recordset_sql($sql, $whereparams); } + */ /** * Returns the number of courses for a trigger for counting. diff --git a/trigger/opencast/classes/privacy/provider.php b/trigger/opencast/classes/privacy/provider.php deleted file mode 100644 index 7fe0bf1c..00000000 --- a/trigger/opencast/classes/privacy/provider.php +++ /dev/null @@ -1,39 +0,0 @@ -. - -namespace lifecycletrigger_opencast\privacy; - -use core_privacy\local\metadata\null_provider; - -/** - * Privacy subsystem implementation for lifecycletrigger_opencast. - * - * @package lifecycletrigger_opencast - * @copyright 2025 Thomas Niedermaier University Münster - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class provider implements null_provider { - - /** - * Get the language string identifier with the component's language - * file to explain why this plugin stores no data. - * - * @return string the reason - */ - public static function get_reason(): string { - return 'privacy:metadata'; - } -} diff --git a/trigger/opencast/lang/de/lifecycletrigger_opencast.php b/trigger/opencast/lang/de/lifecycletrigger_opencast.php deleted file mode 100644 index 41a6ab72..00000000 --- a/trigger/opencast/lang/de/lifecycletrigger_opencast.php +++ /dev/null @@ -1,37 +0,0 @@ -. - -/** - * Lang strings for opencast trigger - * - * @package lifecycletrigger_opencast - * @copyright 2025 Thomas Niedermaier University Münster - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -$string['activity'] = 'Aktivität'; -$string['activity_help'] = 'Hier geben Sie an, ob Kurse getriggert werden sollen, die mindestens eine Episode oder Serie enthalten, die über die Opencast-Aktivität eingebunden ist.'; -$string['exclude'] = 'Ausschließen'; -$string['exclude_help'] = 'Falls ausgewählt, werden Kurse mit den definierten Opencast-Videos NICHT ausgelöst.'; -$string['lti'] = 'LTI'; -$string['lti_do_not_exist'] = 'Es gibt keine LTI-Tools mit den folgenden IDs: {$a}.'; -$string['lti_help'] = 'Inkludiere Kurse, die mindestens eine Opencast Episode und/oder Serie via LTI-Tool eingebunden haben.'; -$string['lti_noselection'] = 'Bitte wählen Sie mindestens einen LTI-Typ aus.'; -$string['ltitools'] = 'LTI-Tools'; -$string['ltitools_help'] = 'Wählen Sie die LTI-Tools, welche die Episoden und/oder Serien aus Opencast zur Verfügung stellen.'; -$string['plugindescription'] = 'Selektiert alle Kurse mit mindestens einer Opencast Video-Einbindung.'; -$string['pluginname'] = 'Opencast-Trigger'; -$string['privacy:metadata'] = 'Dieses Subplugin speichert keine persönlichen Daten.'; diff --git a/trigger/opencast/lang/en/lifecycletrigger_opencast.php b/trigger/opencast/lang/en/lifecycletrigger_opencast.php deleted file mode 100644 index b45c8452..00000000 --- a/trigger/opencast/lang/en/lifecycletrigger_opencast.php +++ /dev/null @@ -1,37 +0,0 @@ -. - -/** - * Lang strings for opencast trigger - * - * @package lifecycletrigger_opencast - * @copyright 2025 Thomas Niedermaier University Münster - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -$string['activity'] = 'Activity'; -$string['activity_help'] = 'Set this option to trigger courses with at least one Opencast episode or series integrated by an Opencast activity.'; -$string['exclude'] = 'Exclude'; -$string['exclude_help'] = 'If ticked, the triggered courses are excluded from selection instead.'; -$string['lti'] = 'LTI'; -$string['lti_do_not_exist'] = 'There are no LTI Tool with the following ids: {$a}.'; -$string['lti_help'] = 'Include courses with at least one Opencast episode and/or series provided by a LTI Tool.'; -$string['lti_noselection'] = 'Please choose at least one LTI Tool.'; -$string['ltitools'] = 'LTI Tools'; -$string['ltitools_help'] = 'Select the LTI Tools which connect to Opencast to provide episodes and/or series.'; -$string['plugindescription'] = 'Selects all courses with at least one Opencast video integration.'; -$string['pluginname'] = 'Opencast Trigger'; -$string['privacy:metadata'] = 'This subplugin does not store any personal data.'; diff --git a/trigger/opencast/lib.php b/trigger/opencast/lib.php deleted file mode 100644 index d08fb154..00000000 --- a/trigger/opencast/lib.php +++ /dev/null @@ -1,219 +0,0 @@ -. - -/** - * Trigger subplugin to include or exclude courses with certain opencast videos. - * - * @package lifecycletrigger_opencast - * @copyright 2025 Thomas Niedermaier University Münster - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace tool_lifecycle\trigger; - -use tool_lifecycle\local\manager\settings_manager; -use tool_lifecycle\local\response\trigger_response; -use tool_lifecycle\settings_type; - -defined('MOODLE_INTERNAL') || die(); -require_once(__DIR__ . '/../lib.php'); -require_once(__DIR__ . '/../../lib.php'); -require_once(__DIR__ . '/../../../../../mod/lti/locallib.php'); - -/** - * Class which implements the basic methods necessary for a cleanyp courses trigger subplugin - * @package lifecycletrigger_opencast - * @copyright 2025 Thomas Niedermaier University Münster - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class opencast extends base_automatic { - - /** - * If check_course_code() returns true, code to check the given course is placed here - * @param object $course - * @param int $triggerid - * @return trigger_response - */ - public function check_course($course, $triggerid) { - return trigger_response::trigger(); - } - - /** - * Returns whether the lib function check_course contains particular selection code per course or not. - * @return bool - */ - public function check_course_code() { - return false; - } - - /** - * Return sql snippet for including (or excluding) the courses with defined opencast videos. - * @param int $triggerid Id of the trigger. - * @return array A list containing the constructed sql fragment and an array of parameters. - * @throws \coding_exception - * @throws \dml_exception - */ - public function get_course_recordset_where($triggerid) { - global $DB; - - $sql = " TRUE "; - $inparams = []; - - $exclude = false; - $activity = false; - $lti = false; - - $settings = settings_manager::get_settings($triggerid, settings_type::TRIGGER); - if (isset($settings['exclude']) && $settings['exclude'] != false) { - $exclude = true; - } - if (isset($settings['activity']) && $settings['activity'] != false) { - $activity = true; - } - if (isset($settings['lti']) && $settings['lti'] != false) { - $lti = true; - } - - $not = $exclude ? 'NOT' : ''; - if ($activity) { - $sql = " c.id $not IN (SELECT DISTINCT(course) FROM {opencast}) "; - } - if ($lti) { - $ltitools = settings_manager::get_settings($triggerid, settings_type::TRIGGER)['ltitools']; - $ltitoolsarr = explode(",", $ltitools); - [$insql, $inparams] = $DB->get_in_or_equal($ltitoolsarr, SQL_PARAMS_NAMED); - if ($sql) { - if ($exclude) { - $sql = "($sql AND c.id $not IN (SELECT DISTINCT(l.course) FROM {lti} l where - l.typeid $insql))"; - } else { - $sql = "($sql OR c.id IN (SELECT DISTINCT(l.course) FROM {lti} l where - l.typeid $insql))"; - } - } else { - $sql = "c.id $not IN (SELECT DISTINCT(l.course) FROM {lti} l where - l.typeid $insql)"; - } - } - - $where = $sql; - - return [$where, $inparams]; - } - - /** - * The return value should be equivalent with the name of the subplugin folder. - * @return string technical name of the subplugin - */ - public function get_subpluginname() { - return 'opencast'; - } - - /** - * Defines which settings each instance of the subplugin offers for the user to define. - * @return instance_setting[] containing settings keys and PARAM_TYPES - */ - public function instance_settings() { - return [ - new instance_setting('activity', PARAM_BOOL), - new instance_setting('lti', PARAM_BOOL), - new instance_setting('ltitools', PARAM_SEQUENCE), - new instance_setting('exclude', PARAM_BOOL), - ]; - } - - /** - * This method can be overriden, to add form elements to the form_trigger_instance. - * It is called in definition(). - * @param \MoodleQuickForm $mform - * @throws \coding_exception - * @throws \dml_exception - */ - public function extend_add_instance_form_definition($mform) { - - $mform->addElement('advcheckbox', 'activity', - get_string('activity', 'lifecycletrigger_opencast')); - $mform->setType('activity', PARAM_BOOL); - $mform->addHelpButton('activity', 'activity', 'lifecycletrigger_opencast'); - - $ltitypes = lti_filter_get_types(false); - $ltis = []; - foreach ($ltitypes as $key => $type) { - $ltis[$key] = $type->name." (".$type->baseurl.")"; - } - if ($ltis) { - $mform->addElement('advcheckbox', 'lti', - get_string('lti', 'lifecycletrigger_opencast')); - $mform->setType('lti', PARAM_BOOL); - $mform->addHelpButton('lti', 'lti', 'lifecycletrigger_opencast'); - $options = [ - 'multiple' => true, - 'noselectionstring' => get_string('lti_noselection', 'lifecycletrigger_opencast'), - ]; - $mform->addElement('autocomplete', 'ltitools', "", $ltis, $options); - $mform->setType('ltitools', PARAM_SEQUENCE); - - // Hide lti tools unless lti checkbox is checked. - $mform->hideIf('ltitools', 'lti', 'notchecked'); - } - - $mform->addElement('advcheckbox', 'exclude', get_string('exclude', 'lifecycletrigger_opencast')); - $mform->addHelpButton('exclude', 'exclude', 'lifecycletrigger_opencast'); - } - - /** - * Since the rendering of frozen autocomplete elements is awful, we override it here. - * @param \MoodleQuickForm $mform - * @param array $settings array containing the settings from the db. - * @throws \coding_exception - */ - public function extend_add_instance_form_definition_after_data($mform, $settings) { - $type = $mform->getElementType('instancename'); - if (($type ?? "") != "text") { - if (is_array($settings) && array_key_exists('ltitools', $settings)) { - $triggerltitools = explode(",", $settings['ltitools']); - } else { - $triggerltitools = []; - } - $types = lti_filter_get_types(get_site()->id); - $configuredtools = lti_filter_tool_types($types, LTI_TOOL_STATE_CONFIGURED); - $ltitoolshtml = ""; - foreach ($configuredtools as $key => $tool) { - if (in_array($key, $triggerltitools)) { - $ltitoolshtml .= \html_writer::div($tool->name." (".$tool->baseurl.")", "badge badge-secondary mr-1"); - } - } - $mform->insertElementBefore($mform->createElement( - 'static', - 'ltitoolsstatic', - get_string('ltitools', 'lifecycletrigger_opencast'), - $ltitoolshtml), 'buttonar'); - $mform->insertElementBefore($mform->createElement( - 'advcheckbox', - 'exclude', - get_string('exclude', 'lifecycletrigger_opencast')), - 'buttonar'); - $mform->setType('exclude', PARAM_BOOL); - } - } - - /** - * Returns the string of the specific icon for this trigger. - * @return string icon string - */ - public function get_icon() { - return 'e/insert_edit_video'; - } -} diff --git a/trigger/opencast/version.php b/trigger/opencast/version.php deleted file mode 100644 index 5828bd04..00000000 --- a/trigger/opencast/version.php +++ /dev/null @@ -1,32 +0,0 @@ -. - -/** - * Life Cycle Opencast Trigger - * - * @package lifecycletrigger_opencast - * @copyright 2025 Thomas Niedermaier University Münster - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die; - -$plugin->component = 'lifecycletrigger_opencast'; -$plugin->maturity = MATURITY_STABLE; -$plugin->version = 2026012004; -$plugin->requires = 2024100700; // Requires Moodle 4.5+. -$plugin->supported = [405, 501]; -$plugin->release = 'v5.1-r5'; diff --git a/version.php b/version.php index f577a563..d9206c80 100644 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ $plugin->component = 'tool_lifecycle'; $plugin->maturity = MATURITY_STABLE; -$plugin->version = 2026012005; +$plugin->version = 2026060102; $plugin->requires = 2024100700; // Requires Moodle 4.5+. -$plugin->supported = [405, 501]; -$plugin->release = 'v5.1-r6'; +$plugin->supported = [405, 502]; +$plugin->release = 'v5.2-r1';