LTI Allow create tools when there is no key/secret available for launch - refs BT#13469

pull/2731/head
Angel Fernando Quiroz Campos 7 years ago
parent 585ea84fba
commit b8bb53d154
  1. 6
      plugin/ims_lti/Entity/ImsLtiTool.php
  2. 44
      plugin/ims_lti/ImsLtiPlugin.php
  3. 12
      plugin/ims_lti/README.md
  4. 36
      plugin/ims_lti/configure.php
  5. 35
      plugin/ims_lti/create.php
  6. 16
      plugin/ims_lti/edit.php
  7. 32
      plugin/ims_lti/form.php
  8. 2
      plugin/ims_lti/lang/english.php
  9. 2
      plugin/ims_lti/lang/spanish.php
  10. 4
      plugin/ims_lti/src/Form/FrmAdd.php
  11. 4
      plugin/ims_lti/src/Form/FrmEdit.php

@ -45,13 +45,13 @@ class ImsLtiTool
/** /**
* @var string * @var string
* *
* @ORM\Column(name="consumer_key", type="string") * @ORM\Column(name="consumer_key", type="string", nullable=true)
*/ */
private $consumerKey = ''; private $consumerKey = '';
/** /**
* @var string * @var string
* *
* @ORM\Column(name="shared_secret", type="string") * @ORM\Column(name="shared_secret", type="string", nullable=true)
*/ */
private $sharedSecret = ''; private $sharedSecret = '';
/** /**
@ -117,6 +117,8 @@ class ImsLtiTool
$this->gradebookEval =null; $this->gradebookEval =null;
$this->privacy = null; $this->privacy = null;
$this->children = new ArrayCollection(); $this->children = new ArrayCollection();
$this->consumerKey = null;
$this->sharedSecret = null;
} }
/** /**

@ -125,8 +125,8 @@ class ImsLtiPlugin extends Plugin
name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL,
description LONGTEXT DEFAULT NULL, description LONGTEXT DEFAULT NULL,
launch_url VARCHAR(255) NOT NULL, launch_url VARCHAR(255) NOT NULL,
consumer_key VARCHAR(255) NOT NULL, consumer_key VARCHAR(255) DEFAULT NULL,
shared_secret VARCHAR(255) NOT NULL, shared_secret VARCHAR(255) DEFAULT NULL,
custom_params LONGTEXT DEFAULT NULL, custom_params LONGTEXT DEFAULT NULL,
active_deep_linking TINYINT(1) DEFAULT \'0\' NOT NULL, active_deep_linking TINYINT(1) DEFAULT \'0\' NOT NULL,
privacy LONGTEXT DEFAULT NULL, privacy LONGTEXT DEFAULT NULL,
@ -466,4 +466,44 @@ class ImsLtiPlugin extends Plugin
return !empty($tool); return !empty($tool);
} }
/**
* @param string $configUrl
*
* @return string
* @throws Exception
*/
public function getLaunchUrlFromCartridge($configUrl)
{
$options = [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_POST => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => '',
CURLOPT_SSL_VERIFYPEER => false,
];
$ch = curl_init($configUrl);
curl_setopt_array($ch, $options);
$content = curl_exec($ch);
$errno = curl_errno($ch);
curl_close($ch);
if ($errno !== 0) {
throw new Exception($this->get_lang('NoAccessToUrl'));
}
$xml = new SimpleXMLElement($content);
$result = $xml->xpath('blti:launch_url');
if (empty($result)) {
throw new Exception($this->get_lang('LaunchUrlNotFound'));
}
$launchUrl = $result[0];
return (string) $launchUrl;
}
} }

@ -1,7 +1,7 @@
IMS/LTI plugin IMS/LTI plugin
=== ===
Version 1.3 (beta) Version 1.4 (beta)
This plugin is meant to be later integrated into Chamilo (in a major version This plugin is meant to be later integrated into Chamilo (in a major version
release). release).
@ -34,6 +34,9 @@ external tool.
* Privacy settings added. Allow to indicate id the launcher's data * Privacy settings added. Allow to indicate id the launcher's data
should be sent in request. should be sent in request.
**v1.4**
* Allow create external tools when there is no key/secret available for launch
# Installation # Installation
1. Install the plugin from Plugin page 1. Install the plugin from Plugin page
@ -75,3 +78,10 @@ CREATE INDEX IDX_C5E47F7C727ACA70 ON plugin_ims_lti_tool (parent_id);
```sql ```sql
ALTER TABLE plugin_ims_lti_tool ADD privacy LONGTEXT DEFAULT NULL; ALTER TABLE plugin_ims_lti_tool ADD privacy LONGTEXT DEFAULT NULL;
``` ```
**To v.4**
```sql
ALTER TABLE plugin_ims_lti_tool
CHANGE consumer_key consumer_key VARCHAR(255) DEFAULT NULL,
CHANGE shared_secret shared_secret VARCHAR(255) DEFAULT NULL;
```

