Minor - update from 1.x

pull/2744/head
Julio Montoya 8 years ago
parent 65060bef05
commit 52eb3b717f
  1. 2
      plugin/bbb/lang/english.php
  2. 4
      plugin/bbb/lib/bbb.lib.php
  3. 3
      plugin/bbb/lib/bbb_plugin.class.php
  4. 19
      plugin/customcertificate/src/CustomCertificatePlugin.php
  5. 14
      plugin/customcertificate/src/print_certificate.php
  6. 227
      plugin/ims_lti/Entity/ImsLtiTool.php
  7. 142
      plugin/ims_lti/ImsLtiPlugin.php
  8. 716
      plugin/ims_lti/OAuthSimple.php
  9. 40
      plugin/ims_lti/README.md
  10. 115
      plugin/ims_lti/add.php
  11. 2
      plugin/ims_lti/admin.php
  12. 194
      plugin/ims_lti/configure.php
  13. 34
      plugin/ims_lti/create.php
  14. 54
      plugin/ims_lti/edit.php
  15. 52
      plugin/ims_lti/form.php
  16. 193
      plugin/ims_lti/gradebook/OutcomeForm.php
  17. 144
      plugin/ims_lti/gradebook/add_eval.php
  18. 28
      plugin/ims_lti/item_return.php
  19. 11
      plugin/ims_lti/lang/english.php
  20. 11
      plugin/ims_lti/lang/french.php
  21. 13
      plugin/ims_lti/lang/spanish.php
  22. 64
      plugin/ims_lti/outcome_service.php
  23. 94
      plugin/ims_lti/src/Form/FrmAdd.php
  24. 115
      plugin/ims_lti/src/Form/FrmEdit.php
  25. 65
      plugin/ims_lti/src/ImsLtiServiceDeleteRequest.php
  26. 29
      plugin/ims_lti/src/ImsLtiServiceDeleteResponse.php
  27. 73
      plugin/ims_lti/src/ImsLtiServiceReadRequest.php
  28. 35
      plugin/ims_lti/src/ImsLtiServiceReadResponse.php
  29. 84
      plugin/ims_lti/src/ImsLtiServiceReplaceRequest.php
  30. 29
      plugin/ims_lti/src/ImsLtiServiceReplaceResponse.php
  31. 82
      plugin/ims_lti/src/ImsLtiServiceRequest.php
  32. 31
      plugin/ims_lti/src/ImsLtiServiceRequestFactory.php
  33. 64
      plugin/ims_lti/src/ImsLtiServiceResponse.php
  34. 29
      plugin/ims_lti/src/ImsLtiServiceResponseFactory.php
  35. 162
      plugin/ims_lti/src/ImsLtiServiceResponseStatus.php
  36. 86
      plugin/ims_lti/view/add.tpl
  37. 2
      plugin/learning_calendar/LearningCalendarPlugin.php
  38. 1
      plugin/learning_calendar/view/calendar.tpl
  39. 7
      plugin/rss/index.php
  40. 1
      plugin/rss/lang/english.php
  41. 2
      plugin/whispeakauth/ajax/record_audio.php

@ -45,6 +45,8 @@ $strings['enable_global_conference_per_user'] = 'Enable global conference per us
$strings['enable_conference_in_course_groups'] = 'Enable conference in course groups';
$strings['enable_global_conference_link'] = 'Enable the link to the global conference in the homepage';
$strings['disable_download_conference_link'] = 'Disable download conference';
$strings['big_blue_button_record_and_store'] = 'Record and store sessions';
$strings['bbb_enable_conference_in_groups'] = 'Allow conference in groups';
$strings['plugin_tool_bbb'] = 'Video';

