diff --git a/src/Controller/ResourceController.php b/src/Controller/ResourceController.php index 4881d6d..399d33e 100644 --- a/src/Controller/ResourceController.php +++ b/src/Controller/ResourceController.php @@ -11,6 +11,7 @@ namespace Symfony\Cmf\Bundle\ResourceRestBundle\Controller; +use Symfony\Cmf\Bundle\ResourceRestBundle\Serializer\Jms\Handler\ResourceHandler; use Symfony\Cmf\Component\Resource\Puli\Api\ResourceRepository; use Symfony\Cmf\Component\Resource\Puli\Api\ResourceNotFoundException; use Symfony\Cmf\Component\Resource\RepositoryRegistryInterface; @@ -38,6 +39,11 @@ class ResourceController */ private $serializer; + /** + * @var ResourceHandler + */ + private $resourceHandler; + /** * @var AuthorizationCheckerInterface|null */ @@ -47,11 +53,12 @@ class ResourceController * @param SerializerInterface $serializer * @param RepositoryRegistryInterface $registry */ - public function __construct(SerializerInterface $serializer, RepositoryRegistryInterface $registry, AuthorizationCheckerInterface $authorizationChecker = null) + public function __construct(SerializerInterface $serializer, RepositoryRegistryInterface $registry, ResourceHandler $resourceHandler, AuthorizationCheckerInterface $authorizationChecker = null) { $this->serializer = $serializer; $this->registry = $registry; $this->authorizationChecker = $authorizationChecker; + $this->resourceHandler = $resourceHandler; } /** @@ -60,8 +67,12 @@ public function __construct(SerializerInterface $serializer, RepositoryRegistryI * @param string $repositoryName * @param string $path */ - public function getResourceAction($repositoryName, $path) + public function getResourceAction(Request $request, $repositoryName, $path) { + if ($request->query->has('depth')) { + $this->resourceHandler->setMaxDepth($request->query->getInt('depth')); + } + $path = '/'.ltrim($path, '/'); try { diff --git a/src/DependencyInjection/CmfResourceRestExtension.php b/src/DependencyInjection/CmfResourceRestExtension.php index a960969..c824a74 100644 --- a/src/DependencyInjection/CmfResourceRestExtension.php +++ b/src/DependencyInjection/CmfResourceRestExtension.php @@ -35,6 +35,13 @@ public function load(array $configs, ContainerBuilder $container) $configuration = new Configuration(); $config = $processor->processConfiguration($configuration, $configs); + $bundles = $container->getParameter('kernel.bundles'); + if (!array_key_exists('JMSSerializerBundle', $bundles)) { + throw new \LogicException('The JMSSerializerBundle must be registered in order to use the CmfResourceRestBundle.'); + } + + $container->setParameter('cmf_resource_rest.max_depth', $config['max_depth']); + $loader->load('serializer.xml'); $loader->load('resource-rest.xml'); diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 10fd8a6..d0cbe2c 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -28,6 +28,7 @@ public function getConfigTreeBuilder() ->fixXmlConfig('payload_alias', 'payload_alias_map') ->fixXmlConfig('enhance', 'enhancer_map') ->children() + ->integerNode('max_depth')->defaultValue(2)->end() ->arrayNode('payload_alias_map') ->useAttributeAsKey('name') ->prototype('array') diff --git a/src/Resources/config/resource-rest.xml b/src/Resources/config/resource-rest.xml index 7f760ea..e279b01 100644 --- a/src/Resources/config/resource-rest.xml +++ b/src/Resources/config/resource-rest.xml @@ -9,6 +9,7 @@ + diff --git a/src/Resources/config/serializer.xml b/src/Resources/config/serializer.xml index 6b1b171..6a6118e 100644 --- a/src/Resources/config/serializer.xml +++ b/src/Resources/config/serializer.xml @@ -9,6 +9,8 @@ + %cmf_resource_rest.max_depth% + diff --git a/src/Serializer/Jms/Handler/ResourceHandler.php b/src/Serializer/Jms/Handler/ResourceHandler.php index cd9b020..0927623 100644 --- a/src/Serializer/Jms/Handler/ResourceHandler.php +++ b/src/Serializer/Jms/Handler/ResourceHandler.php @@ -33,15 +33,18 @@ class ResourceHandler implements SubscribingHandlerInterface private $registry; private $payloadAliasRegistry; private $enhancerRegistry; + private $maxDepth; public function __construct( RepositoryRegistryInterface $registry, PayloadAliasRegistry $payloadAliasRegistry, - EnhancerRegistry $enhancerRegistry + EnhancerRegistry $enhancerRegistry, + $maxDepth = 2 ) { $this->registry = $registry; $this->payloadAliasRegistry = $payloadAliasRegistry; $this->enhancerRegistry = $enhancerRegistry; + $this->maxDepth = $maxDepth; } public static function getSubscribingMethods() @@ -72,6 +75,11 @@ public function serializeResource( $context->accept($data); } + public function setMaxDepth($maxDepth) + { + $this->maxDepth = $maxDepth; + } + private function doSerializeResource(PuliResource $resource, $depth = 0) { $data = array(); @@ -96,7 +104,7 @@ private function doSerializeResource(PuliResource $resource, $depth = 0) foreach ($resource->listChildren() as $name => $childResource) { $children[$name] = array(); - if ($depth < 2) { + if ($depth < $this->maxDepth) { $children[$name] = $this->doSerializeResource($childResource, $depth + 1); } } diff --git a/tests/Features/nesting.feature b/tests/Features/nesting.feature new file mode 100644 index 0000000..b90daae --- /dev/null +++ b/tests/Features/nesting.feature @@ -0,0 +1,68 @@ +Feature: Nesting resources + In order to retrieve a tree of data + As a webservice user + I need to be able to get nested resources + + Background: + Given the test application has the following configuration: + """ + cmf_resource: + repositories: + default: + type: doctrine/phpcr-odm + basepath: /tests/cmf/articles + """ + And there exists an "Article" document at "/cmf/articles/foo": + | title | Article 1 | + | body | This is my article | + And there exists an "Article" document at "/cmf/articles/foo/sub": + | title | Sub-article 1 | + | body | This is my article | + + Scenario: Retrieving nested resources + When I send a GET request to "/api/default/foo" + Then the response should contain json: + """ + { + "repository_alias": "default", + "repository_type": "doctrine/phpcr-odm", + "payload_alias": null, + "payload_type": "Symfony\\Cmf\\Bundle\\ResourceRestBundle\\Tests\\Resources\\TestBundle\\Document\\Article", + "path": "\/foo", + "node_name": "foo", + "label": "foo", + "repository_path": "\/foo", + "children": { + "sub": { + "repository_alias": "default", + "repository_type": "doctrine/phpcr-odm", + "payload_alias": null, + "payload_type": "Symfony\\Cmf\\Bundle\\ResourceRestBundle\\Tests\\Resources\\TestBundle\\Document\\Article", + "path": "\/foo\/sub", + "node_name": "sub", + "label": "sub", + "repository_path": "\/foo\/sub", + "children": [] + } + } + } + """ + + Scenario: Specifying a depth + When I send a GET request to "/api/default/foo?depth=0" + Then the response should contain json: + """ + { + "repository_alias": "default", + "repository_type": "doctrine/phpcr-odm", + "payload_alias": null, + "payload_type": "Symfony\\Cmf\\Bundle\\ResourceRestBundle\\Tests\\Resources\\TestBundle\\Document\\Article", + "path": "\/foo", + "node_name": "foo", + "label": "foo", + "repository_path": "\/foo", + "children": { + "sub": [] + } + } + """ diff --git a/tests/Features/resource_api_filesystem.feature b/tests/Features/resource_api_filesystem.feature index eae12ee..45c262e 100644 --- a/tests/Features/resource_api_filesystem.feature +++ b/tests/Features/resource_api_filesystem.feature @@ -9,7 +9,7 @@ Feature: Filesystem resource repository # cmf_resource: # repositories: # default: -# type: filesystem +# type: puli/filesystem # base_dir: "%kernel.root_dir%/Resources/views/snippets" # """ # And there is a file named "%kernel.root_dir%/Resources/views/snippets/snippet1.html" with: @@ -24,7 +24,7 @@ Feature: Filesystem resource repository # """ # { # "repository_alias": "default", -# "repository_type": "filesystem", +# "repository_type": "puli/filesystem", # "payload_alias": null, # "payload_type": null, # "path": "\/snippet1.html", diff --git a/tests/Features/resource_api_phpcr.feature b/tests/Features/resource_api_phpcr.feature index abf5e4d..ec6500a 100644 --- a/tests/Features/resource_api_phpcr.feature +++ b/tests/Features/resource_api_phpcr.feature @@ -9,7 +9,7 @@ Feature: PHPCR resource repository cmf_resource: repositories: phpcr_repo: - type: doctrine_phpcr + type: phpcr/phpcr basepath: /tests/cmf/articles cmf_resource_rest: @@ -29,7 +29,7 @@ Feature: PHPCR resource repository """ { "repository_alias": "phpcr_repo", - "repository_type": "doctrine_phpcr", + "repository_type": "phpcr/phpcr", "payload_alias": null, "payload_type": "nt:unstructured", "path": "\/foo", diff --git a/tests/Features/resource_api_phpcr_odm.feature b/tests/Features/resource_api_phpcr_odm.feature index e706760..399108f 100644 --- a/tests/Features/resource_api_phpcr_odm.feature +++ b/tests/Features/resource_api_phpcr_odm.feature @@ -9,13 +9,13 @@ Feature: PHPCR-ODM resource repository cmf_resource: repositories: phpcrodm_repo: - type: doctrine_phpcr_odm + type: doctrine/phpcr-odm basepath: /tests/cmf/articles cmf_resource_rest: payload_alias_map: article: - repository: doctrine_phpcr_odm + repository: doctrine/phpcr-odm type: "Symfony\\Cmf\\Bundle\\ResourceRestBundle\\Tests\\Resources\\TestBundle\\Document\\Article" """ @@ -30,7 +30,7 @@ Feature: PHPCR-ODM resource repository """ { "repository_alias": "phpcrodm_repo", - "repository_type": "doctrine_phpcr_odm", + "repository_type": "doctrine/phpcr-odm", "payload_alias": "article", "payload_type": "Symfony\\Cmf\\Bundle\\ResourceRestBundle\\Tests\\Resources\\TestBundle\\Document\\Article", "path": "\/foo", @@ -57,7 +57,7 @@ Feature: PHPCR-ODM resource repository """ { "repository_alias": "phpcrodm_repo", - "repository_type": "doctrine_phpcr_odm", + "repository_type": "doctrine/phpcr-odm", "payload_alias": "article", "payload_type": "Symfony\\Cmf\\Bundle\\ResourceRestBundle\\Tests\\Resources\\TestBundle\\Document\\Article", "path": "\/foo", @@ -67,7 +67,7 @@ Feature: PHPCR-ODM resource repository "children": { "bar": { "repository_alias": "phpcrodm_repo", - "repository_type": "doctrine_phpcr_odm", + "repository_type": "doctrine/phpcr-odm", "payload_alias": "article", "payload_type": "Symfony\\Cmf\\Bundle\\ResourceRestBundle\\Tests\\Resources\\TestBundle\\Document\\Article", "path": "/foo/bar", @@ -78,7 +78,7 @@ Feature: PHPCR-ODM resource repository }, "boo": { "repository_alias": "phpcrodm_repo", - "repository_type": "doctrine_phpcr_odm", + "repository_type": "doctrine/phpcr-odm", "payload_alias": "article", "payload_type": "Symfony\\Cmf\\Bundle\\ResourceRestBundle\\Tests\\Resources\\TestBundle\\Document\\Article", "path": "/foo/boo", diff --git a/tests/Features/security.feature b/tests/Features/security.feature index f5506ba..5781389 100644 --- a/tests/Features/security.feature +++ b/tests/Features/security.feature @@ -9,7 +9,7 @@ Feature: Security cmf_resource: repositories: security: - type: doctrine_phpcr + type: phpcr/phpcr basepath: /tests/cmf/articles """ And there exists an "Article" document at "/private/foo": diff --git a/tests/Resources/app/config/routing.php b/tests/Resources/app/config/routing.php index ff57da9..99cba3b 100644 --- a/tests/Resources/app/config/routing.php +++ b/tests/Resources/app/config/routing.php @@ -13,7 +13,7 @@ $collection = new RouteCollection(); $collection->addCollection( - $loader->import(__DIR__.'/../../../../Resources/config/routing.yml') + $loader->import('@CmfResourceRestBundle/Resources/config/routing.yml') ); return $collection; diff --git a/tests/Unit/DependencyInjection/CmfResourceRestExtensionTest.php b/tests/Unit/DependencyInjection/CmfResourceRestExtensionTest.php index f26e01a..c89f264 100644 --- a/tests/Unit/DependencyInjection/CmfResourceRestExtensionTest.php +++ b/tests/Unit/DependencyInjection/CmfResourceRestExtensionTest.php @@ -49,9 +49,23 @@ public function provideExtension() */ public function testExtension($config) { - $this->container->setParameter('kernel.bundles', array()); + $this->container->setParameter('kernel.bundles', ['JMSSerializerBundle' => true]); $this->container->addCompilerPass(new EnhancerPass()); + $this->load($config); + + $this->compile(); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage The JMSSerializerBundle must be registered + */ + public function testNoJmsSerializerBundleRegistered() + { + $this->container->setParameter('kernel.bundles', []); + + $this->load([]); $this->compile(); } } diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index b762717..7f1b0b8 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -53,6 +53,7 @@ public function testConfig($source) 'enhancer' => 'my_enhancer', ), ), + 'max_depth' => 2, ), array($source)); } }