mirror of
https://github.com/flarum/framework.git
synced 2025-02-20 04:00:18 +08:00
chore: bind request to container then boot app
This commit is contained in:
parent
9c3460a619
commit
834bd732da
|
@ -28,27 +28,12 @@ use Flarum\Http\RouteHandlerFactory;
|
|||
use Flarum\Locale\LocaleManager;
|
||||
use Flarum\Settings\Event\Saved;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class AdminServiceProvider extends AbstractServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
$this->booted(function (Container $container) {
|
||||
/** @var Router $router */
|
||||
$router = $container->make(Router::class);
|
||||
/** @var Config $config */
|
||||
$config = $container->make(Config::class);
|
||||
|
||||
$router->middlewareGroup('admin', $container->make('flarum.admin.middleware'));
|
||||
|
||||
$factory = $container->make(RouteHandlerFactory::class);
|
||||
|
||||
$router->middleware('admin')
|
||||
->prefix($config->path('admin'))
|
||||
->name('admin.')
|
||||
->group(fn (Router $router) => (include __DIR__.'/routes.php')($router, $factory));
|
||||
});
|
||||
|
||||
$this->container->singleton('flarum.admin.middleware', function () {
|
||||
return [
|
||||
HttpMiddleware\InjectActorReference::class,
|
||||
|
@ -101,18 +86,17 @@ class AdminServiceProvider extends AbstractServiceProvider
|
|||
});
|
||||
}
|
||||
|
||||
public function boot(): void
|
||||
public function boot(Container $container, Dispatcher $events): void
|
||||
{
|
||||
$this->addRoutes($container);
|
||||
$this->loadViewsFrom(__DIR__.'/../../views', 'flarum.admin');
|
||||
|
||||
$events = $this->container->make('events');
|
||||
|
||||
$events->listen(
|
||||
[Enabled::class, Disabled::class, ClearingCache::class],
|
||||
function () {
|
||||
function () use ($container) {
|
||||
$recompile = new RecompileFrontendAssets(
|
||||
$this->container->make('flarum.assets.admin'),
|
||||
$this->container->make(LocaleManager::class)
|
||||
$container->make('flarum.assets.admin'),
|
||||
$container->make(LocaleManager::class)
|
||||
);
|
||||
$recompile->flush();
|
||||
}
|
||||
|
@ -120,13 +104,30 @@ class AdminServiceProvider extends AbstractServiceProvider
|
|||
|
||||
$events->listen(
|
||||
Saved::class,
|
||||
function (Saved $event) {
|
||||
function (Saved $event) use ($container) {
|
||||
$recompile = new RecompileFrontendAssets(
|
||||
$this->container->make('flarum.assets.admin'),
|
||||
$this->container->make(LocaleManager::class)
|
||||
$container->make('flarum.assets.admin'),
|
||||
$container->make(LocaleManager::class)
|
||||
);
|
||||
$recompile->whenSettingsSaved($event);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protected function addRoutes(Container $container)
|
||||
{
|
||||
/** @var Router $router */
|
||||
$router = $container->make(Router::class);
|
||||
/** @var Config $config */
|
||||
$config = $container->make(Config::class);
|
||||
|
||||
$router->middlewareGroup('admin', $container->make('flarum.admin.middleware'));
|
||||
|
||||
$factory = $container->make(RouteHandlerFactory::class);
|
||||
|
||||
$router->middleware('admin')
|
||||
->prefix($config->path('admin'))
|
||||
->name('admin.')
|
||||
->group(fn (Router $router) => (include __DIR__.'/routes.php')($router, $factory));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,31 +19,19 @@ use Flarum\Foundation\ErrorHandling\JsonApiFormatter;
|
|||
use Flarum\Foundation\ErrorHandling\Registry;
|
||||
use Flarum\Foundation\ErrorHandling\Reporter;
|
||||
use Flarum\Http\Middleware as HttpMiddleware;
|
||||
use Flarum\Http\RouteHandlerFactory;
|
||||
use Flarum\Http\Router;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ApiServiceProvider extends AbstractServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
$this->booted(function (Container $container) {
|
||||
/** @var Router $router */
|
||||
$router = $container->make(Router::class);
|
||||
/** @var Config $config */
|
||||
$config = $container->make(Config::class);
|
||||
|
||||
$router->middlewareGroup('api', $container->make('flarum.api.middleware'));
|
||||
|
||||
$router->middleware('api')
|
||||
->prefix($config->path('api'))
|
||||
->name('api.')
|
||||
->group(fn (Router $router) => (include __DIR__.'/routes.php')($router));
|
||||
});
|
||||
|
||||
$this->container->singleton('flarum.api.throttlers', function () {
|
||||
return [
|
||||
'bypassThrottlingAttribute' => function ($request) {
|
||||
if ($request->getAttribute('bypassThrottling')) {
|
||||
'bypassThrottlingAttribute' => function (Request $request) {
|
||||
if ($request->attributes->get('bypassThrottling')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -108,6 +96,7 @@ class ApiServiceProvider extends AbstractServiceProvider
|
|||
|
||||
public function boot(Container $container): void
|
||||
{
|
||||
$this->addRoutes($container);
|
||||
$this->setNotificationSerializers();
|
||||
|
||||
AbstractSerializeController::setContainer($container);
|
||||
|
@ -123,4 +112,21 @@ class ApiServiceProvider extends AbstractServiceProvider
|
|||
NotificationSerializer::setSubjectSerializer($type, $serializer);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addRoutes(Container $container)
|
||||
{
|
||||
/** @var Router $router */
|
||||
$router = $container->make(Router::class);
|
||||
/** @var Config $config */
|
||||
$config = $container->make(Config::class);
|
||||
|
||||
$router->middlewareGroup('api', $container->make('flarum.api.middleware'));
|
||||
|
||||
$factory = $container->make(RouteHandlerFactory::class);
|
||||
|
||||
$router->middleware('api')
|
||||
->prefix($config->path('api'))
|
||||
->name('api.')
|
||||
->group(fn (Router $router) => (include __DIR__.'/routes.php')($router, $factory));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ use Flarum\Foundation\AbstractServiceProvider;
|
|||
use Illuminate\Container\Container as ContainerImplementation;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Database\Capsule\Manager;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use Illuminate\Database\ConnectionResolverInterface;
|
||||
|
||||
class DatabaseServiceProvider extends AbstractServiceProvider
|
||||
|
@ -32,7 +31,8 @@ class DatabaseServiceProvider extends AbstractServiceProvider
|
|||
return $manager;
|
||||
});
|
||||
|
||||
$this->container->singleton(ConnectionResolverInterface::class, function (Container $container) {
|
||||
$this->container->singleton('db', function (Container $container) {
|
||||
/** @var Manager $manager */
|
||||
$manager = $container->make(Manager::class);
|
||||
$manager->setAsGlobal();
|
||||
$manager->bootEloquent();
|
||||
|
@ -43,19 +43,15 @@ class DatabaseServiceProvider extends AbstractServiceProvider
|
|||
return $dbManager;
|
||||
});
|
||||
|
||||
$this->container->alias(ConnectionResolverInterface::class, 'db');
|
||||
|
||||
$this->container->singleton(ConnectionInterface::class, function (Container $container) {
|
||||
$resolver = $container->make(ConnectionResolverInterface::class);
|
||||
$this->container->singleton('db.connection', function (Container $container) {
|
||||
/** @var ConnectionResolverInterface $resolver */
|
||||
$resolver = $container->make('db');
|
||||
|
||||
return $resolver->connection();
|
||||
});
|
||||
|
||||
$this->container->alias(ConnectionInterface::class, 'db.connection');
|
||||
$this->container->alias(ConnectionInterface::class, 'flarum.db');
|
||||
|
||||
$this->container->singleton(MigrationRepositoryInterface::class, function (Container $container) {
|
||||
return new DatabaseMigrationRepository($container['flarum.db'], 'migrations');
|
||||
return new DatabaseMigrationRepository($container['db.connection'], 'migrations');
|
||||
});
|
||||
|
||||
$this->container->singleton('flarum.database.model_private_checkers', function () {
|
||||
|
|
|
@ -26,6 +26,7 @@ trait ExtendsRoutes
|
|||
/** @var Router $router */
|
||||
$router = $container->make(Router::class);
|
||||
/** @var Config $config */
|
||||
$config = $container->make(Config::class);
|
||||
|
||||
foreach ($this->removedRoutes as $routeName) {
|
||||
$router->forgetRoute($routeName);
|
||||
|
|
|
@ -28,7 +28,7 @@ class ThrottleApi implements ExtenderInterface
|
|||
* The callable can be a closure or invokable class, and should accept:
|
||||
* - $request: The current `\Illuminate\Http\Request` request object.
|
||||
* `\Flarum\Http\RequestUtil::getActor($request)` can be used to get the current user.
|
||||
* `$request->getAttribute('routeName')` can be used to get the current route.
|
||||
* `$request->attributes->get('routeName')` can be used to get the current route.
|
||||
* Please note that every throttler runs by default on every route.
|
||||
* If you only want to throttle certain routes, you'll need to check for that inside your logic.
|
||||
*
|
||||
|
|
|
@ -104,6 +104,6 @@ class Discussion
|
|||
throw new RouteNotFoundException;
|
||||
}
|
||||
|
||||
return json_decode($response->getBody());
|
||||
return $response->getData();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ class Index
|
|||
$document->content = $this->view->make('flarum.forum::frontend.content.index', compact('apiDocument', 'page'));
|
||||
$document->payload['apiDocument'] = $apiDocument;
|
||||
|
||||
$document->canonicalUrl = $this->url->base('forum').($defaultRoute === '/all' ? '' : $request->getUri()->getPath());
|
||||
$document->canonicalUrl = $this->url->base('forum').($defaultRoute === '/all' ? '' : $request->getUri());
|
||||
$document->page = $page;
|
||||
$document->hasNextPage = isset($apiDocument->links->next);
|
||||
|
||||
|
@ -66,6 +66,6 @@ class Index
|
|||
*/
|
||||
protected function getApiDocument(Request $request, array $params): object
|
||||
{
|
||||
return json_decode($this->api->withParentRequest($request)->withQueryParams($params)->get('/discussions')->getBody());
|
||||
return $this->api->withParentRequest($request)->withQueryParams($params)->get('/discussions')->getData();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class LogInController extends AbstractController
|
|||
$response = $this->apiClient->withParentRequest($request)->withBody($params)->post('/token');
|
||||
|
||||
if ($response->getStatusCode() === 200) {
|
||||
$data = json_decode($response->getBody());
|
||||
$data = $response->getData();
|
||||
|
||||
$token = AccessToken::findValid($data->token);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class RegisterController extends AbstractController
|
|||
|
||||
$response = $this->api->withParentRequest($request)->withBody($params)->post('/users');
|
||||
|
||||
$body = json_decode($response->getBody());
|
||||
$body = $response->getData();
|
||||
|
||||
if (isset($body->data)) {
|
||||
$userId = $body->data->id;
|
||||
|
|
|
@ -34,33 +34,13 @@ use Flarum\Settings\SettingsRepositoryInterface;
|
|||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Support\Arr;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class ForumServiceProvider extends AbstractServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
$this->booted(function (Container $container) {
|
||||
/** @var Router $router */
|
||||
$router = $container->make(Router::class);
|
||||
/** @var Config $config */
|
||||
$config = $container->make(Config::class);
|
||||
|
||||
$router->middlewareGroup('forum', $container->make('flarum.forum.middleware'));
|
||||
|
||||
$factory = $container->make(RouteHandlerFactory::class);
|
||||
|
||||
$router->middleware('forum')
|
||||
->prefix($config->path('forum'))
|
||||
->name('forum.')
|
||||
->group(fn (Router $router) => (include __DIR__.'/routes.php')($router, $factory));
|
||||
|
||||
$this->setDefaultRoute(
|
||||
$router,
|
||||
$container->make(SettingsRepositoryInterface::class)
|
||||
);
|
||||
});
|
||||
|
||||
$this->container->singleton('flarum.forum.middleware', function () {
|
||||
return [
|
||||
HttpMiddleware\InjectActorReference::class,
|
||||
|
@ -130,6 +110,7 @@ class ForumServiceProvider extends AbstractServiceProvider
|
|||
|
||||
public function boot(Container $container, Dispatcher $events, Factory $view): void
|
||||
{
|
||||
$this->addRoutes($container);
|
||||
$this->loadViewsFrom(__DIR__.'/../../views', 'flarum.forum');
|
||||
|
||||
$view->share([
|
||||
|
@ -181,10 +162,33 @@ class ForumServiceProvider extends AbstractServiceProvider
|
|||
);
|
||||
}
|
||||
|
||||
protected function addRoutes(Container $container): void
|
||||
{
|
||||
/** @var Router $router */
|
||||
$router = $container->make(Router::class);
|
||||
/** @var Config $config */
|
||||
$config = $container->make(Config::class);
|
||||
|
||||
$router->middlewareGroup('forum', $container->make('flarum.forum.middleware'));
|
||||
|
||||
$factory = $container->make(RouteHandlerFactory::class);
|
||||
|
||||
$router->middleware('forum')
|
||||
->prefix($config->path('forum'))
|
||||
->name('forum.')
|
||||
->group(fn (Router $router) => (include __DIR__.'/routes.php')($router, $factory));
|
||||
|
||||
$this->setDefaultRoute(
|
||||
$router,
|
||||
$container->make(SettingsRepositoryInterface::class)
|
||||
);
|
||||
}
|
||||
|
||||
protected function setDefaultRoute(Router $router, SettingsRepositoryInterface $settings): void
|
||||
{
|
||||
$defaultRoute = $settings->get('default_route');
|
||||
$action = $router->getRoutes()->getByName($defaultRoute)?->getAction() ?? 'index';
|
||||
$router->get('/', $action)->name('default');
|
||||
$defaultRoutePath = ltrim($settings->get('default_route', '/all'), '/');
|
||||
/** @var \Illuminate\Routing\Route $route */
|
||||
$route = $router->getRoutes()->getRoutesByMethod()['GET'][$defaultRoutePath];
|
||||
$router->get('/', Arr::except($route->getAction(), ['as']))->name('forum.default');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
|
||||
namespace Flarum\Foundation;
|
||||
|
||||
use Flarum\Database\DatabaseServiceProvider;
|
||||
use Flarum\Foundation\Concerns\InteractsWithLaravel;
|
||||
use Flarum\Http\RoutingServiceProvider;
|
||||
use Flarum\Settings\SettingsServiceProvider;
|
||||
use Illuminate\Container\Container as IlluminateContainer;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Foundation\Application as LaravelApplication;
|
||||
|
@ -39,6 +41,8 @@ class Application extends IlluminateContainer implements LaravelApplication
|
|||
|
||||
protected array $loadedProviders = [];
|
||||
|
||||
protected bool $hasBeenBootstrapped = false;
|
||||
|
||||
public function __construct(
|
||||
protected Paths $paths
|
||||
) {
|
||||
|
@ -80,6 +84,13 @@ class Application extends IlluminateContainer implements LaravelApplication
|
|||
{
|
||||
$this->register(new EventServiceProvider($this));
|
||||
$this->register(new RoutingServiceProvider($this));
|
||||
|
||||
// Because we need to check very early if the version of the app
|
||||
// in the settings table matches the current version, we need
|
||||
// to register the settings provider and therefore the database
|
||||
// provider very early on.
|
||||
$this->register(new DatabaseServiceProvider($this));
|
||||
$this->register(new SettingsServiceProvider($this));
|
||||
}
|
||||
|
||||
public function register($provider, $force = false): ServiceProvider
|
||||
|
@ -194,16 +205,35 @@ class Application extends IlluminateContainer implements LaravelApplication
|
|||
}
|
||||
}
|
||||
|
||||
public function bootstrapWith(array $bootstrappers): void
|
||||
{
|
||||
$this->hasBeenBootstrapped = true;
|
||||
|
||||
foreach ($bootstrappers as $bootstrapper) {
|
||||
$this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]);
|
||||
|
||||
$this->make($bootstrapper)->bootstrap($this);
|
||||
|
||||
$this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]);
|
||||
}
|
||||
}
|
||||
|
||||
public function hasBeenBootstrapped(): bool
|
||||
{
|
||||
return $this->hasBeenBootstrapped;
|
||||
}
|
||||
|
||||
public function registerCoreContainerAliases(): void
|
||||
{
|
||||
$aliases = [
|
||||
'app' => [\Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class, \Psr\Container\ContainerInterface::class],
|
||||
'blade.compiler' => [\Illuminate\View\Compilers\BladeCompiler::class],
|
||||
'cache' => [\Illuminate\Cache\CacheManager::class, \Illuminate\Contracts\Cache\Factory::class],
|
||||
'cache.filestore' => [\Illuminate\Cache\FileStore::class, \Illuminate\Contracts\Cache\Store::class],
|
||||
'cache.store' => [\Illuminate\Cache\Repository::class, \Illuminate\Contracts\Cache\Repository::class],
|
||||
'config' => [\Illuminate\Config\Repository::class, \Illuminate\Contracts\Config\Repository::class],
|
||||
'container' => [\Illuminate\Contracts\Container\Container::class, \Psr\Container\ContainerInterface::class],
|
||||
'db' => [\Illuminate\Database\DatabaseManager::class],
|
||||
'db' => [\Illuminate\Database\ConnectionResolverInterface::class, \Illuminate\Database\DatabaseManager::class],
|
||||
'db.connection' => [\Illuminate\Database\Connection::class, \Illuminate\Database\ConnectionInterface::class],
|
||||
'events' => [\Illuminate\Events\Dispatcher::class, \Illuminate\Contracts\Events\Dispatcher::class],
|
||||
'files' => [\Illuminate\Filesystem\Filesystem::class],
|
||||
|
@ -211,9 +241,12 @@ class Application extends IlluminateContainer implements LaravelApplication
|
|||
'filesystem.disk' => [\Illuminate\Contracts\Filesystem\Filesystem::class],
|
||||
'filesystem.cloud' => [\Illuminate\Contracts\Filesystem\Cloud::class],
|
||||
'flarum' => [self::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class, \Psr\Container\ContainerInterface::class],
|
||||
'flarum.config' => [Config::class],
|
||||
'flarum.paths' => [Paths::class],
|
||||
'flarum.settings' => [\Flarum\Settings\SettingsRepositoryInterface::class],
|
||||
'hash' => [\Illuminate\Contracts\Hashing\Hasher::class],
|
||||
'mailer' => [\Illuminate\Mail\Mailer::class, \Illuminate\Contracts\Mail\Mailer::class, \Illuminate\Contracts\Mail\MailQueue::class],
|
||||
'request' => [\Illuminate\Http\Request::class, \Symfony\Component\HttpFoundation\Request::class],
|
||||
'router' => [\Flarum\Http\Router::class, \Illuminate\Routing\Router::class, \Illuminate\Contracts\Routing\Registrar::class, \Illuminate\Contracts\Routing\BindingRegistrar::class],
|
||||
'session' => [\Illuminate\Session\SessionManager::class],
|
||||
'session.store' => [\Illuminate\Session\Store::class, \Illuminate\Contracts\Session\Session::class],
|
||||
|
|
15
framework/core/src/Foundation/Bootstrap/BootProviders.php
Normal file
15
framework/core/src/Foundation/Bootstrap/BootProviders.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace Flarum\Foundation\Bootstrap;
|
||||
|
||||
use Flarum\Foundation\Bootstrap\IlluminateBootstrapperInterface;
|
||||
use Flarum\Foundation\SafeBooter;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
|
||||
class BootProviders implements IlluminateBootstrapperInterface
|
||||
{
|
||||
public function bootstrap(Application $app): void
|
||||
{
|
||||
(new SafeBooter($app))->boot();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Flarum\Foundation\Bootstrap;
|
||||
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
|
||||
interface IlluminateBootstrapperInterface
|
||||
{
|
||||
public function bootstrap(Application $app): void;
|
||||
}
|
71
framework/core/src/Foundation/Bootstrap/PrepareInstaller.php
Normal file
71
framework/core/src/Foundation/Bootstrap/PrepareInstaller.php
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace Flarum\Foundation\Bootstrap;
|
||||
|
||||
use Flarum\Foundation\ErrorServiceProvider;
|
||||
use Flarum\Install\InstallServiceProvider;
|
||||
use Flarum\Locale\LocaleServiceProvider;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
use Flarum\Settings\UninstalledSettingsRepository;
|
||||
use Flarum\User\SessionServiceProvider;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
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\Level;
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class PrepareInstaller implements IlluminateBootstrapperInterface
|
||||
{
|
||||
public function bootstrap(Application $app): void
|
||||
{
|
||||
$app->register(ErrorServiceProvider::class);
|
||||
$app->register(LocaleServiceProvider::class);
|
||||
$app->register(FilesystemServiceProvider::class);
|
||||
$app->register(SessionServiceProvider::class);
|
||||
$app->register(ValidationServiceProvider::class);
|
||||
|
||||
$app->register(InstallServiceProvider::class);
|
||||
|
||||
$this->registerLogger($app);
|
||||
|
||||
$app->singleton(
|
||||
SettingsRepositoryInterface::class,
|
||||
UninstalledSettingsRepository::class
|
||||
);
|
||||
|
||||
$app->singleton('view', function ($app) {
|
||||
$engines = new EngineResolver();
|
||||
$engines->register('php', function () use ($app) {
|
||||
return $app->make(PhpEngine::class);
|
||||
});
|
||||
$finder = new FileViewFinder($app->make('files'), []);
|
||||
$dispatcher = $app->make(Dispatcher::class);
|
||||
|
||||
return new \Illuminate\View\Factory(
|
||||
$engines,
|
||||
$finder,
|
||||
$dispatcher
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
protected function registerLogger(Application $app): void
|
||||
{
|
||||
/** @var \Flarum\Foundation\Paths $paths */
|
||||
$paths = $app['flarum.paths'];
|
||||
|
||||
$logPath = $paths->storage.'/logs/flarum-installer.log';
|
||||
$handler = new StreamHandler($logPath, Level::Debug);
|
||||
$handler->setFormatter(new LineFormatter(null, null, true, true));
|
||||
|
||||
$app->instance('log', new Logger('Flarum Installer', [$handler]));
|
||||
$app->alias('log', LoggerInterface::class);
|
||||
}
|
||||
}
|
25
framework/core/src/Foundation/Bootstrap/RegisterCache.php
Normal file
25
framework/core/src/Foundation/Bootstrap/RegisterCache.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Flarum\Foundation\Bootstrap;
|
||||
|
||||
use Illuminate\Cache\FileStore;
|
||||
use Illuminate\Cache\Repository as CacheRepository;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
|
||||
class RegisterCache implements IlluminateBootstrapperInterface
|
||||
{
|
||||
public function bootstrap(Application $app): void
|
||||
{
|
||||
/** @var \Flarum\Foundation\Paths $paths */
|
||||
$paths = $app['flarum.paths'];
|
||||
|
||||
$app->singleton('cache.store', function ($app) {
|
||||
return new CacheRepository($app->make('cache.filestore'));
|
||||
});
|
||||
|
||||
$app->singleton('cache.filestore', function () use ($paths) {
|
||||
return new FileStore(new Filesystem, $paths->storage.'/cache');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace Flarum\Foundation\Bootstrap;
|
||||
|
||||
use Flarum\Admin\AdminServiceProvider;
|
||||
use Flarum\Api\ApiServiceProvider;
|
||||
use Flarum\Bus\BusServiceProvider;
|
||||
use Flarum\Console\ConsoleServiceProvider;
|
||||
use Flarum\Database\DatabaseServiceProvider;
|
||||
use Flarum\Discussion\DiscussionServiceProvider;
|
||||
use Flarum\Extension\ExtensionServiceProvider;
|
||||
use Flarum\Filesystem\FilesystemServiceProvider;
|
||||
use Flarum\Filter\FilterServiceProvider;
|
||||
use Flarum\Formatter\FormatterServiceProvider;
|
||||
use Flarum\Forum\ForumServiceProvider;
|
||||
use Flarum\Foundation\ErrorServiceProvider;
|
||||
use Flarum\Frontend\FrontendServiceProvider;
|
||||
use Flarum\Group\GroupServiceProvider;
|
||||
use Flarum\Http\HttpServiceProvider;
|
||||
use Flarum\Locale\LocaleServiceProvider;
|
||||
use Flarum\Mail\MailServiceProvider;
|
||||
use Flarum\Notification\NotificationServiceProvider;
|
||||
use Flarum\Post\PostServiceProvider;
|
||||
use Flarum\Queue\QueueServiceProvider;
|
||||
use Flarum\Search\SearchServiceProvider;
|
||||
use Flarum\Settings\SettingsServiceProvider;
|
||||
use Flarum\Update\UpdateServiceProvider;
|
||||
use Flarum\User\SessionServiceProvider;
|
||||
use Flarum\User\UserServiceProvider;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Hashing\HashServiceProvider;
|
||||
use Illuminate\Validation\ValidationServiceProvider;
|
||||
use Illuminate\View\ViewServiceProvider;
|
||||
|
||||
class RegisterCoreProviders implements IlluminateBootstrapperInterface
|
||||
{
|
||||
public function bootstrap(Application $app): void
|
||||
{
|
||||
$app->register(AdminServiceProvider::class);
|
||||
$app->register(ApiServiceProvider::class);
|
||||
$app->register(BusServiceProvider::class);
|
||||
$app->register(ConsoleServiceProvider::class);
|
||||
$app->register(DiscussionServiceProvider::class);
|
||||
$app->register(ExtensionServiceProvider::class);
|
||||
$app->register(ErrorServiceProvider::class);
|
||||
$app->register(FilesystemServiceProvider::class);
|
||||
$app->register(FilterServiceProvider::class);
|
||||
$app->register(FormatterServiceProvider::class);
|
||||
$app->register(ForumServiceProvider::class);
|
||||
$app->register(FrontendServiceProvider::class);
|
||||
$app->register(GroupServiceProvider::class);
|
||||
$app->register(HashServiceProvider::class);
|
||||
$app->register(HttpServiceProvider::class);
|
||||
$app->register(LocaleServiceProvider::class);
|
||||
$app->register(MailServiceProvider::class);
|
||||
$app->register(NotificationServiceProvider::class);
|
||||
$app->register(PostServiceProvider::class);
|
||||
$app->register(QueueServiceProvider::class);
|
||||
$app->register(SearchServiceProvider::class);
|
||||
$app->register(SessionServiceProvider::class);
|
||||
$app->register(UpdateServiceProvider::class);
|
||||
$app->register(UserServiceProvider::class);
|
||||
$app->register(ValidationServiceProvider::class);
|
||||
$app->register(ViewServiceProvider::class);
|
||||
}
|
||||
}
|
31
framework/core/src/Foundation/Bootstrap/RegisterLogger.php
Normal file
31
framework/core/src/Foundation/Bootstrap/RegisterLogger.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Flarum\Foundation\Bootstrap;
|
||||
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Handler\RotatingFileHandler;
|
||||
use Monolog\Level;
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class RegisterLogger implements IlluminateBootstrapperInterface
|
||||
{
|
||||
public function bootstrap(Application $app): void
|
||||
{
|
||||
/**
|
||||
* @var \Flarum\Foundation\Paths $paths
|
||||
* @var \Flarum\Foundation\Config $config
|
||||
*/
|
||||
$paths = $app['flarum.paths'];
|
||||
$config = $app['flarum.config'];
|
||||
|
||||
$logPath = $paths->storage.'/logs/flarum.log';
|
||||
$logLevel = $config->inDebugMode() ? Level::Debug : Level::Info;
|
||||
$handler = new RotatingFileHandler($logPath, 0, $logLevel);
|
||||
$handler->setFormatter(new LineFormatter(null, null, true, true));
|
||||
|
||||
$app->instance('log', new Logger('flarum', [$handler]));
|
||||
$app->alias('log', LoggerInterface::class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Flarum\Foundation\Bootstrap;
|
||||
|
||||
use Flarum\Foundation\MaintenanceModeHandler;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
|
||||
class RegisterMaintenanceHandler implements IlluminateBootstrapperInterface
|
||||
{
|
||||
public function bootstrap(Application $app): void
|
||||
{
|
||||
$app->instance('flarum.maintenance.handler', new MaintenanceModeHandler);
|
||||
}
|
||||
}
|
|
@ -165,14 +165,6 @@ trait InteractsWithLaravel
|
|||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Not actually used/has no meaning in Flarum.
|
||||
*/
|
||||
public function bootstrapWith(array $bootstrappers)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function getLocale()
|
||||
{
|
||||
return $this->make(LocaleManager::class)->getLocale();
|
||||
|
@ -190,14 +182,6 @@ trait InteractsWithLaravel
|
|||
return Arr::where($this->serviceProviders, fn ($value) => $value instanceof $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Not actually used/has no meaning in Flarum.
|
||||
*/
|
||||
public function hasBeenBootstrapped()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Not actually used/has no meaning in Flarum.
|
||||
*/
|
||||
|
|
|
@ -12,14 +12,11 @@ namespace Flarum\Foundation;
|
|||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Contracts\Foundation\Application as ApplicationContract;
|
||||
use Laminas\Stratigility\Middleware\OriginalMessages;
|
||||
use Middlewares\BasePath;
|
||||
|
||||
class InstalledApp implements AppInterface
|
||||
{
|
||||
public function __construct(
|
||||
protected ApplicationContract $app,
|
||||
protected Config $config
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -51,23 +48,17 @@ class InstalledApp implements AppInterface
|
|||
protected function getUpdaterMiddlewareStack(): array
|
||||
{
|
||||
return [
|
||||
new BasePath($this->basePath()),
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
protected function getStandardMiddlewareStack(): array
|
||||
{
|
||||
return [
|
||||
new BasePath($this->basePath()),
|
||||
new OriginalMessages,
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
protected function basePath(): string
|
||||
{
|
||||
return $this->config->url()->getPath() ?: '/';
|
||||
}
|
||||
|
||||
public function getConsoleCommands(): array
|
||||
{
|
||||
return array_map(function ($command) {
|
||||
|
|
|
@ -9,47 +9,9 @@
|
|||
|
||||
namespace Flarum\Foundation;
|
||||
|
||||
use Flarum\Admin\AdminServiceProvider;
|
||||
use Flarum\Api\ApiServiceProvider;
|
||||
use Flarum\Bus\BusServiceProvider;
|
||||
use Flarum\Console\ConsoleServiceProvider;
|
||||
use Flarum\Database\DatabaseServiceProvider;
|
||||
use Flarum\Discussion\DiscussionServiceProvider;
|
||||
use Flarum\Extend\ExtenderInterface;
|
||||
use Flarum\Extension\ExtensionServiceProvider;
|
||||
use Flarum\Filesystem\FilesystemServiceProvider;
|
||||
use Flarum\Filter\FilterServiceProvider;
|
||||
use Flarum\Formatter\FormatterServiceProvider;
|
||||
use Flarum\Forum\ForumServiceProvider;
|
||||
use Flarum\Frontend\FrontendServiceProvider;
|
||||
use Flarum\Group\GroupServiceProvider;
|
||||
use Flarum\Http\HttpServiceProvider;
|
||||
use Flarum\Locale\LocaleServiceProvider;
|
||||
use Flarum\Mail\MailServiceProvider;
|
||||
use Flarum\Notification\NotificationServiceProvider;
|
||||
use Flarum\Post\PostServiceProvider;
|
||||
use Flarum\Queue\QueueServiceProvider;
|
||||
use Flarum\Search\SearchServiceProvider;
|
||||
use Flarum\Settings\SettingsServiceProvider;
|
||||
use Flarum\Update\UpdateServiceProvider;
|
||||
use Flarum\User\SessionServiceProvider;
|
||||
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\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Foundation\Application as ApplicationContract;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Hashing\HashServiceProvider;
|
||||
use Illuminate\Validation\ValidationServiceProvider;
|
||||
use Illuminate\View\ViewServiceProvider;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Handler\RotatingFileHandler;
|
||||
use Monolog\Level;
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class InstalledSite implements SiteInterface
|
||||
{
|
||||
|
@ -69,11 +31,10 @@ class InstalledSite implements SiteInterface
|
|||
*
|
||||
* @return InstalledApp
|
||||
*/
|
||||
public function bootApp(): AppInterface
|
||||
public function init(): AppInterface
|
||||
{
|
||||
return new InstalledApp(
|
||||
$this->bootLaravel(),
|
||||
$this->config
|
||||
$this->createApp()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -88,48 +49,14 @@ class InstalledSite implements SiteInterface
|
|||
return $this;
|
||||
}
|
||||
|
||||
protected function bootLaravel(): ApplicationContract
|
||||
protected function createApp(): ApplicationContract
|
||||
{
|
||||
$app = new Application($this->paths);
|
||||
|
||||
$app->instance('env', $this->config->environment());
|
||||
$app->instance('flarum.config', $this->config);
|
||||
$app->alias('flarum.config', Config::class);
|
||||
$app->instance('flarum.debug', $this->config->inDebugMode());
|
||||
$app->instance('config', $this->getIlluminateConfig());
|
||||
$app->instance('flarum.maintenance.handler', new MaintenanceModeHandler);
|
||||
|
||||
$this->registerLogger($app);
|
||||
$this->registerCache($app);
|
||||
|
||||
$app->register(AdminServiceProvider::class);
|
||||
$app->register(ApiServiceProvider::class);
|
||||
$app->register(BusServiceProvider::class);
|
||||
$app->register(ConsoleServiceProvider::class);
|
||||
$app->register(DatabaseServiceProvider::class);
|
||||
$app->register(DiscussionServiceProvider::class);
|
||||
$app->register(ExtensionServiceProvider::class);
|
||||
$app->register(ErrorServiceProvider::class);
|
||||
$app->register(FilesystemServiceProvider::class);
|
||||
$app->register(FilterServiceProvider::class);
|
||||
$app->register(FormatterServiceProvider::class);
|
||||
$app->register(ForumServiceProvider::class);
|
||||
$app->register(FrontendServiceProvider::class);
|
||||
$app->register(GroupServiceProvider::class);
|
||||
$app->register(HashServiceProvider::class);
|
||||
$app->register(HttpServiceProvider::class);
|
||||
$app->register(LocaleServiceProvider::class);
|
||||
$app->register(MailServiceProvider::class);
|
||||
$app->register(NotificationServiceProvider::class);
|
||||
$app->register(PostServiceProvider::class);
|
||||
$app->register(QueueServiceProvider::class);
|
||||
$app->register(SearchServiceProvider::class);
|
||||
$app->register(SessionServiceProvider::class);
|
||||
$app->register(SettingsServiceProvider::class);
|
||||
$app->register(UpdateServiceProvider::class);
|
||||
$app->register(UserServiceProvider::class);
|
||||
$app->register(ValidationServiceProvider::class);
|
||||
$app->register(ViewServiceProvider::class);
|
||||
|
||||
$app->booting(function () use ($app) {
|
||||
// Run all local-site extenders before booting service providers
|
||||
|
@ -140,11 +67,20 @@ class InstalledSite implements SiteInterface
|
|||
}
|
||||
});
|
||||
|
||||
$app->boot();
|
||||
|
||||
return $app;
|
||||
}
|
||||
|
||||
public function bootstrappers(): array
|
||||
{
|
||||
return [
|
||||
\Flarum\Foundation\Bootstrap\RegisterMaintenanceHandler::class,
|
||||
\Flarum\Foundation\Bootstrap\RegisterLogger::class,
|
||||
\Flarum\Foundation\Bootstrap\RegisterCache::class,
|
||||
\Flarum\Foundation\Bootstrap\RegisterCoreProviders::class,
|
||||
\Flarum\Foundation\Bootstrap\BootProviders::class,
|
||||
];
|
||||
}
|
||||
|
||||
protected function getIlluminateConfig(): ConfigRepository
|
||||
{
|
||||
return new ConfigRepository([
|
||||
|
@ -162,28 +98,4 @@ class InstalledSite implements SiteInterface
|
|||
]
|
||||
]);
|
||||
}
|
||||
|
||||
protected function registerLogger(Container $container): void
|
||||
{
|
||||
$logPath = $this->paths->storage.'/logs/flarum.log';
|
||||
$logLevel = $this->config->inDebugMode() ? Level::Debug : Level::Info;
|
||||
$handler = new RotatingFileHandler($logPath, 0, $logLevel);
|
||||
$handler->setFormatter(new LineFormatter(null, null, true, true));
|
||||
|
||||
$container->instance('log', new Logger('flarum', [$handler]));
|
||||
$container->alias('log', LoggerInterface::class);
|
||||
}
|
||||
|
||||
protected function registerCache(Container $container): void
|
||||
{
|
||||
$container->singleton('cache.store', function ($container) {
|
||||
return new CacheRepository($container->make('cache.filestore'));
|
||||
});
|
||||
$container->alias('cache.store', Repository::class);
|
||||
|
||||
$container->singleton('cache.filestore', function () {
|
||||
return new FileStore(new Filesystem, $this->paths->storage.'/cache');
|
||||
});
|
||||
$container->alias('cache.filestore', Store::class);
|
||||
}
|
||||
}
|
||||
|
|
97
framework/core/src/Foundation/SafeBooter.php
Normal file
97
framework/core/src/Foundation/SafeBooter.php
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
namespace Flarum\Foundation;
|
||||
|
||||
use Flarum\Foundation\ErrorHandling\LogReporter;
|
||||
use Illuminate\Contracts\Foundation\Application as ApplicationContract;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Throwable;
|
||||
|
||||
class SafeBooter
|
||||
{
|
||||
public function __construct(
|
||||
protected ApplicationContract $app
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to boot Flarum, and retrieve the app's HTTP request handler.
|
||||
*
|
||||
* We catch all exceptions happening during this process and format them to
|
||||
* prevent exposure of sensitive information.
|
||||
*
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
try {
|
||||
$this->app->boot();
|
||||
} catch (Throwable $e) {
|
||||
// Apply response code first so whatever happens, it's set before anything is printed
|
||||
http_response_code(500);
|
||||
|
||||
try {
|
||||
$this->cleanBootExceptionLog($e);
|
||||
} catch (Throwable $e) {
|
||||
// Ignore errors in logger. The important goal is to log the original error
|
||||
}
|
||||
|
||||
$this->fallbackBootExceptionLog($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to log the boot exception in a clean way and stop the script execution.
|
||||
* This means looking for debug mode and/or our normal error logger.
|
||||
* There is always a risk for this to fail,
|
||||
* for example if the container bindings aren't present
|
||||
* or if there is a filesystem error.
|
||||
* @param Throwable $error
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function cleanBootExceptionLog(Throwable $error): void
|
||||
{
|
||||
if ($this->app->has('flarum.config') && resolve('flarum.config')->inDebugMode()) {
|
||||
// If the application booted far enough for the config to be available, we will check for debug mode
|
||||
// Since the config is loaded very early, it is very likely to be available from the container
|
||||
$message = $error->getMessage();
|
||||
$file = $error->getFile();
|
||||
$line = $error->getLine();
|
||||
$type = get_class($error);
|
||||
|
||||
echo <<<ERROR
|
||||
Flarum encountered a boot error ($type)<br />
|
||||
<b>$message</b><br />
|
||||
thrown in <b>$file</b> on line <b>$line</b>
|
||||
|
||||
<pre>$error</pre>
|
||||
ERROR;
|
||||
exit(1);
|
||||
} elseif ($this->app->has(LoggerInterface::class)) {
|
||||
// If the application booted far enough for the logger to be available, we will log the error there
|
||||
// Considering most boot errors are related to database or extensions, the logger should already be loaded
|
||||
// We check for LoggerInterface binding because it's a constructor dependency of LogReporter,
|
||||
// then instantiate LogReporter through the container for automatic dependency injection
|
||||
resolve(LogReporter::class)->report($error);
|
||||
|
||||
echo 'Flarum encountered a boot error. Details have been logged to the Flarum log file.';
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the clean logging doesn't work, then we have a last opportunity.
|
||||
* Here we need to be extra careful not to include anything that might be sensitive on the page.
|
||||
*
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function fallbackBootExceptionLog(Throwable $error): void
|
||||
{
|
||||
echo 'Flarum encountered a boot error. Details have been logged to the system PHP log file.<br />';
|
||||
|
||||
// Throwing the exception ensures it will be visible with PHP display_errors=On
|
||||
// but invisible if that feature is turned off
|
||||
// PHP will also automatically choose a valid place to log it based on the system settings
|
||||
throw $error;
|
||||
}
|
||||
}
|
|
@ -14,5 +14,10 @@ interface SiteInterface
|
|||
/**
|
||||
* Create and boot a Flarum application instance.
|
||||
*/
|
||||
public function bootApp(): AppInterface;
|
||||
public function init(): AppInterface;
|
||||
|
||||
/**
|
||||
* Bootstrappers make up the booting process of the Application.
|
||||
*/
|
||||
public function bootstrappers(): array;
|
||||
}
|
||||
|
|
|
@ -10,23 +10,8 @@
|
|||
namespace Flarum\Foundation;
|
||||
|
||||
use Flarum\Install\Installer;
|
||||
use Flarum\Install\InstallServiceProvider;
|
||||
use Flarum\Locale\LocaleServiceProvider;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
use Flarum\Settings\UninstalledSettingsRepository;
|
||||
use Flarum\User\SessionServiceProvider;
|
||||
use Illuminate\Config\Repository as ConfigRepository;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
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;
|
||||
use Illuminate\Contracts\Foundation\Application as ApplicationContract;
|
||||
|
||||
class UninstalledSite implements SiteInterface
|
||||
{
|
||||
|
@ -36,17 +21,14 @@ class UninstalledSite implements SiteInterface
|
|||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and boot a Flarum application instance.
|
||||
*/
|
||||
public function bootApp(): AppInterface
|
||||
public function init(): AppInterface
|
||||
{
|
||||
return new Installer(
|
||||
$this->bootLaravel()
|
||||
$this->createApp()
|
||||
);
|
||||
}
|
||||
|
||||
protected function bootLaravel(): Container
|
||||
protected function createApp(): ApplicationContract
|
||||
{
|
||||
$app = new Application($this->paths);
|
||||
|
||||
|
@ -54,43 +36,19 @@ class UninstalledSite implements SiteInterface
|
|||
$app->instance('flarum.config', new Config(['url' => $this->baseUrl]));
|
||||
$app->alias('flarum.config', Config::class);
|
||||
$app->instance('flarum.debug', true);
|
||||
$app->instance('config', $config = $this->getIlluminateConfig());
|
||||
|
||||
$this->registerLogger($app);
|
||||
|
||||
$app->register(ErrorServiceProvider::class);
|
||||
$app->register(LocaleServiceProvider::class);
|
||||
$app->register(FilesystemServiceProvider::class);
|
||||
$app->register(SessionServiceProvider::class);
|
||||
$app->register(ValidationServiceProvider::class);
|
||||
|
||||
$app->register(InstallServiceProvider::class);
|
||||
|
||||
$app->singleton(
|
||||
SettingsRepositoryInterface::class,
|
||||
UninstalledSettingsRepository::class
|
||||
);
|
||||
|
||||
$app->singleton('view', function ($app) {
|
||||
$engines = new EngineResolver();
|
||||
$engines->register('php', function () use ($app) {
|
||||
return $app->make(PhpEngine::class);
|
||||
});
|
||||
$finder = new FileViewFinder($app->make('files'), []);
|
||||
$dispatcher = $app->make(Dispatcher::class);
|
||||
|
||||
return new \Illuminate\View\Factory(
|
||||
$engines,
|
||||
$finder,
|
||||
$dispatcher
|
||||
);
|
||||
});
|
||||
|
||||
$app->boot();
|
||||
$app->instance('config', $this->getIlluminateConfig());
|
||||
|
||||
return $app;
|
||||
}
|
||||
|
||||
public function bootstrappers(): array
|
||||
{
|
||||
return [
|
||||
\Flarum\Foundation\Bootstrap\PrepareInstaller::class,
|
||||
\Flarum\Foundation\Bootstrap\BootProviders::class,
|
||||
];
|
||||
}
|
||||
|
||||
protected function getIlluminateConfig(): ConfigRepository
|
||||
{
|
||||
return new ConfigRepository([
|
||||
|
@ -104,14 +62,4 @@ class UninstalledSite implements SiteInterface
|
|||
],
|
||||
]);
|
||||
}
|
||||
|
||||
protected function registerLogger(Container $container): void
|
||||
{
|
||||
$logPath = $this->paths->storage.'/logs/flarum-installer.log';
|
||||
$handler = new StreamHandler($logPath, Logger::DEBUG);
|
||||
$handler->setFormatter(new LineFormatter(null, null, true, true));
|
||||
|
||||
$container->instance('log', new Logger('Flarum Installer', [$handler]));
|
||||
$container->alias('log', LoggerInterface::class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
|||
use Illuminate\Contracts\Session\Session;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Session\Store;
|
||||
use Illuminate\Support\Arr;
|
||||
use SessionHandlerInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
|
@ -53,7 +52,7 @@ class StartSession implements IlluminateMiddlewareInterface
|
|||
return new Store(
|
||||
$this->config['cookie'],
|
||||
$this->handler,
|
||||
Arr::get($request->getCookieParams(), $this->cookie->getName($this->config['cookie']))
|
||||
$request->cookie($this->cookie->getName($this->config['cookie']))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace Flarum\Http;
|
|||
use Closure;
|
||||
use Flarum\Frontend\Controller as FrontendController;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Http\Request;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
/**
|
||||
|
@ -38,13 +39,18 @@ class RouteHandlerFactory
|
|||
|
||||
public function toFrontend(string $frontend, callable|string|null $content = null): callable
|
||||
{
|
||||
$frontend = $this->container->make("flarum.frontend.$frontend");
|
||||
return function (Request $request) use ($frontend, $content): mixed {
|
||||
$frontend = $this->container->make("flarum.frontend.$frontend");
|
||||
|
||||
if ($content) {
|
||||
$frontend->content(is_callable($content) ? $content : $this->container->make($content));
|
||||
}
|
||||
if ($content) {
|
||||
$frontend->content(is_callable($content) ? $content : $this->container->make($content));
|
||||
}
|
||||
|
||||
return new FrontendController($frontend);
|
||||
return $this->container->call(
|
||||
$this->container->make(FrontendController::class, compact('frontend')),
|
||||
compact('request')
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
public function toForum(string $content = null): Closure
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Flarum\Http;
|
||||
|
||||
use Flarum\Foundation\Config;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Routing\RoutingServiceProvider as IlluminateRoutingServiceProvider;
|
||||
|
||||
|
@ -12,6 +13,11 @@ class RoutingServiceProvider extends IlluminateRoutingServiceProvider
|
|||
$this->app->singleton('router', function (Container $container) {
|
||||
return new Router($container['events'], $container);
|
||||
});
|
||||
|
||||
$this->app->booted(function (Container $container) {
|
||||
$container['router']->getRoutes()->refreshNameLookups();
|
||||
$container['router']->getRoutes()->refreshActionLookups();
|
||||
});
|
||||
}
|
||||
|
||||
protected function registerUrlGenerator(): void
|
||||
|
@ -24,11 +30,17 @@ class RoutingServiceProvider extends IlluminateRoutingServiceProvider
|
|||
// and all the registered routes will be available to the generator.
|
||||
$container->instance('routes', $routes);
|
||||
|
||||
return new UrlGenerator(
|
||||
$url = new UrlGenerator(
|
||||
$routes, $container->rebinding(
|
||||
'request', $this->requestRebinder()
|
||||
), $container['config']['app.asset_url']
|
||||
);
|
||||
|
||||
$url->setConfig(
|
||||
$container->make(Config::class)
|
||||
);
|
||||
|
||||
return $url;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,16 +9,11 @@
|
|||
|
||||
namespace Flarum\Http;
|
||||
|
||||
use Flarum\Foundation\AppInterface;
|
||||
use Flarum\Foundation\ErrorHandling\LogReporter;
|
||||
use Flarum\Foundation\SiteInterface;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Pipeline;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Throwable;
|
||||
|
||||
class Server
|
||||
{
|
||||
|
@ -29,15 +24,21 @@ class Server
|
|||
|
||||
public function listen(): void
|
||||
{
|
||||
$siteApp = $this->safelyBoot();
|
||||
$siteApp = $this->site->init();
|
||||
$app = $siteApp->getContainer();
|
||||
$globalMiddleware = $siteApp->getMiddlewareStack();
|
||||
|
||||
$this->send(Request::capture(), $app, $globalMiddleware);
|
||||
$this
|
||||
->handle(Request::capture(), $app, $globalMiddleware)
|
||||
->send();
|
||||
}
|
||||
|
||||
public function send(Request $request, Application $app, array $globalMiddleware): Response
|
||||
public function handle(Request $request, Application $app, array $globalMiddleware): Response
|
||||
{
|
||||
$app->instance('request', $request);
|
||||
|
||||
$this->bootstrap($app);
|
||||
|
||||
return (new Pipeline($app))
|
||||
->send($request)
|
||||
->through($globalMiddleware)
|
||||
|
@ -46,86 +47,12 @@ class Server
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to boot Flarum, and retrieve the app's HTTP request handler.
|
||||
*
|
||||
* We catch all exceptions happening during this process and format them to
|
||||
* prevent exposure of sensitive information.
|
||||
*
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function safelyBoot(): AppInterface
|
||||
public function bootstrap(Application $app): void
|
||||
{
|
||||
try {
|
||||
return $this->site->bootApp();
|
||||
} catch (Throwable $e) {
|
||||
// Apply response code first so whatever happens, it's set before anything is printed
|
||||
http_response_code(500);
|
||||
|
||||
try {
|
||||
$this->cleanBootExceptionLog($e);
|
||||
} catch (Throwable $e) {
|
||||
// Ignore errors in logger. The important goal is to log the original error
|
||||
}
|
||||
|
||||
$this->fallbackBootExceptionLog($e);
|
||||
if (! $app->hasBeenBootstrapped()) {
|
||||
$app->bootstrapWith(
|
||||
$this->site->bootstrappers()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to log the boot exception in a clean way and stop the script execution.
|
||||
* This means looking for debug mode and/or our normal error logger.
|
||||
* There is always a risk for this to fail,
|
||||
* for example if the container bindings aren't present
|
||||
* or if there is a filesystem error.
|
||||
* @param Throwable $error
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function cleanBootExceptionLog(Throwable $error): void
|
||||
{
|
||||
$container = resolve(Container::class);
|
||||
|
||||
if ($container->has('flarum.config') && resolve('flarum.config')->inDebugMode()) {
|
||||
// If the application booted far enough for the config to be available, we will check for debug mode
|
||||
// Since the config is loaded very early, it is very likely to be available from the container
|
||||
$message = $error->getMessage();
|
||||
$file = $error->getFile();
|
||||
$line = $error->getLine();
|
||||
$type = get_class($error);
|
||||
|
||||
echo <<<ERROR
|
||||
Flarum encountered a boot error ($type)<br />
|
||||
<b>$message</b><br />
|
||||
thrown in <b>$file</b> on line <b>$line</b>
|
||||
|
||||
<pre>$error</pre>
|
||||
ERROR;
|
||||
exit(1);
|
||||
} elseif ($container->has(LoggerInterface::class)) {
|
||||
// If the application booted far enough for the logger to be available, we will log the error there
|
||||
// Considering most boot errors are related to database or extensions, the logger should already be loaded
|
||||
// We check for LoggerInterface binding because it's a constructor dependency of LogReporter,
|
||||
// then instantiate LogReporter through the container for automatic dependency injection
|
||||
resolve(LogReporter::class)->report($error);
|
||||
|
||||
echo 'Flarum encountered a boot error. Details have been logged to the Flarum log file.';
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the clean logging doesn't work, then we have a last opportunity.
|
||||
* Here we need to be extra careful not to include anything that might be sensitive on the page.
|
||||
*
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function fallbackBootExceptionLog(Throwable $error): void
|
||||
{
|
||||
echo 'Flarum encountered a boot error. Details have been logged to the system PHP log file.<br />';
|
||||
|
||||
// Throwing the exception ensures it will be visible with PHP display_errors=On
|
||||
// but invisible if that feature is turned off
|
||||
// PHP will also automatically choose a valid place to log it based on the system settings
|
||||
throw $error;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ class SettingsServiceProvider extends AbstractServiceProvider
|
|||
]);
|
||||
});
|
||||
|
||||
$this->container->singleton(SettingsRepositoryInterface::class, function (Container $container) {
|
||||
$this->container->singleton('flarum.settings', function (Container $container) {
|
||||
return new DefaultSettingsRepository(
|
||||
new MemoryCacheSettingsRepository(
|
||||
new DatabaseSettingsRepository(
|
||||
|
@ -37,8 +37,6 @@ class SettingsServiceProvider extends AbstractServiceProvider
|
|||
$container->make('flarum.settings.default')
|
||||
);
|
||||
});
|
||||
|
||||
$this->container->alias(SettingsRepositoryInterface::class, 'flarum.settings');
|
||||
}
|
||||
|
||||
public function boot(Dispatcher $events, SettingsValidator $settingsValidator): void
|
||||
|
|
|
@ -19,4 +19,4 @@ if (! function_exists('database_path')) {
|
|||
}
|
||||
|
||||
$site = (new \Flarum\Testing\integration\Setup\Bootstrapper())->run();
|
||||
$site->bootApp();
|
||||
$site->init();
|
||||
|
|
|
@ -55,7 +55,7 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase
|
|||
$this->extenders
|
||||
);
|
||||
|
||||
$this->app = $bootstrapper->run()->bootApp();
|
||||
$this->app = $bootstrapper->run()->init();
|
||||
|
||||
$this->database = $bootstrapper->database;
|
||||
|
||||
|
@ -215,7 +215,7 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase
|
|||
*/
|
||||
protected function send(Request $request): Response
|
||||
{
|
||||
return $this->server()->send($request, $this->app->getContainer(), []);
|
||||
return $this->server()->handle($request, $this->app->getContainer(), []);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue
Block a user