Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
DebugCommand.php
001 <?php
002
003 /*
004 * This file is part of the Symfony package.
005 *
006 * (c) Fabien Potencier <fabien@symfony.com>
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 namespace Symfony\Bridge\Twig\Command;
013
014 use Symfony\Component\Console\Command\Command;
015 use Symfony\Component\Console\Formatter\OutputFormatter;
016 use Symfony\Component\Console\Input\InputArgument;
017 use Symfony\Component\Console\Input\InputInterface;
018 use Symfony\Component\Console\Input\InputOption;
019 use Symfony\Component\Console\Output\OutputInterface;
020 use Symfony\Component\Console\Style\SymfonyStyle;
021 use Twig\Environment;
022 use Twig\Loader\FilesystemLoader;
023
024 /**
025 * Lists twig functions, filters, globals and tests present in the current project.
026 *
027 * @author Jordi Boggiano <j.boggiano@seld.be>
028 */
029 class DebugCommand extends Command
030 {
031 protected static $defaultName = 'debug:twig';
032
033 private $twig;
034 private $projectDir;
035
036 /**
037 * @param Environment $twig
038 * @param string|null $projectDir
039 */
040 public function __construct($twig = null, $projectDir = null)
041 {
042 if (!$twig instanceof Environment) {
043 @trigger_error(sprintf('Passing a command name as the first argument of "%s()" is deprecated since Symfony 3.4 and support for it will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), \E_USER_DEPRECATED);
044
045 parent::__construct($twig);
046
047 return;
048 }
049
050 parent::__construct();
051
052 $this->twig = $twig;
053 $this->projectDir = $projectDir;
054 }
055
056 public function setTwigEnvironment(Environment $twig)
057 {
058 @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), \E_USER_DEPRECATED);
059
060 $this->twig = $twig;
061 }
062
063 /**
064 * @return Environment $twig
065 */
066 protected function getTwigEnvironment()
067 {
068 @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), \E_USER_DEPRECATED);
069
070 return $this->twig;
071 }
072
073 protected function configure()
074 {
075 $this
076 ->setDefinition([
077 new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'),
078 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'),
079 ])
080 ->setDescription('Shows a list of twig functions, filters, globals and tests')
081 ->setHelp(<<<'EOF'
082 The <info>%command.name%</info> command outputs a list of twig functions,
083 filters, globals and tests. Output can be filtered with an optional argument.
084
085 <info>php %command.full_name%</info>
086
087 The command lists all functions, filters, etc.
088
089 <info>php %command.full_name% date</info>
090
091 The command lists everything that contains the word date.
092
093 <info>php %command.full_name% --format=json</info>
094
095 The command lists everything in a machine readable json format.
096 EOF
097 )
098 ;
099 }
100
101 protected function execute(InputInterface $input, OutputInterface $output)
102 {
103 $io = new SymfonyStyle($input, $output);
104 $decorated = $io->isDecorated();
105
106 // BC to be removed in 4.0
107 if (__CLASS__ !== static::class) {
108 $r = new \ReflectionMethod($this, 'getTwigEnvironment');
109 if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
110 @trigger_error(sprintf('Usage of method "%s" is deprecated since Symfony 3.4 and will no longer be supported in 4.0. Construct the command with its required arguments instead.', static::class.'::getTwigEnvironment'), \E_USER_DEPRECATED);
111
112 $this->twig = $this->getTwigEnvironment();
113 }
114 }
115 if (null === $this->twig) {
116 throw new \RuntimeException('The Twig environment needs to be set.');
117 }
118
119 $filter = $input->getArgument('filter');
120 $types = ['functions', 'filters', 'tests', 'globals'];
121
122 if ('json' === $input->getOption('format')) {
123 $data = [];
124 foreach ($types as $type) {
125 foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) {
126 if (!$filter || false !== strpos($name, $filter)) {
127 $data[$type][$name] = $this->getMetadata($type, $entity);
128 }
129 }
130 }
131
132 if (isset($data['tests'])) {
133 $data['tests'] = array_keys($data['tests']);
134 }
135
136 $data['loader_paths'] = $this->getLoaderPaths();
137 $data = json_encode($data, \JSON_PRETTY_PRINT);
138 $io->writeln($decorated ? OutputFormatter::escape($data) : $data);
139
140 return 0;
141 }
142
143 foreach ($types as $index => $type) {
144 $items = [];
145 foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) {
146 if (!$filter || false !== strpos($name, $filter)) {
147 $items[$name] = $name.$this->getPrettyMetadata($type, $entity, $decorated);
148 }
149 }
150
151 if (!$items) {
152 continue;
153 }
154
155 $io->section(ucfirst($type));
156
157 ksort($items);
158 $io->listing($items);
159 }
160
161 $rows = [];
162 $firstNamespace = true;
163 $prevHasSeparator = false;
164 foreach ($this->getLoaderPaths() as $namespace => $paths) {
165 if (!$firstNamespace && !$prevHasSeparator && \count($paths) > 1) {
166 $rows[] = ['', ''];
167 }
168 $firstNamespace = false;
169 foreach ($paths as $path) {
170 $rows[] = [$namespace, $path.\DIRECTORY_SEPARATOR];
171 $namespace = '';
172 }
173 if (\count($paths) > 1) {
174 $rows[] = ['', ''];
175 $prevHasSeparator = true;
176 } else {
177 $prevHasSeparator = false;
178 }
179 }
180 if ($prevHasSeparator) {
181 array_pop($rows);
182 }
183 $io->section('Loader Paths');
184 $io->table(['Namespace', 'Paths'], $rows);
185
186 return 0;
187 }
188
189 private function getLoaderPaths()
190 {
191 if (!($loader = $this->twig->getLoader()) instanceof FilesystemLoader) {
192 return [];
193 }
194
195 $loaderPaths = [];
196 foreach ($loader->getNamespaces() as $namespace) {
197 $paths = array_map(function ($path) {
198 if (null !== $this->projectDir && 0 === strpos($path, $this->projectDir)) {
199 $path = ltrim(substr($path, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
200 }
201
202 return $path;
203 }, $loader->getPaths($namespace));
204
205 if (FilesystemLoader::MAIN_NAMESPACE === $namespace) {
206 $namespace = '(None)';
207 } else {
208 $namespace = '@'.$namespace;
209 }
210
211 $loaderPaths[$namespace] = $paths;
212 }
213
214 return $loaderPaths;
215 }
216
217 private function getMetadata($type, $entity)
218 {
219 if ('globals' === $type) {
220 return $entity;
221 }
222 if ('tests' === $type) {
223 return null;
224 }
225 if ('functions' === $type || 'filters' === $type) {
226 $cb = $entity->getCallable();
227 if (null === $cb) {
228 return null;
229 }
230 if (\is_array($cb)) {
231 if (!method_exists($cb[0], $cb[1])) {
232 return null;
233 }
234 $refl = new \ReflectionMethod($cb[0], $cb[1]);
235 } elseif (\is_object($cb) && method_exists($cb, '__invoke')) {
236 $refl = new \ReflectionMethod($cb, '__invoke');
237 } elseif (\function_exists($cb)) {
238 $refl = new \ReflectionFunction($cb);
239 } elseif (\is_string($cb) && preg_match('{^(.+)::(.+)$}', $cb, $m) && method_exists($m[1], $m[2])) {
240 $refl = new \ReflectionMethod($m[1], $m[2]);
241 } else {
242 throw new \UnexpectedValueException('Unsupported callback type.');
243 }
244
245 $args = $refl->getParameters();
246
247 // filter out context/environment args
248 if ($entity->needsEnvironment()) {
249 array_shift($args);
250 }
251 if ($entity->needsContext()) {
252 array_shift($args);
253 }
254
255 if ('filters' === $type) {
256 // remove the value the filter is applied on
257 array_shift($args);
258 }
259
260 // format args
261 $args = array_map(function ($param) {
262 if ($param->isDefaultValueAvailable()) {
263 return $param->getName().' = '.json_encode($param->getDefaultValue());
264 }
265
266 return $param->getName();
267 }, $args);
268
269 return $args;
270 }
271
272 return null;
273 }
274
275 private function getPrettyMetadata($type, $entity, $decorated)
276 {
277 if ('tests' === $type) {
278 return '';
279 }
280
281 try {
282 $meta = $this->getMetadata($type, $entity);
283 if (null === $meta) {
284 return '(unknown?)';
285 }
286 } catch (\UnexpectedValueException $e) {
287 return sprintf(' <error>%s</error>', $decorated ? OutputFormatter::escape($e->getMessage()) : $e->getMessage());
288 }
289
290 if ('globals' === $type) {
291 if (\is_object($meta)) {
292 return ' = object('.\get_class($meta).')';
293 }
294
295 $description = substr(@json_encode($meta), 0, 50);
296
297 return sprintf(' = %s', $decorated ? OutputFormatter::escape($description) : $description);
298 }
299
300 if ('functions' === $type) {
301 return '('.implode(', ', $meta).')';
302 }
303
304 if ('filters' === $type) {
305 return $meta ? '('.implode(', ', $meta).')' : '';
306 }
307
308 return null;
309 }
310 }
311