From 323cc1aa346da3aa2d48d8d86c91997e4e96127a Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Fri, 8 Dec 2023 18:28:17 +0100 Subject: [PATCH] fix: installing beta packages #3792 --- extensions/package-manager/extend.php | 25 +++--- .../admin/components/ConfigureComposer.tsx | 83 +++++++++++++++++++ .../js/src/admin/components/SettingsPage.tsx | 34 ++++++++ .../package-manager/js/src/admin/index.tsx | 16 ---- .../less/admin/ControlSection.less | 4 + extensions/package-manager/locale/en.yml | 11 +++ .../ConfigureComposerController.php | 79 ++++++++++++++++++ .../Api/Controller/GlobalUpdateController.php | 2 - .../src/Command/CheckForUpdatesHandler.php | 4 + .../src/Command/GlobalUpdateHandler.php | 2 - .../src/Composer/ComposerAdapter.php | 41 +++++++-- .../src/ConfigureComposerValidator.php | 19 +++++ .../src/PackageManagerServiceProvider.php | 8 +- 13 files changed, 284 insertions(+), 44 deletions(-) create mode 100644 extensions/package-manager/js/src/admin/components/ConfigureComposer.tsx create mode 100755 extensions/package-manager/src/Api/Controller/ConfigureComposerController.php create mode 100644 extensions/package-manager/src/ConfigureComposerValidator.php diff --git a/extensions/package-manager/extend.php b/extensions/package-manager/extend.php index 0a617e8e06..c506da8fd7 100755 --- a/extensions/package-manager/extend.php +++ b/extensions/package-manager/extend.php @@ -12,13 +12,6 @@ use Flarum\Extend; use Flarum\Foundation\Paths; use Flarum\Frontend\Document; -use Flarum\PackageManager\Exception\ComposerCommandFailedException; -use Flarum\PackageManager\Exception\ComposerRequireFailedException; -use Flarum\PackageManager\Exception\ComposerUpdateFailedException; -use Flarum\PackageManager\Exception\ExceptionHandler; -use Flarum\PackageManager\Exception\MajorUpdateFailedException; -use Flarum\PackageManager\Settings\LastUpdateCheck; -use Flarum\PackageManager\Settings\LastUpdateRun; use Illuminate\Contracts\Queue\Queue; use Illuminate\Queue\SyncQueue; @@ -32,7 +25,8 @@ ->post('/package-manager/minor-update', 'package-manager.minor-update', Api\Controller\MinorUpdateController::class) ->post('/package-manager/major-update', 'package-manager.major-update', Api\Controller\MajorUpdateController::class) ->post('/package-manager/global-update', 'package-manager.global-update', Api\Controller\GlobalUpdateController::class) - ->get('/package-manager-tasks', 'package-manager.tasks.index', Api\Controller\ListTasksController::class), + ->get('/package-manager-tasks', 'package-manager.tasks.index', Api\Controller\ListTasksController::class) + ->post('/package-manager/composer', 'package-manager.composer', Api\Controller\ConfigureComposerController::class), (new Extend\Frontend('admin')) ->css(__DIR__.'/less/admin.less') @@ -52,18 +46,19 @@ new Extend\Locales(__DIR__.'/locale'), (new Extend\Settings()) - ->default(LastUpdateCheck::key(), json_encode(LastUpdateCheck::default())) - ->default(LastUpdateRun::key(), json_encode(LastUpdateRun::default())) - ->default('flarum-package-manager.queue_jobs', false), + ->default(Settings\LastUpdateCheck::key(), json_encode(Settings\LastUpdateCheck::default())) + ->default(Settings\LastUpdateRun::key(), json_encode(Settings\LastUpdateRun::default())) + ->default('flarum-package-manager.queue_jobs', false) + ->default('flarum-package-manager.minimum_stability', 'stable'), (new Extend\ServiceProvider) ->register(PackageManagerServiceProvider::class), (new Extend\ErrorHandling) - ->handler(ComposerCommandFailedException::class, ExceptionHandler::class) - ->handler(ComposerRequireFailedException::class, ExceptionHandler::class) - ->handler(ComposerUpdateFailedException::class, ExceptionHandler::class) - ->handler(MajorUpdateFailedException::class, ExceptionHandler::class) + ->handler(Exception\ComposerCommandFailedException::class, Exception\ExceptionHandler::class) + ->handler(Exception\ComposerRequireFailedException::class, Exception\ExceptionHandler::class) + ->handler(Exception\ComposerUpdateFailedException::class, Exception\ExceptionHandler::class) + ->handler(Exception\MajorUpdateFailedException::class, Exception\ExceptionHandler::class) ->status('extension_already_installed', 409) ->status('extension_not_installed', 409) ->status('no_new_major_version', 409), diff --git a/extensions/package-manager/js/src/admin/components/ConfigureComposer.tsx b/extensions/package-manager/js/src/admin/components/ConfigureComposer.tsx new file mode 100644 index 0000000000..30d180fd93 --- /dev/null +++ b/extensions/package-manager/js/src/admin/components/ConfigureComposer.tsx @@ -0,0 +1,83 @@ +import app from 'flarum/admin/app'; +import type Mithril from 'mithril'; +import Component, { type ComponentAttrs } from 'flarum/common/Component'; +import { CommonSettingsItemOptions, type SettingsComponentOptions } from '@flarum/core/src/admin/components/AdminPage'; +import AdminPage from 'flarum/admin/components/AdminPage'; +import type ItemList from 'flarum/common/utils/ItemList'; +import Stream from 'flarum/common/utils/Stream'; +import Button from 'flarum/common/components/Button'; + +export interface IConfigureComposer extends ComponentAttrs { + buildSettingComponent: (entry: ((this: this) => Mithril.Children) | SettingsComponentOptions) => Mithril.Children; +} + +export default class ConfigureComposer extends Component { + protected settings: Record> = {}; + protected loading: boolean = false; + + oninit(vnode: Mithril.Vnode) { + super.oninit(vnode); + + this.submit(); + } + + view(): Mithril.Children { + return ( +
+ {this.attrs.buildSettingComponent.call(this, { + setting: 'minimum-stability', + label: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.label'), + help: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.help'), + type: 'select', + options: { + stable: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.options.stable'), + RC: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.options.rc'), + beta: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.options.beta'), + alpha: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.options.alpha'), + dev: app.translator.trans('flarum-package-manager.admin.composer.minimum_stability.options.dev'), + }, + })} + +
+ +
+
+ ); + } + + customSettingComponents(): ItemList<(attributes: CommonSettingsItemOptions) => Mithril.Children> { + return AdminPage.prototype.customSettingComponents(); + } + + setting(key: string) { + return this.settings[key] ?? (() => null); + } + + submit() { + this.loading = true; + + const configuration: any = {}; + + Object.keys(this.settings).forEach((key) => { + configuration[key] = this.settings[key](); + }); + + app + .request({ + method: 'POST', + url: app.forum.attribute('apiUrl') + '/package-manager/composer', + body: { data: configuration }, + }) + .then(({ data }: any) => { + Object.keys(data).forEach((key) => { + this.settings[key] = Stream(data[key]); + }); + }) + .finally(() => { + this.loading = false; + m.redraw(); + }); + } +} diff --git a/extensions/package-manager/js/src/admin/components/SettingsPage.tsx b/extensions/package-manager/js/src/admin/components/SettingsPage.tsx index 6328ff9572..0caf823370 100644 --- a/extensions/package-manager/js/src/admin/components/SettingsPage.tsx +++ b/extensions/package-manager/js/src/admin/components/SettingsPage.tsx @@ -5,8 +5,42 @@ import ItemList from 'flarum/common/utils/ItemList'; import QueueSection from './QueueSection'; import ControlSection from './ControlSection'; +import ConfigureComposer from './ConfigureComposer'; +import Alert from 'flarum/common/components/Alert'; +import listItems from 'flarum/common/helpers/listItems'; export default class SettingsPage extends ExtensionPage { + content() { + const settings = app.extensionData.getSettings(this.extension.id); + + const warnings = [app.translator.trans('flarum-package-manager.admin.settings.access_warning')]; + + if (app.data.debugEnabled) warnings.push(app.translator.trans('flarum-package-manager.admin.settings.debug_mode_warning')); + + return ( +
+
+
+ +
    {listItems(warnings)}
+
+
+ {settings ? ( +
+
+ {settings.map(this.buildSettingComponent.bind(this))} +
{this.submitButton()}
+
+ +
+ ) : ( +

{app.translator.trans('core.admin.extension.no_settings')}

+ )} +
+
+ ); + } + sections(vnode: Mithril.VnodeDOM): ItemList { const items = super.sections(vnode); diff --git a/extensions/package-manager/js/src/admin/index.tsx b/extensions/package-manager/js/src/admin/index.tsx index a9b4869118..45d8b0c1fe 100755 --- a/extensions/package-manager/js/src/admin/index.tsx +++ b/extensions/package-manager/js/src/admin/index.tsx @@ -20,22 +20,6 @@ app.initializers.add('flarum-package-manager', (app) => { app.extensionData .for('flarum-package-manager') - .registerSetting(() => ( -
- - {app.translator.trans('flarum-package-manager.admin.settings.access_warning')} - -
- )) - .registerSetting(() => - app.data.debugEnabled ? ( -
- - {app.translator.trans('flarum-package-manager.admin.settings.debug_mode_warning')} - -
- ) : null - ) .registerSetting({ setting: 'flarum-package-manager.queue_jobs', label: app.translator.trans('flarum-package-manager.admin.settings.queue_jobs'), diff --git a/extensions/package-manager/less/admin/ControlSection.less b/extensions/package-manager/less/admin/ControlSection.less index 489c738c47..b74c877e09 100644 --- a/extensions/package-manager/less/admin/ControlSection.less +++ b/extensions/package-manager/less/admin/ControlSection.less @@ -164,3 +164,7 @@ .PackageManager-controlSection .container { max-width: 1030px; } + +.PackageManager-primaryWarning ul { + margin: 0; +} diff --git a/extensions/package-manager/locale/en.yml b/extensions/package-manager/locale/en.yml index 6bdff719ed..e9232721c5 100755 --- a/extensions/package-manager/locale/en.yml +++ b/extensions/package-manager/locale/en.yml @@ -1,5 +1,16 @@ flarum-package-manager: admin: + composer: + minimum_stability: + label: Minimum Stability + help: The type of packages allowed to be installed. Do not change this unless you know what you are doing. + options: + stable: Stable (Recommended) + rc: Release Candidate + beta: Beta + alpha: Alpha + dev: Dev + exceptions: composer_command_failure: Failed to execute. Check the composer logs in storage/logs/composer. extension_already_installed: Extension is already installed. diff --git a/extensions/package-manager/src/Api/Controller/ConfigureComposerController.php b/extensions/package-manager/src/Api/Controller/ConfigureComposerController.php new file mode 100755 index 0000000000..16f399f951 --- /dev/null +++ b/extensions/package-manager/src/Api/Controller/ConfigureComposerController.php @@ -0,0 +1,79 @@ +validator = $validator; + $this->paths = $paths; + } + + public function handle(ServerRequestInterface $request): ResponseInterface + { + $actor = RequestUtil::getActor($request); + $data = Arr::only(Arr::get($request->getParsedBody(), 'data'), $this->configurable); + + $actor->assertAdmin(); + + $this->validator->assertValid($data); + $composerJson = $this->readComposerJson(); + + if (! empty($data)) { + foreach ($data as $key => $value) { + Arr::set($composerJson, $key, $value); + } + + $this->writeComposerJson($composerJson); + } + + return new JsonResponse([ + 'data' => Arr::only($composerJson, $this->configurable), + ]); + } + + protected function readComposerJson() + { + $composerJson = file_get_contents($this->paths->base.'/composer.json'); + $composerJson = json_decode($composerJson, true); + + return $composerJson; + } + + protected function writeComposerJson($composerJson) + { + $composerJson = json_encode($composerJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + file_put_contents($this->paths->base.'/composer.json', $composerJson); + } +} diff --git a/extensions/package-manager/src/Api/Controller/GlobalUpdateController.php b/extensions/package-manager/src/Api/Controller/GlobalUpdateController.php index 8a6022e75a..158618e5d9 100755 --- a/extensions/package-manager/src/Api/Controller/GlobalUpdateController.php +++ b/extensions/package-manager/src/Api/Controller/GlobalUpdateController.php @@ -37,8 +37,6 @@ public function handle(ServerRequestInterface $request): ResponseInterface { $actor = RequestUtil::getActor($request); - dd('wat'); - $response = $this->bus->dispatch( new GlobalUpdate($actor) ); diff --git a/extensions/package-manager/src/Command/CheckForUpdatesHandler.php b/extensions/package-manager/src/Command/CheckForUpdatesHandler.php index 1f3e8baf22..8cd96d1d0c 100755 --- a/extensions/package-manager/src/Command/CheckForUpdatesHandler.php +++ b/extensions/package-manager/src/Command/CheckForUpdatesHandler.php @@ -77,6 +77,10 @@ public function handle(CheckForUpdates $command) foreach ($firstOutput['installed'] as &$mainPackageUpdate) { $mainPackageUpdate['latest-minor'] = $mainPackageUpdate['latest-major'] = null; + if ($mainPackageUpdate['latest-status'] === 'up-to-date') { + continue; + } + if (isset($mainPackageUpdate['latest-status']) && $mainPackageUpdate['latest-status'] === 'update-possible' && Util::isMajorUpdate($mainPackageUpdate['version'], $mainPackageUpdate['latest'])) { $mainPackageUpdate['latest-major'] = $mainPackageUpdate['latest']; diff --git a/extensions/package-manager/src/Command/GlobalUpdateHandler.php b/extensions/package-manager/src/Command/GlobalUpdateHandler.php index 41c4bc98d8..6b59351a83 100644 --- a/extensions/package-manager/src/Command/GlobalUpdateHandler.php +++ b/extensions/package-manager/src/Command/GlobalUpdateHandler.php @@ -62,8 +62,6 @@ public function handle(GlobalUpdate $command) '--with-all-dependencies' => true, ]; - dd($this->config->inDebugMode()); - $output = $this->composer->run( new ArrayInput($input), $command->task ?? null diff --git a/extensions/package-manager/src/Composer/ComposerAdapter.php b/extensions/package-manager/src/Composer/ComposerAdapter.php index eac5fcd068..815ddbf2d1 100644 --- a/extensions/package-manager/src/Composer/ComposerAdapter.php +++ b/extensions/package-manager/src/Composer/ComposerAdapter.php @@ -15,6 +15,7 @@ use Flarum\PackageManager\OutputLogger; use Flarum\PackageManager\Support\Util; use Flarum\PackageManager\Task\Task; +use Flarum\Settings\SettingsRepositoryInterface; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\BufferedOutput; @@ -34,36 +35,41 @@ class ComposerAdapter private $logger; /** - * @var BufferedOutput + * @var Paths */ - private $output; + private $paths; /** - * @var Paths + * @var SettingsRepositoryInterface */ - private $paths; + private $settings; - public function __construct(Application $application, OutputLogger $logger, Paths $paths) + public function __construct(Application $application, OutputLogger $logger, Paths $paths, SettingsRepositoryInterface $settings) { $this->application = $application; $this->logger = $logger; $this->paths = $paths; - $this->output = new BufferedOutput(); + $this->settings = $settings; } public function run(InputInterface $input, ?Task $task = null): ComposerOutput { $this->application->resetComposer(); + // Pre-configure composer + $this->configureComposer(); + + $output = new BufferedOutput(); + // This hack is necessary so that relative path repositories are resolved properly. $currDir = getcwd(); chdir($this->paths->base); - $exitCode = $this->application->run($input, $this->output); + $exitCode = $this->application->run($input, $output); chdir($currDir); // @phpstan-ignore-next-line $command = Util::readableConsoleInput($input); - $output = $this->output->fetch(); + $output = $output->fetch(); if ($task) { $task->update(compact('command', 'output')); @@ -78,4 +84,23 @@ public static function setPhpVersion(string $phpVersion) { Config::$defaultConfig['platform']['php'] = $phpVersion; } + + private function configureComposer(): void + { + $composerJson = json_decode(file_get_contents($this->paths->base.'/composer.json'), true); + $dirty = false; + + // Set the minimum stability if not already set. + $minimumStability = $this->settings->get('flarum-package-manager.minimum_stability'); + $composerMinimumStability = $composerJson['minimum-stability'] ?? null; + + if ($minimumStability && $composerMinimumStability !== $minimumStability) { + $composerJson['minimum-stability'] = $minimumStability; + $dirty = true; + } + + if ($dirty) { + file_put_contents($this->paths->base.'/composer.json', json_encode($composerJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + } + } } diff --git a/extensions/package-manager/src/ConfigureComposerValidator.php b/extensions/package-manager/src/ConfigureComposerValidator.php new file mode 100644 index 0000000000..184b52fb92 --- /dev/null +++ b/extensions/package-manager/src/ConfigureComposerValidator.php @@ -0,0 +1,19 @@ + ['sometimes', 'in:stable,RC,beta,alpha,dev'], + ]; +} diff --git a/extensions/package-manager/src/PackageManagerServiceProvider.php b/extensions/package-manager/src/PackageManagerServiceProvider.php index afa26cfbbf..50aa155b5f 100755 --- a/extensions/package-manager/src/PackageManagerServiceProvider.php +++ b/extensions/package-manager/src/PackageManagerServiceProvider.php @@ -22,6 +22,7 @@ use Flarum\PackageManager\Extension\Event\Updated; use Flarum\PackageManager\Listener\ClearCacheAfterUpdate; use Flarum\PackageManager\Listener\ReCheckForUpdates; +use Flarum\Settings\SettingsRepositoryInterface; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Events\Dispatcher; use Monolog\Formatter\LineFormatter; @@ -52,7 +53,12 @@ public function register() @ini_set('memory_limit', '1G'); @set_time_limit(5 * 60); - return new ComposerAdapter($composer, $container->make(OutputLogger::class), $container->make(Paths::class)); + return new ComposerAdapter( + $composer, + $container->make(OutputLogger::class), + $container->make(Paths::class), + $container->make(SettingsRepositoryInterface::class) + ); }); $this->container->alias(ComposerAdapter::class, 'flarum.composer');