@ -49,15 +49,6 @@ switch ($action) {
->setDescription( ->setDescription(
empty($formValues['description']) ? null : $formValues['description'] empty($formValues['description']) ? null : $formValues['description']
) )
->setLaunchUrl(
$baseTool ? $baseTool->getLaunchUrl() : $formValues['launch_url']
)
->setConsumerKey(
$baseTool ? $baseTool->getConsumerKey() : $formValues['consumer_key']
)
->setSharedSecret(
$baseTool ? $baseTool->getSharedSecret() : $formValues['shared_secret']
)
->setCustomParams( ->setCustomParams(
empty($formValues['custom_params']) ? null : $formValues['custom_params'] empty($formValues['custom_params']) ? null : $formValues['custom_params']
) )
@ -69,6 +60,33 @@ switch ($action) {
!empty($formValues['share_picture']) !empty($formValues['share_picture'])
); );
if ($baseTool) {
$tool
->setLaunchUrl($baseTool->getLaunchUrl())
->setConsumerKey($baseTool->getConsumerKey())
->setSharedSecret($baseTool->getSharedSecret());
} else {
if (empty($formValues['consumer_key']) && empty($formValues['shared_secret'])) {
try {
$launchUrl = $plugin->getLaunchUrlFromCartridge($formValues['launch_url']);
} catch (Exception $e) {
Display::addFlash(
Display::return_message($e->getMessage(), 'error')
);
header('Location: '.api_get_self().'?'.api_get_cidreq());
exit;
}
$tool->setLaunchUrl($launchUrl);
} else {
$tool
->setLaunchUrl($formValues['launch_url'])
->setConsumerKey($formValues['consumer_key'])
->setSharedSecret($formValues['shared_secret']);
}
}
if (null === $baseTool || if (null === $baseTool ||
($baseTool && !$baseTool->isActiveDeepLinking()) ($baseTool && !$baseTool->isActiveDeepLinking())
) { ) {

@ -21,11 +21,12 @@ if ($form->validate()) {
$externalTool = new ImsLtiTool(); $externalTool = new ImsLtiTool();
$externalTool $externalTool
->setName($formValues['name']) ->setName($formValues['name'])
->setDescription($formValues['description']) ->setDescription(
->setLaunchUrl($formValues['launch_url']) empty($formValues['description']) ? null : $formValues['description']
->setConsumerKey($formValues['consumer_key']) )
->setSharedSecret($formValues['shared_secret']) ->setCustomParams(
->setCustomParams($formValues['custom_params']) empty($formValues['custom_params']) ? null : $formValues['custom_params']
)
->setCourse(null) ->setCourse(null)
->setActiveDeepLinking( ->setActiveDeepLinking(
isset($formValues['deep_linking']) isset($formValues['deep_linking'])
@ -36,6 +37,30 @@ if ($form->validate()) {
isset($formValues['share_picture']) isset($formValues['share_picture'])
); );
if (empty($formValues['consumer_key']) && empty($formValues['shared_secret'])) {
try {
$launchUrl = $plugin->getLaunchUrlFromCartridge($formValues['launch_url']);
} catch (Exception $e) {
Display::addFlash(
Display::return_message($e->getMessage(), 'error')
);
header('Location: '.api_get_path(WEB_PLUGIN_PATH).'ims_lti/admin.php');
exit;
}
$externalTool->setLaunchUrl($launchUrl);
} else {
$externalTool
->setLaunchUrl($formValues['launch_url'])
->setConsumerKey(
empty($formValues['consumer_key']) ? null : $formValues['consumer_key']
)
->setSharedSecret(
empty($formValues['shared_secret']) ? null : $formValues['shared_secret']
);
}
$em->persist($externalTool); $em->persist($externalTool);
$em->flush(); $em->flush();

@ -37,8 +37,12 @@ if ($form->validate()) {
$tool $tool
->setName($formValues['name']) ->setName($formValues['name'])
->setDescription($formValues['description']) ->setDescription(
->setCustomParams($formValues['custom_params']) empty($formValues['description']) ? null : $formValues['description']
)
->setCustomParams(
empty($formValues['custom_params']) ? null : $formValues['custom_params']
)
->setPrivacy( ->setPrivacy(
!empty($formValues['share_name']), !empty($formValues['share_name']),
!empty($formValues['share_email']), !empty($formValues['share_email']),
@ -48,8 +52,12 @@ if ($form->validate()) {
if (null === $tool->getParent()) { if (null === $tool->getParent()) {
$tool $tool
->setLaunchUrl($formValues['launch_url']) ->setLaunchUrl($formValues['launch_url'])
->setConsumerKey($formValues['consumer_key']) ->setConsumerKey(
->setSharedSecret($formValues['shared_secret']); empty($formValues['consumer_key']) ? null : $formValues['consumer_key']
)
->setSharedSecret(
empty($formValues['shared_secret']) ? null : $formValues['shared_secret']
);
} }
if (null === $tool->getParent() || if (null === $tool->getParent() ||

@ -112,19 +112,23 @@ $params['tool_consumer_instance_contact_email'] = api_get_setting('emailAdminist
$params += $tool->parseCustomParams(); $params += $tool->parseCustomParams();
$oauth = new OAuthSimple( if (!empty($tool->getConsumerKey()) && !empty($tool->getSharedSecret())) {
$tool->getConsumerKey(), $oauth = new OAuthSimple(
$tool->getSharedSecret() $tool->getConsumerKey(),
); $tool->getSharedSecret()
$oauth->setAction('post'); );
$oauth->setSignatureMethod('HMAC-SHA1'); $oauth->setAction('post');
$oauth->setParameters($params); $oauth->setSignatureMethod('HMAC-SHA1');
$result = $oauth->sign(array( $oauth->setParameters($params);
'path' => $tool->getLaunchUrl(), $result = $oauth->sign(array(
'parameters' => array( 'path' => $tool->getLaunchUrl(),
'oauth_callback' => 'about:blank' 'parameters' => array(
) 'oauth_callback' => 'about:blank'
)); )
));
$params = $result['parameters'];
}
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@ -135,7 +139,7 @@ $result = $oauth->sign(array(
<form action="<?php echo $tool->getLaunchUrl() ?>" name="ltiLaunchForm" method="post" <form action="<?php echo $tool->getLaunchUrl() ?>" name="ltiLaunchForm" method="post"
encType="application/x-www-form-urlencoded"> encType="application/x-www-form-urlencoded">
<?php <?php
foreach ($result["parameters"] as $key => $values) { //Dump parameters foreach ($params as $key => $values) {
echo '<input type="hidden" name="'.$key.'" value="'.htmlspecialchars($values).'" />'.PHP_EOL; echo '<input type="hidden" name="'.$key.'" value="'.htmlspecialchars($values).'" />'.PHP_EOL;
} }
?> ?>

@ -36,3 +36,5 @@ $strings['ShareLauncherPicture'] = 'Share launcher\'s picture';
$strings['NoTool'] = 'Tool not exists'; $strings['NoTool'] = 'Tool not exists';
$strings['ToolAddedOnCourseX'] = 'Tool addeed on course <strong>%s</strong>.'; $strings['ToolAddedOnCourseX'] = 'Tool addeed on course <strong>%s</strong>.';
$strings['SupportDeppLinkingHelp'] = 'Contact your Tool Provider to verify if Deep Linking support is mandatory'; $strings['SupportDeppLinkingHelp'] = 'Contact your Tool Provider to verify if Deep Linking support is mandatory';
$strings['NoAccessToUrl'] = 'No access to URL';
$strings['LaunchUrlNotFound'] = 'Launch URL not found';

@ -36,3 +36,5 @@ $strings['ShareLauncherPicture'] = 'Enviar la foto del usuario';
$strings['NoTool'] = 'La herramienta no existe'; $strings['NoTool'] = 'La herramienta no existe';
$strings['ToolAddedOnCourseX'] = 'Herramienta agregada en el curso <strong>%s</strong>.'; $strings['ToolAddedOnCourseX'] = 'Herramienta agregada en el curso <strong>%s</strong>.';
$strings['SupportDeppLinkingHelp'] = 'Contacte a su Proveedor de Herramienta para verificar si el soporte a Deep Linking es obligatorio'; $strings['SupportDeppLinkingHelp'] = 'Contacte a su Proveedor de Herramienta para verificar si el soporte a Deep Linking es obligatorio';
$strings['NoAccessToUrl'] = 'Sin acceso a la URL';
$strings['LaunchUrlNotFound'] = 'URL de lanzamiento no encontrada';

@ -43,8 +43,8 @@ class FrmAdd extends FormValidator
if (null === $this->baseTool) { if (null === $this->baseTool) {
$this->addUrl('launch_url', $plugin->get_lang('LaunchUrl'), true); $this->addUrl('launch_url', $plugin->get_lang('LaunchUrl'), true);
$this->addText('consumer_key', $plugin->get_lang('ConsumerKey')); $this->addText('consumer_key', $plugin->get_lang('ConsumerKey'), false);
$this->addText('shared_secret', $plugin->get_lang('SharedSecret')); $this->addText('shared_secret', $plugin->get_lang('SharedSecret'), false);
} }
$this->addButtonAdvancedSettings('lti_adv'); $this->addButtonAdvancedSettings('lti_adv');

@ -60,8 +60,8 @@ class FrmEdit extends FormValidator
if (null === $parent) { if (null === $parent) {
$this->addUrl('launch_url', $plugin->get_lang('LaunchUrl'), true); $this->addUrl('launch_url', $plugin->get_lang('LaunchUrl'), true);
$this->addText('consumer_key', $plugin->get_lang('ConsumerKey')); $this->addText('consumer_key', $plugin->get_lang('ConsumerKey'), false);
$this->addText('shared_secret', $plugin->get_lang('SharedSecret')); $this->addText('shared_secret', $plugin->get_lang('SharedSecret'), false);
} }
$this->addButtonAdvancedSettings('lti_adv'); $this->addButtonAdvancedSettings('lti_adv');

Loading…
Cancel
Save