XApi: Send statements from chamilo by cron script - refs BT#16742

pull/3680/head
Angel Fernando Quiroz Campos 5 years ago
parent e48dc568ac
commit 94529e9bc8
  1. 71
      plugin/xapi/cron/send_statements.php
  2. 75
      plugin/xapi/src/Entity/SharedStatement.php
  3. 92
      plugin/xapi/src/Hook/XApiActivityHookObserver.php
  4. 10
      plugin/xapi/src/Hook/XApiLearningPathEndHookObserver.php
  5. 9
      plugin/xapi/src/Hook/XApiLearningPathItemViewedHookObserver.php
  6. 11
      plugin/xapi/src/Hook/XApiQuizEndHookObserver.php
  7. 14
      plugin/xapi/src/Hook/XApiQuizQuestionAnsweredHookObserver.php

@ -0,0 +1,71 @@
<?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\Serializer\Symfony\Serializer;
use Xabbuh\XApi\Serializer\Symfony\StatementSerializer;
require_once __DIR__.'/../../../main/inc/global.inc.php';
if (php_sapi_name() !== 'cli') {
exit;
}
echo 'XAPI: Cron to send statements.'.PHP_EOL;
$em = Database::getManager();
$serializer = Serializer::createSerializer();
$statementSerializer = new StatementSerializer($serializer);
$notSentSharedStatements = $em
->getRepository(SharedStatement::class)
->findBy(
['uuid' => null, 'sent' => false],
null,
100
);
$countNotSent = count($notSentSharedStatements);
if ($countNotSent > 0) {
echo '['.time().'] Trying to send '.$countNotSent.' statements to LRS'.PHP_EOL;
$client = XApiPlugin::create()->getXApiStatementClient();
/** @var SharedStatement $notSentSharedStatement */
foreach ($notSentSharedStatements as $notSentSharedStatement) {
$notSentStatement = $statementSerializer->deserializeStatement(
json_encode($notSentSharedStatement->getStatement())
);
try {
echo '['.time()."] Sending shared statement ({$notSentSharedStatement->getId()})";
$sentStatement = $client->storeStatement($notSentStatement);
echo "\t\tStatement ID received: \"{$sentStatement->getId()->getValue()}\"";
} catch (ConflictException $e) {
echo $e->getMessage().PHP_EOL;
continue;
} catch (XApiException $e) {
echo $e->getMessage().PHP_EOL;
continue;
}
$notSentSharedStatement
->setUuid($sentStatement->getId()->getValue())
->setSent(true);
$em->persist($notSentSharedStatement);
echo "\t\tShared statement updated".PHP_EOL;
}
$em->flush();
} else {
echo 'No statements to process.'.PHP_EOL;
}

@ -14,10 +14,7 @@ use Doctrine\ORM\Mapping as ORM;
* @ORM\Table( * @ORM\Table(
* name="xapi_shared_statement", * name="xapi_shared_statement",
* indexes={ * indexes={
* @ORM\Index(name="idx_datatype_dataid", columns={"data_type", "data_id"}) * @ORM\Index(name="idx_uuid", columns={"uuid"})
* },
* uniqueConstraints={
* @ORM\UniqueConstraint(name="idx_uuid", columns={"uuid"})
* } * }
* ) * )
* @ORM\Entity() * @ORM\Entity()
@ -33,58 +30,60 @@ class SharedStatement
*/ */
private $id; private $id;
/** /**
* @var string * @var string|null
* *
* @ORM\Column(name="uuid", type="string") * @ORM\Column(name="uuid", type="string", nullable=true)
*/ */
private $uuid; private $uuid;
/** /**
* @var string * @var array
* *
* @ORM\Column(name="data_type", type="string") * @ORM\Column(name="statement", type="array")
*/ */
private $dataType; private $statement;
/** /**
* @var int * @var bool
* *
* @ORM\Column(name="data_id", type="integer") * @ORM\Column(name="sent", type="boolean", options={"default":false})
*/ */
private $dataId; private $sent;
/** /**
* @return int * SharedStatement constructor.
*
* @param array $statement
* @param null $uuid
* @param false $sent
*/ */
public function getId() public function __construct($statement, $uuid = null, $sent = false)
{ {
return $this->id; $this->statement = $statement;
$this->uuid = $uuid;
$this->sent = $sent;
} }
/** /**
* @param int $id * @return int
*
* @return SharedStatement
*/ */
public function setId($id) public function getId(): int
{ {
$this->id = $id; return $this->id;
return $this;
} }
/** /**
* @return string * @return string|null
*/ */
public function getUuid() public function getUuid(): ?string
{ {
return $this->uuid; return $this->uuid;
} }
/** /**
* @param string $uuid * @param string|null $uuid
* *
* @return SharedStatement * @return SharedStatement
*/ */
public function setUuid($uuid) public function setUuid(?string $uuid): SharedStatement
{ {
$this->uuid = $uuid; $this->uuid = $uuid;
@ -92,41 +91,41 @@ class SharedStatement
} }
/** /**
* @return string * @return array
*/ */
public function getDataType() public function getStatement(): array
{ {
return $this->dataType; return $this->statement;
} }
/** /**
* @param string $dataType * @param array $statement
* *
* @return SharedStatement * @return SharedStatement
*/ */
public function setDataType($dataType) public function setStatement(array $statement): SharedStatement
{ {
$this->dataType = $dataType; $this->statement = $statement;
return $this; return $this;
} }
/** /**
* @return int * @return bool
*/ */
public function getDataId() public function isSent(): bool
{ {
return $this->dataId; return $this->sent;
} }
/** /**
* @param int $dataId * @param bool $sent
* *
* @return SharedStatement * @return SharedStatement
*/ */
public function setDataId($dataId) public function setSent(bool $sent): SharedStatement
{ {
$this->dataId = $dataId; $this->sent = $sent;
return $this; return $this;
} }

