izumi-kun / lti-tool-provider-library-php Goto Github PK
View Code? Open in Web Editor NEWThis project forked from 1edtech/lti-tool-provider-library-php
LTI Tool Provider library for PHP
License: Apache License 2.0
This project forked from 1edtech/lti-tool-provider-library-php
LTI Tool Provider library for PHP
License: Apache License 2.0
In the 1st launch with the given context and resource link getRecordId() returns null because the context is not yet in the database. That is why lti2_resource_link.context_pk is null.
Following link launch fixes the situation.
Ideally, the context should be set to resource link after the context was saved to the database e.g.
on the line 1155 reset the context
if (!empty($this->context)) {
$this->resourceLink->setContextId($this->context->getRecordId());
}
LTI Version | Date of the Last New Certification | Date of the Last Recertification | Market Availability Through* | Comments | |
---|---|---|---|---|---|
1.0 | Basic Launch | 12/31/2019 | 12/31/2019 | 12/31/2020 | Deprecated |
1.0.1 | Basic Launch with Updated Security *** | 6/30/2020 | 6/30/2021 | 6/30/2022 | |
1.1 | Basic Outcomes | 12/31/2019 | 12/31/2019 | 12/31/2020 | Deprecated, and related services** |
1.1.1 | Minor update to roles | 12/31/2019 | 12/31/2019 | 12/31/2020 | Deprecated |
1.1.2 | Basic Outcomes with Updated Security *** | 06/30/2020 | 06/30/2021 | 06/30/2022 | |
1.2 | Tool Consumer Profile | 12/31/2019 | 12/31/2019 | 12/31/2020 | Deprecated |
1.3 | LTI Advantage Core (currently LTI 1.3) | Ongoing | Ongoing | Ongoing | Recommended LTI Version |
2.0 | Tool Consumer, Proxy and Auto-Registration | 12/31/2019 | 12/31/2019 | 12/30/2020 | Deprecated |
* Certifications and recertifications have a minimum 12-month validity period and therefore may be active and valid for up to 12 months after certification.
** Associated LTI services that are also to be deprecated, Deep Linking v1.0, Names and Role Provisioning Service v1.0, Basic Outcomes v1.0.
*** Link to documentation https://www.imsglobal.org/spec/lti/security-update/v1p0
This commit: 12c4c03
Broke our LTI2 Registration flow. We now get: Required capability not offered: oauth_consumer_key, resource_link_id, roles, user_id
The latest commit doesn't check against "Array of message types to which the constraint applies (optional, default is all)" (see: \IMSGlobal\LTI\ToolProvider\ToolProvider::setParameterConstraint)
Code snippets.
$_POST['lti_message_type'] === 'ToolProxyRegistrationRequest'
$tool->setParameterConstraint( 'oauth_consumer_key', true, 50, [ 'basic-lti-launch-request', 'ContentItemSelectionRequest' ] );
$tool->setParameterConstraint( 'resource_link_id', true, 50, [ 'basic-lti-launch-request' ] );
$tool->setParameterConstraint( 'user_id', true, 50, [ 'basic-lti-launch-request' ] );
$tool->setParameterConstraint( 'roles', true, null, [ 'basic-lti-launch-request' ] );
Tested using:
https://community.blackboard.com/docs/DOC-4242-using-the-developer-ami
When doing a LTI2 registration with Blackboard, the LMS errors with:
{"status":400,"message":"Could not read document: Can not deserialize instance of out of START_OBJECT token\
at [Source: @3fe45ab9; line: 1, column: 1263] (through reference chain: [\\"tool_profile\\"]->[\\"resource_handler\\"]->[0]->[\\"icon_info\\"]); nested exception is : Can not deserialize instance of out of START_OBJECT token\
at [Source: @3fe45ab9; line: 1, column: 1263] (through reference chain: [\\"tool_profile\\"]->[\\"resource_handler\\"]->[0]->[\\"icon_info\\"])","extraInfo":"b711870c01384a0cb406dbda5c4ef919"}
If I If comment out the icon_info node then the LTI2 registration works fine.
// $this->icon_info = new \stdClass;
// $this->icon_info->default_location = new \stdClass;
// $this->icon_info->default_location->path = $resourceHandler->icon;
// $this->icon_info->key = "{$resourceHandler->item->id}.icon.path";
IMHO the icon is fine and follows the standard this is a bug in Blackboard.
https://www.imsglobal.org/lti/model/uml/purl.imsglobal.org/vocab/lti/v2/lti/index.html#IconInfo
I emailed developers<at>blackboard.com
with this info and am waiting for a reply. If they do nothing then it would be nice to have the option of not building icon_info somehow....
public function send(HTTPMessage $message)
{
$opts = [
'method' => $message->method,
'content' => $message->request,
'ignore_errors' => true
];
if (!empty($message->requestHeaders)) {
$opts['header'] = $message->requestHeaders;
}
try {
$ctx = stream_context_create(['http' => $opts]);
$fp = @fopen($message->url, 'rb', false, $ctx);
if ($fp) {
$resp = @stream_get_contents($fp);
$ok = $resp !== false;
if ($ok) {
$message->response = $resp;
if (isset($http_response_header[0])) {
$message->responseHeaders = $http_response_header;
if( preg_match( "/HTTP\/\d.\d\s+(\d+)/", $message->responseHeaders[0], $out )) {
$message->status = $out[1];
}
$ok = $message->status < 400;
if (!$ok) {
$message->error = $message->responseHeaders[0];
}
}
return $ok;
}
}
} catch (\Exception $e){
$message->error = $e->getMessage();
return false;
}
$message->error = error_get_last()["message"];
return false;
}
My default PHP HTTP wrapper requires "Accept" header e.g. "Accept: /" otherwise it will return "HTTP/1.1 406 Not Acceptable" so maybe part of client functionality should be that at adding "Accept: /" if no accept header exists.
7.1 Requests for a Tool Consumer Profile
A request for a Tool Consumer profile is made by sending a GET request to the URL provided in the requested custom parameter from a basic launch request for the same Tool Consumer. A query parameter should be added to the URL to specify the LTI version for which the profile is being requested; in this case a value of LTI-1p2 should be used. For example:
GET /lti/ToolConsumerProfile?lti_version=LTI-1p2 HTTP/1.0
.....
Maybe somethin like this:
$url = $_POST['custom_tc_profile_url'];
$url .= (strpos($url, "?") !== false ? "&" : "?")."lti_version=".$_POST['lti_version'];
$http = new HTTPMessage($url, 'GET', null, 'Accept: application/vnd.ims.lti.v2.toolconsumerprofile+json');
Test 7.1 Valid request (passed)
Applies to: 1.2 [required]
Expected result: This test checks the request made for the Tool Consumer Profile to ensure it is valid
I watch this repo as the authority for LTI-Tool-Provider-Library-PHP.
Two emails came in about pull requests and it took me a few minutes to figure out where the PRs were coming from (Because it's the morning and I need a coffee? They're coming from markn86 and not this repo?)
It would have been less confusing if the stale branches were deleted.
Keep master because it's origin, or maybe rename origin, etc.
Thank you for your consideration.
Should be changed to something like:
$this->ok = $_POST['lti_version'] == self::LTI_VERSION1;
if (!$this->ok) {
$this->reason = 'Wrong lti_version parameter.';
} else {
$this->ok = isset($_POST['resource_link_id']) && (strlen(trim($_POST['resource_link_id'])) > 0);
if (!$this->ok) {
$this->reason = 'Missing resource link ID.';
}
}
I am new to the LTI, I have not found much information about the structure they should have and the operation of the protocol.
I would like to be able to return a qualification to an LMS (Moodle) someone has some extremely simple LTI that can serve as a guideline?
Related:
I'm using your fork for an LTI Provider plugin i'm working on. Thanks for all your fixes and composer support. Very nice.
I need access to $consumer->toolProxy
. In my database, AFAIK, lti2_consumer.tool_proxy is stored as a JSON string just like lti2_consumer.profile. Everywhere I see >toolProxy =
I see:
$consumer->profile = json_decode($row['profile']);
$consumer->toolProxy = $row['tool_proxy'];
(Seen in: ToolProvider/DataConnector/DataConnector_mysql.php
and ToolProvider/DataConnector/DataConnector_pdo.php
)
One is coverted into an object, the other is not. I think it should be:
$consumer->profile = json_decode($row['profile']);
$consumer->toolProxy = json_decode($row['tool_proxy']);
Or maybe something like:
function isJson($string) {
json_decode($string);
return (json_last_error() == JSON_ERROR_NONE);
}
// ... snip ...
$consumer->profile = isJson( $row['profile'] ) ? json_decode( $row['profile'] ) : $row['profile'];
$consumer->toolProxy = isJson( $row['tool_proxy'] ) ? json_decode( $row['tool_proxy'] ) : $row['tool_proxy'];
What do you think?
PS: $consumer->toolProxy
is declared dynamically. No stub in ToolProvider/ToolConsumer.php
. This makes it harder to code because my IDE doesn't recognize that field. It would be nice to add it.
Hello, thanks for this fork. I'm doing my first implementation of LTI and was glad to come across this since the original is now abandoned.
I am trying to integrate this into an existing Symfony application and it's a bit of a challenge using the ToolProvider class. I'm still very early on but what's hanging me up comes down to being unable to override some of these private methods.
For example, result()
directly calls header()
to redirect, and other times it does inline echo statements. That makes it very hard to try and pass data to views, add logging, etc.
At first I thought about using output buffering to capture the echos but the inline header()
calls make that problematic.
I could just fork this repository and handle it that way, but I thought maybe others could benefit. Is there a good reason to keep these private? Has anyone else integrated this into a framework like Symfony and worked around this in other ways?
Thanks much!
Pull request #10,
New code call urldecode on all of the POST properties effectively substituting + sign for the white space in OAuth Signature. Thus causing all signatures that have + to be invalid.
I will see if have time to make pull request.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.