Skip to content

Commit

Permalink
Provide more detailed information about service tags (#1)
Browse files Browse the repository at this point in the history
* give more detailed information about service tags
  • Loading branch information
IonBazan authored Mar 3, 2021
1 parent 2590c82 commit 283defc
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 12 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
- '7.2'
- '7.3'
- '7.4'
- '8.0'
include:
- php-versions: '7.0'
composer-flags: '--prefer-lowest'
Expand Down Expand Up @@ -47,7 +48,7 @@ jobs:
composer req infection/infection
vendor/bin/infection --ignore-msi-with-no-mutations --min-covered-msi=100 --min-msi=100 -s -j4
- name: Run phpstan
if: ${{ matrix.php-versions >= 7.1 && matrix.php-versions < 8.0 }}
if: ${{ matrix.php-versions >= 7.1 }}
run: |
composer req phpstan/phpstan
vendor/bin/phpstan analyse src -l 6
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# CHANGELOG

## Unreleased

## v1.2.0 (2020-09-17)

- Provide more detailed information about service tags
- Add colors to the output

## v1.1.0 (2020-09-17)

- Support Laravel 8

## v1.0.1 (2020-07-19)

- Add package keywords

## v1.0.0 (2020-07-19)

- Initial release
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Laravel Container Debug command

[![Laravel 5.4|6|7|8](https://img.shields.io/badge/Laravel-5.4+_|_6_|_7_|_8-informational.svg)](http://laravel.com)
[![Latest version](https://img.shields.io/packagist/v/ion-bazan/laravel-container-debug.svg)](https://packagist.org/packages/ion-bazan/laravel-container-debug)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/IonBazan/laravel-container-debug/Tests)](https://github.com/IonBazan/laravel-container-debug/actions)
[![PHP version](https://img.shields.io/packagist/php-v/ion-bazan/laravel-container-debug.svg)](https://packagist.org/packages/ion-bazan/laravel-container-debug)
Expand All @@ -8,7 +9,7 @@
[![Downloads](https://img.shields.io/packagist/dt/ion-bazan/laravel-container-debug.svg)](https://packagist.org/packages/ion-bazan/laravel-container-debug)
[![License](https://img.shields.io/packagist/l/ion-bazan/laravel-container-debug.svg)](https://packagist.org/packages/ion-bazan/laravel-container-debug)

Symfony-inspired package to list available services in Laravel IoC Container. Works with Laravel 5.4+, 6.x and 7.x.
Symfony-inspired package to list available services in Laravel IoC Container. Works with Laravel 5.4+, 6, 7 and 8.

# Example output

Expand Down
55 changes: 52 additions & 3 deletions src/Command/ContainerDebugCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,34 @@ class ContainerDebugCommand extends Command
*/
protected $description = 'Displays application services and tags';

/**
* The console command help text.
*
* @var string
*/
protected $help = <<<EOF
The <info>%command.name%</info> command displays all <comment>bound</comment> services and parameters:
<info>php %command.full_name%</info>
To get specific information about a service, specify its name:
<info>php %command.full_name% translator</info>
To get profiling information, add <comment>--profile</comment> flag:
<info>php %command.full_name% translator --profile</info>
Use the <comment>--tags</comment> option to display tagged services grouped by tag:
<info>php %command.full_name% --tags</info>
Find all services with a specific tag using <comment>--tag</comment> option:
<info>php %command.full_name% --tag=foo</info>
EOF;

/**
* Execute the console command.
*
Expand Down Expand Up @@ -78,10 +106,15 @@ public function handle()
throw new InvalidArgumentException(sprintf('Service "%s" not found', $name));
}

$services = [$name];
$this->showSingleService($name);

return 0;
}

$this->showServices($services);
$this->getOutput()->newLine();
$this->info('To search for a specific service, re-run this command with a search term. (e.g. <comment>container:debug translator</comment>)');
$this->getOutput()->newLine();

return 0;
}
Expand All @@ -93,7 +126,7 @@ public function handle()
*/
private function showTaggedServices(string $tag, array $services)
{
$this->line(sprintf('Services tagged with "%s" tag', $tag));
$this->getOutput()->section(sprintf('Services tagged with "%s" tag', $tag));
$this->showServices($services);
}

Expand Down Expand Up @@ -129,6 +162,22 @@ private function showServices(array $services)
$this->table($headers, $rows);
}

/**
* @return void
*/
private function showSingleService(string $id)
{
$this->getOutput()->title(sprintf('Information for Service "<info>%s</info>"', $id));
$tableRows = [
['Service ID', $id],
['Class', $this->helper->getClassNameDescription($id)],
['Shared', $this->helper->getContainer()->isShared($id) ? 'Yes' : 'No'],
['Alias', $this->helper->getContainer()->isAlias($id) ? 'Yes' : 'No'],
['Tags', implode(PHP_EOL, $this->helper->getServiceTags($id))],
];
$this->table(['Option', 'Value'], $tableRows);
}

/**
* @return string[]
*/
Expand All @@ -139,7 +188,7 @@ private function getRow(string $id): array
$resolutionTime = microtime(true) - $start;

return [
$id,
sprintf('<fg=cyan>%s</>', $id),
$className,
$this->helper->getContainer()->isShared($id) ? 'Yes' : 'No',
$this->helper->getContainer()->isAlias($id) ? 'Yes' : 'No',
Expand Down
16 changes: 16 additions & 0 deletions src/Helper/ContainerHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,22 @@ public function getAliases(): array
return $aliasIds;
}

/**
* @return string[]
*/
public function getServiceTags(string $serviceName): array
{
$tags = array_keys(array_filter(
$this->getProtectedProperty('tags'),
static function (array $services) use ($serviceName) {
return in_array($serviceName, $services, true);
})
);
sort($tags);

return $tags;
}

public function getClassNameDescription(string $id): string
{
if ($this->container->isAlias($id)) {
Expand Down
39 changes: 32 additions & 7 deletions tests/Command/ContainerDebugCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public function testOutputsAllServicesInAlphabeticalOrder()
+--------------------------------------------------------------+-------------------------------------------------------------+--------+-------+
| IonBazan\Laravel\ContainerDebug\Tests\IContainerContractStub | IonBazan\Laravel\ContainerDebug\Tests\ContainerConcreteStub | No | No |
| IonBazan\Laravel\ContainerDebug\Tests\SingletonService | IonBazan\Laravel\ContainerDebug\Tests\SingletonService | Yes | No |
| \RootClass | N/A | Yes | No |
| alias.b | alias for "service.b" | No | Yes |
| alias.c | alias for "service.c" | No | Yes |
| service.a | IonBazan\Laravel\ContainerDebug\Tests\ServiceStubA | No | No |
Expand All @@ -39,6 +40,9 @@ public function testOutputsAllServicesInAlphabeticalOrder()
| simple.value.string | <string> test | No | No |
+--------------------------------------------------------------+-------------------------------------------------------------+--------+-------+
To search for a specific service, re-run this command with a search term. (e.g. container:debug translator)
OUTPUT;
self::assertSame($output, $display);
}
Expand All @@ -54,6 +58,7 @@ public function testShowsProfilingInformation()
+--------------------------------------------------------------+-------------------------------------------------------------+--------+-------+-----------------+
| IonBazan\Laravel\ContainerDebug\Tests\IContainerContractStub | IonBazan\Laravel\ContainerDebug\Tests\ContainerConcreteStub | No | No | 0 |
| IonBazan\Laravel\ContainerDebug\Tests\SingletonService | IonBazan\Laravel\ContainerDebug\Tests\SingletonService | Yes | No | 0 |
| \RootClass | N/A | Yes | No | 0 |
| alias.b | alias for "service.b" | No | Yes | 0 |
| alias.c | alias for "service.c" | No | Yes | 0 |
| service.a | IonBazan\Laravel\ContainerDebug\Tests\ServiceStubA | No | No | 0 |
Expand All @@ -65,26 +70,46 @@ public function testShowsProfilingInformation()
| simple.value.string | <string> test | No | No | 0 |
+--------------------------------------------------------------+-------------------------------------------------------------+--------+-------+-----------------+
To search for a specific service, re-run this command with a search term. (e.g. container:debug translator)
OUTPUT;
self::assertSame($output, $display);
}

public function testOutputsSpecificService()
{
$tester = $this->getCommandTester();
self::assertSame(0, $tester->execute(['name' => 'service.a']));
self::assertSame(0, $tester->execute(['name' => 'service.b']));
$display = $tester->getDisplay();
self::assertContainsString('service.a', $display);
self::assertNotContainsString('service.b', $display);
self::assertNotContainsString('service.c', $display);
$output = <<<OUTPUT
Information for Service "service.b"
===================================
+------------+----------------------------------------------------+
| Option | Value |
+------------+----------------------------------------------------+
| Service ID | service.b |
| Class | IonBazan\Laravel\ContainerDebug\Tests\ServiceStubB |
| Shared | No |
| Alias | No |
| Tags | tag1 |
| | tag2 |
+------------+----------------------------------------------------+
OUTPUT;
self::assertSame($output, $display);
}

public function testFindsMatchingServicesIgnoringBackslashes()
{
$tester = $this->getCommandTester();
self::assertSame(0, $tester->execute(['name' => str_replace('\\', '', SingletonService::class)]));
$display = $tester->getDisplay();
self::assertContainsString(SingletonService::class, $display);
self::assertSame(0, $tester->execute(['name' => '\\IonBazanLaravelContainerDebugTestsSingletonService']));
self::assertContainsString(SingletonService::class, $tester->getDisplay());

self::assertSame(0, $tester->execute(['name' => 'RootClass']));
self::assertContainsString('\\RootClass', $tester->getDisplay());
}

public function testAsksForSpecificService()
Expand Down
1 change: 1 addition & 0 deletions tests/ContainerTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ protected function getTestContainer(): Container
$container->bind('service.a', ServiceStubA::class);
$container->alias('service.c', 'alias.c');
$container->alias('service.b', 'alias.b');
$container->singleton('\\RootClass');
$container->bind(IContainerContractStub::class, ContainerConcreteStub::class);
$container->singleton(SingletonService::class);
$container->tag(['service.c', 'service.b'], ['tag2']);
Expand Down
10 changes: 10 additions & 0 deletions tests/Helper/ContainerHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public function testGetAllServices()
self::assertSame([
IContainerContractStub::class,
SingletonService::class,
'\\RootClass',
'alias.b',
'alias.c',
'service.a',
Expand All @@ -44,6 +45,7 @@ public function testGetAllServices()
self::assertSame([
IContainerContractStub::class,
SingletonService::class,
'\\RootClass',
'service.a',
'service.b',
'service.c',
Expand Down Expand Up @@ -72,6 +74,14 @@ public function testGetAllTags()
self::assertSame(['tag1', 'tag2', 'tag3'], $this->helper->getAllTags());
}

public function testGetTagsForService()
{
self::assertSame(['tag1', 'tag2'], $this->helper->getServiceTags('service.b'));
self::assertSame(['tag1'], $this->helper->getServiceTags('service.a'));
self::assertSame(['tag2'], $this->helper->getServiceTags('service.c'));
self::assertSame([], $this->helper->getServiceTags('service.d'));
}

public function testGetContainer()
{
$container = new Container();
Expand Down

0 comments on commit 283defc

Please sign in to comment.