@ -3,13 +3,15 @@
/* For licensing terms, see /license.txt */ /* For licensing terms, see /license.txt */
use Chamilo\PluginBundle\Entity\XApi\SharedStatement; use Chamilo\PluginBundle\Entity\XApi\SharedStatement;
use Doctrine\ORM\OptimisticLockException;
use Xabbuh\XApi\Common\Exception\ConflictException; use Xabbuh\XApi\Common\Exception\ConflictException;
use Xabbuh\XApi\Common\Exception\StatementIdAlreadyExistsException; use Xabbuh\XApi\Common\Exception\StatementIdAlreadyExistsException;
use Xabbuh\XApi\Common\Exception\XApiException; use Xabbuh\XApi\Common\Exception\XApiException;
use Xabbuh\XApi\Model\Context; use Xabbuh\XApi\Model\Context;
use Xabbuh\XApi\Model\ContextActivities; use Xabbuh\XApi\Model\ContextActivities;
use Xabbuh\XApi\Model\Statement; use Xabbuh\XApi\Model\Statement;
use Xabbuh\XApi\Model\StatementId; use Xabbuh\XApi\Serializer\Symfony\Serializer;
use Xabbuh\XApi\Serializer\Symfony\StatementSerializer;
/** /**
* Class XApiActivityHookObserver. * Class XApiActivityHookObserver.
@ -51,57 +53,44 @@ abstract class XApiActivityHookObserver extends HookObserver
/** /**
* @param \Xabbuh\XApi\Model\Statement $statement * @param \Xabbuh\XApi\Model\Statement $statement
* *
* @throws \Exception * @return \Chamilo\PluginBundle\Entity\XApi\SharedStatement|null
*
* @return \Xabbuh\XApi\Model\Statement
*/ */
protected function sendStatementToLrs(Statement $statement) protected function saveSharedStatement(Statement $statement)
{ {
$client = XApiPlugin::create()->getXApiStatementClient(); $statementSerialized = $this->serializeStatement($statement);
try {
return $client->storeStatement($statement);
} catch (ConflictException $e) {
throw new Exception($e->getMessage());
} catch (XApiException $e) {
throw new Exception($e->getMessage());
}
}
/** $sharedStmt = new SharedStatement(
* @param \Xabbuh\XApi\Model\StatementId $uuid json_decode($statementSerialized, true)
* @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 = Database::getManager();
$em->persist($sharedStmt); $em->persist($sharedStmt);
try {
$em->flush(); $em->flush();
} catch (OptimisticLockException $e) {
return null;
}
return $sharedStmt; return $sharedStmt;
} }
/** /**
* @param \DateTime|null $createdAt
*
* @throws \Xabbuh\XApi\Common\Exception\StatementIdAlreadyExistsException * @throws \Xabbuh\XApi\Common\Exception\StatementIdAlreadyExistsException
* *
* @return \Xabbuh\XApi\Model\Statement * @return \Xabbuh\XApi\Model\Statement
*/ */
protected function createStatement() protected function createStatement(DateTime $createdAt = null)
{ {
$id = $this->getId(); $id = $this->getId();
if ($this->statementAlreadyShared($id->getValue())) { $sharedStmt = Database::getManager()
->getRepository(SharedStatement::class)
->findOneByUuid($id->getValue());
if ($sharedStmt) {
throw new StatementIdAlreadyExistsException($id->getValue()); throw new StatementIdAlreadyExistsException($id->getValue());
} }
@ -112,7 +101,7 @@ abstract class XApiActivityHookObserver extends HookObserver
$this->getActivity(), $this->getActivity(),
$this->getActivityResult(), $this->getActivityResult(),
null, null,
null, $createdAt,
null, null,
$this->getContext() $this->getContext()
); );
@ -123,24 +112,6 @@ abstract class XApiActivityHookObserver extends HookObserver
*/ */
abstract protected function getId(); abstract protected function getId();
/**
* @param string $uuid
*
* @return bool
*/
protected function statementAlreadyShared($uuid)
{
$sharedStmt = Database::getManager()
->getRepository(SharedStatement::class)
->findOneByUuid($uuid);
if ($sharedStmt) {
return true;
}
return false;
}
/** /**
* @return \Xabbuh\XApi\Model\Agent * @return \Xabbuh\XApi\Model\Agent
*/ */
@ -186,20 +157,17 @@ abstract class XApiActivityHookObserver extends HookObserver
} }
/** /**
* Serialize a statement to JSON.
*
* @param \Xabbuh\XApi\Model\Statement $statement * @param \Xabbuh\XApi\Model\Statement $statement
* *
* @return bool * @return string
*/ */
protected function isStatementAlreadySent(Statement $statement) private function serializeStatement(Statement $statement)
{ {
$sharedStmt = Database::getManager() $serializer = Serializer::createSerializer();
->getRepository(SharedStatement::class) $statementSerializer = new StatementSerializer($serializer);
->findOneByUuid($statement->getId()->getValue());
if ($sharedStmt) {
return true;
}
return false; return $statementSerializer->serializeStatement($statement);
} }
} }

