10000 [Routing] Convert the PhpMatcherDumper to an AstGeneratorInterface · symfony/symfony@2b9654b · GitHub
[go: up one dir, main page]

Skip to content

Commit 2b9654b

Browse files
committed
[Routing] Convert the PhpMatcherDumper to an AstGeneratorInterface
1 parent 8e89d34 commit 2b9654b

File tree

2 files changed

+139
-35
lines changed

2 files changed

+139
-35
lines changed

src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php

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

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

14+
use PhpParser\PrettyPrinter\Standard;
15+
use Symfony\Component\AstGenerator\Util\AstHelper;
1416
use Symfony\Component\Routing\Route;
1517
use Symfony\Component\Routing\RouteCollection;
18+
use Symfony\Component\Routing\Matcher\Generator\PhpMatcherGenerator;
1619
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
1720
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
1821

@@ -31,6 +34,7 @@ class PhpMatcherDumper extends MatcherDumper
3134
* @var ExpressionFunctionProviderInterface[]
3235
*/
3336
private $expressionLanguageProviders = array();
37+
private $generator;
3438

3539
/**
3640
* Dumps a set of routes to a PHP class.
@@ -46,42 +50,9 @@ class PhpMatcherDumper extends MatcherDumper
4650
*/
4751
public function dump(array $options = array())
4852
{
49-
$options = array_replace(array(
50-
'class' => 'ProjectUrlMatcher',
51-
'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
52-
), $options);
53+
$generator = new PhpMatcherGenerator();
5354

54-
// trailing slash support is only enabled if we know how to redirect the user
55-
$interfaces = class_implements($options['base_class']);
56-
$supportsRedirections = isset($interfaces['Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface']);
57-
58-
return <<<EOF
59-
<?php
60-
61-
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
62-
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
63-
use Symfony\Component\Routing\RequestContext;
64-
65-
/**
66-
* {$options['class']}.
67-
*
68-
* This class has been auto-generated
69-
* by the Symfony Routing Component.
70-
*/
71-
class {$options['class']} extends {$options['base_class']}
72-
{
73-
/**
74-
* Constructor.
75-
*/
76-
public function __construct(RequestContext \$context)
77-
{
78-
\$this->context = \$context;
79-
}
80-
81-
{$this->generateMatchMethod($supportsRedirections)}
82-
}
83-
84-
EOF;
55+
return AstHelper::dump($generator->generate($this->getRoutes(), $options));
8556
}
8657

8758
public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
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\Matcher\Generator;
13+
14+
use PhpParser\BuilderFactory;
15+
use PhpParser\Comment;
16+
use PhpParser\Node\Arg;
17+
use PhpParser\Node\Name;
18+
use PhpParser\Node\Param;
19+
use PhpParser\Node\Stmt;
20+
use PhpParser\Node\Expr;
21+
use PhpParser\Node\Scalar;
22+
use Symfony\Component\AstGenerator\AstGeneratorInterface;
23+
use Symfony\Component\AstGenerator\Util\AstHelper;
24+
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
25+
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
26+
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
27+
use Symfony\Component\Routing\RequestContext;
28+
29+
/**
30+
* @author Guilhem N. <egetick@gmail.com>
31+
*/
32+
class PhpMatcherGenerator implements AstGeneratorInterface
33+
{
34+
private $expressionLanguage;
35+
36+
/**
37+
* @var ExpressionFunctionProviderInterface[]
38+
*/
39+
private $expressionLanguageProviders = array();
40+
private $factory;
41+
42+
public function __construct()
43+
{
44+
$this->factory = new BuilderFactory();
45+
}
46+
47+
/**
48+
* {@inheritdoc}
49+
*/
50+
public function generate($object, array $context = array())
51+
{
52+
$context = array_replace(array(
53+
'class' => 'ProjectUrlMatcher',
54+
'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher',
55+
), $context);
56+
57+
// trailing slash support is only enabled if we know how to redirect the user
58+
$interfaces = class_implements($context['base_class']);
59+
$supportsRedirections = isset($interfaces['Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface']);
60+
61+
return array($this->generateClass($object, $context)->getNode());
62+
}
63+
64+
/**
65+
* {@inheritdoc}
66+
*/
67+
public function supportsGeneration($object)
68+
{
69+
return is_string($object) && class_exists($object);
70+
}
71+
72+
private function generateClass($object, array $context)
73+
{
74+
$docComment = <<<COMMENT
75+
/**
76+
* {$context['class']}.
77+
*
78+
* This class has been auto-generated
79+
* by the Symfony Routing Component.
80+
*/
81+
COMMENT;
82+
83+
return $this->factory->class($context['class'])
84+
->setDocComment($docComment)
85+
->extend($context['base_class'])
86+
->addStmt($this->factory->property('context')->makePrivate())
87+
->addStmt(
88+
$this->factory->method('__construct')
89+
->makePublic()
90+
->addParam($this->factory->param('context')->setTypeHint(RequestContext::class))
91+
->addStmt(
92+
// $this->context = $context
93+
new Expr\Assign(
94+
new Expr\PropertyFetch(new Expr\Variable('this'), 'context'),
95+
new Expr\Variable('context')
96+
)
97+
)
98+
)
99+
->addStmt($this->generateMatchMethod($object, $context));
100+
}
101+
102+
private function generateMatchMethod($object, array $context)
103+
{
104+
$method = $this->factory
105+
->method('match')
106+
->makePublic()
107+
->addParam($this->factory->param('pathinfo'))
108+
->addStmt(new Expr\Assign(new Expr\Variable('allow'), AstHelper::value(array())))
109+
->addStmt(new Expr\Assign(
110+
new Expr\Variable('pathinfo'),
111+
new Expr\FuncCall(new Name('rawurldecode'), array(
112+
new Arg(new Expr\Variable('pathinfo')),
113+
))
114+
))
115+
->addStmt(new Expr\Assign(new Expr\Variable('context'), new Expr\PropertyFetch(new Expr\Variable('this'), 'context')))
116+
->addStmt(new Expr\Assign(new Expr\Variable('request'), new Expr\PropertyFetch(new Expr\Variable('this'), 'request')));
117+
118+
$method->addStmt(new Stmt\Throw_(new Expr\Ternary(
119+
new Expr\BinaryOp\Smaller(
120+
new Scalar\LNumber(0),
121+
new Expr\FuncCall(new Name('count'), array(new Arg(new Expr\Variable('allow'))))
122+
),
123+
new Expr\New_(new Name(MethodNotAllowedException::class), array(
124+
new Arg(new Expr\FuncCall(new Name('array_unique'), array(
125+
new Arg(new Expr\Variable('allow')),
126+
))),
127+
)),
128+
new Expr\New_(new Name(ResourceNotFoundException::class))
129+
)));
130+
131+
return $method;
132+
}
133+
}

0 commit comments

Comments
 (0)
0