XAPI: Add hooks to send statments to LRS - refs BT#16742

pull/3680/head
Angel Fernando Quiroz Campos 5 years ago
parent 758654653d
commit 4f3f17a7d2
  1. 124
      plugin/xapi/src/Entity/SharedStatement.php
  2. 136
      plugin/xapi/src/Hook/XApiActivityHookObserver.php
  3. 141
      plugin/xapi/src/Hook/XApiLearningPathEndHook.php
  4. 176
      plugin/xapi/src/Hook/XApiLearningPathItemViewedHook.php
  5. 146
      plugin/xapi/src/Hook/XApiQuizEndHook.php
  6. 177
      plugin/xapi/src/Hook/XApiQuizQuestionAnsweredHook.php
  7. 66
      plugin/xapi/src/Traits/XApiStatementTrait.php
  8. 181
      plugin/xapi/src/XApiPlugin.php

@ -0,0 +1,124 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\Entity\XApi;
use Doctrine\ORM\Mapping as ORM;
/**
* Class SharedStatement.
*
* @package Chamilo\PluginBundle\Entity\XApi
*
* @ORM\Table(name="xapi_shared_statement")
* @ORM\Entity()
*/
class SharedStatement
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id()
* @ORM\GeneratedValue()
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="uuid", type="string")
*/
private $uuid;
/**
* @var string
*
* @ORM\Column(name="data_type", type="string")
*/
private $dataType;
/**
* @var int
*
* @ORM\Column(name="data_id", type="integer")
*/
private $dataId;
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* @param int $id
*
* @return SharedStatement
*/
public function setId(int $id): SharedStatement
{
$this->id = $id;
return $this;
}
/**
* @return string
*/
public function getUuid(): string
{
return $this->uuid;
}
/**
* @param string $uuid
*
* @return SharedStatement
*/
public function setUuid(string $uuid): SharedStatement
{
$this->uuid = $uuid;
return $this;
}
/**
* @return string
*/
public function getDataType(): string
{
return $this->dataType;
}
/**
* @param string $dataType
*
* @return SharedStatement
*/
public function setDataType(string $dataType): SharedStatement
{
$this->dataType = $dataType;
return $this;
}
/**
* @return int
*/
public function getDataId(): int
{
return $this->dataId;
}
/**
* @param int $dataId
*
* @return SharedStatement
*/
public function setDataId(int $dataId): SharedStatement
{
$this->dataId = $dataId;
return $this;
}
}

@ -0,0 +1,136 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\PluginBundle\Entity\XApi\SharedStatement;
use Xabbuh\XApi\Common\Exception\ConflictException;
use Xabbuh\XApi\Common\Exception\XApiException;
use Xabbuh\XApi\Model\Context;
use Xabbuh\XApi\Model\Statement;
use Xabbuh\XApi\Model\StatementId;
/**
* Class XApiActivityHookObserver.
*/
abstract class XApiActivityHookObserver extends HookObserver
{
/**
* @var \Chamilo\UserBundle\Entity\User
*/
protected $user;
/**
* @var \XApiPlugin
*/
protected $plugin;
/**
* XApiActivityHookObserver constructor.
*/
protected function __construct()
{
parent::__construct(
'plugin/xapi/src/XApiPlugin.php',
'xapi'
);
$this->plugin = XApiPlugin::create();
}
/**
* @param \Xabbuh\XApi\Model\Statement $statement
*
* @throws \Exception
*
* @return \Xabbuh\XApi\Model\Statement
*/
protected function sendStatementToLrs(Statement $statement)
{
$client = XApiPlugin::create()->getXApiStatementClient();
try {
return $client->storeStatement($statement);
} catch (ConflictException $e) {
throw new Exception($e->getMessage());
} catch (XApiException $e) {
throw new Exception($e->getMessage());
}
}
/**
* @param \Xabbuh\XApi\Model\StatementId $uuid
* @param string $dataType
* @param int $dataId
*
* @throws \Doctrine\ORM\OptimisticLockException
*
* @return \Chamilo\PluginBundle\Entity\XApi\SharedStatement
*/
protected function saveSharedStatement(StatementId $uuid, $dataType, $dataId)
{
$sharedStmt = new SharedStatement();
$sharedStmt
->setUuid($uuid->getValue())
->setDataType($dataType)
->setDataId($dataId);
$em = Database::getManager();
$em->persist($sharedStmt);
$em->flush();
return $sharedStmt;
}
/**
* @return \Xabbuh\XApi\Model\Statement
*/
protected function createStatement()
{
return new Statement(
$this->getId(),
$this->getActor(),
$this->getVerb(),
$this->getActivity(),
$this->getActivityResult(),
null,
null,
null,
$this->getContext()
);
}
/**
* @return \Xabbuh\XApi\Model\StatementId
*/
abstract protected function getId();
/**
* @return \Xabbuh\XApi\Model\Agent
*/
abstract protected function getActor();
/**
* @return \Xabbuh\XApi\Model\Verb
*/
abstract protected function getVerb();
/**
* @return \Xabbuh\XApi\Model\Activity
*/
abstract protected function getActivity();
/**
* @return \Xabbuh\XApi\Model\Result|null
*/
abstract protected function getActivityResult();
/**
* @return \Xabbuh\XApi\Model\Context
*/
protected function getContext()
{
$platform = api_get_setting('Institution').' - '.api_get_setting('siteName');
$context = new Context();
return $context->withPlatform($platform);
}
}

