XAPI: Refactoring statements in hooks for tools - refs BT#18201

pull/3766/head^2
Angel Fernando Quiroz Campos 5 years ago
parent 58837fcd33
commit 5f92f00d9f
  1. 4
      main/inc/lib/hook/interfaces/HookQuizEndObserverInterface.php
  2. 108
      plugin/xapi/src/Hook/XApiActivityHookObserver.php
  3. 111
      plugin/xapi/src/Hook/XApiLearningPathEndHookObserver.php
  4. 142
      plugin/xapi/src/Hook/XApiLearningPathItemViewedHookObserver.php
  5. 89
      plugin/xapi/src/Hook/XApiPortfolioItemAddedHookObserver.php
  6. 105
      plugin/xapi/src/Hook/XApiPortfolioItemCommentedHookObserver.php
  7. 117
      plugin/xapi/src/Hook/XApiQuizEndHookObserver.php
  8. 287
      plugin/xapi/src/Hook/XApiQuizQuestionAnsweredHookObserver.php
  9. 49
      plugin/xapi/src/ToolExperience/Activity/BaseActivity.php
  10. 40
      plugin/xapi/src/ToolExperience/Activity/Course.php
  11. 53
      plugin/xapi/src/ToolExperience/Activity/LearningPath.php
  12. 54
      plugin/xapi/src/ToolExperience/Activity/LearningPathItem.php
  13. 58
      plugin/xapi/src/ToolExperience/Activity/PortfolioCategory.php
  14. 50
      plugin/xapi/src/ToolExperience/Activity/PortfolioComment.php
  15. 49
      plugin/xapi/src/ToolExperience/Activity/PortfolioItem.php
  16. 57
      plugin/xapi/src/ToolExperience/Activity/Quiz.php
  17. 170
      plugin/xapi/src/ToolExperience/Activity/QuizQuestion.php
  18. 33
      plugin/xapi/src/ToolExperience/Activity/Site.php
  19. 17
      plugin/xapi/src/ToolExperience/Actor/BaseActor.php
  20. 35
      plugin/xapi/src/ToolExperience/Actor/User.php
  21. 53
      plugin/xapi/src/ToolExperience/Statement/BaseStatement.php
  22. 61
      plugin/xapi/src/ToolExperience/Statement/LearningPathCompleted.php
  23. 79
      plugin/xapi/src/ToolExperience/Statement/LearningPathItemViewed.php
  24. 72
      plugin/xapi/src/ToolExperience/Statement/PortfolioItemCommented.php
  25. 65
      plugin/xapi/src/ToolExperience/Statement/PortfolioItemShared.php
  26. 70
      plugin/xapi/src/ToolExperience/Statement/QuizCompleted.php
  27. 79
      plugin/xapi/src/ToolExperience/Statement/QuizQuestionAnswered.php
  28. 27
      plugin/xapi/src/ToolExperience/Verb/Answered.php
  29. 17
      plugin/xapi/src/ToolExperience/Verb/BaseVerb.php
  30. 27
      plugin/xapi/src/ToolExperience/Verb/Commented.php
  31. 27
      plugin/xapi/src/ToolExperience/Verb/Completed.php
  32. 28
      plugin/xapi/src/ToolExperience/Verb/Replied.php
  33. 27
      plugin/xapi/src/ToolExperience/Verb/Shared.php
  34. 27
      plugin/xapi/src/ToolExperience/Verb/Viewed.php
  35. 107
      plugin/xapi/src/Traits/XApiStatementTrait.php
  36. 25
      plugin/xapi/src/XApiPlugin.php

@ -7,7 +7,9 @@
interface HookQuizEndObserverInterface
{
/**
* @param \HookQuizEndEventInterface $hookEvent
*
* @return mixed
*/
public function hookQuizEnd(HookQuizEndEventInterface $hookvent);
public function hookQuizEnd(HookQuizEndEventInterface $hookEvent);
}

