Overview
This PHP class encapsulates the code required by a Basic LTI-compliant tool provider to communicate with a tool consumer. It includes support for the proposed extensions to Basic LTI.
These classes are now replaced by the LTI Tool Provider classes.
System requirements
The Basic LTI Tool Provider class is written for PHP 5.2 (or higher) and MySQL 5.0 (or higher). Other versions may also work but have not been tested.
Installation
PHP source files
The download file available from OSCELOT (see Licence section below) includes the following files:
- BasicLTI_Tool_Provider.php
The following dependent PHP files are also required:
All the files should be located in the same directory.
MySQL database tables
The following database tables and relationships should be added to the application database:
consumer_guid VARCHAR(255) NOT NULL,
name VARCHAR(45) NOT NULL,
profile_url VARCHAR(255),
consumer_name VARCHAR(255),
consumer_version VARCHAR(255),
vendor_code VARCHAR(255),
css_path VARCHAR(255),
services TEXT,
capabilities TEXT,
enabled TINYINT(1) NOT NULL,
created DATETIME NOT NULL,
updated DATETIME NOT NULL,
PRIMARY KEY (consumer_guid)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS lti_consumer_instance (
consumer_instance_guid VARCHAR(255) NOT NULL,
consumer_guid VARCHAR(255) NOT NULL,
state VARCHAR(12) NOT NULL,
secret VARCHAR(32) NOT NULL,
created DATETIME NOT NULL,
updated DATETIME NOT NULL,
PRIMARY KEY (consumer_instance_guid)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS lti_context (
consumer_instance_guid VARCHAR(255) NOT NULL,
context_id VARCHAR(255) NOT NULL,
title VARCHAR(255) NOT NULL,
lti_context_id VARCHAR(255),
lti_resource_id VARCHAR(255),
settings TEXT,
primary_consumer_instance_guid VARCHAR(255),
primary_context_id VARCHAR(255),
share_approved TINYINT(1),
created DATETIME NOT NULL,
updated DATETIME NOT NULL,
PRIMARY KEY (consumer_instance_guid, context_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS lti_user (
consumer_instance_guid VARCHAR(255) NOT NULL,
context_id VARCHAR(255) NOT NULL,
user_id VARCHAR(255),
lti_result_sourcedid VARCHAR(255),
created DATETIME NOT NULL,
updated DATETIME NOT NULL,
PRIMARY KEY (consumer_instance_guid, context_id, user_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE lti_context_share_key (
share_key varchar(32) NOT NULL,
primary_consumer_instance_guid VARCHAR(255) NOT NULL,
primary_context_id VARCHAR(255) NOT NULL,
auto_approve TINYINT(1) NOT NULL,
expires INT(10) NOT NULL,
PRIMARY KEY (share_key)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS lti_nonce (
consumer_instance_guid VARCHAR(255) NOT NULL,
value VARCHAR(32) NOT NULL,
timestamp INT UNSIGNED NOT NULL,
PRIMARY KEY (consumer_instance_guid, value)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE lti_consumer_instance
ADD CONSTRAINT lti_consumer_consumer_instance_FK1 FOREIGN KEY (
consumer_guid)
REFERENCES lti_consumer (
consumer_guid);
ALTER TABLE lti_context
ADD CONSTRAINT lti_context_consumer_instance_FK1 FOREIGN KEY (
consumer_instance_guid)
REFERENCES lti_consumer_instance (
consumer_instance_guid);
ALTER TABLE lti_user
ADD CONSTRAINT lti_user_context_FK1 FOREIGN KEY (
consumer_instance_guid, context_id)
REFERENCES lti_context (
consumer_instance_guid, context_id);
ALTER TABLE lti_nonce
ADD CONSTRAINT lti_nonce_consumer_instance_FK1 FOREIGN KEY (
consumer_instance_guid)
REFERENCES lti_consumer_instance (
consumer_instance_guid);
An optional prefix may be added to the table names. For example, if a prefix of "MyApp_" is specified the expected table names would be MyApp_lti_consumer, MyApp_lti_consumer_instance and MyApp_lti_nonce.
Class definitions
The following classes are defined:
- BasicLTI_Tool_Provider
- LTI_Context
- LTI_Context_Share
- LTI_Outcome
- LTI_Tool_Consumer
- LTI_Tool_Consumer_Instance
- LTI_User
BasicLTI_Tool_Provider
This is the main working class which handles launches from LTI tool consumers.
Constructor
function __construct($callbackHandler, $dbTableNamePrefix = '', $autoEnable = FALSE)
where:
- $callbackHandler is the name of the callback method
- $dbTableNamePrefix (optional) is a prefix for the names of database tables
- $autoEnable (optional) will automatically enable the tool consumer when set to true
Method
- execute() - process a launch request from a tool consumer
Properties
- isOK - error status of the current request
- consumer - LTI_Consumer object for the current request
- consumer_instance - LTI_Consumer_Instance object for the current request
- return_url - URL to use when redirecting users back to the tool consumer
- user - LTI_User object for the current request
- context - LTI_Context object for the current request
- autoEnable - automatically enable the tool consumer when set to true (default = false)
- dbTableNamePrefix - prefix for the names of database tables
- defaultEmail - an email address to use when a user does not have one
- allowSharing - allow contexts to be shared when set to true (default = false)
- reason - reason for any error detected during launch
Constants
- CONNECTION_ERROR_MESSAGE - message returned to the tool consumer when a launch fails and debug mode is off
- CONSUMER_TABLE_NAME - name of consumer database table
- CONSUMER_INSTANCE_TABLE_NAME - name of consumer instance database table
- CONTEXT_TABLE_NAME - name of context database table
- CONTEXT_SHARE_KEY_TABLE_NAME - name of context share key database table
- NONCE_TABLE_NAME - name of nonce database table
- LTI_VERSION - version of LTI passed in service requests
- ID_SCOPE_ONLY - just use the user ID to identify users
- ID_SCOPE_GLOBAL - prefix user IDs with the consumer instance GUID
- ID_SCOPE_CONTEXT - prefix user IDs with the consumer instance GUID and the LTI context ID
- ID_SCOPE_RESOURCE - prefix user IDs with the consumer instance GUID and the LTI resource ID
- ID_SCOPE_SEPARATOR - string used to separate elements comprising a user ID
- MAX_SHARE_KEY_AGE - period after which a share key expires (in hours)
Examples
A minimal example:
$tool->execute();
(APP__DB_TABLE_PREFIX is assumed to be a constant which contains the prefix for the application's database table names this parameter may be omitted if the database tables do not have a prefix.)
The properties may be set separately:
$tool->dbTableNamePrefix = APP__DB_TABLE_PREFIX;
$tool->execute();
When an email address is required, it is possible to set a default value to use when the tool consumer does not provide one:
$tool->defaultEmail = 'no_email@domain.com';
$tool->execute();
To force a unique email address merely specify a domain as the default email address; the user ID will then be added as a prefix:
$tool->defaultEmail = '@domain.com';
$tool->execute();
When a launch fails a message is returned to the tool consumer ("Error connecting to LTI application"); this message can be changed at the top of the class file. If a custom parameter named debug (with any value) is included in the launch then a more precise reason for the failure is returned:
- Tool consumer instance has not been enabled by the tool provider.
- Invalid nonce.
- OAuth signature check failed - perhaps an incorrect secret.
- Your sharing request has been refused because sharing is not being permitted.
- An error occurred initialising your share arrangement.
- You have requested to share a context but none is available.
- It is not possible to share your context with yourself.
- You have requested to share a context but none is available.
- You have requested to share a context but none is available.
- Your share request is waiting to be approved.
- You have not requested to share a context but an arrangement is currently in place.
- Unable to load context being shared.
LTI_Tool_Consumer
This class defines the properties of a tool consumer. It is identified by the GUID agreed with the administrator of the tool consumer (typically the domain name).
Constructor
function __construct($guid = NULL, $dbTableNamePrefix = '', $autoEnable = FALSE)
where:
- $guid is an optional value which identifies the tool consumer, if specified the details are automatically loaded from the database
- $dbTableNamePrefix is an optional prefix to use for the names of the database tables
- $autoEnable (optional) will automatically enable the tool consumer when set to true
Methods
- save() - save the details of the tool consumer to the database (updating the record if it already exists)
- delete() - delete the details of the tool consumer from the database
Properties
- guid - the tool consumer ID
- name - the name of the tool consumer
- consumer_name - the name of the system being used as the tool consumer (e.g. "learn-9.1.70081", "webct-8.0.6" or "moodle-2")
- css_path - URL path to the CSS file
- enabled - true if connections are permitted from this tool consumer, false otherwise (which is the default)
- created - date and time when this tool consumer was created
- updated - date and time when the details of this tool consumer were last updated
The consumer_name and css_path properties are automatically populated by any values passed in the ext_lms and ext_launch_presentation_css_url parameters passed by a tool consumer which supports the Basic LTI extensions.
Example
(APP__DB_TABLE_PREFIX is assumed to be a constant which contains the prefix for the application's database table names.)
LTI_Tool_Consumer_Instance
This class defines the properties of an instance of a connection from a tool consumer. It is identified by the GUID supplied by the tool consumer (typically the domain name and the same as the tool consumer GUID).
Constructor
function __construct($guid = NULL, $dbTableNamePrefix = '')
where:
- $guid is an optional value which identifies the tool consumer instance, if specified the details are automatically loaded from the database
- $dbTableNamePrefix is an optional prefix to use for the names of the database tables
Methods
- save() - save the details of the tool consumer instance to the database (updating the record if it already exists)
- delete($deleteConsumer = false) - delete the details of the tool consumer instance from the database and optionally try to delete the tool consumer to which it belonged
- isEnabled() - true if the tool consumer to which this instance is related is set to permit connections, false otherwise
- updateState($state) - update the state to the passed value
- saveNonce($nonce) - save a nonce value (return false if it already exists)
- getRandomString($length = 8) - generate a random string of the specified length
Properties
- guid - the tool consumer instance ID
- consumer_guid - the related tool consumer ID
- state - the current state of the tool consumer instance (set to the LTI version during a launch)
- secret - the shared secret used to secure connections with the tool consumer
- id_scope - the default scope of user ID (default is user ID only)
- defaultEmail - an email address to use when a user does not have one
- created - date and time when this tool consumer was created
- updated - date and time when the details of this tool consumer were last updated
Examples
To create an existing instance of a tool consumer pass the GUID as the second parameter:
(APP__DB_TABLE_PREFIX is assumed to be a constant which contains the prefix for the application's database table names.)
LTI_User
This class is created when a connection is made and defines the user requesting the current action. If the fullname of the user is not provided by the tool consumer, this property will be set to the firstname and lastname separated by a space. If the fullname is provided by the tool consumer but not the firstname and/or lastname, the fullname is split at the first space to provide values for the missing firstname and lastname properties.
Constructor
function __construct(&$context, $id)
where:
- $context is the context with which the user is associated
- $id is the user ID
Methods
- getId($id_scope = NULL) - returns a user ID based on a scope level
- isAdmin() - returns true if the user has an administrator role, false otherwise
- isStaff() - returns true if the user has a staff role (instructor, content developer or teaching assistant, false otherwise
- isLearner() - returns true if the user has a learner role, false otherwise
Properties
- id - user's ID
- firstname - user's firstname
- lastname - user's lastname
- fullname - user's full name
- email - user's email address
- roles - an array of roles associated with the user
- lti_result_sourcedid - user's result sourcedid if provided by the tool consumer
- created - date and time when this user was created
- updated - date and time when the details of this user were last updated
LTI_Context
This class is created when a connection is made and defines the context from which the current request has been sent; typically this will be a course.
Constructor
function __construct(&$consumer_instance, $id)
where:
- $consumer_instance is the consumer instance with which the context is associated
- $id is the id of the context
Properties
- id - context id
- lti_context_id - context id provided by the tool consumer
- lti_resource_id - resource link id provided by the tool consumer
- title - context title
- ext_response - the XML response from the last extension request to the tool consumer
- primary_consumer_instance_id - consumer instance ID of context being shared
- primary_context_id - id of context being shared
- approved - sharing arrangement enabled when set to true
- created - date and time when this context was created
- updated - date and time when the details of this context were last updated
Methods
- save() - save the details of the context to the database (updating the record if it already exists)
- delete() - remove the details of the context from the database
- getSetting($name, $default = '') - get the value of a setting (or the default value if the setting is not defined)
- setSetting($name, $value = NULL) - save the value of a setting (pass a null or empty value to delete a setting)
- getSettings() - get an array of setting values
- saveSettings() - save the settings values
- hasOutcomesService() - true if the Outcomes service is supported (see below)
- hasMembershipsService() - true if the Memberships service is supported (see below)
- hasSettingService() - true if the Setting service is supported (see below)
- doOutcomesService($action, $lti_outcome) - make a request to the Outcomes service (see below)
- doMembershipsService() - make a request to the Memberships service (see below)
- getUserResultSourcedIDs($context_only = FALSE, $id_scope = NULL) - returns an array of LTI_User objects with the result sourcedid for each user (note that the name, email and roles properties are not populated); when $context_only is FALSE the array will include any users enrolled from other contexts, when a value is passed for $id_scope the array will be indexed by the user ID
- doSettingService($action, $value = NULL) - make a request to the Setting service (see below)
- getNewShareKey($life, $auto_approve = FALSE, $length = NULL) - create a new share key with a life in hours
- getShares() - return an array of LTI_Context_Share objects, one for each existing share arrangements for this context
- doApproveShare($consumer_instance_guid, $context_id, $approve) - change the approval status of a share with this context
- doCancelShare($consumer_instance_guid, $context_id) - cancel a share with this context
Constants
- EXT_READ - read/load action for requests to tool consumers
- EXT_WRITE - save/update action for requests to tool consumers
- EXT_DELETE - delete action for requests to tool consumers
- MAX_SHARE_KEY_LENGTH - maximum permitted length for a share key
Extension services
The following settings are saved when a launch request is executed by the BasicLTI_Tool_Provider class:
- ext_resource_link_content
- ext_resource_link_content_signature
- lis_result_sourcedid
- ext_ims_lis_basic_outcome_url
- ext_ims_lis_resultvalue_sourcedids
- ext_ims_lis_memberships_id
- ext_ims_lis_memberships_url
- ext_ims_lti_tool_setting
- ext_ims_lti_tool_setting_id
- ext_ims_lti_tool_setting_url
The getSetting, setSetting and saveSettings methods may also be used with user-defined setting values.
Methods are provided to support the following Basic LTI extension requests:
- Outcomes
- Memberships
- Setting
Outcomes service
Use the doOutcomesService($action, $lti_outcome) method, where:
- $action - is one of the class constants identifying the type of action to perform
- $lti_outcome - an LTI_Outcome object (see below)
The method will return one of the following values:
- FALSE if an error occurs
- the value of the outcome (for read actions)
- TRUE if the request is successful (for update and delete actions)
Memberships service
Use the doMembershipsService() method.
The method will return one of the following values:
- FALSE if an error occurs
- an array of LTI_User objects for each member
If the memberships service is not supported by the tool consumer, the array returned will only be populated with the following properties of the LTI_User object for those users who have already connected to the tool provider with a result sourcedid:
- context
- id
- lti_result_sourcedid
- created
- updated
The name, email and roles properties should already be known by the tool provider anyway.
Setting service
Use the doSettingService($action, $value = NULL) method, where:
- $action - is one of the class constants identifying the type of action to perform
- $value - the value to be saved (omit this parameter for load and delete actions)
The method will return one of the following values:
- FALSE if an error occurs
- the value of the setting (for read actions)
- TRUE if the request is successful (for save and delete actions)
Note that the setting value may also be obtained from the settings of the LTI_Context (use thegetSetting('ext_ims_lti_tool_setting') call). This value is automatically updated whenever a new setting is saved.
LTI_Outcome
This class is used by the Outcomes service to represent an outcome (typically a grade) which is saved in, and retrieved from, the grade book in the tool consumer.
Constructor
function __construct($sourcedid, $value = NULL)
where:
- $sourcedid is the sourcedid of the user and context
- $value is the value of the outcome (only used by update actions)
Methods
- getSourcedid() - returns the sourcedid
- getValue() - returns the outcome value
- setValue() - sets the outcome value
Properties
- language - the language of the outcome value
- status - the status of the outcome (interim, final, unmoderated or moderated)
- date - the date/time of the outcome (defaults to the current time)
- type - the data type of the outcome (decimal, percentage, ratio, letteraf, letterafplus, passfail or freetext)
- data_source - the tool provider's sourcedid of the outcome
All the properties are optional.
Example
To save a final outcome of 58%:
$outcome->type = 'percentage';
$outcome->status = 'final';
$tool->consumer_instance->doOutcomesService(LTI_Context::EXT_WRITE, $outcome);
where:
- $sourcedid - is the sourcedid of a user and context as provided by the tool consumer
- $tool - is an instance of the BasicLTI_Tool_Provider class
LTI_Context_Share
This class is used by the Context class to represent a share arrangement with another context.
Constructor
function __construct()
Properties
- consumer_instance_guid - the consumer instance GUID of the shared context
- context_id - the ID of the shared context
- title - the title of the shared context
- approved - the share arrangement is active if set to true
Usage
A quick way to see how LTI can be used to integrate an external tool with a learning environment is to watch the following
screencast showing how it is being used with WebPA, a peer assessment tool. Note that, whilst this uses Blackboard Learn 9 as the
learning environment, the same integration is possible with any other which provides support for the unofficial extensions,
this includes WebCT, Moodle, Sakai.
View video illustration - An instructor's view of LTI (10:46 minutes)
Having a learning application hosted outside the learning environment also introduces opportunities for users coming from different
contexts to share the same working area within the external tool. This is illustrated by the following screencast which shows
how students from different contexts (which could be from different learning environments and/or different institutions) can be
joined together to work on the same peer assessment exercise.
View video illustration - Using LTI to allow student collaboration (6:13 minutes)
Callback functions
A callback function is associated with the launch action according to the value passed to the constructor of the BasicLTI_Tool_Provider object. The return value of the callback functions may be one of the following:
- a boolean value representing success or failure of the request
- a string starting with 'http://' or 'https://' representing the URL to redirect a user to
- a string containing the text to be returned to the tool consumer (unless a return URL was specified in the request in which case a user is redirected to this URL)
When a user is redirected from the tool consumer to the tool provider, the callback function may be used to:
- create the user account if it does not already exist (or update it if it does);
- create the context if it does not already exist (or update it if it does);
- set up a new session for the user (or otherwise log the user into the tool provider application)
- keep a record of the return URL for the tool consumer (for example, as a session variable)
- return the URL for the home page of the application so the user may be redirected to it (or false if the connection request is not accepted)
require_once('include/classes/lti/BasicLTI_Tool_Provider.php');
...
$tool = new BasicLTI_Tool_Provider('doConnect');
$tool->execute();
...
function doConnect($tool_provider) {
// Insert code here to handle incoming connections - use the user
// and context properties of the $tool_provider parameter
// to access the current user and context.
...
return 'https://www.tool.provider.com/index.php';
}
Version history
Version | Date | Description |
---|---|---|
1.0.00 | 25 September 2011 | First public release |
1.0.01 | 17 October 2011 | Bug fix for problem with setting consumer property for BasicLTI_Tool_Provider class |
1.0.02 | 21 October 2011 |
Bug fix when passing an array of callback methods to BasicLTI_Tool_Provider class Changed definition of profile_url field in lti_consumer table to allow NULLs |
1.1.00 | 15 February 2012 |
Changed default values of LTI_Context (ID and title) Reversed order of parameters in constructor for LTI_Tool_Consumer_Instance class Changed dbTableNamePrefix properties to public in LTI_Tool_Consumer and LTI_Tool_Consumer_Instance classes Added lti_context database table Moved settings and extension services to LTI_Context class (and from LTI_Tool_Consumer table to lti_context table) Changed doMembershipsService() to return an array of LTI_User objects EXT_WRITE option for doSettingService now also updates the locally saved setting value Added setValue() method to LTI_Outcome class and made value parameter optional for the constructor Set state property of LTI_Tool_Consumer_Instance to the LTI version passed from the tool consumer Added defaultEmail property to BasicLTI_Tool_Provider class Added debug mode for reporting launch errors Added option for sharing a context with users from other contexts LTI_Context::return_url property moved to BasicLTI_Tool_Provider class Returns reason for launch failure as lti_errorlog parameter Added context to LTI_User class Added debugMode option to launch requests Added LTI_User::getId() method Save custom settings with LTI settings for each context Fixed problem with apostrophes in data Added lti_user table to record result sourcedid values so they are available for setting grades via the new getUserResultSourcedIDs() method of the LTI_Context object Added support for LTI 1.1 |
1.1.01 | 29 April 2012 |
Updated setting of consumer values passed on launch Improved error checking Removed redundant clearOldNonces() method from LTI_Consumer_Instance class Fixed issue with reading outcomes when both LTI 1.1 and extension services are supported Added workaround to PHP bug with sending HTTP headers from some servers (affecting LTI 1.1 Outcome service requests) |
Licence
This work is written by Stephen Vickers and is released under a Creative Commons GNU General Public Licence. The Basic LTI Tool Provider PHP class is available for download from OSCELOT where it is also possible to report bugs and submit feature requests.