From 77c542942914f1f56e5103975a41886221dd606e Mon Sep 17 00:00:00 2001 From: Thomas Niedermaier Date: Sun, 10 Nov 2024 11:34:15 +0100 Subject: [PATCH 1/6] workflow: new ci file and config.json --- .github/workflows/config.json | 11 +++++++++++ .github/workflows/config_all.json | 15 +++++++++++++++ .github/workflows/moodle-ci.yml | 22 +++++++++++----------- 3 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/config.json create mode 100644 .github/workflows/config_all.json diff --git a/.github/workflows/config.json b/.github/workflows/config.json new file mode 100644 index 0000000..e4f2bee --- /dev/null +++ b/.github/workflows/config.json @@ -0,0 +1,11 @@ +{ + "main-moodle": "MOODLE_405_STABLE", + "main-php": "8.3", + "main-oc": "16.6", + "ocs": ["16.6", "15.11"], + "main-db": "mariadb", + "moodle-php": { + "MOODLE_405_STABLE": ["8.1", "8.2"] + }, + "moodle-plugin-ci": "4.4.5" +} diff --git a/.github/workflows/config_all.json b/.github/workflows/config_all.json new file mode 100644 index 0000000..558800c --- /dev/null +++ b/.github/workflows/config_all.json @@ -0,0 +1,15 @@ +{ + "main-moodle": "MOODLE_405_STABLE", + "main-php": "8.3", + "main-oc": "16.6", + "ocs": ["16.6", "15.11"], + "main-db": "mariadb", + "moodle-php": { + "MOODLE_401_STABLE": ["7.4", "8.0", "8.1"], + "MOODLE_402_STABLE": ["8.0", "8.1", "8.2"], + "MOODLE_403_STABLE": ["8.0", "8.1", "8.2"], + "MOODLE_404_STABLE": ["8.1", "8.2", "8.3"], + "MOODLE_405_STABLE": ["8.1", "8.2", "8.3"] + }, + "moodle-plugin-ci": "4.4.5" +} diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index e50c269..9142136 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -1,11 +1,11 @@ -name: Moodle Plugin CI - -######################################################################################################################## - -on: [push, pull_request] - -######################################################################################################################## - -jobs: - call-moodle-ci-workflow: - uses: Opencast-Moodle/moodle-workflows-opencast/.github/workflows/moodle-ci.yml@master +name: Moodle Plugin CI + +######################################################################################################################## + +on: [ push, pull_request ] + +######################################################################################################################## + +jobs: + call-moodle-ci-workflow: + uses: Opencast-Moodle/moodle-workflows-opencast/.github/workflows/moodle-ci.yml@main \ No newline at end of file From 6d09dfd102463018f1e18da94eb9c134ac3c9c7a Mon Sep 17 00:00:00 2001 From: Thomas Niedermaier Date: Sun, 10 Nov 2024 11:49:22 +0100 Subject: [PATCH 2/6] code checker issues --- classes/local/api.php | 1274 +++++++++---------- classes/local/environment_util.php | 110 +- classes/local/settings_api.php | 516 ++++---- classes/settings/admin_settings_builder.php | 910 ++++++------- db/upgrade.php | 460 +++---- external.php | 654 +++++----- 6 files changed, 1962 insertions(+), 1962 deletions(-) diff --git a/classes/local/api.php b/classes/local/api.php index ef3208e..c49fccd 100644 --- a/classes/local/api.php +++ b/classes/local/api.php @@ -1,637 +1,637 @@ -. - -/** - * API for opencast - * - * @package tool_opencast - * @copyright 2018 Tobias Reischmann - * @copyright 2017 Andreas Wagner, SYNERGY LEARNING - * @author Andreas Wagner - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace tool_opencast\local; - -use local_chunkupload\local\chunkupload_file; -use tool_opencast\empty_configuration_exception; - -defined('MOODLE_INTERNAL') || die; - -require_once($CFG->dirroot . '/lib/filelib.php'); -require_once($CFG->dirroot . '/admin/tool/opencast/vendor/autoload.php'); -/** - * API for opencast - * - * @package tool_opencast - * @copyright 2018 Tobias Reischmann - * @copyright 2017 Andreas Wagner, SYNERGY LEARNING - * @author Andreas Wagner - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class api extends \curl { - - /** @var string the api username */ - private $username; - /** @var string the api password */ - private $password; - /** @var int the curl timeout in milliseconds */ - private $timeout = 2000; - /** @var int the curl connecttimeout in milliseconds */ - private $connecttimeout = 1000; - /** @var string the api baseurl */ - private $baseurl; - /** @var \OpencastApi\Opencast the opencast endpoints instance */ - public $opencastapi; - /** @var \OpencastApi\Rest\OcRestClient the opencast REST Client instance */ - public $opencastrestclient; - - /** @var array array of supported api levels */ - private static $supportedapilevel; - - /** - * Returns the sortparam string - * @param array $params - * @return string - */ - public static function get_sort_param($params) { - if (empty($params)) { - return ''; - } - - foreach ($params as $key => $sortorder) { - $sortdir = (SORT_ASC == $sortorder) ? 'ASC' : 'DESC'; - return "&sort={$key}:" . $sortdir; - } - return ''; - } - - /** - * Returns the COURSE_ACL_ROLE-prfix - * @return string - */ - public static function get_course_acl_role_prefix() { - return "ROLE_GROUP_MOODLE_COURSE_"; - } - - /** - * Returns the course ACL role for the given course - * @param int $courseid the courseid - * @return string the acl role - */ - public static function get_course_acl_role($courseid) { - return self::get_course_acl_role_prefix(). $courseid; - } - - /** - * Returns the course ACL group identifier for the given course - * @param int $courseid the courseid - * @return string the course ACL group identifier - */ - public static function get_course_acl_group_identifier($courseid) { - return "moodle_course_" . $courseid; - } - - /** - * Returns the course ACL group name for the given course - * @param int $courseid the course id - * @return string the course ACL group name - */ - public static function get_course_acl_group_name($courseid) { - return "Moodle_Course_" . $courseid; - } - - /** - * Returns the course series title prefix - * @return string the course series title prefix - */ - public static function get_courses_series_title_prefix() { - return "Course_Series_"; - } - - /** - * Returns the course series title for a given course - * @param int $courseid the courseid - * @return string the course series title - */ - public static function get_courses_series_title($courseid) { - return self::get_courses_series_title_prefix() . $courseid; - } - - /** - * Returns the real api or test api depending on the environment. - * - * @param int|null $instanceid - * Opencast instance id. - * - * @param array $settings - * @param array $customconfigs - * @param boolean $enableingest whether to enable ingest upload. - * - * @return api|api_testable - * - * @throws \dml_exception - * @throws \moodle_exception - */ - public static function get_instance($instanceid = null, - $settings = [], - $customconfigs = [], - $enableingest = false) { - - if (self::use_test_api() === true) { - $apitestable = new api_testable($instanceid, $enableingest); - return $apitestable; - } - - return new api($instanceid, $settings, $customconfigs, $enableingest); - } - - /** - * Returns, whether the test api should be used. - * - * @return bool - * @throws \dml_exception - */ - private static function use_test_api() : bool { - if (defined('BEHAT_SITE_RUNNING') && BEHAT_SITE_RUNNING) { - $defaultocinstance = settings_api::get_default_ocinstance(); - if ($defaultocinstance === null) { - return false; - } - - $defaultocinstanceapiurl = settings_api::get_apiurl($defaultocinstance->id); - if ($defaultocinstanceapiurl === false) { - return false; - } - - if ($defaultocinstanceapiurl === 'http://testapi:8080') { - return true; - } - } - - return false; - } - - /** - * Constructor of the Opencast API. - * - * @param int|null $instanceid - * Opencast instance id. - * - * @param array $settings - * Additional curl settings. - * - * @param array $customconfigs - * Custom api config. - * - * @param boolean $enableingest whether to enable ingest upload. - * - * @throws \dml_exception - * @throws \moodle_exception - */ - public function __construct($instanceid = null, - $settings = [], - $customconfigs = [], - $enableingest = false) { - // Allow access to local ips. - $settings['ignoresecurity'] = true; - parent::__construct($settings); - - $instanceid = intval($instanceid); - - // If there is no custom configs to set, we go for the stored configs. - if (empty($customconfigs)) { - $defaultocinstance = settings_api::get_default_ocinstance(); - if ($defaultocinstance === null) { - throw new \dml_exception('dmlreadexception', null, - 'No default Opencast instance is defined.'); - } - - $storedconfigocinstanceid = !$instanceid ? $defaultocinstance->id : $instanceid; - - $this->username = settings_api::get_apiusername($storedconfigocinstanceid); - $this->password = settings_api::get_apipassword($storedconfigocinstanceid); - $this->timeout = settings_api::get_apitimeout($storedconfigocinstanceid); - $this->connecttimeout = settings_api::get_apiconnecttimeout($storedconfigocinstanceid); - $this->baseurl = settings_api::get_apiurl($storedconfigocinstanceid); - - if (empty($this->username)) { - throw new empty_configuration_exception('apiusernameempty', 'tool_opencast'); - } - - if (empty($this->password)) { - throw new empty_configuration_exception('apipasswordempty', 'tool_opencast'); - } - } else { - // When user wanted to use the api class but not with the stored configs. - if (array_key_exists('apiurl', $customconfigs)) { - $this->baseurl = $customconfigs['apiurl']; - } - - if (array_key_exists('apiusername', $customconfigs)) { - $this->username = $customconfigs['apiusername']; - } - - if (array_key_exists('apipassword', $customconfigs)) { - $this->password = $customconfigs['apipassword']; - } - - if (array_key_exists('apitimeout', $customconfigs)) { - $this->timeout = $customconfigs['apitimeout']; - } - - if (array_key_exists('apiconnecttimeout', $customconfigs)) { - $this->connecttimeout = $customconfigs['apiconnecttimeout']; - } - } - - // If the admin omitted the protocol part, add the HTTPS protocol on-the-fly. - if (!preg_match('/^https?:\/\//', $this->baseurl)) { - $this->baseurl = 'https://'.$this->baseurl; - } - - // The base url is a must and cannot be empty, so we check its existence for both scenarios. - if (empty($this->baseurl)) { - throw new empty_configuration_exception('apiurlempty', 'tool_opencast'); - } - - $this->setopt([ - 'CURLOPT_TIMEOUT_MS' => $this->timeout, - 'CURLOPT_CONNECTTIMEOUT_MS' => $this->connecttimeout, ]); - - $config = [ - 'url' => $this->baseurl, - 'username' => $this->username, - 'password' => $this->password, - 'timeout' => (intval($this->timeout) / 1000), - 'connect_timeout' => (intval($this->connecttimeout) / 1000), - ]; - $this->opencastapi = new \OpencastApi\Opencast($config, [], $enableingest); - $this->opencastrestclient = new \OpencastApi\Rest\OcRestClient($config); - } - - /** - * Set curl timout in milliseconds - * @param int $timeout curl timeout in milliseconds - */ - public function set_timeout($timeout) { - $this->timeout = $timeout; - $this->setopt(['CURLOPT_TIMEOUT_MS' => $this->timeout]); - } - - /** - * Set curl connect timout in milliseconds - * @param int $connecttimeout curl connect timeout in milliseconds - */ - public function set_connecttimeout($connecttimeout) { - $this->connecttimeout = $connecttimeout; - $this->setopt(['CURLOPT_CONNECTTIMEOUT_MS' => $this->connecttimeout]); - } - - /** - * Set base url. - * @param string $baseurl - */ - public function set_baseurl($baseurl) { - $this->baseurl = $baseurl; - } - - /** - * Get http status code - * - * @return int|boolean status code or false if not available. - */ - public function get_http_code() { - - $info = $this->get_info(); - if (!isset($info['http_code'])) { - return false; - } - return $info['http_code']; - } - - /** - * Get an digest authentication header. - * @param array $runwithroles if set, the request is executed within opencast assuming the user has - * the specified roles. - * - * @return array of authentification headers - * @throws \moodle_exception - */ - private function get_authentication_header($runwithroles = []) { - - $options = ['CURLOPT_HEADER' => true]; - $this->setopt($options); - - // Restrict to Roles. - if (!empty($runwithroles)) { - $header[] = "X-RUN-WITH-ROLES: " . implode(', ', $runwithroles); - $this->setHeader($header); - } - - $basicauth = base64_encode($this->username . ":" . $this->password); - - $header = []; - - $header[] = sprintf( - 'Authorization: Basic %s', $basicauth - ); - - return $header; - } - - /** - * Do a GET call to opencast API. - * - * @param string $resource path of the resource. - * @param array $runwithroles if set, the request is executed within opencast assuming the user has - * the specified roles. - * @return string JSON String of result. - * @throws \moodle_exception - */ - public function oc_get($resource, $runwithroles = []) { - $url = $this->baseurl . $resource; - - $this->resetHeader(); - $header = $this->get_authentication_header($runwithroles); - $header[] = 'Content-Type: application/json'; - $this->setHeader($header); - $this->setopt(['CURLOPT_HEADER' => false]); - - return $this->get($url); - } - - /** - * Opencast needs a fileextension for uploaded file, so add a postname - * (which the core curl module does NOT) to curl_file. - * - * @param object|\stored_file $storedfile stored file to be uploaded. - * @param string $key key identifier within the post params array of the stored file. - * @throws \moodle_exception - */ - private function add_postname($storedfile, $key) { - - $curlfile = $this->_tmp_file_post_params[$key]; - - // Ensure that file is uploaded as a curl file (PHP 5 > 5.5.0 is needed). - if (!$curlfile instanceof \CURLFile) { - throw new \moodle_exception('needphp55orhigher', 'tool_opencast'); - } - - // Extracting filename from $file->file_record->source, make sure to have a string filename! - $source = @unserialize($storedfile->get_source()); - $filename = ''; - if (is_object($source)) { - $filename = $source->source; - } else { - // If source is not a serialised object, it is a string containing only the filename. - $filename = $storedfile->get_source(); - } - $extension = pathinfo($filename, PATHINFO_EXTENSION); - - // If extension is empty, add extension base on mimetype. - if (empty($extension)) { - $extension = mimeinfo_from_type('extension', $storedfile->get_mimetype()); - $filename .= '.' . $extension; - } - - // Check mimetype. - $mimetype = mimeinfo('type', $filename); - - $curlfile->postname = $filename; - $curlfile->mime = $mimetype; - } - - /** - * Opencast needs a fileextension for uploaded file, so add a postname - * (which the core curl module does NOT) to curl_file. - * - * @param chunkupload_file $file chunkupload file to be uploaded. - * @param string $key key identifier within the post params array of the stored file. - * @throws \moodle_exception - */ - private function add_postname_chunkupload($file, $key) { - - $curlfile = $this->_tmp_file_post_params[$key]; - - // Ensure that file is uploaded as a curl file (PHP 5 > 5.5.0 is needed). - if (!$curlfile instanceof \CURLFile) { - throw new \moodle_exception('needphp55orhigher', 'tool_opencast'); - } - - $filename = $file->get_filename(); - - $extension = pathinfo($filename, PATHINFO_EXTENSION); - - // If extension is empty, add extension base on mimetype. - if (empty($extension)) { - $mimetype = file_storage::mimetype_from_file($file->get_fullpath()); - $extension = mimeinfo_from_type('extension', $mimetype); - $filename .= '.' . $extension; - } - - // Check mimetype. - $mimetype = mimeinfo('type', $filename); - - $curlfile->postname = $filename; - $curlfile->mime = $mimetype; - } - - /** - * Do a POST call to opencast API. - * - * @param string $resource path of the resource. - * @param array $params post parameters. - * @param array $runwithroles if set, the request is executed within opencast assuming the user has - * the specified roles. - * @return string JSON String of result. - * @throws \moodle_exception - */ - public function oc_post($resource, $params = [], $runwithroles = []) { - - $url = $this->baseurl . $resource; - - $this->resetHeader(); - $header = $this->get_authentication_header($runwithroles); - $header[] = "Content-Type: multipart/form-data"; - $this->setHeader($header); - $this->setopt(['CURLOPT_HEADER' => false]); - - $options['CURLOPT_POST'] = 1; - - if (is_array($params)) { - $this->_tmp_file_post_params = []; - foreach ($params as $key => $value) { - if ($value instanceof \stored_file) { - $value->add_to_curl_request($this, $key); - $this->add_postname($value, $key); - } else if (class_exists('\local_chunkupload\local\chunkupload_file') && - $value instanceof \local_chunkupload\local\chunkupload_file) { - $value->add_to_curl_request($this, $key); - $this->add_postname_chunkupload($value, $key); - } else { - $this->_tmp_file_post_params[$key] = $value; - } - } - $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; - unset($this->_tmp_file_post_params); - } else { - // The raw post data. - $options['CURLOPT_POSTFIELDS'] = $params; - } - return $this->request($url, $options); - } - - /** - * Do a PUT call to opencast API. - * - * @param string $resource path of the resource. - * @param array $params array of parameters. - * @param array $runwithroles if set, the request is executed within opencast assuming the user has - * the specified roles. - * @return string JSON String of result. - * @throws \moodle_exception - */ - public function oc_put($resource, $params = [], $runwithroles = []) { - - $url = $this->baseurl . $resource; - - $this->resetHeader(); - $header = $this->get_authentication_header($runwithroles); - $this->setHeader($header); - $this->setopt(['CURLOPT_HEADER' => false]); - - $options['CURLOPT_CUSTOMREQUEST'] = "PUT"; - if (is_array($params)) { - $this->_tmp_file_post_params = []; - foreach ($params as $key => $value) { - $this->_tmp_file_post_params[$key] = $value; - } - $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; - unset($this->_tmp_file_post_params); - } else { - // The raw post data. - $options['CURLOPT_POSTFIELDS'] = $params; - } - - return $this->request($url, $options); - } - - /** - * Do a DELETE call to opencast API. - * - * @param string $resource path of the resource. - * @param array $params array of parameters. - * @param array $runwithroles if set, the request is executed within opencast assuming the user has - * the specified roles. - * @return string JSON String of result. - * @throws \moodle_exception - */ - public function oc_delete($resource, $params = [], $runwithroles = []) { - - $url = $this->baseurl . $resource; - - $this->resetHeader(); - $header = $this->get_authentication_header($runwithroles); - $this->setHeader($header); - $this->setopt(['CURLOPT_HEADER' => false]); - - $options['CURLOPT_CUSTOMREQUEST'] = "DELETE"; - if (is_array($params)) { - $this->_tmp_file_post_params = []; - foreach ($params as $key => $value) { - $this->_tmp_file_post_params[$key] = $value; - } - $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; - unset($this->_tmp_file_post_params); - } else { - // The raw post data. - $options['CURLOPT_POSTFIELDS'] = $params; - } - - return $this->request($url, $options); - } - - /** - * Checks if the opencast version support a certain version of the External API. - * This is necessary for the decision, which opencast endpoints are used throughout this class. - * @param string $level level to check for - * @return boolean whether the given api $level is supported. - * @throws \moodle_exception - */ - public function supports_api_level($level) { - if (!self::$supportedapilevel) { - - $response = $this->opencastapi->baseApi->getVersion(); - - if ($response['code'] != 200) { - throw new \moodle_exception('Opencast system not reachable.'); - } - $versions = $response['body']; - self::$supportedapilevel = $versions->versions; - } - return is_array(self::$supportedapilevel) && in_array($level, self::$supportedapilevel); - } - - /** - * Checks if the Opencast API URL is reachable and there is an Opencast instance running on that URL. - * - * @return int|boolean http status code, if the API URL is not reachable or an Opencast instance - * is not running on that URL, and true otherwise. - */ - public function connection_test_url() { - // The "/api" resource endpoint returns key characteristics of the API such as the server name and the default version. - $response = $this->opencastapi->baseApi->noHeader()->get(); - // If the connection fails or the Opencast instance could not be found, return the http code. - $httpcode = $response['code']; - if ($httpcode === false) { - $httpcode = 404; // Not Found. - } - if ($httpcode != 200) { - return $httpcode; - } - - return true; - } - - /** - * Checks if the Opencast API username and password is valid. - * - * @return int|boolean http status code, if the API URL is not reachable, an Opencast instance - * is not running on that URL or the credentials are invalid, and true otherwise. - */ - public function connection_test_credentials() { - // The "/api" resource endpoint returns information on the logged in user. - $response = $this->opencastapi->baseApi->getUserInfo(); - $userinfo = $response['body']; - - // If the credentials are invalid, return a corresponding http code. - if (!$userinfo) { - return 400; // Bad Request. - } - - // If the connection fails or the Opencast instance could not be found, return the http code. - $httpcode = $response['code']; - if ($httpcode === false) { - $httpcode = 404; // Not Found. - } - if ($httpcode != 200) { - return $httpcode; - } - - return true; - } -} +. + +/** + * API for opencast + * + * @package tool_opencast + * @copyright 2018 Tobias Reischmann + * @copyright 2017 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_opencast\local; + +use local_chunkupload\local\chunkupload_file; +use tool_opencast\empty_configuration_exception; + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->dirroot . '/lib/filelib.php'); +require_once($CFG->dirroot . '/admin/tool/opencast/vendor/autoload.php'); +/** + * API for opencast + * + * @package tool_opencast + * @copyright 2018 Tobias Reischmann + * @copyright 2017 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class api extends \curl { + + /** @var string the api username */ + private $username; + /** @var string the api password */ + private $password; + /** @var int the curl timeout in milliseconds */ + private $timeout = 2000; + /** @var int the curl connecttimeout in milliseconds */ + private $connecttimeout = 1000; + /** @var string the api baseurl */ + private $baseurl; + /** @var \OpencastApi\Opencast the opencast endpoints instance */ + public $opencastapi; + /** @var \OpencastApi\Rest\OcRestClient the opencast REST Client instance */ + public $opencastrestclient; + + /** @var array array of supported api levels */ + private static $supportedapilevel; + + /** + * Returns the sortparam string + * @param array $params + * @return string + */ + public static function get_sort_param($params) { + if (empty($params)) { + return ''; + } + + foreach ($params as $key => $sortorder) { + $sortdir = (SORT_ASC == $sortorder) ? 'ASC' : 'DESC'; + return "&sort={$key}:" . $sortdir; + } + return ''; + } + + /** + * Returns the COURSE_ACL_ROLE-prfix + * @return string + */ + public static function get_course_acl_role_prefix() { + return "ROLE_GROUP_MOODLE_COURSE_"; + } + + /** + * Returns the course ACL role for the given course + * @param int $courseid the courseid + * @return string the acl role + */ + public static function get_course_acl_role($courseid) { + return self::get_course_acl_role_prefix(). $courseid; + } + + /** + * Returns the course ACL group identifier for the given course + * @param int $courseid the courseid + * @return string the course ACL group identifier + */ + public static function get_course_acl_group_identifier($courseid) { + return "moodle_course_" . $courseid; + } + + /** + * Returns the course ACL group name for the given course + * @param int $courseid the course id + * @return string the course ACL group name + */ + public static function get_course_acl_group_name($courseid) { + return "Moodle_Course_" . $courseid; + } + + /** + * Returns the course series title prefix + * @return string the course series title prefix + */ + public static function get_courses_series_title_prefix() { + return "Course_Series_"; + } + + /** + * Returns the course series title for a given course + * @param int $courseid the courseid + * @return string the course series title + */ + public static function get_courses_series_title($courseid) { + return self::get_courses_series_title_prefix() . $courseid; + } + + /** + * Returns the real api or test api depending on the environment. + * + * @param int|null $instanceid + * Opencast instance id. + * + * @param array $settings + * @param array $customconfigs + * @param boolean $enableingest whether to enable ingest upload. + * + * @return api|api_testable + * + * @throws \dml_exception + * @throws \moodle_exception + */ + public static function get_instance($instanceid = null, + $settings = [], + $customconfigs = [], + $enableingest = false) { + + if (self::use_test_api() === true) { + $apitestable = new api_testable($instanceid, $enableingest); + return $apitestable; + } + + return new api($instanceid, $settings, $customconfigs, $enableingest); + } + + /** + * Returns, whether the test api should be used. + * + * @return bool + * @throws \dml_exception + */ + private static function use_test_api(): bool { + if (defined('BEHAT_SITE_RUNNING') && BEHAT_SITE_RUNNING) { + $defaultocinstance = settings_api::get_default_ocinstance(); + if ($defaultocinstance === null) { + return false; + } + + $defaultocinstanceapiurl = settings_api::get_apiurl($defaultocinstance->id); + if ($defaultocinstanceapiurl === false) { + return false; + } + + if ($defaultocinstanceapiurl === 'http://testapi:8080') { + return true; + } + } + + return false; + } + + /** + * Constructor of the Opencast API. + * + * @param int|null $instanceid + * Opencast instance id. + * + * @param array $settings + * Additional curl settings. + * + * @param array $customconfigs + * Custom api config. + * + * @param boolean $enableingest whether to enable ingest upload. + * + * @throws \dml_exception + * @throws \moodle_exception + */ + public function __construct($instanceid = null, + $settings = [], + $customconfigs = [], + $enableingest = false) { + // Allow access to local ips. + $settings['ignoresecurity'] = true; + parent::__construct($settings); + + $instanceid = intval($instanceid); + + // If there is no custom configs to set, we go for the stored configs. + if (empty($customconfigs)) { + $defaultocinstance = settings_api::get_default_ocinstance(); + if ($defaultocinstance === null) { + throw new \dml_exception('dmlreadexception', null, + 'No default Opencast instance is defined.'); + } + + $storedconfigocinstanceid = !$instanceid ? $defaultocinstance->id : $instanceid; + + $this->username = settings_api::get_apiusername($storedconfigocinstanceid); + $this->password = settings_api::get_apipassword($storedconfigocinstanceid); + $this->timeout = settings_api::get_apitimeout($storedconfigocinstanceid); + $this->connecttimeout = settings_api::get_apiconnecttimeout($storedconfigocinstanceid); + $this->baseurl = settings_api::get_apiurl($storedconfigocinstanceid); + + if (empty($this->username)) { + throw new empty_configuration_exception('apiusernameempty', 'tool_opencast'); + } + + if (empty($this->password)) { + throw new empty_configuration_exception('apipasswordempty', 'tool_opencast'); + } + } else { + // When user wanted to use the api class but not with the stored configs. + if (array_key_exists('apiurl', $customconfigs)) { + $this->baseurl = $customconfigs['apiurl']; + } + + if (array_key_exists('apiusername', $customconfigs)) { + $this->username = $customconfigs['apiusername']; + } + + if (array_key_exists('apipassword', $customconfigs)) { + $this->password = $customconfigs['apipassword']; + } + + if (array_key_exists('apitimeout', $customconfigs)) { + $this->timeout = $customconfigs['apitimeout']; + } + + if (array_key_exists('apiconnecttimeout', $customconfigs)) { + $this->connecttimeout = $customconfigs['apiconnecttimeout']; + } + } + + // If the admin omitted the protocol part, add the HTTPS protocol on-the-fly. + if (!preg_match('/^https?:\/\//', $this->baseurl)) { + $this->baseurl = 'https://'.$this->baseurl; + } + + // The base url is a must and cannot be empty, so we check its existence for both scenarios. + if (empty($this->baseurl)) { + throw new empty_configuration_exception('apiurlempty', 'tool_opencast'); + } + + $this->setopt([ + 'CURLOPT_TIMEOUT_MS' => $this->timeout, + 'CURLOPT_CONNECTTIMEOUT_MS' => $this->connecttimeout, ]); + + $config = [ + 'url' => $this->baseurl, + 'username' => $this->username, + 'password' => $this->password, + 'timeout' => (intval($this->timeout) / 1000), + 'connect_timeout' => (intval($this->connecttimeout) / 1000), + ]; + $this->opencastapi = new \OpencastApi\Opencast($config, [], $enableingest); + $this->opencastrestclient = new \OpencastApi\Rest\OcRestClient($config); + } + + /** + * Set curl timout in milliseconds + * @param int $timeout curl timeout in milliseconds + */ + public function set_timeout($timeout) { + $this->timeout = $timeout; + $this->setopt(['CURLOPT_TIMEOUT_MS' => $this->timeout]); + } + + /** + * Set curl connect timout in milliseconds + * @param int $connecttimeout curl connect timeout in milliseconds + */ + public function set_connecttimeout($connecttimeout) { + $this->connecttimeout = $connecttimeout; + $this->setopt(['CURLOPT_CONNECTTIMEOUT_MS' => $this->connecttimeout]); + } + + /** + * Set base url. + * @param string $baseurl + */ + public function set_baseurl($baseurl) { + $this->baseurl = $baseurl; + } + + /** + * Get http status code + * + * @return int|boolean status code or false if not available. + */ + public function get_http_code() { + + $info = $this->get_info(); + if (!isset($info['http_code'])) { + return false; + } + return $info['http_code']; + } + + /** + * Get an digest authentication header. + * @param array $runwithroles if set, the request is executed within opencast assuming the user has + * the specified roles. + * + * @return array of authentification headers + * @throws \moodle_exception + */ + private function get_authentication_header($runwithroles = []) { + + $options = ['CURLOPT_HEADER' => true]; + $this->setopt($options); + + // Restrict to Roles. + if (!empty($runwithroles)) { + $header[] = "X-RUN-WITH-ROLES: " . implode(', ', $runwithroles); + $this->setHeader($header); + } + + $basicauth = base64_encode($this->username . ":" . $this->password); + + $header = []; + + $header[] = sprintf( + 'Authorization: Basic %s', $basicauth + ); + + return $header; + } + + /** + * Do a GET call to opencast API. + * + * @param string $resource path of the resource. + * @param array $runwithroles if set, the request is executed within opencast assuming the user has + * the specified roles. + * @return string JSON String of result. + * @throws \moodle_exception + */ + public function oc_get($resource, $runwithroles = []) { + $url = $this->baseurl . $resource; + + $this->resetHeader(); + $header = $this->get_authentication_header($runwithroles); + $header[] = 'Content-Type: application/json'; + $this->setHeader($header); + $this->setopt(['CURLOPT_HEADER' => false]); + + return $this->get($url); + } + + /** + * Opencast needs a fileextension for uploaded file, so add a postname + * (which the core curl module does NOT) to curl_file. + * + * @param object|\stored_file $storedfile stored file to be uploaded. + * @param string $key key identifier within the post params array of the stored file. + * @throws \moodle_exception + */ + private function add_postname($storedfile, $key) { + + $curlfile = $this->_tmp_file_post_params[$key]; + + // Ensure that file is uploaded as a curl file (PHP 5 > 5.5.0 is needed). + if (!$curlfile instanceof \CURLFile) { + throw new \moodle_exception('needphp55orhigher', 'tool_opencast'); + } + + // Extracting filename from $file->file_record->source, make sure to have a string filename! + $source = @unserialize($storedfile->get_source()); + $filename = ''; + if (is_object($source)) { + $filename = $source->source; + } else { + // If source is not a serialised object, it is a string containing only the filename. + $filename = $storedfile->get_source(); + } + $extension = pathinfo($filename, PATHINFO_EXTENSION); + + // If extension is empty, add extension base on mimetype. + if (empty($extension)) { + $extension = mimeinfo_from_type('extension', $storedfile->get_mimetype()); + $filename .= '.' . $extension; + } + + // Check mimetype. + $mimetype = mimeinfo('type', $filename); + + $curlfile->postname = $filename; + $curlfile->mime = $mimetype; + } + + /** + * Opencast needs a fileextension for uploaded file, so add a postname + * (which the core curl module does NOT) to curl_file. + * + * @param chunkupload_file $file chunkupload file to be uploaded. + * @param string $key key identifier within the post params array of the stored file. + * @throws \moodle_exception + */ + private function add_postname_chunkupload($file, $key) { + + $curlfile = $this->_tmp_file_post_params[$key]; + + // Ensure that file is uploaded as a curl file (PHP 5 > 5.5.0 is needed). + if (!$curlfile instanceof \CURLFile) { + throw new \moodle_exception('needphp55orhigher', 'tool_opencast'); + } + + $filename = $file->get_filename(); + + $extension = pathinfo($filename, PATHINFO_EXTENSION); + + // If extension is empty, add extension base on mimetype. + if (empty($extension)) { + $mimetype = file_storage::mimetype_from_file($file->get_fullpath()); + $extension = mimeinfo_from_type('extension', $mimetype); + $filename .= '.' . $extension; + } + + // Check mimetype. + $mimetype = mimeinfo('type', $filename); + + $curlfile->postname = $filename; + $curlfile->mime = $mimetype; + } + + /** + * Do a POST call to opencast API. + * + * @param string $resource path of the resource. + * @param array $params post parameters. + * @param array $runwithroles if set, the request is executed within opencast assuming the user has + * the specified roles. + * @return string JSON String of result. + * @throws \moodle_exception + */ + public function oc_post($resource, $params = [], $runwithroles = []) { + + $url = $this->baseurl . $resource; + + $this->resetHeader(); + $header = $this->get_authentication_header($runwithroles); + $header[] = "Content-Type: multipart/form-data"; + $this->setHeader($header); + $this->setopt(['CURLOPT_HEADER' => false]); + + $options['CURLOPT_POST'] = 1; + + if (is_array($params)) { + $this->_tmp_file_post_params = []; + foreach ($params as $key => $value) { + if ($value instanceof \stored_file) { + $value->add_to_curl_request($this, $key); + $this->add_postname($value, $key); + } else if (class_exists('\local_chunkupload\local\chunkupload_file') && + $value instanceof \local_chunkupload\local\chunkupload_file) { + $value->add_to_curl_request($this, $key); + $this->add_postname_chunkupload($value, $key); + } else { + $this->_tmp_file_post_params[$key] = $value; + } + } + $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; + unset($this->_tmp_file_post_params); + } else { + // The raw post data. + $options['CURLOPT_POSTFIELDS'] = $params; + } + return $this->request($url, $options); + } + + /** + * Do a PUT call to opencast API. + * + * @param string $resource path of the resource. + * @param array $params array of parameters. + * @param array $runwithroles if set, the request is executed within opencast assuming the user has + * the specified roles. + * @return string JSON String of result. + * @throws \moodle_exception + */ + public function oc_put($resource, $params = [], $runwithroles = []) { + + $url = $this->baseurl . $resource; + + $this->resetHeader(); + $header = $this->get_authentication_header($runwithroles); + $this->setHeader($header); + $this->setopt(['CURLOPT_HEADER' => false]); + + $options['CURLOPT_CUSTOMREQUEST'] = "PUT"; + if (is_array($params)) { + $this->_tmp_file_post_params = []; + foreach ($params as $key => $value) { + $this->_tmp_file_post_params[$key] = $value; + } + $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; + unset($this->_tmp_file_post_params); + } else { + // The raw post data. + $options['CURLOPT_POSTFIELDS'] = $params; + } + + return $this->request($url, $options); + } + + /** + * Do a DELETE call to opencast API. + * + * @param string $resource path of the resource. + * @param array $params array of parameters. + * @param array $runwithroles if set, the request is executed within opencast assuming the user has + * the specified roles. + * @return string JSON String of result. + * @throws \moodle_exception + */ + public function oc_delete($resource, $params = [], $runwithroles = []) { + + $url = $this->baseurl . $resource; + + $this->resetHeader(); + $header = $this->get_authentication_header($runwithroles); + $this->setHeader($header); + $this->setopt(['CURLOPT_HEADER' => false]); + + $options['CURLOPT_CUSTOMREQUEST'] = "DELETE"; + if (is_array($params)) { + $this->_tmp_file_post_params = []; + foreach ($params as $key => $value) { + $this->_tmp_file_post_params[$key] = $value; + } + $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; + unset($this->_tmp_file_post_params); + } else { + // The raw post data. + $options['CURLOPT_POSTFIELDS'] = $params; + } + + return $this->request($url, $options); + } + + /** + * Checks if the opencast version support a certain version of the External API. + * This is necessary for the decision, which opencast endpoints are used throughout this class. + * @param string $level level to check for + * @return boolean whether the given api $level is supported. + * @throws \moodle_exception + */ + public function supports_api_level($level) { + if (!self::$supportedapilevel) { + + $response = $this->opencastapi->baseApi->getVersion(); + + if ($response['code'] != 200) { + throw new \moodle_exception('Opencast system not reachable.'); + } + $versions = $response['body']; + self::$supportedapilevel = $versions->versions; + } + return is_array(self::$supportedapilevel) && in_array($level, self::$supportedapilevel); + } + + /** + * Checks if the Opencast API URL is reachable and there is an Opencast instance running on that URL. + * + * @return int|boolean http status code, if the API URL is not reachable or an Opencast instance + * is not running on that URL, and true otherwise. + */ + public function connection_test_url() { + // The "/api" resource endpoint returns key characteristics of the API such as the server name and the default version. + $response = $this->opencastapi->baseApi->noHeader()->get(); + // If the connection fails or the Opencast instance could not be found, return the http code. + $httpcode = $response['code']; + if ($httpcode === false) { + $httpcode = 404; // Not Found. + } + if ($httpcode != 200) { + return $httpcode; + } + + return true; + } + + /** + * Checks if the Opencast API username and password is valid. + * + * @return int|boolean http status code, if the API URL is not reachable, an Opencast instance + * is not running on that URL or the credentials are invalid, and true otherwise. + */ + public function connection_test_credentials() { + // The "/api" resource endpoint returns information on the logged in user. + $response = $this->opencastapi->baseApi->getUserInfo(); + $userinfo = $response['body']; + + // If the credentials are invalid, return a corresponding http code. + if (!$userinfo) { + return 400; // Bad Request. + } + + // If the connection fails or the Opencast instance could not be found, return the http code. + $httpcode = $response['code']; + if ($httpcode === false) { + $httpcode = 404; // Not Found. + } + if ($httpcode != 200) { + return $httpcode; + } + + return true; + } +} diff --git a/classes/local/environment_util.php b/classes/local/environment_util.php index 4087e0d..a656544 100644 --- a/classes/local/environment_util.php +++ b/classes/local/environment_util.php @@ -1,55 +1,55 @@ -. - -namespace tool_opencast\local; - -defined('MOODLE_INTERNAL') || die; - -/** - * An environment util for the Opencast Moodle plugins. - * - * @package tool_opencast - * @copyright 2023 Matthias Kollenbroich, University of Münster - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class environment_util { - /** - * Make this class not instantiable. - */ - private function __construct() { - } - - /** - * Returns, whether the current application is a CLI application. - * - * @return bool Returns, true, if the current application is a CLI application, - * and false otherwise. - */ - public static function is_cli_application() : bool { - return http_response_code() === false; - } - - /** - * Returns, whether the current application runs in the environment of a moodle-plugin-ci workflow, - * namely, returns, whether the environment variable is_moodle_plugin_ci_workflow is defined. - * - * @return bool Returns, true, if the current application runs in the environment of a moodle-plugin-ci workflow, - * and false otherwise. - */ - public static function is_moodle_plugin_ci_workflow() : bool { - return !(getenv('is_moodle_plugin_ci_workflow') === false); - } -} +. + +namespace tool_opencast\local; + +defined('MOODLE_INTERNAL') || die; + +/** + * An environment util for the Opencast Moodle plugins. + * + * @package tool_opencast + * @copyright 2023 Matthias Kollenbroich, University of Münster + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class environment_util { + /** + * Make this class not instantiable. + */ + private function __construct() { + } + + /** + * Returns, whether the current application is a CLI application. + * + * @return bool Returns, true, if the current application is a CLI application, + * and false otherwise. + */ + public static function is_cli_application(): bool { + return http_response_code() === false; + } + + /** + * Returns, whether the current application runs in the environment of a moodle-plugin-ci workflow, + * namely, returns, whether the environment variable is_moodle_plugin_ci_workflow is defined. + * + * @return bool Returns, true, if the current application runs in the environment of a moodle-plugin-ci workflow, + * and false otherwise. + */ + public static function is_moodle_plugin_ci_workflow(): bool { + return !(getenv('is_moodle_plugin_ci_workflow') === false); + } +} diff --git a/classes/local/settings_api.php b/classes/local/settings_api.php index 5b0ba39..9559e78 100644 --- a/classes/local/settings_api.php +++ b/classes/local/settings_api.php @@ -1,258 +1,258 @@ -. - -namespace tool_opencast\local; - -defined('MOODLE_INTERNAL') || die; - -require_once($CFG->dirroot . '/lib/filelib.php'); - -/** - * Settings API for opencast. - * - * This static class is used by the Opencast plugins, to fetch information about the settings of - * the defined Opencast instances as well as of the plugin tool_opencast itself. - * An Opencast instance is defined and configured with the admin settings of tool_opencast. - * - * @package tool_opencast - * @copyright 2022 Matthias Kollenbroich, University of Münster - * @copyright 2021 Tamara Gunkel - * @copyright 2018 Tobias Reischmann - * @copyright 2017 Andreas Wagner, SYNERGY LEARNING - * @author Andreas Wagner - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class settings_api { - - /** - * Make this class not instantiable. - */ - private function __construct() { - } - - /** - * Returns the version of the plugin tool_opencast as string - * or false, if the corresponding config was not found. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_plugin_version() { - return get_config('tool_opencast', 'version'); - } - - /** - * Returns the api url of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_apiurl(int $ocinstanceid) { - return get_config('tool_opencast', 'apiurl_' . $ocinstanceid); - } - - /** - * Returns the api username of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_apiusername(int $ocinstanceid) { - return get_config('tool_opencast', 'apiusername_' . $ocinstanceid); - } - - /** - * Returns the api password of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_apipassword(int $ocinstanceid) { - return get_config('tool_opencast', 'apipassword_' . $ocinstanceid); - } - - /** - * Returns the api timeout of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_apitimeout(int $ocinstanceid) { - return get_config('tool_opencast', 'apitimeout_' . $ocinstanceid); - } - - /** - * Returns the api connecttimeout of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_apiconnecttimeout(int $ocinstanceid) { - return get_config('tool_opencast', 'apiconnecttimeout_' . $ocinstanceid); - } - - /** - * Returns the lticonsumerkey of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_lticonsumerkey(int $ocinstanceid) { - return get_config('tool_opencast', 'lticonsumerkey_' . $ocinstanceid); - } - - /** - * Returns the lticonsumersecret of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_lticonsumersecret(int $ocinstanceid) { - return get_config('tool_opencast', 'lticonsumersecret_' . $ocinstanceid); - } - - /** - * Return the Opencast instance for the passed Opencast instance id, if any. - * If no Opencast instance with this id is configured, null is returned. - * - * @param int $ocinstanceid - * The id of the requested Opencast instance. - * - * @return opencast_instance|null - * The corresponding Opencast instance or null. - */ - public static function get_ocinstance(int $ocinstanceid) : ?opencast_instance { - $ocinstances = self::get_ocinstances(); - - foreach ($ocinstances as $ocinstance) { - if (intval($ocinstance->id) === intval($ocinstanceid)) { - return $ocinstance; - } - } - - return null; - } - - /** - * Returns the default Opencast instance, if any. - * If no default Opencast instance is configured, null is returned. - * - * @return opencast_instance|null - * The corresponding Opencast instance or null. - */ - public static function get_default_ocinstance() : ?opencast_instance { - $ocinstances = self::get_ocinstances(); - - foreach ($ocinstances as $ocinstance) { - if (boolval($ocinstance->isdefault) === true) { - return $ocinstance; - } - } - - return null; - } - - /** - * Returns all configured Opencast instances as array. - * - * This array contains instances of the class opencast_instance only. - * - * @return array - * All configured Opencast instances as array. - */ - public static function get_ocinstances() : array { - try { - $ocinstancesconfig = get_config('tool_opencast', 'ocinstances'); - } catch (\dml_exception $exception) { - return []; - } - - $dynamicocinstances = json_decode($ocinstancesconfig); - - $ocinstances = []; - foreach ($dynamicocinstances as $dynamicocinstance) { - $ocinstances[] = new opencast_instance($dynamicocinstance); - } - - return $ocinstances; - } - - /** - * Sets all configured Opencast instances to the passed Opencast instance, - * namely, the passed Opencast instance will be the only configured Opencast instance - * afterwards. - * - * @param \stdClass $dynamicocinstance - * The Opencast instance, to that all configured Opencast instances are set to. - */ - public static function set_ocinstances_to_ocinstance($dynamicocinstance) : void { - set_config('ocinstances', json_encode([$dynamicocinstance]), 'tool_opencast'); - } - - /** - * Returns the number of configured Opencast instances. - * - * @return int - * The number of configured Opencast instances. - */ - public static function num_ocinstances() : int { - return count(self::get_ocinstances()); - } -} +. + +namespace tool_opencast\local; + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->dirroot . '/lib/filelib.php'); + +/** + * Settings API for opencast. + * + * This static class is used by the Opencast plugins, to fetch information about the settings of + * the defined Opencast instances as well as of the plugin tool_opencast itself. + * An Opencast instance is defined and configured with the admin settings of tool_opencast. + * + * @package tool_opencast + * @copyright 2022 Matthias Kollenbroich, University of Münster + * @copyright 2021 Tamara Gunkel + * @copyright 2018 Tobias Reischmann + * @copyright 2017 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class settings_api { + + /** + * Make this class not instantiable. + */ + private function __construct() { + } + + /** + * Returns the version of the plugin tool_opencast as string + * or false, if the corresponding config was not found. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_plugin_version() { + return get_config('tool_opencast', 'version'); + } + + /** + * Returns the api url of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_apiurl(int $ocinstanceid) { + return get_config('tool_opencast', 'apiurl_' . $ocinstanceid); + } + + /** + * Returns the api username of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_apiusername(int $ocinstanceid) { + return get_config('tool_opencast', 'apiusername_' . $ocinstanceid); + } + + /** + * Returns the api password of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_apipassword(int $ocinstanceid) { + return get_config('tool_opencast', 'apipassword_' . $ocinstanceid); + } + + /** + * Returns the api timeout of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_apitimeout(int $ocinstanceid) { + return get_config('tool_opencast', 'apitimeout_' . $ocinstanceid); + } + + /** + * Returns the api connecttimeout of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_apiconnecttimeout(int $ocinstanceid) { + return get_config('tool_opencast', 'apiconnecttimeout_' . $ocinstanceid); + } + + /** + * Returns the lticonsumerkey of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_lticonsumerkey(int $ocinstanceid) { + return get_config('tool_opencast', 'lticonsumerkey_' . $ocinstanceid); + } + + /** + * Returns the lticonsumersecret of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_lticonsumersecret(int $ocinstanceid) { + return get_config('tool_opencast', 'lticonsumersecret_' . $ocinstanceid); + } + + /** + * Return the Opencast instance for the passed Opencast instance id, if any. + * If no Opencast instance with this id is configured, null is returned. + * + * @param int $ocinstanceid + * The id of the requested Opencast instance. + * + * @return opencast_instance|null + * The corresponding Opencast instance or null. + */ + public static function get_ocinstance(int $ocinstanceid): ?opencast_instance { + $ocinstances = self::get_ocinstances(); + + foreach ($ocinstances as $ocinstance) { + if (intval($ocinstance->id) === intval($ocinstanceid)) { + return $ocinstance; + } + } + + return null; + } + + /** + * Returns the default Opencast instance, if any. + * If no default Opencast instance is configured, null is returned. + * + * @return opencast_instance|null + * The corresponding Opencast instance or null. + */ + public static function get_default_ocinstance(): ?opencast_instance { + $ocinstances = self::get_ocinstances(); + + foreach ($ocinstances as $ocinstance) { + if (boolval($ocinstance->isdefault) === true) { + return $ocinstance; + } + } + + return null; + } + + /** + * Returns all configured Opencast instances as array. + * + * This array contains instances of the class opencast_instance only. + * + * @return array + * All configured Opencast instances as array. + */ + public static function get_ocinstances(): array { + try { + $ocinstancesconfig = get_config('tool_opencast', 'ocinstances'); + } catch (\dml_exception $exception) { + return []; + } + + $dynamicocinstances = json_decode($ocinstancesconfig); + + $ocinstances = []; + foreach ($dynamicocinstances as $dynamicocinstance) { + $ocinstances[] = new opencast_instance($dynamicocinstance); + } + + return $ocinstances; + } + + /** + * Sets all configured Opencast instances to the passed Opencast instance, + * namely, the passed Opencast instance will be the only configured Opencast instance + * afterwards. + * + * @param \stdClass $dynamicocinstance + * The Opencast instance, to that all configured Opencast instances are set to. + */ + public static function set_ocinstances_to_ocinstance($dynamicocinstance): void { + set_config('ocinstances', json_encode([$dynamicocinstance]), 'tool_opencast'); + } + + /** + * Returns the number of configured Opencast instances. + * + * @return int + * The number of configured Opencast instances. + */ + public static function num_ocinstances(): int { + return count(self::get_ocinstances()); + } +} diff --git a/classes/settings/admin_settings_builder.php b/classes/settings/admin_settings_builder.php index a35f56e..6f1a5ff 100644 --- a/classes/settings/admin_settings_builder.php +++ b/classes/settings/admin_settings_builder.php @@ -1,455 +1,455 @@ -. - -namespace tool_opencast\settings; - -use tool_opencast\local\settings_api; - -/** - * Static admin setting builder class, which is used, to create and to add admin settings for tool_opencast. - * - * @package tool_opencast - * @copyright 2022 Matthias Kollenbroich, University of Münster - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class admin_settings_builder { - /** - * The name of the plugin tool_opencast. - * - * @var string - */ - private const PLUGINNAME = 'tool_opencast'; - - /** - * The default Opencast instances config. - * - * @var string - */ - private const DEFAULTINSTANCESCONFIG = '[{"id":1,"name":"Default","isvisible":true,"isdefault":true}]'; - - /** - * Make this class not instantiable. - */ - private function __construct() { - } - - /** - * Creates the settings for all Opencast instances and adds them to the admin settings page. - * - * @return void - */ - public static function create_settings() : void { - $instances = settings_api::get_ocinstances(); - - global $ADMIN; - if (!$ADMIN->fulltree) { - self::create_settings_no_fulltree($instances); - return; - } - - self::create_settings_fulltree($instances); - } - - /** - * Creates the settings for all Opencast instances for no fulltree and adds them to the admin settings page. - * - * @param array $instances - * The Opencast instances. - * - * @return void - */ - private static function create_settings_no_fulltree($instances) : void { - self::add_admin_category(); - self::add_admin_settingpage('tool_opencast_instances', 'ocinstances'); - - if (count($instances) <= 1) { - self::add_admin_settingpage('tool_opencast_configuration', 'configuration'); - return; - } - - foreach ($instances as $instance) { - self::add_admin_settingpage('tool_opencast_configuration_' . $instance->id, - 'configuration_instance', $instance->name); - } - } - - /** - * Creates the settings for all Opencast instances for fulltree and adds them to the admin settings page. - * - * @param array $instances - * The Opencast instances. - * - * @return void - */ - private static function create_settings_fulltree($instances) : void { - self::add_admin_category(); - self::add_admin_instances_config(); - - foreach ($instances as $instance) { - $instanceid = $instance->id; - - if (count($instances) <= 1) { - $settings = self::create_admin_settingpage('tool_opencast_configuration', - 'configuration'); - } else { - $settings = self::create_admin_settingpage('tool_opencast_configuration_' . $instanceid, - 'configuration_instance', $instance->name); - } - - self::add_notification_banner_for_demo_instance($settings, $instanceid); - self::add_config_settings_fulltree($settings, $instanceid); - self::add_connection_test_tool($settings, $instanceid); - - self::include_admin_settingpage($settings); - } - } - - /** - * Adds an admin category to the admin settings page. - * - * @return void - */ - private static function add_admin_category() : void { - $category = new \admin_category(self::PLUGINNAME, - new \lang_string('pluginname', self::PLUGINNAME) - ); - - global $ADMIN; - $ADMIN->add('tools', $category); - } - - /** - * Adds an admin settingpage to the admin settings page. - * - * @param string $name - * The internal name for this settingpage. - * - * @param string $stringidentifier - * The identifier for the string, that is used for the displayed name for this settingpage. - * - * @param stdClass|array $stringidentifierarguments - * Optional arguments, which the string for the passed identifier requires, - * that is used for the displayed name for this settingpage. - * - * @return void - */ - private static function add_admin_settingpage(string $name, string $stringidentifier, - $stringidentifierarguments = null) : void { - $settingpage = self::create_admin_settingpage($name, $stringidentifier, $stringidentifierarguments); - self::include_admin_settingpage($settingpage); - } - - /** - * Creates an admin settingpage. - * - * @param string $name - * The internal name for this settingpage. - * - * @param string $stringidentifier - * The identifier for the string, that is used for the displayed name for this settingpage. - * - * @param stdClass|array $stringidentifierarguments - * Optional arguments, which the string for the passed identifier requires, - * that is used for the displayed name for this settingpage. - * - * @return \admin_settingpage - * The created admin settingpage. - */ - private static function create_admin_settingpage(string $name, string $stringidentifier, - $stringidentifierarguments = null) : \admin_settingpage { - return new \admin_settingpage($name, - new \lang_string($stringidentifier, self::PLUGINNAME, $stringidentifierarguments) - ); - } - - /** - * Includes an admin settingpage in the admin settings page. - * - * @param \admin_settingpage $settingpage - * The admin settingpage to include. - * - * @return void - */ - private static function include_admin_settingpage(\admin_settingpage $settingpage) : void { - global $ADMIN; - $ADMIN->add(self::PLUGINNAME, $settingpage); - } - - /** - * Adds the admin instances config to the admin settings page. - * - * The admin instances config is part of the admin settings and - * consists of the table with its description of added Opencast instances as well as - * of the button for adding a new Opencast instance. - * - * Note, that this function calls self::require_amds with the id of the added admin instances config. - * - * @return void - */ - private static function add_admin_instances_config() : void { - $instancesconfig = new admin_setting_configtextwithvalidation( - 'tool_opencast/ocinstances', - get_string('ocinstances', self::PLUGINNAME), - get_string('ocinstancesdesc', self::PLUGINNAME), - self::DEFAULTINSTANCESCONFIG - ); - - self::require_amds($instancesconfig->get_id()); - - $instancessettings = new \admin_settingpage( - 'tool_opencast_instances', - new \lang_string('ocinstances', self::PLUGINNAME) - ); - - $instancessettings->add($instancesconfig); - - $instancessettings->add(new admin_setting_configeditabletable( - 'tool_opencast/instancestable', - 'instancestable') - ); - - global $ADMIN; - $ADMIN->add(self::PLUGINNAME, $instancessettings); - } - - /** - * Requires jquery, amds and css for $PAGE. - * - * @param string $pluginnameid - * The id of the admin instances config of the admin settings of the plugin. - * - * @return void - */ - private static function require_amds(string $pluginnameid) : void { - global $PAGE; - - // Crashes, if plugins.php is opened, because css cannot be included anymore. - if ($PAGE->state === \moodle_page::STATE_IN_BODY) { - return; - } - - $PAGE->requires->jquery(); - $PAGE->requires->js_call_amd('tool_opencast/tool_testtool', 'init'); - $PAGE->requires->js_call_amd('tool_opencast/tool_settings', 'init', [$pluginnameid]); - $PAGE->requires->css('/admin/tool/opencast/css/tabulator.min.css'); - $PAGE->requires->css('/admin/tool/opencast/css/tabulator_bootstrap4.min.css'); - } - - /** - * Adds a notification banner to the passed admin settingpage for the passed Opencast instance id, - * if the plugin is connected to the Opencast demo server for this Opencast instance id. - * - * @param \admin_settingpage $settings - * The admin settingpage, to add a notification banner to. - * - * @param int $instanceid - * The id of the Opencast instance, for which the notification banner is added. - * - * @return void - */ - private static function add_notification_banner_for_demo_instance(\admin_settingpage $settings, - int $instanceid) : void { - $instanceapiurl = settings_api::get_apiurl($instanceid); - - // Show a notification banner, if the plugin is connected to the Opencast demo server. - if (strpos($instanceapiurl, 'stable.opencast.org') !== false) { - global $OUTPUT; - $demoservernotification = $OUTPUT->notification( - get_string('demoservernotification', self::PLUGINNAME), - \core\output\notification::NOTIFY_WARNING - ); - - $settings->add(new \admin_setting_heading( - 'tool_opencast/demoservernotification_' . $instanceid, - '', - $demoservernotification) - ); - } - } - - /** - * Adds the config settings for fulltree to the passed admin settingpage for the - * passed Opencast instance id. - * - * @param \admin_settingpage $settings - * The admin settingpage, the config settings are added to. - * - * @param int $instanceid - * The Opencast instance id, to that the added settings are associated. - * - * @return void - */ - private static function add_config_settings_fulltree(\admin_settingpage $settings, - int $instanceid) : void { - self::add_admin_setting_configtext($settings, - 'tool_opencast/apiurl_' . $instanceid, - 'apiurl', 'apiurldesc', - 'https://stable.opencast.org', - PARAM_URL - ); - - self::add_admin_setting_configtext($settings, - 'tool_opencast/apiusername_' . $instanceid, - 'apiusername', 'apiusernamedesc', - 'admin' - ); - - self::add_admin_setting_configpasswordunmask($settings, - 'tool_opencast/apipassword_' . $instanceid, - 'apipassword', 'apipassworddesc', - 'opencast' - ); - - self::add_admin_setting_configtext($settings, - 'tool_opencast/lticonsumerkey_' . $instanceid, - 'lticonsumerkey', 'lticonsumerkey_desc', - '' - ); - - self::add_admin_setting_configpasswordunmask($settings, - 'tool_opencast/lticonsumersecret_' . $instanceid, - 'lticonsumersecret', 'lticonsumersecret_desc', - '' - ); - - self::add_admin_setting_configtext($settings, - 'tool_opencast/apitimeout_' . $instanceid, - 'timeout', 'timeoutdesc', - '2000', - PARAM_INT - ); - - self::add_admin_setting_configtext($settings, - 'tool_opencast/apiconnecttimeout_' . $instanceid, - 'connecttimeout', 'connecttimeoutdesc', - '1000', - PARAM_INT - ); - } - - /** - * Adds an admin setting configtext to the passed admin settingpage. - * - * @param \admin_settingpage $settings - * The admin settingpage, the configtext is added to. - * - * @param string $name - * The internal name for the configtext. - * - * @param string $visiblenameidentifier - * The identifier for the string, that is used for the visible name of the configtext. - * - * @param string $descriptionidentifier - * The identifier for the string, that is used for the visible description of the configtext. - * - * @param string $defaultsetting - * The default setting for the configtext. - * - * @param mixed $paramtype - * The parameter type of the configtext. - * - * @return void - */ - private static function add_admin_setting_configtext(\admin_settingpage $settings, - string $name, - string $visiblenameidentifier, - string $descriptionidentifier, - string $defaultsetting, - $paramtype = PARAM_RAW) : void { - $settingconfigtext = new \admin_setting_configtext( - $name, - get_string($visiblenameidentifier, self::PLUGINNAME), - get_string($descriptionidentifier, self::PLUGINNAME), - $defaultsetting, - $paramtype - ); - $settings->add($settingconfigtext); - } - - /** - * Adds an admin setting configpasswordunmask to the passed admin settingpage. - * - * @param \admin_settingpage $settings - * The admin settingpage, the configpasswordunmask is added to. - * - * @param string $name - * The internal name for the configpasswordunmask. - * - * @param string $visiblenameidentifier - * The identifier for the string, that is used for the visible name of the configpasswordunmask. - * - * @param string $descriptionidentifier - * The identifier for the string, that is used for the visible description of the configpasswordunmask. - * - * @param string $defaultsetting - * The default password for the configpasswordunmask. - * - * @return void - */ - private static function add_admin_setting_configpasswordunmask(\admin_settingpage $settings, - string $name, - string $visiblenameidentifier, - string $descriptionidentifier, - string $defaultsetting) : void { - $settingconfigpasswordunmask = new \admin_setting_configpasswordunmask( - $name, - get_string($visiblenameidentifier, self::PLUGINNAME), - get_string($descriptionidentifier, self::PLUGINNAME), - $defaultsetting - ); - $settings->add($settingconfigpasswordunmask); - } - - /** - * Adds the connection test tool to the passed admin settingpage for the passed Opencast instance id, - * where a button with its description is added to the passed admin settingpage, - * that can be clicked, to perform this connection test to the corresponding Opencast instance. - * - * A popup is shown, containing the results of this connection test, if this connection test is completed. - * - * @param \admin_settingpage $settings - * The admin settingpage, to add the connection test tool to. - * - * @param int $instanceid - * The id of the Opencast instance, for which the connection test tool is added and the connection test - * is performed. - * - * @return void - */ - private static function add_connection_test_tool(\admin_settingpage $settings, - int $instanceid) : void { - // Provide Connection Test Tool button. - $attributes = [ - 'class' => 'btn btn-warning disabled testtool-modal', - 'disabled' => 'disabled', - 'title' => get_string('testtooldisabledbuttontitle', self::PLUGINNAME), - 'data-instanceid' => strval($instanceid), - ]; - - $connectiontoolbutton = \html_writer::tag( - 'button', - get_string('testtoolurl', self::PLUGINNAME), - $attributes - ); - - // Place the button inside the header description. - $settings->add(new \admin_setting_heading( - 'tool_opencast/testtoolexternalpage', - get_string('testtoolheader', self::PLUGINNAME), - get_string('testtoolheaderdesc', self::PLUGINNAME, $connectiontoolbutton)) - ); - } -} +. + +namespace tool_opencast\settings; + +use tool_opencast\local\settings_api; + +/** + * Static admin setting builder class, which is used, to create and to add admin settings for tool_opencast. + * + * @package tool_opencast + * @copyright 2022 Matthias Kollenbroich, University of Münster + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class admin_settings_builder { + /** + * The name of the plugin tool_opencast. + * + * @var string + */ + private const PLUGINNAME = 'tool_opencast'; + + /** + * The default Opencast instances config. + * + * @var string + */ + private const DEFAULTINSTANCESCONFIG = '[{"id":1,"name":"Default","isvisible":true,"isdefault":true}]'; + + /** + * Make this class not instantiable. + */ + private function __construct() { + } + + /** + * Creates the settings for all Opencast instances and adds them to the admin settings page. + * + * @return void + */ + public static function create_settings(): void { + $instances = settings_api::get_ocinstances(); + + global $ADMIN; + if (!$ADMIN->fulltree) { + self::create_settings_no_fulltree($instances); + return; + } + + self::create_settings_fulltree($instances); + } + + /** + * Creates the settings for all Opencast instances for no fulltree and adds them to the admin settings page. + * + * @param array $instances + * The Opencast instances. + * + * @return void + */ + private static function create_settings_no_fulltree($instances): void { + self::add_admin_category(); + self::add_admin_settingpage('tool_opencast_instances', 'ocinstances'); + + if (count($instances) <= 1) { + self::add_admin_settingpage('tool_opencast_configuration', 'configuration'); + return; + } + + foreach ($instances as $instance) { + self::add_admin_settingpage('tool_opencast_configuration_' . $instance->id, + 'configuration_instance', $instance->name); + } + } + + /** + * Creates the settings for all Opencast instances for fulltree and adds them to the admin settings page. + * + * @param array $instances + * The Opencast instances. + * + * @return void + */ + private static function create_settings_fulltree($instances): void { + self::add_admin_category(); + self::add_admin_instances_config(); + + foreach ($instances as $instance) { + $instanceid = $instance->id; + + if (count($instances) <= 1) { + $settings = self::create_admin_settingpage('tool_opencast_configuration', + 'configuration'); + } else { + $settings = self::create_admin_settingpage('tool_opencast_configuration_' . $instanceid, + 'configuration_instance', $instance->name); + } + + self::add_notification_banner_for_demo_instance($settings, $instanceid); + self::add_config_settings_fulltree($settings, $instanceid); + self::add_connection_test_tool($settings, $instanceid); + + self::include_admin_settingpage($settings); + } + } + + /** + * Adds an admin category to the admin settings page. + * + * @return void + */ + private static function add_admin_category(): void { + $category = new \admin_category(self::PLUGINNAME, + new \lang_string('pluginname', self::PLUGINNAME) + ); + + global $ADMIN; + $ADMIN->add('tools', $category); + } + + /** + * Adds an admin settingpage to the admin settings page. + * + * @param string $name + * The internal name for this settingpage. + * + * @param string $stringidentifier + * The identifier for the string, that is used for the displayed name for this settingpage. + * + * @param stdClass|array $stringidentifierarguments + * Optional arguments, which the string for the passed identifier requires, + * that is used for the displayed name for this settingpage. + * + * @return void + */ + private static function add_admin_settingpage(string $name, string $stringidentifier, + $stringidentifierarguments = null): void { + $settingpage = self::create_admin_settingpage($name, $stringidentifier, $stringidentifierarguments); + self::include_admin_settingpage($settingpage); + } + + /** + * Creates an admin settingpage. + * + * @param string $name + * The internal name for this settingpage. + * + * @param string $stringidentifier + * The identifier for the string, that is used for the displayed name for this settingpage. + * + * @param stdClass|array $stringidentifierarguments + * Optional arguments, which the string for the passed identifier requires, + * that is used for the displayed name for this settingpage. + * + * @return \admin_settingpage + * The created admin settingpage. + */ + private static function create_admin_settingpage(string $name, string $stringidentifier, + $stringidentifierarguments = null): \admin_settingpage { + return new \admin_settingpage($name, + new \lang_string($stringidentifier, self::PLUGINNAME, $stringidentifierarguments) + ); + } + + /** + * Includes an admin settingpage in the admin settings page. + * + * @param \admin_settingpage $settingpage + * The admin settingpage to include. + * + * @return void + */ + private static function include_admin_settingpage(\admin_settingpage $settingpage): void { + global $ADMIN; + $ADMIN->add(self::PLUGINNAME, $settingpage); + } + + /** + * Adds the admin instances config to the admin settings page. + * + * The admin instances config is part of the admin settings and + * consists of the table with its description of added Opencast instances as well as + * of the button for adding a new Opencast instance. + * + * Note, that this function calls self::require_amds with the id of the added admin instances config. + * + * @return void + */ + private static function add_admin_instances_config(): void { + $instancesconfig = new admin_setting_configtextwithvalidation( + 'tool_opencast/ocinstances', + get_string('ocinstances', self::PLUGINNAME), + get_string('ocinstancesdesc', self::PLUGINNAME), + self::DEFAULTINSTANCESCONFIG + ); + + self::require_amds($instancesconfig->get_id()); + + $instancessettings = new \admin_settingpage( + 'tool_opencast_instances', + new \lang_string('ocinstances', self::PLUGINNAME) + ); + + $instancessettings->add($instancesconfig); + + $instancessettings->add(new admin_setting_configeditabletable( + 'tool_opencast/instancestable', + 'instancestable') + ); + + global $ADMIN; + $ADMIN->add(self::PLUGINNAME, $instancessettings); + } + + /** + * Requires jquery, amds and css for $PAGE. + * + * @param string $pluginnameid + * The id of the admin instances config of the admin settings of the plugin. + * + * @return void + */ + private static function require_amds(string $pluginnameid): void { + global $PAGE; + + // Crashes, if plugins.php is opened, because css cannot be included anymore. + if ($PAGE->state === \moodle_page::STATE_IN_BODY) { + return; + } + + $PAGE->requires->jquery(); + $PAGE->requires->js_call_amd('tool_opencast/tool_testtool', 'init'); + $PAGE->requires->js_call_amd('tool_opencast/tool_settings', 'init', [$pluginnameid]); + $PAGE->requires->css('/admin/tool/opencast/css/tabulator.min.css'); + $PAGE->requires->css('/admin/tool/opencast/css/tabulator_bootstrap4.min.css'); + } + + /** + * Adds a notification banner to the passed admin settingpage for the passed Opencast instance id, + * if the plugin is connected to the Opencast demo server for this Opencast instance id. + * + * @param \admin_settingpage $settings + * The admin settingpage, to add a notification banner to. + * + * @param int $instanceid + * The id of the Opencast instance, for which the notification banner is added. + * + * @return void + */ + private static function add_notification_banner_for_demo_instance(\admin_settingpage $settings, + int $instanceid): void { + $instanceapiurl = settings_api::get_apiurl($instanceid); + + // Show a notification banner, if the plugin is connected to the Opencast demo server. + if (strpos($instanceapiurl, 'stable.opencast.org') !== false) { + global $OUTPUT; + $demoservernotification = $OUTPUT->notification( + get_string('demoservernotification', self::PLUGINNAME), + \core\output\notification::NOTIFY_WARNING + ); + + $settings->add(new \admin_setting_heading( + 'tool_opencast/demoservernotification_' . $instanceid, + '', + $demoservernotification) + ); + } + } + + /** + * Adds the config settings for fulltree to the passed admin settingpage for the + * passed Opencast instance id. + * + * @param \admin_settingpage $settings + * The admin settingpage, the config settings are added to. + * + * @param int $instanceid + * The Opencast instance id, to that the added settings are associated. + * + * @return void + */ + private static function add_config_settings_fulltree(\admin_settingpage $settings, + int $instanceid): void { + self::add_admin_setting_configtext($settings, + 'tool_opencast/apiurl_' . $instanceid, + 'apiurl', 'apiurldesc', + 'https://stable.opencast.org', + PARAM_URL + ); + + self::add_admin_setting_configtext($settings, + 'tool_opencast/apiusername_' . $instanceid, + 'apiusername', 'apiusernamedesc', + 'admin' + ); + + self::add_admin_setting_configpasswordunmask($settings, + 'tool_opencast/apipassword_' . $instanceid, + 'apipassword', 'apipassworddesc', + 'opencast' + ); + + self::add_admin_setting_configtext($settings, + 'tool_opencast/lticonsumerkey_' . $instanceid, + 'lticonsumerkey', 'lticonsumerkey_desc', + '' + ); + + self::add_admin_setting_configpasswordunmask($settings, + 'tool_opencast/lticonsumersecret_' . $instanceid, + 'lticonsumersecret', 'lticonsumersecret_desc', + '' + ); + + self::add_admin_setting_configtext($settings, + 'tool_opencast/apitimeout_' . $instanceid, + 'timeout', 'timeoutdesc', + '2000', + PARAM_INT + ); + + self::add_admin_setting_configtext($settings, + 'tool_opencast/apiconnecttimeout_' . $instanceid, + 'connecttimeout', 'connecttimeoutdesc', + '1000', + PARAM_INT + ); + } + + /** + * Adds an admin setting configtext to the passed admin settingpage. + * + * @param \admin_settingpage $settings + * The admin settingpage, the configtext is added to. + * + * @param string $name + * The internal name for the configtext. + * + * @param string $visiblenameidentifier + * The identifier for the string, that is used for the visible name of the configtext. + * + * @param string $descriptionidentifier + * The identifier for the string, that is used for the visible description of the configtext. + * + * @param string $defaultsetting + * The default setting for the configtext. + * + * @param mixed $paramtype + * The parameter type of the configtext. + * + * @return void + */ + private static function add_admin_setting_configtext(\admin_settingpage $settings, + string $name, + string $visiblenameidentifier, + string $descriptionidentifier, + string $defaultsetting, + $paramtype = PARAM_RAW): void { + $settingconfigtext = new \admin_setting_configtext( + $name, + get_string($visiblenameidentifier, self::PLUGINNAME), + get_string($descriptionidentifier, self::PLUGINNAME), + $defaultsetting, + $paramtype + ); + $settings->add($settingconfigtext); + } + + /** + * Adds an admin setting configpasswordunmask to the passed admin settingpage. + * + * @param \admin_settingpage $settings + * The admin settingpage, the configpasswordunmask is added to. + * + * @param string $name + * The internal name for the configpasswordunmask. + * + * @param string $visiblenameidentifier + * The identifier for the string, that is used for the visible name of the configpasswordunmask. + * + * @param string $descriptionidentifier + * The identifier for the string, that is used for the visible description of the configpasswordunmask. + * + * @param string $defaultsetting + * The default password for the configpasswordunmask. + * + * @return void + */ + private static function add_admin_setting_configpasswordunmask(\admin_settingpage $settings, + string $name, + string $visiblenameidentifier, + string $descriptionidentifier, + string $defaultsetting): void { + $settingconfigpasswordunmask = new \admin_setting_configpasswordunmask( + $name, + get_string($visiblenameidentifier, self::PLUGINNAME), + get_string($descriptionidentifier, self::PLUGINNAME), + $defaultsetting + ); + $settings->add($settingconfigpasswordunmask); + } + + /** + * Adds the connection test tool to the passed admin settingpage for the passed Opencast instance id, + * where a button with its description is added to the passed admin settingpage, + * that can be clicked, to perform this connection test to the corresponding Opencast instance. + * + * A popup is shown, containing the results of this connection test, if this connection test is completed. + * + * @param \admin_settingpage $settings + * The admin settingpage, to add the connection test tool to. + * + * @param int $instanceid + * The id of the Opencast instance, for which the connection test tool is added and the connection test + * is performed. + * + * @return void + */ + private static function add_connection_test_tool(\admin_settingpage $settings, + int $instanceid): void { + // Provide Connection Test Tool button. + $attributes = [ + 'class' => 'btn btn-warning disabled testtool-modal', + 'disabled' => 'disabled', + 'title' => get_string('testtooldisabledbuttontitle', self::PLUGINNAME), + 'data-instanceid' => strval($instanceid), + ]; + + $connectiontoolbutton = \html_writer::tag( + 'button', + get_string('testtoolurl', self::PLUGINNAME), + $attributes + ); + + // Place the button inside the header description. + $settings->add(new \admin_setting_heading( + 'tool_opencast/testtoolexternalpage', + get_string('testtoolheader', self::PLUGINNAME), + get_string('testtoolheaderdesc', self::PLUGINNAME, $connectiontoolbutton)) + ); + } +} diff --git a/db/upgrade.php b/db/upgrade.php index 6ce2c01..0d56697 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,230 +1,230 @@ -. - -/** - * Upgrade.php for tool_opencast. - * - * @package tool_opencast - * @copyright 2018 Tobias Reischmann WWU - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -use tool_opencast\local\settings_api; - -/** - * Execute opencast upgrade from the given old version - * - * @param int $oldversion - * @return bool - */ -function xmldb_tool_opencast_upgrade($oldversion) { - global $DB; - $dbman = $DB->get_manager(); - if ($oldversion < 2018013002) { - - // Define table tool_opencast_series to be created. - $table = new xmldb_table('tool_opencast_series'); - - // Adding fields to table tool_opencast_series. - $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); - $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); - $table->add_field('series', XMLDB_TYPE_CHAR, '36', null, XMLDB_NOTNULL, null, null); - - // Adding keys to table tool_opencast_series. - $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); - $table->add_key('fk_course', XMLDB_KEY_FOREIGN_UNIQUE, ['courseid'], 'course', ['id']); - - // Conditionally launch create table for tool_opencast_series. - if (!$dbman->table_exists($table)) { - $dbman->create_table($table); - } - - // Opencast savepoint reached. - upgrade_plugin_savepoint(true, 2018013002, 'error', 'opencast'); - } - - if ($oldversion < 2021091200) { - // Architecture change: Multiple series per course. - $table = new xmldb_table('tool_opencast_series'); - $field = new xmldb_field('isdefault', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 1, 'series'); - - // Conditionally launch add field default. - if (!$dbman->field_exists($table, $field)) { - $dbman->add_field($table, $field); - } - - // Remove unique key. - $dbman->drop_key($table, new xmldb_key('fk_course', XMLDB_KEY_FOREIGN_UNIQUE, ['courseid'], 'course', ['id'])); - - // Check that each course has only exactly one series. - $sql = "SELECT courseid, COUNT(id) FROM {tool_opencast_series} GROUP BY courseid "; - $courseentries = $DB->get_records_sql($sql); - foreach ($courseentries as $entry) { - if (intval($entry->count) > 1) { - // This should not happen. But if it does, simply select the first one as default. - // 1. Set all to 0. - $DB->set_field('tool_opencast_series', 'isdefault', 0, ['courseid' => $entry->courseid]); - - // 2. Set one to 1. - $records = $DB->get_records('tool_opencast_series'); - $firstrecord = array_values($records)[0]; - $firstrecord->isdefault = 1; - $DB->update_record('tool_opencast_series', $firstrecord); - } - } - - // Architecture change: Multiple OC instances. - // Create default instance. - $ocinstance = new \stdClass(); - $ocinstance->id = 1; - $ocinstance->name = 'Default'; - $ocinstance->isvisible = true; - $ocinstance->isdefault = true; - settings_api::set_ocinstances_to_ocinstance($ocinstance); - - // Add new field to series table. - $table = new xmldb_table('tool_opencast_series'); - $field = new xmldb_field('ocinstanceid', XMLDB_TYPE_INTEGER, '10'); - if (!$dbman->field_exists($table, $field)) { - $dbman->add_field($table, $field); - } - - // Use default series for current series. - $DB->set_field('tool_opencast_series', 'ocinstanceid', 1); - - // Set instance field to not null. - $field = new xmldb_field('ocinstanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL); - $dbman->change_field_notnull($table, $field); - - // Add new foreign key and unique constraint. - $table->add_key('fk_course', XMLDB_KEY_FOREIGN, ['courseid'], 'course', ['id']); - $table->add_key('unq_course_series_ocinstance', XMLDB_KEY_UNIQUE, ['courseid', 'ocinstanceid', 'series']); - - // Opencast savepoint reached. - upgrade_plugin_savepoint(true, 2021091200, 'tool', 'opencast'); - } - - if ($oldversion < 2021102700) { - $columns = $DB->get_columns('tool_opencast_series'); - $isdefaultfield = $columns['isdefault']; - - if ($isdefaultfield->__get("type") == "bytea") { - // Changing type of field isdefault on table tool_opencast_series to int. - $table = new xmldb_table('tool_opencast_series'); - $oldfield = new xmldb_field('isdefault', XMLDB_TYPE_BINARY); - $dbman->rename_field($table, $oldfield, 'isdefault_old'); - - $newfield = new xmldb_field('isdefault', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'series'); - $dbman->add_field($table, $newfield); - - // Loop through records because casting in sql depends on database type. - foreach ($DB->get_records('tool_opencast_series') as $record) { - if ($record->isdefault_old) { - $record->isdefault = 1; - $DB->update_record('tool_opencast_series', $record); - } - } - - // Launch change of type for field isdefault. - $dbman->drop_field($table, new xmldb_field('isdefault_old')); - } - - // Opencast savepoint reached. - upgrade_plugin_savepoint(true, 2021102700, 'tool', 'opencast'); - } - - $newversion = 2023030100; - if ($oldversion < $newversion) { - if (remove_default_opencast_instance_settings_without_id() === false) { - return false; - } - - // Opencast savepoint reached. - upgrade_plugin_savepoint(true, $newversion, 'tool', 'opencast'); - } - - return true; -} - -/** - * Removes the settings of the default Opencast instance without an id in their names - * from the database and adds those settings with the corresponding id in their names - * and their previous values to the database again. - * - * @return bool - * Returns true, if this update of the database was successful, and false otherwise. - */ -function remove_default_opencast_instance_settings_without_id() : bool { - $helpersettingsname = 'apiurl'; - $pluginname = 'tool_opencast'; - - // Check, if settings without an id in their names exist (for the default Opencast instance). - $foundoldsetting = get_config($pluginname, $helpersettingsname); - if ($foundoldsetting === false) { - return true; - } - - // Fetch the default Opencast instance, if any. - $defaultocinstance = settings_api::get_default_ocinstance(); - if ($defaultocinstance === null) { - return true; - } - - $defaultocinstanceid = $defaultocinstance->id; - - try { - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiurl'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiusername'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apipassword'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'lticonsumerkey'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'lticonsumersecret'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apitimeout'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiconnecttimeout'); - } catch (\dml_exception $exception) { - return false; - } - - return true; -} - -/** - * Removes the passed setting of the default Opencast instance without an id in its name - * from the database and adds that setting with the passed id in its name - * and its previous value to the database again. - * - * @param int $defaultinstanceid - * The Opencast instance id of the default Opencast instance. - * - * @param string $name - * The name of the setting to replace (without the Opencast instance id). - * - * @throws \dml_exception - */ -function replace_default_opencast_instance_setting_without_id(int $defaultinstanceid, - string $name) : void { - $pluginname = 'tool_opencast'; - - $value = get_config($pluginname, $name); - if ($value === false) { - throw new \dml_exception('dmlreadexception'); - } - - if (unset_config($name, $pluginname) === false) { - throw new \dml_exception('dmlwriteexception'); - } - - set_config($name . '_' . $defaultinstanceid, $value, $pluginname); -} +. + +/** + * Upgrade.php for tool_opencast. + * + * @package tool_opencast + * @copyright 2018 Tobias Reischmann WWU + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +use tool_opencast\local\settings_api; + +/** + * Execute opencast upgrade from the given old version + * + * @param int $oldversion + * @return bool + */ +function xmldb_tool_opencast_upgrade($oldversion) { + global $DB; + $dbman = $DB->get_manager(); + if ($oldversion < 2018013002) { + + // Define table tool_opencast_series to be created. + $table = new xmldb_table('tool_opencast_series'); + + // Adding fields to table tool_opencast_series. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('series', XMLDB_TYPE_CHAR, '36', null, XMLDB_NOTNULL, null, null); + + // Adding keys to table tool_opencast_series. + $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); + $table->add_key('fk_course', XMLDB_KEY_FOREIGN_UNIQUE, ['courseid'], 'course', ['id']); + + // Conditionally launch create table for tool_opencast_series. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Opencast savepoint reached. + upgrade_plugin_savepoint(true, 2018013002, 'error', 'opencast'); + } + + if ($oldversion < 2021091200) { + // Architecture change: Multiple series per course. + $table = new xmldb_table('tool_opencast_series'); + $field = new xmldb_field('isdefault', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 1, 'series'); + + // Conditionally launch add field default. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Remove unique key. + $dbman->drop_key($table, new xmldb_key('fk_course', XMLDB_KEY_FOREIGN_UNIQUE, ['courseid'], 'course', ['id'])); + + // Check that each course has only exactly one series. + $sql = "SELECT courseid, COUNT(id) FROM {tool_opencast_series} GROUP BY courseid "; + $courseentries = $DB->get_records_sql($sql); + foreach ($courseentries as $entry) { + if (intval($entry->count) > 1) { + // This should not happen. But if it does, simply select the first one as default. + // 1. Set all to 0. + $DB->set_field('tool_opencast_series', 'isdefault', 0, ['courseid' => $entry->courseid]); + + // 2. Set one to 1. + $records = $DB->get_records('tool_opencast_series'); + $firstrecord = array_values($records)[0]; + $firstrecord->isdefault = 1; + $DB->update_record('tool_opencast_series', $firstrecord); + } + } + + // Architecture change: Multiple OC instances. + // Create default instance. + $ocinstance = new \stdClass(); + $ocinstance->id = 1; + $ocinstance->name = 'Default'; + $ocinstance->isvisible = true; + $ocinstance->isdefault = true; + settings_api::set_ocinstances_to_ocinstance($ocinstance); + + // Add new field to series table. + $table = new xmldb_table('tool_opencast_series'); + $field = new xmldb_field('ocinstanceid', XMLDB_TYPE_INTEGER, '10'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Use default series for current series. + $DB->set_field('tool_opencast_series', 'ocinstanceid', 1); + + // Set instance field to not null. + $field = new xmldb_field('ocinstanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL); + $dbman->change_field_notnull($table, $field); + + // Add new foreign key and unique constraint. + $table->add_key('fk_course', XMLDB_KEY_FOREIGN, ['courseid'], 'course', ['id']); + $table->add_key('unq_course_series_ocinstance', XMLDB_KEY_UNIQUE, ['courseid', 'ocinstanceid', 'series']); + + // Opencast savepoint reached. + upgrade_plugin_savepoint(true, 2021091200, 'tool', 'opencast'); + } + + if ($oldversion < 2021102700) { + $columns = $DB->get_columns('tool_opencast_series'); + $isdefaultfield = $columns['isdefault']; + + if ($isdefaultfield->__get("type") == "bytea") { + // Changing type of field isdefault on table tool_opencast_series to int. + $table = new xmldb_table('tool_opencast_series'); + $oldfield = new xmldb_field('isdefault', XMLDB_TYPE_BINARY); + $dbman->rename_field($table, $oldfield, 'isdefault_old'); + + $newfield = new xmldb_field('isdefault', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'series'); + $dbman->add_field($table, $newfield); + + // Loop through records because casting in sql depends on database type. + foreach ($DB->get_records('tool_opencast_series') as $record) { + if ($record->isdefault_old) { + $record->isdefault = 1; + $DB->update_record('tool_opencast_series', $record); + } + } + + // Launch change of type for field isdefault. + $dbman->drop_field($table, new xmldb_field('isdefault_old')); + } + + // Opencast savepoint reached. + upgrade_plugin_savepoint(true, 2021102700, 'tool', 'opencast'); + } + + $newversion = 2023030100; + if ($oldversion < $newversion) { + if (remove_default_opencast_instance_settings_without_id() === false) { + return false; + } + + // Opencast savepoint reached. + upgrade_plugin_savepoint(true, $newversion, 'tool', 'opencast'); + } + + return true; +} + +/** + * Removes the settings of the default Opencast instance without an id in their names + * from the database and adds those settings with the corresponding id in their names + * and their previous values to the database again. + * + * @return bool + * Returns true, if this update of the database was successful, and false otherwise. + */ +function remove_default_opencast_instance_settings_without_id(): bool { + $helpersettingsname = 'apiurl'; + $pluginname = 'tool_opencast'; + + // Check, if settings without an id in their names exist (for the default Opencast instance). + $foundoldsetting = get_config($pluginname, $helpersettingsname); + if ($foundoldsetting === false) { + return true; + } + + // Fetch the default Opencast instance, if any. + $defaultocinstance = settings_api::get_default_ocinstance(); + if ($defaultocinstance === null) { + return true; + } + + $defaultocinstanceid = $defaultocinstance->id; + + try { + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiurl'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiusername'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apipassword'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'lticonsumerkey'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'lticonsumersecret'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apitimeout'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiconnecttimeout'); + } catch (\dml_exception $exception) { + return false; + } + + return true; +} + +/** + * Removes the passed setting of the default Opencast instance without an id in its name + * from the database and adds that setting with the passed id in its name + * and its previous value to the database again. + * + * @param int $defaultinstanceid + * The Opencast instance id of the default Opencast instance. + * + * @param string $name + * The name of the setting to replace (without the Opencast instance id). + * + * @throws \dml_exception + */ +function replace_default_opencast_instance_setting_without_id(int $defaultinstanceid, + string $name): void { + $pluginname = 'tool_opencast'; + + $value = get_config($pluginname, $name); + if ($value === false) { + throw new \dml_exception('dmlreadexception'); + } + + if (unset_config($name, $pluginname) === false) { + throw new \dml_exception('dmlwriteexception'); + } + + set_config($name . '_' . $defaultinstanceid, $value, $pluginname); +} diff --git a/external.php b/external.php index 1a9e64b..4b8e86c 100644 --- a/external.php +++ b/external.php @@ -1,327 +1,327 @@ -. - -/** - * Opencast external API - * - * @package tool_opencast - * @category external - * @copyright 2018 Tobias Reischmann - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.2 - */ - -defined('MOODLE_INTERNAL') || die; - -require_once($CFG->libdir . '/externallib.php'); -require_once($CFG->libdir . '/authlib.php'); - -/** - * Opencast external API - * - * @package tool_opencast - * @category external - * @copyright 2018 Tobias Reischmann - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class tool_opencast_external extends external_api { - - /** - * Describes the parameters for getting courses for a opencast instructor. - * - * @return external_function_parameters - * @throws coding_exception - */ - public static function get_courses_for_instructor_parameters() { - return new external_function_parameters( - [ - 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), - ] - ); - } - - /** - * Describes the parameters for getting courses for a opencast learner. - * - * @return external_function_parameters - * @throws coding_exception - */ - public static function get_courses_for_learner_parameters() { - return new external_function_parameters( - [ - 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), - ] - ); - } - - /** - * Describes the parameters for getting groups for a opencast user. - * - * @return external_function_parameters - * @throws coding_exception - */ - public static function get_groups_for_learner_parameters() { - return new external_function_parameters( - [ - 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), - ] - ); - } - - /** - * Get all courses for a user, in which he has the capabilities of a instructor. - * - * @param string $username user name - * @return array list of course ids - * @throws coding_exception - * @throws dml_exception - * @throws invalid_parameter_exception - * @throws required_capability_exception - */ - public static function get_courses_for_instructor($username) { - self::validate_parameters(self::get_courses_for_instructor_parameters(), ['username' => $username]); - - return self::get_courses_with_capability($username, 'tool/opencast:instructor'); - } - - /** - * Get all courses for a user, in which he has the capabilities of a learner. - * - * @param string $username user name - * @return array list of course ids - * @throws coding_exception - * @throws dml_exception - * @throws invalid_parameter_exception - * @throws required_capability_exception - */ - public static function get_courses_for_learner($username) { - self::validate_parameters(self::get_courses_for_learner_parameters(), ['username' => $username]); - - return self::get_courses_with_capability($username, 'tool/opencast:learner'); - } - - /** - * Get all courses for a user, in which he has the capabilities of a learner. - * - * @param string $username user name - * @return array list of course ids - * @throws coding_exception - * @throws dml_exception - * @throws invalid_parameter_exception - * @throws required_capability_exception - */ - public static function get_groups_for_learner($username) { - self::validate_parameters(self::get_groups_for_learner_parameters(), ['username' => $username]); - - $context = context_system::instance(); - if (!has_capability('tool/opencast:externalapi', $context)) { - throw new required_capability_exception($context, 'tool/opencast:externalapi', 'nopermissions', ''); - } - if (!has_capability('moodle/site:accessallgroups', $context)) { - throw new required_capability_exception($context, 'moodle/site:accessallgroups', 'nopermissions', ''); - } - - global $DB; - $user = core_user::get_user_by_username($username); - return $DB->get_records('groups_members', ['userid' => $user->id], '', 'groupid as id'); - } - - /** - * Returns all course ids where the user has the specific capability in. - * @param string $username the username - * @param string $capability the moodle capability - * @return array - * @throws coding_exception - * @throws dml_exception - * @throws required_capability_exception - */ - private static function get_courses_with_capability($username, $capability) { - $result = []; - - $context = context_system::instance(); - if (!has_capability('tool/opencast:externalapi', $context)) { - throw new required_capability_exception($context, 'tool/opencast:externalapi', 'nopermissions', ''); - } - - $user = core_user::get_user_by_username($username); - $courses = enrol_get_all_users_courses($user->id); - foreach ($courses as $course) { - $context = context_course::instance($course->id); - if (has_capability($capability, $context, $user)) { - $result[] = ['id' => $course->id]; - } - } - return $result; - } - - /** - * Describes the confirm_user return value. - * - * @return external_multiple_structure array of course ids - */ - public static function get_courses_for_instructor_returns() { - return new external_multiple_structure( - new external_single_structure( - [ - 'id' => new external_value(PARAM_INT, 'id of course'), - ] - ) - ); - } - - /** - * Describes the confirm_user return value. - * - * @return external_multiple_structure array of course ids - */ - public static function get_courses_for_learner_returns() { - return new external_multiple_structure( - new external_single_structure( - [ - 'id' => new external_value(PARAM_INT, 'id of course'), - ] - ) - ); - } - - /** - * Describes the confirm_user return value. - * - * @return external_multiple_structure array of course ids - */ - public static function get_groups_for_learner_returns() { - return new external_multiple_structure( - new external_single_structure( - [ - 'id' => new external_value(PARAM_INT, 'id of group'), - ] - ) - ); - } - - /** - * Describes the connection_test_tool return value. - * - * @return external_single_structure array the result of the connection test - */ - public static function connection_test_tool_returns() { - return new external_single_structure( - [ - 'testresult' => new external_value(PARAM_RAW, 'Opencast API URL Test result'), - ] - ); - } - - /** - * Describes the parameters for testing the connection. - * - * @return external_function_parameters - * @throws coding_exception - */ - public static function connection_test_tool_parameters() { - return new external_function_parameters( - [ - 'apiurl' => new external_value(PARAM_TEXT, 'Opencast API URL'), - 'apiusername' => new external_value(PARAM_TEXT, 'Opencast API User'), - 'apipassword' => new external_value(PARAM_RAW, 'Opencast API Password'), - 'apitimeout' => new external_value(PARAM_INT, 'API timeout', VALUE_DEFAULT, 2000), - 'apiconnecttimeout' => new external_value(PARAM_INT, 'API connect timeout', VALUE_DEFAULT, 1000), - ] - ); - } - - /** - * Builds a html tag for the alert of the connection test tool. - * - * @param string $connectiontestresult The result of a connection test. - * @param string $testsuccessfulstringidentifier The string identifier of a successful connection test. - * @param string $testfailedstringidentifier The string identifier of a failed connection test. - * @return string The html tag as string. - */ - private static function connection_test_tool_build_html_alert_tag($connectiontestresult, - string $testsuccessfulstringidentifier, - string $testfailedstringidentifier) : string { - // Check, if the test was successful. - if ($connectiontestresult === true) { - return html_writer::tag( - 'p', - get_string($testsuccessfulstringidentifier, 'tool_opencast'), - ['class' => 'alert alert-success'] - ); - } - - return html_writer::tag( - 'p', - get_string($testfailedstringidentifier, 'tool_opencast', $connectiontestresult), - ['class' => 'alert alert-danger'] - ); - } - - /** - * Perform the connection test via Ajax call to be able to show it in Modal. - * - * @param string $apiurl Opencast API URL - * @param string $apiusername Opencast API username - * @param string $apipassword Opencast API password - * @param int $apitimeout Overall API request execution timeout in milliseconds - * @param int $apiconnecttimeout Connection timeout in milliseconds - * @return array - * @throws coding_exception - * @throws dml_exception - * @throws invalid_parameter_exception - * @throws required_capability_exception - */ - public static function connection_test_tool($apiurl, $apiusername, $apipassword, $apitimeout, $apiconnecttimeout) { - - // Validate the parameters. - $params = self::validate_parameters(self::connection_test_tool_parameters(), - [ - 'apiurl' => $apiurl, - 'apiusername' => $apiusername, - 'apipassword' => $apipassword, - 'apitimeout' => $apitimeout, - 'apiconnecttimeout' => $apiconnecttimeout, - ] - ); - - // Get a customized api instance to use. - $customizedapi = \tool_opencast\local\api::get_instance(null, [], [ - 'apiurl' => $params['apiurl'], - 'apiusername' => $params['apiusername'], - 'apipassword' => $params['apipassword'], - 'apitimeout' => $params['apitimeout'], - 'apiconnecttimeout' => $params['apiconnecttimeout'], - ]); - - // Test the URL. - $connectiontesturlresult = $customizedapi->connection_test_url(); - $resulthtml = self::connection_test_tool_build_html_alert_tag( - $connectiontesturlresult, - 'apiurltestsuccessfulshort', - 'apiurltestfailedshort'); - - // Test the Credentials. - $connectiontestcredentialsresult = $customizedapi->connection_test_credentials(); - $resulthtml .= self::connection_test_tool_build_html_alert_tag( - $connectiontestcredentialsresult, - 'apicreadentialstestsuccessfulshort', - 'apicreadentialstestfailedshort'); - - return [ - 'testresult' => $resulthtml, - ]; - } -} +. + +/** + * Opencast external API + * + * @package tool_opencast + * @category external + * @copyright 2018 Tobias Reischmann + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 3.2 + */ + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->libdir . '/externallib.php'); +require_once($CFG->libdir . '/authlib.php'); + +/** + * Opencast external API + * + * @package tool_opencast + * @category external + * @copyright 2018 Tobias Reischmann + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class tool_opencast_external extends external_api { + + /** + * Describes the parameters for getting courses for a opencast instructor. + * + * @return external_function_parameters + * @throws coding_exception + */ + public static function get_courses_for_instructor_parameters() { + return new external_function_parameters( + [ + 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), + ] + ); + } + + /** + * Describes the parameters for getting courses for a opencast learner. + * + * @return external_function_parameters + * @throws coding_exception + */ + public static function get_courses_for_learner_parameters() { + return new external_function_parameters( + [ + 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), + ] + ); + } + + /** + * Describes the parameters for getting groups for a opencast user. + * + * @return external_function_parameters + * @throws coding_exception + */ + public static function get_groups_for_learner_parameters() { + return new external_function_parameters( + [ + 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), + ] + ); + } + + /** + * Get all courses for a user, in which he has the capabilities of a instructor. + * + * @param string $username user name + * @return array list of course ids + * @throws coding_exception + * @throws dml_exception + * @throws invalid_parameter_exception + * @throws required_capability_exception + */ + public static function get_courses_for_instructor($username) { + self::validate_parameters(self::get_courses_for_instructor_parameters(), ['username' => $username]); + + return self::get_courses_with_capability($username, 'tool/opencast:instructor'); + } + + /** + * Get all courses for a user, in which he has the capabilities of a learner. + * + * @param string $username user name + * @return array list of course ids + * @throws coding_exception + * @throws dml_exception + * @throws invalid_parameter_exception + * @throws required_capability_exception + */ + public static function get_courses_for_learner($username) { + self::validate_parameters(self::get_courses_for_learner_parameters(), ['username' => $username]); + + return self::get_courses_with_capability($username, 'tool/opencast:learner'); + } + + /** + * Get all courses for a user, in which he has the capabilities of a learner. + * + * @param string $username user name + * @return array list of course ids + * @throws coding_exception + * @throws dml_exception + * @throws invalid_parameter_exception + * @throws required_capability_exception + */ + public static function get_groups_for_learner($username) { + self::validate_parameters(self::get_groups_for_learner_parameters(), ['username' => $username]); + + $context = context_system::instance(); + if (!has_capability('tool/opencast:externalapi', $context)) { + throw new required_capability_exception($context, 'tool/opencast:externalapi', 'nopermissions', ''); + } + if (!has_capability('moodle/site:accessallgroups', $context)) { + throw new required_capability_exception($context, 'moodle/site:accessallgroups', 'nopermissions', ''); + } + + global $DB; + $user = core_user::get_user_by_username($username); + return $DB->get_records('groups_members', ['userid' => $user->id], '', 'groupid as id'); + } + + /** + * Returns all course ids where the user has the specific capability in. + * @param string $username the username + * @param string $capability the moodle capability + * @return array + * @throws coding_exception + * @throws dml_exception + * @throws required_capability_exception + */ + private static function get_courses_with_capability($username, $capability) { + $result = []; + + $context = context_system::instance(); + if (!has_capability('tool/opencast:externalapi', $context)) { + throw new required_capability_exception($context, 'tool/opencast:externalapi', 'nopermissions', ''); + } + + $user = core_user::get_user_by_username($username); + $courses = enrol_get_all_users_courses($user->id); + foreach ($courses as $course) { + $context = context_course::instance($course->id); + if (has_capability($capability, $context, $user)) { + $result[] = ['id' => $course->id]; + } + } + return $result; + } + + /** + * Describes the confirm_user return value. + * + * @return external_multiple_structure array of course ids + */ + public static function get_courses_for_instructor_returns() { + return new external_multiple_structure( + new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'id of course'), + ] + ) + ); + } + + /** + * Describes the confirm_user return value. + * + * @return external_multiple_structure array of course ids + */ + public static function get_courses_for_learner_returns() { + return new external_multiple_structure( + new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'id of course'), + ] + ) + ); + } + + /** + * Describes the confirm_user return value. + * + * @return external_multiple_structure array of course ids + */ + public static function get_groups_for_learner_returns() { + return new external_multiple_structure( + new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'id of group'), + ] + ) + ); + } + + /** + * Describes the connection_test_tool return value. + * + * @return external_single_structure array the result of the connection test + */ + public static function connection_test_tool_returns() { + return new external_single_structure( + [ + 'testresult' => new external_value(PARAM_RAW, 'Opencast API URL Test result'), + ] + ); + } + + /** + * Describes the parameters for testing the connection. + * + * @return external_function_parameters + * @throws coding_exception + */ + public static function connection_test_tool_parameters() { + return new external_function_parameters( + [ + 'apiurl' => new external_value(PARAM_TEXT, 'Opencast API URL'), + 'apiusername' => new external_value(PARAM_TEXT, 'Opencast API User'), + 'apipassword' => new external_value(PARAM_RAW, 'Opencast API Password'), + 'apitimeout' => new external_value(PARAM_INT, 'API timeout', VALUE_DEFAULT, 2000), + 'apiconnecttimeout' => new external_value(PARAM_INT, 'API connect timeout', VALUE_DEFAULT, 1000), + ] + ); + } + + /** + * Builds a html tag for the alert of the connection test tool. + * + * @param string $connectiontestresult The result of a connection test. + * @param string $testsuccessfulstringidentifier The string identifier of a successful connection test. + * @param string $testfailedstringidentifier The string identifier of a failed connection test. + * @return string The html tag as string. + */ + private static function connection_test_tool_build_html_alert_tag($connectiontestresult, + string $testsuccessfulstringidentifier, + string $testfailedstringidentifier): string { + // Check, if the test was successful. + if ($connectiontestresult === true) { + return html_writer::tag( + 'p', + get_string($testsuccessfulstringidentifier, 'tool_opencast'), + ['class' => 'alert alert-success'] + ); + } + + return html_writer::tag( + 'p', + get_string($testfailedstringidentifier, 'tool_opencast', $connectiontestresult), + ['class' => 'alert alert-danger'] + ); + } + + /** + * Perform the connection test via Ajax call to be able to show it in Modal. + * + * @param string $apiurl Opencast API URL + * @param string $apiusername Opencast API username + * @param string $apipassword Opencast API password + * @param int $apitimeout Overall API request execution timeout in milliseconds + * @param int $apiconnecttimeout Connection timeout in milliseconds + * @return array + * @throws coding_exception + * @throws dml_exception + * @throws invalid_parameter_exception + * @throws required_capability_exception + */ + public static function connection_test_tool($apiurl, $apiusername, $apipassword, $apitimeout, $apiconnecttimeout) { + + // Validate the parameters. + $params = self::validate_parameters(self::connection_test_tool_parameters(), + [ + 'apiurl' => $apiurl, + 'apiusername' => $apiusername, + 'apipassword' => $apipassword, + 'apitimeout' => $apitimeout, + 'apiconnecttimeout' => $apiconnecttimeout, + ] + ); + + // Get a customized api instance to use. + $customizedapi = \tool_opencast\local\api::get_instance(null, [], [ + 'apiurl' => $params['apiurl'], + 'apiusername' => $params['apiusername'], + 'apipassword' => $params['apipassword'], + 'apitimeout' => $params['apitimeout'], + 'apiconnecttimeout' => $params['apiconnecttimeout'], + ]); + + // Test the URL. + $connectiontesturlresult = $customizedapi->connection_test_url(); + $resulthtml = self::connection_test_tool_build_html_alert_tag( + $connectiontesturlresult, + 'apiurltestsuccessfulshort', + 'apiurltestfailedshort'); + + // Test the Credentials. + $connectiontestcredentialsresult = $customizedapi->connection_test_credentials(); + $resulthtml .= self::connection_test_tool_build_html_alert_tag( + $connectiontestcredentialsresult, + 'apicreadentialstestsuccessfulshort', + 'apicreadentialstestfailedshort'); + + return [ + 'testresult' => $resulthtml, + ]; + } +} From 8e691f08f8bc5e1769d476a6e59250c1363b2af9 Mon Sep 17 00:00:00 2001 From: Thomas Niedermaier Date: Sun, 10 Nov 2024 11:55:58 +0100 Subject: [PATCH 3/6] codechecker issues: crlf to lf --- .github/workflows/moodle-ci.yml | 20 +- classes/local/api.php | 1274 +++++++++---------- classes/local/environment_util.php | 110 +- classes/local/settings_api.php | 516 ++++---- classes/settings/admin_settings_builder.php | 910 ++++++------- db/upgrade.php | 460 +++---- external.php | 654 +++++----- 7 files changed, 1972 insertions(+), 1972 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 9142136..7515255 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -1,11 +1,11 @@ -name: Moodle Plugin CI - -######################################################################################################################## - -on: [ push, pull_request ] - -######################################################################################################################## - -jobs: - call-moodle-ci-workflow: +name: Moodle Plugin CI + +######################################################################################################################## + +on: [ push, pull_request ] + +######################################################################################################################## + +jobs: + call-moodle-ci-workflow: uses: Opencast-Moodle/moodle-workflows-opencast/.github/workflows/moodle-ci.yml@main \ No newline at end of file diff --git a/classes/local/api.php b/classes/local/api.php index c49fccd..acf1e70 100644 --- a/classes/local/api.php +++ b/classes/local/api.php @@ -1,637 +1,637 @@ -. - -/** - * API for opencast - * - * @package tool_opencast - * @copyright 2018 Tobias Reischmann - * @copyright 2017 Andreas Wagner, SYNERGY LEARNING - * @author Andreas Wagner - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace tool_opencast\local; - -use local_chunkupload\local\chunkupload_file; -use tool_opencast\empty_configuration_exception; - -defined('MOODLE_INTERNAL') || die; - -require_once($CFG->dirroot . '/lib/filelib.php'); -require_once($CFG->dirroot . '/admin/tool/opencast/vendor/autoload.php'); -/** - * API for opencast - * - * @package tool_opencast - * @copyright 2018 Tobias Reischmann - * @copyright 2017 Andreas Wagner, SYNERGY LEARNING - * @author Andreas Wagner - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class api extends \curl { - - /** @var string the api username */ - private $username; - /** @var string the api password */ - private $password; - /** @var int the curl timeout in milliseconds */ - private $timeout = 2000; - /** @var int the curl connecttimeout in milliseconds */ - private $connecttimeout = 1000; - /** @var string the api baseurl */ - private $baseurl; - /** @var \OpencastApi\Opencast the opencast endpoints instance */ - public $opencastapi; - /** @var \OpencastApi\Rest\OcRestClient the opencast REST Client instance */ - public $opencastrestclient; - - /** @var array array of supported api levels */ - private static $supportedapilevel; - - /** - * Returns the sortparam string - * @param array $params - * @return string - */ - public static function get_sort_param($params) { - if (empty($params)) { - return ''; - } - - foreach ($params as $key => $sortorder) { - $sortdir = (SORT_ASC == $sortorder) ? 'ASC' : 'DESC'; - return "&sort={$key}:" . $sortdir; - } - return ''; - } - - /** - * Returns the COURSE_ACL_ROLE-prfix - * @return string - */ - public static function get_course_acl_role_prefix() { - return "ROLE_GROUP_MOODLE_COURSE_"; - } - - /** - * Returns the course ACL role for the given course - * @param int $courseid the courseid - * @return string the acl role - */ - public static function get_course_acl_role($courseid) { - return self::get_course_acl_role_prefix(). $courseid; - } - - /** - * Returns the course ACL group identifier for the given course - * @param int $courseid the courseid - * @return string the course ACL group identifier - */ - public static function get_course_acl_group_identifier($courseid) { - return "moodle_course_" . $courseid; - } - - /** - * Returns the course ACL group name for the given course - * @param int $courseid the course id - * @return string the course ACL group name - */ - public static function get_course_acl_group_name($courseid) { - return "Moodle_Course_" . $courseid; - } - - /** - * Returns the course series title prefix - * @return string the course series title prefix - */ - public static function get_courses_series_title_prefix() { - return "Course_Series_"; - } - - /** - * Returns the course series title for a given course - * @param int $courseid the courseid - * @return string the course series title - */ - public static function get_courses_series_title($courseid) { - return self::get_courses_series_title_prefix() . $courseid; - } - - /** - * Returns the real api or test api depending on the environment. - * - * @param int|null $instanceid - * Opencast instance id. - * - * @param array $settings - * @param array $customconfigs - * @param boolean $enableingest whether to enable ingest upload. - * - * @return api|api_testable - * - * @throws \dml_exception - * @throws \moodle_exception - */ - public static function get_instance($instanceid = null, - $settings = [], - $customconfigs = [], - $enableingest = false) { - - if (self::use_test_api() === true) { - $apitestable = new api_testable($instanceid, $enableingest); - return $apitestable; - } - - return new api($instanceid, $settings, $customconfigs, $enableingest); - } - - /** - * Returns, whether the test api should be used. - * - * @return bool - * @throws \dml_exception - */ - private static function use_test_api(): bool { - if (defined('BEHAT_SITE_RUNNING') && BEHAT_SITE_RUNNING) { - $defaultocinstance = settings_api::get_default_ocinstance(); - if ($defaultocinstance === null) { - return false; - } - - $defaultocinstanceapiurl = settings_api::get_apiurl($defaultocinstance->id); - if ($defaultocinstanceapiurl === false) { - return false; - } - - if ($defaultocinstanceapiurl === 'http://testapi:8080') { - return true; - } - } - - return false; - } - - /** - * Constructor of the Opencast API. - * - * @param int|null $instanceid - * Opencast instance id. - * - * @param array $settings - * Additional curl settings. - * - * @param array $customconfigs - * Custom api config. - * - * @param boolean $enableingest whether to enable ingest upload. - * - * @throws \dml_exception - * @throws \moodle_exception - */ - public function __construct($instanceid = null, - $settings = [], - $customconfigs = [], - $enableingest = false) { - // Allow access to local ips. - $settings['ignoresecurity'] = true; - parent::__construct($settings); - - $instanceid = intval($instanceid); - - // If there is no custom configs to set, we go for the stored configs. - if (empty($customconfigs)) { - $defaultocinstance = settings_api::get_default_ocinstance(); - if ($defaultocinstance === null) { - throw new \dml_exception('dmlreadexception', null, - 'No default Opencast instance is defined.'); - } - - $storedconfigocinstanceid = !$instanceid ? $defaultocinstance->id : $instanceid; - - $this->username = settings_api::get_apiusername($storedconfigocinstanceid); - $this->password = settings_api::get_apipassword($storedconfigocinstanceid); - $this->timeout = settings_api::get_apitimeout($storedconfigocinstanceid); - $this->connecttimeout = settings_api::get_apiconnecttimeout($storedconfigocinstanceid); - $this->baseurl = settings_api::get_apiurl($storedconfigocinstanceid); - - if (empty($this->username)) { - throw new empty_configuration_exception('apiusernameempty', 'tool_opencast'); - } - - if (empty($this->password)) { - throw new empty_configuration_exception('apipasswordempty', 'tool_opencast'); - } - } else { - // When user wanted to use the api class but not with the stored configs. - if (array_key_exists('apiurl', $customconfigs)) { - $this->baseurl = $customconfigs['apiurl']; - } - - if (array_key_exists('apiusername', $customconfigs)) { - $this->username = $customconfigs['apiusername']; - } - - if (array_key_exists('apipassword', $customconfigs)) { - $this->password = $customconfigs['apipassword']; - } - - if (array_key_exists('apitimeout', $customconfigs)) { - $this->timeout = $customconfigs['apitimeout']; - } - - if (array_key_exists('apiconnecttimeout', $customconfigs)) { - $this->connecttimeout = $customconfigs['apiconnecttimeout']; - } - } - - // If the admin omitted the protocol part, add the HTTPS protocol on-the-fly. - if (!preg_match('/^https?:\/\//', $this->baseurl)) { - $this->baseurl = 'https://'.$this->baseurl; - } - - // The base url is a must and cannot be empty, so we check its existence for both scenarios. - if (empty($this->baseurl)) { - throw new empty_configuration_exception('apiurlempty', 'tool_opencast'); - } - - $this->setopt([ - 'CURLOPT_TIMEOUT_MS' => $this->timeout, - 'CURLOPT_CONNECTTIMEOUT_MS' => $this->connecttimeout, ]); - - $config = [ - 'url' => $this->baseurl, - 'username' => $this->username, - 'password' => $this->password, - 'timeout' => (intval($this->timeout) / 1000), - 'connect_timeout' => (intval($this->connecttimeout) / 1000), - ]; - $this->opencastapi = new \OpencastApi\Opencast($config, [], $enableingest); - $this->opencastrestclient = new \OpencastApi\Rest\OcRestClient($config); - } - - /** - * Set curl timout in milliseconds - * @param int $timeout curl timeout in milliseconds - */ - public function set_timeout($timeout) { - $this->timeout = $timeout; - $this->setopt(['CURLOPT_TIMEOUT_MS' => $this->timeout]); - } - - /** - * Set curl connect timout in milliseconds - * @param int $connecttimeout curl connect timeout in milliseconds - */ - public function set_connecttimeout($connecttimeout) { - $this->connecttimeout = $connecttimeout; - $this->setopt(['CURLOPT_CONNECTTIMEOUT_MS' => $this->connecttimeout]); - } - - /** - * Set base url. - * @param string $baseurl - */ - public function set_baseurl($baseurl) { - $this->baseurl = $baseurl; - } - - /** - * Get http status code - * - * @return int|boolean status code or false if not available. - */ - public function get_http_code() { - - $info = $this->get_info(); - if (!isset($info['http_code'])) { - return false; - } - return $info['http_code']; - } - - /** - * Get an digest authentication header. - * @param array $runwithroles if set, the request is executed within opencast assuming the user has - * the specified roles. - * - * @return array of authentification headers - * @throws \moodle_exception - */ - private function get_authentication_header($runwithroles = []) { - - $options = ['CURLOPT_HEADER' => true]; - $this->setopt($options); - - // Restrict to Roles. - if (!empty($runwithroles)) { - $header[] = "X-RUN-WITH-ROLES: " . implode(', ', $runwithroles); - $this->setHeader($header); - } - - $basicauth = base64_encode($this->username . ":" . $this->password); - - $header = []; - - $header[] = sprintf( - 'Authorization: Basic %s', $basicauth - ); - - return $header; - } - - /** - * Do a GET call to opencast API. - * - * @param string $resource path of the resource. - * @param array $runwithroles if set, the request is executed within opencast assuming the user has - * the specified roles. - * @return string JSON String of result. - * @throws \moodle_exception - */ - public function oc_get($resource, $runwithroles = []) { - $url = $this->baseurl . $resource; - - $this->resetHeader(); - $header = $this->get_authentication_header($runwithroles); - $header[] = 'Content-Type: application/json'; - $this->setHeader($header); - $this->setopt(['CURLOPT_HEADER' => false]); - - return $this->get($url); - } - - /** - * Opencast needs a fileextension for uploaded file, so add a postname - * (which the core curl module does NOT) to curl_file. - * - * @param object|\stored_file $storedfile stored file to be uploaded. - * @param string $key key identifier within the post params array of the stored file. - * @throws \moodle_exception - */ - private function add_postname($storedfile, $key) { - - $curlfile = $this->_tmp_file_post_params[$key]; - - // Ensure that file is uploaded as a curl file (PHP 5 > 5.5.0 is needed). - if (!$curlfile instanceof \CURLFile) { - throw new \moodle_exception('needphp55orhigher', 'tool_opencast'); - } - - // Extracting filename from $file->file_record->source, make sure to have a string filename! - $source = @unserialize($storedfile->get_source()); - $filename = ''; - if (is_object($source)) { - $filename = $source->source; - } else { - // If source is not a serialised object, it is a string containing only the filename. - $filename = $storedfile->get_source(); - } - $extension = pathinfo($filename, PATHINFO_EXTENSION); - - // If extension is empty, add extension base on mimetype. - if (empty($extension)) { - $extension = mimeinfo_from_type('extension', $storedfile->get_mimetype()); - $filename .= '.' . $extension; - } - - // Check mimetype. - $mimetype = mimeinfo('type', $filename); - - $curlfile->postname = $filename; - $curlfile->mime = $mimetype; - } - - /** - * Opencast needs a fileextension for uploaded file, so add a postname - * (which the core curl module does NOT) to curl_file. - * - * @param chunkupload_file $file chunkupload file to be uploaded. - * @param string $key key identifier within the post params array of the stored file. - * @throws \moodle_exception - */ - private function add_postname_chunkupload($file, $key) { - - $curlfile = $this->_tmp_file_post_params[$key]; - - // Ensure that file is uploaded as a curl file (PHP 5 > 5.5.0 is needed). - if (!$curlfile instanceof \CURLFile) { - throw new \moodle_exception('needphp55orhigher', 'tool_opencast'); - } - - $filename = $file->get_filename(); - - $extension = pathinfo($filename, PATHINFO_EXTENSION); - - // If extension is empty, add extension base on mimetype. - if (empty($extension)) { - $mimetype = file_storage::mimetype_from_file($file->get_fullpath()); - $extension = mimeinfo_from_type('extension', $mimetype); - $filename .= '.' . $extension; - } - - // Check mimetype. - $mimetype = mimeinfo('type', $filename); - - $curlfile->postname = $filename; - $curlfile->mime = $mimetype; - } - - /** - * Do a POST call to opencast API. - * - * @param string $resource path of the resource. - * @param array $params post parameters. - * @param array $runwithroles if set, the request is executed within opencast assuming the user has - * the specified roles. - * @return string JSON String of result. - * @throws \moodle_exception - */ - public function oc_post($resource, $params = [], $runwithroles = []) { - - $url = $this->baseurl . $resource; - - $this->resetHeader(); - $header = $this->get_authentication_header($runwithroles); - $header[] = "Content-Type: multipart/form-data"; - $this->setHeader($header); - $this->setopt(['CURLOPT_HEADER' => false]); - - $options['CURLOPT_POST'] = 1; - - if (is_array($params)) { - $this->_tmp_file_post_params = []; - foreach ($params as $key => $value) { - if ($value instanceof \stored_file) { - $value->add_to_curl_request($this, $key); - $this->add_postname($value, $key); - } else if (class_exists('\local_chunkupload\local\chunkupload_file') && - $value instanceof \local_chunkupload\local\chunkupload_file) { - $value->add_to_curl_request($this, $key); - $this->add_postname_chunkupload($value, $key); - } else { - $this->_tmp_file_post_params[$key] = $value; - } - } - $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; - unset($this->_tmp_file_post_params); - } else { - // The raw post data. - $options['CURLOPT_POSTFIELDS'] = $params; - } - return $this->request($url, $options); - } - - /** - * Do a PUT call to opencast API. - * - * @param string $resource path of the resource. - * @param array $params array of parameters. - * @param array $runwithroles if set, the request is executed within opencast assuming the user has - * the specified roles. - * @return string JSON String of result. - * @throws \moodle_exception - */ - public function oc_put($resource, $params = [], $runwithroles = []) { - - $url = $this->baseurl . $resource; - - $this->resetHeader(); - $header = $this->get_authentication_header($runwithroles); - $this->setHeader($header); - $this->setopt(['CURLOPT_HEADER' => false]); - - $options['CURLOPT_CUSTOMREQUEST'] = "PUT"; - if (is_array($params)) { - $this->_tmp_file_post_params = []; - foreach ($params as $key => $value) { - $this->_tmp_file_post_params[$key] = $value; - } - $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; - unset($this->_tmp_file_post_params); - } else { - // The raw post data. - $options['CURLOPT_POSTFIELDS'] = $params; - } - - return $this->request($url, $options); - } - - /** - * Do a DELETE call to opencast API. - * - * @param string $resource path of the resource. - * @param array $params array of parameters. - * @param array $runwithroles if set, the request is executed within opencast assuming the user has - * the specified roles. - * @return string JSON String of result. - * @throws \moodle_exception - */ - public function oc_delete($resource, $params = [], $runwithroles = []) { - - $url = $this->baseurl . $resource; - - $this->resetHeader(); - $header = $this->get_authentication_header($runwithroles); - $this->setHeader($header); - $this->setopt(['CURLOPT_HEADER' => false]); - - $options['CURLOPT_CUSTOMREQUEST'] = "DELETE"; - if (is_array($params)) { - $this->_tmp_file_post_params = []; - foreach ($params as $key => $value) { - $this->_tmp_file_post_params[$key] = $value; - } - $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; - unset($this->_tmp_file_post_params); - } else { - // The raw post data. - $options['CURLOPT_POSTFIELDS'] = $params; - } - - return $this->request($url, $options); - } - - /** - * Checks if the opencast version support a certain version of the External API. - * This is necessary for the decision, which opencast endpoints are used throughout this class. - * @param string $level level to check for - * @return boolean whether the given api $level is supported. - * @throws \moodle_exception - */ - public function supports_api_level($level) { - if (!self::$supportedapilevel) { - - $response = $this->opencastapi->baseApi->getVersion(); - - if ($response['code'] != 200) { - throw new \moodle_exception('Opencast system not reachable.'); - } - $versions = $response['body']; - self::$supportedapilevel = $versions->versions; - } - return is_array(self::$supportedapilevel) && in_array($level, self::$supportedapilevel); - } - - /** - * Checks if the Opencast API URL is reachable and there is an Opencast instance running on that URL. - * - * @return int|boolean http status code, if the API URL is not reachable or an Opencast instance - * is not running on that URL, and true otherwise. - */ - public function connection_test_url() { - // The "/api" resource endpoint returns key characteristics of the API such as the server name and the default version. - $response = $this->opencastapi->baseApi->noHeader()->get(); - // If the connection fails or the Opencast instance could not be found, return the http code. - $httpcode = $response['code']; - if ($httpcode === false) { - $httpcode = 404; // Not Found. - } - if ($httpcode != 200) { - return $httpcode; - } - - return true; - } - - /** - * Checks if the Opencast API username and password is valid. - * - * @return int|boolean http status code, if the API URL is not reachable, an Opencast instance - * is not running on that URL or the credentials are invalid, and true otherwise. - */ - public function connection_test_credentials() { - // The "/api" resource endpoint returns information on the logged in user. - $response = $this->opencastapi->baseApi->getUserInfo(); - $userinfo = $response['body']; - - // If the credentials are invalid, return a corresponding http code. - if (!$userinfo) { - return 400; // Bad Request. - } - - // If the connection fails or the Opencast instance could not be found, return the http code. - $httpcode = $response['code']; - if ($httpcode === false) { - $httpcode = 404; // Not Found. - } - if ($httpcode != 200) { - return $httpcode; - } - - return true; - } -} +. + +/** + * API for opencast + * + * @package tool_opencast + * @copyright 2018 Tobias Reischmann + * @copyright 2017 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_opencast\local; + +use local_chunkupload\local\chunkupload_file; +use tool_opencast\empty_configuration_exception; + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->dirroot . '/lib/filelib.php'); +require_once($CFG->dirroot . '/admin/tool/opencast/vendor/autoload.php'); +/** + * API for opencast + * + * @package tool_opencast + * @copyright 2018 Tobias Reischmann + * @copyright 2017 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class api extends \curl { + + /** @var string the api username */ + private $username; + /** @var string the api password */ + private $password; + /** @var int the curl timeout in milliseconds */ + private $timeout = 2000; + /** @var int the curl connecttimeout in milliseconds */ + private $connecttimeout = 1000; + /** @var string the api baseurl */ + private $baseurl; + /** @var \OpencastApi\Opencast the opencast endpoints instance */ + public $opencastapi; + /** @var \OpencastApi\Rest\OcRestClient the opencast REST Client instance */ + public $opencastrestclient; + + /** @var array array of supported api levels */ + private static $supportedapilevel; + + /** + * Returns the sortparam string + * @param array $params + * @return string + */ + public static function get_sort_param($params) { + if (empty($params)) { + return ''; + } + + foreach ($params as $key => $sortorder) { + $sortdir = (SORT_ASC == $sortorder) ? 'ASC' : 'DESC'; + return "&sort={$key}:" . $sortdir; + } + return ''; + } + + /** + * Returns the COURSE_ACL_ROLE-prfix + * @return string + */ + public static function get_course_acl_role_prefix() { + return "ROLE_GROUP_MOODLE_COURSE_"; + } + + /** + * Returns the course ACL role for the given course + * @param int $courseid the courseid + * @return string the acl role + */ + public static function get_course_acl_role($courseid) { + return self::get_course_acl_role_prefix(). $courseid; + } + + /** + * Returns the course ACL group identifier for the given course + * @param int $courseid the courseid + * @return string the course ACL group identifier + */ + public static function get_course_acl_group_identifier($courseid) { + return "moodle_course_" . $courseid; + } + + /** + * Returns the course ACL group name for the given course + * @param int $courseid the course id + * @return string the course ACL group name + */ + public static function get_course_acl_group_name($courseid) { + return "Moodle_Course_" . $courseid; + } + + /** + * Returns the course series title prefix + * @return string the course series title prefix + */ + public static function get_courses_series_title_prefix() { + return "Course_Series_"; + } + + /** + * Returns the course series title for a given course + * @param int $courseid the courseid + * @return string the course series title + */ + public static function get_courses_series_title($courseid) { + return self::get_courses_series_title_prefix() . $courseid; + } + + /** + * Returns the real api or test api depending on the environment. + * + * @param int|null $instanceid + * Opencast instance id. + * + * @param array $settings + * @param array $customconfigs + * @param boolean $enableingest whether to enable ingest upload. + * + * @return api|api_testable + * + * @throws \dml_exception + * @throws \moodle_exception + */ + public static function get_instance($instanceid = null, + $settings = [], + $customconfigs = [], + $enableingest = false) { + + if (self::use_test_api() === true) { + $apitestable = new api_testable($instanceid, $enableingest); + return $apitestable; + } + + return new api($instanceid, $settings, $customconfigs, $enableingest); + } + + /** + * Returns, whether the test api should be used. + * + * @return bool + * @throws \dml_exception + */ + private static function use_test_api(): bool { + if (defined('BEHAT_SITE_RUNNING') && BEHAT_SITE_RUNNING) { + $defaultocinstance = settings_api::get_default_ocinstance(); + if ($defaultocinstance === null) { + return false; + } + + $defaultocinstanceapiurl = settings_api::get_apiurl($defaultocinstance->id); + if ($defaultocinstanceapiurl === false) { + return false; + } + + if ($defaultocinstanceapiurl === 'http://testapi:8080') { + return true; + } + } + + return false; + } + + /** + * Constructor of the Opencast API. + * + * @param int|null $instanceid + * Opencast instance id. + * + * @param array $settings + * Additional curl settings. + * + * @param array $customconfigs + * Custom api config. + * + * @param boolean $enableingest whether to enable ingest upload. + * + * @throws \dml_exception + * @throws \moodle_exception + */ + public function __construct($instanceid = null, + $settings = [], + $customconfigs = [], + $enableingest = false) { + // Allow access to local ips. + $settings['ignoresecurity'] = true; + parent::__construct($settings); + + $instanceid = intval($instanceid); + + // If there is no custom configs to set, we go for the stored configs. + if (empty($customconfigs)) { + $defaultocinstance = settings_api::get_default_ocinstance(); + if ($defaultocinstance === null) { + throw new \dml_exception('dmlreadexception', null, + 'No default Opencast instance is defined.'); + } + + $storedconfigocinstanceid = !$instanceid ? $defaultocinstance->id : $instanceid; + + $this->username = settings_api::get_apiusername($storedconfigocinstanceid); + $this->password = settings_api::get_apipassword($storedconfigocinstanceid); + $this->timeout = settings_api::get_apitimeout($storedconfigocinstanceid); + $this->connecttimeout = settings_api::get_apiconnecttimeout($storedconfigocinstanceid); + $this->baseurl = settings_api::get_apiurl($storedconfigocinstanceid); + + if (empty($this->username)) { + throw new empty_configuration_exception('apiusernameempty', 'tool_opencast'); + } + + if (empty($this->password)) { + throw new empty_configuration_exception('apipasswordempty', 'tool_opencast'); + } + } else { + // When user wanted to use the api class but not with the stored configs. + if (array_key_exists('apiurl', $customconfigs)) { + $this->baseurl = $customconfigs['apiurl']; + } + + if (array_key_exists('apiusername', $customconfigs)) { + $this->username = $customconfigs['apiusername']; + } + + if (array_key_exists('apipassword', $customconfigs)) { + $this->password = $customconfigs['apipassword']; + } + + if (array_key_exists('apitimeout', $customconfigs)) { + $this->timeout = $customconfigs['apitimeout']; + } + + if (array_key_exists('apiconnecttimeout', $customconfigs)) { + $this->connecttimeout = $customconfigs['apiconnecttimeout']; + } + } + + // If the admin omitted the protocol part, add the HTTPS protocol on-the-fly. + if (!preg_match('/^https?:\/\//', $this->baseurl)) { + $this->baseurl = 'https://'.$this->baseurl; + } + + // The base url is a must and cannot be empty, so we check its existence for both scenarios. + if (empty($this->baseurl)) { + throw new empty_configuration_exception('apiurlempty', 'tool_opencast'); + } + + $this->setopt([ + 'CURLOPT_TIMEOUT_MS' => $this->timeout, + 'CURLOPT_CONNECTTIMEOUT_MS' => $this->connecttimeout, ]); + + $config = [ + 'url' => $this->baseurl, + 'username' => $this->username, + 'password' => $this->password, + 'timeout' => (intval($this->timeout) / 1000), + 'connect_timeout' => (intval($this->connecttimeout) / 1000), + ]; + $this->opencastapi = new \OpencastApi\Opencast($config, [], $enableingest); + $this->opencastrestclient = new \OpencastApi\Rest\OcRestClient($config); + } + + /** + * Set curl timout in milliseconds + * @param int $timeout curl timeout in milliseconds + */ + public function set_timeout($timeout) { + $this->timeout = $timeout; + $this->setopt(['CURLOPT_TIMEOUT_MS' => $this->timeout]); + } + + /** + * Set curl connect timout in milliseconds + * @param int $connecttimeout curl connect timeout in milliseconds + */ + public function set_connecttimeout($connecttimeout) { + $this->connecttimeout = $connecttimeout; + $this->setopt(['CURLOPT_CONNECTTIMEOUT_MS' => $this->connecttimeout]); + } + + /** + * Set base url. + * @param string $baseurl + */ + public function set_baseurl($baseurl) { + $this->baseurl = $baseurl; + } + + /** + * Get http status code + * + * @return int|boolean status code or false if not available. + */ + public function get_http_code() { + + $info = $this->get_info(); + if (!isset($info['http_code'])) { + return false; + } + return $info['http_code']; + } + + /** + * Get an digest authentication header. + * @param array $runwithroles if set, the request is executed within opencast assuming the user has + * the specified roles. + * + * @return array of authentification headers + * @throws \moodle_exception + */ + private function get_authentication_header($runwithroles = []) { + + $options = ['CURLOPT_HEADER' => true]; + $this->setopt($options); + + // Restrict to Roles. + if (!empty($runwithroles)) { + $header[] = "X-RUN-WITH-ROLES: " . implode(', ', $runwithroles); + $this->setHeader($header); + } + + $basicauth = base64_encode($this->username . ":" . $this->password); + + $header = []; + + $header[] = sprintf( + 'Authorization: Basic %s', $basicauth + ); + + return $header; + } + + /** + * Do a GET call to opencast API. + * + * @param string $resource path of the resource. + * @param array $runwithroles if set, the request is executed within opencast assuming the user has + * the specified roles. + * @return string JSON String of result. + * @throws \moodle_exception + */ + public function oc_get($resource, $runwithroles = []) { + $url = $this->baseurl . $resource; + + $this->resetHeader(); + $header = $this->get_authentication_header($runwithroles); + $header[] = 'Content-Type: application/json'; + $this->setHeader($header); + $this->setopt(['CURLOPT_HEADER' => false]); + + return $this->get($url); + } + + /** + * Opencast needs a fileextension for uploaded file, so add a postname + * (which the core curl module does NOT) to curl_file. + * + * @param object|\stored_file $storedfile stored file to be uploaded. + * @param string $key key identifier within the post params array of the stored file. + * @throws \moodle_exception + */ + private function add_postname($storedfile, $key) { + + $curlfile = $this->_tmp_file_post_params[$key]; + + // Ensure that file is uploaded as a curl file (PHP 5 > 5.5.0 is needed). + if (!$curlfile instanceof \CURLFile) { + throw new \moodle_exception('needphp55orhigher', 'tool_opencast'); + } + + // Extracting filename from $file->file_record->source, make sure to have a string filename! + $source = @unserialize($storedfile->get_source()); + $filename = ''; + if (is_object($source)) { + $filename = $source->source; + } else { + // If source is not a serialised object, it is a string containing only the filename. + $filename = $storedfile->get_source(); + } + $extension = pathinfo($filename, PATHINFO_EXTENSION); + + // If extension is empty, add extension base on mimetype. + if (empty($extension)) { + $extension = mimeinfo_from_type('extension', $storedfile->get_mimetype()); + $filename .= '.' . $extension; + } + + // Check mimetype. + $mimetype = mimeinfo('type', $filename); + + $curlfile->postname = $filename; + $curlfile->mime = $mimetype; + } + + /** + * Opencast needs a fileextension for uploaded file, so add a postname + * (which the core curl module does NOT) to curl_file. + * + * @param chunkupload_file $file chunkupload file to be uploaded. + * @param string $key key identifier within the post params array of the stored file. + * @throws \moodle_exception + */ + private function add_postname_chunkupload($file, $key) { + + $curlfile = $this->_tmp_file_post_params[$key]; + + // Ensure that file is uploaded as a curl file (PHP 5 > 5.5.0 is needed). + if (!$curlfile instanceof \CURLFile) { + throw new \moodle_exception('needphp55orhigher', 'tool_opencast'); + } + + $filename = $file->get_filename(); + + $extension = pathinfo($filename, PATHINFO_EXTENSION); + + // If extension is empty, add extension base on mimetype. + if (empty($extension)) { + $mimetype = file_storage::mimetype_from_file($file->get_fullpath()); + $extension = mimeinfo_from_type('extension', $mimetype); + $filename .= '.' . $extension; + } + + // Check mimetype. + $mimetype = mimeinfo('type', $filename); + + $curlfile->postname = $filename; + $curlfile->mime = $mimetype; + } + + /** + * Do a POST call to opencast API. + * + * @param string $resource path of the resource. + * @param array $params post parameters. + * @param array $runwithroles if set, the request is executed within opencast assuming the user has + * the specified roles. + * @return string JSON String of result. + * @throws \moodle_exception + */ + public function oc_post($resource, $params = [], $runwithroles = []) { + + $url = $this->baseurl . $resource; + + $this->resetHeader(); + $header = $this->get_authentication_header($runwithroles); + $header[] = "Content-Type: multipart/form-data"; + $this->setHeader($header); + $this->setopt(['CURLOPT_HEADER' => false]); + + $options['CURLOPT_POST'] = 1; + + if (is_array($params)) { + $this->_tmp_file_post_params = []; + foreach ($params as $key => $value) { + if ($value instanceof \stored_file) { + $value->add_to_curl_request($this, $key); + $this->add_postname($value, $key); + } else if (class_exists('\local_chunkupload\local\chunkupload_file') && + $value instanceof \local_chunkupload\local\chunkupload_file) { + $value->add_to_curl_request($this, $key); + $this->add_postname_chunkupload($value, $key); + } else { + $this->_tmp_file_post_params[$key] = $value; + } + } + $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; + unset($this->_tmp_file_post_params); + } else { + // The raw post data. + $options['CURLOPT_POSTFIELDS'] = $params; + } + return $this->request($url, $options); + } + + /** + * Do a PUT call to opencast API. + * + * @param string $resource path of the resource. + * @param array $params array of parameters. + * @param array $runwithroles if set, the request is executed within opencast assuming the user has + * the specified roles. + * @return string JSON String of result. + * @throws \moodle_exception + */ + public function oc_put($resource, $params = [], $runwithroles = []) { + + $url = $this->baseurl . $resource; + + $this->resetHeader(); + $header = $this->get_authentication_header($runwithroles); + $this->setHeader($header); + $this->setopt(['CURLOPT_HEADER' => false]); + + $options['CURLOPT_CUSTOMREQUEST'] = "PUT"; + if (is_array($params)) { + $this->_tmp_file_post_params = []; + foreach ($params as $key => $value) { + $this->_tmp_file_post_params[$key] = $value; + } + $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; + unset($this->_tmp_file_post_params); + } else { + // The raw post data. + $options['CURLOPT_POSTFIELDS'] = $params; + } + + return $this->request($url, $options); + } + + /** + * Do a DELETE call to opencast API. + * + * @param string $resource path of the resource. + * @param array $params array of parameters. + * @param array $runwithroles if set, the request is executed within opencast assuming the user has + * the specified roles. + * @return string JSON String of result. + * @throws \moodle_exception + */ + public function oc_delete($resource, $params = [], $runwithroles = []) { + + $url = $this->baseurl . $resource; + + $this->resetHeader(); + $header = $this->get_authentication_header($runwithroles); + $this->setHeader($header); + $this->setopt(['CURLOPT_HEADER' => false]); + + $options['CURLOPT_CUSTOMREQUEST'] = "DELETE"; + if (is_array($params)) { + $this->_tmp_file_post_params = []; + foreach ($params as $key => $value) { + $this->_tmp_file_post_params[$key] = $value; + } + $options['CURLOPT_POSTFIELDS'] = $this->_tmp_file_post_params; + unset($this->_tmp_file_post_params); + } else { + // The raw post data. + $options['CURLOPT_POSTFIELDS'] = $params; + } + + return $this->request($url, $options); + } + + /** + * Checks if the opencast version support a certain version of the External API. + * This is necessary for the decision, which opencast endpoints are used throughout this class. + * @param string $level level to check for + * @return boolean whether the given api $level is supported. + * @throws \moodle_exception + */ + public function supports_api_level($level) { + if (!self::$supportedapilevel) { + + $response = $this->opencastapi->baseApi->getVersion(); + + if ($response['code'] != 200) { + throw new \moodle_exception('Opencast system not reachable.'); + } + $versions = $response['body']; + self::$supportedapilevel = $versions->versions; + } + return is_array(self::$supportedapilevel) && in_array($level, self::$supportedapilevel); + } + + /** + * Checks if the Opencast API URL is reachable and there is an Opencast instance running on that URL. + * + * @return int|boolean http status code, if the API URL is not reachable or an Opencast instance + * is not running on that URL, and true otherwise. + */ + public function connection_test_url() { + // The "/api" resource endpoint returns key characteristics of the API such as the server name and the default version. + $response = $this->opencastapi->baseApi->noHeader()->get(); + // If the connection fails or the Opencast instance could not be found, return the http code. + $httpcode = $response['code']; + if ($httpcode === false) { + $httpcode = 404; // Not Found. + } + if ($httpcode != 200) { + return $httpcode; + } + + return true; + } + + /** + * Checks if the Opencast API username and password is valid. + * + * @return int|boolean http status code, if the API URL is not reachable, an Opencast instance + * is not running on that URL or the credentials are invalid, and true otherwise. + */ + public function connection_test_credentials() { + // The "/api" resource endpoint returns information on the logged in user. + $response = $this->opencastapi->baseApi->getUserInfo(); + $userinfo = $response['body']; + + // If the credentials are invalid, return a corresponding http code. + if (!$userinfo) { + return 400; // Bad Request. + } + + // If the connection fails or the Opencast instance could not be found, return the http code. + $httpcode = $response['code']; + if ($httpcode === false) { + $httpcode = 404; // Not Found. + } + if ($httpcode != 200) { + return $httpcode; + } + + return true; + } +} diff --git a/classes/local/environment_util.php b/classes/local/environment_util.php index a656544..ec878ad 100644 --- a/classes/local/environment_util.php +++ b/classes/local/environment_util.php @@ -1,55 +1,55 @@ -. - -namespace tool_opencast\local; - -defined('MOODLE_INTERNAL') || die; - -/** - * An environment util for the Opencast Moodle plugins. - * - * @package tool_opencast - * @copyright 2023 Matthias Kollenbroich, University of Münster - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class environment_util { - /** - * Make this class not instantiable. - */ - private function __construct() { - } - - /** - * Returns, whether the current application is a CLI application. - * - * @return bool Returns, true, if the current application is a CLI application, - * and false otherwise. - */ - public static function is_cli_application(): bool { - return http_response_code() === false; - } - - /** - * Returns, whether the current application runs in the environment of a moodle-plugin-ci workflow, - * namely, returns, whether the environment variable is_moodle_plugin_ci_workflow is defined. - * - * @return bool Returns, true, if the current application runs in the environment of a moodle-plugin-ci workflow, - * and false otherwise. - */ - public static function is_moodle_plugin_ci_workflow(): bool { - return !(getenv('is_moodle_plugin_ci_workflow') === false); - } -} +. + +namespace tool_opencast\local; + +defined('MOODLE_INTERNAL') || die; + +/** + * An environment util for the Opencast Moodle plugins. + * + * @package tool_opencast + * @copyright 2023 Matthias Kollenbroich, University of Münster + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class environment_util { + /** + * Make this class not instantiable. + */ + private function __construct() { + } + + /** + * Returns, whether the current application is a CLI application. + * + * @return bool Returns, true, if the current application is a CLI application, + * and false otherwise. + */ + public static function is_cli_application(): bool { + return http_response_code() === false; + } + + /** + * Returns, whether the current application runs in the environment of a moodle-plugin-ci workflow, + * namely, returns, whether the environment variable is_moodle_plugin_ci_workflow is defined. + * + * @return bool Returns, true, if the current application runs in the environment of a moodle-plugin-ci workflow, + * and false otherwise. + */ + public static function is_moodle_plugin_ci_workflow(): bool { + return !(getenv('is_moodle_plugin_ci_workflow') === false); + } +} diff --git a/classes/local/settings_api.php b/classes/local/settings_api.php index 9559e78..4386950 100644 --- a/classes/local/settings_api.php +++ b/classes/local/settings_api.php @@ -1,258 +1,258 @@ -. - -namespace tool_opencast\local; - -defined('MOODLE_INTERNAL') || die; - -require_once($CFG->dirroot . '/lib/filelib.php'); - -/** - * Settings API for opencast. - * - * This static class is used by the Opencast plugins, to fetch information about the settings of - * the defined Opencast instances as well as of the plugin tool_opencast itself. - * An Opencast instance is defined and configured with the admin settings of tool_opencast. - * - * @package tool_opencast - * @copyright 2022 Matthias Kollenbroich, University of Münster - * @copyright 2021 Tamara Gunkel - * @copyright 2018 Tobias Reischmann - * @copyright 2017 Andreas Wagner, SYNERGY LEARNING - * @author Andreas Wagner - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class settings_api { - - /** - * Make this class not instantiable. - */ - private function __construct() { - } - - /** - * Returns the version of the plugin tool_opencast as string - * or false, if the corresponding config was not found. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_plugin_version() { - return get_config('tool_opencast', 'version'); - } - - /** - * Returns the api url of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_apiurl(int $ocinstanceid) { - return get_config('tool_opencast', 'apiurl_' . $ocinstanceid); - } - - /** - * Returns the api username of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_apiusername(int $ocinstanceid) { - return get_config('tool_opencast', 'apiusername_' . $ocinstanceid); - } - - /** - * Returns the api password of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_apipassword(int $ocinstanceid) { - return get_config('tool_opencast', 'apipassword_' . $ocinstanceid); - } - - /** - * Returns the api timeout of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_apitimeout(int $ocinstanceid) { - return get_config('tool_opencast', 'apitimeout_' . $ocinstanceid); - } - - /** - * Returns the api connecttimeout of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_apiconnecttimeout(int $ocinstanceid) { - return get_config('tool_opencast', 'apiconnecttimeout_' . $ocinstanceid); - } - - /** - * Returns the lticonsumerkey of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_lticonsumerkey(int $ocinstanceid) { - return get_config('tool_opencast', 'lticonsumerkey_' . $ocinstanceid); - } - - /** - * Returns the lticonsumersecret of an Opencast instance as string - * or false, if the corresponding config was not found. - * - * @param int $ocinstanceid - * The id of the Opencast instance, for that the config is retrieved. - * - * @return string|bool - * The requested config as string or false, if the corresponding config was not found. - * - * @throws \dml_exception - */ - public static function get_lticonsumersecret(int $ocinstanceid) { - return get_config('tool_opencast', 'lticonsumersecret_' . $ocinstanceid); - } - - /** - * Return the Opencast instance for the passed Opencast instance id, if any. - * If no Opencast instance with this id is configured, null is returned. - * - * @param int $ocinstanceid - * The id of the requested Opencast instance. - * - * @return opencast_instance|null - * The corresponding Opencast instance or null. - */ - public static function get_ocinstance(int $ocinstanceid): ?opencast_instance { - $ocinstances = self::get_ocinstances(); - - foreach ($ocinstances as $ocinstance) { - if (intval($ocinstance->id) === intval($ocinstanceid)) { - return $ocinstance; - } - } - - return null; - } - - /** - * Returns the default Opencast instance, if any. - * If no default Opencast instance is configured, null is returned. - * - * @return opencast_instance|null - * The corresponding Opencast instance or null. - */ - public static function get_default_ocinstance(): ?opencast_instance { - $ocinstances = self::get_ocinstances(); - - foreach ($ocinstances as $ocinstance) { - if (boolval($ocinstance->isdefault) === true) { - return $ocinstance; - } - } - - return null; - } - - /** - * Returns all configured Opencast instances as array. - * - * This array contains instances of the class opencast_instance only. - * - * @return array - * All configured Opencast instances as array. - */ - public static function get_ocinstances(): array { - try { - $ocinstancesconfig = get_config('tool_opencast', 'ocinstances'); - } catch (\dml_exception $exception) { - return []; - } - - $dynamicocinstances = json_decode($ocinstancesconfig); - - $ocinstances = []; - foreach ($dynamicocinstances as $dynamicocinstance) { - $ocinstances[] = new opencast_instance($dynamicocinstance); - } - - return $ocinstances; - } - - /** - * Sets all configured Opencast instances to the passed Opencast instance, - * namely, the passed Opencast instance will be the only configured Opencast instance - * afterwards. - * - * @param \stdClass $dynamicocinstance - * The Opencast instance, to that all configured Opencast instances are set to. - */ - public static function set_ocinstances_to_ocinstance($dynamicocinstance): void { - set_config('ocinstances', json_encode([$dynamicocinstance]), 'tool_opencast'); - } - - /** - * Returns the number of configured Opencast instances. - * - * @return int - * The number of configured Opencast instances. - */ - public static function num_ocinstances(): int { - return count(self::get_ocinstances()); - } -} +. + +namespace tool_opencast\local; + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->dirroot . '/lib/filelib.php'); + +/** + * Settings API for opencast. + * + * This static class is used by the Opencast plugins, to fetch information about the settings of + * the defined Opencast instances as well as of the plugin tool_opencast itself. + * An Opencast instance is defined and configured with the admin settings of tool_opencast. + * + * @package tool_opencast + * @copyright 2022 Matthias Kollenbroich, University of Münster + * @copyright 2021 Tamara Gunkel + * @copyright 2018 Tobias Reischmann + * @copyright 2017 Andreas Wagner, SYNERGY LEARNING + * @author Andreas Wagner + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class settings_api { + + /** + * Make this class not instantiable. + */ + private function __construct() { + } + + /** + * Returns the version of the plugin tool_opencast as string + * or false, if the corresponding config was not found. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_plugin_version() { + return get_config('tool_opencast', 'version'); + } + + /** + * Returns the api url of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_apiurl(int $ocinstanceid) { + return get_config('tool_opencast', 'apiurl_' . $ocinstanceid); + } + + /** + * Returns the api username of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_apiusername(int $ocinstanceid) { + return get_config('tool_opencast', 'apiusername_' . $ocinstanceid); + } + + /** + * Returns the api password of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_apipassword(int $ocinstanceid) { + return get_config('tool_opencast', 'apipassword_' . $ocinstanceid); + } + + /** + * Returns the api timeout of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_apitimeout(int $ocinstanceid) { + return get_config('tool_opencast', 'apitimeout_' . $ocinstanceid); + } + + /** + * Returns the api connecttimeout of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_apiconnecttimeout(int $ocinstanceid) { + return get_config('tool_opencast', 'apiconnecttimeout_' . $ocinstanceid); + } + + /** + * Returns the lticonsumerkey of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_lticonsumerkey(int $ocinstanceid) { + return get_config('tool_opencast', 'lticonsumerkey_' . $ocinstanceid); + } + + /** + * Returns the lticonsumersecret of an Opencast instance as string + * or false, if the corresponding config was not found. + * + * @param int $ocinstanceid + * The id of the Opencast instance, for that the config is retrieved. + * + * @return string|bool + * The requested config as string or false, if the corresponding config was not found. + * + * @throws \dml_exception + */ + public static function get_lticonsumersecret(int $ocinstanceid) { + return get_config('tool_opencast', 'lticonsumersecret_' . $ocinstanceid); + } + + /** + * Return the Opencast instance for the passed Opencast instance id, if any. + * If no Opencast instance with this id is configured, null is returned. + * + * @param int $ocinstanceid + * The id of the requested Opencast instance. + * + * @return opencast_instance|null + * The corresponding Opencast instance or null. + */ + public static function get_ocinstance(int $ocinstanceid): ?opencast_instance { + $ocinstances = self::get_ocinstances(); + + foreach ($ocinstances as $ocinstance) { + if (intval($ocinstance->id) === intval($ocinstanceid)) { + return $ocinstance; + } + } + + return null; + } + + /** + * Returns the default Opencast instance, if any. + * If no default Opencast instance is configured, null is returned. + * + * @return opencast_instance|null + * The corresponding Opencast instance or null. + */ + public static function get_default_ocinstance(): ?opencast_instance { + $ocinstances = self::get_ocinstances(); + + foreach ($ocinstances as $ocinstance) { + if (boolval($ocinstance->isdefault) === true) { + return $ocinstance; + } + } + + return null; + } + + /** + * Returns all configured Opencast instances as array. + * + * This array contains instances of the class opencast_instance only. + * + * @return array + * All configured Opencast instances as array. + */ + public static function get_ocinstances(): array { + try { + $ocinstancesconfig = get_config('tool_opencast', 'ocinstances'); + } catch (\dml_exception $exception) { + return []; + } + + $dynamicocinstances = json_decode($ocinstancesconfig); + + $ocinstances = []; + foreach ($dynamicocinstances as $dynamicocinstance) { + $ocinstances[] = new opencast_instance($dynamicocinstance); + } + + return $ocinstances; + } + + /** + * Sets all configured Opencast instances to the passed Opencast instance, + * namely, the passed Opencast instance will be the only configured Opencast instance + * afterwards. + * + * @param \stdClass $dynamicocinstance + * The Opencast instance, to that all configured Opencast instances are set to. + */ + public static function set_ocinstances_to_ocinstance($dynamicocinstance): void { + set_config('ocinstances', json_encode([$dynamicocinstance]), 'tool_opencast'); + } + + /** + * Returns the number of configured Opencast instances. + * + * @return int + * The number of configured Opencast instances. + */ + public static function num_ocinstances(): int { + return count(self::get_ocinstances()); + } +} diff --git a/classes/settings/admin_settings_builder.php b/classes/settings/admin_settings_builder.php index 6f1a5ff..1ec838f 100644 --- a/classes/settings/admin_settings_builder.php +++ b/classes/settings/admin_settings_builder.php @@ -1,455 +1,455 @@ -. - -namespace tool_opencast\settings; - -use tool_opencast\local\settings_api; - -/** - * Static admin setting builder class, which is used, to create and to add admin settings for tool_opencast. - * - * @package tool_opencast - * @copyright 2022 Matthias Kollenbroich, University of Münster - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class admin_settings_builder { - /** - * The name of the plugin tool_opencast. - * - * @var string - */ - private const PLUGINNAME = 'tool_opencast'; - - /** - * The default Opencast instances config. - * - * @var string - */ - private const DEFAULTINSTANCESCONFIG = '[{"id":1,"name":"Default","isvisible":true,"isdefault":true}]'; - - /** - * Make this class not instantiable. - */ - private function __construct() { - } - - /** - * Creates the settings for all Opencast instances and adds them to the admin settings page. - * - * @return void - */ - public static function create_settings(): void { - $instances = settings_api::get_ocinstances(); - - global $ADMIN; - if (!$ADMIN->fulltree) { - self::create_settings_no_fulltree($instances); - return; - } - - self::create_settings_fulltree($instances); - } - - /** - * Creates the settings for all Opencast instances for no fulltree and adds them to the admin settings page. - * - * @param array $instances - * The Opencast instances. - * - * @return void - */ - private static function create_settings_no_fulltree($instances): void { - self::add_admin_category(); - self::add_admin_settingpage('tool_opencast_instances', 'ocinstances'); - - if (count($instances) <= 1) { - self::add_admin_settingpage('tool_opencast_configuration', 'configuration'); - return; - } - - foreach ($instances as $instance) { - self::add_admin_settingpage('tool_opencast_configuration_' . $instance->id, - 'configuration_instance', $instance->name); - } - } - - /** - * Creates the settings for all Opencast instances for fulltree and adds them to the admin settings page. - * - * @param array $instances - * The Opencast instances. - * - * @return void - */ - private static function create_settings_fulltree($instances): void { - self::add_admin_category(); - self::add_admin_instances_config(); - - foreach ($instances as $instance) { - $instanceid = $instance->id; - - if (count($instances) <= 1) { - $settings = self::create_admin_settingpage('tool_opencast_configuration', - 'configuration'); - } else { - $settings = self::create_admin_settingpage('tool_opencast_configuration_' . $instanceid, - 'configuration_instance', $instance->name); - } - - self::add_notification_banner_for_demo_instance($settings, $instanceid); - self::add_config_settings_fulltree($settings, $instanceid); - self::add_connection_test_tool($settings, $instanceid); - - self::include_admin_settingpage($settings); - } - } - - /** - * Adds an admin category to the admin settings page. - * - * @return void - */ - private static function add_admin_category(): void { - $category = new \admin_category(self::PLUGINNAME, - new \lang_string('pluginname', self::PLUGINNAME) - ); - - global $ADMIN; - $ADMIN->add('tools', $category); - } - - /** - * Adds an admin settingpage to the admin settings page. - * - * @param string $name - * The internal name for this settingpage. - * - * @param string $stringidentifier - * The identifier for the string, that is used for the displayed name for this settingpage. - * - * @param stdClass|array $stringidentifierarguments - * Optional arguments, which the string for the passed identifier requires, - * that is used for the displayed name for this settingpage. - * - * @return void - */ - private static function add_admin_settingpage(string $name, string $stringidentifier, - $stringidentifierarguments = null): void { - $settingpage = self::create_admin_settingpage($name, $stringidentifier, $stringidentifierarguments); - self::include_admin_settingpage($settingpage); - } - - /** - * Creates an admin settingpage. - * - * @param string $name - * The internal name for this settingpage. - * - * @param string $stringidentifier - * The identifier for the string, that is used for the displayed name for this settingpage. - * - * @param stdClass|array $stringidentifierarguments - * Optional arguments, which the string for the passed identifier requires, - * that is used for the displayed name for this settingpage. - * - * @return \admin_settingpage - * The created admin settingpage. - */ - private static function create_admin_settingpage(string $name, string $stringidentifier, - $stringidentifierarguments = null): \admin_settingpage { - return new \admin_settingpage($name, - new \lang_string($stringidentifier, self::PLUGINNAME, $stringidentifierarguments) - ); - } - - /** - * Includes an admin settingpage in the admin settings page. - * - * @param \admin_settingpage $settingpage - * The admin settingpage to include. - * - * @return void - */ - private static function include_admin_settingpage(\admin_settingpage $settingpage): void { - global $ADMIN; - $ADMIN->add(self::PLUGINNAME, $settingpage); - } - - /** - * Adds the admin instances config to the admin settings page. - * - * The admin instances config is part of the admin settings and - * consists of the table with its description of added Opencast instances as well as - * of the button for adding a new Opencast instance. - * - * Note, that this function calls self::require_amds with the id of the added admin instances config. - * - * @return void - */ - private static function add_admin_instances_config(): void { - $instancesconfig = new admin_setting_configtextwithvalidation( - 'tool_opencast/ocinstances', - get_string('ocinstances', self::PLUGINNAME), - get_string('ocinstancesdesc', self::PLUGINNAME), - self::DEFAULTINSTANCESCONFIG - ); - - self::require_amds($instancesconfig->get_id()); - - $instancessettings = new \admin_settingpage( - 'tool_opencast_instances', - new \lang_string('ocinstances', self::PLUGINNAME) - ); - - $instancessettings->add($instancesconfig); - - $instancessettings->add(new admin_setting_configeditabletable( - 'tool_opencast/instancestable', - 'instancestable') - ); - - global $ADMIN; - $ADMIN->add(self::PLUGINNAME, $instancessettings); - } - - /** - * Requires jquery, amds and css for $PAGE. - * - * @param string $pluginnameid - * The id of the admin instances config of the admin settings of the plugin. - * - * @return void - */ - private static function require_amds(string $pluginnameid): void { - global $PAGE; - - // Crashes, if plugins.php is opened, because css cannot be included anymore. - if ($PAGE->state === \moodle_page::STATE_IN_BODY) { - return; - } - - $PAGE->requires->jquery(); - $PAGE->requires->js_call_amd('tool_opencast/tool_testtool', 'init'); - $PAGE->requires->js_call_amd('tool_opencast/tool_settings', 'init', [$pluginnameid]); - $PAGE->requires->css('/admin/tool/opencast/css/tabulator.min.css'); - $PAGE->requires->css('/admin/tool/opencast/css/tabulator_bootstrap4.min.css'); - } - - /** - * Adds a notification banner to the passed admin settingpage for the passed Opencast instance id, - * if the plugin is connected to the Opencast demo server for this Opencast instance id. - * - * @param \admin_settingpage $settings - * The admin settingpage, to add a notification banner to. - * - * @param int $instanceid - * The id of the Opencast instance, for which the notification banner is added. - * - * @return void - */ - private static function add_notification_banner_for_demo_instance(\admin_settingpage $settings, - int $instanceid): void { - $instanceapiurl = settings_api::get_apiurl($instanceid); - - // Show a notification banner, if the plugin is connected to the Opencast demo server. - if (strpos($instanceapiurl, 'stable.opencast.org') !== false) { - global $OUTPUT; - $demoservernotification = $OUTPUT->notification( - get_string('demoservernotification', self::PLUGINNAME), - \core\output\notification::NOTIFY_WARNING - ); - - $settings->add(new \admin_setting_heading( - 'tool_opencast/demoservernotification_' . $instanceid, - '', - $demoservernotification) - ); - } - } - - /** - * Adds the config settings for fulltree to the passed admin settingpage for the - * passed Opencast instance id. - * - * @param \admin_settingpage $settings - * The admin settingpage, the config settings are added to. - * - * @param int $instanceid - * The Opencast instance id, to that the added settings are associated. - * - * @return void - */ - private static function add_config_settings_fulltree(\admin_settingpage $settings, - int $instanceid): void { - self::add_admin_setting_configtext($settings, - 'tool_opencast/apiurl_' . $instanceid, - 'apiurl', 'apiurldesc', - 'https://stable.opencast.org', - PARAM_URL - ); - - self::add_admin_setting_configtext($settings, - 'tool_opencast/apiusername_' . $instanceid, - 'apiusername', 'apiusernamedesc', - 'admin' - ); - - self::add_admin_setting_configpasswordunmask($settings, - 'tool_opencast/apipassword_' . $instanceid, - 'apipassword', 'apipassworddesc', - 'opencast' - ); - - self::add_admin_setting_configtext($settings, - 'tool_opencast/lticonsumerkey_' . $instanceid, - 'lticonsumerkey', 'lticonsumerkey_desc', - '' - ); - - self::add_admin_setting_configpasswordunmask($settings, - 'tool_opencast/lticonsumersecret_' . $instanceid, - 'lticonsumersecret', 'lticonsumersecret_desc', - '' - ); - - self::add_admin_setting_configtext($settings, - 'tool_opencast/apitimeout_' . $instanceid, - 'timeout', 'timeoutdesc', - '2000', - PARAM_INT - ); - - self::add_admin_setting_configtext($settings, - 'tool_opencast/apiconnecttimeout_' . $instanceid, - 'connecttimeout', 'connecttimeoutdesc', - '1000', - PARAM_INT - ); - } - - /** - * Adds an admin setting configtext to the passed admin settingpage. - * - * @param \admin_settingpage $settings - * The admin settingpage, the configtext is added to. - * - * @param string $name - * The internal name for the configtext. - * - * @param string $visiblenameidentifier - * The identifier for the string, that is used for the visible name of the configtext. - * - * @param string $descriptionidentifier - * The identifier for the string, that is used for the visible description of the configtext. - * - * @param string $defaultsetting - * The default setting for the configtext. - * - * @param mixed $paramtype - * The parameter type of the configtext. - * - * @return void - */ - private static function add_admin_setting_configtext(\admin_settingpage $settings, - string $name, - string $visiblenameidentifier, - string $descriptionidentifier, - string $defaultsetting, - $paramtype = PARAM_RAW): void { - $settingconfigtext = new \admin_setting_configtext( - $name, - get_string($visiblenameidentifier, self::PLUGINNAME), - get_string($descriptionidentifier, self::PLUGINNAME), - $defaultsetting, - $paramtype - ); - $settings->add($settingconfigtext); - } - - /** - * Adds an admin setting configpasswordunmask to the passed admin settingpage. - * - * @param \admin_settingpage $settings - * The admin settingpage, the configpasswordunmask is added to. - * - * @param string $name - * The internal name for the configpasswordunmask. - * - * @param string $visiblenameidentifier - * The identifier for the string, that is used for the visible name of the configpasswordunmask. - * - * @param string $descriptionidentifier - * The identifier for the string, that is used for the visible description of the configpasswordunmask. - * - * @param string $defaultsetting - * The default password for the configpasswordunmask. - * - * @return void - */ - private static function add_admin_setting_configpasswordunmask(\admin_settingpage $settings, - string $name, - string $visiblenameidentifier, - string $descriptionidentifier, - string $defaultsetting): void { - $settingconfigpasswordunmask = new \admin_setting_configpasswordunmask( - $name, - get_string($visiblenameidentifier, self::PLUGINNAME), - get_string($descriptionidentifier, self::PLUGINNAME), - $defaultsetting - ); - $settings->add($settingconfigpasswordunmask); - } - - /** - * Adds the connection test tool to the passed admin settingpage for the passed Opencast instance id, - * where a button with its description is added to the passed admin settingpage, - * that can be clicked, to perform this connection test to the corresponding Opencast instance. - * - * A popup is shown, containing the results of this connection test, if this connection test is completed. - * - * @param \admin_settingpage $settings - * The admin settingpage, to add the connection test tool to. - * - * @param int $instanceid - * The id of the Opencast instance, for which the connection test tool is added and the connection test - * is performed. - * - * @return void - */ - private static function add_connection_test_tool(\admin_settingpage $settings, - int $instanceid): void { - // Provide Connection Test Tool button. - $attributes = [ - 'class' => 'btn btn-warning disabled testtool-modal', - 'disabled' => 'disabled', - 'title' => get_string('testtooldisabledbuttontitle', self::PLUGINNAME), - 'data-instanceid' => strval($instanceid), - ]; - - $connectiontoolbutton = \html_writer::tag( - 'button', - get_string('testtoolurl', self::PLUGINNAME), - $attributes - ); - - // Place the button inside the header description. - $settings->add(new \admin_setting_heading( - 'tool_opencast/testtoolexternalpage', - get_string('testtoolheader', self::PLUGINNAME), - get_string('testtoolheaderdesc', self::PLUGINNAME, $connectiontoolbutton)) - ); - } -} +. + +namespace tool_opencast\settings; + +use tool_opencast\local\settings_api; + +/** + * Static admin setting builder class, which is used, to create and to add admin settings for tool_opencast. + * + * @package tool_opencast + * @copyright 2022 Matthias Kollenbroich, University of Münster + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class admin_settings_builder { + /** + * The name of the plugin tool_opencast. + * + * @var string + */ + private const PLUGINNAME = 'tool_opencast'; + + /** + * The default Opencast instances config. + * + * @var string + */ + private const DEFAULTINSTANCESCONFIG = '[{"id":1,"name":"Default","isvisible":true,"isdefault":true}]'; + + /** + * Make this class not instantiable. + */ + private function __construct() { + } + + /** + * Creates the settings for all Opencast instances and adds them to the admin settings page. + * + * @return void + */ + public static function create_settings(): void { + $instances = settings_api::get_ocinstances(); + + global $ADMIN; + if (!$ADMIN->fulltree) { + self::create_settings_no_fulltree($instances); + return; + } + + self::create_settings_fulltree($instances); + } + + /** + * Creates the settings for all Opencast instances for no fulltree and adds them to the admin settings page. + * + * @param array $instances + * The Opencast instances. + * + * @return void + */ + private static function create_settings_no_fulltree($instances): void { + self::add_admin_category(); + self::add_admin_settingpage('tool_opencast_instances', 'ocinstances'); + + if (count($instances) <= 1) { + self::add_admin_settingpage('tool_opencast_configuration', 'configuration'); + return; + } + + foreach ($instances as $instance) { + self::add_admin_settingpage('tool_opencast_configuration_' . $instance->id, + 'configuration_instance', $instance->name); + } + } + + /** + * Creates the settings for all Opencast instances for fulltree and adds them to the admin settings page. + * + * @param array $instances + * The Opencast instances. + * + * @return void + */ + private static function create_settings_fulltree($instances): void { + self::add_admin_category(); + self::add_admin_instances_config(); + + foreach ($instances as $instance) { + $instanceid = $instance->id; + + if (count($instances) <= 1) { + $settings = self::create_admin_settingpage('tool_opencast_configuration', + 'configuration'); + } else { + $settings = self::create_admin_settingpage('tool_opencast_configuration_' . $instanceid, + 'configuration_instance', $instance->name); + } + + self::add_notification_banner_for_demo_instance($settings, $instanceid); + self::add_config_settings_fulltree($settings, $instanceid); + self::add_connection_test_tool($settings, $instanceid); + + self::include_admin_settingpage($settings); + } + } + + /** + * Adds an admin category to the admin settings page. + * + * @return void + */ + private static function add_admin_category(): void { + $category = new \admin_category(self::PLUGINNAME, + new \lang_string('pluginname', self::PLUGINNAME) + ); + + global $ADMIN; + $ADMIN->add('tools', $category); + } + + /** + * Adds an admin settingpage to the admin settings page. + * + * @param string $name + * The internal name for this settingpage. + * + * @param string $stringidentifier + * The identifier for the string, that is used for the displayed name for this settingpage. + * + * @param stdClass|array $stringidentifierarguments + * Optional arguments, which the string for the passed identifier requires, + * that is used for the displayed name for this settingpage. + * + * @return void + */ + private static function add_admin_settingpage(string $name, string $stringidentifier, + $stringidentifierarguments = null): void { + $settingpage = self::create_admin_settingpage($name, $stringidentifier, $stringidentifierarguments); + self::include_admin_settingpage($settingpage); + } + + /** + * Creates an admin settingpage. + * + * @param string $name + * The internal name for this settingpage. + * + * @param string $stringidentifier + * The identifier for the string, that is used for the displayed name for this settingpage. + * + * @param stdClass|array $stringidentifierarguments + * Optional arguments, which the string for the passed identifier requires, + * that is used for the displayed name for this settingpage. + * + * @return \admin_settingpage + * The created admin settingpage. + */ + private static function create_admin_settingpage(string $name, string $stringidentifier, + $stringidentifierarguments = null): \admin_settingpage { + return new \admin_settingpage($name, + new \lang_string($stringidentifier, self::PLUGINNAME, $stringidentifierarguments) + ); + } + + /** + * Includes an admin settingpage in the admin settings page. + * + * @param \admin_settingpage $settingpage + * The admin settingpage to include. + * + * @return void + */ + private static function include_admin_settingpage(\admin_settingpage $settingpage): void { + global $ADMIN; + $ADMIN->add(self::PLUGINNAME, $settingpage); + } + + /** + * Adds the admin instances config to the admin settings page. + * + * The admin instances config is part of the admin settings and + * consists of the table with its description of added Opencast instances as well as + * of the button for adding a new Opencast instance. + * + * Note, that this function calls self::require_amds with the id of the added admin instances config. + * + * @return void + */ + private static function add_admin_instances_config(): void { + $instancesconfig = new admin_setting_configtextwithvalidation( + 'tool_opencast/ocinstances', + get_string('ocinstances', self::PLUGINNAME), + get_string('ocinstancesdesc', self::PLUGINNAME), + self::DEFAULTINSTANCESCONFIG + ); + + self::require_amds($instancesconfig->get_id()); + + $instancessettings = new \admin_settingpage( + 'tool_opencast_instances', + new \lang_string('ocinstances', self::PLUGINNAME) + ); + + $instancessettings->add($instancesconfig); + + $instancessettings->add(new admin_setting_configeditabletable( + 'tool_opencast/instancestable', + 'instancestable') + ); + + global $ADMIN; + $ADMIN->add(self::PLUGINNAME, $instancessettings); + } + + /** + * Requires jquery, amds and css for $PAGE. + * + * @param string $pluginnameid + * The id of the admin instances config of the admin settings of the plugin. + * + * @return void + */ + private static function require_amds(string $pluginnameid): void { + global $PAGE; + + // Crashes, if plugins.php is opened, because css cannot be included anymore. + if ($PAGE->state === \moodle_page::STATE_IN_BODY) { + return; + } + + $PAGE->requires->jquery(); + $PAGE->requires->js_call_amd('tool_opencast/tool_testtool', 'init'); + $PAGE->requires->js_call_amd('tool_opencast/tool_settings', 'init', [$pluginnameid]); + $PAGE->requires->css('/admin/tool/opencast/css/tabulator.min.css'); + $PAGE->requires->css('/admin/tool/opencast/css/tabulator_bootstrap4.min.css'); + } + + /** + * Adds a notification banner to the passed admin settingpage for the passed Opencast instance id, + * if the plugin is connected to the Opencast demo server for this Opencast instance id. + * + * @param \admin_settingpage $settings + * The admin settingpage, to add a notification banner to. + * + * @param int $instanceid + * The id of the Opencast instance, for which the notification banner is added. + * + * @return void + */ + private static function add_notification_banner_for_demo_instance(\admin_settingpage $settings, + int $instanceid): void { + $instanceapiurl = settings_api::get_apiurl($instanceid); + + // Show a notification banner, if the plugin is connected to the Opencast demo server. + if (strpos($instanceapiurl, 'stable.opencast.org') !== false) { + global $OUTPUT; + $demoservernotification = $OUTPUT->notification( + get_string('demoservernotification', self::PLUGINNAME), + \core\output\notification::NOTIFY_WARNING + ); + + $settings->add(new \admin_setting_heading( + 'tool_opencast/demoservernotification_' . $instanceid, + '', + $demoservernotification) + ); + } + } + + /** + * Adds the config settings for fulltree to the passed admin settingpage for the + * passed Opencast instance id. + * + * @param \admin_settingpage $settings + * The admin settingpage, the config settings are added to. + * + * @param int $instanceid + * The Opencast instance id, to that the added settings are associated. + * + * @return void + */ + private static function add_config_settings_fulltree(\admin_settingpage $settings, + int $instanceid): void { + self::add_admin_setting_configtext($settings, + 'tool_opencast/apiurl_' . $instanceid, + 'apiurl', 'apiurldesc', + 'https://stable.opencast.org', + PARAM_URL + ); + + self::add_admin_setting_configtext($settings, + 'tool_opencast/apiusername_' . $instanceid, + 'apiusername', 'apiusernamedesc', + 'admin' + ); + + self::add_admin_setting_configpasswordunmask($settings, + 'tool_opencast/apipassword_' . $instanceid, + 'apipassword', 'apipassworddesc', + 'opencast' + ); + + self::add_admin_setting_configtext($settings, + 'tool_opencast/lticonsumerkey_' . $instanceid, + 'lticonsumerkey', 'lticonsumerkey_desc', + '' + ); + + self::add_admin_setting_configpasswordunmask($settings, + 'tool_opencast/lticonsumersecret_' . $instanceid, + 'lticonsumersecret', 'lticonsumersecret_desc', + '' + ); + + self::add_admin_setting_configtext($settings, + 'tool_opencast/apitimeout_' . $instanceid, + 'timeout', 'timeoutdesc', + '2000', + PARAM_INT + ); + + self::add_admin_setting_configtext($settings, + 'tool_opencast/apiconnecttimeout_' . $instanceid, + 'connecttimeout', 'connecttimeoutdesc', + '1000', + PARAM_INT + ); + } + + /** + * Adds an admin setting configtext to the passed admin settingpage. + * + * @param \admin_settingpage $settings + * The admin settingpage, the configtext is added to. + * + * @param string $name + * The internal name for the configtext. + * + * @param string $visiblenameidentifier + * The identifier for the string, that is used for the visible name of the configtext. + * + * @param string $descriptionidentifier + * The identifier for the string, that is used for the visible description of the configtext. + * + * @param string $defaultsetting + * The default setting for the configtext. + * + * @param mixed $paramtype + * The parameter type of the configtext. + * + * @return void + */ + private static function add_admin_setting_configtext(\admin_settingpage $settings, + string $name, + string $visiblenameidentifier, + string $descriptionidentifier, + string $defaultsetting, + $paramtype = PARAM_RAW): void { + $settingconfigtext = new \admin_setting_configtext( + $name, + get_string($visiblenameidentifier, self::PLUGINNAME), + get_string($descriptionidentifier, self::PLUGINNAME), + $defaultsetting, + $paramtype + ); + $settings->add($settingconfigtext); + } + + /** + * Adds an admin setting configpasswordunmask to the passed admin settingpage. + * + * @param \admin_settingpage $settings + * The admin settingpage, the configpasswordunmask is added to. + * + * @param string $name + * The internal name for the configpasswordunmask. + * + * @param string $visiblenameidentifier + * The identifier for the string, that is used for the visible name of the configpasswordunmask. + * + * @param string $descriptionidentifier + * The identifier for the string, that is used for the visible description of the configpasswordunmask. + * + * @param string $defaultsetting + * The default password for the configpasswordunmask. + * + * @return void + */ + private static function add_admin_setting_configpasswordunmask(\admin_settingpage $settings, + string $name, + string $visiblenameidentifier, + string $descriptionidentifier, + string $defaultsetting): void { + $settingconfigpasswordunmask = new \admin_setting_configpasswordunmask( + $name, + get_string($visiblenameidentifier, self::PLUGINNAME), + get_string($descriptionidentifier, self::PLUGINNAME), + $defaultsetting + ); + $settings->add($settingconfigpasswordunmask); + } + + /** + * Adds the connection test tool to the passed admin settingpage for the passed Opencast instance id, + * where a button with its description is added to the passed admin settingpage, + * that can be clicked, to perform this connection test to the corresponding Opencast instance. + * + * A popup is shown, containing the results of this connection test, if this connection test is completed. + * + * @param \admin_settingpage $settings + * The admin settingpage, to add the connection test tool to. + * + * @param int $instanceid + * The id of the Opencast instance, for which the connection test tool is added and the connection test + * is performed. + * + * @return void + */ + private static function add_connection_test_tool(\admin_settingpage $settings, + int $instanceid): void { + // Provide Connection Test Tool button. + $attributes = [ + 'class' => 'btn btn-warning disabled testtool-modal', + 'disabled' => 'disabled', + 'title' => get_string('testtooldisabledbuttontitle', self::PLUGINNAME), + 'data-instanceid' => strval($instanceid), + ]; + + $connectiontoolbutton = \html_writer::tag( + 'button', + get_string('testtoolurl', self::PLUGINNAME), + $attributes + ); + + // Place the button inside the header description. + $settings->add(new \admin_setting_heading( + 'tool_opencast/testtoolexternalpage', + get_string('testtoolheader', self::PLUGINNAME), + get_string('testtoolheaderdesc', self::PLUGINNAME, $connectiontoolbutton)) + ); + } +} diff --git a/db/upgrade.php b/db/upgrade.php index 0d56697..12f9781 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,230 +1,230 @@ -. - -/** - * Upgrade.php for tool_opencast. - * - * @package tool_opencast - * @copyright 2018 Tobias Reischmann WWU - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -use tool_opencast\local\settings_api; - -/** - * Execute opencast upgrade from the given old version - * - * @param int $oldversion - * @return bool - */ -function xmldb_tool_opencast_upgrade($oldversion) { - global $DB; - $dbman = $DB->get_manager(); - if ($oldversion < 2018013002) { - - // Define table tool_opencast_series to be created. - $table = new xmldb_table('tool_opencast_series'); - - // Adding fields to table tool_opencast_series. - $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); - $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); - $table->add_field('series', XMLDB_TYPE_CHAR, '36', null, XMLDB_NOTNULL, null, null); - - // Adding keys to table tool_opencast_series. - $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); - $table->add_key('fk_course', XMLDB_KEY_FOREIGN_UNIQUE, ['courseid'], 'course', ['id']); - - // Conditionally launch create table for tool_opencast_series. - if (!$dbman->table_exists($table)) { - $dbman->create_table($table); - } - - // Opencast savepoint reached. - upgrade_plugin_savepoint(true, 2018013002, 'error', 'opencast'); - } - - if ($oldversion < 2021091200) { - // Architecture change: Multiple series per course. - $table = new xmldb_table('tool_opencast_series'); - $field = new xmldb_field('isdefault', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 1, 'series'); - - // Conditionally launch add field default. - if (!$dbman->field_exists($table, $field)) { - $dbman->add_field($table, $field); - } - - // Remove unique key. - $dbman->drop_key($table, new xmldb_key('fk_course', XMLDB_KEY_FOREIGN_UNIQUE, ['courseid'], 'course', ['id'])); - - // Check that each course has only exactly one series. - $sql = "SELECT courseid, COUNT(id) FROM {tool_opencast_series} GROUP BY courseid "; - $courseentries = $DB->get_records_sql($sql); - foreach ($courseentries as $entry) { - if (intval($entry->count) > 1) { - // This should not happen. But if it does, simply select the first one as default. - // 1. Set all to 0. - $DB->set_field('tool_opencast_series', 'isdefault', 0, ['courseid' => $entry->courseid]); - - // 2. Set one to 1. - $records = $DB->get_records('tool_opencast_series'); - $firstrecord = array_values($records)[0]; - $firstrecord->isdefault = 1; - $DB->update_record('tool_opencast_series', $firstrecord); - } - } - - // Architecture change: Multiple OC instances. - // Create default instance. - $ocinstance = new \stdClass(); - $ocinstance->id = 1; - $ocinstance->name = 'Default'; - $ocinstance->isvisible = true; - $ocinstance->isdefault = true; - settings_api::set_ocinstances_to_ocinstance($ocinstance); - - // Add new field to series table. - $table = new xmldb_table('tool_opencast_series'); - $field = new xmldb_field('ocinstanceid', XMLDB_TYPE_INTEGER, '10'); - if (!$dbman->field_exists($table, $field)) { - $dbman->add_field($table, $field); - } - - // Use default series for current series. - $DB->set_field('tool_opencast_series', 'ocinstanceid', 1); - - // Set instance field to not null. - $field = new xmldb_field('ocinstanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL); - $dbman->change_field_notnull($table, $field); - - // Add new foreign key and unique constraint. - $table->add_key('fk_course', XMLDB_KEY_FOREIGN, ['courseid'], 'course', ['id']); - $table->add_key('unq_course_series_ocinstance', XMLDB_KEY_UNIQUE, ['courseid', 'ocinstanceid', 'series']); - - // Opencast savepoint reached. - upgrade_plugin_savepoint(true, 2021091200, 'tool', 'opencast'); - } - - if ($oldversion < 2021102700) { - $columns = $DB->get_columns('tool_opencast_series'); - $isdefaultfield = $columns['isdefault']; - - if ($isdefaultfield->__get("type") == "bytea") { - // Changing type of field isdefault on table tool_opencast_series to int. - $table = new xmldb_table('tool_opencast_series'); - $oldfield = new xmldb_field('isdefault', XMLDB_TYPE_BINARY); - $dbman->rename_field($table, $oldfield, 'isdefault_old'); - - $newfield = new xmldb_field('isdefault', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'series'); - $dbman->add_field($table, $newfield); - - // Loop through records because casting in sql depends on database type. - foreach ($DB->get_records('tool_opencast_series') as $record) { - if ($record->isdefault_old) { - $record->isdefault = 1; - $DB->update_record('tool_opencast_series', $record); - } - } - - // Launch change of type for field isdefault. - $dbman->drop_field($table, new xmldb_field('isdefault_old')); - } - - // Opencast savepoint reached. - upgrade_plugin_savepoint(true, 2021102700, 'tool', 'opencast'); - } - - $newversion = 2023030100; - if ($oldversion < $newversion) { - if (remove_default_opencast_instance_settings_without_id() === false) { - return false; - } - - // Opencast savepoint reached. - upgrade_plugin_savepoint(true, $newversion, 'tool', 'opencast'); - } - - return true; -} - -/** - * Removes the settings of the default Opencast instance without an id in their names - * from the database and adds those settings with the corresponding id in their names - * and their previous values to the database again. - * - * @return bool - * Returns true, if this update of the database was successful, and false otherwise. - */ -function remove_default_opencast_instance_settings_without_id(): bool { - $helpersettingsname = 'apiurl'; - $pluginname = 'tool_opencast'; - - // Check, if settings without an id in their names exist (for the default Opencast instance). - $foundoldsetting = get_config($pluginname, $helpersettingsname); - if ($foundoldsetting === false) { - return true; - } - - // Fetch the default Opencast instance, if any. - $defaultocinstance = settings_api::get_default_ocinstance(); - if ($defaultocinstance === null) { - return true; - } - - $defaultocinstanceid = $defaultocinstance->id; - - try { - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiurl'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiusername'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apipassword'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'lticonsumerkey'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'lticonsumersecret'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apitimeout'); - replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiconnecttimeout'); - } catch (\dml_exception $exception) { - return false; - } - - return true; -} - -/** - * Removes the passed setting of the default Opencast instance without an id in its name - * from the database and adds that setting with the passed id in its name - * and its previous value to the database again. - * - * @param int $defaultinstanceid - * The Opencast instance id of the default Opencast instance. - * - * @param string $name - * The name of the setting to replace (without the Opencast instance id). - * - * @throws \dml_exception - */ -function replace_default_opencast_instance_setting_without_id(int $defaultinstanceid, - string $name): void { - $pluginname = 'tool_opencast'; - - $value = get_config($pluginname, $name); - if ($value === false) { - throw new \dml_exception('dmlreadexception'); - } - - if (unset_config($name, $pluginname) === false) { - throw new \dml_exception('dmlwriteexception'); - } - - set_config($name . '_' . $defaultinstanceid, $value, $pluginname); -} +. + +/** + * Upgrade.php for tool_opencast. + * + * @package tool_opencast + * @copyright 2018 Tobias Reischmann WWU + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +use tool_opencast\local\settings_api; + +/** + * Execute opencast upgrade from the given old version + * + * @param int $oldversion + * @return bool + */ +function xmldb_tool_opencast_upgrade($oldversion) { + global $DB; + $dbman = $DB->get_manager(); + if ($oldversion < 2018013002) { + + // Define table tool_opencast_series to be created. + $table = new xmldb_table('tool_opencast_series'); + + // Adding fields to table tool_opencast_series. + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); + $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); + $table->add_field('series', XMLDB_TYPE_CHAR, '36', null, XMLDB_NOTNULL, null, null); + + // Adding keys to table tool_opencast_series. + $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); + $table->add_key('fk_course', XMLDB_KEY_FOREIGN_UNIQUE, ['courseid'], 'course', ['id']); + + // Conditionally launch create table for tool_opencast_series. + if (!$dbman->table_exists($table)) { + $dbman->create_table($table); + } + + // Opencast savepoint reached. + upgrade_plugin_savepoint(true, 2018013002, 'error', 'opencast'); + } + + if ($oldversion < 2021091200) { + // Architecture change: Multiple series per course. + $table = new xmldb_table('tool_opencast_series'); + $field = new xmldb_field('isdefault', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 1, 'series'); + + // Conditionally launch add field default. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Remove unique key. + $dbman->drop_key($table, new xmldb_key('fk_course', XMLDB_KEY_FOREIGN_UNIQUE, ['courseid'], 'course', ['id'])); + + // Check that each course has only exactly one series. + $sql = "SELECT courseid, COUNT(id) FROM {tool_opencast_series} GROUP BY courseid "; + $courseentries = $DB->get_records_sql($sql); + foreach ($courseentries as $entry) { + if (intval($entry->count) > 1) { + // This should not happen. But if it does, simply select the first one as default. + // 1. Set all to 0. + $DB->set_field('tool_opencast_series', 'isdefault', 0, ['courseid' => $entry->courseid]); + + // 2. Set one to 1. + $records = $DB->get_records('tool_opencast_series'); + $firstrecord = array_values($records)[0]; + $firstrecord->isdefault = 1; + $DB->update_record('tool_opencast_series', $firstrecord); + } + } + + // Architecture change: Multiple OC instances. + // Create default instance. + $ocinstance = new \stdClass(); + $ocinstance->id = 1; + $ocinstance->name = 'Default'; + $ocinstance->isvisible = true; + $ocinstance->isdefault = true; + settings_api::set_ocinstances_to_ocinstance($ocinstance); + + // Add new field to series table. + $table = new xmldb_table('tool_opencast_series'); + $field = new xmldb_field('ocinstanceid', XMLDB_TYPE_INTEGER, '10'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Use default series for current series. + $DB->set_field('tool_opencast_series', 'ocinstanceid', 1); + + // Set instance field to not null. + $field = new xmldb_field('ocinstanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL); + $dbman->change_field_notnull($table, $field); + + // Add new foreign key and unique constraint. + $table->add_key('fk_course', XMLDB_KEY_FOREIGN, ['courseid'], 'course', ['id']); + $table->add_key('unq_course_series_ocinstance', XMLDB_KEY_UNIQUE, ['courseid', 'ocinstanceid', 'series']); + + // Opencast savepoint reached. + upgrade_plugin_savepoint(true, 2021091200, 'tool', 'opencast'); + } + + if ($oldversion < 2021102700) { + $columns = $DB->get_columns('tool_opencast_series'); + $isdefaultfield = $columns['isdefault']; + + if ($isdefaultfield->__get("type") == "bytea") { + // Changing type of field isdefault on table tool_opencast_series to int. + $table = new xmldb_table('tool_opencast_series'); + $oldfield = new xmldb_field('isdefault', XMLDB_TYPE_BINARY); + $dbman->rename_field($table, $oldfield, 'isdefault_old'); + + $newfield = new xmldb_field('isdefault', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'series'); + $dbman->add_field($table, $newfield); + + // Loop through records because casting in sql depends on database type. + foreach ($DB->get_records('tool_opencast_series') as $record) { + if ($record->isdefault_old) { + $record->isdefault = 1; + $DB->update_record('tool_opencast_series', $record); + } + } + + // Launch change of type for field isdefault. + $dbman->drop_field($table, new xmldb_field('isdefault_old')); + } + + // Opencast savepoint reached. + upgrade_plugin_savepoint(true, 2021102700, 'tool', 'opencast'); + } + + $newversion = 2023030100; + if ($oldversion < $newversion) { + if (remove_default_opencast_instance_settings_without_id() === false) { + return false; + } + + // Opencast savepoint reached. + upgrade_plugin_savepoint(true, $newversion, 'tool', 'opencast'); + } + + return true; +} + +/** + * Removes the settings of the default Opencast instance without an id in their names + * from the database and adds those settings with the corresponding id in their names + * and their previous values to the database again. + * + * @return bool + * Returns true, if this update of the database was successful, and false otherwise. + */ +function remove_default_opencast_instance_settings_without_id(): bool { + $helpersettingsname = 'apiurl'; + $pluginname = 'tool_opencast'; + + // Check, if settings without an id in their names exist (for the default Opencast instance). + $foundoldsetting = get_config($pluginname, $helpersettingsname); + if ($foundoldsetting === false) { + return true; + } + + // Fetch the default Opencast instance, if any. + $defaultocinstance = settings_api::get_default_ocinstance(); + if ($defaultocinstance === null) { + return true; + } + + $defaultocinstanceid = $defaultocinstance->id; + + try { + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiurl'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiusername'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apipassword'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'lticonsumerkey'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'lticonsumersecret'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apitimeout'); + replace_default_opencast_instance_setting_without_id($defaultocinstanceid, 'apiconnecttimeout'); + } catch (\dml_exception $exception) { + return false; + } + + return true; +} + +/** + * Removes the passed setting of the default Opencast instance without an id in its name + * from the database and adds that setting with the passed id in its name + * and its previous value to the database again. + * + * @param int $defaultinstanceid + * The Opencast instance id of the default Opencast instance. + * + * @param string $name + * The name of the setting to replace (without the Opencast instance id). + * + * @throws \dml_exception + */ +function replace_default_opencast_instance_setting_without_id(int $defaultinstanceid, + string $name): void { + $pluginname = 'tool_opencast'; + + $value = get_config($pluginname, $name); + if ($value === false) { + throw new \dml_exception('dmlreadexception'); + } + + if (unset_config($name, $pluginname) === false) { + throw new \dml_exception('dmlwriteexception'); + } + + set_config($name . '_' . $defaultinstanceid, $value, $pluginname); +} diff --git a/external.php b/external.php index 4b8e86c..ddb699a 100644 --- a/external.php +++ b/external.php @@ -1,327 +1,327 @@ -. - -/** - * Opencast external API - * - * @package tool_opencast - * @category external - * @copyright 2018 Tobias Reischmann - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 3.2 - */ - -defined('MOODLE_INTERNAL') || die; - -require_once($CFG->libdir . '/externallib.php'); -require_once($CFG->libdir . '/authlib.php'); - -/** - * Opencast external API - * - * @package tool_opencast - * @category external - * @copyright 2018 Tobias Reischmann - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class tool_opencast_external extends external_api { - - /** - * Describes the parameters for getting courses for a opencast instructor. - * - * @return external_function_parameters - * @throws coding_exception - */ - public static function get_courses_for_instructor_parameters() { - return new external_function_parameters( - [ - 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), - ] - ); - } - - /** - * Describes the parameters for getting courses for a opencast learner. - * - * @return external_function_parameters - * @throws coding_exception - */ - public static function get_courses_for_learner_parameters() { - return new external_function_parameters( - [ - 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), - ] - ); - } - - /** - * Describes the parameters for getting groups for a opencast user. - * - * @return external_function_parameters - * @throws coding_exception - */ - public static function get_groups_for_learner_parameters() { - return new external_function_parameters( - [ - 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), - ] - ); - } - - /** - * Get all courses for a user, in which he has the capabilities of a instructor. - * - * @param string $username user name - * @return array list of course ids - * @throws coding_exception - * @throws dml_exception - * @throws invalid_parameter_exception - * @throws required_capability_exception - */ - public static function get_courses_for_instructor($username) { - self::validate_parameters(self::get_courses_for_instructor_parameters(), ['username' => $username]); - - return self::get_courses_with_capability($username, 'tool/opencast:instructor'); - } - - /** - * Get all courses for a user, in which he has the capabilities of a learner. - * - * @param string $username user name - * @return array list of course ids - * @throws coding_exception - * @throws dml_exception - * @throws invalid_parameter_exception - * @throws required_capability_exception - */ - public static function get_courses_for_learner($username) { - self::validate_parameters(self::get_courses_for_learner_parameters(), ['username' => $username]); - - return self::get_courses_with_capability($username, 'tool/opencast:learner'); - } - - /** - * Get all courses for a user, in which he has the capabilities of a learner. - * - * @param string $username user name - * @return array list of course ids - * @throws coding_exception - * @throws dml_exception - * @throws invalid_parameter_exception - * @throws required_capability_exception - */ - public static function get_groups_for_learner($username) { - self::validate_parameters(self::get_groups_for_learner_parameters(), ['username' => $username]); - - $context = context_system::instance(); - if (!has_capability('tool/opencast:externalapi', $context)) { - throw new required_capability_exception($context, 'tool/opencast:externalapi', 'nopermissions', ''); - } - if (!has_capability('moodle/site:accessallgroups', $context)) { - throw new required_capability_exception($context, 'moodle/site:accessallgroups', 'nopermissions', ''); - } - - global $DB; - $user = core_user::get_user_by_username($username); - return $DB->get_records('groups_members', ['userid' => $user->id], '', 'groupid as id'); - } - - /** - * Returns all course ids where the user has the specific capability in. - * @param string $username the username - * @param string $capability the moodle capability - * @return array - * @throws coding_exception - * @throws dml_exception - * @throws required_capability_exception - */ - private static function get_courses_with_capability($username, $capability) { - $result = []; - - $context = context_system::instance(); - if (!has_capability('tool/opencast:externalapi', $context)) { - throw new required_capability_exception($context, 'tool/opencast:externalapi', 'nopermissions', ''); - } - - $user = core_user::get_user_by_username($username); - $courses = enrol_get_all_users_courses($user->id); - foreach ($courses as $course) { - $context = context_course::instance($course->id); - if (has_capability($capability, $context, $user)) { - $result[] = ['id' => $course->id]; - } - } - return $result; - } - - /** - * Describes the confirm_user return value. - * - * @return external_multiple_structure array of course ids - */ - public static function get_courses_for_instructor_returns() { - return new external_multiple_structure( - new external_single_structure( - [ - 'id' => new external_value(PARAM_INT, 'id of course'), - ] - ) - ); - } - - /** - * Describes the confirm_user return value. - * - * @return external_multiple_structure array of course ids - */ - public static function get_courses_for_learner_returns() { - return new external_multiple_structure( - new external_single_structure( - [ - 'id' => new external_value(PARAM_INT, 'id of course'), - ] - ) - ); - } - - /** - * Describes the confirm_user return value. - * - * @return external_multiple_structure array of course ids - */ - public static function get_groups_for_learner_returns() { - return new external_multiple_structure( - new external_single_structure( - [ - 'id' => new external_value(PARAM_INT, 'id of group'), - ] - ) - ); - } - - /** - * Describes the connection_test_tool return value. - * - * @return external_single_structure array the result of the connection test - */ - public static function connection_test_tool_returns() { - return new external_single_structure( - [ - 'testresult' => new external_value(PARAM_RAW, 'Opencast API URL Test result'), - ] - ); - } - - /** - * Describes the parameters for testing the connection. - * - * @return external_function_parameters - * @throws coding_exception - */ - public static function connection_test_tool_parameters() { - return new external_function_parameters( - [ - 'apiurl' => new external_value(PARAM_TEXT, 'Opencast API URL'), - 'apiusername' => new external_value(PARAM_TEXT, 'Opencast API User'), - 'apipassword' => new external_value(PARAM_RAW, 'Opencast API Password'), - 'apitimeout' => new external_value(PARAM_INT, 'API timeout', VALUE_DEFAULT, 2000), - 'apiconnecttimeout' => new external_value(PARAM_INT, 'API connect timeout', VALUE_DEFAULT, 1000), - ] - ); - } - - /** - * Builds a html tag for the alert of the connection test tool. - * - * @param string $connectiontestresult The result of a connection test. - * @param string $testsuccessfulstringidentifier The string identifier of a successful connection test. - * @param string $testfailedstringidentifier The string identifier of a failed connection test. - * @return string The html tag as string. - */ - private static function connection_test_tool_build_html_alert_tag($connectiontestresult, - string $testsuccessfulstringidentifier, - string $testfailedstringidentifier): string { - // Check, if the test was successful. - if ($connectiontestresult === true) { - return html_writer::tag( - 'p', - get_string($testsuccessfulstringidentifier, 'tool_opencast'), - ['class' => 'alert alert-success'] - ); - } - - return html_writer::tag( - 'p', - get_string($testfailedstringidentifier, 'tool_opencast', $connectiontestresult), - ['class' => 'alert alert-danger'] - ); - } - - /** - * Perform the connection test via Ajax call to be able to show it in Modal. - * - * @param string $apiurl Opencast API URL - * @param string $apiusername Opencast API username - * @param string $apipassword Opencast API password - * @param int $apitimeout Overall API request execution timeout in milliseconds - * @param int $apiconnecttimeout Connection timeout in milliseconds - * @return array - * @throws coding_exception - * @throws dml_exception - * @throws invalid_parameter_exception - * @throws required_capability_exception - */ - public static function connection_test_tool($apiurl, $apiusername, $apipassword, $apitimeout, $apiconnecttimeout) { - - // Validate the parameters. - $params = self::validate_parameters(self::connection_test_tool_parameters(), - [ - 'apiurl' => $apiurl, - 'apiusername' => $apiusername, - 'apipassword' => $apipassword, - 'apitimeout' => $apitimeout, - 'apiconnecttimeout' => $apiconnecttimeout, - ] - ); - - // Get a customized api instance to use. - $customizedapi = \tool_opencast\local\api::get_instance(null, [], [ - 'apiurl' => $params['apiurl'], - 'apiusername' => $params['apiusername'], - 'apipassword' => $params['apipassword'], - 'apitimeout' => $params['apitimeout'], - 'apiconnecttimeout' => $params['apiconnecttimeout'], - ]); - - // Test the URL. - $connectiontesturlresult = $customizedapi->connection_test_url(); - $resulthtml = self::connection_test_tool_build_html_alert_tag( - $connectiontesturlresult, - 'apiurltestsuccessfulshort', - 'apiurltestfailedshort'); - - // Test the Credentials. - $connectiontestcredentialsresult = $customizedapi->connection_test_credentials(); - $resulthtml .= self::connection_test_tool_build_html_alert_tag( - $connectiontestcredentialsresult, - 'apicreadentialstestsuccessfulshort', - 'apicreadentialstestfailedshort'); - - return [ - 'testresult' => $resulthtml, - ]; - } -} +. + +/** + * Opencast external API + * + * @package tool_opencast + * @category external + * @copyright 2018 Tobias Reischmann + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 3.2 + */ + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->libdir . '/externallib.php'); +require_once($CFG->libdir . '/authlib.php'); + +/** + * Opencast external API + * + * @package tool_opencast + * @category external + * @copyright 2018 Tobias Reischmann + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class tool_opencast_external extends external_api { + + /** + * Describes the parameters for getting courses for a opencast instructor. + * + * @return external_function_parameters + * @throws coding_exception + */ + public static function get_courses_for_instructor_parameters() { + return new external_function_parameters( + [ + 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), + ] + ); + } + + /** + * Describes the parameters for getting courses for a opencast learner. + * + * @return external_function_parameters + * @throws coding_exception + */ + public static function get_courses_for_learner_parameters() { + return new external_function_parameters( + [ + 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), + ] + ); + } + + /** + * Describes the parameters for getting groups for a opencast user. + * + * @return external_function_parameters + * @throws coding_exception + */ + public static function get_groups_for_learner_parameters() { + return new external_function_parameters( + [ + 'username' => new external_value(core_user::get_property_type('username'), 'User Name'), + ] + ); + } + + /** + * Get all courses for a user, in which he has the capabilities of a instructor. + * + * @param string $username user name + * @return array list of course ids + * @throws coding_exception + * @throws dml_exception + * @throws invalid_parameter_exception + * @throws required_capability_exception + */ + public static function get_courses_for_instructor($username) { + self::validate_parameters(self::get_courses_for_instructor_parameters(), ['username' => $username]); + + return self::get_courses_with_capability($username, 'tool/opencast:instructor'); + } + + /** + * Get all courses for a user, in which he has the capabilities of a learner. + * + * @param string $username user name + * @return array list of course ids + * @throws coding_exception + * @throws dml_exception + * @throws invalid_parameter_exception + * @throws required_capability_exception + */ + public static function get_courses_for_learner($username) { + self::validate_parameters(self::get_courses_for_learner_parameters(), ['username' => $username]); + + return self::get_courses_with_capability($username, 'tool/opencast:learner'); + } + + /** + * Get all courses for a user, in which he has the capabilities of a learner. + * + * @param string $username user name + * @return array list of course ids + * @throws coding_exception + * @throws dml_exception + * @throws invalid_parameter_exception + * @throws required_capability_exception + */ + public static function get_groups_for_learner($username) { + self::validate_parameters(self::get_groups_for_learner_parameters(), ['username' => $username]); + + $context = context_system::instance(); + if (!has_capability('tool/opencast:externalapi', $context)) { + throw new required_capability_exception($context, 'tool/opencast:externalapi', 'nopermissions', ''); + } + if (!has_capability('moodle/site:accessallgroups', $context)) { + throw new required_capability_exception($context, 'moodle/site:accessallgroups', 'nopermissions', ''); + } + + global $DB; + $user = core_user::get_user_by_username($username); + return $DB->get_records('groups_members', ['userid' => $user->id], '', 'groupid as id'); + } + + /** + * Returns all course ids where the user has the specific capability in. + * @param string $username the username + * @param string $capability the moodle capability + * @return array + * @throws coding_exception + * @throws dml_exception + * @throws required_capability_exception + */ + private static function get_courses_with_capability($username, $capability) { + $result = []; + + $context = context_system::instance(); + if (!has_capability('tool/opencast:externalapi', $context)) { + throw new required_capability_exception($context, 'tool/opencast:externalapi', 'nopermissions', ''); + } + + $user = core_user::get_user_by_username($username); + $courses = enrol_get_all_users_courses($user->id); + foreach ($courses as $course) { + $context = context_course::instance($course->id); + if (has_capability($capability, $context, $user)) { + $result[] = ['id' => $course->id]; + } + } + return $result; + } + + /** + * Describes the confirm_user return value. + * + * @return external_multiple_structure array of course ids + */ + public static function get_courses_for_instructor_returns() { + return new external_multiple_structure( + new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'id of course'), + ] + ) + ); + } + + /** + * Describes the confirm_user return value. + * + * @return external_multiple_structure array of course ids + */ + public static function get_courses_for_learner_returns() { + return new external_multiple_structure( + new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'id of course'), + ] + ) + ); + } + + /** + * Describes the confirm_user return value. + * + * @return external_multiple_structure array of course ids + */ + public static function get_groups_for_learner_returns() { + return new external_multiple_structure( + new external_single_structure( + [ + 'id' => new external_value(PARAM_INT, 'id of group'), + ] + ) + ); + } + + /** + * Describes the connection_test_tool return value. + * + * @return external_single_structure array the result of the connection test + */ + public static function connection_test_tool_returns() { + return new external_single_structure( + [ + 'testresult' => new external_value(PARAM_RAW, 'Opencast API URL Test result'), + ] + ); + } + + /** + * Describes the parameters for testing the connection. + * + * @return external_function_parameters + * @throws coding_exception + */ + public static function connection_test_tool_parameters() { + return new external_function_parameters( + [ + 'apiurl' => new external_value(PARAM_TEXT, 'Opencast API URL'), + 'apiusername' => new external_value(PARAM_TEXT, 'Opencast API User'), + 'apipassword' => new external_value(PARAM_RAW, 'Opencast API Password'), + 'apitimeout' => new external_value(PARAM_INT, 'API timeout', VALUE_DEFAULT, 2000), + 'apiconnecttimeout' => new external_value(PARAM_INT, 'API connect timeout', VALUE_DEFAULT, 1000), + ] + ); + } + + /** + * Builds a html tag for the alert of the connection test tool. + * + * @param string $connectiontestresult The result of a connection test. + * @param string $testsuccessfulstringidentifier The string identifier of a successful connection test. + * @param string $testfailedstringidentifier The string identifier of a failed connection test. + * @return string The html tag as string. + */ + private static function connection_test_tool_build_html_alert_tag($connectiontestresult, + string $testsuccessfulstringidentifier, + string $testfailedstringidentifier): string { + // Check, if the test was successful. + if ($connectiontestresult === true) { + return html_writer::tag( + 'p', + get_string($testsuccessfulstringidentifier, 'tool_opencast'), + ['class' => 'alert alert-success'] + ); + } + + return html_writer::tag( + 'p', + get_string($testfailedstringidentifier, 'tool_opencast', $connectiontestresult), + ['class' => 'alert alert-danger'] + ); + } + + /** + * Perform the connection test via Ajax call to be able to show it in Modal. + * + * @param string $apiurl Opencast API URL + * @param string $apiusername Opencast API username + * @param string $apipassword Opencast API password + * @param int $apitimeout Overall API request execution timeout in milliseconds + * @param int $apiconnecttimeout Connection timeout in milliseconds + * @return array + * @throws coding_exception + * @throws dml_exception + * @throws invalid_parameter_exception + * @throws required_capability_exception + */ + public static function connection_test_tool($apiurl, $apiusername, $apipassword, $apitimeout, $apiconnecttimeout) { + + // Validate the parameters. + $params = self::validate_parameters(self::connection_test_tool_parameters(), + [ + 'apiurl' => $apiurl, + 'apiusername' => $apiusername, + 'apipassword' => $apipassword, + 'apitimeout' => $apitimeout, + 'apiconnecttimeout' => $apiconnecttimeout, + ] + ); + + // Get a customized api instance to use. + $customizedapi = \tool_opencast\local\api::get_instance(null, [], [ + 'apiurl' => $params['apiurl'], + 'apiusername' => $params['apiusername'], + 'apipassword' => $params['apipassword'], + 'apitimeout' => $params['apitimeout'], + 'apiconnecttimeout' => $params['apiconnecttimeout'], + ]); + + // Test the URL. + $connectiontesturlresult = $customizedapi->connection_test_url(); + $resulthtml = self::connection_test_tool_build_html_alert_tag( + $connectiontesturlresult, + 'apiurltestsuccessfulshort', + 'apiurltestfailedshort'); + + // Test the Credentials. + $connectiontestcredentialsresult = $customizedapi->connection_test_credentials(); + $resulthtml .= self::connection_test_tool_build_html_alert_tag( + $connectiontestcredentialsresult, + 'apicreadentialstestsuccessfulshort', + 'apicreadentialstestfailedshort'); + + return [ + 'testresult' => $resulthtml, + ]; + } +} From d3f05689908c28dd26d3b8ac00a15f8b7041deab Mon Sep 17 00:00:00 2001 From: Thomas Niedermaier Date: Sun, 10 Nov 2024 19:40:02 +0100 Subject: [PATCH 4/6] version.php --- version.php | 63 +++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/version.php b/version.php index bcd03e7..80c96f3 100644 --- a/version.php +++ b/version.php @@ -1,31 +1,32 @@ -. - -/** - * Plugin version and other meta-data are defined here. - * - * @package tool_opencast - * @copyright 2018 Tobias Reischmann - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$plugin->component = 'tool_opencast'; -$plugin->release = 'v4.4-r1'; -$plugin->version = 2024060400; -$plugin->requires = 2022112800; // Requires Moodle 4.1+. -$plugin->maturity = MATURITY_STABLE; +. + +/** + * Plugin version and other meta-data are defined here. + * + * @package tool_opencast + * @copyright 2024 Thomas Niedermaier + * @copyright 2018 Tobias Reischmann + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->component = 'tool_opencast'; +$plugin->release = 'v4.5-rc'; +$plugin->version = 2024111100; +$plugin->requires = 2024100700; // Requires Moodle 4.5+. +$plugin->maturity = MATURITY_RC; From c870d0be2b3499d1da905b859f220b603fdfcec4 Mon Sep 17 00:00:00 2001 From: Thomas Niedermaier Date: Sun, 10 Nov 2024 19:42:53 +0100 Subject: [PATCH 5/6] crlf to lf --- version.php | 64 ++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/version.php b/version.php index 80c96f3..8027390 100644 --- a/version.php +++ b/version.php @@ -1,32 +1,32 @@ -. - -/** - * Plugin version and other meta-data are defined here. - * - * @package tool_opencast - * @copyright 2024 Thomas Niedermaier - * @copyright 2018 Tobias Reischmann - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -$plugin->component = 'tool_opencast'; -$plugin->release = 'v4.5-rc'; -$plugin->version = 2024111100; -$plugin->requires = 2024100700; // Requires Moodle 4.5+. -$plugin->maturity = MATURITY_RC; +. + +/** + * Plugin version and other meta-data are defined here. + * + * @package tool_opencast + * @copyright 2024 Thomas Niedermaier + * @copyright 2018 Tobias Reischmann + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->component = 'tool_opencast'; +$plugin->release = 'v4.5-rc'; +$plugin->version = 2024111100; +$plugin->requires = 2024100700; // Requires Moodle 4.5+. +$plugin->maturity = MATURITY_RC; From 3770f94f99cf0df33069848cd88530e07742ab2d Mon Sep 17 00:00:00 2001 From: Thomas Niedermaier Date: Mon, 11 Nov 2024 14:31:30 +0100 Subject: [PATCH 6/6] version.php --- version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.php b/version.php index 8027390..5eccdd3 100644 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'tool_opencast'; -$plugin->release = 'v4.5-rc'; +$plugin->release = 'v4.5-r1'; $plugin->version = 2024111100; $plugin->requires = 2024100700; // Requires Moodle 4.5+. -$plugin->maturity = MATURITY_RC; +$plugin->maturity = MATURITY_STABLE;