@ -0,0 +1,141 @@
<?php
/* For licensing terms, see /license.txt */
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Result as ActivityResult;
use Xabbuh\XApi\Model\Score;
/**
* Class XApiLearningPathEndHook.
*/
class XApiLearningPathEndHook extends XApiActivityHookObserver implements HookLearningPathEndObserverInterface
{
use XApiStatementTrait;
/**
* @var \Chamilo\CourseBundle\Entity\CLpView
*/
private $lpView;
/**
* @var \Chamilo\CourseBundle\Entity\CLp
*/
private $lp;
/**
* @var \Chamilo\CoreBundle\Entity\Course
*/
private $course;
/**
* @var \Chamilo\CoreBundle\Entity\Session
*/
private $session;
/**
* @var \Chamilo\CourseBundle\Entity\CLpView|object|null
*/
/**
* @inheritDoc
*/
public function notifyLearningPathEnd(HookLearningPathEndEventInterface $event)
{
$data = $event->getEventData();
$em = Database::getManager();
$this->lpView = $em->find('ChamiloCourseBundle:CLpView', $data['lp_view_id']);
$this->lp = $em->find('ChamiloCourseBundle:CLp', $this->lpView->getLpId());
$this->user = api_get_user_entity($this->lpView->getUserId());
$this->course = api_get_course_entity($this->lpView->getCId());
$this->session = api_get_session_entity($this->lpView->getSessionId());
$statement = $this->createStatement();
try {
$statement = $this->sendStatementToLrs($statement);
$this->saveSharedStatement(
$statement->getId(),
XApiPlugin::DATA_TYPE_LP_VIEW,
$this->lpView->getId()
);
} catch (Exception $e) {
return;
}
}
/**
* @inheritDoc
*/
public function getActivityResult()
{
$raw = (float) $this->lpView->getProgress();
$max = 100;
$scaled = $raw / $max;
return new ActivityResult(
new Score($scaled, $raw, 0, $max),
null,
true
);
}
/**
* @inheritDoc
*/
protected function getActivity()
{
$lpName = strip_tags($this->lp->getName());
$lpName = trim($lpName);
$languageIso = api_get_language_isocode($this->course->getCourseLanguage());
$nameMap = LanguageMap::create([$languageIso => $lpName]);
$activityIdIri = $this->plugin->generateIri(
$this->lp->getId(),
'lp'
);
return new Activity(
IRI::fromString($activityIdIri),
new Definition(
$nameMap,
null,
IRI::fromString(XApiPlugin::IRI_LESSON)
)
);
}
/**
* @inheritDoc
*/
protected function getId()
{
return $this->generateId(
XApiPlugin::DATA_TYPE_LP_VIEW,
$this->lpView->getId()
);
}
/**
* @inheritDoc
*/
protected function getActor()
{
return $this->generateActor(
$this->user
);
}
/**
* @inheritDoc
*/
protected function getVerb()
{
return $this->generateVerb(
'terminated',
XApiPlugin::VERB_TERMINATED
);
}
}