@ -3,10 +3,6 @@
/* For licensing terms, see /license.txt */
use Chamilo\PluginBundle\Entity\XApi\SharedStatement;
use Doctrine\ORM\OptimisticLockException;
use Xabbuh\XApi\Common\Exception\StatementIdAlreadyExistsException;
use Xabbuh\XApi\Model\Context;
use Xabbuh\XApi\Model\ContextActivities;
use Xabbuh\XApi\Model\Statement;
use Xabbuh\XApi\Serializer\Symfony\Serializer;
use Xabbuh\XApi\Serializer\Symfony\StatementSerializer;
@ -16,20 +12,6 @@ use Xabbuh\XApi\Serializer\Symfony\StatementSerializer;
*/
abstract class XApiActivityHookObserver extends HookObserver
{
use XApiStatementTrait;
/**
* @var \Chamilo\CoreBundle\Entity\Course|null
*/
protected $course;
/**
* @var \Chamilo\CoreBundle\Entity\Session|null
*/
protected $session;
/**
* @var \Chamilo\UserBundle\Entity\User
*/
protected $user;
/**
* @var \XApiPlugin
*/
@ -61,99 +43,11 @@ abstract class XApiActivityHookObserver extends HookObserver
$em = Database::getManager();
$em->persist($sharedStmt);
try {
$em->flush();
} catch (OptimisticLockException $e) {
return null;
}
$em->flush();
return $sharedStmt;
}
/**
* @param \DateTime|null $createdAt
*
* @throws \Xabbuh\XApi\Common\Exception\StatementIdAlreadyExistsException
*
* @return \Xabbuh\XApi\Model\Statement
*/
protected function createStatement(DateTime $createdAt = null)
{
$id = $this->getId();
$sharedStmt = Database::getManager()
->getRepository(SharedStatement::class)
->findOneByUuid($id->getValue());
if ($sharedStmt) {
throw new StatementIdAlreadyExistsException($id->getValue());
}
return new Statement(
$id,
$this->getActor(),
$this->getVerb(),
$this->getActivity(),
$this->getActivityResult(),
null,
$createdAt,
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');
$groupingActivities = [];
$groupingActivities[] = $this->generateActivityFromSite();
if ($this->course) {
$groupingActivities[] = $this->generateActivityFromCourse($this->course, $this->session);
}
$context = new Context();
return $context
->withPlatform($platform)
->withLanguage(
api_get_language_isocode()
)
->withContextActivities(
new ContextActivities(null, $groupingActivities)
);
}
/**
* Serialize a statement to JSON.
*

@ -2,124 +2,25 @@
/* 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;
use Chamilo\PluginBundle\XApi\ToolExperience\Statement\LearningPathCompleted;
/**
* Class XApiLearningPathEndHookObserver.
*/
class XApiLearningPathEndHookObserver extends XApiActivityHookObserver implements HookLearningPathEndObserverInterface
{
use XApiStatementTrait;
/**
* @var \Chamilo\CourseBundle\Entity\CLpView
*/
private $lpView;
/**
* @var \Chamilo\CourseBundle\Entity\CLp
*/
private $lp;
/**
* {@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());
try {
$statement = $this->createStatement();
} catch (Exception $e) {
return;
}
$this->saveSharedStatement($statement);
}
/**
* {@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);
$lpView = $em->find('ChamiloCourseBundle:CLpView', $data['lp_view_id']);
$lp = $em->find('ChamiloCourseBundle:CLp', $lpView->getLpId());
$languageIso = api_get_language_isocode($this->course->getCourseLanguage());
$learningPathEnded = new LearningPathCompleted($lpView, $lp);
$nameMap = LanguageMap::create([$languageIso => $lpName]);
$statement = $learningPathEnded->generate();
$id = $this->plugin->generateIri(
$this->lp->getId(),
'lp'
);
return new Activity(
$id,
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
);
$this->saveSharedStatement($statement);
}
}

@ -2,33 +2,14 @@
/* 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 Chamilo\PluginBundle\XApi\ToolExperience\Statement\LearningPathItemViewed;
/**
* Class XApiLearningPathItemViewedHookObserver.
*/
class XApiLearningPathItemViewedHookObserver extends XApiActivityHookObserver implements HookLearningPathItemViewedObserverInterface
class XApiLearningPathItemViewedHookObserver 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;
/**
* {@inheritdoc}
*/
@ -37,122 +18,19 @@ class XApiLearningPathItemViewedHookObserver extends XApiActivityHookObserver im
$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());
$lpItemView = $em->find('ChamiloCourseBundle:CLpItemView', $data['item_view_id']);
$lpItem = $em->find('ChamiloCourseBundle:CLpItem', $lpItemView->getLpItemId());
if ('quiz' == $this->lpItem->getItemType()) {
if ('quiz' == $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());
$lpView = $em->find('ChamiloCourseBundle:CLpView', $lpItemView->getLpViewId());
try {
$statement = $this->createStatement();
} catch (Exception $e) {
return;
}
$this->saveSharedStatement($statement);
}
/**
* {@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);
$lpItemViewed = new LearningPathItemViewed($lpItemView, $lpItem, $lpView);
$languageIso = api_get_language_isocode($this->course->getCourseLanguage());
$statement = $lpItemViewed->generate();
$titleMap = LanguageMap::create([$languageIso => $itemTitle]);
$id = $this->plugin->generateIri(
$this->lpItem->getId(),
'lp_item'
);
return new Activity(
$id,
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()
{
$id = $this->plugin->generateIri(
$this->lpView->getLpId(),
XApiPlugin::TYPE_LP
);
$lpActivity = new Activity($id);
$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()
);
$this->saveSharedStatement($statement);
}
}

@ -2,12 +2,7 @@
/* For licensing terms, see /license.txt */
use Xabbuh\XApi\Common\Exception\StatementIdAlreadyExistsException;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Verb;
use Chamilo\PluginBundle\XApi\ToolExperience\Statement\PortfolioItemShared;
/**
* Class XApiPortfolioItemAddedHookObserver.
@ -15,93 +10,17 @@ use Xabbuh\XApi\Model\Verb;
class XApiPortfolioItemAddedHookObserver extends XApiActivityHookObserver
implements HookPortfolioItemAddedObserverInterface
{
/**
* @var \Chamilo\CoreBundle\Entity\Portfolio
*/
private $item;
/**
* @inheritDoc
*/
public function hookItemAdded(HookPortfolioItemAddedEventInterface $hookEvent)
{
$this->item = $hookEvent->getEventData()['portfolio'];
$item = $hookEvent->getEventData()['portfolio'];
$this->user = $this->item->getUser();
$this->course = $this->item->getCourse();
$this->session = $this->item->getSession();
$portfolioItemShared = new PortfolioItemShared($item);
try {
$statement = $this->createStatement(
$this->item->getCreationDate()
);
} catch (StatementIdAlreadyExistsException $e) {
return;
}
$statement = $portfolioItemShared->generate();
$this->saveSharedStatement($statement);
}
/**
* @inheritDoc
*/
protected function getId()
{
return $this->generateId(
XApiPlugin::DATA_TYPE_PORTFOLIO_ITEM,
$this->item->getId()
);
}
/**
* @inheritDoc
*/
protected function getActor()
{
return $this->generateActor(
$this->item->getUser()
);
}
/**
* @inheritDoc
*/
protected function getVerb()
{
$languageMap = XApiPlugin::create()->getLangMap('shared');
return new Verb(
IRI::fromString(XApiPlugin::VERB_SHARED),
LanguageMap::create($languageMap)
);
}
/**
* @inheritDoc
*/
protected function getActivity()
{
if ($this->course) {
$languageIso = api_get_language_isocode($this->course->getCourseLanguage());
} else {
$languageIso = api_get_language_isocode($this->user->getLanguage());
}
$id = $this->plugin->generateIri($this->item->getId(), 'portfolio-item');
return new Activity(
$id,
new Definition(
LanguageMap::create([$languageIso => $this->item->getTitle()])
)
);
}
/**
* @inheritDoc
*/
protected function getActivityResult()
{
return null;
}
}

@ -2,12 +2,7 @@
/* For licensing terms, see /license.txt */
use Xabbuh\XApi\Common\Exception\StatementIdAlreadyExistsException;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Verb;
use Chamilo\PluginBundle\XApi\ToolExperience\Statement\PortfolioItemCommented;
/**
* Class XApiPortfolioItemCommentedHookObserver.
@ -15,109 +10,17 @@ use Xabbuh\XApi\Model\Verb;
class XApiPortfolioItemCommentedHookObserver extends XApiActivityHookObserver
implements HookPortfolioItemCommentedObserverInterface
{
/**
* @var \Chamilo\CoreBundle\Entity\PortfolioComment
*/
private $comment;
/**
* @inheritDoc
*/
public function hookItemCommented(HookPortfolioItemCommentedEventInterface $hookEvent)
{
$this->comment = $hookEvent->getEventData()['comment'];
$comment = $hookEvent->getEventData()['comment'];
$this->user = $this->comment->getAuthor();
$this->course = $this->comment->getItem()->getCourse();
$this->session = $this->comment->getItem()->getSession();
$portfolioItemCommented = new PortfolioItemCommented($comment);
try {
$statement = $this->createStatement(
$this->comment->getDate()
);
} catch (StatementIdAlreadyExistsException $e) {
return;
}
$statement = $portfolioItemCommented->generate();
$this->saveSharedStatement($statement);
}
/**
* @inheritDoc
*/
protected function getId()
{
return $this->generateId(
XApiPlugin::DATA_TYPE_PORTFOLIO_COMMENT,
$this->comment->getId()
);
}
/**
* @inheritDoc
*/
protected function getActor()
{
return $this->generateActor(
$this->comment->getAuthor()
);
}
/**
* @inheritDoc
*/
protected function getVerb()
{
$languageMap = XApiPlugin::create()->getLangMap('commented');
return new Verb(
IRI::fromString(XApiPlugin::VERB_COMMENTED),
LanguageMap::create($languageMap)
);
}
/**
* @inheritDoc
*/
protected function getActivity()
{
if ($this->comment->getParent()) {
$parent = $this->comment->getParent();
$id = $this->plugin->generateIri($parent->getId(), 'portfolio-comment');
$titleMap = $this->plugin->getLangMap('AReplyOnAPortfolioComment');
} else {
$item = $this->comment->getItem();
$id = $this->plugin->generateIri($item->getId(), 'portfolio-item');
if ($this->course) {
$languageIso = api_get_language_isocode($this->course->getCourseLanguage());
} else {
$languageIso = api_get_language_isocode($this->user->getLanguage());
}
$titleMap = [$languageIso => $item->getTitle()];
}
return new Activity(
$id,
new Definition(
LanguageMap::create($titleMap)
)
);
}
/**
* @inheritDoc
*/
protected function getActivityResult()
{
return new \Xabbuh\XApi\Model\Result(
null,
null,
null,
$this->comment->getContent()
);
}
}

