Compare commits
3 Commits
c48fe53e6a
...
9413202660
| Author | SHA1 | Date | |
|---|---|---|---|
| 9413202660 | |||
| 215e325a8c | |||
| 9f8682c896 |
@@ -56,6 +56,7 @@ class AppKernel extends Kernel
|
||||
new JMS\SerializerBundle\JMSSerializerBundle(),
|
||||
new FOS\RestBundle\FOSRestBundle(),
|
||||
new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
|
||||
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(),
|
||||
];
|
||||
|
||||
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
|
||||
|
||||
@@ -238,12 +238,17 @@ fos_rest:
|
||||
view:
|
||||
formats: { json: true, xml: false, rss: false }
|
||||
view_response_listener: true
|
||||
mime_types:
|
||||
json: ['application/json', 'application/json;version=1.0', 'application/json;version=2.0']
|
||||
serializer:
|
||||
serialize_null: true
|
||||
format_listener:
|
||||
rules:
|
||||
- { path: '^/api/', priorities: ['json'], fallback_format: 'json' }
|
||||
param_fetcher_listener: true
|
||||
# versioning:
|
||||
# enabled: true
|
||||
# regex: '/(v|version)=(?P<version>[0-9\.]+)/'
|
||||
|
||||
# sensio_framework_extra:
|
||||
# view: { annotations: false }
|
||||
|
||||
@@ -5,12 +5,19 @@ security:
|
||||
fos_userbundle:
|
||||
#id: fos_user.user_provider.username_email
|
||||
id: app.user_provider
|
||||
|
||||
|
||||
firewalls:
|
||||
dev:
|
||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||
security: false
|
||||
|
||||
api:
|
||||
pattern: ^/api
|
||||
stateless: true
|
||||
simple_preauth:
|
||||
authenticator: app.api_key_authenticator
|
||||
provider: fos_userbundle
|
||||
|
||||
main:
|
||||
pattern: ^/
|
||||
remember_me:
|
||||
@@ -33,6 +40,8 @@ security:
|
||||
anonymous: true
|
||||
switch_user:
|
||||
provider: fos_userbundle
|
||||
|
||||
|
||||
access_control:
|
||||
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||
|
||||
@@ -79,3 +79,6 @@ services:
|
||||
app.user_provider:
|
||||
class: AppBundle\Security\Core\User\FOSUBUserProvider
|
||||
arguments: ["@fos_user.user_manager","@doctrine.orm.entity_manager","@mt.slug","@service_container", { facebook: facebookId, linkedin: linkedinId}]
|
||||
|
||||
app.api_key_authenticator:
|
||||
class: AppBundle\Security\ApiKeyAuthenticator
|
||||
|
||||
@@ -55,7 +55,8 @@
|
||||
"jms/serializer-bundle": "^2.4",
|
||||
"friendsofsymfony/rest-bundle": "^2.4",
|
||||
"symfony/twig-bundle": "^4.1",
|
||||
"white-october/pagerfanta-bundle": "^1.2"
|
||||
"white-october/pagerfanta-bundle": "^1.2",
|
||||
"willdurand/hateoas-bundle": "^1.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"sensio/generator-bundle": "^3.0",
|
||||
|
||||
Generated
+119
-1
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "452758fcee42c8c80f3c08ed2a0d3361",
|
||||
"content-hash": "fbdda65eb230886b1e84516b1efe5b55",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alcaeus/mongo-php-adapter",
|
||||
@@ -6090,6 +6090,124 @@
|
||||
],
|
||||
"time": "2018-06-20T09:32:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "willdurand/hateoas",
|
||||
"version": "2.12.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/willdurand/Hateoas.git",
|
||||
"reference": "71b1af62b398dc9a870ac0b16c84bdc23a76a5c5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/willdurand/Hateoas/zipball/71b1af62b398dc9a870ac0b16c84bdc23a76a5c5",
|
||||
"reference": "71b1af62b398dc9a870ac0b16c84bdc23a76a5c5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/annotations": "~1.0",
|
||||
"doctrine/common": "~2.0",
|
||||
"jms/metadata": "~1.1",
|
||||
"jms/serializer": "^1.7",
|
||||
"php": "^5.5|^7.0",
|
||||
"phpoption/phpoption": ">=1.1.0,<2.0-dev",
|
||||
"symfony/expression-language": "~2.4 || ~3.0 || ~4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"pagerfanta/pagerfanta": "~1.0",
|
||||
"phpunit/phpunit": "~5",
|
||||
"symfony/dependency-injection": "~2.4 || ~3.0 || ~4.0",
|
||||
"symfony/routing": "~2.4 || ~3.0 || ~4.0",
|
||||
"symfony/yaml": "~2.4 || ~3.0 || ~4.0",
|
||||
"twig/twig": "~1.12"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/routing": "To use the SymfonyRouteFactory.",
|
||||
"symfony/yaml": "To use yaml based configuration.",
|
||||
"twig/twig": "To use the Twig extensions."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.12-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Hateoas": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Adrien Brault",
|
||||
"email": "adrien.brault@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "William Durand",
|
||||
"email": "william.durand1@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A PHP library to support implementing representations for HATEOAS REST web services",
|
||||
"time": "2018-02-23T17:05:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "willdurand/hateoas-bundle",
|
||||
"version": "1.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/willdurand/BazingaHateoasBundle.git",
|
||||
"reference": "d1f915fd4f8a7cd43a88a0ce97ffb28abe3a94fa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/willdurand/BazingaHateoasBundle/zipball/d1f915fd4f8a7cd43a88a0ce97ffb28abe3a94fa",
|
||||
"reference": "d1f915fd4f8a7cd43a88a0ce97ffb28abe3a94fa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"jms/serializer-bundle": "~1.0 || ^2.0",
|
||||
"php": ">5.4 |^7.0",
|
||||
"symfony/framework-bundle": "~2.3 || ~3.0 || ~4.0",
|
||||
"willdurand/hateoas": "^2.10.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.5 || ~5.0",
|
||||
"symfony/expression-language": "~2.4 || ~3.0 || ~4.0",
|
||||
"symfony/stopwatch": "~2.4 || ~3.0 || ~4.0",
|
||||
"twig/twig": "~1.12"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Bazinga\\Bundle\\HateoasBundle\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "William Durand",
|
||||
"email": "william.durand1@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Integration of Hateoas into Symfony2.",
|
||||
"keywords": [
|
||||
"HATEOAS",
|
||||
"rest"
|
||||
],
|
||||
"time": "2018-01-27T13:03:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "willdurand/jsonp-callback-validator",
|
||||
"version": "v1.1.0",
|
||||
|
||||
@@ -13,16 +13,21 @@ use FOS\RestBundle\Request\ParamFetcherInterface;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
use AppBundle\Representation\SingleAd;
|
||||
|
||||
class AdController extends FOSRestController
|
||||
{
|
||||
/**
|
||||
* @Rest\Get(path="/api/ads/{id}", name="api_ad_show", requirements={"id"="\d+"})
|
||||
* @Rest\View
|
||||
*
|
||||
*/
|
||||
public function showAction(Ad $ad)
|
||||
{
|
||||
return $ad;
|
||||
// return $ad;
|
||||
return new SingleAd($ad);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@ use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use JMS\Serializer\Annotation\ExclusionPolicy;
|
||||
use JMS\Serializer\Annotation\Expose;
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
|
||||
/**
|
||||
* Ad
|
||||
@@ -19,6 +20,22 @@ use JMS\Serializer\Annotation\Expose;
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
*
|
||||
* @ExclusionPolicy("all")
|
||||
*
|
||||
* @Hateoas\Relation(
|
||||
* "self",
|
||||
* href = @Hateoas\Route(
|
||||
* "api_ad_show",
|
||||
* parameters = { "id" = "expr(object.getId())" },
|
||||
* absolute=true
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @Hateoas\Relation(
|
||||
* "company",
|
||||
* embedded = @Hateoas\Embedded("expr(object.getCompany())")
|
||||
* )
|
||||
*
|
||||
*
|
||||
*/
|
||||
class Ad
|
||||
{
|
||||
|
||||
@@ -9,6 +9,8 @@ use AppBundle\Utils\Traits\TagsJsonTrait;
|
||||
use AppBundle\Utils\Traits\TimestampableTrait;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use JMS\Serializer\Annotation\ExclusionPolicy;
|
||||
use JMS\Serializer\Annotation\Expose;
|
||||
|
||||
/**
|
||||
* Company
|
||||
@@ -16,6 +18,8 @@ use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
* @ORM\Table(name="company")
|
||||
* @ORM\Entity(repositoryClass="AppBundle\Repository\CompanyRepository")
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
*
|
||||
* @ExclusionPolicy("all")
|
||||
*/
|
||||
class Company
|
||||
{
|
||||
@@ -32,6 +36,7 @@ class Company
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
* @Expose
|
||||
*/
|
||||
private $id;
|
||||
|
||||
@@ -39,6 +44,7 @@ class Company
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(name="brand_name", type="string", length=255, options={"comment":"Nom commercial"}, nullable=true)
|
||||
* @Expose
|
||||
*/
|
||||
private $brandName;
|
||||
|
||||
@@ -67,6 +73,7 @@ class Company
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(name="logo", type="string", nullable=true)
|
||||
* @Expose
|
||||
*/
|
||||
private $logo;
|
||||
|
||||
|
||||
@@ -6,10 +6,15 @@ use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use FOS\UserBundle\Model\User as BaseUser;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use JMS\Serializer\Annotation\ExclusionPolicy;
|
||||
use JMS\Serializer\Annotation\Expose;
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
|
||||
* @ORM\Table(name="fos_user")
|
||||
*
|
||||
* @ExclusionPolicy("all")
|
||||
*/
|
||||
class User extends BaseUser
|
||||
{
|
||||
@@ -24,6 +29,7 @@ class User extends BaseUser
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(name="firstname", type="string", length=255, nullable=true)
|
||||
* @Expose
|
||||
*/
|
||||
private $firstname;
|
||||
|
||||
@@ -31,6 +37,7 @@ class User extends BaseUser
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(name="lastname", type="string", length=255, nullable=true)
|
||||
* @Expose
|
||||
*/
|
||||
private $lastname;
|
||||
|
||||
@@ -38,6 +45,7 @@ class User extends BaseUser
|
||||
* @var \DateTime
|
||||
*
|
||||
* @ORM\Column(name="birthday", type="datetime", length=255, nullable=true)
|
||||
* @Expose
|
||||
*/
|
||||
private $birthday;
|
||||
|
||||
@@ -52,6 +60,7 @@ class User extends BaseUser
|
||||
* @var string
|
||||
*
|
||||
* @ORM\Column(name="gender", type="string", length=255, nullable=true)
|
||||
* @Expose
|
||||
*/
|
||||
private $gender;
|
||||
|
||||
|
||||
@@ -2,9 +2,16 @@
|
||||
|
||||
namespace AppBundle\Representation;
|
||||
|
||||
use Pagerfanta\Pagerfanta;
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
use JMS\Serializer\Annotation\Type;
|
||||
use Pagerfanta\Pagerfanta;
|
||||
|
||||
/**
|
||||
* @Hateoas\Relation(
|
||||
* "authenticated_user",
|
||||
* embedded = @Hateoas\Embedded("expr(service('security.token_storage').getToken().getUser())")
|
||||
* )
|
||||
*/
|
||||
class Ads
|
||||
{
|
||||
/**
|
||||
@@ -12,28 +19,28 @@ class Ads
|
||||
*/
|
||||
public $data;
|
||||
public $meta;
|
||||
|
||||
|
||||
public function __construct(Pagerfanta $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
|
||||
|
||||
$this->addMeta('limit', $data->getMaxPerPage());
|
||||
$this->addMeta('current_items', count($data->getCurrentPageResults()));
|
||||
$this->addMeta('total_items', $data->getNbResults());
|
||||
$this->addMeta('offset', $data->getCurrentPageOffsetStart());
|
||||
}
|
||||
|
||||
|
||||
public function addMeta($name, $value)
|
||||
{
|
||||
if (isset($this->meta[$name])) {
|
||||
throw new \LogicException(sprintf('This meta already exists. You are trying to override this meta, use the setMeta method instead for the %s meta.', $name));
|
||||
}
|
||||
|
||||
|
||||
$this->setMeta($name, $value);
|
||||
}
|
||||
|
||||
|
||||
public function setMeta($name, $value)
|
||||
{
|
||||
$this->meta[$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace AppBundle\Representation;
|
||||
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
use JMS\Serializer\Annotation\Type;
|
||||
use AppBundle\Entity\Ad;
|
||||
|
||||
/**
|
||||
* @Hateoas\Relation(
|
||||
* "authenticated_user",
|
||||
* embedded = @Hateoas\Embedded("expr(service('security.token_storage').getToken().getUser())")
|
||||
* )
|
||||
*/
|
||||
class SingleAd
|
||||
{
|
||||
/**
|
||||
* @Type("AppBundle\Entity\Ad")
|
||||
*/
|
||||
public $data;
|
||||
|
||||
public function __construct(Ad $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
namespace AppBundle\Security;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationException;
|
||||
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
|
||||
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface;
|
||||
|
||||
class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface
|
||||
{
|
||||
public function createToken(Request $request, $providerKey)
|
||||
{
|
||||
$bearer = $request->headers->get('Authorization');
|
||||
|
||||
if (!$bearer) {
|
||||
throw new BadCredentialsException();
|
||||
}
|
||||
|
||||
return new PreAuthenticatedToken(
|
||||
'anon.',
|
||||
$bearer,
|
||||
$providerKey
|
||||
);
|
||||
}
|
||||
|
||||
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
|
||||
{
|
||||
$accessToken = $token->getCredentials();
|
||||
$username = $userProvider->getUsernameForApiKey($accessToken);
|
||||
|
||||
if (!$username) {
|
||||
// CAUTION: this message will be returned to the client
|
||||
// (so don't put any un-trusted messages / error strings here)
|
||||
throw new CustomUserMessageAuthenticationException(
|
||||
sprintf('API Key "%s" does not exist.', $apiKey)
|
||||
);
|
||||
}
|
||||
|
||||
$user = $userProvider->loadUserByUsername($username);
|
||||
|
||||
return new PreAuthenticatedToken(
|
||||
$user,
|
||||
$accessToken,
|
||||
$providerKey,
|
||||
$user->getRoles()
|
||||
);
|
||||
}
|
||||
|
||||
public function supportsToken(TokenInterface $token, $providerKey)
|
||||
{
|
||||
return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey;
|
||||
}
|
||||
|
||||
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
|
||||
{
|
||||
return new Response("Authentication Failed :(", 401);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace AppBundle\Security;
|
||||
|
||||
use Symfony\Component\Security\Core\User\UserProviderInterface;
|
||||
use Symfony\Component\Security\Core\User\User;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
||||
|
||||
// NOT USED AT THE MOMENT
|
||||
|
||||
|
||||
class ApiKeyUserProvider implements UserProviderInterface
|
||||
{
|
||||
public function getUsernameForApiKey($apiKey)
|
||||
{
|
||||
// Look up the username based on the token in the database, via
|
||||
// an API call, or do something entirely different
|
||||
// $username = ...;
|
||||
|
||||
return $username;
|
||||
}
|
||||
|
||||
public function loadUserByUsername($username)
|
||||
{
|
||||
return new User(
|
||||
$username,
|
||||
null,
|
||||
// the roles for the user - you may choose to determine
|
||||
// these dynamically somehow based on the user
|
||||
array('ROLE_API')
|
||||
);
|
||||
}
|
||||
|
||||
public function refreshUser(UserInterface $user)
|
||||
{
|
||||
// this is used for storing authentication in the session
|
||||
// but in this example, the token is sent in each request,
|
||||
// so authentication can be stateless. Throwing this exception
|
||||
// is proper to make things stateless
|
||||
throw new UnsupportedUserException();
|
||||
}
|
||||
|
||||
public function supportsClass($class)
|
||||
{
|
||||
return User::class === $class;
|
||||
}
|
||||
}
|
||||
@@ -227,4 +227,11 @@ class FOSUBUserProvider extends BaseFOSUBProvider
|
||||
$user->$setter($response->getAccessToken());
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function getUsernameForApiKey($apiKey)
|
||||
{
|
||||
$username = 'clementNv';
|
||||
|
||||
return $username;
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,12 @@ return array(
|
||||
'06dd8487319ccd8403765f5b8c9f2d61' => $vendorDir . '/alcaeus/mongo-php-adapter/lib/Mongo/functions.php',
|
||||
'92c8763cd6170fce6fcfe7e26b4e8c10' => $vendorDir . '/symfony/phpunit-bridge/bootstrap.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
|
||||
'ddc0a4d7e61c0286f0f8593b1903e894' => $vendorDir . '/clue/stream-filter/src/functions.php',
|
||||
'8cff32064859f4559445b89279f3199c' => $vendorDir . '/php-http/message/src/filters.php',
|
||||
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
'8cff32064859f4559445b89279f3199c' => $vendorDir . '/php-http/message/src/filters.php',
|
||||
'2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
|
||||
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
|
||||
'32dcc8afd4335739640db7d200c1971d' => $vendorDir . '/symfony/polyfill-apcu/bootstrap.php',
|
||||
|
||||
@@ -21,6 +21,7 @@ return array(
|
||||
'JMS\\Serializer' => array($vendorDir . '/jms/serializer/src'),
|
||||
'JMS\\' => array($vendorDir . '/jms/parser-lib/src'),
|
||||
'Imagine' => array($vendorDir . '/imagine/imagine/lib'),
|
||||
'Hateoas' => array($vendorDir . '/willdurand/hateoas/src'),
|
||||
'FFMpeg' => array($vendorDir . '/php-ffmpeg/php-ffmpeg/src'),
|
||||
'Evenement' => array($vendorDir . '/evenement/evenement/src'),
|
||||
'Doctrine\\ODM\\MongoDB' => array($vendorDir . '/doctrine/mongodb-odm/lib'),
|
||||
|
||||
@@ -85,6 +85,7 @@ return array(
|
||||
'Doctrine\\Bundle\\DoctrineBundle\\' => array($vendorDir . '/doctrine/doctrine-bundle'),
|
||||
'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
|
||||
'Clue\\StreamFilter\\' => array($vendorDir . '/clue/stream-filter/src'),
|
||||
'Bazinga\\Bundle\\HateoasBundle\\' => array($vendorDir . '/willdurand/hateoas-bundle'),
|
||||
'Alcaeus\\MongoDbAdapter\\' => array($vendorDir . '/alcaeus/mongo-php-adapter/lib/Alcaeus/MongoDbAdapter'),
|
||||
'' => array($baseDir . '/src'),
|
||||
);
|
||||
|
||||
+17
-2
@@ -11,12 +11,12 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
|
||||
'06dd8487319ccd8403765f5b8c9f2d61' => __DIR__ . '/..' . '/alcaeus/mongo-php-adapter/lib/Mongo/functions.php',
|
||||
'92c8763cd6170fce6fcfe7e26b4e8c10' => __DIR__ . '/..' . '/symfony/phpunit-bridge/bootstrap.php',
|
||||
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
|
||||
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
|
||||
'ddc0a4d7e61c0286f0f8593b1903e894' => __DIR__ . '/..' . '/clue/stream-filter/src/functions.php',
|
||||
'8cff32064859f4559445b89279f3199c' => __DIR__ . '/..' . '/php-http/message/src/filters.php',
|
||||
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
'8cff32064859f4559445b89279f3199c' => __DIR__ . '/..' . '/php-http/message/src/filters.php',
|
||||
'2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php',
|
||||
'5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
|
||||
'32dcc8afd4335739640db7d200c1971d' => __DIR__ . '/..' . '/symfony/polyfill-apcu/bootstrap.php',
|
||||
@@ -157,6 +157,10 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
|
||||
'Composer\\CaBundle\\' => 18,
|
||||
'Clue\\StreamFilter\\' => 18,
|
||||
),
|
||||
'B' =>
|
||||
array (
|
||||
'Bazinga\\Bundle\\HateoasBundle\\' => 29,
|
||||
),
|
||||
'A' =>
|
||||
array (
|
||||
'Alcaeus\\MongoDbAdapter\\' => 23,
|
||||
@@ -486,6 +490,10 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/clue/stream-filter/src',
|
||||
),
|
||||
'Bazinga\\Bundle\\HateoasBundle\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/willdurand/hateoas-bundle',
|
||||
),
|
||||
'Alcaeus\\MongoDbAdapter\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/alcaeus/mongo-php-adapter/lib/Alcaeus/MongoDbAdapter',
|
||||
@@ -581,6 +589,13 @@ class ComposerStaticInit1b32d02bd8fea2d524bf79b36ada5830
|
||||
0 => __DIR__ . '/..' . '/imagine/imagine/lib',
|
||||
),
|
||||
),
|
||||
'H' =>
|
||||
array (
|
||||
'Hateoas' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/willdurand/hateoas/src',
|
||||
),
|
||||
),
|
||||
'F' =>
|
||||
array (
|
||||
'FFMpeg' =>
|
||||
|
||||
@@ -6478,6 +6478,128 @@
|
||||
"paging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "willdurand/hateoas",
|
||||
"version": "2.12.0",
|
||||
"version_normalized": "2.12.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/willdurand/Hateoas.git",
|
||||
"reference": "71b1af62b398dc9a870ac0b16c84bdc23a76a5c5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/willdurand/Hateoas/zipball/71b1af62b398dc9a870ac0b16c84bdc23a76a5c5",
|
||||
"reference": "71b1af62b398dc9a870ac0b16c84bdc23a76a5c5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/annotations": "~1.0",
|
||||
"doctrine/common": "~2.0",
|
||||
"jms/metadata": "~1.1",
|
||||
"jms/serializer": "^1.7",
|
||||
"php": "^5.5|^7.0",
|
||||
"phpoption/phpoption": ">=1.1.0,<2.0-dev",
|
||||
"symfony/expression-language": "~2.4 || ~3.0 || ~4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"pagerfanta/pagerfanta": "~1.0",
|
||||
"phpunit/phpunit": "~5",
|
||||
"symfony/dependency-injection": "~2.4 || ~3.0 || ~4.0",
|
||||
"symfony/routing": "~2.4 || ~3.0 || ~4.0",
|
||||
"symfony/yaml": "~2.4 || ~3.0 || ~4.0",
|
||||
"twig/twig": "~1.12"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/routing": "To use the SymfonyRouteFactory.",
|
||||
"symfony/yaml": "To use yaml based configuration.",
|
||||
"twig/twig": "To use the Twig extensions."
|
||||
},
|
||||
"time": "2018-02-23T17:05:31+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.12-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Hateoas": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Adrien Brault",
|
||||
"email": "adrien.brault@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "William Durand",
|
||||
"email": "william.durand1@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A PHP library to support implementing representations for HATEOAS REST web services"
|
||||
},
|
||||
{
|
||||
"name": "willdurand/hateoas-bundle",
|
||||
"version": "1.4.0",
|
||||
"version_normalized": "1.4.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/willdurand/BazingaHateoasBundle.git",
|
||||
"reference": "d1f915fd4f8a7cd43a88a0ce97ffb28abe3a94fa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/willdurand/BazingaHateoasBundle/zipball/d1f915fd4f8a7cd43a88a0ce97ffb28abe3a94fa",
|
||||
"reference": "d1f915fd4f8a7cd43a88a0ce97ffb28abe3a94fa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"jms/serializer-bundle": "~1.0 || ^2.0",
|
||||
"php": ">5.4 |^7.0",
|
||||
"symfony/framework-bundle": "~2.3 || ~3.0 || ~4.0",
|
||||
"willdurand/hateoas": "^2.10.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.5 || ~5.0",
|
||||
"symfony/expression-language": "~2.4 || ~3.0 || ~4.0",
|
||||
"symfony/stopwatch": "~2.4 || ~3.0 || ~4.0",
|
||||
"twig/twig": "~1.12"
|
||||
},
|
||||
"time": "2018-01-27T13:03:07+00:00",
|
||||
"type": "symfony-bundle",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Bazinga\\Bundle\\HateoasBundle\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "William Durand",
|
||||
"email": "william.durand1@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Integration of Hateoas into Symfony2.",
|
||||
"keywords": [
|
||||
"HATEOAS",
|
||||
"rest"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "willdurand/jsonp-callback-validator",
|
||||
"version": "v1.1.0",
|
||||
|
||||
+2
@@ -107,6 +107,8 @@ final class Versions
|
||||
'twig/twig' => 'v2.5.0@6a5f676b77a90823c2d4eaf76137b771adf31323',
|
||||
'vimeo/vimeo-api' => '1.3.0@46820e2d777362849137c1eb14f5cdb657c289ea',
|
||||
'white-october/pagerfanta-bundle' => 'v1.2.1@3f97e71c9d3f75e7a6179aa82c863497bf298b2d',
|
||||
'willdurand/hateoas' => '2.12.0@71b1af62b398dc9a870ac0b16c84bdc23a76a5c5',
|
||||
'willdurand/hateoas-bundle' => '1.4.0@d1f915fd4f8a7cd43a88a0ce97ffb28abe3a94fa',
|
||||
'willdurand/jsonp-callback-validator' => 'v1.1.0@1a7d388bb521959e612ef50c5c7b1691b097e909',
|
||||
'willdurand/negotiation' => 'v2.3.1@03436ededa67c6e83b9b12defac15384cb399dc9',
|
||||
'zendframework/zend-code' => '3.3.1@c21db169075c6ec4b342149f446e7b7b724f95eb',
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
vendor/
|
||||
composer.lock
|
||||
@@ -0,0 +1,54 @@
|
||||
language: php
|
||||
|
||||
sudo: false
|
||||
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
|
||||
php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- php: 5.5
|
||||
env: SYMFONY_VERSION=4.0.*
|
||||
- php: 5.6
|
||||
env: SYMFONY_VERSION=4.0.*
|
||||
- php: 7.0
|
||||
env: SYMFONY_VERSION=4.0.*
|
||||
- php: hhvm
|
||||
env: SYMFONY_VERSION=4.0.*
|
||||
|
||||
env:
|
||||
- SYMFONY_VERSION=2.3.*
|
||||
- SYMFONY_VERSION=2.4.*
|
||||
- SYMFONY_VERSION=2.8.*
|
||||
- SYMFONY_VERSION=3.0.*
|
||||
- SYMFONY_VERSION=3.2.*
|
||||
- SYMFONY_VERSION=2.3.* DEPS=low
|
||||
- SYMFONY_VERSION=2.4.* DEPS=low
|
||||
- SYMFONY_VERSION=2.8.* DEPS=low
|
||||
- SYMFONY_VERSION=3.0.* DEPS=low
|
||||
- SYMFONY_VERSION=3.2.* DEPS=low
|
||||
- SYMFONY_VERSION=4.0.*
|
||||
|
||||
before_script:
|
||||
- if [ "$DEPS" = 'low' ] ; then COMPOSER_PARAMS="--prefer-lowest --prefer-stable" ; fi
|
||||
- composer self-update
|
||||
- composer require symfony/framework-bundle:${SYMFONY_VERSION} --no-update
|
||||
- composer update $COMPOSER_PARAMS
|
||||
|
||||
script:
|
||||
- ./vendor/bin/phpunit --coverage-text
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the HateoasBundle package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
*/
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle;
|
||||
|
||||
use Bazinga\Bundle\HateoasBundle\DependencyInjection\Compiler\ExpressionFunctionPass;
|
||||
use Bazinga\Bundle\HateoasBundle\DependencyInjection\Compiler\ExtensionDriverPass;
|
||||
use Bazinga\Bundle\HateoasBundle\DependencyInjection\Compiler\RelationProviderPass;
|
||||
use Bazinga\Bundle\HateoasBundle\DependencyInjection\Compiler\UrlGeneratorPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class BazingaHateoasBundle extends Bundle
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build(ContainerBuilder $container)
|
||||
{
|
||||
parent::build($container);
|
||||
|
||||
$container->addCompilerPass(new UrlGeneratorPass());
|
||||
$container->addCompilerPass(new ExpressionFunctionPass());
|
||||
$container->addCompilerPass(new RelationProviderPass());
|
||||
$container->addCompilerPass(new ExtensionDriverPass());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
First of all, **thank you** for contributing, **you are awesome**!
|
||||
|
||||
Here are a few rules to follow in order to ease code reviews, and discussions before
|
||||
maintainers accept and merge your work.
|
||||
|
||||
You MUST follow the [PSR-1](http://www.php-fig.org/psr/1/) and
|
||||
[PSR-2](http://www.php-fig.org/psr/2/). If you don't know about any of them, you
|
||||
should really read the recommendations. Can't wait? Use the [PHP-CS-Fixer
|
||||
tool](http://cs.sensiolabs.org/).
|
||||
|
||||
You MUST run the test suite.
|
||||
|
||||
You MUST write (or update) unit tests.
|
||||
|
||||
You SHOULD write documentation.
|
||||
|
||||
Please, write [commit messages that make
|
||||
sense](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
|
||||
and [rebase your branch](http://git-scm.com/book/en/Git-Branching-Rebasing)
|
||||
before submitting your Pull Request.
|
||||
|
||||
One may ask you to [squash your
|
||||
commits](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html)
|
||||
too. This is used to "clean" your Pull Request before merging it (we don't want
|
||||
commits such as `fix tests`, `fix 2`, `fix 3`, etc.).
|
||||
|
||||
Thank you!
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the HateoasBundle package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
*/
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
|
||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
|
||||
/**
|
||||
* @author William Durand <william.durand1@gmail.com>
|
||||
*/
|
||||
class BazingaHateoasExtension extends Extension
|
||||
{
|
||||
public function load(array $configs, ContainerBuilder $container)
|
||||
{
|
||||
$config = $this->processConfiguration(new Configuration(), $configs);
|
||||
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
|
||||
|
||||
foreach (array('serializer', 'configuration', 'generator', 'helper', 'twig') as $file) {
|
||||
if ('twig' === $file && false === $config['twig_extension']['enabled']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$loader->load($file . '.xml');
|
||||
}
|
||||
|
||||
// Based on JMSSerializerBundle
|
||||
if ('none' === $config['metadata']['cache']) {
|
||||
$container->removeAlias('hateoas.configuration.metadata.cache');
|
||||
} elseif ('file' === $config['metadata']['cache']) {
|
||||
$container
|
||||
->getDefinition('hateoas.configuration.metadata.cache.file_cache')
|
||||
->replaceArgument(0, $config['metadata']['file_cache']['dir']);
|
||||
|
||||
$dir = $container->getParameterBag()->resolveValue($config['metadata']['file_cache']['dir']);
|
||||
|
||||
if (!file_exists($dir)) {
|
||||
if (!$rs = @mkdir($dir, 0777, true)) {
|
||||
throw new \RuntimeException(sprintf('Could not create cache directory "%s".', $dir));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$container->setAlias(
|
||||
'hateoas.configuration.metadata.cache',
|
||||
new Alias($config['metadata']['cache'], false)
|
||||
);
|
||||
}
|
||||
|
||||
$container
|
||||
->getDefinition('hateoas.event_subscriber.json')
|
||||
->setPublic(true)
|
||||
->replaceArgument(0, new Reference($config['serializer']['json']));
|
||||
|
||||
$container
|
||||
->getDefinition('hateoas.event_subscriber.xml')
|
||||
->setPublic(true)
|
||||
->replaceArgument(0, new Reference($config['serializer']['xml']));
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the HateoasBundle package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
*/
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class ExpressionFunctionPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$expressionEvaluator = $container->getDefinition('hateoas.expression.evaluator');
|
||||
|
||||
foreach ($container->findTaggedServiceIds('hateoas.expression_function') as $id => $tags) {
|
||||
$functionDefinition = $container->getDefinition($id);
|
||||
|
||||
if (!$this->implementsExpressionFunctionInterface($container, $functionDefinition)) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'Service %s tagged with hateoas.expression_function must implement %s',
|
||||
$id,
|
||||
'Hateoas\Expression\ExpressionFunctionInterface'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$expressionEvaluator->addMethodCall('registerFunctionId', array($id));
|
||||
}
|
||||
}
|
||||
|
||||
private function implementsExpressionFunctionInterface(ContainerBuilder $container, Definition $definition)
|
||||
{
|
||||
$class = $container->getParameterBag()->resolveValue($definition->getClass());
|
||||
$refClass = new \ReflectionClass($class);
|
||||
|
||||
return $refClass->implementsInterface('Hateoas\Expression\ExpressionFunctionInterface');
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the HateoasBundle package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
*/
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
|
||||
class ExtensionDriverPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$extensionDriver = $container->getDefinition('hateoas.configuration.metadata.extension_driver');
|
||||
|
||||
foreach ($container->findTaggedServiceIds('hateoas.configuration_extension') as $id => $tags) {
|
||||
$extensionDefinition = $container->getDefinition($id);
|
||||
|
||||
if (!$this->implementsConfigurationExtensionInterface($container, $extensionDefinition)) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf(
|
||||
'Service %s tagged with hateoas.configuration_extension must implement %s',
|
||||
$id,
|
||||
'Hateoas\Configuration\Metadata\ConfigurationExtensionInterface'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$extensionDriver->addMethodCall('registerExtension', [$extensionDefinition]);
|
||||
}
|
||||
}
|
||||
|
||||
private function implementsConfigurationExtensionInterface(ContainerBuilder $container, Definition $definition)
|
||||
{
|
||||
$class = $container->getParameterBag()->resolveValue($definition->getClass());
|
||||
$refClass = new \ReflectionClass($class);
|
||||
|
||||
return $refClass->implementsInterface('Hateoas\Configuration\Metadata\ConfigurationExtensionInterface');
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the HateoasBundle package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
*/
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @author Daniel Leech <daniel@dantleech.com>
|
||||
*/
|
||||
class RelationProviderPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$registryDefinition = $container->getDefinition('hateoas.configuration.provider.resolver.chain');
|
||||
|
||||
$relationProviderDefinitions = array();
|
||||
foreach (array_keys($container->findTaggedServiceIds('hateoas.relation_provider')) as $id) {
|
||||
$definition = $container->getDefinition($id);
|
||||
$this->assertProvider($container, $definition);
|
||||
$relationProviderDefinitions[] = $definition;
|
||||
}
|
||||
|
||||
$registryDefinition->replaceArgument(0, $relationProviderDefinitions);
|
||||
}
|
||||
|
||||
private function assertProvider(ContainerBuilder $container, Definition $definition)
|
||||
{
|
||||
$class = $container->getParameterBag()->resolveValue($definition->getClass());
|
||||
$refClass = new \ReflectionClass($class);
|
||||
|
||||
if (!$refClass->implementsInterface('Hateoas\Configuration\Provider\Resolver\RelationProviderResolverInterface')) {
|
||||
throw new InvalidArgumentException(sprintf(
|
||||
'Relation provider "%s" does not implement the ReleationProviderResolver interface',
|
||||
$definition->getClass()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the HateoasBundle package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
*/
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class UrlGeneratorPass implements CompilerPassInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$registryDefinition = $container->getDefinition('hateoas.generator.registry');
|
||||
|
||||
foreach ($container->findTaggedServiceIds('hateoas.url_generator') as $id => $attributes) {
|
||||
$name = !empty($attributes[0]['alias']) ? $attributes[0]['alias'] : $id;
|
||||
|
||||
if ($this->isSymfonyUrlGenerator($container, $container->getDefinition($id))) {
|
||||
$definition = new Definition(
|
||||
'Hateoas\UrlGenerator\SymfonyUrlGenerator',
|
||||
array(new Reference($id))
|
||||
);
|
||||
$definition->setPublic(false);
|
||||
|
||||
$id = 'hateoas.generator.user.' . $name;
|
||||
|
||||
$container->setDefinition($id, $definition);
|
||||
}
|
||||
|
||||
$registryDefinition->addMethodCall(
|
||||
'set',
|
||||
array($name, new Reference($id))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function isSymfonyUrlGenerator(ContainerBuilder $container, Definition $definition)
|
||||
{
|
||||
$class = $container->getParameterBag()->resolveValue($definition->getClass());
|
||||
$refClass = new \ReflectionClass($class);
|
||||
|
||||
return $refClass->implementsInterface('Symfony\Component\Routing\Generator\UrlGeneratorInterface');
|
||||
}
|
||||
}
|
||||
Vendored
+60
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the HateoasBundle package.
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @license MIT License
|
||||
*/
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\DependencyInjection;
|
||||
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
|
||||
/**
|
||||
* @author William Durand <william.durand1@gmail.com>
|
||||
*/
|
||||
class Configuration implements ConfigurationInterface
|
||||
{
|
||||
/**
|
||||
* Generates the configuration tree builder.
|
||||
*
|
||||
* @return TreeBuilder The tree builder
|
||||
*/
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder();
|
||||
$rootNode = $treeBuilder->root('bazinga_hateoas');
|
||||
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('metadata')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->scalarNode('cache')->defaultValue('file')->end()
|
||||
->arrayNode('file_cache')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->scalarNode('dir')->defaultValue('%kernel.cache_dir%/hateoas')->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('serializer')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->scalarNode('json')->defaultValue('hateoas.serializer.json_hal')->end()
|
||||
->scalarNode('xml')->defaultValue('hateoas.serializer.xml')->end()
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('twig_extension')
|
||||
->addDefaultsIfNotSet()
|
||||
->canBeDisabled()
|
||||
->end()
|
||||
;
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
}
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\ExpressionLanguage;
|
||||
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
|
||||
|
||||
/**
|
||||
* Adds some function to the default ExpressionLanguage.
|
||||
*
|
||||
* To get a service, use service('request').
|
||||
* To get a parameter, use parameter('kernel.debug').
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class ExpressionLanguage extends BaseExpressionLanguage
|
||||
{
|
||||
protected function registerFunctions()
|
||||
{
|
||||
parent::registerFunctions();
|
||||
|
||||
$this->register('service', function ($arg) {
|
||||
return sprintf('$this->get(%s)', $arg);
|
||||
}, function (array $variables, $value) {
|
||||
return $variables['container']->get($value);
|
||||
});
|
||||
|
||||
$this->register('parameter', function ($arg) {
|
||||
return sprintf('$this->getParameter(%s)', $arg);
|
||||
}, function (array $variables, $value) {
|
||||
return $variables['container']->getParameter($value);
|
||||
});
|
||||
|
||||
$this->register('is_granted', function ($attribute, $object = null) {
|
||||
return sprintf('call_user_func_array(array($this->get(security.authorization_checker), isGranted), array(%s, %s))', $attribute, $object);
|
||||
}, function (array $variables, $attribute, $object = null) {
|
||||
return call_user_func_array(
|
||||
array($variables['container']->get('security.authorization_checker'), 'isGranted'),
|
||||
[$attribute, $object]
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\Hateoas\Expression;
|
||||
|
||||
use Hateoas\Expression\ExpressionEvaluator;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||
|
||||
class LazyFunctionExpressionEvaluator extends ExpressionEvaluator
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
private $functionsIds = array();
|
||||
|
||||
public function __construct(
|
||||
ExpressionLanguage $expressionLanguage,
|
||||
array $context = array(),
|
||||
ContainerInterface $container
|
||||
) {
|
||||
parent::__construct($expressionLanguage, $context);
|
||||
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function evaluate($expression, $data)
|
||||
{
|
||||
if (!empty($this->functionsIds)) {
|
||||
$this->registerFunctions();
|
||||
}
|
||||
|
||||
return parent::evaluate($expression, $data);
|
||||
}
|
||||
|
||||
public function evaluateArray(array $array, $data)
|
||||
{
|
||||
if (!empty($this->functionsIds)) {
|
||||
$this->registerFunctions();
|
||||
}
|
||||
|
||||
return parent::evaluateArray($array, $data);
|
||||
}
|
||||
|
||||
public function registerFunctionId($serviceId)
|
||||
{
|
||||
$this->functionsIds[] = $serviceId;
|
||||
}
|
||||
|
||||
private function registerFunctions()
|
||||
{
|
||||
foreach ($this->functionsIds as $serviceId) {
|
||||
$this->registerFunction($this->container->get($serviceId));
|
||||
}
|
||||
$this->functionsIds = array();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2017 William Durand <william.durand1@gmail.com>
|
||||
|
||||
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 @@
|
||||
BazingaHateoasBundle
|
||||
====================
|
||||
|
||||
[](http://travis-ci.org/willdurand/BazingaHateoasBundle)
|
||||
|
||||
This bundle integrates [Hateoas](http://github.com/willdurand/Hateoas) with
|
||||
[Symfony](http://symfony.com).
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
For documentation, see:
|
||||
|
||||
Resources/doc/
|
||||
|
||||
[Read the documentation](https://github.com/willdurand/BazingaHateoasBundle/blob/master/Resources/doc/index.md)
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
See
|
||||
[CONTRIBUTING](https://github.com/willdurand/BazingaHateoasBundle/blob/master/CONTRIBUTING.md)
|
||||
file.
|
||||
|
||||
|
||||
Credits
|
||||
-------
|
||||
|
||||
* William Durand <william.durand1@gmail.com>
|
||||
* [All contributors](https://github.com/willdurand/BazingaHateoasBundle/contributors)
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This bundle is released under the MIT license. See the complete license in the
|
||||
bundle:
|
||||
|
||||
Resources/meta/LICENSE
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" ?>
|
||||
<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">
|
||||
|
||||
<parameters>
|
||||
<parameter key="hateoas.configuration.provider.resolver.chain.class">Hateoas\Configuration\Provider\Resolver\ChainResolver</parameter>
|
||||
<parameter key="hateoas.configuration.provider.resolver.method.class">Hateoas\Configuration\Provider\Resolver\MethodResolver</parameter>
|
||||
<parameter key="hateoas.configuration.provider.resolver.static_method.class">Hateoas\Configuration\Provider\Resolver\StaticMethodResolver</parameter>
|
||||
<parameter key="hateoas.configuration.provider.resolver.symfony_container.class">Hateoas\Configuration\Provider\Resolver\SymfonyContainerResolver</parameter>
|
||||
<parameter key="hateoas.configuration.relation_provider.class">Hateoas\Configuration\Provider\RelationProvider</parameter>
|
||||
<parameter key="hateoas.configuration.relations_repository.class">Hateoas\Configuration\RelationsRepository</parameter>
|
||||
<parameter key="hateoas.configuration.metadata.yaml_driver.class">Hateoas\Configuration\Metadata\Driver\YamlDriver</parameter>
|
||||
<parameter key="hateoas.configuration.metadata.xml_driver.class">Hateoas\Configuration\Metadata\Driver\XmlDriver</parameter>
|
||||
<parameter key="hateoas.configuration.metadata.annotation_driver.class">Hateoas\Configuration\Metadata\Driver\AnnotationDriver</parameter>
|
||||
<parameter key="hateoas.configuration.metadata.extension_driver.class">Hateoas\Configuration\Metadata\Driver\ExtensionDriver</parameter>
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
<service id="hateoas.configuration.provider.resolver.chain" class="%hateoas.configuration.provider.resolver.chain.class%" public="false">
|
||||
<argument type="collection"></argument>
|
||||
</service>
|
||||
|
||||
<service id="hateoas.configuration.provider.resolver.method" class="%hateoas.configuration.provider.resolver.method.class%" public="false">
|
||||
<tag name="hateoas.relation_provider" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.configuration.provider.resolver.static_method" class="%hateoas.configuration.provider.resolver.static_method.class%" public="false">
|
||||
<tag name="hateoas.relation_provider" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.configuration.provider.resolver.symfony_container" class="%hateoas.configuration.provider.resolver.symfony_container.class%" public="false">
|
||||
<argument type="service" id="service_container"/>
|
||||
<tag name="hateoas.relation_provider" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.configuration.provider.resolver" alias="hateoas.configuration.provider.resolver.chain"/>
|
||||
|
||||
<service id="hateoas.configuration.relation_provider" class="%hateoas.configuration.relation_provider.class%" public="false">
|
||||
<argument type="service" id="hateoas.configuration.metadata_factory" />
|
||||
<argument type="service" id="hateoas.configuration.provider.resolver" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.configuration.relations_repository" class="%hateoas.configuration.relations_repository.class%" public="false">
|
||||
<argument type="service" id="hateoas.configuration.metadata_factory" />
|
||||
<argument type="service" id="hateoas.configuration.relation_provider" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.configuration.metadata.yaml_driver" class="%hateoas.configuration.metadata.yaml_driver.class%" public="false">
|
||||
<argument type="service" id="jms_serializer.metadata.file_locator" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.configuration.metadata.xml_driver" class="%hateoas.configuration.metadata.xml_driver.class%" public="false">
|
||||
<argument type="service" id="jms_serializer.metadata.file_locator" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.configuration.metadata.annotation_driver" class="%hateoas.configuration.metadata.annotation_driver.class%" public="false">
|
||||
<argument type="service" id="annotation_reader" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.configuration.metadata.extension_driver" class="%hateoas.configuration.metadata.extension_driver.class%" public="false">
|
||||
<argument type="service" id="hateoas.configuration.metadata.annotation_driver" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.configuration.metadata.chain_driver" class="%jms_serializer.metadata.chain_driver.class%" public="false">
|
||||
<argument type="collection">
|
||||
<argument type="service" id="hateoas.configuration.metadata.yaml_driver" />
|
||||
<argument type="service" id="hateoas.configuration.metadata.xml_driver" />
|
||||
<argument type="service" id="hateoas.configuration.metadata.extension_driver" />
|
||||
</argument>
|
||||
</service>
|
||||
|
||||
<service id="hateoas.configuration.metadata.cache.file_cache" class="%jms_serializer.metadata.cache.file_cache.class%" public="false">
|
||||
<argument></argument> <!-- Directory -->
|
||||
</service>
|
||||
<service id="hateoas.configuration.metadata.cache" alias="hateoas.configuration.metadata.cache.file_cache" public="false"></service>
|
||||
|
||||
<service id="hateoas.configuration.metadata_factory" class="%jms_serializer.metadata.metadata_factory.class%" public="false">
|
||||
<argument type="service" id="hateoas.configuration.metadata.chain_driver" />
|
||||
<argument>Metadata\ClassHierarchyMetadata</argument>
|
||||
<argument>%kernel.debug%</argument>
|
||||
<call method="setCache">
|
||||
<argument type="service" id="hateoas.configuration.metadata.cache" on-invalid="ignore" />
|
||||
</call>
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" ?>
|
||||
<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">
|
||||
|
||||
<parameters>
|
||||
<parameter key="hateoas.generator.registry.class">Hateoas\UrlGenerator\UrlGeneratorRegistry</parameter>
|
||||
<parameter key="hateoas.generator.symfony.class">Hateoas\UrlGenerator\SymfonyUrlGenerator</parameter>
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
<service id="hateoas.generator.registry" class="%hateoas.generator.registry.class%" public="true">
|
||||
<argument type="service" id="hateoas.generator.symfony" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.generator.symfony" class="%hateoas.generator.symfony.class%">
|
||||
<argument type="service" id="router" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" ?>
|
||||
<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">
|
||||
|
||||
<parameters>
|
||||
<parameter key="hateoas.helper.link.class">Hateoas\Helper\LinkHelper</parameter>
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
<service id="hateoas.helper.link" class="%hateoas.helper.link.class%" public="true">
|
||||
<argument type="service" id="hateoas.link_factory" />
|
||||
<argument type="service" id="hateoas.configuration.relations_repository" />
|
||||
</service>
|
||||
</services>
|
||||
|
||||
</container>
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" ?>
|
||||
<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">
|
||||
|
||||
<parameters>
|
||||
<!-- Factories -->
|
||||
<parameter key="hateoas.link_factory.class">Hateoas\Factory\LinkFactory</parameter>
|
||||
<parameter key="hateoas.links_factory.class">Hateoas\Factory\LinksFactory</parameter>
|
||||
<parameter key="hateoas.embeds_factory.class">Hateoas\Factory\EmbeddedsFactory</parameter>
|
||||
|
||||
<!-- Expressions -->
|
||||
<parameter key="hateoas.expression.evaluator.class">Bazinga\Bundle\HateoasBundle\Hateoas\Expression\LazyFunctionExpressionEvaluator</parameter>
|
||||
<parameter key="bazinga_hateoas.expression_language.class">Bazinga\Bundle\HateoasBundle\ExpressionLanguage\ExpressionLanguage</parameter>
|
||||
<parameter key="hateoas.expression.link.class">Hateoas\Expression\LinkExpressionFunction</parameter>
|
||||
|
||||
<!-- Serializers & Handlers -->
|
||||
<parameter key="hateoas.serializer.xml.class">Hateoas\Serializer\XmlSerializer</parameter>
|
||||
<parameter key="hateoas.serializer.json_hal.class">Hateoas\Serializer\JsonHalSerializer</parameter>
|
||||
<parameter key="hateoas.serializer.exclusion_manager.class">Hateoas\Serializer\ExclusionManager</parameter>
|
||||
|
||||
<!-- Subscribers -->
|
||||
<parameter key="hateoas.event_subscriber.xml.class">Hateoas\Serializer\EventSubscriber\XmlEventSubscriber</parameter>
|
||||
<parameter key="hateoas.event_subscriber.json.class">Hateoas\Serializer\EventSubscriber\JsonEventSubscriber</parameter>
|
||||
|
||||
<!-- Inline deferrers -->
|
||||
<parameter key="hateoas.inline_deferrer.embeds.class">Hateoas\Serializer\Metadata\InlineDeferrer</parameter>
|
||||
<parameter key="hateoas.inline_deferrer.links.class">Hateoas\Serializer\Metadata\InlineDeferrer</parameter>
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
<!-- Factories -->
|
||||
<service id="hateoas.link_factory" class="%hateoas.link_factory.class%" public="false">
|
||||
<argument type="service" id="hateoas.expression.evaluator" />
|
||||
<argument type="service" id="hateoas.generator.registry" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.links_factory" class="%hateoas.links_factory.class%" public="false">
|
||||
<argument type="service" id="hateoas.configuration.relations_repository" />
|
||||
<argument type="service" id="hateoas.link_factory" />
|
||||
<argument type="service" id="hateoas.serializer.exclusion_manager" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.embeds_factory" class="%hateoas.embeds_factory.class%" public="false">
|
||||
<argument type="service" id="hateoas.configuration.relations_repository" />
|
||||
<argument type="service" id="hateoas.expression.evaluator" />
|
||||
<argument type="service" id="hateoas.serializer.exclusion_manager" />
|
||||
</service>
|
||||
|
||||
<!-- Expressions -->
|
||||
<service id="hateoas.expression.evaluator" class="%hateoas.expression.evaluator.class%">
|
||||
<argument type="service" id="bazinga_hateoas.expression_language" />
|
||||
<argument type="collection"/>
|
||||
<argument type="service" id="service_container" />
|
||||
<call method="setContextVariable">
|
||||
<argument>container</argument>
|
||||
<argument type="service" id="service_container"/>
|
||||
</call>
|
||||
</service>
|
||||
|
||||
<service id="bazinga_hateoas.expression_language" class="%bazinga_hateoas.expression_language.class%" />
|
||||
|
||||
<service id="hateoas.expression.link" class="%hateoas.expression.link.class%" public="true">
|
||||
<argument type="service" id="hateoas.helper.link" />
|
||||
<tag name="hateoas.expression_function"/>
|
||||
</service>
|
||||
|
||||
<!-- Serializers & Handlers -->
|
||||
<service id="hateoas.serializer.xml" class="%hateoas.serializer.xml.class%" public="false">
|
||||
<call method="setMetadataFactory">
|
||||
<argument type="service" id="jms_serializer.metadata_factory" />
|
||||
</call>
|
||||
</service>
|
||||
<service id="hateoas.serializer.json_hal" class="%hateoas.serializer.json_hal.class%" public="false" />
|
||||
|
||||
<service id="hateoas.serializer.exclusion_manager" class="%hateoas.serializer.exclusion_manager.class%">
|
||||
<argument type="service" id="hateoas.expression.evaluator" />
|
||||
</service>
|
||||
|
||||
<!-- Subscribers -->
|
||||
<service id="hateoas.event_subscriber.xml" class="%hateoas.event_subscriber.xml.class%">
|
||||
<tag name="jms_serializer.event_subscriber" />
|
||||
<argument /> <!-- xml serializer -->
|
||||
<argument type="service" id="hateoas.links_factory" />
|
||||
<argument type="service" id="hateoas.embeds_factory" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.event_subscriber.json" class="%hateoas.event_subscriber.json.class%">
|
||||
<tag name="jms_serializer.event_subscriber" />
|
||||
<argument /> <!-- json serializer -->
|
||||
<argument type="service" id="hateoas.links_factory" />
|
||||
<argument type="service" id="hateoas.embeds_factory" />
|
||||
<argument type="service" id="hateoas.inline_deferrer.embeds" />
|
||||
<argument type="service" id="hateoas.inline_deferrer.links" />
|
||||
</service>
|
||||
|
||||
<service id="hateoas.inline_deferrer.embeds" class="%hateoas.inline_deferrer.embeds.class%" public="false">
|
||||
<argument type="service" id="jms_serializer.metadata_factory"/>
|
||||
</service>
|
||||
|
||||
<service id="hateoas.inline_deferrer.links" class="%hateoas.inline_deferrer.links.class%" public="false">
|
||||
<argument type="service" id="jms_serializer.metadata_factory"/>
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" ?>
|
||||
<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">
|
||||
|
||||
<parameters>
|
||||
<parameter key="hateoas.twig.link.class">Hateoas\Twig\Extension\LinkExtension</parameter>
|
||||
</parameters>
|
||||
|
||||
<services>
|
||||
<service id="hateoas.twig.link" class="%hateoas.twig.link.class%">
|
||||
<argument type="service" id="hateoas.helper.link" />
|
||||
<tag name="twig.extension" />
|
||||
</service>
|
||||
</services>
|
||||
|
||||
</container>
|
||||
+260
@@ -0,0 +1,260 @@
|
||||
BazingaHateoasBundle
|
||||
====================
|
||||
|
||||
This bundle integrates [Hateoas](http://github.com/willdurand/Hateoas) into
|
||||
[Symfony](http://symfony.com).
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
### Step 1: Download the Bundle
|
||||
|
||||
Open a command console, enter your project directory and execute the
|
||||
following command to download the latest stable version of this bundle:
|
||||
|
||||
```bash
|
||||
$ composer require willdurand/hateoas-bundle
|
||||
```
|
||||
|
||||
This command requires you to have Composer installed globally, as explained
|
||||
in the [installation chapter](https://getcomposer.org/doc/00-intro.md)
|
||||
of the Composer documentation.
|
||||
|
||||
### Step 2: Enable the Bundle
|
||||
|
||||
Then, enable the bundle by adding the following line in the `app/AppKernel.php`
|
||||
file of your project:
|
||||
|
||||
```php
|
||||
<?php
|
||||
// app/AppKernel.php
|
||||
|
||||
// ...
|
||||
class AppKernel extends Kernel
|
||||
{
|
||||
public function registerBundles()
|
||||
{
|
||||
$bundles = array(
|
||||
// ...
|
||||
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(),
|
||||
);
|
||||
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:**
|
||||
> The bundle requires the [JMSSerializerBundle](http://jmsyst.com/bundles/JMSSerializerBundle) to be
|
||||
> registered. If you haven't done that already, you should register it in the kernel aswell:
|
||||
>
|
||||
> ```php
|
||||
> // app/AppKernel.php
|
||||
>
|
||||
> // ...
|
||||
> public function registerBundles()
|
||||
> {
|
||||
> $bundles = array(
|
||||
> // ...
|
||||
> new JMS\SerializerBundle\JMSSerializerBundle(),
|
||||
> );
|
||||
>
|
||||
> // ...
|
||||
> }
|
||||
> ```
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
### Mapping Objects
|
||||
|
||||
Refer to the [Hateoas documentation](http://github.com/willdurand/Hateoas) to
|
||||
find out how to map your objects.
|
||||
|
||||
### Serializing objects
|
||||
|
||||
The BazingaHateoasBundle transparently hooks into the JMS serializer, there
|
||||
are no special considerations:
|
||||
|
||||
````php
|
||||
// My/Controller.php
|
||||
|
||||
class SomeController extends Controller
|
||||
{
|
||||
public function resourceAction(Request $request)
|
||||
{
|
||||
$post = $repository->find('BlogBundle:post');
|
||||
$json = $this->container->get('jms_serializer')->serialize($post, 'json');
|
||||
|
||||
return new Response($json, 200, array('Content-Type' => 'application/json'));
|
||||
}
|
||||
}
|
||||
````
|
||||
|
||||
Expression Language
|
||||
-------------------
|
||||
|
||||
This bundle provides three extra functions to the expression language:
|
||||
|
||||
## `is_granted`
|
||||
|
||||
Allows you to exclude certain routes by checking whether the currently authenticated user
|
||||
has certain permissions or not. For example:
|
||||
|
||||
```php
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
|
||||
/**
|
||||
* @Hateoas\Relation(
|
||||
* "delete",
|
||||
* href = @Hateoas\Route(
|
||||
* "post_delete",
|
||||
* parameters = { "id" = "expr(object.getId())" }
|
||||
* ),
|
||||
* exclusion = @Hateoas\Exclusion(
|
||||
* excludeIf = "expr(not is_granted(['ROLE_ADMIN']))"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
class Post
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
If the authenticated user has the `ROLE_ADMIN` role the route will be exposed, otherwise
|
||||
the route will be excluded.
|
||||
|
||||
## `parameter`
|
||||
|
||||
Allows you to fetch a parameter from the service container:
|
||||
|
||||
```
|
||||
/**
|
||||
* @Hateoas\Relation(
|
||||
* "delete",
|
||||
* href = @Hateoas\Route(
|
||||
* "post_delete",
|
||||
* parameters = { "foo" = "expr(parameter('foo'))" }
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
class Post
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
## `service`
|
||||
|
||||
Allows you to fetch a service from the service container.
|
||||
|
||||
Extending
|
||||
---------
|
||||
|
||||
### RelationProviderResolver
|
||||
|
||||
A relation provider resolver is a class which provides a PHP callable. This
|
||||
callable will provide relations (links) for a given object.
|
||||
|
||||
You can add new relation providers by implementing the
|
||||
`Hateoas\Configuration\Provider\Resolver\RelationProviderResolverInterface`
|
||||
interface and adding a definition to the dependency injection configuration
|
||||
with the tag `hateoas.relation_provider`:
|
||||
|
||||
````xml
|
||||
<?xml version="1.0" ?>
|
||||
<container ...>
|
||||
|
||||
<!-- ... -->
|
||||
|
||||
<services>
|
||||
<!-- ... -->
|
||||
|
||||
<service id="acme_foo.hateoas.relation_provider_resolver.foobar" class="Acme\FooBundle\Hateoas\RelationProviderResolver\Foobar">
|
||||
<tag name="hateoas.relation_provider" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
````
|
||||
|
||||
### Configuration Extension
|
||||
|
||||
A configuration extension allows you to override already configured relations.
|
||||
|
||||
You can add an extension configuration by adding a definition to the dependency
|
||||
injection configuration with the tag `hateoas.configuration_extension`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" ?>
|
||||
<container ...>
|
||||
|
||||
<!-- ... -->
|
||||
|
||||
<services>
|
||||
<!-- ... -->
|
||||
|
||||
<service id="acme_foo.hateoas.configuration_extension.foobar" class="Acme\FooBundle\Hateoas\ConfigurationExtension\AcmeFooConfigurationExtension">
|
||||
<tag name="hateoas.configuration_extension" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
```
|
||||
|
||||
```php
|
||||
<?php
|
||||
namespace Acme\FooBundle\Hateoas\ConfigurationExtension;
|
||||
|
||||
use Hateoas\Configuration\Metadata\ConfigurationExtensionInterface;
|
||||
use Hateoas\Configuration\Metadata\ClassMetadataInterface;
|
||||
use Hateoas\Configuration\Relation;
|
||||
|
||||
class AcmeFooConfigurationExtension implements ConfigurationExtensionInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function decorate(ClassMetadataInterface $classMetadata)
|
||||
{
|
||||
if (0 === strpos('Acme\Foo\Model', $classMetadata->getName())) {
|
||||
// Add a "root" relation to all classes in the `Acme\Foo\Model` namespace
|
||||
$classMetadata->addRelation(
|
||||
new Relation(
|
||||
'root',
|
||||
'/'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Reference Configuration
|
||||
-----------------------
|
||||
|
||||
``` yaml
|
||||
# app/config/config*.yml
|
||||
|
||||
bazinga_hateoas:
|
||||
metadata:
|
||||
cache: file
|
||||
file_cache:
|
||||
dir: %kernel.cache_dir%/hateoas
|
||||
serializer:
|
||||
json: hateoas.serializer.json_hal
|
||||
xml: hateoas.serializer.xml
|
||||
twig_extension:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Setup the test suite using [Composer](http://getcomposer.org/):
|
||||
|
||||
$ composer install --dev
|
||||
|
||||
Run it using PHPUnit:
|
||||
|
||||
$ phpunit
|
||||
+271
@@ -0,0 +1,271 @@
|
||||
<?php
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\Tests\DependencyInjection;
|
||||
|
||||
use Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle;
|
||||
use Bazinga\Bundle\HateoasBundle\DependencyInjection\Compiler\UrlGeneratorPass;
|
||||
use Bazinga\Bundle\HateoasBundle\Tests\TestCase;
|
||||
use Bazinga\Bundle\HateoasBundle\Tests\Fixtures\SimpleObject;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use JMS\SerializerBundle\JMSSerializerBundle;
|
||||
use Symfony\Component\DependencyInjection\Compiler\ResolveParameterPlaceHoldersPass;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
|
||||
class BazingaHateoasExtensionTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
$this->clearTempDir();
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
$this->clearTempDir();
|
||||
}
|
||||
|
||||
public function testLoad()
|
||||
{
|
||||
$container = $this->getContainerForConfig(array(array()));
|
||||
$container->compile();
|
||||
|
||||
$serializer = $container->get('jms_serializer');
|
||||
|
||||
$this->assertEquals(
|
||||
json_encode(array(
|
||||
'name' => 'hello',
|
||||
'_links' => array(
|
||||
'all' => array(
|
||||
'href' => 'http://somewhere/simple-objects',
|
||||
'foo' => 'bar',
|
||||
),
|
||||
'all_2' => array(
|
||||
'href' => 'http://somewhere/simple-objects',
|
||||
),
|
||||
)
|
||||
)),
|
||||
$serializer->serialize(new SimpleObject('hello'), 'json')
|
||||
);
|
||||
}
|
||||
|
||||
public function testRelationProviderPassInvalidProvider()
|
||||
{
|
||||
$container = $this->getContainerForConfig(array(array()));
|
||||
$container->compile();
|
||||
$definition = $container->getDefinition('hateoas.configuration.provider.resolver.chain');
|
||||
$arguments = $definition->getArguments();
|
||||
$this->assertCount(1, $arguments);
|
||||
$this->assertCount(3, $arguments[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testRelationProviderPass()
|
||||
{
|
||||
$container = $this->getContainerForConfig(array(array()));
|
||||
$definition = $container->register('invalid_relation_provider', 'stdClass');
|
||||
$definition->addTag('hateoas.relation_provider');
|
||||
$container->compile();
|
||||
}
|
||||
|
||||
public function testLoadUrlGenerator()
|
||||
{
|
||||
$container = $this->getContainerForConfig(array(array()));
|
||||
|
||||
$urlGeneratorClass = 'Bazinga\Bundle\HateoasBundle\Tests\Fixtures\UrlGenerator';
|
||||
$container->setParameter('url_generator_2.class', $urlGeneratorClass);
|
||||
|
||||
$this->registerUrlGenerator($container, 'url_generator_1', $urlGeneratorClass);
|
||||
$this->registerUrlGenerator($container, 'url_generator_2', '%url_generator_2.class%');
|
||||
|
||||
$container->compile();
|
||||
|
||||
$urlGeneratorRegistry = $container->get('hateoas.generator.registry');
|
||||
|
||||
$urlGenerator1 = $urlGeneratorRegistry->get('url_generator_1');
|
||||
$this->assertInstanceOf($urlGeneratorClass, $urlGenerator1);
|
||||
|
||||
$urlGenerator2 = $urlGeneratorRegistry->get('url_generator_2');
|
||||
$this->assertInstanceOf($urlGeneratorClass, $urlGenerator2);
|
||||
}
|
||||
|
||||
public function testLoadSerializer()
|
||||
{
|
||||
$class = 'Bazinga\Bundle\HateoasBundle\Tests\Fixtures\JsonSerializer';
|
||||
$container = $this->getContainerForConfig(array('bazinga_hateoas' => array('serializer' => array('json' => 'custom_serializer'))));
|
||||
$container->setDefinition('custom_serializer', new Definition($class));
|
||||
$container->compile();
|
||||
|
||||
$jsonListener = $container->get('hateoas.event_subscriber.json');
|
||||
|
||||
$reflClass = new \ReflectionClass($jsonListener);
|
||||
$reflProp = $reflClass->getProperty('jsonSerializer');
|
||||
$reflProp->setAccessible(true);
|
||||
|
||||
$this->assertInstanceOf($class, $reflProp->getValue($jsonListener));
|
||||
|
||||
$xmlListener = $container->get('hateoas.event_subscriber.xml');
|
||||
|
||||
$reflClass = new \ReflectionClass($xmlListener);
|
||||
$reflProp = $reflClass->getProperty('xmlSerializer');
|
||||
$reflProp->setAccessible(true);
|
||||
|
||||
$this->assertInstanceOf('Hateoas\Serializer\XmlSerializer', $reflProp->getValue($xmlListener));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
||||
*/
|
||||
public function testNotLoadingTwigHelper()
|
||||
{
|
||||
$container = $this->getContainerForConfig(array('bazinga_hateoas' => array('twig_extension' => array('enabled' => false))));
|
||||
$container->findDefinition('hateoas.twig.link');
|
||||
$container->compile();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
||||
* @expectedExceptionMessage Service invalid_expression_function tagged with hateoas.expression_function must implement Hateoas\Expression\ExpressionFunctionInterface
|
||||
*/
|
||||
public function testLoadInvalidExpressionFunction()
|
||||
{
|
||||
$container = $this->getContainerForConfig(array(array()));
|
||||
$container
|
||||
->setDefinition(
|
||||
'invalid_expression_function',
|
||||
new Definition('stdClass')
|
||||
)
|
||||
->addTag('hateoas.expression_function')
|
||||
;
|
||||
$container->compile();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
||||
* @expectedExceptionMessage Service invalid_configuration_extension tagged with hateoas.configuration_extension must implement Hateoas\Configuration\Metadata\ConfigurationExtensionInterface
|
||||
*/
|
||||
public function testLoadInvalidConfigurationExtension()
|
||||
{
|
||||
$container = $this->getContainerForConfig(array(array()));
|
||||
$container
|
||||
->setDefinition(
|
||||
'invalid_configuration_extension',
|
||||
new Definition('stdClass')
|
||||
)
|
||||
->addTag('hateoas.configuration_extension')
|
||||
;
|
||||
$container->compile();
|
||||
}
|
||||
|
||||
private function clearTempDir()
|
||||
{
|
||||
// clear temporary directory
|
||||
$dir = $this->getTempDir();
|
||||
if (is_dir($dir)) {
|
||||
foreach (new \RecursiveDirectoryIterator($dir) as $file) {
|
||||
$filename = $file->getFileName();
|
||||
if ('.' === $filename || '..' === $filename) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@unlink($file->getPathName());
|
||||
}
|
||||
|
||||
@rmdir($dir);
|
||||
}
|
||||
}
|
||||
|
||||
private function getTempDir()
|
||||
{
|
||||
return sys_get_temp_dir() . '/hateoas-bundle';
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/schmittjoh/JMSSerializerBundle/blob/master/Tests/DependencyInjection/JMSSerializerExtensionTest.php
|
||||
*/
|
||||
private function getContainerForConfig(array $configs, KernelInterface $kernel = null)
|
||||
{
|
||||
if (null === $kernel) {
|
||||
$kernel = $this->getMock(KernelInterface::class);
|
||||
$kernel
|
||||
->expects($this->any())
|
||||
->method('getBundles')
|
||||
->will($this->returnValue(array()))
|
||||
;
|
||||
}
|
||||
|
||||
$router = $this->getMock(UrlGeneratorInterface::class);
|
||||
$bundles = array(
|
||||
new BazingaHateoasBundle($kernel),
|
||||
new JMSSerializerBundle($kernel),
|
||||
);
|
||||
|
||||
$extensions = array_map(function ($bundle) {
|
||||
return $bundle->getContainerExtension();
|
||||
}, $bundles);
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->setParameter('kernel.debug', true);
|
||||
$container->setParameter('kernel.cache_dir', $this->getTempDir());
|
||||
$container->setParameter('kernel.bundles', array());
|
||||
$container->set('annotation_reader', new AnnotationReader());
|
||||
$container->set('router', $router);
|
||||
$container->set('debug.stopwatch', $this->getMock(Stopwatch::class));
|
||||
|
||||
$container->setParameter('foo', 'bar');
|
||||
|
||||
foreach ($extensions as $extension) {
|
||||
$extensionConfig = isset($configs[$extension->getAlias()]) ? $configs[$extension->getAlias()] : array();
|
||||
|
||||
$container->registerExtension($extension);
|
||||
$extension->load(array($extension->getAlias() => $extensionConfig), $container);
|
||||
}
|
||||
|
||||
foreach ($bundles as $bundle) {
|
||||
$bundle->build($container);
|
||||
}
|
||||
|
||||
$this->setOptimizationPasses($container);
|
||||
$container->getCompilerPassConfig()->setRemovingPasses(array());
|
||||
|
||||
return $container;
|
||||
}
|
||||
|
||||
private function registerUrlGenerator(ContainerBuilder $container, $id, $class)
|
||||
{
|
||||
$urlGeneratorDefinition = new Definition($class);
|
||||
$urlGeneratorDefinition->addTag('hateoas.url_generator');
|
||||
|
||||
$container->setDefinition($id, $urlGeneratorDefinition);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $container
|
||||
*/
|
||||
private function setOptimizationPasses(Container $container)
|
||||
{
|
||||
if (class_exists('Symfony\Component\DependencyInjection\Compiler\ResolveDefinitionTemplatesPass')) {
|
||||
$container->getCompilerPassConfig()->setOptimizationPasses(
|
||||
array(
|
||||
new ResolveParameterPlaceHoldersPass(),
|
||||
new \Symfony\Component\DependencyInjection\Compiler\ResolveDefinitionTemplatesPass(),
|
||||
new UrlGeneratorPass(),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$container->getCompilerPassConfig()->setOptimizationPasses(
|
||||
array(
|
||||
new ResolveParameterPlaceHoldersPass(),
|
||||
new \Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass(),
|
||||
new UrlGeneratorPass(),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\Tests\Fixtures;
|
||||
|
||||
use Hateoas\Serializer\JsonSerializerInterface;
|
||||
use JMS\Serializer\JsonSerializationVisitor;
|
||||
use JMS\Serializer\SerializationContext;
|
||||
|
||||
class JsonSerializer implements JsonSerializerInterface
|
||||
{
|
||||
public function serializeLinks(array $links, JsonSerializationVisitor $visitor, SerializationContext $context)
|
||||
{
|
||||
}
|
||||
|
||||
public function serializeEmbeddeds(array $embeddeds, JsonSerializationVisitor $visitor, SerializationContext $context)
|
||||
{
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\Tests\Fixtures;
|
||||
|
||||
use JMS\Serializer\Annotation\SerializedName;
|
||||
use JMS\Serializer\Annotation\Type;
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
|
||||
/**
|
||||
* @Hateoas\Relation(
|
||||
* "all",
|
||||
* href = "http://somewhere/simple-objects",
|
||||
* attributes = { "foo" = "expr(parameter('foo'))" }
|
||||
* )
|
||||
* @Hateoas\Relation(
|
||||
* "all_2",
|
||||
* href = "expr(link(object, 'all'))"
|
||||
* )
|
||||
*/
|
||||
class SimpleObject
|
||||
{
|
||||
/**
|
||||
* @Type("string")
|
||||
* @SerializedName("name")
|
||||
*/
|
||||
private $value;
|
||||
|
||||
public function __construct($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\Tests\Fixtures;
|
||||
|
||||
use Hateoas\UrlGenerator\UrlGeneratorInterface;
|
||||
|
||||
class UrlGenerator implements UrlGeneratorInterface
|
||||
{
|
||||
public function generate($name, array $parameters, $absolute = false)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Bazinga\Bundle\HateoasBundle\Tests;
|
||||
|
||||
abstract class TestCase extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationRegistry;
|
||||
|
||||
if (!($loader = @include __DIR__ . '/../vendor/autoload.php')) {
|
||||
die(<<<EOT
|
||||
You need to install the project dependencies using Composer:
|
||||
$ wget http://getcomposer.org/composer.phar
|
||||
OR
|
||||
$ curl -s https://getcomposer.org/installer | php
|
||||
$ php composer.phar install --dev
|
||||
$ phpunit
|
||||
EOT
|
||||
);
|
||||
}
|
||||
|
||||
AnnotationRegistry::registerLoader('class_exists');
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "willdurand/hateoas-bundle",
|
||||
"description": "Integration of Hateoas into Symfony2.",
|
||||
"keywords": [ "rest", "hateoas" ],
|
||||
"type": "symfony-bundle",
|
||||
"minimum-stability": "dev",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "William Durand",
|
||||
"email": "william.durand1@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">5.4 |^7.0",
|
||||
"symfony/framework-bundle": "~2.3 || ~3.0 || ~4.0",
|
||||
"willdurand/hateoas": "^2.10.0",
|
||||
"jms/serializer-bundle": "~1.0 || ^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/expression-language": "~2.4 || ~3.0 || ~4.0",
|
||||
"twig/twig": "~1.12",
|
||||
"phpunit/phpunit": "~4.5 || ~5.0",
|
||||
"symfony/stopwatch": "~2.4 || ~3.0 || ~4.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Bazinga\\Bundle\\HateoasBundle\\": "" }
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="./Tests/bootstrap.php"
|
||||
>
|
||||
|
||||
<testsuites>
|
||||
<testsuite name="BazingaHateoasBundle Test Suite">
|
||||
<directory>./Tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>.</directory>
|
||||
<exclude>
|
||||
<directory>Resources</directory>
|
||||
<directory>Tests</directory>
|
||||
<directory>vendor</directory>
|
||||
</exclude>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
@@ -0,0 +1,4 @@
|
||||
vendor
|
||||
composer.lock
|
||||
composer.phar
|
||||
bin
|
||||
@@ -0,0 +1,51 @@
|
||||
language: php
|
||||
sudo: required
|
||||
dist: trusty
|
||||
group: edge
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
|
||||
php:
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- php: 5.6
|
||||
env: SYMFONY_VERSION=4.0.*
|
||||
- php: 7.0
|
||||
env: SYMFONY_VERSION=4.0.*
|
||||
- php: hhvm-3.9
|
||||
env: SYMFONY_VERSION=4.0.*
|
||||
- php: hhvm-3.12
|
||||
env: SYMFONY_VERSION=4.0.*
|
||||
- php: hhvm-3.15
|
||||
env: SYMFONY_VERSION=4.0.*
|
||||
- php: hhvm-3.18
|
||||
env: SYMFONY_VERSION=4.0.*
|
||||
fast_finish: true
|
||||
env:
|
||||
- SYMFONY_VERSION=2.4.*
|
||||
- SYMFONY_VERSION=2.5.*
|
||||
- SYMFONY_VERSION=2.6.*
|
||||
- SYMFONY_VERSION=2.7.*
|
||||
- SYMFONY_VERSION=2.8.*
|
||||
- SYMFONY_VERSION=3.0.*
|
||||
- SYMFONY_VERSION=3.2.*
|
||||
- SYMFONY_VERSION=4.0.*
|
||||
|
||||
before_install:
|
||||
- composer self-update
|
||||
- composer require --no-update symfony/expression-language "$SYMFONY_VERSION"
|
||||
- composer require --no-update --dev symfony/yaml "$SYMFONY_VERSION"
|
||||
- composer require --no-update --dev symfony/routing "$SYMFONY_VERSION"
|
||||
- composer require --no-update --dev symfony/dependency-injection "$SYMFONY_VERSION"
|
||||
|
||||
install:
|
||||
- composer install --no-interaction --prefer-dist
|
||||
|
||||
script:
|
||||
- ./bin/phpunit --coverage-text
|
||||
@@ -0,0 +1,33 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
First of all, **thank you** for contributing, **you are awesome**!
|
||||
|
||||
Here are a few rules to follow in order to ease code reviews, and discussions before
|
||||
maintainers accept and merge your work.
|
||||
|
||||
You MUST follow the [PSR-1](http://www.php-fig.org/psr/1/) and
|
||||
[PSR-2](http://www.php-fig.org/psr/2/). If you don't know about any of them, you
|
||||
should really read the recommendations. Can't wait? Use the [PHP-CS-Fixer
|
||||
tool](http://cs.sensiolabs.org/).
|
||||
|
||||
You MUST run the test suite.
|
||||
|
||||
You MUST write (or update) unit tests.
|
||||
|
||||
You SHOULD write documentation.
|
||||
|
||||
Please, write [commit messages that make
|
||||
sense](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
|
||||
and [rebase your branch](http://git-scm.com/book/en/Git-Branching-Rebasing)
|
||||
before submitting your Pull Request.
|
||||
|
||||
One may ask you to [squash your
|
||||
commits](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html)
|
||||
too. This is used to "clean" your Pull Request before merging it (we don't want
|
||||
commits such as `fix tests`, `fix 2`, `fix 3`, etc.).
|
||||
|
||||
Also, while creating your Pull Request on GitHub, you MUST write a description
|
||||
which gives the context and/or explains why you are creating it.
|
||||
|
||||
Thank you!
|
||||
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2012-2013 William Durand <william.durand1@gmail.com>
|
||||
Adrien Brault <adrien.brault@gmail.com>
|
||||
|
||||
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.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "willdurand/hateoas",
|
||||
"description": "A PHP library to support implementing representations for HATEOAS REST web services",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "William Durand",
|
||||
"email": "william.durand1@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Adrien Brault",
|
||||
"email": "adrien.brault@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^5.5|^7.0",
|
||||
"doctrine/common": "~2.0",
|
||||
"doctrine/annotations": "~1.0",
|
||||
"jms/metadata": "~1.1",
|
||||
"jms/serializer": "^1.7",
|
||||
"symfony/expression-language": "~2.4 || ~3.0 || ~4.0",
|
||||
"phpoption/phpoption": ">=1.1.0,<2.0-dev"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~5",
|
||||
"symfony/yaml": "~2.4 || ~3.0 || ~4.0",
|
||||
"symfony/routing": "~2.4 || ~3.0 || ~4.0",
|
||||
"symfony/dependency-injection": "~2.4 || ~3.0 || ~4.0",
|
||||
"pagerfanta/pagerfanta": "~1.0",
|
||||
"twig/twig": "~1.12"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/yaml": "To use yaml based configuration.",
|
||||
"symfony/routing": "To use the SymfonyRouteFactory.",
|
||||
"twig/twig": "To use the Twig extensions."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Hateoas": "src/" }
|
||||
},
|
||||
"config": {
|
||||
"bin-dir": "bin"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.12-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="https://github.com/willdurand/Hateoas"
|
||||
xmlns:h="https://github.com/willdurand/Hateoas"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<annotation>
|
||||
<documentation><![CDATA[This is the XML Schema for the hateoas serialization]]></documentation>
|
||||
</annotation>
|
||||
|
||||
<complexType name="class">
|
||||
<sequence>
|
||||
<element name="relation" type="h:relation" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="providers" type="normalizedString" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="relation">
|
||||
<sequence>
|
||||
<element name="href" type="h:href" minOccurs="0"/>
|
||||
<element name="embedded" type="h:embedded" minOccurs="0"/>
|
||||
<element name="exclusion" type="h:exclusion" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<element name="attribute" type="h:attribute" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="rel" type="token" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="attribute">
|
||||
<attribute name="name" type="normalizedString" use="required"/>
|
||||
<attribute name="value" type="normalizedString" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="href">
|
||||
<sequence>
|
||||
<element name="parameter" type="h:attribute" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="uri" type="normalizedString" use="optional"/>
|
||||
<attribute name="route" type="normalizedString" use="optional"/>
|
||||
<attribute name="absolute" type="boolean" use="optional"/>
|
||||
<attribute name="generator" type="normalizedString" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="embedded">
|
||||
<sequence>
|
||||
<element name="content" type="normalizedString"/>
|
||||
<element name="exclusion" type="h:exclusion" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="xml-element-name" type="token" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<complexType name="exclusion">
|
||||
<attribute name="groups" type="normalizedString" use="optional"/>
|
||||
<attribute name="since-version" type="normalizedString" use="optional"/>
|
||||
<attribute name="until-version" type="normalizedString" use="optional"/>
|
||||
<attribute name="max-depth" type="normalizedString" use="optional"/>
|
||||
<attribute name="exclude-if" type="normalizedString" use="optional"/>
|
||||
</complexType>
|
||||
</schema>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="tests/bootstrap.php"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Hateoas Test Suite">
|
||||
<directory>./tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>./src/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Annotation;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("ANNOTATION")
|
||||
*
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class Embedded
|
||||
{
|
||||
/**
|
||||
* @Required
|
||||
*/
|
||||
public $content;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $xmlElementName;
|
||||
|
||||
/**
|
||||
* @var \Hateoas\Configuration\Annotation\Exclusion
|
||||
*/
|
||||
public $exclusion = null;
|
||||
}
|
||||
Vendored
+41
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Annotation;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("ANNOTATION")
|
||||
*
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
final class Exclusion
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $groups = null;
|
||||
|
||||
/**
|
||||
* @var mixed float/integer
|
||||
*/
|
||||
public $sinceVersion = null;
|
||||
|
||||
/**
|
||||
* @var mixed float/integer
|
||||
*/
|
||||
public $untilVersion = null;
|
||||
|
||||
/**
|
||||
* If you are working with the FOS/Rest Bundle, be reminded to set
|
||||
* Rest\View(serializerEnableMaxDepthChecks=true)
|
||||
* on your controller
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $maxDepth = null;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $excludeIf = null;
|
||||
}
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Annotation;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
final class Relation
|
||||
{
|
||||
/**
|
||||
* @Required
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
public $href = null;
|
||||
|
||||
public $embedded = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $attributes = array();
|
||||
|
||||
/**
|
||||
* @var \Hateoas\Configuration\Annotation\Exclusion
|
||||
*/
|
||||
public $exclusion = null;
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Annotation;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class RelationProvider
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
}
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Annotation;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("ANNOTATION")
|
||||
*
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class Route
|
||||
{
|
||||
/**
|
||||
* @Required
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @Required
|
||||
*/
|
||||
public $parameters = array();
|
||||
|
||||
public $absolute = false;
|
||||
|
||||
public $generator = null;
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class Embedded
|
||||
{
|
||||
/**
|
||||
* @var string|mixed
|
||||
*/
|
||||
private $content;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $xmlElementName;
|
||||
|
||||
/**
|
||||
* @var Exclusion|null
|
||||
*/
|
||||
private $exclusion;
|
||||
|
||||
/**
|
||||
* @param string|mixed $content
|
||||
* @param string|null $xmlElementName
|
||||
* @param Exclusion $exclusion
|
||||
*/
|
||||
public function __construct($content, $xmlElementName = null, Exclusion $exclusion = null)
|
||||
{
|
||||
$this->content = $content;
|
||||
$this->xmlElementName = $xmlElementName;
|
||||
$this->exclusion = $exclusion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed|string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
*/
|
||||
public function getXmlElementName()
|
||||
{
|
||||
return $this->xmlElementName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Exclusion|null
|
||||
*/
|
||||
public function getExclusion()
|
||||
{
|
||||
return $this->exclusion;
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class Exclusion
|
||||
{
|
||||
/**
|
||||
* @var null|array
|
||||
*/
|
||||
private $groups;
|
||||
|
||||
/**
|
||||
* @var null|float
|
||||
*/
|
||||
private $sinceVersion;
|
||||
|
||||
/**
|
||||
* @var null|float
|
||||
*/
|
||||
private $untilVersion;
|
||||
|
||||
/**
|
||||
* @var null|integer
|
||||
*/
|
||||
private $maxDepth;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
private $excludeIf;
|
||||
|
||||
public function __construct(
|
||||
array $groups = null,
|
||||
$sinceVersion = null,
|
||||
$untilVersion = null,
|
||||
$maxDepth = null,
|
||||
$excludeIf = null
|
||||
) {
|
||||
$this->groups = $groups;
|
||||
$this->sinceVersion = null !== $sinceVersion ? (float) $sinceVersion : null;
|
||||
$this->untilVersion = null !== $untilVersion ? (float) $untilVersion : null;
|
||||
$this->maxDepth = null !== $maxDepth ? (int) $maxDepth : null;
|
||||
$this->excludeIf = $excludeIf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|array
|
||||
*/
|
||||
public function getGroups()
|
||||
{
|
||||
return $this->groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|float
|
||||
*/
|
||||
public function getSinceVersion()
|
||||
{
|
||||
return $this->sinceVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|float
|
||||
*/
|
||||
public function getUntilVersion()
|
||||
{
|
||||
return $this->untilVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getMaxDepth()
|
||||
{
|
||||
return $this->maxDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
*/
|
||||
public function getExcludeIf()
|
||||
{
|
||||
return $this->excludeIf;
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Metadata;
|
||||
|
||||
use Hateoas\Configuration\Relation;
|
||||
use Hateoas\Configuration\RelationProvider;
|
||||
use Metadata\MergeableClassMetadata;
|
||||
use Metadata\MergeableInterface;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class ClassMetadata extends MergeableClassMetadata implements ClassMetadataInterface
|
||||
{
|
||||
/**
|
||||
* @var Relation[]
|
||||
*/
|
||||
private $relations = array();
|
||||
|
||||
/**
|
||||
* @var RelationProvider[]
|
||||
*/
|
||||
private $relationProviders = array();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getRelations()
|
||||
{
|
||||
return $this->relations;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getRelationProviders()
|
||||
{
|
||||
return $this->relationProviders;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function addRelation(Relation $relation)
|
||||
{
|
||||
$this->relations[] = $relation;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function addRelationProvider(RelationProvider $relationProvider)
|
||||
{
|
||||
$this->relationProviders[] = $relationProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function merge(MergeableInterface $object)
|
||||
{
|
||||
if (!$object instanceof self) {
|
||||
throw new \InvalidArgumentException(sprintf('Object must be an instance of %s.', __CLASS__));
|
||||
}
|
||||
|
||||
parent::merge($object);
|
||||
|
||||
$this->relations = array_merge($this->relations, $object->getRelations());
|
||||
$this->relationProviders = array_merge($this->relationProviders, $object->getRelationProviders());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize(array(
|
||||
$this->relations,
|
||||
$this->relationProviders,
|
||||
parent::serialize(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function unserialize($str)
|
||||
{
|
||||
list(
|
||||
$this->relations,
|
||||
$this->relationProviders,
|
||||
$parentStr
|
||||
) = unserialize($str);
|
||||
|
||||
parent::unserialize($parentStr);
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Metadata;
|
||||
|
||||
use Hateoas\Configuration\Relation;
|
||||
use Hateoas\Configuration\RelationProvider;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
interface ClassMetadataInterface
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* @return Relation[]
|
||||
*/
|
||||
public function getRelations();
|
||||
|
||||
/**
|
||||
* @return RelationProvider[]
|
||||
*/
|
||||
public function getRelationProviders();
|
||||
|
||||
/**
|
||||
* @param Relation $relation
|
||||
*/
|
||||
public function addRelation(Relation $relation);
|
||||
|
||||
/**
|
||||
* @param RelationProvider $relationProvider
|
||||
*/
|
||||
public function addRelationProvider(RelationProvider $relationProvider);
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Metadata;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
interface ConfigurationExtensionInterface
|
||||
{
|
||||
public function decorate(ClassMetadataInterface $classMetadata);
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Metadata\Driver;
|
||||
|
||||
use Doctrine\Common\Annotations\Reader as AnnotationsReader;
|
||||
use Hateoas\Configuration\Annotation;
|
||||
use Hateoas\Configuration\Embedded;
|
||||
use Hateoas\Configuration\Exclusion;
|
||||
use Hateoas\Configuration\Metadata\ClassMetadata;
|
||||
use Hateoas\Configuration\Relation;
|
||||
use Hateoas\Configuration\RelationProvider;
|
||||
use Hateoas\Configuration\Route;
|
||||
use Metadata\Driver\DriverInterface;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class AnnotationDriver implements DriverInterface
|
||||
{
|
||||
/**
|
||||
* @var AnnotationsReader
|
||||
*/
|
||||
private $reader;
|
||||
|
||||
/**
|
||||
* @param AnnotationsReader $reader
|
||||
*/
|
||||
public function __construct(AnnotationsReader $reader)
|
||||
{
|
||||
$this->reader = $reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadMetadataForClass(\ReflectionClass $class)
|
||||
{
|
||||
$annotations = $this->reader->getClassAnnotations($class);
|
||||
|
||||
if (0 === count($annotations)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$classMetadata = new ClassMetadata($class->getName());
|
||||
$classMetadata->fileResources[] = $class->getFilename();
|
||||
|
||||
foreach ($annotations as $annotation) {
|
||||
if ($annotation instanceof Annotation\Relation) {
|
||||
$classMetadata->addRelation(new Relation(
|
||||
$annotation->name,
|
||||
$this->createHref($annotation->href),
|
||||
$this->createEmbedded($annotation->embedded),
|
||||
$annotation->attributes ?: array(),
|
||||
$this->createExclusion($annotation->exclusion)
|
||||
));
|
||||
} elseif ($annotation instanceof Annotation\RelationProvider) {
|
||||
$classMetadata->addRelationProvider(new RelationProvider($annotation->name));
|
||||
}
|
||||
}
|
||||
|
||||
if (0 === count($classMetadata->getRelations()) && 0 === count($classMetadata->getRelationProviders())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $classMetadata;
|
||||
}
|
||||
|
||||
private function parseExclusion(Annotation\Exclusion $exclusion)
|
||||
{
|
||||
return new Exclusion(
|
||||
$exclusion->groups,
|
||||
$exclusion->sinceVersion,
|
||||
$exclusion->untilVersion,
|
||||
$exclusion->maxDepth,
|
||||
$exclusion->excludeIf
|
||||
);
|
||||
}
|
||||
|
||||
private function createHref($href)
|
||||
{
|
||||
if ($href instanceof Annotation\Route) {
|
||||
$href = new Route($href->name, $href->parameters, $href->absolute, $href->generator);
|
||||
}
|
||||
|
||||
return $href;
|
||||
}
|
||||
|
||||
private function createEmbedded($embedded)
|
||||
{
|
||||
if ($embedded instanceof Annotation\Embedded) {
|
||||
$embeddedExclusion = $embedded->exclusion;
|
||||
|
||||
if (null !== $embeddedExclusion) {
|
||||
$embeddedExclusion = $this->parseExclusion($embeddedExclusion);
|
||||
}
|
||||
|
||||
$embedded = new Embedded($embedded->content, $embedded->xmlElementName, $embeddedExclusion);
|
||||
}
|
||||
|
||||
return $embedded;
|
||||
}
|
||||
|
||||
private function createExclusion($exclusion)
|
||||
{
|
||||
if (null !== $exclusion) {
|
||||
$exclusion = $this->parseExclusion($exclusion);
|
||||
}
|
||||
|
||||
return $exclusion;
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Metadata\Driver;
|
||||
|
||||
use Hateoas\Configuration\Metadata\ClassMetadata;
|
||||
use Hateoas\Configuration\Metadata\ConfigurationExtensionInterface;
|
||||
use Metadata\Driver\DriverInterface;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class ExtensionDriver implements DriverInterface
|
||||
{
|
||||
/**
|
||||
* @var DriverInterface
|
||||
*/
|
||||
private $delegate;
|
||||
|
||||
/**
|
||||
* @var ConfigurationExtensionInterface[]
|
||||
*/
|
||||
private $extensions;
|
||||
|
||||
public function __construct(DriverInterface $delegate, array $extensions = [])
|
||||
{
|
||||
$this->delegate = $delegate;
|
||||
$this->extensions = $extensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadMetadataForClass(\ReflectionClass $class)
|
||||
{
|
||||
$metadata = $this->delegate->loadMetadataForClass($class);
|
||||
$newMetadata = false;
|
||||
|
||||
if (empty($this->extensions)) {
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
if (null === $metadata) {
|
||||
$metadata = new ClassMetadata($class->getName());
|
||||
$newMetadata = true;
|
||||
}
|
||||
|
||||
foreach ($this->extensions as $extension) {
|
||||
$extension->decorate($metadata);
|
||||
}
|
||||
|
||||
if ($newMetadata && count($metadata->getRelations()) < 1 && count($metadata->getRelationProviders()) < 1) {
|
||||
$metadata = null;
|
||||
}
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConfigurationExtensionInterface $extension
|
||||
*/
|
||||
public function registerExtension(ConfigurationExtensionInterface $extension)
|
||||
{
|
||||
$this->extensions[] = $extension;
|
||||
}
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Metadata\Driver;
|
||||
|
||||
use Hateoas\Configuration\Embedded;
|
||||
use Hateoas\Configuration\Exclusion;
|
||||
use Hateoas\Configuration\Metadata\ClassMetadata;
|
||||
use Hateoas\Configuration\Relation;
|
||||
use Hateoas\Configuration\RelationProvider;
|
||||
use Hateoas\Configuration\Route;
|
||||
use JMS\Serializer\Exception\XmlErrorException;
|
||||
use Metadata\Driver\AbstractFileDriver;
|
||||
|
||||
/**
|
||||
* @author Miha Vrhovnik <miha.vrhovnik@pagein.net>
|
||||
*/
|
||||
class XmlDriver extends AbstractFileDriver
|
||||
{
|
||||
const NAMESPACE_URI = 'https://github.com/willdurand/Hateoas';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function loadMetadataFromFile(\ReflectionClass $class, $file)
|
||||
{
|
||||
$previous = libxml_use_internal_errors(true);
|
||||
$root = simplexml_load_file($file);
|
||||
libxml_use_internal_errors($previous);
|
||||
|
||||
if (false === $root) {
|
||||
throw new XmlErrorException(libxml_get_last_error());
|
||||
}
|
||||
|
||||
$name = $class->getName();
|
||||
if (!$exists = $root->xpath("./class[@name = '" . $name . "']")) {
|
||||
throw new \RuntimeException(sprintf('Expected metadata for class %s to be defined in %s.', $name, $file));
|
||||
}
|
||||
|
||||
$classMetadata = new ClassMetadata($name);
|
||||
$classMetadata->fileResources[] = $file;
|
||||
$classMetadata->fileResources[] = $class->getFileName();
|
||||
|
||||
if ($exists[0]->attributes(self::NAMESPACE_URI)->providers) {
|
||||
$providers = preg_split('/\s*,\s*/', (string) $exists[0]->attributes(self::NAMESPACE_URI)->providers);
|
||||
|
||||
foreach ($providers as $relationProvider) {
|
||||
$classMetadata->addRelationProvider(new RelationProvider($relationProvider));
|
||||
}
|
||||
}
|
||||
|
||||
$elements = $exists[0]->children(self::NAMESPACE_URI);
|
||||
|
||||
foreach ($elements->relation as $relation) {
|
||||
$name = (string) $relation->attributes('')->rel;
|
||||
|
||||
$href = null;
|
||||
if (isset($relation->href)) {
|
||||
$href = $this->createHref($relation->href, $name);
|
||||
}
|
||||
|
||||
$embedded = null;
|
||||
if (isset($relation->embedded)) {
|
||||
$embedded = $this->createEmbedded($relation->embedded);
|
||||
}
|
||||
|
||||
$attributes = array();
|
||||
foreach ($relation->attribute as $attribute) {
|
||||
$attributes[(string) $attribute->attributes('')->name] = (string) $attribute->attributes('')->value;
|
||||
}
|
||||
|
||||
$exclusion = isset($relation->exclusion) ? $this->parseExclusion($relation->exclusion) : null;
|
||||
|
||||
$classMetadata->addRelation(
|
||||
new Relation(
|
||||
$name,
|
||||
$href,
|
||||
$embedded,
|
||||
$attributes,
|
||||
$exclusion
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $classMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExtension()
|
||||
{
|
||||
return 'xml';
|
||||
}
|
||||
|
||||
private function parseExclusion(\SimpleXMLElement $exclusion)
|
||||
{
|
||||
return new Exclusion(
|
||||
isset($exclusion->attributes('')->groups) ? preg_split('/\s*,\s*/', (string) $exclusion->attributes('')->groups) : null,
|
||||
isset($exclusion->attributes('')->{'since-version'}) ? (string) $exclusion->attributes('')->{'since-version'} : null,
|
||||
isset($exclusion->attributes('')->{'until-version'}) ? (string) $exclusion->attributes('')->{'until-version'} : null,
|
||||
isset($exclusion->attributes('')->{'max-depth'}) ? (string) $exclusion->attributes('')->{'max-depth'} : null,
|
||||
isset($exclusion->attributes('')->{'exclude-if'}) ? (string) $exclusion->attributes('')->{'exclude-if'} : null
|
||||
);
|
||||
}
|
||||
|
||||
private function createHref($href, $name)
|
||||
{
|
||||
if (isset($href->attributes('')->uri) && isset($href->attributes('')->route)) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'uri and route attributes are mutually exclusive, please set only one of them. The problematic relation rel is %s.',
|
||||
$name
|
||||
));
|
||||
} elseif (isset($href->attributes('')->uri)) {
|
||||
$href = (string) $href->attributes('')->uri;
|
||||
} else {
|
||||
$parameters = array();
|
||||
foreach ($href->parameter as $parameter) {
|
||||
$parameters[(string) $parameter->attributes('')->name] = (string) $parameter->attributes('')->value;
|
||||
}
|
||||
|
||||
$href = new Route(
|
||||
(string) $href->attributes('')->route,
|
||||
$parameters,
|
||||
null !== ($absolute = $href->attributes('')->absolute) ? 'true' === strtolower($absolute) : false,
|
||||
isset($href->attributes('')->generator) ? (string) $href->attributes('')->generator : null
|
||||
);
|
||||
}
|
||||
|
||||
return $href;
|
||||
}
|
||||
|
||||
private function createEmbedded($embedded)
|
||||
{
|
||||
$embeddedExclusion = isset($embedded->exclusion) ? $this->parseExclusion($embedded->exclusion) : null;
|
||||
$xmlElementName = isset($embedded->attributes('')->{'xml-element-name'}) ? (string) $embedded->attributes('')->{'xml-element-name'} : null;
|
||||
|
||||
return new Embedded(
|
||||
(string) $embedded->content,
|
||||
$xmlElementName,
|
||||
$embeddedExclusion
|
||||
);
|
||||
}
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Metadata\Driver;
|
||||
|
||||
use Hateoas\Configuration\Embedded;
|
||||
use Hateoas\Configuration\Exclusion;
|
||||
use Hateoas\Configuration\Metadata\ClassMetadata;
|
||||
use Hateoas\Configuration\Relation;
|
||||
use Hateoas\Configuration\RelationProvider;
|
||||
use Hateoas\Configuration\Route;
|
||||
use Metadata\Driver\AbstractFileDriver;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class YamlDriver extends AbstractFileDriver
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function loadMetadataFromFile(\ReflectionClass $class, $file)
|
||||
{
|
||||
$config = Yaml::parse(file_get_contents($file));
|
||||
|
||||
if (!isset($config[$name = $class->getName()])) {
|
||||
throw new \RuntimeException(sprintf('Expected metadata for class %s to be defined in %s.', $name, $file));
|
||||
}
|
||||
|
||||
$config = $config[$name];
|
||||
$classMetadata = new ClassMetadata($name);
|
||||
$classMetadata->fileResources[] = $file;
|
||||
$classMetadata->fileResources[] = $class->getFileName();
|
||||
|
||||
if (isset($config['relations'])) {
|
||||
foreach ($config['relations'] as $relation) {
|
||||
$classMetadata->addRelation(new Relation(
|
||||
$relation['rel'],
|
||||
$this->createHref($relation),
|
||||
$this->createEmbedded($relation),
|
||||
isset($relation['attributes']) ? $relation['attributes'] : array(),
|
||||
$this->createExclusion($relation)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($config['relation_providers'])) {
|
||||
foreach ($config['relation_providers'] as $relationProvider) {
|
||||
$classMetadata->addRelationProvider(new RelationProvider($relationProvider));
|
||||
}
|
||||
}
|
||||
|
||||
return $classMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExtension()
|
||||
{
|
||||
return 'yml';
|
||||
}
|
||||
|
||||
private function parseExclusion(array $exclusion)
|
||||
{
|
||||
return new Exclusion(
|
||||
isset($exclusion['groups']) ? $exclusion['groups'] : null,
|
||||
isset($exclusion['since_version']) ? $exclusion['since_version'] : null,
|
||||
isset($exclusion['until_version']) ? $exclusion['until_version'] : null,
|
||||
isset($exclusion['max_depth']) ? $exclusion['max_depth'] : null,
|
||||
isset($exclusion['exclude_if']) ? $exclusion['exclude_if'] : null
|
||||
);
|
||||
}
|
||||
|
||||
private function createHref($relation)
|
||||
{
|
||||
$href = null;
|
||||
if (isset($relation['href']) && is_array($href = $relation['href']) && isset($href['route'])) {
|
||||
$href = new Route(
|
||||
$href['route'],
|
||||
isset($href['parameters']) ? $href['parameters'] : array(),
|
||||
isset($href['absolute']) ? $href['absolute'] : false,
|
||||
isset($href['generator']) ? $href['generator'] : null
|
||||
);
|
||||
}
|
||||
|
||||
return $href;
|
||||
}
|
||||
|
||||
private function createEmbedded($relation)
|
||||
{
|
||||
$embedded = null;
|
||||
if (isset($relation['embedded'])) {
|
||||
$embedded = $relation['embedded'];
|
||||
|
||||
if (is_array($embedded)) {
|
||||
$embeddedExclusion = null;
|
||||
if (isset($embedded['exclusion'])) {
|
||||
$embeddedExclusion = $this->parseExclusion($embedded['exclusion']);
|
||||
}
|
||||
|
||||
$xmlElementName = isset($embedded['xmlElementName']) ? $embedded['xmlElementName'] : null;
|
||||
$embedded = new Embedded($embedded['content'], $xmlElementName, $embeddedExclusion);
|
||||
}
|
||||
}
|
||||
|
||||
return $embedded;
|
||||
}
|
||||
|
||||
private function createExclusion($relation)
|
||||
{
|
||||
$exclusion = null;
|
||||
if (isset($relation['exclusion'])) {
|
||||
$exclusion = $this->parseExclusion($relation['exclusion']);
|
||||
}
|
||||
|
||||
return $exclusion;
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Provider;
|
||||
|
||||
use Hateoas\Configuration\Metadata\ClassMetadataInterface;
|
||||
use Hateoas\Configuration\Provider\Resolver\RelationProviderResolverInterface;
|
||||
use Metadata\MetadataFactoryInterface;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class RelationProvider implements RelationProviderInterface
|
||||
{
|
||||
/**
|
||||
* @var MetadataFactoryInterface
|
||||
*/
|
||||
private $metadataFactory;
|
||||
|
||||
/**
|
||||
* @var RelationProviderResolverInterface
|
||||
*/
|
||||
private $resolver;
|
||||
|
||||
public function __construct(MetadataFactoryInterface $metadataFactory, RelationProviderResolverInterface $resolver)
|
||||
{
|
||||
$this->metadataFactory = $metadataFactory;
|
||||
$this->resolver = $resolver;
|
||||
}
|
||||
|
||||
public function getRelations($object)
|
||||
{
|
||||
$classMetadata = $this->metadataFactory->getMetadataForClass(get_class($object));
|
||||
|
||||
if (!$classMetadata instanceof ClassMetadataInterface) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$relations = array();
|
||||
foreach ($classMetadata->getRelationProviders() as $configuration) {
|
||||
if (null === $relationProviderCallable = $this->resolver->getRelationProvider($configuration, $object)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_callable($relationProviderCallable)) {
|
||||
throw new \RuntimeException('The returned relation provider is not callable, it should be.');
|
||||
}
|
||||
|
||||
$newRelations = call_user_func_array(
|
||||
$relationProviderCallable,
|
||||
array($object, $classMetadata)
|
||||
);
|
||||
|
||||
if (is_array($newRelations)) {
|
||||
$relations = array_merge($relations, $newRelations);
|
||||
}
|
||||
}
|
||||
|
||||
return $relations;
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Provider;
|
||||
|
||||
/**
|
||||
* @author Vyacheslav Salakhutdinov <megazoll@gmail.com>
|
||||
*/
|
||||
interface RelationProviderInterface
|
||||
{
|
||||
/**
|
||||
* @param object $object
|
||||
* @return \Hateoas\Configuration\Relation[] Returns array of Relations for specified object.
|
||||
*/
|
||||
public function getRelations($object);
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Provider\Resolver;
|
||||
|
||||
use Hateoas\Configuration\RelationProvider as RelationProviderConfiguration;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class ChainResolver implements RelationProviderResolverInterface
|
||||
{
|
||||
/**
|
||||
* @var RelationProviderResolverInterface[]
|
||||
*/
|
||||
private $resolvers;
|
||||
|
||||
public function __construct(array $resolvers)
|
||||
{
|
||||
$this->resolvers = $resolvers;
|
||||
}
|
||||
|
||||
public function addResolver(RelationProviderResolverInterface $resolver)
|
||||
{
|
||||
$this->resolvers[] = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRelationProvider(RelationProviderConfiguration $configuration, $object)
|
||||
{
|
||||
$configurationCallable = null;
|
||||
foreach ($this->resolvers as $resolver) {
|
||||
$configurationCallable = $resolver->getRelationProvider($configuration, $object);
|
||||
|
||||
if (null !== $configurationCallable) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $configurationCallable;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Provider\Resolver;
|
||||
|
||||
use Hateoas\Configuration\RelationProvider as RelationProviderConfiguration;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class MethodResolver implements RelationProviderResolverInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRelationProvider(RelationProviderConfiguration $configuration, $object)
|
||||
{
|
||||
if (!preg_match('/^[a-z0-9_]+$/i', $configuration->getName(), $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array($object, $matches[0]);
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Provider\Resolver;
|
||||
|
||||
use Hateoas\Configuration\RelationProvider as RelationProviderConfiguration;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
interface RelationProviderResolverInterface
|
||||
{
|
||||
/**
|
||||
* @param object $object
|
||||
* @return callable|null Returns `null` if it does not support this RelationProvider,
|
||||
* a `callable` otherwise.
|
||||
*/
|
||||
public function getRelationProvider(RelationProviderConfiguration $configuration, $object);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Provider\Resolver;
|
||||
|
||||
use Hateoas\Configuration\RelationProvider as RelationProviderConfiguration;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class StaticMethodResolver implements RelationProviderResolverInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRelationProvider(RelationProviderConfiguration $configuration, $object)
|
||||
{
|
||||
if (!preg_match('/^(?P<class>[a-z0-9_\\\\]+)::(?P<method>[a-z0-9_]+)$/i', $configuration->getName(), $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array($matches['class'], $matches['method']);
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration\Provider\Resolver;
|
||||
|
||||
use Hateoas\Configuration\RelationProvider as RelationProviderConfiguration;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class SymfonyContainerResolver implements RelationProviderResolverInterface
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
public function __construct(ContainerInterface $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getRelationProvider(RelationProviderConfiguration $configuration, $object)
|
||||
{
|
||||
if (!preg_match('/^(?P<service>[a-z0-9_.]+):(?P<method>[a-z0-9_]+)$/i', $configuration->getName(), $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array(
|
||||
$this->container->get($matches['service']),
|
||||
$matches['method']
|
||||
);
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class Relation
|
||||
{
|
||||
/**
|
||||
* @var string The link "rel" attribute
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var string|Route|null
|
||||
*/
|
||||
private $href;
|
||||
|
||||
/**
|
||||
* @var array Extra link attributes
|
||||
*/
|
||||
private $attributes;
|
||||
|
||||
/**
|
||||
* @var Embedded|null
|
||||
*/
|
||||
private $embedded;
|
||||
|
||||
/**
|
||||
* @var Exclusion|null
|
||||
*/
|
||||
private $exclusion;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string|Route $href
|
||||
* @param Embedded|string|mixed $embedded
|
||||
* @param array $attributes
|
||||
* @param Exclusion $exclusion
|
||||
*/
|
||||
public function __construct($name, $href = null, $embedded = null, array $attributes = array(), Exclusion $exclusion = null)
|
||||
{
|
||||
if (null !== $embedded && !$embedded instanceof Embedded) {
|
||||
$embedded = new Embedded($embedded);
|
||||
}
|
||||
|
||||
if (null === !$href && null === $embedded) {
|
||||
throw new \InvalidArgumentException('$href and $embedded cannot be both null.');
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->href = $href;
|
||||
$this->embedded = $embedded;
|
||||
$this->attributes = $attributes;
|
||||
$this->exclusion = $exclusion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Route|string|null
|
||||
*/
|
||||
public function getHref()
|
||||
{
|
||||
return $this->href;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Embedded|null
|
||||
*/
|
||||
public function getEmbedded()
|
||||
{
|
||||
return $this->embedded;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Exclusion|null
|
||||
*/
|
||||
public function getExclusion()
|
||||
{
|
||||
return $this->exclusion;
|
||||
}
|
||||
}
|
||||
Vendored
+30
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class RelationProvider
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
Vendored
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration;
|
||||
|
||||
use Hateoas\Configuration\Provider\RelationProviderInterface as RelationProviderProviderInterface;
|
||||
use Metadata\MetadataFactoryInterface;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class RelationsRepository
|
||||
{
|
||||
/**
|
||||
* @var MetadataFactoryInterface
|
||||
*/
|
||||
private $metadataFactory;
|
||||
|
||||
/**
|
||||
* @var RelationProviderProvider
|
||||
*/
|
||||
private $relationProvider;
|
||||
|
||||
/**
|
||||
* @param MetadataFactoryInterface $metadataFactory
|
||||
* @param RelationProviderProviderInterface $relationProvider
|
||||
*/
|
||||
public function __construct(MetadataFactoryInterface $metadataFactory, RelationProviderProviderInterface $relationProvider)
|
||||
{
|
||||
$this->metadataFactory = $metadataFactory;
|
||||
$this->relationProvider = $relationProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $object
|
||||
*
|
||||
* @return Relation[]
|
||||
*/
|
||||
public function getRelations($object)
|
||||
{
|
||||
$relations = array();
|
||||
|
||||
if (null !== $classMetadata = $this->metadataFactory->getMetadataForClass(get_class($object))) {
|
||||
$relations = array_merge($relations, $classMetadata->getRelations());
|
||||
}
|
||||
|
||||
$relations = array_merge($relations, $this->relationProvider->getRelations($object));
|
||||
|
||||
return $relations;
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Configuration;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class Route
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var string|array
|
||||
*/
|
||||
private $parameters;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $absolute;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
private $generator;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string|array $parameters
|
||||
* @param boolean $absolute
|
||||
* @param string|null $generator
|
||||
*/
|
||||
public function __construct($name, $parameters = array(), $absolute = false, $generator = null)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->parameters = $parameters;
|
||||
$this->absolute = $absolute;
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|array
|
||||
*/
|
||||
public function getParameters()
|
||||
{
|
||||
return $this->parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isAbsolute()
|
||||
{
|
||||
return $this->absolute;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
*/
|
||||
public function getGenerator()
|
||||
{
|
||||
return $this->generator;
|
||||
}
|
||||
}
|
||||
Vendored
+116
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Expression;
|
||||
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
* @author William Durand <william.durand1@gmail.com>
|
||||
*/
|
||||
class ExpressionEvaluator
|
||||
{
|
||||
const EXPRESSION_REGEX = '/expr\((?P<expression>.+)\)/';
|
||||
|
||||
/**
|
||||
* @var ExpressionLanguage
|
||||
*/
|
||||
private $expressionLanguage;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $context;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
public function __construct(ExpressionLanguage $expressionLanguage, array $context = array(), array $cache = array())
|
||||
{
|
||||
$this->expressionLanguage = $expressionLanguage;
|
||||
$this->context = $context;
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setContextVariable($name, $value)
|
||||
{
|
||||
$this->context[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $expression
|
||||
* @param mixed $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function evaluate($expression, $data)
|
||||
{
|
||||
if (!is_string($expression)) {
|
||||
return $expression;
|
||||
}
|
||||
|
||||
$key = $expression;
|
||||
|
||||
if (!array_key_exists($key, $this->cache)) {
|
||||
if (!preg_match(self::EXPRESSION_REGEX, $expression, $matches)) {
|
||||
$this->cache[$key] = false;
|
||||
} else {
|
||||
$expression = $matches['expression'];
|
||||
$context = $this->context;
|
||||
$context['object'] = $data;
|
||||
$this->cache[$key] = $this->expressionLanguage->parse($expression, array_keys($context));
|
||||
}
|
||||
}
|
||||
|
||||
if (false !== $this->cache[$key]) {
|
||||
if (!isset($context)) {
|
||||
$context = $this->context;
|
||||
$context['object'] = $data;
|
||||
}
|
||||
|
||||
return $this->expressionLanguage->evaluate($this->cache[$key], $context);
|
||||
}
|
||||
|
||||
return $expression;
|
||||
}
|
||||
|
||||
public function evaluateArray(array $array, $data)
|
||||
{
|
||||
$newArray = array();
|
||||
foreach ($array as $key => $value) {
|
||||
$key = $this->evaluate($key, $data);
|
||||
$value = is_array($value) ? $this->evaluateArray($value, $data) : $this->evaluate($value, $data);
|
||||
|
||||
$newArray[$key] = $value;
|
||||
}
|
||||
|
||||
return $newArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new new ExpressionLanguage function.
|
||||
*
|
||||
* @param ExpressionFunctionInterface $function
|
||||
*
|
||||
* @return ExpressionEvaluator
|
||||
*/
|
||||
public function registerFunction(ExpressionFunctionInterface $function)
|
||||
{
|
||||
$this->expressionLanguage->register(
|
||||
$function->getName(),
|
||||
$function->getCompiler(),
|
||||
$function->getEvaluator()
|
||||
);
|
||||
|
||||
foreach ($function->getContextVariables() as $name => $value) {
|
||||
$this->setContextVariable($name, $value);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Expression;
|
||||
|
||||
/**
|
||||
* @author William Durand <william.durand1@gmail.com>
|
||||
*/
|
||||
interface ExpressionFunctionInterface
|
||||
{
|
||||
/**
|
||||
* Return the name of the function in an expression.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Return a function executed when compiling an expression using the function.
|
||||
*
|
||||
* @return closure
|
||||
*/
|
||||
public function getCompiler();
|
||||
|
||||
/**
|
||||
* Return a function executed when the expression is evaluated.
|
||||
*
|
||||
* @return closure
|
||||
*/
|
||||
public function getEvaluator();
|
||||
|
||||
/**
|
||||
* Return context variables as an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getContextVariables();
|
||||
}
|
||||
Vendored
+60
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Expression;
|
||||
|
||||
use Hateoas\Helper\LinkHelper;
|
||||
|
||||
/**
|
||||
* @author William Durand <william.durand1@gmail.com>
|
||||
*/
|
||||
class LinkExpressionFunction implements ExpressionFunctionInterface
|
||||
{
|
||||
/**
|
||||
* @var LinkHelper
|
||||
*/
|
||||
private $linkHelper;
|
||||
|
||||
/**
|
||||
* @param LinkHelper $linkHelper
|
||||
*/
|
||||
public function __construct(LinkHelper $linkHelper)
|
||||
{
|
||||
$this->linkHelper = $linkHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'link';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getCompiler()
|
||||
{
|
||||
return function ($object, $rel, $absolute = false) {
|
||||
return sprintf('$link_helper->getLinkHref(%s, %s, %s)', $object, $rel, $absolute);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getEvaluator()
|
||||
{
|
||||
return function ($context, $object, $rel, $absolute = false) {
|
||||
return $context['link_helper']->getLinkHref($object, $rel, $absolute);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getContextVariables()
|
||||
{
|
||||
return array('link_helper' => $this->linkHelper);
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Factory;
|
||||
|
||||
use Hateoas\Configuration\RelationsRepository;
|
||||
use Hateoas\Expression\ExpressionEvaluator;
|
||||
use Hateoas\Model\Embedded;
|
||||
use Hateoas\Serializer\ExclusionManager;
|
||||
use Hateoas\Serializer\Metadata\RelationPropertyMetadata;
|
||||
use JMS\Serializer\SerializationContext;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class EmbeddedsFactory
|
||||
{
|
||||
/**
|
||||
* @var RelationsRepository
|
||||
*/
|
||||
private $relationsRepository;
|
||||
|
||||
/**
|
||||
* @var ExpressionEvaluator
|
||||
*/
|
||||
private $expressionEvaluator;
|
||||
|
||||
/**
|
||||
* @var ExclusionManager
|
||||
*/
|
||||
private $exclusionManager;
|
||||
|
||||
/**
|
||||
* @param RelationsRepository $relationsRepository
|
||||
* @param ExpressionEvaluator $expressionEvaluator
|
||||
* @param ExclusionManager $exclusionManager
|
||||
*/
|
||||
public function __construct(
|
||||
RelationsRepository $relationsRepository,
|
||||
ExpressionEvaluator $expressionEvaluator,
|
||||
ExclusionManager $exclusionManager
|
||||
) {
|
||||
$this->relationsRepository = $relationsRepository;
|
||||
$this->expressionEvaluator = $expressionEvaluator;
|
||||
$this->exclusionManager = $exclusionManager;
|
||||
}
|
||||
/**
|
||||
* @param object $object
|
||||
* @param SerializationContext $context
|
||||
* @return Embedded[]
|
||||
*/
|
||||
public function create($object, SerializationContext $context)
|
||||
{
|
||||
$embeddeds = array();
|
||||
foreach ($this->relationsRepository->getRelations($object) as $relation) {
|
||||
if ($this->exclusionManager->shouldSkipEmbedded($object, $relation, $context)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rel = $this->expressionEvaluator->evaluate($relation->getName(), $object);
|
||||
$data = $this->expressionEvaluator->evaluate($relation->getEmbedded()->getContent(), $object);
|
||||
$xmlElementName = $this->expressionEvaluator->evaluate($relation->getEmbedded()->getXmlElementName(), $object);
|
||||
|
||||
$propertyMetadata = new RelationPropertyMetadata($relation->getEmbedded()->getExclusion(), $relation);
|
||||
|
||||
$embeddeds[] = new Embedded($rel, $data, $propertyMetadata, $xmlElementName);
|
||||
}
|
||||
|
||||
return $embeddeds;
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Factory;
|
||||
|
||||
use Hateoas\Configuration\Relation;
|
||||
use Hateoas\Configuration\Route;
|
||||
use Hateoas\Expression\ExpressionEvaluator;
|
||||
use Hateoas\Model\Link;
|
||||
use Hateoas\UrlGenerator\UrlGeneratorRegistry;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class LinkFactory
|
||||
{
|
||||
/**
|
||||
* @var ExpressionEvaluator
|
||||
*/
|
||||
private $expressionEvaluator;
|
||||
|
||||
/**
|
||||
* @var UrlGeneratorRegistry
|
||||
*/
|
||||
private $urlGeneratorRegistry;
|
||||
|
||||
/**
|
||||
* @param ExpressionEvaluator $expressionEvaluator
|
||||
* @param UrlGeneratorRegistry $urlGeneratorRegistry
|
||||
*/
|
||||
public function __construct(ExpressionEvaluator $expressionEvaluator, UrlGeneratorRegistry $urlGeneratorRegistry)
|
||||
{
|
||||
$this->expressionEvaluator = $expressionEvaluator;
|
||||
$this->urlGeneratorRegistry = $urlGeneratorRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $object
|
||||
* @param Relation $relation
|
||||
*
|
||||
* @return Link
|
||||
*/
|
||||
public function createLink($object, Relation $relation)
|
||||
{
|
||||
$rel = $this->expressionEvaluator->evaluate($relation->getName(), $object);
|
||||
$href = $relation->getHref();
|
||||
|
||||
if ($href instanceof Route) {
|
||||
if (!$this->urlGeneratorRegistry->hasGenerators()) {
|
||||
throw new \RuntimeException('You cannot use a route without an url generator.');
|
||||
}
|
||||
|
||||
$name = $this->expressionEvaluator->evaluate($href->getName(), $object);
|
||||
$parameters = is_array($href->getParameters())
|
||||
? $this->expressionEvaluator->evaluateArray($href->getParameters(), $object)
|
||||
: $this->expressionEvaluator->evaluate($href->getParameters(), $object)
|
||||
;
|
||||
$isAbsolute = $this->expressionEvaluator->evaluate($href->isAbsolute(), $object);
|
||||
|
||||
if (!is_array($parameters)) {
|
||||
throw new \RuntimeException(
|
||||
sprintf(
|
||||
'The route parameters should be an array, %s given. Maybe you forgot to wrap the expression in expr(...).',
|
||||
gettype($parameters)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$href = $this->urlGeneratorRegistry
|
||||
->get($href->getGenerator())
|
||||
->generate($name, $parameters, $isAbsolute)
|
||||
;
|
||||
} else {
|
||||
$href = $this->expressionEvaluator->evaluate($href, $object);
|
||||
}
|
||||
|
||||
$attributes = $this->expressionEvaluator->evaluateArray($relation->getAttributes(), $object);
|
||||
|
||||
return new Link($rel, $href, $attributes);
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Factory;
|
||||
|
||||
use Hateoas\Configuration\RelationsRepository;
|
||||
use Hateoas\Model\Link;
|
||||
use Hateoas\Serializer\ExclusionManager;
|
||||
use JMS\Serializer\SerializationContext;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class LinksFactory
|
||||
{
|
||||
/**
|
||||
* @var RelationsRepository
|
||||
*/
|
||||
private $relationsRepository;
|
||||
|
||||
/**
|
||||
* @var LinkFactory
|
||||
*/
|
||||
private $linkFactory;
|
||||
|
||||
/**
|
||||
* @var ExclusionManager
|
||||
*/
|
||||
private $exclusionManager;
|
||||
|
||||
/**
|
||||
* @param RelationsRepository $relationsRepository
|
||||
* @param LinkFactory $linkFactory
|
||||
* @param ExclusionManager $exclusionManager
|
||||
*/
|
||||
public function __construct(RelationsRepository $relationsRepository, LinkFactory $linkFactory, ExclusionManager $exclusionManager)
|
||||
{
|
||||
$this->relationsRepository = $relationsRepository;
|
||||
$this->linkFactory = $linkFactory;
|
||||
$this->exclusionManager = $exclusionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $object
|
||||
* @param SerializationContext $context
|
||||
*
|
||||
* @return Link[]
|
||||
*/
|
||||
public function create($object, SerializationContext $context)
|
||||
{
|
||||
$links = array();
|
||||
foreach ($this->relationsRepository->getRelations($object) as $relation) {
|
||||
if ($this->exclusionManager->shouldSkipLink($object, $relation, $context)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$links[] = $this->linkFactory->createLink($object, $relation);
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas;
|
||||
|
||||
use Hateoas\Helper\LinkHelper;
|
||||
use JMS\Serializer\DeserializationContext;
|
||||
use JMS\Serializer\SerializationContext;
|
||||
use JMS\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class Hateoas implements SerializerInterface
|
||||
{
|
||||
/**
|
||||
* @var SerializerInterface
|
||||
*/
|
||||
private $serializer;
|
||||
|
||||
/**
|
||||
* @var LinkHelper
|
||||
*/
|
||||
private $linkHelper;
|
||||
|
||||
/**
|
||||
* @param SerializerInterface $serializer
|
||||
* @param LinkHelper $linkHelper
|
||||
*/
|
||||
public function __construct(SerializerInterface $serializer, LinkHelper $linkHelper)
|
||||
{
|
||||
$this->serializer = $serializer;
|
||||
$this->linkHelper = $linkHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function serialize($data, $format, SerializationContext $context = null)
|
||||
{
|
||||
return $this->serializer->serialize($data, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function deserialize($data, $type, $format, DeserializationContext $context = null)
|
||||
{
|
||||
return $this->serializer->deserialize($data, $type, $format, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SerializerInterface
|
||||
*/
|
||||
public function getSerializer()
|
||||
{
|
||||
return $this->serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LinkHelper
|
||||
*/
|
||||
public function getLinkHelper()
|
||||
{
|
||||
return $this->linkHelper;
|
||||
}
|
||||
}
|
||||
+521
@@ -0,0 +1,521 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas;
|
||||
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Annotations\FileCacheReader;
|
||||
use Hateoas\Configuration\Metadata\ConfigurationExtensionInterface;
|
||||
use Hateoas\Configuration\Metadata\Driver\AnnotationDriver;
|
||||
use Hateoas\Configuration\Metadata\Driver\ExtensionDriver;
|
||||
use Hateoas\Configuration\Metadata\Driver\YamlDriver;
|
||||
use Hateoas\Configuration\Metadata\Driver\XmlDriver;
|
||||
use Hateoas\Configuration\Provider\Resolver\MethodResolver;
|
||||
use Hateoas\Configuration\Provider\Resolver\ChainResolver;
|
||||
use Hateoas\Configuration\Provider\RelationProvider;
|
||||
use Hateoas\Configuration\Provider\Resolver\RelationProviderResolverInterface;
|
||||
use Hateoas\Configuration\Provider\Resolver\StaticMethodResolver;
|
||||
use Hateoas\Configuration\RelationsRepository;
|
||||
use Hateoas\Expression\ExpressionEvaluator;
|
||||
use Hateoas\Expression\ExpressionFunctionInterface;
|
||||
use Hateoas\Expression\LinkExpressionFunction;
|
||||
use Hateoas\Factory\EmbeddedsFactory;
|
||||
use Hateoas\Factory\LinkFactory;
|
||||
use Hateoas\Factory\LinksFactory;
|
||||
use Hateoas\Helper\LinkHelper;
|
||||
use Hateoas\UrlGenerator\UrlGeneratorInterface;
|
||||
use Hateoas\UrlGenerator\UrlGeneratorRegistry;
|
||||
use Hateoas\Serializer\EventSubscriber\JsonEventSubscriber;
|
||||
use Hateoas\Serializer\EventSubscriber\XmlEventSubscriber;
|
||||
use Hateoas\Serializer\ExclusionManager;
|
||||
use Hateoas\Serializer\JsonHalSerializer;
|
||||
use Hateoas\Serializer\JsonSerializerInterface;
|
||||
use Hateoas\Serializer\JMSSerializerMetadataAwareInterface;
|
||||
use Hateoas\Serializer\Metadata\InlineDeferrer;
|
||||
use Hateoas\Serializer\XmlSerializer;
|
||||
use Hateoas\Serializer\XmlSerializerInterface;
|
||||
use JMS\Serializer\EventDispatcher\EventDispatcherInterface;
|
||||
use JMS\Serializer\SerializerBuilder;
|
||||
use Metadata\Cache\FileCache;
|
||||
use Metadata\Driver\DriverChain;
|
||||
use Metadata\Driver\FileLocator;
|
||||
use Metadata\MetadataFactory;
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*
|
||||
* Some code (metadata things) from this class has been taken from
|
||||
* https://github.com/schmittjoh/serializer/blob/a29f1e5083654ba2c126acd94ddb2287069b0b5b/src/JMS/Serializer/SerializerBuilder.php
|
||||
*/
|
||||
class HateoasBuilder
|
||||
{
|
||||
/**
|
||||
* @var SerializerBuilder
|
||||
*/
|
||||
private $serializerBuilder;
|
||||
|
||||
/**
|
||||
* @var ExpressionLanguage
|
||||
*/
|
||||
private $expressionLanguage;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $contextVariables = array();
|
||||
|
||||
/**
|
||||
* ExpressionFunctionInterface[]
|
||||
*/
|
||||
private $expressionFunctions = array();
|
||||
|
||||
/**
|
||||
* @var XmlSerializerInterface
|
||||
*/
|
||||
private $xmlSerializer;
|
||||
|
||||
/**
|
||||
* @var JsonSerializerInterface
|
||||
*/
|
||||
private $jsonSerializer;
|
||||
|
||||
/**
|
||||
* @var UrlGeneratorRegistry
|
||||
*/
|
||||
private $urlGeneratorRegistry;
|
||||
|
||||
private $configurationExtensions = array();
|
||||
|
||||
private $chainResolver;
|
||||
|
||||
private $metadataDirs = array();
|
||||
|
||||
private $debug = false;
|
||||
|
||||
private $cacheDir;
|
||||
|
||||
private $annotationReader;
|
||||
|
||||
private $includeInterfaceMetadata = false;
|
||||
|
||||
/**
|
||||
* @param SerializerBuilder $serializerBuilder
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public static function create(SerializerBuilder $serializerBuilder = null)
|
||||
{
|
||||
return new static($serializerBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Hateoas
|
||||
*/
|
||||
public static function buildHateoas()
|
||||
{
|
||||
$builder = static::create();
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
|
||||
public function __construct(SerializerBuilder $serializerBuilder = null)
|
||||
{
|
||||
$this->serializerBuilder = $serializerBuilder ?: SerializerBuilder::create();
|
||||
$this->urlGeneratorRegistry = new UrlGeneratorRegistry();
|
||||
$this->chainResolver = new ChainResolver(array(
|
||||
new MethodResolver(),
|
||||
new StaticMethodResolver(),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a configured Hateoas instance.
|
||||
*
|
||||
* @return Hateoas
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$metadataFactory = $this->buildMetadataFactory();
|
||||
$relationProvider = new RelationProvider($metadataFactory, $this->chainResolver);
|
||||
$relationsRepository = new RelationsRepository($metadataFactory, $relationProvider);
|
||||
$expressionEvaluator = new ExpressionEvaluator($this->getExpressionLanguage(), $this->contextVariables);
|
||||
$linkFactory = new LinkFactory($expressionEvaluator, $this->urlGeneratorRegistry);
|
||||
$exclusionManager = new ExclusionManager($expressionEvaluator);
|
||||
$linksFactory = new LinksFactory($relationsRepository, $linkFactory, $exclusionManager);
|
||||
$embeddedsFactory = new EmbeddedsFactory($relationsRepository, $expressionEvaluator, $exclusionManager);
|
||||
$linkHelper = new LinkHelper($linkFactory, $relationsRepository);
|
||||
|
||||
// Register Hateoas core functions
|
||||
$expressionEvaluator->registerFunction(new LinkExpressionFunction($linkHelper));
|
||||
|
||||
// Register user functions
|
||||
foreach ($this->expressionFunctions as $expressionFunction) {
|
||||
$expressionEvaluator->registerFunction($expressionFunction);
|
||||
}
|
||||
|
||||
if (null === $this->xmlSerializer) {
|
||||
$this->setDefaultXmlSerializer();
|
||||
}
|
||||
|
||||
if (null === $this->jsonSerializer) {
|
||||
$this->setDefaultJsonSerializer();
|
||||
}
|
||||
|
||||
$inlineDeferrers = array();
|
||||
$eventSubscribers = array(
|
||||
new XmlEventSubscriber($this->xmlSerializer, $linksFactory, $embeddedsFactory),
|
||||
new JsonEventSubscriber(
|
||||
$this->jsonSerializer,
|
||||
$linksFactory,
|
||||
$embeddedsFactory,
|
||||
$inlineDeferrers[] = new InlineDeferrer(),
|
||||
$inlineDeferrers[] = new InlineDeferrer()
|
||||
),
|
||||
);
|
||||
|
||||
$this->serializerBuilder
|
||||
->addDefaultListeners()
|
||||
->configureListeners(function (EventDispatcherInterface $dispatcher) use ($eventSubscribers) {
|
||||
foreach ($eventSubscribers as $eventSubscriber) {
|
||||
$dispatcher->addSubscriber($eventSubscriber);
|
||||
}
|
||||
})
|
||||
;
|
||||
|
||||
$jmsSerializer = $this->serializerBuilder->build();
|
||||
foreach (array_merge($inlineDeferrers, array($this->jsonSerializer, $this->xmlSerializer)) as $serializer) {
|
||||
if ($serializer instanceof JMSSerializerMetadataAwareInterface) {
|
||||
$serializer->setMetadataFactory($jmsSerializer->getMetadataFactory());
|
||||
}
|
||||
}
|
||||
|
||||
return new Hateoas($jmsSerializer, $linkHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param XmlSerializerInterface $xmlSerializer
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function setXmlSerializer(XmlSerializerInterface $xmlSerializer)
|
||||
{
|
||||
$this->xmlSerializer = $xmlSerializer;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default XML serializer (`XmlSerializer`).
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function setDefaultXmlSerializer()
|
||||
{
|
||||
return $this->setXmlSerializer(new XmlSerializer());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JsonSerializerInterface $jsonSerializer
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function setJsonSerializer(JsonSerializerInterface $jsonSerializer)
|
||||
{
|
||||
$this->jsonSerializer = $jsonSerializer;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default JSON serializer (`JsonHalSerializer`).
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function setDefaultJsonSerializer()
|
||||
{
|
||||
return $this->setJsonSerializer(new JsonHalSerializer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new URL generator. If you pass `null` as name, it will be the
|
||||
* default URL generator.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @param UrlGeneratorInterface $urlGenerator
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function setUrlGenerator($name, UrlGeneratorInterface $urlGenerator)
|
||||
{
|
||||
$this->urlGeneratorRegistry->set($name, $urlGenerator);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new expression context variable.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function setExpressionContextVariable($name, $value)
|
||||
{
|
||||
$this->contextVariables[$name] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExpressionLanguage $expressionLanguage
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function setExpressionLanguage(ExpressionLanguage $expressionLanguage)
|
||||
{
|
||||
$this->expressionLanguage = $expressionLanguage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExpressionFunctionInterface $expressionFunction
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function registerExpressionFunction(ExpressionFunctionInterface $expressionFunction)
|
||||
{
|
||||
$this->expressionFunctions[] = $expressionFunction;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new relation provider resolver.
|
||||
*
|
||||
* @param RelationProviderResolverInterface $resolver
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function addRelationProviderResolver(RelationProviderResolverInterface $resolver)
|
||||
{
|
||||
$this->chainResolver->addResolver($resolver);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConfigurationExtensionInterface $configurationExtension
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function addConfigurationExtension(ConfigurationExtensionInterface $configurationExtension)
|
||||
{
|
||||
$this->configurationExtensions[] = $configurationExtension;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $debug
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function setDebug($debug)
|
||||
{
|
||||
$this->debug = (boolean) $debug;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function setCacheDir($dir)
|
||||
{
|
||||
if (!is_dir($dir)) {
|
||||
$this->createDir($dir);
|
||||
}
|
||||
|
||||
if (!is_writable($dir)) {
|
||||
throw new \InvalidArgumentException(sprintf('The cache directory "%s" is not writable.', $dir));
|
||||
}
|
||||
|
||||
$this->cacheDir = $dir;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $include Whether to include the metadata from the interfaces
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function includeInterfaceMetadata($include)
|
||||
{
|
||||
$this->includeInterfaceMetadata = (boolean) $include;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a map of namespace prefixes to directories.
|
||||
*
|
||||
* This method overrides any previously defined directories.
|
||||
*
|
||||
* @param array $namespacePrefixToDirMap
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function setMetadataDirs(array $namespacePrefixToDirMap)
|
||||
{
|
||||
foreach ($namespacePrefixToDirMap as $dir) {
|
||||
if (!is_dir($dir)) {
|
||||
throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
|
||||
}
|
||||
}
|
||||
|
||||
$this->metadataDirs = $namespacePrefixToDirMap;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a directory where the serializer will look for class metadata.
|
||||
*
|
||||
* The namespace prefix will make the names of the actual metadata files a bit shorter. For example, let's assume
|
||||
* that you have a directory where you only store metadata files for the ``MyApplication\Entity`` namespace.
|
||||
*
|
||||
* If you use an empty prefix, your metadata files would need to look like:
|
||||
*
|
||||
* ``my-dir/MyApplication.Entity.SomeObject.yml``
|
||||
* ``my-dir/MyApplication.Entity.OtherObject.yml``
|
||||
*
|
||||
* If you use ``MyApplication\Entity`` as prefix, your metadata files would need to look like:
|
||||
*
|
||||
* ``my-dir/SomeObject.yml``
|
||||
* ``my-dir/OtherObject.yml``
|
||||
*
|
||||
* Please keep in mind that you currently may only have one directory per namespace prefix.
|
||||
*
|
||||
* @param string $dir The directory where metadata files are located.
|
||||
* @param string $namespacePrefix An optional prefix if you only store metadata for specific namespaces in this directory.
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function addMetadataDir($dir, $namespacePrefix = '')
|
||||
{
|
||||
if (!is_dir($dir)) {
|
||||
throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
|
||||
}
|
||||
|
||||
if (isset($this->metadataDirs[$namespacePrefix])) {
|
||||
throw new \InvalidArgumentException(sprintf('There is already a directory configured for the namespace prefix "%s". Please use replaceMetadataDir() to override directories.', $namespacePrefix));
|
||||
}
|
||||
|
||||
$this->metadataDirs[$namespacePrefix] = $dir;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a map of namespace prefixes to directories.
|
||||
*
|
||||
* @param array $namespacePrefixToDirMap
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function addMetadataDirs(array $namespacePrefixToDirMap)
|
||||
{
|
||||
foreach ($namespacePrefixToDirMap as $prefix => $dir) {
|
||||
$this->addMetadataDir($dir, $prefix);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to addMetadataDir(), but overrides an existing entry.
|
||||
*
|
||||
* @param string $dir
|
||||
* @param string $namespacePrefix
|
||||
*
|
||||
* @return HateoasBuilder
|
||||
*/
|
||||
public function replaceMetadataDir($dir, $namespacePrefix = '')
|
||||
{
|
||||
if (!is_dir($dir)) {
|
||||
throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist.', $dir));
|
||||
}
|
||||
|
||||
if (!isset($this->metadataDirs[$namespacePrefix])) {
|
||||
throw new \InvalidArgumentException(sprintf('There is no directory configured for namespace prefix "%s". Please use addMetadataDir() for adding new directories.', $namespacePrefix));
|
||||
}
|
||||
|
||||
$this->metadataDirs[$namespacePrefix] = $dir;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function buildMetadataFactory()
|
||||
{
|
||||
$annotationReader = $this->annotationReader;
|
||||
|
||||
if (null === $annotationReader) {
|
||||
$annotationReader = new AnnotationReader();
|
||||
|
||||
if (null !== $this->cacheDir) {
|
||||
$this->createDir($this->cacheDir.'/annotations');
|
||||
$annotationReader = new FileCacheReader($annotationReader, $this->cacheDir.'/annotations', $this->debug);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($this->metadataDirs)) {
|
||||
$fileLocator = new FileLocator($this->metadataDirs);
|
||||
$metadataDriver = new DriverChain(array(
|
||||
new YamlDriver($fileLocator),
|
||||
new XmlDriver($fileLocator),
|
||||
new AnnotationDriver($annotationReader),
|
||||
));
|
||||
} else {
|
||||
$metadataDriver = new AnnotationDriver($annotationReader);
|
||||
}
|
||||
|
||||
$metadataDriver = new ExtensionDriver($metadataDriver, $this->configurationExtensions);
|
||||
$metadataFactory = new MetadataFactory($metadataDriver, null, $this->debug);
|
||||
$metadataFactory->setIncludeInterfaces($this->includeInterfaceMetadata);
|
||||
|
||||
if (null !== $this->cacheDir) {
|
||||
$this->createDir($this->cacheDir.'/metadata');
|
||||
$metadataFactory->setCache(new FileCache($this->cacheDir.'/metadata'));
|
||||
}
|
||||
|
||||
return $metadataFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
*/
|
||||
private function createDir($dir)
|
||||
{
|
||||
if (is_dir($dir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
|
||||
throw new \RuntimeException(sprintf('Could not create directory "%s".', $dir));
|
||||
}
|
||||
}
|
||||
|
||||
private function getExpressionLanguage()
|
||||
{
|
||||
if (null === $this->expressionLanguage) {
|
||||
$this->expressionLanguage = new ExpressionLanguage();
|
||||
}
|
||||
|
||||
return $this->expressionLanguage;
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Helper;
|
||||
|
||||
use Hateoas\Configuration\RelationsRepository;
|
||||
use Hateoas\Configuration\Relation;
|
||||
use Hateoas\Configuration\Route;
|
||||
use Hateoas\Factory\LinkFactory;
|
||||
|
||||
/**
|
||||
* @author William Durand <william.durand1@gmail.com>
|
||||
*/
|
||||
class LinkHelper
|
||||
{
|
||||
/**
|
||||
* @var LinkFactory
|
||||
*/
|
||||
private $linkFactory;
|
||||
|
||||
/**
|
||||
* @var RelationsRepository
|
||||
*/
|
||||
private $relationsRepository;
|
||||
|
||||
/**
|
||||
* @param LinkFactory $linkFactory
|
||||
* @param RelationsRepository $relationsRepository
|
||||
*/
|
||||
public function __construct(LinkFactory $linkFactory, RelationsRepository $relationsRepository)
|
||||
{
|
||||
$this->linkFactory = $linkFactory;
|
||||
$this->relationsRepository = $relationsRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $object
|
||||
* @param string $rel
|
||||
* @param boolean $absolute
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLinkHref($object, $rel, $absolute = false)
|
||||
{
|
||||
foreach ($this->relationsRepository->getRelations($object) as $relation) {
|
||||
if ($rel === $relation->getName()) {
|
||||
$relation = $this->patchAbsolute($relation, $absolute);
|
||||
|
||||
if (null !== $link = $this->linkFactory->createLink($object, $relation)) {
|
||||
return $link->getHref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function patchAbsolute(Relation $relation, $absolute)
|
||||
{
|
||||
$href = $relation->getHref();
|
||||
|
||||
if ($href instanceof Route) {
|
||||
$href = new Route(
|
||||
$href->getName(),
|
||||
$href->getParameters(),
|
||||
$absolute,
|
||||
$href->getGenerator()
|
||||
);
|
||||
}
|
||||
|
||||
return new Relation(
|
||||
$relation->getName(),
|
||||
$href,
|
||||
$relation->getEmbedded(),
|
||||
$relation->getAttributes(),
|
||||
$relation->getExclusion()
|
||||
);
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Model;
|
||||
|
||||
use Hateoas\Serializer\Metadata\RelationPropertyMetadata;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class Embedded
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $rel;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $xmlElementName;
|
||||
|
||||
/**
|
||||
* @var RelationPropertyMetadata
|
||||
*/
|
||||
private $metadata;
|
||||
|
||||
/**
|
||||
* @param string $rel
|
||||
* @param mixed $data
|
||||
* @param string|null $xmlElementName
|
||||
* @param RelationPropertyMetadata $metadata
|
||||
*/
|
||||
public function __construct($rel, $data, RelationPropertyMetadata $metadata, $xmlElementName = null)
|
||||
{
|
||||
$this->rel = $rel;
|
||||
$this->data = $data;
|
||||
$this->metadata = $metadata;
|
||||
$this->xmlElementName = $xmlElementName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RelationPropertyMetadata
|
||||
*/
|
||||
public function getMetadata()
|
||||
{
|
||||
return $this->metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRel()
|
||||
{
|
||||
return $this->rel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
*/
|
||||
public function getXmlElementName()
|
||||
{
|
||||
return $this->xmlElementName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Model;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class Link
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $rel;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $href;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $attributes;
|
||||
|
||||
/**
|
||||
* @param string $rel
|
||||
* @param string $href
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct($rel, $href, array $attributes = array())
|
||||
{
|
||||
$this->rel = $rel;
|
||||
$this->href = $href;
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAttributes()
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getHref()
|
||||
{
|
||||
return $this->href;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRel()
|
||||
{
|
||||
return $this->rel;
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Representation;
|
||||
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*
|
||||
* @author Premi Giorgio <giosh94mhz@gmail.com>
|
||||
*/
|
||||
abstract class AbstractSegmentedRepresentation extends RouteAwareRepresentation
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose
|
||||
* @Serializer\Type("integer")
|
||||
* @Serializer\XmlAttribute
|
||||
*/
|
||||
private $limit;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose
|
||||
* @Serializer\Type("integer")
|
||||
* @Serializer\XmlAttribute
|
||||
*/
|
||||
private $total;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $limitParameterName;
|
||||
|
||||
public function __construct(
|
||||
$inline,
|
||||
$route,
|
||||
array $parameters = array(),
|
||||
$limit,
|
||||
$total = null,
|
||||
$limitParameterName = null,
|
||||
$absolute = false
|
||||
) {
|
||||
parent::__construct($inline, $route, $parameters, $absolute);
|
||||
|
||||
$this->total = $total;
|
||||
$this->limit = $limit;
|
||||
$this->limitParameterName = $limitParameterName ?: 'limit';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLimit()
|
||||
{
|
||||
return $this->limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getParameters($limit = null)
|
||||
{
|
||||
$parameters = parent::getParameters();
|
||||
|
||||
$parameters[$this->limitParameterName] = null === $limit ? $this->getLimit() : $limit;
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTotal()
|
||||
{
|
||||
return $this->total;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLimitParameterName()
|
||||
{
|
||||
return $this->limitParameterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*/
|
||||
protected function moveParameterToEnd(array &$parameters, $key)
|
||||
{
|
||||
if (! array_key_exists($key, $parameters)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$value = $parameters[$key];
|
||||
unset($parameters[$key]);
|
||||
$parameters[$key] = $value;
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Representation;
|
||||
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
use Hateoas\Configuration\Embedded;
|
||||
use Hateoas\Configuration\Exclusion;
|
||||
use Hateoas\Configuration\Metadata\ClassMetadataInterface;
|
||||
use Hateoas\Configuration\Relation;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
* @Serializer\XmlRoot("collection")
|
||||
*
|
||||
* @Hateoas\RelationProvider("getRelations")
|
||||
*
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class CollectionRepresentation
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $rel;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
private $resources;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
private $xmlElementName;
|
||||
|
||||
/**
|
||||
* @var null|Exclusion
|
||||
*/
|
||||
private $exclusion;
|
||||
|
||||
/**
|
||||
* @var null|Exclusion
|
||||
*/
|
||||
private $embedExclusion;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $relations;
|
||||
|
||||
/**
|
||||
* @param string $rel
|
||||
* @param string $xmlElementName
|
||||
*/
|
||||
public function __construct(
|
||||
$resources,
|
||||
$rel = null,
|
||||
$xmlElementName = null,
|
||||
Exclusion $exclusion = null,
|
||||
Exclusion $embedExclusion = null,
|
||||
array $relations = array()
|
||||
) {
|
||||
if ($resources instanceof \Traversable) {
|
||||
$resources = iterator_to_array($resources);
|
||||
}
|
||||
|
||||
$this->resources = $resources;
|
||||
$this->rel = $rel ?: 'items';
|
||||
$this->xmlElementName = $xmlElementName;
|
||||
$this->exclusion = $exclusion;
|
||||
$this->embedExclusion = $embedExclusion;
|
||||
$this->relations = $relations;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRel()
|
||||
{
|
||||
return $this->rel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $rel
|
||||
*/
|
||||
public function setRel($rel)
|
||||
{
|
||||
$this->rel = $rel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResources()
|
||||
{
|
||||
return $this->resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
*/
|
||||
public function getXmlElementName()
|
||||
{
|
||||
return $this->xmlElementName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|string $xmlElementName
|
||||
*/
|
||||
public function setXmlElementName($xmlElementName)
|
||||
{
|
||||
$this->xmlElementName = $xmlElementName;
|
||||
}
|
||||
|
||||
public function getRelations($object, ClassMetadataInterface $classMetadata)
|
||||
{
|
||||
return array_merge(array(
|
||||
new Relation(
|
||||
$this->rel,
|
||||
null,
|
||||
new Embedded(
|
||||
'expr(object.getResources())',
|
||||
$this->xmlElementName,
|
||||
$this->embedExclusion
|
||||
),
|
||||
array(),
|
||||
$this->exclusion
|
||||
)
|
||||
), $this->relations);
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Representation\Factory;
|
||||
|
||||
use Hateoas\Configuration\Route;
|
||||
use Hateoas\Representation\CollectionRepresentation;
|
||||
use Hateoas\Representation\PaginatedRepresentation;
|
||||
use Pagerfanta\Pagerfanta;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class PagerfantaFactory
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $pageParameterName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $limitParameterName;
|
||||
|
||||
/**
|
||||
* @param string $pageParameterName
|
||||
* @param string $limitParameterName
|
||||
*/
|
||||
public function __construct($pageParameterName = null, $limitParameterName = null)
|
||||
{
|
||||
$this->pageParameterName = $pageParameterName;
|
||||
$this->limitParameterName = $limitParameterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Pagerfanta $pager The pager
|
||||
* @param Route $route The collection's route
|
||||
* @param mixed $inline Most of the time, a custom `CollectionRepresentation` instance
|
||||
*
|
||||
* @return PaginatedRepresentation
|
||||
*/
|
||||
public function createRepresentation(Pagerfanta $pager, Route $route, $inline = null)
|
||||
{
|
||||
if (null === $inline) {
|
||||
$inline = new CollectionRepresentation($pager->getCurrentPageResults());
|
||||
}
|
||||
|
||||
return new PaginatedRepresentation(
|
||||
$inline,
|
||||
$route->getName(),
|
||||
$route->getParameters(),
|
||||
$pager->getCurrentPage(),
|
||||
$pager->getMaxPerPage(),
|
||||
$pager->getNbPages(),
|
||||
$this->getPageParameterName(),
|
||||
$this->getLimitParameterName(),
|
||||
$route->isAbsolute(),
|
||||
$pager->getNbResults()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPageParameterName()
|
||||
{
|
||||
return $this->pageParameterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLimitParameterName()
|
||||
{
|
||||
return $this->limitParameterName;
|
||||
}
|
||||
}
|
||||
volume/www/website/www/vendor/willdurand/hateoas/src/Hateoas/Representation/OffsetRepresentation.php
Vendored
+134
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Representation;
|
||||
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
* @Serializer\XmlRoot("collection")
|
||||
* @Serializer\AccessorOrder("custom", custom = {"offset", "limit", "total"})
|
||||
*
|
||||
* @Hateoas\Relation(
|
||||
* "first",
|
||||
* href = @Hateoas\Route(
|
||||
* "expr(object.getRoute())",
|
||||
* parameters = "expr(object.getParameters(0))",
|
||||
* absolute = "expr(object.isAbsolute())"
|
||||
* )
|
||||
* )
|
||||
* @Hateoas\Relation(
|
||||
* "last",
|
||||
* href = @Hateoas\Route(
|
||||
* "expr(object.getRoute())",
|
||||
* parameters = "expr(object.getParameters((object.getTotal() - 1) - (object.getTotal() - 1) % object.getLimit()))",
|
||||
* absolute = "expr(object.isAbsolute())"
|
||||
* ),
|
||||
* exclusion = @Hateoas\Exclusion(
|
||||
* excludeIf = "expr(object.getTotal() === null)"
|
||||
* )
|
||||
* )
|
||||
* @Hateoas\Relation(
|
||||
* "next",
|
||||
* href = @Hateoas\Route(
|
||||
* "expr(object.getRoute())",
|
||||
* parameters = "expr(object.getParameters(object.getOffset() + object.getLimit()))",
|
||||
* absolute = "expr(object.isAbsolute())"
|
||||
* ),
|
||||
* exclusion = @Hateoas\Exclusion(
|
||||
* excludeIf = "expr(object.getTotal() !== null && (object.getOffset() + object.getLimit()) >= object.getTotal())"
|
||||
* )
|
||||
* )
|
||||
* @Hateoas\Relation(
|
||||
* "previous",
|
||||
* href = @Hateoas\Route(
|
||||
* "expr(object.getRoute())",
|
||||
* parameters = "expr(object.getParameters((object.getOffset() > object.getLimit()) ? object.getOffset() - object.getLimit() : 0))",
|
||||
* absolute = "expr(object.isAbsolute())"
|
||||
* ),
|
||||
* exclusion = @Hateoas\Exclusion(
|
||||
* excludeIf = "expr(! object.getOffset())"
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @author Premi Giorgio <giosh94mhz@gmail.com>
|
||||
*/
|
||||
class OffsetRepresentation extends AbstractSegmentedRepresentation
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose
|
||||
* @Serializer\XmlAttribute
|
||||
*/
|
||||
private $offset;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $offsetParameterName;
|
||||
|
||||
/**
|
||||
* @param CollectionRepresentation $inline
|
||||
* @param string $route
|
||||
* @param integer|null $offset
|
||||
* @param integer $limit
|
||||
* @param integer $total
|
||||
*/
|
||||
public function __construct(
|
||||
$inline,
|
||||
$route,
|
||||
array $parameters = array(),
|
||||
$offset,
|
||||
$limit,
|
||||
$total = null,
|
||||
$offsetParameterName = null,
|
||||
$limitParameterName = null,
|
||||
$absolute = false
|
||||
) {
|
||||
parent::__construct($inline, $route, $parameters, $limit, $total, $limitParameterName, $absolute);
|
||||
|
||||
$this->offset = $offset;
|
||||
$this->offsetParameterName = $offsetParameterName ?: 'offset';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getOffset()
|
||||
{
|
||||
return $this->offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $offset
|
||||
* @param null $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getParameters($offset = null, $limit = null)
|
||||
{
|
||||
$parameters = parent::getParameters($limit);
|
||||
|
||||
unset($parameters[$this->offsetParameterName]);
|
||||
|
||||
if (null === $offset) {
|
||||
$offset = $this->getOffset();
|
||||
}
|
||||
|
||||
if ($offset) {
|
||||
$parameters[$this->offsetParameterName] = $offset;
|
||||
$this->moveParameterToEnd($parameters, $this->getLimitParameterName());
|
||||
}
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOffsetParameterName()
|
||||
{
|
||||
return $this->offsetParameterName;
|
||||
}
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Representation;
|
||||
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
* @Serializer\XmlRoot("collection")
|
||||
* @Serializer\AccessorOrder("custom", custom = {"page", "limit", "pages", "total"})
|
||||
*
|
||||
* @Hateoas\Relation(
|
||||
* "first",
|
||||
* href = @Hateoas\Route(
|
||||
* "expr(object.getRoute())",
|
||||
* parameters = "expr(object.getParameters(1))",
|
||||
* absolute = "expr(object.isAbsolute())"
|
||||
* )
|
||||
* )
|
||||
* @Hateoas\Relation(
|
||||
* "last",
|
||||
* href = @Hateoas\Route(
|
||||
* "expr(object.getRoute())",
|
||||
* parameters = "expr(object.getParameters(object.getPages()))",
|
||||
* absolute = "expr(object.isAbsolute())"
|
||||
* ),
|
||||
* exclusion = @Hateoas\Exclusion(
|
||||
* excludeIf = "expr(object.getPages() === null)"
|
||||
* )
|
||||
* )
|
||||
* @Hateoas\Relation(
|
||||
* "next",
|
||||
* href = @Hateoas\Route(
|
||||
* "expr(object.getRoute())",
|
||||
* parameters = "expr(object.getParameters(object.getPage() + 1))",
|
||||
* absolute = "expr(object.isAbsolute())"
|
||||
* ),
|
||||
* exclusion = @Hateoas\Exclusion(
|
||||
* excludeIf = "expr(object.getPages() !== null && (object.getPage() + 1) > object.getPages())"
|
||||
* )
|
||||
* )
|
||||
* @Hateoas\Relation(
|
||||
* "previous",
|
||||
* href = @Hateoas\Route(
|
||||
* "expr(object.getRoute())",
|
||||
* parameters = "expr(object.getParameters(object.getPage() - 1))",
|
||||
* absolute = "expr(object.isAbsolute())"
|
||||
* ),
|
||||
* exclusion = @Hateoas\Exclusion(
|
||||
* excludeIf = "expr((object.getPage() - 1) < 1)"
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class PaginatedRepresentation extends AbstractSegmentedRepresentation
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose
|
||||
* @Serializer\Type("integer")
|
||||
* @Serializer\XmlAttribute
|
||||
*/
|
||||
private $page;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @Serializer\Expose
|
||||
* @Serializer\Type("integer")
|
||||
* @Serializer\XmlAttribute
|
||||
*/
|
||||
private $pages;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $pageParameterName;
|
||||
|
||||
public function __construct(
|
||||
$inline,
|
||||
$route,
|
||||
array $parameters = array(),
|
||||
$page,
|
||||
$limit,
|
||||
$pages,
|
||||
$pageParameterName = null,
|
||||
$limitParameterName = null,
|
||||
$absolute = false,
|
||||
$total = null
|
||||
) {
|
||||
parent::__construct($inline, $route, $parameters, $limit, $total, $limitParameterName, $absolute);
|
||||
|
||||
$this->page = $page;
|
||||
$this->pages = $pages;
|
||||
$this->pageParameterName = $pageParameterName ?: 'page';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPage()
|
||||
{
|
||||
return $this->page;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $page
|
||||
* @param null $limit
|
||||
* @return array
|
||||
*/
|
||||
public function getParameters($page = null, $limit = null)
|
||||
{
|
||||
$parameters = parent::getParameters($limit);
|
||||
|
||||
unset($parameters[$this->pageParameterName]);
|
||||
$parameters[$this->pageParameterName] = null === $page ? $this->getPage() : $page;
|
||||
|
||||
$this->moveParameterToEnd($parameters, $this->getLimitParameterName());
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPages()
|
||||
{
|
||||
return $this->pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPageParameterName()
|
||||
{
|
||||
return $this->pageParameterName;
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Representation;
|
||||
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*
|
||||
* @Hateoas\Relation(
|
||||
* "self",
|
||||
* href = @Hateoas\Route(
|
||||
* "expr(object.getRoute())",
|
||||
* parameters = "expr(object.getParameters())",
|
||||
* absolute = "expr(object.isAbsolute())"
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class RouteAwareRepresentation
|
||||
{
|
||||
/**
|
||||
* @Serializer\Inline
|
||||
* @Serializer\Expose
|
||||
*/
|
||||
private $inline;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $route;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $parameters;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
private $absolute;
|
||||
|
||||
public function __construct($inline, $route, array $parameters = array(), $absolute = false)
|
||||
{
|
||||
$this->inline = $inline;
|
||||
$this->route = $route;
|
||||
$this->parameters = $parameters;
|
||||
$this->absolute = $absolute;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getInline()
|
||||
{
|
||||
return $this->inline;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRoute()
|
||||
{
|
||||
return $this->route;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getParameters()
|
||||
{
|
||||
return $this->parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function isAbsolute()
|
||||
{
|
||||
return $this->absolute;
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Hateoas\Representation;
|
||||
|
||||
use Hateoas\Configuration\Relation;
|
||||
use Hateoas\Configuration\Annotation as Hateoas;
|
||||
use Hateoas\Configuration\Metadata\ClassMetadataInterface;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
* @Serializer\XmlRoot("resource")
|
||||
*
|
||||
* @Hateoas\RelationProvider("getRelations")
|
||||
*
|
||||
* @author William Durand <william.durand1@gmail.com>
|
||||
*/
|
||||
class VndErrorRepresentation
|
||||
{
|
||||
/**
|
||||
* @Serializer\Expose
|
||||
*/
|
||||
private $message;
|
||||
|
||||
/**
|
||||
* @Serializer\Expose
|
||||
* @Serializer\XmlAttribute
|
||||
*/
|
||||
private $logref;
|
||||
|
||||
/**
|
||||
* @var Relation
|
||||
*/
|
||||
private $help;
|
||||
|
||||
/**
|
||||
* @var Relation
|
||||
*/
|
||||
private $describes;
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param integer $logref
|
||||
*/
|
||||
public function __construct($message, $logref = null, Relation $help = null, Relation $describes = null)
|
||||
{
|
||||
$this->message = $message;
|
||||
$this->logref = $logref;
|
||||
$this->help = $help;
|
||||
$this->describes = $describes;
|
||||
}
|
||||
|
||||
public function getRelations($object, ClassMetadataInterface $classMetadata)
|
||||
{
|
||||
$relations = array();
|
||||
|
||||
if (null !== $this->help) {
|
||||
$relations[] = $this->help;
|
||||
}
|
||||
|
||||
if (null !== $this->describes) {
|
||||
$relations[] = $this->describes;
|
||||
}
|
||||
|
||||
return $relations;
|
||||
}
|
||||
|
||||
public function getMessage()
|
||||
{
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
public function getLogref()
|
||||
{
|
||||
return $this->logref;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user