@ -0,0 +1,176 @@
<?php
/* For licensing terms, see /license.txt */
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\ContextActivities;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Result as ActivityResult;
/**
* Class XApiLearningPathItemViewedHook.
*/
class XApiLearningPathItemViewedHook
extends XApiActivityHookObserver
implements HookLearningPathItemViewedObserverInterface
{
use XApiStatementTrait;
/**
* @var \Chamilo\CourseBundle\Entity\CLpItemView
*/
private $lpItemView;
/**
* @var \Chamilo\CourseBundle\Entity\CLpItem
*/
private $lpItem;
/**
* @var \Chamilo\CourseBundle\Entity\CLpView;
*/
private $lpView;
/**
* @var \Chamilo\CoreBundle\Entity\Course
*/
private $course;
/**
* @var \Chamilo\CoreBundle\Entity\Session
*/
private $session;
/**
* @inheritDoc
*/
public function hookLearningPathItemViewed(HookLearningPathItemViewedEventInterface $event)
{
$data = $event->getEventData();
$em = Database::getManager();
$this->lpItemView = $em->find('ChamiloCourseBundle:CLpItemView', $data['item_view_id']);
$this->lpItem = $em->find('ChamiloCourseBundle:CLpItem', $this->lpItemView->getLpItemId());
if ('quiz' == $this->lpItem->getItemType()) {
return null;
}
$this->lpView = $em->find('ChamiloCourseBundle:CLpView', $this->lpItemView->getLpViewId());
$this->user = api_get_user_entity($this->lpView->getUserId());
$this->course = api_get_course_entity($this->lpView->getCId());
$this->session = api_get_session_entity($this->lpView->getSessionId());
$statement = $this->createStatement();
try {
$statement = $this->sendStatementToLrs($statement);
$this->saveSharedStatement(
$statement->getId(),
XApiPlugin::DATA_TYPE_LP_ITEM_VIEW,
$this->lpItemView->getId()
);
} catch (Exception $e) {
return;
}
}
/**
* @inheritDoc
*/
protected function getActor()
{
return $this->generateActor(
$this->user
);
}
/**
* @inheritDoc
*/
protected function getVerb()
{
return $this->generateVerb(
'viewed',
XApiPlugin::VERB_VIEWED
);
}
/**
* @inheritDoc
*/
protected function getActivity()
{
$itemTitle = strip_tags($this->lpItem->getTitle());
$itemTitle = trim($itemTitle);
$languageIso = api_get_language_isocode($this->course->getCourseLanguage());
$titleMap = LanguageMap::create([$languageIso => $itemTitle]);
$activityIdIri = $this->plugin->generateIri(
$this->lpItem->getId(),
'lp_item'
);
return new Activity(
IRI::fromString($activityIdIri),
new Definition(
$titleMap,
null,
IRI::fromString(XApiPlugin::IRI_RESOURCE)
)
);
}
/**
* @inheritDoc
*/
protected function getActivityResult()
{
if ('quiz' == $this->lpItem->getItemType()) {
return null;
}
$completion = $this->lpItemView->getStatus() === 'completed';
return new ActivityResult(
null,
null,
$completion,
null,
"PT{$this->lpItemView->getTotalTime()}S"
);
}
/**
* @inheritDoc
*/
protected function getContext()
{
$lpIri = $this->plugin->generateIri(
$this->lpView->getLpId(),
XApiPlugin::TYPE_LP
);
$lpActivity = new Activity(
IRI::fromString($lpIri)
);
$activities = new ContextActivities(
[$lpActivity]
);
return parent::getContext()->withContextActivities($activities);
}
/**
* @inheritDoc
*/
protected function getId()
{
return $this->generateId(
XApiPlugin::DATA_TYPE_LP_ITEM_VIEW,
$this->lpItemView->getId()
);
}
}

