Skip to content

Commit

Permalink
1.0.8 release includes returning a score / result / outcome
Browse files Browse the repository at this point in the history
  • Loading branch information
adamzammit committed Oct 14, 2021
1 parent b32efbe commit f462e2a
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 20 deletions.
2 changes: 1 addition & 1 deletion LTI-Tool-Provider-Library-PHP
131 changes: 127 additions & 4 deletions LTIPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,65 @@
use IMSGlobal\LTI\OAuth\OAuthServer;
use IMSGlobal\LTI\OAuth\OAuthSignatureMethod_HMAC_SHA1;
use IMSGlobal\LTI\OAuth\OAuthRequest;
use IMSGlobal\LTI\ToolProvider;

class LTIResourceLink extends ToolProvider\ResourceLink
{
public function setConsumer($consumer)
{
$this->consumer = $consumer;
}
}

class LTIConsumer
{
public $secret;
private $key;
public function getKey()
{
return $this->key;
}
public function __construct($key,$secret)
{
$this->secret = $secret;
$this->key = $key;
}
}


class LTIResource
{
public $outcomeServiceURL;
public function getSetting($setting)
{
if ($setting == "lis_outcome_service_url") {
return $this->outcomeServiceURL;
}
return false;
}
public function __construct($outcomeserviceurl)
{
$this->outcomeServiceURL = $outcomeserviceurl;
}
}


class LTIUser
{
public $ltiResultSourcedId;
private $resourceLink;

public function getResourceLink()
{
return $this->resourceLink;
}

public function __construct($outcomeserviceurl,$sourceid) {
$this->ltiResultSourcedId = $sourceid;
$this->resourceLink = new LTIResource($outcomeserviceurl);
}
}


class LTIPlugin extends PluginBase
{
Expand All @@ -41,6 +100,7 @@ public function init()
$this->subscribe('newSurveySettings');
$this->subscribe('newDirectRequest'); //for LTI call
$this->subscribe('newUnsecureRequest', 'newDirectRequest'); //for LTI call
$this->subscribe('afterSurveyComplete'); //for LTI result return
}