@ -2,29 +2,13 @@
/* 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;
use Chamilo\PluginBundle\XApi\ToolExperience\Statement\QuizCompleted;
/**
* Class XApiQuizEndHookObserver.
*/
class XApiQuizEndHookObserver extends XApiActivityHookObserver implements HookQuizEndObserverInterface
{
use XApiStatementTrait;
/**
* @var \Chamilo\CoreBundle\Entity\TrackEExercises
*/
private $exe;
/**
* @var \Chamilo\CourseBundle\Entity\CQuiz
*/
private $quiz;
/**
* {@inheritdoc}
*/
@ -33,102 +17,13 @@ class XApiQuizEndHookObserver extends XApiActivityHookObserver implements HookQu
$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());
try {
$statement = $this->createStatement(
$this->exe->getExeDate()
);
} catch (Exception $e) {
return;
}
$this->saveSharedStatement($statement);
}
/**
* {@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);
$exe = $em->find('ChamiloCoreBundle:TrackEExercises', $data['exe_id']);
$quiz = $em->find('ChamiloCourseBundle:CQuiz', $exe->getExeExoId());
$languageIso = api_get_language_isocode($this->course->getCourseLanguage());
$quizCompleted = new QuizCompleted($exe, $quiz);
$titleMap = LanguageMap::create([$languageIso => $title]);
$descriptionMap = $description ? LanguageMap::create([$languageIso => $description]) : null;
$statement = $quizCompleted->generate();
$id = $this->plugin->generateIri(
$this->quiz->getId(),
'quiz'
);
return new Activity(
$id,
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()
);
$this->saveSharedStatement($statement);
}
}

@ -2,43 +2,18 @@
/* For licensing terms, see /license.txt */
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\Interaction\ChoiceInteractionDefinition;
use Xabbuh\XApi\Model\Interaction\InteractionComponent;
use Xabbuh\XApi\Model\Interaction\LongFillInInteractionDefinition;
use Xabbuh\XApi\Model\Interaction\MatchingInteractionDefinition;
use Xabbuh\XApi\Model\Interaction\OtherInteractionDefinition;
use Xabbuh\XApi\Model\Interaction\SequencingInteractionDefinition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Result as ActivityResult;
use Xabbuh\XApi\Model\Score;
use Chamilo\CoreBundle\Entity\TrackEAttempt;
use Chamilo\CoreBundle\Entity\TrackEExercises;
use Chamilo\CourseBundle\Entity\CQuiz;
use Chamilo\CourseBundle\Entity\CQuizQuestion;
use Chamilo\PluginBundle\XApi\ToolExperience\Statement\QuizQuestionAnswered;
/**
* Class XApiQuizQuestionAnsweredHook.
*/
class XApiQuizQuestionAnsweredHookObserver extends XApiActivityHookObserver implements HookQuizQuestionAnsweredObserverInterface
class XApiQuizQuestionAnsweredHookObserver 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 array
*/
private $quizInfo;
/**
* {@inheritdoc}
*/
@ -47,244 +22,22 @@ class XApiQuizQuestionAnsweredHookObserver extends XApiActivityHookObserver impl
$data = $event->getEventData();
$em = Database::getManager();
$this->exe = $em->find('ChamiloCoreBundle:TrackEExercises', $data['exe_id']);
$this->quizInfo = $data['quiz'];
$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());
try {
$statement = $this->createStatement(
$this->attempt->getTms()
);
} catch (Exception $e) {
return;
}
$this->saveSharedStatement($statement);
}
/**
* {@inheritdoc}
*/
protected function getActor()
{
return $this->generateActor(
$this->user
);
}
/**
* {@inheritdoc}
*/
protected function getVerb()
{
return $this->generateVerb(
'answered',
XApiPlugin::VERB_ANSWERED
);
}
/**
* {@inheritdoc}
*/
protected function getActivity()
{
$id = $this->plugin->generateIri(
$this->question->getId(),
'quiz_question'
);
return new Activity(
$id,
$this->generateActivityDefinitionFromQuestionType()
);
}
/**
* {@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()
{
$languageIso = api_get_language_isocode($this->course->getCourseLanguage());
$id = $this->plugin->generateIri($this->quizInfo['id'], XApiPlugin::TYPE_QUIZ);
$quizActivity = new Activity(
$id,
new Definition(
LanguageMap::create([$languageIso => $this->quizInfo['title']]),
null,
IRI::fromString(XApiPlugin::IRI_QUIZ)
)
);
$context = parent::getContext();
$contextActivities = $context->getContextActivities()->withAddedGroupingActivity($quizActivity);
return $context->withContextActivities($contextActivities);
}
/**
* {@inheritdoc}
*/
protected function getId()
{
return $this->generateId(
XApiPlugin::DATA_TYPE_ATTEMPT,
$this->attempt->getId()
$attemptRepo = $em->getRepository(TrackEAttempt::class);
$exe = $em->find(TrackEExercises::class, $data['exe_id']);
$question = $em->find(CQuizQuestion::class, $data['question']['id']);
$attempt = $attemptRepo->findOneBy(
[
'exeId' => $exe->getExeId(),
'questionId' => $question->getId(),
]
);
}
/**
* @return \Xabbuh\XApi\Model\Interaction\InteractionDefinition
*/
private function generateActivityDefinitionFromQuestionType()
{
$languageIso = api_get_language_isocode($this->course->getCourseLanguage());
$questionTitle = strip_tags($this->question->getQuestion());
$questionTitle = trim($questionTitle);
$questionDescription = strip_tags($this->question->getDescription());
$questionDescription = trim($questionDescription);
$titleMap = LanguageMap::create([$languageIso => $questionTitle]);
$descriptionMap = $questionDescription ? LanguageMap::create([$languageIso => $questionDescription]) : null;
$objAnswer = new Answer($this->question->getId(), $this->course->getId());
$objAnswer->read();
$quiz = $em->find(CQuiz::class, $data['quiz']['id']);
$type = IRI::fromString(XApiPlugin::IRI_INTERACTION);
$quizQuestionAnswered = new QuizQuestionAnswered($attempt, $question, $quiz);
switch ($this->question->getType()) {
case MULTIPLE_ANSWER:
case UNIQUE_ANSWER:
case UNIQUE_ANSWER_IMAGE:
case READING_COMPREHENSION:
$choices = [];
$correctResponsesPattern = [];
$statement = $quizQuestionAnswered->generate();
for ($i = 1; $i <= $objAnswer->nbrAnswers; $i++) {
$choices[] = new InteractionComponent(
$objAnswer->iid[$i],
LanguageMap::create([$languageIso => $objAnswer->selectAnswer($i)])
);
if ($objAnswer->isCorrect($i)) {
$correctResponsesPattern[] = $objAnswer->iid[$i];
}
}
return new ChoiceInteractionDefinition(
$titleMap,
$descriptionMap,
$type,
null,
null,
[implode('[,]', $correctResponsesPattern)],
$choices
);
case DRAGGABLE:
$choices = [];
for ($i = 1; $i <= $objAnswer->nbrAnswers; $i++) {
if ((int) $objAnswer->correct[$i] > 0) {
$choices[] = new InteractionComponent(
$objAnswer->correct[$i],
LanguageMap::create([$languageIso => $objAnswer->answer[$i]])
);
}
}
$correctResponsesPattern = array_slice($objAnswer->autoId, 0, $objAnswer->nbrAnswers / 2);
return new SequencingInteractionDefinition(
$titleMap,
$descriptionMap,
$type,
null,
null,
[implode('[,]', $correctResponsesPattern)],
$choices
);
case MATCHING:
case MATCHING_DRAGGABLE:
/** @var array|InteractionComponent[] $source */
$source = [];
/** @var array|InteractionComponent[] $source */
$target = [];
$correctResponsesPattern = [];
for ($i = 1; $i <= $objAnswer->nbrAnswers; $i++) {
$interactionComponent = new InteractionComponent(
$objAnswer->selectAutoId($i),
LanguageMap::create([$languageIso => $objAnswer->selectAnswer($i)])
);
if ((int) $objAnswer->correct[$i] > 0) {
$source[] = $interactionComponent;
$correctResponsesPattern[] = $objAnswer->selectAutoId($i).'[.]'.$objAnswer->correct[$i];
} else {
$target[] = $interactionComponent;
}
}
return new MatchingInteractionDefinition(
$titleMap,
$descriptionMap,
$type,
null,
null,
[implode('[,]', $correctResponsesPattern)],
$source,
$target
);
case FREE_ANSWER:
return new LongFillInInteractionDefinition(
$titleMap,
$descriptionMap,
$type
);
case FILL_IN_BLANKS:
case HOT_SPOT:
case HOT_SPOT_DELINEATION:
case MULTIPLE_ANSWER_COMBINATION:
case UNIQUE_ANSWER_NO_OPTION:
case MULTIPLE_ANSWER_TRUE_FALSE:
case MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY:
case MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE:
case GLOBAL_MULTIPLE_ANSWER:
case CALCULATED_ANSWER:
case ANNOTATION:
case ORAL_EXPRESSION:
default:
return new OtherInteractionDefinition(
$titleMap,
$descriptionMap,
$type
);
}
$this->saveSharedStatement($statement);
}
}

