1
0
mirror of https://github.com/flarum/core.git synced 2025-07-30 21:20:24 +02: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:
Franz Liedke
2018-04-16 01:31:00 +02:00
parent 7a6e208554
commit 5b821b21b1
10 changed files with 683 additions and 441 deletions

View File

@@ -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';
}
}