fix: circular dependencies disable all involved extensions (#3785)

This commit is contained in:
Sami Mazouz 2023-04-12 21:59:06 +01:00 committed by GitHub
parent 1247a7f1dd
commit e8c867dcac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 1 deletions

View File

@ -605,6 +605,7 @@ core:
# These translations are displayed as error messages.
error:
circular_dependencies_message: "Circular dependencies detected: {extensions}. Aborting. Please disable one of the extensions and try again."
dependent_extensions_message: "Cannot disable {extension} until the following dependent extensions are disabled: {extensions}"
extension_initialiation_failed_message: "{extension} failed to initialize, check the browser console for further information."
generic_message: "Oops! Something went wrong. Please reload the page and try again."

View File

@ -0,0 +1,25 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Extension\Exception;
use Exception;
use Flarum\Extension\ExtensionManager;
class CircularDependenciesException extends Exception
{
public $circular_dependencies;
public function __construct(array $circularDependencies)
{
$this->circular_dependencies = $circularDependencies;
parent::__construct('Circular dependencies detected: '.implode(', ', ExtensionManager::pluckTitles($circularDependencies)).' - aborting. Please fix this by disabling the extensions that are causing the circular dependencies.');
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Extension\Exception;
use Flarum\Extension\ExtensionManager;
use Flarum\Foundation\ErrorHandling\HandledError;
class CircularDependenciesExceptionHandler
{
public function handle(CircularDependenciesException $e): HandledError
{
return (new HandledError(
$e,
'circular_dependencies',
409
))->withDetails($this->errorDetails($e));
}
protected function errorDetails(CircularDependenciesException $e): array
{
return [[
'extensions' => ExtensionManager::pluckTitles($e->circular_dependencies),
]];
}
}

View File

@ -15,6 +15,7 @@ use Flarum\Extension\Event\Disabling;
use Flarum\Extension\Event\Enabled;
use Flarum\Extension\Event\Enabling;
use Flarum\Extension\Event\Uninstalled;
use Flarum\Extension\Exception\CircularDependenciesException;
use Flarum\Foundation\Paths;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Contracts\Container\Container;
@ -157,6 +158,13 @@ class ExtensionManager
return $this->extensions;
}
public function getExtensionsById(array $ids): Collection
{
return $this->getExtensions()->filter(function (Extension $extension) use ($ids) {
return in_array($extension->getId(), $ids);
});
}
/**
* Loads an Extension with all information.
*
@ -397,10 +405,19 @@ class ExtensionManager
* Persist the currently enabled extensions.
*
* @param array $enabledExtensions
* @throws CircularDependenciesException
*/
protected function setEnabledExtensions(array $enabledExtensions)
{
$sortedEnabled = static::resolveExtensionOrder($enabledExtensions)['valid'];
$resolved = static::resolveExtensionOrder($enabledExtensions);
if (! empty($resolved['circularDependencies'])) {
throw new Exception\CircularDependenciesException(
$this->getExtensionsById($resolved['circularDependencies'])->values()->all()
);
}
$sortedEnabled = $resolved['valid'];
$sortedEnabledIds = array_map(function (Extension $extension) {
return $extension->getId();

View File

@ -58,6 +58,7 @@ class ErrorServiceProvider extends AbstractServiceProvider
return [
IlluminateValidationException::class => Handling\ExceptionHandler\IlluminateValidationExceptionHandler::class,
ValidationException::class => Handling\ExceptionHandler\ValidationExceptionHandler::class,
ExtensionException\CircularDependenciesException::class => ExtensionException\CircularDependenciesExceptionHandler::class,
ExtensionException\DependentExtensionsException::class => ExtensionException\DependentExtensionsExceptionHandler::class,
ExtensionException\MissingDependenciesException::class => ExtensionException\MissingDependenciesExceptionHandler::class,
];