parent
758654653d
commit
4f3f17a7d2
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue