Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADR implementation, JSON-LD decoupling and content negociation support #191

Merged
merged 6 commits into from Jul 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
68 changes: 68 additions & 0 deletions Action/ActionUtilTrait.php
@@ -0,0 +1,68 @@
<?php

/*
* This file is part of the DunglasApiBundle package.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Dunglas\ApiBundle\Action;

use Dunglas\ApiBundle\Api\ResourceInterface;
use Dunglas\ApiBundle\Exception\RuntimeException;
use Dunglas\ApiBundle\Model\DataProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
* Checks if the request is properly configured.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
trait ActionUtilTrait
{
/**
* Gets an item using the data provider. Throws a 404 error if not found.
*
* @param DataProviderInterface $dataProvider
* @param ResourceInterface $resourceType
* @param string|int $id
*
* @return object
*
* @throws NotFoundHttpException
*/
private function getItem(DataProviderInterface $dataProvider, ResourceInterface $resourceType, $id)
{
$data = $dataProvider->getItem($resourceType, $id, true);
if (!$data) {
throw new NotFoundHttpException();
}

return $data;
}

/**
* Extract resource type and format request attributes. Throws an exception if the request does not contain required
* attributes.
*
* @param Request $request
*
* @return array
*
* @throws RuntimeException
*/
private function extractAttributes(Request $request)
{
$resourceType = $request->attributes->get('_resource_type');
$format = $request->attributes->get('_api_format');
if (!$resourceType || !$format) {
throw new RuntimeException('The API is not properly configured.');
}

return [$resourceType, $format];
}
}
55 changes: 55 additions & 0 deletions Action/DeleteItemAction.php
@@ -0,0 +1,55 @@
<?php

/*
* This file is part of the DunglasApiBundle package.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Dunglas\ApiBundle\Action;

use Dunglas\ApiBundle\Exception\RuntimeException;
use Dunglas\ApiBundle\Model\DataProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
* Default API action deleting a resource.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class DeleteItemAction
{
use ActionUtilTrait;

/**
* @var DataProviderInterface
*/
private $dataProvider;

public function __construct(DataProviderInterface $dataProvider)
{
$this->dataProvider = $dataProvider;
}

/**
* Returns an item to delete.
*
* @param Request $request
* @param string|int $id
*
* @return mixed
*
* @throws NotFoundHttpException
* @throws RuntimeException
*/
public function __invoke(Request $request, $id)
{
list($resourceType) = $this->extractAttributes($request);

return $this->getItem($this->dataProvider, $resourceType, $id);
}
}
52 changes: 52 additions & 0 deletions Action/GetCollectionAction.php
@@ -0,0 +1,52 @@
<?php

/*
* This file is part of the DunglasApiBundle package.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Dunglas\ApiBundle\Action;

use Dunglas\ApiBundle\Exception\RuntimeException;
use Dunglas\ApiBundle\Model\DataProviderInterface;
use Symfony\Component\HttpFoundation\Request;

/**
* Default API action retrieving a collection of resources.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class GetCollectionAction
{
use ActionUtilTrait;

/**
* @var DataProviderInterface
*/
private $dataProvider;

public function __construct(DataProviderInterface $dataProvider)
{
$this->dataProvider = $dataProvider;
}

/**
* Retrieves a collection of resources.
*
* @param Request $request
*
* @return array|\Dunglas\ApiBundle\Model\PaginatorInterface|\Traversable
*
* @throws RuntimeException
*/
public function __invoke(Request $request)
{
list($resourceType) = $this->extractAttributes($request);

return $this->dataProvider->getCollection($resourceType, $request);
}
}
55 changes: 55 additions & 0 deletions Action/GetItemAction.php
@@ -0,0 +1,55 @@
<?php

/*
* This file is part of the DunglasApiBundle package.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Dunglas\ApiBundle\Action;

use Dunglas\ApiBundle\Exception\RuntimeException;
use Dunglas\ApiBundle\Model\DataProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
* Default API action retrieving a resource.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class GetItemAction
{
use ActionUtilTrait;

/**
* @var DataProviderInterface
*/
private $dataProvider;

public function __construct(DataProviderInterface $dataProvider)
{
$this->dataProvider = $dataProvider;
}

/**
* Retrieves an item.
*
* @param Request $request
* @param string|int $id
*
* @return mixed
*
* @throws NotFoundHttpException
* @throws RuntimeException
*/
public function __invoke(Request $request, $id)
{
list($resourceType) = $this->extractAttributes($request);

return $this->getItem($this->dataProvider, $resourceType, $id);
}
}
63 changes: 63 additions & 0 deletions Action/PostItemAction.php
@@ -0,0 +1,63 @@
<?php

/*
* This file is part of the DunglasApiBundle package.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Dunglas\ApiBundle\Action;

use Dunglas\ApiBundle\Exception\RuntimeException;
use Dunglas\ApiBundle\Model\DataProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Serializer\SerializerInterface;

/**
* Add a new resource to a collection.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class PostItemAction
{
use ActionUtilTrait;

/**
* @var DataProviderInterface
*/
private $dataProvider;
/**
* @var SerializerInterface
*/
private $serializer;

public function __construct(DataProviderInterface $dataProvider, SerializerInterface $serializer)
{
$this->dataProvider = $dataProvider;
$this->serializer = $serializer;
}

/**
* Hydrate an item to persist.
*
* @param Request $request
*
* @return mixed
*
* @throws RuntimeException
*/
public function __invoke(Request $request)
{
list($resourceType, $format) = $this->extractAttributes($request);

return $this->serializer->deserialize(
$request->getContent(),
$resourceType->getEntityClass(),
$format,
$resourceType->getDenormalizationContext()
);
}
}
72 changes: 72 additions & 0 deletions Action/PutItemAction.php
@@ -0,0 +1,72 @@
<?php

/*
* This file is part of the DunglasApiBundle package.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Dunglas\ApiBundle\Action;

use Dunglas\ApiBundle\Exception\RuntimeException;
use Dunglas\ApiBundle\Model\DataProviderInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Serializer\SerializerInterface;

/**
* Updates a resource.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
class PutItemAction
{
use ActionUtilTrait;

/**
* @var DataProviderInterface
*/
private $dataProvider;
/**
* @var SerializerInterface
*/
private $serializer;

public function __construct(DataProviderInterface $dataProvider, SerializerInterface $serializer)
{
$this->dataProvider = $dataProvider;
$this->serializer = $serializer;
}

/**
* Create a new item.
*
* @param Request $request
* @param string|int $id
*
* @return mixed
*
* @throws NotFoundHttpException
* @throws RuntimeException
*/
public function __invoke(Request $request, $id)
{
list($resourceType, $format) = $this->extractAttributes($request);
$data = $this->getItem($this->dataProvider, $resourceType, $id);

$context = $resourceType->getDenormalizationContext();
$context['object_to_populate'] = $data;

$data = $this->serializer->deserialize(
$request->getContent(),
$resourceType->getEntityClass(),
$format,
$context
);

return $data;
}
}