feature #7887 [FrameworkBundle] adds routing/container descriptors (jfsimon)
This PR was squashed before being merged into the master branch (closes #7887).
Discussion
----------
[FrameworkBundle] adds routing/container descriptors
The goal of this PR is to add descriptors (as in #7454) for routing and container. This will permit add a `--format` option to `router:debug` and `container:debug` commands (with `txt`, `json`, `xml` and `md` formats).
Commits
-------
22f9bc8
[FrameworkBundle] adds routing/container descriptors
This commit is contained in:
commit
31fb8c7cc3
@ -11,12 +11,11 @@
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Command;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\Config\FileLocator;
|
||||
@ -46,7 +45,9 @@ class ContainerDebugCommand extends ContainerAwareCommand
|
||||
new InputOption('tag', null, InputOption::VALUE_REQUIRED, 'Show all services with a specific tag'),
|
||||
new InputOption('tags', null, InputOption::VALUE_NONE, 'Displays tagged services for an application'),
|
||||
new InputOption('parameter', null, InputOption::VALUE_REQUIRED, 'Displays a specific parameter for an application'),
|
||||
new InputOption('parameters', null, InputOption::VALUE_NONE, 'Displays parameters for an application')
|
||||
new InputOption('parameters', null, InputOption::VALUE_NONE, 'Displays parameters for an application'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output description in other formats'),
|
||||
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'),
|
||||
))
|
||||
->setDescription('Displays current services for an application')
|
||||
->setHelp(<<<EOF
|
||||
@ -92,50 +93,37 @@ EOF
|
||||
{
|
||||
$this->validateInput($input);
|
||||
|
||||
$this->containerBuilder = $this->getContainerBuilder();
|
||||
|
||||
if ($input->getOption('parameters')) {
|
||||
$parameters = $this->getContainerBuilder()->getParameterBag()->all();
|
||||
|
||||
// Sort parameters alphabetically
|
||||
ksort($parameters);
|
||||
|
||||
$this->outputParameters($output, $parameters);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$parameter = $input->getOption('parameter');
|
||||
if (null !== $parameter) {
|
||||
$output->write($this->formatParameter($this->getContainerBuilder()->getParameter($parameter)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($input->getOption('tags')) {
|
||||
$this->outputTags($output, $input->getOption('show-private'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$tag = $input->getOption('tag');
|
||||
if (null !== $tag) {
|
||||
$serviceIds = array_keys($this->containerBuilder->findTaggedServiceIds($tag));
|
||||
$object = $this->getContainerBuilder()->getParameterBag();
|
||||
$options = array();
|
||||
} elseif ($parameter = $input->getOption('parameter')) {
|
||||
$object = $this->getContainerBuilder();
|
||||
$options = array('parameter' => $parameter);
|
||||
} elseif ($input->getOption('tags')) {
|
||||
$object = $this->getContainerBuilder();
|
||||
$options = array('group_by' => 'tags', 'show_private' => $input->getOption('show-private'));
|
||||
} elseif ($tag = $input->getOption('tag')) {
|
||||
$object = $this->getContainerBuilder();
|
||||
$options = array('tag' => $tag, 'show_private' => $input->getOption('show-private'));
|
||||
} elseif ($name = $input->getArgument('name')) {
|
||||
$object = $this->getContainerBuilder();
|
||||
$options = array('id' => $name);
|
||||
} else {
|
||||
$serviceIds = $this->containerBuilder->getServiceIds();
|
||||
$object = $this->getContainerBuilder();
|
||||
$options = array('show_private' => $input->getOption('show-private'));
|
||||
}
|
||||
|
||||
// sort so that it reads like an index of services
|
||||
asort($serviceIds);
|
||||
|
||||
$name = $input->getArgument('name');
|
||||
if ($name) {
|
||||
$this->outputService($output, $name);
|
||||
} else {
|
||||
$this->outputServices($output, $serviceIds, $input->getOption('show-private'), $tag);
|
||||
}
|
||||
$helper = new DescriptorHelper();
|
||||
$helper->describe($output, $object, $input->getOption('format'), $input->getOption('raw'), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates input arguments and options.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
protected function validateInput(InputInterface $input)
|
||||
{
|
||||
$options = array('tags', 'tag', 'parameters', 'parameter');
|
||||
@ -155,211 +143,6 @@ EOF
|
||||
}
|
||||
}
|
||||
|
||||
protected function outputServices(OutputInterface $output, $serviceIds, $showPrivate = false, $showTagAttributes = null)
|
||||
{
|
||||
// set the label to specify public or public+private
|
||||
if ($showPrivate) {
|
||||
$label = '<comment>Public</comment> and <comment>private</comment> services';
|
||||
} else {
|
||||
$label = '<comment>Public</comment> services';
|
||||
}
|
||||
if ($showTagAttributes) {
|
||||
$label .= ' with tag <info>'.$showTagAttributes.'</info>';
|
||||
}
|
||||
|
||||
$output->writeln($this->getHelper('formatter')->formatSection('container', $label));
|
||||
|
||||
// loop through to get space needed and filter private services
|
||||
$maxName = 4;
|
||||
$maxScope = 6;
|
||||
$maxTags = array();
|
||||
foreach ($serviceIds as $key => $serviceId) {
|
||||
$definition = $this->resolveServiceDefinition($serviceId);
|
||||
|
||||
if ($definition instanceof Definition) {
|
||||
// filter out private services unless shown explicitly
|
||||
if (!$showPrivate && !$definition->isPublic()) {
|
||||
unset($serviceIds[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen($definition->getScope()) > $maxScope) {
|
||||
$maxScope = strlen($definition->getScope());
|
||||
}
|
||||
|
||||
if (null !== $showTagAttributes) {
|
||||
$tags = $definition->getTag($showTagAttributes);
|
||||
foreach ($tags as $tag) {
|
||||
foreach ($tag as $key => $value) {
|
||||
if (!isset($maxTags[$key])) {
|
||||
$maxTags[$key] = strlen($key);
|
||||
}
|
||||
if (strlen($value) > $maxTags[$key]) {
|
||||
$maxTags[$key] = strlen($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen($serviceId) > $maxName) {
|
||||
$maxName = strlen($serviceId);
|
||||
}
|
||||
}
|
||||
$format = '%-'.$maxName.'s ';
|
||||
$format .= implode("", array_map(function($length) { return "%-{$length}s "; }, $maxTags));
|
||||
$format .= '%-'.$maxScope.'s %s';
|
||||
|
||||
// the title field needs extra space to make up for comment tags
|
||||
$format1 = '%-'.($maxName + 19).'s ';
|
||||
$format1 .= implode("", array_map(function($length) { return '%-'.($length + 19).'s '; }, $maxTags));
|
||||
$format1 .= '%-'.($maxScope + 19).'s %s';
|
||||
|
||||
$tags = array();
|
||||
foreach ($maxTags as $tagName => $length) {
|
||||
$tags[] = '<comment>'.$tagName.'</comment>';
|
||||
}
|
||||
$output->writeln(vsprintf($format1, $this->buildArgumentsArray('<comment>Service Id</comment>', '<comment>Scope</comment>', '<comment>Class Name</comment>', $tags)));
|
||||
|
||||
foreach ($serviceIds as $serviceId) {
|
||||
$definition = $this->resolveServiceDefinition($serviceId);
|
||||
|
||||
if ($definition instanceof Definition) {
|
||||
$lines = array();
|
||||
if (null !== $showTagAttributes) {
|
||||
foreach ($definition->getTag($showTagAttributes) as $key => $tag) {
|
||||
$tagValues = array();
|
||||
foreach (array_keys($maxTags) as $tagName) {
|
||||
$tagValues[] = isset($tag[$tagName]) ? $tag[$tagName] : "";
|
||||
}
|
||||
if (0 === $key) {
|
||||
$lines[] = $this->buildArgumentsArray($serviceId, $definition->getScope(), $definition->getClass(), $tagValues);
|
||||
} else {
|
||||
$lines[] = $this->buildArgumentsArray(' "', '', '', $tagValues);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$lines[] = $this->buildArgumentsArray($serviceId, $definition->getScope(), $definition->getClass());
|
||||
}
|
||||
|
||||
foreach ($lines as $arguments) {
|
||||
$output->writeln(vsprintf($format, $arguments));
|
||||
}
|
||||
} elseif ($definition instanceof Alias) {
|
||||
$alias = $definition;
|
||||
$output->writeln(vsprintf($format, $this->buildArgumentsArray($serviceId, 'n/a', sprintf('<comment>alias for</comment> <info>%s</info>', (string) $alias), count($maxTags) ? array_fill(0, count($maxTags), "") : array())));
|
||||
} else {
|
||||
// we have no information (happens with "service_container")
|
||||
$service = $definition;
|
||||
$output->writeln(vsprintf($format, $this->buildArgumentsArray($serviceId, '', get_class($service), count($maxTags) ? array_fill(0, count($maxTags), "") : array())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function buildArgumentsArray($serviceId, $scope, $className, array $tagAttributes = array())
|
||||
{
|
||||
$arguments = array($serviceId);
|
||||
foreach ($tagAttributes as $tagAttribute) {
|
||||
$arguments[] = $tagAttribute;
|
||||
}
|
||||
$arguments[] = $scope;
|
||||
$arguments[] = $className;
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders detailed service information about one service
|
||||
*/
|
||||
protected function outputService(OutputInterface $output, $serviceId)
|
||||
{
|
||||
$definition = $this->resolveServiceDefinition($serviceId);
|
||||
|
||||
$label = sprintf('Information for service <info>%s</info>', $serviceId);
|
||||
$output->writeln($this->getHelper('formatter')->formatSection('container', $label));
|
||||
$output->writeln('');
|
||||
|
||||
if ($definition instanceof Definition) {
|
||||
$output->writeln(sprintf('<comment>Service Id</comment> %s', $serviceId));
|
||||
$output->writeln(sprintf('<comment>Class</comment> %s', $definition->getClass() ?: "-"));
|
||||
|
||||
$tags = $definition->getTags();
|
||||
if (count($tags)) {
|
||||
$output->writeln('<comment>Tags</comment>');
|
||||
foreach ($tags as $tagName => $tagData) {
|
||||
foreach ($tagData as $singleTagData) {
|
||||
$output->writeln(sprintf(' - %-30s (%s)', $tagName, implode(', ', array_map(function($key, $value) {
|
||||
return sprintf('<info>%s</info>: %s', $key, $value);
|
||||
}, array_keys($singleTagData), array_values($singleTagData)))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$output->writeln('<comment>Tags</comment> -');
|
||||
}
|
||||
|
||||
$output->writeln(sprintf('<comment>Scope</comment> %s', $definition->getScope()));
|
||||
|
||||
$public = $definition->isPublic() ? 'yes' : 'no';
|
||||
$output->writeln(sprintf('<comment>Public</comment> %s', $public));
|
||||
|
||||
$synthetic = $definition->isSynthetic() ? 'yes' : 'no';
|
||||
$output->writeln(sprintf('<comment>Synthetic</comment> %s', $synthetic));
|
||||
|
||||
$file = $definition->getFile() ? $definition->getFile() : '-';
|
||||
$output->writeln(sprintf('<comment>Required File</comment> %s', $file));
|
||||
} elseif ($definition instanceof Alias) {
|
||||
$alias = $definition;
|
||||
$output->writeln(sprintf('This service is an alias for the service <info>%s</info>', (string) $alias));
|
||||
} else {
|
||||
// edge case (but true for "service_container", all we have is the service itself
|
||||
$service = $definition;
|
||||
$output->writeln(sprintf('<comment>Service Id</comment> %s', $serviceId));
|
||||
$output->writeln(sprintf('<comment>Class</comment> %s', get_class($service)));
|
||||
}
|
||||
}
|
||||
|
||||
protected function outputParameters(OutputInterface $output, $parameters)
|
||||
{
|
||||
$output->writeln($this->getHelper('formatter')->formatSection('container', 'List of parameters'));
|
||||
|
||||
$terminalDimensions = $this->getApplication()->getTerminalDimensions();
|
||||
$maxTerminalWidth = $terminalDimensions[0];
|
||||
$maxParameterWidth = 0;
|
||||
$maxValueWidth = 0;
|
||||
|
||||
// Determine max parameter & value length
|
||||
foreach ($parameters as $parameter => $value) {
|
||||
$parameterWidth = strlen($parameter);
|
||||
if ($parameterWidth > $maxParameterWidth) {
|
||||
$maxParameterWidth = $parameterWidth;
|
||||
}
|
||||
|
||||
$valueWith = strlen($this->formatParameter($value));
|
||||
if ($valueWith > $maxValueWidth) {
|
||||
$maxValueWidth = $valueWith;
|
||||
}
|
||||
}
|
||||
|
||||
$maxValueWidth = min($maxValueWidth, $maxTerminalWidth - $maxParameterWidth - 1);
|
||||
|
||||
$formatTitle = '%-'.($maxParameterWidth + 19).'s %-'.($maxValueWidth + 19).'s';
|
||||
$format = '%-'.$maxParameterWidth.'s %-'.$maxValueWidth.'s';
|
||||
|
||||
$output->writeln(sprintf($formatTitle, '<comment>Parameter</comment>', '<comment>Value</comment>'));
|
||||
|
||||
foreach ($parameters as $parameter => $value) {
|
||||
$splits = str_split($this->formatParameter($value), $maxValueWidth);
|
||||
|
||||
foreach ($splits as $index => $split) {
|
||||
if (0 === $index) {
|
||||
$output->writeln(sprintf($format, $parameter, $split));
|
||||
} else {
|
||||
$output->writeln(sprintf($format, ' ', $split));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the ContainerBuilder from the cache.
|
||||
*
|
||||
@ -384,77 +167,4 @@ EOF
|
||||
|
||||
return $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of service IDs, this returns the array of corresponding
|
||||
* Definition and Alias objects that those ids represent.
|
||||
*
|
||||
* @param string $serviceId The service id to resolve
|
||||
*
|
||||
* @return Definition|Alias
|
||||
*/
|
||||
protected function resolveServiceDefinition($serviceId)
|
||||
{
|
||||
if ($this->containerBuilder->hasDefinition($serviceId)) {
|
||||
return $this->containerBuilder->getDefinition($serviceId);
|
||||
}
|
||||
|
||||
// Some service IDs don't have a Definition, they're simply an Alias
|
||||
if ($this->containerBuilder->hasAlias($serviceId)) {
|
||||
return $this->containerBuilder->getAlias($serviceId);
|
||||
}
|
||||
|
||||
// the service has been injected in some special way, just return the service
|
||||
return $this->containerBuilder->get($serviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders list of tagged services grouped by tag
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param Boolean $showPrivate
|
||||
*/
|
||||
protected function outputTags(OutputInterface $output, $showPrivate = false)
|
||||
{
|
||||
$tags = $this->containerBuilder->findTags();
|
||||
asort($tags);
|
||||
|
||||
$label = 'Tagged services';
|
||||
$output->writeln($this->getHelper('formatter')->formatSection('container', $label));
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
$serviceIds = $this->containerBuilder->findTaggedServiceIds($tag);
|
||||
|
||||
foreach ($serviceIds as $serviceId => $attributes) {
|
||||
$definition = $this->resolveServiceDefinition($serviceId);
|
||||
if ($definition instanceof Definition) {
|
||||
if (!$showPrivate && !$definition->isPublic()) {
|
||||
unset($serviceIds[$serviceId]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($serviceIds) === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$output->writeln($this->getHelper('formatter')->formatSection('tag', $tag));
|
||||
|
||||
foreach ($serviceIds as $serviceId => $attributes) {
|
||||
$output->writeln($serviceId);
|
||||
}
|
||||
|
||||
$output->writeln('');
|
||||
}
|
||||
}
|
||||
|
||||
protected function formatParameter($value)
|
||||
{
|
||||
if (is_bool($value) || is_array($value) || (null === $value)) {
|
||||
return json_encode($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Command;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
@ -50,7 +51,9 @@ class RouterDebugCommand extends ContainerAwareCommand
|
||||
->setName('router:debug')
|
||||
->setDefinition(array(
|
||||
new InputArgument('name', InputArgument::OPTIONAL, 'A route name'),
|
||||
new InputOption('show-controllers', null, InputOption::VALUE_NONE, 'Show assigned controllers in overview')
|
||||
new InputOption('show-controllers', null, InputOption::VALUE_NONE, 'Show assigned controllers in overview'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'To output route(s) in other formats'),
|
||||
new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw route(s)'),
|
||||
))
|
||||
->setDescription('Displays current routes for an application')
|
||||
->setHelp(<<<EOF
|
||||
@ -70,151 +73,21 @@ EOF
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$name = $input->getArgument('name');
|
||||
$helper = new DescriptorHelper();
|
||||
|
||||
if ($name) {
|
||||
$this->outputRoute($output, $name);
|
||||
} else {
|
||||
$this->outputRoutes($output, null, $input->getOption('show-controllers'));
|
||||
}
|
||||
}
|
||||
|
||||
protected function outputRoutes(OutputInterface $output, $routes = null, $showControllers = false)
|
||||
{
|
||||
if (null === $routes) {
|
||||
$routes = $this->getContainer()->get('router')->getRouteCollection()->all();
|
||||
}
|
||||
|
||||
$output->writeln($this->getHelper('formatter')->formatSection('router', 'Current routes'));
|
||||
|
||||
$maxName = strlen('name');
|
||||
$maxMethod = strlen('method');
|
||||
$maxScheme = strlen('scheme');
|
||||
$maxHost = strlen('host');
|
||||
$maxPath = strlen('path');
|
||||
|
||||
foreach ($routes as $name => $route) {
|
||||
$method = $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY';
|
||||
$scheme = $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY';
|
||||
$host = '' !== $route->getHost() ? $route->getHost() : 'ANY';
|
||||
$path = $route->getPath();
|
||||
$maxName = max($maxName, strlen($name));
|
||||
$maxMethod = max($maxMethod, strlen($method));
|
||||
$maxScheme = max($maxScheme, strlen($scheme));
|
||||
$maxHost = max($maxHost, strlen($host));
|
||||
$maxPath = max($maxPath, strlen($path));
|
||||
}
|
||||
|
||||
$format = '%-'.$maxName.'s %-'.$maxMethod.'s %-'.$maxScheme.'s %-'.$maxHost.'s %s';
|
||||
$formatHeader = '%-'.($maxName + 19).'s %-'.($maxMethod + 19).'s %-'.($maxScheme + 19).'s %-'.($maxHost + 19).'s %-'.($maxPath + 19).'s';
|
||||
|
||||
if ($showControllers) {
|
||||
$format = str_replace('s %s', 's %-'.$maxPath.'s %s', $format);
|
||||
$formatHeader = $formatHeader . ' %s';
|
||||
}
|
||||
|
||||
if ($showControllers) {
|
||||
$output->writeln(sprintf($formatHeader, '<comment>Name</comment>', '<comment>Method</comment>', '<comment>Scheme</comment>', '<comment>Host</comment>', '<comment>Path</comment>', '<comment>Controller</comment>'));
|
||||
} else {
|
||||
$output->writeln(sprintf($formatHeader, '<comment>Name</comment>', '<comment>Method</comment>', '<comment>Scheme</comment>', '<comment>Host</comment>', '<comment>Path</comment>'));
|
||||
}
|
||||
|
||||
foreach ($routes as $name => $route) {
|
||||
$method = $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY';
|
||||
$scheme = $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY';
|
||||
$host = '' !== $route->getHost() ? $route->getHost() : 'ANY';
|
||||
if ($showControllers) {
|
||||
$defaultData = $route->getDefaults();
|
||||
$controller = $defaultData['_controller'] ? $defaultData['_controller'] : '';
|
||||
if ($controller instanceof \Closure) {
|
||||
$controller = 'Closure';
|
||||
} else {
|
||||
if (is_object($controller)) {
|
||||
$controller = get_class($controller);
|
||||
}
|
||||
}
|
||||
$output->writeln(sprintf($format, $name, $method, $scheme, $host, $route->getPath(), $controller), OutputInterface::OUTPUT_RAW);
|
||||
} else {
|
||||
$output->writeln(sprintf($format, $name, $method, $scheme, $host, $route->getPath()), OutputInterface::OUTPUT_RAW);
|
||||
$route = $this->getContainer()->get('router')->getRouteCollection()->get($name);
|
||||
if (!$route) {
|
||||
throw new \InvalidArgumentException(sprintf('The route "%s" does not exist.', $name));
|
||||
}
|
||||
$helper->describe($output, $route, $input->getOption('format'), $input->getOption('raw'), array('name' => $name));
|
||||
} else {
|
||||
$routes = $this->getContainer()->get('router')->getRouteCollection();
|
||||
$helper->describe($output, $routes, array(
|
||||
'format' => $input->getOption('format'),
|
||||
'raw_text' => $input->getOption('raw'),
|
||||
'show_controllers' => $input->getOption('show-controllers'),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \InvalidArgumentException When route does not exist
|
||||
*/
|
||||
protected function outputRoute(OutputInterface $output, $name)
|
||||
{
|
||||
$route = $this->getContainer()->get('router')->getRouteCollection()->get($name);
|
||||
if (!$route) {
|
||||
throw new \InvalidArgumentException(sprintf('The route "%s" does not exist.', $name));
|
||||
}
|
||||
|
||||
$output->writeln($this->getHelper('formatter')->formatSection('router', sprintf('Route "%s"', $name)));
|
||||
|
||||
$method = $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY';
|
||||
$scheme = $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY';
|
||||
$host = '' !== $route->getHost() ? $route->getHost() : 'ANY';
|
||||
|
||||
$output->write('<comment>Name</comment> ');
|
||||
$output->writeln($name, OutputInterface::OUTPUT_RAW);
|
||||
|
||||
$output->write('<comment>Path</comment> ');
|
||||
$output->writeln($route->getPath(), OutputInterface::OUTPUT_RAW);
|
||||
|
||||
$output->write('<comment>Host</comment> ');
|
||||
$output->writeln($host, OutputInterface::OUTPUT_RAW);
|
||||
|
||||
$output->write('<comment>Scheme</comment> ');
|
||||
$output->writeln($scheme, OutputInterface::OUTPUT_RAW);
|
||||
|
||||
$output->write('<comment>Method</comment> ');
|
||||
$output->writeln($method, OutputInterface::OUTPUT_RAW);
|
||||
|
||||
$output->write('<comment>Class</comment> ');
|
||||
$output->writeln(get_class($route), OutputInterface::OUTPUT_RAW);
|
||||
|
||||
$output->write('<comment>Defaults</comment> ');
|
||||
$output->writeln($this->formatConfigs($route->getDefaults()), OutputInterface::OUTPUT_RAW);
|
||||
|
||||
$output->write('<comment>Requirements</comment> ');
|
||||
// we do not want to show the schemes and methods again that are also in the requirements for BC
|
||||
$requirements = $route->getRequirements();
|
||||
unset($requirements['_scheme'], $requirements['_method']);
|
||||
$output->writeln($this->formatConfigs($requirements) ?: 'NO CUSTOM', OutputInterface::OUTPUT_RAW);
|
||||
|
||||
$output->write('<comment>Options</comment> ');
|
||||
$output->writeln($this->formatConfigs($route->getOptions()), OutputInterface::OUTPUT_RAW);
|
||||
|
||||
$output->write('<comment>Path-Regex</comment> ');
|
||||
$output->writeln($route->compile()->getRegex(), OutputInterface::OUTPUT_RAW);
|
||||
|
||||
if (null !== $route->compile()->getHostRegex()) {
|
||||
$output->write('<comment>Host-Regex</comment> ');
|
||||
$output->writeln($route->compile()->getHostRegex(), OutputInterface::OUTPUT_RAW);
|
||||
}
|
||||
}
|
||||
|
||||
protected function formatValue($value)
|
||||
{
|
||||
if (is_object($value)) {
|
||||
return sprintf('object(%s)', get_class($value));
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return preg_replace("/\n\s*/s", '', var_export($value, true));
|
||||
}
|
||||
|
||||
private function formatConfigs(array $array)
|
||||
{
|
||||
$string = '';
|
||||
ksort($array);
|
||||
foreach ($array as $name => $value) {
|
||||
$string .= ($string ? "\n".str_repeat(' ', 13) : '').$name.': '.$this->formatValue($value);
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,273 @@
|
||||
<?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 Symfony\Bundle\FrameworkBundle\Console\Descriptor;
|
||||
|
||||
use Symfony\Component\Console\Descriptor\DescriptorInterface;
|
||||
use Symfony\Component\Console\Helper\TableHelper;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
abstract class Descriptor implements DescriptorInterface
|
||||
{
|
||||
/**
|
||||
* @var OutputInterface
|
||||
*/
|
||||
private $output;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function describe(OutputInterface $output, $object, array $options = array())
|
||||
{
|
||||
$this->output = $output;
|
||||
|
||||
switch (true) {
|
||||
case $object instanceof RouteCollection:
|
||||
$this->describeRouteCollection($object, $options);
|
||||
break;
|
||||
case $object instanceof Route:
|
||||
$this->describeRoute($object, $options);
|
||||
break;
|
||||
case $object instanceof ParameterBag:
|
||||
$this->describeContainerParameters($object, $options);
|
||||
break;
|
||||
case $object instanceof ContainerBuilder && isset($options['group_by']) && 'tags' === $options['group_by']:
|
||||
$this->describeContainerTags($object, $options);
|
||||
break;
|
||||
case $object instanceof ContainerBuilder && isset($options['id']):
|
||||
$this->describeContainerService($this->resolveServiceDefinition($object, $options['id']), $options);
|
||||
break;
|
||||
case $object instanceof ContainerBuilder && isset($options['parameter']):
|
||||
$this->formatParameter($object->getParameter($options['parameter']));
|
||||
break;
|
||||
case $object instanceof ContainerBuilder:
|
||||
$this->describeContainerServices($object, $options);
|
||||
break;
|
||||
case $object instanceof Definition:
|
||||
$this->describeContainerDefinition($object, $options);
|
||||
break;
|
||||
case $object instanceof Alias:
|
||||
$this->describeContainerAlias($object, $options);
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes content to output.
|
||||
*
|
||||
* @param string $content
|
||||
* @param boolean $decorated
|
||||
*/
|
||||
protected function write($content, $decorated = false)
|
||||
{
|
||||
$this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes content to output.
|
||||
*
|
||||
* @param TableHelper $table
|
||||
* @param boolean $decorated
|
||||
*/
|
||||
protected function renderTable(TableHelper $table, $decorated = false)
|
||||
{
|
||||
if (!$decorated) {
|
||||
$table->setCellRowFormat('%s');
|
||||
$table->setCellHeaderFormat('%s');
|
||||
}
|
||||
|
||||
$table->render($this->output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes an InputArgument instance.
|
||||
*
|
||||
* @param RouteCollection $routes
|
||||
* @param array $options
|
||||
*/
|
||||
abstract protected function describeRouteCollection(RouteCollection $routes, array $options = array());
|
||||
|
||||
/**
|
||||
* Describes an InputOption instance.
|
||||
*
|
||||
* @param Route $route
|
||||
* @param array $options
|
||||
*/
|
||||
abstract protected function describeRoute(Route $route, array $options = array());
|
||||
|
||||
/**
|
||||
* Describes container parameters.
|
||||
*
|
||||
* @param ParameterBag $parameters
|
||||
* @param array $options
|
||||
*/
|
||||
abstract protected function describeContainerParameters(ParameterBag $parameters, array $options = array());
|
||||
|
||||
/**
|
||||
* Describes container tags.
|
||||
*
|
||||
* @param ContainerBuilder $builder
|
||||
* @param array $options
|
||||
*/
|
||||
abstract protected function describeContainerTags(ContainerBuilder $builder, array $options = array());
|
||||
|
||||
/**
|
||||
* Describes a container service by its name.
|
||||
*
|
||||
* Common options are:
|
||||
* * name: name of described service
|
||||
*
|
||||
* @param Definition|Alias|object $service
|
||||
* @param array $options
|
||||
*/
|
||||
abstract protected function describeContainerService($service, array $options = array());
|
||||
|
||||
/**
|
||||
* Describes container services.
|
||||
*
|
||||
* Common options are:
|
||||
* * tag: filters described services by given tag
|
||||
*
|
||||
* @param ContainerBuilder $builder
|
||||
* @param array $options
|
||||
*/
|
||||
abstract protected function describeContainerServices(ContainerBuilder $builder, array $options = array());
|
||||
|
||||
/**
|
||||
* Describes a service definition.
|
||||
*
|
||||
* @param Definition $definition
|
||||
* @param array $options
|
||||
*/
|
||||
abstract protected function describeContainerDefinition(Definition $definition, array $options = array());
|
||||
|
||||
/**
|
||||
* Describes a service alias.
|
||||
*
|
||||
* @param Alias $alias
|
||||
* @param array $options
|
||||
*/
|
||||
abstract protected function describeContainerAlias(Alias $alias, array $options = array());
|
||||
|
||||
/**
|
||||
* Formats a value as string.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatValue($value)
|
||||
{
|
||||
if (is_object($value)) {
|
||||
return sprintf('object(%s)', get_class($value));
|
||||
}
|
||||
|
||||
if (is_string($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return preg_replace("/\n\s*/s", '', var_export($value, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a parameter.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatParameter($value)
|
||||
{
|
||||
if (is_bool($value) || is_array($value) || (null === $value)) {
|
||||
return json_encode($value);
|
||||
}
|
||||
|
||||
return (string) $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerBuilder $builder
|
||||
* @param string $serviceId
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function resolveServiceDefinition(ContainerBuilder $builder, $serviceId)
|
||||
{
|
||||
if ($builder->hasDefinition($serviceId)) {
|
||||
return $builder->getDefinition($serviceId);
|
||||
}
|
||||
|
||||
// Some service IDs don't have a Definition, they're simply an Alias
|
||||
if ($builder->hasAlias($serviceId)) {
|
||||
return $builder->getAlias($serviceId);
|
||||
}
|
||||
|
||||
// the service has been injected in some special way, just return the service
|
||||
return $builder->get($serviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerBuilder $builder
|
||||
* @param boolean $showPrivate
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function findDefinitionsByTag(ContainerBuilder $builder, $showPrivate)
|
||||
{
|
||||
$definitions = array();
|
||||
$tags = $builder->findTags();
|
||||
asort($tags);
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
foreach ($builder->findTaggedServiceIds($tag) as $serviceId => $attributes) {
|
||||
$definition = $this->resolveServiceDefinition($builder, $serviceId);
|
||||
|
||||
if (!$definition instanceof Definition || !$showPrivate && !$definition->isPublic()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($definitions[$tag])) {
|
||||
$definitions[$tag] = array();
|
||||
}
|
||||
|
||||
$definitions[$tag][$serviceId] = $definition;
|
||||
}
|
||||
}
|
||||
|
||||
return $definitions;
|
||||
}
|
||||
|
||||
protected function sortParameters(ParameterBag $parameters)
|
||||
{
|
||||
$parameters = $parameters->all();
|
||||
ksort($parameters);
|
||||
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
protected function sortServiceIds(array $serviceIds)
|
||||
{
|
||||
asort($serviceIds);
|
||||
|
||||
return $serviceIds;
|
||||
}
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
class JsonDescriptor extends Descriptor
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeRouteCollection(RouteCollection $routes, array $options = array())
|
||||
{
|
||||
$data = array();
|
||||
foreach ($routes->all() as $name => $route) {
|
||||
$data[$name] = $this->getRouteData($route);
|
||||
}
|
||||
|
||||
$this->writeData($data, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeRoute(Route $route, array $options = array())
|
||||
{
|
||||
$this->writeData($this->getRouteData($route), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerParameters(ParameterBag $parameters, array $options = array())
|
||||
{
|
||||
$this->writeData($this->sortParameters($parameters), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerTags(ContainerBuilder $builder, array $options = array())
|
||||
{
|
||||
$showPrivate = isset($options['show_private']) && $options['show_private'];
|
||||
$data = array();
|
||||
|
||||
foreach ($this->findDefinitionsByTag($builder, $showPrivate) as $tag => $definitions) {
|
||||
$data[$tag] = array();
|
||||
foreach ($definitions as $definition) {
|
||||
$data[$tag][] = $this->getContainerDefinitionData($definition, true);
|
||||
}
|
||||
}
|
||||
|
||||
$this->writeData($data, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerService($service, array $options = array())
|
||||
{
|
||||
if (!isset($options['id'])) {
|
||||
throw new \InvalidArgumentException('An "id" option must be provided.');
|
||||
}
|
||||
|
||||
if ($service instanceof Alias) {
|
||||
$this->writeData($this->getContainerAliasData($service), $options);
|
||||
} elseif ($service instanceof Definition) {
|
||||
$this->writeData($this->getContainerDefinitionData($service), $options);
|
||||
} else {
|
||||
$this->writeData(get_class($service), $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerServices(ContainerBuilder $builder, array $options = array())
|
||||
{
|
||||
$serviceIds = isset($options['tag']) && $options['tag'] ? array_keys($builder->findTaggedServiceIds($options['tag'])) : $builder->getServiceIds();
|
||||
$showPrivate = isset($options['show_private']) && $options['show_private'];
|
||||
$data = array('definitions' => array(), 'aliases' => array(), 'services' => array());
|
||||
|
||||
foreach ($this->sortServiceIds($serviceIds) as $serviceId) {
|
||||
$service = $this->resolveServiceDefinition($builder, $serviceId);
|
||||
|
||||
if ($service instanceof Alias) {
|
||||
$data['aliases'][$serviceId] = $this->getContainerAliasData($service);
|
||||
} elseif ($service instanceof Definition) {
|
||||
if (($showPrivate || $service->isPublic())) {
|
||||
$data['definitions'][$serviceId] = $this->getContainerDefinitionData($service);
|
||||
}
|
||||
} else {
|
||||
$data['services'][$serviceId] = get_class($service);
|
||||
}
|
||||
}
|
||||
|
||||
$this->writeData($data, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerDefinition(Definition $definition, array $options = array())
|
||||
{
|
||||
$this->writeData($this->getContainerDefinitionData($definition, isset($options['omit_tags']) && $options['omit_tags']), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerAlias(Alias $alias, array $options = array())
|
||||
{
|
||||
$this->writeData($this->getContainerAliasData($alias), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes data as json.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $options
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
private function writeData(array $data, array $options)
|
||||
{
|
||||
$this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Route $route
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getRouteData(Route $route)
|
||||
{
|
||||
$requirements = $route->getRequirements();
|
||||
unset($requirements['_scheme'], $requirements['_method']);
|
||||
|
||||
return array(
|
||||
'path' => $route->getPath(),
|
||||
'host' => '' !== $route->getHost() ? $route->getHost() : 'ANY',
|
||||
'scheme' => $route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY',
|
||||
'method' => $route->getMethods() ? implode('|', $route->getMethods()) : 'ANY',
|
||||
'class' => get_class($route),
|
||||
'defaults' => $route->getDefaults(),
|
||||
'requirements' => $requirements ?: 'NO CUSTOM',
|
||||
'options' => $route->getOptions(),
|
||||
'pathRegex' => $route->compile()->getRegex(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Definition $definition
|
||||
* @param boolean $omitTags
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getContainerDefinitionData(Definition $definition, $omitTags = false)
|
||||
{
|
||||
$data = array(
|
||||
'class' => (string) $definition->getClass(),
|
||||
'scope' => $definition->getScope(),
|
||||
'public' => $definition->isPublic(),
|
||||
'synthetic' => $definition->isSynthetic(),
|
||||
'file' => $definition->getFile(),
|
||||
);
|
||||
|
||||
if (!$omitTags) {
|
||||
$data['tags'] = array();
|
||||
if (count($definition->getTags())) {
|
||||
foreach ($definition->getTags() as $tagName => $tagData) {
|
||||
foreach ($tagData as $parameters) {
|
||||
$data['tags'][] = array('name' => $tagName, 'parameters' => $parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Alias $alias
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getContainerAliasData(Alias $alias)
|
||||
{
|
||||
return array(
|
||||
'service' => (string) $alias,
|
||||
'public' => $alias->isPublic(),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
class MarkdownDescriptor extends Descriptor
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeRouteCollection(RouteCollection $routes, array $options = array())
|
||||
{
|
||||
$first = true;
|
||||
foreach ($routes->all() as $name => $route) {
|
||||
if ($first) {
|
||||
$first = false;
|
||||
} else {
|
||||
$this->write("\n\n");
|
||||
}
|
||||
$this->describeRoute($route, array('name' => $name));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeRoute(Route $route, array $options = array())
|
||||
{
|
||||
$requirements = $route->getRequirements();
|
||||
unset($requirements['_scheme'], $requirements['_method']);
|
||||
|
||||
$output = '- Path: '.$route->getPath()
|
||||
."\n".'- Host: '.('' !== $route->getHost() ? $route->getHost() : 'ANY')
|
||||
."\n".'- Scheme: '.($route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY')
|
||||
."\n".'- Method: '.($route->getMethods() ? implode('|', $route->getMethods()) : 'ANY')
|
||||
."\n".'- Class: '.get_class($route)
|
||||
."\n".'- Defaults: '.$this->formatRouterConfig($route->getDefaults())
|
||||
."\n".'- Requirements: '.$this->formatRouterConfig($requirements) ?: 'NONE'
|
||||
."\n".'- Options: '.$this->formatRouterConfig($route->getOptions())
|
||||
."\n".'- Path-Regex: '.$route->compile()->getRegex();
|
||||
|
||||
$this->write(isset($options['name'])
|
||||
? $options['name']."\n".str_repeat('-', strlen($options['name']))."\n".$output
|
||||
: $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerParameters(ParameterBag $parameters, array $options = array())
|
||||
{
|
||||
$this->write("Container parameters\n====================\n");
|
||||
foreach ($this->sortParameters($parameters) as $key => $value) {
|
||||
$this->write(sprintf("\n- `%s`: `%s`", $key, $this->formatParameter($value)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerTags(ContainerBuilder $builder, array $options = array())
|
||||
{
|
||||
$showPrivate = isset($options['show_private']) && $options['show_private'];
|
||||
$this->write("Container tags\n==============");
|
||||
|
||||
foreach ($this->findDefinitionsByTag($builder, $showPrivate) as $tag => $definitions) {
|
||||
$this->write("\n\n".$tag."\n".str_repeat('-', strlen($tag)));
|
||||
foreach ($definitions as $serviceId => $definition) {
|
||||
$this->write("\n\n");
|
||||
$this->describeContainerDefinition($definition, array('omit_tags' => true, 'id' => $serviceId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerService($service, array $options = array())
|
||||
{
|
||||
if (!isset($options['id'])) {
|
||||
throw new \InvalidArgumentException('An "id" option must be provided.');
|
||||
}
|
||||
|
||||
$childOptions = array('id' => $options['id'], 'as_array' => true);
|
||||
|
||||
if ($service instanceof Alias) {
|
||||
$this->describeContainerAlias($service, $childOptions);
|
||||
} elseif ($service instanceof Definition) {
|
||||
$this->describeContainerDefinition($service, $childOptions);
|
||||
} else {
|
||||
$this->write(sprintf("**`%s`:** `%s`", $options['id'], get_class($service)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerServices(ContainerBuilder $builder, array $options = array())
|
||||
{
|
||||
$showPrivate = isset($options['show_private']) && $options['show_private'];
|
||||
|
||||
$title = $showPrivate ? 'Public and private services' : 'Public services';
|
||||
if (isset($options['tag'])) {
|
||||
$title .= ' with tag `'.$options['tag'].'`';
|
||||
}
|
||||
$this->write($title."\n".str_repeat('=', strlen($title)));
|
||||
|
||||
$serviceIds = isset($options['tag']) && $options['tag'] ? array_keys($builder->findTaggedServiceIds($options['tag'])) : $builder->getServiceIds();
|
||||
$showPrivate = isset($options['show_private']) && $options['show_private'];
|
||||
$services = array('definitions' => array(), 'aliases' => array(), 'services' => array());
|
||||
|
||||
foreach ($this->sortServiceIds($serviceIds) as $serviceId) {
|
||||
$service = $this->resolveServiceDefinition($builder, $serviceId);
|
||||
|
||||
if ($service instanceof Alias) {
|
||||
$services['aliases'][$serviceId] = $service;
|
||||
} elseif ($service instanceof Definition) {
|
||||
if (($showPrivate || $service->isPublic())) {
|
||||
$services['definitions'][$serviceId] = $service;
|
||||
}
|
||||
} else {
|
||||
$services['services'][$serviceId] = $service;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($services['definitions'])) {
|
||||
$this->write("\n\nDefinitions\n-----------");
|
||||
foreach ($services['definitions'] as $id => $service) {
|
||||
$this->write("\n\n");
|
||||
$this->describeContainerDefinition($service, array('id' => $id));
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($services['aliases'])) {
|
||||
$this->write("\n\nAliases\n-------");
|
||||
foreach ($services['aliases'] as $id => $service) {
|
||||
$this->write("\n\n");
|
||||
$this->describeContainerAlias($service, array('id' => $id));
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($services['services'])) {
|
||||
$this->write("\n\nServices\n--------\n");
|
||||
foreach ($services['services'] as $id => $service) {
|
||||
$this->write("\n");
|
||||
$this->write(sprintf('- `%s`: `%s`', $id, get_class($service)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerDefinition(Definition $definition, array $options = array())
|
||||
{
|
||||
$output = '- Class: `'.$definition->getClass().'`'
|
||||
."\n".'- Scope: `'.$definition->getScope().'`'
|
||||
."\n".'- Public: '.($definition->isPublic() ? 'yes' : 'no')
|
||||
."\n".'- Synthetic: '.($definition->isSynthetic() ? 'yes' : 'no');
|
||||
|
||||
if ($definition->getFile()) {
|
||||
$output .= "\n".'- File: `'.$definition->getFile().'`';
|
||||
}
|
||||
|
||||
if (!(isset($options['omit_tags']) && $options['omit_tags'])) {
|
||||
foreach ($definition->getTags() as $tagName => $tagData) {
|
||||
foreach ($tagData as $parameters) {
|
||||
$output .= "\n".'- Tag: `'.$tagName.'`';
|
||||
foreach ($parameters as $name => $value) {
|
||||
$output .= "\n".' - '.ucfirst($name).': '.$value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->write(isset($options['id']) ? sprintf("**`%s`:**\n%s", $options['id'], $output) : $output);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerAlias(Alias $alias, array $options = array())
|
||||
{
|
||||
$output = '- Service: `'.$alias.'`'
|
||||
."\n".'- Public: '.($alias->isPublic() ? 'yes' : 'no');
|
||||
|
||||
$this->write(isset($options['id']) ? sprintf("**`%s`:**\n%s", $options['id'], $output) : $output);
|
||||
}
|
||||
|
||||
private function formatRouterConfig(array $array)
|
||||
{
|
||||
if (!count($array)) {
|
||||
return 'NONE';
|
||||
}
|
||||
|
||||
$string = '';
|
||||
ksort($array);
|
||||
foreach ($array as $name => $value) {
|
||||
$string .= "\n".' - `'.$name.'`: '.$this->formatValue($value);
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
@ -0,0 +1,308 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor;
|
||||
|
||||
use Symfony\Component\Console\Helper\TableHelper;
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
class TextDescriptor extends Descriptor
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeRouteCollection(RouteCollection $routes, array $options = array())
|
||||
{
|
||||
$showControllers = isset($options['show_controllers']) && $options['show_controllers'];
|
||||
$headers = array('Name', 'Method', 'Scheme', 'Host', 'Path');
|
||||
$table = new TableHelper();
|
||||
$table->setHeaders($showControllers ? array_merge($headers, array('Controller')) : $headers);
|
||||
|
||||
foreach ($routes->all() as $name => $route) {
|
||||
$row = array(
|
||||
$name,
|
||||
$route->getMethods() ? implode('|', $route->getMethods()) : 'ANY',
|
||||
$route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY',
|
||||
'' !== $route->getHost() ? $route->getHost() : 'ANY',
|
||||
$route->getPath(),
|
||||
);
|
||||
|
||||
if ($showControllers) {
|
||||
$defaultData = $route->getDefaults();
|
||||
$controller = $defaultData['_controller'] ? $defaultData['_controller'] : '';
|
||||
if ($controller instanceof \Closure) {
|
||||
$controller = 'Closure';
|
||||
} else {
|
||||
if (is_object($controller)) {
|
||||
$controller = get_class($controller);
|
||||
}
|
||||
}
|
||||
$row[] = $controller;
|
||||
}
|
||||
|
||||
$table->addRow($row);
|
||||
}
|
||||
|
||||
$this->writeText($this->formatSection('router', 'Current routes')."\n", $options);
|
||||
$this->renderTable($table, !(isset($options['raw_output']) && $options['raw_output']));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeRoute(Route $route, array $options = array())
|
||||
{
|
||||
$requirements = $route->getRequirements();
|
||||
unset($requirements['_scheme'], $requirements['_method']);
|
||||
|
||||
// fixme: values were originally written as raw
|
||||
$description = array(
|
||||
'<comment>Path</comment> '.$route->getPath(),
|
||||
'<comment>Host</comment> '.('' !== $route->getHost() ? $route->getHost() : 'ANY'),
|
||||
'<comment>Scheme</comment> '.($route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY'),
|
||||
'<comment>Method</comment> '.($route->getMethods() ? implode('|', $route->getMethods()) : 'ANY'),
|
||||
'<comment>Class</comment> '.get_class($route),
|
||||
'<comment>Defaults</comment> '.$this->formatRouterConfig($route->getDefaults()),
|
||||
'<comment>Requirements</comment> '.$this->formatRouterConfig($requirements) ?: 'NO CUSTOM',
|
||||
'<comment>Options</comment> '.$this->formatRouterConfig($route->getOptions()),
|
||||
'<comment>Path-Regex</comment> '.$route->compile()->getRegex(),
|
||||
);
|
||||
|
||||
if (isset($options['name'])) {
|
||||
array_unshift($description, '<comment>Name</comment> '.$options['name']);
|
||||
array_unshift($description, $this->formatSection('router', sprintf('Route "%s"', $options['name'])));
|
||||
}
|
||||
|
||||
if (null !== $route->compile()->getHostRegex()) {
|
||||
$description[] = '<comment>Host-Regex</comment> '.$route->compile()->getHostRegex();
|
||||
}
|
||||
|
||||
$this->writeText(implode("\n", $description), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerParameters(ParameterBag $parameters, array $options = array())
|
||||
{
|
||||
$table = new TableHelper();
|
||||
$table->setHeaders(array('Parameter', 'Value'));
|
||||
|
||||
foreach ($this->sortParameters($parameters) as $parameter => $value) {
|
||||
$table->addRow(array($parameter, $this->formatParameter($value)));
|
||||
}
|
||||
|
||||
$this->writeText($this->formatSection('container', 'List of parameters')."\n", $options);
|
||||
$this->renderTable($table, !(isset($options['raw_output']) && $options['raw_output']));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerTags(ContainerBuilder $builder, array $options = array())
|
||||
{
|
||||
$showPrivate = isset($options['show_private']) && $options['show_private'];
|
||||
$description = array($this->formatSection('container', 'Tagged services'));
|
||||
|
||||
foreach ($this->findDefinitionsByTag($builder, $showPrivate) as $tag => $definitions) {
|
||||
$description[] = $this->formatSection('tag', $tag);
|
||||
$description = array_merge($description, array_keys($definitions));
|
||||
$description[] = '';
|
||||
}
|
||||
|
||||
$this->writeText(implode("\n", $description), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerService($service, array $options = array())
|
||||
{
|
||||
if (!isset($options['id'])) {
|
||||
throw new \InvalidArgumentException('An "id" option must be provided.');
|
||||
}
|
||||
|
||||
if ($service instanceof Alias) {
|
||||
$this->describeContainerAlias($service, $options);
|
||||
} elseif ($service instanceof Definition) {
|
||||
$this->describeContainerDefinition($service, $options);
|
||||
} else {
|
||||
$description = $this->formatSection('container', sprintf('Information for service <info>%s</info>', $options['id']))
|
||||
."\n".sprintf('<comment>Service Id</comment> %s', isset($options['id']) ? $options['id'] : '-')
|
||||
."\n".sprintf('<comment>Class</comment> %s', get_class($service));
|
||||
|
||||
$this->writeText($description, $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerServices(ContainerBuilder $builder, array $options = array())
|
||||
{
|
||||
$showPrivate = isset($options['show_private']) && $options['show_private'];
|
||||
$showTag = isset($options['tag']) ? $options['tag'] : null;
|
||||
|
||||
if ($showPrivate) {
|
||||
$label = '<comment>Public</comment> and <comment>private</comment> services';
|
||||
} else {
|
||||
$label = '<comment>Public</comment> services';
|
||||
}
|
||||
|
||||
if ($showTag) {
|
||||
$label .= ' with tag <info>'.$options['tag'].'</info>';
|
||||
}
|
||||
|
||||
$this->writeText($this->formatSection('container', $label)."\n", $options);
|
||||
|
||||
$serviceIds = isset($options['tag']) && $options['tag'] ? array_keys($builder->findTaggedServiceIds($options['tag'])) : $builder->getServiceIds();
|
||||
$maxTags = array();
|
||||
|
||||
foreach ($serviceIds as $key => $serviceId) {
|
||||
$definition = $this->resolveServiceDefinition($builder, $serviceId);
|
||||
if ($definition instanceof Definition) {
|
||||
// filter out private services unless shown explicitly
|
||||
if (!$showPrivate && !$definition->isPublic()) {
|
||||
unset($serviceIds[$key]);
|
||||
continue;
|
||||
}
|
||||
if ($showTag) {
|
||||
$tags = $definition->getTag($showTag);
|
||||
foreach ($tags as $tag) {
|
||||
foreach ($tag as $key => $value) {
|
||||
if (!isset($maxTags[$key])) {
|
||||
$maxTags[$key] = strlen($key);
|
||||
}
|
||||
if (strlen($value) > $maxTags[$key]) {
|
||||
$maxTags[$key] = strlen($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tagsCount = count($maxTags);
|
||||
$tagsNames = array_keys($maxTags);
|
||||
|
||||
$table = new TableHelper();
|
||||
$table->setHeaders(array_merge(array('Service ID'), $tagsNames, array('Scope', 'Class name')));
|
||||
|
||||
foreach ($this->sortServiceIds($serviceIds) as $serviceId) {
|
||||
$definition = $this->resolveServiceDefinition($builder, $serviceId);
|
||||
if ($definition instanceof Definition) {
|
||||
if ($showTag) {
|
||||
foreach ($definition->getTag($showTag) as $key => $tag) {
|
||||
$tagValues = array();
|
||||
foreach ($tagsNames as $tagName) {
|
||||
$tagValues[] = isset($tag[$tagName]) ? $tag[$tagName] : "";
|
||||
}
|
||||
if (0 === $key) {
|
||||
$table->addRow(array_merge(array($serviceId), $tagValues, array($definition->getScope(), $definition->getClass())));
|
||||
} else {
|
||||
$table->addRow(array_merge(array(' "'), $tagValues, array('', '')));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$table->addRow(array($serviceId, $definition->getScope(), $definition->getClass()));
|
||||
}
|
||||
} elseif ($definition instanceof Alias) {
|
||||
$alias = $definition;
|
||||
$table->addRow(array_merge(array($serviceId, 'n/a', sprintf('alias for "%s"', $alias)), $tagsCount ? array_fill(0, $tagsCount, "") : array()));
|
||||
} else {
|
||||
// we have no information (happens with "service_container")
|
||||
$table->addRow(array_merge(array($serviceId, '', get_class($definition)), $tagsCount ? array_fill(0, $tagsCount, "") : array()));
|
||||
}
|
||||
}
|
||||
|
||||
$this->renderTable($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerDefinition(Definition $definition, array $options = array())
|
||||
{
|
||||
$description = isset($options['id'])
|
||||
? array($this->formatSection('container', sprintf('Information for service <info>%s</info>', $options['id'])))
|
||||
: array();
|
||||
|
||||
$description[] = sprintf('<comment>Service Id</comment> %s', isset($options['id']) ? $options['id'] : '-');
|
||||
$description[] = sprintf('<comment>Class</comment> %s', $definition->getClass() ?: "-");
|
||||
|
||||
$tags = $definition->getTags();
|
||||
if (count($tags)) {
|
||||
$description[] = '<comment>Tags</comment>';
|
||||
foreach ($tags as $tagName => $tagData) {
|
||||
foreach ($tagData as $parameters) {
|
||||
$description[] = sprintf(' - %-30s (%s)', $tagName, implode(', ', array_map(function($key, $value) {
|
||||
return sprintf('<info>%s</info>: %s', $key, $value);
|
||||
}, array_keys($parameters), array_values($parameters))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$description[] = '<comment>Tags</comment> -';
|
||||
}
|
||||
|
||||
$description[] = sprintf('<comment>Scope</comment> %s', $definition->getScope());
|
||||
$description[] = sprintf('<comment>Public</comment> %s', $definition->isPublic() ? 'yes' : 'no');
|
||||
$description[] = sprintf('<comment>Synthetic</comment> %s', $definition->isSynthetic() ? 'yes' : 'no');
|
||||
$description[] = sprintf('<comment>Required File</comment> %s', $definition->getFile() ? $definition->getFile() : '-');
|
||||
|
||||
$this->writeText(implode("\n", $description), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerAlias(Alias $alias, array $options = array())
|
||||
{
|
||||
$this->writeText(sprintf('This service is an alias for the service <info>%s</info>', (string) $alias), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function formatRouterConfig(array $array)
|
||||
{
|
||||
$string = '';
|
||||
ksort($array);
|
||||
foreach ($array as $name => $value) {
|
||||
$string .= ($string ? "\n".str_repeat(' ', 13) : '').$name.': '.$this->formatValue($value);
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $section
|
||||
* @param string $message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function formatSection($section, $message)
|
||||
{
|
||||
return sprintf('<info>[%s]</info> %s', $section, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* @param array $options
|
||||
*/
|
||||
private function writeText($content, array $options = array())
|
||||
{
|
||||
$this->write(
|
||||
isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
|
||||
isset($options['raw_output']) ? !$options['raw_output'] : true
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,341 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
class XmlDescriptor extends Descriptor
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeRouteCollection(RouteCollection $routes, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getRouteCollectionDocument($routes));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeRoute(Route $route, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getRouteDocument($route, isset($options['name']) ? $options['name'] : null));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerParameters(ParameterBag $parameters, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getContainerParametersDocument($parameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerTags(ContainerBuilder $builder, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getContainerTagsDocument($builder, isset($options['show_private']) && $options['show_private']));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerService($service, array $options = array())
|
||||
{
|
||||
if (!isset($options['id'])) {
|
||||
throw new \InvalidArgumentException('An "id" option must be provided.');
|
||||
}
|
||||
|
||||
$this->writeDocument($this->getContainerServiceDocument($service, $options['id']));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerServices(ContainerBuilder $builder, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getContainerServicesDocument($builder, isset($options['tag']) ? $options['tag'] : null, isset($options['show_private']) && $options['show_private']));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerDefinition(Definition $definition, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getContainerDefinitionDocument($definition, isset($options['id']) ? $options['id'] : null, isset($options['omit_tags']) && $options['omit_tags']));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function describeContainerAlias(Alias $alias, array $options = array())
|
||||
{
|
||||
$this->writeDocument($this->getContainerAliasDocument($alias, isset($options['id']) ? $options['id'] : null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes DOM document.
|
||||
*
|
||||
* @param \DOMDocument $dom
|
||||
*
|
||||
* @return \DOMDocument|string
|
||||
*/
|
||||
private function writeDocument(\DOMDocument $dom)
|
||||
{
|
||||
$dom->formatOutput = true;
|
||||
$this->write($dom->saveXML());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RouteCollection $routes
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function getRouteCollectionDocument(RouteCollection $routes)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($routesXML = $dom->createElement('routes'));
|
||||
|
||||
foreach ($routes->all() as $name => $route) {
|
||||
$routeXML = $this->getRouteDocument($route, $name);
|
||||
$routesXML->appendChild($routesXML->ownerDocument->importNode($routeXML->childNodes->item(0), true));
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Route $route
|
||||
* @param string|null $name
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function getRouteDocument(Route $route, $name = null)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($routeXML = $dom->createElement('route'));
|
||||
|
||||
if ($name) {
|
||||
$routeXML->setAttribute('name', $name);
|
||||
}
|
||||
|
||||
$routeXML->setAttribute('path', $route->getPath());
|
||||
$routeXML->setAttribute('class', get_class($route));
|
||||
$routeXML->setAttribute('path_regex', $route->compile()->getRegex());
|
||||
|
||||
if ('' !== $route->getHost()) {
|
||||
$routeXML->appendChild($hostXML = $dom->createElement('host'));
|
||||
$hostXML->setAttribute('regex', $route->compile()->getHostRegex());
|
||||
$hostXML->appendChild(new \DOMText($route->getHost()));
|
||||
}
|
||||
|
||||
foreach ($route->getSchemes() as $scheme) {
|
||||
$routeXML->appendChild($schemeXML = $dom->createElement('scheme'));
|
||||
$schemeXML->appendChild(new \DOMText($scheme));
|
||||
}
|
||||
|
||||
foreach ($route->getMethods() as $method) {
|
||||
$routeXML->appendChild($methodXML = $dom->createElement('method'));
|
||||
$methodXML->appendChild(new \DOMText($method));
|
||||
}
|
||||
|
||||
if (count($route->getDefaults())) {
|
||||
$routeXML->appendChild($defaultsXML = $dom->createElement('defaults'));
|
||||
foreach ($route->getDefaults() as $attribute => $value) {
|
||||
$defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
|
||||
$defaultXML->setAttribute('key', $attribute);
|
||||
$defaultXML->appendChild(new \DOMText($this->formatValue($value)));
|
||||
}
|
||||
}
|
||||
|
||||
$requirements = $route->getRequirements();
|
||||
unset($requirements['_scheme'], $requirements['_method']);
|
||||
if (count($requirements)) {
|
||||
$routeXML->appendChild($requirementsXML = $dom->createElement('requirements'));
|
||||
foreach ($requirements as $attribute => $pattern) {
|
||||
$requirementsXML->appendChild($requirementXML = $dom->createElement('requirement'));
|
||||
$requirementXML->setAttribute('key', $attribute);
|
||||
$requirementXML->appendChild(new \DOMText($pattern));
|
||||
}
|
||||
}
|
||||
|
||||
if (count($route->getOptions())) {
|
||||
$routeXML->appendChild($optionsXML = $dom->createElement('options'));
|
||||
foreach ($route->getOptions() as $name => $value) {
|
||||
$optionsXML->appendChild($optionXML = $dom->createElement('option'));
|
||||
$optionXML->setAttribute('key', $name);
|
||||
$optionXML->appendChild(new \DOMText($this->formatValue($value)));
|
||||
}
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParameterBag $parameters
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function getContainerParametersDocument(ParameterBag $parameters)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($parametersXML = $dom->createElement('parameters'));
|
||||
|
||||
foreach ($this->sortParameters($parameters) as $key => $value) {
|
||||
$parametersXML->appendChild($parameterXML = $dom->createElement('parameter'));
|
||||
$parameterXML->setAttribute('key', $key);
|
||||
$parameterXML->appendChild(new \DOMText($this->formatParameter($value)));
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerBuilder $builder
|
||||
* @param boolean $showPrivate
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function getContainerTagsDocument(ContainerBuilder $builder, $showPrivate = false)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($containerXML = $dom->createElement('container'));
|
||||
|
||||
foreach ($this->findDefinitionsByTag($builder, $showPrivate) as $tag => $definitions) {
|
||||
$containerXML->appendChild($tagXML = $dom->createElement('tag'));
|
||||
$tagXML->setAttribute('name', $tag);
|
||||
|
||||
foreach ($definitions as $serviceId => $definition) {
|
||||
$definitionXML = $this->getContainerDefinitionDocument($definition, $serviceId, true);
|
||||
$tagXML->appendChild($dom->importNode($definitionXML->childNodes->item(0), true));
|
||||
}
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $service
|
||||
* @param string $id
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function getContainerServiceDocument($service, $id)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
|
||||
if ($service instanceof Alias) {
|
||||
$dom->appendChild($dom->importNode($this->getContainerAliasDocument($service, $id)->childNodes->item(0), true));
|
||||
} elseif ($service instanceof Definition) {
|
||||
$dom->appendChild($dom->importNode($this->getContainerDefinitionDocument($service, $id)->childNodes->item(0), true));
|
||||
} else {
|
||||
$dom->appendChild($serviceXML = $dom->createElement('service'));
|
||||
$serviceXML->setAttribute('id', $id);
|
||||
$serviceXML->setAttribute('class', get_class($service));
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContainerBuilder $builder
|
||||
* @param string|null $tag
|
||||
* @param boolean $showPrivate
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function getContainerServicesDocument(ContainerBuilder $builder, $tag = null, $showPrivate = false)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($containerXML = $dom->createElement('container'));
|
||||
|
||||
$serviceIds = $tag ? array_keys($builder->findTaggedServiceIds($tag)) : $builder->getServiceIds();
|
||||
|
||||
foreach ($this->sortServiceIds($serviceIds) as $serviceId) {
|
||||
$service = $this->resolveServiceDefinition($builder, $serviceId);
|
||||
|
||||
if ($service instanceof Definition && !($showPrivate || $service->isPublic())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$serviceXML = $this->getContainerServiceDocument($service, $serviceId);
|
||||
$containerXML->appendChild($containerXML->ownerDocument->importNode($serviceXML->childNodes->item(0), true));
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Definition $definition
|
||||
* @param string|null $id
|
||||
* @param boolean $omitTags
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function getContainerDefinitionDocument(Definition $definition, $id = null, $omitTags = false)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($serviceXML = $dom->createElement('definition'));
|
||||
|
||||
if ($id) {
|
||||
$serviceXML->setAttribute('id', $id);
|
||||
}
|
||||
|
||||
$serviceXML->setAttribute('class', $definition->getClass());
|
||||
$serviceXML->setAttribute('scope', $definition->getScope());
|
||||
$serviceXML->setAttribute('public', $definition->isPublic() ? 'true' : 'false');
|
||||
$serviceXML->setAttribute('synthetic', $definition->isSynthetic() ? 'true' : 'false');
|
||||
$serviceXML->setAttribute('file', $definition->getFile());
|
||||
|
||||
if (!$omitTags) {
|
||||
$tags = $definition->getTags();
|
||||
|
||||
if (count($tags) > 0) {
|
||||
$serviceXML->appendChild($tagsXML = $dom->createElement('tags'));
|
||||
foreach ($tags as $tagName => $tagData) {
|
||||
foreach ($tagData as $parameters) {
|
||||
$tagsXML->appendChild($tagXML = $dom->createElement('tag'));
|
||||
$tagXML->setAttribute('name', $tagName);
|
||||
foreach ($parameters as $name => $value) {
|
||||
$tagXML->appendChild($parameterXML = $dom->createElement('parameter'));
|
||||
$parameterXML->setAttribute('name', $name);
|
||||
$parameterXML->textContent = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Alias $alias
|
||||
* @param string|null $id
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
private function getContainerAliasDocument(Alias $alias, $id = null)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->appendChild($aliasXML = $dom->createElement('alias'));
|
||||
|
||||
if ($id) {
|
||||
$aliasXML->setAttribute('id', $id);
|
||||
}
|
||||
|
||||
$aliasXML->setAttribute('service', (string) $alias);
|
||||
$aliasXML->setAttribute('public', $alias->isPublic() ? 'true' : 'false');
|
||||
|
||||
return $dom;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Console\Helper;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Descriptor\JsonDescriptor;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Descriptor\MarkdownDescriptor;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Descriptor\TextDescriptor;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Descriptor\XmlDescriptor;
|
||||
use Symfony\Component\Console\Helper\DescriptorHelper as BaseDescriptorHelper;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
class DescriptorHelper extends BaseDescriptorHelper
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this
|
||||
->register('txt', new TextDescriptor())
|
||||
->register('xml', new XmlDescriptor())
|
||||
->register('json', new JsonDescriptor())
|
||||
->register('md', new MarkdownDescriptor())
|
||||
;
|
||||
}
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
<?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 Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor;
|
||||
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
abstract class AbstractDescriptorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @dataProvider getDescribeRouteCollectionTestData */
|
||||
public function testDescribeRouteCollection(RouteCollection $routes, $expectedDescription)
|
||||
{
|
||||
$this->assertDescription($expectedDescription, $routes);
|
||||
}
|
||||
|
||||
public function getDescribeRouteCollectionTestData()
|
||||
{
|
||||
return $this->getDescriptionTestData(ObjectsProvider::getRouteCollections());
|
||||
}
|
||||
|
||||
/** @dataProvider getDescribeRouteTestData */
|
||||
public function testDescribeRoute(Route $route, $expectedDescription)
|
||||
{
|
||||
$this->assertDescription($expectedDescription, $route);
|
||||
}
|
||||
|
||||
public function getDescribeRouteTestData()
|
||||
{
|
||||
return $this->getDescriptionTestData(ObjectsProvider::getRoutes());
|
||||
}
|
||||
|
||||
/** @dataProvider getDescribeContainerParametersTestData */
|
||||
public function testDescribeContainerParameters(ParameterBag $parameters, $expectedDescription)
|
||||
{
|
||||
$this->assertDescription($expectedDescription, $parameters);
|
||||
}
|
||||
|
||||
public function getDescribeContainerParametersTestData()
|
||||
{
|
||||
return $this->getDescriptionTestData(ObjectsProvider::getContainerParameters());
|
||||
}
|
||||
|
||||
/** @dataProvider getDescribeContainerBuilderTestData */
|
||||
public function testDescribeContainerBuilder(ContainerBuilder $builder, $expectedDescription, array $options)
|
||||
{
|
||||
$this->assertDescription($expectedDescription, $builder, $options);
|
||||
}
|
||||
|
||||
public function getDescribeContainerBuilderTestData()
|
||||
{
|
||||
return $this->getContainerBuilderDescriptionTestData(ObjectsProvider::getContainerBuilders());
|
||||
}
|
||||
|
||||
/** @dataProvider getDescribeContainerDefinitionTestData */
|
||||
public function testDescribeContainerDefinition(Definition $definition, $expectedDescription)
|
||||
{
|
||||
$this->assertDescription($expectedDescription, $definition);
|
||||
}
|
||||
|
||||
public function getDescribeContainerDefinitionTestData()
|
||||
{
|
||||
return $this->getDescriptionTestData(ObjectsProvider::getContainerDefinitions());
|
||||
}
|
||||
|
||||
/** @dataProvider getDescribeContainerAliasTestData */
|
||||
public function testDescribeContainerAlias(Alias $alias, $expectedDescription)
|
||||
{
|
||||
$this->assertDescription($expectedDescription, $alias);
|
||||
}
|
||||
|
||||
public function getDescribeContainerAliasTestData()
|
||||
{
|
||||
return $this->getDescriptionTestData(ObjectsProvider::getContainerAliases());
|
||||
}
|
||||
|
||||
abstract protected function getDescriptor();
|
||||
abstract protected function getFormat();
|
||||
|
||||
private function assertDescription($expectedDescription, $describedObject, array $options = array())
|
||||
{
|
||||
$options['raw_output'] = true;
|
||||
$output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
|
||||
$this->getDescriptor()->describe($output, $describedObject, $options);
|
||||
$this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $output->fetch())));
|
||||
}
|
||||
|
||||
private function getDescriptionTestData(array $objects)
|
||||
{
|
||||
$data = array();
|
||||
foreach ($objects as $name => $object) {
|
||||
$description = file_get_contents(sprintf('%s/../../Fixtures/Descriptor/%s.%s', __DIR__, $name, $this->getFormat()));
|
||||
$data[] = array($object, $description);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function getContainerBuilderDescriptionTestData(array $objects)
|
||||
{
|
||||
$variations = array(
|
||||
'services' => array('show_private' => true),
|
||||
'public' => array('show_private' => false),
|
||||
'tag1' => array('show_private' => true, 'tag' => 'tag1'),
|
||||
'tags' => array('group_by' => 'tags', 'show_private' => true)
|
||||
);
|
||||
|
||||
$data = array();
|
||||
foreach ($objects as $name => $object) {
|
||||
foreach ($variations as $suffix => $options) {
|
||||
$description = file_get_contents(sprintf('%s/../../Fixtures/Descriptor/%s_%s.%s', __DIR__, $name, $suffix, $this->getFormat()));
|
||||
$data[] = array($object, $description, $options);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?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 Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Descriptor\JsonDescriptor;
|
||||
|
||||
class JsonDescriptorTest extends AbstractDescriptorTest
|
||||
{
|
||||
protected function getDescriptor()
|
||||
{
|
||||
return new JsonDescriptor();
|
||||
}
|
||||
|
||||
protected function getFormat()
|
||||
{
|
||||
return 'json';
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?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 Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Descriptor\MarkdownDescriptor;
|
||||
|
||||
class MarkdownDescriptorTest extends AbstractDescriptorTest
|
||||
{
|
||||
protected function getDescriptor()
|
||||
{
|
||||
return new MarkdownDescriptor();
|
||||
}
|
||||
|
||||
protected function getFormat()
|
||||
{
|
||||
return 'md';
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
class ObjectsProvider
|
||||
{
|
||||
public static function getRouteCollections()
|
||||
{
|
||||
$collection1 = new RouteCollection();
|
||||
foreach (self::getRoutes() as $name => $route) {
|
||||
$collection1->add($name, $route);
|
||||
}
|
||||
|
||||
return array('route_collection_1' => $collection1);
|
||||
}
|
||||
|
||||
public static function getRoutes()
|
||||
{
|
||||
return array(
|
||||
'route_1' => new Route(
|
||||
'/hello/{name}',
|
||||
array('name' => 'Joseph'),
|
||||
array('name' => '[a-z]+'),
|
||||
array('opt1' => 'val1', 'opt2' => 'val2'),
|
||||
'localhost',
|
||||
array('http', 'https'),
|
||||
array('get', 'head')
|
||||
),
|
||||
'route_2' => new Route(
|
||||
'/name/add',
|
||||
array(),
|
||||
array(),
|
||||
array('opt1' => 'val1', 'opt2' => 'val2'),
|
||||
'localhost',
|
||||
array('http', 'https'),
|
||||
array('put', 'post')
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public static function getContainerParameters()
|
||||
{
|
||||
return array(
|
||||
'parameters_1' => new ParameterBag(array(
|
||||
'integer' => 12,
|
||||
'string' => 'Hello world!',
|
||||
'boolean' => true,
|
||||
'array' => array(12, 'Hello world!', true),
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
public static function getContainerBuilders()
|
||||
{
|
||||
$builder1 = new ContainerBuilder();
|
||||
$builder1->setDefinitions(self::getContainerDefinitions());
|
||||
$builder1->setAliases(self::getContainerAliases());
|
||||
|
||||
return array('builder_1' => $builder1);
|
||||
}
|
||||
|
||||
public static function getContainerDefinitions()
|
||||
{
|
||||
$definition1 = new Definition('Full\\Qualified\\Class1');
|
||||
$definition2 = new Definition('Full\\Qualified\\Class2');
|
||||
|
||||
return array(
|
||||
'definition_1' => $definition1
|
||||
->setPublic(true)
|
||||
->setSynthetic(false),
|
||||
'definition_2' => $definition2
|
||||
->setPublic(false)
|
||||
->setSynthetic(true)
|
||||
->setFile('/path/to/file')
|
||||
->addTag('tag1', array('attr1' => 'val1', 'attr2' => 'val2'))
|
||||
->addTag('tag1', array('attr3' => 'val3'))
|
||||
->addTag('tag2'),
|
||||
);
|
||||
}
|
||||
|
||||
public static function getContainerAliases()
|
||||
{
|
||||
return array(
|
||||
'alias_1' => new Alias('service_1', true),
|
||||
'alias_2' => new Alias('service_2', false),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?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 Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Descriptor\TextDescriptor;
|
||||
|
||||
class TextDescriptorTest extends AbstractDescriptorTest
|
||||
{
|
||||
protected function getDescriptor()
|
||||
{
|
||||
return new TextDescriptor();
|
||||
}
|
||||
|
||||
protected function getFormat()
|
||||
{
|
||||
return 'txt';
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?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 Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Descriptor\XmlDescriptor;
|
||||
|
||||
class XmlDescriptorTest extends AbstractDescriptorTest
|
||||
{
|
||||
protected function getDescriptor()
|
||||
{
|
||||
return new XmlDescriptor();
|
||||
}
|
||||
|
||||
protected function getFormat()
|
||||
{
|
||||
return 'xml';
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
{"service":"service_1","public":true}
|
@ -0,0 +1,2 @@
|
||||
- Service: `service_1`
|
||||
- Public: yes
|
@ -0,0 +1 @@
|
||||
This service is an alias for the service <info>service_1</info>
|
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<alias service="service_1" public="true"/>
|
@ -0,0 +1 @@
|
||||
{"service":"service_2","public":false}
|
@ -0,0 +1,2 @@
|
||||
- Service: `service_2`
|
||||
- Public: no
|
@ -0,0 +1 @@
|
||||
This service is an alias for the service <info>service_2</info>
|
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<alias service="service_2" public="false"/>
|
@ -0,0 +1 @@
|
||||
{"definitions":{"definition_1":{"class":"Full\\Qualified\\Class1","scope":"container","public":true,"synthetic":false,"file":null,"tags":[]}},"aliases":{"alias_1":{"service":"service_1","public":true},"alias_2":{"service":"service_2","public":false}},"services":{"service_container":"Symfony\\Component\\DependencyInjection\\ContainerBuilder"}}
|
@ -0,0 +1,27 @@
|
||||
Public services
|
||||
===============
|
||||
|
||||
Definitions
|
||||
-----------
|
||||
|
||||
**`definition_1`:**
|
||||
- Class: `Full\Qualified\Class1`
|
||||
- Scope: `container`
|
||||
- Public: yes
|
||||
- Synthetic: no
|
||||
|
||||
Aliases
|
||||
-------
|
||||
|
||||
**`alias_1`:**
|
||||
- Service: `service_1`
|
||||
- Public: yes
|
||||
|
||||
**`alias_2`:**
|
||||
- Service: `service_2`
|
||||
- Public: no
|
||||
|
||||
Services
|
||||
--------
|
||||
|
||||
- `service_container`: `Symfony\Component\DependencyInjection\ContainerBuilder`
|
@ -0,0 +1,9 @@
|
||||
<info>[container]</info> <comment>Public</comment> services
|
||||
+-------------------+-----------+--------------------------------------------------------+
|
||||
| Service ID | Scope | Class name |
|
||||
+-------------------+-----------+--------------------------------------------------------+
|
||||
| alias_1 | n/a | alias for "service_1" |
|
||||
| alias_2 | n/a | alias for "service_2" |
|
||||
| definition_1 | container | Full\Qualified\Class1 |
|
||||
| service_container | | Symfony\Component\DependencyInjection\ContainerBuilder |
|
||||
+-------------------+-----------+--------------------------------------------------------+
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<container>
|
||||
<alias id="alias_1" service="service_1" public="true"/>
|
||||
<alias id="alias_2" service="service_2" public="false"/>
|
||||
<definition id="definition_1" class="Full\Qualified\Class1" scope="container" public="true" synthetic="false" file=""/>
|
||||
<service id="service_container" class="Symfony\Component\DependencyInjection\ContainerBuilder"/>
|
||||
</container>
|
@ -0,0 +1 @@
|
||||
{"definitions":{"definition_1":{"class":"Full\\Qualified\\Class1","scope":"container","public":true,"synthetic":false,"file":null,"tags":[]},"definition_2":{"class":"Full\\Qualified\\Class2","scope":"container","public":false,"synthetic":true,"file":"\/path\/to\/file","tags":[{"name":"tag1","parameters":{"attr1":"val1","attr2":"val2"}},{"name":"tag1","parameters":{"attr3":"val3"}},{"name":"tag2","parameters":[]}]}},"aliases":{"alias_1":{"service":"service_1","public":true},"alias_2":{"service":"service_2","public":false}},"services":{"service_container":"Symfony\\Component\\DependencyInjection\\ContainerBuilder"}}
|
@ -0,0 +1,40 @@
|
||||
Public and private services
|
||||
===========================
|
||||
|
||||
Definitions
|
||||
-----------
|
||||
|
||||
**`definition_1`:**
|
||||
- Class: `Full\Qualified\Class1`
|
||||
- Scope: `container`
|
||||
- Public: yes
|
||||
- Synthetic: no
|
||||
|
||||
**`definition_2`:**
|
||||
- Class: `Full\Qualified\Class2`
|
||||
- Scope: `container`
|
||||
- Public: no
|
||||
- Synthetic: yes
|
||||
- File: `/path/to/file`
|
||||
- Tag: `tag1`
|
||||
- Attr1: val1
|
||||
- Attr2: val2
|
||||
- Tag: `tag1`
|
||||
- Attr3: val3
|
||||
- Tag: `tag2`
|
||||
|
||||
Aliases
|
||||
-------
|
||||
|
||||
**`alias_1`:**
|
||||
- Service: `service_1`
|
||||
- Public: yes
|
||||
|
||||
**`alias_2`:**
|
||||
- Service: `service_2`
|
||||
- Public: no
|
||||
|
||||
Services
|
||||
--------
|
||||
|
||||
- `service_container`: `Symfony\Component\DependencyInjection\ContainerBuilder`
|
@ -0,0 +1,10 @@
|
||||
<info>[container]</info> <comment>Public</comment> and <comment>private</comment> services
|
||||
+-------------------+-----------+--------------------------------------------------------+
|
||||
| Service ID | Scope | Class name |
|
||||
+-------------------+-----------+--------------------------------------------------------+
|
||||
| alias_1 | n/a | alias for "service_1" |
|
||||
| alias_2 | n/a | alias for "service_2" |
|
||||
| definition_1 | container | Full\Qualified\Class1 |
|
||||
| definition_2 | container | Full\Qualified\Class2 |
|
||||
| service_container | | Symfony\Component\DependencyInjection\ContainerBuilder |
|
||||
+-------------------+-----------+--------------------------------------------------------+
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<container>
|
||||
<alias id="alias_1" service="service_1" public="true"/>
|
||||
<alias id="alias_2" service="service_2" public="false"/>
|
||||
<definition id="definition_1" class="Full\Qualified\Class1" scope="container" public="true" synthetic="false" file=""/>
|
||||
<definition id="definition_2" class="Full\Qualified\Class2" scope="container" public="false" synthetic="true" file="/path/to/file">
|
||||
<tags>
|
||||
<tag name="tag1">
|
||||
<parameter name="attr1"/>
|
||||
<parameter name="attr2"/>
|
||||
</tag>
|
||||
<tag name="tag1">
|
||||
<parameter name="attr3"/>
|
||||
</tag>
|
||||
<tag name="tag2"/>
|
||||
</tags>
|
||||
</definition>
|
||||
<service id="service_container" class="Symfony\Component\DependencyInjection\ContainerBuilder"/>
|
||||
</container>
|
@ -0,0 +1 @@
|
||||
{"definitions":{"definition_2":{"class":"Full\\Qualified\\Class2","scope":"container","public":false,"synthetic":true,"file":"\/path\/to\/file","tags":[{"name":"tag1","parameters":{"attr1":"val1","attr2":"val2"}},{"name":"tag1","parameters":{"attr3":"val3"}},{"name":"tag2","parameters":[]}]}},"aliases":[],"services":[]}
|
@ -0,0 +1,18 @@
|
||||
Public and private services with tag `tag1`
|
||||
===========================================
|
||||
|
||||
Definitions
|
||||
-----------
|
||||
|
||||
**`definition_2`:**
|
||||
- Class: `Full\Qualified\Class2`
|
||||
- Scope: `container`
|
||||
- Public: no
|
||||
- Synthetic: yes
|
||||
- File: `/path/to/file`
|
||||
- Tag: `tag1`
|
||||
- Attr1: val1
|
||||
- Attr2: val2
|
||||
- Tag: `tag1`
|
||||
- Attr3: val3
|
||||
- Tag: `tag2`
|
@ -0,0 +1,7 @@
|
||||
<info>[container]</info> <comment>Public</comment> and <comment>private</comment> services with tag <info>tag1</info>
|
||||
+--------------+-------+-------+-------+-----------+-----------------------+
|
||||
| Service ID | attr1 | attr2 | attr3 | Scope | Class name |
|
||||
+--------------+-------+-------+-------+-----------+-----------------------+
|
||||
| definition_2 | val1 | val2 | | container | Full\Qualified\Class2 |
|
||||
| " | | | val3 | | |
|
||||
+--------------+-------+-------+-------+-----------+-----------------------+
|
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<container>
|
||||
<definition id="definition_2" class="Full\Qualified\Class2" scope="container" public="false" synthetic="true" file="/path/to/file">
|
||||
<tags>
|
||||
<tag name="tag1">
|
||||
<parameter name="attr1"/>
|
||||
<parameter name="attr2"/>
|
||||
</tag>
|
||||
<tag name="tag1">
|
||||
<parameter name="attr3"/>
|
||||
</tag>
|
||||
<tag name="tag2"/>
|
||||
</tags>
|
||||
</definition>
|
||||
</container>
|
@ -0,0 +1 @@
|
||||
{"tag1":[{"class":"Full\\Qualified\\Class2","scope":"container","public":false,"synthetic":true,"file":"\/path\/to\/file"}],"tag2":[{"class":"Full\\Qualified\\Class2","scope":"container","public":false,"synthetic":true,"file":"\/path\/to\/file"}]}
|
@ -0,0 +1,22 @@
|
||||
Container tags
|
||||
==============
|
||||
|
||||
tag1
|
||||
----
|
||||
|
||||
**`definition_2`:**
|
||||
- Class: `Full\Qualified\Class2`
|
||||
- Scope: `container`
|
||||
- Public: no
|
||||
- Synthetic: yes
|
||||
- File: `/path/to/file`
|
||||
|
||||
tag2
|
||||
----
|
||||
|
||||
**`definition_2`:**
|
||||
- Class: `Full\Qualified\Class2`
|
||||
- Scope: `container`
|
||||
- Public: no
|
||||
- Synthetic: yes
|
||||
- File: `/path/to/file`
|
@ -0,0 +1,6 @@
|
||||
<info>[container]</info> Tagged services
|
||||
<info>[tag]</info> tag1
|
||||
definition_2
|
||||
|
||||
<info>[tag]</info> tag2
|
||||
definition_2
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<container>
|
||||
<tag name="tag1">
|
||||
<definition id="definition_2" class="Full\Qualified\Class2" scope="container" public="false" synthetic="true" file="/path/to/file"/>
|
||||
</tag>
|
||||
<tag name="tag2">
|
||||
<definition id="definition_2" class="Full\Qualified\Class2" scope="container" public="false" synthetic="true" file="/path/to/file"/>
|
||||
</tag>
|
||||
</container>
|
@ -0,0 +1 @@
|
||||
{"class":"Full\\Qualified\\Class1","scope":"container","public":true,"synthetic":false,"file":null,"tags":[]}
|
@ -0,0 +1,4 @@
|
||||
- Class: `Full\Qualified\Class1`
|
||||
- Scope: `container`
|
||||
- Public: yes
|
||||
- Synthetic: no
|
@ -0,0 +1,7 @@
|
||||
<comment>Service Id</comment> -
|
||||
<comment>Class</comment> Full\Qualified\Class1
|
||||
<comment>Tags</comment> -
|
||||
<comment>Scope</comment> container
|
||||
<comment>Public</comment> yes
|
||||
<comment>Synthetic</comment> no
|
||||
<comment>Required File</comment> -
|
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definition class="Full\Qualified\Class1" scope="container" public="true" synthetic="false" file=""/>
|
@ -0,0 +1 @@
|
||||
{"class":"Full\\Qualified\\Class2","scope":"container","public":false,"synthetic":true,"file":"\/path\/to\/file","tags":[{"name":"tag1","parameters":{"attr1":"val1","attr2":"val2"}},{"name":"tag1","parameters":{"attr3":"val3"}},{"name":"tag2","parameters":[]}]}
|
@ -0,0 +1,11 @@
|
||||
- Class: `Full\Qualified\Class2`
|
||||
- Scope: `container`
|
||||
- Public: no
|
||||
- Synthetic: yes
|
||||
- File: `/path/to/file`
|
||||
- Tag: `tag1`
|
||||
- Attr1: val1
|
||||
- Attr2: val2
|
||||
- Tag: `tag1`
|
||||
- Attr3: val3
|
||||
- Tag: `tag2`
|
@ -0,0 +1,10 @@
|
||||
<comment>Service Id</comment> -
|
||||
<comment>Class</comment> Full\Qualified\Class2
|
||||
<comment>Tags</comment>
|
||||
- tag1 (<info>attr1</info>: val1, <info>attr2</info>: val2)
|
||||
- tag1 (<info>attr3</info>: val3)
|
||||
- tag2 ()
|
||||
<comment>Scope</comment> container
|
||||
<comment>Public</comment> no
|
||||
<comment>Synthetic</comment> yes
|
||||
<comment>Required File</comment> /path/to/file
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definition class="Full\Qualified\Class2" scope="container" public="false" synthetic="true" file="/path/to/file">
|
||||
<tags>
|
||||
<tag name="tag1">
|
||||
<parameter name="attr1"/>
|
||||
<parameter name="attr2"/>
|
||||
</tag>
|
||||
<tag name="tag1">
|
||||
<parameter name="attr3"/>
|
||||
</tag>
|
||||
<tag name="tag2"/>
|
||||
</tags>
|
||||
</definition>
|
@ -0,0 +1 @@
|
||||
{"array":[12,"Hello world!",true],"boolean":true,"integer":12,"string":"Hello world!"}
|
@ -0,0 +1,7 @@
|
||||
Container parameters
|
||||
====================
|
||||
|
||||
- `array`: `[12,"Hello world!",true]`
|
||||
- `boolean`: `true`
|
||||
- `integer`: `12`
|
||||
- `string`: `Hello world!`
|
@ -0,0 +1,9 @@
|
||||
<info>[container]</info> List of parameters
|
||||
+-----------+--------------------------+
|
||||
| Parameter | Value |
|
||||
+-----------+--------------------------+
|
||||
| array | [12,"Hello world!",true] |
|
||||
| boolean | true |
|
||||
| integer | 12 |
|
||||
| string | Hello world! |
|
||||
+-----------+--------------------------+
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<parameters>
|
||||
<parameter key="array">[12,"Hello world!",true]</parameter>
|
||||
<parameter key="boolean">true</parameter>
|
||||
<parameter key="integer">12</parameter>
|
||||
<parameter key="string">Hello world!</parameter>
|
||||
</parameters>
|
@ -0,0 +1 @@
|
||||
{"path":"\/hello\/{name}","host":"localhost","scheme":"http|https","method":"GET|HEAD","class":"Symfony\\Component\\Routing\\Route","defaults":{"name":"Joseph"},"requirements":{"name":"[a-z]+"},"options":{"compiler_class":"Symfony\\Component\\Routing\\RouteCompiler","opt1":"val1","opt2":"val2"},"pathRegex":"#^\/hello(?:\/(?P<name>[a-z]+))?$#s"}
|
@ -0,0 +1,9 @@
|
||||
- Path: /hello/{name}
|
||||
- Host: localhost
|
||||
- Scheme: http|https
|
||||
- Method: GET|HEAD
|
||||
- Class: Symfony\Component\Routing\Route
|
||||
- Defaults:
|
||||
- `name`: Joseph
|
||||
- Requirements:
|
||||
- `name`: [a-z]+
|
@ -0,0 +1,12 @@
|
||||
<comment>Path</comment> /hello/{name}
|
||||
<comment>Host</comment> localhost
|
||||
<comment>Scheme</comment> http|https
|
||||
<comment>Method</comment> GET|HEAD
|
||||
<comment>Class</comment> Symfony\Component\Routing\Route
|
||||
<comment>Defaults</comment> name: Joseph
|
||||
<comment>Requirements</comment> name: [a-z]+
|
||||
<comment>Options</comment> compiler_class: Symfony\Component\Routing\RouteCompiler
|
||||
opt1: val1
|
||||
opt2: val2
|
||||
<comment>Path-Regex</comment> #^/hello(?:/(?P<name>[a-z]+))?$#s
|
||||
<comment>Host-Regex</comment> #^localhost$#s
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<route path="/hello/{name}" class="Symfony\Component\Routing\Route" path_regex="#^/hello(?:/(?P<name>[a-z]+))?$#s">
|
||||
<host regex="#^localhost$#s">localhost</host>
|
||||
<scheme>http</scheme>
|
||||
<scheme>https</scheme>
|
||||
<method>GET</method>
|
||||
<method>HEAD</method>
|
||||
<defaults>
|
||||
<default key="name">Joseph</default>
|
||||
</defaults>
|
||||
<requirements>
|
||||
<requirement key="name">[a-z]+</requirement>
|
||||
</requirements>
|
||||
<options>
|
||||
<option key="compiler_class">Symfony\Component\Routing\RouteCompiler</option>
|
||||
<option key="opt1">val1</option>
|
||||
<option key="opt2">val2</option>
|
||||
</options>
|
||||
</route>
|
@ -0,0 +1 @@
|
||||
{"path":"\/name\/add","host":"localhost","scheme":"http|https","method":"PUT|POST","class":"Symfony\\Component\\Routing\\Route","defaults":[],"requirements":"NO CUSTOM","options":{"compiler_class":"Symfony\\Component\\Routing\\RouteCompiler","opt1":"val1","opt2":"val2"},"pathRegex":"#^\/name\/add$#s"}
|
@ -0,0 +1,7 @@
|
||||
- Path: /name/add
|
||||
- Host: localhost
|
||||
- Scheme: http|https
|
||||
- Method: PUT|POST
|
||||
- Class: Symfony\Component\Routing\Route
|
||||
- Defaults: NONE
|
||||
- Requirements: NONE
|
@ -0,0 +1,12 @@
|
||||
<comment>Path</comment> /name/add
|
||||
<comment>Host</comment> localhost
|
||||
<comment>Scheme</comment> http|https
|
||||
<comment>Method</comment> PUT|POST
|
||||
<comment>Class</comment> Symfony\Component\Routing\Route
|
||||
<comment>Defaults</comment>
|
||||
<comment>Requirements</comment>
|
||||
<comment>Options</comment> compiler_class: Symfony\Component\Routing\RouteCompiler
|
||||
opt1: val1
|
||||
opt2: val2
|
||||
<comment>Path-Regex</comment> #^/name/add$#s
|
||||
<comment>Host-Regex</comment> #^localhost$#s
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<route path="/name/add" class="Symfony\Component\Routing\Route" path_regex="#^/name/add$#s">
|
||||
<host regex="#^localhost$#s">localhost</host>
|
||||
<scheme>http</scheme>
|
||||
<scheme>https</scheme>
|
||||
<method>PUT</method>
|
||||
<method>POST</method>
|
||||
<options>
|
||||
<option key="compiler_class">Symfony\Component\Routing\RouteCompiler</option>
|
||||
<option key="opt1">val1</option>
|
||||
<option key="opt2">val2</option>
|
||||
</options>
|
||||
</route>
|
@ -0,0 +1 @@
|
||||
{"route_1":{"path":"\/hello\/{name}","host":"localhost","scheme":"http|https","method":"GET|HEAD","class":"Symfony\\Component\\Routing\\Route","defaults":{"name":"Joseph"},"requirements":{"name":"[a-z]+"},"options":{"compiler_class":"Symfony\\Component\\Routing\\RouteCompiler","opt1":"val1","opt2":"val2"},"pathRegex":"#^\/hello(?:\/(?P<name>[a-z]+))?$#s"},"route_2":{"path":"\/name\/add","host":"localhost","scheme":"http|https","method":"PUT|POST","class":"Symfony\\Component\\Routing\\Route","defaults":[],"requirements":"NO CUSTOM","options":{"compiler_class":"Symfony\\Component\\Routing\\RouteCompiler","opt1":"val1","opt2":"val2"},"pathRegex":"#^\/name\/add$#s"}}
|
@ -0,0 +1,21 @@
|
||||
route_1
|
||||
-------
|
||||
- Path: /hello/{name}
|
||||
- Host: localhost
|
||||
- Scheme: http|https
|
||||
- Method: GET|HEAD
|
||||
- Class: Symfony\Component\Routing\Route
|
||||
- Defaults:
|
||||
- `name`: Joseph
|
||||
- Requirements:
|
||||
- `name`: [a-z]+
|
||||
|
||||
route_2
|
||||
-------
|
||||
- Path: /name/add
|
||||
- Host: localhost
|
||||
- Scheme: http|https
|
||||
- Method: PUT|POST
|
||||
- Class: Symfony\Component\Routing\Route
|
||||
- Defaults: NONE
|
||||
- Requirements: NONE
|
@ -0,0 +1,7 @@
|
||||
<info>[router]</info> Current routes
|
||||
+---------+----------+------------+-----------+---------------+
|
||||
| Name | Method | Scheme | Host | Path |
|
||||
+---------+----------+------------+-----------+---------------+
|
||||
| route_1 | GET|HEAD | http|https | localhost | /hello/{name} |
|
||||
| route_2 | PUT|POST | http|https | localhost | /name/add |
|
||||
+---------+----------+------------+-----------+---------------+
|
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<routes>
|
||||
<route name="route_1" path="/hello/{name}" class="Symfony\Component\Routing\Route" path_regex="#^/hello(?:/(?P<name>[a-z]+))?$#s">
|
||||
<host regex="#^localhost$#s">localhost</host>
|
||||
<scheme>http</scheme>
|
||||
<scheme>https</scheme>
|
||||
<method>GET</method>
|
||||
<method>HEAD</method>
|
||||
<defaults>
|
||||
<default key="name">Joseph</default>
|
||||
</defaults>
|
||||
<requirements>
|
||||
<requirement key="name">[a-z]+</requirement>
|
||||
</requirements>
|
||||
<options>
|
||||
<option key="compiler_class">Symfony\Component\Routing\RouteCompiler</option>
|
||||
<option key="opt1">val1</option>
|
||||
<option key="opt2">val2</option>
|
||||
</options>
|
||||
</route>
|
||||
<route name="route_2" path="/name/add" class="Symfony\Component\Routing\Route" path_regex="#^/name/add$#s">
|
||||
<host regex="#^localhost$#s">localhost</host>
|
||||
<scheme>http</scheme>
|
||||
<scheme>https</scheme>
|
||||
<method>PUT</method>
|
||||
<method>POST</method>
|
||||
<options>
|
||||
<option key="compiler_class">Symfony\Component\Routing\RouteCompiler</option>
|
||||
<option key="opt1">val1</option>
|
||||
<option key="opt2">val2</option>
|
||||
</options>
|
||||
</route>
|
||||
</routes>
|
Reference in New Issue
Block a user