[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
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\Bridge\Twig\Command; 13 14 use Symfony\Component\Console\Command\Command; 15 use Symfony\Component\Console\Formatter\OutputFormatter; 16 use Symfony\Component\Console\Input\InputArgument; 17 use Symfony\Component\Console\Input\InputInterface; 18 use Symfony\Component\Console\Input\InputOption; 19 use Symfony\Component\Console\Output\OutputInterface; 20 use Symfony\Component\Console\Style\SymfonyStyle; 21 use Twig\Environment; 22 use Twig\Loader\FilesystemLoader; 23 24 /** 25 * Lists twig functions, filters, globals and tests present in the current project. 26 * 27 * @author Jordi Boggiano <j.boggiano@seld.be> 28 */ 29 class DebugCommand extends Command 30 { 31 protected static $defaultName = 'debug:twig'; 32 33 private $twig; 34 private $projectDir; 35 36 /** 37 * @param Environment $twig 38 * @param string|null $projectDir 39 */ 40 public function __construct($twig = null, $projectDir = null) 41 { 42 if (!$twig instanceof Environment) { 43 @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); 44 45 parent::__construct($twig); 46 47 return; 48 } 49 50 parent::__construct(); 51 52 $this->twig = $twig; 53 $this->projectDir = $projectDir; 54 } 55 56 public function setTwigEnvironment(Environment $twig) 57 { 58 @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), \E_USER_DEPRECATED); 59 60 $this->twig = $twig; 61 } 62 63 /** 64 * @return Environment $twig 65 */ 66 protected function getTwigEnvironment() 67 { 68 @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), \E_USER_DEPRECATED); 69 70 return $this->twig; 71 } 72 73 protected function configure() 74 { 75 $this 76 ->setDefinition([ 77 new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'), 78 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'), 79 ]) 80 ->setDescription('Shows a list of twig functions, filters, globals and tests') 81 ->setHelp(<<<'EOF' 82 The <info>%command.name%</info> command outputs a list of twig functions, 83 filters, globals and tests. Output can be filtered with an optional argument. 84 85 <info>php %command.full_name%</info> 86 87 The command lists all functions, filters, etc. 88 89 <info>php %command.full_name% date</info> 90 91 The command lists everything that contains the word date. 92 93 <info>php %command.full_name% --format=json</info> 94 95 The command lists everything in a machine readable json format. 96 EOF 97 ) 98 ; 99 } 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |