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. 94
      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. 16
      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(
* name="xapi_shared_statement",
* indexes={
* @ORM\Index(name="idx_datatype_dataid", columns={"data_type", "data_id"})
* },
* uniqueConstraints={
* @ORM\UniqueConstraint(name="idx_uuid", columns={"uuid"})
* @ORM\Index(name="idx_uuid", columns={"uuid"})
* }
* )
* @ORM\Entity()
@ -33,58 +30,60 @@ class SharedStatement
*/
private $id;
/**
* @var string
* @var string|null
*
* @ORM\Column(name="uuid", type="string")
* @ORM\Column(name="uuid", type="string", nullable=true)
*/
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 SharedStatement
* @return int
*/
public function setId($id)
public function getId(): int
{
$this->id = $id;
return $this;
return $this->id;
}
/**
* @return string
* @return string|null
*/
public function getUuid()
public function getUuid(): ?string
{
return $this->uuid;
}
/**
* @param string $uuid
* @param string|null $uuid
*
* @return SharedStatement
*/
public function setUuid($uuid)
public function setUuid(?string $uuid): SharedStatement
{
$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
*/
public function setDataType($dataType)
public function setStatement(array $statement): SharedStatement
{
$this->dataType = $dataType;
$this->statement = $statement;
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
*/
public function setDataId($dataId)
public function setSent(bool $sent): SharedStatement
{
$this->dataId = $dataId;
$this->sent = $sent;
return $this;
}

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

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

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

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

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

Loading…
Cancel
Save