From 4ecff8dd80d610a23aaa2d073670c92dbb0122ee Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Mon, 10 Oct 2022 15:35:53 +0100 Subject: [PATCH 1/2] 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 --- framework/core/src/Install/Console/FileDataProvider.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/framework/core/src/Install/Console/FileDataProvider.php b/framework/core/src/Install/Console/FileDataProvider.php index 5655cbbee9..356ebefefc 100644 --- a/framework/core/src/Install/Console/FileDataProvider.php +++ b/framework/core/src/Install/Console/FileDataProvider.php @@ -24,6 +24,7 @@ class FileDataProvider implements DataProviderInterface protected $databaseConfiguration = []; protected $adminUser = []; protected $settings = []; + protected $extensions = []; public function __construct(InputInterface $input) { @@ -48,6 +49,7 @@ public function __construct(InputInterface $input) $this->databaseConfiguration = $configuration['databaseConfiguration'] ?? []; $this->adminUser = $configuration['adminUser'] ?? []; $this->settings = $configuration['settings'] ?? []; + $this->extensions = explode(',', $configuration['extensions'] ?? ''); } else { throw new Exception('Configuration file does not exist.'); } @@ -60,7 +62,8 @@ public function configure(Installation $installation): Installation ->baseUrl(BaseUrl::fromString($this->baseUrl)) ->databaseConfig($this->getDatabaseConfiguration()) ->adminUser($this->getAdminUser()) - ->settings($this->settings); + ->settings($this->settings) + ->extensions($this->extensions); } private function getDatabaseConfiguration(): DatabaseConfig From 3d2c2ce94281fd294cb9bd9ee1edc3ed8441a139 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Mon, 10 Oct 2022 17:19:09 +0100 Subject: [PATCH 2/2] fix: consider dependency graph before running migrations Signed-off-by: Sami Mazouz --- framework/core/src/Extension/Extension.php | 2 +- .../core/src/Extension/ExtensionManager.php | 12 ++++--- .../Install/Steps/EnableBundledExtensions.php | 32 ++++++++++++------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/framework/core/src/Extension/Extension.php b/framework/core/src/Extension/Extension.php index dfe664d22b..6856d9214d 100644 --- a/framework/core/src/Extension/Extension.php +++ b/framework/core/src/Extension/Extension.php @@ -211,7 +211,7 @@ public function setVersion($version) /** * 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 $extensionSet: An associative array where keys are the composer package names * of installed extensions. Used to figure out which dependencies * are flarum extensions. * @internal diff --git a/framework/core/src/Extension/ExtensionManager.php b/framework/core/src/Extension/ExtensionManager.php index d4ecefed17..5e33db2bb3 100644 --- a/framework/core/src/Extension/ExtensionManager.php +++ b/framework/core/src/Extension/ExtensionManager.php @@ -441,11 +441,12 @@ public static function pluckTitles(array $exts) * * @param Extension[] $extensionList * - * @return array with 2 keys: 'valid' points to an ordered array of \Flarum\Extension\Extension - * 'missingDependencies' points to an associative array of extensions that could not be resolved due - * to missing dependencies, in the format extension id => array of missing dependency IDs. - * 'circularDependencies' points to an array of extensions ids of extensions - * that cannot be processed due to circular dependencies + * @return array{valid: Extension[], missingDependencies: array, circularDependencies: string[]} + * 'valid' points to an ordered array of \Flarum\Extension\Extension + * 'missingDependencies' points to an associative array of extensions that could not be resolved due + * to missing dependencies, in the format extension id => array of missing dependency IDs. + * 'circularDependencies' points to an array of extensions ids of extensions + * that cannot be processed due to circular dependencies * * @internal */ @@ -471,6 +472,7 @@ public static function resolveExtensionOrder($extensionList) $extensionIdMapping[$extension->getId()] = $extension; } + /** @var Extension $extension */ foreach ($extensionList as $extension) { $optionalDependencies = array_filter($extension->getOptionalDependencyIds(), function ($id) use ($extensionIdMapping) { return array_key_exists($id, $extensionIdMapping); diff --git a/framework/core/src/Install/Steps/EnableBundledExtensions.php b/framework/core/src/Install/Steps/EnableBundledExtensions.php index 5abcdf14e8..b26ec5087d 100644 --- a/framework/core/src/Install/Steps/EnableBundledExtensions.php +++ b/framework/core/src/Install/Steps/EnableBundledExtensions.php @@ -12,6 +12,7 @@ use Flarum\Database\DatabaseMigrationRepository; use Flarum\Database\Migrator; use Flarum\Extension\Extension; +use Flarum\Extension\ExtensionManager; use Flarum\Install\Step; use Flarum\Settings\DatabaseSettingsRepository; use Illuminate\Database\ConnectionInterface; @@ -80,7 +81,7 @@ public function getMessage() public function run() { - $extensions = $this->loadExtensions(); + $extensions = ExtensionManager::resolveExtensionOrder($this->loadExtensions()->all())['valid']; foreach ($extensions as $extension) { $extension->migrate($this->getMigrator()); @@ -89,14 +90,15 @@ public function run() ); } - (new DatabaseSettingsRepository($this->database))->set( - 'extensions_enabled', - $extensions->keys()->toJson() - ); + $extensionNames = json_encode(array_map(function (Extension $extension) { + return $extension->getId(); + }, $extensions)); + + (new DatabaseSettingsRepository($this->database))->set('extensions_enabled', $extensionNames); } /** - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ private function loadExtensions() { @@ -106,7 +108,7 @@ private function loadExtensions() // Composer 2.0 changes the structure of the installed.json manifest $installed = $installed['packages'] ?? $installed; - return (new Collection($installed)) + $installedExtensions = (new Collection($installed)) ->filter(function ($package) { return Arr::get($package, 'type') == 'flarum-extension'; })->filter(function ($package) { @@ -120,13 +122,19 @@ private function loadExtensions() $extension->setVersion(Arr::get($package, 'version')); return $extension; - })->filter(function (Extension $extension) { - return in_array($extension->getId(), $this->enabledExtensions); - })->sortBy(function (Extension $extension) { - return $extension->getTitle(); })->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