mirror of
https://github.com/flarum/framework.git
synced 2025-01-21 00:36:32 +08:00
Split up Site into several classes
Depending on the state of the Flarum installation (installed, not installed, currently upgrading, maintenance mode), we should enable different sets of service providers. For example, during installation we should not resolve a setting repository from the container. This new architecture lets us do so, but we can easily (and cleanly) register a different implementation during installation. This should prevent problems such as #1370 in the future.
This commit is contained in:
parent
7a6e208554
commit
5b821b21b1
|
@ -12,74 +12,37 @@
|
|||
namespace Flarum\Console;
|
||||
|
||||
use Flarum\Console\Event\Configuring;
|
||||
use Flarum\Database\Console\GenerateMigrationCommand;
|
||||
use Flarum\Database\Console\MigrateCommand;
|
||||
use Flarum\Database\Console\ResetCommand;
|
||||
use Flarum\Foundation\Application;
|
||||
use Flarum\Foundation\Console\CacheClearCommand;
|
||||
use Flarum\Foundation\Console\InfoCommand;
|
||||
use Flarum\Foundation\Site;
|
||||
use Flarum\Install\Console\InstallCommand;
|
||||
use Flarum\Install\InstallServiceProvider;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Symfony\Component\Console\Application as ConsoleApplication;
|
||||
|
||||
class Server
|
||||
{
|
||||
/**
|
||||
* @param Site $site
|
||||
* @return Server
|
||||
*/
|
||||
public static function fromSite(Site $site)
|
||||
{
|
||||
return new static($site->boot());
|
||||
}
|
||||
protected $commands;
|
||||
|
||||
public function __construct(Application $app)
|
||||
public function __construct(array $commands)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->commands = $commands;
|
||||
}
|
||||
|
||||
public function listen()
|
||||
{
|
||||
$console = $this->getConsoleApplication();
|
||||
$console = new ConsoleApplication('Flarum', Application::VERSION);
|
||||
|
||||
foreach ($this->commands as $command) {
|
||||
$console->add($command);
|
||||
}
|
||||
|
||||
$this->extend($console);
|
||||
|
||||
exit($console->run());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ConsoleApplication
|
||||
*/
|
||||
protected function getConsoleApplication()
|
||||
private function extend(ConsoleApplication $console)
|
||||
{
|
||||
$console = new ConsoleApplication('Flarum', $this->app->version());
|
||||
$app = Application::getInstance();
|
||||
|
||||
$this->app->register(InstallServiceProvider::class);
|
||||
|
||||
$commands = [
|
||||
InstallCommand::class,
|
||||
MigrateCommand::class,
|
||||
ResetCommand::class,
|
||||
GenerateMigrationCommand::class,
|
||||
];
|
||||
|
||||
if ($this->app->isInstalled()) {
|
||||
$commands = array_merge($commands, [
|
||||
InfoCommand::class,
|
||||
CacheClearCommand::class
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($commands as $command) {
|
||||
$console->add($this->app->make(
|
||||
$command,
|
||||
['config' => $this->app->isInstalled() ? $this->app->make('flarum.config') : []]
|
||||
));
|
||||
}
|
||||
|
||||
$events = $this->app->make(Dispatcher::class);
|
||||
$events->fire(new Configuring($this->app, $console));
|
||||
|
||||
return $console;
|
||||
$events = $app->make(Dispatcher::class);
|
||||
$events->fire(new Configuring($app, $console));
|
||||
}
|
||||
}
|
||||
|
|
25
src/Foundation/AppInterface.php
Normal file
25
src/Foundation/AppInterface.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Foundation;
|
||||
|
||||
interface AppInterface
|
||||
{
|
||||
/**
|
||||
* @return \Psr\Http\Server\RequestHandlerInterface
|
||||
*/
|
||||
public function getRequestHandler();
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\Console\Command\Command[]
|
||||
*/
|
||||
public function getConsoleCommands();
|
||||
}
|
132
src/Foundation/InstalledApp.php
Normal file
132
src/Foundation/InstalledApp.php
Normal file
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Foundation;
|
||||
|
||||
use Flarum\Database\Console\GenerateMigrationCommand;
|
||||
use Flarum\Database\Console\MigrateCommand;
|
||||
use Flarum\Database\Console\ResetCommand;
|
||||
use Flarum\Foundation\Console\CacheClearCommand;
|
||||
use Flarum\Foundation\Console\InfoCommand;
|
||||
use Flarum\Http\Middleware\DispatchRoute;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
use Zend\Diactoros\Response\HtmlResponse;
|
||||
use Zend\Stratigility\MiddlewarePipe;
|
||||
use function Zend\Stratigility\middleware;
|
||||
use function Zend\Stratigility\path;
|
||||
|
||||
class InstalledApp implements AppInterface
|
||||
{
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
protected $laravel;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
public function __construct(Application $laravel, array $config)
|
||||
{
|
||||
$this->laravel = $laravel;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Psr\Http\Server\RequestHandlerInterface
|
||||
*/
|
||||
public function getRequestHandler()
|
||||
{
|
||||
if ($this->inMaintenanceMode()) {
|
||||
return $this->getMaintenanceMiddleware();
|
||||
} elseif ($this->needsUpdate()) {
|
||||
return $this->getUpdaterMiddleware();
|
||||
}
|
||||
|
||||
$pipe = new MiddlewarePipe;
|
||||
|
||||
$pipe->pipe($this->subPath('api', 'flarum.api.middleware'));
|
||||
$pipe->pipe($this->subPath('admin', 'flarum.admin.middleware'));
|
||||
$pipe->pipe($this->subPath('', 'flarum.forum.middleware'));
|
||||
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
private function inMaintenanceMode(): bool
|
||||
{
|
||||
return $this->config['offline'] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Psr\Http\Server\RequestHandlerInterface
|
||||
*/
|
||||
private function getMaintenanceMiddleware()
|
||||
{
|
||||
$pipe = new MiddlewarePipe;
|
||||
|
||||
$pipe->pipe(middleware(function () {
|
||||
// FIXME: Fix path to 503.html
|
||||
// TODO: FOR API render JSON-API error document for HTTP 503
|
||||
return new HtmlResponse(
|
||||
file_get_contents(__DIR__.'/../../503.html'), 503
|
||||
);
|
||||
}));
|
||||
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
private function needsUpdate(): bool
|
||||
{
|
||||
$settings = $this->laravel->make(SettingsRepositoryInterface::class);
|
||||
$version = $settings->get('version');
|
||||
|
||||
return $version !== Application::VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Psr\Http\Server\RequestHandlerInterface
|
||||
*/
|
||||
public function getUpdaterMiddleware()
|
||||
{
|
||||
$pipe = new MiddlewarePipe;
|
||||
$pipe->pipe(
|
||||
$this->laravel->make(
|
||||
DispatchRoute::class,
|
||||
['routes' => $this->laravel->make('flarum.update.routes')]
|
||||
)
|
||||
);
|
||||
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
private function subPath($pathName, $middlewareStack)
|
||||
{
|
||||
return path(
|
||||
parse_url($this->laravel->url($pathName), PHP_URL_PATH) ?: '/',
|
||||
$this->laravel->make($middlewareStack)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\Console\Command\Command[]
|
||||
*/
|
||||
public function getConsoleCommands()
|
||||
{
|
||||
return [
|
||||
$this->laravel->make(GenerateMigrationCommand::class),
|
||||
$this->laravel->make(InfoCommand::class, ['config' => $this->config]),
|
||||
$this->laravel->make(MigrateCommand::class),
|
||||
$this->laravel->make(ResetCommand::class),
|
||||
$this->laravel->make(CacheClearCommand::class),
|
||||
];
|
||||
}
|
||||
}
|
221
src/Foundation/InstalledSite.php
Normal file
221
src/Foundation/InstalledSite.php
Normal file
|
@ -0,0 +1,221 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Foundation;
|
||||
|
||||
use Flarum\Admin\AdminServiceProvider;
|
||||
use Flarum\Api\ApiServiceProvider;
|
||||
use Flarum\Bus\BusServiceProvider as BusProvider;
|
||||
use Flarum\Database\DatabaseServiceProvider;
|
||||
use Flarum\Database\MigrationServiceProvider;
|
||||
use Flarum\Discussion\DiscussionServiceProvider;
|
||||
use Flarum\Extension\ExtensionServiceProvider;
|
||||
use Flarum\Formatter\FormatterServiceProvider;
|
||||
use Flarum\Forum\ForumServiceProvider;
|
||||
use Flarum\Frontend\FrontendServiceProvider;
|
||||
use Flarum\Group\GroupServiceProvider;
|
||||
use Flarum\Locale\LocaleServiceProvider;
|
||||
use Flarum\Notification\NotificationServiceProvider;
|
||||
use Flarum\Post\PostServiceProvider;
|
||||
use Flarum\Search\SearchServiceProvider;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
use Flarum\Settings\SettingsServiceProvider;
|
||||
use Flarum\Update\UpdateServiceProvider;
|
||||
use Flarum\User\UserServiceProvider;
|
||||
use Illuminate\Cache\FileStore;
|
||||
use Illuminate\Cache\Repository as CacheRepository;
|
||||
use Illuminate\Config\Repository as ConfigRepository;
|
||||
use Illuminate\Contracts\Cache\Repository;
|
||||
use Illuminate\Contracts\Cache\Store;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Filesystem\FilesystemServiceProvider;
|
||||
use Illuminate\Hashing\HashServiceProvider;
|
||||
use Illuminate\Mail\MailServiceProvider;
|
||||
use Illuminate\Validation\ValidationServiceProvider;
|
||||
use Illuminate\View\ViewServiceProvider;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class InstalledSite implements SiteInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $basePath;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $publicPath;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $storagePath;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
public function __construct($basePath, $publicPath, array $config)
|
||||
{
|
||||
$this->basePath = $basePath;
|
||||
$this->publicPath = $publicPath;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and boot a Flarum application instance.
|
||||
*
|
||||
* @return AppInterface
|
||||
*/
|
||||
public function bootApp(): AppInterface
|
||||
{
|
||||
return new InstalledApp(
|
||||
$this->bootLaravel(),
|
||||
$this->config
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $storagePath
|
||||
* @return static
|
||||
*/
|
||||
public function setStoragePath($storagePath)
|
||||
{
|
||||
$this->storagePath = $storagePath;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function bootLaravel(): Application
|
||||
{
|
||||
$laravel = new Application($this->basePath, $this->publicPath);
|
||||
|
||||
if ($this->storagePath) {
|
||||
$laravel->useStoragePath($this->storagePath);
|
||||
}
|
||||
|
||||
$laravel->instance('env', 'production');
|
||||
$laravel->instance('flarum.config', $this->config);
|
||||
$laravel->instance('config', $config = $this->getIlluminateConfig($laravel));
|
||||
|
||||
$this->registerLogger($laravel);
|
||||
$this->registerCache($laravel);
|
||||
|
||||
$laravel->register(DatabaseServiceProvider::class);
|
||||
$laravel->register(MigrationServiceProvider::class);
|
||||
$laravel->register(SettingsServiceProvider::class);
|
||||
$laravel->register(LocaleServiceProvider::class);
|
||||
$laravel->register(BusServiceProvider::class);
|
||||
$laravel->register(FilesystemServiceProvider::class);
|
||||
$laravel->register(HashServiceProvider::class);
|
||||
$laravel->register(MailServiceProvider::class);
|
||||
$laravel->register(ViewServiceProvider::class);
|
||||
$laravel->register(ValidationServiceProvider::class);
|
||||
|
||||
$laravel->register(BusProvider::class);
|
||||
|
||||
$settings = $laravel->make(SettingsRepositoryInterface::class);
|
||||
|
||||
$config->set('mail.driver', $settings->get('mail_driver'));
|
||||
$config->set('mail.host', $settings->get('mail_host'));
|
||||
$config->set('mail.port', $settings->get('mail_port'));
|
||||
$config->set('mail.from.address', $settings->get('mail_from'));
|
||||
$config->set('mail.from.name', $settings->get('forum_title'));
|
||||
$config->set('mail.encryption', $settings->get('mail_encryption'));
|
||||
$config->set('mail.username', $settings->get('mail_username'));
|
||||
$config->set('mail.password', $settings->get('mail_password'));
|
||||
|
||||
$laravel->register(DiscussionServiceProvider::class);
|
||||
$laravel->register(FormatterServiceProvider::class);
|
||||
$laravel->register(FrontendServiceProvider::class);
|
||||
$laravel->register(GroupServiceProvider::class);
|
||||
$laravel->register(NotificationServiceProvider::class);
|
||||
$laravel->register(PostServiceProvider::class);
|
||||
$laravel->register(SearchServiceProvider::class);
|
||||
$laravel->register(UserServiceProvider::class);
|
||||
$laravel->register(UpdateServiceProvider::class);
|
||||
|
||||
$laravel->register(ApiServiceProvider::class);
|
||||
$laravel->register(ForumServiceProvider::class);
|
||||
$laravel->register(AdminServiceProvider::class);
|
||||
|
||||
$laravel->register(ExtensionServiceProvider::class);
|
||||
|
||||
$laravel->boot();
|
||||
|
||||
return $laravel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Application $app
|
||||
* @return ConfigRepository
|
||||
*/
|
||||
protected function getIlluminateConfig(Application $app)
|
||||
{
|
||||
return new ConfigRepository([
|
||||
'view' => [
|
||||
'paths' => [],
|
||||
'compiled' => $app->storagePath().'/views',
|
||||
],
|
||||
'mail' => [
|
||||
'driver' => 'mail',
|
||||
],
|
||||
'filesystems' => [
|
||||
'default' => 'local',
|
||||
'cloud' => 's3',
|
||||
'disks' => [
|
||||
'flarum-assets' => [
|
||||
'driver' => 'local',
|
||||
'root' => $app->publicPath().'/assets',
|
||||
'url' => $app->url('assets')
|
||||
],
|
||||
'flarum-avatars' => [
|
||||
'driver' => 'local',
|
||||
'root' => $app->publicPath().'/assets/avatars'
|
||||
]
|
||||
]
|
||||
],
|
||||
'session' => [
|
||||
'lifetime' => 120,
|
||||
'files' => $app->storagePath().'/sessions',
|
||||
'cookie' => 'session'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
protected function registerLogger(Application $app)
|
||||
{
|
||||
$logPath = $app->storagePath().'/logs/flarum.log';
|
||||
$handler = new StreamHandler($logPath, Logger::INFO);
|
||||
$handler->setFormatter(new LineFormatter(null, null, true, true));
|
||||
|
||||
$app->instance('log', new Logger($app->environment(), [$handler]));
|
||||
$app->alias('log', LoggerInterface::class);
|
||||
}
|
||||
|
||||
protected function registerCache(Application $app)
|
||||
{
|
||||
$app->singleton('cache.store', function ($app) {
|
||||
return new CacheRepository($app->make('cache.filestore'));
|
||||
});
|
||||
$app->alias('cache.store', Repository::class);
|
||||
|
||||
$app->singleton('cache.filestore', function ($app) {
|
||||
return new FileStore(new Filesystem, $app->storagePath().'/cache');
|
||||
});
|
||||
$app->alias('cache.filestore', Store::class);
|
||||
}
|
||||
}
|
|
@ -11,281 +11,53 @@
|
|||
|
||||
namespace Flarum\Foundation;
|
||||
|
||||
use Flarum\Admin\AdminServiceProvider;
|
||||
use Flarum\Api\ApiServiceProvider;
|
||||
use Flarum\Bus\BusServiceProvider as BusProvider;
|
||||
use Flarum\Database\DatabaseServiceProvider;
|
||||
use Flarum\Database\MigrationServiceProvider;
|
||||
use Flarum\Discussion\DiscussionServiceProvider;
|
||||
use Flarum\Extension\ExtensionServiceProvider;
|
||||
use Flarum\Formatter\FormatterServiceProvider;
|
||||
use Flarum\Forum\ForumServiceProvider;
|
||||
use Flarum\Frontend\FrontendServiceProvider;
|
||||
use Flarum\Group\GroupServiceProvider;
|
||||
use Flarum\Locale\LocaleServiceProvider;
|
||||
use Flarum\Notification\NotificationServiceProvider;
|
||||
use Flarum\Post\PostServiceProvider;
|
||||
use Flarum\Search\SearchServiceProvider;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
use Flarum\Settings\SettingsServiceProvider;
|
||||
use Flarum\User\UserServiceProvider;
|
||||
use Illuminate\Bus\BusServiceProvider;
|
||||
use Illuminate\Config\Repository as ConfigRepository;
|
||||
use Illuminate\Filesystem\FilesystemServiceProvider;
|
||||
use Illuminate\Hashing\HashServiceProvider;
|
||||
use Illuminate\Mail\MailServiceProvider;
|
||||
use Illuminate\Validation\ValidationServiceProvider;
|
||||
use Illuminate\View\ViewServiceProvider;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Logger;
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
|
||||
// TODO: This should be an interface maybe?
|
||||
class Site
|
||||
{
|
||||
/**
|
||||
* @var Application
|
||||
* @param array $paths
|
||||
* @return SiteInterface
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $basePath;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $publicPath;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $storagePath;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
protected $extenders = [];
|
||||
|
||||
public function __construct()
|
||||
public static function fromPaths(array $paths)
|
||||
{
|
||||
$this->basePath = getcwd();
|
||||
$this->publicPath = $this->basePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Application
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
return $this->getApp();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $basePath
|
||||
* @return static
|
||||
*/
|
||||
public function setBasePath($basePath)
|
||||
{
|
||||
$this->basePath = $basePath;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $publicPath
|
||||
* @return static
|
||||
*/
|
||||
public function setPublicPath($publicPath)
|
||||
{
|
||||
$this->publicPath = $publicPath;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $storagePath
|
||||
* @return static
|
||||
*/
|
||||
public function setStoragePath($storagePath)
|
||||
{
|
||||
$this->storagePath = $storagePath;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @return static
|
||||
*/
|
||||
public function setConfig(array $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getConfig()
|
||||
{
|
||||
if (empty($this->config) && file_exists($file = $this->basePath.'/config.php')) {
|
||||
$this->config = include $file;
|
||||
if (! isset($paths['base'])) {
|
||||
throw new InvalidArgumentException(
|
||||
'No base path given'
|
||||
);
|
||||
}
|
||||
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Application
|
||||
*/
|
||||
protected function getApp()
|
||||
{
|
||||
if ($this->app !== null) {
|
||||
return $this->app;
|
||||
if (! isset($paths['public'])) {
|
||||
$paths['public'] = $paths['base'];
|
||||
}
|
||||
|
||||
date_default_timezone_set('UTC');
|
||||
|
||||
$app = new Application($this->basePath, $this->publicPath);
|
||||
|
||||
if ($this->storagePath) {
|
||||
$app->useStoragePath($this->storagePath);
|
||||
}
|
||||
|
||||
$app->instance('env', 'production');
|
||||
$app->instance('flarum.config', $this->getConfig());
|
||||
$app->instance('config', $config = $this->getIlluminateConfig($app));
|
||||
|
||||
$this->registerLogger($app);
|
||||
|
||||
$this->registerCache($app);
|
||||
|
||||
$app->register(DatabaseServiceProvider::class);
|
||||
$app->register(MigrationServiceProvider::class);
|
||||
$app->register(SettingsServiceProvider::class);
|
||||
$app->register(LocaleServiceProvider::class);
|
||||
$app->register(BusServiceProvider::class);
|
||||
$app->register(FilesystemServiceProvider::class);
|
||||
$app->register(HashServiceProvider::class);
|
||||
$app->register(MailServiceProvider::class);
|
||||
$app->register(ViewServiceProvider::class);
|
||||
$app->register(ValidationServiceProvider::class);
|
||||
|
||||
$app->register(BusProvider::class);
|
||||
|
||||
if ($app->isInstalled() && $app->isUpToDate()) {
|
||||
$settings = $app->make(SettingsRepositoryInterface::class);
|
||||
|
||||
$config->set('mail.driver', $settings->get('mail_driver'));
|
||||
$config->set('mail.host', $settings->get('mail_host'));
|
||||
$config->set('mail.port', $settings->get('mail_port'));
|
||||
$config->set('mail.from.address', $settings->get('mail_from'));
|
||||
$config->set('mail.from.name', $settings->get('forum_title'));
|
||||
$config->set('mail.encryption', $settings->get('mail_encryption'));
|
||||
$config->set('mail.username', $settings->get('mail_username'));
|
||||
$config->set('mail.password', $settings->get('mail_password'));
|
||||
|
||||
$app->register(DiscussionServiceProvider::class);
|
||||
$app->register(FormatterServiceProvider::class);
|
||||
$app->register(FrontendServiceProvider::class);
|
||||
$app->register(GroupServiceProvider::class);
|
||||
$app->register(NotificationServiceProvider::class);
|
||||
$app->register(PostServiceProvider::class);
|
||||
$app->register(SearchServiceProvider::class);
|
||||
$app->register(UserServiceProvider::class);
|
||||
|
||||
$app->register(ApiServiceProvider::class);
|
||||
$app->register(ForumServiceProvider::class);
|
||||
$app->register(AdminServiceProvider::class);
|
||||
|
||||
foreach ($this->extenders as $extender) {
|
||||
// TODO: Create extenders architecture
|
||||
// $extender->apply($app);
|
||||
}
|
||||
|
||||
$app->register(ExtensionServiceProvider::class);
|
||||
}
|
||||
|
||||
$app->boot();
|
||||
|
||||
$this->app = $app;
|
||||
|
||||
return $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Application $app
|
||||
* @return ConfigRepository
|
||||
*/
|
||||
protected function getIlluminateConfig(Application $app)
|
||||
{
|
||||
return new ConfigRepository([
|
||||
'view' => [
|
||||
'paths' => [],
|
||||
'compiled' => $app->storagePath().'/views',
|
||||
],
|
||||
'mail' => [
|
||||
'driver' => 'mail',
|
||||
],
|
||||
'filesystems' => [
|
||||
'default' => 'local',
|
||||
'cloud' => 's3',
|
||||
'disks' => [
|
||||
'flarum-assets' => [
|
||||
'driver' => 'local',
|
||||
'root' => $app->publicPath().'/assets',
|
||||
'url' => $app->url('assets')
|
||||
],
|
||||
'flarum-avatars' => [
|
||||
'driver' => 'local',
|
||||
'root' => $app->publicPath().'/assets/avatars'
|
||||
]
|
||||
]
|
||||
],
|
||||
'session' => [
|
||||
'lifetime' => 120,
|
||||
'files' => $app->storagePath().'/sessions',
|
||||
'cookie' => 'session'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Application $app
|
||||
*/
|
||||
protected function registerLogger(Application $app)
|
||||
{
|
||||
$logger = new Logger($app->environment());
|
||||
$logPath = $app->storagePath().'/logs/flarum.log';
|
||||
|
||||
$handler = new StreamHandler($logPath, Logger::DEBUG);
|
||||
$handler->setFormatter(new LineFormatter(null, null, true, true));
|
||||
|
||||
$logger->pushHandler($handler);
|
||||
|
||||
$app->instance('log', $logger);
|
||||
$app->alias('log', 'Psr\Log\LoggerInterface');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Application $app
|
||||
*/
|
||||
protected function registerCache(Application $app)
|
||||
{
|
||||
$app->singleton('cache.store', function ($app) {
|
||||
return new \Illuminate\Cache\Repository($app->make('cache.filestore'));
|
||||
});
|
||||
|
||||
$app->singleton('cache.filestore', function ($app) {
|
||||
return new \Illuminate\Cache\FileStore(
|
||||
new \Illuminate\Filesystem\Filesystem(),
|
||||
$app->storagePath().'/cache'
|
||||
if (static::hasConfigFile($paths['base'])) {
|
||||
return new InstalledSite(
|
||||
$paths['base'],
|
||||
$paths['public'],
|
||||
static::loadConfig($paths['base'])
|
||||
);
|
||||
});
|
||||
} else {
|
||||
return new UninstalledSite($paths['base'], $paths['public']);
|
||||
}
|
||||
}
|
||||
|
||||
$app->alias('cache.filestore', 'Illuminate\Contracts\Cache\Store');
|
||||
$app->alias('cache.store', 'Illuminate\Contracts\Cache\Repository');
|
||||
private static function hasConfigFile($basePath)
|
||||
{
|
||||
return file_exists("$basePath/config.php");
|
||||
}
|
||||
|
||||
private static function loadConfig($basePath): array
|
||||
{
|
||||
$config = include "$basePath/config.php";
|
||||
|
||||
if (! is_array($config)) {
|
||||
throw new RuntimeException('config.php should return an array');
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
|
|
22
src/Foundation/SiteInterface.php
Normal file
22
src/Foundation/SiteInterface.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Foundation;
|
||||
|
||||
interface SiteInterface
|
||||
{
|
||||
/**
|
||||
* Create and boot a Flarum application instance.
|
||||
*
|
||||
* @return AppInterface
|
||||
*/
|
||||
public function bootApp(): AppInterface;
|
||||
}
|
133
src/Foundation/UninstalledSite.php
Normal file
133
src/Foundation/UninstalledSite.php
Normal file
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Foundation;
|
||||
|
||||
use Flarum\Install\Installer;
|
||||
use Flarum\Install\InstallServiceProvider;
|
||||
use Flarum\Locale\LocaleServiceProvider;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
use Flarum\Settings\UninstalledSettingsRepository;
|
||||
use Illuminate\Config\Repository as ConfigRepository;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Filesystem\FilesystemServiceProvider;
|
||||
use Illuminate\Validation\ValidationServiceProvider;
|
||||
use Illuminate\View\Engines\EngineResolver;
|
||||
use Illuminate\View\Engines\PhpEngine;
|
||||
use Illuminate\View\FileViewFinder;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class UninstalledSite implements SiteInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $basePath;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $publicPath;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $storagePath;
|
||||
|
||||
public function __construct($basePath, $publicPath)
|
||||
{
|
||||
$this->basePath = $basePath;
|
||||
$this->publicPath = $publicPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and boot a Flarum application instance.
|
||||
*
|
||||
* @return AppInterface
|
||||
*/
|
||||
public function bootApp(): AppInterface
|
||||
{
|
||||
return new Installer(
|
||||
$this->bootLaravel()
|
||||
);
|
||||
}
|
||||
|
||||
private function bootLaravel(): Application
|
||||
{
|
||||
$laravel = new Application($this->basePath, $this->publicPath);
|
||||
|
||||
if ($this->storagePath) {
|
||||
$laravel->useStoragePath($this->storagePath);
|
||||
}
|
||||
|
||||
$laravel->instance('env', 'production');
|
||||
$laravel->instance('flarum.config', []);
|
||||
$laravel->instance('config', $config = $this->getIlluminateConfig($laravel));
|
||||
|
||||
$this->registerLogger($laravel);
|
||||
|
||||
$laravel->register(LocaleServiceProvider::class);
|
||||
$laravel->register(FilesystemServiceProvider::class);
|
||||
$laravel->register(ValidationServiceProvider::class);
|
||||
|
||||
$laravel->register(InstallServiceProvider::class);
|
||||
|
||||
$laravel->singleton(
|
||||
SettingsRepositoryInterface::class,
|
||||
UninstalledSettingsRepository::class
|
||||
);
|
||||
|
||||
$laravel->singleton('view', function ($app) {
|
||||
$engines = new EngineResolver();
|
||||
$engines->register('php', function () {
|
||||
return new PhpEngine();
|
||||
});
|
||||
$finder = new FileViewFinder($app->make('files'), []);
|
||||
$dispatcher = $app->make(Dispatcher::class);
|
||||
|
||||
return new \Illuminate\View\Factory(
|
||||
$engines, $finder, $dispatcher
|
||||
);
|
||||
});
|
||||
|
||||
$laravel->boot();
|
||||
|
||||
return $laravel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Application $app
|
||||
* @return ConfigRepository
|
||||
*/
|
||||
protected function getIlluminateConfig(Application $app)
|
||||
{
|
||||
return new ConfigRepository([
|
||||
'session' => [
|
||||
'lifetime' => 120,
|
||||
'files' => $app->storagePath().'/sessions',
|
||||
'cookie' => 'session'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
protected function registerLogger(Application $app)
|
||||
{
|
||||
$logPath = $app->storagePath().'/logs/flarum-installer.log';
|
||||
$handler = new StreamHandler($logPath, Logger::DEBUG);
|
||||
$handler->setFormatter(new LineFormatter(null, null, true, true));
|
||||
|
||||
$app->instance('log', new Logger('Flarum Installer', [$handler]));
|
||||
$app->alias('log', LoggerInterface::class);
|
||||
}
|
||||
}
|
|
@ -11,43 +11,22 @@
|
|||
|
||||
namespace Flarum\Http;
|
||||
|
||||
use Flarum\Foundation\Application;
|
||||
use Flarum\Foundation\Site;
|
||||
use Flarum\Http\Middleware\DispatchRoute;
|
||||
use Flarum\Http\Middleware\HandleErrors;
|
||||
use Flarum\Http\Middleware\StartSession;
|
||||
use Flarum\Install\InstallServiceProvider;
|
||||
use Flarum\Update\UpdateServiceProvider;
|
||||
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;
|
||||
use Zend\Diactoros\Response\HtmlResponse;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Zend\Diactoros\Server as DiactorosServer;
|
||||
use Zend\Stratigility\MiddlewarePipe;
|
||||
use function Zend\Stratigility\middleware;
|
||||
use function Zend\Stratigility\path;
|
||||
|
||||
class Server implements Middleware, Handler
|
||||
class Server
|
||||
{
|
||||
/**
|
||||
* @param Site $site
|
||||
* @return Server
|
||||
*/
|
||||
public static function fromSite(Site $site)
|
||||
{
|
||||
return new static($site->boot());
|
||||
}
|
||||
protected $requestHandler;
|
||||
|
||||
public function __construct(Application $app)
|
||||
public function __construct(RequestHandlerInterface $requestHandler)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->requestHandler = $requestHandler;
|
||||
}
|
||||
|
||||
public function listen()
|
||||
{
|
||||
DiactorosServer::createServer(
|
||||
[$this, 'handle'],
|
||||
[$this->requestHandler, 'handle'],
|
||||
$_SERVER,
|
||||
$_GET,
|
||||
$_POST,
|
||||
|
@ -55,105 +34,4 @@ class Server implements Middleware, Handler
|
|||
$_FILES
|
||||
)->listen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Use as PSR-15 middleware.
|
||||
*/
|
||||
public function process(Request $request, Handler $handler): Response
|
||||
{
|
||||
$middleware = $this->getMiddleware($request->getUri()->getPath());
|
||||
|
||||
return $middleware->process($request, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use as PSR-15 request handler.
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$middleware = $this->getMiddleware($request->getUri()->getPath());
|
||||
|
||||
return $middleware->handle($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $requestPath
|
||||
* @return MiddlewarePipe
|
||||
*/
|
||||
protected function getMiddleware($requestPath)
|
||||
{
|
||||
$pipe = new MiddlewarePipe;
|
||||
|
||||
if (! $this->app->isInstalled()) {
|
||||
return $this->getInstallerMiddleware($pipe);
|
||||
}
|
||||
|
||||
if ($this->app->isDownForMaintenance()) {
|
||||
return $this->getMaintenanceMiddleware($pipe);
|
||||
}
|
||||
|
||||
if (! $this->app->isUpToDate()) {
|
||||
return $this->getUpdaterMiddleware($pipe);
|
||||
}
|
||||
|
||||
$api = parse_url($this->app->url('api'), PHP_URL_PATH);
|
||||
$admin = parse_url($this->app->url('admin'), PHP_URL_PATH);
|
||||
$forum = parse_url($this->app->url(''), PHP_URL_PATH) ?: '/';
|
||||
|
||||
if ($this->pathStartsWith($requestPath, $api)) {
|
||||
$pipe->pipe(path($api, $this->app->make('flarum.api.middleware')));
|
||||
} elseif ($this->pathStartsWith($requestPath, $admin)) {
|
||||
$pipe->pipe(path($admin, $this->app->make('flarum.admin.middleware')));
|
||||
} else {
|
||||
$pipe->pipe(path($forum, $this->app->make('flarum.forum.middleware')));
|
||||
}
|
||||
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
private function pathStartsWith($path, $prefix)
|
||||
{
|
||||
return $path === $prefix || starts_with($path, "$prefix/");
|
||||
}
|
||||
|
||||
protected function getInstallerMiddleware(MiddlewarePipe $pipe)
|
||||
{
|
||||
$this->app->register(InstallServiceProvider::class);
|
||||
|
||||
// FIXME: Re-enable HandleErrors middleware, if possible
|
||||
// (Right now it tries to resolve a database connection because of the injected settings repo instance)
|
||||
// We could register a different settings repo when Flarum is not installed
|
||||
//$pipe->pipe($this->app->make(HandleErrors::class, ['debug' => true]));
|
||||
//$pipe->pipe($this->app->make(StartSession::class));
|
||||
$pipe->pipe($this->app->make(DispatchRoute::class, ['routes' => $this->app->make('flarum.install.routes')]));
|
||||
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
protected function getMaintenanceMiddleware(MiddlewarePipe $pipe)
|
||||
{
|
||||
$pipe->pipe(middleware(function () {
|
||||
return new HtmlResponse(file_get_contents($this->getErrorDir().'/503.html', 503));
|
||||
}));
|
||||
|
||||
// TODO: FOR API render JSON-API error document for HTTP 503
|
||||
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
protected function getUpdaterMiddleware(MiddlewarePipe $pipe)
|
||||
{
|
||||
$this->app->register(UpdateServiceProvider::class);
|
||||
|
||||
$pipe->pipe($this->app->make(DispatchRoute::class, ['routes' => $this->app->make('flarum.update.routes')]));
|
||||
|
||||
// TODO: FOR API render JSON-API error document for HTTP 503
|
||||
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
private function getErrorDir()
|
||||
{
|
||||
return __DIR__.'/../../error';
|
||||
}
|
||||
}
|
||||
|
|
61
src/Install/Installer.php
Normal file
61
src/Install/Installer.php
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Install;
|
||||
|
||||
use Flarum\Foundation\AppInterface;
|
||||
use Flarum\Foundation\Application;
|
||||
use Flarum\Http\Middleware\DispatchRoute;
|
||||
use Flarum\Http\Middleware\HandleErrorsWithWhoops;
|
||||
use Flarum\Http\Middleware\StartSession;
|
||||
use Flarum\Install\Console\InstallCommand;
|
||||
use Zend\Stratigility\MiddlewarePipe;
|
||||
|
||||
class Installer implements AppInterface
|
||||
{
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
protected $laravel;
|
||||
|
||||
public function __construct(Application $laravel)
|
||||
{
|
||||
$this->laravel = $laravel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Psr\Http\Server\RequestHandlerInterface
|
||||
*/
|
||||
public function getRequestHandler()
|
||||
{
|
||||
$pipe = new MiddlewarePipe;
|
||||
$pipe->pipe($this->laravel->make(HandleErrorsWithWhoops::class));
|
||||
#$pipe->pipe($this->laravel->make(StartSession::class));
|
||||
$pipe->pipe(
|
||||
$this->laravel->make(
|
||||
DispatchRoute::class,
|
||||
['routes' => $this->laravel->make('flarum.install.routes')]
|
||||
)
|
||||
);
|
||||
|
||||
return $pipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\Console\Command\Command[]
|
||||
*/
|
||||
public function getConsoleCommands()
|
||||
{
|
||||
return [
|
||||
$this->laravel->make(InstallCommand::class),
|
||||
];
|
||||
}
|
||||
}
|
35
src/Settings/UninstalledSettingsRepository.php
Normal file
35
src/Settings/UninstalledSettingsRepository.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Settings;
|
||||
|
||||
class UninstalledSettingsRepository implements SettingsRepositoryInterface
|
||||
{
|
||||
public function all()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
return $default;
|
||||
}
|
||||
|
||||
public function set($key, $value)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public function delete($keyLike)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user