Extract Flarum\Foundation\Site class

This class holds all information relevant to a local Flarum site,
such as paths and local configuration. From this information, it
is able to instantiate a Flarum\Foundation\Application instance,
which represents a Flarum installation's runtime.

This will also be useful for setting up e.g. multi-tenant
environments.
This commit is contained in:
Franz Liedke 2017-07-02 13:30:02 +02:00
parent 051bb5acb8
commit e46b3d54d1
No known key found for this signature in database
GPG Key ID: 9A0231A879B055F4
4 changed files with 143 additions and 123 deletions

View File

@ -13,14 +13,30 @@ namespace Flarum\Console;
use Flarum\Database\Console\GenerateMigrationCommand; use Flarum\Database\Console\GenerateMigrationCommand;
use Flarum\Database\Console\MigrateCommand; use Flarum\Database\Console\MigrateCommand;
use Flarum\Foundation\AbstractServer; use Flarum\Foundation\Application;
use Flarum\Foundation\Console\CacheClearCommand; use Flarum\Foundation\Console\CacheClearCommand;
use Flarum\Foundation\Console\InfoCommand; use Flarum\Foundation\Console\InfoCommand;
use Flarum\Foundation\Site;
use Flarum\Install\Console\InstallCommand; use Flarum\Install\Console\InstallCommand;
use Symfony\Component\Console\Application; use Flarum\Install\InstallServiceProvider;
use Symfony\Component\Console\Application as ConsoleApplication;
class Server extends AbstractServer class Server
{ {
/**
* @param Site $site
* @return Server
*/
public static function fromSite(Site $site)
{
return new static($site->boot());
}
public function __construct(Application $app)
{
$this->app = $app;
}
public function listen() public function listen()
{ {
$console = $this->getConsoleApplication(); $console = $this->getConsoleApplication();
@ -29,14 +45,13 @@ class Server extends AbstractServer
} }
/** /**
* @return Application * @return ConsoleApplication
*/ */
protected function getConsoleApplication() protected function getConsoleApplication()
{ {
$app = $this->getApp(); $console = new ConsoleApplication('Flarum', $this->app->version());
$console = new Application('Flarum', $app->version());
$app->register('Flarum\Install\InstallServiceProvider'); $this->app->register(InstallServiceProvider::class);
$commands = [ $commands = [
InstallCommand::class, InstallCommand::class,
@ -44,7 +59,7 @@ class Server extends AbstractServer
GenerateMigrationCommand::class, GenerateMigrationCommand::class,
]; ];
if ($app->isInstalled()) { if ($this->app->isInstalled()) {
$commands = array_merge($commands, [ $commands = array_merge($commands, [
InfoCommand::class, InfoCommand::class,
CacheClearCommand::class CacheClearCommand::class
@ -52,9 +67,9 @@ class Server extends AbstractServer
} }
foreach ($commands as $command) { foreach ($commands as $command) {
$console->add($app->make( $console->add($this->app->make(
$command, $command,
['config' => $app->isInstalled() ? $app->make('flarum.config') : []] ['config' => $this->app->isInstalled() ? $this->app->make('flarum.config') : []]
)); ));
} }

View File

@ -11,6 +11,7 @@
namespace Flarum\Foundation; namespace Flarum\Foundation;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Container\Container; use Illuminate\Container\Container;
use Illuminate\Contracts\Foundation\Application as ApplicationContract; use Illuminate\Contracts\Foundation\Application as ApplicationContract;
use Illuminate\Events\EventServiceProvider; use Illuminate\Events\EventServiceProvider;
@ -125,7 +126,7 @@ class Application extends Container implements ApplicationContract
public function isUpToDate() public function isUpToDate()
{ {
$settings = $this->make('Flarum\Settings\SettingsRepositoryInterface'); $settings = $this->make(SettingsRepositoryInterface::class);
try { try {
$version = $settings->get('version'); $version = $settings->get('version');

View File

@ -11,12 +11,35 @@
namespace Flarum\Foundation; namespace Flarum\Foundation;
use Flarum\Admin\AdminServiceProvider;
use Flarum\Api\ApiServiceProvider;
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\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\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\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler; use Monolog\Handler\StreamHandler;
use Monolog\Logger; use Monolog\Logger;
abstract class AbstractServer // TODO: This should be an interface maybe?
class Site
{ {
/** /**
* @var Application * @var Application
@ -43,27 +66,12 @@ abstract class AbstractServer
*/ */
protected $config; protected $config;
/** protected $extenders = [];
* @var callable[]
*/
protected $extendCallbacks = [];
/** public function __construct()
* @param null $basePath
* @param null $publicPath
*/
public function __construct($basePath = null, $publicPath = null)
{ {
if ($basePath === null) { $this->basePath = getcwd();
$basePath = getcwd(); $this->publicPath = $this->basePath;
}
if ($publicPath === null) {
$publicPath = $basePath;
}
$this->basePath = $basePath;
$this->publicPath = $publicPath;
if (file_exists($file = $this->basePath.'/config.php')) { if (file_exists($file = $this->basePath.'/config.php')) {
$this->config = include $file; $this->config = include $file;
@ -71,81 +79,61 @@ abstract class AbstractServer
} }
/** /**
* @return string * @return Application
*/ */
public function getBasePath() public function boot()
{ {
return $this->basePath; return $this->getApp();
}
/**
* @return string
*/
public function getPublicPath()
{
return $this->publicPath;
}
/**
* @return string
*/
public function getStoragePath()
{
return $this->storagePath;
} }
/** /**
* @param $basePath * @param $basePath
* @return static
*/ */
public function setBasePath($basePath) public function setBasePath($basePath)
{ {
$this->basePath = $basePath; $this->basePath = $basePath;
return $this;
} }
/** /**
* @param $publicPath * @param $publicPath
* @return static
*/ */
public function setPublicPath($publicPath) public function setPublicPath($publicPath)
{ {
$this->publicPath = $publicPath; $this->publicPath = $publicPath;
return $this;
} }
/** /**
* @param $storagePath * @param $storagePath
* @return static
*/ */
public function setStoragePath($storagePath) public function setStoragePath($storagePath)
{ {
$this->storagePath = $storagePath; $this->storagePath = $storagePath;
}
/** return $this;
* @return array
*/
public function getConfig()
{
return $this->config;
} }
/** /**
* @param array $config * @param array $config
* @return static
*/ */
public function setConfig(array $config) public function setConfig(array $config)
{ {
$this->config = $config; $this->config = $config;
}
/** return $this;
* @param callable $callback
*/
public function extend(callable $callback)
{
$this->extendCallbacks[] = $callback;
} }
/** /**
* @return Application * @return Application
*/ */
public function getApp() protected function getApp()
{ {
if ($this->app !== null) { if ($this->app !== null) {
return $this->app; return $this->app;
@ -167,19 +155,19 @@ abstract class AbstractServer
$this->registerCache($app); $this->registerCache($app);
$app->register('Flarum\Database\DatabaseServiceProvider'); $app->register(DatabaseServiceProvider::class);
$app->register('Flarum\Database\MigrationServiceProvider'); $app->register(MigrationServiceProvider::class);
$app->register('Flarum\Settings\SettingsServiceProvider'); $app->register(SettingsServiceProvider::class);
$app->register('Flarum\Locale\LocaleServiceProvider'); $app->register(LocaleServiceProvider::class);
$app->register('Illuminate\Bus\BusServiceProvider'); $app->register(BusServiceProvider::class);
$app->register('Illuminate\Filesystem\FilesystemServiceProvider'); $app->register(FilesystemServiceProvider::class);
$app->register('Illuminate\Hashing\HashServiceProvider'); $app->register(HashServiceProvider::class);
$app->register('Illuminate\Mail\MailServiceProvider'); $app->register(MailServiceProvider::class);
$app->register('Illuminate\View\ViewServiceProvider'); $app->register(ViewServiceProvider::class);
$app->register('Illuminate\Validation\ValidationServiceProvider'); $app->register(ValidationServiceProvider::class);
if ($app->isInstalled() && $app->isUpToDate()) { if ($app->isInstalled() && $app->isUpToDate()) {
$settings = $app->make('Flarum\Settings\SettingsRepositoryInterface'); $settings = $app->make(SettingsRepositoryInterface::class);
$config->set('mail.driver', $settings->get('mail_driver')); $config->set('mail.driver', $settings->get('mail_driver'));
$config->set('mail.host', $settings->get('mail_host')); $config->set('mail.host', $settings->get('mail_host'));
@ -190,25 +178,26 @@ abstract class AbstractServer
$config->set('mail.username', $settings->get('mail_username')); $config->set('mail.username', $settings->get('mail_username'));
$config->set('mail.password', $settings->get('mail_password')); $config->set('mail.password', $settings->get('mail_password'));
$app->register('Flarum\BusServiceProvider'); $app->register(\Flarum\BusServiceProvider::class);
$app->register('Flarum\Discussion\DiscussionServiceProvider'); $app->register(DiscussionServiceProvider::class);
$app->register('Flarum\Formatter\FormatterServiceProvider'); $app->register(FormatterServiceProvider::class);
$app->register('Flarum\Group\GroupServiceProvider'); $app->register(GroupServiceProvider::class);
$app->register('Flarum\Notification\NotificationServiceProvider'); $app->register(NotificationServiceProvider::class);
$app->register('Flarum\Post\PostServiceProvider'); $app->register(PostServiceProvider::class);
$app->register('Flarum\Search\SearchServiceProvider'); $app->register(SearchServiceProvider::class);
$app->register('Flarum\User\UserServiceProvider'); $app->register(UserServiceProvider::class);
$app->register('Flarum\Api\ApiServiceProvider'); $app->register(ApiServiceProvider::class);
$app->register('Flarum\Forum\ForumServiceProvider'); $app->register(ForumServiceProvider::class);
$app->register('Flarum\Admin\AdminServiceProvider'); $app->register(AdminServiceProvider::class);
foreach ($this->extendCallbacks as $callback) { foreach ($this->extenders as $extender) {
$app->call($callback); // TODO: Create extenders architecture
// $extender->apply($app);
} }
$app->register('Flarum\Extension\ExtensionServiceProvider'); $app->register(ExtensionServiceProvider::class);
} }
$app->boot(); $app->boot();

View File

@ -11,8 +11,8 @@
namespace Flarum\Http; namespace Flarum\Http;
use Flarum\Foundation\AbstractServer;
use Flarum\Foundation\Application; use Flarum\Foundation\Application;
use Flarum\Foundation\Site;
use Flarum\Http\Middleware\DispatchRoute; use Flarum\Http\Middleware\DispatchRoute;
use Flarum\Http\Middleware\HandleErrors; use Flarum\Http\Middleware\HandleErrors;
use Flarum\Http\Middleware\StartSession; use Flarum\Http\Middleware\StartSession;
@ -29,8 +29,22 @@ use Zend\Stratigility\MiddlewareInterface;
use Zend\Stratigility\MiddlewarePipe; use Zend\Stratigility\MiddlewarePipe;
use Zend\Stratigility\NoopFinalHandler; use Zend\Stratigility\NoopFinalHandler;
class Server extends AbstractServer class Server
{ {
/**
* @param Site $site
* @return Server
*/
public static function fromSite(Site $site)
{
return new static($site->boot());
}
public function __construct(Application $app)
{
$this->app = $app;
}
public function listen() public function listen()
{ {
DiactorosServer::createServer( DiactorosServer::createServer(
@ -53,43 +67,44 @@ class Server extends AbstractServer
*/ */
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $out) public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $out)
{ {
$app = $this->getApp(); $this->collectGarbage();
$this->collectGarbage($app); $middleware = $this->getMiddleware($request->getUri()->getPath());
$middleware = $this->getMiddleware($app, $request->getUri()->getPath());
return $middleware($request, $response, $out); return $middleware($request, $response, $out);
} }
/** /**
* @param Application $app
* @param string $requestPath * @param string $requestPath
* @return MiddlewareInterface * @return MiddlewareInterface
*/ */
protected function getMiddleware(Application $app, $requestPath) protected function getMiddleware($requestPath)
{ {
$pipe = new MiddlewarePipe; $pipe = new MiddlewarePipe;
$pipe->raiseThrowables(); $pipe->raiseThrowables();
if (! $app->isInstalled()) { if (! $this->app->isInstalled()) {
return $this->getInstallerMiddleware($pipe, $app); return $this->getInstallerMiddleware($pipe);
} elseif ($app->isDownForMaintenance()) {
return $this->getMaintenanceMiddleware($pipe);
} elseif (! $app->isUpToDate()) {
return $this->getUpdaterMiddleware($pipe, $app);
} }
$forum = parse_url($app->url(''), PHP_URL_PATH) ?: '/'; if ($this->app->isDownForMaintenance()) {
$admin = parse_url($app->url('admin'), PHP_URL_PATH); return $this->getMaintenanceMiddleware($pipe);
$api = parse_url($app->url('api'), PHP_URL_PATH); }
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)) { if ($this->pathStartsWith($requestPath, $api)) {
$pipe->pipe($api, $app->make('flarum.api.middleware')); $pipe->pipe($api, $this->app->make('flarum.api.middleware'));
} elseif ($this->pathStartsWith($requestPath, $admin)) { } elseif ($this->pathStartsWith($requestPath, $admin)) {
$pipe->pipe($admin, $app->make('flarum.admin.middleware')); $pipe->pipe($admin, $this->app->make('flarum.admin.middleware'));
} else { } else {
$pipe->pipe($forum, $app->make('flarum.forum.middleware')); $pipe->pipe($forum, $this->app->make('flarum.forum.middleware'));
} }
return $pipe; return $pipe;
@ -100,14 +115,14 @@ class Server extends AbstractServer
return $path === $prefix || starts_with($path, "$prefix/"); return $path === $prefix || starts_with($path, "$prefix/");
} }
protected function getInstallerMiddleware(MiddlewarePipe $pipe, Application $app) protected function getInstallerMiddleware(MiddlewarePipe $pipe)
{ {
$app->register(InstallServiceProvider::class); $this->app->register(InstallServiceProvider::class);
$pipe->pipe(new HandleErrors($this->getErrorDir(), $app->make('log'), true)); $pipe->pipe(new HandleErrors($this->getErrorDir(), $this->app->make('log'), true));
$pipe->pipe($app->make(StartSession::class)); $pipe->pipe($this->app->make(StartSession::class));
$pipe->pipe($app->make(DispatchRoute::class, ['routes' => $app->make('flarum.install.routes')])); $pipe->pipe($this->app->make(DispatchRoute::class, ['routes' => $this->app->make('flarum.install.routes')]));
return $pipe; return $pipe;
} }
@ -123,11 +138,11 @@ class Server extends AbstractServer
return $pipe; return $pipe;
} }
protected function getUpdaterMiddleware(MiddlewarePipe $pipe, Application $app) protected function getUpdaterMiddleware(MiddlewarePipe $pipe)
{ {
$app->register(UpdateServiceProvider::class); $this->app->register(UpdateServiceProvider::class);
$pipe->pipe($app->make(DispatchRoute::class, ['routes' => $app->make('flarum.update.routes')])); $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 // TODO: FOR API render JSON-API error document for HTTP 503
@ -147,13 +162,13 @@ class Server extends AbstractServer
} }
} }
private function getErrorDir()
{
return __DIR__.'/../../error';
}
private function hitsLottery() private function hitsLottery()
{ {
return mt_rand(1, 100) <= 2; return mt_rand(1, 100) <= 2;
} }
private function getErrorDir()
{
return __DIR__.'/../../error';
}
} }