Skip to content

Commit

Permalink
XAPI: Start statements api - refs BT#16742
Browse files Browse the repository at this point in the history
  • Loading branch information
AngelFQC committed Nov 27, 2020
1 parent 5038d0c commit b661dbe
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 0 deletions.
11 changes: 11 additions & 0 deletions plugin/xapi/lrs.php
@@ -0,0 +1,11 @@
<?php
/* For licensing terms, see /license.txt */

use Chamilo\PluginBundle\XApi\Lrs\LrsRequest;

$cidReset = true;

require_once __DIR__.'/../../main/inc/global.inc.php';

$lrsRequest = new LrsRequest();
$lrsRequest->send();
27 changes: 27 additions & 0 deletions plugin/xapi/src/Lrs/BaseController.php
@@ -0,0 +1,27 @@
<?php
/* For licensing terms, see /license.txt */

namespace Chamilo\PluginBundle\XApi\Lrs;

use Symfony\Component\HttpFoundation\Request;

/**
* Class BaseController.
*
* @package Chamilo\PluginBundle\XApi\Lrs
*/
abstract class BaseController
{
/**
* @var \Symfony\Component\HttpFoundation\Request
*/
protected $httpRequest;

/**
* BaseController constructor.
*/
public function __construct()
{
$this->httpRequest = Request::createFromGlobals();
}
}
103 changes: 103 additions & 0 deletions plugin/xapi/src/Lrs/LrsRequest.php
@@ -0,0 +1,103 @@
<?php
/* For licensing terms, see /license.txt */

namespace Chamilo\PluginBundle\XApi\Lrs;

use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Symfony\Component\HttpFoundation\Response as HttpResponse;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

/**
* Class LrsRequest.
*
* @package Chamilo\PluginBundle\XApi\Lrs
*/
class LrsRequest
{
/**
* @var HttpRequest
*/
private $request;

/**
* LrsRequest constructor.
*/
public function __construct()
{
$this->request = HttpRequest::createFromGlobals();
}

public function send()
{
$version = $this->request->headers->get('X-Experience-API-Version');

if (null === $version) {
throw new BadRequestHttpException('The "X-Experience-API-Version" header is required.');
}

if (!$this->isValidVersion($version)) {
throw new BadRequestHttpException("The xAPI version \"$version\" is not supported.");
}

$controllerName = $this->getControllerName();
$methodName = $this->getMethodName();

if ($controllerName
&& class_exists($controllerName)
&& method_exists($controllerName, $methodName)
) {
/** @var HttpResponse $response */
$response = call_user_func([new $controllerName, $methodName]);
} else {
$response = HttpResponse::create('Not Found', HttpResponse::HTTP_NOT_FOUND);
}

$response->headers->set('X-Experience-API-Version', '1.0.3');

$response->send();
}

/**
* @return string|null
*/
private function getControllerName()
{
$segments = explode('/', $this->request->getPathInfo());

if (empty($segments[1])) {
return null;
}

$controllerName = ucfirst($segments[1]).'Controller';

return "Chamilo\\PluginBundle\\XApi\Lrs\\$controllerName";
}

/**
* @return string
*/
private function getMethodName()
{
$method = $this->request->getMethod();

return strtolower($method);
}

/**
* @param string $version
*
* @return bool
*/
private function isValidVersion($version)
{
if (preg_match('/^1\.0(?:\.\d+)?$/', $version)) {
if ('1.0' === $version) {
$this->request->headers->set('X-Experience-API-Version', '1.0.0');
}

return true;
}

return false;
}
}
78 changes: 78 additions & 0 deletions plugin/xapi/src/Lrs/StatementsController.php
@@ -0,0 +1,78 @@
<?php
/* For licensing terms, see /license.txt */

namespace Chamilo\PluginBundle\XApi\Lrs;

use Chamilo\PluginBundle\Entity\XApi\Statement as StatementEntity;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
use Xabbuh\XApi\Model\Statement;
use Xabbuh\XApi\Model\StatementId;
use Xabbuh\XApi\Serializer\Symfony\Serializer;

/**
* Class StatementsController.
*
* @package Chamilo\PluginBundle\XApi\Lrs
*/
class StatementsController extends BaseController
{
/**
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
* @throws \Doctrine\ORM\TransactionRequiredException
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function put()
{
$request = $this->httpRequest;

if (null === $request->query->get('statementId')) {
throw new BadRequestHttpException('Required statementId parameter is missing.');
}

$statementId = $request->query->get('statementId');
$id = StatementId::fromString($statementId);

$statement = $this->deserializeStatement(
$this->httpRequest->getContent()
);

if (null !== $statement->getId() && !$id->equals($statement->getId())) {
throw new ConflictHttpException(
"Id parameter ({$id->getValue()}) and statement id ({$statement->getId()->getValue()}) do not match."
);
}

$em = \Database::getManager();

$existingStatement = $em->find(StatementEntity::class, $id->getValue());

if ($existingStatement && !$existingStatement->equals($statement)) {
throw new ConflictHttpException('The new statement is not equal to an existing statement with the same id.');
}

$em->persist(StatementEntity::fromModel($statement));
$em->flush();

return JsonResponse::create(
null,
Response::HTTP_NO_CONTENT
);
}

/**
* @param string $content
*
* @return \Xabbuh\XApi\Model\Statement
*/
private function deserializeStatement($content)
{
$serializer = Serializer::createSerializer();

return $serializer->deserialize($content, Statement::class, 'json');
}
}

0 comments on commit b661dbe

Please sign in to comment.