diff --git a/backup/moodle2/restore_subplugin.class.php b/backup/moodle2/restore_subplugin.class.php index 640968b88afbb..c848219ccf867 100644 --- a/backup/moodle2/restore_subplugin.class.php +++ b/backup/moodle2/restore_subplugin.class.php @@ -87,6 +87,23 @@ public function launch_after_execute_methods() { } } + /** + * The after_restore dispatcher for any restore_subplugin class. + * + * This method will dispatch execution to the corresponding + * after_restore_xxx() method when available, with xxx + * being the connection point of the instance, so subplugin + * classes with multiple connection points will support + * multiple after_restore methods, one for each connection point. + */ + public function launch_after_restore_methods() { + // Check if the after_restore method exists and launch it. + $afterestore = 'after_restore_' . basename($this->connectionpoint->get_path()); + if (method_exists($this, $afterestore)) { + $this->$afterestore(); + } + } + // Protected API starts here // restore_step/structure_step/task wrappers diff --git a/lib/classes/plugin_manager.php b/lib/classes/plugin_manager.php index 302e5363dbf83..cb6c2fe2899fb 100644 --- a/lib/classes/plugin_manager.php +++ b/lib/classes/plugin_manager.php @@ -1804,7 +1804,7 @@ public static function standard_plugins_list($type) { ), 'ltiservice' => array( - 'memberships', 'profile', 'toolproxy', 'toolsettings' + 'gradebookservices', 'memberships', 'profile', 'toolproxy', 'toolsettings' ), 'mlbackend' => array( diff --git a/mod/lti/classes/local/ltiservice/resource_base.php b/mod/lti/classes/local/ltiservice/resource_base.php index 4d617fe1f2120..1fdb72ec76667 100644 --- a/mod/lti/classes/local/ltiservice/resource_base.php +++ b/mod/lti/classes/local/ltiservice/resource_base.php @@ -28,6 +28,7 @@ defined('MOODLE_INTERNAL') || die(); +global $CFG; require_once($CFG->dirroot . '/mod/lti/locallib.php'); @@ -41,7 +42,16 @@ */ abstract class resource_base { - /** @var object Service associated with this resource. */ + /** HTTP Post method */ + const HTTP_POST = 'POST'; + /** HTTP Get method */ + const HTTP_GET = 'GET'; + /** HTTP Put method */ + const HTTP_PUT = 'PUT'; + /** HTTP Delete method */ + const HTTP_DELETE = 'DELETE'; + + /** @var service_base Service associated with this resource. */ private $service; /** @var string Type for this resource. */ protected $type; @@ -62,7 +72,7 @@ abstract class resource_base { /** * Class constructor. * - * @param mod_lti\local\ltiservice\service_base $service Service instance + * @param service_base $service Service instance */ public function __construct($service) { @@ -125,7 +135,7 @@ public function get_type() { /** * Get the resource's service. * - * @return mod_lti\local\ltiservice\service_base + * @return mixed */ public function get_service() { @@ -190,7 +200,7 @@ public function get_endpoint() { /** * Execute the request for this resource. * - * @param mod_lti\local\ltiservice\response $response Response object for this request. + * @param response $response Response object for this request. */ public abstract function execute($response); @@ -224,7 +234,7 @@ public function check_tool_proxy($toolproxyguid, $body = null) { } } if (!$ok) { - debugging('Requested service not included in tool proxy: ' . $this->get_id()); + debugging('Requested service not included in tool proxy: ' . $this->get_id(), DEBUG_DEVELOPER); } } } @@ -233,6 +243,45 @@ public function check_tool_proxy($toolproxyguid, $body = null) { } + /** + * Check to make sure the request is valid. + * + * @param int $typeid The typeid we want to use + * @param int $contextid The course we are at + * @param string $permissionrequested The permission to be checked + * @param string $body Body of HTTP request message + * + * @return boolean + */ + public function check_type($typeid, $contextid, $permissionrequested, $body = null) { + $ok = false; + if ($this->get_service()->check_type($typeid, $contextid, $body)) { + $neededpermissions = $this->get_permissions($typeid); + foreach ($neededpermissions as $permission) { + if ($permission == $permissionrequested) { + $ok = true; + break; + } + } + if (!$ok) { + debugging('Requested service ' . $permissionrequested . ' not included in tool type: ' . $typeid, + DEBUG_DEVELOPER); + } + } + return $ok; + + } + + /** + * get permissions from the config of the tool for that resource + * + * @param int $ltitype Type of LTI + * @return array with the permissions related to this resource by the $ltitype or empty if none. + */ + public function get_permissions($ltitype) { + return array(); + } + /** * Parse a value for custom parameter substitution variables. * diff --git a/mod/lti/classes/local/ltiservice/response.php b/mod/lti/classes/local/ltiservice/response.php index 5029d216acedb..8f4bcabcd2e8e 100644 --- a/mod/lti/classes/local/ltiservice/response.php +++ b/mod/lti/classes/local/ltiservice/response.php @@ -54,6 +54,8 @@ class response { private $body; /** @var array HTTP response codes. */ private $responsecodes; + /** @var array HTTP additional headers. */ + private $additionalheaders; /** * Class constructor. @@ -83,6 +85,7 @@ public function __construct() { 500 => 'Internal Server Error', 501 => 'Not Implemented' ); + $this->additionalheaders = array(); } @@ -202,11 +205,23 @@ public function set_body($body) { $this->body = $body; } + /** + * Add an additional header. + * + * @param string $header The new header + */ + public function add_additional_header($header) { + array_push($this->additionalheaders, $header); + } + /** * Send the response. */ public function send() { header("HTTP/1.0 {$this->code} {$this->get_reason()}"); + foreach ($this->additionalheaders as $header) { + header($header); + } if (($this->code >= 200) && ($this->code < 300)) { if (!empty($this->contenttype)) { header("Content-Type: {$this->contenttype};charset=UTF-8"); diff --git a/mod/lti/classes/local/ltiservice/service_base.php b/mod/lti/classes/local/ltiservice/service_base.php index 73726bd4e224e..26a89c1bcd8a5 100644 --- a/mod/lti/classes/local/ltiservice/service_base.php +++ b/mod/lti/classes/local/ltiservice/service_base.php @@ -28,11 +28,13 @@ defined('MOODLE_INTERNAL') || die(); +global $CFG; require_once($CFG->dirroot . '/mod/lti/locallib.php'); require_once($CFG->dirroot . '/mod/lti/OAuthBody.php'); // TODO: Switch to core oauthlib once implemented - MDL-30149. use moodle\mod\lti as lti; +use stdClass; /** @@ -133,10 +135,80 @@ public function set_tool_proxy($toolproxy) { /** * Get the resources for this service. * - * @return array + * @return resource_base[] */ abstract public function get_resources(); + /** + * Returns the configuration options for this service. + * + * @param \MoodleQuickForm $mform Moodle quickform object definition + */ + public function get_configuration_options(&$mform) { + + } + + /** + * Return an array with the names of the parameters that the service will be saving in the configuration + * + * @return array Names list of the parameters that the service will be saving in the configuration + */ + public function get_configuration_parameter_names() { + return array(); + } + + /** + * Default implementation will check for the existence of at least one mod_lti entry for that tool and context. + * + * It may be overridden if other inferences can be done. + * + * Ideally a Site Tool should be explicitly engaged with a course, the check on the presence of a link is a proxy + * to infer a Site Tool engagement until an explicit Site Tool - Course relationship exists. + * + * @param int $typeid The tool lti type id. + * @param int $courseid The course id. + * @return bool returns True if tool is used in context, false otherwise. + */ + public function is_used_in_context($typeid, $courseid) { + global $DB; + + $ok = $DB->record_exists('lti', array('course' => $courseid, 'typeid' => $typeid)); + return $ok || $DB->record_exists('lti_types', array('course' => $courseid, 'id' => $typeid)); + } + + /** + * Checks if there is a site tool or a course tool for this site. + * + * @param int $typeid The tool lti type id. + * @param int $courseid The course id. + * @return bool returns True if tool is allowed in context, false otherwise. + */ + public function is_allowed_in_context($typeid, $courseid) { + global $DB; + + // Check if it is a Course tool for this course or a Site tool. + $type = $DB->get_record('lti_types', array('id' => $typeid)); + + return $type && ($type->course == $courseid || $type->course == SITEID); + } + + /** + * Return an array of key/values to add to the launch parameters. + * + * @param string $messagetype 'basic-lti-launch-request' or 'ContentItemSelectionRequest'. + * @param string $courseid The course id. + * @param string $userid The user id. + * @param string $typeid The tool lti type id. + * @param string $modlti The id of the lti activity. + * + * The type is passed to check the configuration and not return parameters for services not used. + * + * @return array Key/value pairs to add as launch parameters. + */ + public function get_launch_parameters($messagetype, $courseid, $userid, $typeid, $modlti = null) { + return array(); + } + /** * Get the path for service requests. * @@ -202,9 +274,35 @@ public function check_tool_proxy($toolproxyguid, $body = null) { if ($ok) { $this->toolproxy = $toolproxy; } - return $ok; + } + /** + * Check that the request has been properly signed. + * + * @param int $typeid The tool id + * @param int $courseid The course we are at + * @param string $body Request body (null if none) + * + * @return bool + */ + public function check_type($typeid, $courseid, $body = null) { + $ok = false; + $tool = null; + $consumerkey = lti\get_oauth_key_from_headers(); + if (empty($typeid)) { + return $ok; + } else if ($this->is_allowed_in_context($typeid, $courseid)) { + $tool = lti_get_type_type_config($typeid); + if ($tool !== false) { + if (!$this->is_unsigned() && ($tool->lti_resourcekey == $consumerkey)) { + $ok = $this->check_signature($tool->lti_resourcekey, $tool->lti_password, $body); + } else { + $ok = $this->is_unsigned(); + } + } + } + return $ok; } /** diff --git a/mod/lti/edit_form.php b/mod/lti/edit_form.php index 8db9ca53c95c7..5e618dec0f2d1 100644 --- a/mod/lti/edit_form.php +++ b/mod/lti/edit_form.php @@ -49,10 +49,24 @@ defined('MOODLE_INTERNAL') || die; +global $CFG; require_once($CFG->libdir.'/formslib.php'); require_once($CFG->dirroot.'/mod/lti/locallib.php'); -class mod_lti_edit_types_form extends moodleform{ +/** + * LTI Edit Form + * + * @package mod_lti + * @copyright 2009 Marc Alier, Jordi Piguillem, Nikolas Galanis + * marc.alier@upc.edu + * @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class mod_lti_edit_types_form extends moodleform { + + /** + * Define this form. + */ public function definition() { global $CFG; @@ -147,6 +161,16 @@ public function definition() { $mform->disabledIf('lti_contentitem', null); } + $mform->addElement('text', 'lti_toolurl_ContentItemSelectionRequest', + get_string('toolurl_contentitemselectionrequest', 'lti'), array('size' => '64')); + $mform->setType('lti_toolurl_ContentItemSelectionRequest', PARAM_URL); + $mform->setAdvanced('lti_toolurl_ContentItemSelectionRequest'); + $mform->addHelpButton('lti_toolurl_ContentItemSelectionRequest', 'toolurl_contentitemselectionrequest', 'lti'); + $mform->disabledIf('lti_toolurl_ContentItemSelectionRequest', 'lti_contentitem', 'notchecked'); + if ($istool) { + $mform->disabledIf('lti_toolurl__ContentItemSelectionRequest', null); + } + $mform->addElement('hidden', 'oldicon'); $mform->setType('oldicon', PARAM_URL); @@ -160,6 +184,11 @@ public function definition() { $mform->setAdvanced('lti_secureicon'); $mform->addHelpButton('lti_secureicon', 'secure_icon_url', 'lti'); + if (!$istool) { + // Display the lti advantage services. + $this->get_lti_advantage_services($mform); + } + if (!$istool) { // Add privacy preferences fieldset where users choose whether to send their data. $mform->addElement('header', 'privacy', get_string('privacy', 'lti')); @@ -253,4 +282,19 @@ public function get_data() { } return $data; } + + /** + * Generates the lti advantage extra configuration adding it to the mform + * + * @param MoodleQuickForm $mform + */ + public function get_lti_advantage_services(&$mform) { + // For each service add the label and get the array of configuration. + $services = lti_get_services(); + $mform->addElement('header', 'services', get_string('services', 'lti')); + foreach ($services as $service) { + /** @var \mod_lti\local\ltiservice\service_base $service */ + $service->get_configuration_options($mform); + } + } } diff --git a/mod/lti/lang/en/lti.php b/mod/lti/lang/en/lti.php index 11391c1ce8855..12e68000f18d5 100644 --- a/mod/lti/lang/en/lti.php +++ b/mod/lti/lang/en/lti.php @@ -510,9 +510,10 @@ If two different tool configurations are for the same domain, the most specific match will be used. You can also insert a cartridge URL if you have one and the details for the tool will be automatically filled.'; +$string['toolurl_contentitemselectionrequest'] = 'Content Selection URL'; +$string['toolurl_contentitemselectionrequest_help'] = 'The Content Selection URL will be used to launch the content selection page from the tool provider. If it is empty, the Tool URL will be used'; $string['typename'] = 'Tool name'; -$string['typename_help'] = 'The tool name is used to identify the tool provider within Moodle. The name entered will be visible -to teachers when adding external tools within courses.'; +$string['typename_help'] = 'The tool name is used to identify the tool provider within Moodle. The name entered will be visible to teachers when adding external tools within courses.'; $string['types'] = 'Types'; $string['unabletocreatetooltype'] = 'Unable to create tool'; $string['unabletofindtooltype'] = 'Unable to find tool for {$a->id}'; diff --git a/mod/lti/locallib.php b/mod/lti/locallib.php index 13ca7c5bc5f92..b501b2cf7cdff 100644 --- a/mod/lti/locallib.php +++ b/mod/lti/locallib.php @@ -53,6 +53,7 @@ // TODO: Switch to core oauthlib once implemented - MDL-30149. use moodle\mod\lti as lti; +global $CFG; require_once($CFG->dirroot.'/mod/lti/OAuth.php'); require_once($CFG->libdir.'/weblib.php'); require_once($CFG->dirroot . '/course/modlib.php'); @@ -96,7 +97,7 @@ * @since Moodle 3.0 */ function lti_get_launch_data($instance) { - global $PAGE, $CFG; + global $PAGE, $CFG, $USER; if (empty($instance->typeid)) { $tool = lti_get_tool_by_url_match($instance->toolurl, $instance->course); @@ -230,6 +231,18 @@ function lti_get_launch_data($instance) { $requestparams['launch_presentation_return_url'] = $returnurl; + // Add the parameters configured by the LTI advantage services. + if ($typeid && !$islti2) { + $services = lti_get_services(); + foreach ($services as $service) { + $ltiadvantageparameters = $service->get_launch_parameters('basic-lti-launch-request', + $course->id, $USER->id , $typeid, $instance->id); + foreach ($ltiadvantageparameters as $ltiadvantagekey => $ltiadvantagevalue) { + $requestparams[$ltiadvantagekey] = $ltiadvantagevalue; + } + } + } + // Allow request params to be updated by sub-plugins. $plugins = core_component::get_plugin_list('ltisource'); foreach (array_keys($plugins) as $plugin) { @@ -284,7 +297,7 @@ function lti_launch_tool($instance) { /** * Prepares an LTI registration request message * - * $param object $instance Tool Proxy instance object + * @param object $toolproxy Tool Proxy instance object */ function lti_register($toolproxy) { $endpoint = $toolproxy->regurl; @@ -617,6 +630,8 @@ function lti_build_custom_parameters($toolproxy, $tool, $instance, $params, $cus function lti_build_content_item_selection_request($id, $course, moodle_url $returnurl, $title = '', $text = '', $mediatypes = [], $presentationtargets = [], $autocreate = false, $multiple = false, $unsigned = false, $canconfirm = false, $copyadvice = false) { + global $USER; + $tool = lti_get_type($id); // Validate parameters. if (!$tool) { @@ -693,6 +708,18 @@ function lti_build_content_item_selection_request($id, $course, moodle_url $retu $requestparams = array_merge($requestparams, $lti2params); } + // Add the parameters configured by the LTI advantage services. + if ($id && !$islti2) { + $services = lti_get_services(); + foreach ($services as $service) { + $ltiadvantageparameters = $service->get_launch_parameters('ContentItemSelectionRequest', + $course->id, $USER->id , $id); + foreach ($ltiadvantageparameters as $ltiadvantagekey => $ltiadvantagevalue) { + $requestparams[$ltiadvantagekey] = $ltiadvantagevalue; + } + } + } + // Get standard request parameters and merge to the request parameters. $orgid = !empty($typeconfig['organizationid']) ? $typeconfig['organizationid'] : ''; $standardparams = lti_build_standard_request(null, $orgid, $islti2, 'ContentItemSelectionRequest'); @@ -856,9 +883,6 @@ function lti_tool_configuration_from_content_item($typeid, $messagetype, $ltiver if (empty($items)) { throw new moodle_exception('errorinvaliddata', 'mod_lti', '', $contentitemsjson); } - if ($items->{'@context'} !== 'http://purl.imsglobal.org/ctx/lti/v1/ContentItem') { - throw new moodle_exception('errorinvalidmediatype', 'mod_lti', '', $items->{'@context'}); - } if (!isset($items->{'@graph'}) || !is_array($items->{'@graph'}) || (count($items->{'@graph'}) > 1)) { throw new moodle_exception('errorinvalidresponseformat', 'mod_lti'); } @@ -922,7 +946,7 @@ function lti_tool_configuration_from_content_item($typeid, $messagetype, $ltiver } function lti_get_tool_table($tools, $id) { - global $CFG, $OUTPUT, $USER; + global $OUTPUT; $html = ''; $typename = get_string('typename', 'lti'); @@ -1124,9 +1148,9 @@ function lti_get_tool_proxy_table($toolproxies, $id) { /** * Extracts the enabled capabilities into an array, including those implicitly declared in a parameter * - * @param object $tool Tool instance object + * @param object $tool Tool instance object * - * @return Array of enabled capabilities + * @return array List of enabled capabilities */ function lti_get_enabled_capabilities($tool) { if (!isset($tool)) { @@ -1224,10 +1248,11 @@ function lti_get_custom_parameters($toolproxy, $tool, $params, $parameters) { * @param string $value Custom parameter value * @param boolean $islti2 True if an LTI 2 tool is being launched * - * @return Parsed value of custom parameter + * @return string Parsed value of custom parameter */ function lti_parse_custom_parameter($toolproxy, $tool, $params, $value, $islti2) { - global $USER, $COURSE; + // This is required as {${$valarr[0]}->{$valarr[1]}}" may be using the USER var. + global $USER; if ($value) { if (substr($value, 0, 1) == '\\') { @@ -1403,8 +1428,6 @@ function lti_get_tools_by_url($url, $state, $courseid = null) { function lti_get_tools_by_domain($domain, $state = null, $courseid = null) { global $DB, $SITE; - $filters = array('tooldomain' => $domain); - $statefilter = ''; $coursefilter = ''; @@ -1433,6 +1456,9 @@ function lti_get_tools_by_domain($domain, $state = null, $courseid = null) { /** * Returns all basicLTI tools configured by the administrator * + * @param int $course + * + * @return array */ function lti_filter_get_types($course) { global $DB; @@ -1698,7 +1724,7 @@ function lti_delete_type($id) { function lti_set_state_for_type($id, $state) { global $DB; - $DB->update_record('lti_types', array('id' => $id, 'state' => $state)); + $DB->update_record('lti_types', (object)array('id' => $id, 'state' => $state)); } /** @@ -1709,7 +1735,6 @@ function lti_set_state_for_type($id, $state) { * @return array Basic LTI configuration details */ function lti_get_config($ltiobject) { - $typeconfig = array(); $typeconfig = (array)$ltiobject; $additionalconfig = lti_get_type_config($ltiobject->typeid); $typeconfig = array_merge($typeconfig, $additionalconfig); @@ -1722,7 +1747,7 @@ function lti_get_config($ltiobject) { * * @param int $id * - * @return Instance configuration + * @return object configuration * */ function lti_get_type_config_from_instance($id) { @@ -1760,7 +1785,7 @@ function lti_get_type_config_from_instance($id) { * * @param int $id * - * @return Configuration details + * @return stdClass Configuration details */ function lti_get_type_type_config($id) { global $DB; @@ -1847,6 +1872,10 @@ function lti_get_type_type_config($id) { $type->lti_contentitem = $config['contentitem']; } + if (isset($config['toolurl_ContentItemSelectionRequest'])) { + $type->lti_toolurl_ContentItemSelectionRequest = $config['toolurl_ContentItemSelectionRequest']; + } + if (isset($config['debuglaunch'])) { $type->lti_debuglaunch = $config['debuglaunch']; } @@ -1855,6 +1884,19 @@ function lti_get_type_type_config($id) { $type->lti_module_class_type = $config['module_class_type']; } + // Get the parameters from the LTI services. + $services = lti_get_services(); + $ltiserviceprefixlength = 11; + foreach ($services as $service) { + $configurationparameters = $service->get_configuration_parameter_names(); + foreach ($configurationparameters as $ltiserviceparameter) { + $shortltiserviceparameter = substr($ltiserviceparameter, $ltiserviceprefixlength); + if (isset($config[$shortltiserviceparameter])) { + $type->$ltiserviceparameter = $config[$shortltiserviceparameter]; + } + } + } + return $type; } @@ -1886,6 +1928,14 @@ function lti_prepare_type_for_save($type, $config) { $type->contentitem = !empty($config->lti_contentitem) ? $config->lti_contentitem : 0; $config->lti_contentitem = $type->contentitem; } + if (isset($config->lti_toolurl_ContentItemSelectionRequest)) { + if (!empty($config->lti_toolurl_ContentItemSelectionRequest)) { + $type->toolurl_ContentItemSelectionRequest = $config->lti_toolurl_ContentItemSelectionRequest; + } else { + $type->toolurl_ContentItemSelectionRequest = ''; + } + $config->lti_toolurl_ContentItemSelectionRequest = $type->toolurl_ContentItemSelectionRequest; + } $type->timemodified = time(); @@ -1901,7 +1951,6 @@ function lti_update_type($type, $config) { lti_prepare_type_for_save($type, $config); - $clearcache = false; if (lti_request_is_using_ssl() && !empty($type->secureicon)) { $clearcache = !isset($config->oldicon) || ($config->oldicon !== $type->secureicon); } else { @@ -1918,6 +1967,13 @@ function lti_update_type($type, $config) { $record->value = $value; lti_update_config($record); } + if (substr($key, 0, 11) == 'ltiservice_' && !is_null($value)) { + $record = new \StdClass(); + $record->typeid = $type->id; + $record->name = substr($key, 11); + $record->value = $value; + lti_update_config($record); + } } require_once($CFG->libdir.'/modinfolib.php'); if ($clearcache) { @@ -1964,10 +2020,17 @@ function lti_add_type($type, $config) { if ($id) { foreach ($config as $key => $value) { - if (substr($key, 0, 4) == 'lti_' && !is_null($value)) { + if (!is_null($value)) { + $fieldparts = preg_split("/(lti|ltiservice)_/i", $key); + // If array has only one element, it did not start with the pattern. + if (count($fieldparts) < 2) { + continue; + } + $fieldname = $fieldparts[1]; + $record = new \StdClass(); $record->typeid = $id; - $record->name = substr($key, 4); + $record->name = $fieldname; $record->value = $value; lti_add_config($record); @@ -2033,7 +2096,7 @@ function lti_get_tool_proxies_from_registration_url($regurl) { * * @param int $id * - * @return Tool Proxy details + * @return mixed Tool Proxy details */ function lti_get_tool_proxy($id) { global $DB; @@ -2052,7 +2115,6 @@ function lti_get_tool_proxies($orphanedonly) { global $DB; if ($orphanedonly) { - $tools = $DB->get_records('lti_types'); $usedproxyids = array_values($DB->get_fieldset_select('lti_types', 'toolproxyid', 'toolproxyid IS NOT NULL')); $proxies = $DB->get_records('lti_tool_proxies', null, 'state DESC, timemodified DESC'); foreach ($proxies as $key => $value) { @@ -2071,7 +2133,7 @@ function lti_get_tool_proxies($orphanedonly) { * * @param int $id * - * @return Tool Proxy details + * @return mixed Tool Proxy details */ function lti_get_tool_proxy_config($id) { $toolproxy = lti_get_tool_proxy($id); @@ -2190,12 +2252,11 @@ function lti_add_config($config) { * * @param object $config Tool configuration * - * @return Record id number + * @return mixed Record id number */ function lti_update_config($config) { global $DB; - $return = true; $old = $DB->get_record('lti_types_config', array('typeid' => $config->typeid, 'name' => $config->name)); if ($old) { @@ -2243,7 +2304,7 @@ function lti_set_tool_settings($settings, $toolproxyid, $courseid = null, $insta $record = $DB->get_record('lti_tool_settings', array('toolproxyid' => $toolproxyid, 'course' => $courseid, 'coursemoduleid' => $instanceid)); if ($record !== false) { - $DB->update_record('lti_tool_settings', array('id' => $record->id, 'settings' => $json, 'timemodified' => time())); + $DB->update_record('lti_tool_settings', (object)array('id' => $record->id, 'settings' => $json, 'timemodified' => time())); } else { $record = new \stdClass(); $record->toolproxyid = $toolproxyid; @@ -2259,11 +2320,12 @@ function lti_set_tool_settings($settings, $toolproxyid, $courseid = null, $insta /** * Signs the petition to launch the external tool using OAuth * - * @param $oldparms Parameters to be passed for signing - * @param $endpoint url of the external tool - * @param $method Method for sending the parameters (e.g. POST) - * @param $oauth_consumoer_key Key - * @param $oauth_consumoer_secret Secret + * @param array $oldparms Parameters to be passed for signing + * @param string $endpoint url of the external tool + * @param string $method Method for sending the parameters (e.g. POST) + * @param string $oauthconsumerkey + * @param string $oauthconsumersecret + * @return array|null */ function lti_sign_parameters($oldparms, $endpoint, $method, $oauthconsumerkey, $oauthconsumersecret) { @@ -2285,9 +2347,10 @@ function lti_sign_parameters($oldparms, $endpoint, $method, $oauthconsumerkey, $ /** * Posts the launch petition HTML * - * @param $newparms Signed parameters - * @param $endpoint URL of the external tool - * @param $debug Debug (true/false) + * @param array $newparms Signed parameters + * @param string $endpoint URL of the external tool + * @param bool $debug Debug (true/false) + * @return string */ function lti_post_launch_html($newparms, $endpoint, $debug=false) { $r = "