1
0
Fork 0

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

pull/11326/head
Nicolas Grekas 2023-02-10 14:01:11 +01:00 committed by GitHub
parent 67f5892a5d
commit 2a8efc7a85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 5 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

@ -198,7 +198,8 @@ class PluginManager
} }
} }
if (!$this->isPluginAllowed($package->getName(), $isGlobalPlugin)) { $extra = $package->getExtra();
if (!$this->isPluginAllowed($package->getName(), $isGlobalPlugin, isset($extra['plugin-optional']) && true === $extra['plugin-optional'])) {
$this->io->writeError('Skipped loading "'.$package->getName() . '" '.($isGlobalPlugin ? '(installed globally) ' : '').'as it is not in config.allow-plugins', true, IOInterface::DEBUG); $this->io->writeError('Skipped loading "'.$package->getName() . '" '.($isGlobalPlugin ? '(installed globally) ' : '').'as it is not in config.allow-plugins', true, IOInterface::DEBUG);
return; return;
@ -394,10 +395,13 @@ 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)) { } else {
$extra = $sourcePackage->getExtra();
if (!$this->isPluginAllowed($sourcePackage->getName(), $isGlobalPlugin, isset($extra['plugin-optional']) && true === $extra['plugin-optional'])) {
$this->io->writeError('Skipped loading "'.get_class($plugin).' from '.$sourcePackage->getName() . '" '.($isGlobalPlugin ? '(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 ? '(installed globally) ' : '').' as it is not in config.allow-plugins', true, IOInterface::DEBUG);
return; return;
} }
}
$details = array(); $details = array();
if ($sourcePackage) { if ($sourcePackage) {
@ -693,9 +697,10 @@ class PluginManager
* *
* @param string $package * @param string $package
* @param bool $isGlobalPlugin * @param bool $isGlobalPlugin
* @param bool $optional
* @return bool * @return bool
*/ */
public function isPluginAllowed($package, $isGlobalPlugin) public function isPluginAllowed($package, $isGlobalPlugin, $optional = false)
{ {
if ($isGlobalPlugin) { if ($isGlobalPlugin) {
$rules = &$this->allowGlobalPluginRules; $rules = &$this->allowGlobalPluginRules;
@ -763,6 +768,8 @@ class PluginManager
break; break;
} }
} }
} elseif ($optional) {
return false;
} }
throw new PluginBlockedException( throw new PluginBlockedException(