@ -0,0 +1,146 @@
<?php
/* For licensing terms, see /license.txt */
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Result as ActivityResult;
use Xabbuh\XApi\Model\Score;
/**
* Class XApiQuizEndHook.
*/
class XApiQuizEndHook extends XApiActivityHookObserver implements HookQuizEndObserverInterface
{
use XApiStatementTrait;
/**
* @var \Chamilo\CoreBundle\Entity\TrackEExercises
*/
private $exe;
/**
* @var \Chamilo\CourseBundle\Entity\CQuiz
*/
private $quiz;
/**
* @var \Chamilo\CoreBundle\Entity\Course
*/
private $course;
/**
* @var \Chamilo\CoreBundle\Entity\Session|null
*/
private $session;
/**
* @inheritDoc
*/
public function hookQuizEnd(HookQuizEndEventInterface $hookEvent)
{
$data = $hookEvent->getEventData();
$em = Database::getManager();
$this->exe = $em->find('ChamiloCoreBundle:TrackEExercises', $data['exe_id']);
$this->quiz = $em->find('ChamiloCourseBundle:CQuiz', $this->exe->getExeExoId());
$this->user = api_get_user_entity($this->exe->getExeUserId());
$this->course = api_get_course_entity($this->exe->getCId());
$this->session = api_get_session_entity($this->exe->getSessionId());
$statement = $this->createStatement();
try {
$statement = $this->sendStatementToLrs($statement);
$this->saveSharedStatement(
$statement->getId(),
XApiPlugin::DATA_TYPE_EXERCISE,
$this->exe->getExeId()
);
} catch (Exception $e) {
return;
}
}
/**
* @inheritDoc
*/
protected function getActor()
{
return $this->generateActor(
$this->user
);
}
/**
* @inheritDoc
*/
protected function getVerb()
{
return $this->generateVerb(
'terminated',
XApiPlugin::VERB_TERMINATED
);
}
/**
* @inheritDoc
*/
protected function getActivity()
{
$title = strip_tags($this->quiz->getTitle());
$title = trim($title);
$description = strip_tags($this->quiz->getDescription());
$description = trim($description);
$languageIso = api_get_language_isocode($this->course->getCourseLanguage());
$titleMap = LanguageMap::create([$languageIso => $title]);
$descriptionMap = $description ? LanguageMap::create([$languageIso => $description]) : null;
$activityIdIri = $this->plugin->generateIri(
$this->quiz->getId(),
'quiz'
);
return new Activity(
IRI::fromString($activityIdIri),
new Definition(
$titleMap,
$descriptionMap,
IRI::fromString(XApiPlugin::IRI_QUIZ)
)
);
}
/**
* @inheritDoc
*/
protected function getActivityResult()
{
$raw = $this->exe->getExeResult();
$max = $this->exe->getExeWeighting();
$scaled = $raw / $max;
$duration = $this->exe->getExeDuration();
return new ActivityResult(
new Score($scaled, $raw, 0, $max),
null,
true,
null,
$duration ? "PT{$duration}S" : null
);
}
/**
* @return \Xabbuh\XApi\Model\StatementId
*/
protected function getId()
{
return $this->generateId(
XApiPlugin::DATA_TYPE_EXERCISE,
$this->exe->getExeId()
);
}
}

