From b661dbe42cbc8af5a91e5bd62ca02e9179cbe9df Mon Sep 17 00:00:00 2001 From: Angel Fernando Quiroz Campos Date: Thu, 19 Nov 2020 03:36:29 -0500 Subject: [PATCH] XAPI: Start statements api - refs BT#16742 --- plugin/xapi/lrs.php | 11 ++ plugin/xapi/src/Lrs/BaseController.php | 27 +++++ plugin/xapi/src/Lrs/LrsRequest.php | 103 +++++++++++++++++++ plugin/xapi/src/Lrs/StatementsController.php | 78 ++++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 plugin/xapi/lrs.php create mode 100644 plugin/xapi/src/Lrs/BaseController.php create mode 100644 plugin/xapi/src/Lrs/LrsRequest.php create mode 100644 plugin/xapi/src/Lrs/StatementsController.php diff --git a/plugin/xapi/lrs.php b/plugin/xapi/lrs.php new file mode 100644 index 0000000000..72ced517b0 --- /dev/null +++ b/plugin/xapi/lrs.php @@ -0,0 +1,11 @@ +send(); diff --git a/plugin/xapi/src/Lrs/BaseController.php b/plugin/xapi/src/Lrs/BaseController.php new file mode 100644 index 0000000000..684528fba0 --- /dev/null +++ b/plugin/xapi/src/Lrs/BaseController.php @@ -0,0 +1,27 @@ +httpRequest = Request::createFromGlobals(); + } +} diff --git a/plugin/xapi/src/Lrs/LrsRequest.php b/plugin/xapi/src/Lrs/LrsRequest.php new file mode 100644 index 0000000000..bcaf1a914f --- /dev/null +++ b/plugin/xapi/src/Lrs/LrsRequest.php @@ -0,0 +1,103 @@ +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; + } +} diff --git a/plugin/xapi/src/Lrs/StatementsController.php b/plugin/xapi/src/Lrs/StatementsController.php new file mode 100644 index 0000000000..611b9862c2 --- /dev/null +++ b/plugin/xapi/src/Lrs/StatementsController.php @@ -0,0 +1,78 @@ +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'); + } +}