Skip to content
This repository was archived by the owner on Sep 16, 2021. It is now read-only.

Commit 3f2f8c4

Browse files
committed
Decorator support
1 parent cef66f0 commit 3f2f8c4

21 files changed

+452
-71
lines changed

CmfResourceRestBundle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313

1414
use Symfony\Component\HttpKernel\Bundle\Bundle;
1515
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Cmf\Bundle\ResourceRestBundle\DependencyInjection\Compiler\DecoratorPass;
1617

1718
class CmfResourceRestBundle extends Bundle
1819
{
1920
public function build(ContainerBuilder $container)
2021
{
22+
$container->addCompilerPass(new DecoratorPass());
2123
parent::build($container);
2224
}
2325
}

Decorator/DecoratorInterface.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony CMF package.
5+
*
6+
* (c) 2011-2014 Symfony CMF
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Cmf\Bundle\ResourceRestBundle\Decorator;
13+
14+
use JMS\Serializer\Context;
15+
use Puli\Repository\Api\Resource\Resource;
16+
17+
/**
18+
* Decorator classes decorate the REST response for resources
19+
*
20+
* @author Daniel Leech <[email protected]>
21+
*/
22+
interface DecoratorInterface
23+
{
24+
/**
25+
* Decorate the given serialization context.
26+
*
27+
* For example:
28+
*
29+
* $context->addData('foobar', 'Some value');
30+
*
31+
* @param Context Serialization context
32+
* @param resource The resource being serialized
33+
*/
34+
public function decorate(Context $context, Resource $resource);
35+
}

Decorator/PayloadDecorator.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony CMF package.
5+
*
6+
* (c) 2011-2014 Symfony CMF
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Cmf\Bundle\ResourceRestBundle\Decorator;
13+
14+
use JMS\Serializer\Context;
15+
use Puli\Repository\Api\Resource\Resource;
16+
17+
/**
18+
* Serialize the payload
19+
*
20+
* @author Daniel Leech <[email protected]>
21+
*/
22+
class PayloadDecorator implements DecoratorInterface
23+
{
24+
/**
25+
* {@inheritDoc}
26+
*/
27+
public function decorate(Context $context, Resource $resource)
28+
{
29+
$visitor = $context->getVisitor();
30+
$visitor->addData('payload', $context->accept($resource->getPayload()));
31+
}
32+
}

DependencyInjection/CmfResourceRestExtension.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,24 @@ public function load(array $configs, ContainerBuilder $container)
5454

5555
$loader->load('serializer.xml');
5656
$loader->load('resource-rest.xml');
57+
$loader->load('decorator.xml');
5758

5859
$this->configurePayloadAliasRegistry($container, $config['payload_alias_map']);
60+
$this->configureDecoratorMap($container, $config['decorator_map']);
5961
}
6062

6163
private function configurePayloadAliasRegistry(ContainerBuilder $container, $aliasMap)
6264
{
63-
$registry = $container->getDefinition('cmf_resource_rest.payload_alias_registry');
65+
$registry = $container->getDefinition('cmf_resource_rest.registry.payload_alias');
6466
$registry->replaceArgument(1, $aliasMap);
6567
}
6668

