├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── composer.json ├── composer.lock ├── ruleset.xml ├── src ├── CompilerExtension.php ├── ConfigurableExtensionsExtension.php └── GroupedNeonAdapter.php └── tests ├── .gitignore ├── bootstrap.php ├── helpers ├── CommandsStack.php ├── CustomExtension1.php ├── CustomExtension2.php ├── CustomExtension3.php ├── CustomExtension4.php ├── Definition.php ├── ExtensionEmptyConfig.php ├── FakeLatteMacro.php ├── IService5Factory.php ├── Service1.php ├── Service2.php ├── Service3.php ├── Service4.php └── Service5.php ├── src ├── CompilerExtension.phpt ├── DeprecatedAddConfig.phpt ├── ExtensionsManipulation.phpt ├── GroupedNeonAdapterTest.phpt ├── ProvideConfigSources.phpt ├── UnknownExtensionParameter.phpt └── config.neon └── temp └── .gitignore /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.0 5 | - 7.1 6 | 7 | before_script: 8 | - composer selfupdate --no-progress 9 | - travis_retry composer install --prefer-dist 10 | - vendor/bin/parallel-lint . -e php,php3,php4,php5,phtml,phpt --exclude vendor --blame 11 | 12 | script: 13 | - vendor/bin/tester tests -C 14 | - vendor/bin/phpcs --standard=ruleset.xml --extensions=php --encoding=utf-8 --tab-width=4 -sp src/ --ignore=bootstrap.php 15 | - vendor/bin/phpcs --standard=ruleset.xml --extensions=php,phpt --encoding=utf-8 --tab-width=4 -sp tests/ --ignore=*/output/*,temp/*,bootstrap.php 16 | 17 | notifications: 18 | email: false 19 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Adeira 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > At this moment I don't have time, energy and money to maintain this project. But it's a shame so if you depend on this project and you want to become a sponsor or develop it further please don't hesitate to contact me. Otherwise, I am not able to guarantee bright future of this repo... :) 2 | 3 | # Enhanced CompilerExtension for Nette Framework 4 | 5 | [![Build Status](https://travis-ci.org/adeira/compiler-extension.svg?branch=master)](https://travis-ci.org/adeira/compiler-extension) 6 | 7 | If you have more complicated project structure with a lot of bundles (DIC extensions), it's very common that you have to setup a lot of things and it may be quite difficult. But not with this extension. All you need is to use `Adeira\ConfigurableExtensionsExtension` instead of default `ExtensionsExtension` like this (probably in `bootstrap.php`): 8 | 9 | ```php 10 | $configurator->defaultExtensions['extensions'] = \Adeira\ConfigurableExtensionsExtension::class; 11 | ``` 12 | 13 | This new extension will take care of configuration files in your bundles. Next if you want to use custom config for extension, just use `provideConfig` method: 14 | 15 | ```php 16 | setMapping(['Articles' => 'App\Articles\*Module\Presenters\*Presenter']); 31 | } 32 | 33 | } 34 | ``` 35 | 36 | You don't have to extend `Adeira\CompilerExtension` but there is useful helper `setMapping()` (it just setups custom presenter mapping). But `provideConfig` metod will work with `Nette\DI\CompilerExtension` descendants as well. **And why is this so interesting?** Imagine you have this config in your application (added in bootstrap via `Nette\DI\Compiler::addConfig`): 37 | 38 | ```yaml 39 | parameters: 40 | key1: value1 41 | key2: value2 42 | 43 | services: 44 | - DefaultService 45 | named: Tests\Service 46 | 47 | extensions: 48 | ext2: CustomExtension2 49 | 50 | ext2: 51 | ext_key1: ext_value1 52 | ext_key2: ext_value2 53 | 54 | application: 55 | mapping: 56 | *: * 57 | ``` 58 | 59 | And now you'll add another config in your DIC extension using `provideConfig` method: 60 | 61 | ```yaml 62 | parameters: 63 | key2: overridden 64 | key3: value3 65 | 66 | services: 67 | - Tests\TestService 68 | named: Service2 69 | 70 | ext2: 71 | ext_key2: overridden 72 | ext_key3: ext_value3 73 | 74 | latte: 75 | macros: 76 | - App\Grid\Latte\Macros 77 | ``` 78 | 79 | What is the result? Now there are three global parameters: 80 | 81 | ```yaml 82 | parameters: 83 | key1: value1 84 | key2: overridden 85 | key3: value3 86 | ``` 87 | 88 | As you can see your custom DIC extension has priority. Extensions parameters (`ext2`) behaves exactly the same. What about services? As you can expect there will be three services: 89 | 90 | ```yaml 91 | - DefaultService 92 | named: Service2 93 | - Tests\TestService 94 | ``` 95 | 96 | And here comes the most interesting part. If you have a lot of extensions it's good idea to use custom config files (it's simple and easy to understand). But it may be hard to get extension configuration from neon file. In `Nette\DI\CompilerExtension` descendant class you could do simply `$this->getConfig()` to get configuration related to the extension, but there is no equivalent for doing this in neon. This extension adds special syntax for this case. From the previous examples there are three options related to the `ext2` extension: 97 | 98 | ```yaml 99 | ext2: 100 | ext_key1: ext_value1 101 | ext_key2: overridden 102 | ext_key3: ext_value3 103 | ``` 104 | 105 | To get second parameter into service use this: 106 | 107 | ```yaml 108 | services: 109 | - Tests\TestService(%%ext_key2%%) 110 | ``` 111 | 112 | 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). 113 | 114 | ### Experimental features 115 | 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: 116 | 117 | ```php 118 | $configurator->defaultExtensions['extensions'] = [\Adeira\ConfigurableExtensionsExtension::class, [TRUE]]; // Become superhero! 119 | ``` 120 | 121 | At this moment there is so called `GroupedNeonAdapter`. It allows you to write service definitions in NEON with grouped syntax. Before: 122 | 123 | ```php 124 | graphql: 125 | types: 126 | - Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationRecordType 127 | - Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationsConnectionType 128 | - Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationsEdgeType 129 | - Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\WeatherStationType 130 | ``` 131 | 132 | After: 133 | 134 | ```php 135 | graphql: 136 | types: 137 | - Adeira\Connector\Devices\Infrastructure\Delivery\API\GraphQL\Type\( # namespace must end with backslash 138 | WeatherStationRecordType 139 | WeatherStationsConnectionType 140 | WeatherStationsEdgeType 141 | WeatherStationType 142 | ) 143 | ``` 144 | 145 | 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. 146 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "adeira/compiler-extension", 3 | "license": "MIT", 4 | "require": { 5 | "php": "^7.0", 6 | "nette/application": "^2.4", 7 | "nette/di": "^2.4" 8 | }, 9 | "require-dev": { 10 | "jakub-onderka/php-parallel-lint": "^0.9.2", 11 | "latte/latte": "^2.4", 12 | "nette/bootstrap": "^2.4", 13 | "nette/tester": "dev-master", 14 | "slevomat/coding-standard": "dev-php7" 15 | }, 16 | "autoload": { 17 | "psr-4": { 18 | "Adeira\\": "src/" 19 | } 20 | }, 21 | "autoload-dev": { 22 | "psr-4": { 23 | "Adeira\\Tests\\": "tests/helpers/" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "cb784fa0659269f6c8263894fbab35b1", 8 | "packages": [ 9 | { 10 | "name": "nette/application", 11 | "version": "v2.4.5", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/nette/application.git", 15 | "reference": "cec392dd66d5432d47b856d70ac64a5ce15f2538" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/nette/application/zipball/cec392dd66d5432d47b856d70ac64a5ce15f2538", 20 | "reference": "cec392dd66d5432d47b856d70ac64a5ce15f2538", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "nette/component-model": "^2.3", 25 | "nette/http": "^2.2", 26 | "nette/reflection": "^2.2", 27 | "nette/utils": "^2.4 || ~3.0.0", 28 | "php": ">=5.6.0" 29 | }, 30 | "conflict": { 31 | "nette/di": "<2.4", 32 | "nette/forms": "<2.4", 33 | "nette/latte": "<2.4", 34 | "nette/nette": "<2.2" 35 | }, 36 | "require-dev": { 37 | "latte/latte": "^2.4.3", 38 | "mockery/mockery": "^0.9.5", 39 | "nette/di": "^2.4 || ~3.0.0", 40 | "nette/forms": "^2.4", 41 | "nette/robot-loader": "^2.4.2 || ^3.0", 42 | "nette/security": "^2.4", 43 | "nette/tester": "^2.0", 44 | "tracy/tracy": "^2.4" 45 | }, 46 | "suggest": { 47 | "latte/latte": "Allows using Latte in templates", 48 | "nette/forms": "Allows to use Nette\\Application\\UI\\Form" 49 | }, 50 | "type": "library", 51 | "extra": { 52 | "branch-alias": { 53 | "dev-master": "2.4-dev" 54 | } 55 | }, 56 | "autoload": { 57 | "classmap": [ 58 | "src/" 59 | ], 60 | "files": [ 61 | "src/compatibility.php" 62 | ] 63 | }, 64 | "notification-url": "https://packagist.org/downloads/", 65 | "license": [ 66 | "BSD-3-Clause", 67 | "GPL-2.0", 68 | "GPL-3.0" 69 | ], 70 | "authors": [ 71 | { 72 | "name": "David Grudl", 73 | "homepage": "https://davidgrudl.com" 74 | }, 75 | { 76 | "name": "Nette Community", 77 | "homepage": "https://nette.org/contributors" 78 | } 79 | ], 80 | "description": "Nette Application MVC Component", 81 | "homepage": "https://nette.org", 82 | "time": "2017-02-02T02:25:28+00:00" 83 | }, 84 | { 85 | "name": "nette/caching", 86 | "version": "v2.5.3", 87 | "source": { 88 | "type": "git", 89 | "url": "https://github.com/nette/caching.git", 90 | "reference": "2436e530484a346d0a246733519ceaa40b943bd6" 91 | }, 92 | "dist": { 93 | "type": "zip", 94 | "url": "https://api.github.com/repos/nette/caching/zipball/2436e530484a346d0a246733519ceaa40b943bd6", 95 | "reference": "2436e530484a346d0a246733519ceaa40b943bd6", 96 | "shasum": "" 97 | }, 98 | "require": { 99 | "nette/finder": "^2.2 || ~3.0.0", 100 | "nette/utils": "^2.4 || ~3.0.0", 101 | "php": ">=5.6.0" 102 | }, 103 | "conflict": { 104 | "nette/nette": "<2.2" 105 | }, 106 | "require-dev": { 107 | "latte/latte": "^2.4", 108 | "nette/di": "^2.4 || ~3.0.0", 109 | "nette/tester": "^2.0", 110 | "tracy/tracy": "^2.4" 111 | }, 112 | "suggest": { 113 | "ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal" 114 | }, 115 | "type": "library", 116 | "extra": { 117 | "branch-alias": { 118 | "dev-master": "2.5-dev" 119 | } 120 | }, 121 | "autoload": { 122 | "classmap": [ 123 | "src/" 124 | ] 125 | }, 126 | "notification-url": "https://packagist.org/downloads/", 127 | "license": [ 128 | "BSD-3-Clause", 129 | "GPL-2.0", 130 | "GPL-3.0" 131 | ], 132 | "authors": [ 133 | { 134 | "name": "David Grudl", 135 | "homepage": "https://davidgrudl.com" 136 | }, 137 | { 138 | "name": "Nette Community", 139 | "homepage": "https://nette.org/contributors" 140 | } 141 | ], 142 | "description": "Nette Caching Component", 143 | "homepage": "https://nette.org", 144 | "time": "2017-01-29T20:40:55+00:00" 145 | }, 146 | { 147 | "name": "nette/component-model", 148 | "version": "v2.3.0", 149 | "source": { 150 | "type": "git", 151 | "url": "https://github.com/nette/component-model.git", 152 | "reference": "9b5817b246bf409b8f0f8309c23e599dd8729d28" 153 | }, 154 | "dist": { 155 | "type": "zip", 156 | "url": "https://api.github.com/repos/nette/component-model/zipball/9b5817b246bf409b8f0f8309c23e599dd8729d28", 157 | "reference": "9b5817b246bf409b8f0f8309c23e599dd8729d28", 158 | "shasum": "" 159 | }, 160 | "require": { 161 | "nette/utils": "^2.4", 162 | "php": ">=5.6.0" 163 | }, 164 | "conflict": { 165 | "nette/application": "<2.4", 166 | "nette/nette": "<2.2" 167 | }, 168 | "require-dev": { 169 | "nette/tester": "~2.0", 170 | "tracy/tracy": "^2.3" 171 | }, 172 | "type": "library", 173 | "extra": { 174 | "branch-alias": { 175 | "dev-master": "2.3-dev" 176 | } 177 | }, 178 | "autoload": { 179 | "classmap": [ 180 | "src/" 181 | ] 182 | }, 183 | "notification-url": "https://packagist.org/downloads/", 184 | "license": [ 185 | "BSD-3-Clause", 186 | "GPL-2.0", 187 | "GPL-3.0" 188 | ], 189 | "authors": [ 190 | { 191 | "name": "David Grudl", 192 | "homepage": "https://davidgrudl.com" 193 | }, 194 | { 195 | "name": "Nette Community", 196 | "homepage": "https://nette.org/contributors" 197 | } 198 | ], 199 | "description": "Nette Component Model", 200 | "homepage": "https://nette.org", 201 | "time": "2016-06-17T17:36:56+00:00" 202 | }, 203 | { 204 | "name": "nette/di", 205 | "version": "v2.4.6", 206 | "source": { 207 | "type": "git", 208 | "url": "https://github.com/nette/di.git", 209 | "reference": "28767a0abef69faa08bfa700e2e3f80ac58ab58e" 210 | }, 211 | "dist": { 212 | "type": "zip", 213 | "url": "https://api.github.com/repos/nette/di/zipball/28767a0abef69faa08bfa700e2e3f80ac58ab58e", 214 | "reference": "28767a0abef69faa08bfa700e2e3f80ac58ab58e", 215 | "shasum": "" 216 | }, 217 | "require": { 218 | "ext-tokenizer": "*", 219 | "nette/neon": "^2.3.3", 220 | "nette/php-generator": "^2.5", 221 | "nette/utils": "^2.4.3", 222 | "php": ">=5.6.0" 223 | }, 224 | "conflict": { 225 | "nette/bootstrap": "<2.4", 226 | "nette/nette": "<2.2" 227 | }, 228 | "require-dev": { 229 | "nette/tester": "~2.0", 230 | "tracy/tracy": "^2.3" 231 | }, 232 | "type": "library", 233 | "extra": { 234 | "branch-alias": { 235 | "dev-master": "2.4-dev" 236 | } 237 | }, 238 | "autoload": { 239 | "classmap": [ 240 | "src/" 241 | ] 242 | }, 243 | "notification-url": "https://packagist.org/downloads/", 244 | "license": [ 245 | "BSD-3-Clause", 246 | "GPL-2.0", 247 | "GPL-3.0" 248 | ], 249 | "authors": [ 250 | { 251 | "name": "David Grudl", 252 | "homepage": "https://davidgrudl.com" 253 | }, 254 | { 255 | "name": "Nette Community", 256 | "homepage": "https://nette.org/contributors" 257 | } 258 | ], 259 | "description": "Nette Dependency Injection Component", 260 | "homepage": "https://nette.org", 261 | "time": "2017-01-15T14:08:41+00:00" 262 | }, 263 | { 264 | "name": "nette/finder", 265 | "version": "v2.4.0", 266 | "source": { 267 | "type": "git", 268 | "url": "https://github.com/nette/finder.git", 269 | "reference": "5cabd5fe89f9903715359a403b820c7f94f9bb5e" 270 | }, 271 | "dist": { 272 | "type": "zip", 273 | "url": "https://api.github.com/repos/nette/finder/zipball/5cabd5fe89f9903715359a403b820c7f94f9bb5e", 274 | "reference": "5cabd5fe89f9903715359a403b820c7f94f9bb5e", 275 | "shasum": "" 276 | }, 277 | "require": { 278 | "nette/utils": "~2.4", 279 | "php": ">=5.6.0" 280 | }, 281 | "conflict": { 282 | "nette/nette": "<2.2" 283 | }, 284 | "require-dev": { 285 | "nette/tester": "~2.0", 286 | "tracy/tracy": "^2.3" 287 | }, 288 | "type": "library", 289 | "extra": { 290 | "branch-alias": { 291 | "dev-master": "2.4-dev" 292 | } 293 | }, 294 | "autoload": { 295 | "classmap": [ 296 | "src/" 297 | ] 298 | }, 299 | "notification-url": "https://packagist.org/downloads/", 300 | "license": [ 301 | "BSD-3-Clause", 302 | "GPL-2.0", 303 | "GPL-3.0" 304 | ], 305 | "authors": [ 306 | { 307 | "name": "David Grudl", 308 | "homepage": "https://davidgrudl.com" 309 | }, 310 | { 311 | "name": "Nette Community", 312 | "homepage": "https://nette.org/contributors" 313 | } 314 | ], 315 | "description": "Nette Finder: Files Searching", 316 | "homepage": "https://nette.org", 317 | "time": "2016-05-17T15:49:06+00:00" 318 | }, 319 | { 320 | "name": "nette/http", 321 | "version": "v2.4.4", 322 | "source": { 323 | "type": "git", 324 | "url": "https://github.com/nette/http.git", 325 | "reference": "7727507129934e18c59bdc4060fd32730b0d9e87" 326 | }, 327 | "dist": { 328 | "type": "zip", 329 | "url": "https://api.github.com/repos/nette/http/zipball/7727507129934e18c59bdc4060fd32730b0d9e87", 330 | "reference": "7727507129934e18c59bdc4060fd32730b0d9e87", 331 | "shasum": "" 332 | }, 333 | "require": { 334 | "nette/utils": "^2.4", 335 | "php": ">=5.6.0" 336 | }, 337 | "conflict": { 338 | "nette/nette": "<2.2" 339 | }, 340 | "require-dev": { 341 | "nette/di": "^2.4.6", 342 | "nette/tester": "~2.0", 343 | "tracy/tracy": "^2.4" 344 | }, 345 | "suggest": { 346 | "ext-fileinfo": "to detect type of uploaded files" 347 | }, 348 | "type": "library", 349 | "extra": { 350 | "branch-alias": { 351 | "dev-master": "2.4-dev" 352 | } 353 | }, 354 | "autoload": { 355 | "classmap": [ 356 | "src/" 357 | ] 358 | }, 359 | "notification-url": "https://packagist.org/downloads/", 360 | "license": [ 361 | "BSD-3-Clause", 362 | "GPL-2.0", 363 | "GPL-3.0" 364 | ], 365 | "authors": [ 366 | { 367 | "name": "David Grudl", 368 | "homepage": "https://davidgrudl.com" 369 | }, 370 | { 371 | "name": "Nette Community", 372 | "homepage": "https://nette.org/contributors" 373 | } 374 | ], 375 | "description": "Nette HTTP Component", 376 | "homepage": "https://nette.org", 377 | "time": "2017-01-18T03:03:04+00:00" 378 | }, 379 | { 380 | "name": "nette/neon", 381 | "version": "v2.4.1", 382 | "source": { 383 | "type": "git", 384 | "url": "https://github.com/nette/neon.git", 385 | "reference": "1a78ff64b1e161ebccc03bdf9366450a69365f5b" 386 | }, 387 | "dist": { 388 | "type": "zip", 389 | "url": "https://api.github.com/repos/nette/neon/zipball/1a78ff64b1e161ebccc03bdf9366450a69365f5b", 390 | "reference": "1a78ff64b1e161ebccc03bdf9366450a69365f5b", 391 | "shasum": "" 392 | }, 393 | "require": { 394 | "ext-iconv": "*", 395 | "ext-json": "*", 396 | "php": ">=5.6.0" 397 | }, 398 | "require-dev": { 399 | "nette/tester": "~2.0", 400 | "tracy/tracy": "^2.3" 401 | }, 402 | "type": "library", 403 | "extra": { 404 | "branch-alias": { 405 | "dev-master": "2.4-dev" 406 | } 407 | }, 408 | "autoload": { 409 | "classmap": [ 410 | "src/" 411 | ] 412 | }, 413 | "notification-url": "https://packagist.org/downloads/", 414 | "license": [ 415 | "BSD-3-Clause", 416 | "GPL-2.0", 417 | "GPL-3.0" 418 | ], 419 | "authors": [ 420 | { 421 | "name": "David Grudl", 422 | "homepage": "https://davidgrudl.com" 423 | }, 424 | { 425 | "name": "Nette Community", 426 | "homepage": "https://nette.org/contributors" 427 | } 428 | ], 429 | "description": "Nette NEON: parser & generator for Nette Object Notation", 430 | "homepage": "http://ne-on.org", 431 | "time": "2017-01-13T08:00:19+00:00" 432 | }, 433 | { 434 | "name": "nette/php-generator", 435 | "version": "v2.5.0", 436 | "source": { 437 | "type": "git", 438 | "url": "https://github.com/nette/php-generator.git", 439 | "reference": "3f317dc211953cc93e9efa61598dc074adc3b0de" 440 | }, 441 | "dist": { 442 | "type": "zip", 443 | "url": "https://api.github.com/repos/nette/php-generator/zipball/3f317dc211953cc93e9efa61598dc074adc3b0de", 444 | "reference": "3f317dc211953cc93e9efa61598dc074adc3b0de", 445 | "shasum": "" 446 | }, 447 | "require": { 448 | "nette/utils": "~2.4", 449 | "php": ">=5.6.0" 450 | }, 451 | "conflict": { 452 | "nette/nette": "<2.2" 453 | }, 454 | "require-dev": { 455 | "nette/tester": "~2.0", 456 | "tracy/tracy": "^2.3" 457 | }, 458 | "type": "library", 459 | "extra": { 460 | "branch-alias": { 461 | "dev-master": "2.5-dev" 462 | } 463 | }, 464 | "autoload": { 465 | "classmap": [ 466 | "src/" 467 | ] 468 | }, 469 | "notification-url": "https://packagist.org/downloads/", 470 | "license": [ 471 | "BSD-3-Clause", 472 | "GPL-2.0", 473 | "GPL-3.0" 474 | ], 475 | "authors": [ 476 | { 477 | "name": "David Grudl", 478 | "homepage": "https://davidgrudl.com" 479 | }, 480 | { 481 | "name": "Nette Community", 482 | "homepage": "https://nette.org/contributors" 483 | } 484 | ], 485 | "description": "Nette PHP Generator", 486 | "homepage": "https://nette.org", 487 | "time": "2017-01-13T08:02:14+00:00" 488 | }, 489 | { 490 | "name": "nette/reflection", 491 | "version": "v2.4.1", 492 | "source": { 493 | "type": "git", 494 | "url": "https://github.com/nette/reflection.git", 495 | "reference": "ca6bafe1f73c19719238b58f91e6a399f281069b" 496 | }, 497 | "dist": { 498 | "type": "zip", 499 | "url": "https://api.github.com/repos/nette/reflection/zipball/ca6bafe1f73c19719238b58f91e6a399f281069b", 500 | "reference": "ca6bafe1f73c19719238b58f91e6a399f281069b", 501 | "shasum": "" 502 | }, 503 | "require": { 504 | "ext-tokenizer": "*", 505 | "nette/caching": "^2.2 || ^3.0", 506 | "nette/utils": "^2.4 || ^3.0", 507 | "php": ">=5.6.0" 508 | }, 509 | "conflict": { 510 | "nette/nette": "<2.2" 511 | }, 512 | "require-dev": { 513 | "nette/di": "^2.4 || ^3.0", 514 | "nette/tester": "^2.0", 515 | "tracy/tracy": "^2.4" 516 | }, 517 | "type": "library", 518 | "extra": { 519 | "branch-alias": { 520 | "dev-master": "2.4-dev" 521 | } 522 | }, 523 | "autoload": { 524 | "classmap": [ 525 | "src/" 526 | ] 527 | }, 528 | "notification-url": "https://packagist.org/downloads/", 529 | "license": [ 530 | "BSD-3-Clause", 531 | "GPL-2.0", 532 | "GPL-3.0" 533 | ], 534 | "authors": [ 535 | { 536 | "name": "David Grudl", 537 | "homepage": "https://davidgrudl.com" 538 | }, 539 | { 540 | "name": "Nette Community", 541 | "homepage": "https://nette.org/contributors" 542 | } 543 | ], 544 | "description": "Nette PHP Reflection Component", 545 | "homepage": "https://nette.org", 546 | "time": "2017-01-10T16:10:27+00:00" 547 | }, 548 | { 549 | "name": "nette/utils", 550 | "version": "v2.4.4", 551 | "source": { 552 | "type": "git", 553 | "url": "https://github.com/nette/utils.git", 554 | "reference": "714afb64d0da07d0da7178cbf5680008e4b0180b" 555 | }, 556 | "dist": { 557 | "type": "zip", 558 | "url": "https://api.github.com/repos/nette/utils/zipball/714afb64d0da07d0da7178cbf5680008e4b0180b", 559 | "reference": "714afb64d0da07d0da7178cbf5680008e4b0180b", 560 | "shasum": "" 561 | }, 562 | "require": { 563 | "php": ">=5.6.0" 564 | }, 565 | "conflict": { 566 | "nette/nette": "<2.2" 567 | }, 568 | "require-dev": { 569 | "nette/tester": "~2.0", 570 | "tracy/tracy": "^2.3" 571 | }, 572 | "suggest": { 573 | "ext-gd": "to use Image", 574 | "ext-iconv": "to use Strings::webalize() and toAscii()", 575 | "ext-intl": "for script transliteration in Strings::webalize() and toAscii()", 576 | "ext-json": "to use Nette\\Utils\\Json", 577 | "ext-mbstring": "to use Strings::lower() etc...", 578 | "ext-xml": "to use Strings::length() etc. when mbstring is not available" 579 | }, 580 | "type": "library", 581 | "extra": { 582 | "branch-alias": { 583 | "dev-master": "2.4-dev" 584 | } 585 | }, 586 | "autoload": { 587 | "classmap": [ 588 | "src/" 589 | ] 590 | }, 591 | "notification-url": "https://packagist.org/downloads/", 592 | "license": [ 593 | "BSD-3-Clause", 594 | "GPL-2.0", 595 | "GPL-3.0" 596 | ], 597 | "authors": [ 598 | { 599 | "name": "David Grudl", 600 | "homepage": "https://davidgrudl.com" 601 | }, 602 | { 603 | "name": "Nette Community", 604 | "homepage": "https://nette.org/contributors" 605 | } 606 | ], 607 | "description": "Nette Utility Classes", 608 | "homepage": "https://nette.org", 609 | "time": "2017-01-16T12:30:14+00:00" 610 | } 611 | ], 612 | "packages-dev": [ 613 | { 614 | "name": "jakub-onderka/php-parallel-lint", 615 | "version": "v0.9.2", 616 | "source": { 617 | "type": "git", 618 | "url": "https://github.com/JakubOnderka/PHP-Parallel-Lint.git", 619 | "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa" 620 | }, 621 | "dist": { 622 | "type": "zip", 623 | "url": "https://api.github.com/repos/JakubOnderka/PHP-Parallel-Lint/zipball/2ead2e4043ab125bee9554f356e0a86742c2d4fa", 624 | "reference": "2ead2e4043ab125bee9554f356e0a86742c2d4fa", 625 | "shasum": "" 626 | }, 627 | "require": { 628 | "php": ">=5.3.3" 629 | }, 630 | "require-dev": { 631 | "jakub-onderka/php-console-highlighter": "~0.3", 632 | "nette/tester": "~1.3" 633 | }, 634 | "suggest": { 635 | "jakub-onderka/php-console-highlighter": "Highlight syntax in code snippet" 636 | }, 637 | "bin": [ 638 | "parallel-lint" 639 | ], 640 | "type": "library", 641 | "autoload": { 642 | "classmap": [ 643 | "./" 644 | ] 645 | }, 646 | "notification-url": "https://packagist.org/downloads/", 647 | "license": [ 648 | "BSD-2-Clause" 649 | ], 650 | "authors": [ 651 | { 652 | "name": "Jakub Onderka", 653 | "email": "jakub.onderka@gmail.com" 654 | } 655 | ], 656 | "description": "This tool check syntax of PHP files about 20x faster than serial check.", 657 | "homepage": "https://github.com/JakubOnderka/PHP-Parallel-Lint", 658 | "time": "2015-12-15T10:42:16+00:00" 659 | }, 660 | { 661 | "name": "latte/latte", 662 | "version": "v2.4.3", 663 | "source": { 664 | "type": "git", 665 | "url": "https://github.com/nette/latte.git", 666 | "reference": "b62ee346467e1e2402a43c499cf6047fddc5d321" 667 | }, 668 | "dist": { 669 | "type": "zip", 670 | "url": "https://api.github.com/repos/nette/latte/zipball/b62ee346467e1e2402a43c499cf6047fddc5d321", 671 | "reference": "b62ee346467e1e2402a43c499cf6047fddc5d321", 672 | "shasum": "" 673 | }, 674 | "require": { 675 | "ext-json": "*", 676 | "ext-tokenizer": "*", 677 | "php": ">=5.4.4" 678 | }, 679 | "conflict": { 680 | "nette/application": "<2.4.1" 681 | }, 682 | "require-dev": { 683 | "nette/tester": "~2.0", 684 | "tracy/tracy": "^2.3" 685 | }, 686 | "suggest": { 687 | "ext-fileinfo": "to use filter |datastream", 688 | "ext-mbstring": "to use filters like lower, upper, capitalize, ...", 689 | "ext-xml": "to use filters like length, substring, ..." 690 | }, 691 | "type": "library", 692 | "extra": { 693 | "branch-alias": { 694 | "dev-master": "2.4-dev" 695 | } 696 | }, 697 | "autoload": { 698 | "classmap": [ 699 | "src/" 700 | ] 701 | }, 702 | "notification-url": "https://packagist.org/downloads/", 703 | "license": [ 704 | "BSD-3-Clause", 705 | "GPL-2.0", 706 | "GPL-3.0" 707 | ], 708 | "authors": [ 709 | { 710 | "name": "David Grudl", 711 | "homepage": "https://davidgrudl.com" 712 | }, 713 | { 714 | "name": "Nette Community", 715 | "homepage": "https://nette.org/contributors" 716 | } 717 | ], 718 | "description": "Latte: the amazing template engine for PHP", 719 | "homepage": "https://latte.nette.org", 720 | "keywords": [ 721 | "templating", 722 | "twig" 723 | ], 724 | "time": "2017-01-19T11:06:59+00:00" 725 | }, 726 | { 727 | "name": "nette/bootstrap", 728 | "version": "v2.4.2", 729 | "source": { 730 | "type": "git", 731 | "url": "https://github.com/nette/bootstrap.git", 732 | "reference": "4db37e6d42ddf41b50417950741113b5dfc86e27" 733 | }, 734 | "dist": { 735 | "type": "zip", 736 | "url": "https://api.github.com/repos/nette/bootstrap/zipball/4db37e6d42ddf41b50417950741113b5dfc86e27", 737 | "reference": "4db37e6d42ddf41b50417950741113b5dfc86e27", 738 | "shasum": "" 739 | }, 740 | "require": { 741 | "nette/di": "~2.4.0", 742 | "nette/utils": "~2.4", 743 | "php": ">=5.6.0" 744 | }, 745 | "conflict": { 746 | "nette/nette": "<2.2" 747 | }, 748 | "require-dev": { 749 | "latte/latte": "~2.2", 750 | "nette/application": "~2.3", 751 | "nette/caching": "~2.3", 752 | "nette/database": "~2.3", 753 | "nette/forms": "~2.3", 754 | "nette/http": "~2.4.0", 755 | "nette/mail": "~2.3", 756 | "nette/robot-loader": "~2.2", 757 | "nette/safe-stream": "~2.2", 758 | "nette/security": "~2.3", 759 | "nette/tester": "~2.0", 760 | "tracy/tracy": "^2.4.1" 761 | }, 762 | "suggest": { 763 | "nette/robot-loader": "to use Configurator::createRobotLoader()", 764 | "tracy/tracy": "to use Configurator::enableTracy()" 765 | }, 766 | "type": "library", 767 | "extra": { 768 | "branch-alias": { 769 | "dev-master": "2.4-dev" 770 | } 771 | }, 772 | "autoload": { 773 | "classmap": [ 774 | "src/" 775 | ] 776 | }, 777 | "notification-url": "https://packagist.org/downloads/", 778 | "license": [ 779 | "BSD-3-Clause", 780 | "GPL-2.0", 781 | "GPL-3.0" 782 | ], 783 | "authors": [ 784 | { 785 | "name": "David Grudl", 786 | "homepage": "https://davidgrudl.com" 787 | }, 788 | { 789 | "name": "Nette Community", 790 | "homepage": "https://nette.org/contributors" 791 | } 792 | ], 793 | "description": "Nette Bootstrap", 794 | "homepage": "https://nette.org", 795 | "time": "2016-12-19T12:12:10+00:00" 796 | }, 797 | { 798 | "name": "nette/tester", 799 | "version": "dev-master", 800 | "source": { 801 | "type": "git", 802 | "url": "https://github.com/nette/tester.git", 803 | "reference": "83317fa991ab9cd2bb9610129fc75c53c2c417b6" 804 | }, 805 | "dist": { 806 | "type": "zip", 807 | "url": "https://api.github.com/repos/nette/tester/zipball/83317fa991ab9cd2bb9610129fc75c53c2c417b6", 808 | "reference": "83317fa991ab9cd2bb9610129fc75c53c2c417b6", 809 | "shasum": "" 810 | }, 811 | "require": { 812 | "php": ">=5.4.0" 813 | }, 814 | "bin": [ 815 | "src/tester" 816 | ], 817 | "type": "library", 818 | "extra": { 819 | "branch-alias": { 820 | "dev-master": "2.0-dev" 821 | } 822 | }, 823 | "autoload": { 824 | "classmap": [ 825 | "src/" 826 | ] 827 | }, 828 | "notification-url": "https://packagist.org/downloads/", 829 | "license": [ 830 | "BSD-3-Clause", 831 | "GPL-2.0", 832 | "GPL-3.0" 833 | ], 834 | "authors": [ 835 | { 836 | "name": "David Grudl", 837 | "homepage": "https://davidgrudl.com" 838 | }, 839 | { 840 | "name": "Nette Community", 841 | "homepage": "https://nette.org/contributors" 842 | } 843 | ], 844 | "description": "An easy-to-use PHP unit testing framework.", 845 | "homepage": "https://tester.nette.org", 846 | "keywords": [ 847 | "nette", 848 | "testing", 849 | "unit" 850 | ], 851 | "time": "2017-02-04 14:42:23" 852 | }, 853 | { 854 | "name": "slevomat/coding-standard", 855 | "version": "dev-php7", 856 | "source": { 857 | "type": "git", 858 | "url": "https://github.com/slevomat/coding-standard.git", 859 | "reference": "d4a1a9cd4e9375332bca1d33f9af4debe4b2a949" 860 | }, 861 | "dist": { 862 | "type": "zip", 863 | "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/d4a1a9cd4e9375332bca1d33f9af4debe4b2a949", 864 | "reference": "d4a1a9cd4e9375332bca1d33f9af4debe4b2a949", 865 | "shasum": "" 866 | }, 867 | "require": { 868 | "jakub-onderka/php-parallel-lint": "^0.9.2", 869 | "php": "^7.0", 870 | "squizlabs/php_codesniffer": "^2.7.0" 871 | }, 872 | "require-dev": { 873 | "consistence/coding-standard": "^0.12.0", 874 | "phing/phing": "^2.9", 875 | "phpstan/phpstan": "dev-master#372ffc86b7", 876 | "phpunit/phpunit": "^5.5", 877 | "satooshi/php-coveralls": "^1.0" 878 | }, 879 | "type": "library", 880 | "notification-url": "https://packagist.org/downloads/", 881 | "license": [ 882 | "MIT" 883 | ], 884 | "description": "Slevomat Coding Standard for PHP_CodeSniffer extends Consistence Coding Standard by providing sniffs with additional checks.", 885 | "time": "2016-09-07 19:57:10" 886 | }, 887 | { 888 | "name": "squizlabs/php_codesniffer", 889 | "version": "2.8.0", 890 | "source": { 891 | "type": "git", 892 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 893 | "reference": "86dd55a522238211f9f3631e3361703578941d9a" 894 | }, 895 | "dist": { 896 | "type": "zip", 897 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/86dd55a522238211f9f3631e3361703578941d9a", 898 | "reference": "86dd55a522238211f9f3631e3361703578941d9a", 899 | "shasum": "" 900 | }, 901 | "require": { 902 | "ext-simplexml": "*", 903 | "ext-tokenizer": "*", 904 | "ext-xmlwriter": "*", 905 | "php": ">=5.1.2" 906 | }, 907 | "require-dev": { 908 | "phpunit/phpunit": "~4.0" 909 | }, 910 | "bin": [ 911 | "scripts/phpcs", 912 | "scripts/phpcbf" 913 | ], 914 | "type": "library", 915 | "extra": { 916 | "branch-alias": { 917 | "dev-master": "2.x-dev" 918 | } 919 | }, 920 | "autoload": { 921 | "classmap": [ 922 | "CodeSniffer.php", 923 | "CodeSniffer/CLI.php", 924 | "CodeSniffer/Exception.php", 925 | "CodeSniffer/File.php", 926 | "CodeSniffer/Fixer.php", 927 | "CodeSniffer/Report.php", 928 | "CodeSniffer/Reporting.php", 929 | "CodeSniffer/Sniff.php", 930 | "CodeSniffer/Tokens.php", 931 | "CodeSniffer/Reports/", 932 | "CodeSniffer/Tokenizers/", 933 | "CodeSniffer/DocGenerators/", 934 | "CodeSniffer/Standards/AbstractPatternSniff.php", 935 | "CodeSniffer/Standards/AbstractScopeSniff.php", 936 | "CodeSniffer/Standards/AbstractVariableSniff.php", 937 | "CodeSniffer/Standards/IncorrectPatternException.php", 938 | "CodeSniffer/Standards/Generic/Sniffs/", 939 | "CodeSniffer/Standards/MySource/Sniffs/", 940 | "CodeSniffer/Standards/PEAR/Sniffs/", 941 | "CodeSniffer/Standards/PSR1/Sniffs/", 942 | "CodeSniffer/Standards/PSR2/Sniffs/", 943 | "CodeSniffer/Standards/Squiz/Sniffs/", 944 | "CodeSniffer/Standards/Zend/Sniffs/" 945 | ] 946 | }, 947 | "notification-url": "https://packagist.org/downloads/", 948 | "license": [ 949 | "BSD-3-Clause" 950 | ], 951 | "authors": [ 952 | { 953 | "name": "Greg Sherwood", 954 | "role": "lead" 955 | } 956 | ], 957 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 958 | "homepage": "http://www.squizlabs.com/php-codesniffer", 959 | "keywords": [ 960 | "phpcs", 961 | "standards" 962 | ], 963 | "time": "2017-02-02T03:30:00+00:00" 964 | } 965 | ], 966 | "aliases": [], 967 | "minimum-stability": "stable", 968 | "stability-flags": { 969 | "nette/tester": 20, 970 | "slevomat/coding-standard": 20 971 | }, 972 | "prefer-stable": false, 973 | "prefer-lowest": false, 974 | "platform": { 975 | "php": "^7.0" 976 | }, 977 | "platform-dev": [] 978 | } 979 | -------------------------------------------------------------------------------- /ruleset.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Source of code quality rules for Adeira packages 4 | */vendor/* 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/CompilerExtension.php: -------------------------------------------------------------------------------- 1 | loadFromFile($configFile); 21 | } 22 | 23 | /** 24 | * Should be called in beforeCompile(). 25 | * 26 | * @param array $mapping ['Articles' => 'Ant\Articles\Presenters\*Presenter'] 27 | */ 28 | protected function setMapping(array $mapping) 29 | { 30 | $builder = $this->getContainerBuilder(); 31 | $presenterFactory = $builder->getByType(IPresenterFactory::class); 32 | if ($presenterFactory === NULL) { 33 | throw new \Nette\InvalidStateException('Cannot find Nette\Application\IPresenterFactory implementation.'); 34 | } 35 | $builder->getDefinition($presenterFactory)->addSetup('setMapping', [$mapping]); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/ConfigurableExtensionsExtension.php: -------------------------------------------------------------------------------- 1 | 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 | 28 | public function loadConfiguration() 29 | { 30 | $ceeConfig = $this->getConfig(); // configuration of this extension (list of extensions) 31 | 32 | foreach ($ceeConfig as $name => $class) { 33 | if ($class instanceof Nette\DI\Statement) { 34 | $rc = new \ReflectionClass($class->getEntity()); 35 | $this->compiler->addExtension($name, $extension = $rc->newInstanceArgs($class->arguments)); 36 | } else { 37 | $this->compiler->addExtension($name, $extension = new $class); 38 | } 39 | 40 | $builder = $this->getContainerBuilder(); 41 | $extensionConfigFile = FALSE; 42 | if (method_exists($extension, 'provideConfig')) { 43 | $extensionConfigFile = $extension->provideConfig(); 44 | } 45 | 46 | if ($extensionConfigFile) { 47 | $extensionsExtensions = array_keys($this->compiler->getExtensions(\Nette\DI\Extensions\ExtensionsExtension::class)); 48 | 49 | if (is_array($extensionConfigFile)) { 50 | $extensionConfig = $extensionConfigFile; 51 | } elseif (is_file($extensionConfigFile)) { 52 | $extensionConfig = $this->loadFromFile($extensionConfigFile); 53 | } else { 54 | $type = gettype($extensionConfigFile); 55 | throw new \Nette\UnexpectedValueException("Method 'provideConfig' should return file name or array with configuration but '$type' given."); 56 | } 57 | 58 | foreach ($extensionsExtensions as $originalExtensionsExtensionName) { 59 | if (array_key_exists($originalExtensionsExtensionName, $extensionConfig)) { 60 | // TODO: maybe allow original extensions manipulation (?) 61 | throw new \Nette\NotSupportedException('You cannot manipulate original extensions. This operation is not supported.'); 62 | } 63 | } 64 | 65 | if (isset($extensionConfig['parameters'])) { 66 | $builder->parameters = \Nette\DI\Config\Helpers::merge( 67 | \Nette\DI\Helpers::expand($extensionConfig['parameters'], $extensionConfig['parameters'], TRUE), 68 | $builder->parameters 69 | ); 70 | } 71 | 72 | if (isset($extensionConfig['services'])) { 73 | $services = $this->expandExtensionParametersInServices( 74 | $extensionConfig['services'], 75 | $this->compiler->getConfig()[$name] ?? [] 76 | ); 77 | $extensionConfig['services'] = $services; 78 | } 79 | 80 | $this->compiler->addConfig($extensionConfig); 81 | } 82 | } 83 | } 84 | 85 | /** 86 | * Expands %%variables%% in extensions scope. 87 | * 88 | * @throws \Nette\OutOfRangeException 89 | * @throws \Nette\InvalidArgumentException 90 | */ 91 | private function expandExtensionParametersInServices($services, array $config) 92 | { 93 | return self::expand($services, $config, TRUE); 94 | } 95 | 96 | /** 97 | * Expands %%placeholders%% 98 | * 99 | * @return mixed 100 | * 101 | * @throws Nette\InvalidArgumentException 102 | * @throws Nette\OutOfRangeException 103 | * 104 | * This is basically copy of \Nette\DI\Helpers::expand 105 | */ 106 | public static function expand($var, array $params, $recursive = FALSE) 107 | { 108 | if (is_array($var)) { 109 | $res = []; 110 | foreach ($var as $key => $val) { 111 | $res[$key] = self::expand($val, $params, $recursive); 112 | } 113 | return $res; 114 | } elseif ($var instanceof Nette\DI\Statement) { 115 | return new Nette\DI\Statement( 116 | self::expand($var->getEntity(), $params, $recursive), 117 | self::expand($var->arguments, $params, $recursive) 118 | ); 119 | } elseif (!is_string($var)) { 120 | return $var; 121 | } 122 | 123 | $parts = preg_split('#%%([\w.-]*)%%#i', $var, -1, PREG_SPLIT_DELIM_CAPTURE); 124 | $res = ''; 125 | foreach ($parts as $n => $part) { 126 | if ($n % 2 === 0) { 127 | $res .= $part; 128 | } elseif ($part === '') { 129 | $res .= '%'; 130 | } elseif (isset($recursive[$part])) { 131 | throw new \Nette\InvalidArgumentException( 132 | sprintf('Circular reference detected for variables: %s.', implode(', ', array_keys($recursive))) 133 | ); 134 | } else { 135 | try { 136 | $val = Nette\Utils\Arrays::get($params, explode('.', $part)); 137 | } catch (\Nette\InvalidArgumentException $exc) { 138 | //FIXME: OutOfRangeException only because of BC 139 | throw new \Nette\OutOfRangeException( 140 | "Cannot replace %%$part%% because parameter does not exist.", 141 | 0, 142 | $exc 143 | ); 144 | } 145 | if ($recursive) { 146 | $val = self::expand($val, $params, (is_array($recursive) ? $recursive : []) + [$part => 1]); 147 | } 148 | if (strlen($part) + 4 === strlen($var)) { 149 | return $val; 150 | } 151 | if (!is_scalar($val) && $val !== NULL) { 152 | throw new \Nette\InvalidArgumentException("Unable to concatenate non-scalar parameter '$part' into '$var'."); 153 | } 154 | $res .= $val; 155 | } 156 | } 157 | return $res; 158 | } 159 | 160 | } 161 | -------------------------------------------------------------------------------- /src/GroupedNeonAdapter.php: -------------------------------------------------------------------------------- 1 | $entity) { 13 | if ($entity instanceof \Nette\Neon\Entity) { 14 | if (\Nette\Utils\Strings::endsWith($entity->value, '\\')) { 15 | if (!$this->isEntityRegisteredAsAnonymous($originalKey)) { 16 | $message = "Service with grouped classes must be anonymous. You have to remove key '$originalKey' to use this feature."; 17 | throw new \Nette\Neon\Exception($message); 18 | } 19 | 20 | unset($configKeys[$originalKey]); 21 | 22 | foreach ($entity->attributes as $attributeKey => $attribute) { 23 | if (!$this->isEntityRegisteredAsAnonymous($attributeKey)) { 24 | $message = "Grouped classes in service definition must be anonymous. Please remove key '$attributeKey'."; 25 | throw new \Nette\Neon\Exception($message); 26 | } 27 | 28 | $configKeys[] = $entity->value . $attribute; //add grouped services 29 | } 30 | } 31 | } 32 | } 33 | } 34 | } 35 | unset($configKeys); //unreference 36 | return parent::process($arr); 37 | } 38 | 39 | private function isEntityRegisteredAsAnonymous($entityKey) 40 | { 41 | return (string)(int)$entityKey === (string)$entityKey; //anonymous 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | /temp/* 2 | **.actual 3 | **.expected 4 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | commands = $commands; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /tests/helpers/CustomExtension1.php: -------------------------------------------------------------------------------- 1 | getContainerBuilder(); 38 | $builder->addDefinition($this->prefix('commands.stack')) 39 | ->setClass(\Adeira\Tests\CommandsStack::class) 40 | ->addSetup('?->addCommands(?)', [ 41 | '@self', 42 | $this->config['commands'], 43 | ]); 44 | } 45 | 46 | public function beforeCompile() 47 | { 48 | $this->setMapping(['Module' => 'App\*Module\Controllers\*Controller']); 49 | } 50 | 51 | public function getExtensions($type = NULL) 52 | { 53 | return $this->compiler->getExtensions($type); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /tests/helpers/CustomExtension2.php: -------------------------------------------------------------------------------- 1 | getContainerBuilder() 24 | ->addDefinition($this->prefix('definition')) 25 | ->setClass(\Adeira\Tests\Definition::class); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /tests/helpers/CustomExtension3.php: -------------------------------------------------------------------------------- 1 | defaultExtensions = [ 29 | 'extensions' => [\Adeira\ConfigurableExtensionsExtension::class, [TRUE]], 30 | 'application' => [Nette\Bridges\ApplicationDI\ApplicationExtension::class, ['%debugMode%', ['%appDir%'], '%tempDir%/cache']], 31 | 'http' => [Nette\Bridges\HttpDI\HttpExtension::class, ['%consoleMode%']], 32 | 'latte' => [Nette\Bridges\ApplicationDI\LatteExtension::class, ['%tempDir%/cache/latte', '%debugMode%']], 33 | 'routing' => [Nette\Bridges\ApplicationDI\RoutingExtension::class, ['%debugMode%']], 34 | ]; 35 | $configurator->setTempDirectory($tempDir); 36 | $configurator->addConfig(__DIR__ . '/config.neon'); 37 | $configurator->onCompile[] = function (Nette\Configurator $sender, Nette\DI\Compiler $compiler) { 38 | $this->compiler = $compiler; 39 | }; 40 | $dic = $configurator->createContainer(); 41 | $this->generatedContainer = $dic; 42 | } 43 | 44 | /** 45 | * Original parameters are added in config.neon: 46 | * 47 | * parameters: 48 | * k1: v1 49 | * k2: v2 50 | * 51 | * These parameters are overridden by CustomExtension1 using addConfig method. 52 | */ 53 | public function testAddConfigParameters() 54 | { 55 | $parameters = $this->generatedContainer->getParameters(); 56 | Assert::same('v1', $parameters['k1']); 57 | Assert::same('overridden', $parameters['k2']); 58 | Assert::same('v3', $parameters['k3']); 59 | } 60 | 61 | public function testExtensionParametersExpand() 62 | { 63 | //there is test in constructor of Service3 64 | $this->generatedContainer->getByType(\Adeira\Tests\Service3::class); 65 | //do not add another asserts so it will fail when the test forgets to execute an assertion 66 | } 67 | 68 | public function testExtensionParametersExpandFactory() 69 | { 70 | //there is test in constructor of Service5 71 | $this->generatedContainer->getByType(\Adeira\Tests\IService5Factory::class)->create(); 72 | //do not add another asserts so it will fail when the test forgets to execute an assertion 73 | } 74 | 75 | public function testAddConfigExtensions() 76 | { 77 | Assert::same([ 78 | 'extensions' => 'Adeira\\ConfigurableExtensionsExtension', 79 | 'application' => 'Nette\\Bridges\\ApplicationDI\\ApplicationExtension', 80 | 'http' => 'Nette\\Bridges\\HttpDI\\HttpExtension', 81 | 'latte' => 'Nette\\Bridges\\ApplicationDI\\LatteExtension', 82 | 'routing' => 'Nette\\Bridges\\ApplicationDI\\RoutingExtension', 83 | 'ext1' => 'Adeira\\Tests\\CustomExtension1', 84 | 'ext2' => 'Adeira\\Tests\\CustomExtension2', 85 | 'ext3' => 'Adeira\\Tests\\ExtensionEmptyConfig', 86 | 'ext4' => 'Adeira\\Tests\\CustomExtension4', 87 | ], array_map(function ($item) { 88 | return get_class($item); 89 | }, $this->compiler->getExtensions())); 90 | 91 | /** @var CustomExtension2 $extension */ 92 | $extension = $this->compiler->getExtensions('Adeira\Tests\CustomExtension2')['ext2']; 93 | Assert::same([ 94 | 'ek1' => 'ev1', 95 | 'ek2' => 'overridden', 96 | 'ek3' => 'ev3', 97 | ], $extension->getConfig()); 98 | } 99 | 100 | public function testAddConfigServices() 101 | { 102 | $builder = $this->compiler->getContainerBuilder(); 103 | Assert::same([ 104 | 'Nette\\Application\\Application', 105 | 'Nette\\Application\\PresenterFactory', 106 | 'Nette\\Application\\LinkGenerator', 107 | 'Nette\\Http\\RequestFactory', 108 | ['@http.requestFactory', 'createHttpRequest'], 109 | 'Nette\\Http\\Response', 110 | 'Nette\\Http\\Context', 111 | 'Latte\\Engine', 112 | 'Nette\\Bridges\\ApplicationLatte\\TemplateFactory', 113 | 'Nette\\Application\\Routers\\RouteList', 114 | 'Adeira\\Tests\\CommandsStack', 115 | 'Adeira\\Tests\\Definition', 116 | 'Adeira\\Tests\\Service2', //overridden (named service) 117 | 'Adeira\\Tests\\Service4', //registered in config.neon 118 | 'Adeira\\Tests\\Service5', //registered later in extension 119 | 'Adeira\\Tests\\Service3', //registered later in extension 120 | 'Nette\\DI\\Container', 121 | ], array_map(function (\Nette\DI\ServiceDefinition $item) { 122 | return $item->getFactory()->getEntity(); 123 | }, array_values($builder->getDefinitions()))); 124 | } 125 | 126 | public function testSetMapping() 127 | { 128 | /** @var \Nette\Application\IPresenterFactory $presenterFactory */ 129 | $presenterFactory = $this->generatedContainer->getService('application.presenterFactory'); 130 | Assert::type('Nette\Application\PresenterFactory', $presenterFactory); 131 | 132 | $reflectionClass = new \ReflectionClass($presenterFactory); 133 | $reflectionProperty = $reflectionClass->getProperty('mapping'); 134 | $reflectionProperty->setAccessible(TRUE); 135 | Assert::same([ 136 | '*' => ['a\\', '*b\\', '*c'], 137 | 'Nette' => ['NetteModule\\', '*\\', '*Presenter'], 138 | 'Module' => ['App\\', '*Module\\', 'Controllers\\*Controller'], 139 | ], $reflectionProperty->getValue($presenterFactory)); 140 | } 141 | 142 | public function testRegisteredCommands() 143 | { 144 | $stack = $this->generatedContainer->getService('ext1.commands.stack'); 145 | Assert::same([ 146 | 'com1_ext1', 147 | 'com2_ext1', 148 | 'com3_ext1', 149 | 'com1_ext2', 150 | 'com2_ext2', 151 | ], $stack->commands); 152 | } 153 | 154 | } 155 | 156 | (new CompilerExtension)->run(); 157 | -------------------------------------------------------------------------------- /tests/src/DeprecatedAddConfig.phpt: -------------------------------------------------------------------------------- 1 | addConfig(\Tester\FileMock::create('', 'neon')); 27 | } 28 | 29 | }; 30 | $extension->setCompiler(new class extends \Nette\DI\Compiler 31 | { 32 | //empty mock 33 | }, 'compiler'); 34 | $extension->loadConfiguration(); 35 | }, E_USER_NOTICE, 'Adeira\CompilerExtension::addConfig is deprecated. Use Adeira\ConfigurableExtensionsExtension instead.'); 36 | } 37 | 38 | } 39 | 40 | (new DeprecatedAddConfig)->run(); 41 | -------------------------------------------------------------------------------- /tests/src/ExtensionsManipulation.phpt: -------------------------------------------------------------------------------- 1 | addExtension('extensions', new \Adeira\ConfigurableExtensionsExtension); 22 | $compiler->addConfig([ 23 | 'extensions' => [ 24 | new class extends \Nette\DI\CompilerExtension { 25 | 26 | public function provideConfig() 27 | { 28 | $config = <<compile(); 40 | }, \Nette\NotSupportedException::class, 'You cannot manipulate original extensions. This operation is not supported.'); 41 | } 42 | 43 | } 44 | 45 | (new ExtensionsManipulation)->run(); 46 | -------------------------------------------------------------------------------- /tests/src/GroupedNeonAdapterTest.phpt: -------------------------------------------------------------------------------- 1 | addAdapter($extension = 'neon', GroupedNeonAdapter::class); 21 | $configuration = << [ 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 = <<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 = <<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(); 85 | -------------------------------------------------------------------------------- /tests/src/ProvideConfigSources.phpt: -------------------------------------------------------------------------------- 1 | addExtension('extensions', new \Adeira\ConfigurableExtensionsExtension); 21 | $compiler->addExtension('ext', new \Adeira\Tests\CustomExtension3); 22 | $compiler->addConfig([ 23 | 'extensions' => [ 24 | new class extends \Nette\DI\CompilerExtension { 25 | 26 | public function provideConfig() 27 | { 28 | return ['ext' => ['tadá' => 'tudum']]; 29 | } 30 | 31 | }, 32 | ], 33 | ]); 34 | $compiler->compile(); 35 | Assert::same([ 36 | 'tadá' => 'tudum', 37 | ], $compiler->getExtensions(\Adeira\Tests\CustomExtension3::class)['ext']->getConfig()); 38 | } 39 | 40 | public function testThatStringThrowsException() 41 | { 42 | $compiler = new \Nette\DI\Compiler; 43 | $compiler->addExtension('extensions', new \Adeira\ConfigurableExtensionsExtension); 44 | $compiler->addExtension('ext', new \Adeira\Tests\CustomExtension3); 45 | $compiler->addConfig([ 46 | 'extensions' => [ 47 | new class extends \Nette\DI\CompilerExtension { 48 | 49 | public function provideConfig() 50 | { 51 | return 'string'; 52 | } 53 | 54 | }, 55 | ], 56 | ]); 57 | Assert::exception(function() use ($compiler) { 58 | $compiler->compile(); 59 | }, \Nette\UnexpectedValueException::class, "Method 'provideConfig' should return file name or array with configuration but 'string' given."); 60 | } 61 | 62 | } 63 | 64 | (new ProvideConfigSources)->run(); 65 | -------------------------------------------------------------------------------- /tests/src/UnknownExtensionParameter.phpt: -------------------------------------------------------------------------------- 1 | addExtension('extensions', new \Adeira\ConfigurableExtensionsExtension); 20 | $config = <<loadConfig(FileMock::create($config, 'neon')); 25 | Assert::throws( 26 | function () use ($compiler) { 27 | $compiler->compile(); 28 | }, 29 | \OutOfRangeException::class, 30 | 'Cannot replace %%%%thisExtensionParameterDoesNotExist%%%% because parameter does not exist.' 31 | ); 32 | } 33 | 34 | } 35 | 36 | (new UnknownExtensionParameter)->run(); 37 | -------------------------------------------------------------------------------- /tests/src/config.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | k1: v1 3 | k2: v2 4 | 5 | services: 6 | - Adeira\Tests\Service4 7 | named: Adeira\Tests\Service1 8 | 9 | extensions: 10 | ext1: Adeira\Tests\CustomExtension1 11 | ext2: Adeira\Tests\CustomExtension2 12 | ext3: Adeira\Tests\ExtensionEmptyConfig 13 | ext4: Adeira\Tests\CustomExtension4 14 | 15 | ext1: 16 | numericExtensionParameter: 159753 17 | falseExtensionParameter: no 18 | nullExtensionParameter: NULL 19 | arrayKey: 20 | arrayValue: kv 21 | commands: 22 | - 'com1_ext1' 23 | - 'com2_ext1' 24 | - 'com3_ext1' 25 | 26 | ext2: 27 | ek1: ev1 28 | ek2: ev2 29 | 30 | application: 31 | scanDirs: no 32 | scanComposer: no 33 | mapping: 34 | *: a\*b\*c 35 | -------------------------------------------------------------------------------- /tests/temp/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | --------------------------------------------------------------------------------