@ -1544,6 +1544,9 @@ class bbb
);
}
$hide = $this->plugin->get('disable_download_conference_link') === 'true' ? true : false;
if ($hide == false) {
if ($meetingInfo['has_video_m4v']) {
$links[] = Display::url(
Display::return_icon('save.png', get_lang('DownloadFile')),
@ -1560,6 +1563,7 @@ class bbb
'data-id' => $meetingInfo['id']
]
);
}
}
if (!$isAdminReport) {

@ -52,6 +52,7 @@ class BBBPlugin extends Plugin
'enable_global_conference_per_user' => 'boolean',
'enable_conference_in_course_groups' => 'boolean',
'enable_global_conference_link' => 'boolean',
'disable_download_conference_link' => 'boolean',
'max_users_limit' => 'text',
'global_conference_allow_roles' => [
'type' => 'select',
@ -209,7 +210,9 @@ class BBBPlugin extends Plugin
'bbb_host',
'bbb_tool_enable',
'enable_global_conference',
'enable_global_conference_per_user',
'enable_global_conference_link',
'disable_download_conference_link',
'enable_conference_in_course_groups',
'bbb_plugin',
'bbb_plugin_host',

@ -206,17 +206,19 @@ class CustomCertificatePlugin extends Plugin
* Get certificate data.
*
* @param int $id The certificate
* @param int $userId
*
* @return array
*/
public static function getCertificateData($id)
public static function getCertificateData($id, $userId)
{
$id = (int) $id;
if (empty($id)) {
$userId = (int) $userId;
if (empty($id) || empty($userId)) {
return [];
}
$userId = api_get_user_id();
$certificateTable = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
$categoryTable = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
$sql = "SELECT cer.user_id AS user_id, cat.session_id AS session_id, cat.course_code AS course_code
@ -224,6 +226,7 @@ class CustomCertificatePlugin extends Plugin
INNER JOIN $categoryTable cat
ON (cer.cat_id = cat.id AND cer.user_id = $userId)
WHERE cer.id = $id";
$rs = Database::query($sql);
if (Database::num_rows($rs) > 0) {
$row = Database::fetch_assoc($rs);
@ -247,12 +250,16 @@ class CustomCertificatePlugin extends Plugin
*
* @param certificate $certificate
* @param int $certId
* @param int $userId
*/
public static function redirectCheck($certificate, $certId)
public static function redirectCheck($certificate, $certId, $userId)
{
$certId = (int) $certId;
if (api_get_plugin_setting('customcertificate', 'enable_plugin_customcertificate') == 'true') {
$infoCertificate = self::getCertificateData($certId);
$userId = !empty($userId) ? $userId : api_get_user_id();
if (api_get_plugin_setting('customcertificate', 'enable_plugin_customcertificate') === 'true') {
$infoCertificate = self::getCertificateData($certId, $userId);
var_dump($infoCertificate);
if (!empty($infoCertificate)) {
if ($certificate->user_id == api_get_user_id() && !empty($certificate->certificate_data)) {
$certificateId = $certificate->certificate_data['id'];

@ -3,7 +3,9 @@
use Chamilo\CourseBundle\Entity\CLpCategory;
if (intval($_GET['default']) == 1) {
$default = isset($_GET['default']) ? (int) $_GET['default'] : null;
if ($default == 1) {
$cidReset = true;
}
@ -19,7 +21,7 @@ if (!$enable) {
api_not_allowed(true, $plugin->get_lang('ToolDisabled'));
}
if (intval($_GET['default']) == 1) {
if ($default == 1) {
$courseId = 0;
$courseCode = '';
$sessionId = 0;
@ -35,6 +37,10 @@ if (intval($_GET['default']) == 1) {
if (empty($courseCode)) {
$courseCode = isset($_REQUEST['course_code']) ? Database::escape_string($_REQUEST['course_code']) : '';
$courseInfo = api_get_course_info($courseCode);
if (!empty($courseInfo)) {
$courseId = $courseInfo['real_id'];
}
}
if (empty($sessionId)) {
@ -462,10 +468,10 @@ foreach ($userList as $userInfo) {
}
$htmlText .= '</body></html>';
$fileName = 'certificate_'.date("Ymd_His");
$fileName = 'certificate_'.date('Ymd_His');
$params = [
'filename' => $fileName,
'pdf_title' => "Certificate",
'pdf_title' => 'Certificate',
'pdf_description' => '',
'format' => 'A4-L',
'orientation' => 'L',

@ -3,6 +3,9 @@
namespace Chamilo\PluginBundle\Entity\ImsLti;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\GradebookEvaluation;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
@ -60,22 +63,60 @@ class ImsLtiTool
/**
* @var bool
*
* @ORM\Column(name="is_global", type="boolean")
* @ORM\Column(name="active_deep_linking", type="boolean", nullable=false, options={"default": false})
*/
private $isGlobal = false;
private $activeDeepLinking = false;
/**
* @var bool
* @var null|string
*
* @ORM\Column(name="active_deep_linking", type="boolean", nullable=false, options={"default": false})
* @ORM\Column(name="privacy", type="text", nullable=true, options={"default": null})
*/
private $activeDeepLinking = false;
private $privacy = null;
/**
* @var Course|null
*
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Course")
* @ORM\JoinColumn(name="c_id", referencedColumnName="id")
*/
private $course = null;
/**
* @var GradebookEvaluation|null
*
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\GradebookEvaluation")
* @ORM\JoinColumn(name="gradebook_eval_id", referencedColumnName="id", onDelete="SET NULL")
*/
private $gradebookEval = null;
/**
* @var ImsLtiTool|null
*
* @ORM\ManyToOne(targetEntity="Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool", inversedBy="children")
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
*/
private $parent;
/**
* @var ArrayCollection
*
* @ORM\OneToMany(targetEntity="Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool", mappedBy="parent")
*/
private $children;
/**
* ImsLtiTool constructor.
*/
public function __construct()
{
$this->description = null;
$this->customParams = null;
$this->isGlobal = false;
$this->activeDeepLinking = false;
$this->course = null;
$this->gradebookEval =null;
$this->privacy = null;
$this->children = new ArrayCollection();
}
/**
@ -205,18 +246,7 @@ class ImsLtiTool
*/
public function isGlobal()
{
return $this->isGlobal;
}
/**
* @param bool $isGlobal
* @return ImsLtiTool
*/
public function setIsGlobal($isGlobal)
{
$this->isGlobal = $isGlobal;
return $this;
return $this->course === null;
}
/**
@ -224,23 +254,30 @@ class ImsLtiTool
*/
public function parseCustomParams()
{
$strings = explode($this->customParams, "\n");
$pairs = explode('=', $strings);
$params = [];
$strings = explode("\n", $this->customParams);
return [
'key' => 'custom_'.$pairs[0],
'value' => $pairs[1]
];
foreach ($strings as $string) {
$pairs = explode('=', $string);
$params['custom_'.$pairs[0]] = $pairs[1];
}
return $params;
}
/**
* Set activeDeepLinking.
*
* @param bool $activeDeepLinking
*
* @return ImsLtiTool
*/
public function setActiveDeepLinking($activeDeepLinking)
{
$this->activeDeepLinking = $activeDeepLinking;
return $this;
}
/**
@ -252,4 +289,146 @@ class ImsLtiTool
{
return $this->activeDeepLinking;
}
/**
* Get course.
*
* @return Course|null
*/
public function getCourse()
{
return $this->course;
}
/**
* Set course.
*
* @param Course|null $course
*
* @return ImsLtiTool
*/
public function setCourse(Course $course = null)
{
$this->course = $course;
return $this;
}
/**
* Get gradebookEval.
*
* @return GradebookEvaluation|null
*/
public function getGradebookEval()
{
return $this->gradebookEval;
}
/**
* Set gradebookEval.
*
* @param GradebookEvaluation|null $gradebookEval
*
* @return ImsLtiTool
*/
public function setGradebookEval($gradebookEval)
{
$this->gradebookEval = $gradebookEval;
return $this;
}
/**
* Get privacy.
*
* @return null|string
*/
public function getPrivacy()
{
return $this->privacy;
}
/**
* Set privacy.
*
* @param bool $shareName
* @param bool $shareEmail
* @param bool $sharePicture
*
* @return ImsLtiTool
*/
public function setPrivacy($shareName = false, $shareEmail = false, $sharePicture = false)
{
$this->privacy = serialize(
[
'share_name' => $shareName,
'share_email' => $shareEmail,
'share_picture' => $sharePicture,
]
);
return $this;
}
/**
* @return bool
*/
public function isSharingName()
{
$unserialize = $this->unserializePrivacy();
return (bool) $unserialize['share_name'];
}
/**
* @return bool
*/
public function isSharingEmail()
{
$unserialize = $this->unserializePrivacy();
return (bool) $unserialize['share_email'];
}
/**
* @return bool
*/
public function isSharingPicture()
{
$unserialize = $this->unserializePrivacy();
return (bool) $unserialize['share_picture'];
}
/**
* @return mixed
*/
public function unserializePrivacy()
{
return unserialize($this->privacy);
}
/**
* @return ImsLtiTool|null
*/
public function getParent()
{
return $this->parent;
}
/**
* @param ImsLtiTool $parent
*
* @return ImsLtiTool
*/
public function setParent(ImsLtiTool $parent)
{
$this->parent = $parent;
$this->sharedSecret = $parent->getSharedSecret();
$this->consumerKey = $parent->getConsumerKey();
$this->privacy = $parent->getPrivacy();
return $this;
}
}

@ -1,17 +1,17 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\CourseRelUser;
use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
use Chamilo\CourseBundle\Entity\CTool;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool;
use Chamilo\UserBundle\Entity\User;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\DBALException;
use Symfony\Component\Filesystem\Filesystem;
use Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool;
/**
* Description of MsiLti
@ -105,36 +105,47 @@ class ImsLtiPlugin extends Plugin
* Creates the plugin tables on database
*
* @return boolean
* @throws DBALException
*/
private function createPluginTables()
{
$entityManager = Database::getManager();
$connection = $entityManager->getConnection();
$pluginSchema = new Schema();
$platform = $connection->getDatabasePlatform();
if (!$connection->getSchemaManager()->tablesExist(self::TABLE_TOOL)) {
$toolTable = $pluginSchema->createTable(self::TABLE_TOOL);
$toolTable->addColumn(
'id',
\Doctrine\DBAL\Types\Type::INTEGER,
['autoincrement' => true, 'unsigned' => true]
);
$toolTable->addColumn('name', Type::STRING);
$toolTable->addColumn('description', Type::TEXT)->setNotnull(false);
$toolTable->addColumn('launch_url', Type::TEXT);
$toolTable->addColumn('consumer_key', Type::STRING);
$toolTable->addColumn('shared_secret', Type::STRING);
$toolTable->addColumn('custom_params', Type::TEXT)->setNotnull(false);
$toolTable->addColumn('is_global', Type::BOOLEAN);
$toolTable->setPrimaryKey(['id']);
$queries = $pluginSchema->toSql($platform);
foreach ($queries as $query) {
Database::query($query);
}
if ($connection->getSchemaManager()->tablesExist(self::TABLE_TOOL)) {
return true;
}
$queries = [
'CREATE TABLE '.self::TABLE_TOOL.' (
id INT AUTO_INCREMENT NOT NULL,
c_id INT DEFAULT NULL,
gradebook_eval_id INT DEFAULT NULL,
parent_id INT DEFAULT NULL,
name VARCHAR(255) NOT NULL,
description LONGTEXT DEFAULT NULL,
launch_url VARCHAR(255) NOT NULL,
consumer_key VARCHAR(255) NOT NULL,
shared_secret VARCHAR(255) NOT NULL,
custom_params LONGTEXT DEFAULT NULL,
active_deep_linking TINYINT(1) DEFAULT \'0\' NOT NULL,
privacy LONGTEXT DEFAULT NULL,
INDEX IDX_C5E47F7C91D79BD3 (c_id),
INDEX IDX_C5E47F7C82F80D8B (gradebook_eval_id),
INDEX IDX_C5E47F7C727ACA70 (parent_id),
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB',
'ALTER TABLE '.self::TABLE_TOOL.' ADD CONSTRAINT FK_C5E47F7C91D79BD3
FOREIGN KEY (c_id) REFERENCES course (id)',
'ALTER TABLE '.self::TABLE_TOOL.' ADD CONSTRAINT FK_C5E47F7C82F80D8B
FOREIGN KEY (gradebook_eval_id) REFERENCES gradebook_evaluation (id) ON DELETE SET NULL',
'ALTER TABLE '.self::TABLE_TOOL.' ADD CONSTRAINT FK_C5E47F7C727ACA70
FOREIGN KEY (parent_id) REFERENCES '.self::TABLE_TOOL.' (id);',
];
foreach ($queries as $query) {
Database::query($query);
}
return true;
}
@ -176,7 +187,7 @@ class ImsLtiPlugin extends Plugin
{
$button = Display::toolbarButton(
$this->get_lang('ConfigureExternalTool'),
api_get_path(WEB_PLUGIN_PATH).'ims_lti/add.php?'.api_get_cidreq(),
api_get_path(WEB_PLUGIN_PATH).'ims_lti/configure.php?'.api_get_cidreq(),
'cog',
'primary'
);
@ -204,7 +215,7 @@ class ImsLtiPlugin extends Plugin
$cTool = $toolRepo->findOneBy(
[
'cId' => $course,
'link' => self::generateToolLink($ltiTool)
'link' => self::generateToolLink($ltiTool),
]
);
@ -345,36 +356,39 @@ class ImsLtiPlugin extends Plugin
/**
* @param array $contentItem
* @param ImsLtiTool $ltiTool
* @param ImsLtiTool $baseLtiTool
* @param Course $course
*
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function saveItemAsLtiLink(array $contentItem, ImsLtiTool $ltiTool, Course $course)
public function saveItemAsLtiLink(array $contentItem, ImsLtiTool $baseLtiTool, Course $course)
{
$em = Database::getManager();
$ltiToolRepo = $em->getRepository('ChamiloPluginBundle:ImsLti\ImsLtiTool');
$url = empty($contentItem['url']) ? $ltiTool->getLaunchUrl() : $contentItem['url'];
$url = empty($contentItem['url']) ? $baseLtiTool->getLaunchUrl() : $contentItem['url'];
/** @var ImsLtiTool $newLtiTool */
$newLtiTool = $ltiToolRepo->findOneBy(['launchUrl' => $url, 'isGlobal' => false]);
$newLtiTool = $ltiToolRepo->findOneBy(['launchUrl' => $url, 'parent' => $baseLtiTool, 'course' => $course]);
if (empty($newLtiTool)) {
if (null === $newLtiTool) {
$newLtiTool = new ImsLtiTool();
$newLtiTool
->setLaunchUrl($url)
->setConsumerKey(
$ltiTool->getConsumerKey()
->setParent(
$baseLtiTool
)
->setPrivacy(
$baseLtiTool->isSharingName(),
$baseLtiTool->isSharingEmail(),
$baseLtiTool->isSharingPicture()
)
->setSharedSecret(
$ltiTool->getSharedSecret()
);
->setCourse($course);
}
$newLtiTool
->setName(
!empty($contentItem['title']) ? $contentItem['title'] : $ltiTool->getName()
!empty($contentItem['title']) ? $contentItem['title'] : $baseLtiTool->getName()
)
->setDescription(
!empty($contentItem['text']) ? $contentItem['text'] : null
@ -393,4 +407,54 @@ class ImsLtiPlugin extends Plugin
$this->addCourseTool($course, $newLtiTool);
}
/**
* @return null|SimpleXMLElement
*/
private function getRequestXmlElement()
{
$request = file_get_contents("php://input");
if (empty($request)) {
return null;
}
$xml = new SimpleXMLElement($request);
return $xml;
}
/**
* @return ImsLtiServiceResponse|null
*/
public function processServiceRequest()
{
$xml = $this->getRequestXmlElement();
if (empty($xml)) {
return null;
}
$request = ImsLtiServiceRequestFactory::create($xml);
$response = $request->process();
return $response;
}
/**
* @param int $toolId
* @param Course $course
*
* @return bool
*/
public static function existsToolInCourse($toolId, Course $course)
{
$em = Database::getManager();
$toolRepo = $em->getRepository('ChamiloPluginBundle:ImsLti\ImsLtiTool');
/** @var ImsLtiTool $tool */
$tool = $toolRepo->findOneBy(['id' => $toolId, 'course' => $course]);
return !empty($tool);
}
}

@ -1,4 +1,5 @@
<?php
/**
* OAuthSimple - A simpler version of OAuth
*
@ -7,35 +8,34 @@
* @author jr conlin <src@jrconlin.com>
* @copyright unitedHeroes.net 2011
* @version 1.3
* @license See license.txt
*
* @license BSD licence.
*/
class OAuthSimple {
class OAuthSimple
{
private $_secrets;
private $_default_signature_method;
private $_action;
private $_nonce_chars;
/**
* Constructor
* OAuthSimple constructor.
*
* @access public
* @param api_key (String) The API Key (sometimes referred to as the consumer key) This value is usually supplied by the site you wish to use.
* @param shared_secret (String) The shared secret. This value is also usually provided by the site you wish to use.
* @return OAuthSimple (Object)
* @param string $APIKey The API Key (sometimes referred to as the consumer key). This value is usually
* supplied by the site you wish to use.
* @param string $sharedSecret The shared secret. This value is also usually provided by the site you wish to use.
*
* @return OAuthSimple
*/
function __construct ($APIKey = "", $sharedSecret=""){
function __construct($APIKey = "", $sharedSecret = "")
{
if (!empty($APIKey))
{
$this->_secrets['consumer_key'] = $APIKey;
}
if (!empty($APIKey)) {
$this->_secrets['consumer_key'] = $APIKey;
}
if (!empty($sharedSecret))
{
$this->_secrets['shared_secret'] = $sharedSecret;
}
if (!empty($sharedSecret)) {
$this->_secrets['shared_secret'] = $sharedSecret;
}
$this->_default_signature_method = "HMAC-SHA1";
$this->_action = "GET";
@ -45,495 +45,577 @@ class OAuthSimple {
}
/**
* Reset the parameters and URL
*
* @access public
* @return OAuthSimple (Object)
*/
public function reset() {
* Reset the parameters and URL.
*
* @return OAuthSimple
*/
public function reset()
{
$this->_parameters = Array();
$this->path = NULL;
$this->sbs = NULL;
$this->path = null;
$this->sbs = null;
return $this;
}
/**
* Set the parameters either from a hash or a string
*
* @access public
* @param(string, object) List of parameters for the call, this can either be a URI string (e.g. "foo=bar&gorp=banana" or an object/hash)
* @return OAuthSimple (Object)
*/
public function setParameters ($parameters=Array()) {
if (is_string($parameters))
{
$parameters = $this->_parseParameterString($parameters);
}
if (empty($this->_parameters))
{
$this->_parameters = $parameters;
}
else if (!empty($parameters))
{
$this->_parameters = array_merge($this->_parameters,$parameters);
}
if (empty($this->_parameters['oauth_nonce']))
{
$this->_getNonce();
}
if (empty($this->_parameters['oauth_timestamp']))
{
$this->_getTimeStamp();
}
if (empty($this->_parameters['oauth_consumer_key']))
{
$this->_getApiKey();
}
if (empty($this->_parameters['oauth_token']))
{
$this->_getAccessToken();
}
if (empty($this->_parameters['oauth_signature_method']))
{
* Set the parameters either from a hash or a string.
*
* @param array $parameters List of parameters for the call,
* this can either be a URI string (e.g."foo=bar&gorp=banana" or an object/hash)
*
* @throws OAuthSimpleException
*
* @return OAuthSimple
*/
public function setParameters($parameters = [])
{
if (is_string($parameters)) {
$parameters = $this->_parseParameterString($parameters);
}
if (empty($this->_parameters)) {
$this->_parameters = $parameters;
} elseif (!empty($parameters)) {
$this->_parameters = array_merge($this->_parameters, $parameters);
}
if (empty($this->_parameters['oauth_nonce'])) {
$this->_getNonce();
}
if (empty($this->_parameters['oauth_timestamp'])) {
$this->_getTimeStamp();
}
if (empty($this->_parameters['oauth_consumer_key'])) {
$this->_getApiKey();
}
if (empty($this->_parameters['oauth_token'])) {
$this->_getAccessToken();
}
if (empty($this->_parameters['oauth_signature_method'])) {
$this->setSignatureMethod();
}
if (empty($this->_parameters['oauth_version']))
{
$this->_parameters['oauth_version']="1.0";
}
}
if (empty($this->_parameters['oauth_version'])) {
$this->_parameters['oauth_version'] = "1.0";
}
return $this;
}
/**
* Convenience method for setParameters
*
* @access public
* @see setParameters
*/
public function setQueryString ($parameters)
* Convenience method for setParameters.
*
* @param array $parameters
*
* @throws OAuthSimpleException
*
* @return OAuthSimple
*/
public function setQueryString($parameters)
{
return $this->setParameters($parameters);
}
/**
* Set the target URL (does not include the parameters)
*
* @param path (String) the fully qualified URI (excluding query arguments) (e.g "http://example.org/foo")
* @return OAuthSimple (Object)
* Set the target URL (does not include the parameters).
*
* @param string $path The fully qualified URI (excluding query arguments) (e.g "http://example.org/foo")
*
* @throws OAuthSimpleException
*
* @return OAuthSimple
*/
public function setURL ($path)
{
if (empty($path))
{
public function setURL($path)
{
if (empty($path)) {
throw new OAuthSimpleException('No path specified for OAuthSimple.setURL');
}
$this->_path=$path;
}
$this->_path = $path;
return $this;
}
/**
* Convenience method for setURL
* Convenience method for setURL.
*
* @param string $path
*
* @param path (String)
* @see setURL
* @return mixed
*/
public function setPath ($path)
public function setPath($path)
{
return $this->_path=$path;
return $this->_path = $path;
}
/**
* Set the "action" for the url, (e.g. GET,POST, DELETE, etc.)
* Set the "action" for the url, (e.g. GET,POST, DELETE, etc.).
*
* @param action (String) HTTP Action word.
* @return OAuthSimple (Object)
* @param string $action HTTP Action word.
*
* @throws OAuthSimpleException
*
* @return $this
*/
public function setAction ($action)
public function setAction($action)
{
if (empty($action))
{
$action = 'GET';
}
if (empty($action)) {
$action = 'GET';
}
$action = strtoupper($action);
if (preg_match('/[^A-Z]/',$action))
{
if (preg_match('/[^A-Z]/', $action)) {
throw new OAuthSimpleException('Invalid action specified for OAuthSimple.setAction');
}
}
$this->_action = $action;
return $this;
}
/**
* Set the signatures (as well as validate the ones you have)
* Set the signatures (as well as validate the ones you have).
*
* @param array $signatures object/hash of the token/signature pairs {api_key:, shared_secret:, oauth_token:
* oauth_secret:}
*
* @param signatures (object) object/hash of the token/signature pairs {api_key:, shared_secret:, oauth_token: oauth_secret:}
* @return OAuthSimple (Object)
* @throws OAuthSimpleException
*
* @return $this
*/
public function signatures ($signatures)
public function signatures($signatures)
{
if (!empty($signatures) && !is_array($signatures))
{
if (!empty($signatures) && !is_array($signatures)) {
throw new OAuthSimpleException('Must pass dictionary array to OAuthSimple.signatures');
}
if (!empty($signatures))
{
if (empty($this->_secrets))
{
$this->_secrets=Array();
}
if (!empty($signatures)) {
if (empty($this->_secrets)) {
$this->_secrets = Array();
}
$this->_secrets=array_merge($this->_secrets,$signatures);
$this->_secrets = array_merge($this->_secrets, $signatures);
}
if (isset($this->_secrets['api_key']))
{
if (isset($this->_secrets['api_key'])) {
$this->_secrets['consumer_key'] = $this->_secrets['api_key'];
}
if (isset($this->_secrets['access_token']))
{
}
if (isset($this->_secrets['access_token'])) {
$this->_secrets['oauth_token'] = $this->_secrets['access_token'];
}
if (isset($this->_secrets['access_secret']))
{
}
if (isset($this->_secrets['access_secret'])) {
$this->_secrets['shared_secret'] = $this->_secrets['access_secret'];
}
if (isset($this->_secrets['oauth_token_secret']))
{
if (isset($this->_secrets['oauth_token_secret'])) {
$this->_secrets['oauth_secret'] = $this->_secrets['oauth_token_secret'];
}
if (empty($this->_secrets['consumer_key']))
{
}
if (empty($this->_secrets['consumer_key'])) {
throw new OAuthSimpleException('Missing required consumer_key in OAuthSimple.signatures');
}
if (empty($this->_secrets['shared_secret']))
{
if (empty($this->_secrets['shared_secret'])) {
throw new OAuthSimpleException('Missing requires shared_secret in OAuthSimple.signatures');
}
if (!empty($this->_secrets['oauth_token']) && empty($this->_secrets['oauth_secret']))
{
}
if (!empty($this->_secrets['oauth_token']) && empty($this->_secrets['oauth_secret'])) {
throw new OAuthSimpleException('Missing oauth_secret for supplied oauth_token in OAuthSimple.signatures');
}
}
return $this;
}
/**
* @param array $signatures
*
* @throws OAuthSimpleException
*
* @return OAuthSimple
*/
public function setTokensAndSecrets($signatures)
{
return $this->signatures($signatures);
}
/**
* Set the signature method (currently only Plaintext or SHA-MAC1)
*
* @param method (String) Method of signing the transaction (only PLAINTEXT and SHA-MAC1 allowed for now)
* @return OAuthSimple (Object)
*/
public function setSignatureMethod ($method="")
{
if (empty($method))
{
* Set the signature method (currently only Plaintext or SHA-MAC1).
*
* @param string $method Method of signing the transaction (only PLAINTEXT and SHA-MAC1 allowed for now).
*
* @throws OAuthSimpleException
*
* @return $this
*/
public function setSignatureMethod($method = "")
{
if (empty($method)) {
$method = $this->_default_signature_method;
}
}
$method = strtoupper($method);
switch($method)
{
switch ($method) {
case 'PLAINTEXT':
case 'HMAC-SHA1':
$this->_parameters['oauth_signature_method']=$method;
break;
$this->_parameters['oauth_signature_method'] = $method;
break;
default:
throw new OAuthSimpleException ("Unknown signing method $method specified for OAuthSimple.setSignatureMethod");
break;
throw new OAuthSimpleException (
"Unknown signing method $method specified for OAuthSimple.setSignatureMethod"
);
break;
}
return $this;
return $this;
}
/** sign the request
/**
* Sign the request.
*
* note: all arguments are optional, provided you've set them using the
* other helper functions.
*
* @param args (Array) hash of arguments for the call {action, path, parameters (array), method, signatures (array)} all arguments are optional.
* @return (Array) signed values
* @param array $args Optional.
* Hash of arguments for the call {action, path, parameters (array), method, signatures, (array)}
*
* @throws OAuthSimpleException
*
* @return array
*/
public function sign($args=array())
public function sign($args = array())
{
if (!empty($args['action']))
{
if (!empty($args['action'])) {
$this->setAction($args['action']);
}
if (!empty($args['path']))
{
}
if (!empty($args['path'])) {
$this->setPath($args['path']);
}
if (!empty($args['method']))
{
if (!empty($args['method'])) {
$this->setSignatureMethod($args['method']);
}
if (!empty($args['signatures']))
{
}
if (!empty($args['signatures'])) {
$this->signatures($args['signatures']);
}
if (empty($args['parameters']))
{
$args['parameters']=array();
}
}
if (empty($args['parameters'])) {
$args['parameters'] = array();
}
$this->setParameters($args['parameters']);
$normParams = $this->_normalizedParameters();
return Array (
return Array(
'parameters' => $this->_parameters,
'signature' => self::_oauthEscape($this->_parameters['oauth_signature']),
'signed_url' => $this->_path . '?' . $normParams,
'signed_url' => $this->_path.'?'.$normParams,
'header' => $this->getHeaderString(),
'sbs'=> $this->sbs
);
'sbs' => $this->sbs,
);
}
/**
* Return a formatted "header" string
* Return a formatted "header" string.
*
* NOTE: This doesn't set the "Authorization: " prefix, which is required.
* It's not set because various set header functions prefer different
* ways to do that.
*
* @param args (Array)
* @return $result (String)
*/
public function getHeaderString ($args=array())
* @param array $args
*
* @throws OAuthSimpleException
*
* @return null|string|string[]
*/
public function getHeaderString($args = array())
{
if (empty($this->_parameters['oauth_signature']))
{
if (empty($this->_parameters['oauth_signature'])) {
$this->sign($args);
}
}
$result = 'OAuth ';
foreach ($this->_parameters as $pName => $pValue)
{
if (strpos($pName,'oauth_') !== 0)
{
foreach ($this->_parameters as $pName => $pValue) {
if (strpos($pName, 'oauth_') !== 0) {
continue;
}
if (is_array($pValue))
{
foreach ($pValue as $val)
{
$result .= $pName .'="' . self::_oauthEscape($val) . '", ';
}
}
else
{
$result .= $pName . '="' . self::_oauthEscape($pValue) . '", ';
if (is_array($pValue)) {
foreach ($pValue as $val) {
$result .= $pName.'="'.self::_oauthEscape($val).'", ';
}
} else {
$result .= $pName.'="'.self::_oauthEscape($pValue).'", ';
}
}
return preg_replace('/, $/','',$result);
return preg_replace('/, $/', '', $result);
}
private function _parseParameterString ($paramString)
/**
* @param string $paramString
*
* @return array
*/
private function _parseParameterString($paramString)
{
$elements = explode('&',$paramString);
$elements = explode('&', $paramString);
$result = array();
foreach ($elements as $element)
{
list ($key,$token) = explode('=',$element);
if ($token)
{
foreach ($elements as $element) {
list ($key, $token) = explode('=', $element);
if ($token) {
$token = urldecode($token);
}
if (!empty($result[$key]))
{
if (!is_array($result[$key]))
{
$result[$key] = array($result[$key],$token);
}
else
{
array_push($result[$key],$token);
}
}
else
$result[$key]=$token;
if (!empty($result[$key])) {
if (!is_array($result[$key])) {
$result[$key] = array($result[$key], $token);
} else {
array_push($result[$key], $token);
}
} else {
$result[$key] = $token;
}
}
return $result;
}
/**
* @param string $string
*
* @throws OAuthSimpleException
*
* @return int|mixed|string
*/
private static function _oauthEscape($string)
{
if ($string === 0) { return 0; }
if ($string == '0') { return '0'; }
if (strlen($string) == 0) { return ''; }
if ($string === 0) {
return 0;
}
if ($string == '0') {
return '0';
}
if (strlen($string) == 0) {
return '';
}
if (is_array($string)) {
throw new OAuthSimpleException('Array passed to _oauthEscape');
}
}
$string = urlencode($string);
//FIX: urlencode of ~ and '+'
//FIX: urlencode of ~ and '+'
$string = str_replace(
Array('%7E','+' ), // Replace these
Array('~', '%20'), // with these
$string);
Array('%7E', '+'), // Replace these
Array('~', '%20'), // with these
$string
);
return $string;
}
private function _getNonce($length=5)
/**
* @param int $length
*
* @return string
*/
private function _getNonce($length = 5)
{
$result = '';
$cLength = strlen($this->_nonce_chars);
for ($i=0; $i < $length; $i++)
{
$rnum = rand(0,$cLength - 1);
$result .= substr($this->_nonce_chars,$rnum,1);
for ($i = 0; $i < $length; $i++) {
$rnum = rand(0, $cLength - 1);
$result .= substr($this->_nonce_chars, $rnum, 1);
}
$this->_parameters['oauth_nonce'] = $result;
return $result;
}
/**
* @throws OAuthSimpleException
*
* @return mixed
*/
private function _getApiKey()
{
if (empty($this->_secrets['consumer_key']))
{
if (empty($this->_secrets['consumer_key'])) {
throw new OAuthSimpleException('No consumer_key set for OAuthSimple');
}
$this->_parameters['oauth_consumer_key']=$this->_secrets['consumer_key'];
$this->_parameters['oauth_consumer_key'] = $this->_secrets['consumer_key'];
return $this->_parameters['oauth_consumer_key'];
}
/**
* @throws OAuthSimpleException
*
* @return string
*/
private function _getAccessToken()
{
if (!isset($this->_secrets['oauth_secret']))
{
if (!isset($this->_secrets['oauth_secret'])) {
return '';
}
if (!isset($this->_secrets['oauth_token']))
{
}
if (!isset($this->_secrets['oauth_token'])) {
throw new OAuthSimpleException('No access token (oauth_token) set for OAuthSimple.');
}
}
$this->_parameters['oauth_token'] = $this->_secrets['oauth_token'];
return $this->_parameters['oauth_token'];
}
/**
* @return int
*/
private function _getTimeStamp()
{
return $this->_parameters['oauth_timestamp'] = time();
}
/**
* @throws OAuthSimpleException
*
* @return string
*/
private function _normalizedParameters()
{
$normalized_keys = array();
$return_array = array();
$normalized_keys = array();
$return_array = array();
foreach ( $this->_parameters as $paramName=>$paramValue) {
foreach ($this->_parameters as $paramName => $paramValue) {
if (preg_match('/w+_secret/', $paramName) OR
$paramName == "oauth_signature") {
continue;
}
continue;
}
// Read parameters from a file. Hope you're practicing safe PHP.
//if (strpos($paramValue, '@') !== 0 && !file_exists(substr($paramValue, 1)))
//{
if (is_array($paramValue))
{
$normalized_keys[self::_oauthEscape($paramName)] = array();
foreach($paramValue as $item)
{
array_push($normalized_keys[self::_oauthEscape($paramName)], self::_oauthEscape($item));
}
}
else
{
$normalized_keys[self::_oauthEscape($paramName)] = self::_oauthEscape($paramValue);
}
//}
}
ksort($normalized_keys);
foreach($normalized_keys as $key=>$val)
{
if (is_array($val))
{
sort($val);
foreach($val as $element)
{
array_push($return_array, $key . "=" . $element);
}
}
else
{
array_push($return_array, $key .'='. $val);
}
//{
if (is_array($paramValue)) {
$normalized_keys[self::_oauthEscape($paramName)] = array();
foreach ($paramValue as $item) {
array_push($normalized_keys[self::_oauthEscape($paramName)], self::_oauthEscape($item));
}
} else {
$normalized_keys[self::_oauthEscape($paramName)] = self::_oauthEscape($paramValue);
}
//}
}
ksort($normalized_keys);
foreach ($normalized_keys as $key => $val) {
if (is_array($val)) {
sort($val);
foreach ($val as $element) {
array_push($return_array, $key."=".$element);
}
} else {
array_push($return_array, $key.'='.$val);
}
}
$presig = join("&", $return_array);
$sig = $this->_generateSignature($presig);
$this->_parameters['oauth_signature']=$sig;
$this->_parameters['oauth_signature'] = $sig;
array_push($return_array, "oauth_signature=$sig");
return join("&", $return_array);
}
return join("&", $return_array);
}
private function _generateSignature ($parameters="")
/**
* @param string $parameters
*
* @throws OAuthSimpleException
*
* @return string
*/
private function _generateSignature($parameters = "")
{
$secretKey = '';
if(isset($this->_secrets['shared_secret']))
{
$secretKey = self::_oauthEscape($this->_secrets['shared_secret']);
}
$secretKey .= '&';
if(isset($this->_secrets['oauth_secret']))
{
if (isset($this->_secrets['shared_secret'])) {
$secretKey = self::_oauthEscape($this->_secrets['shared_secret']);
}
$secretKey .= '&';
if (isset($this->_secrets['oauth_secret'])) {
$secretKey .= self::_oauthEscape($this->_secrets['oauth_secret']);
}
if(!empty($parameters)){
if (!empty($parameters)) {
$parameters = urlencode($parameters);
}
switch($this->_parameters['oauth_signature_method'])
{
switch ($this->_parameters['oauth_signature_method']) {
case 'PLAINTEXT':
return urlencode($secretKey);;
case 'HMAC-SHA1':
$this->sbs = self::_oauthEscape($this->_action).'&'.self::_oauthEscape($this->_path).'&'.$parameters;
return base64_encode(hash_hmac('sha1',$this->sbs,$secretKey,TRUE));
return base64_encode(hash_hmac('sha1', $this->sbs, $secretKey, true));
default:
throw new OAuthSimpleException('Unknown signature method for OAuthSimple');
break;
break;
}
}
/**
* @param $string
*
* @return string
*/
public static function generateBodyHash($string)
{
$hash = sha1($string, true);
return base64_encode($hash);
}
/**
* @param string $authorizationHeader
*
* @return array
*/
public static function getAuthorizationParams($authorizationHeader)
{
if ('OAuth ' !== substr($authorizationHeader, 0, 6)) {
return [];
}
$params = [];
$authString = str_replace('OAuth ', '', $authorizationHeader);
$authParts = explode(',', $authString);
foreach ($authParts as $authPart) {
list($key, $value) = explode('=', $authPart, 2);
$key = trim($key);
$value = trim($value, " \"");
$params[$key] = urldecode($value);
}
return $params;
}
}
class OAuthSimpleException extends Exception {
public function __construct($err, $isDebug = FALSE)
{
self::log_error($err);
if ($isDebug)
{
self::display_error($err, TRUE);
}
}
public static function log_error($err)
{
error_log($err, 0);
}
public static function display_error($err, $kill = FALSE)
{
print_r($err);
if ($kill === FALSE)
{
die();
}
}
/**
* Class OAuthSimpleException.
*/
class OAuthSimpleException extends Exception
{
/**
* OAuthSimpleException constructor.
*
* @param string $err
* @param bool $isDebug
*/
public function __construct($err, $isDebug = false)
{
self::log_error($err);
if ($isDebug) {
self::display_error($err, true);
}
}
/**
* @param string $err
*/
public static function log_error($err)
{
error_log($err, 0);
}
/**
* @param string $err
* @param bool $kill
*/
public static function display_error($err, $kill = false)
{
print_r($err);
if ($kill === false) {
die();
}
}
}

@ -1,7 +1,7 @@
IMS/LTI plugin
===
Version 1.1 (beta)
Version 1.3 (beta)
This plugin is meant to be later integrated into Chamilo (in a major version
release).
@ -23,8 +23,16 @@ external tool.
# Changelog
**v1.1**
* Support for Deep-Linking added.
* Support for outcomes services. And register score on course gradebook.
**v1.2**
* Register course in which the tool was added.
* Register parent tool from which the new tool comes from.
**v1.3**
* Privacy settings added. Allow to indicate id the launcher's data
should be sent in request.
# Installation
@ -34,12 +42,36 @@ external tool.
# Upgrading
**To v1.1**
Run this changes on database:
**To v1.1**
```sql
ALTER TABLE plugin_ims_lti_tool
ADD active_deep_linking TINYINT(1) DEFAULT '0' NOT NULL,
CHANGE id id INT AUTO_INCREMENT NOT NULL,
CHANGE launch_url launch_url VARCHAR(255) NOT NULL;
ALTER TABLE plugin_ims_lti_tool ADD gradebook_eval_id INT DEFAULT NULL;
ALTER TABLE plugin_ims_lti_tool ADD CONSTRAINT FK_C5E47F7C82F80D8B
FOREIGN KEY (gradebook_eval_id) REFERENCES gradebook_evaluation (id)
ON DELETE SET NULL;
CREATE INDEX IDX_C5E47F7C82F80D8B ON plugin_ims_lti_tool (gradebook_eval_id);
```
**To v1.2**
```sql
ALTER TABLE plugin_ims_lti_tool ADD c_id INT DEFAULT NULL;
ALTER TABLE plugin_ims_lti_tool ADD CONSTRAINT FK_C5E47F7C91D79BD3
FOREIGN KEY (c_id) REFERENCES course (id);
CREATE INDEX IDX_C5E47F7C91D79BD3 ON plugin_ims_lti_tool (c_id);
ALTER TABLE plugin_ims_lti_tool ADD parent_id INT DEFAULT NULL, DROP is_global;
ALTER TABLE plugin_ims_lti_tool ADD CONSTRAINT FK_C5E47F7C727ACA70
FOREIGN KEY (parent_id) REFERENCES plugin_ims_lti_tool (id);
CREATE INDEX IDX_C5E47F7C727ACA70 ON plugin_ims_lti_tool (parent_id);
```
**To v1.3**
```sql
ALTER TABLE plugin_ims_lti_tool ADD privacy LONGTEXT DEFAULT NULL;
```

@ -1,115 +0,0 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_course_script();
api_protect_teacher_script();
$plugin = ImsLtiPlugin::create();
$em = Database::getManager();
$toolsRepo = $em->getRepository('ChamiloPluginBundle:ImsLti\ImsLtiTool');
/** @var ImsLtiTool $baseTool */
$baseTool = isset($_REQUEST['type']) ? $toolsRepo->find($_REQUEST['type']) : null;
/** @var Course $course */
$course = $em->find('ChamiloCoreBundle:Course', api_get_course_int_id());
$globalTools = $toolsRepo->findBy(['isGlobal' => true]);
if ($baseTool && !$baseTool->isGlobal()) {
Display::addFlash(
Display::return_message($plugin->get_lang('ToolNotAvailable'), 'warning')
);
header('Location: '.api_get_self().'?'.api_get_cidreq());
exit;
}
$form = new FormValidator('ims_lti_add_tool');
$form->addHeader($plugin->get_lang('ToolSettings'));
if ($baseTool) {
$form->addHtml('<p class="lead">'.Security::remove_XSS($baseTool->getDescription()).'</p>');
}
$form->addText('name', get_lang('Title'));
if (!$baseTool) {
$form->addElement('url', 'url', $plugin->get_lang('LaunchUrl'));
$form->addText('consumer_key', $plugin->get_lang('ConsumerKey'), true);
$form->addText('shared_secret', $plugin->get_lang('SharedSecret'), true);
$form->addRule('url', get_lang('Required'), 'required');
}
$form->addButtonAdvancedSettings('lti_adv');
$form->addHtml('<div id="lti_adv_options" style="display:none;">');
$form->addTextarea('description', get_lang('Description'), ['rows' => 3]);
if (!$baseTool) {
$form->addTextarea('custom_params', [$plugin->get_lang('CustomParams'), $plugin->get_lang('CustomParamsHelp')]);
$form->addCheckBox('deep_linking', $plugin->get_lang('SupportDeepLinking'), get_lang('Yes'));
}
if ($baseTool) {
$form->addHidden('type', $baseTool->getId());
}
$form->addHtml('</div>');
$form->addButtonCreate($plugin->get_lang('AddExternalTool'));
if ($form->validate()) {
$formValues = $form->getSubmitValues();
$tool = null;
if ($baseTool) {
$tool = clone $baseTool;
} else {
$tool = new ImsLtiTool();
$tool
->setLaunchUrl($formValues['url'])
->setConsumerKey($formValues['consumer_key'])
->setSharedSecret($formValues['shared_secret'])
->setCustomParams(
empty($formValues['custom_params']) ? null : $formValues['custom_params']
);
}
$tool
->setName($formValues['name'])
->setDescription(
empty($formValues['description']) ? null : $formValues['description']
)
->setIsGlobal(false);
$em->persist($tool);
$em->flush();
$plugin->addCourseTool($course, $tool);
Display::addFlash(
Display::return_message($plugin->get_lang('ToolAdded'), 'success')
);
header('Location: '.api_get_course_url());
exit;
}
$template = new Template($plugin->get_lang('AddExternalTool'));
$template->assign('type', $baseTool ? $baseTool->getId() : null);
$template->assign('tools', $globalTools);
$template->assign('form', $form->returnForm());
$content = $template->fetch('ims_lti/view/add.tpl');
$actions = Display::url(
Display::return_icon('add.png', $plugin->get_lang('AddExternalTool'), [], ICON_SIZE_MEDIUM),
api_get_self().'?'.api_get_cidreq()
);
$template->assign('actions', Display::toolbarAction('lti_toolbar', [$actions]));
$template->assign('content', $content);
$template->display_one_col_template();

@ -11,6 +11,8 @@ $plugin = ImsLtiPlugin::create();
$em = Database::getManager();
$tools = $em->getRepository('ChamiloPluginBundle:ImsLti\ImsLtiTool')->findAll();
$interbreadcrumb[] = ['url' => api_get_path(WEB_CODE_PATH).'admin/index.php', 'name' => get_lang('PlatformAdmin')];
$template = new Template($plugin->get_title());
$template->assign('tools', $tools);

@ -0,0 +1,194 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool;
require_once __DIR__.'/../../main/inc/global.inc.php';
api_protect_course_script();
api_protect_teacher_script();
$plugin = ImsLtiPlugin::create();
$em = Database::getManager();
$toolsRepo = $em->getRepository('ChamiloPluginBundle:ImsLti\ImsLtiTool');
/** @var ImsLtiTool $baseTool */
$baseTool = isset($_REQUEST['type']) ? $toolsRepo->find(intval($_REQUEST['type'])) : null;
$action = !empty($_REQUEST['action']) ? $_REQUEST['action'] : 'add';
/** @var Course $course */
$course = $em->find('ChamiloCoreBundle:Course', api_get_course_int_id());
$addedTools = $toolsRepo->findBy(['course' => $course]);
$globalTools = $toolsRepo->findBy(['parent' => null, 'course' => null]);
if ($baseTool && !$baseTool->isGlobal()) {
Display::addFlash(
Display::return_message($plugin->get_lang('ToolNotAvailable'), 'warning')
);
header('Location: '.api_get_self().'?'.api_get_cidreq());
exit;
}
switch ($action) {
case 'add':
$form = new FrmAdd('ims_lti_add_tool', [], $baseTool);
$form->build();
if ($baseTool) {
$form->addHidden('type', $baseTool->getId());
}
if ($form->validate()) {
$formValues = $form->getSubmitValues();
$tool = new ImsLtiTool();
$tool
->setName($formValues['name'])
->setDescription(
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(
empty($formValues['custom_params']) ? null : $formValues['custom_params']
)
->setCourse($course)
->setActiveDeepLinking(!empty($formValues['deep_linking']))
->setPrivacy(
!empty($formValues['share_name']),
!empty($formValues['share_email']),
!empty($formValues['share_picture'])
);
if (null === $baseTool ||
($baseTool && !$baseTool->isActiveDeepLinking())
) {
$tool
->setActiveDeepLinking(
!empty($formValues['deep_linking'])
);
}
if ($baseTool) {
$tool->setParent($baseTool);
}
$em->persist($tool);
$em->flush();
if (!$tool->isActiveDeepLinking()) {
$plugin->addCourseTool($course, $tool);
}
Display::addFlash(
Display::return_message($plugin->get_lang('ToolAdded'), 'success')
);
header('Location: '.api_get_self().'?'.api_get_cidreq());
exit;
}
$form->setDefaultValues();
break;
case 'edit':
/** @var ImsLtiTool|null $tool */
$tool = null;
if (!empty($_REQUEST['id'])) {
$tool = $em->find('ChamiloPluginBundle:ImsLti\ImsLtiTool', (int) $_REQUEST['id']);
}
if (empty($tool) ||
!ImsLtiPlugin::existsToolInCourse($tool->getId(), $course)
) {
api_not_allowed(
true,
Display::return_message($plugin->get_lang('ToolNotAvailable'), 'error')
);
break;
}
$form = new FrmEdit('ims_lti_edit_tool', [], $tool);
$form->build(false);
if ($form->validate()) {
$formValues = $form->getSubmitValues();
$tool
->setName($formValues['name'])
->setDescription($formValues['description'])
->setActiveDeepLinking(
!empty($formValues['deep_linking'])
)
->setCustomParams(
empty($formValues['custom_params']) ? null : $formValues['custom_params']
)
->setPrivacy(
!empty($formValues['share_name']),
!empty($formValues['share_email']),
!empty($formValues['share_picture'])
);
if (null === $tool->getParent()) {
$tool
->setLaunchUrl($formValues['launch_url'])
->setConsumerKey($formValues['consumer_key'])
->setSharedSecret($formValues['shared_secret']);
}
$em->persist($tool);
$em->flush();
$courseTool = $plugin->findCourseToolByLink($course, $tool);
if ($courseTool) {
$plugin->updateCourseTool($courseTool, $tool);
}
Display::addFlash(
Display::return_message($plugin->get_lang('ToolEdited'), 'success')
);
header('Location: '.api_get_self().'?'.api_get_cidreq());
exit;
}
$form->setDefaultValues();
break;
}
$categories = Category::load(null, null, $course->getCode());
$template = new Template($plugin->get_lang('AddExternalTool'));
$template->assign('type', $baseTool ? $baseTool->getId() : null);
$template->assign('added_tools', $addedTools);
$template->assign('global_tools', $globalTools);
$template->assign('form', $form->returnForm());
$content = $template->fetch('ims_lti/view/add.tpl');
$actions = Display::url(
Display::return_icon('add.png', $plugin->get_lang('AddExternalTool'), [], ICON_SIZE_MEDIUM),
api_get_self().'?'.api_get_cidreq()
);
if (!empty($categories)) {
$actions .= Display::url(
Display::return_icon('gradebook.png', get_lang('MakeQualifiable'), [], ICON_SIZE_MEDIUM),
'./gradebook/add_eval.php?selectcat='.$categories[0]->get_id().'&'.api_get_cidreq()
);
}
$template->assign('actions', Display::toolbarAction('lti_toolbar', [$actions]));
$template->assign('content', $content);
$template->display_one_col_template();

@ -12,18 +12,8 @@ $plugin = ImsLtiPlugin::create();
$em = Database::getManager();
$form = new FormValidator('ism_lti_create_tool');
$form->addText('name', get_lang('Name'));
$form->addText('base_url', $plugin->get_lang('LaunchUrl'));
$form->addText('consumer_key', $plugin->get_lang('ConsumerKey'));
$form->addText('shared_secret', $plugin->get_lang('SharedSecret'));
$form->addButtonAdvancedSettings('lti_adv');
$form->addHtml('<div id="lti_adv_options" style="display:none;">');
$form->addTextarea('description', get_lang('Description'), ['rows' => 3]);
$form->addTextarea('custom_params', [$plugin->get_lang('CustomParams'), $plugin->get_lang('CustomParamsHelp')]);
$form->addCheckBox('deep_linking', $plugin->get_lang('SupportDeepLinking'), get_lang('Yes'));
$form->addHtml('</div>');
$form->addButtonCreate($plugin->get_lang('AddExternalTool'));
$form = new FrmAdd('ism_lti_create_tool');
$form->build();
if ($form->validate()) {
$formValues = $form->exportValues();
@ -32,13 +22,18 @@ if ($form->validate()) {
$externalTool
->setName($formValues['name'])
->setDescription($formValues['description'])
->setLaunchUrl($formValues['base_url'])
->setLaunchUrl($formValues['launch_url'])
->setConsumerKey($formValues['consumer_key'])
->setSharedSecret($formValues['shared_secret'])
->setCustomParams($formValues['custom_params'])
->setIsGlobal(true)
->setCourse(null)
->setActiveDeepLinking(
isset($formValues['deep_linking'])
)
->setPrivacy(
isset($formValues['share_name']),
isset($formValues['share_email']),
isset($formValues['share_picture'])
);
$em->persist($externalTool);
@ -52,11 +47,18 @@ if ($form->validate()) {
exit;
}
$template = new Template($plugin->get_lang('AddExternalTool'));
$form->setDefaultValues();
$interbreadcrumb[] = ['url' => api_get_path(WEB_CODE_PATH).'admin/index.php', 'name' => get_lang('PlatformAdmin')];
$interbreadcrumb[] = ['url' => api_get_path(WEB_PLUGIN_PATH).'ims_lti/admin.php', 'name' => $plugin->get_title()];
$pageTitle = $plugin->get_lang('AddExternalTool');
$template = new Template($pageTitle);
$template->assign('form', $form->returnForm());
$content = $template->fetch('ims_lti/view/add.tpl');
$template->assign('header', $plugin->get_title());
$template->assign('header', $pageTitle);
$template->assign('content', $content);
$template->display_one_col_template();

@ -29,28 +29,8 @@ if (!$tool) {
exit;
}
$form = new FormValidator('ims_lti_edit_tool');
$form->addText('name', get_lang('Name'));
$form->addText('url', $plugin->get_lang('LaunchUrl'));
$form->addText('consumer_key', $plugin->get_lang('ConsumerKey'));
$form->addText('shared_secret', $plugin->get_lang('SharedSecret'));
$form->addButtonAdvancedSettings('lti_adv');
$form->addHtml('<div id="lti_adv_options" style="display:none;">');
$form->addTextarea('description', get_lang('Description'), ['rows' => 3]);
$form->addTextarea('custom_params', [$plugin->get_lang('CustomParams'), $plugin->get_lang('CustomParamsHelp')]);
$form->addCheckBox('deep_linking', $plugin->get_lang('SupportDeepLinking'), get_lang('Yes'));
$form->addHtml('</div>');
$form->addButtonSave(get_lang('Save'));
$form->addHidden('id', $tool->getId());
$form->setDefaults([
'name' => $tool->getName(),
'description' => $tool->getDescription(),
'url' => $tool->getLaunchUrl(),
'consumer_key' => $tool->getConsumerKey(),
'shared_secret' => $tool->getSharedSecret(),
'custom_params' => $tool->getCustomParams(),
'deep_linking' => $tool->isActiveDeepLinking(),
]);
$form = new FrmEdit('ims_lti_edit_tool', [], $tool);
$form->build();
if ($form->validate()) {
$formValues = $form->exportValues();
@ -58,22 +38,42 @@ if ($form->validate()) {
$tool
->setName($formValues['name'])
->setDescription($formValues['description'])
->setLaunchUrl($formValues['url'])
->setConsumerKey($formValues['consumer_key'])
->setSharedSecret($formValues['shared_secret'])
->setCustomParams($formValues['custom_params']);
->setCustomParams($formValues['custom_params'])
->setPrivacy(
!empty($formValues['share_name']),
!empty($formValues['share_email']),
!empty($formValues['share_picture'])
);
if (null === $tool->getParent()) {
$tool
->setLaunchUrl($formValues['launch_url'])
->setConsumerKey($formValues['consumer_key'])
->setSharedSecret($formValues['shared_secret']);
}
if (null === $tool->getParent() ||
(null !== $tool->getParent() && !$tool->getParent()->isActiveDeepLinking())
) {
$tool->setActiveDeepLinking(!empty($formValues['deep_linking']));
}
$em->persist($tool);
$em->flush();
Display::addFlash(
Display::return_message($plugin->get_lang('ToolUpdated'), 'success')
Display::return_message($plugin->get_lang('ToolEdited'), 'success')
);
header('Location: '.api_get_path(WEB_PLUGIN_PATH).'ims_lti/admin.php');
exit;
}
$form->setDefaultValues();
$interbreadcrumb[] = ['url' => api_get_path(WEB_CODE_PATH).'admin/index.php', 'name' => get_lang('PlatformAdmin')];
$interbreadcrumb[] = ['url' => api_get_path(WEB_PLUGIN_PATH).'ims_lti/admin.php', 'name' => $plugin->get_title()];
$template = new Template($plugin->get_lang('EditExternalTool'));
$template->assign('form', $form->returnForm());

@ -15,7 +15,9 @@ api_block_anonymous_users(false);
$em = Database::getManager();
/** @var ImsLtiTool $tool */
$tool = isset($_GET['id']) ? $em->find('ChamiloPluginBundle:ImsLti\ImsLtiTool', intval($_GET['id'])) : 0;
$tool = isset($_GET['id'])
? $em->find('ChamiloPluginBundle:ImsLti\ImsLtiTool', (int) $_GET['id'])
: null;
if (!$tool) {
api_not_allowed(true);
@ -30,15 +32,16 @@ $course = $em->find('ChamiloCoreBundle:Course', api_get_course_int_id());
/** @var User $user */
$user = $em->find('ChamiloUserBundle:User', api_get_user_id());
$siteName = api_get_setting('siteName');
$toolUserId = ImsLtiPlugin::generateToolUserId($user);
$pluginPath = api_get_path(WEB_PLUGIN_PATH).'ims_lti/';
$toolUserId = ImsLtiPlugin::generateToolUserId($user->getId());
$platformDomain = str_replace(['https://', 'http://'], '', api_get_setting('InstitutionUrl'));
$params = [];
$params['lti_version'] = 'LTI-1p0';
if ($tool->isActiveDeepLinking()) {
$params['lti_message_type'] = 'ContentItemSelectionRequest';
$params['content_item_return_url'] = api_get_path(WEB_PLUGIN_PATH).'ims_lti/item_return.php';
$params['content_item_return_url'] = $pluginPath.'item_return.php';
$params['accept_media_types'] = '*/*';
$params['accept_presentation_document_targets'] = 'iframe';
//$params['accept_unsigned'];
@ -53,15 +56,38 @@ if ($tool->isActiveDeepLinking()) {
$params['resource_link_id'] = $tool->getId();
$params['resource_link_title'] = $tool->getName();
$params['resource_link_description'] = $tool->getDescription();
$toolEval = $tool->getGradebookEval();
if (!empty($toolEval)) {
$params['lis_result_sourcedid'] = $toolEval->getId().':'.$user->getId();
$params['lis_outcome_service_url'] = api_get_path(WEB_PATH).'ims_lti/outcome_service/'.$tool->getId();
$params['lis_person_sourcedid'] = "$platformDomain:$toolUserId";
$params['lis_course_offering_sourcedid'] = "$platformDomain:".$course->getId();
if ($session) {
$params['lis_course_offering_sourcedid'] .= ':'.$session->getId();
}
}
}
$params['user_id'] = $toolUserId;
if ($tool->isSharingPicture()) {
$params['user_image'] = UserManager::getUserPicture($user->getId());
}
$params['user_id'] = ImsLtiPlugin::generateToolUserId($user->getId());
$params['user_image'] = UserManager::getUserPicture($user->getId());
$params['roles'] = ImsLtiPlugin::getUserRoles($user);
$params['lis_person_name_given'] = $user->getFirstname();
$params['lis_person_name_family'] = $user->getLastname();
$params['lis_person_name_full'] = $user->getCompleteName();
$params['lis_person_contact_email_primary'] = $user->getEmail();
if ($tool->isSharingName()) {
$params['lis_person_name_given'] = $user->getFirstname();
$params['lis_person_name_family'] = $user->getLastname();
$params['lis_person_name_full'] = $user->getCompleteName();
}
if ($tool->isSharingEmail()) {
$params['lis_person_contact_email_primary'] = $user->getEmail();
}
if (api_is_allowed_to_edit(false, true)) {
$params['role_scope_mentor'] = ImsLtiPlugin::getRoleScopeMentor($course, $session);
@ -75,11 +101,13 @@ $params['launch_presentation_locale'] = api_get_language_isocode();
$params['launch_presentation_document_target'] = 'iframe';
$params['tool_consumer_info_product_family_code'] = 'Chamilo LMS';
$params['tool_consumer_info_version'] = api_get_version();
$params['tool_consumer_instance_guid'] = str_replace(['https://', 'http://'], '', api_get_setting('InstitutionUrl'));
$params['tool_consumer_instance_name'] = $siteName;
$params['tool_consumer_instance_guid'] = $platformDomain;
$params['tool_consumer_instance_name'] = api_get_setting('siteName');
$params['tool_consumer_instance_url'] = api_get_path(WEB_PATH);
$params['tool_consumer_instance_contact_email'] = api_get_setting('emailAdministrator');
$params += $tool->parseCustomParams();
$oauth = new OAuthSimple(
$tool->getConsumerKey(),
$tool->getSharedSecret()

@ -0,0 +1,193 @@
<?php
/* For licensing terms, see /license.txt */
class OutcomeForm extends EvalForm
{
/**
* Builds a form containing form items based on a given parameter.
*
* @param int $form_type 1=add, 2=edit,3=move,4=result_add
* @param Evaluation $evaluation_object the category object
* @param obj $result_object the result object
* @param string $form_name
* @param string $method
* @param string $action
*/
public function __construct(
$evaluation_object,
$result_object,
$form_name,
$method = 'post',
$action = null,
$extra1 = null,
$extra2 = null
) {
parent::__construct(
-1,
$evaluation_object,
$result_object,
$form_name,
$method,
$action,
$extra1,
$extra2
);
$this->build_add_form();
$this->setDefaults();
}
/**
* Builds a basic form that is used in add and edit.
*
* @param int $edit
*
* @throws Exception
*/
private function build_basic_form($edit = 0)
{
$this->addElement('header', get_plugin_lang('NewOutcomeFormTitle'));
$this->addElement('hidden', 'hid_user_id');
$this->addElement('hidden', 'hid_course_code');
$this->addText(
'name',
get_lang('EvaluationName'),
true,
[
'maxlength' => '50',
'id' => 'evaluation_title',
]
);
$cat_id = $this->evaluation_object->get_category_id();
$session_id = api_get_session_id();
$course_code = api_get_course_id();
$all_categories = Category:: load(null, null, $course_code, null, null, $session_id, false);
if (count($all_categories) == 1) {
$this->addElement('hidden', 'hid_category_id', $cat_id);
} else {
$select_gradebook = $this->addElement(
'select',
'hid_category_id',
get_lang('SelectGradebook'),
[],
['id' => 'hid_category_id']
);
$this->addRule('hid_category_id', get_lang('ThisFieldIsRequired'), 'nonzero');
$default_weight = 0;
if (!empty($all_categories)) {
foreach ($all_categories as $my_cat) {
if ($my_cat->get_course_code() == api_get_course_id()) {
$grade_model_id = $my_cat->get_grade_model_id();
if (empty($grade_model_id)) {
if ($my_cat->get_parent_id() == 0) {
$default_weight = $my_cat->get_weight();
$select_gradebook->addoption(get_lang('Default'), $my_cat->get_id());
$cats_added[] = $my_cat->get_id();
} else {
$select_gradebook->addoption($my_cat->get_name(), $my_cat->get_id());
$cats_added[] = $my_cat->get_id();
}
} else {
$select_gradebook->addoption(get_lang('Select'), 0);
}
if ($this->evaluation_object->get_category_id() == $my_cat->get_id()) {
$default_weight = $my_cat->get_weight();
}
}
}
}
}
$this->addFloat(
'weight_mask',
[
get_lang('Weight'),
null,
' [0 .. <span id="max_weight">'.$all_categories[0]->get_weight().'</span>] ',
],
true,
[
'size' => '4',
'maxlength' => '5',
]
);
if ($edit) {
if (!$this->evaluation_object->has_results()) {
$this->addText(
'max',
get_lang('QualificationNumeric'),
true,
[
'maxlength' => '5',
]
);
} else {
$this->addText(
'max',
[get_lang('QualificationNumeric'), get_lang('CannotChangeTheMaxNote')],
false,
[
'maxlength' => '5',
'disabled' => 'disabled',
]
);
}
} else {
$this->addText(
'max',
get_lang('QualificationNumeric'),
true,
[
'maxlength' => '5',
]
);
$default_max = api_get_setting('gradebook_default_weight');
$defaults['max'] = isset($default_max) ? $default_max : 100;
$this->setDefaults($defaults);
}
$this->addElement('textarea', 'description', get_lang('Description'));
$this->addRule('hid_category_id', get_lang('ThisFieldIsRequired'), 'required');
$this->addElement('checkbox', 'visible', null, get_lang('Visible'));
$this->addRule('max', get_lang('OnlyNumbers'), 'numeric');
$this->addRule(
'max',
get_lang('NegativeValue'),
'compare',
'>=',
'server',
false,
false,
0
);
$setting = api_get_setting('tool_visible_by_default_at_creation');
$visibility_default = 1;
if (isset($setting['gradebook']) && $setting['gradebook'] == 'false') {
$visibility_default = 0;
}
$this->setDefaults(['visible' => $visibility_default]);
}
/**
*
*/
protected function build_add_form()
{
$this->setDefaults(
[
'hid_user_id' => $this->evaluation_object->get_user_id(),
'hid_category_id' => $this->evaluation_object->get_category_id(),
'hid_course_code' => $this->evaluation_object->get_course_code(),
'created_at' => api_get_utc_datetime(),
]
);
$this->build_basic_form();
$this->addButtonCreate(get_lang('AddAssessment'), 'submit');
}
}

@ -0,0 +1,144 @@
<?php
/* For licensing terms, see /license.txt */
/**
* @package plugin.ims_lti
*/
use Chamilo\CoreBundle\Entity\GradebookEvaluation;
use Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool;
require_once __DIR__.'/../../../main/inc/global.inc.php';
$current_course_tool = TOOL_GRADEBOOK;
api_protect_course_script(true);
api_block_anonymous_users();
GradebookUtils::block_students();
$select_cat = isset($_GET['selectcat']) ? (int) $_GET['selectcat'] : 0;
$is_allowedToEdit = $is_courseAdmin;
$em = Database::getManager();
/** @var \Chamilo\CoreBundle\Entity\Course $course */
$course = $em->find('ChamiloCoreBundle:Course', api_get_course_int_id());
$ltiToolRepo = $em->getRepository('ChamiloPluginBundle:ImsLti\ImsLtiTool');
$categories = Category::load(null, null, $course->getCode());
if (empty($categories)) {
$message = Display::return_message(
get_plugin_lang('GradebookNotSetWarning', 'ImsLtiPlugin'),
'warning'
);
api_not_allowed(true, $message);
}
$evaladd = new Evaluation();
$evaladd->set_user_id($_user['user_id']);
if (!empty($select_cat)) {
$evaladd->set_category_id($_GET['selectcat']);
$cat = Category::load($_GET['selectcat']);
$evaladd->set_course_code($cat[0]->get_course_code());
} else {
$evaladd->set_category_id(0);
}
$form = new EvalForm(
EvalForm::TYPE_ADD,
$evaladd,
null,
'add_eval_form',
null,
api_get_self().'?selectcat='.$select_cat.'&'.api_get_cidreq()
);
$form->removeElement('name');
$form->removeElement('addresult');
$slcLtiTools = $form->createElement('select', 'name', get_lang('Tool'));
$form->insertElementBefore($slcLtiTools, 'hid_category_id');
$form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
$ltiTools = $ltiToolRepo->findBy(['course' => $course, 'gradebookEval' => null]);
/** @var ImsLtiTool $ltiTool */
foreach ($ltiTools as $ltiTool) {
$slcLtiTools->addOption($ltiTool->getName(), $ltiTool->getId());
}
if ($form->validate()) {
$values = $form->exportValues();
/** @var ImsLtiTool $ltiTool */
$ltiTool = $ltiToolRepo->find($values['name']);
if (!$ltiTool) {
api_not_allowed();
}
$eval = new Evaluation();
$eval->set_name($ltiTool->getName());
$eval->set_description($values['description']);
$eval->set_user_id($values['hid_user_id']);
if (!empty($values['hid_course_code'])) {
$eval->set_course_code($values['hid_course_code']);
}
//Always add the gradebook to the course
$eval->set_course_code(api_get_course_id());
$eval->set_category_id($values['hid_category_id']);
$parent_cat = Category::load($values['hid_category_id']);
$global_weight = $cat[0]->get_weight();
//$values['weight'] = $values['weight_mask']/$global_weight*$parent_cat[0]->get_weight();
$values['weight'] = $values['weight_mask'];
$eval->set_weight($values['weight']);
$eval->set_max($values['max']);
$eval->set_visible(empty($values['visible']) ? 0 : 1);
$eval->add();
/** @var GradebookEvaluation $gradebookEval */
$gradebookEval = $em->find('ChamiloCoreBundle:GradebookEvaluation', $eval->get_id());
$ltiTool->setGradebookEval($gradebookEval);
$em->persist($ltiTool);
$em->flush();
header('Location: '.Category::getUrl().'selectcat='.$eval->get_category_id());
exit;
}
$interbreadcrumb[] = [
'url' => Category::getUrl().'selectcat='.$select_cat,
'name' => get_lang('Gradebook'),
];
$this_section = SECTION_COURSES;
$htmlHeadXtra[] = '<script>
$(document).ready( function() {
$("#hid_category_id").change(function() {
$("#hid_category_id option:selected").each(function () {
var cat_id = $(this).val();
$.ajax({
url: "'.api_get_path(WEB_AJAX_PATH).'gradebook.ajax.php?a=get_gradebook_weight",
data: "cat_id="+cat_id,
success: function(return_value) {
if (return_value != 0 ) {
$("#max_weight").html(return_value);
}
}
});
});
});
});
</script>';
Display::display_header(get_lang('NewEvaluation'));
$form->display();
Display::display_footer();

@ -23,7 +23,33 @@ $course = $em->find('ChamiloCoreBundle:Course', api_get_course_int_id());
$ltiTool = $em->find('ChamiloPluginBundle:ImsLti\ImsLtiTool', $toolId);
if (!$ltiTool) {
api_not_allowed(false);
api_not_allowed();
}
$oauth = new OAuthSimple(
$_POST['oauth_consumer_key'],
$ltiTool->getSharedSecret()
);
$oauth->setAction('POST');
$oauth->setSignatureMethod($_POST['oauth_signature_method']);
$result = $oauth->sign(
[
'path' => api_get_path(WEB_PLUGIN_PATH).'ims_lti/item_return.php',
'parameters' => [
'content_items' => $_POST['content_items'],
'data' => $_POST['data'],
'lti_version' => $_POST['lti_version'],
'lti_message_type' => $_POST['lti_message_type'],
'oauth_nonce' => $_POST['oauth_nonce'],
'oauth_timestamp' => $_POST['oauth_timestamp'],
'oauth_signature_method' => $_POST['oauth_signature_method'],
'oauth_callback' => $_POST['oauth_callback'],
],
]
);
if ($result['parameters']['oauth_signature'] !== $_POST['oauth_signature']) {
api_not_allowed();
}
$contentItems = json_decode($_POST['content_items'], true);

@ -23,7 +23,16 @@ $strings['IsGlobal'] = 'Is global';
$strings['EditExternalTool'] = 'Edit external tool';
$strings['ToolDeleted'] = 'Tool deleted';
$strings['ToolAdded'] = 'Tool added';
$strings['ToolUpdated'] = 'Tool updated';
$strings['PressToContinue'] = 'Press to continue to external tool';
$strings['ConfigureExternalTool'] = 'Configure external tools';
$strings['SupportDeepLinking'] = 'Support Deep-Linking';
$strings['ScoreNotSet'] = 'Score not set';
$strings['ScoreForXUserIsYScore'] = 'Score for %s is %s';
$strings['ToolsAdded'] = 'Added tools';
$strings['ToolEdited'] = 'Tool edited';
$strings['ShareLauncherName'] = 'Share launcher\'s name';
$strings['ShareLauncherEmail'] = 'Share launcher\'s email';
$strings['ShareLauncherPicture'] = 'Share launcher\'s picture';
$strings['NoTool'] = 'Tool not exists';
$strings['ToolAddedOnCourseX'] = 'Tool addeed on course <strong>%s</strong>.';
$strings['SupportDeppLinkingHelp'] = 'Contact your Tool Provider to verify if Deep Linking support is mandatory';

@ -23,7 +23,16 @@ $strings['IsGlobal'] = 'Est global';
$strings['EditExternalTool'] = 'Éditer outil externe';
$strings['ToolDeleted'] = 'Outil supprimé';
$strings['ToolAdded'] = 'Outil ajouté';
$strings['ToolAdded'] = 'outil mis à jour';
$strings['PressToContinue'] = 'Appuyez sur pour continuer à l\'outil externe';
$strings['ConfigureExternalTool'] = 'Configure external tools';
$strings['SupportDeepLinking'] = 'Support Deep-Linking';
$strings['ScoreNotSet'] = 'Score non défini';
$strings['ScoreForXUserIsYScore'] = 'Score pour %s est %s';
$strings['ToolsAdded'] = 'Outils ajoutés';
$strings['ToolEdited'] = 'Outil édité';
$strings['ShareLauncherName'] = 'Share launcher\'s name';
$strings['ShareLauncherEmail'] = 'Share launcher\'s email';
$strings['ShareLauncherPicture'] = 'Share launcher\'s picture';
$strings['NoTool'] = 'Tool not exists';
$strings['ToolAddedOnCourseX'] = 'Tool addeed on course <strong>%s</strong>.';
$strings['SupportDeppLinkingHelp'] = 'Contact your Tool Provider to verify if Deep Linking support is mandatory';

@ -23,7 +23,16 @@ $strings['IsGlobal'] = 'Es global';
$strings['EditExternalTool'] = 'Editar herramienta externa';
$strings['ToolDeleted'] = 'Herramienta eliminada';
$strings['ToolAdded'] = 'Herramienta agregada';
$strings['ToolUpdated'] = 'Herramienta actualizada';
$strings['PressToContinue'] = 'Presione para continuar con la herramienta externa';
$strings['ConfigureExternalTool'] = 'Configure external tools';
$strings['SupportDeepLinking'] = 'Support Deep-Linking';
$strings['SupportDeepLinking'] = 'Soportar Deep-Linking';
$strings['ScoreNotSet'] = 'Puntuación no establecida';
$strings['ScoreForXUserIsYScore'] = 'Puntuación para %s es %s';
$strings['ToolsAdded'] = 'Herramientas agregadas';
$strings['ToolEdited'] = 'Herramienta editada';
$strings['ShareLauncherName'] = 'Enviar el nombre del usuario';
$strings['ShareLauncherEmail'] = 'Enviar el correo electrónico del usuario';
$strings['ShareLauncherPicture'] = 'Enviar la foto del usuario';
$strings['NoTool'] = 'La herramienta no existe';
$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';

@ -0,0 +1,64 @@
<?php
/* For license terms, see /license.txt */
use Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool;
require_once __DIR__.'/../../main/inc/global.inc.php';
require_once './OAuthSimple.php';
header('Content-Type: application/xml');
if (empty($_GET['t'])) {
exit;
}
$em = Database::getManager();
/** @var ImsLtiTool $tool */
$tool = $em->find('ChamiloPluginBundle:ImsLti\ImsLtiTool', (int) $_GET['t']);
if (empty($tool)) {
exit;
}
$body = file_get_contents('php://input');
$bodyHash = OAuthSimple::generateBodyHash($body);
$url = api_get_path(WEB_PATH).'ims_lti/outcome_service/'.$tool->getId();
$headers = getallheaders();
$params = OAuthSimple::getAuthorizationParams($headers['Authorization']);
if (empty($params)) {
exit;
}
$oauth = new OAuthSimple(
$params['oauth_consumer_key'],
$tool->getSharedSecret()
);
$oauth->setAction('POST');
$oauth->setSignatureMethod('HMAC-SHA1');
$result = $oauth->sign(
[
'path' => $url,
'parameters' => [
'oauth_body_hash' => $params['oauth_body_hash'],
'oauth_nonce' => $params['oauth_nonce'],
'oauth_timestamp' => $params['oauth_timestamp'],
'oauth_signature_method' => $params['oauth_signature_method'],
],
]
);
$signatureValid = urldecode($result['signature']) == $params['oauth_signature'];
$bodyHashValid = $bodyHash === $params['oauth_body_hash'];
if (!$signatureValid || !$bodyHashValid) {
exit;
}
$plugin = ImsLtiPlugin::create();
$process = $plugin->processServiceRequest();
echo $process;

@ -0,0 +1,94 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool;
/**
* Class FrmAdd.
*/
class FrmAdd extends FormValidator
{
/**
* @var ImsLtiTool|null
*/
private $baseTool;
/**
* FrmAdd constructor.
*
* @param string $name
* @param array $attributes
* @param ImsLtiTool|null $tool
*/
public function __construct(
$name,
$attributes = [],
ImsLtiTool $tool = null
) {
parent::__construct($name, 'POST', '', '', $attributes, self::LAYOUT_HORIZONTAL, true);
$this->baseTool = $tool;
}
/**
* Build the form
*/
public function build()
{
$plugin = ImsLtiPlugin::create();
$this->addHeader($plugin->get_lang('ToolSettings'));
$this->addText('name', get_lang('Name'));
$this->addTextarea('description', get_lang('Description'));
if (null === $this->baseTool) {
$this->addElement('url', 'launch_url', $plugin->get_lang('LaunchUrl'));
$this->addRule('launch_url', get_lang('Required'), 'required');
$this->addText('consumer_key', $plugin->get_lang('ConsumerKey'));
$this->addText('shared_secret', $plugin->get_lang('SharedSecret'));
}
$this->addButtonAdvancedSettings('lti_adv');
$this->addHtml('<div id="lti_adv_options" style="display:none;">');
$this->addTextarea(
'custom_params',
[$plugin->get_lang('CustomParams'), $plugin->get_lang('CustomParamsHelp')]
);
if (null === $this->baseTool ||
($this->baseTool && !$this->baseTool->isActiveDeepLinking())
) {
$this->addCheckBox(
'deep_linking',
[null, $plugin->get_lang('SupportDeppLinkingHelp'), null],
$plugin->get_lang('SupportDeepLinking')
);
}
$this->addHtml('</div>');
$this->addButtonAdvancedSettings('lti_privacy', get_lang('Privacy'));
$this->addHtml('<div id="lti_privacy_options" style="display:none;">');
$this->addCheckBox('share_name', null, $plugin->get_lang('ShareLauncherName'));
$this->addCheckBox('share_email', null, $plugin->get_lang('ShareLauncherEmail'));
$this->addCheckBox('share_picture', null, $plugin->get_lang('ShareLauncherPicture'));
$this->addHtml('</div>');
$this->addButtonCreate($plugin->get_lang('AddExternalTool'));
$this->applyFilter('__ALL__', 'Security::remove_XSS');
}
public function setDefaultValues()
{
if (null !== $this->baseTool) {
$this->setDefaults(
[
'name' => $this->baseTool->getName(),
'description' => $this->baseTool->getDescription(),
'custom_params' => $this->baseTool->getCustomParams(),
'share_name' => $this->baseTool->isSharingName(),
'share_email' => $this->baseTool->isSharingEmail(),
'share_picture' => $this->baseTool->isSharingPicture(),
]
);
}
}
}

@ -0,0 +1,115 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\PluginBundle\Entity\ImsLti\ImsLtiTool;
/**
* Class FrmAdd.
*/
class FrmEdit extends FormValidator
{
/**
* @var ImsLtiTool|null
*/
private $tool;
/**
* FrmAdd constructor.
*
* @param string $name
* @param array $attributes
* @param ImsLtiTool|null $tool
*/
public function __construct(
$name,
$attributes = [],
ImsLtiTool $tool = null
) {
parent::__construct($name, 'POST', '', '', $attributes, self::LAYOUT_HORIZONTAL, true);
$this->tool = $tool;
}
/**
* Build the form.
*
* @param bool $globalMode
*
* @throws Exception
*/
public function build($globalMode = true)
{
$plugin = ImsLtiPlugin::create();
$course = $this->tool->getCourse();
$parent = $this->tool->getParent();
$this->addHeader($plugin->get_lang('ToolSettings'));
if (null !== $course && $globalMode) {
$this->addHtml(
Display::return_message(
sprintf($plugin->get_lang('ToolAddedOnCourseX'), $course->getTitle()),
'normal',
false
)
);
}
$this->addText('name', get_lang('Name'));
$this->addTextarea('description', get_lang('Description'));
if (null === $parent) {
$this->addElement('url', 'launch_url', $plugin->get_lang('LaunchUrl'));
$this->addRule('launch_url', get_lang('Required'), 'required');
$this->addText('consumer_key', $plugin->get_lang('ConsumerKey'));
$this->addText('shared_secret', $plugin->get_lang('SharedSecret'));
}
$this->addButtonAdvancedSettings('lti_adv');
$this->addHtml('<div id="lti_adv_options" style="display:none;">');
$this->addTextarea(
'custom_params',
[$plugin->get_lang('CustomParams'), $plugin->get_lang('CustomParamsHelp')]
);
if (null === $parent ||
(null !== $parent && !$parent->isActiveDeepLinking())
) {
$this->addCheckBox(
'deep_linking',
[null, $plugin->get_lang('SupportDeppLinkingHelp'), null],
$plugin->get_lang('SupportDeepLinking')
);
}
$this->addHtml('</div>');
$this->addButtonAdvancedSettings('lti_privacy', get_lang('Privacy'));
$this->addHtml('<div id="lti_privacy_options" style="display:none;">');
$this->addCheckBox('share_name', null, $plugin->get_lang('ShareLauncherName'));
$this->addCheckBox('share_email', null, $plugin->get_lang('ShareLauncherEmail'));
$this->addCheckBox('share_picture', null, $plugin->get_lang('ShareLauncherPicture'));
$this->addHtml('</div>');
$this->addButtonCreate($plugin->get_lang('EditExternalTool'));
$this->addHidden('id', $this->tool->getId());
$this->addHidden('action', 'edit');
$this->applyFilter('__ALL__', 'Security::remove_XSS');
}
public function setDefaultValues()
{
$this->setDefaults(
[
'name' => $this->tool->getName(),
'description' => $this->tool->getDescription(),
'launch_url' => $this->tool->getLaunchUrl(),
'consumer_key' => $this->tool->getConsumerKey(),
'shared_secret' => $this->tool->getSharedSecret(),
'custom_params' => $this->tool->getCustomParams(),
'deep_linking' => $this->tool->isActiveDeepLinking(),
'share_name' => $this->tool->isSharingName(),
'share_email' => $this->tool->isSharingEmail(),
'share_picture' => $this->tool->isSharingPicture(),
]
);
}
}

@ -0,0 +1,65 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\GradebookEvaluation;
use Chamilo\UserBundle\Entity\User;
/**
* Class ImsLtiDeleteServiceRequest.
*/
class ImsLtiServiceDeleteRequest extends ImsLtiServiceRequest
{
/**
* ImsLtiDeleteServiceRequest constructor.
*
* @param SimpleXMLElement $xml
*/
public function __construct(SimpleXMLElement $xml)
{
parent::__construct($xml);
$this->responseType = ImsLtiServiceResponse::TYPE_DELETE;
$this->xmlRequest = $this->xmlRequest->deleteResultRequest;
}
protected function processBody()
{
$resultRecord = $this->xmlRequest->resultRecord;
$sourcedId = (string) $resultRecord->sourcedGUID->sourcedId;
$sourcedParts = explode(':', $sourcedId);
$em = Database::getManager();
/** @var GradebookEvaluation $evaluation */
$evaluation = $em->find('ChamiloCoreBundle:GradebookEvaluation', $sourcedParts[0]);
/** @var User $user */
$user = $em->find('ChamiloUserBundle:User', $sourcedParts[1]);
if (empty($evaluation) || empty($user)) {
$this->statusInfo
->setSeverity(ImsLtiServiceResponseStatus::SEVERITY_STATUS)
->setCodeMajor(ImsLtiServiceResponseStatus::CODEMAJOR_FAILURE);
return;
}
$results = Result::load(null, $user->getId(), $evaluation->getId());
if (empty($results)) {
$this->statusInfo
->setSeverity(ImsLtiServiceResponseStatus::SEVERITY_STATUS)
->setCodeMajor(ImsLtiServiceResponseStatus::CODEMAJOR_FAILURE);
return;
}
/** @var Result $result */
$result = $results[0];
$result->addResultLog($user->getId(), $evaluation->getId());
$result->delete();
$this->statusInfo
->setSeverity(ImsLtiServiceResponseStatus::SEVERITY_STATUS)
->setCodeMajor(ImsLtiServiceResponseStatus::CODEMAJOR_SUCCESS);
}
}

@ -0,0 +1,29 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Class ImsLtiServiceDeleteResponse.
*/
class ImsLtiServiceDeleteResponse extends ImsLtiServiceResponse
{
/**
* ImsLtiServiceDeleteResponse constructor.
*
* @param ImsLtiServiceResponseStatus $statusInfo
* @param mixed|null $bodyParam
*/
public function __construct(ImsLtiServiceResponseStatus $statusInfo, $bodyParam = null)
{
$statusInfo->setOperationRefIdentifier('deleteResult');
parent::__construct($statusInfo, $bodyParam);
}
/**
* @param SimpleXMLElement $xmlBody
*/
protected function generateBody(SimpleXMLElement $xmlBody)
{
$xmlBody->addChild('deleteResultResponse');
}
}

@ -0,0 +1,73 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\GradebookEvaluation;
use Chamilo\UserBundle\Entity\User;
/**
* Class ImsLtiServiceReadRequest.
*/
class ImsLtiServiceReadRequest extends ImsLtiServiceRequest
{
/**
* ImsLtiServiceReadRequest constructor.
*
* @param SimpleXMLElement $xml
*/
public function __construct(SimpleXMLElement $xml)
{
parent::__construct($xml);
$this->responseType = ImsLtiServiceResponse::TYPE_READ;
$this->xmlRequest = $this->xmlRequest->readResultRequest;
}
protected function processBody()
{
$resultRecord = $this->xmlRequest->resultRecord;
$sourcedId = (string) $resultRecord->sourcedGUID->sourcedId;
$sourcedParts = explode(':', $sourcedId);
$em = Database::getManager();
/** @var GradebookEvaluation $evaluation */
$evaluation = $em->find('ChamiloCoreBundle:GradebookEvaluation', $sourcedParts[0]);
/** @var User $user */
$user = $em->find('ChamiloUserBundle:User', $sourcedParts[1]);
if (empty($evaluation) || empty($user)) {
$this->statusInfo
->setSeverity(ImsLtiServiceResponseStatus::SEVERITY_STATUS)
->setCodeMajor(ImsLtiServiceResponseStatus::CODEMAJOR_FAILURE);
return;
}
$results = Result::load(null, $user->getId(), $evaluation->getId());
$ltiScore = '';
$responseDescription = get_plugin_lang('ScoreNotSet', 'ImsLtiPlugin');
if (!empty($results)) {
/** @var Result $result */
$result = $results[0];
if (!empty($result->get_score())) {
$ltiScore = $result->get_score() / $evaluation->getMax();
$responseDescription = sprintf(
get_plugin_lang('ScoreForXUserIsYScore', 'ImsLtiPlugin'),
$user->getId(),
$ltiScore
);
}
}
$this->statusInfo
->setSeverity(ImsLtiServiceResponseStatus::SEVERITY_STATUS)
->setCodeMajor(ImsLtiServiceResponseStatus::CODEMAJOR_SUCCESS)
->setDescription($responseDescription);
$this->responseBodyParam = (string) $ltiScore;
}
}

@ -0,0 +1,35 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Class ImsLtiReadServiceResponse
*/
class ImsLtiServiceReadResponse extends ImsLtiServiceResponse
{
/**
* ImsLtiServiceReadResponse constructor.
*
* @param ImsLtiServiceResponseStatus $statusInfo
* @param mixed|null $bodyParam
*/
public function __construct(ImsLtiServiceResponseStatus $statusInfo, $bodyParam = null)
{
$statusInfo->setOperationRefIdentifier('readResult');
parent::__construct($statusInfo, $bodyParam);
}
/**
* @param SimpleXMLElement $xmlBody
*/
protected function generateBody(SimpleXMLElement $xmlBody)
{
$resultResponse = $xmlBody->addChild('readResultResponse');
$xmlResultScore = $resultResponse->addChild('result')
->addChild('resultScore');
$xmlResultScore->addChild('language', 'en');
$xmlResultScore->addChild('textString', $this->bodyParams);
}
}

@ -0,0 +1,84 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\GradebookEvaluation;
use Chamilo\UserBundle\Entity\User;
/**
* Class ImsLtiReplaceServiceRequest.
*/
class ImsLtiServiceReplaceRequest extends ImsLtiServiceRequest
{
/**
* ImsLtiReplaceServiceRequest constructor.
*
* @param SimpleXMLElement $xml
*/
public function __construct(SimpleXMLElement $xml)
{
parent::__construct($xml);
$this->responseType = ImsLtiServiceResponse::TYPE_DELETE;
$this->xmlRequest = $this->xmlRequest->replaceResultRequest;
}
protected function processBody()
{
$resultRecord = $this->xmlRequest->resultRecord;
$sourcedId = (string) $resultRecord->sourcedGUID->sourcedId;
$resultScore = (float) $resultRecord->result->resultScore->textString;
if (0 > $resultScore || 1 < $resultScore) {
$this->statusInfo
->setSeverity(ImsLtiServiceResponseStatus::SEVERITY_WARNING)
->setCodeMajor(ImsLtiServiceResponseStatus::CODEMAJOR_FAILURE);
return;
}
$sourcedParts = explode(':', $sourcedId);
$em = Database::getManager();
/** @var GradebookEvaluation $evaluation */
$evaluation = $em->find('ChamiloCoreBundle:GradebookEvaluation', $sourcedParts[0]);
/** @var User $user */
$user = $em->find('ChamiloUserBundle:User', $sourcedParts[1]);
if (empty($evaluation) || empty($user)) {
$this->statusInfo
->setSeverity(ImsLtiServiceResponseStatus::SEVERITY_STATUS)
->setCodeMajor(ImsLtiServiceResponseStatus::CODEMAJOR_FAILURE);
return;
}
$score = $evaluation->getMax() * $resultScore;
$results = Result::load(null, $user->getId(), $evaluation->getId());
if (empty($results)) {
$result = new Result();
$result->set_evaluation_id($evaluation->getId());
$result->set_user_id($user->getId());
$result->set_score($score);
$result->add();
} else {
/** @var Result $result */
$result = $results[0];
$result->addResultLog($user->getId(), $evaluation->getId());
$result->set_score($score);
$result->save();
}
$this->statusInfo
->setSeverity(ImsLtiServiceResponseStatus::SEVERITY_STATUS)
->setCodeMajor(ImsLtiServiceResponseStatus::CODEMAJOR_SUCCESS)
->setDescription(
sprintf(
get_plugin_lang('ScoreForXUserIsYScore', 'ImsLtiPlugin'),
$user->getId(),
$resultScore
)
);
}
}

@ -0,0 +1,29 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Class ImsLtiReplaceServiceResponse.
*/
class ImsLtiServiceReplaceResponse extends ImsLtiServiceResponse
{
/**
* ImsLtiServiceReplaceResponse constructor.
*
* @param ImsLtiServiceResponseStatus $statusInfo
* @param mixed|null $bodyParam
*/
public function __construct(ImsLtiServiceResponseStatus $statusInfo, $bodyParam = null)
{
$statusInfo->setOperationRefIdentifier('replaceResult');
parent::__construct($statusInfo, $bodyParam);
}
/**
* @param SimpleXMLElement $xmlBody
*/
protected function generateBody(SimpleXMLElement $xmlBody)
{
$xmlBody->addChild('replaceResultResponse');
}
}

@ -0,0 +1,82 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Class ImsLtiServiceRequest.
*/
abstract class ImsLtiServiceRequest
{
/**
* @var string
*/
protected $responseType;
/**
* @var SimpleXMLElement
*/
protected $xmlHeaderInfo;
/**
* @var SimpleXMLElement
*/
protected $xmlRequest;
/**
* @var ImsLtiServiceResponseStatus
*/
protected $statusInfo;
/**
* @var mixed
*/
protected $responseBodyParam;
/**
* ImsLtiServiceRequest constructor.
*
* @param SimpleXMLElement $xml
*/
public function __construct(SimpleXMLElement $xml)
{
$this->statusInfo = new ImsLtiServiceResponseStatus();
$this->xmlHeaderInfo = $xml->imsx_POXHeader->imsx_POXRequestHeaderInfo;
$this->xmlRequest = $xml->imsx_POXBody->children();
}
protected function processHeader()
{
$info = $this->xmlHeaderInfo;
$this->statusInfo->setMessageRefIdentifier($info->imsx_messageIdentifier);
error_log("Service Request: tool version {$info->imsx_version} message ID {$info->imsx_messageIdentifier}");
}
abstract protected function processBody();
/**
* @return ImsLtiServiceResponse|null
*/
private function generateResponse()
{
$response = ImsLtiServiceResponseFactory::create(
$this->responseType,
$this->statusInfo,
$this->responseBodyParam
);
return $response;
}
/**
* @return ImsLtiServiceResponse|null
*/
public function process()
{
$this->processHeader();
$this->processBody();
return $this->generateResponse();
}
}

@ -0,0 +1,31 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Class ImsLtiServiceRequestFactory.
*/
class ImsLtiServiceRequestFactory
{
/**
* @param SimpleXMLElement $xml
*
* @return ImsLtiServiceRequest|null
*/
public static function create(SimpleXMLElement $xml)
{
$bodyChildren = $xml->imsx_POXBody->children();
if (!empty($bodyChildren)) {
switch ($bodyChildren->getName()) {
case 'replaceResultRequest':
return new ImsLtiServiceReplaceRequest($xml);
case 'readResultRequest':
return new ImsLtiServiceReadRequest($xml);
case 'deleteResultRequest':
return new ImsLtiServiceDeleteRequest($xml);
}
}
return null;
}
}

@ -0,0 +1,64 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Class ImsLtiServiceResponse.
*/
abstract class ImsLtiServiceResponse
{
const TYPE_REPLACE = 'replace';
const TYPE_READ = 'read';
const TYPE_DELETE = 'delete';
/**
* @var mixed
*/
protected $bodyParams;
/**
* @var ImsLtiServiceResponseStatus
*/
private $statusInfo;
/**
* ImsLtiServiceResponse constructor.
*
* @param ImsLtiServiceResponseStatus $statusInfo
* @param mixed|null $bodyParam
*/
public function __construct(ImsLtiServiceResponseStatus $statusInfo, $bodyParam = null)
{
$this->statusInfo = $statusInfo;
$this->bodyParams = $bodyParam;
}
/**
* @return string
*/
public function __toString()
{
$xml = new SimpleXMLElement('<imsx_POXEnvelopeResponse></imsx_POXEnvelopeResponse>');
$xml->addAttribute('xmlns', 'http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0');
$headerInfo = $xml->addChild('imsx_POXHeader')->addChild('imsx_POXResponseHeaderInfo');
$headerInfo->addChild('imsx_version', 'V1.0');
$headerInfo->addChild('imsx_messageIdentifier', time());
$statusInfo = $headerInfo->addChild('imsx_statusInfo');
$statusInfo->addChild('imsx_codeMajor', $this->statusInfo->getCodeMajor());
$statusInfo->addChild('imsx_severity', $this->statusInfo->getSeverity());
$statusInfo->addChild('imsx_description', $this->statusInfo->getDescription());
$statusInfo->addChild('imsx_messageRefIdentifier', $this->statusInfo->getMessageRefIdentifier());
$statusInfo->addChild('imsx_operationRefIdentifier', $this->statusInfo->getOperationRefIdentifier());
$body = $xml->addChild('imsx_POXBody');
$this->generateBody($body);
return $xml->asXML();
}
/**
* @param SimpleXMLElement $xmlBody
*/
abstract protected function generateBody(SimpleXMLElement $xmlBody);
}

@ -0,0 +1,29 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Class ImsLtiServiceResponseFactory.
*/
class ImsLtiServiceResponseFactory
{
/**
* @param string $type
* @param ImsLtiServiceResponseStatus $statusInfo
* @param mixed $bodyParam
*
* @return ImsLtiServiceResponse|null
*/
public static function create($type, ImsLtiServiceResponseStatus $statusInfo, $bodyParam = null)
{
switch ($type) {
case ImsLtiServiceResponse::TYPE_REPLACE:
return new ImsLtiServiceReplaceResponse($statusInfo, $bodyParam);
case ImsLtiServiceResponse::TYPE_READ:
return new ImsLtiServiceReadResponse($statusInfo, $bodyParam);
case ImsLtiServiceResponse::TYPE_DELETE:
return new ImsLtiServiceDeleteResponse($statusInfo, $bodyParam);
}
return null;
}
}

@ -0,0 +1,162 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Class ImsLtiResponseStatus.
*/
class ImsLtiServiceResponseStatus
{
const SEVERITY_STATUS = 'status';
const SEVERITY_WARNING = 'warning';
const SEVERITY_ERROR = 'error';
const CODEMAJOR_SUCCESS = 'success';
const CODEMAJOR_PROCESSING = 'processing';
const CODEMAJOR_FAILURE = 'failure';
const CODEMAJOR_UNSUPPORTED = 'supported';
/**
* @var string
*/
private $codeMajor = '';
/**
* @var string
*/
private $severity = '';
/**
* @var string
*/
private $messageRefIdentifier = '';
/**
* @var string
*/
private $operationRefIdentifier = '';
/**
* @var string
*/
private $description = '';
/**
* Get codeMajor.
*
* @return string
*/
public function getCodeMajor()
{
return $this->codeMajor;
}
/**
* Set codeMajor.
*
* @param string $codeMajor
*
* @return ImsLtiServiceResponseStatus
*/
public function setCodeMajor($codeMajor)
{
$this->codeMajor = $codeMajor;
return $this;
}
/**
* Get severity.
*
* @return string
*/
public function getSeverity()
{
return $this->severity;
}
/**
* Set severity.
*
* @param string $severity
*
* @return ImsLtiServiceResponseStatus
*/
public function setSeverity($severity)
{
$this->severity = $severity;
return $this;
}
/**
* Get messageRefIdentifier.
*
* @return int
*/
public function getMessageRefIdentifier()
{
return $this->messageRefIdentifier;
}
/**
* Set messageRefIdentifier.
*
* @param int $messageRefIdentifier
*
* @return ImsLtiServiceResponseStatus
*/
public function setMessageRefIdentifier($messageRefIdentifier)
{
$this->messageRefIdentifier = $messageRefIdentifier;
return $this;
}
/**
* Get operationRefIdentifier.
*
* @return int
*/
public function getOperationRefIdentifier()
{
return $this->operationRefIdentifier;
}
/**
* Set operationRefIdentifier.
*
* @param int $operationRefIdentifier
*
* @return ImsLtiServiceResponseStatus
*/
public function setOperationRefIdentifier($operationRefIdentifier)
{
$this->operationRefIdentifier = $operationRefIdentifier;
return $this;
}
/**
* Get description.
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set description.
*
* @param string $description
*
* @return ImsLtiServiceResponseStatus
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
}

@ -1,41 +1,61 @@
<div class="row">
{% if tools|length %}
{% if global_tools|length or added_tools|length %}
<div class="col-sm-3">
<h2>{{ 'AvailableTools'|get_plugin_lang('ImsLtiPlugin') }}</h2>
<ul class="nav nav-pills nav-stacked">
{% for tool in tools %}
<li class="{{ type == tool.id ? 'active' : '' }}">
{% if tool.isActiveDeepLinking %}
<a href="{{ _p.web_plugin }}ims_lti/start.php?id={{ tool.id }}&{{ _p.web_cid_query }}">{{ tool.name }}</a>
{% else %}
<a href="{{ _p.web_self }}?type={{ tool.id }}&{{ _p.web_cid_query }}">{{ tool.name }}</a>
{% endif %}
</li>
{% endfor %}
</ul>
{% if added_tools|length %}
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">{{ 'ToolsAdded'|get_plugin_lang('ImsLtiPlugin') }}</h2>
</div>
<ul class="list-group">
{% for tool in added_tools %}
<li class="list-group-item {{ type == tool.id ? 'active' : '' }}">
<div class="pull-right">
{% if tool.isActiveDeepLinking %}
<a href="{{ _p.web_plugin }}ims_lti/start.php?id={{ tool.id }}&{{ _p.web_cid_query }}">
{{ 'settings.png'|img(22, 'Configure'|get_lang) }}
</a>
{% endif %}
<a href="{{ _p.web_plugin }}ims_lti/configure.php?action=edit&id={{ tool.id }}&{{ _p.web_cid_query }}">
{{ 'edit.png'|img(22, 'Edit'|get_lang) }}
</a>
</div>
{{ tool.name }}
</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% if global_tools|length %}
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">{{ 'AvailableTools'|get_plugin_lang('ImsLtiPlugin') }}</h2>
</div>
<ul class="list-group">
{% for tool in global_tools %}
<li class="list-group-item {{ type == tool.id ? 'active' : '' }}">
<div class="pull-right">
{% if tool.isActiveDeepLinking %}
<a href="{{ _p.web_plugin }}ims_lti/start.php?id={{ tool.id }}&{{ _p.web_cid_query }}">
{{ 'settings.png'|img(22, 'Configure'|get_lang) }}
</a>
{% else %}
<a href="{{ _p.web_self }}?type={{ tool.id }}&{{ _p.web_cid_query }}">
{{ 'add.png'|img(22, 'Add'|get_lang) }}
</a>
{% endif %}
</div>
{{ tool.name }}
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
{% endif %}
<div class="{{ tools|length ? 'col-sm-9' : 'col-sm-12' }}">
{% if tools|length == 0 %}
<h2>{{ 'ToolSettings'|get_plugin_lang('ImsLtiPlugin') }}</h2>
{% endif %}
<div class="col-sm-9 {{ not global_tools|length and not added_tools|length ? 'col-md-offset-3' : '' }}">
{{ form }}
</div>
</div>
<script>
$(document).on('ready', function () {
$('select[name="type"]').on('change', function () {
var advancedOptionsEl = $('#show_advanced_options');
var type = parseInt($(this).val());
if (type > 0) {
advancedOptionsEl.hide();
} else {
advancedOptionsEl.show();
}
});
});
</script>

@ -709,7 +709,7 @@ class LearningCalendarPlugin extends Plugin
ON (r.evaluation_id = e.id)
WHERE
e.type = 'evaluation' AND
r.score > 0 AND
r.score >= 2 AND
r.user_id = $userId
$courseSessionConditionToString
";

@ -8,7 +8,6 @@
for (var i = 0; i < response.length; i++) {
var startDate = moment(response[i].start_date + " 13:00:00").toDate();
var endDate = moment(response[i].end_date + " 13:00:00").toDate();
myData.push({
id: response[i].id,
title: response[i].title,

@ -16,9 +16,8 @@ if (empty($url)) {
return;
}
try {
$channel = Reader::import($url);
if (!empty($channel)) {
/** @var FeedInterface $item */
foreach ($channel as $item) {
@ -29,4 +28,8 @@ if (!empty($channel)) {
}
echo Display::panel($item->getDescription(), $title);
}
}
} catch (Exception $e) {
echo Display::return_message($plugin->get_lang('no_valid_rss'), 'warning');
error_log($e->getMessage());
}

@ -13,3 +13,4 @@ $strings['block_title'] = "Block title";
$strings['title'] = "Title";
$strings['no_rss'] = "There is no RSS configured. Please add a RSS";
$strings['no_valid_rss'] = "Please check if the URL contains a valid RSS URL";

@ -56,7 +56,7 @@ if (false === $path) {
exit;
}
$originFullPath = api_get_path(SYS_UPLOAD_PATH).'whispeakauth'.$path['path_to_save'];
$newFullPath = $originFullPath = api_get_path(SYS_UPLOAD_PATH).'whispeakauth'.$path['path_to_save'];
$fileType = mime_content_type($originFullPath);
if ('wav' !== substr($fileType, -3)) {

Loading…
Cancel
Save