Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\GeneratorBundle\Manipulator;
use Symfony\Component\HttpKernel\KernelInterface;
use Sensio\Bundle\GeneratorBundle\Generator\Generator;
/**
* Changes the PHP code of a Kernel.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class KernelManipulator extends Manipulator
{
protected $kernel;
protected $reflected;
public function __construct(KernelInterface $kernel)
{
$this->kernel = $kernel;
$this->reflected = new \ReflectionObject($kernel);
}
/**
* Adds a bundle at the end of the existing ones.
*
* @param string $bundle The bundle class name
*
* @return bool Whether the operation succeeded
*
* @throws \RuntimeException If bundle is already defined
*/
public function addBundle($bundle)
{
if (!$this->getFilename()) {
return false;
}
$src = file($this->getFilename());
$method = $this->reflected->getMethod('registerBundles');
$lines = array_slice($src, $method->getStartLine() - 1, $method->getEndLine() - $method->getStartLine() + 1);
// Don't add same bundle twice
if (false !== strpos(implode('', $lines), $bundle)) {
throw new \RuntimeException(sprintf('Bundle "%s" is already defined in "AppKernel::registerBundles()".', $bundle));
}
$this->setCode(token_get_all('<?php '.implode('', $lines)), $method->getStartLine());
while ($token = $this->next()) {
// $bundles
if (T_VARIABLE !== $token[0] || '$bundles' !== $token[1]) {
continue;
}
// =
$this->next();
// array start with traditional or short syntax
$token = $this->next();
if (T_ARRAY !== $token[0] && '[' !== $this->value($token)) {
return false;
}
// add the bundle at the end of the array
while ($token = $this->next()) {
// look for ); or ];
if (')' !== $this->value($token) && ']' !== $this->value($token)) {
continue;
}
if (';' !== $this->value($this->peek())) {
continue;
}
$this->next();
$leadingContent = implode('', array_slice($src, 0, $this->line));
// trim semicolon
$leadingContent = rtrim(rtrim($leadingContent), ';');
// We want to match ) & ]
$closingSymbolRegex = '#(\)|])$#';
// get closing symbol used
preg_match($closingSymbolRegex, $leadingContent, $matches);
$closingSymbol = $matches[0];
// remove last close parentheses
$leadingContent = rtrim(preg_replace($closingSymbolRegex, '', rtrim($leadingContent)));
if ('(' !== substr($leadingContent, -1) && '[' !== substr($leadingContent, -1)) {
// end of leading content is not open parentheses or bracket, then assume that array contains at least one element
$leadingContent = rtrim($leadingContent, ',').',';
}
$lines = array_merge(
array($leadingContent, "\n"),
array(str_repeat(' ', 12), sprintf('new %s(),', $bundle), "\n"),
array(str_repeat(' ', 8), $closingSymbol.';', "\n"),
array_slice($src, $this->line)
);
Generator::dump($this->getFilename(), implode('', $lines));
return true;
}
}
}
public function getFilename()
{
return $this->reflected->getFileName();
}
}