/** * Given an object containing all the necessary data, * (defined by the form in mod_form.php) this function * will create a new instance and return the id number * of the new instance. * * @param object $opencast Moodle {opencast} table DB record * * @return int newly created instance ID */ function opencast_add_instance($opencast) { global $DB, $USER; $opencast->timemodified = time(); $scast = new mod_opencast_series(); if (isset($opencast->newchannelname)) { $scast->setChannelName($opencast->newchannelname); } //$scast->setCourseId(); // $scast->setLicense($opencast->license); // $scast->setDepartment($opencast->department); $scast->setAllowAnnotations($opencast->allow_annotations == OPENCAST_ANNOTATIONS); // if (isset($opencast->template_id)) { // not set if creating new instance with existing channel // $scast->setTemplateId($opencast->template_id); // } $scast->setIvt($opencast->is_ivt); if (isset($opencast->inviting)) { $scast->setInvitingPossible($opencast->inviting); } $scast->setOrganizationDomain(mod_opencast_series::getOrganizationByEmail($USER->email)); $opencast->organization_domain = $scast->getOrganization(); if ($opencast->channelnew == OPENCAST_CHANNEL_NEW) { // New channel $scast->setProducer(mod_opencast_user::getExtIdFromMoodleUserId($USER->id)); $scast->doCreate(); $opencast->ext_id = $scast->getExtId(); } else { // Existing channel $scast->setExtId($opencast->ext_id); $scast->update(); } if (empty($opencast->timerestrict)) { $opencast->timeopen = 0; $opencast->timeclose = 0; } $opencast->id = $DB->insert_record('opencast', $opencast); return $opencast->id; }
/** * Displays a user selector * * @param bool $withproducers shall the producers be included ? * @param string $action_url where the form shall be posted * @param string $buttonlabel value attribute of the submit button * @param bool $switchaaionly display users with ExternalAccount only * @param bool $with_emtpyoption display 'remove user' option or not * @param bool $selectonly display HTML SELECT element only * @param int $selected_id if not zero, select OPTION with this index */ function display_user_selector($withproducers = false, $action_url = '', $buttonlabel = 'OK', $switchaaionly = false, $with_emtpyoption = false, $selectonly = false, $selected_id = 0) { global $context, $url, $course; if ($withproducers === false) { $producers = get_users_by_capability($context, 'mod/opencast:isproducer', 'u.id'); } $possible_users = get_users_by_capability($context, 'mod/opencast:use', 'u.id, u.lastname, u.firstname, u.maildisplay, u.email', 'u.lastname, u.firstname'); $options = []; if ($with_emtpyoption) { $options[-1] = '(' . get_string('removeowner', 'opencast') . ')'; } foreach ($possible_users as $possible_user_id => $possible_user) { if (in_array($possible_user_id, $this->displayed_userids)) { continue; } if ($withproducers === false && array_key_exists($possible_user_id, $producers)) { continue; } if ($switchaaionly && !mod_opencast_user::getExtIdFromMoodleUserId($possible_user_id)) { continue; } $option_text = $possible_user->lastname . ', ' . $possible_user->firstname; if ($possible_user->maildisplay == 1 or $possible_user->maildisplay == 2 and $course->id != SITEID and !isguestuser() or has_capability('moodle/course:viewhiddenuserfields', $context)) { $option_text .= ' (' . $possible_user->email . ')'; } $options[$possible_user_id] = $option_text; } if (count($options)) { if (!$selectonly) { echo html_writer::start_tag('form', ['method' => 'post', 'action' => $action_url, 'onsubmit' => 'return document.getElementById(\'menuuserid\').selectedIndex != 0;']); echo html_writer::input_hidden_params($url, ['action', 'userid']); echo html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()]); echo html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'action', 'value' => 'add']); } echo html_writer::select($options, 'userid', $selected_id); if (!$selectonly) { echo html_writer::empty_tag('input', ['type' => 'submit', 'value' => $buttonlabel]); echo html_writer::end_tag('form'); } } else { if (!$selectonly) { echo html_writer::start_tag('form'); } echo html_writer::select($options, 'userid', null, null, ['disabled' => 'disabled']); if (!$selectonly) { echo html_writer::empty_tag('input', ['type' => 'submit', 'value' => $buttonlabel, 'disabled' => 'disabled']); echo html_writer::tag('div', get_string('nomoreusers', 'opencast')); echo html_writer::end_tag('form'); } } }
/** * Sends an API request to the NEW Matterhorn server * * @param $url * @param string $request_type request type * @param array $data input data for POST/PUT * @param boolean $return_rawdata return raw XML? * @param boolean $usecache try to use cache? * @param string $file video file to upload * @param bool $runas run the API request as the current logged in user? * @param bool $haltonerror halt on error, or just return FALSE * * @return bool|stdClass|array result object or false if error * @throws moodle_exception */ static function sendRequest($url, $request_type, $data = null, $return_rawdata = false, $usecache = true, $file = null, $runas = true, $haltonerror = true) { global $CFG, $USER; $request_url = mod_opencast_series::getValueForKey('switch_api_host') . $url; $cache_time = mod_opencast_series::getValueForKey('local_cache_time'); $cache_dir = $CFG->dataroot . '/cache/mod_opencast'; if ($request_type !== 'GET') { // a modification has been made, clear the cache for consistency $reason = $request_type . ' ' . $request_url; $matches = false; if (preg_match('/\\/series\\/([0-9a-zA-Z]+)/', $request_url, $matches)) { // TODO Check because not working when deleting an event mod_opencast_log::write("CACHE : destroying cache for series " . $matches[1] . " because " . $reason); self::clear_cache($cache_dir, $matches[1]); } else { // No need to destroy the cache, the requests not containning "/series/xyzxyz" have no effect on clip/series metadata // TODO yes I think we do! BUT NOT ALWAYS! e.g. not needed when /sign mod_opencast_log::write("CACHE : destroying entire cache because " . $reason); self::clear_cache($cache_dir); } } if (!file_exists($cache_dir)) { mod_opencast_log::write("CACHE : initializing empty cache"); mkdir($cache_dir); } if (is_array($data) || is_object($data)) { $data_json = json_encode($data); } mod_opencast_log::write("REQUEST " . $request_type . " " . $request_url); mod_opencast_log::write("INPUT " . print_r($data, true)); $cache_filename = $cache_dir . '/' . self::hashfilename($request_url); if ($usecache && (string) $request_type === 'GET' && $cache_time && $cache_dir && file_exists($cache_filename) && time() - filemtime($cache_filename) < $cache_time) { // use the appropriate cached file mod_opencast_log::write("CACHE : using cached file " . $cache_filename); $output = file_get_contents($cache_filename); } else { // no cache for this request mod_opencast_log::write("CACHE : no cached file"); libxml_use_internal_errors(true); $curl_request = curl_init(); curl_setopt($curl_request, CURLOPT_SAFE_UPLOAD, true); curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl_request, CURLOPT_CUSTOMREQUEST, $request_type); if ($runas) { $role_user = '******' . mod_opencast_user::getExtIdFromMoodleUserId($USER->id); curl_setopt($curl_request, CURLOPT_HTTPHEADER, ['X-RUN-WITH-ROLES: ' . $role_user]); } else { curl_setopt($curl_request, CURLOPT_HTTPHEADER, ['X-RUN-WITH-ROLES: ROLE_EXTERNAL_APPLICATION']); } if (isset($file)) { if (!filesize($file) || !is_readable($file)) { mod_opencast_log::write("CURL UPLOAD ERROR : empty or unreadable file"); if ($haltonerror) { throw new moodle_exception('uploaderror', 'opencast'); } return false; } $curl_file = new CURLFile($file); curl_setopt($curl_request, CURLOPT_TIMEOUT_MS, 300000); // curl_setopt($curl_request, CURLOPT_PUT, true); // must be set, elsewise the multipart info will also be sent // curl_setopt($curl_request, CURLOPT_BINARYTRANSFER, 1); // curl_setopt($curl_request, CURLOPT_VERBOSE, (bool)mod_opencast_obj::getValueForKey('logging_enabled')); } else { curl_setopt($curl_request, CURLOPT_TIMEOUT_MS, (int) mod_opencast_series::getValueForKey('curl_timeout') * 1000); } curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, false); // TODO WAIT FOR SWITCH : no signing for now (test phase) curl_setopt($curl_request, CURLOPT_USERPWD, mod_opencast_series::getValueForKey('switch_api_username') . ':' . mod_opencast_series::getValueForKey('switch_api_password')); curl_setopt($curl_request, CURLOPT_URL, $request_url); if (mod_opencast_series::getValueForKey('curl_proxy')) { curl_setopt($curl_request, CURLOPT_PROXY, mod_opencast_series::getValueForKey('curl_proxy')); } if (is_array($data)) { $postfields = []; if ($file) { $postfields['presentation'] = $curl_file; } foreach ($data as $key => $value) { $postfields[$key] = $value; // htmlentities($value, ENT_NOQUOTES); // not necessary anymore } curl_setopt($curl_request, CURLOPT_POSTFIELDS, $postfields); curl_setopt($curl_request, CURLOPT_HTTPHEADER, ['Accept: application/v1.0.0+json']); } $output = curl_exec($curl_request); $curl_errno = curl_errno($curl_request); // 0 if fine $response_details = curl_getinfo($curl_request); if (isset($file)) { if ($curl_errno) { curl_close($curl_request); mod_opencast_log::write("CURL UPLOAD ERROR : no. " . $curl_errno); mod_opencast_log::write(" : " . $output); if ($haltonerror) { throw new moodle_exception('uploaderror', 'opencast'); } return false; } } curl_close($curl_request); if ($output && (string) $request_type === 'GET' && (isset($response_details) && $response_details['http_code'] < 400) && ($cache_time && $cache_dir && is_writable($cache_dir))) { // write cache to file, only if response is not an error mod_opencast_log::write("CACHE : writing output to cache file " . $cache_filename); $fh_w = fopen($cache_filename, 'w'); fwrite($fh_w, $output); fclose($fh_w); // TODO SOMETIME : here, see if we can do sth like the following (i.e. cache all events from 1 API call) // if (strstr($request_url, 'clips.xml?full=true') !== false) { // // we're getting full clip matadata (woohoo!), so let's fill in the cache // // on these clips, before making any further API calls. // $channelfull = new SimpleXMLElement($output); // foreach ($channelfull as $clipxml) { // $clip_request_url = // preg_replace('/^(.*)clips\.xml\?full=true.*/', '\1clips/' . $clipxml->ext_id . '.xml', // $request_url); // $cache_clip_filename = $cache_dir . '/' . self::hashfilename($clip_request_url); // $fh_w = fopen($cache_clip_filename, 'w'); // fwrite($fh_w, $clipxml->asXML()); // fclose($fh_w); // } // } } } if ($return_rawdata) { return $output; } if ($output === false) { if ($curl_errno) { mod_opencast_log::write("CURL REQUEST ERROR : no. " . $curl_errno); } if ($haltonerror) { print_error('switch_api_down', 'opencast'); } return false; } mod_opencast_log::write("OUTPUT " . $output); // $output = html_entity_decode($output, ENT_NOQUOTES); // not necessary anymore try { $return = json_decode($output); } catch (Exception $e) { if ($haltonerror) { print_error('api_fail', 'opencast', null, $e->getMessage() . $e->getCode()); } return false; } if (isset($response_details) && $response_details['http_code'] >= 400) { if ($response_details['http_code'] == 404) { if ($haltonerror) { print_error('api_404', 'opencast', null, $response_details['http_code']); } } if ($haltonerror) { print_error('api_fail', 'opencast', null, $response_details['http_code']); } return false; } return $return; }
print_error('fileis_notavideo', 'opencast', $url, $file->get_mimetype()); } $filename = $file->get_filename(); preg_match('/\\.([^.]+)$/', $filename, $extension); if (!in_array(strtolower($extension[1]), mod_opencast_series::getAllowedFileExtensions())) { $file->delete(); $a = new stdClass(); $a->yours = $extension[1]; $a->allowed = implode(', ', mod_opencast_series::getAllowedFileExtensions()); print_error('fileis_notextensionallowed', 'opencast', $url, $a); } $filetoupload = $CFG->dataroot . '/temp/files/mod_opencast_' . md5(microtime()) . '.' . $extension[1]; $a_file = $file->copy_content_to_temp(); rename($a_file, $filetoupload); try { $result = $sc_obj->createClip(['title' => $formdata->cliptitle, 'subtitle' => $formdata->clipsubtitle, 'presenter' => $formdata->clippresenter, 'location' => $formdata->cliplocation, 'ivt__owner' => mod_opencast_user::getExtIdFromMoodleUserId($USER->id), 'filename' => $filetoupload]); } catch (Exception $e) { unlink($filetoupload); $file->delete(); $retryurl = new moodle_url($url, ['formdata' => serialize($formdata)]); print_error('userupload_error', 'opencast', $retryurl); } unlink($filetoupload); $file->delete(); } } } if (isset($formdata) && isset($result)) { // data submitted: record file upload $uploaded_clip = new stdClass(); $uploaded_clip->userid = $USER->id;