@@ -79,6 +79,10 @@ class Configurator
7979 /** @var array<string, mixed> */
8080 private array $ defaultParameters ;
8181
82+ /** @var string[] extension names to exclude from auto-discovery */
83+ private array $ excludeExtensions = [];
84+ private bool $ autoDiscovery = true ;
85+
8286
8387 public function __construct ()
8488 {
@@ -180,6 +184,21 @@ public function addServices(array $services): static
180184 }
181185
182186
187+ /**
188+ * Disables auto-discovery of extensions from installed packages.
189+ * Without arguments disables completely, with arguments disables only specified extensions.
190+ */
191+ public function excludeExtension (string ...$ extensions ): static
192+ {
193+ if (count ($ extensions ) === 0 ) {
194+ $ this ->autoDiscovery = false ;
195+ } else {
196+ $ this ->excludeExtensions = array_merge ($ this ->excludeExtensions , $ extensions );
197+ }
198+ return $ this ;
199+ }
200+
201+
183202 /** @return array<string, mixed> */
184203 protected function getDefaultParameters (): array
185204 {
@@ -265,6 +284,30 @@ public function addConfig(string|array $config): static
265284 }
266285
267286
287+ /**
288+ * Discovers extensions from installed Composer packages.
289+ * Reads extra.nette.di-extensions from vendor/composer/installed.json
290+ * @return array<string, string|array{class: class-string, args: array}>
291+ */
292+ protected function discoverExtensions (): array
293+ {
294+ $ vendorDir = $ this ->staticParameters ['vendorDir ' ] ?? null ;
295+ if (!$ vendorDir || !is_file ($ installedJson = $ vendorDir . '/composer/installed.json ' )) {
296+ return [];
297+ }
298+
299+ $ installed = json_decode (Nette \Utils \FileSystem::read ($ installedJson ), true );
300+ $ extensions = [];
301+ foreach ($ installed ['packages ' ] ?? [] as $ package ) {
302+ foreach ($ package ['extra ' ]['nette ' ]['di-extensions ' ] ?? [] as $ name => $ def ) {
303+ $ extensions [$ name ] = is_string ($ def ) ? $ def : [$ def ['class ' ], $ def ['args ' ] ?? []];
304+ }
305+ }
306+
307+ return $ extensions ;
308+ }
309+
310+
268311 /**
269312 * Returns system DI container.
270313 */
@@ -326,7 +369,10 @@ public function generateContainer(DI\Compiler $compiler): void
326369 $ builder = $ compiler ->getContainerBuilder ();
327370 $ builder ->addExcludedClasses ($ this ->autowireExcludedClasses );
328371
329- foreach ($ this ->defaultExtensions as $ name => $ extension ) {
372+ $ extensions = $ this ->autoDiscovery ? $ this ->discoverExtensions () : [];
373+ $ extensions = array_merge ($ extensions , $ this ->defaultExtensions );
374+ $ extensions = array_diff_key ($ extensions , $ this ->excludeExtensions );
375+ foreach ($ extensions as $ name => $ extension ) {
330376 [$ class , $ args ] = is_string ($ extension )
331377 ? [$ extension , []]
332378 : $ extension ;
@@ -358,6 +404,7 @@ protected function generateContainerKey(): array
358404 class_exists (ClassLoader::class) // composer update
359405 ? filemtime ((new \ReflectionClass (ClassLoader::class))->getFilename ())
360406 : null ,
407+ $ this ->autoDiscovery ? $ this ->excludeExtensions : null ,
361408 ];
362409 }
363410
0 commit comments