From 367a7d88c01209a1473013c3f746b1fecb53aae8 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 19 Dec 2013 01:01:08 +0100 Subject: [PATCH 1/3] [TwigBundle] Add command to list twig functions, filters, globals and tests --- .../Bundle/TwigBundle/Command/DocCommand.php | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 src/Symfony/Bundle/TwigBundle/Command/DocCommand.php diff --git a/src/Symfony/Bundle/TwigBundle/Command/DocCommand.php b/src/Symfony/Bundle/TwigBundle/Command/DocCommand.php new file mode 100644 index 000000000000..675d66098142 --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Command/DocCommand.php @@ -0,0 +1,187 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\TwigBundle\Command; + +use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Lists twig functions, filters, globals and tests present in the current project + * + * @author Jordi Boggiano + */ +class DocCommand extends ContainerAwareCommand +{ + protected function configure() + { + $this + ->setName('twig:doc') + ->setDefinition(array( + new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'), + new InputOption('json', null, InputOption::VALUE_NONE, 'Show complete json formatted information for machine reading'), + )) + ->setDescription('Shows a list of twig functions, filters, globals and tests') + ->setHelp(<<%command.name% command outputs a list of twig functions, +filters, globals and tests. Output can be filtered with an optional argument. + +php %command.full_name% + +The command lists all functions, filters, etc. + +php %command.full_name% date + +The command lists everything that contains the word date. + +php %command.full_name% --json + +The command lists everything in a machine readable json format. +EOF + ) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $twig = $this->getContainer()->get('twig'); + $types = array('functions', 'filters', 'tests', 'globals'); + + if ($input->getOption('json')) { + $data = array(); + foreach ($types as $type) { + foreach ($twig->{'get'.ucfirst($type)}() as $name => $entity) { + $data[$type][$name] = $this->getMetadata($type, $entity); + } + } + $data['tests'] = array_keys($data['tests']); + $output->writeln(json_encode($data)); + + return 0; + } + + $filter = $input->getArgument('filter'); + + foreach ($types as $index => $type) { + $items = array(); + foreach ($twig->{'get'.ucfirst($type)}() as $name => $entity) { + if (!$filter || false !== strpos($name, $filter)) { + $items[$name] = $name . $this->getPrettyMetadata($type, $entity); + } + } + + if (!$items) { + continue; + } + if ($index > 0) { + $output->writeln(''); + } + $output->writeln('' . ucfirst($type) . ''); + ksort($items); + foreach ($items as $item) { + $output->writeln(' '.$item); + } + } + + return 0; + } + + private function getMetadata($type, $entity) + { + if ($type === 'globals') { + return $entity; + } + if ($type === 'tests') { + return; + } + if ($type === 'functions' || $type === 'filters') { + $args = array(); + $cb = $entity->getCallable(); + if (is_null($cb)) { + return; + } + if (is_array($cb)) { + if (!method_exists($cb[0], $cb[1])) { + return; + } + $refl = new \ReflectionMethod($cb[0], $cb[1]); + } elseif (is_object($cb) && is_callable($cb)) { + $refl = new \ReflectionMethod($cb, '__invoke'); + } elseif (function_exists($cb)) { + $refl = new \ReflectionFunction($cb); + } elseif (is_string($cb) && preg_match('{^(.+)::(.+)$}', $cb, $m) && method_exists($m[1], $m[2])) { + $refl = new \ReflectionMethod($m[1], $m[2]); + } else { + throw new \UnexpectedValueException('Unsupported callback type'); + } + + // filter out context/environment args + $args = array_filter($refl->getParameters(), function ($param) use ($entity) { + if ($entity->needsContext() && $param->getName() === 'context') { + return false; + } + + return !$param->getClass() || $param->getClass()->getName() !== 'Twig_Environment'; + }); + + // format args + $args = array_map(function ($param) { + if ($param->isDefaultValueAvailable()) { + return $param->getName() . ' = ' . json_encode($param->getDefaultValue()); + } + + return $param->getName(); + }, $args); + + if ($type === 'filters') { + // remove the value the filter is applied on + array_shift($args); + } + + return $args; + } + } + + private function getPrettyMetadata($type, $entity) + { + if ($type === 'tests') { + return ''; + } + + try { + $meta = $this->getMetadata($type, $entity); + if ($meta === null) { + return '(unknown?)'; + } + } catch (\UnexpectedValueException $e) { + return ' ' . $e->getMessage() . ''; + } + + if ($type === 'globals') { + if (is_object($meta)) { + return ' = object('.get_class($meta).')'; + } + + return ' = '.substr(@json_encode($meta), 0, 50); + } + + if ($type === 'functions') { + return '(' . implode(', ', $meta) . ')'; + } + + if ($type === 'filters') { + return $meta ? '(' . implode(', ', $meta) . ')' : ''; + } + } +} From 02abf2e7bdac1d8eb08c6217f3ceb43d2bb3a015 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Thu, 19 Dec 2013 21:04:44 +0100 Subject: [PATCH 2/3] Add format option --- src/Symfony/Bundle/TwigBundle/Command/DocCommand.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Command/DocCommand.php b/src/Symfony/Bundle/TwigBundle/Command/DocCommand.php index 675d66098142..ac19c3f0f418 100644 --- a/src/Symfony/Bundle/TwigBundle/Command/DocCommand.php +++ b/src/Symfony/Bundle/TwigBundle/Command/DocCommand.php @@ -30,7 +30,7 @@ protected function configure() ->setName('twig:doc') ->setDefinition(array( new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'), - new InputOption('json', null, InputOption::VALUE_NONE, 'Show complete json formatted information for machine reading'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'Output format: text or json', 'text'), )) ->setDescription('Shows a list of twig functions, filters, globals and tests') ->setHelp(<<php %command.full_name% --json +php %command.full_name% --format=json The command lists everything in a machine readable json format. EOF @@ -58,7 +58,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $twig = $this->getContainer()->get('twig'); $types = array('functions', 'filters', 'tests', 'globals'); - if ($input->getOption('json')) { + if ($input->getOption('format') === 'json') { $data = array(); foreach ($types as $type) { foreach ($twig->{'get'.ucfirst($type)}() as $name => $entity) { From 21c66bdf2abca9456a18eeafd0f68bdaa6933eca Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 20 Dec 2013 17:09:11 +0100 Subject: [PATCH 3/3] Rename twig:doc to twig:debug --- .../TwigBundle/Command/{DocCommand.php => DebugCommand.php} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/Symfony/Bundle/TwigBundle/Command/{DocCommand.php => DebugCommand.php} (98%) diff --git a/src/Symfony/Bundle/TwigBundle/Command/DocCommand.php b/src/Symfony/Bundle/TwigBundle/Command/DebugCommand.php similarity index 98% rename from src/Symfony/Bundle/TwigBundle/Command/DocCommand.php rename to src/Symfony/Bundle/TwigBundle/Command/DebugCommand.php index ac19c3f0f418..a2bf79ee726f 100644 --- a/src/Symfony/Bundle/TwigBundle/Command/DocCommand.php +++ b/src/Symfony/Bundle/TwigBundle/Command/DebugCommand.php @@ -22,12 +22,12 @@ * * @author Jordi Boggiano */ -class DocCommand extends ContainerAwareCommand +class DebugCommand extends ContainerAwareCommand { protected function configure() { $this - ->setName('twig:doc') + ->setName('twig:debug') ->setDefinition(array( new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'Output format: text or json', 'text'), pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy