Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d258187

Browse files
committed
[Routing] Convert the PhpGeneratorDumper to an AstGeneratorInterface
1 parent 0b61e4c commit d258187

File tree

2 files changed

+173
-84
lines changed

2 files changed

+173
-84
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Component\Routing\Generator\AstGenerator;
13+
14+
use PhpParser\BuilderFactory;
15+
use PhpParser\Comment;
16+
use PhpParser\Node\Name;
17+
use PhpParser\Node\Param;
18+
use PhpParser\Node\Stmt;
19+
use PhpParser\Node\Expr;
20+
use Psr\Log\LoggerInterface;
21+
use Symfony\Component\AstGenerator\AstGeneratorInterface;
22+
use Symfony\Component\AstGenerator\Util\AstHelper;
23+
use Symfony\Component\Routing\Exception\RouteNotFoundException;
24+
use Symfony\Component\Routing\Generator\UrlGenerator;
25+
use Symfony\Component\Routing\RequestContext;
26+
27+
/**
28+
* @author Guilhem N. <[email protected]>
29+
*/
30+
class UrlGeneratorGenerator implements AstGeneratorInterface
31+
{
32+
public function __construct()
33+
{
34+
$this->factory = new BuilderFactory();
35+
}
36+
37+
/**
38+
* {@inheritdoc}
39+
*/
40+
public function generate($object, array $context = array())
41+
{
42+
$context = array_replace(array(
43+
'class' => 'ProjectUrlGenerator',
44+
'base_class' => UrlGenerator::class,
45+
), $context);
46+
47+
return array($this->generateClass($object, $context)->getNode());
48+
}
49+
50+
/**
51+
* {@inheritdoc}
52+
*/
53+
public function supportsGeneration($object)
54+
{
55+
return is_string($object) && class_exists($object);
56+
}
57+
58+
private function generateClass($object, array $context)
59+
{
60+
$docComment = <<<COMMENT
61+
/**
62+
* {$context['class']}.
63+
*
64+
* This class has been auto-generated
65+
* by the Symfony Routing Component.
66+
*/
67+
COMMENT;
68+
69+
return $this->factory->class($context['class'])
70+
->setDocComment($docComment)
71+
->extend($context['base_class'])
72+
->addStmt($this->factory->property('declaredRoutes')->makePrivate()->makeStatic())
73+
->addStmt($this->generateConstructor($object, $context))
74+
->addStmt($this->generateGenerateMethod($object, $context));
75+
}
76+
77+
private function generateConstructor($object, array $context)
78+
{
79+
$constructor = $this->factory->method('__construct')
80+
->makePublic()
81+
->addParam($this->factory->param('context')->setTypeHint(RequestContext::class))
82+
->addParam($this->factory->param('logger')->setTypeHint(LoggerInterface::class)->setDefault(null));
83+
84+
$code = <<<'EOF'
85+
$this->context = $context;
86+
$this->logger = $logger;
87+
EOF;
88+
foreach (AstHelper::raw($code) as $stmt) {
89+
$constructor->addStmt($stmt);
90+
}
91+
92+
$constructor->addStmt(new Stmt\If_(
93+
new Expr\BinaryOp\Equal(
94+
AstHelper::value(null),
95+
new Expr\StaticPropertyFetch(new Name('self'), 'declaredRoutes')
96+
),
97+
array(
98+
'stmts' => array(
99+
new Expr\Assign(
100+
new Expr\StaticPropertyFetch(new Name('self'), 'declaredRoutes'),
101+
$this->generateDeclaredRoutes($object, $context)
102+
),
103+
),
104+
)
105+
));
106+
107+
return $constructor;
108+
}
109+
110+
/**
111+
* Generates an AST node representing an array of defined routes
112+
* together with the routes properties (e.g. requirements).
113+
*
114+
* @return Expr\Array_
115+
*/
116+
private function generateDeclaredRoutes($object, array $context)
117+
{
118+
$routes = array();
119+
foreach ($object->all() as $name => $route) {
120+
$compiledRoute = $route->compile();
121+
122+
$properties = array();
123+
$properties[] = $compiledRoute->getVariables();
124+
$properties[] = $route->getDefaults();
125+
$properties[] = $route->getRequirements();
126+
$properties[] = $compiledRoute->getTokens();
127+
$properties[] = $compiledRoute->getHostTokens();
128+
$properties[] = $route->getSchemes();
129+
130+
$routes[$name] = $properties;
131+
}
132+
133+
return AstHelper::value($routes);
134+
}
135+
136+
/**
137+
* Generates an AST node representing the `generate` method that implements the UrlGeneratorInterface.
138+
*
139+
* @return string PHP code
140+
*/
141+
private function generateGenerateMethod()
142+
{
143+
$generateMethod = $this->factory
144+
->method('generate')
145+
->makePublic()
146+
->addParam($this->factory->param('name'))
147+
->addParam($this->factory->param('parameters')->setDefault(array()))
148+
->addParam($this->factory->param('referenceType')->setDefault(UrlGenerator::ABSOLUTE_PATH));
149+
150+
$exception = RouteNotFoundException::class;
151+
$code = <<<EOF
152+
if (!isset(self::\$declaredRoutes[\$name])) {
153+
throw new {$exception}(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', \$name));
154+
}
155+
156+
list(\$variables, \$defaults, \$requirements, \$tokens, \$hostTokens, \$requiredSchemes) = self::\$declaredRoutes[\$name];
157+
158+
return \$this->doGenerate(\$variables, \$defaults, \$requirements, \$tokens, \$parameters, \$name, \$referenceType, \$hostTokens, \$requiredSchemes);
159+
EOF;
160+
161+
foreach (AstHelper::raw($code) as $stmt) {
162+
$generateMethod->addStmt($stmt);
163+
}
164+
165+
return $generateMethod;
166+
}
167+
}

src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php

Lines changed: 6 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
namespace Symfony\Component\Routing\Generator\Dumper;
1313

14+
use Symfony\Component\AstGenerator\Util\AstHelper;
15+
use Symfony\Component\Routing\Generator\AstGenerator\UrlGeneratorGenerator;
16+
1417
/**
1518
* PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes.
1619
*
@@ -33,91 +36,10 @@ class PhpGeneratorDumper extends GeneratorDumper
3336
*/
3437
public function dump(array $options = array())
3538
{
36-
$options = array_merge(array(
37-
'class' => 'ProjectUrlGenerator',
38-
'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator',
39-
), $options);
40-
41-
return <<<EOF
42-
<?php
43-
44-
use Symfony\Component\Routing\RequestContext;
45-
use Symfony\Component\Routing\Exception\RouteNotFoundException;
46-
use Psr\Log\LoggerInterface;
47-
48-
/**
49-
* {$options['class']}
50-
*
51-
* This class has been auto-generated
52-
* by the Symfony Routing Component.
53-
*/
54-
class {$options['class']} extends {$options['base_class']}
55-
{
56-
private static \$declaredRoutes;
57-
58-
/**
59-
* Constructor.
60-
*/
61-
public function __construct(RequestContext \$context, LoggerInterface \$logger = null)
62-
{
63-
\$this->context = \$context;
64-
\$this->logger = \$logger;
65-
if (null === self::\$declaredRoutes) {
66-
self::\$declaredRoutes = {$this->generateDeclaredRoutes()};
67-
}
68-
}
69-
70-
{$this->generateGenerateMethod()}
71-
}
72-
73-
EOF;
74-
}
75-
76-
/**
77-
* Generates PHP code representing an array of defined routes
78-
* together with the routes properties (e.g. requirements).
79-
*
80-
* @return string PHP code
81-
*/
82-
private function generateDeclaredRoutes()
83-
{
84-
$routes = "array(\n";
85-
foreach ($this->getRoutes()->all() as $name => $route) {
86-
$compiledRoute = $route->compile();
87-
88-
$properties = array();
89-
$properties[] = $compiledRoute->getVariables();
90-
$properties[] = $route->getDefaults();
91-
$properties[] = $route->getRequirements();
92-
$properties[] = $compiledRoute->getTokens();
93-
$properties[] = $compiledRoute->getHostTokens();
94-
$properties[] = $route->getSchemes();
39+
$generator = new UrlGeneratorGenerator();
9540

96-
$routes .= sprintf(" '%s' => %s,\n", $name, str_replace("\n", '', var_export($properties, true)));
97-
}
98-
$routes .= ' )';
99-
100-
return $routes;
101-
}
41+
$code = AstHelper::dump($generator->generate($this->getRoutes(), $options));
10242

103-
/**
104-
* Generates PHP code representing the `generate` method that implements the UrlGeneratorInterface.
105-
*
106-
* @return string PHP code
107-
*/
108-
private function generateGenerateMethod()
109-
{
110-
return <<<'EOF'
111-
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
112-
{
113-
if (!isset(self::$declaredRoutes[$name])) {
114-
throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
115-
}
116-
117-
list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = self::$declaredRoutes[$name];
118-
119-
return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);
120-
}
121-
EOF;
43+
return $code;
12244
}
12345
}

0 commit comments

Comments
 (0)