diff --git a/src/Core/Config/Middleware/ExtensionMiddleware.php b/src/Core/Config/Middleware/ExtensionMiddleware.php index f41da6d9275..f05ae866f75 100644 --- a/src/Core/Config/Middleware/ExtensionMiddleware.php +++ b/src/Core/Config/Middleware/ExtensionMiddleware.php @@ -63,6 +63,11 @@ protected function getExtraConfig($class, $classConfig, $excludeMiddleware) $extensions = $extensionSourceConfig['extensions']; foreach ($extensions as $extension) { + // Allow removing extensions via yaml config by setting named extension config to null + if ($extension === null) { + continue; + } + list($extensionClass, $extensionArgs) = ClassInfo::parse_class_spec($extension); // Strip service name specifier $extensionClass = strtok($extensionClass ?? '', '.'); diff --git a/src/Core/Extensible.php b/src/Core/Extensible.php index 37e79a1850d..f041caf4a0c 100644 --- a/src/Core/Extensible.php +++ b/src/Core/Extensible.php @@ -553,6 +553,11 @@ public function getExtensionInstances() if ($extensions) { foreach ($extensions as $extension) { + // Allow removing extensions via yaml config by setting named extension config to null + if ($extension === null) { + continue; + } + $name = $extension; // Allow service names of the form "%$ServiceName" if (substr($name ?? '', 0, 2) == '%$') { diff --git a/tests/php/Core/ExtensionTest.php b/tests/php/Core/ExtensionTest.php new file mode 100644 index 00000000000..4b3baefd14b --- /dev/null +++ b/tests/php/Core/ExtensionTest.php @@ -0,0 +1,48 @@ +setAccessible(true); + $reflectionProperty->setValue([]); + // Add named extension config like we would in yaml + Config::modify()->merge(DataObject::class, 'extensions', ['NamedExtension' => NamedExtension::class]); + } + + public function testHasNamedExtension() + { + $this->assertTrue(DataObject::has_extension(NamedExtension::class)); + $instance = new DataObject(); + $this->assertTrue($instance->hasMethod('getTestValue')); + $this->assertSame('test', $instance->getTestValue()); + } + + public function testRemoveNamedExtension() + { + Config::modify()->merge(DataObject::class, 'extensions', ['NamedExtension' => null]); + $this->assertFalse(DataObject::has_extension(NamedExtension::class)); + $instance = new DataObject(); + $this->assertFalse($instance->hasMethod('getTestValue')); + } + + public function testRemoveNamedExtensionException() + { + Config::modify()->merge(DataObject::class, 'extensions', ['NamedExtension' => null]); + $instance = new DataObject(); + $this->expectException(BadMethodCallException::class); + $instance->getTestValue(); + } +} diff --git a/tests/php/Core/ExtensionTest/NamedExtension.php b/tests/php/Core/ExtensionTest/NamedExtension.php new file mode 100644 index 00000000000..2314c42045c --- /dev/null +++ b/tests/php/Core/ExtensionTest/NamedExtension.php @@ -0,0 +1,14 @@ +