@ -0,0 +1,49 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Activity;
use Xabbuh\XApi\Model\Activity;
/**
* Class BaseActivity.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Activity
*/
abstract class BaseActivity
{
/**
* @var \Chamilo\UserBundle\Entity\User
*/
protected $user;
/**
* @var \Chamilo\CoreBundle\Entity\Course|null
*/
protected $course;
/**
* @var \Chamilo\CoreBundle\Entity\Session|null
*/
protected $session;
public abstract function generate(): Activity;
protected function generateIri(string $path, string $resource, array $params = []): string
{
$cidReq = api_get_cidreq();
$url = api_get_path($path).$resource;
if ($params) {
$url .= '?'.http_build_query($params).'&';
} elseif (empty($params) && $cidReq) {
$url .= '?';
}
if ($cidReq) {
$url .= $cidReq;
}
return $url;
}
}

@ -0,0 +1,40 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Activity;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
/**
* Class Course.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Activity
*/
class Course extends BaseActivity
{
public function generate(): Activity
{
$course = api_get_course_entity();
$session = api_get_session_entity();
$languageIso = api_get_language_isocode($course->getCourseLanguage());
$courseUrl = api_get_course_url(
$course->getCode(),
$session ? $session->getId() : 0
);
return new Activity(
IRI::fromString($courseUrl),
new Definition(
LanguageMap::create([$languageIso => $course->getTitle()]),
null,
IRI::fromString('http://id.tincanapi.com/activitytype/lms/course')
)
);
}
}

@ -0,0 +1,53 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Activity;
use Chamilo\CourseBundle\Entity\CLp;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
/**
* Class LearningPath.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Activity
*/
class LearningPath extends BaseActivity
{
/**
* @var \Chamilo\CourseBundle\Entity\CLp
*/
private $lp;
public function __construct(CLp $lp)
{
$this->lp = $lp;
}
public function generate(): Activity
{
$lanIso = api_get_language_isocode();
$iri = $this->generateIri(
WEB_CODE_PATH,
'lp/lp_controller.php',
[
'action' => 'view',
'lp_id' => $this->lp->getId(),
'isStudentView' => 'true',
]
);
return new Activity(
IRI::fromString($iri),
new Definition(
LanguageMap::create([$lanIso => $this->lp->getName()]),
null,
IRI::fromString('http://adlnet.gov/expapi/activities/lesson')
)
);
}
}

@ -0,0 +1,54 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Activity;
use Chamilo\CourseBundle\Entity\CLpItem;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
/**
* Class LearningPathItem.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Activity
*/
class LearningPathItem extends BaseActivity
{
/**
* @var \Chamilo\CourseBundle\Entity\CLpItem
*/
private $lpItem;
public function __construct(CLpItem $lpItem)
{
$this->lpItem = $lpItem;
}
public function generate(): Activity
{
$langIso = api_get_language_isocode();
$iri = $this->generateIri(
WEB_CODE_PATH,
'lp/lp_controller.php',
[
'action' => 'view',
'lp_id' => $this->lpItem->getLpId(),
'isStudentView' => 'true',
'lp_item' => $this->lpItem->getId(),
]
);
return new Activity(
IRI::fromString($iri),
new Definition(
LanguageMap::create([$langIso => $this->lpItem->getTitle()]),
null,
IRI::fromString('http://id.tincanapi.com/activitytype/resource')
)
);
}
}