@ -41,17 +41,11 @@ class XApiLearningPathEndHookObserver extends XApiActivityHookObserver implement
try { try {
$statement = $this->createStatement(); $statement = $this->createStatement();
$sharedStmt = $this->sendStatementToLrs($statement);
$this->saveSharedStatement(
$sharedStmt->getId(),
XApiPlugin::DATA_TYPE_LP_VIEW,
$this->lpView->getId()
);
} catch (Exception $e) { } catch (Exception $e) {
return; return;
} }
$this->saveSharedStatement($statement);
} }
/** /**

@ -53,18 +53,11 @@ class XApiLearningPathItemViewedHookObserver
try { try {
$statement = $this->createStatement(); $statement = $this->createStatement();
$sharedStmt = $this->sendStatementToLrs($statement);
$this->saveSharedStatement(
$sharedStmt->getId(),
XApiPlugin::DATA_TYPE_LP_ITEM_VIEW,
$this->lpItemView->getId()
);
} catch (Exception $e) { } catch (Exception $e) {
return; return;
} }
$this->saveSharedStatement($statement);
} }
/** /**

@ -40,19 +40,14 @@ class XApiQuizEndHookObserver extends XApiActivityHookObserver implements HookQu
$this->session = api_get_session_entity($this->exe->getSessionId()); $this->session = api_get_session_entity($this->exe->getSessionId());
try { try {
$statement = $this->createStatement(); $statement = $this->createStatement(
$this->exe->getExeDate()
$sharedStmt = $this->sendStatementToLrs($statement);
$this->saveSharedStatement(
$sharedStmt->getId(),
XApiPlugin::DATA_TYPE_EXERCISE,
$this->exe->getExeId()
); );
} catch (Exception $e) { } catch (Exception $e) {
return; return;
} }
$this->saveSharedStatement($statement);
} }
/** /**

@ -63,22 +63,14 @@ class XApiQuizQuestionAnsweredHookObserver
$this->session = api_get_session_entity($this->exe->getSessionId()); $this->session = api_get_session_entity($this->exe->getSessionId());
try { try {
$statement = $this $statement = $this->createStatement(
->createStatement()
->withCreated(
$this->attempt->getTms() $this->attempt->getTms()
); );
$sharedStmt = $this->sendStatementToLrs($statement);
$this->saveSharedStatement(
$sharedStmt->getId(),
XApiPlugin::DATA_TYPE_ATTEMPT,
$this->attempt->getId()
);
} catch (Exception $e) { } catch (Exception $e) {
return; return;
} }
$this->saveSharedStatement($statement);
} }
/** /**

Loading…
Cancel
Save