@ -0,0 +1,177 @@
<?php
/* For licensing terms, see /license.txt */
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\ContextActivities;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Result as ActivityResult;
use Xabbuh\XApi\Model\Score;
/**
* Class XApiQuizQuestionAnsweredHook.
*/
class XApiQuizQuestionAnsweredHook
extends XApiActivityHookObserver
implements HookQuizQuestionAnsweredObserverInterface
{
use XApiStatementTrait;
/**
* @var \Chamilo\CoreBundle\Entity\TrackEExercises
*/
private $exe;
/**
* @var \Chamilo\CoreBundle\Entity\TrackEAttempt
*/
private $attempt;
/**
* @var \Chamilo\CourseBundle\Entity\CQuizQuestion
*/
private $question;
/**
* @var \Chamilo\CoreBundle\Entity\Course
*/
private $course;
/**
* @var \Chamilo\CoreBundle\Entity\Session|null
*/
private $session;
/**
* @inheritDoc
*/
public function hookQuizQuestionAnswered(HookQuizQuestionAnsweredEventInterface $event)
{
$data = $event->getEventData();
$em = Database::getManager();
$this->exe = $em->find('ChamiloCoreBundle:TrackEExercises', $data['exe_id']);
$this->question = $em->find('ChamiloCourseBundle:CQuizQuestion', $data['question']['id']);
$this->attempt = $em
->getRepository('ChamiloCoreBundle:TrackEAttempt')
->findOneBy(['exeId' => $this->exe->getExeId(), 'questionId' => $this->question->getId()]);
$this->user = api_get_user_entity($this->exe->getExeUserId());
$this->course = api_get_course_entity($this->exe->getCId());
$this->session = api_get_session_entity($this->exe->getSessionId());
$statement = $this
->createStatement()
->withCreated(
$this->attempt->getTms()
);
try {
$statement = $this->sendStatementToLrs($statement);
$this->saveSharedStatement(
$statement->getId(),
XApiPlugin::DATA_TYPE_ATTEMPT,
$this->attempt->getId()
);
} catch (Exception $e) {
return;
}
}
/**
* @inheritDoc
*/
protected function getActor()
{
return $this->generateActor(
$this->user
);
}
/**
* @inheritDoc
*/
protected function getVerb()
{
return $this->generateVerb(
'answered',
XApiPlugin::VERB_ANSWERED
);
}
/**
* @inheritDoc
*/
protected function getActivity()
{
$questionTitle = strip_tags($this->question->getQuestion());
$questionTitle = trim($questionTitle);
$questionDescription = strip_tags($this->question->getDescription());
$questionDescription = trim($questionDescription);
$languageIso = api_get_language_isocode($this->course->getCourseLanguage());
$titleMap = LanguageMap::create([$languageIso => $questionTitle]);
$descriptionMap = $questionDescription ? LanguageMap::create([$languageIso => $questionDescription]) : null;
$activityIdIri = $this->plugin->generateIri(
$this->question->getId(),
'quiz_question'
);
return new Activity(
IRI::fromString($activityIdIri),
new Definition(
$titleMap,
$descriptionMap,
IRI::fromString(XApiPlugin::IRI_QUIZ_QUESTION)
)
);
}
/**
* @inheritDoc
*/
protected function getActivityResult()
{
$raw = $this->attempt->getMarks();
$max = $this->question->getPonderation();
$scaled = $raw / $max;
return new ActivityResult(
new Score($scaled, $raw, null, $max),
null,
true
);
}
/**
* @inheritDoc
*/
protected function getContext()
{
$quizIri = $this->plugin->generateIri(
$this->exe->getExeExoId(),
XApiPlugin::TYPE_QUIZ
);
$quizActivity = new Activity(
IRI::fromString($quizIri)
);
$activities = new ContextActivities(
[$quizActivity]
);
return parent::getContext()->withContextActivities($activities);
}
/**
* @inheritDoc
*/
protected function getId()
{
return $this->generateId(
XApiPlugin::DATA_TYPE_ATTEMPT,
$this->attempt->getId()
);
}
}

@ -0,0 +1,66 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\UserBundle\Entity\User as UserEntity;
use Xabbuh\XApi\Model\Agent;
use Xabbuh\XApi\Model\InverseFunctionalIdentifier;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\StatementId;
use Xabbuh\XApi\Model\Uuid;
use Xabbuh\XApi\Model\Verb;
/**
* Trait XApiStatementTrait.
*/
trait XApiStatementTrait
{
/**
* @param UserEntity $user
*
* @return \Xabbuh\XApi\Model\Agent
*/
protected function generateActor(UserEntity $user)
{
$mboxIri = IRI::fromString(
'mailto:'.$user->getEmail()
);
return new Agent(
InverseFunctionalIdentifier::withMbox($mboxIri),
$user->getCompleteName()
);
}
/**
* @param string $word
* @param string $uri
*
* @return \Xabbuh\XApi\Model\Verb
*/
protected function generateVerb($word, $uri)
{
$languageMap = XApiPlugin::create()->getLangMap($word);
return new Verb(
IRI::fromString($uri),
LanguageMap::create($languageMap)
);
}
/**
* @param string $type
* @param string $value
*
* @return \Xabbuh\XApi\Model\StatementId
*/
protected function generateId($type, $value)
{
$uuid = Uuid::uuid5(
XApiPlugin::create()->get(XApiPlugin::SETTING_UUID_NAMESPACE),
"$type/$value"
);
return StatementId::fromUuid($uuid);
}
}