69+
private function configureDecoratorMap(ContainerBuilder $container, $decoratorMap)
70+
{
71+
$registry = $container->getDefinition('cmf_resource_rest.registry.decorator');
72+
$registry->replaceArgument(1, $decoratorMap);
73+
}
74+
6775
public function getNamespace()
6876
{
6977
return 'http://cmf.symfony.com/schema/dic/' . $this->getAlias();
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony CMF package.
5+
*
6+
* (c) 2011-2014 Symfony CMF
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Cmf\Bundle\ResourceRestBundle\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\ContainerBuilder;
15+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16+
use Symfony\Component\DependencyInjection\Reference;
17+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
18+
19+
/**
20+
* @author Daniel Leech <[email protected]>
21+
*/
22+
class DecoratorPass implements CompilerPassInterface
23+
{
24+
public function process(ContainerBuilder $container)
25+
{
26+
if (!$container->has('cmf_resource_rest.registry.decorator')) {
27+
return;
28+
}
29+
30+
$taggedIds = $container->findTaggedServiceIds('cmf_resource_rest.decorator');
31+
32+
$repositoryMap = array();
33+
$aliasMap = array();
34+
foreach ($taggedIds as $id => $attributes) {
35+
if (!isset($attributes[0]['alias'])) {
36+
throw new InvalidArgumentException(sprintf(
37+
'Resource decorator "%s" has no "alias" attribute in its tag',
38+
$id
39+
));
40+
}
41+
42+
$name = $attributes[0]['alias'];
43+
44+
if (isset($aliasMap[$name])) {
45+
throw new InvalidArgumentException(sprintf(
46+
'Decorator with name "%s" (id: "%s") has already been registered',
47+
$name,
48+
$id
49+
));
50+
}
51+
52+
$aliasMap[$name] = $id;
53+
}
54+
55+
$registryDef = $container->getDefinition('cmf_resource_rest.registry.decorator');
56+
$registryDef->replaceArgument(2, $aliasMap);
57+
}
58+
}

DependencyInjection/Configuration.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ public function getConfigTreeBuilder()
3636
->end()
3737
->end()
3838
->end()
39+
->arrayNode('decorator_map')
40+
->useAttributeAsKey('repository')
41+
->prototype('array')
42+
->prototype('scalar')->end()
43+
->end()
44+
->end()
3945
->end();
4046

4147
return $treeBuilder;

Registry/DecoratorRegistry.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony CMF package.
5+
*
6+
* (c) 2011-2014 Symfony CMF
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Cmf\Bundle\ResourceRestBundle\Registry;
13+
14+
use Symfony\Cmf\Component\Resource\RepositoryFactoryInterface;
15+
use Symfony\Component\DependencyInjection\ContainerInterface;
16+
use Symfony\Cmf\Component\Resource\RepositoryRegistryInterface;
17+
use Puli\Repository\Api\Resource\Resource;
18+
use Puli\Repository\Api\ResourceRepository;
19+
20+
/**
21+
* Registry for resource decorators
22+
*
23+
* @author Daniel Leech <[email protected]>
24+
*/
25+
class DecoratorRegistry
26+
{
27+
/**
28+
* @var array
29+
*/
30+
private $aliasMap = array();
31+
32+
/**
33+
* @var array
34+
*/
35+
private $decoratorMap = array();
36+
37+
/**
38+
* @var ContainerInterface
39+
*/
40+
private $container;
41+
42+
/**
43+
* @param ContainerInterface $container The service container
44+
* @param array $decoratorMap Map of decorator aliases to repository names
45+
* @param array $aliasMap Serice ID map for decorator aliases
46+
*/
47+
public function __construct(
48+
ContainerInterface $container,
49+
$decoratorMap = array(),
50+
$aliasMap = array()
51+
)
52+
{
53+
$this->container = $container;
54+
$this->decoratorMap = $decoratorMap;
55+
$this->aliasMap = $aliasMap;
56+
}
57+
58+
/**
59+
* Return all of the decorators which are reigstered against
60+
* the repository with the given alias.
61+
*
62+
* @param string $repositoryAlias
63+
* @return DecoratorInterface[]
64+
*/
65+
public function getDecorators($repositoryAlias)
66+
{
67+
if (!isset($this->decoratorMap[$repositoryAlias])) {
68+
return array();
69+
}
70+
71+
$aliases = $this->decoratorMap[$repositoryAlias];
72+
73+
foreach ($aliases as $alias) {
74+
if (!isset($this->aliasMap[$alias])) {
75+
throw new \InvalidArgumentException(sprintf(
76+
'Unknown decorator alias "%s". Known aliases: "%s"',
77+
implode('", "', array_keys($this->aliasMap))
78+
));
79+
}
80+
81+
$decorator = $this->container->get(
82+
$this->aliasMap[$alias]
83+
);
84+
$decorators[] = $decorator;
85+
}
86+
87+
return $decorators;
88+
}
89+
}

PayloadAliasRegistry.php renamed to Registry/PayloadAliasRegistry.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* file that was distributed with this source code.
1010
*/
1111

12-
namespace Symfony\Cmf\Bundle\ResourceRestBundle;
12+
namespace Symfony\Cmf\Bundle\ResourceRestBundle\Registry;
1313

1414
use Symfony\Cmf\Component\Resource\RepositoryFactoryInterface;
1515
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -27,7 +27,7 @@ class PayloadAliasRegistry
2727
/**
2828
* @var array
2929
*/
30-
private $aliasesByRepository;
30+
private $aliasesByRepository = array();
3131

3232
/**
3333
* @var RepositoryRegistryInterface
@@ -57,7 +57,6 @@ public function __construct(
5757
* Return the alias for the given PHPCR resource
5858
*
5959
* @param Resource $resource
60-
*
6160
* @return string
6261
*/
6362
public function getPayloadAlias(Resource $resource)
@@ -73,15 +72,11 @@ public function getPayloadAlias(Resource $resource)
7372
}
7473

