diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..aa9a047
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,15 @@
+# This file is for unifying the coding style for different editors and IDEs
+# editorconfig.org
+
+# PHP PSR-2 Coding Standards
+# http://www.php-fig.org/psr/psr-2/
+
+root = true
+
+[*.php]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = space
+indent_size = 4
diff --git a/.gitignore b/.gitignore
index 841356e..9f87aac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
# authentication credentials
.htpasswd
-secrets.xml
+config.xml
# dynamically-loaded and/or caches
/logs/*.log
@@ -10,6 +10,3 @@ secrets.xml
/smarty/templates_c/*
!/smarty/templates_c/README.md
/admin/.htaccess
-
-# file system
-.DS_*
diff --git a/.htaccess b/.htaccess
index d890306..ca5afec 100644
--- a/.htaccess
+++ b/.htaccess
@@ -1,21 +1,9 @@
-# block access to all Apache config files
-users.csv
is ready and download should start automatically in a few seconds. Click the link below if the download does not start automatically.',
+ NotificationMessage::GOOD
+ );
+ } catch (Exception $e) {
+ $toolbox->smarty_addMessage('Error ' . $e->getCode(), $e->getMessage(), NotificationMessage::ERROR);
}
- $smarty->assign('csv', basename(__FILE__, '.php') . "/$account/users");
- $smarty->assign('filename', date('Y-m-d_H-i-s') . "_account-{$account}_observers");
- $smarty->addMessage(
- 'Ready for Download',
- 'users.csv
is ready and download should start automatically in a few seconds. Click the link below if the download does not start automatically.',
- NotificationMessage::GOOD
- );
- } catch (Exception $e) {
- $smarty->addMessage('Error ' . $e->getCode(), $e->getMessage(), NotificationMessage::ERROR);
- }
-
- /* flows into STEP_INSTRUCTIONS */
-
- case STEP_INSTRUCTIONS:
- default:
- $smarty->assign('formHidden', array('step' => STEP_CSV, 'account' => $_SESSION['accountId']));
- $smarty->display(basename(__FILE__, '.php') . '/instructions.tpl');
-}
-
-?>
\ No newline at end of file
+
+ /* flows into STEP_INSTRUCTIONS */
+
+ case STEP_INSTRUCTIONS:
+ default:
+ $toolbox->smarty_assign('formHidden', [
+ 'step' => STEP_CSV,
+ 'account' => $_SESSION[ACCOUNT_ID]
+ ]);
+ $toolbox->smarty_display(basename(__FILE__, '.php') . '/instructions.tpl');
+ }
+} $toolbox->cache_popKey();
diff --git a/account/index.php b/account/index.php
index c802dda..006a071 100644
--- a/account/index.php
+++ b/account/index.php
@@ -1,7 +1,4 @@
display('subpage.tpl');
-
-?>
\ No newline at end of file
+header('Location: create-advisor-observers.php');
+exit;
diff --git a/account/rename-advisory-groups.php b/account/rename-advisory-groups.php
index be18dc4..a9695b4 100644
--- a/account/rename-advisory-groups.php
+++ b/account/rename-advisory-groups.php
@@ -2,50 +2,40 @@
require_once('common.inc.php');
+use Battis\BootstrapSmarty\NotificationMessage;
+
define('STEP_INSTRUCTIONS', 1);
define('STEP_RENAME', 2);
$step = (empty($_REQUEST['step']) ? STEP_INSTRUCTIONS : $_REQUEST['step']);
switch ($step) {
-
+
case STEP_RENAME:
try {
$updated = 0;
$unchanged = 0;
- $courses = $api->get(
- "accounts/{$_REQUEST['account']}/courses",
- array(
- 'enrollment_term_id' => $_REQUEST['term'],
- 'with_enrollments' => 'true'
- )
- );
+ $courses = $toolbox->api_get("accounts/{$_REQUEST['account']}/courses", [
+ 'enrollment_term_id' => $_REQUEST['term'],
+ 'with_enrollments' => 'true'
+ ]);
foreach ($courses as $course) {
- $teachers = $api->get(
- "/courses/{$course['id']}/enrollments",
- array(
- 'type' => 'TeacherEnrollment'
- )
- );
+ $teachers = $toolbox->api_get("/courses/{$course['id']}/enrollments", [
+ 'type' => 'TeacherEnrollment'
+ ]);
if ($teacher = $teachers[0]['user']) {
$nameParts = explode(',', $teacher['sortable_name']);
$courseName = trim($nameParts[0]) . ' Advisory Group';
- $api->put(
- "courses/{$course['id']}",
- array(
- 'course[name]' => $courseName,
- 'course[course_code]' => $courseName
- )
- );
- $sections = $api->get("courses/{$course['id']}/sections");
+ $toolbox->api_put("courses/{$course['id']}", [
+ 'course[name]' => $courseName,
+ 'course[course_code]' => $courseName
+ ]);
+ $sections = $toolbox->api_get("courses/{$course['id']}/sections");
foreach($sections as $section) {
if ($section['name'] == $course['name']) {
- $api->put(
- "sections/{$sections[0]['id']}",
- array(
- 'course_section[name]' => $courseName
- )
- );
+ $toolbox->api_put("sections/{$sections[0]['id']}", [
+ 'course_section[name]' => $courseName
+ ]);
}
}
$updated++;
@@ -54,34 +44,28 @@
}
}
} catch (Exception $e) {
- exceptionErrorMessage($e);
+ $toolbox->smarty_addMessage('Error ' . $e->getCode(), $e->getMessage(), NotificationMessage::ERROR);
}
- $courses = $api->get(
- "accounts/{$_REQUEST['account']}/courses",
- array(
- 'enrollment_term_id' => $_REQUEST['term'],
- 'with_enrollments' => 'true',
- 'published' => 'true'
- )
- );
-
- $smarty->addMessage(
+ $courses = $toolbox->api_get("accounts/{$_REQUEST['account']}/courses", [
+ 'enrollment_term_id' => $_REQUEST['term'],
+ 'with_enrollments' => 'true',
+ 'published' => 'true'
+ ]);
+
+ $toolbox->smarty_addMessage(
'Renamed advisory courses',
"$updated courses were renamed, and $unchanged were left unchanged.",
NotificationMessage::GOOD
);
-
+
case STEP_INSTRUCTIONS:
default:
- $smarty->assign('terms', getTermList());
- $smarty->assign(
- 'formHidden',
- array(
+ $toolbox->smarty_assign([
+ 'terms' => $toolbox->getTermList(),
+ 'formHidden' => [
'step' => STEP_RENAME,
'account' => $_SESSION['accountId']
- )
- );
- $smarty->display(basename(__FILE__, '.php') . '/instructions.tpl');
+ ]
+ ]);
+ $toolbox->smarty_display(basename(__FILE__, '.php') . '/instructions.tpl');
}
-
-?>
\ No newline at end of file
diff --git a/admin/README.md b/admin/README.md
deleted file mode 100644
index aa1aefe..0000000
--- a/admin/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# admin/
-
-Administrative interface for the service that backs the LTI Tool Provider (TP).
\ No newline at end of file
diff --git a/admin/common.inc.php b/admin/common.inc.php
index cea323c..06ac97e 100644
--- a/admin/common.inc.php
+++ b/admin/common.inc.php
@@ -1,7 +1,7 @@
assign('category', 'Admin Panel');
+require_once __DIR__ . '/../common.inc.php';
-?>
\ No newline at end of file
+use Battis\DataUtilities;
+
+$toolbox->smarty_assign('category', DataUtilities::titleCase(basename(__DIR__)));
diff --git a/admin/consumers-control-panel.php b/admin/consumers-control-panel.php
new file mode 100644
index 0000000..826e84c
--- /dev/null
+++ b/admin/consumers-control-panel.php
@@ -0,0 +1,79 @@
+getMySQL()),
+ true // wicked confusing _not_ to autoenable
+ );
+
+ /* pre-fill secret if not editing an existing consumer */
+ if (empty($key)) {
+ $consumer->secret = LTI_Data_Connector::getRandomString(32);
+ }
+
+ return $consumer;
+}
+
+/* load requested consumer (or create new if none requested) */
+$consumer = createConsumer($toolbox, $key);
+
+/* what are we asked to do with this consumer? */
+switch ($action) {
+ case 'update':
+ case 'insert': {
+ $consumer->name = $name;
+ $consumer->secret = $secret;
+ $consumer->enabled = $enabled;
+ if (!$consumer->save()) {
+ $toolbox->smarty_addMessage(
+ 'Error saving consumer',
+ 'There was an error attempting to save your new or updated consumer information to the database.',
+ NotificationMessage::ERROR
+ );
+ }
+ break;
+ }
+ case 'delete': {
+ $consumer->delete();
+ break;
+ }
+ case 'select': {
+ $toolbox->smarty_assign('key', $key);
+ break;
+ }
+}
+
+/*
+ * if action was anything other than 'select', create a new empty consumer to
+ * fill the form with
+ */
+if ($action && $action !== 'select') {
+ $consumer = createConsumer($toolbox);
+}
+
+/* display a list of consumers */
+$consumers = $toolbox->lti_getConsumers();
+$toolbox->smarty_assign([
+ 'consumers' => $consumers,
+ 'consumer' => $consumer,
+ 'formAction' => $_SERVER['PHP_SELF'],
+ 'appUrl' => $toolbox->config('APP_URL')
+]);
+$toolbox->smarty_display(basename(__FILE__, '.php') . '.tpl');
diff --git a/admin/consumers.php b/admin/consumers.php
deleted file mode 100644
index 1d092a8..0000000
--- a/admin/consumers.php
+++ /dev/null
@@ -1,91 +0,0 @@
-name = $_name;
- $consumer->secret = $_REQUEST['secret'];
- $consumer->enabled = isset($_REQUEST['enabled']);
- if (!$consumer->save()) {
- $valid = false;
- $message = "Consumer could not be saved. {$sql->error}";
- }
- }
-
- if (!$valid) {
- $smarty->addMessage(
- 'Required information missing',
- $message,
- NotificationMessage::ERROR
- );
- }
-
-/* look up consumer to edit, if requested */
-} elseif (isset($_REQUEST['consumer_key'])) {
- $consumer = new LTI_Tool_Consumer($_REQUEST['consumer_key'], LTI_Data_Connector::getDataConnector($sql));
- if (isset($_REQUEST['action']))
- switch ($_REQUEST['action']) {
- case 'delete': {
- $consumer->delete();
- break;
- }
- case 'select': {
- $name = $consumer->name;
- $key = $consumer->getKey();
- $secret = $consumer->secret;
- $enabled = $consumer->enabled;
- break;
- }
- case 'update':
- case 'insert':
- default: {
- // leave default form values set
- }
- }
-}
-
-/* display a list of consumers */
-$response = $sql->query("SELECT * FROM `" . LTI_Data_Connector::CONSUMER_TABLE_NAME . "` ORDER BY `name` ASC, `consumer_key` ASC");
-$consumers = array();
-while ($consumer = $response->fetch_assoc()) {
- $consumers[] = $consumer;
-}
-if (!empty($consumers)) {
- $smarty->assign('fields', array_keys($consumers[0]));
-}
-$smarty->assign('consumers', $consumers);
-
-/* use current values */
-$smarty->assign('name', $name);
-$smarty->assign('key', $key);
-$smarty->assign('secret', $secret);
-$smarty->assign('enabled', $enabled);
-
-$smarty->assign('formAction', $_SERVER['PHP_SELF']);
-$smarty->assign('requestKey', (isset($_REQUEST['consumer_key']) ? $_REQUEST['consumer_key'] : null));
-
-$smarty->display('lti-consumers.tpl');
\ No newline at end of file
diff --git a/admin/index.php b/admin/index.php
index a95010c..3726f45 100644
--- a/admin/index.php
+++ b/admin/index.php
@@ -1,11 +1,6 @@
\ No newline at end of file
+header('Location: consumers-control-panel.php');
+exit;
diff --git a/admin/install-app.inc.php b/admin/install-app.inc.php
deleted file mode 100644
index 86a1332..0000000
--- a/admin/install-app.inc.php
+++ /dev/null
@@ -1,39 +0,0 @@
-addMessage(
- 'App metadata updated',
- 'Application metadata has been updated to create config.xml',
- NotificationMessage::GOOD
-);
-
-?>
diff --git a/admin/install.php b/admin/install.php
deleted file mode 100644
index a67487b..0000000
--- a/admin/install.php
+++ /dev/null
@@ -1,78 +0,0 @@
-addMessage(
- 'App already installed',
- 'It appears that the application has already been installed and is ready for
- use.'
- );
-
-/* ...otherwise, let's start with the SECRETS_FILE */
-} else {
- if(!file_exists(SECRETS_FILE)) {
- if (isset($_REQUEST['step']) && $_REQUEST['step'] == CanvasAPIviaLTI_Installer::SECRETS_ENTERED_STEP) {
- CanvasAPIviaLTI_Installer::createSecretsFile(CanvasAPIviaLTI_Installer::SECRETS_ENTERED_STEP);
- } else {
- CanvasAPIviaLTI_Installer::createSecretsFile();
- }
- }
-}
-
-/* establish our database connection */
-$secrets = initSecrets();
-$sql = initMySql();
-
-try {
- if (!isset($_REQUEST['step'])) {
- /* load all of our various schema into the database... */
- CanvasAPIviaLTI_Installer::createLTIDatabaseTables();
- CanvasAPIviaLTI_Installer::createAppDatabaseTables();
-
- /* ...and initialize the app metadata... */
- $metadata = CanvasAPIviaLTI_Installer::createAppMetadata();
-
- /* ...optionally, acquire an API token for the app */
- CanvasAPIviaLTI_Installer::acquireAPIToken(CanvasAPIviaLTI_Installer::API_DECISION_NEEDED_STEP);
- } else {
- $metadata = new AppMetadata($sql, $secrets->app->id);
- $skip = (isset($_REQUEST['skip']) ? $_REQUEST['skip'] : false);
- CanvasAPIviaLTI_Installer::acquireAPIToken($_REQUEST['step'], $skip);
- }
-} catch (CanvasAPIviaLTI_Installer_Exception $e) {
- $smarty->addMessage(
- 'LTI Installer error',
- $e->getMessage() . ' [Error ' . $e->getCode() . ']',
- NotificationMessage::ERROR
- );
- $smarty->display();
- exit;
-}
-
-try {
- /* any additional app-specific install steps */
- require_once('install-app.inc.php');
-} catch (CanvasAPIviaLTI_Installer_Exception $e) {
- $smarty->addMessage(
- 'App Installer error',
- $e->getMessage() . ' [Error ' . $e->getCode() . ']',
- NotificationMessage::ERROR
- );
-}
-
-/* reset $metadata to get update any computed values */
-$metadata = initAppMetadata();
-
-$smarty->assign('content', '
-
The application installation is complete. You may configure LTI Tool Consumer (TC) information by navigating to Consumers.
' -); - -$smarty->display(); - -?> \ No newline at end of file diff --git a/admin/oauth.php b/admin/oauth.php index b5033b4..833f040 100644 --- a/admin/oauth.php +++ b/admin/oauth.php @@ -1,56 +1,59 @@ oauth->id, - (string) $secrets->oauth->key, - "{$metadata['APP_URL']}/admin/install.php?step={$_REQUEST['step']}", - (string) $secrets->app->name - ); - } - - /* OAuthNegotiator will return here periodically and we will just keep re-instantiating it until it finishes */ - $oauth = new OAuthNegotiator(); -} catch (OAuthNegotiator_Exception $e) { - $smarty->addMessage( - 'OAuthNegotiator error', - $e->getMessage() . ' [Error ' . $e->getCode() . ']', - NotificationMessage::ERROR - ); - $smarty->assign( - 'content', - 'An error interrupted the installation process. To restart, click here.
'); - $smarty->display(); +/* do we have a Canvas instance URL yet? */ +if (empty($_SESSION[CANVAS_INSTANCE_URL]) && empty ($_REQUEST['url'])) { + $toolbox->smarty_assign('formAction', $_SERVER['PHP_SELF']); + $toolbox->smarty_display('oauth.tpl'); exit; +} elseif (empty($_SESSION[CANVAS_INSTANCE_URL]) && !empty($_REQUEST['url'])) { + $_SESSION[CANVAS_INSTANCE_URL] = $_REQUEST['url']; } -?> \ No newline at end of file +$canvas = $toolbox->config('TOOL_CANVAS_API'); +$provider = new CanvasLMS([ + 'clientId' => $canvas['key'], + 'clientSecret' => $canvas['secret'], + 'purpose' => $toolbox->config('TOOL_NAME'), + 'redirectUri' => DataUtilities::URLfromPath(__FILE__), + 'canvasInstanceUrl' => $_SESSION[CANVAS_INSTANCE_URL] +]); + +/* if we don't already have an authorization code, let's get one! */ +if (!isset($_GET['code'])) { + $authorizationUrl = $provider->getAuthorizationUrl(); + $_SESSION[OAUTH_STATE] = $provider->getState(); + header("Location: $authorizationUrl"); + exit; + +/* check that the passed state matches the stored state to mitigate cross-site request forgery attacks */ +} elseif (empty($_GET['state']) || $_GET['state'] !== $_SESSION[OAUTH_STATE]) { + unset($_SESSION[OAUTH_STATE]); + exit('Invalid state'); + +} else { + /* acquire and save our token (using our existing code) */ + $canvas = $toolbox->config('TOOL_CANVAS_API'); + $canvas['url'] = $_SESSION[CANVAS_INSTANCE_URL]; + $canvas['token'] = $provider->getAccessToken('authorization_code', ['code' => $_GET['code']])->getToken(); + + /* pass back the newly-acquired token in session data */ + $_SESSION['TOOL_CANVAS_API'] = $canvas; + + /* return to what we were doing before we had to authenticate */ + header("Location: {$_SESSION['oauth-return']}"); + unset($_SESSION[OAUTH_STATE]); + unset($_SESSION['oauth-return']); + exit; +} diff --git a/admin/schema-app.sql b/admin/schema-app.sql deleted file mode 100644 index 104fec0..0000000 --- a/admin/schema-app.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* the table to store user tokens (admin tokens are stored in the AppMetadata table) */ -CREATE TABLE IF NOT EXISTS `user_tokens` ( - `consumer_key` varchar(255) NOT NULL DEFAULT '', - `id` varchar(255) NOT NULL DEFAULT '', - `token` varchar(255) DEFAULT '', - `api_url` text, - `modified` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -/* add any other tables to support the application logic here */ \ No newline at end of file diff --git a/app.php b/app.php deleted file mode 100644 index 040ee36..0000000 --- a/app.php +++ /dev/null @@ -1,15 +0,0 @@ -user->getResourceLink()->settings['custom_canvas_account_id'])) { - $_SESSION['accountId'] = $_SESSION['toolProvider']->user->getResourceLink()->settings['custom_canvas_account_id']; - header("Location: account/"); - exit; -} else { - $_SESSION['courseId'] = $_SESSION['toolProvider']->user->getResourceLink()->settings['custom_canvas_course_id']; - header('Location: course/'); -} - - -?> \ No newline at end of file diff --git a/classes/CanvasAPIviaLTI.php b/classes/CanvasAPIviaLTI.php deleted file mode 100644 index bbe652f..0000000 --- a/classes/CanvasAPIviaLTI.php +++ /dev/null @@ -1,116 +0,0 @@ - - **/ -class CanvasAPIviaLTI extends LTI_Tool_Provider { - - /** - * Handle launch requests, which start the application running - **/ - public function onLaunch() { - global $metadata; // FIXME grown-ups don't program like this - global $sql; // FIXME grown-ups don't program like this - - /* is this user in a role that can use this app? */ - if ($this->user->isAdmin() || $this->user->isStaff()) { - - /* set up any needed session variables */ - $_SESSION['consumer_key'] = $this->consumer->getKey(); - $_SESSION['resource_id'] = $this->resource_link->getId(); - $_SESSION['user_consumer_key'] = $this->user->getResourceLink()->getConsumer()->getKey(); - $_SESSION['user_id'] = $this->user->getId(); - $_SESSION['isStudent'] = $this->user->isLearner(); - $_SESSION['isContentItem'] = FALSE; - - /* do we have an admin API access token? */ - $haveToken = true; - if (empty($metadata['CANVAS_API_TOKEN'])) { - - /* ...if not, do we have a user API access token for this user? */ - $userToken = new UserAPIToken($_SESSION['user_consumer_key'], $_SESSION['user_id'], $sql); - if (empty($userToken->getToken())) { - - /* ...if this user has no token, let's start by getting one */ - $haveToken = false; - $this->redirectURL = "{$metadata['APP_URL']}/lti/token_request.php?oauth=request"; - } else { - - /* ...but if the user does have a token, rock on! */ - $_SESSION['isUserToken'] = true; - $_SESSION['apiToken'] = $userToken->getToken(); - //$_SESSION['apiUrl'] = $userToken->getAPIUrl(); - } - } else { - - /* ...if we have an admin API token, rock on! */ - $_SESSION['isUserToken'] = false; - $_SESSION['apiToken'] = $metadata['CANVAS_API_TOKEN']; - //$_SESSION['apiUrl'] = $metadata['CANVAS_API_URL']; - } - $_SESSION['apiUrl'] = 'https://' . $this->user->getResourceLink()->settings['custom_canvas_api_domain'] . '/api/v1'; - - /* pass control off to the app */ - if ($haveToken) { - $this->redirectURL = "{$metadata['APP_URL']}/app.php?lti-request=launch"; - } - - /* ...otherwise set an appropriate error message and fail */ - } else { - $this->reason = 'Invalid role'; - $this->isOK = false; - } - } - - /** - * Handle errors created while processing the LTI request - **/ - public function onError() { - global $metadata; // FIXME grown-ups don't program like this - - $this->redirectURL = "{$metadata['APP_URL']}/app.php?lti-request=error&reason={$this->reason}"; - } - - /** - * Handle dashboard requests (coming in LTI v2.0, I guess) - **/ - public function onDashboard() { - global $metadata; // FIXME grown-ups don't program like this - - $this->redirectURL = "{$metadata['APP_URL']}/app.php?lti-request=dashboard"; - } - - /** - * Handle configure requests (coming in LTI v2.0, I guess) - **/ - public function onConfigure() { - global $metadata; // FIXME grown-ups don't program like this - - $this->redirectURL = "{$metadata['APP_URL']}/app.php?lti-request=configure"; - } - - /** - * Handle content-item requests (that is we're a tool provider that adds a button in the content editor) - **/ - public function onContentItem() { - global $metadata; // FIXME grown-ups don't program like this - - $this->redirectURL = "{$metadata['APP_URL']}/app.php?lti-request=content-item"; - } -} - -/** - * Exceptions thrown by CanvasAPIviaLTI - * - * @author Seth Battissecrets.xml
contains your authentication credentials and
- should be carefully protected. Be sure not to commit it to a public
- repository!",
- NotificationMessage::GOOD
- );
- } else {
- throw new CanvasAPIviaLTI_Installer_Exception(
- 'Missing a required app identity (name, id, admin username and admin password all required).',
- CanvasAPIviaLTI_Installer_Exception::SECRETS_FILE_APP
- );
- }
-
- /* clear the processed step */
- unset($_REQUEST['step']);
-
- break;
- }
-
- default: {
- throw new CanvasAPIviaLTI_Installer_Exception(
- "Unknown step ($step) in SECRETS_FILE creation.",
- CanvasAPIviaLTI_Installer_Exception::SECRETS_NEEDED_STEP
- );
- }
- }
- }
-
- /**
- * Create database tables to back LTI_Tool_Provider
- *
- * @throws CanvasAPIviaLTI_Installer_Exception If database schema not found in vendors directory
- * @throws CanvasAPIviaLTI_Installer_Exception If database tables are not created
- **/
- public static function createLTIDatabaseTables() {
- global $sql; // FIXME grown-ups don't program like this
- global $smarty; // FIXME grown-ups don't program like this
-
- $ltiSchema = realpath(__DIR__ . '/../vendor/spvsoftwareproducts/LTI_Tool_Provider/lti-tables-mysql.sql');
-
- if ($sql->query("SHOW TABLES LIKE 'lti_%'")->num_rows >= 5) {
- $smarty->addMessage('LTI database tables exist', 'Database tables to support the LTI Tool Provider (TP) already exist and have not been re-created.');
- } elseif (file_exists($ltiSchema)) {
- $queries = explode(";", file_get_contents($ltiSchema));
- $created = true;
- foreach($queries as $query) {
- if (!empty(trim($query))) {
- if (!$sql->query($query)) {
- throw new CanvasAPIviaLTI_Installer_Exception(
- "Error creating LTI database tables: {$sql->error}",
- CanvasAPIviaLTI_Installer_Exception::LTI_PREPARE_DATABASE
- );
- }
- }
- }
-
- $smarty->addMessage(
- 'LTI database tables created',
- 'Database tables to support the LTI Tool Provider (TP) have been created in
- your MySQL database.',
- NotificationMessage::GOOD
- );
- } else {
- throw new CanvasAPIviaLTI_Exception("$ltiSchema not found.");
- }
- }
-
- /**
- * Create database tables to back app
- *
- * @throws CanvasAPIviaLTI_Installer_Exception If database tables are not created
- **/
- public static function createAppDatabaseTables() {
- global $sql; // FIXME grown-ups don't program like this
- global $smarty; // FIXME grown-ups don't program like this
-
- if (file_exists(SCHEMA_FILE)) {
- $queries = explode(";", file_get_contents(SCHEMA_FILE));
- $created = true;
- foreach ($queries as $query) {
- if (!empty(trim($query))) {
- if (preg_match('/CREATE\s+TABLE\s+(`([^`]+)`|\w+)/i', $query, $tableName)) {
- $tableName = (empty($tableName[2]) ? $tableName[1] : $tableName[2]);
- if ($sql->query("SHOW TABLES LIKE '$tableName'")->num_rows > 0) {
- $created = false;
- } else {
- if (!$sql->query($query)) {
- throw new CanvasAPIviaLTI_Installer_Exception(
- "Error creating app database tables: {$sql->error}",
- CanvasAPIviaLTI_Installer_Exception::APP_CREATE_TABLE
- );
- }
- }
- } else {
- if (!$sql->query($query)) {
- throw new CanvasAPIviaLTI_Installer_Exception(
- "Error creating app database tables: {$sql->error}",
- CanvasAPIviaLTI_Installer_Exception::APP_PREPARE_DATABASE
- );
- }
- }
- }
- }
-
- if ($created) {
- $smarty->addMessage(
- 'App database tables created',
- 'Database tables to support the application have been created in your
- MySQL database.',
- NotificationMessage::GOOD
- );
- } else {
- $smarty->addMessage(
- 'App database tables exist',
- 'Database tables to support the application already exist and have not
- been re-created.'
- );
- }
- }
- }
-
- /**
- * Initialize the app metadata store, especially the APP_PATH and APP_URL
- *
- * @return AppMetadata
- **/
- public static function createAppMetadata() {
- global $secrets; // FIXME grown-ups don't program like this
- global $sql; // FIXME grown-ups don't program like this
- global $metadata; // FIXME grown-ups don't program like this
- global $smarty; // FIXME grown-ups don't program like this
-
- $metadata = initAppMetadata();
- $metadata['APP_PATH'] = preg_replace('/\/classes$/', '', __DIR__);
- $metadata['APP_URL'] = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on' ? 'http://' : 'https://') . $_SERVER['SERVER_NAME'] . preg_replace("|^{$_SERVER['DOCUMENT_ROOT']}(.*)$|", '$1', $metadata['APP_PATH']);
- $metadata['APP_NAME'] = (string) $secrets->app->name;
- $metadata['APP_ID'] = (string) $secrets->app->id;
- $metadata['CANVAS_INSTANCE_URL_PLACEHOLDER'] = 'https://canvas.instructure.com';
- $smarty->assign('metadata', $metadata);
-
- $smarty->addMessage(
- 'App metadata initialized',
- 'Basic application metadata has been updated, including APP_PATH and APP_URL',
- NotificationMessage::GOOD
- );
-
- return $metadata;
- }
-
- /**
- * Obtain a Canvas API token, if needed.
- *
- * @param scalar $step optional Where are we in the API token negotiation workflow? (defaults to API_DECISION_NEEDED_STEP -- the beginning)
- * @param boolean $skip optional Skip this step (defaults to FALSE)
- *
- * @throws CanvasAPIviaLTI_Installer_Exception If $step is not a pre-defined *_STEP constant
- **/
- public static function acquireAPIToken($step = self::API_DECISION_NEEDED_STEP, $skip = false) {
- global $secrets; // FIXME grown-ups don't program like this
- global $metadata; // FIXME grown-ups don't program like this
- global $smarty; // FIXME grown-ups don't program like this
-
- if ($skip) {
- if (isset($metadata['CANVAS_API_TOKEN']) || isset($metadata['CANVAS_API_USER'])) {
- $api = new CanvasPest("{$metadata['CANVAS_INSTANCE_URL']}/login/oauth2", $metadata['CANVAS_API_TOKEN']);
- $api->delete('token');
- unset($metadata['CANVAS_API_TOKEN']);
- unset($metadata['CANVAS_API_USER']);
- $smarty->addMessage(
- 'Existing admin Canvas API token information expunged',
- 'There was already an administrative access token stored in your
- application metadata, and it has now been expunged.'
- );
- } else {
- $smarty->addMessage(
- 'No admin Canvas API token acquired',
- 'An administrative API token has not been acquired. Users will be asked to
- acquire their own API tokens on their first use of the LTI.'
- );
- }
- } else {
- switch ($step) {
- case self::API_DECISION_NEEDED_STEP: {
- $smarty->assign('content', '
-
- or
-
- ');
- $smarty->display();
- exit;
- }
- case self::API_DECISION_ENTERED_STEP: {
- $oauth = new OAuthNegotiator();
-
- if ($oauth->isAPIToken()) {
- $metadata['CANVAS_API_TOKEN'] = $oauth->getToken();
-
- $smarty->addMessage(
- 'Admin Canvas API token acquired',
- 'An administrative API access token has been acquired and stored in your application metadata.',
- NotificationMessage::GOOD
- );
- }
-
- /* clear the processed step */
- unset($_REQUEST['step']);
-
- break;
- }
- case self::API_TOKEN_PROVIDED_STEP: {
- $smarty->addMessage(
- 'Admin Canvas API token provided',
- 'You provided an API access token and it has been stored in your application metadata.'
- );
- break;
- }
- default: {
- throw new CanvasAPIviaLTI_Installer_Exception(
- "Unknown step ($step) in obtaining API token.",
- CanvasAPIviaLTI_Installer_Exception::API_STEP_MISMATCH
- );
- }
- }
- }
- }
-}
-
-/**
- * Exceptions thrown by CanvasAPIviaLTI_Installer
- *
- * @author Seth Battis '; - var_dump($var); - echo ''; +/* set the Tool Consumer's instance URL, if present */ +if (empty($_SESSION[CANVAS_INSTANCE_URL]) && + !empty($_SESSION[ToolProvider::class]['canvas']['api_domain']) +) { + $_SESSION[CANVAS_INSTANCE_URL] = 'https://' . $_SESSION[ToolProvider::class]['canvas']['api_domain']; } - -/***************************************************************************** - * * - * The script begins here * - * * - *****************************************************************************/ - -/* assume everything's going to be fine... */ -$ready = true; - -/* preliminary interactive only initialization */ -if (php_sapi_name() != 'cli') { - session_start(); - - /* fire up the templating engine for interactive scripts */ - $smarty = StMarksSmarty::getSmarty(); - $smarty->addTemplateDir(__DIR__ . '/templates', 'starter-canvas-api-via-lti'); - $smarty->setFramed(true); -} - -/* initialization that needs to happen for interactive and CLI scripts */ -try { - /* initialize global variables */ - $secrets = initSecrets(); - $sql = initMySql(); - $metadata = initAppMetadata(); -} catch (CanvasAPIviaLTI_Exception $e) { - $smarty->addMessage( - 'Initialization Failure', - $e->getMessage(), - NotificationMessage::ERROR - ); - $smarty->display(); - exit; -} - -/* interactive initialization only */ -if ($ready && php_sapi_name() != 'cli') { - - /* allow web apps to use common.inc.php without LTI authentication */ - if (!defined('IGNORE_LTI')) { - - try { - if (midLaunch()) { - $ready = false; - } elseif (isset($_SESSION['toolProvider'])) { - $toolProvider = $_SESSION['toolProvider']; - } else { - throw new CanvasAPIviaLTI_Exception( - 'The LTI launch request is missing', - CanvasAPIviaLTI_Exception::LAUNCH_REQUEST - ); - } - - } catch (CanvasAPIviaLTI_Exception $e) { - $ready = false; - } - } - - if ($ready) { - $smarty->addStylesheet($metadata['APP_URL'] . '/css/canvas-api-via-lti.css', 'starter-canvas-api-via-lti'); - $smarty->addStylesheet($metadata['APP_URL'] . '/css/app.css'); - - if (!midLaunch() || !defined('IGNORE_LTI')) { - require_once(__DIR__ . '/common-app.inc.php'); - } - } -} - - -?> \ No newline at end of file diff --git a/composer.json b/composer.json index 1dc978c..170bef9 100644 --- a/composer.json +++ b/composer.json @@ -3,40 +3,41 @@ "description": "A dashboard for advisors in Canvas", "license": "LGPL-3.0", "config": { - "secure-http": false - }, - "repositories": [ - { - "type": "package", - "package": { - "name": "spvsoftwareproducts/LTI_Tool_Provider", - "version": "2.5.01", - "dist": { - "url": "http://projects.oscelot.org/gf/download/frsrelease/956/6025/LTI_Tool_Provider-2.5.01.zip", - "type": "zip" - }, - "license": "LGPL-3.0", - "authors": [ - { - "name": "Stephen Vickers" - } - ], - "homepage": "http://spvsoftwareproducts.com/php/lti_tool_provider/" - } - } - ], + "secure-http": false + }, + "repositories": [ + { + "type": "package", + "package": { + "name": "spvsoftwareproducts/LTI_Tool_Provider", + "version": "2.5.01", + "dist": { + "url": "http://projects.oscelot.org/gf/download/frsrelease/956/6025/LTI_Tool_Provider-2.5.01.zip", + "type": "zip" + }, + "license": "LGPL-3.0", + "authors": [ + { + "name": "Stephen Vickers" + } + ], + "homepage": "http://spvsoftwareproducts.com/php/lti_tool_provider/", + "autoload": { + "classmap": [""] + } + } + } + ], "require": { - "smtech/stmarkssmarty": "dev-master", - "smtech/canvaspest": "~1.0", - "smtech/oauth-negotiator": "~1.0", - "battis/appmetadata": "~1.0", - "spvsoftwareproducts/LTI_Tool_Provider": "~2.5", - "pear/log": "~1.12", - "battis/simplecache": "~1.0", + "smtech/stmarks-reflexive-canvas-lti": "~0.1", + "smtech/oauth2-canvaslms": "~1.0", + "battis/data-utilities": "~0.1", "roderik/pwgen-php": "~0.1" }, "autoload": { - "classmap": [""] + "psr-4": { + "smtech\\AdvisorDashboard\\": "src" + } }, "authors": [ { @@ -44,5 +45,5 @@ "email": "sethbattis@stmarksschool.org" } ], - "minimum-stability": "dev" + "minimum-stability": "stable" } diff --git a/composer.lock b/composer.lock index 5beb8e7..0241ae5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,27 +4,27 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "4da6eb06c2ec02e61de543cbd8142dec", - "content-hash": "16879f2a53b7020c9aff06e8bef5a102", + "hash": "a27f893cdcf19f89091e781361f1bbbf", + "content-hash": "4f547057f1ef27e1ccebb76122a06d71", "packages": [ { "name": "battis/appmetadata", - "version": "v1.2.1", + "version": "v1.2.2", "source": { "type": "git", "url": "https://github.com/battis/appmetadata.git", - "reference": "a97bdc20627008ed165b638737b618a0d6f606c2" + "reference": "1d9f4c7e29576dbd4ae0b56bd97c29fc8ff4c3b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/battis/appmetadata/zipball/a97bdc20627008ed165b638737b618a0d6f606c2", - "reference": "a97bdc20627008ed165b638737b618a0d6f606c2", + "url": "https://api.github.com/repos/battis/appmetadata/zipball/1d9f4c7e29576dbd4ae0b56bd97c29fc8ff4c3b5", + "reference": "1d9f4c7e29576dbd4ae0b56bd97c29fc8ff4c3b5", "shasum": "" }, "type": "library", "autoload": { "psr-4": { - "Battis\\": "" + "Battis\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -38,29 +38,62 @@ } ], "description": "An object to store app metadata backed by a MySQL table", - "time": "2015-10-22 20:25:29" + "time": "2016-07-22 06:29:17" }, { "name": "battis/bootstrapsmarty", - "version": "v1.1.2", + "version": "v2.0", "source": { "type": "git", "url": "https://github.com/battis/bootstrapsmarty.git", - "reference": "097ff9d3931aedbc38677d207b5c4540b4de812c" + "reference": "c95297336ca37a48f3bcbc655275996ebbd0a2f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/battis/bootstrapsmarty/zipball/097ff9d3931aedbc38677d207b5c4540b4de812c", - "reference": "097ff9d3931aedbc38677d207b5c4540b4de812c", + "url": "https://api.github.com/repos/battis/bootstrapsmarty/zipball/c95297336ca37a48f3bcbc655275996ebbd0a2f9", + "reference": "c95297336ca37a48f3bcbc655275996ebbd0a2f9", "shasum": "" }, "require": { - "battis/data-utilities": "dev-master", - "bower-asset/bootstrap-colorpicker": "dev-master", - "bower-asset/bootstrap-datepicker": "dev-master", - "bower-asset/bootstrap-sortable": "dev-master", + "battis/data-utilities": "~0.1", + "bower-asset/bootstrap-colorpicker-2.x": "~2.3", + "bower-asset/bootstrap-datepicker-1.x": "~1.6", + "bower-asset/bootstrap-sortable-2.x": "~2.0", "fxp/composer-asset-plugin": "^1.1", - "smarty/smarty": "3.1.*" + "smarty/smarty": "~3.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Battis\\BootstrapSmarty\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Seth Battis", + "email": "seth@battis.net" + } + ], + "description": "A wrapper for Smarty to set (and maintain) defaults within a Bootstrap UI environment", + "time": "2016-08-01 13:10:10" + }, + { + "name": "battis/configxml", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/battis/configxml.git", + "reference": "b68daa917e052bd8f53c3be0378b23d33526f961" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/battis/configxml/zipball/b68daa917e052bd8f53c3be0378b23d33526f961", + "reference": "b68daa917e052bd8f53c3be0378b23d33526f961", + "shasum": "" }, "require-dev": { "phpunit/phpunit": "~5.0" @@ -68,7 +101,7 @@ "type": "library", "autoload": { "psr-4": { - "Battis\\BootstrapSmarty\\": "src/" + "Battis\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -81,12 +114,12 @@ "email": "seth@battis.net" } ], - "description": "A wrapper for Smarty to set (and maintain) defaults within a Bootstrap UI environment", - "time": "2016-04-14 02:09:19" + "description": "Load a configuration XML file for quick use", + "time": "2016-05-09 19:47:21" }, { "name": "battis/data-utilities", - "version": "dev-master", + "version": "v0.1", "source": { "type": "git", "url": "https://github.com/battis/data-utilities.git", @@ -122,7 +155,7 @@ }, { "name": "battis/educoder-pest-fork", - "version": "dev-master", + "version": "v1.0.1", "source": { "type": "git", "url": "https://github.com/battis/pest.git", @@ -197,20 +230,20 @@ }, { "name": "bower-asset/bootstrap", - "version": "dev-master", + "version": "v3.3.7", "source": { "type": "git", "url": "https://github.com/twbs/bootstrap.git", - "reference": "edefe0e77a39149f971c4215301f7f8a7f15f210" + "reference": "0b9c4a4007c44201dce9a6cc1a38407005c26c86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twbs/bootstrap/zipball/edefe0e77a39149f971c4215301f7f8a7f15f210", - "reference": "edefe0e77a39149f971c4215301f7f8a7f15f210", + "url": "https://api.github.com/repos/twbs/bootstrap/zipball/0b9c4a4007c44201dce9a6cc1a38407005c26c86", + "reference": "0b9c4a4007c44201dce9a6cc1a38407005c26c86", "shasum": "" }, "require": { - "bower-asset/jquery": ">=1.9.1,<=3" + "bower-asset/jquery": ">=1.9.1,<4.0" }, "type": "bower-asset-library", "extra": { @@ -245,17 +278,17 @@ ] }, { - "name": "bower-asset/bootstrap-colorpicker", - "version": "dev-master", + "name": "bower-asset/bootstrap-colorpicker-2.x", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/mjolnic/bootstrap-colorpicker.git", - "reference": "7847a84ab7ec3b17474fb16b7e68fc02838efe52" + "reference": "59f06437c86b7c0e074aee8a699819fd1c07a173" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mjolnic/bootstrap-colorpicker/zipball/7847a84ab7ec3b17474fb16b7e68fc02838efe52", - "reference": "7847a84ab7ec3b17474fb16b7e68fc02838efe52", + "url": "https://api.github.com/repos/mjolnic/bootstrap-colorpicker/zipball/59f06437c86b7c0e074aee8a699819fd1c07a173", + "reference": "59f06437c86b7c0e074aee8a699819fd1c07a173", "shasum": "" }, "require": { @@ -281,27 +314,27 @@ } }, { - "name": "bower-asset/bootstrap-datepicker", - "version": "dev-master", + "name": "bower-asset/bootstrap-datepicker-1.x", + "version": "v1.6.1", "source": { "type": "git", "url": "https://github.com/eternicode/bootstrap-datepicker.git", - "reference": "3bde2d87a291fcc1808a86dc9317eba9d361b7a0" + "reference": "f4df9ac6679b15b12157324c556e0da1c628af6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/eternicode/bootstrap-datepicker/zipball/3bde2d87a291fcc1808a86dc9317eba9d361b7a0", - "reference": "3bde2d87a291fcc1808a86dc9317eba9d361b7a0", + "url": "https://api.github.com/repos/eternicode/bootstrap-datepicker/zipball/f4df9ac6679b15b12157324c556e0da1c628af6e", + "reference": "f4df9ac6679b15b12157324c556e0da1c628af6e", "shasum": "" }, "require": { - "bower-asset/jquery": ">=1.7.1,<3.0.0" + "bower-asset/jquery": ">=1.7.1" }, "type": "bower-asset-library", "extra": { "bower-asset-main": [ "dist/css/bootstrap-datepicker3.css", - "dist/js/bootstrap-datepicker.js" + "dist/js/bootstrap-datepicker.min.js" ], "bower-asset-ignore": [] }, @@ -310,8 +343,8 @@ ] }, { - "name": "bower-asset/bootstrap-sortable", - "version": "dev-master", + "name": "bower-asset/bootstrap-sortable-2.x", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/drvic10k/bootstrap-sortable.git", @@ -332,10 +365,7 @@ "bower-asset-main": "Scripts/bootstrap-sortable.js", "bower-asset-ignore": [ "Scripts/moment.min.js" - ], - "branch-alias": { - "dev-master": "2.0.0-dev" - } + ] }, "license": [ "MIT" @@ -351,16 +381,16 @@ }, { "name": "bower-asset/jquery", - "version": "2.2.4", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/jquery/jquery-dist.git", - "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72" + "reference": "6f02bc382c0529d3b4f68f6b2ad21876642dbbfe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/c0185ab7c75aab88762c5aae780b9d83b80eda72", - "reference": "c0185ab7c75aab88762c5aae780b9d83b80eda72", + "url": "https://api.github.com/repos/jquery/jquery-dist/zipball/6f02bc382c0529d3b4f68f6b2ad21876642dbbfe", + "reference": "6f02bc382c0529d3b4f68f6b2ad21876642dbbfe", "shasum": "" }, "type": "bower-asset-library", @@ -382,7 +412,7 @@ }, { "name": "bower-asset/moment", - "version": "dev-master", + "version": "2.14.1", "source": { "type": "git", "url": "https://github.com/moment/moment.git", @@ -419,16 +449,16 @@ }, { "name": "fxp/composer-asset-plugin", - "version": "dev-master", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/fxpio/composer-asset-plugin.git", - "reference": "47c08367901b64d41d87f84e7f3fd2aa9417ea71" + "reference": "8d74bc7c714aadbda54622c216b2e7bf786595cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fxpio/composer-asset-plugin/zipball/47c08367901b64d41d87f84e7f3fd2aa9417ea71", - "reference": "47c08367901b64d41d87f84e7f3fd2aa9417ea71", + "url": "https://api.github.com/repos/fxpio/composer-asset-plugin/zipball/8d74bc7c714aadbda54622c216b2e7bf786595cb", + "reference": "8d74bc7c714aadbda54622c216b2e7bf786595cb", "shasum": "" }, "require": { @@ -471,7 +501,380 @@ "npm", "package" ], - "time": "2016-07-14 08:50:38" + "time": "2016-07-01 12:04:16" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.2.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/3f808fba627f2c5b69e2501217bf31af349c1427", + "reference": "3f808fba627f2c5b69e2501217bf31af349c1427", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.3.1", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.2-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2016-07-15 17:22:37" + }, + { + "name": "guzzlehttp/promises", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579", + "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-05-18 16:56:05" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "reference": "5c6447c9df362e8f8093bda8f5d8873fe5c7f65b", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "PSR-7 message implementation", + "keywords": [ + "http", + "message", + "stream", + "uri" + ], + "time": "2016-06-24 23:00:38" + }, + { + "name": "ircmaxell/random-lib", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/ircmaxell/RandomLib.git", + "reference": "13efa4368bb2ac88bb3b1459b487d907de4dbf7c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ircmaxell/RandomLib/zipball/13efa4368bb2ac88bb3b1459b487d907de4dbf7c", + "reference": "13efa4368bb2ac88bb3b1459b487d907de4dbf7c", + "shasum": "" + }, + "require": { + "ircmaxell/security-lib": "1.0.*@dev", + "php": ">=5.3.2" + }, + "require-dev": { + "mikey179/vfsstream": "1.1.*", + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "RandomLib": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anthony Ferrara", + "email": "ircmaxell@ircmaxell.com", + "homepage": "http://blog.ircmaxell.com" + } + ], + "description": "A Library For Generating Secure Random Numbers", + "homepage": "https://github.com/ircmaxell/RandomLib", + "keywords": [ + "cryptography", + "random", + "random-numbers", + "random-strings" + ], + "time": "2015-01-15 16:31:45" + }, + { + "name": "ircmaxell/security-lib", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/ircmaxell/SecurityLib.git", + "reference": "80934de3c482dcafb46b5756e59ebece082b6dc7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ircmaxell/SecurityLib/zipball/80934de3c482dcafb46b5756e59ebece082b6dc7", + "reference": "80934de3c482dcafb46b5756e59ebece082b6dc7", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "mikey179/vfsstream": "1.1.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "SecurityLib": "lib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anthony Ferrara", + "email": "ircmaxell@ircmaxell.com", + "homepage": "http://blog.ircmaxell.com" + } + ], + "description": "A Base Security Library", + "homepage": "https://github.com/ircmaxell/PHP-SecurityLib", + "time": "2013-04-30 18:00:34" + }, + { + "name": "league/oauth2-client", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth2-client.git", + "reference": "01f955b85040b41cf48885b078f7fd39a8be5411" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/01f955b85040b41cf48885b078f7fd39a8be5411", + "reference": "01f955b85040b41cf48885b078f7fd39a8be5411", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "guzzlehttp/guzzle": "~6.0", + "ircmaxell/random-lib": "~1.1", + "php": ">=5.5.0" + }, + "require-dev": { + "jakub-onderka/php-parallel-lint": "0.8.*", + "mockery/mockery": "~0.9", + "phpunit/phpunit": "~4.0", + "satooshi/php-coveralls": "0.6.*", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth2\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alex Bilbie", + "email": "hello@alexbilbie.com", + "homepage": "http://www.alexbilbie.com", + "role": "Developer" + } + ], + "description": "OAuth 2.0 Client Library", + "keywords": [ + "Authentication", + "SSO", + "authorization", + "identity", + "idp", + "oauth", + "oauth2", + "single sign on" + ], + "time": "2016-07-28 13:20:43" + }, + { + "name": "myclabs/php-enum", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/php-enum.git", + "reference": "07da9d1a7469941ae05b046193fac4c83bdb0d7e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/07da9d1a7469941ae05b046193fac4c83bdb0d7e", + "reference": "07da9d1a7469941ae05b046193fac4c83bdb0d7e", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "4.*", + "squizlabs/php_codesniffer": "1.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "description": "PHP Enum implementation", + "homepage": "http://github.com/myclabs/php-enum", + "keywords": [ + "enum" + ], + "time": "2015-07-22 16:14:03" }, { "name": "pear/log", @@ -581,6 +984,55 @@ ], "time": "2015-02-10 20:07:52" }, + { + "name": "psr/http-message", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2015-05-04 20:22:00" + }, { "name": "roderik/pwgen-php", "version": "0.1.5", @@ -627,16 +1079,16 @@ }, { "name": "smarty/smarty", - "version": "dev-master", + "version": "v3.1.29", "source": { "type": "git", "url": "https://github.com/smarty-php/smarty.git", - "reference": "6d7d36d9a675f69a18f5a8722dd22c0f2f70504d" + "reference": "35480f10e7ce9b0fdaf23d3799d7b79463919b1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/smarty-php/smarty/zipball/6d7d36d9a675f69a18f5a8722dd22c0f2f70504d", - "reference": "6d7d36d9a675f69a18f5a8722dd22c0f2f70504d", + "url": "https://api.github.com/repos/smarty-php/smarty/zipball/35480f10e7ce9b0fdaf23d3799d7b79463919b1e", + "reference": "35480f10e7ce9b0fdaf23d3799d7b79463919b1e", "shasum": "" }, "require": { @@ -678,7 +1130,7 @@ "keywords": [ "templating" ], - "time": "2016-07-19 18:22:10" + "time": "2015-12-21 01:57:06" }, { "name": "smtech/canvaspest", @@ -686,16 +1138,16 @@ "source": { "type": "git", "url": "https://github.com/smtech/canvaspest.git", - "reference": "d9b48fb1e368bbaccfd305c5fe49c07da1519f39" + "reference": "c1a5b7901e5d637afd05158541b1090d70027ed4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/smtech/canvaspest/zipball/d9b48fb1e368bbaccfd305c5fe49c07da1519f39", - "reference": "d9b48fb1e368bbaccfd305c5fe49c07da1519f39", + "url": "https://api.github.com/repos/smtech/canvaspest/zipball/c1a5b7901e5d637afd05158541b1090d70027ed4", + "reference": "c1a5b7901e5d637afd05158541b1090d70027ed4", "shasum": "" }, "require": { - "battis/educoder-pest-fork": "dev-master" + "battis/educoder-pest-fork": "~1.0" }, "type": "library", "autoload": { @@ -714,26 +1166,111 @@ } ], "description": "An extension of Pest to make RESTful queries to the Instructure Canvas API", - "time": "2016-06-10 13:35:42" + "time": "2016-07-25 02:29:48" + }, + { + "name": "smtech/lti-configuration-xml", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/smtech/lti-configuration-xml.git", + "reference": "ab9a963bb0f9d4a6689c20af20532d3af7f49a1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/smtech/lti-configuration-xml/zipball/ab9a963bb0f9d4a6689c20af20532d3af7f49a1f", + "reference": "ab9a963bb0f9d4a6689c20af20532d3af7f49a1f", + "shasum": "" + }, + "require": { + "myclabs/php-enum": "~1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "smtech\\LTI\\Configuration\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Seth Battis", + "email": "sethbattis@stmarksschool.org" + } + ], + "description": "Generate an LTI configuration XML file from parameters", + "time": "2016-07-26 18:38:05" + }, + { + "name": "smtech/oauth2-canvaslms", + "version": "v1.0", + "source": { + "type": "git", + "url": "https://github.com/smtech/oauth2-canvaslms.git", + "reference": "aa77bf14cb83c4666db8a110c3ecd74d46c2cece" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/smtech/oauth2-canvaslms/zipball/aa77bf14cb83c4666db8a110c3ecd74d46c2cece", + "reference": "aa77bf14cb83c4666db8a110c3ecd74d46c2cece", + "shasum": "" + }, + "require": { + "league/oauth2-client": "~1.0", + "php": ">=5.5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "smtech\\OAuth2\\Client\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Seth Battis", + "email": "sethbattis@stmarksschool.org" + } + ], + "description": "Canvas LMS OAuth 2.0 support for the PHP League's OAuth 2.0 Client", + "time": "2016-07-14 18:35:06" }, { - "name": "smtech/oauth-negotiator", - "version": "v1.1.2", + "name": "smtech/reflexive-canvas-lti", + "version": "v1.0.2", "source": { "type": "git", - "url": "https://github.com/smtech/oauth-negotiator.git", - "reference": "79f1ec4e80f0eba390fb23ac23ad110197961dd7" + "url": "https://github.com/smtech/reflexive-canvas-lti.git", + "reference": "6282241595a0675bbeb4a5fcfc6e8871ec6853ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/smtech/oauth-negotiator/zipball/79f1ec4e80f0eba390fb23ac23ad110197961dd7", - "reference": "79f1ec4e80f0eba390fb23ac23ad110197961dd7", + "url": "https://api.github.com/repos/smtech/reflexive-canvas-lti/zipball/6282241595a0675bbeb4a5fcfc6e8871ec6853ad", + "reference": "6282241595a0675bbeb4a5fcfc6e8871ec6853ad", "shasum": "" }, "require": { - "battis/educoder-pest-fork": "dev-master" + "battis/appmetadata": "~1.0", + "battis/configxml": "~1.0", + "battis/data-utilities": "~0.1", + "myclabs/php-enum": "~1.0", + "pear/log": "~1.0", + "smtech/canvaspest": "~1.0", + "smtech/lti-configuration-xml": "~1.0", + "spvsoftwareproducts/lti_tool_provider": "~2.5" }, "type": "library", + "autoload": { + "psr-4": { + "smtech\\ReflexiveCanvasLTI\\": "src/" + } + }, "notification-url": "https://packagist.org/downloads/", "license": [ "LGPL-3.0" @@ -744,13 +1281,12 @@ "email": "sethbattis@stmarksschool.org" } ], - "description": "Negotiate an OAuth 2 authentication or API token", - "abandoned": "smtech/oauth2-canvaslms", - "time": "2016-02-15 19:30:24" + "description": "LTI tool provider class that includes the \"reflexive\" reach back into Canvas via the API", + "time": "2016-08-01 13:25:20" }, { "name": "smtech/stmarks-colors", - "version": "dev-master", + "version": "v1.1", "source": { "type": "git", "url": "https://github.com/smtech/stmarks-colors.git", @@ -782,25 +1318,62 @@ "time": "2016-03-17 15:26:18" }, { - "name": "smtech/stmarkssmarty", - "version": "dev-master", + "name": "smtech/stmarks-reflexive-canvas-lti", + "version": "v0.1", "source": { "type": "git", - "url": "https://github.com/smtech/stmarkssmarty.git", - "reference": "ddb27fba830765e3f663b693c7eb79746d97a8d4" + "url": "https://github.com/smtech/stmarks-reflexive-canvas-lti.git", + "reference": "06497222d29efbcdb89b6f053e92ce18ded8142d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/smtech/stmarkssmarty/zipball/ddb27fba830765e3f663b693c7eb79746d97a8d4", - "reference": "ddb27fba830765e3f663b693c7eb79746d97a8d4", + "url": "https://api.github.com/repos/smtech/stmarks-reflexive-canvas-lti/zipball/06497222d29efbcdb89b6f053e92ce18ded8142d", + "reference": "06497222d29efbcdb89b6f053e92ce18ded8142d", "shasum": "" }, "require": { - "battis/bootstrapsmarty": "^1.1", - "smtech/stmarks-colors": "dev-master" + "battis/data-utilities": "~0.1", + "battis/simplecache": "~1.0", + "smtech/reflexive-canvas-lti": "~1.0", + "smtech/stmarkssmarty": "~1.0" }, - "suggest": { - "battis/appmetadata": "MySQL-backed globals array for app metadata storage" + "type": "library", + "autoload": { + "psr-4": { + "smtech\\StMarksReflexiveCanvasLTI\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Seth Battis", + "email": "sethbattis@stmarksschool.org" + } + ], + "description": "A toolbox for managing LTI authentication and tool provider development (with St. Mark's templating)", + "time": "2016-08-01 15:10:04" + }, + { + "name": "smtech/stmarkssmarty", + "version": "v1.0", + "source": { + "type": "git", + "url": "https://github.com/smtech/stmarks-bootstrapsmarty.git", + "reference": "e481110eed523a1c6dc3e1a8d152785ab909cfc9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/smtech/stmarks-bootstrapsmarty/zipball/e481110eed523a1c6dc3e1a8d152785ab909cfc9", + "reference": "e481110eed523a1c6dc3e1a8d152785ab909cfc9", + "shasum": "" + }, + "require": { + "battis/bootstrapsmarty": "~2.0", + "battis/data-utilities": "~0.1", + "smtech/stmarks-colors": "~1.0" }, "type": "library", "autoload": { @@ -819,7 +1392,7 @@ } ], "description": "A standard Smarty install for St. Mark's projects", - "time": "2016-03-17 20:07:04" + "time": "2016-08-01 13:20:55" }, { "name": "spvsoftwareproducts/LTI_Tool_Provider", @@ -831,6 +1404,11 @@ "shasum": null }, "type": "library", + "autoload": { + "classmap": [ + "" + ] + }, "license": [ "LGPL-3.0" ], @@ -844,10 +1422,8 @@ ], "packages-dev": [], "aliases": [], - "minimum-stability": "dev", - "stability-flags": { - "smtech/stmarkssmarty": 20 - }, + "minimum-stability": "stable", + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": [], diff --git a/config.example.xml b/config.example.xml new file mode 100644 index 0000000..029f4b1 --- /dev/null +++ b/config.example.xml @@ -0,0 +1,34 @@ + +
Below are visualizations of your advisee's relative performance in their classes, as compared to the other students' performance on each assignment.
Nota bene: zero-point assignments and ungraded assignments (assignments where the maximum grade was zero) have been filtered out of this view. If your advisee has "bottomed out" at zero on an assignment, it may mean that their submission is not yet graded, while other students' submissions have been graded.
- +This application requires access to the Canvas APIs. Canvas is about to ask you to give permission for this.
- '); - $smarty->display(); - exit; - } - case 'process': { - $oauth = new OAuthNegotiator( - 'https://' . $toolProvider->user->getResourceLink()->settings['custom_canvas_api_domain'] . '/login/oauth2', - (string) $secrets->oauth->id, - (string) $secrets->oauth->key, - "{$_SERVER['PHP_SELF']}?oauth=complete", - (string) $secrets->app->name - ); - break; - } - case 'complete': { - $user = new UserAPIToken($_SESSION['user_consumer_key'], $_SESSION['user_id'], $sql); - $user->setToken($oauth->getToken()); - $user->setAPIUrl("{$metadata['CANVAS_INSTANCE_URL']}/api/v1"); - - $_SESSION['apiToken'] = $user->getToken(); - $_SESSION['apiUrl'] = $user->getAPIUrl(); - $_SESSION['isUserToken'] = true; - - header("Location: {$metadata['APP_URL']}/app.php"); - exit; - } - } -} - -?> \ No newline at end of file diff --git a/secrets-example.xml b/secrets-example.xml deleted file mode 100644 index c2c1318..0000000 --- a/secrets-example.xml +++ /dev/null @@ -1,21 +0,0 @@ - -Name | +Consumer Key | +Shared Secret | +Enabled | +|
---|---|---|---|---|
{$_consumer->name} | +{$_consumer->getKey()} | +{$_consumer->secret} | +
+
+ enabled}checked="checked"{/if} readonly />
+
+ |
+ {if !$selected}
+ + + | + {/if} +
No consumers registered yet. | + + {/if} +
To install this LTI, users should choose configuration type By URL and provide their consumer key and secret above. They should point their installer at:
+ +
-
|
- {if $closed}
- - - | - {/if} -
No consumers
- {/if} -To install this LTI, users should choose configuration type By URL and provide their consumer key and secret above. They should point their installer at:
- -This tool requires access to the Canvas APIs. You can provide this access either by editing your config.xml
file to include the URL of your Canvas API and a valid API access token, or by interactively authenticating to Canvas to issue an API token directly right now.