MDL-45843 mod_lti: introduced support to LTI 2.0

This commit introduces support to the LTI module for LTI 2.0.
As well as the initial commit the following changes were made
and then squashed into the single commit for integration:

* Fixed bug in services
  Fixed bug which limited characters allowed in values of template
  variables (e.g. vendor ID) in service endpoints.
  Changed language file to refer to tool registrations rather than
  tool proxies.

* Refactored service classes
  Moved classes relating to services into areas where Moodle will
  autoload them

* Ran code through code checker
  Removed all errors reported by the Code checker module
  excluding third-party OAuth.php file.

* UI improvements
  Mainly when adding an external tool to a course - fields which
  should not be changed for a selected tool are either hidden or
  disabled. Admin settings page now shows the Tool Registration
  name against a tool rather than the launch URL, and the
  registration URL replaces the GUID on the tool registrations
  page.

* Updated tool proxy registration
  Added check of tool proxy to ensure only offered capabilities
  and services are included.  Also check tool proxy when processing
  a service request.

* Code review changes
  Some fixes based on code review by Mark Nielsen and addition of
  some PHPDocs comments.

* Updates from code/PHPdocs checks
  Removed use of eval and corrected invalid PHPdocs for new
  functions/classes

* Corrected namespace error and incorrect string terminator

* Updates based on forum feedback
  Added dependencies and backup, restore and uninstall methods for
  ltiservice subplugins.
  Changed most uses of is_null to empty

* Updated custom parameters test
  Updated test_split_custom_parameters to include new function
  parameters.
  Corrected PHPdoc entry for lti_split_custom_parameters
  Fixed incorrect line separators in ltiservice.php

* Added require_capability to registrationreturn.php

* SQL and EOL updates
  Moved PHP variable in SQL into a named parameter
  Improved checks for end-of-line characters to include CR and LF
  on their own or together

* Check for semicolon separators
  Semicolon separators in custom parameters are changed to EOL
  characters when upgrading to the 2014100100 version.

* Remove unused file
  basiclti.js file not being used so removed.

* Adjust line lengths
  Split long lines in upgrade.php

* Added savepoint to upgrade.php
  savepoint omitted from earlier update to upgrade.php

* Updated namespaces and upgrade
  Service and resource classes moved into .../local/...
  Upgrade SQL moved into a function and unit test created

* Updated lti_tool_proxies table
  Added indices and foreign keys to lti_tool_proxies table

* Fixed formatting and documentation issues

* ltiservice class moved into local

* Replaced lti_scale_used comments
  Put back commented out code for lti_scale_used

* Removed redundant sesskey code

* Fixed namespace and path check
  Updated ltiservice namespace for move into local
  Added check for existence of $_SERVER['PATH_INFO']

* Updated upgrade code
  Added indices and keys to lti_tool_settings table when upgrading
  Fixed errors in upgradelib_test.php (thanks to jleyva)
  Update SQL to use Moodle functions

* Use of empty with class method
  PHP 5.4 does not like the use of empty with a class method so saved the
  value to a variable first.  PHP 5.5 seems to accept the use of a method
  with empty.

* Removed redundant indices
  Removed creation of indices for foreign keys on lti_tool_settings table
  from install.xml and upgrade.php

* Fixes based on feedback
  Minor changes and corrections based on review in JIRA

* Fixed bug in toolproxy service
  Corrected bug which failed to respond properly to an invalid request
  Also updated upgrade.txt file

* Improved admin navigation
  Added the manage tool registrations page as a separate entry on the
  admin menu (within a folder named LTI).  Made this entry the current
  position for the related pages.

* Updated PHPdocs with class names
  Added class names with namespaces to PHPdocs to replace generic
  references to "object"

* Changed object to iframe
  Use of object tag in register.php changed to use an iframe tag in line
  with the similar update made to view.php.

* Improved registration process
  A message is now displayed if the registration page has not been loaded
  in the iframe within 20 seconds.  If a user is returned to Moodle
  without a tool proxy being sent, the registration is moved back from
  pending to configured.

* Fixes for integration
  Removed comment - the template is the default path unless overridden, so
  get_path and get_template should both be defined.
  Added comment and intval to fix the issue with obtaining an error
  reason.
This commit is contained in:
spvickers 2014-09-03 23:35:39 +01:00 committed by Sam Hemelryk
parent 529e38d141
commit e3f69b58a2
67 changed files with 4938 additions and 844 deletions

View File

@ -1052,6 +1052,10 @@ class core_plugin_manager {
'database', 'legacy', 'standard',
),
'ltiservice' => array(
'profile', 'toolproxy', 'toolsettings'
),
'message' => array(
'airnotifier', 'email', 'jabber', 'popup'
),

View File