@ -1,6 +1,8 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\PluginBundle\Entity\XApi\SharedStatement;
use Doctrine\ORM\Tools\SchemaTool;
use GuzzleHttp\RequestOptions;
use Http\Adapter\Guzzle6\Client;
use Http\Message\MessageFactory\GuzzleMessageFactory;
@ -11,11 +13,35 @@ use Xabbuh\XApi\Client\XApiClientBuilderInterface;
/**
* Class XApiPlugin.
*/
class XApiPlugin extends Plugin
class XApiPlugin extends Plugin implements HookPluginInterface
{
const SETTING_LRS_URL = 'lrs_url';
const SETTING_LRS_AUTH = 'lrs_auth';
const SETTING_UUID_NAMESPACE = 'uuid_namespace';
const SETTING_LRS_LP_ITEM_ACTIVE = 'lrs_lp_item_viewed_active';
const SETTING_LRS_LP_ACTIVE = 'lrs_lp_end_active';
const SETTING_LRS_QUIZ_ACTIVE = 'lrs_quiz_active';
const SETTING_LRS_QUIZ_QUESTION_ACTIVE = 'lrs_quiz_question_active';
const VERB_TERMINATED = 'http://adlnet.gov/expapi/verbs/terminated';
const VERB_COMPLETED = 'http://adlnet.gov/expapi/verbs/completed';
const VERB_ANSWERED = 'http://adlnet.gov/expapi/verbs/answered';
const VERB_VIEWED = 'http://id.tincanapi.com/verb/viewed';
const IRI_QUIZ = 'http://adlnet.gov/expapi/activities/assessment';
const IRI_QUIZ_QUESTION = 'http://adlnet.gov/expapi/activities/question';
const IRI_LESSON = 'http://adlnet.gov/expapi/activities/lesson';
const IRI_RESOURCE = 'http://id.tincanapi.com/activitytype/resource';
const DATA_TYPE_ATTEMPT = 'e_attempt';
const DATA_TYPE_EXERCISE = 'e_exercise';
const DATA_TYPE_LP_ITEM_VIEW = 'lp_item_view';
const DATA_TYPE_LP_VIEW = 'lp_view';
const TYPE_QUIZ = 'quiz';
const TYPE_QUIZ_QUESTION = 'quiz_question';
const TYPE_LP = 'lp';
const TYPE_LP_ITEM = 'lp_item';
/**
* XApiPlugin constructor.
@ -30,6 +56,10 @@ class XApiPlugin extends Plugin
self::SETTING_UUID_NAMESPACE => 'text',
self::SETTING_LRS_URL => 'text',
self::SETTING_LRS_AUTH => 'text',
self::SETTING_LRS_LP_ITEM_ACTIVE => 'boolean',
self::SETTING_LRS_LP_ACTIVE => 'boolean',
self::SETTING_LRS_QUIZ_ACTIVE => 'boolean',
self::SETTING_LRS_QUIZ_QUESTION_ACTIVE => 'boolean',
];
parent::__construct(
@ -54,9 +84,35 @@ class XApiPlugin extends Plugin
*/
public function install()
{
$em = Database::getManager();
$tablesExists = $em->getConnection()->getSchemaManager()->tablesExist(
['xapi_shared_statement']
);
if ($tablesExists) {
return;
}
$this->installPluginDbTables();
$this->installUuid();
}
/**
* @throws \Doctrine\ORM\Tools\ToolsException
*/
private function installPluginDbTables()
{
$em = Database::getManager();
$schemaTool = new SchemaTool($em);
$schemaTool->createSchema(
[
$em->getClassMetadata(SharedStatement::class),
]
);
}
/**
* @throws \Exception
*/
@ -87,6 +143,38 @@ class XApiPlugin extends Plugin
*/
public function uninstall()
{
$this->uninstallHook();
$this->uninstallPluginDbTables();
}
/**
* @inheritDoc
*/
public function uninstallHook()
{
$learningPathItemViewedHook = XApiLearningPathItemViewedHook::create();
$learningPathEndHook = XApiLearningPathEndHook::create();
$quizQuestionAnsweredHook = XApiQuizQuestionAnsweredHook::create();
$quizEndHook = XApiQuizEndHook::create();
HookLearningPathItemViewed::create()->attach($learningPathItemViewedHook);
HookLearningPathEnd::create()->detach($learningPathEndHook);
HookQuizQuestionAnswered::create()->attach($quizQuestionAnsweredHook);
HookQuizEnd::create()->attach($quizEndHook);
return 1;
}
public function uninstallPluginDbTables()
{
$em = Database::getManager();
$schemaTool = new SchemaTool($em);
$schemaTool->dropSchema(
[
$em->getClassMetadata(SharedStatement::class),
]
);
}
/**
@ -139,4 +227,95 @@ class XApiPlugin extends Plugin
return $clientBuilder;
}
/**
* Perform actions after save the plugin configuration.
*
* @return \XApiPlugin
*/
public function performActionsAfterConfigure()
{
$learningPathItemViewedHook = XApiLearningPathItemViewedHook::create();
$learningPathEndHook = XApiLearningPathEndHook::create();
$quizQuestionAnsweredHook = XApiQuizQuestionAnsweredHook::create();
$quizEndHook = XApiQuizEndHook::create();
$learningPathItemViewedEvent = HookLearningPathItemViewed::create();
$learningPathEndEvent = HookLearningPathEnd::create();
$quizQuestionAnsweredEvent = HookQuizQuestionAnswered::create();
$quizEndEvent = HookQuizEnd::create();
if ('true' === $this->get(self::SETTING_LRS_LP_ITEM_ACTIVE)) {
$learningPathItemViewedEvent->attach($learningPathItemViewedHook);
} else {
$learningPathItemViewedEvent->detach($learningPathItemViewedHook);
}
if ('true' === $this->get(self::SETTING_LRS_LP_ACTIVE)) {
$learningPathEndEvent->attach($learningPathEndHook);
} else {
$learningPathEndEvent->detach($learningPathEndHook);
}
if ('true' === $this->get(self::SETTING_LRS_QUIZ_ACTIVE)) {
$quizQuestionAnsweredEvent->attach($quizQuestionAnsweredHook);
} else {
$quizQuestionAnsweredEvent->detach($quizQuestionAnsweredHook);
}
if ('true' === $this->get(self::SETTING_LRS_QUIZ_QUESTION_ACTIVE)) {
$quizEndEvent->attach($quizEndHook);
} else {
$quizEndEvent->detach($quizEndHook);
}
return $this;
}
/**
* @inheritDoc
*/
public function installHook()
{
return 0;
}
/**
* @param string $variable
*
* @return array
*/
public function getLangMap($variable)
{
$platformLanguage = api_get_setting('platformLanguage');
$platformLanguageIso = api_get_language_isocode($platformLanguage);
$map = [];
$map[$platformLanguageIso] = $this->getLangFromFile($variable, $platformLanguage);
try {
$interfaceLanguage = api_get_interface_language();
} catch (Exception $e) {
return $map;
}
if (!empty($interfaceLanguage) && $platformLanguage !== $interfaceLanguage) {
$interfaceLanguageIso = api_get_language_isocode($interfaceLanguage);
$map[$interfaceLanguageIso] = $this->getLangFromFile($variable, $interfaceLanguage);
}
return $map;
}
/**
* @param string $value
* @param string $type
*
* @return string
*/
public function generateIri($value, $type)
{
return api_get_path(WEB_PATH)."xapi/$type/$value";
}
}

Loading…
Cancel
Save