2

I have created custom annotations to generate JSON files (for NodeRed if you ask...) and i'm testing them successfully from a dummy method in a dummy controller.

I would like to port all that to a custom Sf command whose job would be to read all Controllers annotations in my bundle and achieve the same result (aka create JSON files).

How could i achieve that ? Would looping through XxxxController.php file(s) with the finder be a good option ? Or am too ambitious ? :p

Annotation example:

/**
 * @NodeRedFlows(
 *     triggerBy="testFlow", options={"interval":"45"}  
 * )
 */
 public function indexAction() { /*...*/ }

Sorry its not easy to post some more code because i have the whole reader class, the annotation class and another class creating JSON flows based on the triggerBy="testFlow" id.

Bottom line:*

I would like to be able to create my JSON flow file from a Command instead of here in my Controller (used it for tests).

1 Answer 1

2

Load all controller actions, which have been assigned a route in Symfony (see this and this).

Then load the annotations for every found controller action:

use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\HttpFoundation\Request;

$annotationReader = new AnnotationReader();
$routes = $this->container->get('router')->getRouteCollection()->all();
$this->container->set('request', new Request(), 'request');

foreach ($routes as $route => $param) {
    $defaults = $params->getDefaults();

    if (isset($defaults['_controller'])) {
         list($controllerService, $controllerMethod) = explode(':', $defaults['_controller']);
         $controllerObject = $this->container->get($controllerService);
         $reflectedMethod = new \ReflectionMethod($controllerObject, $controllerMethod);

         // the annotations
         $annotations = $annotationReader->getMethodAnnotations($reflectedMethod );
    }
}

UPDATE:

If you need all controller methods, including those without the @Route annotation, then I would do what you suggest in your question:

// Load all registered bundles
$bundles = $this->container->getParameter('kernel.bundles');

foreach ($bundles as $name => $class) {
    // Check these are really your bundles, not the vendor bundles
    $bundlePrefix = 'MyBundle';
    if (substr($name, 0, strlen($bundlePrefix)) != $bundlePrefix) continue;

    $namespaceParts = explode('\\', $class);
    // remove class name
    array_pop($namespaceParts);
    $bundleNamespace = implode('\\', $namespaceParts);
    $rootPath = $this->container->get('kernel')->getRootDir().'/../src/';
    $controllerDir = $rootPath.$bundleNamespace.'/Controller';

    $files = scandir($controllerDir);
    foreach ($files as $file) {
        list($filename, $ext) = explode('.', $file);
        if ($ext != 'php') continue;

        $class = $bundleNamespace.'\\Controller\\'.$filename;
        $reflectedClass = new \ReflectionClass($class);

        foreach ($reflectedClass->getMethods() as $reflectedMethod) {
            // the annotations
            $annotations = $annotationReader->getMethodAnnotations($reflectedMethod);
        }
    }
}
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks, but the comment don't always have a @Route annotation... Besides, the line "$controllerObject = $container->get($controllerService);" give the error: " You cannot create a service ("request") of an inactive scope ("request").". It seems this is going in the right direction thought.
I updated the answer to address the You cannot create a service ("request") of an inactive scope ("request"). error
Updated the answer to include actions without @Route annotation too. I haven't tested the code, but it should work.
Thank you. I'll go with your first solution, on afterthoughts. It works well (i've change the Reflection to avoid the You cannot create a service ("request") of an inactive scope ("request") error but i get double annotations strangely
Just do $this->container->set('request', new Request(), 'request'); to avoid the error.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.