From de0d7be1773f47b268f01836fa19e5187dd8621b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Zl=C3=A1mal?= Date: Wed, 1 Feb 2017 09:33:35 +0100 Subject: [PATCH] Add GroupedNeonAdapter --- README.md | 33 ++++++++++ src/ConfigurableExtensionsExtension.php | 18 ++++++ src/GroupedNeonAdapter.php | 42 +++++++++++++ tests/src/CompilerExtension.phpt | 2 +- tests/src/GroupedNeonAdapterTest.phpt | 84 +++++++++++++++++++++++++ 5 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 src/GroupedNeonAdapter.php create mode 100644 tests/src/GroupedNeonAdapterTest.phpt diff --git a/README.md b/README.md index 7cc27dc..c511c9e 100644 --- a/README.md +++ b/README.md @@ -108,3 +108,36 @@ services: ``` Remember that this is possible only if you are using custom config added by `provideConfig` method. It will not work in configs added in bootstrap file (via `Nette\DI\Compiler::addConfig`). This is because only under extension it's possible to get key from the right extension section (`ext2.ext_key2` in this case). + +### Experimental features +These features are not enabled by default now (but may be enabled by default in the future). To enable experimental features now you have to register this extension differently: + +```php + $configurator->defaultExtensions['extensions'] = [\Adeira\ConfigurableExtensionsExtension::class, [TRUE]]; // Become superhero! +``` + +At this moment there is so called `GroupedNeonAdapter`. It allows you to write service definitions in NEON with grouped syntax. Before: + +```php +graphql: + types: + - Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationRecordType + - Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationsConnectionType + - Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationsEdgeType + - Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationType +``` + +After: + +```php +graphql: + types: + - Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\( # namespace must end with backslash + WeatherStationRecordType + WeatherStationsConnectionType + WeatherStationsEdgeType + WeatherStationType + ) +``` + +This feature is optional and works only in NEON files provided via `provideConfig` method. All classes must be registered anonymously. If it's not possible just don't use this feature. diff --git a/src/ConfigurableExtensionsExtension.php b/src/ConfigurableExtensionsExtension.php index 5574df3..e0a241f 100644 --- a/src/ConfigurableExtensionsExtension.php +++ b/src/ConfigurableExtensionsExtension.php @@ -7,6 +7,24 @@ class ConfigurableExtensionsExtension extends \Nette\DI\Extensions\ExtensionsExtension { + private $experimental; + + public function __construct($experimental = FALSE) + { + $this->experimental = $experimental; + } + + public function loadFromFile($file) + { + $loader = new \Nette\DI\Config\Loader; + if ($this->experimental === TRUE) { + $loader->addAdapter('neon', GroupedNeonAdapter::class); + } + $res = $loader->load($file); + $this->compiler->addDependencies($loader->getDependencies()); + return $res; + } + public function loadConfiguration() { $ceeConfig = $this->getConfig(); // configuration of this extension (list of extensions) diff --git a/src/GroupedNeonAdapter.php b/src/GroupedNeonAdapter.php new file mode 100644 index 0000000..06ddc79 --- /dev/null +++ b/src/GroupedNeonAdapter.php @@ -0,0 +1,42 @@ + $entity) { + if ($entity instanceof \Nette\Neon\Entity) { + if (\Nette\Utils\Strings::endsWith($entity->value, '\\')) { + if (!$this->isEntityRegisteredAsAnonymous($originalKey)) { + throw new \Nette\Neon\Exception("Service with grouped classes must be anonymous. You have to remove key '$originalKey' to use this feature."); + } + + unset($configKeys[$originalKey]); + + foreach ($entity->attributes as $attributeKey => $attribute) { + if (!$this->isEntityRegisteredAsAnonymous($attributeKey)) { + throw new \Nette\Neon\Exception("Grouped classes in service definition must be anonymous. Please remove key '$attributeKey'."); + } + + $configKeys[] = $entity->value . $attribute; //add grouped services + } + } + } + } + } + } + unset($configKeys); //unreference + return parent::process($arr); + } + + private function isEntityRegisteredAsAnonymous($entityKey) + { + return (string)(int)$entityKey === (string)$entityKey; //anonymous + } + +} diff --git a/tests/src/CompilerExtension.phpt b/tests/src/CompilerExtension.phpt index 062201c..2767a1e 100644 --- a/tests/src/CompilerExtension.phpt +++ b/tests/src/CompilerExtension.phpt @@ -26,7 +26,7 @@ class CompilerExtension extends \Tester\TestCase $configurator = new Nette\Configurator; $configurator->defaultExtensions = [ - 'extensions' => \Adeira\ConfigurableExtensionsExtension::class, + 'extensions' => [\Adeira\ConfigurableExtensionsExtension::class, [TRUE]], 'application' => [Nette\Bridges\ApplicationDI\ApplicationExtension::class, ['%debugMode%', ['%appDir%'], '%tempDir%/cache']], 'http' => [Nette\Bridges\HttpDI\HttpExtension::class, ['%consoleMode%']], 'latte' => [Nette\Bridges\ApplicationDI\LatteExtension::class, ['%tempDir%/cache/latte', '%debugMode%']], diff --git a/tests/src/GroupedNeonAdapterTest.phpt b/tests/src/GroupedNeonAdapterTest.phpt new file mode 100644 index 0000000..f375ce9 --- /dev/null +++ b/tests/src/GroupedNeonAdapterTest.phpt @@ -0,0 +1,84 @@ +addAdapter($extension = 'neon', GroupedNeonAdapter::class); + $configuration = << [ + 0 => 'Namespace\\ClassA', + 'B' => 'Namespace\\ClassB', + 2 => 'Namespace\\ClassC', // it doesn't cleanup indices but who cares + 4 => 'Namespace\\Class_1', + 5 => 'Namespace\\Class_2', + 6 => 'Namespace\\Class_3', + 7 => 'Namespace\\Class_4', + ], + ], $loader->load(FileMock::create($configuration, $extension))); + } + + public function testThatClassMustBeAnonymous() + { + $loader = new \Nette\DI\Config\Loader; + $loader->addAdapter($extension = 'neon', GroupedNeonAdapter::class); + $configuration = <<load(FileMock::create($configuration, $extension)); + }, \Nette\Neon\Exception::class, 'Service with grouped classes must be anonymous. You have to remove key \'B\' to use this feature.'); + } + + public function testThatExpandedClassMustBeAnonymous() + { + $loader = new \Nette\DI\Config\Loader; + $loader->addAdapter($extension = 'neon', GroupedNeonAdapter::class); + $configuration = <<load(FileMock::create($configuration, $extension)); + }, \Nette\Neon\Exception::class, 'Grouped classes in service definition must be anonymous. Please remove key \'c3\'.'); + } + +} + +(new GroupedNeonAdapterTest)->run();