From 7242c869063743d618b5938eefe57a1353c5f5ed Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 3 May 2017 15:48:30 -0400 Subject: [PATCH 1/2] Adding a new debug:container --types option to dump classes/interfaces that can be used for type-hinting --- .../Command/ContainerDebugCommand.php | 24 ++++++++++++++++++- .../Console/Descriptor/JsonDescriptor.php | 4 ++++ .../Console/Descriptor/MarkdownDescriptor.php | 4 ++++ .../Console/Descriptor/TextDescriptor.php | 4 ++++ .../Console/Descriptor/XmlDescriptor.php | 9 +++++-- 5 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php index f71851a23ace3..891ca9279ed5f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php @@ -50,6 +50,7 @@ protected function configure() 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('types', null, InputOption::VALUE_NONE, 'Displays types (classes/interfaces) available in the container'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw description'), )) @@ -63,6 +64,10 @@ protected function configure() php %command.full_name% validator +To see available types that can be used for autowiring, use the --types flag: + + php %command.full_name% --types + By default, private services are hidden. You can display all services by using the --show-private flag: @@ -100,7 +105,10 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->validateInput($input); $object = $this->getContainerBuilder(); - if ($input->getOption('parameters')) { + if ($input->getOption('types')) { + $options = array('show_private' => true); + $options['filter'] = array($this, 'filterToServiceTypes'); + } elseif ($input->getOption('parameters')) { $parameters = array(); foreach ($object->getParameterBag()->all() as $k => $v) { $parameters[$k] = $object->resolveEnvPlaceholders($v); @@ -221,4 +229,18 @@ private function findServiceIdsContaining(ContainerBuilder $builder, $name) return $foundServiceIds; } + + /** + * @internal + */ + public function filterToServiceTypes($serviceId) + { + // filter out things that could not be valid class names + if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $serviceId)) { + return false; + } + + // see if the class exists (only need to trigger autoload once) + return class_exists($serviceId) || interface_exists($serviceId, false); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php index 30410b93ea329..d49c57adfec2e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php @@ -105,6 +105,10 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o $showArguments = isset($options['show_arguments']) && $options['show_arguments']; $data = array('definitions' => array(), 'aliases' => array(), 'services' => array()); + if (isset($options['filter'])) { + $serviceIds = array_filter($serviceIds, $options['filter']); + } + foreach ($this->sortServiceIds($serviceIds) as $serviceId) { $service = $this->resolveServiceDefinition($builder, $serviceId); diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php index 33cd28d4ce53a..59e382d3a9cad 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php @@ -131,6 +131,10 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o $showArguments = isset($options['show_arguments']) && $options['show_arguments']; $services = array('definitions' => array(), 'aliases' => array(), 'services' => array()); + if (isset($options['filter'])) { + $serviceIds = array_filter($serviceIds, $options['filter']); + } + foreach ($this->sortServiceIds($serviceIds) as $serviceId) { $service = $this->resolveServiceDefinition($builder, $serviceId); diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index fa785d48ed021..3e4f8922ebc8f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -186,6 +186,10 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o $serviceIds = isset($options['tag']) && $options['tag'] ? array_keys($builder->findTaggedServiceIds($options['tag'])) : $builder->getServiceIds(); $maxTags = array(); + if (isset($options['filter'])) { + $serviceIds = array_filter($serviceIds, $options['filter']); + } + foreach ($serviceIds as $key => $serviceId) { $definition = $this->resolveServiceDefinition($builder, $serviceId); if ($definition instanceof Definition) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php index 6ed96be1be3d6..c1e586cf927f5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php @@ -79,7 +79,7 @@ protected function describeContainerService($service, array $options = array(), */ 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'], isset($options['show_arguments']) && $options['show_arguments'])); + $this->writeDocument($this->getContainerServicesDocument($builder, isset($options['tag']) ? $options['tag'] : null, isset($options['show_private']) && $options['show_private'], isset($options['show_arguments']) && $options['show_arguments'], isset($options['filter']) ? $options['filter'] : null)); } /** @@ -307,16 +307,21 @@ private function getContainerServiceDocument($service, $id, ContainerBuilder $bu * @param string|null $tag * @param bool $showPrivate * @param bool $showArguments + * @param callable $filter * * @return \DOMDocument */ - private function getContainerServicesDocument(ContainerBuilder $builder, $tag = null, $showPrivate = false, $showArguments = false) + private function getContainerServicesDocument(ContainerBuilder $builder, $tag = null, $showPrivate = false, $showArguments = false, $filter = null) { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($containerXML = $dom->createElement('container')); $serviceIds = $tag ? array_keys($builder->findTaggedServiceIds($tag)) : $builder->getServiceIds(); + if ($filter) { + $serviceIds = array_filter($serviceIds, $filter); + } + foreach ($this->sortServiceIds($serviceIds) as $serviceId) { $service = $this->resolveServiceDefinition($builder, $serviceId); From a827e296abd7216a3e1d56c77f89b4246761ade9 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 3 May 2017 15:48:55 -0400 Subject: [PATCH 2/2] Making the service id jump out with debug:container or debug:types --- .../FrameworkBundle/Console/Descriptor/TextDescriptor.php | 8 +++++--- .../Tests/Console/Descriptor/AbstractDescriptorTest.php | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index 3e4f8922ebc8f..173df2b529162 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -224,8 +224,10 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o $tableHeaders = array_merge(array('Service ID'), $tagsNames, array('Class name')); $tableRows = array(); + $rawOutput = isset($options['raw_text']) && $options['raw_text']; foreach ($this->sortServiceIds($serviceIds) as $serviceId) { $definition = $this->resolveServiceDefinition($builder, $serviceId); + $styledServiceId = $rawOutput ? $serviceId : sprintf('%s', $serviceId); if ($definition instanceof Definition) { if ($showTag) { foreach ($definition->getTag($showTag) as $key => $tag) { @@ -240,13 +242,13 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o } } } else { - $tableRows[] = array($serviceId, $definition->getClass()); + $tableRows[] = array($styledServiceId, $definition->getClass()); } } elseif ($definition instanceof Alias) { $alias = $definition; - $tableRows[] = array_merge(array($serviceId, sprintf('alias for "%s"', $alias)), $tagsCount ? array_fill(0, $tagsCount, '') : array()); + $tableRows[] = array_merge(array($styledServiceId, sprintf('alias for "%s"', $alias)), $tagsCount ? array_fill(0, $tagsCount, '') : array()); } else { - $tableRows[] = array_merge(array($serviceId, get_class($definition)), $tagsCount ? array_fill(0, $tagsCount, '') : array()); + $tableRows[] = array_merge(array($styledServiceId, get_class($definition)), $tagsCount ? array_fill(0, $tagsCount, '') : array()); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php index 32b70a0829efb..ab5c95a7d8b85 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php @@ -183,6 +183,7 @@ abstract protected function getFormat(); private function assertDescription($expectedDescription, $describedObject, array $options = array()) { $options['raw_output'] = true; + $options['raw_text'] = true; $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); if ('txt' === $this->getFormat()) {