@ -1,4 +1,19 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
//
// This file is part of BasicLTI4Moodle
//
// BasicLTI4Moodle is an IMS BasicLTI (Basic Learning Tools for Interoperability)
@ -15,96 +30,51 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
//
// OAuthBody.php is distributed under the MIT License
//
// The MIT License
//
// Copyright (c) 2007 Andy Smith
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
namespace moodle\mod\lti;//Using a namespace as the basicLTI module imports classes with the same names
namespace moodle\mod\lti; // Using a namespace as the basicLTI module imports classes with the same names.
defined('MOODLE_INTERNAL') || die;
require_once($CFG->dirroot . '/mod/lti/OAuth.php');
require_once($CFG->dirroot . '/mod/lti/TrivialStore.php');
function getOAuthKeyFromHeaders()
{
$request_headers = OAuthUtil::get_headers();
// print_r($request_headers);
function get_oauth_key_from_headers() {
$requestheaders = OAuthUtil::get_headers();
if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") {
$header_parameters = OAuthUtil::split_header($request_headers['Authorization']);
if (@substr($requestheaders['Authorization'], 0, 6) == "OAuth ") {
$headerparameters = OAuthUtil::split_header($requestheaders['Authorization']);
// echo("HEADER PARMS=\n");
// print_r($header_parameters);
return $header_parameters['oauth_consumer_key'];
return format_string($headerparameters['oauth_consumer_key']);
}
return false;
}
function handleOAuthBodyPOST($oauth_consumer_key, $oauth_consumer_secret, $body, $request_headers = null)
{
if($request_headers == null){
$request_headers = OAuthUtil::get_headers();
function handle_oauth_body_post($oauthconsumerkey, $oauthconsumersecret, $body, $requestheaders = null) {
if ($requestheaders == null) {
$requestheaders = OAuthUtil::get_headers();
}
// Must reject application/x-www-form-urlencoded
if (isset($request_headers['Content-type'])) {
if ($request_headers['Content-type'] == 'application/x-www-form-urlencoded' ) {
// Must reject application/x-www-form-urlencoded.
if (isset($requestheaders['Content-type'])) {
if ($requestheaders['Content-type'] == 'application/x-www-form-urlencoded' ) {
throw new OAuthException("OAuth request body signing must not use application/x-www-form-urlencoded");
}
}
if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") {
$header_parameters = OAuthUtil::split_header($request_headers['Authorization']);
// echo("HEADER PARMS=\n");
// print_r($header_parameters);
$oauth_body_hash = $header_parameters['oauth_body_hash'];
// echo("OBH=".$oauth_body_hash."\n");
if (@substr($requestheaders['Authorization'], 0, 6) == "OAuth ") {
$headerparameters = OAuthUtil::split_header($requestheaders['Authorization']);
$oauthbodyhash = $headerparameters['oauth_body_hash'];
}
if ( ! isset($oauth_body_hash) ) {
if ( ! isset($oauthbodyhash) ) {
throw new OAuthException("OAuth request body signing requires oauth_body_hash body");
}
// Verify the message signature
// Verify the message signature.
$store = new TrivialOAuthDataStore();
$store->add_consumer($oauth_consumer_key, $oauth_consumer_secret);
$store->add_consumer($oauthconsumerkey, $oauthconsumersecret);
$server = new OAuthServer($store);
@ -120,46 +90,12 @@ function handleOAuthBodyPOST($oauth_consumer_key, $oauth_consumer_secret, $body,
}
$postdata = $body;
// echo($postdata);
$hash = base64_encode(sha1($postdata, TRUE));
$hash = base64_encode(sha1($postdata, true));
if ( $hash != $oauth_body_hash ) {
if ( $hash != $oauthbodyhash ) {
throw new OAuthException("OAuth oauth_body_hash mismatch");
}
return $postdata;
}
function sendOAuthBodyPOST($method, $endpoint, $oauth_consumer_key, $oauth_consumer_secret, $content_type, $body)
{
$hash = base64_encode(sha1($body, TRUE));
$parms = array('oauth_body_hash' => $hash);
$test_token = '';
$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
$test_consumer = new OAuthConsumer($oauth_consumer_key, $oauth_consumer_secret, NULL);
$acc_req = OAuthRequest::from_consumer_and_token($test_consumer, $test_token, $method, $endpoint, $parms);
$acc_req->sign_request($hmac_method, $test_consumer, $test_token);
$header = $acc_req->to_header();
$header = $header . "\r\nContent-type: " . $content_type . "\r\n";
$params = array('http' => array(
'method' => 'POST',
'content' => $body,
'header' => $header
));
$ctx = stream_context_create($params);
$fp = @fopen($endpoint, 'rb', false, $ctx);
if (!$fp) {
throw new OAuthException("Problem with $endpoint, $php_errormsg");
}
$response = @stream_get_contents($fp);
if ($response === false) {
throw new OAuthException("Problem reading data from $endpoint, $php_errormsg");
}
return $response;
}

View File

@ -1,23 +1,21 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
//
// This file is part of BasicLTI4Moodle
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// BasicLTI4Moodle is an IMS BasicLTI (Basic Learning Tools for Interoperability)
// consumer for Moodle 1.9 and Moodle 2.0. BasicLTI is a IMS Standard that allows web
// based learning tools to be easily integrated in LMS as native ones. The IMS BasicLTI
@ -32,20 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file contains a Trivial memory-based store - no support for tokens
@ -58,50 +43,97 @@
* @license http://www.apache.org/licenses/LICENSE-2.0
*/
namespace moodle\mod\lti;//Using a namespace as the basicLTI module imports classes with the same names
namespace moodle\mod\lti; // Using a namespace as the basicLTI module imports classes with the same names.
defined('MOODLE_INTERNAL') || die;
/**
* A Trivial memory-based store - no support for tokens
* A Trivial memory-based store - no support for tokens.
*/
class TrivialOAuthDataStore extends OAuthDataStore {
/** @var array $consumers Array of tool consumer keys and secrets */
private $consumers = array();
function add_consumer($consumer_key, $consumer_secret) {
$this->consumers[$consumer_key] = $consumer_secret;
/**
* Add a consumer to the array
*
* @param string $consumerkey Consumer key
* @param string $consumersecret Consumer secret
*/
public function add_consumer($consumerkey, $consumersecret) {
$this->consumers[$consumerkey] = $consumersecret;
}
function lookup_consumer($consumer_key) {
if ( strpos($consumer_key, "http://" ) === 0 ) {
$consumer = new OAuthConsumer($consumer_key, "secret", null);
/**
* Get OAuth consumer given its key
*
* @param string $consumerkey Consumer key
*
* @return moodle\mod\lti\OAuthConsumer OAuthConsumer object
*/
public function lookup_consumer($consumerkey) {
if (strpos($consumerkey, "http://" ) === 0) {
$consumer = new OAuthConsumer($consumerkey, "secret", null);
return $consumer;
}
if ( $this->consumers[$consumer_key] ) {
$consumer = new OAuthConsumer($consumer_key, $this->consumers[$consumer_key], null);
if ( $this->consumers[$consumerkey] ) {
$consumer = new OAuthConsumer($consumerkey, $this->consumers[$consumerkey], null);
return $consumer;
}
return null;
}
function lookup_token($consumer, $token_type, $token) {
return new OAuthToken($consumer, "");
/**
* Create a dummy OAuthToken object for a consumer
*
* @param moodle\mod\lti\OAuthConsumer $consumer Consumer
* @param string $tokentype Type of token
* @param string $token Token ID
*
* @return moodle\mod\lti\OAuthToken OAuthToken object
*/
public function lookup_token($consumer, $tokentype, $token) {
return new OAuthToken($consumer, '');
}
// Return NULL if the nonce has not been used
// Return $nonce if the nonce was previously used
function lookup_nonce($consumer, $token, $nonce, $timestamp) {
/**
* Nonce values are not checked so just return a null
*
* @param moodle\mod\lti\OAuthConsumer $consumer Consumer
* @param string $token Token ID
* @param string $nonce Nonce value
* @param string $timestamp Timestamp
*
* @return null
*/
public function lookup_nonce($consumer, $token, $nonce, $timestamp) {
// Should add some clever logic to keep nonces from
// being reused - for no we are really trusting
// that the timestamp will save us
// being reused - for now we are really trusting
// that the timestamp will save us.
return null;
}
function new_request_token($consumer) {
/**
* Tokens are not used so just return a null.
*
* @param moodle\mod\lti\OAuthConsumer $consumer Consumer
*
* @return null
*/
public function new_request_token($consumer) {
return null;
}
function new_access_token($token, $consumer) {
/**
* Tokens are not used so just return a null.
*
* @param string $token Token ID
* @param moodle\mod\lti\OAuthConsumer $consumer Consumer
*
* @return null
*/
public function new_access_token($token, $consumer) {
return null;
}
}

View File

@ -15,10 +15,12 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* AJAX service used when adding an External Tool to provide immediate feedback
* AJAX service used when adding an External Tool.
*
* It is used to provide immediate feedback
* of which tool provider is to be used based on the Launch URL.
*
* @package mod
* @package mod_lti
* @subpackage xml
* @copyright Copyright (c) 2011 Moodlerooms Inc. (http://www.moodlerooms.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
@ -41,10 +43,10 @@ switch ($action) {
$toolurl = required_param('toolurl', PARAM_RAW);
$toolid = optional_param('toolid', 0, PARAM_INT);
if(empty($toolid) && !empty($toolurl)){
if (empty($toolid) && !empty($toolurl)) {
$tool = lti_get_tool_by_url_match($toolurl, $courseid);
if(!empty($tool)){
if (!empty($tool)) {
$toolid = $tool->id;
$response->toolid = $tool->id;
@ -56,7 +58,7 @@ switch ($action) {
}
if (!empty($toolid)) {
// Look up privacy settings
// Look up privacy settings.
$query = '
SELECT name, value
FROM {lti_types_config}
@ -66,7 +68,7 @@ switch ($action) {
';
$privacyconfigs = $DB->get_records_sql($query, array('typeid' => $toolid));
foreach($privacyconfigs as $config){
foreach ($privacyconfigs as $config) {
$configname = $config->name;
$response->$configname = $config->value;
}

View File

@ -34,18 +34,18 @@ class moodle1_mod_lti_handler extends moodle1_mod_handler {
protected $moduleid = null;
/**
* Declare the paths in moodle.xml we are able to convert
*
* The method returns list of {@link convert_path} instances.
* For each path returned, the corresponding conversion method must be
* defined.
*
* Note that the path /MOODLE_BACKUP/COURSE/MODULES/MOD/LTI does not
* actually exist in the file. The last element with the module name was
* appended by the moodle1_converter class.
*
* @return array of {@link convert_path} instances
*/
* Declare the paths in moodle.xml we are able to convert
*
* The method returns list of {@link convert_path} instances.
* For each path returned, the corresponding conversion method must be
* defined.
*
* Note that the path /MOODLE_BACKUP/COURSE/MODULES/MOD/LTI does not
* actually exist in the file. The last element with the module name was
* appended by the moodle1_converter class.
*
* @return array of {@link convert_path} instances
*/
public function get_paths() {
return array(
@ -57,33 +57,33 @@ class moodle1_mod_lti_handler extends moodle1_mod_handler {
}
/**
* This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/LTI
* data available
*/
* This is executed every time we have one /MOODLE_BACKUP/COURSE/MODULES/MOD/LTI
* data available
*/
public function process_basiclti($data) {
global $DB;
// get the course module id and context id
// Get the course module id and context id.
$instanceid = $data['id'];
$cminfo = $this->get_cminfo($instanceid);
$this->moduleid = $cminfo['id'];
$contextid = $this->converter->get_contextid(CONTEXT_MODULE, $this->moduleid);
// get a fresh new file manager for this instance
// Get a fresh new file manager for this instance.
$this->fileman = $this->converter->get_file_manager($contextid, 'mod_lti');
// convert course files embedded into the intro
// Convert course files embedded into the intro.
$this->fileman->filearea = 'intro';
$this->fileman->itemid = 0;
$data['intro'] = moodle1_converter::migrate_referenced_files($data['intro'], $this->fileman);
// start writing assignment.xml
// Start writing assignment.xml.
$this->open_xml_writer("activities/lti_{$this->moduleid}/lti.xml");
$this->xmlwriter->begin_tag('activity', array('id' => $instanceid, 'moduleid' => $this->moduleid,
'modulename' => 'lti', 'contextid' => $contextid));
$this->xmlwriter->begin_tag('lti', array('id' => $instanceid));
$ignore_fields = array('id', 'modtype');
$ignorefields = array('id', 'modtype');
if (!$DB->record_exists('lti_types', array('id' => $data['typeid']))) {
$ntypeid = $DB->get_field('lti_types_config',
'typeid',
@ -105,7 +105,7 @@ class moodle1_mod_lti_handler extends moodle1_mod_handler {
$data['servicesalt'] = uniqid('', true);
}
foreach ($data as $field => $value) {
if (!in_array($field, $ignore_fields)) {
if (!in_array($field, $ignorefields)) {
$this->xmlwriter->full_tag($field, $value);
}
}
@ -114,15 +114,15 @@ class moodle1_mod_lti_handler extends moodle1_mod_handler {
}
/**
* This is executed when we reach the closing </MOD> tag of our 'lti' path
*/
* This is executed when we reach the closing </MOD> tag of our 'lti' path
*/
public function on_basiclti_end() {
// finish writing basiclti.xml
// Finish writing basiclti.xml.
$this->xmlwriter->end_tag('lti');
$this->xmlwriter->end_tag('activity');
$this->close_xml_writer();
// write inforef.xml
// Write inforef.xml.
$this->open_xml_writer("activities/lti_{$this->moduleid}/inforef.xml");
$this->xmlwriter->begin_tag('inforef');
$this->xmlwriter->begin_tag('fileref');

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* Defines backup_lti_activity_task class
@ -78,13 +78,13 @@ class backup_lti_activity_task extends backup_activity_task {
$base = preg_quote($CFG->wwwroot, "/");
// Link to the list of basiclti tools
$search="/(".$base."\/mod\/lti\/index.php\?id\=)([0-9]+)/";
$content= preg_replace($search, '$@LTIINDEX*$2@$', $content);
// Link to the list of basiclti tools.
$search = "/(".$base."\/mod\/lti\/index.php\?id\=)([0-9]+)/";
$content = preg_replace($search, '$@LTIINDEX*$2@$', $content);
// Link to basiclti view by moduleid
$search="/(".$base."\/mod\/lti\/view.php\?id\=)([0-9]+)/";
$content= preg_replace($search, '$@LTIVIEWBYID*$2@$', $content);
// Link to basiclti view by moduleid.
$search = "/(".$base."\/mod\/lti\/view.php\?id\=)([0-9]+)/";
$content = preg_replace($search, '$@LTIVIEWBYID*$2@$', $content);
return $content;
}

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file contains all the backup steps that will be used
@ -57,10 +57,10 @@ class backup_lti_activity_structure_step extends backup_activity_structure_step
// TODO: MDL-34161 - Fix restore to support course/site tools & submissions.
// To know if we are including userinfo
// To know if we are including userinfo.
$userinfo = $this->get_setting_value('userinfo');
// Define each element separated
// Define each element separated.
$lti = new backup_nested_element('lti', array('id'), array(
'name',
'intro',
@ -88,21 +88,22 @@ class backup_lti_activity_structure_step extends backup_activity_structure_step
);
// Build the tree
// (none)
// (none).
// Define sources
// Define sources.
$lti->set_source_table('lti', array('id' => backup::VAR_ACTIVITYID));
// Define id annotations
// (none)
// (none).
// Define file annotations
$lti->annotate_files('mod_lti', 'intro', null); // This file areas haven't itemid
// Define file annotations.
$lti->annotate_files('mod_lti', 'intro', null); // This file areas haven't itemid.
// Add support for subplugin structure.
// Add support for subplugin structures.
$this->add_subplugin_structure('ltisource', $lti, true);
$this->add_subplugin_structure('ltiservice', $lti, true);
// Return the root element (lti), wrapped into standard activity structure
// Return the root element (lti), wrapped into standard activity structure.
return $this->prepare_activity_structure($lti);
}
}

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file contains the lti module restore class

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file contains all the restore steps that will be used
@ -59,8 +59,9 @@ class restore_lti_activity_structure_step extends restore_activity_structure_ste
$lti = new restore_path_element('lti', '/activity/lti');
$paths[] = $lti;
// Add support for subplugin structure.
// Add support for subplugin structures.
$this->add_subplugin_structure('ltisource', $lti);
$this->add_subplugin_structure('ltiservice', $lti);
// Return the paths wrapped into standard activity structure.
return $this->prepare_activity_structure($paths);

View File

@ -1,56 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
//
// This file is part of BasicLTI4Moodle
//
// BasicLTI4Moodle is an IMS BasicLTI (Basic Learning Tools for Interoperability)
// consumer for Moodle 1.9 and Moodle 2.0. BasicLTI is a IMS Standard that allows web
// based learning tools to be easily integrated in LMS as native ones. The IMS BasicLTI
// specification is part of the IMS standard Common Cartridge 1.1 Sakai and other main LMS
// are already supporting or going to support BasicLTI. This project Implements the consumer
// for Moodle. Moodle is a Free Open source Learning Management System by Martin Dougiamas.
// BasicLTI4Moodle is a project iniciated and leaded by Ludo(Marc Alier) and Jordi Piguillem
// at the GESSI research group at UPC.
// SimpleLTI consumer for Moodle is an implementation of the early specification of LTI
// by Charles Severance (Dr Chuck) htp://dr-chuck.com , developed by Jordi Piguillem in a
// Google Summer of Code 2008 project co-mentored by Charles Severance and Marc Alier.
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
/**
* This file contains a library of javasxript functions for the lti module
*
* @package mod
* @subpackage lti
* @copyright 2009 Marc Alier, Jordi Piguillem, Nikolas Galanis
* marc.alier@upc.edu
* @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu
* @author Marc Alier
* @author Jordi Piguillem
* @author Nikolas Galanis
* @author Charles Severance
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
function basicltiDebugToggle() {
var ele = document.getElementById('basicltiDebug');
if (ele.style.display == 'block') {
ele.style.display = 'none';
} else {
ele.style.display = 'block';
}
}

View File

@ -0,0 +1,277 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains an abstract definition of an LTI resource
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_lti\local\ltiservice;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/mod/lti/locallib.php');
/**
* The mod_lti\local\ltiservice\resource_base class.
*
* @package mod_lti
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class resource_base {
/** @var object Service associated with this resource. */
private $service;
/** @var string Type for this resource. */
protected $type;
/** @var string ID for this resource. */
protected $id;
/** @var string Template for this resource. */
protected $template;
/** @var array Custom parameter substitution variables associated with this resource. */
protected $variables;
/** @var array Media types supported by this resource. */
protected $formats;
/** @var array HTTP actions supported by this resource. */
protected $methods;
/** @var array Template variables parsed from the resource template. */
protected $params;
/**
* Class constructor.
*
* @param mod_lti\local\ltiservice\service_base $service Service instance
*/
public function __construct($service) {
$this->service = $service;
$this->type = 'RestService';
$this->id = null;
$this->template = null;
$this->methods = array();
$this->variables = array();
$this->formats = array();
$this->methods = array();
$this->params = null;
}
/**
* Get the resource ID.
*
* @return string
*/
public function get_id() {
return $this->id;
}
/**
* Get the resource template.
*
* @return string
*/
public function get_template() {
return $this->template;
}
/**
* Get the resource path.
*
* @return string
*/
public function get_path() {
return $this->get_template();
}
/**
* Get the resource type.
*
* @return string
*/
public function get_type() {
return $this->type;
}
/**
* Get the resource's service.
*
* @return mod_lti\local\ltiservice\service_base
*/
public function get_service() {
return $this->service;
}
/**
* Get the resource methods.
*
* @return array
*/
public function get_methods() {
return $this->methods;
}
/**
* Get the resource media types.
*
* @return array
*/
public function get_formats() {
return $this->formats;
}
/**
* Get the resource template variables.
*
* @return array
*/
public function get_variables() {
return $this->variables;
}
/**
* Get the resource fully qualified endpoint.
*
* @return string
*/
public function get_endpoint() {
$this->parse_template();
$url = $this->get_service()->get_service_path() . $this->get_template();
foreach ($this->params as $key => $value) {
$url = str_replace('{' . $key . '}', $value, $url);
}
$toolproxy = $this->get_service()->get_tool_proxy();
if (!empty($toolproxy)) {
$url = str_replace('{tool_proxy_id}', $toolproxy->guid, $url);
}
return $url;
}
/**
* Execute the request for this resource.
*
* @param mod_lti\local\ltiservice\response $response Response object for this request.
*/
public abstract function execute($response);
/**
* Check to make sure the request is valid.
*
* @param string $toolproxyguid Consumer key
* @param string $body Body of HTTP request message
*
* @return boolean
*/
public function check_tool_proxy($toolproxyguid, $body = null) {
$ok = false;
if ($this->get_service()->check_tool_proxy($toolproxyguid, $body)) {
$toolproxyjson = $this->get_service()->get_tool_proxy()->toolproxy;
if (empty($toolproxyjson)) {
$ok = true;
} else {
$toolproxy = json_decode($toolproxyjson);
if (!empty($toolproxy) && isset($toolproxy->security_contract->tool_service)) {
$contexts = lti_get_contexts($toolproxy);
$tpservices = $toolproxy->security_contract->tool_service;
foreach ($tpservices as $service) {
$fqid = lti_get_fqid($contexts, $service->service);
$id = explode('#', $fqid, 2);
if ($this->get_id() === $id[1]) {
$ok = true;
break;
}
}
}
if (!$ok) {
debugging('Requested service not included in tool proxy: ' . $this->get_id());
}
}
}
return $ok;
}
/**
* Parse a value for custom parameter substitution variables.
*
* @param string $value String to be parsed
*
* @return string
*/
public function parse_value($value) {
return $value;
}
/**
* Parse the template for variables.
*
* @return array
*/
protected function parse_template() {
if (empty($this->params)) {
$this->params = array();
if (isset($_SERVER['PATH_INFO'])) {
$path = explode('/', $_SERVER['PATH_INFO']);
$parts = explode('/', $this->get_template());
for ($i = 0; $i < count($parts); $i++) {
if ((substr($parts[$i], 0, 1) == '{') && (substr($parts[$i], -1) == '}')) {
$value = '';
if ($i < count($path)) {
$value = $path[$i];
}
$this->params[substr($parts[$i], 1, -1)] = $value;
}
}
}
}
return $this->params;
}
}

View File

@ -0,0 +1,220 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains an abstract definition of an LTI service
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_lti\local\ltiservice;
defined('MOODLE_INTERNAL') || die;
/**
* The mod_lti\local\ltiservice\response class.
*
* @package mod_lti
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class response {
/** @var int HTTP response code. */
private $code;
/** @var string HTTP response reason. */
private $reason;
/** @var string HTTP request method. */
private $requestmethod;
/** @var string HTTP request accept header. */
private $accept;
/** @var string HTTP response content type. */
private $contenttype;
/** @var string HTTP request body. */
private $data;
/** @var string HTTP response body. */
private $body;
/** @var array HTTP response codes. */
private $responsecodes;
/**
* Class constructor.
*/
public function __construct() {
$this->code = 200;
$this->reason = '';
$this->requestmethod = $_SERVER['REQUEST_METHOD'];
$this->accept = '';
$this->contenttype = '';
$this->data = '';
$this->body = '';
$this->responsecodes = array(
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
300 => 'Multiple Choices',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
415 => 'Unsupported Media Type',
500 => 'Internal Server Error',
501 => 'Not Implemented'
);
}
/**
* Get the response code.
*
* @return int
*/
public function get_code() {
return $this->code;
}
/**
* Set the response code.
*
* @param int $code Response code
*/
public function set_code($code) {
$this->code = $code;
$this->reason = '';
}
/**
* Get the response reason.
*
* @return string
*/
public function get_reason() {
if (empty($this->reason)) {
$this->reason = $this->responsecodes[$this->code];
}
// Use generic reason for this category (based on first digit) if a specific reason is not defined.
if (empty($this->reason)) {
$this->reason = $this->responsecodes[intval($this->code / 100) * 100];
}
return $this->reason;
}
/**
* Set the response reason.
*
* @param string $reason Reason
*/
public function set_reason($reason) {
$this->reason = $reason;
}
/**
* Get the request method.
*
* @return string
*/
public function get_request_method() {
return $this->requestmethod;
}
/**
* Get the request accept header.
*
* @return string
*/
public function get_accept() {
return $this->accept;
}
/**
* Set the request accept header.
*
* @param string $accept Accept header value
*/
public function set_accept($accept) {
$this->accept = $accept;
}
/**
* Get the response content type.
*
* @return string
*/
public function get_content_type() {
return $this->contenttype;
}
/**
* Set the response content type.
*
* @param string $contenttype Content type
*/
public function set_content_type($contenttype) {
$this->contenttype = $contenttype;
}
/**
* Get the request body.
*
* @return string
*/
public function get_request_data() {
return $this->data;
}
/**
* Set the response body.
*
* @param string $data Body data
*/
public function set_request_data($data) {
$this->data = $data;
}
/**
* Set the response body.
*
* @param string $body Body data
*/
public function set_body($body) {
$this->body = $body;
}
/**
* Send the response.
*/
public function send() {
header("HTTP/1.0 {$this->code} {$this->get_reason()}");
if (($this->code >= 200) && ($this->code < 300)) {
if (!empty($this->contenttype)) {
header("Content-Type: {$this->contenttype};charset=UTF-8");
}
if (!empty($this->body)) {
echo $this->body;
}
}
}
}

View File

@ -0,0 +1,234 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains an abstract definition of an LTI service
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_lti\local\ltiservice;
defined('MOODLE_INTERNAL') || die();
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;
/**
* The mod_lti\local\ltiservice\service_base class.
*
* @package mod_lti
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class service_base {
/** Label representing an LTI 2 message type */
const LTI_VERSION2P0 = 'LTI-2p0';
/** @var string ID for the service. */
protected $id;
/** @var string Human readable name for the service. */
protected $name;
/** @var boolean <code>true</code> if requests for this service do not need to be signed. */
protected $unsigned;
/** @var stdClass Tool proxy object for the current service request. */
private $toolproxy;
/** @var array Instances of the resources associated with this service. */
protected $resources;
/**
* Class constructor.
*/
public function __construct() {
$this->id = null;
$this->name = null;
$this->unsigned = false;
$this->toolproxy = null;
$this->resources = null;
}
/**
* Get the service ID.
*
* @return string
*/
public function get_id() {
return $this->id;
}
/**
* Get the service name.
*
* @return string
*/
public function get_name() {
return $this->name;
}
/**
* Get whether the service requests need to be signed.
*
* @return boolean
*/
public function is_unsigned() {
return $this->unsigned;
}
/**
* Get the tool proxy object.
*
* @return stdClass
*/
public function get_tool_proxy() {
return $this->toolproxy;
}
/**
* Set the tool proxy object.
*
* @param object $toolproxy The tool proxy for this service request
*
* @var stdClass
*/
public function set_tool_proxy($toolproxy) {
$this->toolproxy = $toolproxy;
}
/**
* Get the resources for this service.
*
* @return array
*/
abstract public function get_resources();
/**
* Get the path for service requests.
*
* @return string
*/
public static function get_service_path() {
$url = new \moodle_url('/mod/lti/services.php');
return $url->out(false);
}
/**
* Parse a string for custom substitution parameter variables supported by this service's resources.
*
* @param string $value Value to be parsed
*
* @return string
*/
public function parse_value($value) {
if (empty($this->resources)) {
$this->resources = $this->get_resources();
}
if (!empty($this->resources)) {
foreach ($this->resources as $resource) {
$value = $resource->parse_value($value);
}
}
return $value;
}
/**
* Check that the request has been properly signed.
*
* @param string $toolproxyguid Tool Proxy GUID
* @param string $body Request body (null if none)
*
* @return boolean
*/
public function check_tool_proxy($toolproxyguid, $body = null) {
$ok = false;
$toolproxy = null;
$consumerkey = lti\get_oauth_key_from_headers();
if (empty($toolproxyguid)) {
$toolproxyguid = $consumerkey;
}
if (!empty($toolproxyguid)) {
$toolproxy = lti_get_tool_proxy_from_guid($toolproxyguid);
if ($toolproxy !== false) {
if (!$this->is_unsigned() && ($toolproxy->guid == $consumerkey)) {
$ok = $this->check_signature($toolproxy->guid, $toolproxy->secret, $body);
} else {
$ok = $this->is_unsigned();
}
}
}
if ($ok) {
$this->toolproxy = $toolproxy;
}
return $ok;
}
/**
* Check the request signature.
*
* @param string $consumerkey Consumer key
* @param string $secret Shared secret
* @param string $body Request body
*
* @return boolean
*/
private function check_signature($consumerkey, $secret, $body) {
$ok = true;
try {
// TODO: Switch to core oauthlib once implemented - MDL-30149.
lti\handle_oauth_body_post($consumerkey, $secret, $body);
} catch (\Exception $e) {
debugging($e->getMessage() . "\n");
$ok = false;
}
return $ok;
}
}

View File

@ -0,0 +1,59 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* LTI service plugin info.
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_lti\plugininfo;
use core\plugininfo\base;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_lti\plugininfo\ltiservice class.
*
* @package mod_lti
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class ltiservice extends base {
/**
* Should there be a way to uninstall the plugin via the administration UI?
*
* Uninstallation is not allowed for core subplugins.
*
* @return boolean
*/
public function is_uninstall_allowed() {
if ($this->is_standard()) {
return false;
}
return true;
}
}

View File

@ -57,7 +57,7 @@ $capabilities = array(
),
// When the user arrives at the external tool, if they have this capability
// in Moodle, then they given the Instructor role in the remote system,
// in Moodle, then they are given the Instructor role in the remote system,
// otherwise they are given Learner. See the lti_get_ims_role function.
'mod/lti:manage' => array(
'riskbitmask' => RISK_PERSONAL, // A bit of a guess, but seems likely.
@ -81,7 +81,7 @@ $capabilities = array(
)
),
// The ability to request the adminstirator to configure a particular
// The ability to request the administrator to configure a particular
// External tool globally.
'mod/lti:requesttooladd' => array(
'captype' => 'write',

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/lti/db" VERSION="20120122" COMMENT="XMLDB file for Moodle mod/lti"
<XMLDB PATH="mod/lti/db" VERSION="20140612" COMMENT="XMLDB file for Moodle mod/lti"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
@ -40,6 +40,29 @@
<INDEX NAME="course" UNIQUE="false" FIELDS="course"/>
</INDEXES>
</TABLE>
<TABLE NAME="lti_tool_proxies" COMMENT="LTI tool proxy registrations">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" DEFAULT="Tool Provider" SEQUENCE="false" COMMENT="Tool Provider name"/>
<FIELD NAME="regurl" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="state" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="Configured = 1, Pending = 2, Accepted = 3, Rejected = 4, Cancelled = 5"/>
<FIELD NAME="guid" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="secret" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="vendorcode" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="capabilityoffered" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="List of capabilities offered, one per line"/>
<FIELD NAME="serviceoffered" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="List of services offered, one per line"/>
<FIELD NAME="toolproxy" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="JSON string representing tool proxy returned by tool provider"/>
<FIELD NAME="createdby" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of user which initiated the registration process"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Date/time at which the record was created"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Date/time at which the record was last modified"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</KEYS>
<INDEXES>
<INDEX NAME="guid" UNIQUE="true" FIELDS="guid"/>
</INDEXES>
</TABLE>
<TABLE NAME="lti_types" COMMENT="Basic LTI pre-configured activities">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
@ -49,6 +72,11 @@
<FIELD NAME="state" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="2" SEQUENCE="false" COMMENT="Active = 1, Pending = 2, Rejected = 3"/>
<FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="coursevisible" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="toolproxyid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Primary key of related tool proxy (null for LTI 1 tools)"/>
<FIELD NAME="enabledcapability" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Enabled capabilities, one per line (null for LTI 1 tools)"/>
<FIELD NAME="parameter" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Launch parameters, one per line (null for LTI 1 tools)"/>
<FIELD NAME="icon" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="URL to icon file"/>
<FIELD NAME="secureicon" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Secure URL to icon file"/>
<FIELD NAME="createdby" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
@ -75,6 +103,23 @@
<INDEX NAME="typeid" UNIQUE="false" FIELDS="typeid"/>
</INDEXES>
</TABLE>
<TABLE NAME="lti_tool_settings" COMMENT="LTI tool setting values">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="toolproxyid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Primary key of related tool proxy"/>
<FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Primary key of course (null for system-wide settings)"/>
<FIELD NAME="coursemoduleid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Primary key of course module - tool link added to course (null for system-wide and context-wide settings)"/>
<FIELD NAME="settings" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Setting values as JSON"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Date/time at which the record was created"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Date/time at which the record was last modified"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="toolproxy" TYPE="foreign" FIELDS="toolproxyid" REFTABLE="lti_tool_proxies" REFFIELDS="id" COMMENT="The tool proxy to which the setting relates"/>
<KEY NAME="course" TYPE="foreign" FIELDS="course" REFTABLE="course" REFFIELDS="id" COMMENT="The course to which the setting relates"/>
<KEY NAME="coursemodule" TYPE="foreign" FIELDS="coursemoduleid" REFTABLE="lti" REFFIELDS="id" COMMENT="The module instance to which the setting relates"/>
</KEYS>
</TABLE>
<TABLE NAME="lti_submission" COMMENT="Keeps track of individual submissions for LTI activities.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>

View File

@ -27,7 +27,7 @@
defined('MOODLE_INTERNAL') || die();
$logs = array(
array('module'=>'lti', 'action'=>'view', 'mtable'=>'lti', 'field'=>'name'),
array('module'=>'lti', 'action'=>'launch', 'mtable'=>'lti', 'field'=>'name'),
array('module'=>'lti', 'action'=>'view all', 'mtable'=>'lti', 'field'=>'name')
array('module' => 'lti', 'action' => 'view', 'mtable' => 'lti', 'field' => 'name'),
array('module' => 'lti', 'action' => 'launch', 'mtable' => 'lti', 'field' => 'name'),
array('module' => 'lti', 'action' => 'view all', 'mtable' => 'lti', 'field' => 'name')
);

View File

@ -1,5 +1,4 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
@ -27,4 +26,5 @@ defined('MOODLE_INTERNAL') || die();
$subplugins = array(
'ltisource' => 'mod/lti/source',
'ltiservice' => 'mod/lti/service'
);

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file keeps track of upgrades to the lti module
@ -61,24 +61,22 @@
function xmldb_lti_upgrade($oldversion) {
global $CFG, $DB;
require_once(__DIR__ . '/upgradelib.php');
$dbman = $DB->get_manager();
// Moodle v2.2.0 release upgrade line
// Put any upgrade step following this
// Put any upgrade step following this.
// Moodle v2.3.0 release upgrade line
// Put any upgrade step following this
// Put any upgrade step following this.
// Moodle v2.4.0 release upgrade line
// Put any upgrade step following this
// Put any upgrade step following this.
// Moodle v2.5.0 release upgrade line.
// Put any upgrade step following this.
// Moodle v2.6.0 release upgrade line.
// Put any upgrade step following this.
@ -99,6 +97,97 @@ function xmldb_lti_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2014060201, 'lti');
}
if ($oldversion < 2014061200) {
// Define table lti_tool_proxies to be created.
$table = new xmldb_table('lti_tool_proxies');
// Adding fields to table lti_tool_proxies.
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, 'Tool Provider');
$table->add_field('regurl', XMLDB_TYPE_TEXT, null, null, null, null, null);
$table->add_field('state', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1');
$table->add_field('guid', XMLDB_TYPE_CHAR, '255', null, null, null, null);
$table->add_field('secret', XMLDB_TYPE_CHAR, '255', null, null, null, null);
$table->add_field('vendorcode', XMLDB_TYPE_CHAR, '255', null, null, null, null);
$table->add_field('capabilityoffered', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
$table->add_field('serviceoffered', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
$table->add_field('toolproxy', XMLDB_TYPE_TEXT, null, null, null, null, null);
$table->add_field('createdby', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
// Adding keys to table lti_tool_proxies.
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
// Adding indexes to table lti_tool_proxies.
$table->add_index('guid', XMLDB_INDEX_UNIQUE, array('guid'));
// Conditionally launch create table for lti_tool_proxies.
if (!$dbman->table_exists($table)) {
$dbman->create_table($table);
}
// Define table lti_tool_settings to be created.
$table = new xmldb_table('lti_tool_settings');
// Adding fields to table lti_tool_settings.
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('toolproxyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
$table->add_field('coursemoduleid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
$table->add_field('settings', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
$table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
// Adding keys to table lti_tool_settings.
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
$table->add_key('toolproxy', XMLDB_KEY_FOREIGN, array('toolproxyid'), 'lti_tool_proxies', array('id'));
$table->add_key('course', XMLDB_KEY_FOREIGN, array('course'), 'course', array('id'));
$table->add_key('coursemodule', XMLDB_KEY_FOREIGN, array('coursemoduleid'), 'lti', array('id'));
// Conditionally launch create table for lti_tool_settings.
if (!$dbman->table_exists($table)) {
$dbman->create_table($table);
}
// Define table lti_types to be updated.
$table = new xmldb_table('lti_types');
// Adding fields to table lti_types.
$field = new xmldb_field('toolproxyid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
$field = new xmldb_field('enabledcapability', XMLDB_TYPE_TEXT, null, null, null, null, null);
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
$field = new xmldb_field('parameter', XMLDB_TYPE_TEXT, null, null, null, null, null);
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
$field = new xmldb_field('icon', XMLDB_TYPE_TEXT, null, null, null, null, null);
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
$field = new xmldb_field('secureicon', XMLDB_TYPE_TEXT, null, null, null, null, null);
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Lti savepoint reached.
upgrade_mod_savepoint(true, 2014061200, 'lti');
}
if ($oldversion < 2014100300) {
mod_lti_upgrade_custom_separator();
// Lti savepoint reached.
upgrade_mod_savepoint(true, 2014100300, 'lti');
}
return true;
}

62
mod/lti/db/upgradelib.php Normal file
View File

@ -0,0 +1,62 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* LTI upgrade script.
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Update any custom parameter settings separated by semicolons.
*/
function mod_lti_upgrade_custom_separator() {
global $DB;
if ($DB->replace_all_text_supported()) {
// Initialise parameter array.
$params = array('semicolon' => ';', 'likecr' => "%\r%", 'likelf' => "%\n%", 'lf' => "\n");
// Initialise NOT LIKE clauses to check for CR and LF characters.
$notlikecr = $DB->sql_like('value', ':likecr', true, true, true);
$notlikelf = $DB->sql_like('value', ':likelf', true, true, true);
// Update any instances in the lti_types_config table.
$sql = 'UPDATE {lti_types_config} ' .
'SET value = REPLACE(value, :semicolon, :lf) ' .
'WHERE (name = \'customparameters\') AND (' . $notlikecr . ') AND (' . $notlikelf . ')';
$DB->execute($sql, $params);
// Initialise NOT LIKE clauses to check for CR and LF characters.
$notlikecr = $DB->sql_like('instructorcustomparameters', ':likecr', true, true, true);
$notlikelf = $DB->sql_like('instructorcustomparameters', ':likelf', true, true, true);
// Update any instances in the lti table.
$sql = 'UPDATE {lti} ' .
'SET instructorcustomparameters = REPLACE(instructorcustomparameters, :semicolon, :lf) ' .
'WHERE (instructorcustomparameters IS NOT NULL) AND (' . $notlikecr . ') AND (' . $notlikelf . ')';
$DB->execute($sql, $params);
}
}

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file defines de main basiclti configuration form
@ -58,8 +58,9 @@ class mod_lti_edit_types_form extends moodleform{
$mform =& $this->_form;
//-------------------------------------------------------------------------------
// Add basiclti elements
$istool = $this->_customdata->istool;
// Add basiclti elements.
$mform->addElement('header', 'setup', get_string('tool_settings', 'lti'));
$mform->addElement('text', 'lti_typename', get_string('typename', 'lti'));
@ -67,24 +68,37 @@ class mod_lti_edit_types_form extends moodleform{
$mform->addHelpButton('lti_typename', 'typename', 'lti');
$mform->addRule('lti_typename', null, 'required', null, 'client');
$mform->addElement('text', 'lti_toolurl', get_string('toolurl', 'lti'), array('size'=>'64'));
$mform->addElement('text', 'lti_toolurl', get_string('toolurl', 'lti'), array('size' => '64'));
$mform->setType('lti_toolurl', PARAM_TEXT);
$mform->addHelpButton('lti_toolurl', 'toolurl', 'lti');
$mform->addRule('lti_toolurl', null, 'required', null, 'client');
if (!$istool) {
$mform->addRule('lti_toolurl', null, 'required', null, 'client');
} else {
$mform->disabledIf('lti_toolurl', null);
}
$mform->addElement('text', 'lti_resourcekey', get_string('resourcekey_admin', 'lti'));
$mform->setType('lti_resourcekey', PARAM_TEXT);
$mform->addHelpButton('lti_resourcekey', 'resourcekey_admin', 'lti');
if (!$istool) {
$mform->addElement('text', 'lti_resourcekey', get_string('resourcekey_admin', 'lti'));
$mform->setType('lti_resourcekey', PARAM_TEXT);
$mform->addHelpButton('lti_resourcekey', 'resourcekey_admin', 'lti');
$mform->addElement('passwordunmask', 'lti_password', get_string('password_admin', 'lti'));
$mform->setType('lti_password', PARAM_TEXT);
$mform->addHelpButton('lti_password', 'password_admin', 'lti');
$mform->addElement('passwordunmask', 'lti_password', get_string('password_admin', 'lti'));
$mform->setType('lti_password', PARAM_TEXT);
$mform->addHelpButton('lti_password', 'password_admin', 'lti');
}
$mform->addElement('textarea', 'lti_customparameters', get_string('custom', 'lti'), array('rows'=>4, 'cols'=>60));
if ($istool) {
$mform->addElement('textarea', 'lti_parameters', get_string('parameter', 'lti'), array('rows' => 4, 'cols' => 60));
$mform->setType('lti_parameters', PARAM_TEXT);
$mform->addHelpButton('lti_parameters', 'parameter', 'lti');
$mform->disabledIf('lti_parameters', null);
}
$mform->addElement('textarea', 'lti_customparameters', get_string('custom', 'lti'), array('rows' => 4, 'cols' => 60));
$mform->setType('lti_customparameters', PARAM_TEXT);
$mform->addHelpButton('lti_customparameters', 'custom', 'lti');
if (!empty($this->_customdata->isadmin)) {
if (!$istool && !empty($this->_customdata->isadmin)) {
$mform->addElement('checkbox', 'lti_coursevisible', '&nbsp;', ' ' . get_string('show_in_course', 'lti'));
$mform->addHelpButton('lti_coursevisible', 'show_in_course', 'lti');
} else {
@ -95,7 +109,7 @@ class mod_lti_edit_types_form extends moodleform{
$mform->addElement('hidden', 'typeid');
$mform->setType('typeid', PARAM_INT);
$launchoptions=array();
$launchoptions = array();
$launchoptions[LTI_LAUNCH_CONTAINER_EMBED] = get_string('embed', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS] = get_string('embed_no_blocks', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_REPLACE_MOODLE_WINDOW] = get_string('existing_window', 'lti');
@ -106,76 +120,72 @@ class mod_lti_edit_types_form extends moodleform{
$mform->addHelpButton('lti_launchcontainer', 'default_launch_container', 'lti');
$mform->setType('lti_launchcontainer', PARAM_INT);
// Add privacy preferences fieldset where users choose whether to send their data
$mform->addElement('header', 'privacy', get_string('privacy', 'lti'));
if (!$istool) {
// Add privacy preferences fieldset where users choose whether to send their data.
$mform->addElement('header', 'privacy', get_string('privacy', 'lti'));
$options=array();
$options[0] = get_string('never', 'lti');
$options[1] = get_string('always', 'lti');
$options[2] = get_string('delegate', 'lti');
$options = array();
$options[0] = get_string('never', 'lti');
$options[1] = get_string('always', 'lti');
$options[2] = get_string('delegate', 'lti');
$mform->addElement('select', 'lti_sendname', get_string('share_name_admin', 'lti'), $options);
$mform->setType('lti_sendname', PARAM_INT);
$mform->setDefault('lti_sendname', '2');
$mform->addHelpButton('lti_sendname', 'share_name_admin', 'lti');
$mform->addElement('select', 'lti_sendname', get_string('share_name_admin', 'lti'), $options);
$mform->setType('lti_sendname', PARAM_INT);
$mform->setDefault('lti_sendname', '2');
$mform->addHelpButton('lti_sendname', 'share_name_admin', 'lti');
$mform->addElement('select', 'lti_sendemailaddr', get_string('share_email_admin', 'lti'), $options);
$mform->setType('lti_sendemailaddr', PARAM_INT);
$mform->setDefault('lti_sendemailaddr', '2');
$mform->addHelpButton('lti_sendemailaddr', 'share_email_admin', 'lti');
$mform->addElement('select', 'lti_sendemailaddr', get_string('share_email_admin', 'lti'), $options);
$mform->setType('lti_sendemailaddr', PARAM_INT);
$mform->setDefault('lti_sendemailaddr', '2');
$mform->addHelpButton('lti_sendemailaddr', 'share_email_admin', 'lti');
//-------------------------------------------------------------------------------
// LTI Extensions
// LTI Extensions.
// Add grading preferences fieldset where the tool is allowed to return grades
$mform->addElement('select', 'lti_acceptgrades', get_string('accept_grades_admin', 'lti'), $options);
$mform->setType('lti_acceptgrades', PARAM_INT);
$mform->setDefault('lti_acceptgrades', '2');
$mform->addHelpButton('lti_acceptgrades', 'accept_grades_admin', 'lti');
// Add grading preferences fieldset where the tool is allowed to return grades.
$mform->addElement('select', 'lti_acceptgrades', get_string('accept_grades_admin', 'lti'), $options);
$mform->setType('lti_acceptgrades', PARAM_INT);
$mform->setDefault('lti_acceptgrades', '2');
$mform->addHelpButton('lti_acceptgrades', 'accept_grades_admin', 'lti');
// Add grading preferences fieldset where the tool is allowed to retrieve rosters
//$mform->addElement('select', 'lti_allowroster', get_string('share_roster_admin', 'lti'), $options);
//$mform->setDefault('lti_allowroster', '2');
//$mform->addHelpButton('lti_allowroster', 'share_roster_admin', 'lti');
$mform->addElement('checkbox', 'lti_forcessl', '&nbsp;', ' ' . get_string('force_ssl', 'lti'), $options);
$mform->setType('lti_forcessl', PARAM_BOOL);
if (!empty($CFG->mod_lti_forcessl)) {
$mform->setDefault('lti_forcessl', '1');
$mform->freeze('lti_forcessl');
} else {
$mform->setDefault('lti_forcessl', '0');
}
$mform->addHelpButton('lti_forcessl', 'force_ssl', 'lti');
$mform->addElement('checkbox', 'lti_forcessl', '&nbsp;', ' ' . get_string('force_ssl', 'lti'), $options);
$mform->setType('lti_forcessl', PARAM_BOOL);
if (!empty($CFG->mod_lti_forcessl)) {
$mform->setDefault('lti_forcessl', '1');
$mform->freeze('lti_forcessl');
} else {
$mform->setDefault('lti_forcessl', '0');
}
$mform->addHelpButton('lti_forcessl', 'force_ssl', 'lti');
if (!empty($this->_customdata->isadmin)) {
// Add setup parameters fieldset.
$mform->addElement('header', 'setupoptions', get_string('miscellaneous', 'lti'));
if (!empty($this->_customdata->isadmin)) {
//-------------------------------------------------------------------------------
// Add setup parameters fieldset
$mform->addElement('header', 'setupoptions', get_string('miscellaneous', 'lti'));
// Adding option to change id that is placed in context_id.
$idoptions = array();
$idoptions[0] = get_string('id', 'lti');
$idoptions[1] = get_string('courseid', 'lti');
// Adding option to change id that is placed in context_id
$idoptions = array();
$idoptions[0] = get_string('id', 'lti');
$idoptions[1] = get_string('courseid', 'lti');
$mform->addElement('text', 'lti_organizationid', get_string('organizationid', 'lti'));
$mform->setType('lti_organizationid', PARAM_TEXT);
$mform->addHelpButton('lti_organizationid', 'organizationid', 'lti');
$mform->addElement('text', 'lti_organizationid', get_string('organizationid', 'lti'));
$mform->setType('lti_organizationid', PARAM_TEXT);
$mform->addHelpButton('lti_organizationid', 'organizationid', 'lti');
$mform->addElement('text', 'lti_organizationurl', get_string('organizationurl', 'lti'));
$mform->setType('lti_organizationurl', PARAM_TEXT);
$mform->addHelpButton('lti_organizationurl', 'organizationurl', 'lti');
$mform->addElement('text', 'lti_organizationurl', get_string('organizationurl', 'lti'));
$mform->setType('lti_organizationurl', PARAM_TEXT);
$mform->addHelpButton('lti_organizationurl', 'organizationurl', 'lti');
}
}
/* Suppress this for now - Chuck
$mform->addElement('text', 'lti_organizationdescr', get_string('organizationdescr', 'lti'));
$mform->setType('lti_organizationdescr', PARAM_TEXT);
$mform->addHelpButton('lti_organizationdescr', 'organizationdescr', 'lti');
*/
* mform->addElement('text', 'lti_organizationdescr', get_string('organizationdescr', 'lti'))
* mform->setType('lti_organizationdescr', PARAM_TEXT)
* mform->addHelpButton('lti_organizationdescr', 'organizationdescr', 'lti')
*/
//-------------------------------------------------------------------------------
/*
// Add a hidden element to signal a tool fixing operation after a problematic backup - restore process
//$mform->addElement('hidden', 'lti_fix');
*/
$tab = optional_param('tab', '', PARAM_ALPHAEXT);
$mform->addElement('hidden', 'tab', $tab);
@ -185,8 +195,7 @@ class mod_lti_edit_types_form extends moodleform{
$mform->addElement('hidden', 'course', $courseid);
$mform->setType('course', PARAM_INT);
//-------------------------------------------------------------------------------
// Add standard buttons, common to all modules
// Add standard buttons, common to all modules.
$this->add_action_buttons();
}

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file contains submissions-specific code for the lti module

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This page lists all the instances of lti in a particular course
@ -48,9 +48,9 @@
require_once("../../config.php");
require_once($CFG->dirroot.'/mod/lti/lib.php');
$id = required_param('id', PARAM_INT); // course id
$id = required_param('id', PARAM_INT); // Course id.
$course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST);
$course = $DB->get_record('course', array('id' => $id), '*', MUST_EXIST);
require_login($course);
$PAGE->set_pagelayout('incourse');
@ -69,16 +69,16 @@ $PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
// Print the main part of the page
// Print the main part of the page.
echo $OUTPUT->heading(get_string("modulenamepluralformatted", "lti"));
// Get all the appropriate data
// Get all the appropriate data.
if (! $basicltis = get_all_instances_in_course("lti", $course)) {
notice(get_string('noltis', 'lti'), "../../course/view.php?id=$course->id");
die;
}
// Print the list of instances (your module will probably extend this)
// Print the list of instances (your module will probably extend this).
$timenow = time();
$strname = get_string("name");
$usesections = course_format_uses_sections($course->format);
@ -96,10 +96,10 @@ if ($usesections) {
foreach ($basicltis as $basiclti) {
if (!$basiclti->visible) {
//Show dimmed if the mod is hidden
// Show dimmed if the mod is hidden.
$link = "<a class=\"dimmed\" href=\"view.php?id=$basiclti->coursemodule\">$basiclti->name</a>";
} else {
//Show normal if the mod is visible
// Show normal if the mod is visible.
$link = "<a href=\"view.php?id=$basiclti->coursemodule\">$basiclti->name</a>";
}
@ -114,5 +114,5 @@ echo "<br />";
echo html_writer::table($table);
// Finish the page
// Finish the page.
echo $OUTPUT->footer();

View File

@ -59,7 +59,7 @@ if ($data = $form->get_data()) {
$fromdb = lti_get_type($typeid);
$json = json_encode($fromdb);
//Output script to update the calling window.
// Output script to update the calling window.
$script = "
<html>
<script type=\"text/javascript\">
@ -80,7 +80,7 @@ if ($data = $form->get_data()) {
$fromdb = lti_get_type($id);
$json = json_encode($fromdb);
//Output script to update the calling window.
// Output script to update the calling window.
$script = "
<html>
<script type=\"text/javascript\">
@ -107,7 +107,7 @@ if ($data = $form->get_data()) {
die;
}
//Delete action is called via ajax
// Delete action is called via ajax.
if ($action == 'delete') {
lti_delete_type($typeid);
die;

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file contains en_utf8 translation of the Basic LTI module
@ -49,6 +49,7 @@
defined('MOODLE_INTERNAL') || die;
$string['accept'] = 'Accept';
$string['accepted'] = 'Accepted';
$string['accept_grades'] = 'Accept grades from the tool';
$string['accept_grades_admin'] = 'Accept grades from the tool';
$string['accept_grades_admin_help'] = 'Specify whether the tool provider can add, update, read, and delete grades associated with instances of this tool type.
@ -72,7 +73,7 @@ $string['allowinstructorcustom'] = 'Allow teachers to add custom parameters';
$string['allowsetting'] = 'Allow tool to store 8K of settings in Moodle';
$string['always'] = 'Always';
$string['automatic'] = 'Automatic, based on Launch URL';
$string['baseurl'] = 'Base URL';
$string['baseurl'] = 'Base URL/Tool Registration Name';
$string['basiclti'] = 'LTI';
$string['basiclti_base_string'] = 'LTI OAuth Base String';
$string['basiclti_endpoint'] = 'LTI Launch Endpoint';
@ -83,8 +84,13 @@ $string['basicltifieldset'] = 'Custom example fieldset';
$string['basicltiintro'] = 'Activity Description';
$string['basicltiname'] = 'Activity Name';
$string['basicltisettings'] = 'Basic Learning Tool Interoperability Settings';
$string['cancel'] = 'Cancel';
$string['cancelled'] = 'Cancelled';
$string['cannot_delete'] = 'You may not delete this tool configuration.';
$string['cannot_edit'] = 'You may not edit this tool configuration.';
$string['capabilities'] = 'Capabilities';
$string['capabilities_help'] = 'Select those capabilities which you wish to offer to the tool provider. More than one capability can be selected.';
$string['click_to_continue'] = '<a href="{$a->link}" target="_top">Click to continue</a>';
$string['comment'] = 'Comment';
$string['configpassword'] = 'Default Remote Tool Password';
$string['configpreferheight'] = 'Default preferred height';
@ -93,6 +99,7 @@ $string['configpreferwidth'] = 'Default preferred width';
$string['configresourceurl'] = 'Default Resource URL';
$string['configtoolurl'] = 'Default Remote Tool URL';
$string['configtypes'] = 'Enable LTI Applications';
$string['configured'] = 'Configured';
$string['course_tool_types'] = 'Course tool types';
$string['courseid'] = 'Course id number';
$string['coursemisconf'] = 'Course is misconfigured';
@ -101,7 +108,7 @@ $string['curllibrarymissing'] = 'PHP Curl library must be installed to use LTI';
$string['custom'] = 'Custom parameters';
$string['custom_config'] = 'Using custom tool configuration.';
$string['custom_help'] = 'Custom parameters are settings used by the tool provider. For example, a custom parameter may be used to display
a specific resource from the provider.
a specific resource from the provider. Each parameter should be entered on a separate line using a format of "name=value"; for example, "chapter=3".
It is safe to leave this field unchanged unless directed by the tool provider.';
$string['custominstr'] = 'Custom parameters';
@ -141,6 +148,7 @@ $string['domain_mismatch'] = 'Launch URL\'s domain does not match tool configura
$string['donot'] = 'Do not send';
$string['donotaccept'] = 'Do not accept';
$string['donotallow'] = 'Do not allow';
$string['duplicateregurl'] = 'This registration URL is already in use';
$string['edittype'] = 'Edit external tool configuration';
$string['embed'] = 'Embed';
$string['embed_no_blocks'] = 'Embed, without blocks';
@ -250,6 +258,8 @@ Tool types listed on this page are separated into three categories:
Teachers may still use tools from these providers if they have a consumer key and shared secret, or if none is required.
* **Rejected** - These tools providers are flagged as ones which an administrator has no intention of making available to the entire
Moodle instance. Teachers may still use tools from these providers if they have a consumer key and shared secret, or if none is required.';
$string['manage_tools'] = 'Manage External Tool Types';
$string['manage_tool_proxies'] = 'Manage External Tool Registrations';
$string['miscellaneous'] = 'Miscellaneous';
$string['misconfiguredtools'] = 'Misconfigured tool instances were detected';
$string['missingparameterserror'] = 'The page is misconfigured: "{$a}"';
@ -267,28 +277,37 @@ External tool activities differ from URL resources in a few ways:
$string['modulename_link'] = 'mod/lti/view';
$string['modulenameplural'] = 'External Tools';
$string['modulenamepluralformatted'] = 'LTI Instances';
$string['name'] = 'Name';
$string['never'] = 'Never';
$string['new_window'] = 'New window';
$string['no_lti_configured'] = 'There are no active External Tools configured.';
$string['no_lti_pending'] = 'There are no pending External Tools.';
$string['no_lti_rejected'] = 'There are no rejected External Tools.';
$string['no_tp_accepted'] = 'There are no accepted External Tool Registrations.';
$string['no_tp_cancelled'] = 'There are no cancelled External Tool Registrations .';
$string['no_tp_configured'] = 'There are no unregistered External Tool Registrations configured.';
$string['no_tp_pending'] = 'There are no pending External Tool Registrations .';
$string['no_tp_rejected'] = 'There are no rejected External Tool Registrations .';
$string['noattempts'] = 'No attempts have been made on this tool instance';
$string['noltis'] = 'There are no lti instances';
$string['noprofileservice'] = 'Profile service not found';
$string['noservers'] = 'No servers found';
$string['notypes'] = 'There are currently no LTI tools setup in Moodle. Click the Install link above to add some.';
$string['noviewusers'] = 'No users were found with permissions to use this tool';
$string['optionalsettings'] = 'Optional settings';
$string['organization'] ='Organization details';
$string['organizationdescr'] ='Organization Description';
$string['organizationid'] ='Organization ID';
$string['organization'] = 'Organization details';
$string['organizationdescr'] = 'Organization Description';
$string['organizationid'] = 'Organization ID';
$string['organizationid_help'] = 'A unique identifier for this Moodle instance. Typically, the DNS name of the organization is used.
If this field is left blank, the host name of this Moodle site will be used as the default value.';
$string['organizationurl'] ='Organization URL';
$string['organizationurl'] = 'Organization URL';
$string['organizationurl_help'] = 'The base URL of this Moodle instance.
If this field is left blank, a default value will be used based on the site configuration.';
$string['pagesize'] = 'Submissions shown per page';
$string['parameter'] = 'Tool parameters';
$string['parameter_help'] = 'Tool parameters are settings requested to be passed by the tool provider in the accepted tool proxy.';
$string['password'] = 'Shared Secret';
$string['password_admin'] = 'Shared Secret';
$string['password_admin_help'] = 'The shared secret can be thought of as a password used to authenticate access to the tool. It should be provided
@ -318,6 +337,14 @@ $string['privacy'] = 'Privacy';
$string['quickgrade'] = 'Allow quick grading';
$string['quickgrade_help'] = 'If enabled, multiple tools can be graded on one page. Add grades and comments then click the "Save all my feedback" button to save all changes for that page.';
$string['redirect'] = 'You will be redirected in few seconds. If you are not, press the button.';
$string['register'] = 'Register';
$string['register_warning'] = 'The registration page seems to be taking a while to open. If it does not appear, check that you entered the correct URL in the configuration settings.';
$string['registertype'] = 'Configure a new External Tool Registration';
$string['registration_options'] = 'Registration Options';
$string['registrationname'] = 'Tool Provider name';
$string['registrationname_help'] = 'Enter the name of the tool provider being registered.';
$string['registrationurl'] = 'Registration URL';
$string['registrationurl_help'] = 'The registration URL should be available from the tool provider as the location to which registration requests should be sent.';
$string['reject'] = 'Reject';
$string['rejected'] = 'Rejected';
$string['resource'] = 'Resource';
@ -358,6 +385,8 @@ is set to always launch through SSL.
The Launch URL may also be set to an https address to force launching through SSL, and this field may be left blank.';
$string['send'] = 'Send';
$string['services'] = 'Services';
$string['services_help'] = 'Select those services which you wish to offer to the tool provider. More than one service can be selected.';
$string['setupoptions'] = 'Setup Options';
$string['share_email'] = 'Share launcher\'s email with the tool';
$string['share_email_admin'] = 'Share launcher\'s email with tool';
@ -396,11 +425,31 @@ $string['size'] = 'Size parameters';
$string['submission'] = 'Submission';
$string['submissions'] = 'Submissions';
$string['submissionsfor'] = 'Submissions for {$a}';
$string['subplugintype_ltiresource'] = 'LTI service resource';
$string['subplugintype_ltiresource_plural'] = 'LTI service resources';
$string['subplugintype_ltiservice'] = 'LTI service';
$string['subplugintype_ltiservice_plural'] = 'LTI services';
$string['subplugintype_ltisource'] = 'LTI source';
$string['subplugintype_ltisource_plural'] = 'LTI sources';
$string['toggle_debug_data'] = 'Toggle Debug Data';
$string['tool_config_not_found'] = 'Tool configuration not found for this URL.';
$string['tool_settings'] = 'Tool Settings';
$string['toolproxy'] = 'External Tool Registrations';
$string['toolproxy_help'] = 'External tool registrations allow Moodle site administrators to configure external tools from a tool proxy obtained from
a tool provider supporting LTI 2.0. A registration URL provided by the tool provider is all that is required to initiate the process. The capabilities
and services offered to the tool provider are selected when configuring a new registration.
Tool registrations listed on this page are separated into four categories:
* **Configured** - These tool registrations have been set up but the registration process has not yet been started.
* **Pending** - The regisitration process for these tool registrations has been started but has not completed. Open and save the settings to move it
back to the \'Configured\' category.
* **Accepted** - These tool registrations have been approved; the resources specified in the tool proxy will appear on the external tool types page
with an initial status of \'Pending\'.
* **Rejected** - These tool registrations are ones which were rejected during the registration process. Open and save the settings to move it
back to the \'Configured\' category so the registration process cna be restarted.';
$string['toolproxyregistration'] = 'External Tool Registration';
$string['toolregistration'] = 'External Tool Registration';
$string['toolsetup'] = 'External Tool Configuration';
$string['toolurl'] = 'Tool Base URL';
$string['toolurl_help'] = 'The tool base URL is used to match tool launch URLs to the correct tool configuration. Prefixing the URL with http(s) is optional.

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file contains all necessary code to view a lti activity instance
@ -50,7 +50,7 @@ require_once("../../config.php");
require_once($CFG->dirroot.'/mod/lti/lib.php');
require_once($CFG->dirroot.'/mod/lti/locallib.php');
$id = required_param('id', PARAM_INT); // Course Module ID
$id = required_param('id', PARAM_INT); // Course Module ID.
$cm = get_coursemodule_from_id('lti', $id, 0, false, MUST_EXIST);
$lti = $DB->get_record('lti', array('id' => $cm->instance), '*', MUST_EXIST);

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file contains a library of functions and constants for the lti module
@ -63,17 +63,20 @@ function lti_get_extra_capabilities() {
* @return mixed True if module supports feature, false if not, null if doesn't know
*/
function lti_supports($feature) {
switch($feature) {
case FEATURE_GROUPS: return false;
case FEATURE_GROUPINGS: return false;
case FEATURE_MOD_INTRO: return true;
case FEATURE_COMPLETION_TRACKS_VIEWS: return true;
case FEATURE_GRADE_HAS_GRADE: return true;
case FEATURE_GRADE_OUTCOMES: return true;
case FEATURE_BACKUP_MOODLE2: return true;
case FEATURE_SHOW_DESCRIPTION: return true;
switch ($feature) {
case FEATURE_GROUPS:
case FEATURE_GROUPINGS:
return false;
case FEATURE_MOD_INTRO:
case FEATURE_COMPLETION_TRACKS_VIEWS:
case FEATURE_GRADE_HAS_GRADE:
case FEATURE_GRADE_OUTCOMES:
case FEATURE_BACKUP_MOODLE2:
case FEATURE_SHOW_DESCRIPTION:
return true;
default: return null;
default:
return null;
}
}
@ -90,6 +93,10 @@ function lti_add_instance($lti, $mform) {
global $DB, $CFG;
require_once($CFG->dirroot.'/mod/lti/locallib.php');
if (!isset($lti->toolurl)) {
$lti->toolurl = '';
}
$lti->timecreated = time();
$lti->timemodified = $lti->timecreated;
$lti->servicesalt = uniqid('', true);
@ -177,9 +184,13 @@ function lti_delete_instance($id) {
$result = true;
# Delete any dependent records here #
// Delete any dependent records here.
lti_grade_item_delete($basiclti);
$ltitype = $DB->get_record('lti_types', array('id' => $basiclti->typeid));
$DB->delete_records('lti_tool_settings',
array('toolproxyid' => $ltitype->toolproxyid, 'course' => $basiclti->course, 'coursemoduleid' => $id));
return $DB->delete_records("lti", array("id" => $basiclti->id));
}
@ -313,7 +324,7 @@ function lti_user_complete($course, $user, $mod, $basiclti) {
* @TODO: implement this moodle function
**/
function lti_print_recent_activity($course, $isteacher, $timestart) {
return false; // True if anything was printed, otherwise false
return false; // True if anything was printed, otherwise false.
}
/**
@ -361,11 +372,11 @@ function lti_grades($basicltiid) {
function lti_scale_used ($basicltiid, $scaleid) {
$return = false;
//$rec = get_record("basiclti","id","$basicltiid","scale","-$scaleid");
// $rec = get_record("basiclti","id","$basicltiid","scale","-$scaleid");
//
//if (!empty($rec) && !empty($scaleid)) {
// $return = true;
//}
// if (!empty($rec) && !empty($scaleid)) {
// $return = true;
// }
return $return;
}
@ -428,11 +439,11 @@ function lti_get_lti_types() {
* @param mixed optional array/object of grade(s); 'reset' means reset grades in gradebook
* @return int 0 if ok, error code otherwise
*/
function lti_grade_item_update($basiclti, $grades=null) {
function lti_grade_item_update($basiclti, $grades = null) {
global $CFG;
require_once($CFG->libdir.'/gradelib.php');
$params = array('itemname'=>$basiclti->name, 'idnumber'=>$basiclti->cmidnumber);
$params = array('itemname' => $basiclti->name, 'idnumber' => $basiclti->cmidnumber);
if ($basiclti->grade > 0) {
$params['gradetype'] = GRADE_TYPE_VALUE;
@ -444,10 +455,10 @@ function lti_grade_item_update($basiclti, $grades=null) {
$params['scaleid'] = -$basiclti->grade;
} else {
$params['gradetype'] = GRADE_TYPE_TEXT; // allow text comments only
$params['gradetype'] = GRADE_TYPE_TEXT; // Allow text comments only.
}
if ($grades === 'reset') {
if ($grades === 'reset') {
$params['reset'] = true;
$grades = null;
}
@ -466,7 +477,7 @@ function lti_grade_item_delete($basiclti) {
global $CFG;
require_once($CFG->libdir.'/gradelib.php');
return grade_update('mod/lti', $basiclti->course, 'mod', 'lti', $basiclti->id, 0, null, array('deleted'=>1));
return grade_update('mod/lti', $basiclti->course, 'mod', 'lti', $basiclti->id, 0, null, array('deleted' => 1));
}
function lti_extend_settings_navigation($settings, $parentnode) {
@ -476,7 +487,7 @@ function lti_extend_settings_navigation($settings, $parentnode) {
$keys = $parentnode->get_children_key_list();
$node = navigation_node::create('Submissions',
new moodle_url('/mod/lti/grade.php', array('id'=>$PAGE->cm->id)),
new moodle_url('/mod/lti/grade.php', array('id' => $PAGE->cm->id)),
navigation_node::TYPE_SETTING, null, 'mod_lti_submissions');
$parentnode->add_node($node, $keys[1]);

View File

@ -1,86 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
//
// This file is part of BasicLTI4Moodle
//
// BasicLTI4Moodle is an IMS BasicLTI (Basic Learning Tools for Interoperability)
// consumer for Moodle 1.9 and Moodle 2.0. BasicLTI is a IMS Standard that allows web
// based learning tools to be easily integrated in LMS as native ones. The IMS BasicLTI
// specification is part of the IMS standard Common Cartridge 1.1 Sakai and other main LMS
// are already supporting or going to support BasicLTI. This project Implements the consumer
// for Moodle. Moodle is a Free Open source Learning Management System by Martin Dougiamas.
// BasicLTI4Moodle is a project iniciated and leaded by Ludo(Marc Alier) and Jordi Piguillem
// at the GESSI research group at UPC.
// SimpleLTI consumer for Moodle is an implementation of the early specification of LTI
// by Charles Severance (Dr Chuck) htp://dr-chuck.com , developed by Jordi Piguillem in a
// Google Summer of Code 2008 project co-mentored by Charles Severance and Marc Alier.
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
/**
* This file contains some functions and classes used by the lti
* module administration
*
* @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
* @author Marc Alier
* @author Jordi Piguillem
* @author Nikolas Galanis
* @author Chris Scribner
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
require_once($CFG->libdir.'/adminlib.php');
/**
*
* @TODO: finish doc this class and it's functions
*/
class admin_setting_ltimodule_configlink extends admin_setting {
/**
* Constructor
* @param string $name of setting
* @param string $visiblename localised
* @param string $description long localised info
*/
public function __construct($name, $visiblename, $description) {
parent::__construct($name, $visiblename, $description, '');
}
public function get_setting() {
return true;
}
public function write_setting($data) {
return "";
}
public function output_html($data, $query='') {
global $CFG;
return format_admin_setting($this, "",
'<div class="defaultsnext" >'.
'<a href="'.$CFG->wwwroot.'/mod/lti/typessettings.php">'.get_string('filterconfig', 'lti').'</a>'.
'</div>',
$this->description, true, '', null, $query);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -54,6 +54,19 @@
updateToolMatches();
self.toggleEditButtons();
if (self.getSelectedToolTypeOption().getAttribute('toolproxy')){
var allowname = Y.one('#id_instructorchoicesendname');
allowname.set('checked', !self.getSelectedToolTypeOption().getAttribute('noname'));
var allowemail = Y.one('#id_instructorchoicesendemailaddr');
allowemail.set('checked', !self.getSelectedToolTypeOption().getAttribute('noemail'));
var allowgrades = Y.one('#id_instructorchoiceacceptgrades');
allowgrades.set('checked', !self.getSelectedToolTypeOption().getAttribute('nogrades'));
self.toggleGradeSection();
}
});
this.createTypeEditorButtons();

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file defines the main lti configuration form
@ -63,21 +63,20 @@ class mod_lti_mod_form extends moodleform_mod {
$this->typeid = 0;
$mform =& $this->_form;
//-------------------------------------------------------------------------------
// Adding the "general" fieldset, where all the common settings are shown
// Adding the "general" fieldset, where all the common settings are shown.
$mform->addElement('header', 'general', get_string('general', 'form'));
// Adding the standard "name" field
$mform->addElement('text', 'name', get_string('basicltiname', 'lti'), array('size'=>'64'));
// Adding the standard "name" field.
$mform->addElement('text', 'name', get_string('basicltiname', 'lti'), array('size' => '64'));
$mform->setType('name', PARAM_TEXT);
$mform->addRule('name', null, 'required', null, 'client');
$mform->addRule('name', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
// Adding the optional "intro" and "introformat" pair of fields
// Adding the optional "intro" and "introformat" pair of fields.
$this->add_intro_editor(false, get_string('basicltiintro', 'lti'));
$mform->setAdvanced('introeditor');
// Display the label to the right of the checkbox so it looks better & matches rest of the form
// Display the label to the right of the checkbox so it looks better & matches rest of the form.
$coursedesc = $mform->getElement('showdescription');
if(!empty($coursedesc)){
if (!empty($coursedesc)) {
$coursedesc->setText(' ' . $coursedesc->getLabel());
$coursedesc->setLabel('&nbsp');
}
@ -93,12 +92,27 @@ class mod_lti_mod_form extends moodleform_mod {
$mform->setAdvanced('showdescriptionlaunch');
$mform->addHelpButton('showdescriptionlaunch', 'display_description', 'lti');
// Tool settings
// Tool settings.
$tooltypes = $mform->addElement('select', 'typeid', get_string('external_tool_type', 'lti'), array());
$mform->addHelpButton('typeid', 'external_tool_type', 'lti');
$toolproxy = array();
foreach (lti_get_types_for_add_instance() as $id => $type) {
if ($type->course == $COURSE->id) {
if (!empty($type->toolproxyid)) {
$toolproxy[] = $type->id;
$attributes = array( 'globalTool' => 1, 'toolproxy' => 1);
$enabledcapabilities = explode("\n", $type->enabledcapability);
if (!in_array('Result.autocreate', $enabledcapabilities)) {
$attributes['nogrades'] = 1;
}
if (!in_array('Person.name.full', $enabledcapabilities) && !in_array('Person.name.family', $enabledcapabilities) &&
!in_array('Person.name.given', $enabledcapabilities)) {
$attributes['noname'] = 1;
}
if (!in_array('Person.email.primary', $enabledcapabilities)) {
$attributes['noemail'] = 1;
}
} else if ($type->course == $COURSE->id) {
$attributes = array( 'editable' => 1, 'courseTool' => 1, 'domain' => $type->tooldomain );
} else if ($id != 0) {
$attributes = array( 'globalTool' => 1, 'domain' => $type->tooldomain);
@ -109,19 +123,21 @@ class mod_lti_mod_form extends moodleform_mod {
$tooltypes->addOption($type->name, $id, $attributes);
}
$mform->addElement('text', 'toolurl', get_string('launch_url', 'lti'), array('size'=>'64'));
$mform->addElement('text', 'toolurl', get_string('launch_url', 'lti'), array('size' => '64'));
$mform->setType('toolurl', PARAM_TEXT);
$mform->addHelpButton('toolurl', 'launch_url', 'lti');
$mform->disabledIf('toolurl', 'typeid', 'neq', '0');
$mform->addElement('text', 'securetoolurl', get_string('secure_launch_url', 'lti'), array('size'=>'64'));
$mform->addElement('text', 'securetoolurl', get_string('secure_launch_url', 'lti'), array('size' => '64'));
$mform->setType('securetoolurl', PARAM_TEXT);
$mform->setAdvanced('securetoolurl');
$mform->addHelpButton('securetoolurl', 'secure_launch_url', 'lti');
$mform->disabledIf('securetoolurl', 'typeid', 'neq', '0');
$mform->addElement('hidden', 'urlmatchedtypeid', '', array( 'id' => 'id_urlmatchedtypeid' ));
$mform->setType('urlmatchedtypeid', PARAM_INT);
$launchoptions=array();
$launchoptions = array();
$launchoptions[LTI_LAUNCH_CONTAINER_DEFAULT] = get_string('default', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_EMBED] = get_string('embed', 'lti');
$launchoptions[LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS] = get_string('embed_no_blocks', 'lti');
@ -136,74 +152,57 @@ class mod_lti_mod_form extends moodleform_mod {
$mform->setType('resourcekey', PARAM_TEXT);
$mform->setAdvanced('resourcekey');
$mform->addHelpButton('resourcekey', 'resourcekey', 'lti');
$mform->disabledIf('resourcekey', 'typeid', 'neq', '0');
$mform->addElement('passwordunmask', 'password', get_string('password', 'lti'));
$mform->setType('password', PARAM_TEXT);
$mform->setAdvanced('password');
$mform->addHelpButton('password', 'password', 'lti');
$mform->disabledIf('password', 'typeid', 'neq', '0');
$mform->addElement('textarea', 'instructorcustomparameters', get_string('custom', 'lti'), array('rows'=>4, 'cols'=>60));
$mform->addElement('textarea', 'instructorcustomparameters', get_string('custom', 'lti'), array('rows' => 4, 'cols' => 60));
$mform->setType('instructorcustomparameters', PARAM_TEXT);
$mform->setAdvanced('instructorcustomparameters');
$mform->addHelpButton('instructorcustomparameters', 'custom', 'lti');
$mform->addElement('text', 'icon', get_string('icon_url', 'lti'), array('size'=>'64'));
$mform->addElement('text', 'icon', get_string('icon_url', 'lti'), array('size' => '64'));
$mform->setType('icon', PARAM_TEXT);
$mform->setAdvanced('icon');
$mform->addHelpButton('icon', 'icon_url', 'lti');
$mform->disabledIf('icon', 'typeid', 'neq', '0');
$mform->addElement('text', 'secureicon', get_string('secure_icon_url', 'lti'), array('size'=>'64'));
$mform->addElement('text', 'secureicon', get_string('secure_icon_url', 'lti'), array('size' => '64'));
$mform->setType('secureicon', PARAM_TEXT);
$mform->setAdvanced('secureicon');
$mform->addHelpButton('secureicon', 'secure_icon_url', 'lti');
$mform->disabledIf('secureicon', 'typeid', 'neq', '0');
//-------------------------------------------------------------------------------
// Add privacy preferences fieldset where users choose whether to send their data
// Add privacy preferences fieldset where users choose whether to send their data.
$mform->addElement('header', 'privacy', get_string('privacy', 'lti'));
$mform->addElement('advcheckbox', 'instructorchoicesendname', '&nbsp;', ' ' . get_string('share_name', 'lti'));
$mform->setDefault('instructorchoicesendname', '1');
$mform->addHelpButton('instructorchoicesendname', 'share_name', 'lti');
$mform->disabledIf('instructorchoicesendname', 'typeid', 'in', $toolproxy);
$mform->addElement('advcheckbox', 'instructorchoicesendemailaddr', '&nbsp;', ' ' . get_string('share_email', 'lti'));
$mform->setDefault('instructorchoicesendemailaddr', '1');
$mform->addHelpButton('instructorchoicesendemailaddr', 'share_email', 'lti');
$mform->disabledIf('instructorchoicesendemailaddr', 'typeid', 'in', $toolproxy);
$mform->addElement('advcheckbox', 'instructorchoiceacceptgrades', '&nbsp;', ' ' . get_string('accept_grades', 'lti'));
$mform->setDefault('instructorchoiceacceptgrades', '1');
$mform->addHelpButton('instructorchoiceacceptgrades', 'accept_grades', 'lti');
//$mform->addElement('checkbox', 'instructorchoiceallowroster', '&nbsp;', ' ' . get_string('share_roster', 'lti'));
//$mform->setDefault('instructorchoiceallowroster', '1');
//$mform->addHelpButton('instructorchoiceallowroster', 'share_roster', 'lti');
//-------------------------------------------------------------------------------
/**
$debugoptions=array();
$debugoptions[0] = get_string('debuglaunchoff', 'lti');
$debugoptions[1] = get_string('debuglaunchon', 'lti');
$mform->addElement('select', 'debuglaunch', get_string('debuglaunch', 'lti'), $debugoptions);
if (isset($this->typeconfig['debuglaunch'])) {
if ($this->typeconfig['debuglaunch'] == 0) {
$mform->setDefault('debuglaunch', '0');
} else if ($this->typeconfig['debuglaunch'] == 1) {
$mform->setDefault('debuglaunch', '1');
}
}
*/
$mform->disabledIf('instructorchoiceacceptgrades', 'typeid', 'in', $toolproxy);
// Add standard course module grading elements.
$this->standard_grading_coursemodule_elements();
//-------------------------------------------------------------------------------
// add standard elements, common to all modules
// Add standard elements, common to all modules.
$this->standard_coursemodule_elements();
$mform->setAdvanced('cmidnumber');
//-------------------------------------------------------------------------------
// add standard buttons, common to all modules
// Add standard buttons, common to all modules.
$this->add_action_buttons();
$editurl = new moodle_url('/mod/lti/instructor_edit_tool_type.php',
@ -222,10 +221,10 @@ class mod_lti_mod_form extends moodleform_mod {
);
$module = array(
'name' => 'mod_lti_edit',
'fullpath' => '/mod/lti/mod_form.js',
'requires' => array('base', 'io', 'querystring-stringify-simple', 'node', 'event', 'json-parse'),
'strings' => array(
'name' => 'mod_lti_edit',
'fullpath' => '/mod/lti/mod_form.js',
'requires' => array('base', 'io', 'querystring-stringify-simple', 'node', 'event', 'json-parse'),
'strings' => array(
array('addtype', 'lti'),
array('edittype', 'lti'),
array('deletetype', 'lti'),
@ -245,24 +244,5 @@ class mod_lti_mod_form extends moodleform_mod {
$PAGE->requires->js_init_call('M.mod_lti.editor.init', array(json_encode($jsinfo)), true, $module);
}
/**
* Make fields editable or non-editable depending on the administrator choices
* @see moodleform_mod::definition_after_data()
*/
public function definition_after_data() {
parent::definition_after_data();
//$mform =& $this->_form;
}
/**
* Function overwritten to change default values using
* global configuration
*
* @param array $default_values passed by reference
*/
public function data_preprocessing(&$default_values) {
}
}

129
mod/lti/register.php Normal file
View File

@ -0,0 +1,129 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains all necessary code to launch a Tool Proxy registration
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot.'/mod/lti/locallib.php');
$id = required_param('id', PARAM_INT);
$tab = optional_param('tab', '', PARAM_ALPHAEXT);
require_login(0, false);
$redirect = new moodle_url('/mod/lti/toolproxies.php', array('tab' => $tab));
$redirect = $redirect->out();
require_sesskey();
$toolproxies = $DB->get_records('lti_tool_proxies');
$duplicate = false;
foreach ($toolproxies as $key => $toolproxy) {
if (($toolproxy->state == LTI_TOOL_PROXY_STATE_PENDING) || ($toolproxy->state == LTI_TOOL_PROXY_STATE_ACCEPTED)) {
if ($toolproxy->regurl == $toolproxies[$id]->regurl) {
$duplicate = true;
break;
}
}
}
$redirect = new moodle_url('/mod/lti/toolproxies.php');
if ($duplicate) {
redirect($redirect, get_string('duplicateregurl', 'lti'));
}
$profileservice = lti_get_service_by_name('profile');
if (empty($profileservice)) {
redirect($redirect, get_string('noprofileservice', 'lti'));
}
$url = new moodle_url('/mod/lti/register.php', array('id' => $id));
$PAGE->set_url($url);
admin_externalpage_setup('ltitoolproxies');
$PAGE->set_heading(get_string('toolproxyregistration', 'lti'));
$PAGE->set_title("{$SITE->shortname}: " . get_string('toolproxyregistration', 'lti'));
// Print the page header.
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('toolproxyregistration', 'lti'));
echo $OUTPUT->box_start('generalbox');
// Request the registration request content with an object tag.
$registration = new moodle_url('/mod/lti/registration.php',
array('id' => $id, 'sesskey' => sesskey()));
echo "<p id=\"id_warning\" style=\"display: none; color: red; font-weight: bold; margin-top: 1em; padding-top: 1em;\">\n";
echo get_string('register_warning', 'lti');
echo "\n</p>\n";
echo '<iframe id="contentframe" height="600px" width="100%" src="' . $registration->out() . '" onload="doOnload()"></iframe>';
// Output script to make the object tag be as large as possible.
$resize = '
<script type="text/javascript">
//<![CDATA[
function doReveal() {
var el = document.getElementById(\'id_warning\');
el.style.display = \'block\';
}
function doOnload() {
window.clearTimeout(mod_lti_timer);
}
var mod_lti_timer = window.setTimeout(doReveal, 20000);
YUI().use("node", "event", function(Y) {
//Take scrollbars off the outer document to prevent double scroll bar effect
var doc = Y.one("body");
doc.setStyle("overflow", "hidden");
var frame = Y.one("#contentframe");
var padding = 15; //The bottom of the iframe wasn\'t visible on some themes. Probably because of border widths, etc.
var lastHeight;
var resize = function(e) {
var viewportHeight = doc.get("winHeight");
if(lastHeight !== Math.min(doc.get("docHeight"), viewportHeight)){
frame.setStyle("height", viewportHeight - frame.getY() - padding + "px");
lastHeight = Math.min(doc.get("docHeight"), doc.get("winHeight"));
}
};
resize();
Y.on("windowresize", resize);
});
//]]
</script>
';
echo $resize;
// Finish the page.
echo $OUTPUT->box_end();
echo $OUTPUT->footer();

127
mod/lti/register_form.php Normal file
View File

@ -0,0 +1,127 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file defines the main tool registration configuration form
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
require_once($CFG->libdir.'/formslib.php');
require_once($CFG->dirroot.'/mod/lti/locallib.php');
/**
* The mod_lti_register_types_form class.
*
* @package mod_lti
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_lti_register_types_form extends moodleform {
/**
* Set up the form definition.
*/
public function definition() {
global $CFG;
$mform =& $this->_form;
$mform->addElement('header', 'setup', get_string('registration_options', 'lti'));
// Tool Provider name.
$mform->addElement('text', 'lti_registrationname', get_string('registrationname', 'lti'));
$mform->setType('lti_registrationname', PARAM_TEXT);
$mform->addHelpButton('lti_registrationname', 'registrationname', 'lti');
$mform->addRule('lti_registrationname', null, 'required', null, 'client');
// Registration URL.
$mform->addElement('text', 'lti_registrationurl', get_string('registrationurl', 'lti'), array('size' => '64'));
$mform->setType('lti_registrationurl', PARAM_TEXT);
$mform->addHelpButton('lti_registrationurl', 'registrationurl', 'lti');
// LTI Capabilities.
$options = array_keys(lti_get_capabilities());
natcasesort($options);
$attributes = array( 'multiple' => 1, 'size' => min(count($options), 10) );
$mform->addElement('select', 'lti_capabilities', get_string('capabilities', 'lti'),
array_combine($options, $options), $attributes);
$mform->setType('lti_capabilities', PARAM_TEXT);
$mform->addHelpButton('lti_capabilities', 'capabilities', 'lti');
// LTI Services.
$services = lti_get_services();
$options = array();
foreach ($services as $service) {
$options[$service->get_id()] = $service->get_name();
}
$attributes = array( 'multiple' => 1, 'size' => min(count($options), 10) );
$mform->addElement('select', 'lti_services', get_string('services', 'lti'), $options, $attributes);
$mform->setType('lti_services', PARAM_TEXT);
$mform->addHelpButton('lti_services', 'services', 'lti');
$mform->addElement('hidden', 'toolproxyid');
$mform->setType('toolproxyid', PARAM_INT);
$tab = optional_param('tab', '', PARAM_ALPHAEXT);
$mform->addElement('hidden', 'tab', $tab);
$mform->setType('tab', PARAM_ALPHAEXT);
$courseid = optional_param('course', 1, PARAM_INT);
$mform->addElement('hidden', 'course', $courseid);
$mform->setType('course', PARAM_INT);
// Add standard buttons, common to all modules.
$this->add_action_buttons();
}
/**
* Set up rules for disabling fields.
*/
public function disable_fields() {
$mform =& $this->_form;
$mform->disabledIf('lti_registrationurl', null);
$mform->disabledIf('lti_capabilities', null);
$mform->disabledIf('lti_services', null);
}
/**
* Set up rules for required fields.
*/
public function required_fields() {
$mform =& $this->_form;
$mform->addRule('lti_registrationurl', null, 'required', null, 'client');
}
}

View File

@ -0,0 +1,94 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the script used to register a new external tool.
*
* It is used to create a new form used to configure the capabilities
* and services to be offered to the tool provider.
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot.'/mod/lti/register_form.php');
require_once($CFG->dirroot.'/mod/lti/locallib.php');
$action = optional_param('action', null, PARAM_ALPHANUMEXT);
$id = optional_param('id', null, PARAM_INT);
$tab = optional_param('tab', '', PARAM_ALPHAEXT);
// No guest autologin.
require_login(0, false);
$isupdate = !empty($id);
$pageurl = new moodle_url('/mod/lti/registersettings.php');
if ($isupdate) {
$pageurl->param('id', $id);
}
$PAGE->set_url($pageurl);
admin_externalpage_setup('ltitoolproxies');
$redirect = new moodle_url('/mod/lti/toolproxies.php', array('tab' => $tab));
$redirect = $redirect->out();
require_sesskey();
if ($action == 'delete') {
lti_delete_tool_proxy($id);
redirect($redirect);
}
$data = array();
if ($isupdate) {
$data['isupdate'] = true;
}
$form = new mod_lti_register_types_form($pageurl, (object)$data);
if ($form->is_cancelled()) {
redirect($redirect);
} else if ($data = $form->get_data()) {
$id = lti_add_tool_proxy($data);
redirect($redirect);
} else {
$PAGE->set_title("{$SITE->shortname}: " . get_string('toolregistration', 'lti'));
$PAGE->navbar->add(get_string('lti_administration', 'lti'), $redirect);
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('toolregistration', 'lti'));
echo $OUTPUT->box_start('generalbox');
if ($action == 'update') {
$toolproxy = lti_get_tool_proxy_config($id);
$form->set_data($toolproxy);
if ($toolproxy->state == LTI_TOOL_PROXY_STATE_ACCEPTED) {
$form->disable_fields();
} else {
$form->required_fields();
}
} else {
$form->required_fields();
}
$form->display();
echo $OUTPUT->box_end();
echo $OUTPUT->footer();
}

39
mod/lti/registration.php Normal file
View File

@ -0,0 +1,39 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains all necessary code to initiate a tool registration process
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once("../../config.php");
require_once($CFG->dirroot.'/mod/lti/lib.php');
require_once($CFG->dirroot.'/mod/lti/locallib.php');
$id = required_param('id', PARAM_INT); // Tool Proxy ID.
$toolproxy = $DB->get_record('lti_tool_proxies', array('id' => $id), '*', MUST_EXIST);
require_login(0, false);
$systemcontext = context_system::instance();
require_capability('moodle/site:config', $systemcontext);
lti_register($toolproxy);

View File

@ -0,0 +1,115 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Handle the return from the Tool Provider after registering a tool proxy.
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../../config.php');
require_once($CFG->dirroot.'/mod/lti/locallib.php');
$top = optional_param('top', 0, PARAM_INT);
$msg = optional_param('lti_msg', '', PARAM_RAW);
$err = optional_param('lti_errormsg', '', PARAM_RAW);
$id = optional_param('id', 0, PARAM_INT);
// No guest autologin.
require_login(0, false);
$systemcontext = context_system::instance();
require_capability('moodle/site:config', $systemcontext);
if (empty($top)) {
$params = array();
$params['top'] = '1';
if (!empty($msg)) {
$params['lti_msg'] = $msg;
}
if (!empty($err)) {
$params['lti_errormsg'] = $err;
}
if (!empty($id)) {
$params['id'] = $id;
}
$redirect = new moodle_url('/mod/lti/registrationreturn.php', $params);
$redirect = $redirect->out(false);
$clickhere = get_string('click_to_continue', 'lti', (object)array('link' => $redirect));
$html = <<< EOD
<html>
<head>
<script type="text/javascript">
//<![CDATA[
top.location.href = '{$redirect}';
//]]
</script>
</head>
<body>
<noscript>
{$clickhere}
</noscript>
</body>
</html>
EOD;
echo $html;
} else if (!empty($msg) && !empty($err)) {
$params = array();
$params['top'] = '1';
if (!empty($err)) {
$params['lti_errormsg'] = $err;
}
if (!empty($id)) {
$params['id'] = $id;
}
$redirect = new moodle_url('/mod/lti/registrationreturn.php', $params);
$redirect = $redirect->out(false);
redirect($redirect, $err);
} else {
$redirect = new moodle_url('/mod/lti/toolproxies.php');
if (!empty($id)) {
$toolproxy = $DB->get_record('lti_tool_proxies', array('id' => $id));
switch($toolproxy->state) {
case LTI_TOOL_PROXY_STATE_ACCEPTED:
$redirect->param('tab', 'tp_accepted');
break;
case LTI_TOOL_PROXY_STATE_REJECTED:
$redirect->param('tab', 'tp_rejected');
break;
case LTI_TOOL_PROXY_STATE_PENDING:
// Change the status to configured.
$toolproxy->state = LTI_TOOL_PROXY_STATE_CONFIGURED;
lti_update_tool_proxy($toolproxy);
}
}
$redirect = $redirect->out();
if (empty($msg)) {
$msg = $err;
}
redirect($redirect, $msg);
}

View File

@ -52,9 +52,9 @@ $PAGE->set_pagelayout('incourse');
echo $OUTPUT->header();
echo $OUTPUT->heading(format_string($lti->name, true, array('context' => $context)));
//Add a tool type if one does not exist already
// Add a tool type if one does not exist already.
if (!lti_get_tool_by_url_match($lti->toolurl, $lti->course, LTI_TOOL_STATE_ANY)) {
//There are no tools (active, pending, or rejected) for the launch URL. Create a new pending tool
// There are no tools (active, pending, or rejected) for the launch URL. Create a new pending tool.
$tooltype = new stdClass();
$toolconfig = new stdClass();

View File

@ -56,7 +56,7 @@ if (!empty($errormsg) || !empty($msg)) {
$PAGE->set_title($pagetitle);
$PAGE->set_heading($course->fullname);
//Avoid frame-in-frame action
// Avoid frame-in-frame action.
if ($launchcontainer == LTI_LAUNCH_CONTAINER_EMBED || $launchcontainer == LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS) {
$PAGE->set_pagelayout('embedded');
} else {
@ -80,7 +80,8 @@ if (!empty($errormsg)) {
echo '<br /><br />';
$links = new stdClass();
$coursetooleditor = new moodle_url('/mod/lti/instructor_edit_tool_type.php', array('course' => $courseid, 'action' => 'add'));
$coursetooleditor = new moodle_url('/mod/lti/instructor_edit_tool_type.php',
array('course' => $courseid, 'action' => 'add'));
$links->course_tool_editor = $coursetooleditor->out(false);
echo get_string('lti_launch_error_unsigned_help', 'lti', $links);
@ -103,9 +104,9 @@ if (!empty($errormsg)) {
$courseurl = new moodle_url('/course/view.php', array('id' => $courseid));
$url = $courseurl->out();
//Avoid frame-in-frame action
// Avoid frame-in-frame action.
if ($launchcontainer == LTI_LAUNCH_CONTAINER_EMBED || $launchcontainer == LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS) {
//Output a page containing some script to break out of frames and redirect them
// Output a page containing some script to break out of frames and redirect them.
echo '<html><body>';
@ -132,7 +133,7 @@ if (!empty($errormsg)) {
echo '</body></html>';
} else {
//If no error, take them back to the course
// If no error, take them back to the course.
redirect($url);
}
}

View File

@ -24,12 +24,13 @@
*/
define('NO_DEBUG_DISPLAY', true);
define('NO_MOODLE_COOKIES', true);
require_once(dirname(__FILE__) . "/../../config.php");
require_once($CFG->dirroot.'/mod/lti/locallib.php');
require_once($CFG->dirroot.'/mod/lti/servicelib.php');
// TODO: Switch to core oauthlib once implemented - MDL-30149
// TODO: Switch to core oauthlib once implemented - MDL-30149.
use moodle\mod\lti as lti;
$rawbody = file_get_contents("php://input");
@ -40,7 +41,7 @@ if (lti_should_log_request($rawbody)) {
foreach (lti\OAuthUtil::get_headers() as $name => $value) {
if ($name === 'Authorization') {
// TODO: Switch to core oauthlib once implemented - MDL-30149
// TODO: Switch to core oauthlib once implemented - MDL-30149.
$oauthparams = lti\OAuthUtil::split_header($value);
$consumerkey = $oauthparams['oauth_consumer_key'];
@ -118,7 +119,7 @@ switch ($messagetype) {
throw new Exception('Tool does not accept grades');
}
//Getting the grade requires the context is set
// Getting the grade requires the context is set.
$context = context_course::instance($ltiinstance->course);
$PAGE->set_context($context);
@ -127,7 +128,7 @@ switch ($messagetype) {
$grade = lti_read_grade($ltiinstance, $parsed->userid);
$responsexml = lti_get_response_xml(
'success', // Empty grade is also 'success'
'success', // Empty grade is also 'success'.
'Result read',
$parsed->messageid,
'readResultResponse'
@ -168,9 +169,9 @@ switch ($messagetype) {
break;
default:
//Fire an event if we get a web service request which we don't support directly.
//This will allow others to extend the LTI services, which I expect to be a common
//use case, at least until the spec matures.
// Fire an event if we get a web service request which we don't support directly.
// This will allow others to extend the LTI services, which I expect to be a common
// use case, at least until the spec matures.
$data = new stdClass();
$data->body = $rawbody;
$data->xml = $xml;
@ -189,20 +190,20 @@ switch ($messagetype) {
break;
}
//If an event handler handles the web service, it should set this global to true
//So this code knows whether to send an "operation not supported" or not.
global $lti_web_service_handled;
$lti_web_service_handled = false;
// If an event handler handles the web service, it should set this global to true
// So this code knows whether to send an "operation not supported" or not.
global $ltiwebservicehandled;
$ltiwebservicehandled = false;
try {
$event = \mod_lti\event\unknown_service_api_called::create($eventdata);
$event->set_message_data($data);
$event->trigger();
} catch (Exception $e) {
$lti_web_service_handled = false;
$ltiwebservicehandled = false;
}
if (!$lti_web_service_handled) {
if (!$ltiwebservicehandled) {
$responsexml = lti_get_response_xml(
'unsupported',
'unsupported',
@ -215,10 +216,3 @@ switch ($messagetype) {
break;
}
//echo print_r(apache_request_headers(), true);
//echo '<br />';
//echo file_get_contents("php://input");

View File

@ -0,0 +1,228 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains a class definition for the Tool Consumer Profile resource
*
* @package ltiservice_profile
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace ltiservice_profile\local\resource;
use \mod_lti\local\ltiservice\service_base;
defined('MOODLE_INTERNAL') || die();
/**
* A resource implementing the Tool Consumer Profile.
*
* @package ltiservice_profile
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class profile extends \mod_lti\local\ltiservice\resource_base {
/**
* Class constructor.
*
* @param ltiservice_profile\local\resource\profile $service Service instance
*/
public function __construct($service) {
parent::__construct($service);
$this->id = 'ToolConsumerProfile';
$this->template = '/profile/{tool_proxy_id}';
$this->variables[] = 'ToolConsumerProfile.url';
$this->formats[] = 'application/vnd.ims.lti.v2.toolconsumerprofile+json';
$this->methods[] = 'GET';
}
/**
* Get the path for this resource.
*
* @return string
*/
public function get_path() {
$path = $this->template;
$toolproxy = $this->get_service()->get_tool_proxy();
if (!empty($toolproxy)) {
$path = str_replace('{tool_proxy_id}', $toolproxy->guid, $path);
}
return $path;
}
/**
* Execute the request for this resource.
*
* @param mod_lti\local\ltiservice\response $response Response object for this request.
*/
public function execute($response) {
global $CFG;
$version = service_base::LTI_VERSION2P0;
$params = $this->parse_template();
$ok = $this->get_service()->check_tool_proxy($params['tool_proxy_id']);
if (!$ok) {
$response->set_code(404);
} else if (optional_param('lti_version', '', PARAM_ALPHANUMEXT) != $version) {
$response->set_code(400);
} else {
$toolproxy = $this->get_service()->get_tool_proxy();
$response->set_content_type($this->formats[0]);
$servicepath = $this->get_service()->get_service_path();
$id = $servicepath . $this->get_path();
$now = date('Y-m-d\TH:iO');
$capabilityofferedarr = explode("\n", $toolproxy->capabilityoffered);
$serviceofferedarr = explode("\n", $toolproxy->serviceoffered);
$serviceoffered = '';
$sep = '';
$services = \core_component::get_plugin_list('ltiservice');
foreach ($services as $name => $location) {
if (in_array($name, $serviceofferedarr)) {
$classname = "\\ltiservice_{$name}\\local\\service\\{$name}";
$service = new $classname();
$service->set_tool_proxy($toolproxy);
$resources = $service->get_resources();
foreach ($resources as $resource) {
$formats = implode("\", \"", $resource->get_formats());
$methods = implode("\", \"", $resource->get_methods());
$capabilityofferedarr = array_merge($capabilityofferedarr, $resource->get_variables());
$path = $servicepath . preg_replace('/\{?.*\}$/', '', $resource->get_path());
$serviceoffered .= <<< EOD
{$sep}
{
"@type":"{$resource->get_type()}",
"@id":"tcp:{$resource->get_id()}",
"endpoint":"{$path}",
"format":["{$formats}"],
"action":["{$methods}"]
}
EOD;
$sep = ',';
}
}
}
$capabilityoffered = implode("\",\n \"", $capabilityofferedarr);
if (strlen($capabilityoffered) > 0) {
$capabilityoffered = "\n \"{$capabilityoffered}\"";
}
$urlparts = parse_url($CFG->wwwroot);
$orgid = $urlparts['host'];
$name = 'Moodle';
$code = 'moodle';
$vendorname = 'Moodle.org';
$vendorcode = 'mdl';
$prodversion = strval($CFG->version);
if (!empty($CFG->mod_lti_institution_name)) {
$consumername = $CFG->mod_lti_institution_name;
$consumerdesc = '';
} else {
$consumername = get_site()->fullname;
$consumerdesc = strip_tags(get_site()->summary);
}
$profile = <<< EOD
{
"@context":[
"http://purl.imsglobal.org/ctx/lti/v2/ToolConsumerProfile",
{
"tcp":"{$id}#"
}
],
"@type":"ToolConsumerProfile",
"@id":"{$id}",
"lti_version":"{$version}",
"guid":"{$toolproxy->guid}",
"product_instance":{
"guid":"{$orgid}",
"product_info":{
"product_name":{
"default_value":"{$name}",
"key":"product.name"
},
"product_version":"{$prodversion}",
"product_family":{
"code":"{$code}",
"vendor":{
"code":"{$vendorcode}",
"vendor_name":{
"default_value":"{$vendorname}",
"key":"product.vendor.name"
},
"timestamp":"{$now}"
}
}
},
"service_owner":{
"@id":"ServiceOwner",
"service_owner_name":{
"default_value":"{$consumername}",
"key":"service_owner.name"
},
"description":{
"default_value":"{$consumerdesc}",
"key":"service_owner.description"
}
}
},
"capability_offered":[{$capabilityoffered}
],
"service_offered":[{$serviceoffered}
]
}
EOD;
$response->set_body($profile);
}
}
/**
* Get the resource fully qualified endpoint.
*
* @return string
*/
public function get_endpoint() {
return parent::get_endpoint() . '?lti_version=' . service_base::LTI_VERSION2P0;
}
/**
* Parse a value for custom parameter substitution variables.
*
* @param string $value String to be parsed
*
* @return string
*/
public function parse_value($value) {
$value = str_replace('$ToolConsumerProfile.url', $this->get_endpoint(), $value);
return $value;
}
}

View File

@ -0,0 +1,69 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains a class definition for the Tool Consumer Profile service
*
* @package ltiservice_profile
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace ltiservice_profile\local\service;
defined('MOODLE_INTERNAL') || die();
/**
* A service implementing the Tool Consumer Profile.
*
* @package ltiservice_profile
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class profile extends \mod_lti\local\ltiservice\service_base {
/**
* Class constructor.
*/
public function __construct() {
parent::__construct();
$this->id = 'profile';
$this->name = 'Tool Consumer Profile';
$this->unsigned = true;
}
/**
* Get the resources for this service.
*
* @return array
*/
public function get_resources() {
if (empty($this->resources)) {
$this->resources = array();
$this->resources[] = new \ltiservice_profile\local\resource\profile($this);
}
return $this->resources;
}
}

View File

@ -0,0 +1,26 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for component 'ltiservice_profile', language 'en'
*
* @package ltiservice_profile
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['pluginname'] = 'Tool Consumer Profile LTI Service';

View File

@ -0,0 +1,32 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Version information for the ltiservice_profile service.
*
* @package ltiservice_profile
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2014092100;
$plugin->requires = 2014050800;
$plugin->component = 'ltiservice_profile';

View File

@ -0,0 +1,28 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains all necessary code to initiate a tool registration process
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
LTI Service plugins directory
==============================
This directory contains LTI service plugins which are discoverable from the Tool
Consumer Profile.

View File

@ -0,0 +1,274 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains a class definition for the Tool Proxy resource
*
* @package ltiservice_toolproxy
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace ltiservice_toolproxy\local\resource;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/mod/lti/OAuth.php');
require_once($CFG->dirroot . '/mod/lti/TrivialStore.php');
// TODO: Switch to core oauthlib once implemented - MDL-30149.
use moodle\mod\lti as lti;
/**
* A resource implementing the Tool Proxy.
*
* @package ltiservice_toolproxy
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class toolproxy extends \mod_lti\local\ltiservice\resource_base {
/**
* Class constructor.
*
* @param ltiservice_toolproxy\local\resource\toolproxy $service Service instance
*/
public function __construct($service) {
parent::__construct($service);
$this->id = 'ToolProxy.collection';
$this->template = '/toolproxy';
$this->formats[] = 'application/vnd.ims.lti.v2.toolproxy+json';
$this->methods[] = 'POST';
}
/**
* Execute the request for this resource.
*
* @param mod_lti\local\ltiservice\response $response Response object for this request.
*/
public function execute($response) {
$ok = $this->check_tool_proxy(null, $response->get_request_data());
if ($ok) {
$toolproxy = $this->get_service()->get_tool_proxy();
} else {
$toolproxy = null;
$response->set_code(401);
}
$tools = array();
// Ensure all required elements are present in the Tool Proxy.
if ($ok) {
$toolproxyjson = json_decode($response->get_request_data());
$ok = !empty($toolproxyjson);
if (!$ok) {
debugging('Tool proxy is not properly formed JSON');
} else {
$ok = isset($toolproxyjson->tool_profile->product_instance->product_info->product_family->vendor->code);
$ok = $ok && isset($toolproxyjson->security_contract->shared_secret);
$ok = $ok && isset($toolproxyjson->tool_profile->resource_handler);
if (!$ok) {
debugging('One or more missing elements from tool proxy: vendor code, shared secret or resource handlers');
}
}
}
// Check all capabilities requested were offered.
if ($ok) {
$offeredcapabilities = explode("\n", $toolproxy->capabilityoffered);
$resources = $toolproxyjson->tool_profile->resource_handler;
$errors = array();
foreach ($resources as $resource) {
if (isset($resource->message)) {
foreach ($resource->message as $message) {
if (!in_array($message->message_type, $offeredcapabilities)) {
$errors[] = $message->message_type;
} else if (isset($resource->parameter)) {
foreach ($message->parameter as $parameter) {
if (isset($parameter->variable) && !in_array($parameter->variable, $offeredcapabilities)) {
$errors[] = $parameter->variable;
}
}
}
}
}
}
if (count($errors) > 0) {
$ok = false;
debugging('Tool proxy contains capabilities which were not offered: ' . implode(', ', $errors));
}
}
// Check all services requested were offered (only tool services currently supported).
if ($ok && isset($toolproxyjson->security_contract->tool_service)) {
$contexts = lti_get_contexts($toolproxyjson);
$profileservice = lti_get_service_by_name('profile');
$profileservice->set_tool_proxy($toolproxy);
$context = $profileservice->get_service_path() . $profileservice->get_resources()[0]->get_path() . '#';
$offeredservices = explode("\n", $toolproxy->serviceoffered);
$services = lti_get_services();
$tpservices = $toolproxyjson->security_contract->tool_service;
$errors = array();
foreach ($tpservices as $service) {
$fqid = lti_get_fqid($contexts, $service->service);
if (substr($fqid, 0, strlen($context)) !== $context) {
$errors[] = $service->service;
} else {
$id = explode('#', $fqid, 2);
$aservice = lti_get_service_by_resource_id($services, $id[1]);
$classname = explode('\\', get_class($aservice));
if (empty($aservice) || !in_array($classname[count($classname) - 1], $offeredservices)) {
$errors[] = $service->service;
}
}
}
if (count($errors) > 0) {
$ok = false;
debugging('Tool proxy contains services which were not offered: ' . implode(', ', $errors));
}
}
// Extract all launchable tools from the resource handlers.
if ($ok) {
$resources = $toolproxyjson->tool_profile->resource_handler;
foreach ($resources as $resource) {
$found = false;
$tool = new \stdClass();
foreach ($resource->message as $message) {
if ($message->message_type == 'basic-lti-launch-request') {
$found = true;
$tool->path = $message->path;
$tool->enabled_capability = $message->enabled_capability;
$tool->parameter = $message->parameter;
break;
}
}
if (!$found) {
continue;
}
$tool->name = $resource->resource_name->default_value;
$tools[] = $tool;
}
$ok = count($tools) > 0;
if (!$ok) {
debugging('No launchable messages found in tool proxy');
}
}
// Add tools and custom parameters.
if ($ok) {
$baseurl = '';
if (isset($toolproxyjson->tool_profile->base_url_choice[0]->default_base_url)) {
$baseurl = $toolproxyjson->tool_profile->base_url_choice[0]->default_base_url;
}
$securebaseurl = '';
if (isset($toolproxyjson->tool_profile->base_url_choice[0]->secure_base_url)) {
$securebaseurl = $toolproxyjson->tool_profile->base_url_choice[0]->secure_base_url;
}
foreach ($tools as $tool) {
$config = new \stdClass();
$config->lti_toolurl = "{$baseurl}{$tool->path}";
$config->lti_typename = $tool->name;
$config->lti_coursevisible = 1;
$config->lti_forcessl = 0;
$type = new \stdClass();
$type->state = LTI_TOOL_STATE_PENDING;
$type->toolproxyid = $toolproxy->id;
$type->enabledcapability = implode("\n", $tool->enabled_capability);
$type->parameter = self::lti_extract_parameters($tool->parameter);
if (isset($resource->icon_info[0]->default_location->path)) {
$iconpath = $resource->icon_info[0]->default_location->path;
$type->icon = "{$baseurl}{$iconpath}";
if (!empty($securebaseurl)) {
$type->secureicon = "{$securebaseurl}{$iconpath}";
}
}
$ok = $ok && (lti_add_type($type, $config) !== false);
}
if (isset($toolproxyjson->custom)) {
lti_set_tool_settings($toolproxyjson->custom, $toolproxy->id);
}
}
if (!empty($toolproxy)) {
if ($ok) {
// If all went OK accept the tool proxy.
$toolproxy->state = LTI_TOOL_PROXY_STATE_ACCEPTED;
$toolproxy->toolproxy = $response->get_request_data();
$toolproxy->secret = $toolproxyjson->security_contract->shared_secret;
$toolproxy->vendorcode = $toolproxyjson->tool_profile->product_instance->product_info->product_family->vendor->code;
$url = $this->get_endpoint();
$body = <<< EOD
{
"@context" : "http://purl.imsglobal.org/ctx/lti/v2/ToolProxyId",
"@type" : "ToolProxy",
"@id" : "{$url}",
"tool_proxy_guid" : "{$toolproxy->guid}"
}
EOD;
$response->set_code(201);
$response->set_content_type('application/vnd.ims.lti.v2.toolproxy.id+json');
$response->set_body($body);
} else {
// Otherwise reject the tool proxy.
$toolproxy->state = LTI_TOOL_PROXY_STATE_REJECTED;
$response->set_code(400);
}
lti_update_tool_proxy($toolproxy);
} else {
$response->set_code(400);
}
}
/**
* Extracts the message parameters from the tool proxy entry
*
* @param array $parameters Parameter section of a message
*
* @return String containing parameters
*/
private static function lti_extract_parameters($parameters) {
$params = array();
foreach ($parameters as $parameter) {
if (isset($parameter->variable)) {
$value = '$' . $parameter->variable;
} else {
$value = $parameter->fixed;
if (strlen($value) > 0) {
$first = substr($value, 0, 1);
if (($first == '$') || ($first == '\\')) {
$value = '\\' . $value;
}
}
}
$params[] = "{$parameter->name}={$value}";
}
return implode("\n", $params);
}
}

View File

@ -0,0 +1,68 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains a class definition for the Tool Proxy service
*
* @package ltiservice_toolproxy
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace ltiservice_toolproxy\local\service;
defined('MOODLE_INTERNAL') || die();
/**
* A service implementing the Tool Proxy.
*
* @package ltiservice_toolproxy
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class toolproxy extends \mod_lti\local\ltiservice\service_base {
/**
* Class constructor.
*/
public function __construct() {
parent::__construct();
$this->id = 'toolproxy';
$this->name = 'Tool Proxy';
}
/**
* Get the resources for this service.
*
* @return array
*/
public function get_resources() {
if (empty($this->resources)) {
$this->resources = array();
$this->resources[] = new \ltiservice_toolproxy\local\resource\toolproxy($this);
}
return $this->resources;
}
}

View File

@ -0,0 +1,26 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for component 'ltiservice_toolproxy', language 'en'
*
* @package ltiservice_toolproxy
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['pluginname'] = 'Tool Proxy Service';

View File

@ -0,0 +1,33 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Version information for the ltiservice_toolproxy service.
*
* @package ltiservice_toolproxy
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2014092100;
$plugin->requires = 2014050800;
$plugin->component = 'ltiservice_toolproxy';
$plugin->dependencies = array('ltiservice_profile' => ANY_VERSION);

View File

@ -0,0 +1,182 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains a class definition for the Context Settings resource
*
* @package ltiservice_toolsettings
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace ltiservice_toolsettings\local\resource;
use ltiservice_toolsettings\local\resource\systemsettings;
use ltiservice_toolsettings\local\service\toolsettings;
defined('MOODLE_INTERNAL') || die();
/**
* A resource implementing the Context-level (ToolProxyBinding) Settings.
*
* @package ltiservice_toolsettings
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class contextsettings extends \mod_lti\local\ltiservice\resource_base {
/**
* Class constructor.
*
* @param ltiservice_toolsettings\local\resource\contextsettings $service Service instance
*/
public function __construct($service) {
parent::__construct($service);
$this->id = 'ToolProxyBindingSettings';
$this->template = '/{context_type}/{context_id}/bindings/{vendor_code}/{product_code}/custom';
$this->variables[] = 'ToolProxyBinding.custom.url';
$this->formats[] = 'application/vnd.ims.lti.v2.toolsettings+json';
$this->formats[] = 'application/vnd.ims.lti.v2.toolsettings.simple+json';
$this->methods[] = 'GET';
$this->methods[] = 'PUT';
}
/**
* Execute the request for this resource.
*
* @param mod_lti\local\ltiservice\response $response Response object for this request.
*/
public function execute($response) {
$params = $this->parse_template();
$contexttype = $params['context_type'];
$contextid = $params['context_id'];
$vendorcode = $params['vendor_code'];
$productcode = $params['product_code'];
$bubble = optional_param('bubble', '', PARAM_ALPHA);
$ok = !empty($contexttype) && !empty($contextid) &&
!empty($vendorcode) && !empty($productcode) &&
$this->check_tool_proxy($productcode, $response->get_request_data());
if (!$ok) {
$response->set_code(401);
}
$contenttype = $response->get_accept();
$simpleformat = !empty($contenttype) && ($contenttype == $this->formats[1]);
if ($ok) {
$ok = (empty($bubble) || ((($bubble == 'distinct') || ($bubble == 'all')))) &&
(!$simpleformat || empty($bubble) || ($bubble != 'all')) &&
(empty($bubble) || ($response->get_request_method() == 'GET'));
}
if (!$ok) {
$response->set_code(404);
} else {
$systemsetting = null;
$contextsettings = lti_get_tool_settings($this->get_service()->get_tool_proxy()->id, $contextid);
if (!empty($bubble)) {
$systemsetting = new systemsettings($this->get_service());
$systemsetting->params['tool_proxy_id'] = $productcode;
$systemsettings = lti_get_tool_settings($this->get_service()->get_tool_proxy()->id);
if ($bubble == 'distinct') {
toolsettings::distinct_settings($systemsettings, $contextsettings, null);
}
} else {
$systemsettings = null;
}
if ($response->get_request_method() == 'GET') {
$json = '';
if ($simpleformat) {
$response->set_content_type($this->formats[1]);
$json .= "{";
} else {
$response->set_content_type($this->formats[0]);
$json .= "{\n \"@context\":\"http://purl.imsglobal.org/ctx/lti/v2/ToolSettings\",\n \"@graph\":[\n";
}
$settings = toolsettings::settings_to_json($systemsettings, $simpleformat, 'ToolProxy', $systemsetting);
$json .= $settings;
$isfirst = strlen($settings) <= 0;
$settings = toolsettings::settings_to_json($contextsettings, $simpleformat, 'ToolProxyBinding', $this);
if ((strlen($settings) > 0) && !$isfirst) {
$json .= ",";
}
$json .= $settings;
if ($simpleformat) {
$json .= "\n}";
} else {
$json .= "\n ]\n}";
}
$response->set_body($json);
} else { // PUT.
$settings = null;
if ($response->get_content_type() == $this->formats[0]) {
$json = json_decode($response->get_request_data());
$ok = !empty($json);
if ($ok) {
$ok = isset($json->{"@graph"}) && is_array($json->{"@graph"}) && (count($json->{"@graph"}) == 1) &&
($json->{"@graph"}[0]->{"@type"} == 'ToolProxyBinding');
}
if ($ok) {
$settings = $json->{"@graph"}[0]->custom;
}
} else { // Simple JSON.
$json = json_decode($response->get_request_data(), true);
$ok = !empty($json);
if ($ok) {
$ok = is_array($json);
}
if ($ok) {
$settings = $json;
}
}
if ($ok) {
lti_set_tool_settings($settings, $this->get_service()->get_tool_proxy()->id, $contextid);
} else {
$response->set_code(406);
}
}
}
}
/**
* Parse a value for custom parameter substitution variables.
*
* @param string $value String to be parsed
*
* @return string
*/
public function parse_value($value) {
global $COURSE;
if ($COURSE->format == 'site') {
$this->params['context_type'] = 'Group';
} else {
$this->params['context_type'] = 'CourseSection';
}
$this->params['context_id'] = $COURSE->id;
$this->params['vendor_code'] = $this->get_service()->get_tool_proxy()->vendorcode;
$this->params['product_code'] = $this->get_service()->get_tool_proxy()->guid;
$value = str_replace('$ToolProxyBinding.custom.url', parent::get_endpoint(), $value);
return $value;
}
}

View File

@ -0,0 +1,208 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains a class definition for the Context Settings resource
*
* @package ltiservice_toolsettings
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace ltiservice_toolsettings\local\resource;
use ltiservice_toolsettings\local\resource\systemsettings;
use ltiservice_toolsettings\local\resource\contextsettings;
use ltiservice_toolsettings\local\service\toolsettings;
defined('MOODLE_INTERNAL') || die();
/**
* A resource implementing the Context-level (ToolProxyBinding) Settings.
*
* @package ltiservice_toolsettings
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class linksettings extends \mod_lti\local\ltiservice\resource_base {
/**
* Class constructor.
*
* @param ltiservice_toolsettings\local\resource\linksettings $service Service instance
*/
public function __construct($service) {
parent::__construct($service);
$this->id = 'LtiLinkSettings';
$this->template = '/links/{link_id}/custom';
$this->variables[] = 'LtiLink.custom.url';
$this->formats[] = 'application/vnd.ims.lti.v2.toolsettings+json';
$this->formats[] = 'application/vnd.ims.lti.v2.toolsettings.simple+json';
$this->methods[] = 'GET';
$this->methods[] = 'PUT';
}
/**
* Execute the request for this resource.
*
* @param mod_lti\local\ltiservice\response $response Response object for this request.
*/
public function execute($response) {
global $DB, $COURSE;
$params = $this->parse_template();
$linkid = $params['link_id'];
$bubble = optional_param('bubble', '', PARAM_ALPHA);
$contenttype = $response->get_accept();
$simpleformat = !empty($contenttype) && ($contenttype == $this->formats[1]);
$ok = (empty($bubble) || ((($bubble == 'distinct') || ($bubble == 'all')))) &&
(!$simpleformat || empty($bubble) || ($bubble != 'all')) &&
(empty($bubble) || ($response->get_request_method() == 'GET'));
if (!$ok) {
$response->set_code(406);
}
$systemsetting = null;
$contextsetting = null;
if ($ok) {
$ok = !empty($linkid);
if ($ok) {
$lti = $DB->get_record('lti', array('id' => $linkid), 'course,typeid', MUST_EXIST);
$ltitype = $DB->get_record('lti_types', array('id' => $lti->typeid));
$toolproxy = $DB->get_record('lti_tool_proxies', array('id' => $ltitype->toolproxyid));
$ok = $this->check_tool_proxy($toolproxy->guid, $response->get_request_data());
}
if (!$ok) {
$response->set_code(401);
}
}
if ($ok) {
$linksettings = lti_get_tool_settings($this->get_service()->get_tool_proxy()->id, $lti->course, $linkid);
if (!empty($bubble)) {
$contextsetting = new contextsettings($this->get_service());
if ($COURSE == 'site') {
$contextsetting->params['context_type'] = 'Group';
} else {
$contextsetting->params['context_type'] = 'CourseSection';
}
$contextsetting->params['context_id'] = $lti->course;
$contextsetting->params['vendor_code'] = $this->get_service()->get_tool_proxy()->vendorcode;
$contextsetting->params['product_code'] = $this->get_service()->get_tool_proxy()->id;
$contextsettings = lti_get_tool_settings($this->get_service()->get_tool_proxy()->id, $lti->course);
$systemsetting = new systemsettings($this->get_service());
$systemsetting->params['tool_proxy_id'] = $this->get_service()->get_tool_proxy()->id;
$systemsettings = lti_get_tool_settings($this->get_service()->get_tool_proxy()->id);
if ($bubble == 'distinct') {
toolsettings::distinct_settings($systemsettings, $contextsettings, $linksettings);
}
} else {
$contextsettings = null;
$systemsettings = null;
}
if ($response->get_request_method() == 'GET') {
$json = '';
if ($simpleformat) {
$response->set_content_type($this->formats[1]);
$json .= "{";
} else {
$response->set_content_type($this->formats[0]);
$json .= "{\n \"@context\":\"http://purl.imsglobal.org/ctx/lti/v2/ToolSettings\",\n \"@graph\":[\n";
}
$settings = toolsettings::settings_to_json($systemsettings, $simpleformat, 'ToolProxy', $systemsetting);
$json .= $settings;
$isfirst = strlen($settings) <= 0;
$settings = toolsettings::settings_to_json($contextsettings, $simpleformat, 'ToolProxyBinding', $contextsetting);
if (strlen($settings) > 0) {
if (!$isfirst) {
$json .= ",";
if (!$simpleformat) {
$json .= "\n";
}
}
$isfirst = false;
}
$json .= $settings;
$settings = toolsettings::settings_to_json($linksettings, $simpleformat, 'LtiLink', $this);
if ((strlen($settings) > 0) && !$isfirst) {
$json .= ",";
if (!$simpleformat) {
$json .= "\n";
}
}
$json .= $settings;
if ($simpleformat) {
$json .= "\n}";
} else {
$json .= "\n ]\n}";
}
$response->set_body($json);
} else { // PUT.
$settings = null;
if ($response->get_content_type() == $this->formats[0]) {
$json = json_decode($response->get_request_data());
$ok = !empty($json);
if ($ok) {
$ok = isset($json->{"@graph"}) && is_array($json->{"@graph"}) && (count($json->{"@graph"}) == 1) &&
($json->{"@graph"}[0]->{"@type"} == 'LtiLink');
}
if ($ok) {
$settings = $json->{"@graph"}[0]->custom;
}
} else { // Simple JSON.
$json = json_decode($response->get_request_data(), true);
$ok = !empty($json);
if ($ok) {
$ok = is_array($json);
}
if ($ok) {
$settings = $json;
}
}
if ($ok) {
lti_set_tool_settings($settings, $this->get_service()->get_tool_proxy()->id, $lti->course, $linkid);
} else {
$response->set_code(406);
}
}
}
}
/**
* Parse a value for custom parameter substitution variables.
*
* @param string $value String to be parsed
*
* @return string
*/
public function parse_value($value) {
$id = optional_param('id', 0, PARAM_INT); // Course Module ID.
if (!empty($id)) {
$cm = get_coursemodule_from_id('lti', $id, 0, false, MUST_EXIST);
$this->params['link_id'] = $cm->instance;
}
$value = str_replace('$LtiLink.custom.url', parent::get_endpoint(), $value);
return $value;
}
}

View File

@ -0,0 +1,152 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains a class definition for the System Settings resource
*
* @package ltiservice_toolsettings
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace ltiservice_toolsettings\local\resource;
use ltiservice_toolsettings\local\service\toolsettings;
defined('MOODLE_INTERNAL') || die();
/**
* A resource implementing the System-level (ToolProxy) Settings.
*
* @package ltiservice_toolsettings
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class systemsettings extends \mod_lti\local\ltiservice\resource_base {
/**
* Class constructor.
*
* @param ltiservice_toolsettings\local\service\toolsettings $service Service instance
*/
public function __construct($service) {
parent::__construct($service);
$this->id = 'ToolProxySettings';
$this->template = '/toolproxy/{tool_proxy_id}/custom';
$this->variables[] = 'ToolProxy.custom.url';
$this->formats[] = 'application/vnd.ims.lti.v2.toolsettings+json';
$this->formats[] = 'application/vnd.ims.lti.v2.toolsettings.simple+json';
$this->methods[] = 'GET';
$this->methods[] = 'PUT';
}
/**
* Execute the request for this resource.
*
* @param mod_lti\local\ltiservice\response $response Response object for this request.
*/
public function execute($response) {
$params = $this->parse_template();
$tpid = $params['tool_proxy_id'];
$bubble = optional_param('bubble', '', PARAM_ALPHA);
$ok = !empty($tpid) && $this->check_tool_proxy($tpid, $response->get_request_data());
if (!$ok) {
$response->set_code(401);
}
$contenttype = $response->get_accept();
$simpleformat = !empty($contenttype) && ($contenttype == $this->formats[1]);
if ($ok) {
$ok = (empty($bubble) || ((($bubble == 'distinct') || ($bubble == 'all')))) &&
(!$simpleformat || empty($bubble) || ($bubble != 'all')) &&
(empty($bubble) || ($response->get_request_method() == 'GET'));
if (!$ok) {
$response->set_code(406);
}
}
if ($ok) {
$systemsettings = lti_get_tool_settings($this->get_service()->get_tool_proxy()->id);
if ($response->get_request_method() == 'GET') {
$json = '';
if ($simpleformat) {
$response->set_content_type($this->formats[1]);
$json .= "{";
} else {
$response->set_content_type($this->formats[0]);
$json .= "{\n \"@context\":\"http://purl.imsglobal.org/ctx/lti/v2/ToolSettings\",\n \"@graph\":[\n";
}
$json .= toolsettings::settings_to_json($systemsettings, $simpleformat,
'ToolProxy', $this);
if ($simpleformat) {
$json .= "\n}";
} else {
$json .= "\n ]\n}";
}
$response->set_body($json);
} else { // PUT.
$settings = null;
if ($response->get_content_type() == $this->formats[0]) {
$json = json_decode($response->get_request_data());
$ok = !empty($json);
if ($ok) {
$ok = isset($json->{"@graph"}) && is_array($json->{"@graph"}) && (count($json->{"@graph"}) == 1) &&
($json->{"@graph"}[0]->{"@type"} == 'ToolProxy');
}
if ($ok) {
$settings = $json->{"@graph"}[0]->custom;
}
} else { // Simple JSON.
$json = json_decode($response->get_request_data(), true);
$ok = !empty($json);
if ($ok) {
$ok = is_array($json);
}
if ($ok) {
$settings = $json;
}
}
if ($ok) {
lti_set_tool_settings($settings, $this->get_service()->get_tool_proxy()->id);
} else {
$response->set_code(406);
}
}
}
}
/**
* Parse a value for custom parameter substitution variables.
*
* @param string $value String to be parsed
*
* @return string
*/
public function parse_value($value) {
$value = str_replace('$ToolProxy.custom.url', parent::get_endpoint(), $value);
return $value;
}
}

View File

@ -0,0 +1,138 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains a class definition for the Tool Settings service
*
* @package ltiservice_toolsettings
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace ltiservice_toolsettings\local\service;
defined('MOODLE_INTERNAL') || die();
/**
* A service implementing Tool Settings.
*
* @package ltiservice_toolsettings
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class toolsettings extends \mod_lti\local\ltiservice\service_base {
/**
* Class constructor.
*/
public function __construct() {
parent::__construct();
$this->id = 'toolsettings';
$this->name = 'Tool Settings';
}
/**
* Get the resources for this service.
*
* @return array
*/
public function get_resources() {
if (empty($this->resources)) {
$this->resources = array();
$this->resources[] = new \ltiservice_toolsettings\local\resource\systemsettings($this);
$this->resources[] = new \ltiservice_toolsettings\local\resource\contextsettings($this);
$this->resources[] = new \ltiservice_toolsettings\local\resource\linksettings($this);
}
return $this->resources;
}
/**
* Get the distinct settings from each level by removing any duplicates from higher levels.
*
* @param array $systemsettings System level settings
* @param array $contextsettings Context level settings
* @param array $linksettings Link level settings
*/
public static function distinct_settings(&$systemsettings, &$contextsettings, $linksettings) {
if (!empty($systemsettings)) {
foreach ($systemsettings as $key => $value) {
if ((!empty($contextsettings) && array_key_exists($key, $contextsettings)) ||
(!empty($linksettings) && array_key_exists($key, $linksettings))) {
unset($systemsettings[$key]);
}
}
}
if (!empty($contextsettings)) {
foreach ($contextsettings as $key => $value) {
if (!empty($linksettings) && array_key_exists($key, $linksettings)) {
unset($contextsettings[$key]);
}
}
}
}
/**
* Get the JSON representation of the settings.
*
* @param array $settings Settings
* @param boolean $simpleformat <code>true</code> if simple JSON is to be returned
* @param string $type JSON-LD type
* @param \mod_lti\local\ltiservice\resource_base $resource Resource handling the request
*
* @return string
*/
public static function settings_to_json($settings, $simpleformat, $type, $resource) {
$json = '';
if (!empty($resource)) {
$indent = '';
if (!$simpleformat) {
$json .= " {\n \"@type\":\"{$type}\",\n";
$json .= " \"@id\":\"{$resource->get_endpoint()}\",\n";
$json .= ' "custom":';
$json .= "{";
$indent = ' ';
}
$isfirst = true;
if (!empty($settings)) {
foreach ($settings as $key => $value) {
if (!$isfirst) {
$json .= ",";
} else {
$isfirst = false;
}
$json .= "\n{$indent} \"{$key}\":\"{$value}\"";
}
}
if (!$simpleformat) {
$json .= "\n{$indent}}\n }";
}
}
return $json;
}
}

View File

@ -0,0 +1,26 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for component 'ltiservice_toolsettings', language 'en'
*
* @package ltiservice_toolsettings
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['pluginname'] = 'Tool Settings Service';

View File

@ -0,0 +1,35 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Version information for the ltiservice_toolsettings service.
*
* @package ltiservice_toolsettings
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2014092100;
$plugin->requires = 2014050800;
$plugin->component = 'ltiservice_toolsettings';
$plugin->dependencies = array('ltiservice_profile' => ANY_VERSION,
'ltiservice_toolproxy' => ANY_VERSION
);

View File

@ -27,7 +27,7 @@ defined('MOODLE_INTERNAL') || die;
require_once($CFG->dirroot.'/mod/lti/OAuthBody.php');
// TODO: Switch to core oauthlib once implemented - MDL-30149
// TODO: Switch to core oauthlib once implemented - MDL-30149.
use moodle\mod\lti as lti;
define('LTI_ITEM_TYPE', 'mod');
@ -48,7 +48,7 @@ function lti_get_response_xml($codemajor, $description, $messageref, $messagetyp
$statusinfo->addChild('imsx_severity', 'status');
$statusinfo->addChild('imsx_description', $description);
$statusinfo->addChild('imsx_messageRefIdentifier', $messageref);
$incomingtype = str_replace('Response','Request', $messagetype);
$incomingtype = str_replace('Response', 'Request', $messagetype);
$statusinfo->addChild('imsx_operationRefIdentifier', $incomingtype);
$xml->addChild('imsx_POXBody')->addChild($messagetype);
@ -125,14 +125,23 @@ function lti_parse_grade_delete_message($xml) {
}
function lti_accepts_grades($ltiinstance) {
global $DB;
$acceptsgrades = true;
$typeconfig = lti_get_config($ltiinstance);
$ltitype = $DB->get_record('lti_types', array('id' => $ltiinstance->typeid));
$typeacceptgrades = isset($typeconfig['acceptgrades']) ? $typeconfig['acceptgrades'] : LTI_SETTING_DELEGATE;
if (empty($ltitype->toolproxyid)) {
$typeconfig = lti_get_config($ltiinstance);
if (!($typeacceptgrades == LTI_SETTING_ALWAYS ||
($typeacceptgrades == LTI_SETTING_DELEGATE && $ltiinstance->instructorchoiceacceptgrades == LTI_SETTING_ALWAYS))) {
$acceptsgrades = false;
$typeacceptgrades = isset($typeconfig['acceptgrades']) ? $typeconfig['acceptgrades'] : LTI_SETTING_DELEGATE;
if (!($typeacceptgrades == LTI_SETTING_ALWAYS ||
($typeacceptgrades == LTI_SETTING_DELEGATE && $ltiinstance->instructorchoiceacceptgrades == LTI_SETTING_ALWAYS))) {
$acceptsgrades = false;
}
} else {
$enabledcapabilities = explode("\n", $ltitype->enabledcapability);
$acceptsgrades = in_array('Result.autocreate', $enabledcapabilities);
}
return $acceptsgrades;
@ -166,7 +175,8 @@ function lti_update_grade($ltiinstance, $userid, $launchid, $gradeval) {
$status = grade_update(LTI_SOURCE, $ltiinstance->course, LTI_ITEM_TYPE, LTI_ITEM_MODULE, $ltiinstance->id, 0, $grade, $params);
$record = $DB->get_record('lti_submission', array('ltiid' => $ltiinstance->id, 'userid' => $userid, 'launchid' => $launchid), 'id');
$record = $DB->get_record('lti_submission', array('ltiid' => $ltiinstance->id, 'userid' => $userid,
'launchid' => $launchid), 'id');
if ($record) {
$id = $record->id;
} else {
@ -235,14 +245,14 @@ function lti_verify_message($key, $sharedsecrets, $body, $headers = null) {
$signaturefailed = false;
try {
// TODO: Switch to core oauthlib once implemented - MDL-30149
lti\handleOAuthBodyPOST($key, $secret, $body, $headers);
// TODO: Switch to core oauthlib once implemented - MDL-30149.
lti\handle_oauth_body_post($key, $secret, $body, $headers);
} catch (Exception $e) {
$signaturefailed = true;
}
if (!$signaturefailed) {
return $secret;//Return the secret used to sign the message)
return $secret; // Return the secret used to sign the message).
}
}
@ -276,7 +286,7 @@ function lti_extend_lti_services($data) {
$plugins = get_plugin_list_with_function('ltisource', $data->messagetype);
if (!empty($plugins)) {
try {
// There can only be one
// There can only be one.
if (count($plugins) > 1) {
throw new coding_exception('More than one ltisource plugin handler found');
}

78
mod/lti/services.php Normal file
View File

@ -0,0 +1,78 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains a controller for receiving LTI service requests
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('NO_DEBUG_DISPLAY', true);
define('NO_MOODLE_COOKIES', true);
require_once(dirname(__FILE__) . '/../../config.php');
require_once($CFG->dirroot . '/mod/lti/locallib.php');
$response = new \mod_lti\local\ltiservice\response();
$isget = $response->get_request_method() == 'GET';
if ($isget) {
$response->set_accept(isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : '');
} else {
$response->set_content_type(isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : '');
}
$ok = false;
$path = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
$accept = $response->get_accept();
$services = lti_get_services();
foreach ($services as $service) {
$resources = $service->get_resources();
foreach ($resources as $resource) {
if (($isget && !empty($accept) && (strpos($accept, '*/*') === false) &&
!in_array($accept, $resource->get_formats())) ||
(!$isget && !in_array($response->get_content_type(), $resource->get_formats()))) {
continue;
}
$template = $resource->get_template();
$template = preg_replace('/\{[a-zA-Z_]+\}/', '[^/]+', $template);
$template = preg_replace('/\{\?[0-9a-zA-Z_\-,]+\}$/', '', $template);
$template = str_replace('/', '\/', $template);
if (preg_match("/{$template}/", $path) === 1) {
$ok = true;
break 2;
}
}
}
if (!$ok) {
$response->set_code(400);
} else {
$body = file_get_contents('php://input');
$response->set_request_data($body);
if (in_array($response->get_request_method(), $resource->get_methods())) {
$resource->execute($response);
} else {
$response->set_code(405);
}
}
$response->send();

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file defines the global lti administration form
@ -48,17 +48,27 @@
defined('MOODLE_INTERNAL') || die;
/** @var admin_settingpage $settings */
/*
* @var admin_settingpage $settings
*/
$modltifolder = new admin_category('modltifolder', new lang_string('pluginname', 'mod_lti'), $module->is_enabled() === false);
$ADMIN->add('modsettings', $modltifolder);
$settings->visiblename = new lang_string('manage_tools', 'mod_lti');
$ADMIN->add('modltifolder', $settings);
$ADMIN->add('modltifolder', new admin_externalpage('ltitoolproxies',
get_string('manage_tool_proxies', 'lti'),
new moodle_url('/mod/lti/toolproxies.php')));
foreach (core_plugin_manager::instance()->get_plugins_of_type('ltisource') as $plugin) {
/** @var \mod_lti\plugininfo\ltisource $plugin */
/*
* @var \mod_lti\plugininfo\ltisource $plugin
*/
$plugin->load_settings($ADMIN, 'modltifolder', $hassiteconfig);
}
$toolproxiesurl = new moodle_url('/mod/lti/toolproxies.php');
$toolproxiesurl = $toolproxiesurl->out();
if ($ADMIN->fulltree) {
require_once($CFG->dirroot.'/mod/lti/locallib.php');
@ -110,28 +120,33 @@ if ($ADMIN->fulltree) {
$activeselected = 'class="selected"';
break;
}
$addtype = get_string('addtype', 'lti');
$config = get_string('manage_tool_proxies', 'lti');
$template = "
<div id=\"lti_tabs\" class=\"yui-navset\">
<ul id=\"lti_tab_heading\" class=\"yui-nav\" style=\"display:none\">
$addtypeurl = "{$CFG->wwwroot}/mod/lti/typessettings.php?action=add&amp;sesskey={$USER->sesskey}";
$template = <<< EOD
<div id="lti_tabs" class="yui-navset">
<ul id="lti_tab_heading" class="yui-nav" style="display:none">
<li {$activeselected}>
<a href=\"#tab1\">
<a href="#tab1">
<em>$active</em>
</a>
</li>
<li {$pendingselected}>
<a href=\"#tab2\">
<a href="#tab2">
<em>$pending</em>
</a>
</li>
<li {$rejectedselected}>
<a href=\"#tab3\">
<a href="#tab3">
<em>$rejected</em>
</a>
</li>
</ul>
<div class=\"yui-content\">
<div class="yui-content">
<div>
<div><a style="margin-top:.25em" href="{$addtypeurl}">{$addtype}</a></div>
$configuredtoolshtml
</div>
<div>
@ -143,7 +158,7 @@ if ($ADMIN->fulltree) {
</div>
</div>
<script type=\"text/javascript\">
<script type="text/javascript">
//<![CDATA[
YUI().use('yui2-tabview', 'yui2-datatable', function(Y) {
//If javascript is disabled, they will just see the three tabs one after another
@ -183,23 +198,17 @@ if ($ADMIN->fulltree) {
}
};
setupTools('lti_configured', {key:'name', dir:'asc'});
setupTools('lti_pending', {key:'timecreated', dir:'desc'});
setupTools('lti_rejected', {key:'timecreated', dir:'desc'});
setupTools('lti_configured_tools', {key:'name', dir:'asc'});
setupTools('lti_pending_tools', {key:'timecreated', dir:'desc'});
setupTools('lti_rejected_tools', {key:'timecreated', dir:'desc'});
});
//]]
</script>
";
$settings->add(new admin_setting_heading('lti_types', new lang_string('external_tool_types', 'lti') . $OUTPUT->help_icon('main_admin', 'lti'), $template));
EOD;
$settings->add(new admin_setting_heading('lti_types', new lang_string('external_tool_types', 'lti') .
$OUTPUT->help_icon('main_admin', 'lti'), $template));
}
if (count($modltifolder->children) <= 1) {
// No need for a folder, revert to default activity settings page.
$ADMIN->prune('modltifolder');
} else {
// Using the folder, update settings name.
$settings->visiblename = new lang_string('ltisettings', 'mod_lti');
// Tell core we already added the settings structure.
$settings = null;
// Tell core we already added the settings structure.
$settings = null;
}

View File

@ -34,7 +34,7 @@ use mod_lti\event\unknown_service_api_called;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_lti_event_unknown_service_api_called_test extends advanced_testcase {
/**
/*
* Ensure create event works.
*/
public function test_create_event() {
@ -42,7 +42,7 @@ class mod_lti_event_unknown_service_api_called_test extends advanced_testcase {
$this->assertInstanceOf('\mod_lti\event\unknown_service_api_called', $event);
}
/**
/*
* Ensure event context works.
*/
public function test_event_context() {
@ -50,7 +50,7 @@ class mod_lti_event_unknown_service_api_called_test extends advanced_testcase {
$this->assertEquals(context_system::instance(), $event->get_context());
}
/**
/*
* Ensure we can trigger the event.
*/
public function test_trigger_event() {
@ -62,7 +62,7 @@ class mod_lti_event_unknown_service_api_called_test extends advanced_testcase {
$this->assertCount(1, $events);
}
/**
/*
* Ensure get/set message data is functioning as expected.
*/
public function test_get_message_data() {
@ -71,9 +71,11 @@ class mod_lti_event_unknown_service_api_called_test extends advanced_testcase {
'bat' => 'baz',
);
/** @var unknown_service_api_called $event */
/*
* @var unknown_service_api_called $event
*/
$event = unknown_service_api_called::create();
$event->set_message_data($data);
$this->assertSame($data, $event->get_message_data());
}
}
}

View File

@ -45,7 +45,9 @@ class mod_lti_generator_testcase extends advanced_testcase {
$course = $this->getDataGenerator()->create_course();
/** @var mod_lti_generator $generator */
/*
* @var mod_lti_generator $generator
*/
$generator = $this->getDataGenerator()->get_plugin_generator('mod_lti');
$this->assertInstanceOf('mod_lti_generator', $generator);
$this->assertEquals('lti', $generator->get_modulename());
@ -63,9 +65,10 @@ class mod_lti_generator_testcase extends advanced_testcase {
$context = context_module::instance($cm->id);
$this->assertEquals($lti->cmid, $context->instanceid);
// test gradebook integration using low level DB access - DO NOT USE IN PLUGIN CODE!
// Test gradebook integration using low level DB access - DO NOT USE IN PLUGIN CODE!
$lti = $generator->create_instance(array('course' => $course->id, 'assessed' => 1, 'scale' => 100));
$gitem = $DB->get_record('grade_items', array('courseid' => $course->id, 'itemtype' => 'mod', 'itemmodule' => 'lti', 'iteminstance' => $lti->id));
$gitem = $DB->get_record('grade_items', array('courseid' => $course->id, 'itemtype' => 'mod',
'itemmodule' => 'lti', 'iteminstance' => $lti->id));
$this->assertNotEmpty($gitem);
$this->assertEquals(100, $gitem->grademax);
$this->assertEquals(0, $gitem->grademin);

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file contains unit tests for (some of) lti/locallib.php
@ -63,17 +63,19 @@ require_once($CFG->dirroot . '/mod/lti/servicelib.php');
class mod_lti_locallib_testcase extends advanced_testcase {
public function test_split_custom_parameters() {
$this->assertEquals(lti_split_custom_parameters("x=1\ny=2"),
array('custom_x' => '1', 'custom_y'=> '2'));
$tool = new stdClass();
$tool->enabledcapability = '';
$this->assertEquals(lti_split_custom_parameters(null, $tool, array(), "x=1\ny=2", false),
array('custom_x' => '1', 'custom_y' => '2'));
$this->assertEquals(lti_split_custom_parameters('x=1;y=2'),
array('custom_x' => '1', 'custom_y'=> '2'));
// Removed repeat of previous test with a semicolon separator.
$this->assertEquals(lti_split_custom_parameters('Review:Chapter=1.2.56'),
$this->assertEquals(lti_split_custom_parameters(null, $tool, array(), 'Review:Chapter=1.2.56', false),
array('custom_review_chapter' => '1.2.56'));
$this->assertEquals(lti_split_custom_parameters('Complex!@#$^*(){}[]KEY=Complex!@#$^*(){}[]Value'),
array('custom_complex____________key' => 'Complex!@#$^*(){}[]Value'));
$this->assertEquals(lti_split_custom_parameters(null, $tool, array(),
'Complex!@#$^*(){}[]KEY=Complex!@#$^*;(){}[]½Value', false),
array('custom_complex____________key' => 'Complex!@#$^*;(){}[]½Value'));
}
/**
@ -83,9 +85,16 @@ class mod_lti_locallib_testcase extends advanced_testcase {
* outside-checks to the conformance tests. MDL-30347
*/
public function disabled_test_sign_parameters() {
$correct = array ( 'context_id' => '12345', 'context_label' => 'SI124', 'context_title' => 'Social Computing', 'ext_submit' => 'Click Me', 'lti_message_type' => 'basic-lti-launch-request', 'lti_version' => 'LTI-1p0', 'oauth_consumer_key' => 'lmsng.school.edu', 'oauth_nonce' => '47458148e33a8f9dafb888c3684cf476', 'oauth_signature' => 'qWgaBIezihCbeHgcwUy14tZcyDQ=', 'oauth_signature_method' => 'HMAC-SHA1', 'oauth_timestamp' => '1307141660', 'oauth_version' => '1.0', 'resource_link_id' => '123', 'resource_link_title' => 'Weekly Blog', 'roles' => 'Learner', 'tool_consumer_instance_guid' => 'lmsng.school.edu', 'user_id' => '789');
$correct = array ( 'context_id' => '12345', 'context_label' => 'SI124', 'context_title' => 'Social Computing',
'ext_submit' => 'Click Me', 'lti_message_type' => 'basic-lti-launch-request', 'lti_version' => 'LTI-1p0',
'oauth_consumer_key' => 'lmsng.school.edu', 'oauth_nonce' => '47458148e33a8f9dafb888c3684cf476',
'oauth_signature' => 'qWgaBIezihCbeHgcwUy14tZcyDQ=', 'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => '1307141660', 'oauth_version' => '1.0', 'resource_link_id' => '123',
'resource_link_title' => 'Weekly Blog', 'roles' => 'Learner', 'tool_consumer_instance_guid' => 'lmsng.school.edu',
'user_id' => '789');
$requestparams = array('resource_link_id' => '123', 'resource_link_title' => 'Weekly Blog', 'user_id' => '789', 'roles' => 'Learner', 'context_id' => '12345', 'context_label' => 'SI124', 'context_title' => 'Social Computing');
$requestparams = array('resource_link_id' => '123', 'resource_link_title' => 'Weekly Blog', 'user_id' => '789',
'roles' => 'Learner', 'context_id' => '12345', 'context_label' => 'SI124', 'context_title' => 'Social Computing');
$parms = lti_sign_parameters($requestparams, 'http://www.imsglobal.org/developer/LTI/tool.php', 'POST',
'lmsng.school.edu', 'secret', 'Click Me', 'lmsng.school.edu' /*, $org_desc*/);
@ -93,7 +102,7 @@ class mod_lti_locallib_testcase extends advanced_testcase {
$this->assertTrue(isset($parms['oauth_signature']));
$this->assertTrue(isset($parms['oauth_timestamp']));
// Those things that are hard to mock
// Those things that are hard to mock.
$correct['oauth_nonce'] = $parms['oauth_nonce'];
$correct['oauth_signature'] = $parms['oauth_signature'];
$correct['oauth_timestamp'] = $parms['oauth_timestamp'];
@ -121,7 +130,10 @@ class mod_lti_locallib_testcase extends advanced_testcase {
<replaceResultRequest>
<resultRecord>
<sourcedGUID>
<sourcedId>{&quot;data&quot;:{&quot;instanceid&quot;:&quot;2&quot;,&quot;userid&quot;:&quot;2&quot;},&quot;hash&quot;:&quot;0b5078feab59b9938c333ceaae21d8e003a7b295e43cdf55338445254421076b&quot;}</sourcedId>
<sourcedId>' .
'{&quot;data&quot;:{&quot;instanceid&quot;:&quot;2&quot;,&quot;userid&quot;:&quot;2&quot;},&quot;hash&quot;:' .
'&quot;0b5078feab59b9938c333ceaae21d8e003a7b295e43cdf55338445254421076b&quot;}' .
'</sourcedId>
</sourcedGUID>
<result>
<resultScore>

View File

@ -0,0 +1,90 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* LTI upgrade script.
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/lti/locallib.php');
require_once($CFG->dirroot . '/mod/lti/db/upgradelib.php');
/**
* Unit tests for mod_lti upgrades.
*
* @package mod_lti
* @since Moodle 2.8
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_lti_upgradelib_testcase extends advanced_testcase {
/**
* Test conversion of semicolon separated custom parameters.
*/
public function test_custom_parameter() {
global $DB, $SITE, $USER;
$custom1 = 'a=one;b=two;three=3';
$custom2 = "a=one\nb=two\nthree=3";
$this->resetAfterTest(true);
$ltigenerator = $this->getDataGenerator()->get_plugin_generator('mod_lti');
// Create 2 tools with custom parameters.
$toolid1 = $DB->insert_record('lti_types', array('course' => $SITE->id, 'baseurl' => '', 'createdby' => $USER->id,
'timecreated' => time(), 'timemodified' => time()));
$configid1 = $DB->insert_record('lti_types_config', array('typeid' => $toolid1, 'name' => 'customparameters',
'value' => $custom1));
$toolid2 = $DB->insert_record('lti_types', array('course' => $SITE->id, 'baseurl' => '', 'createdby' => $USER->id,
'timecreated' => time(), 'timemodified' => time()));
$configid2 = $DB->insert_record('lti_types_config', array('typeid' => $toolid2, 'name' => 'customparameters',
'value' => $custom2));
// Create 2 instances with custom parameters.
$activity1 = $ltigenerator->create_instance(array('course' => $SITE->id, 'name' => 'LTI activity 1',
'typeid' => $toolid1, 'toolurl' => '', 'instructorcustomparameters' => $custom1));
$activity2 = $ltigenerator->create_instance(array('course' => $SITE->id, 'name' => 'LTI activity 2',
'typeid' => $toolid2, 'toolurl' => '', 'instructorcustomparameters' => $custom2));
// Run upgrade script.
mod_lti_upgrade_custom_separator();
// Check semicolon-separated custom parameters have been updated but others have not.
$config = $DB->get_record('lti_types_config', array('id' => $configid1));
$this->assertEquals($config->value, $custom2);
$config = $DB->get_record('lti_types_config', array('id' => $configid2));
$this->assertEquals($config->value, $custom2);
$config = $DB->get_record('lti', array('id' => $activity1->id));
$this->assertEquals($config->instructorcustomparameters, $custom2);
$config = $DB->get_record('lti', array('id' => $activity2->id));
$this->assertEquals($config->instructorcustomparameters, $custom2);
}
}

193
mod/lti/toolproxies.php Normal file
View File

@ -0,0 +1,193 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains all necessary code to launch a Tool Proxy registration
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot.'/mod/lti/locallib.php');
// No guest autologin.
require_login(0, false);
$pageurl = new moodle_url('/mod/lti/toolproxies.php');
$PAGE->set_url($pageurl);
admin_externalpage_setup('ltitoolproxies');
$PAGE->set_title("{$SITE->shortname}: " . get_string('toolregistration', 'lti'));
$configuredtoolproxieshtml = '';
$pendingtoolproxieshtml = '';
$acceptedtoolproxieshtml = '';
$rejectedtoolproxieshtml = '';
$configured = get_string('configured', 'lti');
$pending = get_string('pending', 'lti');
$accepted = get_string('accepted', 'lti');
$rejected = get_string('rejected', 'lti');
$name = get_string('name', 'lti');
$url = get_string('registrationurl', 'lti');
$action = get_string('action', 'lti');
$createdon = get_string('createdon', 'lti');
$toolproxies = $DB->get_records('lti_tool_proxies');
$configuredtoolproxies = lti_filter_tool_proxy_types($toolproxies, LTI_TOOL_PROXY_STATE_CONFIGURED);
$configuredtoolproxieshtml = lti_get_tool_proxy_table($configuredtoolproxies, 'tp_configured');
$pendingtoolproxies = lti_filter_tool_proxy_types($toolproxies, LTI_TOOL_PROXY_STATE_PENDING);
$pendingtoolproxieshtml = lti_get_tool_proxy_table($pendingtoolproxies, 'tp_pending');
$acceptedtoolproxies = lti_filter_tool_proxy_types($toolproxies, LTI_TOOL_PROXY_STATE_ACCEPTED);
$acceptedtoolproxieshtml = lti_get_tool_proxy_table($acceptedtoolproxies, 'tp_accepted');
$rejectedtoolproxies = lti_filter_tool_proxy_types($toolproxies, LTI_TOOL_PROXY_STATE_REJECTED);
$rejectedtoolproxieshtml = lti_get_tool_proxy_table($rejectedtoolproxies, 'tp_rejected');
$tab = optional_param('tab', '', PARAM_ALPHAEXT);
$configuredselected = '';
$pendingselected = '';
$acceptedselected = '';
$rejectedselected = '';
switch ($tab) {
case 'tp_pending':
$pendingselected = 'class="selected"';
break;
case 'tp_accepted':
$acceptedselected = 'class="selected"';
break;
case 'tp_rejected':
$rejectedselected = 'class="selected"';
break;
default:
$configuredselected = 'class="selected"';
break;
}
$registertype = get_string('registertype', 'lti');
$config = get_string('manage_tools', 'lti');
$registertypeurl = "{$CFG->wwwroot}/mod/lti/registersettings.php?action=add&amp;sesskey={$USER->sesskey}&amp;tab=tool_proxy";
$template = <<< EOD
<div id="tp_tabs" class="yui-navset">
<ul id="tp_tab_heading" class="yui-nav" style="display:none">
<li {$configuredselected}>
<a href="#tab1">
<em>$configured</em>
</a>
</li>
<li {$pendingselected}>
<a href="#tab2">
<em>$pending</em>
</a>
</li>
<li {$acceptedselected}>
<a href="#tab3">
<em>$accepted</em>
</a>
</li>
<li {$rejectedselected}>
<a href="#tab4">
<em>$rejected</em>
</a>
</li>
</ul>
<div class="yui-content">
<div>
<div><a style="margin-top:.25em" href="{$registertypeurl}">{$registertype}</a></div>
$configuredtoolproxieshtml
</div>
<div>
$pendingtoolproxieshtml
</div>
<div>
$acceptedtoolproxieshtml
</div>
<div>
$rejectedtoolproxieshtml
</div>
</div>
</div>
<script type="text/javascript">
//<![CDATA[
YUI().use('yui2-tabview', 'yui2-datatable', function(Y) {
//If javascript is disabled, they will just see the three tabs one after another
var tp_tab_heading = document.getElementById('tp_tab_heading');
tp_tab_heading.style.display = '';
new Y.YUI2.widget.TabView('tp_tabs');
var setupTools = function(id, sort){
var tp_tool_proxies = Y.YUI2.util.Dom.get(id);
if(tp_tool_proxies){
var dataSource = new Y.YUI2.util.DataSource(tp_tool_proxies);
var configuredColumns = [
{key:'name', label:'$name', sortable:true},
{key:'url', label:'$url', sortable:true},
{key:'timecreated', label:'$createdon', sortable:true},
{key:'action', label:'$action'}
];
dataSource.responseType = Y.YUI2.util.DataSource.TYPE_HTMLTABLE;
dataSource.responseSchema = {
fields: [
{key:'name'},
{key:'url'},
{key:'timecreated'},
{key:'action'}
]
};
new Y.YUI2.widget.DataTable(id + '_container', configuredColumns, dataSource,
{
sortedBy: sort
}
);
}
};
setupTools('tp_configured_tool_proxies', {key:'name', dir:'asc'});
setupTools('tp_pending_tool_proxies', {key:'timecreated', dir:'desc'});
setupTools('tp_accepted_tool_proxies', {key:'timecreated', dir:'desc'});
setupTools('tp_rejected_tool_proxies', {key:'timecreated', dir:'desc'});
});
//]]
</script>
EOD;
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('manage_tool_proxies', 'lti'), 2);
echo $OUTPUT->heading(new lang_string('toolproxy', 'lti') .
$OUTPUT->help_icon('toolproxy', 'lti'), 3);
echo $OUTPUT->box_start('generalbox');
echo $template;
echo $OUTPUT->box_end();
echo $OUTPUT->footer();

102
mod/lti/toolssettings.php Normal file
View File

@ -0,0 +1,102 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the script used to register a new external tool.
*
* It is used to create a new form used to configure the capabilities
* and services to be offered to the tool provider.
*
* @package mod_lti
* @copyright 2014 Vital Source Technologies http://vitalsource.com
* @author Stephen Vickers
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot.'/mod/lti/edit_form.php');
require_once($CFG->dirroot.'/mod/lti/locallib.php');
$action = optional_param('action', '', PARAM_ALPHANUMEXT);
$id = optional_param('id', '', PARAM_INT);
$tab = optional_param('tab', '', PARAM_ALPHAEXT);
// No guest autologin.
require_login(0, false);
require_sesskey();
// Check this is for a tool created from a tool proxy.
$err = empty($id);
if (!$err) {
$type = lti_get_type_type_config($id);
$err = empty($type->toolproxyid);
}
if ($err) {
$redirect = new moodle_url('/mod/lti/typessettings.php',
array('action' => $action, 'id' => $id, 'sesskey' => sesskey(), 'tab' => $tab));
redirect($redirect);
}
$pageurl = new moodle_url('/mod/lti/toolssettings.php');
if (!empty($id)) {
$pageurl->param('id', $id);
}
$PAGE->set_url($pageurl);
admin_externalpage_setup('managemodules'); // Hacky solution for printing the admin page.
$redirect = "$CFG->wwwroot/$CFG->admin/settings.php?section=modsettinglti&tab={$tab}";
if ($action == 'accept') {
lti_set_state_for_type($id, LTI_TOOL_STATE_CONFIGURED);
redirect($redirect);
} else if (($action == 'reject') || ($action == 'delete')) {
lti_set_state_for_type($id, LTI_TOOL_STATE_REJECTED);
redirect($redirect);
}
$form = new mod_lti_edit_types_form($pageurl, (object)array('isadmin' => true, 'istool' => true));
if ($data = $form->get_data()) {
$type = new stdClass();
if (!empty($id)) {
$type->id = $id;
lti_update_type($type, $data);
} else {
$type->state = LTI_TOOL_STATE_CONFIGURED;
lti_add_type($type, $data);
}
redirect($redirect);
} else if ($form->is_cancelled()) {
redirect($redirect);
}
$PAGE->set_title(format_string($SITE->shortname) . ': ' . get_string('toolsetup', 'lti'));
$PAGE->navbar->add(get_string('lti_administration', 'lti'), $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=modsettinglti');
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('toolsetup', 'lti'));
echo $OUTPUT->box_start('generalbox');
if ($action == 'update') {
$form->set_data($type);
}
$form->display();
echo $OUTPUT->box_end();
echo $OUTPUT->footer();

View File

@ -30,10 +30,11 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file contains the script used to clone Moodle admin setting page.
*
* It is used to create a new form used to pre-configure lti activities
*
* @package mod_lti
@ -56,21 +57,34 @@ $action = optional_param('action', null, PARAM_ALPHANUMEXT);
$id = optional_param('id', null, PARAM_INT);
$tab = optional_param('tab', '', PARAM_ALPHAEXT);
// no guest autologin
// No guest autologin.
require_login(0, false);
require_sesskey();
// Check this is not for a tool created from a tool proxy.
if (!empty($id)) {
$type = lti_get_type_type_config($id);
if (!empty($type->toolproxyid)) {
$sesskey = required_param('sesskey', PARAM_RAW);
$redirect = new moodle_url('/mod/lti/toolssettings.php',
array('action' => $action, 'id' => $id, 'sesskey' => $sesskey, 'tab' => $tab));
redirect($redirect);
}
} else {
$type = new stdClass();
}
$pageurl = new moodle_url('/mod/lti/typessettings.php');
if (!empty($id)) {
$pageurl->param('id', $id);
}
$PAGE->set_url($pageurl);
admin_externalpage_setup('managemodules'); // Hacky solution for printing the admin page
admin_externalpage_setup('managemodules'); // Hacky solution for printing the admin page.
$redirect = "$CFG->wwwroot/$CFG->admin/settings.php?section=modsettinglti&tab={$tab}";
require_sesskey();
if ($action == 'accept') {
lti_set_state_for_type($id, LTI_TOOL_STATE_CONFIGURED);
redirect($redirect);
@ -82,20 +96,17 @@ if ($action == 'accept') {
redirect($redirect);
}
$form = new mod_lti_edit_types_form($pageurl, (object)array('isadmin' => true));
$form = new mod_lti_edit_types_form($pageurl, (object)array('isadmin' => true, 'istool' => false));
if ($data = $form->get_data()) {
$type = new stdClass();
if (!empty($id)) {
$type->id = $id;
lti_update_type($type, $data);
redirect($redirect);
} else {
$type->state = LTI_TOOL_STATE_CONFIGURED;
lti_add_type($type, $data);
redirect($redirect);
@ -112,7 +123,6 @@ echo $OUTPUT->heading(get_string('toolsetup', 'lti'));
echo $OUTPUT->box_start('generalbox');
if ($action == 'update') {
$type = lti_get_type_type_config($id);
$form->set_data($type);
}

View File

@ -9,3 +9,8 @@ This files describes API changes in the lti code.
* mod_lti\event\unknown_service_api_called now has less data stored in 'other'
but everything is still available for event observers via method get_message_data()
=== 2.8 ===
* Support for LTI 2 added, including extensible services implemented as ltiservice plugins.
* Function sendOAuthBodyPOST removed from OAuthBody.php because it was not being used.

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file defines the version of lti
@ -48,7 +48,7 @@
defined('MOODLE_INTERNAL') || die;
$plugin->version = 2014060201; // The current module version (Date: YYYYMMDDXX)
$plugin->requires = 2014050800; // Requires this Moodle version
$plugin->component = 'mod_lti'; // Full name of the plugin (used for diagnostics)
$plugin->version = 2014100300; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2014050800; // Requires this Moodle version.
$plugin->component = 'mod_lti'; // Full name of the plugin (used for diagnostics).
$plugin->cron = 0;

View File

@ -30,7 +30,7 @@
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.
/**
* This file contains all necessary code to view a lti activity instance
@ -52,9 +52,9 @@ require_once($CFG->dirroot.'/mod/lti/lib.php');
require_once($CFG->dirroot.'/mod/lti/locallib.php');
$id = optional_param('id', 0, PARAM_INT); // Course Module ID, or
$l = optional_param('l', 0, PARAM_INT); // lti ID
$l = optional_param('l', 0, PARAM_INT); // lti ID.
if ($l) { // Two ways to specify the module
if ($l) { // Two ways to specify the module.
$lti = $DB->get_record('lti', array('id' => $l), '*', MUST_EXIST);
$cm = get_coursemodule_from_instance('lti', $lti->id, $lti->course, false, MUST_EXIST);
@ -72,21 +72,21 @@ if ($tool) {
$toolconfig = array();
}
$PAGE->set_cm($cm, $course); // set's up global $COURSE
$PAGE->set_cm($cm, $course); // Set's up global $COURSE.
$context = context_module::instance($cm->id);
$PAGE->set_context($context);
require_login($course, true, $cm);
require_capability('mod/lti:view', $context);
$url = new moodle_url('/mod/lti/view.php', array('id'=>$cm->id));
$url = new moodle_url('/mod/lti/view.php', array('id' => $cm->id));
$PAGE->set_url($url);
$launchcontainer = lti_get_launch_container($lti, $toolconfig);
if ($launchcontainer == LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS) {
$PAGE->set_pagelayout('frametop'); //Most frametops don't include footer, and pre-post blocks
$PAGE->blocks->show_only_fake_blocks(); //Disable blocks for layouts which do include pre-post blocks
$PAGE->set_pagelayout('frametop'); // Most frametops don't include footer, and pre-post blocks.
$PAGE->blocks->show_only_fake_blocks(); // Disable blocks for layouts which do include pre-post blocks.
} else if ($launchcontainer == LTI_LAUNCH_CONTAINER_REPLACE_MOODLE_WINDOW) {
redirect('launch.php?id=' . $cm->id);
} else {
@ -111,11 +111,11 @@ $pagetitle = strip_tags($course->shortname.': '.format_string($lti->name));
$PAGE->set_title($pagetitle);
$PAGE->set_heading($course->fullname);
// Print the page header
// Print the page header.
echo $OUTPUT->header();
if ($lti->showtitlelaunch) {
// Print the main part of the page
// Print the main part of the page.
echo $OUTPUT->heading(format_string($lti->name, true, array('context' => $context)));
}
@ -133,7 +133,7 @@ if ( $launchcontainer == LTI_LAUNCH_CONTAINER_WINDOW ) {
// Request the launch content with an iframe tag.
echo '<iframe id="contentframe" height="600px" width="100%" src="launch.php?id='.$cm->id.'"></iframe>';
// Output script to make the iframe be as large as possible.
// Output script to make the iframe tag be as large as possible.
$resize = '
<script type="text/javascript">
//<![CDATA[
@ -164,5 +164,5 @@ if ( $launchcontainer == LTI_LAUNCH_CONTAINER_WINDOW ) {
echo $resize;
}
// Finish the page
// Finish the page.
echo $OUTPUT->footer();