-
Notifications
You must be signed in to change notification settings - Fork 38
Installation
Add the following entry to the require element of the composer.json
file for your web application:
"require" : {
"celtic/lti": "^3.1.0"
},
In a command-line interface, change directory to the root of your web application and run the following command:
composer install
Then, add the following to your PHP script:
require_once('vendor/autoload.php');
To install the library, clone the src
directory from the repository into your desired application directory (for example, .../vendor/ceLTIc/LTI/src
). The class files can be automatically loaded into your web application by loading a file like the following:
<?php
/**
* Autoload a class file.
*
* @param string $class The fully-qualified class name.
*/
spl_autoload_register(function ($class) {
// Base directory for the class files
$base_dir = __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR;
// Replace the namespace prefix with the base directory, replace namespace
// separators with directory separators in the relative class name, append
// with .php
$file = $base_dir . preg_replace('/[\\\\\/]/', DIRECTORY_SEPARATOR, $class) . '.php';
// Update location if class requested is from the LTI class library
$file = str_replace(DIRECTORY_SEPARATOR . 'ceLTIc' . DIRECTORY_SEPARATOR . 'LTI' . DIRECTORY_SEPARATOR,
DIRECTORY_SEPARATOR . 'ceLTIc' . DIRECTORY_SEPARATOR . 'LTI' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR, $file);
// If the file exists, require it
if (file_exists($file)) {
require($file);
}
});
?>
Just change the value of the $base_dir
variable to wherever you located the library files.
The library uses a set of database files to record LTI-related data, including the keys and secrets issued to tool consumers. The DDL for creating these tables is given below. The library supports adding a prefix to the table names so that, for example, you may wish to change lti2_consumer
to something like app1_lti2_consumer
. If you want to change the name of the table itself, make sure you update the constants in the DataConnector class file. You may also adapt this structure to integrate it with your own application tables - just create your own subclass of the DataConnector class to implement the SQL to access the required objects from wherever they exist in your database.
The library supports the following databases as standard; follow the link for an SQL script to create the tables:
The MySQL script is shown here as an example.
CREATE TABLE lti2_consumer (
consumer_pk int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) NOT NULL,
consumer_key256 varchar(256) NOT NULL,
consumer_key text DEFAULT NULL,
secret varchar(1024) NOT NULL,
lti_version varchar(10) DEFAULT NULL,
signature_method varchar(15) NOT NULL DEFAULT 'HMAC-SHA1',
consumer_name varchar(255) DEFAULT NULL,
consumer_version varchar(255) DEFAULT NULL,
consumer_guid varchar(1024) DEFAULT NULL,
profile text DEFAULT NULL,
tool_proxy text DEFAULT NULL,
settings text DEFAULT NULL,
protected tinyint(1) NOT NULL,
enabled tinyint(1) NOT NULL,
enable_from datetime DEFAULT NULL,
enable_until datetime DEFAULT NULL,
last_access date DEFAULT NULL,
created datetime NOT NULL,
updated datetime NOT NULL,
PRIMARY KEY (consumer_pk)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE lti2_consumer
ADD UNIQUE INDEX lti2_consumer_consumer_key_UNIQUE (consumer_key256 ASC);
CREATE TABLE lti2_nonce (
consumer_pk int(11) NOT NULL,
value varchar(50) NOT NULL,
expires datetime NOT NULL,
PRIMARY KEY (consumer_pk, value)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE lti2_nonce
ADD CONSTRAINT lti2_nonce_lti2_consumer_FK1 FOREIGN KEY (consumer_pk)
REFERENCES lti2_consumer (consumer_pk);
CREATE TABLE lti2_context (
context_pk int(11) NOT NULL AUTO_INCREMENT,
consumer_pk int(11) NOT NULL,
title varchar(255) DEFAULT NULL,
lti_context_id varchar(255) NOT NULL,
type varchar(50) DEFAULT NULL,
settings text DEFAULT NULL,
created datetime NOT NULL,
updated datetime NOT NULL,
PRIMARY KEY (context_pk)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE lti2_context
ADD CONSTRAINT lti2_context_lti2_consumer_FK1 FOREIGN KEY (consumer_pk)
REFERENCES lti2_consumer (consumer_pk);
ALTER TABLE lti2_context
ADD INDEX lti2_context_consumer_id_IDX (consumer_pk ASC);
CREATE TABLE lti2_resource_link (
resource_link_pk int(11) AUTO_INCREMENT,
context_pk int(11) DEFAULT NULL,
consumer_pk int(11) DEFAULT NULL,
title varchar(255) DEFAULT NULL,
lti_resource_link_id varchar(255) NOT NULL,
settings text,
primary_resource_link_pk int(11) DEFAULT NULL,
share_approved tinyint(1) DEFAULT NULL,
created datetime NOT NULL,
updated datetime NOT NULL,
PRIMARY KEY (resource_link_pk)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE lti2_resource_link
ADD CONSTRAINT lti2_resource_link_lti2_consumer_FK1 FOREIGN KEY (consumer_pk)
REFERENCES lti2_consumer (consumer_pk);
ALTER TABLE lti2_resource_link
ADD CONSTRAINT lti2_resource_link_lti2_context_FK1 FOREIGN KEY (context_pk)
REFERENCES lti2_context (context_pk);
ALTER TABLE lti2_resource_link
ADD CONSTRAINT lti2_resource_link_lti2_resource_link_FK1 FOREIGN KEY (primary_resource_link_pk)
REFERENCES lti2_resource_link (resource_link_pk);
ALTER TABLE lti2_resource_link
ADD INDEX lti2_resource_link_consumer_pk_IDX (consumer_pk ASC);
ALTER TABLE lti2_resource_link
ADD INDEX lti2_resource_link_context_pk_IDX (context_pk ASC);
CREATE TABLE lti2_user_result (
user_result_pk int(11) AUTO_INCREMENT,
resource_link_pk int(11) NOT NULL,
lti_user_id varchar(255) NOT NULL,
lti_result_sourcedid varchar(1024) NOT NULL,
created datetime NOT NULL,
updated datetime NOT NULL,
PRIMARY KEY (user_result_pk)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE lti2_user_result
ADD CONSTRAINT lti2_user_result_lti2_resource_link_FK1 FOREIGN KEY (resource_link_pk)
REFERENCES lti2_resource_link (resource_link_pk);
ALTER TABLE lti2_user_result
ADD INDEX lti2_user_result_resource_link_pk_IDX (resource_link_pk ASC);
CREATE TABLE lti2_share_key (
share_key_id varchar(32) NOT NULL,
resource_link_pk int(11) NOT NULL,
auto_approve tinyint(1) NOT NULL,
expires datetime NOT NULL,
PRIMARY KEY (share_key_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE lti2_share_key
ADD CONSTRAINT lti2_share_key_lti2_resource_link_FK1 FOREIGN KEY (resource_link_pk)
REFERENCES lti2_resource_link (resource_link_pk);
ALTER TABLE lti2_share_key
ADD INDEX lti2_share_key_resource_link_pk_IDX (resource_link_pk ASC);
Updating to this release of the LTI class library from previous related versions may require alterations to the PHP source files and to the database structure.
Review the Usage
section of this site and the code documentation for examples of how to reference and access the LTI classes. A sample tool provider named Rating
is also available to illustrate the use of the library.
Create new database tables (see above) and use the following migration script (modify for databases other than MySQL) to copy the data from the old tables. Once complete and tested the old LTI tables can be deleted. (Remember to add a table name prefix to the script if one is being used.)
SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE TABLE lti2_user_result;
TRUNCATE TABLE lti2_share_key;
TRUNCATE TABLE lti2_resource_link;
TRUNCATE TABLE lti2_context;
TRUNCATE TABLE lti2_nonce;
TRUNCATE TABLE lti2_consumer;
SET FOREIGN_KEY_CHECKS = 1;
-- Consumers
INSERT INTO lti2_consumer (name, consumer_key256, consumer_key, secret, lti_version,
signature_method, consumer_name, consumer_version, consumer_guid, profile, tool_proxy,
settings, protected, enabled, enable_from, enable_until, last_access, created, updated)
SELECT name, consumer_key, NULL, secret, lti_version,
'HMAC-SHA1', consumer_name, consumer_version, consumer_guid, NULL, NULL,
NULL, protected, enabled, enable_from, enable_until, last_access, created, updated
FROM lti_consumer;
-- Nonces
INSERT INTO lti2_nonce (consumer_pk, value, expires)
SELECT c.consumer_pk, n.value, n.expires
FROM lti_nonce n INNER JOIN lti2_consumer c ON n.consumer_key = c.consumer_key256;
-- Contexts
INSERT INTO lti2_context (consumer_pk, title, lti_context_id, type, settings, created, updated)
SELECT c.consumer_pk, IF(INSTR(x.title, ':') > 0, SUBSTRING(x.title, 1, INSTR(x.title, ':') - 1), ''), x.lti_context_id, NULL, NULL, x.created, x.updated
FROM lti_context x INNER JOIN lti2_consumer c ON x.consumer_key = c.consumer_key256
WHERE x.lti_context_id IS NOT NULL
GROUP BY c.consumer_pk, x.lti_context_id;
-- Resource links without contexts
INSERT INTO lti2_resource_link (context_pk, consumer_pk, title, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated)
SELECT x.context_pk, c.consumer_pk, r.title, r.lti_resource_id, r.settings, NULL, NULL, r.created, r.updated
FROM lti_context r INNER JOIN lti2_consumer c ON r.consumer_key = c.consumer_key256
LEFT OUTER JOIN lti2_context x ON x.lti_context_id = r.lti_context_id
WHERE r.lti_context_id IS NULL;
-- Resource links for contexts
INSERT INTO lti2_resource_link (context_pk, consumer_pk, title, lti_resource_link_id, settings, primary_resource_link_pk, share_approved, created, updated)
SELECT x.context_pk, NULL, IF(INSTR(r.title, ':') > 0, TRIM(SUBSTRING(r.title, INSTR(r.title, ':') + 1)), r.title), r.lti_resource_id, r.settings, NULL, NULL, r.created, r.updated
FROM lti_context r INNER JOIN lti2_consumer c ON r.consumer_key = c.consumer_key256
INNER JOIN lti2_context x ON x.lti_context_id = r.lti_context_id
GROUP BY c.consumer_pk, r.context_id, r.lti_context_id;
-- Update resource link shares
UPDATE lti2_resource_link r
INNER JOIN lti_context x ON (x.context_id = r.lti_resource_link_id)
INNER JOIN lti2_consumer c ON c.consumer_key256 = x.consumer_key
INNER JOIN lti2_resource_link r2 ON (x.primary_context_id = r2.lti_resource_link_id)
INNER JOIN lti2_consumer c2 ON c2.consumer_pk = r2.consumer_pk
SET r.primary_resource_link_pk = r2.resource_link_pk, r.share_approved = x.share_approved;
-- Share keys
INSERT INTO lti2_share_key (share_key_id, resource_link_pk, auto_approve, expires)
SELECT s.share_key_id, r.resource_link_pk, s.auto_approve, s.expires
FROM lti_share_key s INNER JOIN lti2_resource_link r ON s.primary_context_id = r.lti_resource_link_id
INNER JOIN lti2_consumer c ON r.consumer_pk = c.consumer_pk
WHERE c.consumer_key256 = s.primary_consumer_key;
-- User results
INSERT INTO lti2_user_result (resource_link_pk, lti_user_id, lti_result_sourcedid, created, updated)
SELECT r.resource_link_pk, u.user_id, u.lti_result_sourcedid, u.created, u.updated
FROM lti_user u INNER JOIN lti2_resource_link r ON u.context_id = r.lti_resource_link_id
INNER JOIN lti2_consumer c ON r.consumer_pk = c.consumer_pk
WHERE c.consumer_key256 = u.consumer_key;
- Change all
IMSGlobal/LTI/ToolProvider
namespace references toceLTIc/LTI
. - Reverse the order of the
$dbTableNamePrefix
and$db
parameters in calls to thegetDataConnector
method.
-
lti2_consumer
table: add fieldsignature_method varchar(15) NOT NULL DEFAULT 'HMAC-SHA1'
- drop
lti2_tool_proxy
table -
lti2_nonce
table: change size ofvalue
field to50
-
lti2_context
table: add fieldstitle varchar(255) DEFAULT NULL
andtype varchar(50) DEFAULT NULL
-
lti2_resource_link
table: add fieldtitle varchar(255) DEFAULT NULL
© 2022 Stephen P Vickers. All Rights Reserved.