From cbe8661f69a636527045b5b5f696448e53ac8a4f Mon Sep 17 00:00:00 2001 From: dantleech Date: Sun, 26 Jan 2014 17:54:43 +0000 Subject: [PATCH 1/3] First pass for adding metadata + annotations --- DependencyInjection/CmfRoutingExtension.php | 63 ++++---------- Enhancer/FieldByClassEnhancer.php | 82 +++++++++++++++++++ Metadata/Annotations/Controller.php | 11 +++ Metadata/Annotations/Template.php | 11 +++ Metadata/ClassMetadata.php | 11 +++ Metadata/Driver/AnnotationDriver.php | 45 ++++++++++ Resources/config/metadata.xml | 37 +++++++++ Resources/config/routing-dynamic.xml | 11 ++- .../Metadata/Driver/AnnotationDriverTest.php | 44 ++++++++++ .../Functional/Routing/DynamicRouterTest.php | 3 +- Tests/Resources/Document/AnnotatedContent.php | 46 +++++++++++ Tests/Resources/app/config/cmf_routing.yml | 4 - composer.json | 3 +- phpunit.xml.dist | 4 + 14 files changed, 318 insertions(+), 57 deletions(-) create mode 100644 Enhancer/FieldByClassEnhancer.php create mode 100644 Metadata/Annotations/Controller.php create mode 100644 Metadata/Annotations/Template.php create mode 100644 Metadata/ClassMetadata.php create mode 100644 Metadata/Driver/AnnotationDriver.php create mode 100644 Resources/config/metadata.xml create mode 100644 Tests/Functional/Metadata/Driver/AnnotationDriverTest.php create mode 100644 Tests/Resources/Document/AnnotatedContent.php diff --git a/DependencyInjection/CmfRoutingExtension.php b/DependencyInjection/CmfRoutingExtension.php index e9d5176b..5a8f0351 100644 --- a/DependencyInjection/CmfRoutingExtension.php +++ b/DependencyInjection/CmfRoutingExtension.php @@ -34,6 +34,7 @@ public function load(array $configs, ContainerBuilder $container) { $config = $this->processConfiguration(new Configuration(), $configs); $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('metadata.xml'); if ($config['dynamic']['enabled']) { // load this even if no explicit enabled value but some configuration @@ -150,55 +151,23 @@ private function setupDynamicRouter(array $config, ContainerBuilder $container, ) ); } - if (!empty($config['controllers_by_class'])) { - $dynamic->addMethodCall( - 'addRouteEnhancer', - array( - new Reference($this->getAlias() . '.enhancer.controllers_by_class'), - 50 - ) - ); - } - if (!empty($config['templates_by_class'])) { - $dynamic->addMethodCall( - 'addRouteEnhancer', - array( - new Reference($this->getAlias() . '.enhancer.templates_by_class'), - 40 - ) - ); - /* - * The CoreBundle prepends the controller from ContentBundle if the - * ContentBundle is present in the project. - * If you are sure you do not need a generic controller, set the field - * to false to disable this check explicitly. But you would need - * something else like the default_controller to set the controller, - * as no controller will be set here. - */ - if (null === $config['generic_controller']) { - throw new InvalidConfigurationException('If you want to configure templates_by_class, you need to configure the generic_controller option.'); - } + $dynamic->addMethodCall( + 'addRouteEnhancer', + array( + new Reference($this->getAlias() . '.enhancer.controllers_by_class'), + 50 + ) + ); + + $dynamic->addMethodCall( + 'addRouteEnhancer', + array( + new Reference($this->getAlias() . '.enhancer.templates_by_class'), + 40 + ) + ); - if (is_string($config['generic_controller'])) { - // if the content class defines the template, we also need to make sure we use the generic controller for those routes - $controllerForTemplates = array(); - foreach ($config['templates_by_class'] as $key => $value) { - $controllerForTemplates[$key] = $config['generic_controller']; - } - - $definition = $container->getDefinition($this->getAlias() . '.enhancer.controller_for_templates_by_class'); - $definition->replaceArgument(2, $controllerForTemplates); - - $dynamic->addMethodCall( - 'addRouteEnhancer', - array( - new Reference($this->getAlias() . '.enhancer.controller_for_templates_by_class'), - 30 - ) - ); - } - } if (!empty($config['generic_controller']) && $config['generic_controller'] !== $defaultController) { $dynamic->addMethodCall( 'addRouteEnhancer', diff --git a/Enhancer/FieldByClassEnhancer.php b/Enhancer/FieldByClassEnhancer.php new file mode 100644 index 00000000..a1cf518c --- /dev/null +++ b/Enhancer/FieldByClassEnhancer.php @@ -0,0 +1,82 @@ + + */ +class FieldByClassEnhancer implements RouteEnhancerInterface +{ + /** + * @var string field for the className class + */ + protected $classField; + + /** + * @var string field to write hashmap lookup result into + */ + protected $targetField; + + /** + * @var string field to write hashmap lookup result into + */ + protected $metaField; + + /** + * @var Metadata\MetadataFactoryInterface + */ + protected $metadataFactory; + + /** + * @param string $className the field name of the class + * @param string $targetField the field name to set from the map + * @param array $map the map of class names to field values + */ + public function __construct( + $classField, + $targetField, + $metaField, + MetadataFactoryInterface $metadataFactory + ) + { + $this->classField = $classField; + $this->targetField = $targetField; + $this->metaField = $metaField; + $this->metadataFactory = $metadataFactory; + } + + /** + * If the class name is mapped + * + * {@inheritDoc} + */ + public function enhance(array $defaults, Request $request) + { + if (isset($defaults[$this->targetField])) { + return $defaults; + } + + // return if the field containg the class name has not been set + if (! isset($defaults[$this->classField])) { + return $defaults; + } + + $className = get_class($defaults[$this->classField]); + + $meta = $this->metadataFactory->getMetadataForClass($className); + + if (null !== $meta) { + $meta = $meta->getOutsideClassMetadata(); + $defaults[$this->targetField] = $meta->{$this->metaField}; + } + + return $defaults; + } +} diff --git a/Metadata/Annotations/Controller.php b/Metadata/Annotations/Controller.php new file mode 100644 index 00000000..561bd604 --- /dev/null +++ b/Metadata/Annotations/Controller.php @@ -0,0 +1,11 @@ +reader = $reader; + } + + public function loadMetadataForClass(\ReflectionClass $class) + { + $templateAnnotation = $this->reader->getClassAnnotation( + $class, + 'Symfony\Cmf\Bundle\RoutingBundle\Metadata\Annotations\Template' + ); + $controllerAnnotation = $this->reader->getClassAnnotation( + $class, + 'Symfony\Cmf\Bundle\RoutingBundle\Metadata\Annotations\Controller' + ); + + + $meta = new ClassMetadata($class->name); + + if (null !== $templateAnnotation) { + $meta->template = $templateAnnotation->resource; + } + + if (null !== $controllerAnnotation) { + $meta->controller = $controllerAnnotation->controller; + } + + return $meta; + } +} diff --git a/Resources/config/metadata.xml b/Resources/config/metadata.xml new file mode 100644 index 00000000..27dc9c92 --- /dev/null +++ b/Resources/config/metadata.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Resources/config/routing-dynamic.xml b/Resources/config/routing-dynamic.xml index 894512a7..2a824135 100644 --- a/Resources/config/routing-dynamic.xml +++ b/Resources/config/routing-dynamic.xml @@ -15,7 +15,7 @@ Symfony\Cmf\Component\Routing\Enhancer\FieldPresenceEnhancer Symfony\Cmf\Component\Routing\Enhancer\FieldPresenceEnhancer Symfony\Cmf\Component\Routing\Enhancer\FieldMapEnhancer - Symfony\Cmf\Component\Routing\Enhancer\FieldByClassEnhancer + Symfony\Cmf\Bundle\RoutingBundle\Enhancer\FieldByClassEnhancer Symfony\Cmf\Bundle\RoutingBundle\Controller\RedirectController @@ -46,19 +46,22 @@ _content _controller - %cmf_routing.controllers_by_class% + controller + _content _controller - + controller + _content _template - %cmf_routing.templates_by_class% + template + diff --git a/Tests/Functional/Metadata/Driver/AnnotationDriverTest.php b/Tests/Functional/Metadata/Driver/AnnotationDriverTest.php new file mode 100644 index 00000000..48dc856a --- /dev/null +++ b/Tests/Functional/Metadata/Driver/AnnotationDriverTest.php @@ -0,0 +1,44 @@ +driver = $this->getContainer()->get('cmf_routing.metadata.factory'); + } + + public function testDriver() + { + $meta = $this->driver->getMetadataForClass( + 'Symfony\Cmf\Bundle\RoutingBundle\Tests\Resources\Document\AnnotatedContent' + ); + + $this->assertNotNull($meta); + + $meta = $meta->getOutsideClassMetadata(); + + $this->assertEquals('TestBundle:Content:index.html.twig', $meta->template); + $this->assertEquals('ThisIsAController', $meta->controller); + } +} diff --git a/Tests/Functional/Routing/DynamicRouterTest.php b/Tests/Functional/Routing/DynamicRouterTest.php index 561b9368..a0874ef0 100644 --- a/Tests/Functional/Routing/DynamicRouterTest.php +++ b/Tests/Functional/Routing/DynamicRouterTest.php @@ -23,6 +23,7 @@ use Symfony\Cmf\Bundle\RoutingBundle\Tests\Functional\BaseTestCase; use Symfony\Cmf\Component\Testing\Document\Content; +use Symfony\Cmf\Bundle\RoutingBundle\Tests\Resources\Document\AnnotatedContent; /** * The goal of these tests is to test the interoperation with DI and everything. @@ -310,7 +311,7 @@ public function testEnhanceTemplateByClass() $this->getDm()->flush(); } NodeHelper::createPath($this->getDm()->getPhpcrSession(), '/test/content'); - $document = new Content(); + $document = new AnnotatedContent(); $document->setId('/test/content/templatebyclass'); $document->setTitle('the title'); $this->getDm()->persist($document); diff --git a/Tests/Resources/Document/AnnotatedContent.php b/Tests/Resources/Document/AnnotatedContent.php new file mode 100644 index 00000000..8a8a22ab --- /dev/null +++ b/Tests/Resources/Document/AnnotatedContent.php @@ -0,0 +1,46 @@ +path = $path; + } + + public function setTitle($title) + { + $this->title = $title; + } +} diff --git a/Tests/Resources/app/config/cmf_routing.yml b/Tests/Resources/app/config/cmf_routing.yml index a6789aec..fb3cb936 100644 --- a/Tests/Resources/app/config/cmf_routing.yml +++ b/Tests/Resources/app/config/cmf_routing.yml @@ -8,10 +8,6 @@ cmf_routing: generic_controller: cmf_content.controller:indexAction controllers_by_type: demo_alias: test.controller:aliasAction - controllers_by_class: - Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\RedirectRoute: cmf_routing.redirect_controller:redirectAction - templates_by_class: - Symfony\Cmf\Component\Testing\Document\Content: TestBundle:Content:index.html.twig locales: - en - de diff --git a/composer.json b/composer.json index 07afa7c0..2ce8a7e1 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "require": { "php": ">=5.3.3", "symfony-cmf/routing": "~1.2.0", - "symfony/framework-bundle": "~2.2" + "symfony/framework-bundle": "~2.2", + "jms/metadata": "1.5.0" }, "require-dev": { "symfony-cmf/core-bundle": "1.0.*", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 15fce6e1..893d12f2 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -19,6 +19,10 @@ ./Tests/Functional/Doctrine/Orm + + + ./Tests/Functional/Metadata + From 3b1ce3ec3b0559d5217723f124539ad1a1994fee Mon Sep 17 00:00:00 2001 From: dantleech Date: Sun, 2 Feb 2014 16:02:14 +0000 Subject: [PATCH 2/3] Added metadata driver: ConfigurationDriver --- DependencyInjection/CmfRoutingExtension.php | 46 +++++++++++++++++-- Enhancer/FieldByClassEnhancer.php | 4 +- Metadata/Driver/AbstractDriver.php | 23 ++++++++++ Metadata/Driver/AnnotationDriver.php | 5 +- Metadata/Driver/ConfigurationDriver.php | 46 +++++++++++++++++++ Resources/config/metadata.xml | 9 ++++ .../Functional/Routing/DynamicRouterTest.php | 3 +- Tests/Resources/Document/AnnotatedContent.php | 2 +- Tests/Resources/app/config/cmf_routing.yml | 4 ++ .../Driver/ConfigurationDriverTest.php | 43 +++++++++++++++++ 10 files changed, 176 insertions(+), 9 deletions(-) create mode 100644 Metadata/Driver/AbstractDriver.php create mode 100644 Metadata/Driver/ConfigurationDriver.php create mode 100644 Tests/Unit/Metadata/Driver/ConfigurationDriverTest.php diff --git a/DependencyInjection/CmfRoutingExtension.php b/DependencyInjection/CmfRoutingExtension.php index 5a8f0351..72cef529 100644 --- a/DependencyInjection/CmfRoutingExtension.php +++ b/DependencyInjection/CmfRoutingExtension.php @@ -39,6 +39,7 @@ public function load(array $configs, ContainerBuilder $container) if ($config['dynamic']['enabled']) { // load this even if no explicit enabled value but some configuration $this->setupDynamicRouter($config['dynamic'], $container, $loader); + $this->setupMetadataConfigurationDriver($config['dynamic'], $container); } /* set up the chain router */ @@ -54,6 +55,46 @@ public function load(array $configs, ContainerBuilder $container) $this->setupFormTypes($config, $container, $loader); } + public function setupMetadataConfigurationDriver($config, ContainerBuilder $container) + { + $driver = $container->getDefinition($this->getAlias() . '.metadata.driver.configuration'); + $mapping = array(); + + $controller = $container->getParameter($this->getAlias() . '.generic_controller');; + + $mappings = array(); + + if (!empty($config['controllers_by_class'])) { + foreach ($config['controllers_by_class'] as $classFqn => $controller) { + if (!isset($mappings[$classFqn])) { + $mappings[$classFqn] = array(); + } + + $mappings[$classFqn]['controller'] = $controller; + } + } + + if (!empty($config['templates_by_class'])) { + foreach ($config['templates_by_class'] as $classFqn => $template) { + if (!isset($mappings[$classFqn])) { + $mappings[$classFqn] = array(); + } + + $mappings[$classFqn]['template'] = $template; + } + } + + foreach ($mappings as $classFqn => &$mapping) { + if (!isset($mapping['controller'])) { + $mapping['controller'] = $container->getParameter( + $this->getAlias() . '.generic_controller' + ); + } + + $driver->addMethodCall('registerMapping', array($classFqn, $mapping)); + } + } + public function setupFormTypes(array $config, ContainerBuilder $container, LoaderInterface $loader) { $loader->load('form-type.xml'); @@ -77,7 +118,7 @@ public function setupFormTypes(array $config, ContainerBuilder $container, Loade private function setupDynamicRouter(array $config, ContainerBuilder $container, LoaderInterface $loader) { // strip whitespace (XML support) - foreach (array('controllers_by_type', 'controllers_by_class', 'templates_by_class', 'route_filters_by_id') as $option) { + foreach (array('controllers_by_type', 'route_filters_by_id') as $option) { $config[$option] = array_map(function ($value) { return trim($value); }, $config[$option]); @@ -87,11 +128,10 @@ private function setupDynamicRouter(array $config, ContainerBuilder $container, if (null === $defaultController) { $defaultController = $config['generic_controller']; } + $container->setParameter($this->getAlias() . '.default_controller', $defaultController); $container->setParameter($this->getAlias() . '.generic_controller', $config['generic_controller']); $container->setParameter($this->getAlias() . '.controllers_by_type', $config['controllers_by_type']); - $container->setParameter($this->getAlias() . '.controllers_by_class', $config['controllers_by_class']); - $container->setParameter($this->getAlias() . '.templates_by_class', $config['templates_by_class']); $container->setParameter($this->getAlias() . '.uri_filter_regexp', $config['uri_filter_regexp']); $container->setParameter($this->getAlias() . '.route_collection_limit', $config['route_collection_limit']); diff --git a/Enhancer/FieldByClassEnhancer.php b/Enhancer/FieldByClassEnhancer.php index a1cf518c..bb73eeda 100644 --- a/Enhancer/FieldByClassEnhancer.php +++ b/Enhancer/FieldByClassEnhancer.php @@ -74,7 +74,9 @@ public function enhance(array $defaults, Request $request) if (null !== $meta) { $meta = $meta->getOutsideClassMetadata(); - $defaults[$this->targetField] = $meta->{$this->metaField}; + if (null !== $meta->{$this->metaField}) { + $defaults[$this->targetField] = $meta->{$this->metaField}; + } } return $defaults; diff --git a/Metadata/Driver/AbstractDriver.php b/Metadata/Driver/AbstractDriver.php new file mode 100644 index 00000000..acee906d --- /dev/null +++ b/Metadata/Driver/AbstractDriver.php @@ -0,0 +1,23 @@ +template && + null == $meta->controller + ) { + throw new \InvalidArgumentException(sprintf( + 'Template specified for class "%s" but no controller specified.' .PHP_EOL. + 'You must either explicitly map a controller to the class or define'.PHP_EOL. + 'a "generic_controller" in the main configuration.' + , $meta->name)); + } + } +} diff --git a/Metadata/Driver/AnnotationDriver.php b/Metadata/Driver/AnnotationDriver.php index 88b72727..32e6ea47 100644 --- a/Metadata/Driver/AnnotationDriver.php +++ b/Metadata/Driver/AnnotationDriver.php @@ -2,11 +2,10 @@ namespace Symfony\Cmf\Bundle\RoutingBundle\Metadata\Driver; -use Metadata\Driver\DriverInterface; use Symfony\Cmf\Bundle\RoutingBundle\Metadata\ClassMetadata; use Doctrine\Common\Annotations\Reader; -class AnnotationDriver implements DriverInterface +class AnnotationDriver implements AbstractDriver { protected $reader; @@ -40,6 +39,8 @@ public function loadMetadataForClass(\ReflectionClass $class) $meta->controller = $controllerAnnotation->controller; } + $this->validateMetadata($meta); + return $meta; } } diff --git a/Metadata/Driver/ConfigurationDriver.php b/Metadata/Driver/ConfigurationDriver.php new file mode 100644 index 00000000..60bda400 --- /dev/null +++ b/Metadata/Driver/ConfigurationDriver.php @@ -0,0 +1,46 @@ + + */ +class ConfigurationDriver extends AbstractDriver +{ + protected $reader; + protected $metadata = array(); + + /** + * Eagerly loads the class metadata + */ + public function registerMapping($classFqn, $mapping) + { + $meta = new ClassMetadata($classFqn); + + if (isset($mapping['template'])) { + $meta->template = $mapping['template']; + } + + if (isset($mapping['controller'])) { + $meta->controller = $mapping['controller']; + } + + $this->validateMetadata($meta); + + $this->metadata[$classFqn] = $meta; + } + + public function loadMetadataForClass(\ReflectionClass $class) + { + if (!isset($this->metadata[$class->name])) { + return null; + } + + return $this->metadata[$class->name]; + } +} + diff --git a/Resources/config/metadata.xml b/Resources/config/metadata.xml index 27dc9c92..4951b89a 100644 --- a/Resources/config/metadata.xml +++ b/Resources/config/metadata.xml @@ -21,6 +21,7 @@ class="Metadata\Driver\DriverChain" > + @@ -33,5 +34,13 @@ + + + + + diff --git a/Tests/Functional/Routing/DynamicRouterTest.php b/Tests/Functional/Routing/DynamicRouterTest.php index a0874ef0..561b9368 100644 --- a/Tests/Functional/Routing/DynamicRouterTest.php +++ b/Tests/Functional/Routing/DynamicRouterTest.php @@ -23,7 +23,6 @@ use Symfony\Cmf\Bundle\RoutingBundle\Tests\Functional\BaseTestCase; use Symfony\Cmf\Component\Testing\Document\Content; -use Symfony\Cmf\Bundle\RoutingBundle\Tests\Resources\Document\AnnotatedContent; /** * The goal of these tests is to test the interoperation with DI and everything. @@ -311,7 +310,7 @@ public function testEnhanceTemplateByClass() $this->getDm()->flush(); } NodeHelper::createPath($this->getDm()->getPhpcrSession(), '/test/content'); - $document = new AnnotatedContent(); + $document = new Content(); $document->setId('/test/content/templatebyclass'); $document->setTitle('the title'); $this->getDm()->persist($document); diff --git a/Tests/Resources/Document/AnnotatedContent.php b/Tests/Resources/Document/AnnotatedContent.php index 8a8a22ab..ff25853c 100644 --- a/Tests/Resources/Document/AnnotatedContent.php +++ b/Tests/Resources/Document/AnnotatedContent.php @@ -20,7 +20,7 @@ * @PHPCRODM\Document(referenceable=true) * * @CmfRouting\Template("TestBundle:Content:index.html.twig") - * @CmfRouting\Controller("cmf_content.controller:indexAction") + * @CmfRouting\Controller("ThisIsAController") */ class AnnotatedContent { diff --git a/Tests/Resources/app/config/cmf_routing.yml b/Tests/Resources/app/config/cmf_routing.yml index fb3cb936..a6789aec 100644 --- a/Tests/Resources/app/config/cmf_routing.yml +++ b/Tests/Resources/app/config/cmf_routing.yml @@ -8,6 +8,10 @@ cmf_routing: generic_controller: cmf_content.controller:indexAction controllers_by_type: demo_alias: test.controller:aliasAction + controllers_by_class: + Symfony\Cmf\Bundle\RoutingBundle\Doctrine\Phpcr\RedirectRoute: cmf_routing.redirect_controller:redirectAction + templates_by_class: + Symfony\Cmf\Component\Testing\Document\Content: TestBundle:Content:index.html.twig locales: - en - de diff --git a/Tests/Unit/Metadata/Driver/ConfigurationDriverTest.php b/Tests/Unit/Metadata/Driver/ConfigurationDriverTest.php new file mode 100644 index 00000000..b3379401 --- /dev/null +++ b/Tests/Unit/Metadata/Driver/ConfigurationDriverTest.php @@ -0,0 +1,43 @@ +driver = new ConfigurationDriver; + } + + public function testDriver() + { + $this->driver->registerMapping('stdClass', array( + 'template' => 'foobar.html.twig', + 'controller' => 'FoobarController', + )); + + $refl = new \ReflectionClass('stdClass'); + $meta = $this->driver->loadMetadataForClass($refl); + + $this->assertEquals('foobar.html.twig', $meta->template); + $this->assertEquals('FoobarController', $meta->controller); + } + + /** + * @expectedException InvalidArgumentException + * @expectedExceptionMessage but no controller specified + */ + public function testDriverMissingController() + { + $this->driver->registerMapping('stdClass', array( + 'template' => 'foobar.html.twig', + )); + + $refl = new \ReflectionClass('stdClass'); + $meta = $this->driver->loadMetadataForClass($refl); + } +} From 8f5011951160b87c96622440d5235107304f1d1c Mon Sep 17 00:00:00 2001 From: dantleech Date: Sun, 2 Feb 2014 16:12:53 +0000 Subject: [PATCH 3/3] Added tests for class metadata validation --- DependencyInjection/CmfRoutingExtension.php | 14 ++++-- Metadata/Driver/AnnotationDriver.php | 12 ++++- .../Metadata/Driver/AnnotationDriverTest.php | 33 ++++++++++++-- .../Document/AnnotatedContentTemplateOnly.php | 45 +++++++++++++++++++ 4 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 Tests/Resources/Document/AnnotatedContentTemplateOnly.php diff --git a/DependencyInjection/CmfRoutingExtension.php b/DependencyInjection/CmfRoutingExtension.php index 72cef529..316fdb88 100644 --- a/DependencyInjection/CmfRoutingExtension.php +++ b/DependencyInjection/CmfRoutingExtension.php @@ -39,7 +39,7 @@ public function load(array $configs, ContainerBuilder $container) if ($config['dynamic']['enabled']) { // load this even if no explicit enabled value but some configuration $this->setupDynamicRouter($config['dynamic'], $container, $loader); - $this->setupMetadataConfigurationDriver($config['dynamic'], $container); + $this->setupMetadataDrivers($config['dynamic'], $container); } /* set up the chain router */ @@ -55,15 +55,21 @@ public function load(array $configs, ContainerBuilder $container) $this->setupFormTypes($config, $container, $loader); } - public function setupMetadataConfigurationDriver($config, ContainerBuilder $container) + public function setupMetadataDrivers($config, ContainerBuilder $container) { - $driver = $container->getDefinition($this->getAlias() . '.metadata.driver.configuration'); + $configDriver = $container->getDefinition($this->getAlias() . '.metadata.driver.configuration'); + $annotationDriver = $container->getDefinition($this->getAlias() . '.metadata.driver.annotation'); + $mapping = array(); $controller = $container->getParameter($this->getAlias() . '.generic_controller');; + // configure annotation driver + $annotationDriver->addMethodCall('setGenericController', array($controller)); + $mappings = array(); + // configure configuration driver if (!empty($config['controllers_by_class'])) { foreach ($config['controllers_by_class'] as $classFqn => $controller) { if (!isset($mappings[$classFqn])) { @@ -91,7 +97,7 @@ public function setupMetadataConfigurationDriver($config, ContainerBuilder $cont ); } - $driver->addMethodCall('registerMapping', array($classFqn, $mapping)); + $configDriver->addMethodCall('registerMapping', array($classFqn, $mapping)); } } diff --git a/Metadata/Driver/AnnotationDriver.php b/Metadata/Driver/AnnotationDriver.php index 32e6ea47..f7aa967b 100644 --- a/Metadata/Driver/AnnotationDriver.php +++ b/Metadata/Driver/AnnotationDriver.php @@ -5,9 +5,10 @@ use Symfony\Cmf\Bundle\RoutingBundle\Metadata\ClassMetadata; use Doctrine\Common\Annotations\Reader; -class AnnotationDriver implements AbstractDriver +class AnnotationDriver extends AbstractDriver { protected $reader; + protected $genericController; /** * @param AnnotationReader $reader @@ -17,6 +18,11 @@ public function __construct(Reader $reader) $this->reader = $reader; } + public function setGenericController($genericController) + { + $this->genericController = $genericController; + } + public function loadMetadataForClass(\ReflectionClass $class) { $templateAnnotation = $this->reader->getClassAnnotation( @@ -39,6 +45,10 @@ public function loadMetadataForClass(\ReflectionClass $class) $meta->controller = $controllerAnnotation->controller; } + if (null === $meta->controller) { + $meta->controller = $this->genericController; + } + $this->validateMetadata($meta); return $meta; diff --git a/Tests/Functional/Metadata/Driver/AnnotationDriverTest.php b/Tests/Functional/Metadata/Driver/AnnotationDriverTest.php index 48dc856a..ffaeda4d 100644 --- a/Tests/Functional/Metadata/Driver/AnnotationDriverTest.php +++ b/Tests/Functional/Metadata/Driver/AnnotationDriverTest.php @@ -25,12 +25,13 @@ public function setUp() { parent::setUp(); - $this->driver = $this->getContainer()->get('cmf_routing.metadata.factory'); + $this->chainDriver = $this->getContainer()->get('cmf_routing.metadata.factory'); + $this->annotDriver = $this->getContainer()->get('cmf_routing.metadata.driver.annotation'); } - public function testDriver() + public function testDriverTemplateAndContent() { - $meta = $this->driver->getMetadataForClass( + $meta = $this->chainDriver->getMetadataForClass( 'Symfony\Cmf\Bundle\RoutingBundle\Tests\Resources\Document\AnnotatedContent' ); @@ -41,4 +42,30 @@ public function testDriver() $this->assertEquals('TestBundle:Content:index.html.twig', $meta->template); $this->assertEquals('ThisIsAController', $meta->controller); } + + public function testDriverTemplateOnlyWithGenericController() + { + $meta = $this->chainDriver->getMetadataForClass( + 'Symfony\Cmf\Bundle\RoutingBundle\Tests\Resources\Document\AnnotatedContentTemplateOnly' + ); + + $this->assertNotNull($meta); + + $meta = $meta->getOutsideClassMetadata(); + + $this->assertEquals('TestBundle:Content:index.html.twig', $meta->template); + $this->assertEquals('cmf_content.controller:indexAction', $meta->controller); + } + + /** + * @expectedException InvalidArgumentException + * @expectedExceptionMessage but no controller specified + */ + public function testDriverTemplateOnlyNoController() + { + $this->annotDriver->setGenericController(null); + $meta = $this->chainDriver->getMetadataForClass( + 'Symfony\Cmf\Bundle\RoutingBundle\Tests\Resources\Document\AnnotatedContentTemplateOnly' + ); + } } diff --git a/Tests/Resources/Document/AnnotatedContentTemplateOnly.php b/Tests/Resources/Document/AnnotatedContentTemplateOnly.php new file mode 100644 index 00000000..ef76ac92 --- /dev/null +++ b/Tests/Resources/Document/AnnotatedContentTemplateOnly.php @@ -0,0 +1,45 @@ +path = $path; + } + + public function setTitle($title) + { + $this->title = $title; + } +}