1
0
mirror of https://github.com/flarum/core.git synced 2025-08-10 10:24:46 +02:00
This commit is contained in:
Daniël Klabbers
2024-12-31 17:17:21 +01:00
parent 9fe17b3c24
commit cebb1f27f5
14 changed files with 369 additions and 87 deletions

View File

@@ -63,6 +63,7 @@ class AdminServiceProvider extends AbstractServiceProvider
HttpMiddleware\ReferrerPolicyHeader::class,
HttpMiddleware\ContentTypeOptionsHeader::class,
Middleware\DisableBrowserCache::class,
Middleware\GatherDebugInformation::class,
];
});

View File

@@ -0,0 +1,43 @@
<?php
namespace Flarum\Admin\Middleware;
use Flarum\Settings\SettingsRepositoryInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface as Middleware;
use Psr\Http\Server\RequestHandlerInterface as Handler;
class GatherDebugInformation implements Middleware
{
public function __construct(protected SettingsRepositoryInterface $settings)
{
}
public function process(Request $request, Handler $handler): Response
{
// Read current web user, so we can compare that against CLI executions,
// these often cause file permission issues.
$user = $this->settings->get('core.debug.web_user');
$currentUser = get_current_user();
if ($user !== $currentUser) {
$this->settings->set(
"core.web_user",
$currentUser
);
}
// Read the opcache situation, this is only visible in web.
$opcache = $this->settings->get('core.debug.opcache_enabled');
$opcacheStatus = function_exists('opcache_get_configuration')
&& opcache_get_configuration() !== false;
if ($opcache !== $opcacheStatus) {
$this->settings->set(
'core.debug.opcache_enabled',
$opcacheStatus
);
}
return $handler->handle($request);
}
}

View File

