tao-test/app/taoLti/models/classes/LtiLaunchData.php

478 lines
15 KiB
PHP

<?php
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2013-2019 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT);
*
*/
namespace oat\taoLti\models\classes;
use common_http_Request;
use core_kernel_classes_Resource;
use OAT\Library\Lti1p3Core\Message\Payload\LtiMessagePayloadInterface;
use oat\taoLti\models\classes\LtiMessages\LtiErrorMessage;
use oat\taoLti\models\classes\Platform\LtiPlatform;
use tao_helpers_Request;
use oat\oatbox\log\LoggerAwareTrait;
use Psr\Http\Message\ServerRequestInterface;
class LtiLaunchData implements \JsonSerializable
{
use LoggerAwareTrait;
const OAUTH_CONSUMER_KEY = 'oauth_consumer_key';
const RESOURCE_LINK_ID = 'resource_link_id';
const RESOURCE_LINK_TITLE = 'resource_link_title';
const CONTEXT_ID = 'context_id';
const CONTEXT_LABEL = 'context_label';
const CONTEXT_TITLE = 'context_title';
const USER_ID = 'user_id';
const ROLES = 'roles';
const LIS_PERSON_NAME_GIVEN = 'lis_person_name_given';
const LIS_PERSON_NAME_FAMILY = 'lis_person_name_family';
const LIS_PERSON_NAME_FULL = 'lis_person_name_full';
const LIS_PERSON_CONTACT_EMAIL_PRIMARY = 'lis_person_contact_email_primary';
const LAUNCH_PRESENTATION_LOCALE = 'launch_presentation_locale';
const LAUNCH_PRESENTATION_RETURN_URL = 'launch_presentation_return_url';
const TOOL_CONSUMER_INSTANCE_ID = 'tool_consumer_instance_id';
const TOOL_CONSUMER_INSTANCE_NAME = 'tool_consumer_instance_name';
const TOOL_CONSUMER_INSTANCE_DESCRIPTION = 'tool_consumer_instance_description';
const LTI_VERSION = 'lti_version';
const LTI_MESSAGE_TYPE = 'lti_message_type';
const LIS_RESULT_SOURCEDID = 'lis_result_sourcedid';
const LIS_OUTCOME_SERVICE_URL = 'lis_outcome_service_url';
// review mode
const LTI_SHOW_SCORE = 'custom_show_score';
const LTI_SHOW_CORRECT = 'custom_show_correct';
/**
* LTI variables
*
* @var array
*/
private $variables;
/**
* Custom parameters of the LTI call
*
* @var array
*/
private $customParams;
/**
* @var core_kernel_classes_Resource
*/
private $ltiConsumer;
/**
* Spawns an LtiSession
*
* @param array $ltiVariables
* @param array $customParameters
*/
public function __construct(array $ltiVariables, array $customParameters)
{
$this->variables = $ltiVariables;
$this->customParams = $customParameters;
}
/**
* @param array $json
* @return LtiLaunchData
*/
public static function fromJsonArray($json)
{
return new static($json['variables'], $json['customParams']);
}
/**
*
* @param common_http_Request $request
* @return LtiLaunchData
* @throws \ResolverException
*/
public static function fromPsrRequest(ServerRequestInterface $request)
{
$extra = self::getParametersFromUrl($request->getUri()->__toString());
$combined = array_merge($request->getQueryParams(), $request->getParsedBody());
return new static($combined, $extra);
}
/**
*
* @param common_http_Request $request
* @return LtiLaunchData
* @throws \ResolverException
*/
public static function fromRequest(common_http_Request $request)
{
$extra = self::getParametersFromUrl($request->getUrl());
return new static($request->getParams(), $extra);
}
public static function fromLti1p3MessagePayload(LtiMessagePayloadInterface $ltiMessagePayload, LtiPlatform $platform = null)
{
$variables[self::OAUTH_CONSUMER_KEY] = '';
$variables[self::RESOURCE_LINK_ID] = $ltiMessagePayload->getResourceLink() ? $ltiMessagePayload->getResourceLink()->getIdentifier() : null;
$variables[self::RESOURCE_LINK_TITLE] = $ltiMessagePayload->getResourceLink() ? $ltiMessagePayload->getResourceLink()->getTitle() : null;
$variables[self::CONTEXT_ID] = $ltiMessagePayload->getContext() ? $ltiMessagePayload->getContext()->getIdentifier() : null;
$variables[self::CONTEXT_LABEL] = $ltiMessagePayload->getContext() ? $ltiMessagePayload->getContext()->getLabel() : null;
$variables[self::CONTEXT_TITLE] = $ltiMessagePayload->getContext() ? $ltiMessagePayload->getContext()->getTitle() : null;
$variables[self::USER_ID] = $ltiMessagePayload->getUserIdentity() ? $ltiMessagePayload->getUserIdentity()->getIdentifier() : null;
$variables[self::ROLES] = implode(',', $ltiMessagePayload->getRoles());
$variables[self::LIS_PERSON_NAME_GIVEN] = $ltiMessagePayload->getUserIdentity() ? $ltiMessagePayload->getUserIdentity()->getGivenName() : null;
$variables[self::LIS_PERSON_NAME_FAMILY] = $ltiMessagePayload->getUserIdentity() ? $ltiMessagePayload->getUserIdentity()->getFamilyName() : null;
$variables[self::LIS_PERSON_NAME_FULL] = $ltiMessagePayload->getUserIdentity() ? $ltiMessagePayload->getUserIdentity()->getName() : null;
$variables[self::LIS_PERSON_CONTACT_EMAIL_PRIMARY] = $ltiMessagePayload->getUserIdentity() ? $ltiMessagePayload->getUserIdentity()->getEmail() : null;
$variables[self::LAUNCH_PRESENTATION_LOCALE] = $ltiMessagePayload->getLaunchPresentation() ? $ltiMessagePayload->getLaunchPresentation()->getLocale(): null;
$variables[self::LAUNCH_PRESENTATION_RETURN_URL] = $ltiMessagePayload->getLaunchPresentation() ? $ltiMessagePayload->getLaunchPresentation()->getReturnUrl() : null;
$variables[self::LTI_VERSION] = $ltiMessagePayload->getVersion();
$variables[self::LTI_MESSAGE_TYPE] = $ltiMessagePayload->getMessageType();
$variables[self::LIS_RESULT_SOURCEDID] = $ltiMessagePayload->getBasicOutcome() ? $ltiMessagePayload->getBasicOutcome()->getLisResultSourcedId() : null;
$variables[self::LIS_OUTCOME_SERVICE_URL] = $ltiMessagePayload->getBasicOutcome() ? $ltiMessagePayload->getBasicOutcome()->getLisOutcomeServiceUrl() : null;
if ($platform) {
// we need to have inner platform ID
$variables[self::TOOL_CONSUMER_INSTANCE_ID] = $platform->getId();
if ($platformFromClaim = $ltiMessagePayload->getPlatformInstance()) {
$variables[self::TOOL_CONSUMER_INSTANCE_NAME] = $platformFromClaim->getName();
$variables[self::TOOL_CONSUMER_INSTANCE_DESCRIPTION] = $platformFromClaim->getDescription();
} else {
$variables[self::TOOL_CONSUMER_INSTANCE_NAME] = $platform->getLabel();
$variables[self::TOOL_CONSUMER_INSTANCE_DESCRIPTION] = $platform->getLabel();
}
}
$customParams = $ltiMessagePayload->getCustom();
// review mode
if (isset($customParams[self::LTI_SHOW_SCORE])) {
$variables[self::LTI_SHOW_SCORE] = true;
}
if (isset($customParams[self::LTI_SHOW_CORRECT])) {
$variables[self::LTI_SHOW_CORRECT] = true;
}
return new static($variables, $customParams);
}
/**
* @param string $url
* @return array
* @throws \ResolverException
*/
private static function getParametersFromUrl($url)
{
$returnValue = [];
// get parameters
parse_str(parse_url($url, PHP_URL_QUERY), $returnValue);
// encoded in url
$parts = explode('/', tao_helpers_Request::getRelativeUrl($url), 4);
if (count($parts) == 4) {
list ($extension, $module, $action, $codedUri) = $parts;
$base64String = base64_decode($codedUri);
if ($base64String !== false) {
// old serialised url
if (substr($base64String, 0, strlen('a:')) == 'a:') {
$additionalParams = unserialize($base64String);
} else {
$additionalParams = json_decode($base64String, true);
}
if ($additionalParams !== false && is_array($additionalParams)) {
foreach ($additionalParams as $key => $value) {
$returnValue[$key] = $value;
}
}
}
}
return $returnValue;
}
/**
* @param string $key
* @return mixed|null
*/
public function getCustomParameter($key)
{
return isset($this->customParams[$key]) ? $this->customParams[$key] : null;
}
/**
* Get all custom parameters provided during launch.
*
* @return array
*/
public function getCustomParameters()
{
return $this->customParams;
}
/**
* Get all lti variables provided during launch.
*
* @return array
*/
public function getVariables()
{
return $this->variables;
}
/**
* @return mixed
* @throws LtiVariableMissingException
*/
public function getResourceLinkID()
{
return $this->getVariable(self::RESOURCE_LINK_ID);
}
/**
* @param $key
* @return mixed
* @throws LtiVariableMissingException
*/
public function getVariable($key)
{
if (isset($this->variables[$key])) {
return $this->variables[$key];
} else {
throw new LtiVariableMissingException($key);
}
}
/**
* @param string $key
* @return boolean mixed
*
* @throws LtiException
* @throws LtiVariableMissingException
*/
public function getBooleanVariable($key)
{
$var = mb_strtolower($this->getVariable($key));
if ($var === 'true') {
return true;
} elseif ($var === 'false') {
return false;
} else {
throw new LtiInvalidVariableException(
'Invalid value of `' . $key . '` variable, boolean string expected.',
LtiErrorMessage::ERROR_INVALID_PARAMETER
);
}
}
/**
* @return mixed|string
* @throws LtiVariableMissingException
*/
public function getResourceLinkTitle()
{
if ($this->hasVariable(self::RESOURCE_LINK_TITLE)) {
return $this->getVariable(self::RESOURCE_LINK_TITLE);
} else {
return __('link');
}
}
public function hasVariable($key)
{
return isset($this->variables[$key]);
}
/**
* @return mixed
* @throws LtiVariableMissingException
*/
public function getUserID()
{
return $this->getVariable(self::USER_ID);
}
/**
* @return mixed
*/
public function getUserGivenName()
{
if ($this->hasVariable(static::LIS_PERSON_NAME_GIVEN)) {
return $this->getVariable(static::LIS_PERSON_NAME_GIVEN);
}
}
/**
* @return mixed
*/
public function getUserFamilyName()
{
if ($this->hasVariable(static::LIS_PERSON_NAME_FAMILY)) {
return $this->getVariable(static::LIS_PERSON_NAME_FAMILY);
}
}
/**
* @return mixed
* @throws LtiVariableMissingException
*/
public function getUserFullName()
{
if ($this->hasVariable(self::LIS_PERSON_NAME_FULL)) {
return $this->getVariable(self::LIS_PERSON_NAME_FULL);
}
}
/**
* @return mixed
* @throws LtiVariableMissingException
*/
public function getUserEmail()
{
return $this->getVariable(self::LIS_PERSON_CONTACT_EMAIL_PRIMARY);
}
/**
* @return array
* @throws LtiVariableMissingException
*/
public function getUserRoles()
{
return explode(',', $this->getVariable(self::ROLES));
}
public function hasLaunchLanguage()
{
return $this->hasVariable(self::LAUNCH_PRESENTATION_LOCALE);
}
/**
* @return mixed
* @throws LtiVariableMissingException
*/
public function getLaunchLanguage()
{
return $this->getVariable(self::LAUNCH_PRESENTATION_LOCALE);
}
/**
* Tries to return the tool consumer name
*
* Returns null if no name found
*
* @return string
* @throws LtiVariableMissingException
*/
public function getToolConsumerName()
{
$consumerName = null;
if ($this->hasVariable(self::TOOL_CONSUMER_INSTANCE_NAME)) {
$consumerName = $this->getVariable(self::TOOL_CONSUMER_INSTANCE_NAME);
}
if (
$consumerName === null
&& $this->hasVariable(self::TOOL_CONSUMER_INSTANCE_DESCRIPTION)
) {
$consumerName = $this->getVariable(self::TOOL_CONSUMER_INSTANCE_DESCRIPTION);
}
return $consumerName;
}
/**
* @return core_kernel_classes_Resource
* @throws LtiVariableMissingException
*/
public function getLtiConsumer()
{
if (is_null($this->ltiConsumer)) {
$dataStore = new \tao_models_classes_oauth_DataStore();
$this->ltiConsumer = $dataStore->findOauthConsumerResource($this->getOauthKey())->getUri();
}
return new \core_kernel_classes_Resource($this->ltiConsumer);
}
/**
* @return mixed
* @throws LtiVariableMissingException
*/
public function getOauthKey()
{
return $this->getVariable(self::OAUTH_CONSUMER_KEY);
}
/**
* @return bool
* @throws LtiException
*/
public function hasReturnUrl()
{
if ($this->hasVariable(self::LAUNCH_PRESENTATION_RETURN_URL)) {
$returnUrl = $this->getReturnUrl();
if (!empty($returnUrl)) {
if (filter_var($returnUrl, FILTER_VALIDATE_URL)) {
return true;
} else {
$this->logWarning("Invalid LTI Return URL '${returnUrl}'.");
}
}
}
return false;
}
/**
* Return the returnUrl to the tool consumer
*
* @return string
* @throws LtiException
*/
public function getReturnUrl()
{
return $this->getVariable(self::LAUNCH_PRESENTATION_RETURN_URL);
}
/**
* Specify data which should be serialized to JSON
* @link https://php.net/manual/en/jsonserializable.jsonserialize.php
* @return mixed data which can be serialized by <b>json_encode</b>,
* which is a value of any type other than a resource.
* @since 5.4.0
*/
public function jsonSerialize()
{
return [
'variables' => $this->variables,
'customParams' => $this->customParams,
];
}
}