diff --git a/composer.json b/composer.json index 8818af4a1..a94d8a946 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,9 @@ "symfony/console": "^2.7", "symfony/yaml": "^2.7", "doctrine/dbal": "^2.5", - "zendframework/zend-stratigility": "^1.1" + "zendframework/zend-stratigility": "^1.1", + "monolog/monolog": "^1.16.0", + "franzl/whoops-middleware": "dev-master" }, "require-dev": { "mockery/mockery": "^0.9.4", diff --git a/error/404.html b/error/404.html new file mode 100644 index 000000000..262b80985 --- /dev/null +++ b/error/404.html @@ -0,0 +1,13 @@ + + + + + + + + +

404 Not Found

+

Looks like this page could not be found.

+ + + \ No newline at end of file diff --git a/error/500.html b/error/500.html new file mode 100644 index 000000000..873fddb39 --- /dev/null +++ b/error/500.html @@ -0,0 +1,13 @@ + + + + + + + + +

500 Internal Server Error

+

Something went wrong on our server.

+ + + \ No newline at end of file diff --git a/src/Server/ConsoleServer.php b/src/Server/ConsoleServer.php new file mode 100644 index 000000000..26945e506 --- /dev/null +++ b/src/Server/ConsoleServer.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Server; + +use Flarum\Core; +use Symfony\Component\Console\Application; + +class ConsoleServer extends ServerAbstract +{ + /** + * @return void + */ + public function listen() + { + $console = $this->getConsoleApplication(); + + exit($console->run()); + } + + /** + * @return Application + */ + protected function getConsoleApplication() + { + $app = $this->getApp(); + + $console = new Application('Flarum', $app::VERSION); + + if (!Core::isInstalled()) { + $app->register('Flarum\Install\InstallServiceProvider'); + $console->add($app->make('Flarum\Install\Console\InstallCommand')); + } + + $console->add($app->make('Flarum\Console\UpgradeCommand')); + $console->add($app->make('Flarum\Console\GenerateExtensionCommand')); + $console->add($app->make('Flarum\Console\GenerateMigrationCommand')); + + return $console; + } +} diff --git a/src/Server/ServerAbstract.php b/src/Server/ServerAbstract.php new file mode 100644 index 000000000..4470a86cc --- /dev/null +++ b/src/Server/ServerAbstract.php @@ -0,0 +1,172 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Server; + +use Flarum\Core; +use Flarum\Core\Application; +use Illuminate\Cache\FileStore; +use Illuminate\Cache\Repository as CacheRepository; +use Illuminate\Config\Repository as ConfigRepository; +use Illuminate\Filesystem\Filesystem; + +abstract class ServerAbstract +{ + /** + * @var string + */ + protected $directory; + + /** + * @var array + */ + protected $config; + + /** + * @param string $directory + */ + public function __construct($directory) + { + $this->directory = $directory; + + if (file_exists($file = $this->directory.'/config.php')) { + $this->config = include $file; + } + } + + /** + * @param string $directory + */ + public function setDirectory($directory) + { + $this->directory = $directory; + } + + /** + * @param array $config + */ + public function setConfig($config) + { + $this->config = $config; + } + + /** + * @return \Flarum\Core\Application + */ + protected function getApp() + { + // franzliedke/studio currently doesn't autoload files (see issue + // below), so we will need to load them manually if we're using studio. + // https://github.com/franzliedke/studio/issues/29 + if (file_exists($corePath = $this->directory.'/core')) { + require $corePath.'/src/helpers.php'; + require $corePath.'/vendor/swiftmailer/swiftmailer/lib/swift_required.php'; + } + + $app = new Application($this->directory); + $app->instance('path.public', $this->directory); + + \Illuminate\Container\Container::setInstance($app); + + $app->instance('flarum.config', $this->config); + + date_default_timezone_set('UTC'); + + $app->instance('config', $config = new ConfigRepository([ + 'view' => [ + 'paths' => [ + realpath(base_path('resources/views')) + ], + 'compiled' => realpath(storage_path().'/framework/views'), + ], + 'mail' => [ + 'driver' => 'mail', + ], + 'cache' => [ + 'default' => 'file', + 'stores' => [ + 'file' => [ + 'driver' => 'file', + 'path' => storage_path().'/framework/cache', + ], + ], + 'prefix' => 'flarum', + ], + 'filesystems' => [ + 'default' => 'local', + 'cloud' => 's3', + 'disks' => [ + 'flarum-avatars' => [ + 'driver' => 'local', + 'root' => public_path('assets/avatars') + ], + ], + ], + ])); + + $logger = new \Monolog\Logger($app->environment()); + $logPath = $app->storagePath() . '/logs/flarum.log'; + $handler = new \Monolog\Handler\StreamHandler($logPath, \Monolog\Logger::DEBUG); + $handler->setFormatter(new \Monolog\Formatter\LineFormatter(null, null, true, true)); + $logger->pushHandler($handler); + + $app->instance('log', $logger); + $app->alias('log', 'Psr\Log\LoggerInterface'); + + $app->singleton('cache', function ($app) { + $store = new FileStore(new Filesystem(), storage_path('framework/cache')); + $repository = new CacheRepository($store); + $repository->setEventDispatcher($app->make('events')); + return $repository; + }); + $app->alias('cache', 'Illuminate\Contracts\Cache\Repository'); + + $serviceProviders = [ + 'Flarum\Core\DatabaseServiceProvider', + 'Flarum\Core\Settings\SettingsServiceProvider', + 'Flarum\Locale\LocaleServiceProvider', + + 'Illuminate\Bus\BusServiceProvider', + 'Illuminate\Filesystem\FilesystemServiceProvider', + 'Illuminate\Hashing\HashServiceProvider', + 'Illuminate\Mail\MailServiceProvider', + 'Illuminate\View\ViewServiceProvider', + 'Illuminate\Events\EventServiceProvider', + 'Illuminate\Validation\ValidationServiceProvider', + ]; + + foreach ($serviceProviders as $provider) { + $app->register(new $provider($app)); + } + + if (Core::isInstalled()) { + $settings = $app->make('Flarum\Core\Settings\SettingsRepository'); + + $app->register(new \Flarum\Core\CoreServiceProvider($app)); + + $config->set('mail.driver', Core::config('mail_driver')); + $config->set('mail.host', Core::config('mail_host')); + $config->set('mail.port', Core::config('mail_port')); + $config->set('mail.from.address', Core::config('mail_from')); + $config->set('mail.from.name', Core::config('forum_title')); + $config->set('mail.encryption', Core::config('mail_encryption')); + $config->set('mail.username', Core::config('mail_username')); + $config->set('mail.password', Core::config('mail_password')); + + // Register extensions and tell them to listen for events + $app->register(new \Flarum\Support\ExtensionsServiceProvider($app)); + } + + $app->boot(); + + return $app; + } +} diff --git a/src/Server/WebServer.php b/src/Server/WebServer.php new file mode 100644 index 000000000..11e793eb9 --- /dev/null +++ b/src/Server/WebServer.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Server; + +use Zend\Diactoros\Server as HttpServer; +use Flarum\Core; +use Flarum\Core\Application; +use Zend\Stratigility\MiddlewarePipe; +use Flarum\Api\Middleware\JsonApiErrors; +use Flarum\Forum\Middleware\HandleErrors; +use Franzl\Middleware\Whoops\Middleware as WhoopsMiddleware; + +class WebServer extends ServerAbstract +{ + /** + * @return void + */ + public function listen() + { + $app = $this->getApp(); + + $server = HttpServer::createServer( + $this->getMiddlewarePipe($app), + $_SERVER, + $_GET, + $_POST, + $_COOKIE, + $_FILES + ); + + $server->listen(); + } + + /** + * @param \Flarum\Core\Application + * + * @return \Zend\Stratigility\MiddlewarePipe + */ + protected function getMiddlewarePipe(Application $app) + { + $flarum = new MiddlewarePipe(); + + if (Core::isInstalled()) { + $flarum->pipe($app->make('Flarum\Forum\Middleware\LoginWithCookie')); + $flarum->pipe($app->make('Flarum\Api\Middleware\ReadJsonParameters')); + + // API + $app->register('Flarum\Api\ApiServiceProvider'); + $apiPath = parse_url(Core::url('api'), PHP_URL_PATH); + $router = $app->make('Flarum\Http\RouterMiddleware', ['routes' => $app->make('flarum.api.routes')]); + + $flarum->pipe($apiPath, $app->make('Flarum\Api\Middleware\LoginWithHeader')); + $flarum->pipe($apiPath, $app->make('Flarum\Api\Middleware\FakeHttpMethods')); + $flarum->pipe($apiPath, $router); + + // Admin + $app->register('Flarum\Admin\AdminServiceProvider'); + $adminPath = parse_url(Core::url('admin'), PHP_URL_PATH); + $router = $app->make('Flarum\Http\RouterMiddleware', ['routes' => $app->make('flarum.admin.routes')]); + + $flarum->pipe($adminPath, $router); + + // Forum + $app->register('Flarum\Forum\ForumServiceProvider'); + $basePath = parse_url(Core::url(), PHP_URL_PATH); + $router = $app->make('Flarum\Http\RouterMiddleware', ['routes' => $app->make('flarum.forum.routes')]); + + $flarum->pipe($basePath, $router); + + if (Core::inDebugMode()) { + $flarum->pipe(new WhoopsMiddleware()); + } else { + $flarum->pipe(new HandleErrors(__DIR__.'/../../error')); + } + } else { + $app->register('Flarum\Install\InstallServiceProvider'); + + $basePath = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); + $router = $app->make('Flarum\Http\RouterMiddleware', ['routes' => $app->make('flarum.install.routes')]); + $flarum->pipe($basePath, $router); + $flarum->pipe(new WhoopsMiddleware()); + } + + return $flarum; + } +}