1
0
Fork 0

Add extra.plugin-optional to auto-disable plugins in non-interactive mode (#11315)

pull/11318/head
Nicolas Grekas 2023-02-10 13:19:41 +01:00 committed by GitHub
parent e6ef9eb332
commit 4b94e55b03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 3 deletions

View File

@ -332,6 +332,20 @@ in your composer.json to hint to Composer that the plugin should be activated as
as possible to prevent any bad side-effects from Composer assuming packages are installed as possible to prevent any bad side-effects from Composer assuming packages are installed
in another location than they actually are. in another location than they actually are.
### plugin-optional
Because Composer plugins can be used to perform actions which are necessary for installing
a working application, like modifying which path files get stored in, skipping required
plugins unintentionally can result in broken applications. So, in non-interactive mode,
Composer will fail if a new plugin is not listed in ["allow-plugins"](../06-config.md#allow-plugins)
to force users to decide if they want to execute the plugin, to avoid silent failures.
As of Composer 2.5.3, you can use the setting `{"extra": {"plugin-optional": true}}` on
your plugin, to tell Composer that skipping the plugin has no catastrophic consequences,
and it can safely be disabled in non-interactive mode if it is not yet listed in
"allow-plugins". The next interactive run of Composer will still prompt users to choose if
they want to enable or disable the plugin.
## Plugin Autoloading ## Plugin Autoloading
Due to plugins being loaded by Composer at runtime, and to ensure that plugins which Due to plugins being loaded by Composer at runtime, and to ensure that plugins which

View File

@ -187,7 +187,7 @@ class PluginManager
} }
} }
if (!$this->isPluginAllowed($package->getName(), $isGlobalPlugin)) { if (!$this->isPluginAllowed($package->getName(), $isGlobalPlugin, $package->getExtra()['plugin-optional'] ?? false)) {
$this->io->writeError('Skipped loading "'.$package->getName() . '" '.($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '').'as it is not in config.allow-plugins', true, IOInterface::DEBUG); $this->io->writeError('Skipped loading "'.$package->getName() . '" '.($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '').'as it is not in config.allow-plugins', true, IOInterface::DEBUG);
return; return;
@ -370,7 +370,7 @@ class PluginManager
if ($sourcePackage === null) { if ($sourcePackage === null) {
trigger_error('Calling PluginManager::addPlugin without $sourcePackage is deprecated, if you are using this please get in touch with us to explain the use case', E_USER_DEPRECATED); trigger_error('Calling PluginManager::addPlugin without $sourcePackage is deprecated, if you are using this please get in touch with us to explain the use case', E_USER_DEPRECATED);
} elseif (!$this->isPluginAllowed($sourcePackage->getName(), $isGlobalPlugin)) { } elseif (!$this->isPluginAllowed($sourcePackage->getName(), $isGlobalPlugin, $sourcePackage->getExtra()['plugin-optional'] ?? false)) {
$this->io->writeError('Skipped loading "'.get_class($plugin).' from '.$sourcePackage->getName() . '" '.($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '').' as it is not in config.allow-plugins', true, IOInterface::DEBUG); $this->io->writeError('Skipped loading "'.get_class($plugin).' from '.$sourcePackage->getName() . '" '.($isGlobalPlugin || $this->runningInGlobalDir ? '(installed globally) ' : '').' as it is not in config.allow-plugins', true, IOInterface::DEBUG);
return; return;
@ -656,7 +656,7 @@ class PluginManager
/** /**
* @internal * @internal
*/ */
public function isPluginAllowed(string $package, bool $isGlobalPlugin): bool public function isPluginAllowed(string $package, bool $isGlobalPlugin, bool $optional = false): bool
{ {
if ($isGlobalPlugin) { if ($isGlobalPlugin) {
$rules = &$this->allowGlobalPluginRules; $rules = &$this->allowGlobalPluginRules;
@ -733,6 +733,8 @@ class PluginManager
break; break;
} }
} }
} elseif ($optional) {
return false;
} }
throw new PluginBlockedException( throw new PluginBlockedException(