@ -0,0 +1,58 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Activity;
use Chamilo\CoreBundle\Entity\PortfolioCategory as PortfolioCategoryEntity;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
/**
* Class PortfolioCategory.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Activity
*/
class PortfolioCategory extends BaseActivity
{
/**
* @var \Chamilo\CoreBundle\Entity\PortfolioCategory
*/
private $category;
public function __construct(PortfolioCategoryEntity $category)
{
$this->category = $category;
}
public function generate(): Activity
{
$iri = $this->generateIri(
WEB_PATH,
'xapi/portfolio/',
[
'user' => $this->category->getUser()->getId(),
'category' => $this->category->getId(),
]
);
$langIso = api_get_language_isocode();
$categoryDescription = $this->category->getDescription();
$definitionDescription = $categoryDescription
? LanguageMap::create([$langIso => $categoryDescription])
: null;
return new Activity(
IRI::fromString($iri),
new Definition(
LanguageMap::create([$langIso => $this->category->getTitle()]),
$definitionDescription,
IRI::fromString('http://id.tincanapi.com/activitytype/category')
)
);
}
}

@ -0,0 +1,50 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Activity;
use Chamilo\CoreBundle\Entity\PortfolioComment as PortfolioCommentEntity;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
/**
* Class PortfolioComment.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Activity
*/
class PortfolioComment extends BaseActivity
{
/**
* @var \Chamilo\CoreBundle\Entity\PortfolioComment
*/
private $comment;
public function __construct(PortfolioCommentEntity $comment)
{
$this->comment = $comment;
}
public function generate(): Activity
{
$iri = $this->generateIri(
WEB_CODE_PATH,
'portfolio/index.php',
[
'action' => 'view',
'id' => $this->comment->getItem()->getId(),
'comment' => $this->comment->getId(),
]
);
return new Activity(
IRI::fromString($iri),
new Definition(
null,
null,
IRI::fromString('http://activitystrea.ms/schema/1.0/comment')
)
);
}
}

@ -0,0 +1,49 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Activity;
use Chamilo\CoreBundle\Entity\Portfolio;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
/**
* Class PortfolioItem.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Activity
*/
class PortfolioItem extends BaseActivity
{
/**
* @var \Chamilo\CoreBundle\Entity\Portfolio
*/
private $item;
public function __construct(Portfolio $item)
{
$this->item = $item;
}
public function generate(): Activity
{
$langIso = api_get_language_isocode();
$iri = $this->generateIri(
WEB_CODE_PATH,
'portfolio/index.php',
['action' => 'view', 'id' => $this->item->getId()]
);
return new Activity(
IRI::fromString($iri),
new Definition(
LanguageMap::create([$langIso => $this->item->getTitle()]),
null,
IRI::fromString('http://activitystrea.ms/schema/1.0/article')
)
);
}
}

@ -0,0 +1,57 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Activity;
use Chamilo\CourseBundle\Entity\CQuiz;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
/**
* Class Quiz.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Activity
*/
class Quiz extends BaseActivity
{
/**
* @var \Chamilo\CourseBundle\Entity\CQuiz
*/
private $quiz;
public function __construct(CQuiz $quiz)
{
$this->quiz = $quiz;
}
public function generate(): Activity
{
$langIso = api_get_language_isocode();
$iri = $this->generateIri(
WEB_CODE_PATH,
'exercise/overview.php',
['exerciseId' => $this->quiz->getId()]
);
$definitionDescription = null;
if ($this->quiz->getDescription()) {
$definitionDescription = LanguageMap::create(
[$langIso => $this->quiz->getDescription()]
);
}
return new Activity(
IRI::fromString($iri),
new Definition(
LanguageMap::create([$langIso => $this->quiz->getTitle()]),
$definitionDescription,
IRI::fromString('http://adlnet.gov/expapi/activities/assessment')
)
);
}
}

@ -0,0 +1,170 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Activity;
use Answer;
use Chamilo\CourseBundle\Entity\CQuizQuestion;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Interaction\ChoiceInteractionDefinition;
use Xabbuh\XApi\Model\Interaction\InteractionComponent;
use Xabbuh\XApi\Model\Interaction\LongFillInInteractionDefinition;
use Xabbuh\XApi\Model\Interaction\MatchingInteractionDefinition;
use Xabbuh\XApi\Model\Interaction\OtherInteractionDefinition;
use Xabbuh\XApi\Model\Interaction\SequencingInteractionDefinition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
/**
* Class QuizQuestion.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Activity
*/
class QuizQuestion extends BaseActivity
{
private $question;
public function __construct(CQuizQuestion $question)
{
$this->question = $question;
}
public function generate(): Activity
{
$iri = $this->generateIri(
WEB_CODE_PATH,
'xapi/quiz/',
['question' => $this->question->getId()]
);
return new Activity(
IRI::fromString($iri),
$this->generateActivityDefinitionFromQuestionType()
);
}
/**
* @return \Xabbuh\XApi\Model\Interaction\InteractionDefinition
*/
private function generateActivityDefinitionFromQuestionType()
{
$languageIso = api_get_language_isocode();
$courseId = api_get_course_int_id();
$questionTitle = strip_tags($this->question->getQuestion());
$questionTitle = trim($questionTitle);
$questionDescription = strip_tags($this->question->getDescription());
$questionDescription = trim($questionDescription);
$titleMap = LanguageMap::create([$languageIso => $questionTitle]);
$descriptionMap = $questionDescription ? LanguageMap::create([$languageIso => $questionDescription]) : null;
$objAnswer = new Answer($this->question->getId(), $courseId);
$objAnswer->read();
$type = IRI::fromString('http://adlnet.gov/expapi/activities/question');
switch ($this->question->getType()) {
case MULTIPLE_ANSWER:
case UNIQUE_ANSWER:
case UNIQUE_ANSWER_IMAGE:
case READING_COMPREHENSION:
$choices = [];
$correctResponsesPattern = [];
for ($i = 1; $i <= $objAnswer->nbrAnswers; $i++) {
$choices[] = new InteractionComponent(
$objAnswer->iid[$i],
LanguageMap::create([$languageIso => $objAnswer->selectAnswer($i)])
);
if ($objAnswer->isCorrect($i)) {
$correctResponsesPattern[] = $objAnswer->iid[$i];
}
}
return new ChoiceInteractionDefinition(
$titleMap,
$descriptionMap,
$type,
null,
null,
[implode('[,]', $correctResponsesPattern)],
$choices
);
case DRAGGABLE:
$choices = [];
for ($i = 1; $i <= $objAnswer->nbrAnswers; $i++) {
if ((int)$objAnswer->correct[$i] > 0) {
$choices[] = new InteractionComponent(
$objAnswer->correct[$i],
LanguageMap::create([$languageIso => $objAnswer->answer[$i]])
);
}
}
$correctResponsesPattern = array_slice($objAnswer->autoId, 0, $objAnswer->nbrAnswers / 2);
return new SequencingInteractionDefinition(
$titleMap,
$descriptionMap,
$type,
null,
null,
[implode('[,]', $correctResponsesPattern)],
$choices
);
case MATCHING:
case MATCHING_DRAGGABLE:
/** @var array|InteractionComponent[] $source */
$source = [];
/** @var array|InteractionComponent[] $source */
$target = [];
$correctResponsesPattern = [];
for ($i = 1; $i <= $objAnswer->nbrAnswers; $i++) {
$interactionComponent = new InteractionComponent(
$objAnswer->selectAutoId($i),
LanguageMap::create([$languageIso => $objAnswer->selectAnswer($i)])
);
if ((int)$objAnswer->correct[$i] > 0) {
$source[] = $interactionComponent;
$correctResponsesPattern[] = $objAnswer->selectAutoId($i).'[.]'.$objAnswer->correct[$i];
} else {
$target[] = $interactionComponent;
}
}
return new MatchingInteractionDefinition(
$titleMap,
$descriptionMap,
$type,
null,
null,
[implode('[,]', $correctResponsesPattern)],
$source,
$target
);
case FREE_ANSWER:
return new LongFillInInteractionDefinition($titleMap, $descriptionMap, $type);
case FILL_IN_BLANKS:
case HOT_SPOT:
case HOT_SPOT_DELINEATION:
case MULTIPLE_ANSWER_COMBINATION:
case UNIQUE_ANSWER_NO_OPTION:
case MULTIPLE_ANSWER_TRUE_FALSE:
case MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY:
case MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE:
case GLOBAL_MULTIPLE_ANSWER:
case CALCULATED_ANSWER:
case ANNOTATION:
case ORAL_EXPRESSION:
default:
return new OtherInteractionDefinition($titleMap, $descriptionMap, $type);
}
}
}

