mirror of
https://github.com/flarum/core.git
synced 2025-08-10 18:35:56 +02:00
wip
This commit is contained in:
@@ -63,6 +63,7 @@ class AdminServiceProvider extends AbstractServiceProvider
|
||||
HttpMiddleware\ReferrerPolicyHeader::class,
|
||||
HttpMiddleware\ContentTypeOptionsHeader::class,
|
||||
Middleware\DisableBrowserCache::class,
|
||||
Middleware\GatherDebugInformation::class,
|
||||
];
|
||||
});
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
46
framework/core/src/Foundation/Info/Renderer/CliRenderer.php
Normal file
46
framework/core/src/Foundation/Info/Renderer/CliRenderer.php
Normal 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
|
||||
{
|
||||
}
|
||||
}
|
17
framework/core/src/Foundation/Info/RendererInterface.php
Normal file
17
framework/core/src/Foundation/Info/RendererInterface.php
Normal 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;
|
||||
|
||||
}
|
37
framework/core/src/Foundation/Info/Report.php
Normal file
37
framework/core/src/Foundation/Info/Report.php
Normal 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();
|
||||
}
|
||||
}
|
21
framework/core/src/Foundation/Info/Section/CoreVersion.php
Normal file
21
framework/core/src/Foundation/Info/Section/CoreVersion.php
Normal 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)
|
||||
);
|
||||
}
|
||||
}
|
26
framework/core/src/Foundation/Info/Section/Debug.php
Normal file
26
framework/core/src/Foundation/Info/Section/Debug.php
Normal 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.");
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
59
framework/core/src/Foundation/Info/Section/Features.php
Normal file
59
framework/core/src/Foundation/Info/Section/Features.php
Normal 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;
|
||||
}
|
||||
}
|
27
framework/core/src/Foundation/Info/Section/PHP.php
Normal file
27
framework/core/src/Foundation/Info/Section/PHP.php
Normal 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())
|
||||
);
|
||||
}
|
||||
}
|
8
framework/core/src/Foundation/Info/SectionInterface.php
Normal file
8
framework/core/src/Foundation/Info/SectionInterface.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Flarum\Foundation\Info;
|
||||
|
||||
interface SectionInterface
|
||||
{
|
||||
public function __invoke(RendererInterface $renderer): void;
|
||||
}
|
Reference in New Issue
Block a user