protected $settings = [
Expand Down Expand Up @@ -86,6 +146,18 @@ public function init()
'label' => 'Optional: The LTI attributes that stores the last name of the participant',
'help' => 'Leave blank for no data to be stored. For openEdX and Canvas it appears to be lis_person_name_family. This maps to lastname in your participant table'
],
'sResultSourceAttribute' => [
'type' => 'string',
'default' => 'lis_result_sourcedid',
'label' => 'Optional: The LTI attributes that stores the result sourcedid - this is required when you want to return a result to the LMS. The default appears to be lis_result_sourcedid',
'help' => 'Leave blank for no data to be stored. This maps to ATTRIBUTE_5'
],
'sOutcomeServiceURLAttribute' => [
'type' => 'string',
'default' => 'lis_outcome_service_url',
'label' => 'Optional: The LTI attributes that stores the outcome service URL - this is required when you want to return a result to the LMS',
'help' => 'Leave blank for no data to be stored. This maps to ATTRIBUTE_6. The default appears to be lis_outcome_service_url'
],
'bDebugMode' => [
'type' => 'select',
'options' => [
Expand Down Expand Up @@ -150,7 +222,6 @@ public function newDirectRequest()

// Get the current token count
$tokenCount = $multipleCompletions ? 0 : (int) Token::model($surveyId)->countByAttributes($tokenQuery);

// If no token, then create a new one and start survey
if ($multipleCompletions || $tokenCount === 0) {
$firstname = $params[$this->get('sFirstNameAttribute', null, null, $this->settings['sFirstNameAttribute'])] ?? '';
Expand All @@ -164,8 +235,15 @@ public function newDirectRequest()
'lastname' => $lastname,
'email' => $email
];
$tokenReturn = [];
if (!empty($this->get('sReturnExpression', 'Survey', $surveyId))) {
$tokenReturn = [
'attribute_5' => $params[$this->get('sResultSourceAttribute', null, null, $this->settings['sResultSourceAttribute'])] ?? '',
'attribute_6' => $params[$this->get('sOutcomeServiceURLAttribute', null, null, $this->settings['sOutcomeServiceURLAttribute'])] ?? ''
];
}
$token = Token::create($surveyId);
$token->setAttributes(array_merge($tokenQuery, $tokenAdd));
$token->setAttributes(array_merge($tokenQuery, $tokenAdd, $tokenReturn));
$token->generateToken();

if (!$token->save()) {
Expand Down Expand Up @@ -199,6 +277,39 @@ public function newDirectRequest()
Yii::app()->getController()->redirect($redirectUrl);
}

/**
* If result return is enabled - send a result back
*/
public function afterSurveyComplete()
{
$event = $this->event;
$surveyId = $event->get('surveyId');

$rr = $this->get('sReturnExpression', 'Survey', $surveyId);

if (!empty($rr)) { //return the assessment value
$survey = Survey::model()->findByPk($surveyId);
if (isset($survey->tokenAttributes['attribute_5']) &&
isset($survey->tokenAttributes['attribute_6'])) {

$responseId = $event->get('responseId');
$response = $this->api->getResponse($surveyId, $responseId);
$token = Token::model($surveyId)->findByToken($response['token']);
$pr = LimeExpressionManager::ProcessString($rr, null, array(), 3, 1, false, false, true);
if (!empty($token->attribute_5) && !empty($token->attribute_6)) {
//send result back
$lti_outcome = new ToolProvider\Outcome($pr);
$resource_link = new LTIResourceLink();
$consumer = new LTIConsumer($this->get('sAuthKey', 'Survey', $surveyId),$this->get('sAuthSecret', 'Survey', $surveyId));
$resource_link->setConsumer($consumer);
$user = new LTIUser($token->attribute_6,$token->attribute_5);
$res = $resource_link->doOutcomesService(ToolProvider\ResourceLink::EXT_WRITE, $lti_outcome, $user);
}
}
}
}


/**
* Add setting on survey level: provide URL for LTI connector and check that tokens table / attributes exist
*/
Expand All @@ -214,11 +325,17 @@ public function beforeSurveySettings()
$info = 'Please activate the survey before continuing';
}

$rr = $this->get('sReturnExpression', 'Survey', $event->get('survey'));

if (!(isset($survey->tokenAttributes['attribute_1']) &&
isset($survey->tokenAttributes['attribute_2']) &&
isset($survey->tokenAttributes['attribute_3']) &&
isset($survey->tokenAttributes['attribute_4']))) {
$info = 'Please ensure the survey participant function has been enabled, and that there at least 4 attributes created';
isset($survey->tokenAttributes['attribute_4']))
|| ((!empty($rr)) &&
!(isset($survey->tokenAttributes['attribute_5']) &&
isset($survey->tokenAttributes['attribute_6'])))
) {
$info = 'Please ensure the survey participant function has been enabled, and that there at least ' . (empty($rr) ? "4" : "6") . ' attributes created';
}