@@ -40,18 +40,21 @@ class ApplicationInfoProvider
return count($this->schedule->events()) > 0;
}
public function getSchedulerStatus(): string
public function getSchedulerStatus(bool $translated = true): string
{
$status = $this->settings->get('schedule.last_run');
if (! $status) {
return $this->translator->trans('core.admin.dashboard.status.scheduler.never-run');
$key = match(true) {
! $status => 'never-run',
Carbon::parse($status) > Carbon::now()->subMinutes(5) => 'active',
default => 'inactive'
};
if ($translated) {
return $this->translator->trans("core.admin.dashboard.status.scheduler.$key");
}
// If the schedule has not run in the last 5 minutes, mark it as inactive.
return Carbon::parse($status) > Carbon::now()->subMinutes(5)
? $this->translator->trans('core.admin.dashboard.status.scheduler.active')
: $this->translator->trans('core.admin.dashboard.status.scheduler.inactive');
return $key;
}
public function identifyQueueDriver(): string

View File

@@ -14,7 +14,10 @@ use Flarum\Extension\ExtensionManager;
use Flarum\Foundation\Application;
use Flarum\Foundation\ApplicationInfoProvider;
use Flarum\Foundation\Config;
use Flarum\Foundation\Info\Renderer\CliRenderer;
use Flarum\Foundation\Info\Report;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Contracts\Container\Container;
use Illuminate\Database\ConnectionInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
@@ -23,11 +26,7 @@ use Symfony\Component\Console\Helper\TableStyle;
class InfoCommand extends AbstractCommand
{
public function __construct(
protected ExtensionManager $extensions,
protected Config $config,
protected SettingsRepositoryInterface $settings,
protected ConnectionInterface $db,
protected ApplicationInfoProvider $appInfo
protected Container $container
) {
parent::__construct();
}
@@ -41,83 +40,13 @@ class InfoCommand extends AbstractCommand
protected function fire(): int
{
$coreVersion = $this->findPackageVersion(__DIR__.'/../../../', Application::VERSION);
$this->output->writeln("<info>Flarum core:</info> $coreVersion");
$report = new Report(
new CliRenderer($this->output),
$this->container
);
$this->output->writeln('<info>PHP version:</info> '.$this->appInfo->identifyPHPVersion());
$this->output->writeln('<info>'.$this->appInfo->identifyDatabaseDriver().' version:</info> '.$this->appInfo->identifyDatabaseVersion());
$phpExtensions = implode(', ', get_loaded_extensions());
$this->output->writeln("<info>Loaded extensions:</info> $phpExtensions");
$this->getExtensionTable()->render();
$this->output->writeln('<info>Base URL:</info> '.$this->config->url());
$this->output->writeln('<info>Installation path:</info> '.getcwd());
$this->output->writeln('<info>Queue driver:</info> '.$this->appInfo->identifyQueueDriver());
$this->output->writeln('<info>Session driver:</info> '.$this->appInfo->identifySessionDriver());
if ($this->appInfo->scheduledTasksRegistered()) {
$this->output->writeln('<info>Scheduler status:</info> '.$this->appInfo->getSchedulerStatus());
}
$this->output->writeln('<info>Mail driver:</info> '.$this->settings->get('mail_driver', 'unknown'));
$this->output->writeln('<info>Debug mode:</info> '.($this->config->inDebugMode() ? '<error>ON</error>' : 'off'));
if ($this->config->inDebugMode()) {
$this->output->writeln('');
$this->error(
"Don't forget to turn off debug mode! It should never be turned on in a production system."
);
}
$report->render();
return Command::SUCCESS;
}
private function getExtensionTable(): Table
{
$table = (new Table($this->output))
->setHeaders([
['Flarum Extensions'],
['ID', 'Version', 'Commit']
])->setStyle(
(new TableStyle)->setCellHeaderFormat('<info>%s</info>')
);
foreach ($this->extensions->getEnabledExtensions() as $extension) {
$table->addRow([
$extension->getId(),
$extension->getVersion(),
$this->findPackageVersion($extension->getPath())
]);
}
return $table;
}
/**
* Try to detect a package's exact version.
*
* If the package seems to be a Git version, we extract the currently
* checked out commit using the command line.
*/
private function findPackageVersion(string $path, ?string $fallback = null): ?string
{
if (file_exists("$path/.git")) {
$cwd = getcwd();
chdir($path);
$output = [];
$status = null;
exec('git rev-parse HEAD 2>&1', $output, $status);
chdir($cwd);
if ($status == 0) {
return isset($fallback) ? "$fallback ($output[0])" : $output[0];
}
}
return $fallback;
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace Flarum\Foundation\Info\Concerns;
trait PackageVersionFromPath
{
/**
* Try to detect a package's exact version.
*
* If the package seems to be a Git version, we extract the currently
* checked out commit using the command line.
*/
private function findPackageVersion(string $path, ?string $fallback = null): ?string
{
if (file_exists("$path/.git")) {
$cwd = getcwd();
chdir($path);
$output = [];
$status = null;
exec('git rev-parse HEAD 2>&1', $output, $status);
chdir($cwd);
if ($status == 0) {
return isset($fallback) ? "$fallback ($output[0])" : $output[0];
}
}
return $fallback;
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace Flarum\Foundation\Info\Renderer;
use Flarum\Foundation\Info\RendererInterface;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableStyle;
use Symfony\Component\Console\Output\OutputInterface;
class CliRenderer implements RendererInterface
{
public function __construct(protected OutputInterface $output)
{}
public function heading(string $title): void
{
$this->output->writeln("<bg=gray,options=bold>$title</>");
}
public function keyValue(string $key, mixed $value): void
{
$this->output->writeln("<info>$key:</info> $value");
}
public function table(array $headers, array $rows): void
{
$table = (new Table($this->output))
->setHeaders($headers)->setStyle(
(new TableStyle)->setCellHeaderFormat('<info>%s</info>')
);
foreach ($rows as $row) {
$table->addRow($row);
}
$table->render();
}
public function open(): void
{
}
public function close(): void
{
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Flarum\Foundation\Info;
interface RendererInterface
{
public function heading(string $title): void;
public function keyValue(string $key, mixed $value): void;
public function table(array $headers, array $rows): void;
public function open(): void;
public function close(): void;
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Flarum\Foundation\Info;
use Illuminate\Contracts\Container\Container;
class Report
{
protected array $sections = [
Section\CoreVersion::class,
Section\PHP::class,
Section\EnabledExtensions::class,
Section\Features::class,
Section\Debug::class,
];
public function __construct(
protected RendererInterface $renderer,
protected Container $container
)
{}
public function render(): void
{
$sections = $this->sections;
$this->renderer->open();
foreach($sections as &$section) {
$section = $this->container->make($section);
$section($this->renderer);
}
$this->renderer->close();
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace Flarum\Foundation\Info\Section;
use Flarum\Foundation\Application;
use Flarum\Foundation\Info\Concerns\PackageVersionFromPath;
use Flarum\Foundation\Info\RendererInterface;
use Flarum\Foundation\Info\SectionInterface;
class CoreVersion implements SectionInterface
{
use PackageVersionFromPath;
public function __invoke(RendererInterface $renderer): void
{
$renderer->keyValue(
'Flarum Core',
$this->findPackageVersion(__DIR__.'/../../../../', Application::VERSION)
);
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace Flarum\Foundation\Info\Section;
use Flarum\Foundation\Config;
use Flarum\Foundation\Info\RendererInterface;
use Flarum\Foundation\Info\SectionInterface;
class Debug implements SectionInterface
{
public function __construct(protected Config $config)
{
}
public function __invoke(RendererInterface $renderer): void
{
$renderer->keyValue(
'Debug mode',
$this->config->inDebugMode() ? 'on' : 'off'
);
if ($this->config->inDebugMode()) {
$renderer->heading("Debug mode should not be enabled in production; this will cause javascript and stylesheets to be recompiled on each visit.");
}
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Flarum\Foundation\Info\Section;
use Flarum\Extension\Extension;
use Flarum\Extension\ExtensionManager;
use Flarum\Foundation\Info\Concerns\PackageVersionFromPath;
use Flarum\Foundation\Info\RendererInterface;
use Flarum\Foundation\Info\SectionInterface;
class EnabledExtensions implements SectionInterface
{
use PackageVersionFromPath;
public function __construct(protected ExtensionManager $extensions)
{
}
public function __invoke(RendererInterface $renderer): void
{
$rows = collect($this->extensions->getEnabledExtensions())
->map(fn (Extension $extension) => [
$extension->getId(),
$this->findPackageVersion($extension->getPath(), $extension->getVersion())
])
->toArray();
$renderer->table([
['Flarum Extensions'],
['ID', 'Version']
], $rows);
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace Flarum\Foundation\Info\Section;
use Flarum\Foundation\ApplicationInfoProvider;
use Flarum\Foundation\Info\RendererInterface;
use Flarum\Foundation\Info\SectionInterface;
use Flarum\Mail\NullDriver;
use Illuminate\Contracts\Container\Container;
class Features implements SectionInterface
{
public function __construct(
protected ApplicationInfoProvider $appInfo,
protected Container $container
)
{
}
public function __invoke(RendererInterface $renderer): void
{
$renderer->keyValue(
'Scheduler required',
$this->appInfo->scheduledTasksRegistered() ? 'yes' : 'no'
);
$renderer->keyValue(
'Scheduler status',
$this->appInfo->getSchedulerStatus(translated: false)
);
$renderer->keyValue(
'Queue driver',
$this->appInfo->identifyQueueDriver()
);
$renderer->keyValue(
'Session driver',
$this->appInfo->identifySessionDriver()
);
$renderer->keyValue(
'Mail driver',
$this->mail()
);
}
protected function mail()
{
$driver = $this->container->make('mail.driver');
$configured = $this->container->make('flarum.mail.configured_driver');
if ($driver instanceof NullDriver) {
$configured .= " (not active)";
}
return $configured;
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace Flarum\Foundation\Info\Section;
use Flarum\Foundation\ApplicationInfoProvider;
use Flarum\Foundation\Info\RendererInterface;
use Flarum\Foundation\Info\SectionInterface;
class PHP implements SectionInterface
{
public function __construct(protected ApplicationInfoProvider $appInfo)
{
}
public function __invoke(RendererInterface $renderer): void
{
$renderer->keyValue(
'PHP version',
$this->appInfo->identifyPHPVersion()
);
$renderer->keyValue(
'PHP extensions',
implode(', ', get_loaded_extensions())
);
}
}

View File

@@ -0,0 +1,8 @@
<?php
namespace Flarum\Foundation\Info;
interface SectionInterface
{
public function __invoke(RendererInterface $renderer): void;
}