@ -0,0 +1,33 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Activity;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Definition;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
/**
* Class Site.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Activity
*/
class Site extends BaseActivity
{
public function generate(): Activity
{
$platformLanguageIso = api_get_language_isocode(
api_get_setting('platformLanguage')
);
$platform = api_get_setting('Institution').' - '.api_get_setting('siteName');
return new Activity(
IRI::fromString('http://id.tincanapi.com/activitytype/lms'),
new Definition(
LanguageMap::create([$platformLanguageIso => $platform])
)
);
}
}

@ -0,0 +1,17 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Actor;
use Xabbuh\XApi\Model\Agent;
/**
* Class BaseActor.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Actor
*/
abstract class BaseActor
{
abstract public function generate(): Agent;
}

@ -0,0 +1,35 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Actor;
use Chamilo\UserBundle\Entity\User as UserEntity;
use Xabbuh\XApi\Model\Agent;
use Xabbuh\XApi\Model\InverseFunctionalIdentifier;
use Xabbuh\XApi\Model\IRI;
/**
* Class User.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Actor
*/
class User extends BaseActor
{
private $user;
public function __construct(UserEntity $user)
{
$this->user = $user;
}
public function generate(): Agent
{
return new Agent(
InverseFunctionalIdentifier::withMbox(
IRI::fromString('mailto:'.$this->user->getEmail())
),
$this->user->getCompleteName()
);
}
}

@ -0,0 +1,53 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Statement;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\Course as CourseActivity;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\Site as SiteActivity;
use Xabbuh\XApi\Model\Context;
use Xabbuh\XApi\Model\ContextActivities;
use Xabbuh\XApi\Model\Statement;
use Xabbuh\XApi\Model\StatementId;
use Xabbuh\XApi\Model\Uuid;
use XApiPlugin;
/**
* Class BaseStatement
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Statement
*/
abstract class BaseStatement
{
abstract public function generate(): Statement;
protected function generateStatementId(string $type, string $value): StatementId
{
$uuid = Uuid::uuid5(
XApiPlugin::create()->get(XApiPlugin::SETTING_UUID_NAMESPACE),
"$type/$value"
);
return StatementId::fromUuid($uuid);
}
protected function generateContext(): Context
{
$platform = api_get_setting('Institution').' - '.api_get_setting('siteName');
$groupingActivities = [];
$groupingActivities[] = (new SiteActivity())->generate();
if (api_get_course_id()) {
$groupingActivities[] = (new CourseActivity())->generate();
}
return (new Context())
->withPlatform($platform)
->withLanguage(api_get_language_isocode())
->withContextActivities(
new ContextActivities(null, $groupingActivities)
);
}
}

@ -0,0 +1,61 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Statement;
use Chamilo\CourseBundle\Entity\CLp as CLpEntity;
use Chamilo\CourseBundle\Entity\CLpView as CLpViewEntity;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\LearningPath as LearningPathActivity;
use Chamilo\PluginBundle\XApi\ToolExperience\Actor\User as UserActor;
use Chamilo\PluginBundle\XApi\ToolExperience\Verb\Completed;
use Xabbuh\XApi\Model\Result;
use Xabbuh\XApi\Model\Score;
use Xabbuh\XApi\Model\Statement;
/**
* Class LearningPathCompleted.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Statement
*/
class LearningPathCompleted extends BaseStatement
{
/**
* @var \Chamilo\CourseBundle\Entity\CLpView
*/
private $lpView;
/**
* @var \Chamilo\CourseBundle\Entity\CLp
*/
private $lp;
public function __construct(CLpViewEntity $lpView, CLpEntity $lp)
{
$this->lpView = $lpView;
$this->lp = $lp;
}
public function generate(): Statement
{
$user = api_get_user_entity($this->lpView->getUserId());
$userActor = new UserActor($user);
$completedVerb = new Completed();
$lpActivity = new LearningPathActivity($this->lp);
return new Statement(
null,
$userActor->generate(),
$completedVerb->generate(),
$lpActivity->generate(),
new Result(
new Score(1, 100, 0, 100),
null,
true
),
null,
api_get_utc_datetime(null, false, true),
null,
$this->generateContext()
);
}
}

@ -0,0 +1,79 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Statement;
use Chamilo\CourseBundle\Entity\CLp;
use Chamilo\CourseBundle\Entity\CLpItem;
use Chamilo\CourseBundle\Entity\CLpItemView;
use Chamilo\CourseBundle\Entity\CLpView;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\LearningPath;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\LearningPathItem as LearningPathItemActivity;
use Chamilo\PluginBundle\XApi\ToolExperience\Actor\User as UserActor;
use Chamilo\PluginBundle\XApi\ToolExperience\Verb\Viewed as ViewedVerb;
use Database;
use Xabbuh\XApi\Model\Result;
use Xabbuh\XApi\Model\Statement;
/**
* Class LearningPathItemViewed
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Statement
*/
class LearningPathItemViewed extends BaseStatement
{
/**
* @var \Chamilo\CourseBundle\Entity\CLpItemView
*/
private $lpItemView;
/**
* @var \Chamilo\CourseBundle\Entity\CLpItem
*/
private $lpItem;
/**
* @var \Chamilo\CourseBundle\Entity\CLpView
*/
private $lpView;
public function __construct(CLpItemView $lpItemView, CLpItem $lpItem, CLpView $lpView)
{
$this->lpItemView = $lpItemView;
$this->lpItem = $lpItem;
$this->lpView = $lpView;
}
public function generate(): Statement
{
$user = api_get_user_entity($this->lpView->getUserId());
$lp = Database::getManager()->find(CLp::class, $this->lpView->getLpId());
$userActor = new UserActor($user);
$viewedVerb = new ViewedVerb();
$lpItemActivity = new LearningPathItemActivity($this->lpItem);
$lpActivity = new LearningPath($lp);
$context = $this->generateContext();
$contextActivities = $context
->getContextActivities()
->withAddedGroupingActivity($lpActivity->generate());
return new Statement(
null,
$userActor->generate(),
$viewedVerb->generate(),
$lpItemActivity->generate(),
new Result(
null,
null,
'completed' === $this->lpItemView->getStatus(),
null,
'PT'.$this->lpItemView->getTotalTime().'S'
),
null,
api_get_utc_datetime(null, false, true),
null,
$context->withContextActivities($contextActivities)
);
}
}