7574
if (!isset($this->aliasesByRepository[$repositoryType])) {
76-
throw new \RuntimeException(sprintf(
77-
'No repositories registered with alias "%s". Known aliases "%s"',
78-
$repositoryType,
79-
implode('", "', array_keys($this->aliasesByRepository))
80-
));
75+
return null;
8176
}
8277

8378
if (!isset($this->aliasesByRepository[$repositoryType][$type])) {
84-
return $type;
79+
return null;
8580
}
8681

8782
return $this->aliasesByRepository[$repositoryType][$type];

Resources/config/decorator.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
6+
7+
<parameters>
8+
<parameter key="cmf_resource_rest.decorator.payload.class">Symfony\Cmf\Bundle\ResourceRestBundle\Decorator\PayloadDecorator</parameter>
9+
</parameters>
10+
11+
<services>
12+
13+
<service id="cmf_resource_rest.decorator.payload" class="%cmf_resource_rest.decorator.payload.class%">
14+
<tag name="cmf_resource_rest.decorator" alias="payload" />
15+
</service>
16+
17+
</services>
18+
</container>
19+

Resources/config/resource-rest.xml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
<parameters>
88
<parameter key="cmf_resource_rest.controller.resource.class">Symfony\Cmf\Bundle\ResourceRestBundle\Controller\ResourceController</parameter>
99
<parameter key="cmf_resource_rest.path_helper.class">Symfony\Cmf\Bundle\ResourceRestBundle\Helper\PathHelper</parameter>
10-
<parameter key="cmf_resource_rest.payload_alias_registry.class">Symfony\Cmf\Bundle\ResourceRestBundle\PayloadAliasRegistry</parameter>
10+
<parameter key="cmf_resource_rest.registry.payload_alias.class">Symfony\Cmf\Bundle\ResourceRestBundle\Registry\PayloadAliasRegistry</parameter>
11+
<parameter key="cmf_resource_rest.registry.decorator.class">Symfony\Cmf\Bundle\ResourceRestBundle\Registry\DecoratorRegistry</parameter>
1112
</parameters>
1213

1314
<services>
@@ -20,10 +21,16 @@
2021

2122
<service id="cmf_resource_rest.path_helper" class="%cmf_resource_rest.path_helper.class%" />
2223

23-
<service id="cmf_resource_rest.payload_alias_registry" class="%cmf_resource_rest.payload_alias_registry.class%">
24+
<service id="cmf_resource_rest.registry.payload_alias" class="%cmf_resource_rest.registry.payload_alias.class%">
2425
<argument type="service" id="cmf_resource.registry" />
2526
<argument type="collection" />
2627
</service>
2728

29+
<service id="cmf_resource_rest.registry.decorator" class="%cmf_resource_rest.registry.decorator.class%">
30+
<argument type="service" id="service_container" />
31+
<argument type="collection" />
32+
<argument type="collection" />
33+
</service>
34+
2835
</services>
2936
</container>

0 commit comments

Comments
 (0)