1
0
mirror of https://github.com/flarum/core.git synced 2025-08-05 16:07:34 +02:00

feat: allow specifying extensions when installing an instance (#3655)

* feat: allow specifying extensions when installing an instance

Useful when doing migrations where more than the default extensions are required to migrate the data to flarum. This allows quickly spinning up a flarum database with the necessary schema.

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

* fix: consider dependency graph before running migrations

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>
This commit is contained in:
Sami Mazouz
2022-11-06 19:43:13 +01:00
committed by GitHub
parent f005b9e031
commit 69311ae689
4 changed files with 32 additions and 19 deletions

View File

@@ -211,7 +211,7 @@ class Extension implements Arrayable
/** /**
* Get the list of flarum extensions that this extension depends on. * Get the list of flarum extensions that this extension depends on.
* *
* @param array $extensionSet: An associative array where keys are the composer package names * @param array<string, mixed> $extensionSet: An associative array where keys are the composer package names
* of installed extensions. Used to figure out which dependencies * of installed extensions. Used to figure out which dependencies
* are flarum extensions. * are flarum extensions.
* @internal * @internal

View File

@@ -441,11 +441,12 @@ class ExtensionManager
* *
* @param Extension[] $extensionList * @param Extension[] $extensionList
* *
* @return array with 2 keys: 'valid' points to an ordered array of \Flarum\Extension\Extension * @return array{valid: Extension[], missingDependencies: array<string, string[]>, circularDependencies: string[]}
* 'missingDependencies' points to an associative array of extensions that could not be resolved due * 'valid' points to an ordered array of \Flarum\Extension\Extension
* to missing dependencies, in the format extension id => array of missing dependency IDs. * 'missingDependencies' points to an associative array of extensions that could not be resolved due
* 'circularDependencies' points to an array of extensions ids of extensions * to missing dependencies, in the format extension id => array of missing dependency IDs.
* that cannot be processed due to circular dependencies * 'circularDependencies' points to an array of extensions ids of extensions
* that cannot be processed due to circular dependencies
* *
* @internal * @internal
*/ */
@@ -471,6 +472,7 @@ class ExtensionManager
$extensionIdMapping[$extension->getId()] = $extension; $extensionIdMapping[$extension->getId()] = $extension;
} }
/** @var Extension $extension */
foreach ($extensionList as $extension) { foreach ($extensionList as $extension) {
$optionalDependencies = array_filter($extension->getOptionalDependencyIds(), function ($id) use ($extensionIdMapping) { $optionalDependencies = array_filter($extension->getOptionalDependencyIds(), function ($id) use ($extensionIdMapping) {
return array_key_exists($id, $extensionIdMapping); return array_key_exists($id, $extensionIdMapping);

View File

@@ -24,6 +24,7 @@ class FileDataProvider implements DataProviderInterface
protected $databaseConfiguration = []; protected $databaseConfiguration = [];
protected $adminUser = []; protected $adminUser = [];
protected $settings = []; protected $settings = [];
protected $extensions = [];
public function __construct(InputInterface $input) public function __construct(InputInterface $input)
{ {
@@ -48,6 +49,7 @@ class FileDataProvider implements DataProviderInterface
$this->databaseConfiguration = $configuration['databaseConfiguration'] ?? []; $this->databaseConfiguration = $configuration['databaseConfiguration'] ?? [];
$this->adminUser = $configuration['adminUser'] ?? []; $this->adminUser = $configuration['adminUser'] ?? [];
$this->settings = $configuration['settings'] ?? []; $this->settings = $configuration['settings'] ?? [];
$this->extensions = explode(',', $configuration['extensions'] ?? '');
} else { } else {
throw new Exception('Configuration file does not exist.'); throw new Exception('Configuration file does not exist.');
} }
@@ -60,7 +62,8 @@ class FileDataProvider implements DataProviderInterface
->baseUrl(BaseUrl::fromString($this->baseUrl)) ->baseUrl(BaseUrl::fromString($this->baseUrl))
->databaseConfig($this->getDatabaseConfiguration()) ->databaseConfig($this->getDatabaseConfiguration())
->adminUser($this->getAdminUser()) ->adminUser($this->getAdminUser())
->settings($this->settings); ->settings($this->settings)
->extensions($this->extensions);
} }
private function getDatabaseConfiguration(): DatabaseConfig private function getDatabaseConfiguration(): DatabaseConfig

View File

@@ -12,6 +12,7 @@ namespace Flarum\Install\Steps;
use Flarum\Database\DatabaseMigrationRepository; use Flarum\Database\DatabaseMigrationRepository;
use Flarum\Database\Migrator; use Flarum\Database\Migrator;
use Flarum\Extension\Extension; use Flarum\Extension\Extension;
use Flarum\Extension\ExtensionManager;
use Flarum\Install\Step; use Flarum\Install\Step;
use Flarum\Settings\DatabaseSettingsRepository; use Flarum\Settings\DatabaseSettingsRepository;
use Illuminate\Database\ConnectionInterface; use Illuminate\Database\ConnectionInterface;
@@ -80,7 +81,7 @@ class EnableBundledExtensions implements Step
public function run() public function run()
{ {
$extensions = $this->loadExtensions(); $extensions = ExtensionManager::resolveExtensionOrder($this->loadExtensions()->all())['valid'];
foreach ($extensions as $extension) { foreach ($extensions as $extension) {
$extension->migrate($this->getMigrator()); $extension->migrate($this->getMigrator());
@@ -89,14 +90,15 @@ class EnableBundledExtensions implements Step
); );
} }
(new DatabaseSettingsRepository($this->database))->set( $extensionNames = json_encode(array_map(function (Extension $extension) {
'extensions_enabled', return $extension->getId();
$extensions->keys()->toJson() }, $extensions));
);
(new DatabaseSettingsRepository($this->database))->set('extensions_enabled', $extensionNames);
} }
/** /**
* @return \Illuminate\Support\Collection * @return \Illuminate\Support\Collection<Extension>
*/ */
private function loadExtensions() private function loadExtensions()
{ {
@@ -106,7 +108,7 @@ class EnableBundledExtensions implements Step
// Composer 2.0 changes the structure of the installed.json manifest // Composer 2.0 changes the structure of the installed.json manifest
$installed = $installed['packages'] ?? $installed; $installed = $installed['packages'] ?? $installed;
return (new Collection($installed)) $installedExtensions = (new Collection($installed))
->filter(function ($package) { ->filter(function ($package) {
return Arr::get($package, 'type') == 'flarum-extension'; return Arr::get($package, 'type') == 'flarum-extension';
})->filter(function ($package) { })->filter(function ($package) {
@@ -120,13 +122,19 @@ class EnableBundledExtensions implements Step
$extension->setVersion(Arr::get($package, 'version')); $extension->setVersion(Arr::get($package, 'version'));
return $extension; return $extension;
})->filter(function (Extension $extension) {
return in_array($extension->getId(), $this->enabledExtensions);
})->sortBy(function (Extension $extension) {
return $extension->getTitle();
})->mapWithKeys(function (Extension $extension) { })->mapWithKeys(function (Extension $extension) {
return [$extension->getId() => $extension]; return [$extension->name => $extension];
}); });
return $installedExtensions->filter(function (Extension $extension) {
return in_array($extension->getId(), $this->enabledExtensions);
})->map(function (Extension $extension) use ($installedExtensions) {
$extension->calculateDependencies($installedExtensions->map(function () {
return true;
})->toArray());
return $extension;
});
} }
private function getMigrator(): Migrator private function getMigrator(): Migrator