@ -0,0 +1,72 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Statement;
use Chamilo\CoreBundle\Entity\PortfolioComment as PortfolioCommentEntity;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\PortfolioComment as PortfolioCommentActivity;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\PortfolioItem as PortfolioItemActivity;
use Chamilo\PluginBundle\XApi\ToolExperience\Actor\User as UserActor;
use Chamilo\PluginBundle\XApi\ToolExperience\Verb\Commented as CommentedVerb;
use Chamilo\PluginBundle\XApi\ToolExperience\Verb\Replied as RepliedVerb;
use Xabbuh\XApi\Model\Result;
use Xabbuh\XApi\Model\Statement;
class PortfolioItemCommented extends BaseStatement
{
/**
* @var \Chamilo\CoreBundle\Entity\PortfolioComment
*/
private $comment;
public function __construct(PortfolioCommentEntity $comment)
{
$this->comment = $comment;
}
public function generate(): Statement
{
$portfolioItem = $this->comment->getItem();
$commentParent = $this->comment->getParent();
$userActor = new UserActor($this->comment->getAuthor());
$statementResult = new Result(null, null, null, $this->comment->getContent());
$context = $this->generateContext();
if ($commentParent) {
$repliedVerb = new RepliedVerb();
$itemActivity = new PortfolioItemActivity($portfolioItem);
$parentCommentActivity = new PortfolioCommentActivity($commentParent);
$contextActivities = $context
->getContextActivities()
->withAddedGroupingActivity($itemActivity->generate());
return new Statement(
null,
$userActor->generate(),
$repliedVerb->generate(),
$parentCommentActivity->generate(),
$statementResult,
null,
$this->comment->getDate(),
null,
$context->withContextActivities($contextActivities)
);
} else {
$itemShared = new PortfolioItemShared($portfolioItem);
$commentedVerb = new CommentedVerb();
return $itemShared->generate()
->withActor($userActor->generate())
->withVerb($commentedVerb->generate())
->withStored($this->comment->getDate())
->withResult($statementResult)
->withContext($context);
}
}
}

@ -0,0 +1,65 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Statement;
use Chamilo\CoreBundle\Entity\Portfolio as PortfolioEntity;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\PortfolioCategory as PortfolioCategoryActivity;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\PortfolioItem as PortfolioItemActivity;
use Chamilo\PluginBundle\XApi\ToolExperience\Actor\User as UserActor;
use Chamilo\PluginBundle\XApi\ToolExperience\Verb\Shared as SharedVerb;
use Xabbuh\XApi\Model\Statement;
/**
* Class PortfolioItemShared.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Statement
*/
class PortfolioItemShared extends BaseStatement
{
/**
* @var \Chamilo\CoreBundle\Entity\Portfolio
*/
private $portfolioItem;
public function __construct(PortfolioEntity $item)
{
$this->portfolioItem = $item;
}
public function generate(): Statement
{
$userActor = new UserActor(
$this->portfolioItem->getUser()
);
$sharedVerb = new SharedVerb();
$itemActivity = new PortfolioItemActivity($this->portfolioItem);
$context = $this->generateContext();
if ($this->portfolioItem->getCategory()) {
$categoryActivity = new PortfolioCategoryActivity($this->portfolioItem->getCategory());
$contextActivities = $context
->getContextActivities()
->withAddedCategoryActivity(
$categoryActivity->generate()
);
$context = $context->withContextActivities($contextActivities);
}
return new Statement(
null,
$userActor->generate(),
$sharedVerb->generate(),
$itemActivity->generate(),
null,
null,
$this->portfolioItem->getCreationDate(),
null,
$context
);
}
}

@ -0,0 +1,70 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Statement;
use Chamilo\CoreBundle\Entity\TrackEExercises;
use Chamilo\CourseBundle\Entity\CQuiz;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\Quiz as QuizActivity;
use Chamilo\PluginBundle\XApi\ToolExperience\Actor\User as UserActor;
use Chamilo\PluginBundle\XApi\ToolExperience\Verb\Completed as CompletedVerb;
use Xabbuh\XApi\Model\Result;
use Xabbuh\XApi\Model\Score;
use Xabbuh\XApi\Model\Statement;
/**
* Class QuizCompleted.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Statement
*/
class QuizCompleted extends BaseStatement
{
/**
* @var \Chamilo\CoreBundle\Entity\TrackEExercises
*/
private $exe;
/**
* @var \Chamilo\CourseBundle\Entity\CQuiz
*/
private $quiz;
public function __construct(TrackEExercises $exe, CQuiz $quiz)
{
$this->exe = $exe;
$this->quiz = $quiz;
}
public function generate(): Statement
{
$user = api_get_user_entity($this->exe->getExeUserId());
$userActor = new UserActor($user);
$completedVerb = new CompletedVerb();
$quizActivity = new QuizActivity($this->quiz);
$rawResult = $this->exe->getExeResult();
$maxResult = $this->exe->getExeWeighting();
$scaledResult = $rawResult / $maxResult;
$duration = $this->exe->getExeDuration();
return new Statement(
null,
$userActor->generate(),
$completedVerb->generate(),
$quizActivity->generate(),
new Result(
new Score($scaledResult, $rawResult, 0, $maxResult),
null,
true,
null,
$duration ? "PT{$duration}S" : null
),
null,
$this->exe->getExeDate(),
null,
$this->generateContext()
);
}
}

