parent
							
								
									fe334b013b
								
							
						
					
					
						commit
						e48dc568ac
					
				@ -1,4 +1,4 @@ | 
				
			||||
Copyright (c) 2014-2017 Christian Flothmann | 
				
			||||
Copyright (c) 2016-2017 Christian Flothmann | 
				
			||||
 | 
				
			||||
Permission is hereby granted, free of charge, to any person obtaining a copy | 
				
			||||
of this software and associated documentation files (the "Software"), to deal | 
				
			||||
@ -0,0 +1,51 @@ | 
				
			||||
{ | 
				
			||||
    "name": "php-xapi/lrs-bundle", | 
				
			||||
    "type": "symfony-bundle", | 
				
			||||
    "description": "Experience API (xAPI) Learning Record Store (LRS) based on the Symfony Framework", | 
				
			||||
    "keywords": ["xAPI", "Experience API", "Tin Can API", "LRS", "Learning Record Store", "Symfony", "bundle"], | 
				
			||||
    "homepage": "https://github.com/php-xapi/lrs-bundle", | 
				
			||||
    "license": "MIT", | 
				
			||||
    "authors": [ | 
				
			||||
        { | 
				
			||||
            "name": "Christian Flothmann", | 
				
			||||
            "homepage": "https://github.com/xabbuh" | 
				
			||||
        }, | 
				
			||||
        { | 
				
			||||
            "name": "Jérôme Parmentier", | 
				
			||||
            "homepage": "https://github.com/Lctrs" | 
				
			||||
        } | 
				
			||||
    ], | 
				
			||||
    "require": { | 
				
			||||
        "php": "^7.1", | 
				
			||||
        "php-xapi/exception": "^0.1 || ^0.2", | 
				
			||||
        "php-xapi/model": "^1.1 || ^2.0 || ^3.0", | 
				
			||||
        "php-xapi/repository-api": "^0.3@dev || ^0.4@dev", | 
				
			||||
        "php-xapi/serializer": "^1.0 || ^2.0", | 
				
			||||
        "php-xapi/symfony-serializer": "^1.0 || ^2.0", | 
				
			||||
        "symfony/config": "^3.4 || ^4.3", | 
				
			||||
        "symfony/dependency-injection": "^3.4 || ^4.3", | 
				
			||||
        "symfony/http-foundation": "^3.4 || ^4.3", | 
				
			||||
        "symfony/http-kernel": "^3.4 || ^4.3" | 
				
			||||
    }, | 
				
			||||
    "require-dev": { | 
				
			||||
        "phpspec/phpspec": "~2.3", | 
				
			||||
        "php-xapi/json-test-fixtures": "^1.0 || ^2.0", | 
				
			||||
        "php-xapi/test-fixtures": "^1.0.1", | 
				
			||||
        "ramsey/uuid": "^2.9 || ^3.0" | 
				
			||||
    }, | 
				
			||||
    "autoload": { | 
				
			||||
        "psr-4": { | 
				
			||||
            "XApi\\LrsBundle\\": "src/" | 
				
			||||
        } | 
				
			||||
    }, | 
				
			||||
    "autoload-dev": { | 
				
			||||
        "psr-4": { | 
				
			||||
            "spec\\XApi\\LrsBundle\\": "spec/" | 
				
			||||
        } | 
				
			||||
    }, | 
				
			||||
    "extra": { | 
				
			||||
        "branch-alias": { | 
				
			||||
            "dev-master": "0.1.x-dev" | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,4 @@ | 
				
			||||
suites: | 
				
			||||
  default: | 
				
			||||
    namespace: XApi\LrsBundle | 
				
			||||
    psr4_prefix: XApi\LrsBundle | 
				
			||||
@ -0,0 +1,197 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace spec\XApi\LrsBundle\Controller; | 
				
			||||
 | 
				
			||||
use PhpSpec\ObjectBehavior; | 
				
			||||
use Prophecy\Argument; | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag; | 
				
			||||
use Xabbuh\XApi\Common\Exception\NotFoundException; | 
				
			||||
use Xabbuh\XApi\DataFixtures\StatementFixtures; | 
				
			||||
use Xabbuh\XApi\Model\StatementId; | 
				
			||||
use Xabbuh\XApi\Model\StatementResult; | 
				
			||||
use Xabbuh\XApi\Model\StatementsFilter; | 
				
			||||
use Xabbuh\XApi\Serializer\StatementResultSerializerInterface; | 
				
			||||
use Xabbuh\XApi\Serializer\StatementSerializerInterface; | 
				
			||||
use XApi\Fixtures\Json\StatementJsonFixtures; | 
				
			||||
use XApi\Fixtures\Json\StatementResultJsonFixtures; | 
				
			||||
use XApi\LrsBundle\Model\StatementsFilterFactory; | 
				
			||||
use XApi\Repository\Api\StatementRepositoryInterface; | 
				
			||||
 | 
				
			||||
class StatementGetControllerSpec extends ObjectBehavior | 
				
			||||
{ | 
				
			||||
    function let(StatementRepositoryInterface $repository, StatementSerializerInterface $statementSerializer, StatementResultSerializerInterface $statementResultSerializer, StatementsFilterFactory $statementsFilterFactory) | 
				
			||||
    { | 
				
			||||
        $statement = StatementFixtures::getAllPropertiesStatement(); | 
				
			||||
        $voidedStatement = StatementFixtures::getVoidingStatement()->withStored(new \DateTime()); | 
				
			||||
        $statementCollection = StatementFixtures::getStatementCollection(); | 
				
			||||
        $statementsFilter = new StatementsFilter(); | 
				
			||||
 | 
				
			||||
        $statementsFilterFactory->createFromParameterBag(Argument::type('\Symfony\Component\HttpFoundation\ParameterBag'))->willReturn($statementsFilter); | 
				
			||||
 | 
				
			||||
        $repository->findStatementById(StatementId::fromString(StatementFixtures::DEFAULT_STATEMENT_ID))->willReturn($statement); | 
				
			||||
        $repository->findVoidedStatementById(StatementId::fromString(StatementFixtures::DEFAULT_STATEMENT_ID))->willReturn($voidedStatement); | 
				
			||||
        $repository->findStatementsBy($statementsFilter)->willReturn($statementCollection); | 
				
			||||
 | 
				
			||||
        $statementSerializer->serializeStatement(Argument::type('\Xabbuh\XApi\Model\Statement'))->willReturn(StatementJsonFixtures::getTypicalStatement()); | 
				
			||||
 | 
				
			||||
        $statementResultSerializer->serializeStatementResult(Argument::type('\Xabbuh\XApi\Model\StatementResult'))->willReturn(StatementResultJsonFixtures::getStatementResult()); | 
				
			||||
 | 
				
			||||
        $this->beConstructedWith($repository, $statementSerializer, $statementResultSerializer, $statementsFilterFactory); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_badrequesthttpexception_if_the_request_has_given_statement_id_and_voided_statement_id() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
        $request->query->set('voidedStatementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\Symfony\Component\HttpKernel\Exception\BadRequestHttpException') | 
				
			||||
            ->during('getStatement', array($request)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_badrequesthttpexception_if_the_request_has_statement_id_and_format_and_attachements_and_any_other_parameters() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
        $request->query->set('format', 'ids'); | 
				
			||||
        $request->query->set('attachments', false); | 
				
			||||
        $request->query->set('related_agents', false); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\Symfony\Component\HttpKernel\Exception\BadRequestHttpException') | 
				
			||||
            ->during('getStatement', array($request)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_badrequesthttpexception_if_the_request_has_voided_statement_id_and_format_and_any_other_parameters_except_attachments() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('voidedStatementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
        $request->query->set('format', 'ids'); | 
				
			||||
        $request->query->set('related_agents', false); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\Symfony\Component\HttpKernel\Exception\BadRequestHttpException') | 
				
			||||
            ->during('getStatement', array($request)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_badrequesthttpexception_if_the_request_has_statement_id_and_attachments_and_any_other_parameters_except_format() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
        $request->query->set('attachments', false); | 
				
			||||
        $request->query->set('related_agents', false); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\Symfony\Component\HttpKernel\Exception\BadRequestHttpException') | 
				
			||||
            ->during('getStatement', array($request)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_badrequesthttpexception_if_the_request_has_voided_statement_id_and_any_other_parameters_except_format_and_attachments() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('voidedStatementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
        $request->query->set('related_agents', false); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\Symfony\Component\HttpKernel\Exception\BadRequestHttpException') | 
				
			||||
            ->during('getStatement', array($request)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_a_X_Experience_API_Consistent_Through_header_to_the_response() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
 | 
				
			||||
        $response = $this->getStatement($request); | 
				
			||||
 | 
				
			||||
        /** @var ResponseHeaderBag $headers */ | 
				
			||||
        $headers = $response->headers; | 
				
			||||
 | 
				
			||||
        $headers->has('X-Experience-API-Consistent-Through')->shouldBe(true); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_includes_a_Last_Modified_Header_if_a_single_statement_is_fetched() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
 | 
				
			||||
        $response = $this->getStatement($request); | 
				
			||||
 | 
				
			||||
        /** @var ResponseHeaderBag $headers */ | 
				
			||||
        $headers = $response->headers; | 
				
			||||
 | 
				
			||||
        $headers->has('Last-Modified')->shouldBe(true); | 
				
			||||
 | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('voidedStatementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
 | 
				
			||||
        $response = $this->getStatement($request); | 
				
			||||
 | 
				
			||||
        /** @var ResponseHeaderBag $headers */ | 
				
			||||
        $headers = $response->headers; | 
				
			||||
 | 
				
			||||
        $headers->has('Last-Modified')->shouldBe(true); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_returns_a_multipart_response_if_attachments_parameter_is_true() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('attachments', true); | 
				
			||||
 | 
				
			||||
        $this->getStatement($request)->shouldReturnAnInstanceOf('XApi\LrsBundle\Response\MultipartResponse'); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_returns_a_jsonresponse_if_attachments_parameter_is_false_or_not_set() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
 | 
				
			||||
        $this->getStatement($request)->shouldReturnAnInstanceOf('\Symfony\Component\HttpFoundation\JsonResponse'); | 
				
			||||
 | 
				
			||||
        $request->query->set('attachments', false); | 
				
			||||
 | 
				
			||||
        $this->getStatement($request)->shouldReturnAnInstanceOf('\Symfony\Component\HttpFoundation\JsonResponse'); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_fetch_a_statement(StatementRepositoryInterface $repository) | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
 | 
				
			||||
        $repository->findStatementById(StatementId::fromString(StatementFixtures::DEFAULT_STATEMENT_ID))->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $this->getStatement($request); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_fetch_a_voided_statement_id(StatementRepositoryInterface $repository) | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('voidedStatementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
 | 
				
			||||
        $repository->findVoidedStatementById(StatementId::fromString(StatementFixtures::DEFAULT_STATEMENT_ID))->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $this->getStatement($request); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_filter_all_statements_if_no_statement_id_or_voided_statement_id_is_provided(StatementRepositoryInterface $repository) | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
 | 
				
			||||
        $repository->findStatementsBy(Argument::type('\Xabbuh\XApi\Model\StatementsFilter'))->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $this->getStatement($request); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_build_an_empty_statement_result_response_if_no_statement_is_found(StatementRepositoryInterface $repository, StatementResultSerializerInterface $statementResultSerializer) | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', StatementFixtures::DEFAULT_STATEMENT_ID); | 
				
			||||
 | 
				
			||||
        $repository->findStatementById(StatementId::fromString(StatementFixtures::DEFAULT_STATEMENT_ID))->willThrow('\Xabbuh\XApi\Common\Exception\NotFoundException'); | 
				
			||||
 | 
				
			||||
        $statementResultSerializer->serializeStatementResult(new StatementResult(array()))->shouldBeCalled()->willReturn(StatementResultJsonFixtures::getStatementResult()); | 
				
			||||
 | 
				
			||||
        $this->getStatement($request); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,106 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace spec\XApi\LrsBundle\Controller; | 
				
			||||
 | 
				
			||||
use PhpSpec\ObjectBehavior; | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
use Xabbuh\XApi\Common\Exception\NotFoundException; | 
				
			||||
use Xabbuh\XApi\DataFixtures\StatementFixtures; | 
				
			||||
use Xabbuh\XApi\Model\StatementId; | 
				
			||||
use XApi\Repository\Api\StatementRepositoryInterface; | 
				
			||||
 | 
				
			||||
class StatementPutControllerSpec extends ObjectBehavior | 
				
			||||
{ | 
				
			||||
    function let(StatementRepositoryInterface $repository) | 
				
			||||
    { | 
				
			||||
        $this->beConstructedWith($repository); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_badrequesthttpexception_if_a_statement_id_is_not_part_of_a_put_request() | 
				
			||||
    { | 
				
			||||
        $statement = StatementFixtures::getTypicalStatement(); | 
				
			||||
        $request = new Request(); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\Symfony\Component\HttpKernel\Exception\BadRequestHttpException') | 
				
			||||
            ->during('putStatement', array($request, $statement)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_badrequesthttpexception_if_the_given_statement_id_as_part_of_a_put_request_is_not_a_valid_uuid() | 
				
			||||
    { | 
				
			||||
        $statement = StatementFixtures::getTypicalStatement(); | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', 'invalid-uuid'); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\Symfony\Component\HttpKernel\Exception\BadRequestHttpException') | 
				
			||||
            ->during('putStatement', array($request, $statement)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_stores_a_statement_and_returns_a_204_response_if_the_statement_did_not_exist_before(StatementRepositoryInterface $repository) | 
				
			||||
    { | 
				
			||||
        $statement = StatementFixtures::getTypicalStatement(); | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', $statement->getId()->getValue()); | 
				
			||||
 | 
				
			||||
        $repository->findStatementById($statement->getId())->willThrow(new NotFoundException('')); | 
				
			||||
        $repository->storeStatement($statement, true)->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $response = $this->putStatement($request, $statement); | 
				
			||||
 | 
				
			||||
        $response->shouldHaveType('Symfony\Component\HttpFoundation\Response'); | 
				
			||||
        $response->getStatusCode()->shouldReturn(204); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_conflicthttpexception_if_the_id_parameter_and_the_statement_id_do_not_match_during_a_put_request() | 
				
			||||
    { | 
				
			||||
        $statement = StatementFixtures::getTypicalStatement(); | 
				
			||||
        $statementId = StatementId::fromString('39e24cc4-69af-4b01-a824-1fdc6ea8a3af'); | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', $statementId->getValue()); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\Symfony\Component\HttpKernel\Exception\ConflictHttpException') | 
				
			||||
            ->during('putStatement', array($request, $statement)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_uses_id_parameter_in_put_request_if_statement_id_is_null(StatementRepositoryInterface $repository) | 
				
			||||
    { | 
				
			||||
        $statement = StatementFixtures::getTypicalStatement(); | 
				
			||||
        $statementId = $statement->getId(); | 
				
			||||
        $statement = $statement->withId(null); | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', $statementId->getValue()); | 
				
			||||
 | 
				
			||||
        $repository->findStatementById($statementId)->willReturn($statement); | 
				
			||||
        $repository->findStatementById($statementId)->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $this->putStatement($request, $statement); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_does_not_override_an_existing_statement(StatementRepositoryInterface $repository) | 
				
			||||
    { | 
				
			||||
        $statement = StatementFixtures::getTypicalStatement(); | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', $statement->getId()->getValue()); | 
				
			||||
 | 
				
			||||
        $repository->findStatementById($statement->getId())->willReturn($statement); | 
				
			||||
        $repository->storeStatement($statement, true)->shouldNotBeCalled(); | 
				
			||||
 | 
				
			||||
        $this->putStatement($request, $statement); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_conflicthttpexception_if_an_existing_statement_with_the_same_id_is_not_equal_during_a_put_request(StatementRepositoryInterface $repository) | 
				
			||||
    { | 
				
			||||
        $statement = StatementFixtures::getTypicalStatement(); | 
				
			||||
        $existingStatement = StatementFixtures::getAttachmentStatement()->withId($statement->getId()); | 
				
			||||
        $request = new Request(); | 
				
			||||
        $request->query->set('statementId', $statement->getId()->getValue()); | 
				
			||||
 | 
				
			||||
        $repository->findStatementById($statement->getId())->willReturn($existingStatement); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\Symfony\Component\HttpKernel\Exception\ConflictHttpException') | 
				
			||||
            ->during('putStatement', array($request, $statement)); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,18 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace spec\XApi\LrsBundle\DependencyInjection; | 
				
			||||
 | 
				
			||||
use PhpSpec\ObjectBehavior; | 
				
			||||
 | 
				
			||||
class XApiLrsExtensionSpec extends ObjectBehavior | 
				
			||||
{ | 
				
			||||
    function it_is_a_di_extension() | 
				
			||||
    { | 
				
			||||
        $this->shouldHaveType('Symfony\Component\DependencyInjection\Extension\ExtensionInterface'); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function its_alias_is_xapi_lrs() | 
				
			||||
    { | 
				
			||||
        $this->getAlias()->shouldReturn('xapi_lrs'); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,160 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace spec\XApi\LrsBundle\EventListener; | 
				
			||||
 | 
				
			||||
use PhpSpec\ObjectBehavior; | 
				
			||||
use Symfony\Component\HttpFoundation\FileBag; | 
				
			||||
use Symfony\Component\HttpFoundation\HeaderBag; | 
				
			||||
use Symfony\Component\HttpFoundation\ParameterBag; | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
use Symfony\Component\HttpFoundation\ServerBag; | 
				
			||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent; | 
				
			||||
 | 
				
			||||
class AlternateRequestSyntaxListenerSpec extends ObjectBehavior | 
				
			||||
{ | 
				
			||||
    function let(GetResponseEvent $event, Request $request, ParameterBag $query, ParameterBag $post, ParameterBag $attributes, HeaderBag $headers) | 
				
			||||
    { | 
				
			||||
        $query->count()->willReturn(1); | 
				
			||||
        $query->get('method')->willReturn('GET'); | 
				
			||||
 | 
				
			||||
        $post->getIterator()->willReturn(new \ArrayIterator()); | 
				
			||||
        $post->get('content')->willReturn(null); | 
				
			||||
 | 
				
			||||
        $attributes->has('xapi_lrs.route')->willReturn(true); | 
				
			||||
 | 
				
			||||
        $request->query = $query; | 
				
			||||
        $request->request = $post; | 
				
			||||
        $request->attributes = $attributes; | 
				
			||||
        $request->headers = $headers; | 
				
			||||
        $request->getMethod()->willReturn('POST'); | 
				
			||||
 | 
				
			||||
        $event->isMasterRequest()->willReturn(true); | 
				
			||||
        $event->getRequest()->willReturn($request); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_returns_null_if_request_is_not_master(GetResponseEvent $event) | 
				
			||||
    { | 
				
			||||
        $event->isMasterRequest()->willReturn(false); | 
				
			||||
        $event->getRequest()->shouldNotBeCalled(); | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($event)->shouldReturn(null); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_returns_null_if_request_has_no_attribute_xapi_lrs_route(GetResponseEvent $event, ParameterBag $attributes) | 
				
			||||
    { | 
				
			||||
        $attributes->has('xapi_lrs.route')->shouldBeCalled()->willReturn(false); | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($event)->shouldReturn(null); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_returns_null_if_request_method_is_get(GetResponseEvent $event, Request $request, ParameterBag $query) | 
				
			||||
    { | 
				
			||||
        $query->get('method')->shouldNotBeCalled(); | 
				
			||||
        $request->getMethod()->willReturn('GET'); | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($event)->shouldReturn(null); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_returns_null_if_request_method_is_put(GetResponseEvent $event, Request $request, ParameterBag $query) | 
				
			||||
    { | 
				
			||||
        $query->get('method')->shouldNotBeCalled(); | 
				
			||||
        $request->getMethod()->willReturn('PUT'); | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($event)->shouldReturn(null); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_badrequesthttpexception_if_other_query_parameter_than_method_is_set(GetResponseEvent $event, ParameterBag $query) | 
				
			||||
    { | 
				
			||||
        $query->count()->shouldBeCalled()->willReturn(2); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\Symfony\Component\HttpKernel\Exception\BadRequestHttpException') | 
				
			||||
            ->during('onKernelRequest', array($event)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_the_request_method_equals_to_method_query_parameter(GetResponseEvent $event, Request $request, ParameterBag $query) | 
				
			||||
    { | 
				
			||||
        $query->remove('method')->shouldBeCalled(); | 
				
			||||
        $request->setMethod('GET')->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($event); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_defined_post_parameters_as_header(GetResponseEvent $event, Request $request, ParameterBag $query, ParameterBag $post, HeaderBag $headers) | 
				
			||||
    { | 
				
			||||
        $request->setMethod('GET')->shouldBeCalled(); | 
				
			||||
        $query->remove('method')->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $headerList = array( | 
				
			||||
            'Authorization' => 'Authorization', | 
				
			||||
            'X-Experience-API-Version' => 'X-Experience-API-Version', | 
				
			||||
            'Content-Type' => 'Content-Type', | 
				
			||||
            'Content-Length' => 'Content-Length', | 
				
			||||
            'If-Match' => 'If-Match', | 
				
			||||
            'If-None-Match' => 'If-None-Match', | 
				
			||||
        ); | 
				
			||||
 | 
				
			||||
        $post->getIterator()->shouldBeCalled()->willReturn(new \ArrayIterator($headerList)); | 
				
			||||
 | 
				
			||||
        foreach ($headerList as $key => $value) { | 
				
			||||
            $post->remove($key)->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
            $headers->set($key, $value)->shouldBeCalled(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($event); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_other_post_parameters_as_query_parameters(GetResponseEvent $event, Request $request, ParameterBag $query, ParameterBag $post) | 
				
			||||
    { | 
				
			||||
        $request->setMethod('GET')->shouldBeCalled(); | 
				
			||||
        $query->remove('method')->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $parameterList = array( | 
				
			||||
            'token' => 'a-token', | 
				
			||||
            'attachments' => true, | 
				
			||||
        ); | 
				
			||||
 | 
				
			||||
        $post->getIterator()->shouldBeCalled()->willReturn(new \ArrayIterator($parameterList)); | 
				
			||||
 | 
				
			||||
        foreach ($parameterList as $key => $value) { | 
				
			||||
            $post->remove($key)->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
            $query->set($key, $value)->shouldBeCalled(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($event); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_content_from_post_parameters(GetResponseEvent $event, Request $request, ParameterBag $query, ParameterBag $post, ParameterBag $attributes, ParameterBag $cookies, FileBag $files, ServerBag $server) | 
				
			||||
    { | 
				
			||||
        $query->all()->shouldBeCalled()->willReturn(array()); | 
				
			||||
        $query->remove('method')->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $post->all()->shouldBeCalled()->willReturn(array()); | 
				
			||||
        $post->get('content')->shouldBeCalled()->willReturn('a content'); | 
				
			||||
        $post->remove('content')->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $attributes->all()->shouldBeCalled()->willReturn(array()); | 
				
			||||
        $cookies->all()->shouldBeCalled()->willReturn(array()); | 
				
			||||
        $files->all()->shouldBeCalled()->willReturn(array()); | 
				
			||||
        $server->all()->shouldBeCalled()->willReturn(array()); | 
				
			||||
 | 
				
			||||
        $request->setMethod('GET')->shouldBeCalled(); | 
				
			||||
        $request->initialize( | 
				
			||||
            array(), | 
				
			||||
            array(), | 
				
			||||
            array(), | 
				
			||||
            array(), | 
				
			||||
            array(), | 
				
			||||
            array(), | 
				
			||||
            'a content' | 
				
			||||
        )->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $request->cookies = $cookies; | 
				
			||||
        $request->files = $files; | 
				
			||||
        $request->server = $server; | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($event); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,9 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace spec\XApi\LrsBundle\EventListener; | 
				
			||||
 | 
				
			||||
use PhpSpec\ObjectBehavior; | 
				
			||||
 | 
				
			||||
class ExceptionListenerSpec extends ObjectBehavior | 
				
			||||
{ | 
				
			||||
} | 
				
			||||
@ -0,0 +1,59 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace spec\XApi\LrsBundle\EventListener; | 
				
			||||
 | 
				
			||||
use PhpSpec\ObjectBehavior; | 
				
			||||
use Symfony\Component\HttpFoundation\ParameterBag; | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent; | 
				
			||||
use Xabbuh\XApi\Serializer\StatementSerializerInterface; | 
				
			||||
use XApi\Fixtures\Json\StatementJsonFixtures; | 
				
			||||
 | 
				
			||||
class SerializerListenerSpec extends ObjectBehavior | 
				
			||||
{ | 
				
			||||
    function let(StatementSerializerInterface $statementSerializer, GetResponseEvent $event, Request $request, ParameterBag $attributes) | 
				
			||||
    { | 
				
			||||
        $attributes->has('xapi_lrs.route')->willReturn(true); | 
				
			||||
 | 
				
			||||
        $request->attributes = $attributes; | 
				
			||||
 | 
				
			||||
        $event->getRequest()->willReturn($request); | 
				
			||||
 | 
				
			||||
        $this->beConstructedWith($statementSerializer); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_returns_null_if_request_has_no_attribute_xapi_lrs_route(GetResponseEvent $event, ParameterBag $attributes) | 
				
			||||
    { | 
				
			||||
        $attributes->has('xapi_lrs.route')->shouldBeCalled()->willReturn(false); | 
				
			||||
        $attributes->get('xapi_serializer')->shouldNotBeCalled(); | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($event)->shouldReturn(null); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_unserialized_data_as_request_attributes(StatementSerializerInterface $statementSerializer, GetResponseEvent $event, Request $request, ParameterBag $attributes) | 
				
			||||
    { | 
				
			||||
        $jsonString = StatementJsonFixtures::getTypicalStatement(); | 
				
			||||
 | 
				
			||||
        $statementSerializer->deserializeStatement($jsonString)->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $attributes->get('xapi_serializer')->willReturn('statement'); | 
				
			||||
        $attributes->set('statement', null)->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $request->getContent()->shouldBeCalled()->willReturn($jsonString); | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($event); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_badrequesthttpexception_if_the_serializer_fails(StatementSerializerInterface $statementSerializer, GetResponseEvent $event, Request $request, ParameterBag $attributes) | 
				
			||||
    { | 
				
			||||
        $statementSerializer->deserializeStatement(null)->shouldBeCalled()->willThrow('\Symfony\Component\Serializer\Exception\InvalidArgumentException'); | 
				
			||||
 | 
				
			||||
        $attributes->get('xapi_serializer')->willReturn('statement'); | 
				
			||||
 | 
				
			||||
        $request->attributes = $attributes; | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\Symfony\Component\HttpKernel\Exception\BadRequestHttpException') | 
				
			||||
            ->during('onKernelRequest', array($event)); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,102 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace spec\XApi\LrsBundle\EventListener; | 
				
			||||
 | 
				
			||||
use PhpSpec\ObjectBehavior; | 
				
			||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; | 
				
			||||
use Symfony\Component\HttpFoundation\HeaderBag; | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
use Symfony\Component\HttpFoundation\Response; | 
				
			||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent; | 
				
			||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent; | 
				
			||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; | 
				
			||||
 | 
				
			||||
class VersionListenerSpec extends ObjectBehavior | 
				
			||||
{ | 
				
			||||
    function let(GetResponseEvent $getResponseEvent, FilterResponseEvent $filterResponseEvent, Request $request, ParameterBag $attributes, HeaderBag $requestHeaders) | 
				
			||||
    { | 
				
			||||
        $attributes->has('xapi_lrs.route')->willReturn(true); | 
				
			||||
 | 
				
			||||
        $request->attributes = $attributes; | 
				
			||||
        $request->headers = $requestHeaders; | 
				
			||||
 | 
				
			||||
        $getResponseEvent->isMasterRequest()->willReturn(true); | 
				
			||||
        $getResponseEvent->getRequest()->willReturn($request); | 
				
			||||
 | 
				
			||||
        $filterResponseEvent->isMasterRequest()->willReturn(true); | 
				
			||||
        $filterResponseEvent->getRequest()->willReturn($request); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_returns_null_if_requests_are_not_master(GetResponseEvent $getResponseEvent, FilterResponseEvent $filterResponseEvent) | 
				
			||||
    { | 
				
			||||
        $getResponseEvent->isMasterRequest()->willReturn(false); | 
				
			||||
        $getResponseEvent->getRequest()->shouldNotBeCalled(); | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($getResponseEvent)->shouldReturn(null); | 
				
			||||
 | 
				
			||||
        $filterResponseEvent->isMasterRequest()->willReturn(false); | 
				
			||||
        $filterResponseEvent->getRequest()->shouldNotBeCalled(); | 
				
			||||
 | 
				
			||||
        $this->onKernelResponse($filterResponseEvent)->shouldReturn(null); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_returns_null_if_not_xapi_route(GetResponseEvent $getResponseEvent, FilterResponseEvent $filterResponseEvent, ParameterBag $attributes) | 
				
			||||
    { | 
				
			||||
        $attributes->has('xapi_lrs.route')->shouldBeCalled()->willReturn(false); | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($getResponseEvent)->shouldReturn(null); | 
				
			||||
 | 
				
			||||
        $this->onKernelResponse($filterResponseEvent)->shouldReturn(null); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_badrequesthttpexception_if_no_X_Experience_API_Version_header_is_set(GetResponseEvent $getResponseEvent, HeaderBag $requestHeaders) | 
				
			||||
    { | 
				
			||||
        $requestHeaders->get('X-Experience-API-Version')->shouldBeCalled()->willReturn(null); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow(new BadRequestHttpException('Missing required "X-Experience-API-Version" header.')) | 
				
			||||
            ->during('onKernelRequest', array($getResponseEvent)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_throws_a_badrequesthttpexception_if_specified_version_is_not_supported(GetResponseEvent $getResponseEvent, HeaderBag $requestHeaders) | 
				
			||||
    { | 
				
			||||
        $requestHeaders->get('X-Experience-API-Version')->shouldBeCalled()->willReturn('0.9.5'); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow(new BadRequestHttpException('xAPI version "0.9.5" is not supported.')) | 
				
			||||
            ->during('onKernelRequest', array($getResponseEvent)); | 
				
			||||
 | 
				
			||||
        $requestHeaders->get('X-Experience-API-Version')->shouldBeCalled()->willReturn('1.1.0'); | 
				
			||||
 | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow(new BadRequestHttpException('xAPI version "1.1.0" is not supported.')) | 
				
			||||
            ->during('onKernelRequest', array($getResponseEvent)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_normalizes_the_X_Experience_API_Version_header(GetResponseEvent $getResponseEvent, HeaderBag $requestHeaders) | 
				
			||||
    { | 
				
			||||
        $requestHeaders->get('X-Experience-API-Version')->shouldBeCalled()->willReturn('1.0'); | 
				
			||||
        $requestHeaders->set('X-Experience-API-Version', '1.0.0')->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($getResponseEvent); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_returns_null_if_version_is_supported(GetResponseEvent $getResponseEvent, HeaderBag $requestHeaders) | 
				
			||||
    { | 
				
			||||
        $requestHeaders->get('X-Experience-API-Version')->shouldBeCalled()->willReturn('1.0.0'); | 
				
			||||
 | 
				
			||||
        $this->onKernelRequest($getResponseEvent)->shouldReturn(null); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_a_X_Experience_API_Version_header_in_response(FilterResponseEvent $filterResponseEvent, Response $response, HeaderBag $responseHeaders) | 
				
			||||
    { | 
				
			||||
        $responseHeaders->has('X-Experience-API-Version')->shouldBeCalled()->willReturn(false); | 
				
			||||
        $responseHeaders->set('X-Experience-API-Version', '1.0.3')->shouldBeCalled(); | 
				
			||||
 | 
				
			||||
        $response->headers = $responseHeaders; | 
				
			||||
 | 
				
			||||
        $filterResponseEvent->getResponse()->shouldBeCalled()->willReturn($response); | 
				
			||||
 | 
				
			||||
        $this->onKernelResponse($filterResponseEvent); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,159 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace spec\XApi\LrsBundle\Model; | 
				
			||||
 | 
				
			||||
use PhpSpec\ObjectBehavior; | 
				
			||||
use Symfony\Component\HttpFoundation\ParameterBag; | 
				
			||||
use Xabbuh\XApi\DataFixtures\ActorFixtures; | 
				
			||||
use Xabbuh\XApi\DataFixtures\UuidFixtures; | 
				
			||||
use Xabbuh\XApi\Model\StatementsFilter; | 
				
			||||
use Xabbuh\XApi\Serializer\ActorSerializerInterface; | 
				
			||||
use XApi\Fixtures\Json\ActorJsonFixtures; | 
				
			||||
 | 
				
			||||
class StatementsFilterFactorySpec extends ObjectBehavior | 
				
			||||
{ | 
				
			||||
    function let(ActorSerializerInterface $actorSerializer) | 
				
			||||
    { | 
				
			||||
        $this->beConstructedWith($actorSerializer); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_default_filter_when_parameters_are_empty() | 
				
			||||
    { | 
				
			||||
        $filter = $this->createFromParameterBag(new ParameterBag())->getFilter(); | 
				
			||||
 | 
				
			||||
        $filter->shouldNotHaveKey('agent'); | 
				
			||||
        $filter->shouldNotHaveKey('verb'); | 
				
			||||
        $filter->shouldNotHaveKey('activity'); | 
				
			||||
        $filter->shouldNotHaveKey('registration'); | 
				
			||||
        $filter->shouldNotHaveKey('since'); | 
				
			||||
        $filter->shouldNotHaveKey('until'); | 
				
			||||
        $filter->shouldHaveKeyWithValue('related_activities', 'false'); | 
				
			||||
        $filter->shouldHaveKeyWithValue('related_agents', 'false'); | 
				
			||||
        $filter->shouldHaveKeyWithValue('ascending', 'false'); | 
				
			||||
        $filter->shouldHaveKeyWithValue('limit', 0); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_an_agent_filter(ActorSerializerInterface $actorSerializer) | 
				
			||||
    { | 
				
			||||
        $json = ActorJsonFixtures::getTypicalAgent(); | 
				
			||||
        $actor = ActorFixtures::getTypicalAgent(); | 
				
			||||
 | 
				
			||||
        $actorSerializer->deserializeActor($json)->shouldBeCalled()->willReturn($actor); | 
				
			||||
 | 
				
			||||
        $this->beConstructedWith($actorSerializer); | 
				
			||||
 | 
				
			||||
        $parameters = new ParameterBag(); | 
				
			||||
        $parameters->set('agent', $json); | 
				
			||||
 | 
				
			||||
        /** @var StatementsFilter $filter */ | 
				
			||||
        $filter = $this->createFromParameterBag($parameters); | 
				
			||||
 | 
				
			||||
        $filter->getFilter()->shouldHaveKeyWithValue('agent', $actor); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_a_verb_filter() | 
				
			||||
    { | 
				
			||||
        $verbId = 'http://tincanapi.com/conformancetest/verbid'; | 
				
			||||
        $parameters = new ParameterBag(); | 
				
			||||
        $parameters->set('verb', $verbId); | 
				
			||||
 | 
				
			||||
        /** @var StatementsFilter $filter */ | 
				
			||||
        $filter = $this->createFromParameterBag($parameters); | 
				
			||||
 | 
				
			||||
        $filter->getFilter()->shouldHaveKeyWithValue('verb', $verbId); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_an_activity_filter() | 
				
			||||
    { | 
				
			||||
        $activityId = 'http://tincanapi.com/conformancetest/activityid'; | 
				
			||||
        $parameters = new ParameterBag(); | 
				
			||||
        $parameters->set('activity', $activityId); | 
				
			||||
 | 
				
			||||
        /** @var StatementsFilter $filter */ | 
				
			||||
        $filter = $this->createFromParameterBag($parameters); | 
				
			||||
 | 
				
			||||
        $filter->getFilter()->shouldHaveKeyWithValue('activity', $activityId); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_a_registration_filter() | 
				
			||||
    { | 
				
			||||
        $registration = UuidFixtures::getGoodUuid(); | 
				
			||||
        $parameters = new ParameterBag(); | 
				
			||||
        $parameters->set('registration', $registration); | 
				
			||||
 | 
				
			||||
        /** @var StatementsFilter $filter */ | 
				
			||||
        $filter = $this->createFromParameterBag($parameters); | 
				
			||||
 | 
				
			||||
        $filter->getFilter()->shouldHaveKeyWithValue('registration', $registration); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_a_related_activities_filter() | 
				
			||||
    { | 
				
			||||
        $parameters = new ParameterBag(); | 
				
			||||
        $parameters->set('related_activities', true); | 
				
			||||
 | 
				
			||||
        /** @var StatementsFilter $filter */ | 
				
			||||
        $filter = $this->createFromParameterBag($parameters); | 
				
			||||
 | 
				
			||||
        $filter->getFilter()->shouldHaveKeyWithValue('related_activities', 'true'); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_a_related_agents_filter() | 
				
			||||
    { | 
				
			||||
        $parameters = new ParameterBag(); | 
				
			||||
        $parameters->set('related_agents', true); | 
				
			||||
 | 
				
			||||
        /** @var StatementsFilter $filter */ | 
				
			||||
        $filter = $this->createFromParameterBag($parameters); | 
				
			||||
 | 
				
			||||
        $filter->getFilter()->shouldHaveKeyWithValue('related_agents', 'true'); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_a_since_filter() | 
				
			||||
    { | 
				
			||||
        $now = new \DateTime(); | 
				
			||||
 | 
				
			||||
        $parameters = new ParameterBag(); | 
				
			||||
        $parameters->set('since', $now->format(\DateTime::ATOM)); | 
				
			||||
 | 
				
			||||
        /** @var StatementsFilter $filter */ | 
				
			||||
        $filter = $this->createFromParameterBag($parameters); | 
				
			||||
 | 
				
			||||
        $filter->getFilter()->shouldHaveKeyWithValue('since', $now->format('c')); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_an_until_filter() | 
				
			||||
    { | 
				
			||||
        $now = new \DateTime(); | 
				
			||||
 | 
				
			||||
        $parameters = new ParameterBag(); | 
				
			||||
        $parameters->set('until', $now->format(\DateTime::ATOM)); | 
				
			||||
 | 
				
			||||
        /** @var StatementsFilter $filter */ | 
				
			||||
        $filter = $this->createFromParameterBag($parameters); | 
				
			||||
 | 
				
			||||
        $filter->getFilter()->shouldHaveKeyWithValue('until', $now->format('c')); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_an_ascending_filter() | 
				
			||||
    { | 
				
			||||
        $parameters = new ParameterBag(); | 
				
			||||
        $parameters->set('ascending', true); | 
				
			||||
 | 
				
			||||
        /** @var StatementsFilter $filter */ | 
				
			||||
        $filter = $this->createFromParameterBag($parameters); | 
				
			||||
 | 
				
			||||
        $filter->getFilter()->shouldHaveKeyWithValue('ascending', 'true'); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_sets_a_limit_filter() | 
				
			||||
    { | 
				
			||||
        $parameters = new ParameterBag(); | 
				
			||||
        $parameters->set('limit', 10); | 
				
			||||
 | 
				
			||||
        /** @var StatementsFilter $filter */ | 
				
			||||
        $filter = $this->createFromParameterBag($parameters); | 
				
			||||
 | 
				
			||||
        $filter->getFilter()->shouldHaveKeyWithValue('limit', 10); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,69 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace spec\XApi\LrsBundle\Response; | 
				
			||||
 | 
				
			||||
use PhpSpec\ObjectBehavior; | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
use Xabbuh\XApi\DataFixtures\AttachmentFixtures; | 
				
			||||
use Xabbuh\XApi\Model\Attachment; | 
				
			||||
 | 
				
			||||
class AttachmentResponseSpec extends ObjectBehavior | 
				
			||||
{ | 
				
			||||
    /** | 
				
			||||
     * @var Attachment | 
				
			||||
     */ | 
				
			||||
    private $attachment; | 
				
			||||
 | 
				
			||||
    function let() | 
				
			||||
    { | 
				
			||||
        $this->attachment = AttachmentFixtures::getTextAttachment(); | 
				
			||||
 | 
				
			||||
        $this->beConstructedWith($this->attachment); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_throw_a_logicexception_when_sending_content() | 
				
			||||
    { | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\LogicException') | 
				
			||||
            ->during('sendContent'); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_throw_a_logicexception_when_setting_content() | 
				
			||||
    { | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\LogicException') | 
				
			||||
            ->during('setContent', array('a custom content')); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_return_content_of_the_attachment() | 
				
			||||
    { | 
				
			||||
        $this->getContent()->shouldBe($this->attachment->getContent()); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_set_Content_Type_header_equals_to_ContentType_property_of_attachment() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
 | 
				
			||||
        $this->prepare($request); | 
				
			||||
 | 
				
			||||
        $this->headers->get('Content-Type')->shouldBe($this->attachment->getContentType()); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_set_Content_Transfer_Encoding_header_equals_to_binary() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
 | 
				
			||||
        $this->prepare($request); | 
				
			||||
 | 
				
			||||
        $this->headers->get('Content-Transfer-Encoding')->shouldBe('binary'); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_set_X_Experience_API_Hash_header_equals_to_sha2_property_of_attachment() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
 | 
				
			||||
        $this->prepare($request); | 
				
			||||
 | 
				
			||||
        $this->headers->get('X-Experience-API-Hash')->shouldBe($this->attachment->getSha2()); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,31 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace spec\XApi\LrsBundle\Response; | 
				
			||||
 | 
				
			||||
use PhpSpec\ObjectBehavior; | 
				
			||||
use Symfony\Component\HttpFoundation\JsonResponse; | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
 | 
				
			||||
class MultipartResponseSpec extends ObjectBehavior | 
				
			||||
{ | 
				
			||||
    function let(JsonResponse $statementResponse) | 
				
			||||
    { | 
				
			||||
        $this->beConstructedWith($statementResponse); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_throw_a_logicexception_when_setting_content() | 
				
			||||
    { | 
				
			||||
        $this | 
				
			||||
            ->shouldThrow('\LogicException') | 
				
			||||
            ->during('setContent', array('a custom content')); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    function it_should_set_Content_Type_header_of_a_multipart_response() | 
				
			||||
    { | 
				
			||||
        $request = new Request(); | 
				
			||||
 | 
				
			||||
        $this->prepare($request); | 
				
			||||
 | 
				
			||||
        $this->headers->get('Content-Type')->shouldStartWith('multipart/mixed; boundary='); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,13 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace spec\XApi\LrsBundle; | 
				
			||||
 | 
				
			||||
use PhpSpec\ObjectBehavior; | 
				
			||||
 | 
				
			||||
class XApiLrsBundleSpec extends ObjectBehavior | 
				
			||||
{ | 
				
			||||
    function it_is_a_bundle() | 
				
			||||
    { | 
				
			||||
        $this->shouldHaveType('Symfony\Component\HttpKernel\Bundle\Bundle'); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,194 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\Controller; | 
				
			||||
 | 
				
			||||
use Symfony\Component\HttpFoundation\JsonResponse; | 
				
			||||
use Symfony\Component\HttpFoundation\ParameterBag; | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
use Symfony\Component\HttpFoundation\Response; | 
				
			||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; | 
				
			||||
use Xabbuh\XApi\Common\Exception\NotFoundException; | 
				
			||||
use Xabbuh\XApi\Model\Statement; | 
				
			||||
use Xabbuh\XApi\Model\StatementId; | 
				
			||||
use Xabbuh\XApi\Model\StatementResult; | 
				
			||||
use Xabbuh\XApi\Serializer\StatementResultSerializerInterface; | 
				
			||||
use Xabbuh\XApi\Serializer\StatementSerializerInterface; | 
				
			||||
use XApi\LrsBundle\Model\StatementsFilterFactory; | 
				
			||||
use XApi\LrsBundle\Response\AttachmentResponse; | 
				
			||||
use XApi\LrsBundle\Response\MultipartResponse; | 
				
			||||
use XApi\Repository\Api\StatementRepositoryInterface; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Jérôme Parmentier <jerome.parmentier@acensi.fr> | 
				
			||||
 */ | 
				
			||||
final class StatementGetController | 
				
			||||
{ | 
				
			||||
    private static $getParameters = array( | 
				
			||||
        'statementId' => true, | 
				
			||||
        'voidedStatementId' => true, | 
				
			||||
        'agent' => true, | 
				
			||||
        'verb' => true, | 
				
			||||
        'activity' => true, | 
				
			||||
        'registration' => true, | 
				
			||||
        'related_activities' => true, | 
				
			||||
        'related_agents' => true, | 
				
			||||
        'since' => true, | 
				
			||||
        'until' => true, | 
				
			||||
        'limit' => true, | 
				
			||||
        'format' => true, | 
				
			||||
        'attachments' => true, | 
				
			||||
        'ascending' => true, | 
				
			||||
    ); | 
				
			||||
 | 
				
			||||
    private $repository; | 
				
			||||
    private $statementSerializer; | 
				
			||||
    private $statementResultSerializer; | 
				
			||||
    private $statementsFilterFactory; | 
				
			||||
 | 
				
			||||
    public function __construct(StatementRepositoryInterface $repository, StatementSerializerInterface $statementSerializer, StatementResultSerializerInterface $statementResultSerializer, StatementsFilterFactory $statementsFilterFactory) | 
				
			||||
    { | 
				
			||||
        $this->repository = $repository; | 
				
			||||
        $this->statementSerializer = $statementSerializer; | 
				
			||||
        $this->statementResultSerializer = $statementResultSerializer; | 
				
			||||
        $this->statementsFilterFactory = $statementsFilterFactory; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param Request $request | 
				
			||||
     * | 
				
			||||
     * @throws BadRequestHttpException if the query parameters does not comply with xAPI specification | 
				
			||||
     * | 
				
			||||
     * @return Response | 
				
			||||
     */ | 
				
			||||
    public function getStatement(Request $request) | 
				
			||||
    { | 
				
			||||
        $query = new ParameterBag(\array_intersect_key($request->query->all(), self::$getParameters)); | 
				
			||||
 | 
				
			||||
        $this->validate($query); | 
				
			||||
 | 
				
			||||
        $includeAttachments = $query->filter('attachments', false, FILTER_VALIDATE_BOOLEAN); | 
				
			||||
        try { | 
				
			||||
            if (($statementId = $query->get('statementId')) !== null) { | 
				
			||||
                $statement = $this->repository->findStatementById(StatementId::fromString($statementId)); | 
				
			||||
 | 
				
			||||
                $response = $this->buildSingleStatementResponse($statement, $includeAttachments); | 
				
			||||
            } elseif (($voidedStatementId = $query->get('voidedStatementId')) !== null) { | 
				
			||||
                $statement = $this->repository->findVoidedStatementById(StatementId::fromString($voidedStatementId)); | 
				
			||||
 | 
				
			||||
                $response = $this->buildSingleStatementResponse($statement, $includeAttachments); | 
				
			||||
            } else { | 
				
			||||
                $statements = $this->repository->findStatementsBy($this->statementsFilterFactory->createFromParameterBag($query)); | 
				
			||||
 | 
				
			||||
                $response = $this->buildMultiStatementsResponse($statements, $includeAttachments); | 
				
			||||
            } | 
				
			||||
        } catch (NotFoundException $e) { | 
				
			||||
            $response = $this->buildMultiStatementsResponse(array()); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $now = new \DateTime(); | 
				
			||||
        $response->headers->set('X-Experience-API-Consistent-Through', $now->format(\DateTime::ATOM)); | 
				
			||||
 | 
				
			||||
        return $response; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param Statement $statement | 
				
			||||
     * @param bool      $includeAttachments true to include the attachments in the response, false otherwise | 
				
			||||
     * | 
				
			||||
     * @return JsonResponse|MultipartResponse | 
				
			||||
     */ | 
				
			||||
    protected function buildSingleStatementResponse(Statement $statement, $includeAttachments = false) | 
				
			||||
    { | 
				
			||||
        $json = $this->statementSerializer->serializeStatement($statement); | 
				
			||||
 | 
				
			||||
        $response = new JsonResponse($json, 200, array(), true); | 
				
			||||
 | 
				
			||||
        if ($includeAttachments) { | 
				
			||||
            $response = $this->buildMultipartResponse($response, array($statement)); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $response->setLastModified($statement->getStored()); | 
				
			||||
 | 
				
			||||
        return $response; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param Statement[] $statements | 
				
			||||
     * @param bool        $includeAttachments true to include the attachments in the response, false otherwise | 
				
			||||
     * | 
				
			||||
     * @return JsonResponse|MultipartResponse | 
				
			||||
     */ | 
				
			||||
    protected function buildMultiStatementsResponse(array $statements, $includeAttachments = false) | 
				
			||||
    { | 
				
			||||
        $json = $this->statementResultSerializer->serializeStatementResult(new StatementResult($statements)); | 
				
			||||
 | 
				
			||||
        $response = new JsonResponse($json, 200, array(), true); | 
				
			||||
 | 
				
			||||
        if ($includeAttachments) { | 
				
			||||
            $response = $this->buildMultipartResponse($response, $statements); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $response; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param JsonResponse $statementResponse | 
				
			||||
     * @param Statement[]  $statements | 
				
			||||
     * | 
				
			||||
     * @return MultipartResponse | 
				
			||||
     */ | 
				
			||||
    protected function buildMultipartResponse(JsonResponse $statementResponse, array $statements) | 
				
			||||
    { | 
				
			||||
        $attachmentsParts = array(); | 
				
			||||
 | 
				
			||||
        foreach ($statements as $statement) { | 
				
			||||
            foreach ((array) $statement->getAttachments() as $attachment) { | 
				
			||||
                $attachmentsParts[] = new AttachmentResponse($attachment); | 
				
			||||
            } | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return new MultipartResponse($statementResponse, $attachmentsParts); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * Validate the parameters. | 
				
			||||
     * | 
				
			||||
     * @param ParameterBag $query | 
				
			||||
     * | 
				
			||||
     * @throws BadRequestHttpException if the parameters does not comply with the xAPI specification | 
				
			||||
     */ | 
				
			||||
    private function validate(ParameterBag $query) | 
				
			||||
    { | 
				
			||||
        $hasStatementId = $query->has('statementId'); | 
				
			||||
        $hasVoidedStatementId = $query->has('voidedStatementId'); | 
				
			||||
 | 
				
			||||
        if ($hasStatementId && $hasVoidedStatementId) { | 
				
			||||
            throw new BadRequestHttpException('Request must not have both statementId and voidedStatementId parameters at the same time.'); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $hasAttachments = $query->has('attachments'); | 
				
			||||
        $hasFormat = $query->has('format'); | 
				
			||||
        $queryCount = $query->count(); | 
				
			||||
 | 
				
			||||
        if (($hasStatementId || $hasVoidedStatementId) && $hasAttachments && $hasFormat && $queryCount > 3) { | 
				
			||||
            throw new BadRequestHttpException('Request must not contain statementId or voidedStatementId parameters, and also any other parameter besides "attachments" or "format".'); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (($hasStatementId || $hasVoidedStatementId) && ($hasAttachments || $hasFormat) && $queryCount > 2) { | 
				
			||||
            throw new BadRequestHttpException('Request must not contain statementId or voidedStatementId parameters, and also any other parameter besides "attachments" or "format".'); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (($hasStatementId || $hasVoidedStatementId) && $queryCount > 1) { | 
				
			||||
            throw new BadRequestHttpException('Request must not contain statementId or voidedStatementId parameters, and also any other parameter besides "attachments" or "format".'); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,33 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\Controller; | 
				
			||||
 | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
use Xabbuh\XApi\Model\Statement; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Jérôme Parmentier <jerome.parmentier@acensi.fr> | 
				
			||||
 */ | 
				
			||||
final class StatementPostController | 
				
			||||
{ | 
				
			||||
    public function postStatement(Request $request, Statement $statement) | 
				
			||||
    { | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param Request     $request | 
				
			||||
     * @param Statement[] $statements | 
				
			||||
     */ | 
				
			||||
    public function postStatements(Request $request, array $statements) | 
				
			||||
    { | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,63 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\Controller; | 
				
			||||
 | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
use Symfony\Component\HttpFoundation\Response; | 
				
			||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; | 
				
			||||
use Symfony\Component\HttpKernel\Exception\ConflictHttpException; | 
				
			||||
use Xabbuh\XApi\Common\Exception\NotFoundException; | 
				
			||||
use Xabbuh\XApi\Model\Statement; | 
				
			||||
use Xabbuh\XApi\Model\StatementId; | 
				
			||||
use XApi\Repository\Api\StatementRepositoryInterface; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 */ | 
				
			||||
final class StatementPutController | 
				
			||||
{ | 
				
			||||
    private $repository; | 
				
			||||
 | 
				
			||||
    public function __construct(StatementRepositoryInterface $repository) | 
				
			||||
    { | 
				
			||||
        $this->repository = $repository; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public function putStatement(Request $request, Statement $statement) | 
				
			||||
    { | 
				
			||||
        if (null === $statementId = $request->query->get('statementId')) { | 
				
			||||
            throw new BadRequestHttpException('Required statementId parameter is missing.'); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        try { | 
				
			||||
            $id = StatementId::fromString($statementId); | 
				
			||||
        } catch (\InvalidArgumentException $e) { | 
				
			||||
            throw new BadRequestHttpException(sprintf('Parameter statementId ("%s") is not a valid UUID.', $statementId), $e); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $statement->getId() && !$id->equals($statement->getId())) { | 
				
			||||
            throw new ConflictHttpException(sprintf('Id parameter ("%s") and statement id ("%s") do not match.', $id->getValue(), $statement->getId()->getValue())); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        try { | 
				
			||||
            $existingStatement = $this->repository->findStatementById($id); | 
				
			||||
 | 
				
			||||
            if (!$existingStatement->equals($statement)) { | 
				
			||||
                throw new ConflictHttpException('The new statement is not equal to an existing statement with the same id.'); | 
				
			||||
            } | 
				
			||||
        } catch (NotFoundException $e) { | 
				
			||||
            $this->repository->storeStatement($statement, true); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return new Response('', 204); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,35 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\DependencyInjection; | 
				
			||||
 | 
				
			||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder; | 
				
			||||
use Symfony\Component\Config\Definition\ConfigurationInterface; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 */ | 
				
			||||
final class Configuration implements ConfigurationInterface | 
				
			||||
{ | 
				
			||||
    public function getConfigTreeBuilder() | 
				
			||||
    { | 
				
			||||
        $treeBuilder = new TreeBuilder(); | 
				
			||||
 | 
				
			||||
        $treeBuilder | 
				
			||||
            ->root('xapi_lrs') | 
				
			||||
                ->beforeNormalization() | 
				
			||||
                    ->ifTrue(function ($v) { return isset($v['type']) && in_array($v['type'], array('mongodb', 'orm')) && !isset($v['object_manager_service']); }) | 
				
			||||
                    ->thenInvalid('You need to configure the object manager service when the repository type is "mongodb" or orm".') | 
				
			||||
                ->end() | 
				
			||||
                ->children() | 
				
			||||
                    ->enumNode('type') | 
				
			||||
                        ->isRequired() | 
				
			||||
                        ->values(array('in_memory', 'mongodb', 'orm')) | 
				
			||||
                    ->end() | 
				
			||||
                    ->scalarNode('object_manager_service')->end() | 
				
			||||
                ->end() | 
				
			||||
            ->end() | 
				
			||||
        ; | 
				
			||||
 | 
				
			||||
        return $treeBuilder; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,60 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\DependencyInjection; | 
				
			||||
 | 
				
			||||
use Symfony\Component\Config\FileLocator; | 
				
			||||
use Symfony\Component\DependencyInjection\ContainerBuilder; | 
				
			||||
use Symfony\Component\DependencyInjection\Extension\Extension; | 
				
			||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 */ | 
				
			||||
final class XApiLrsExtension extends Extension | 
				
			||||
{ | 
				
			||||
    public function load(array $configs, ContainerBuilder $container) | 
				
			||||
    { | 
				
			||||
        $configuration = new Configuration(); | 
				
			||||
        $config = $this->processConfiguration($configuration, $configs); | 
				
			||||
 | 
				
			||||
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); | 
				
			||||
 | 
				
			||||
        $loader->load('controller.xml'); | 
				
			||||
        $loader->load('event_listener.xml'); | 
				
			||||
        $loader->load('factory.xml'); | 
				
			||||
        $loader->load('serializer.xml'); | 
				
			||||
 | 
				
			||||
        switch ($config['type']) { | 
				
			||||
            case 'in_memory': | 
				
			||||
                break; | 
				
			||||
            case 'mongodb': | 
				
			||||
                $loader->load('doctrine.xml'); | 
				
			||||
                $loader->load('mongodb.xml'); | 
				
			||||
 | 
				
			||||
                $container->setAlias('xapi_lrs.doctrine.object_manager', $config['object_manager_service']); | 
				
			||||
                $container->setAlias('xapi_lrs.repository.statement', 'xapi_lrs.repository.statement.doctrine'); | 
				
			||||
                break; | 
				
			||||
            case 'orm': | 
				
			||||
                $loader->load('doctrine.xml'); | 
				
			||||
                $loader->load('orm.xml'); | 
				
			||||
 | 
				
			||||
                $container->setAlias('xapi_lrs.doctrine.object_manager', $config['object_manager_service']); | 
				
			||||
                $container->setAlias('xapi_lrs.repository.statement', 'xapi_lrs.repository.statement.doctrine'); | 
				
			||||
                break; | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public function getAlias() | 
				
			||||
    { | 
				
			||||
        return 'xapi_lrs'; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,73 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\EventListener; | 
				
			||||
 | 
				
			||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent; | 
				
			||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Jérôme Parmentier <jerome.parmentier@acensi.fr> | 
				
			||||
 */ | 
				
			||||
class AlternateRequestSyntaxListener | 
				
			||||
{ | 
				
			||||
    public function onKernelRequest(GetResponseEvent $event) | 
				
			||||
    { | 
				
			||||
        if (!$event->isMasterRequest()) { | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $request = $event->getRequest(); | 
				
			||||
 | 
				
			||||
        if (!$request->attributes->has('xapi_lrs.route')) { | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ('POST' !== $request->getMethod()) { | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null === $method = $request->query->get('method')) { | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($request->query->count() > 1) { | 
				
			||||
            throw new BadRequestHttpException('Including other query parameters than "method" is not allowed. You have to send them as POST parameters inside the request body.'); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $request->setMethod($method); | 
				
			||||
        $request->query->remove('method'); | 
				
			||||
 | 
				
			||||
        if (null !== $content = $request->request->get('content')) { | 
				
			||||
            $request->request->remove('content'); | 
				
			||||
 | 
				
			||||
            $request->initialize( | 
				
			||||
                $request->query->all(), | 
				
			||||
                $request->request->all(), | 
				
			||||
                $request->attributes->all(), | 
				
			||||
                $request->cookies->all(), | 
				
			||||
                $request->files->all(), | 
				
			||||
                $request->server->all(), | 
				
			||||
                $content | 
				
			||||
            ); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        foreach ($request->request as $key => $value) { | 
				
			||||
            if (in_array($key, array('Authorization', 'X-Experience-API-Version', 'Content-Type', 'Content-Length', 'If-Match', 'If-None-Match'), true)) { | 
				
			||||
                $request->headers->set($key, $value); | 
				
			||||
            } else { | 
				
			||||
                $request->query->set($key, $value); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            $request->request->remove($key); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,17 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\EventListener; | 
				
			||||
 | 
				
			||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * Converts Experience API specific domain exceptions into proper HTTP responses. | 
				
			||||
 * | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 */ | 
				
			||||
class ExceptionListener | 
				
			||||
{ | 
				
			||||
    public function onKernelException(GetResponseForExceptionEvent $event) | 
				
			||||
    { | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,40 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\EventListener; | 
				
			||||
 | 
				
			||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent; | 
				
			||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; | 
				
			||||
use Symfony\Component\Serializer\Exception\ExceptionInterface as BaseSerializerException; | 
				
			||||
use Xabbuh\XApi\Serializer\StatementSerializerInterface; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 */ | 
				
			||||
class SerializerListener | 
				
			||||
{ | 
				
			||||
    private $statementSerializer; | 
				
			||||
 | 
				
			||||
    public function __construct(StatementSerializerInterface $statementSerializer) | 
				
			||||
    { | 
				
			||||
        $this->statementSerializer = $statementSerializer; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public function onKernelRequest(GetResponseEvent $event) | 
				
			||||
    { | 
				
			||||
        $request = $event->getRequest(); | 
				
			||||
 | 
				
			||||
        if (!$request->attributes->has('xapi_lrs.route')) { | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        try { | 
				
			||||
            switch ($request->attributes->get('xapi_serializer')) { | 
				
			||||
                case 'statement': | 
				
			||||
                    $request->attributes->set('statement', $this->statementSerializer->deserializeStatement($request->getContent())); | 
				
			||||
                    break; | 
				
			||||
            } | 
				
			||||
        } catch (BaseSerializerException $e) { | 
				
			||||
            throw new BadRequestHttpException(sprintf('The content of the request cannot be deserialized into a valid xAPI %s.', $request->attributes->get('xapi_serializer')), $e); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,66 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\EventListener; | 
				
			||||
 | 
				
			||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent; | 
				
			||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent; | 
				
			||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Jérôme Parmentier <jerome.parmentier@acensi.fr> | 
				
			||||
 */ | 
				
			||||
class VersionListener | 
				
			||||
{ | 
				
			||||
    public function onKernelRequest(GetResponseEvent $event) | 
				
			||||
    { | 
				
			||||
        if (!$event->isMasterRequest()) { | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $request = $event->getRequest(); | 
				
			||||
 | 
				
			||||
        if (!$request->attributes->has('xapi_lrs.route')) { | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null === $version = $request->headers->get('X-Experience-API-Version')) { | 
				
			||||
            throw new BadRequestHttpException('Missing required "X-Experience-API-Version" header.'); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (preg_match('/^1\.0(?:\.\d+)?$/', $version)) { | 
				
			||||
            if ('1.0' === $version) { | 
				
			||||
                $request->headers->set('X-Experience-API-Version', '1.0.0'); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        throw new BadRequestHttpException(sprintf('xAPI version "%s" is not supported.', $version)); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public function onKernelResponse(FilterResponseEvent $event) | 
				
			||||
    { | 
				
			||||
        if (!$event->isMasterRequest()) { | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (!$event->getRequest()->attributes->has('xapi_lrs.route')) { | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $headers = $event->getResponse()->headers; | 
				
			||||
 | 
				
			||||
        if (!$headers->has('X-Experience-API-Version')) { | 
				
			||||
            $headers->set('X-Experience-API-Version', '1.0.3'); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,88 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\Model; | 
				
			||||
 | 
				
			||||
use Symfony\Component\HttpFoundation\ParameterBag; | 
				
			||||
use Xabbuh\XApi\Model\Activity; | 
				
			||||
use Xabbuh\XApi\Model\IRI; | 
				
			||||
use Xabbuh\XApi\Model\StatementsFilter; | 
				
			||||
use Xabbuh\XApi\Model\Verb; | 
				
			||||
use Xabbuh\XApi\Serializer\ActorSerializerInterface; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Jérôme Parmentier <jerome.parmentier@acensi.fr> | 
				
			||||
 */ | 
				
			||||
class StatementsFilterFactory | 
				
			||||
{ | 
				
			||||
    private $actorSerializer; | 
				
			||||
 | 
				
			||||
    public function __construct(ActorSerializerInterface $actorSerializer) | 
				
			||||
    { | 
				
			||||
        $this->actorSerializer = $actorSerializer; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param ParameterBag $parameters | 
				
			||||
     * | 
				
			||||
     * @return StatementsFilter | 
				
			||||
     */ | 
				
			||||
    public function createFromParameterBag(ParameterBag $parameters) | 
				
			||||
    { | 
				
			||||
        $filter = new StatementsFilter(); | 
				
			||||
 | 
				
			||||
        if (($actor = $parameters->get('agent')) !== null) { | 
				
			||||
            $filter->byActor($this->actorSerializer->deserializeActor($actor)); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (($verbId = $parameters->get('verb')) !== null) { | 
				
			||||
            $filter->byVerb(new Verb(IRI::fromString($verbId))); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (($activityId = $parameters->get('activity')) !== null) { | 
				
			||||
            $filter->byActivity(new Activity(IRI::fromString($activityId))); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (($registration = $parameters->get('registration')) !== null) { | 
				
			||||
            $filter->byRegistration($registration); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($parameters->filter('related_activities', false, FILTER_VALIDATE_BOOLEAN)) { | 
				
			||||
            $filter->enableRelatedActivityFilter(); | 
				
			||||
        } else { | 
				
			||||
            $filter->disableRelatedActivityFilter(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($parameters->filter('related_agents', false, FILTER_VALIDATE_BOOLEAN)) { | 
				
			||||
            $filter->enableRelatedAgentFilter(); | 
				
			||||
        } else { | 
				
			||||
            $filter->disableRelatedAgentFilter(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (($since = $parameters->get('since')) !== null) { | 
				
			||||
            $filter->since(\DateTime::createFromFormat(\DateTime::ATOM, $since)); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (($until = $parameters->get('until')) !== null) { | 
				
			||||
            $filter->until(\DateTime::createFromFormat(\DateTime::ATOM, $until)); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($parameters->filter('ascending', false, FILTER_VALIDATE_BOOLEAN)) { | 
				
			||||
            $filter->ascending(); | 
				
			||||
        } else { | 
				
			||||
            $filter->descending(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $filter->limit($parameters->getInt('limit')); | 
				
			||||
 | 
				
			||||
        return $filter; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,21 @@ | 
				
			||||
<?xml version="1.0" encoding="UTF-8" ?> | 
				
			||||
<container xmlns="http://symfony.com/schema/dic/services" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://symfony.com/schema/dic/services | 
				
			||||
        http://symfony.com/schema/dic/services/services-1.0.xsd"> | 
				
			||||
 | 
				
			||||
    <services> | 
				
			||||
        <service id="xapi_lrs.controller.statement.get" class="XApi\LrsBundle\Controller\StatementGetController"> | 
				
			||||
            <argument type="service" id="xapi_lrs.repository.statement"/> | 
				
			||||
            <argument type="service" id="xapi_lrs.statement.serializer"/> | 
				
			||||
            <argument type="service" id="xapi_lrs.statement_result.serializer"/> | 
				
			||||
            <argument type="service" id="xapi_lrs.factory.statements_filter"/> | 
				
			||||
        </service> | 
				
			||||
         | 
				
			||||
        <service id="xapi_lrs.controller.statement.post" class="XApi\LrsBundle\Controller\StatementPostController"/> | 
				
			||||
         | 
				
			||||
        <service id="xapi_lrs.controller.statement.put" class="XApi\LrsBundle\Controller\StatementPutController"> | 
				
			||||
            <argument type="service" id="xapi_lrs.repository.statement"/> | 
				
			||||
        </service> | 
				
			||||
    </services> | 
				
			||||
</container> | 
				
			||||
@ -0,0 +1,12 @@ | 
				
			||||
<?xml version="1.0" encoding="UTF-8" ?> | 
				
			||||
<container xmlns="http://symfony.com/schema/dic/services" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://symfony.com/schema/dic/services | 
				
			||||
        http://symfony.com/schema/dic/services/services-1.0.xsd"> | 
				
			||||
 | 
				
			||||
    <services> | 
				
			||||
        <service id="xapi_lrs.repository.statement.doctrine" class="XApi\Repository\Doctrine\Repository\StatementRepository" public="false"> | 
				
			||||
            <argument type="service" id="xapi_lrs.repository.mapped_statement" /> | 
				
			||||
        </service> | 
				
			||||
    </services> | 
				
			||||
</container> | 
				
			||||
@ -0,0 +1,25 @@ | 
				
			||||
<?xml version="1.0" encoding="UTF-8" ?> | 
				
			||||
<container xmlns="http://symfony.com/schema/dic/services" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://symfony.com/schema/dic/services | 
				
			||||
        http://symfony.com/schema/dic/services/services-1.0.xsd"> | 
				
			||||
 | 
				
			||||
    <services> | 
				
			||||
        <service id="xapi_lrs.event_listener.alternate_request_syntax" class="XApi\LrsBundle\EventListener\AlternateRequestSyntaxListener"> | 
				
			||||
            <tag name="kernel.event_listener" event="kernel.request" /> | 
				
			||||
        </service> | 
				
			||||
     | 
				
			||||
        <service id="xapi_lrs.event_listener.exception" class="XApi\LrsBundle\EventListener\ExceptionListener"> | 
				
			||||
        </service> | 
				
			||||
 | 
				
			||||
        <service id="xapi_lrs.event_listener.serializer" class="XApi\LrsBundle\EventListener\SerializerListener"> | 
				
			||||
            <argument type="service" id="xapi_lrs.statement.serializer" /> | 
				
			||||
            <tag name="kernel.event_listener" event="kernel.request" /> | 
				
			||||
        </service> | 
				
			||||
 | 
				
			||||
        <service id="xapi_lrs.event_listener.version" class="XApi\LrsBundle\EventListener\VersionListener"> | 
				
			||||
            <tag name="kernel.event_listener" event="kernel.request" /> | 
				
			||||
            <tag name="kernel.event_listener" event="kernel.response" /> | 
				
			||||
        </service> | 
				
			||||
    </services> | 
				
			||||
</container> | 
				
			||||
@ -0,0 +1,12 @@ | 
				
			||||
<?xml version="1.0" encoding="UTF-8" ?> | 
				
			||||
<container xmlns="http://symfony.com/schema/dic/services" | 
				
			||||
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
           xsi:schemaLocation="http://symfony.com/schema/dic/services | 
				
			||||
        http://symfony.com/schema/dic/services/services-1.0.xsd"> | 
				
			||||
 | 
				
			||||
    <services> | 
				
			||||
        <service id="xapi_lrs.factory.statements_filter" class="XApi\LrsBundle\Model\StatementsFilterFactory"> | 
				
			||||
            <argument type="service" id="xapi_lrs.actor.serializer"/> | 
				
			||||
        </service> | 
				
			||||
    </services> | 
				
			||||
</container> | 
				
			||||
@ -0,0 +1,18 @@ | 
				
			||||
<?xml version="1.0" encoding="UTF-8" ?> | 
				
			||||
<container xmlns="http://symfony.com/schema/dic/services" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://symfony.com/schema/dic/services | 
				
			||||
        http://symfony.com/schema/dic/services/services-1.0.xsd"> | 
				
			||||
 | 
				
			||||
    <services> | 
				
			||||
        <service id="xapi_lrs.doctrine.class_metadata" class="Doctrine\ORM\Mapping\ClassMetadata" public="false"> | 
				
			||||
            <argument>XApi\Repository\Api\Mapping\MappedStatement</argument> | 
				
			||||
            <factory service="xapi_lrs.doctrine.object_manager" method="getClassMetadata" /> | 
				
			||||
        </service> | 
				
			||||
 | 
				
			||||
        <service id="xapi_lrs.repository.mapped_statement" class="XApi\Repository\ORM\MappedStatementRepository" public="false"> | 
				
			||||
            <argument type="service" id="xapi_lrs.doctrine.object_manager" /> | 
				
			||||
            <argument type="service" id="xapi_lrs.doctrine.class_metadata" /> | 
				
			||||
        </service> | 
				
			||||
    </services> | 
				
			||||
</container> | 
				
			||||
@ -0,0 +1,29 @@ | 
				
			||||
<?xml version="1.0" encoding="UTF-8" ?> | 
				
			||||
<routes xmlns="http://symfony.com/schema/routing" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://symfony.com/schema/routing | 
				
			||||
        http://symfony.com/schema/routing/routing-1.0.xsd"> | 
				
			||||
 | 
				
			||||
    <route id="xapi_lrs.statement.put" path="/statements" methods="PUT"> | 
				
			||||
        <default key="_controller">xapi_lrs.controller.statement.put:putStatement</default> | 
				
			||||
        <default key="xapi_serializer">statement</default> | 
				
			||||
        <default key="xapi_lrs.route"> | 
				
			||||
            <bool>true</bool> | 
				
			||||
        </default> | 
				
			||||
    </route> | 
				
			||||
 | 
				
			||||
    <route id="xapi_lrs.statement.post" path="/statements" methods="POST"> | 
				
			||||
        <default key="_controller">xapi_lrs.controller.statement.post:postStatement</default> | 
				
			||||
        <default key="xapi_serializer">statement</default> | 
				
			||||
        <default key="xapi_lrs.route"> | 
				
			||||
            <bool>true</bool> | 
				
			||||
        </default> | 
				
			||||
    </route> | 
				
			||||
 | 
				
			||||
    <route id="xapi_lrs.statement.get" path="/statements" methods="GET"> | 
				
			||||
        <default key="_controller">xapi_lrs.controller.statement.get:getStatement</default> | 
				
			||||
        <default key="xapi_lrs.route"> | 
				
			||||
            <bool>true</bool> | 
				
			||||
        </default> | 
				
			||||
    </route> | 
				
			||||
</routes> | 
				
			||||
@ -0,0 +1,32 @@ | 
				
			||||
<?xml version="1.0" encoding="UTF-8" ?> | 
				
			||||
<container xmlns="http://symfony.com/schema/dic/services" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://symfony.com/schema/dic/services | 
				
			||||
        http://symfony.com/schema/dic/services/services-1.0.xsd"> | 
				
			||||
 | 
				
			||||
    <services> | 
				
			||||
        <service id="xapi_lrs.statement.serializer" class="Xabbuh\XApi\Serializer\StatementSerializerInterface" public="false"> | 
				
			||||
            <factory service="xapi_lrs.serializer.factory" method="createStatementSerializer"/> | 
				
			||||
        </service> | 
				
			||||
 | 
				
			||||
        <service id="xapi_lrs.statement_result.serializer" class="Xabbuh\XApi\Serializer\StatementResultSerializerInterface" public="false"> | 
				
			||||
            <factory service="xapi_lrs.serializer.factory" method="createStatementResultSerializer"/> | 
				
			||||
        </service> | 
				
			||||
 | 
				
			||||
        <service id="xapi_lrs.actor.serializer" class="Xabbuh\XApi\Serializer\ActorSerializerInterface" public="false"> | 
				
			||||
            <factory service="xapi_lrs.serializer.factory" method="createActorSerializer"/> | 
				
			||||
        </service> | 
				
			||||
 | 
				
			||||
        <service id="xapi_lrs.document_data.serializer" class="Xabbuh\XApi\Serializer\DocumentDataSerializerInterface" public="false"> | 
				
			||||
            <factory service="xapi_lrs.serializer.factory" method="createDocumentDataSerializer"/> | 
				
			||||
        </service> | 
				
			||||
 | 
				
			||||
        <service id="xapi_lrs.serializer_factory" class="Xabbuh\XApi\Serializer\Symfony\SerializerFactory" public="false"> | 
				
			||||
            <argument type="service" id="xapi_lrs.serializer"/> | 
				
			||||
        </service> | 
				
			||||
 | 
				
			||||
        <service id="xapi_lrs.serializer" class="Symfony\Component\Serializer\SerializerInterface" public="false"> | 
				
			||||
            <factory class="Xabbuh\XApi\Serializer\Symfony\Serializer" method="createSerializer"/> | 
				
			||||
        </service> | 
				
			||||
    </services> | 
				
			||||
</container> | 
				
			||||
@ -0,0 +1,79 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\Response; | 
				
			||||
 | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
use Symfony\Component\HttpFoundation\Response; | 
				
			||||
use Xabbuh\XApi\Model\Attachment; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Jérôme Parmentier <jerome.parmentier@acensi.fr> | 
				
			||||
 */ | 
				
			||||
class AttachmentResponse extends Response | 
				
			||||
{ | 
				
			||||
    protected $attachment; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param Attachment $attachment | 
				
			||||
     */ | 
				
			||||
    public function __construct(Attachment $attachment) | 
				
			||||
    { | 
				
			||||
        parent::__construct(null); | 
				
			||||
 | 
				
			||||
        $this->attachment = $attachment; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * {@inheritdoc} | 
				
			||||
     */ | 
				
			||||
    public function prepare(Request $request) | 
				
			||||
    { | 
				
			||||
        if (!$this->headers->has('Content-Type')) { | 
				
			||||
            $this->headers->set('Content-Type', $this->attachment->getContentType()); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $this->headers->set('Content-Transfer-Encoding', 'binary'); | 
				
			||||
        $this->headers->set('X-Experience-API-Hash', $this->attachment->getSha2()); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * {@inheritdoc} | 
				
			||||
     * | 
				
			||||
     * @throws \LogicException | 
				
			||||
     */ | 
				
			||||
    public function sendContent() | 
				
			||||
    { | 
				
			||||
        throw new \LogicException('An AttachmentResponse is only meant to be part of a multipart Response.'); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * {@inheritdoc} | 
				
			||||
     * | 
				
			||||
     * @throws \LogicException when the content is not null | 
				
			||||
     */ | 
				
			||||
    public function setContent($content) | 
				
			||||
    { | 
				
			||||
        if (null !== $content) { | 
				
			||||
            throw new \LogicException('The content cannot be set on an AttachmentResponse instance.'); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * {@inheritdoc} | 
				
			||||
     * | 
				
			||||
     * @return null|string | 
				
			||||
     */ | 
				
			||||
    public function getContent() | 
				
			||||
    { | 
				
			||||
        return $this->attachment->getContent(); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,139 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle\Response; | 
				
			||||
 | 
				
			||||
use Symfony\Component\HttpFoundation\JsonResponse; | 
				
			||||
use Symfony\Component\HttpFoundation\Request; | 
				
			||||
use Symfony\Component\HttpFoundation\Response; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Jérôme Parmentier <jerome.parmentier@acensi.fr> | 
				
			||||
 */ | 
				
			||||
class MultipartResponse extends Response | 
				
			||||
{ | 
				
			||||
    protected $subtype; | 
				
			||||
    protected $boundary; | 
				
			||||
    protected $statementPart; | 
				
			||||
    /** | 
				
			||||
     * @var Response[] | 
				
			||||
     */ | 
				
			||||
    protected $parts; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param JsonResponse         $statementPart | 
				
			||||
     * @param AttachmentResponse[] $attachmentsParts | 
				
			||||
     * @param int                  $status | 
				
			||||
     * @param array                $headers | 
				
			||||
     * @param null|string          $subtype | 
				
			||||
     */ | 
				
			||||
    public function __construct(JsonResponse $statementPart, array $attachmentsParts = array(), $status = 200, array $headers = array(), $subtype = null) | 
				
			||||
    { | 
				
			||||
        parent::__construct(null, $status, $headers); | 
				
			||||
 | 
				
			||||
        if (null === $subtype) { | 
				
			||||
            $subtype = 'mixed'; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $this->subtype = $subtype; | 
				
			||||
        $this->boundary = uniqid('', true); | 
				
			||||
        $this->statementPart = $statementPart; | 
				
			||||
 | 
				
			||||
        $this->setAttachmentsParts($attachmentsParts); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param AttachmentResponse $part | 
				
			||||
     * | 
				
			||||
     * @return $this | 
				
			||||
     */ | 
				
			||||
    public function addAttachmentPart(AttachmentResponse $part) | 
				
			||||
    { | 
				
			||||
        if ($part->getContent() !== null) { | 
				
			||||
            $this->parts[] = $part; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $this; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param AttachmentResponse[] $attachmentsParts | 
				
			||||
     * | 
				
			||||
     * @return $this | 
				
			||||
     */ | 
				
			||||
    public function setAttachmentsParts(array $attachmentsParts) | 
				
			||||
    { | 
				
			||||
        $this->parts = array($this->statementPart); | 
				
			||||
 | 
				
			||||
        foreach ($attachmentsParts as $part) { | 
				
			||||
            $this->addAttachmentPart($part); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $this; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * {@inheritdoc} | 
				
			||||
     */ | 
				
			||||
    public function prepare(Request $request) | 
				
			||||
    { | 
				
			||||
        foreach ($this->parts as $part) { | 
				
			||||
            $part->prepare($request); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $this->headers->set('Content-Type', sprintf('multipart/%s; boundary="%s"', $this->subtype, $this->boundary)); | 
				
			||||
        $this->headers->set('Transfer-Encoding', 'chunked'); | 
				
			||||
 | 
				
			||||
        return parent::prepare($request); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * {@inheritdoc} | 
				
			||||
     */ | 
				
			||||
    public function sendContent() | 
				
			||||
    { | 
				
			||||
        $content = ''; | 
				
			||||
        foreach ($this->parts as $part) { | 
				
			||||
            $content .= sprintf('--%s', $this->boundary)."\r\n"; | 
				
			||||
            $content .= $part->headers."\r\n"; | 
				
			||||
            $content .= $part->getContent(); | 
				
			||||
            $content .= "\r\n"; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $content .= sprintf('--%s--', $this->boundary)."\r\n"; | 
				
			||||
 | 
				
			||||
        echo $content; | 
				
			||||
 | 
				
			||||
        return $this; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * {@inheritdoc} | 
				
			||||
     * | 
				
			||||
     * @throws \LogicException when the content is not null | 
				
			||||
     */ | 
				
			||||
    public function setContent($content) | 
				
			||||
    { | 
				
			||||
        if (null !== $content) { | 
				
			||||
            throw new \LogicException('The content cannot be set on a MultipartResponse instance.'); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * {@inheritdoc} | 
				
			||||
     * | 
				
			||||
     * @return false | 
				
			||||
     */ | 
				
			||||
    public function getContent() | 
				
			||||
    { | 
				
			||||
        return false; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,26 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\LrsBundle; | 
				
			||||
 | 
				
			||||
use Symfony\Component\HttpKernel\Bundle\Bundle; | 
				
			||||
use XApi\LrsBundle\DependencyInjection\XApiLrsExtension; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 */ | 
				
			||||
class XApiLrsBundle extends Bundle | 
				
			||||
{ | 
				
			||||
    public function getContainerExtension() | 
				
			||||
    { | 
				
			||||
        return new XApiLrsExtension(); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,19 @@ | 
				
			||||
Copyright (c) 2016-2017 Christian Flothmann | 
				
			||||
 | 
				
			||||
Permission is hereby granted, free of charge, to any person obtaining a copy | 
				
			||||
of this software and associated documentation files (the "Software"), to deal | 
				
			||||
in the Software without restriction, including without limitation the rights | 
				
			||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
				
			||||
copies of the Software, and to permit persons to whom the Software is furnished | 
				
			||||
to do so, subject to the following conditions: | 
				
			||||
 | 
				
			||||
The above copyright notice and this permission notice shall be included in all | 
				
			||||
copies or substantial portions of the Software. | 
				
			||||
 | 
				
			||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
				
			||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
				
			||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
				
			||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
				
			||||
THE SOFTWARE. | 
				
			||||
@ -0,0 +1,41 @@ | 
				
			||||
{ | 
				
			||||
    "name": "php-xapi/repository-doctrine-orm", | 
				
			||||
    "description": "Doctrine based ORM implementations of an Experience API (xAPI) repository", | 
				
			||||
    "keywords": ["xAPI", "Tin Can API", "Experience API", "storage", "database", "repository", "entity", "Doctrine", "ORM"], | 
				
			||||
    "homepage": "https://github.com/php-xapi/repository-orm/", | 
				
			||||
    "license": "MIT", | 
				
			||||
    "authors": [ | 
				
			||||
        { | 
				
			||||
            "name": "Christian Flothmann", | 
				
			||||
            "homepage": "https://github.com/xabbuh" | 
				
			||||
        } | 
				
			||||
    ], | 
				
			||||
    "require": { | 
				
			||||
        "php": "^5.6 || ^7.0", | 
				
			||||
        "doctrine/orm": "^2.3", | 
				
			||||
        "php-xapi/repository-api": "^0.4", | 
				
			||||
        "php-xapi/repository-doctrine": "^0.4" | 
				
			||||
    }, | 
				
			||||
    "require-dev": { | 
				
			||||
        "symfony/phpunit-bridge": "^3.4 || ^4.0" | 
				
			||||
    }, | 
				
			||||
    "provide": { | 
				
			||||
        "php-xapi/repository-implementation": "0.3" | 
				
			||||
    }, | 
				
			||||
    "autoload": { | 
				
			||||
        "psr-4": { | 
				
			||||
            "XApi\\Repository\\ORM\\": "src/" | 
				
			||||
        } | 
				
			||||
    }, | 
				
			||||
    "autoload-dev": { | 
				
			||||
        "psr-4": { | 
				
			||||
            "XApi\\Repository\\ORM\\Tests\\": "tests/" | 
				
			||||
        } | 
				
			||||
    }, | 
				
			||||
    "minimum-stability": "dev", | 
				
			||||
    "extra": { | 
				
			||||
        "branch-alias": { | 
				
			||||
            "dev-master": "0.1.x-dev" | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,19 @@ | 
				
			||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping | 
				
			||||
        http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> | 
				
			||||
 | 
				
			||||
    <entity name="XApi\Repository\Doctrine\Mapping\Actor" table="xapi_actor"> | 
				
			||||
        <id name="identifier" type="integer"> | 
				
			||||
            <generator strategy="AUTO" /> | 
				
			||||
        </id> | 
				
			||||
 | 
				
			||||
        <field name="type" type="string" nullable="true" /> | 
				
			||||
        <field name="mbox" type="string" nullable="true" /> | 
				
			||||
        <field name="mboxSha1Sum" type="string" nullable="true" /> | 
				
			||||
        <field name="openId" type="string" nullable="true" /> | 
				
			||||
        <field name="accountName" type="string" nullable="true" /> | 
				
			||||
        <field name="accountHomePage" type="string" nullable="true" /> | 
				
			||||
        <field name="name" type="string" nullable="true" /> | 
				
			||||
    </entity> | 
				
			||||
</doctrine-mapping> | 
				
			||||
@ -0,0 +1,23 @@ | 
				
			||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping | 
				
			||||
        http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> | 
				
			||||
 | 
				
			||||
    <entity name="XApi\Repository\Doctrine\Mapping\Attachment" table="xapi_attachment"> | 
				
			||||
        <id name="identifier" type="integer"> | 
				
			||||
            <generator strategy="AUTO" /> | 
				
			||||
        </id> | 
				
			||||
 | 
				
			||||
        <field name="usageType" type="string" /> | 
				
			||||
        <field name="contentType" type="string" /> | 
				
			||||
        <field name="length" type="integer" /> | 
				
			||||
        <field name="sha2" type="string" /> | 
				
			||||
        <field name="display" type="json_array" /> | 
				
			||||
        <field name="hasDescription" type="boolean" /> | 
				
			||||
        <field name="description" type="json_array" nullable="true" /> | 
				
			||||
        <field name="fileUrl" type="string" nullable="true" /> | 
				
			||||
        <field name="content" type="text" nullable="true" /> | 
				
			||||
 | 
				
			||||
        <many-to-one field="statement" target-entity="XApi\Repository\Doctrine\Mapping\Statement" inversed-by="attachments" /> | 
				
			||||
    </entity> | 
				
			||||
</doctrine-mapping> | 
				
			||||
@ -0,0 +1,59 @@ | 
				
			||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping | 
				
			||||
        http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> | 
				
			||||
 | 
				
			||||
    <entity name="XApi\Repository\Doctrine\Mapping\Context" table="xapi_context"> | 
				
			||||
        <id name="identifier" type="integer"> | 
				
			||||
            <generator strategy="AUTO" /> | 
				
			||||
        </id> | 
				
			||||
 | 
				
			||||
        <field name="registration" type="string" nullable="true" /> | 
				
			||||
        <field name="hasContextActivities" type="boolean" nullable="true" /> | 
				
			||||
        <field name="revision" type="string" nullable="true" /> | 
				
			||||
        <field name="platform" type="string" nullable="true" /> | 
				
			||||
        <field name="language" type="string" nullable="true" /> | 
				
			||||
        <field name="statement" type="string" nullable="true" /> | 
				
			||||
 | 
				
			||||
        <one-to-one field="instructor" target-entity="XApi\Repository\Doctrine\Mapping\StatementObject"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
        <one-to-one field="team" target-entity="XApi\Repository\Doctrine\Mapping\StatementObject"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
        <one-to-one field="extensions" target-entity="XApi\Repository\Doctrine\Mapping\Extensions"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
 | 
				
			||||
        <!-- context activities --> | 
				
			||||
        <one-to-many field="parentActivities" target-entity="XApi\Repository\Doctrine\Mapping\StatementObject" mapped-by="parentContext"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
        </one-to-many> | 
				
			||||
        <one-to-many field="groupingActivities" target-entity="XApi\Repository\Doctrine\Mapping\StatementObject" mapped-by="groupingContext"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
        </one-to-many> | 
				
			||||
        <one-to-many field="categoryActivities" target-entity="XApi\Repository\Doctrine\Mapping\StatementObject" mapped-by="categoryContext"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
        </one-to-many> | 
				
			||||
        <one-to-many field="otherActivities" target-entity="XApi\Repository\Doctrine\Mapping\StatementObject" mapped-by="otherContext"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
        </one-to-many> | 
				
			||||
    </entity> | 
				
			||||
</doctrine-mapping> | 
				
			||||
@ -0,0 +1,13 @@ | 
				
			||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping | 
				
			||||
        http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> | 
				
			||||
 | 
				
			||||
    <entity name="XApi\Repository\Doctrine\Mapping\Extensions" table="xapi_extensions"> | 
				
			||||
        <id name="identifier" type="integer"> | 
				
			||||
            <generator strategy="AUTO" /> | 
				
			||||
        </id> | 
				
			||||
 | 
				
			||||
        <field name="extensions" type="json_array" /> | 
				
			||||
    </entity> | 
				
			||||
</doctrine-mapping> | 
				
			||||
@ -0,0 +1,28 @@ | 
				
			||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping | 
				
			||||
        http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> | 
				
			||||
 | 
				
			||||
    <entity name="XApi\Repository\Doctrine\Mapping\Result" table="xapi_result"> | 
				
			||||
        <id name="identifier" type="integer"> | 
				
			||||
            <generator strategy="AUTO" /> | 
				
			||||
        </id> | 
				
			||||
 | 
				
			||||
        <field name="hasScore" type="boolean" /> | 
				
			||||
        <field name="scaled" type="float" nullable="true" /> | 
				
			||||
        <field name="raw" type="float" nullable="true" /> | 
				
			||||
        <field name="min" type="float" nullable="true" /> | 
				
			||||
        <field name="max" type="float" nullable="true" /> | 
				
			||||
        <field name="success" type="boolean" nullable="true" /> | 
				
			||||
        <field name="completion" type="boolean" nullable="true" /> | 
				
			||||
        <field name="response" type="string" nullable="true" /> | 
				
			||||
        <field name="duration" type="string" nullable="true" /> | 
				
			||||
 | 
				
			||||
        <one-to-one field="extensions" target-entity="XApi\Repository\Doctrine\Mapping\Extensions"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
    </entity> | 
				
			||||
</doctrine-mapping> | 
				
			||||
@ -0,0 +1,62 @@ | 
				
			||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping | 
				
			||||
        http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> | 
				
			||||
 | 
				
			||||
    <entity name="XApi\Repository\Doctrine\Mapping\Statement" | 
				
			||||
        repository-class="XApi\Repository\ORM\StatementRepository" | 
				
			||||
        table="xapi_statement"> | 
				
			||||
 | 
				
			||||
        <id name="id" type="string"> | 
				
			||||
            <generator strategy="NONE" /> | 
				
			||||
        </id> | 
				
			||||
 | 
				
			||||
        <field name="created" type="bigint" nullable="true" /> | 
				
			||||
        <field name="stored" type="bigint" nullable="true" /> | 
				
			||||
        <field name="hasAttachments" type="boolean" /> | 
				
			||||
 | 
				
			||||
        <one-to-one field="actor" target-entity="XApi\Repository\Doctrine\Mapping\StatementObject"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
        <one-to-one field="verb" target-entity="XApi\Repository\Doctrine\Mapping\Verb"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
        <one-to-one field="object" target-entity="XApi\Repository\Doctrine\Mapping\StatementObject"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
        <one-to-one field="result" target-entity="XApi\Repository\Doctrine\Mapping\Result"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
        <one-to-one field="authority" target-entity="XApi\Repository\Doctrine\Mapping\StatementObject"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
        <one-to-one field="context" target-entity="XApi\Repository\Doctrine\Mapping\Context"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
 | 
				
			||||
        <!-- attachments --> | 
				
			||||
        <one-to-many field="attachments" target-entity="XApi\Repository\Doctrine\Mapping\Attachment" mapped-by="statement"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
        </one-to-many> | 
				
			||||
    </entity> | 
				
			||||
</doctrine-mapping> | 
				
			||||
@ -0,0 +1,83 @@ | 
				
			||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping | 
				
			||||
        http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> | 
				
			||||
 | 
				
			||||
    <entity name="XApi\Repository\Doctrine\Mapping\StatementObject" table="xapi_object"> | 
				
			||||
        <id name="identifier" type="integer"> | 
				
			||||
            <generator strategy="AUTO" /> | 
				
			||||
        </id> | 
				
			||||
 | 
				
			||||
        <!-- discriminator column --> | 
				
			||||
        <field name="type" type="string" nullable="true" /> | 
				
			||||
 | 
				
			||||
        <!-- activity --> | 
				
			||||
        <field name="activityId" type="string" nullable="true" /> | 
				
			||||
        <field name="hasActivityDefinition" type="boolean" nullable="true" /> | 
				
			||||
        <field name="hasActivityName" type="boolean" nullable="true" /> | 
				
			||||
        <field name="activityName" type="json_array" nullable="true" /> | 
				
			||||
        <field name="hasActivityDescription" type="boolean" nullable="true" /> | 
				
			||||
        <field name="activityDescription" type="json_array" nullable="true" /> | 
				
			||||
        <field name="activityType" type="string" nullable="true" /> | 
				
			||||
        <field name="activityMoreInfo" type="string" nullable="true" /> | 
				
			||||
 | 
				
			||||
        <!-- actor --> | 
				
			||||
        <field name="mbox" type="string" nullable="true" /> | 
				
			||||
        <field name="mboxSha1Sum" type="string" nullable="true" /> | 
				
			||||
        <field name="openId" type="string" nullable="true" /> | 
				
			||||
        <field name="accountName" type="string" nullable="true" /> | 
				
			||||
        <field name="accountHomePage" type="string" nullable="true" /> | 
				
			||||
        <field name="name" type="string" nullable="true" /> | 
				
			||||
 | 
				
			||||
        <!-- statement reference --> | 
				
			||||
        <field name="referencedStatementId" type="string" nullable="true" /> | 
				
			||||
 | 
				
			||||
        <!-- sub statement --> | 
				
			||||
        <one-to-one field="actor" target-entity="XApi\Repository\Doctrine\Mapping\StatementObject"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
        <one-to-one field="verb" target-entity="XApi\Repository\Doctrine\Mapping\Verb"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
        <one-to-one field="object" target-entity="XApi\Repository\Doctrine\Mapping\StatementObject"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
 | 
				
			||||
        <!-- activity extensions --> | 
				
			||||
        <one-to-one field="activityExtensions" target-entity="XApi\Repository\Doctrine\Mapping\Extensions"> | 
				
			||||
            <cascade> | 
				
			||||
                <cascade-all /> | 
				
			||||
            </cascade> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </one-to-one> | 
				
			||||
 | 
				
			||||
        <!-- group members --> | 
				
			||||
        <one-to-many target-entity="XApi\Repository\Doctrine\Mapping\StatementObject" mapped-by="group" field="members" /> | 
				
			||||
        <many-to-one target-entity="XApi\Repository\Doctrine\Mapping\StatementObject" field="group" inversed-by="members"> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </many-to-one> | 
				
			||||
 | 
				
			||||
        <!-- context activities --> | 
				
			||||
        <many-to-one target-entity="XApi\Repository\Doctrine\Mapping\Context" field="parentContext" inversed-by="parentActivities"> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </many-to-one> | 
				
			||||
        <many-to-one target-entity="XApi\Repository\Doctrine\Mapping\Context" field="groupingContext" inversed-by="groupingActivities"> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </many-to-one> | 
				
			||||
        <many-to-one target-entity="XApi\Repository\Doctrine\Mapping\Context" field="categoryContext" inversed-by="categoryActivities"> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </many-to-one> | 
				
			||||
        <many-to-one target-entity="XApi\Repository\Doctrine\Mapping\Context" field="otherContext" inversed-by="otherActivities"> | 
				
			||||
            <join-column referenced-column-name="identifier" /> | 
				
			||||
        </many-to-one> | 
				
			||||
    </entity> | 
				
			||||
</doctrine-mapping> | 
				
			||||
@ -0,0 +1,14 @@ | 
				
			||||
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" | 
				
			||||
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
				
			||||
    xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping | 
				
			||||
        http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> | 
				
			||||
 | 
				
			||||
    <entity name="XApi\Repository\Doctrine\Mapping\Verb" table="xapi_verb"> | 
				
			||||
        <id name="identifier" type="integer"> | 
				
			||||
            <generator strategy="AUTO" /> | 
				
			||||
        </id> | 
				
			||||
 | 
				
			||||
        <field name="id" type="string" /> | 
				
			||||
        <field name="display" type="json_array" /> | 
				
			||||
    </entity> | 
				
			||||
</doctrine-mapping> | 
				
			||||
@ -0,0 +1,13 @@ | 
				
			||||
<?xml version="1.0" encoding="UTF-8"?> | 
				
			||||
<phpunit colors="true" bootstrap="vendor/autoload.php"> | 
				
			||||
    <testsuites> | 
				
			||||
        <testsuite name="Doctrine ORM driver implementation for an xAPI repository"> | 
				
			||||
            <directory>./tests</directory> | 
				
			||||
        </testsuite> | 
				
			||||
    </testsuites> | 
				
			||||
    <filter> | 
				
			||||
        <whitelist> | 
				
			||||
            <directory>./src</directory> | 
				
			||||
        </whitelist> | 
				
			||||
    </filter> | 
				
			||||
</phpunit> | 
				
			||||
@ -0,0 +1,50 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\Repository\ORM; | 
				
			||||
 | 
				
			||||
use Doctrine\ORM\EntityRepository; | 
				
			||||
use XApi\Repository\Doctrine\Mapping\Statement; | 
				
			||||
use XApi\Repository\Doctrine\Repository\Mapping\StatementRepository as BaseStatementRepository; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 */ | 
				
			||||
final class StatementRepository extends EntityRepository implements BaseStatementRepository | 
				
			||||
{ | 
				
			||||
    /** | 
				
			||||
     * {@inheritdoc} | 
				
			||||
     */ | 
				
			||||
    public function findStatement(array $criteria) | 
				
			||||
    { | 
				
			||||
        return parent::findOneBy($criteria); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * {@inheritdoc} | 
				
			||||
     */ | 
				
			||||
    public function findStatements(array $criteria) | 
				
			||||
    { | 
				
			||||
        return parent::findBy($criteria); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * {@inheritdoc} | 
				
			||||
     */ | 
				
			||||
    public function storeStatement(Statement $mappedStatement, $flush = true) | 
				
			||||
    { | 
				
			||||
        $this->_em->persist($mappedStatement); | 
				
			||||
 | 
				
			||||
        if ($flush) { | 
				
			||||
            $this->_em->flush(); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,52 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\Repository\ORM\Tests\Functional; | 
				
			||||
 | 
				
			||||
use Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator; | 
				
			||||
use Doctrine\ORM\Configuration; | 
				
			||||
use Doctrine\ORM\EntityManager; | 
				
			||||
use Doctrine\ORM\Mapping\Driver\XmlDriver; | 
				
			||||
use Doctrine\ORM\Tools\SchemaTool; | 
				
			||||
use XApi\Repository\Doctrine\Test\Functional\StatementRepositoryTest as BaseStatementRepositoryTest; | 
				
			||||
 | 
				
			||||
class StatementRepositoryTest extends BaseStatementRepositoryTest | 
				
			||||
{ | 
				
			||||
    protected function createObjectManager() | 
				
			||||
    { | 
				
			||||
        $config = new Configuration(); | 
				
			||||
        $config->setProxyDir(__DIR__.'/../proxies'); | 
				
			||||
        $config->setProxyNamespace('Proxy'); | 
				
			||||
        $fileLocator = new SymfonyFileLocator( | 
				
			||||
            array(__DIR__.'/../../metadata' => 'XApi\Repository\Doctrine\Mapping'), | 
				
			||||
            '.orm.xml' | 
				
			||||
        ); | 
				
			||||
        $driver = new XmlDriver($fileLocator); | 
				
			||||
        $config->setMetadataDriverImpl($driver); | 
				
			||||
 | 
				
			||||
        return EntityManager::create(array('driver' => 'pdo_sqlite', 'path' => __DIR__.'/../data/db.sqlite'), $config); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    protected function getStatementClassName() | 
				
			||||
    { | 
				
			||||
        return 'XApi\Repository\Doctrine\Mapping\Statement'; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    protected function cleanDatabase() | 
				
			||||
    { | 
				
			||||
        $metadata = $this->objectManager->getMetadataFactory()->getAllMetadata(); | 
				
			||||
        $tool = new SchemaTool($this->objectManager); | 
				
			||||
        $tool->dropDatabase(); | 
				
			||||
        $tool->createSchema($metadata); | 
				
			||||
 | 
				
			||||
        parent::cleanDatabase(); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,38 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace XApi\Repository\ORM\Tests\Unit\Repository; | 
				
			||||
 | 
				
			||||
use XApi\Repository\Doctrine\Test\Unit\Repository\Mapping\StatementRepositoryTest as BaseStatementRepositoryTest; | 
				
			||||
use XApi\Repository\ORM\StatementRepository; | 
				
			||||
 | 
				
			||||
class StatementRepositoryTest extends BaseStatementRepositoryTest | 
				
			||||
{ | 
				
			||||
    protected function getObjectManagerClass() | 
				
			||||
    { | 
				
			||||
        return 'Doctrine\ORM\EntityManager'; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    protected function getUnitOfWorkClass() | 
				
			||||
    { | 
				
			||||
        return 'Doctrine\ORM\UnitOfWork'; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    protected function getClassMetadataClass() | 
				
			||||
    { | 
				
			||||
        return 'Doctrine\ORM\Mapping\ClassMetadata'; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    protected function createMappedStatementRepository($objectManager, $unitOfWork, $classMetadata) | 
				
			||||
    { | 
				
			||||
        return new StatementRepository($objectManager, $classMetadata); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,161 +0,0 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace Chamilo\PluginBundle\Entity\XApi\Lrs; | 
				
			||||
 | 
				
			||||
use Doctrine\ORM\Mapping as ORM; | 
				
			||||
use Xabbuh\XApi\Model\Account; | 
				
			||||
use Xabbuh\XApi\Model\Actor as ActorModel; | 
				
			||||
use Xabbuh\XApi\Model\Agent; | 
				
			||||
use Xabbuh\XApi\Model\Group; | 
				
			||||
use Xabbuh\XApi\Model\InverseFunctionalIdentifier; | 
				
			||||
use Xabbuh\XApi\Model\IRI; | 
				
			||||
use Xabbuh\XApi\Model\IRL; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * @ORM\Table(name="xapi_actor") | 
				
			||||
 * @ORM\Entity() | 
				
			||||
 */ | 
				
			||||
class Actor | 
				
			||||
{ | 
				
			||||
    /** | 
				
			||||
     * @var int | 
				
			||||
     * | 
				
			||||
     * @ORM\Id() | 
				
			||||
     * @ORM\GeneratedValue() | 
				
			||||
     * @ORM\Column(type="integer") | 
				
			||||
     */ | 
				
			||||
    public $identifier; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $type; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $mbox; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $mboxSha1Sum; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $openId; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $accountName; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $accountHomePage; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $name; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Actor[]|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column() | 
				
			||||
     */ | 
				
			||||
    public $members; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param \Xabbuh\XApi\Model\Actor $model | 
				
			||||
     * | 
				
			||||
     * @return \Chamilo\PluginBundle\Entity\XApi\Lrs\Actor | 
				
			||||
     */ | 
				
			||||
    public static function fromModel(ActorModel $model) | 
				
			||||
    { | 
				
			||||
        $inverseFunctionalIdentifier = $model->getInverseFunctionalIdentifier(); | 
				
			||||
 | 
				
			||||
        $actor = new self(); | 
				
			||||
        $actor->mboxSha1Sum = $inverseFunctionalIdentifier->getMboxSha1Sum(); | 
				
			||||
        $actor->openId = $inverseFunctionalIdentifier->getOpenId(); | 
				
			||||
 | 
				
			||||
        if (null !== $mbox = $inverseFunctionalIdentifier->getMbox()) { | 
				
			||||
            $actor->mbox = $mbox->getValue(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $account = $inverseFunctionalIdentifier->getAccount()) { | 
				
			||||
            $actor->accountName = $account->getName(); | 
				
			||||
            $actor->accountHomePage = $account->getHomePage()->getValue(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($model instanceof Group) { | 
				
			||||
            $actor->type = 'group'; | 
				
			||||
            $actor->members = array(); | 
				
			||||
 | 
				
			||||
            foreach ($model->getMembers() as $agent) { | 
				
			||||
                $actor->members[] = Actor::fromModel($agent); | 
				
			||||
            } | 
				
			||||
        } else { | 
				
			||||
            $actor->type = 'agent'; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $actor; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @return \Xabbuh\XApi\Model\Agent|\Xabbuh\XApi\Model\Group | 
				
			||||
     */ | 
				
			||||
    public function getModel() | 
				
			||||
    { | 
				
			||||
        $inverseFunctionalIdentifier = null; | 
				
			||||
 | 
				
			||||
        if (null !== $this->mbox) { | 
				
			||||
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withMbox(IRI::fromString($this->mbox)); | 
				
			||||
        } elseif (null !== $this->mboxSha1Sum) { | 
				
			||||
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withMboxSha1Sum($this->mboxSha1Sum); | 
				
			||||
        } elseif (null !== $this->openId) { | 
				
			||||
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withOpenId($this->openId); | 
				
			||||
        } elseif (null !== $this->accountName && null !== $this->accountHomePage) { | 
				
			||||
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withAccount(new Account($this->accountName, IRL::fromString($this->accountHomePage))); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ('group' === $this->type) { | 
				
			||||
            $members = array(); | 
				
			||||
 | 
				
			||||
            foreach ($this->members as $agent) { | 
				
			||||
                $members[] = $agent->getModel(); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            return new Group($inverseFunctionalIdentifier, $this->name, $members); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return new Agent($inverseFunctionalIdentifier, $this->name); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,163 +0,0 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace Chamilo\PluginBundle\Entity\XApi\Lrs; | 
				
			||||
 | 
				
			||||
use Doctrine\ORM\Mapping as ORM; | 
				
			||||
use Xabbuh\XApi\Model\Attachment as AttachmentModel; | 
				
			||||
use Xabbuh\XApi\Model\IRI; | 
				
			||||
use Xabbuh\XApi\Model\IRL; | 
				
			||||
use Xabbuh\XApi\Model\LanguageMap; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * @ORM\Table(name="xapi_attachment") | 
				
			||||
 * @ORM\Entity() | 
				
			||||
 */ | 
				
			||||
class Attachment | 
				
			||||
{ | 
				
			||||
    /** | 
				
			||||
     * @var int | 
				
			||||
     * | 
				
			||||
     * @ORM\Id() | 
				
			||||
     * @ORM\GeneratedValue() | 
				
			||||
     * @ORM\Column(type="integer") | 
				
			||||
     */ | 
				
			||||
    public $identifier; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @ORM\ManyToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Statement", inversedBy="attachments") | 
				
			||||
     */ | 
				
			||||
    public $statement; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string") | 
				
			||||
     */ | 
				
			||||
    public $usageType; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string") | 
				
			||||
     */ | 
				
			||||
    public $contentType; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var int | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="integer") | 
				
			||||
     */ | 
				
			||||
    public $length; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string") | 
				
			||||
     */ | 
				
			||||
    public $sha2; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var array | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="json") | 
				
			||||
     */ | 
				
			||||
    public $display; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var bool | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="boolean") | 
				
			||||
     */ | 
				
			||||
    public $hasDescription; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var array|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="json", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $description; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $fileUrl; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="text", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $content; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param \Xabbuh\XApi\Model\Attachment $model | 
				
			||||
     * | 
				
			||||
     * @return \Chamilo\PluginBundle\Entity\XApi\Lrs\Attachment | 
				
			||||
     */ | 
				
			||||
    public static function fromModel(AttachmentModel $model) | 
				
			||||
    { | 
				
			||||
        $attachment = new self(); | 
				
			||||
        $attachment->usageType = $model->getUsageType()->getValue(); | 
				
			||||
        $attachment->contentType = $model->getContentType(); | 
				
			||||
        $attachment->length = $model->getLength(); | 
				
			||||
        $attachment->sha2 = $model->getSha2(); | 
				
			||||
        $attachment->display = array(); | 
				
			||||
 | 
				
			||||
        if (null !== $model->getFileUrl()) { | 
				
			||||
            $attachment->fileUrl = $model->getFileUrl()->getValue(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        $attachment->content = $model->getContent(); | 
				
			||||
 | 
				
			||||
        $display = $model->getDisplay(); | 
				
			||||
 | 
				
			||||
        foreach ($display->languageTags() as $languageTag) { | 
				
			||||
            $attachment->display[$languageTag] = $display[$languageTag]; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $description = $model->getDescription()) { | 
				
			||||
            $attachment->hasDescription = true; | 
				
			||||
            $attachment->description = array(); | 
				
			||||
 | 
				
			||||
            foreach ($description->languageTags() as $languageTag) { | 
				
			||||
                $attachment->description[$languageTag] = $description[$languageTag]; | 
				
			||||
            } | 
				
			||||
        } else { | 
				
			||||
            $attachment->hasDescription = false; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $attachment; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @return \Xabbuh\XApi\Model\Attachment | 
				
			||||
     */ | 
				
			||||
    public function getModel() | 
				
			||||
    { | 
				
			||||
        $description = null; | 
				
			||||
        $fileUrl = null; | 
				
			||||
 | 
				
			||||
        if ($this->hasDescription) { | 
				
			||||
            $description = LanguageMap::create($this->description); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $this->fileUrl) { | 
				
			||||
            $fileUrl = IRL::fromString($this->fileUrl); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return new AttachmentModel(IRI::fromString($this->usageType), $this->contentType, $this->length, $this->sha2, LanguageMap::create($this->display), $description, $fileUrl, $this->content); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,268 +0,0 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace Chamilo\PluginBundle\Entity\XApi\Lrs; | 
				
			||||
 | 
				
			||||
use Doctrine\ORM\Mapping as ORM; | 
				
			||||
use Xabbuh\XApi\Model\Context as ContextModel; | 
				
			||||
use Xabbuh\XApi\Model\ContextActivities; | 
				
			||||
use Xabbuh\XApi\Model\StatementId; | 
				
			||||
use Xabbuh\XApi\Model\StatementReference; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * @ORM\Table(name="xapi_context") | 
				
			||||
 * @ORM\Entity() | 
				
			||||
 */ | 
				
			||||
class Context | 
				
			||||
{ | 
				
			||||
    /** | 
				
			||||
     * @var int | 
				
			||||
     * | 
				
			||||
     * @ORM\Id() | 
				
			||||
     * @ORM\GeneratedValue() | 
				
			||||
     * @ORM\Column(type="integer") | 
				
			||||
     */ | 
				
			||||
    public $identifier; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $registration; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $instructor; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $team; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var bool|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(name="hasContextActivities", type="boolean", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $hasContextActivities; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject[]|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToMany(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", mappedBy="parentContext", cascade={"ALL"}) | 
				
			||||
     */ | 
				
			||||
    public $parentActivities; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject[]|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToMany(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", mappedBy="groupingContext", cascade={"ALL"}) | 
				
			||||
     */ | 
				
			||||
    public $groupingActivities; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject[]|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToMany(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", mappedBy="categoryContext", cascade={"ALL"}) | 
				
			||||
     */ | 
				
			||||
    public $categoryActivities; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject[]|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToMany(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", mappedBy="otherContext", cascade={"ALL"}) | 
				
			||||
     */ | 
				
			||||
    public $otherActivities; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $revision; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $platform; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $language; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $statement; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Extensions|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Extensions", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $extensions; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param \Xabbuh\XApi\Model\Context $model | 
				
			||||
     * | 
				
			||||
     * @return \Chamilo\PluginBundle\Entity\XApi\Lrs\Context | 
				
			||||
     */ | 
				
			||||
    public static function fromModel(ContextModel $model) | 
				
			||||
    { | 
				
			||||
        $context = new self(); | 
				
			||||
        $context->registration = $model->getRegistration(); | 
				
			||||
        $context->revision = $model->getRevision(); | 
				
			||||
        $context->platform = $model->getPlatform(); | 
				
			||||
        $context->language = $model->getLanguage(); | 
				
			||||
 | 
				
			||||
        if (null !== $instructor = $model->getInstructor()) { | 
				
			||||
            $context->instructor = StatementObject::fromModel($instructor); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $team = $model->getTeam()) { | 
				
			||||
            $context->team = StatementObject::fromModel($team); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $contextActivities = $model->getContextActivities()) { | 
				
			||||
            $context->hasContextActivities = true; | 
				
			||||
 | 
				
			||||
            if (null !== $parentActivities = $contextActivities->getParentActivities()) { | 
				
			||||
                $context->parentActivities = array(); | 
				
			||||
 | 
				
			||||
                foreach ($parentActivities as $parentActivity) { | 
				
			||||
                    $activity = StatementObject::fromModel($parentActivity); | 
				
			||||
                    $activity->parentContext = $context; | 
				
			||||
                    $context->parentActivities[] = $activity; | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $groupingActivities = $contextActivities->getGroupingActivities()) { | 
				
			||||
                $context->groupingActivities = array(); | 
				
			||||
 | 
				
			||||
                foreach ($groupingActivities as $groupingActivity) { | 
				
			||||
                    $activity = StatementObject::fromModel($groupingActivity); | 
				
			||||
                    $activity->groupingContext = $context; | 
				
			||||
                    $context->groupingActivities[] = $activity; | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $categoryActivities = $contextActivities->getCategoryActivities()) { | 
				
			||||
                $context->categoryActivities = array(); | 
				
			||||
 | 
				
			||||
                foreach ($categoryActivities as $categoryActivity) { | 
				
			||||
                    $activity = StatementObject::fromModel($categoryActivity); | 
				
			||||
                    $activity->categoryContext = $context; | 
				
			||||
                    $context->categoryActivities[] = $activity; | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $otherActivities = $contextActivities->getOtherActivities()) { | 
				
			||||
                $context->otherActivities = array(); | 
				
			||||
 | 
				
			||||
                foreach ($otherActivities as $otherActivity) { | 
				
			||||
                    $activity = StatementObject::fromModel($otherActivity); | 
				
			||||
                    $activity->otherContext = $context; | 
				
			||||
                    $context->otherActivities[] = $activity; | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
        } else { | 
				
			||||
            $context->hasContextActivities = false; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $statementReference = $model->getStatement()) { | 
				
			||||
            $context->statement = $statementReference->getStatementId()->getValue(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $contextExtensions = $model->getExtensions()) { | 
				
			||||
            $context->extensions = Extensions::fromModel($contextExtensions); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $context; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @return \Xabbuh\XApi\Model\Context | 
				
			||||
     */ | 
				
			||||
    public function getModel() | 
				
			||||
    { | 
				
			||||
        $context = new ContextModel(); | 
				
			||||
        $context = $context->withRegistration($this->registration); | 
				
			||||
        $context = $context->withRevision($this->revision); | 
				
			||||
        $context = $context->withPlatform($this->platform); | 
				
			||||
        $context = $context->withLanguage($this->language); | 
				
			||||
 | 
				
			||||
        if (null !== $this->instructor) { | 
				
			||||
            $context = $context->withInstructor($this->instructor->getModel()); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $this->team) { | 
				
			||||
            $context = $context->withTeam($this->team->getModel()); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($this->hasContextActivities) { | 
				
			||||
            $contextActivities = new ContextActivities(); | 
				
			||||
 | 
				
			||||
            if (null !== $this->parentActivities) { | 
				
			||||
                foreach ($this->parentActivities as $contextParentActivity) { | 
				
			||||
                    $contextActivities = $contextActivities->withAddedParentActivity($contextParentActivity->getModel()); | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $this->groupingActivities) { | 
				
			||||
                foreach ($this->groupingActivities as $contextGroupingActivity) { | 
				
			||||
                    $contextActivities = $contextActivities->withAddedGroupingActivity($contextGroupingActivity->getModel()); | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $this->categoryActivities) { | 
				
			||||
                foreach ($this->categoryActivities as $contextCategoryActivity) { | 
				
			||||
                    $contextActivities = $contextActivities->withAddedCategoryActivity($contextCategoryActivity->getModel()); | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $this->otherActivities) { | 
				
			||||
                foreach ($this->otherActivities as $contextOtherActivity) { | 
				
			||||
                    $contextActivities = $contextActivities->withAddedOtherActivity($contextOtherActivity->getModel()); | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            $context = $context->withContextActivities($contextActivities); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $this->statement) { | 
				
			||||
            $context = $context->withStatement(new StatementReference(StatementId::fromString($this->statement))); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $this->extensions) { | 
				
			||||
            $context = $context->withExtensions($this->extensions->getModel()); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $context; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,71 +0,0 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace Chamilo\PluginBundle\Entity\XApi\Lrs; | 
				
			||||
 | 
				
			||||
use Doctrine\ORM\Mapping as ORM; | 
				
			||||
use Xabbuh\XApi\Model\Extensions as ExtensionsModel; | 
				
			||||
use Xabbuh\XApi\Model\IRI; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * @ORM\Table(name="xapi_extensions") | 
				
			||||
 * @ORM\Entity() | 
				
			||||
 */ | 
				
			||||
class Extensions | 
				
			||||
{ | 
				
			||||
    /** | 
				
			||||
     * @var int | 
				
			||||
     * | 
				
			||||
     * @ORM\Id() | 
				
			||||
     * @ORM\GeneratedValue() | 
				
			||||
     * @ORM\Column(type="integer") | 
				
			||||
     */ | 
				
			||||
    public $identifier; | 
				
			||||
    /** | 
				
			||||
     * @var array | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="json") | 
				
			||||
     */ | 
				
			||||
    public $extensions; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param \Xabbuh\XApi\Model\Extensions $model | 
				
			||||
     * | 
				
			||||
     * @return \Chamilo\PluginBundle\Entity\XApi\Lrs\Extensions | 
				
			||||
     */ | 
				
			||||
    public static function fromModel(ExtensionsModel $model) | 
				
			||||
    { | 
				
			||||
        $extensions = new self(); | 
				
			||||
        $extensions->extensions = array(); | 
				
			||||
 | 
				
			||||
        foreach ($model->getExtensions() as $key) { | 
				
			||||
            $extensions->extensions[$key->getValue()] = $model[$key]; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $extensions; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @return \Xabbuh\XApi\Model\Extensions | 
				
			||||
     */ | 
				
			||||
    public function getModel() | 
				
			||||
    { | 
				
			||||
        $extensions = new \SplObjectStorage(); | 
				
			||||
 | 
				
			||||
        foreach ($this->extensions as $key => $extension) { | 
				
			||||
            $extensions->attach(IRI::fromString($key), $extension); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return new ExtensionsModel($extensions); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,154 +0,0 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace Chamilo\PluginBundle\Entity\XApi\Lrs; | 
				
			||||
 | 
				
			||||
use Doctrine\ORM\Mapping as ORM; | 
				
			||||
use Xabbuh\XApi\Model\Result as ResultModel; | 
				
			||||
use Xabbuh\XApi\Model\Score; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * @ORM\Table(name="xapi_result") | 
				
			||||
 * @ORM\Entity() | 
				
			||||
 */ | 
				
			||||
class Result | 
				
			||||
{ | 
				
			||||
    /** | 
				
			||||
     * @var int | 
				
			||||
     * | 
				
			||||
     * @ORM\Id() | 
				
			||||
     * @ORM\GeneratedValue() | 
				
			||||
     * @ORM\Column(type="integer") | 
				
			||||
     */ | 
				
			||||
    public $identifier; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var bool | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="boolean") | 
				
			||||
     */ | 
				
			||||
    public $hasScore; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var float|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="float", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $scaled; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var float|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="float", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $raw; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var float|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="float", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $min; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var float|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="float", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $max; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var bool|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="boolean", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $success; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var bool|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="boolean", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $completion; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $response; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $duration; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Extensions|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Extensions", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $extensions; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param \Xabbuh\XApi\Model\Result $model | 
				
			||||
     * | 
				
			||||
     * @return \Chamilo\PluginBundle\Entity\XApi\Lrs\Result | 
				
			||||
     */ | 
				
			||||
    public static function fromModel(ResultModel $model) | 
				
			||||
    { | 
				
			||||
        $result = new self(); | 
				
			||||
        $result->success = $model->getSuccess(); | 
				
			||||
        $result->completion = $model->getCompletion(); | 
				
			||||
        $result->response = $model->getResponse(); | 
				
			||||
        $result->duration = $model->getDuration(); | 
				
			||||
 | 
				
			||||
        if (null !== $score = $model->getScore()) { | 
				
			||||
            $result->hasScore = true; | 
				
			||||
            $result->scaled = $score->getScaled(); | 
				
			||||
            $result->raw = $score->getRaw(); | 
				
			||||
            $result->min = $score->getMin(); | 
				
			||||
            $result->max = $score->getMax(); | 
				
			||||
        } else { | 
				
			||||
            $result->hasScore = false; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $extensions = $model->getExtensions()) { | 
				
			||||
            $result->extensions = Extensions::fromModel($extensions); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $result; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @return \Xabbuh\XApi\Model\Result | 
				
			||||
     */ | 
				
			||||
    public function getModel() | 
				
			||||
    { | 
				
			||||
        $score = null; | 
				
			||||
        $extensions = null; | 
				
			||||
 | 
				
			||||
        if ($this->hasScore) { | 
				
			||||
            $score = new Score($this->scaled, $this->raw, $this->min, $this->max); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $this->extensions) { | 
				
			||||
            $extensions = $this->extensions->getModel(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return new ResultModel($score, $this->success, $this->completion, $this->response, $this->duration, $extensions); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,212 +0,0 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace Chamilo\PluginBundle\Entity\XApi\Lrs; | 
				
			||||
 | 
				
			||||
use Doctrine\ORM\Mapping as ORM; | 
				
			||||
use Xabbuh\XApi\Model\Statement as StatementModel; | 
				
			||||
use Xabbuh\XApi\Model\StatementId; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * A {@link Statement} mapped to a storage backend. | 
				
			||||
 * | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * @ORM\Table(name="xapi_statement") | 
				
			||||
 * @ORM\Entity() | 
				
			||||
 */ | 
				
			||||
class Statement | 
				
			||||
{ | 
				
			||||
    /** | 
				
			||||
     * @var string | 
				
			||||
     * | 
				
			||||
     * @ORM\Id() | 
				
			||||
     * @ORM\GeneratedValue(strategy="NONE") | 
				
			||||
     * @ORM\Column(type="string") | 
				
			||||
     */ | 
				
			||||
    public $id; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $actor; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Verb | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Verb", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $verb; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $object; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Result | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Result", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $result; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $authority; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var int | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="bigint", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $created; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var int | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="bigint", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $stored; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Context | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Context", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $context; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var bool | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="boolean", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $hasAttachments; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Attachment[]|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToMany(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Attachment", mappedBy="statement", cascade={"ALL"}) | 
				
			||||
     */ | 
				
			||||
    public $attachments; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param \Xabbuh\XApi\Model\Statement $model | 
				
			||||
     * | 
				
			||||
     * @return \Chamilo\PluginBundle\Entity\XApi\Lrs\Statement | 
				
			||||
     */ | 
				
			||||
    public static function fromModel(StatementModel $model) | 
				
			||||
    { | 
				
			||||
        $statement = new self(); | 
				
			||||
        $statement->id = $model->getId()->getValue(); | 
				
			||||
        $statement->actor = StatementObject::fromModel($model->getActor()); | 
				
			||||
        $statement->verb = Verb::fromModel($model->getVerb()); | 
				
			||||
        $statement->object = StatementObject::fromModel($model->getObject()); | 
				
			||||
 | 
				
			||||
        if (null !== $model->getCreated()) { | 
				
			||||
            $statement->created = $model->getCreated()->getTimestamp(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $result = $model->getResult()) { | 
				
			||||
            $statement->result = Result::fromModel($result); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $authority = $model->getAuthority()) { | 
				
			||||
            $statement->authority = StatementObject::fromModel($authority); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $context = $model->getContext()) { | 
				
			||||
            $statement->context = Context::fromModel($context); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $attachments = $model->getAttachments()) { | 
				
			||||
            $statement->hasAttachments = true; | 
				
			||||
            $statement->attachments = array(); | 
				
			||||
 | 
				
			||||
            foreach ($attachments as $attachment) { | 
				
			||||
                $mappedAttachment = Attachment::fromModel($attachment); | 
				
			||||
                $mappedAttachment->statement = $statement; | 
				
			||||
                $statement->attachments[] = $mappedAttachment; | 
				
			||||
            } | 
				
			||||
        } else { | 
				
			||||
            $statement->hasAttachments = false; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $statement; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @throws \Exception | 
				
			||||
     * @return \Xabbuh\XApi\Model\Statement | 
				
			||||
     */ | 
				
			||||
    public function getModel() | 
				
			||||
    { | 
				
			||||
        $result = null; | 
				
			||||
        $authority = null; | 
				
			||||
        $created = null; | 
				
			||||
        $stored = null; | 
				
			||||
        $context = null; | 
				
			||||
        $attachments = null; | 
				
			||||
 | 
				
			||||
        if (null !== $this->result) { | 
				
			||||
            $result = $this->result->getModel(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $this->authority) { | 
				
			||||
            $authority = $this->authority->getModel(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $this->created) { | 
				
			||||
            $created = new \DateTime('@'.$this->created); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $this->stored) { | 
				
			||||
            $stored = new \DateTime('@'.$this->stored); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $this->context) { | 
				
			||||
            $context = $this->context->getModel(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($this->hasAttachments) { | 
				
			||||
            $attachments = array(); | 
				
			||||
 | 
				
			||||
            foreach ($this->attachments as $attachment) { | 
				
			||||
                $attachments[] = $attachment->getModel(); | 
				
			||||
            } | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return new StatementModel( | 
				
			||||
            StatementId::fromString($this->id), | 
				
			||||
            $this->actor->getModel(), | 
				
			||||
            $this->verb->getModel(), | 
				
			||||
            $this->object->getModel(), | 
				
			||||
            $result, | 
				
			||||
            $authority, | 
				
			||||
            $created, | 
				
			||||
            $stored, | 
				
			||||
            $context, | 
				
			||||
            $attachments | 
				
			||||
        ); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,496 +0,0 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace Chamilo\PluginBundle\Entity\XApi\Lrs; | 
				
			||||
 | 
				
			||||
use Doctrine\ORM\Mapping as ORM; | 
				
			||||
use Xabbuh\XApi\Model\Account; | 
				
			||||
use Xabbuh\XApi\Model\Activity; | 
				
			||||
use Xabbuh\XApi\Model\Actor as ActorModel; | 
				
			||||
use Xabbuh\XApi\Model\Agent; | 
				
			||||
use Xabbuh\XApi\Model\Definition; | 
				
			||||
use Xabbuh\XApi\Model\Group; | 
				
			||||
use Xabbuh\XApi\Model\InverseFunctionalIdentifier; | 
				
			||||
use Xabbuh\XApi\Model\IRI; | 
				
			||||
use Xabbuh\XApi\Model\IRL; | 
				
			||||
use Xabbuh\XApi\Model\LanguageMap; | 
				
			||||
use Xabbuh\XApi\Model\Object as ObjectModel; | 
				
			||||
use Xabbuh\XApi\Model\StatementObject as StatementObjectModel; | 
				
			||||
use Xabbuh\XApi\Model\StatementId; | 
				
			||||
use Xabbuh\XApi\Model\StatementReference; | 
				
			||||
use Xabbuh\XApi\Model\SubStatement; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * @ORM\Table(name="xapi_object") | 
				
			||||
 * @ORM\Entity() | 
				
			||||
 */ | 
				
			||||
class StatementObject | 
				
			||||
{ | 
				
			||||
    const TYPE_ACTIVITY = 'activity'; | 
				
			||||
    const TYPE_AGENT = 'agent'; | 
				
			||||
    const TYPE_GROUP = 'group'; | 
				
			||||
    const TYPE_STATEMENT_REFERENCE = 'statement_reference'; | 
				
			||||
    const TYPE_SUB_STATEMENT = 'sub_statement'; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var int | 
				
			||||
     * | 
				
			||||
     * @ORM\Id() | 
				
			||||
     * @ORM\GeneratedValue() | 
				
			||||
     * @ORM\Column(type="integer") | 
				
			||||
     */ | 
				
			||||
    public $identifier; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $type; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $activityId; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var bool|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="boolean", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $hasActivityDefinition; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var bool|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="boolean", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $hasActivityName; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var array|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="json", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $activityName; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var bool|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="boolean", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $hasActivityDescription; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var array|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="json", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $activityDescription; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $activityType; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $activityMoreInfo; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Extensions|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Extensions", cascade={"all"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $activityExtensions; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $mbox; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $mboxSha1Sum; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $openId; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $accountName; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $accountHomePage; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $name; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject[]|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToMany(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", mappedBy="group") | 
				
			||||
     */ | 
				
			||||
    public $members; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject|null | 
				
			||||
     * | 
				
			||||
     * @ORM\ManyToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", inversedBy="members") | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $group; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(name="referenced_statement_id", type="string", nullable=true) | 
				
			||||
     */ | 
				
			||||
    public $referencedStatementId; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $actor; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Verb|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Verb", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $verb; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var StatementObject|null | 
				
			||||
     * | 
				
			||||
     * @ORM\OneToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject", cascade={"ALL"}) | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $object; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Result|null | 
				
			||||
     */ | 
				
			||||
    public $result; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Context|null | 
				
			||||
     */ | 
				
			||||
    public $context; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Statement|null | 
				
			||||
     * | 
				
			||||
     * @ORM\ManyToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Context", inversedBy="parentActivities") | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $parentContext; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Statement|null | 
				
			||||
     * | 
				
			||||
     * @ORM\ManyToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Context", inversedBy="groupingActivities") | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $groupingContext; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Statement|null | 
				
			||||
     * | 
				
			||||
     * @ORM\ManyToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Context", inversedBy="categoryActivities") | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $categoryContext; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var Statement|null | 
				
			||||
     * | 
				
			||||
     * @ORM\ManyToOne(targetEntity="Chamilo\PluginBundle\Entity\XApi\Lrs\Context", inversedBy="otherActivities") | 
				
			||||
     * @ORM\JoinColumn(referencedColumnName="identifier") | 
				
			||||
     */ | 
				
			||||
    public $otherContext; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param $model | 
				
			||||
     * | 
				
			||||
     * @return \Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject | 
				
			||||
     */ | 
				
			||||
    public static function fromModel($model) | 
				
			||||
    { | 
				
			||||
        if (!$model instanceof ObjectModel && !$model instanceof StatementObjectModel) { | 
				
			||||
            throw new \InvalidArgumentException(sprintf('Expected a statement object but got %s', is_object($model) ? get_class($model) : gettype($model))); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($model instanceof ActorModel) { | 
				
			||||
            return self::fromActor($model); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($model instanceof StatementReference) { | 
				
			||||
            $object = new self(); | 
				
			||||
            $object->type = self::TYPE_STATEMENT_REFERENCE; | 
				
			||||
            $object->referencedStatementId = $model->getStatementId()->getValue(); | 
				
			||||
 | 
				
			||||
            return $object; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($model instanceof SubStatement) { | 
				
			||||
            return self::fromSubStatement($model); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return self::fromActivity($model); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @return \Xabbuh\XApi\Model\StatementObject | 
				
			||||
     */ | 
				
			||||
    public function getModel() | 
				
			||||
    { | 
				
			||||
        if (self::TYPE_AGENT === $this->type || self::TYPE_GROUP === $this->type) { | 
				
			||||
            return $this->getActorModel(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (self::TYPE_STATEMENT_REFERENCE === $this->type) { | 
				
			||||
            return new StatementReference(StatementId::fromString($this->referencedStatementId)); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (self::TYPE_SUB_STATEMENT === $this->type) { | 
				
			||||
            return $this->getSubStatementModel(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $this->getActivityModel(); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param \Xabbuh\XApi\Model\Activity $model | 
				
			||||
     * | 
				
			||||
     * @return \Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject | 
				
			||||
     */ | 
				
			||||
    private static function fromActivity(Activity $model) | 
				
			||||
    { | 
				
			||||
        $object = new self(); | 
				
			||||
        $object->activityId = $model->getId()->getValue(); | 
				
			||||
 | 
				
			||||
        if (null !== $definition = $model->getDefinition()) { | 
				
			||||
            $object->hasActivityDefinition = true; | 
				
			||||
 | 
				
			||||
            if (null !== $name = $definition->getName()) { | 
				
			||||
                $object->hasActivityName = true; | 
				
			||||
                $object->activityName = array(); | 
				
			||||
 | 
				
			||||
                foreach ($name->languageTags() as $languageTag) { | 
				
			||||
                    $object->activityName[$languageTag] = $name[$languageTag]; | 
				
			||||
                } | 
				
			||||
            } else { | 
				
			||||
                $object->hasActivityName = false; | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $description = $definition->getDescription()) { | 
				
			||||
                $object->hasActivityDescription = true; | 
				
			||||
                $object->activityDescription = array(); | 
				
			||||
 | 
				
			||||
                foreach ($description->languageTags() as $languageTag) { | 
				
			||||
                    $object->activityDescription[$languageTag] = $description[$languageTag]; | 
				
			||||
                } | 
				
			||||
            } else { | 
				
			||||
                $object->hasActivityDescription = false; | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $type = $definition->getType()) { | 
				
			||||
                $object->activityType = $type->getValue(); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $moreInfo = $definition->getMoreInfo()) { | 
				
			||||
                $object->activityMoreInfo = $moreInfo->getValue(); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $extensions = $definition->getExtensions()) { | 
				
			||||
                $object->activityExtensions = Extensions::fromModel($extensions); | 
				
			||||
            } | 
				
			||||
        } else { | 
				
			||||
            $object->hasActivityDefinition = false; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $object; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param \Xabbuh\XApi\Model\Actor $model | 
				
			||||
     * | 
				
			||||
     * @return \Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject | 
				
			||||
     */ | 
				
			||||
    private static function fromActor(ActorModel $model) | 
				
			||||
    { | 
				
			||||
        $inverseFunctionalIdentifier = $model->getInverseFunctionalIdentifier(); | 
				
			||||
 | 
				
			||||
        $object = new self(); | 
				
			||||
        $object->mboxSha1Sum = $inverseFunctionalIdentifier->getMboxSha1Sum(); | 
				
			||||
        $object->openId = $inverseFunctionalIdentifier->getOpenId(); | 
				
			||||
 | 
				
			||||
        if (null !== $mbox = $inverseFunctionalIdentifier->getMbox()) { | 
				
			||||
            $object->mbox = $mbox->getValue(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (null !== $account = $inverseFunctionalIdentifier->getAccount()) { | 
				
			||||
            $object->accountName = $account->getName(); | 
				
			||||
            $object->accountHomePage = $account->getHomePage()->getValue(); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if ($model instanceof Group) { | 
				
			||||
            $object->type = self::TYPE_GROUP; | 
				
			||||
            $object->members = array(); | 
				
			||||
 | 
				
			||||
            foreach ($model->getMembers() as $agent) { | 
				
			||||
                $object->members[] = self::fromActor($agent); | 
				
			||||
            } | 
				
			||||
        } else { | 
				
			||||
            $object->type = self::TYPE_AGENT; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $object; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param \Xabbuh\XApi\Model\SubStatement $model | 
				
			||||
     * | 
				
			||||
     * @return \Chamilo\PluginBundle\Entity\XApi\Lrs\StatementObject | 
				
			||||
     */ | 
				
			||||
    private static function fromSubStatement(SubStatement $model) | 
				
			||||
    { | 
				
			||||
        $object = new self(); | 
				
			||||
        $object->type = self::TYPE_SUB_STATEMENT; | 
				
			||||
        $object->actor = StatementObject::fromModel($model->getActor()); | 
				
			||||
        $object->verb = Verb::fromModel($model->getVerb()); | 
				
			||||
        $object->object = StatementObject::fromModel($model->getObject()); | 
				
			||||
 | 
				
			||||
        return $object; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @return \Xabbuh\XApi\Model\Activity | 
				
			||||
     */ | 
				
			||||
    private function getActivityModel() | 
				
			||||
    { | 
				
			||||
        $definition = null; | 
				
			||||
        $type = null; | 
				
			||||
        $moreInfo = null; | 
				
			||||
 | 
				
			||||
        if ($this->hasActivityDefinition) { | 
				
			||||
            $name = null; | 
				
			||||
            $description = null; | 
				
			||||
            $extensions = null; | 
				
			||||
 | 
				
			||||
            if ($this->hasActivityName) { | 
				
			||||
                $name = LanguageMap::create($this->activityName); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if ($this->hasActivityDescription) { | 
				
			||||
                $description = LanguageMap::create($this->activityDescription); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $this->activityType) { | 
				
			||||
                $type = IRI::fromString($this->activityType); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $this->activityMoreInfo) { | 
				
			||||
                $moreInfo = IRL::fromString($this->activityMoreInfo); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (null !== $this->activityExtensions) { | 
				
			||||
                $extensions = $this->activityExtensions->getModel(); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            $definition = new Definition($name, $description, $type, $moreInfo, $extensions); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return new Activity(IRI::fromString($this->activityId), $definition); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @return \Xabbuh\XApi\Model\Agent|\Xabbuh\XApi\Model\Group | 
				
			||||
     */ | 
				
			||||
    private function getActorModel() | 
				
			||||
    { | 
				
			||||
        $inverseFunctionalIdentifier = null; | 
				
			||||
 | 
				
			||||
        if (null !== $this->mbox) { | 
				
			||||
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withMbox(IRI::fromString($this->mbox)); | 
				
			||||
        } elseif (null !== $this->mboxSha1Sum) { | 
				
			||||
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withMboxSha1Sum($this->mboxSha1Sum); | 
				
			||||
        } elseif (null !== $this->openId) { | 
				
			||||
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withOpenId($this->openId); | 
				
			||||
        } elseif (null !== $this->accountName && null !== $this->accountHomePage) { | 
				
			||||
            $inverseFunctionalIdentifier = InverseFunctionalIdentifier::withAccount(new Account($this->accountName, IRL::fromString($this->accountHomePage))); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if (self::TYPE_GROUP === $this->type) { | 
				
			||||
            $members = array(); | 
				
			||||
 | 
				
			||||
            foreach ($this->members as $agent) { | 
				
			||||
                $members[] = $agent->getModel(); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            return new Group($inverseFunctionalIdentifier, $this->name, $members); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return new Agent($inverseFunctionalIdentifier, $this->name); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @return \Xabbuh\XApi\Model\SubStatement | 
				
			||||
     */ | 
				
			||||
    private function getSubStatementModel() | 
				
			||||
    { | 
				
			||||
        $result = null; | 
				
			||||
        $context = null; | 
				
			||||
 | 
				
			||||
        return new SubStatement( | 
				
			||||
            $this->actor->getModel(), | 
				
			||||
            $this->verb->getModel(), | 
				
			||||
            $this->object->getModel(), | 
				
			||||
            $result, | 
				
			||||
            $context | 
				
			||||
        ); | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
@ -1,86 +0,0 @@ | 
				
			||||
<?php | 
				
			||||
 | 
				
			||||
/* | 
				
			||||
 * This file is part of the xAPI package. | 
				
			||||
 * | 
				
			||||
 * (c) Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * For the full copyright and license information, please view the LICENSE | 
				
			||||
 * file that was distributed with this source code. | 
				
			||||
 */ | 
				
			||||
 | 
				
			||||
namespace Chamilo\PluginBundle\Entity\XApi\Lrs; | 
				
			||||
 | 
				
			||||
use Doctrine\ORM\Mapping as ORM; | 
				
			||||
use Xabbuh\XApi\Model\IRI; | 
				
			||||
use Xabbuh\XApi\Model\LanguageMap; | 
				
			||||
use Xabbuh\XApi\Model\Verb as VerbModel; | 
				
			||||
 | 
				
			||||
/** | 
				
			||||
 * A {@link Verb} mapped to a storage backend. | 
				
			||||
 * | 
				
			||||
 * @author Christian Flothmann <christian.flothmann@xabbuh.de> | 
				
			||||
 * | 
				
			||||
 * @ORM\Table(name="xapi_verb") | 
				
			||||
 * @ORM\Entity() | 
				
			||||
 */ | 
				
			||||
class Verb | 
				
			||||
{ | 
				
			||||
    /** | 
				
			||||
     * @var int | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="integer") | 
				
			||||
     * @ORM\Id() | 
				
			||||
     * @ORM\GeneratedValue() | 
				
			||||
     */ | 
				
			||||
    public $identifier; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var string | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="string") | 
				
			||||
     */ | 
				
			||||
    public $id; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @var array|null | 
				
			||||
     * | 
				
			||||
     * @ORM\Column(type="json") | 
				
			||||
     */ | 
				
			||||
    public $display; | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @return \Xabbuh\XApi\Model\Verb | 
				
			||||
     */ | 
				
			||||
    public function getModel() | 
				
			||||
    { | 
				
			||||
        $display = null; | 
				
			||||
 | 
				
			||||
        if (null !== $this->display) { | 
				
			||||
            $display = LanguageMap::create($this->display); | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return new VerbModel(IRI::fromString($this->id), $display); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    /** | 
				
			||||
     * @param \Xabbuh\XApi\Model\Verb $model | 
				
			||||
     * | 
				
			||||
     * @return \Chamilo\PluginBundle\Entity\XApi\Lrs\Verb | 
				
			||||
     */ | 
				
			||||
    public static function fromModel(VerbModel $model) | 
				
			||||
    { | 
				
			||||
        $verb = new self(); | 
				
			||||
        $verb->id = $model->getId()->getValue(); | 
				
			||||
 | 
				
			||||
        if (null !== $display = $model->getDisplay()) { | 
				
			||||
            $verb->display = array(); | 
				
			||||
 | 
				
			||||
            foreach ($display->languageTags() as $languageTag) { | 
				
			||||
                $verb->display[$languageTag] = $display[$languageTag]; | 
				
			||||
            } | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        return $verb; | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue