Skip to content
This repository was archived by the owner on Jan 1, 2018. It is now read-only.

Commit de0d7be

Browse files
committed
Add GroupedNeonAdapter
1 parent fe7b6ff commit de0d7be

File tree

5 files changed

+178
-1
lines changed

5 files changed

+178
-1
lines changed

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,36 @@ services:
108108
```
109109

110110
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).
111+
112+
### Experimental features
113+
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:
114+
115+
```php
116+
$configurator->defaultExtensions['extensions'] = [\Adeira\ConfigurableExtensionsExtension::class, [TRUE]]; // Become superhero!
117+
```
118+
119+
At this moment there is so called `GroupedNeonAdapter`. It allows you to write service definitions in NEON with grouped syntax. Before:
120+
121+
```php
122+
graphql:
123+
types:
124+
- Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationRecordType
125+
- Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationsConnectionType
126+
- Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationsEdgeType
127+
- Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationType
128+
```
129+
130+
After:
131+
132+
```php
133+
graphql:
134+
types:
135+
- Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\( # namespace must end with backslash
136+
WeatherStationRecordType
137+
WeatherStationsConnectionType
138+
WeatherStationsEdgeType
139+
WeatherStationType
140+
)
141+
```
142+
143+
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.

src/ConfigurableExtensionsExtension.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,24 @@
77
class ConfigurableExtensionsExtension extends \Nette\DI\Extensions\ExtensionsExtension
88
{
99

10+
private $experimental;
11+
12+
public function __construct($experimental = FALSE)
13+
{
14+
$this->experimental = $experimental;
15+
}
16+
17+
public function loadFromFile($file)
18+
{
19+
$loader = new \Nette\DI\Config\Loader;
20+
if ($this->experimental === TRUE) {
21+
$loader->addAdapter('neon', GroupedNeonAdapter::class);
22+
}
23+
$res = $loader->load($file);
24+
$this->compiler->addDependencies($loader->getDependencies());
25+
return $res;
26+
}
27+
1028
public function loadConfiguration()
1129
{
1230
$ceeConfig = $this->getConfig(); // configuration of this extension (list of extensions)

src/GroupedNeonAdapter.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Adeira;
4+
5+
final class GroupedNeonAdapter extends \Nette\DI\Config\Adapters\NeonAdapter
6+
{
7+
8+
public function process(array $arr)
9+
{
10+
foreach ($arr as &$configKeys) {
11+
if (is_array($configKeys)) {
12+
foreach ($configKeys as $originalKey => $entity) {
13+
if ($entity instanceof \Nette\Neon\Entity) {
14+
if (\Nette\Utils\Strings::endsWith($entity->value, '\\')) {
15+
if (!$this->isEntityRegisteredAsAnonymous($originalKey)) {
16+
throw new \Nette\Neon\Exception("Service with grouped classes must be anonymous. You have to remove key '$originalKey' to use this feature.");
17+
}
18+
19+
unset($configKeys[$originalKey]);
20+
21+
foreach ($entity->attributes as $attributeKey => $attribute) {
22+
if (!$this->isEntityRegisteredAsAnonymous($attributeKey)) {
23+
throw new \Nette\Neon\Exception("Grouped classes in service definition must be anonymous. Please remove key '$attributeKey'.");
24+
}
25+
26+
$configKeys[] = $entity->value . $attribute; //add grouped services
27+
}
28+
}
29+
}
30+
}
31+
}
32+
}
33+
unset($configKeys); //unreference
34+
return parent::process($arr);
35+
}
36+
37+
private function isEntityRegisteredAsAnonymous($entityKey)
38+
{
39+
return (string)(int)$entityKey === (string)$entityKey; //anonymous
40+
}
41+
42+
}

tests/src/CompilerExtension.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class CompilerExtension extends \Tester\TestCase
2626

2727
$configurator = new Nette\Configurator;
2828
$configurator->defaultExtensions = [
29-
'extensions' => \Adeira\ConfigurableExtensionsExtension::class,
29+
'extensions' => [\Adeira\ConfigurableExtensionsExtension::class, [TRUE]],
3030
'application' => [Nette\Bridges\ApplicationDI\ApplicationExtension::class, ['%debugMode%', ['%appDir%'], '%tempDir%/cache']],
3131
'http' => [Nette\Bridges\HttpDI\HttpExtension::class, ['%consoleMode%']],
3232
'latte' => [Nette\Bridges\ApplicationDI\LatteExtension::class, ['%tempDir%/cache/latte', '%debugMode%']],
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
namespace Adeira\Tests;
4+
5+
use Adeira\GroupedNeonAdapter;
6+
use Tester\Assert;
7+
use Tester\FileMock;
8+
9+
require dirname(__DIR__) . '/bootstrap.php';
10+
11+
/**
12+
* @testCase
13+
*/
14+
class GroupedNeonAdapterTest extends \Tester\TestCase
15+
{
16+
17+
public function testThatProcessExpandsEntities()
18+
{
19+
$loader = new \Nette\DI\Config\Loader;
20+
$loader->addAdapter($extension = 'neon', GroupedNeonAdapter::class);
21+
$configuration = <<<NEON
22+
section:
23+
- Namespace\ClassA
24+
B: Namespace\ClassB
25+
- Namespace\(Class_1)
26+
- Namespace\ClassC
27+
- Namespace\(
28+
Class_2
29+
Class_3
30+
Class_4
31+
)
32+
NEON;
33+
Assert::same([
34+
'section' => [
35+
0 => 'Namespace\\ClassA',
36+
'B' => 'Namespace\\ClassB',
37+
2 => 'Namespace\\ClassC', // it doesn't cleanup indices but who cares
38+
4 => 'Namespace\\Class_1',
39+
5 => 'Namespace\\Class_2',
40+
6 => 'Namespace\\Class_3',
41+
7 => 'Namespace\\Class_4',
42+
],
43+
], $loader->load(FileMock::create($configuration, $extension)));
44+
}
45+
46+
public function testThatClassMustBeAnonymous()
47+
{
48+
$loader = new \Nette\DI\Config\Loader;
49+
$loader->addAdapter($extension = 'neon', GroupedNeonAdapter::class);
50+
$configuration = <<<NEON
51+
section:
52+
A: Namespace\ClassA
53+
B: Namespace\(
54+
Class_2
55+
Class_3
56+
Class_4
57+
)
58+
NEON;
59+
Assert::exception(function () use ($loader, $configuration, $extension) {
60+
$loader->load(FileMock::create($configuration, $extension));
61+
}, \Nette\Neon\Exception::class, 'Service with grouped classes must be anonymous. You have to remove key \'B\' to use this feature.');
62+
}
63+
64+
public function testThatExpandedClassMustBeAnonymous()
65+
{
66+
$loader = new \Nette\DI\Config\Loader;
67+
$loader->addAdapter($extension = 'neon', GroupedNeonAdapter::class);
68+
$configuration = <<<NEON
69+
section:
70+
A: Namespace\ClassA
71+
- Namespace\(
72+
Class_2,
73+
c3: Class_3,
74+
Class_4,
75+
)
76+
NEON;
77+
Assert::exception(function () use ($loader, $configuration, $extension) {
78+
$loader->load(FileMock::create($configuration, $extension));
79+
}, \Nette\Neon\Exception::class, 'Grouped classes in service definition must be anonymous. Please remove key \'c3\'.');
80+
}
81+
82+
}
83+
84+
(new GroupedNeonAdapterTest)->run();

0 commit comments

Comments
 (0)