@ -0,0 +1,79 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Statement;
use Chamilo\CoreBundle\Entity\TrackEAttempt;
use Chamilo\CourseBundle\Entity\CQuiz;
use Chamilo\CourseBundle\Entity\CQuizQuestion;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\Quiz as QuizActivity;
use Chamilo\PluginBundle\XApi\ToolExperience\Activity\QuizQuestion as QuizQuestionActivity;
use Chamilo\PluginBundle\XApi\ToolExperience\Actor\User as UserActor;
use Chamilo\PluginBundle\XApi\ToolExperience\Verb\Answered as AnsweredVerb;
use Xabbuh\XApi\Model\Result;
use Xabbuh\XApi\Model\Score;
use Xabbuh\XApi\Model\Statement;
/**
* Class QuizQuestionAnswered.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Statement
*/
class QuizQuestionAnswered extends BaseStatement
{
/**
* @var \Chamilo\CoreBundle\Entity\TrackEAttempt
*/
private $attempt;
/**
* @var \Chamilo\CourseBundle\Entity\CQuizQuestion
*/
private $question;
/**
* @var \Chamilo\CourseBundle\Entity\CQuiz
*/
private $quiz;
public function __construct(TrackEAttempt $attempt, CQuizQuestion $question, CQuiz $quiz)
{
$this->attempt = $attempt;
$this->question = $question;
$this->quiz = $quiz;
}
public function generate(): Statement
{
$user = api_get_user_entity($this->attempt->getUserId());
$userActor = new UserActor($user);
$answeredVerb = new AnsweredVerb();
$questionActivity = new QuizQuestionActivity($this->question);
$quizActivity = new QuizActivity($this->quiz);
$rawResult = $this->attempt->getMarks();
$maxResult = $this->question->getPonderation();
$scaledResult = $rawResult / $maxResult;
$context = $this->generateContext();
$contextActivities = $context
->getContextActivities()
->withAddedGroupingActivity($quizActivity->generate());
return new Statement(
null,
$userActor->generate(),
$answeredVerb->generate(),
$questionActivity->generate(),
new Result(
new Score($scaledResult, $rawResult, null, $maxResult),
$rawResult > 0,
true
),
null,
$this->attempt->getTms(),
null,
$context->withContextActivities($contextActivities)
);
}
}

@ -0,0 +1,27 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Verb;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Verb;
/**
* Class Answered.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Verb
*/
class Answered extends BaseVerb
{
public function generate(): Verb
{
$langIso = api_get_language_isocode();
return new Verb(
IRI::fromString('http://adlnet.gov/expapi/verbs/answered'),
LanguageMap::create([$langIso => get_lang('Answered')])
);
}
}

@ -0,0 +1,17 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Verb;
use Xabbuh\XApi\Model\Verb;
/**
* Class BaseVerb
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Verb
*/
abstract class BaseVerb
{
public abstract function generate(): Verb;
}

@ -0,0 +1,27 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Verb;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Verb;
/**
* Class Commented.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Verb
*/
class Commented extends BaseVerb
{
public function generate(): Verb
{
$langIso = api_get_language_isocode();
return new Verb(
IRI::fromString('http://adlnet.gov/expapi/verbs/commented'),
LanguageMap::create([$langIso => get_lang('Commented')])
);
}
}

@ -0,0 +1,27 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Verb;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Verb;
/**
* Class Completed.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Verb
*/
class Completed extends BaseVerb
{
public function generate(): Verb
{
$langIso = api_get_language_isocode();
return new Verb(
IRI::fromString('http://activitystrea.ms/schema/1.0/complete'),
LanguageMap::create([$langIso => get_lang('Completed')])
);
}
}

@ -0,0 +1,28 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Verb;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Verb;
/**
* Class Replied.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Verb
*/
class Replied extends BaseVerb
{
public function generate(): Verb
{
$langIso = api_get_language_isocode();
return new Verb(
IRI::fromString('http://id.tincanapi.com/verb/replied'),
LanguageMap::create([$langIso => get_lang('Replied')])
);
}
}

@ -0,0 +1,27 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Verb;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Verb;
/**
* Class Shared.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Verb
*/
class Shared extends BaseVerb
{
public function generate(): Verb
{
$langIso = api_get_language_isocode();
return new Verb(
IRI::fromString('http://adlnet.gov/expapi/verbs/shared'),
LanguageMap::create([$langIso => get_lang('Shared')])
);
}
}

@ -0,0 +1,27 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\XApi\ToolExperience\Verb;
use Xabbuh\XApi\Model\IRI;
use Xabbuh\XApi\Model\LanguageMap;
use Xabbuh\XApi\Model\Verb;
/**
* Class Viewed.
*
* @package Chamilo\PluginBundle\XApi\ToolExperience\Verb
*/
class Viewed extends BaseVerb
{
public function generate(): Verb
{
$langIso = api_get_language_isocode();
return new Verb(
IRI::fromString('http://id.tincanapi.com/verb/viewed'),
LanguageMap::create([$langIso => get_lang('Viewed')])
);
}
}

@ -1,107 +0,0 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Course as CourseEntity;
use Chamilo\CoreBundle\Entity\Session as SessionEntity;
use Chamilo\UserBundle\Entity\User as UserEntity;
use Xabbuh\XApi\Model\Activity;
use Xabbuh\XApi\Model\Agent;
use Xabbuh\XApi\Model\Definition;
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
{
/**
* @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);
}
/**
* @return \Xabbuh\XApi\Model\Activity
*/
protected function generateActivityFromSite()
{
$platform = api_get_setting('Institution').' - '.api_get_setting('siteName');
$platformLanguage = api_get_setting('platformLanguage');
$platformLanguageIso = api_get_language_isocode($platformLanguage);
return new Activity(
IRI::fromString('http://id.tincanapi.com/activitytype/lms'),
new Definition(
LanguageMap::create([$platformLanguageIso => $platform])
)
);
}
/**
* @return \Xabbuh\XApi\Model\Activity
*/
protected function generateActivityFromCourse(
CourseEntity $course,
SessionEntity $session = null
) {
$languageIso = api_get_language_isocode($course->getCourseLanguage());
return new Activity(
IRI::fromString(
api_get_course_url($course->getCode(), $session ? $session->getId() : null)
),
new Definition(
LanguageMap::create([$languageIso => $course->getTitle()]),
null,
IRI::fromString('http://id.tincanapi.com/activitytype/lms/course')
)
);
}
}

@ -34,31 +34,6 @@ class XApiPlugin extends Plugin implements HookPluginInterface
const SETTING_LRS_QUIZ_QUESTION_ACTIVE = 'lrs_quiz_question_active';
const SETTING_LRS_PORTFOLIO_ACTIVE = 'lrs_portfolio_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 VERB_SHARED = 'http://adlnet.gov/expapi/verbs/shared';
const VERB_COMMENTED = 'http://adlnet.gov/expapi/verbs/commented';
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 IRI_INTERACTION = 'http://adlnet.gov/expapi/activities/cmi.interaction';
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 DATA_TYPE_PORTFOLIO_ITEM = 'portfolio_item';
const DATA_TYPE_PORTFOLIO_COMMENT = 'portfolio_comment';
const TYPE_QUIZ = 'quiz';
const TYPE_QUIZ_QUESTION = 'quiz_question';
const TYPE_LP = 'lp';
const TYPE_LP_ITEM = 'lp_item';
const STATE_FIRST_LAUNCH = 'first_launch';
const STATE_LAST_LAUNCH = 'last_launch';

Loading…
Cancel
Save