$apiKey = $this->get('sAuthKey', 'Survey', $event->get('survey'));
Expand Down Expand Up @@ -267,6 +384,12 @@ public function beforeSurveySettings()
'label' => 'Allow a user in a course to complete this survey more than once',
'help' => 'This will allow multiple tokens to be created for the same user each time they go to access the survey'
],
'sReturnExpression' => [
'type' => 'string',
'label' => 'If returning a result, please enter the text or expression you wish to return here. Leave blank to not return a result. LMS systems typically accept a value between 0 and 1',
'help' => 'For example, {A1} will return whatever was stored in question A1, 1 will just return the score of 1',
'current' => $this->get('sReturnExpression', 'Survey', $event->get('survey')),
],
'sInfo' => [
'type' => 'info',
'label' => 'The URL to access this survey via the LTI Provider',
Expand Down
43 changes: 30 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# LTIPlugin
LimeSurvey Plugin that allows LimeSurvey to act as an LTI provider for tools such as Moodle, Canvas and openEdX. LimeSurvey will have access to the LMS course name and course and student identifier and allow the completion of a survey.
This plugin can also be used to return a grade/score/result back to the LMS based on a LimeSurvey expression. Therefore this plugin can be used to administer an exam or quiz in LimeSurvey which calculates a score and returns it automatically to the LMS.

## Installation

Download the zip from the [releases](https://github.com/adamzammit/LTIPlugin/releases) page and extract to your plugins folder. You can also clone directly from git: go to your plugins directory and type
```
git clone https://github.com/adamzammit/LTIPlugin.git LTIPlugin
git clone --recursive https://github.com/adamzammit/LTIPlugin.git LTIPlugin
```

## Requirements

- LimeSurvey version 3.x, 4.x
- Surveys need to be activated, with a participant table set up with at least 4 attributes avaiable (the plugin will use the first 4 attributes for LTI related data)
- LimeSurvey version 3.x, 4.x, 5.x
- Surveys need to be activated, with a participant table set up with at least 4 attributes avaiable, 6 attributes if you want to return a grade/result (the plugin will use the first 4 or 6 attributes for LTI related data)
- If your LTI Provider is running on HTTPS, then LimeSurvey must run over HTTPS also

## Configuration (LimeSurvey)
Expand All @@ -27,6 +28,32 @@ git clone https://github.com/adamzammit/LTIPlugin.git LTIPlugin
9. A random key and password should be generated - save the settings then a URL to access should be displayed (otherwise a message will be displayed notifying of the requirements for the LTI plugin as above)
10. Use the URL listed and the key and secret generated to set up your LMS to use LimeSUrvey as an LTI Provider (see below for examples)
11. By default a course participant will be able to complete the survey only once, and will return to the previous point of completion when visiting the survey again if not completed. If you want them to be able to complete multiple times for the same unit - please set "Allow a user in a course to complete this survey more than once" to "Yes"
12. If you want to return a grade/score backto the LMS - enter a text or expression in the return result box. You can just put the number 1 if you want 100% returned on completion, otherwise you can use any valid LimeSurvey expression to send a calculated value (this could be used to send back a score on an exam for example). The value should always be a floating point number between 0.0 and 1.0


### Configuration and usage (Canvas)

1. Edit your course
2. In your course, visit "Settings" then the tab "Apps", then "View App Configurations", then click on the green "+_App" button
3. Choose "Manual entry" for your configuration type
4. Name the app
5. Copy the consumer key, secret and Launch URL from the LimeSurvey LTIPlugin settings page (under Simple plugins in your LimeSurvey survey)

Now that the application is configured, you can:
1. Add a new item to a module in your course, and choose "External Tool" then the name of your app and don't forget to "publish"
2. If you add as an "Assignment" and you have the return result set in LimeSurvey simple plugin settings, the score will be returned

If you have recieved a "CSRF Token" error in LimeSurvey you may need to check the box "Load in a new tab" when editing the item in Canvas

### Configuration and Usage (Moodle)

1. Add a new "Activity or resource"
2. Choose "External Tool"
3. The "Tool URL" is the URL that appears on the "Settings for plugin LTI Plugin" page for your survey
4. Click on "Show more" under "General"
5. The "Consumer key" is the key that appears on the LTI plugin settings page
6. The "Shared secret" is the secret that appears on the LTI plugin settings page


### Configuration (OpenEdX)

Expand All @@ -45,16 +72,6 @@ git clone https://github.com/adamzammit/LTIPlugin.git LTIPlugin

If you have recieved a "CSRF Token" error in LimeSurvey you may need to set "LTI Launch Target" to "New Window" in OpenEdX to overcome this.

### Configuration and Usage (Moodle)

1. Add a new "Activity or resource"
2. Choose "External Tool"
3. The "Tool URL" is the URL that appears on the "Settings for plugin LTI Plugin" page for your survey
4. Click on "Show more" under "General"
5. The "Consumer key" is the key that appears on the LTI plugin settings page
6. The "Shared secret" is the secret that appears on the LTI plugin settings page


### Usage (OpenEdX)

1. Add a new "Unit"
Expand Down
4 changes: 2 additions & 2 deletions config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
<name>LTIPlugin</name>
<type>plugin</type>
<creationDate>2020-08-27</creationDate>
<lastUpdate>2021-10-13</lastUpdate>
<lastUpdate>2021-10-14</lastUpdate>
<author>Adam Zammit</author>
<authorUrl>https://acspri.org.au/</authorUrl>
<authorEmail>software@acspri.org.au</authorEmail>
<supportUrl>https://acspri.org.au/</supportUrl>
<version>1.0.7</version>
<version>1.0.8</version>
<license>GNU General Public License v3.0</license>
<description><![CDATA[Make LimeSurvey an LTI provider for tools that support the LTI API such as Canvas and OpenEdX]]></description>
</metadata>
Expand Down

0 comments on commit f462e2a

Please sign in to comment.