2018-04-28 12:20:07 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
use App\Database\DB;
|
2019-05-06 22:49:24 +00:00
|
|
|
use App\Exceptions\MaintenanceException;
|
|
|
|
use App\Exceptions\UnauthorizedException;
|
2018-11-19 11:19:47 +00:00
|
|
|
use App\Web\Lang;
|
2018-11-11 16:02:50 +00:00
|
|
|
use App\Web\Session;
|
2019-05-19 13:39:42 +00:00
|
|
|
use Aws\S3\S3Client;
|
|
|
|
use Google\Cloud\Storage\StorageClient;
|
|
|
|
use League\Flysystem\Adapter\Ftp as FtpAdapter;
|
|
|
|
use League\Flysystem\Adapter\Local;
|
|
|
|
use League\Flysystem\AwsS3v3\AwsS3Adapter;
|
|
|
|
use League\Flysystem\Filesystem;
|
2018-11-11 16:02:50 +00:00
|
|
|
use Monolog\Formatter\LineFormatter;
|
|
|
|
use Monolog\Handler\RotatingFileHandler;
|
|
|
|
use Monolog\Logger;
|
|
|
|
use Slim\App;
|
|
|
|
use Slim\Container;
|
2019-05-06 22:49:24 +00:00
|
|
|
use Slim\Http\Environment;
|
|
|
|
use Slim\Http\Request;
|
|
|
|
use Slim\Http\Response;
|
|
|
|
use Slim\Http\Uri;
|
|
|
|
use Slim\Views\Twig;
|
2019-05-19 13:39:42 +00:00
|
|
|
use Spatie\Dropbox\Client as DropboxClient;
|
|
|
|
use Spatie\FlysystemDropbox\DropboxAdapter;
|
|
|
|
use Superbalist\Flysystem\GoogleStorage\GoogleStorageAdapter;
|
2019-05-06 22:49:24 +00:00
|
|
|
use Twig\TwigFunction;
|
2018-04-28 12:20:07 +00:00
|
|
|
|
2018-11-12 17:56:12 +00:00
|
|
|
if (!file_exists('config.php') && is_dir('install/')) {
|
2018-11-13 17:05:17 +00:00
|
|
|
header('Location: ./install/');
|
2018-11-12 17:56:12 +00:00
|
|
|
exit();
|
|
|
|
} else if (!file_exists('config.php') && !is_dir('install/')) {
|
2019-01-31 19:53:49 +00:00
|
|
|
exit('Cannot find the config file.');
|
2018-11-12 17:56:12 +00:00
|
|
|
}
|
|
|
|
|
2018-10-13 16:25:48 +00:00
|
|
|
// Load the config
|
2018-04-28 12:20:07 +00:00
|
|
|
$config = array_replace_recursive([
|
|
|
|
'app_name' => 'XBackBone',
|
|
|
|
'base_url' => isset($_SERVER['HTTPS']) ? 'https://' . $_SERVER['HTTP_HOST'] : 'http://' . $_SERVER['HTTP_HOST'],
|
2018-11-11 16:02:50 +00:00
|
|
|
'displayErrorDetails' => false,
|
2019-01-31 10:48:39 +00:00
|
|
|
'maintenance' => false,
|
2018-04-28 12:20:07 +00:00
|
|
|
'db' => [
|
|
|
|
'connection' => 'sqlite',
|
2019-02-10 12:48:20 +00:00
|
|
|
'dsn' => BASE_DIR . 'resources/database/xbackbone.db',
|
2018-04-28 12:20:07 +00:00
|
|
|
'username' => null,
|
|
|
|
'password' => null,
|
|
|
|
],
|
2019-05-19 13:39:42 +00:00
|
|
|
'storage' => [
|
|
|
|
'driver' => 'local',
|
|
|
|
],
|
2019-02-10 12:48:20 +00:00
|
|
|
], require BASE_DIR . 'config.php');
|
2018-04-28 12:20:07 +00:00
|
|
|
|
2018-11-17 20:54:05 +00:00
|
|
|
if (!$config['displayErrorDetails']) {
|
2019-02-10 12:48:20 +00:00
|
|
|
$config['routerCacheFile'] = BASE_DIR . 'resources/cache/routes.cache.php';
|
2018-11-17 20:54:05 +00:00
|
|
|
}
|
|
|
|
|
2018-11-11 16:02:50 +00:00
|
|
|
$container = new Container(['settings' => $config]);
|
|
|
|
|
2019-01-31 19:53:49 +00:00
|
|
|
$container['config'] = function ($container) use ($config) {
|
|
|
|
return $config;
|
|
|
|
};
|
|
|
|
|
2018-11-11 16:02:50 +00:00
|
|
|
$container['logger'] = function ($container) {
|
|
|
|
$logger = new Logger('app');
|
|
|
|
|
2019-02-10 12:48:20 +00:00
|
|
|
$streamHandler = new RotatingFileHandler(BASE_DIR . 'logs/log.txt', 10, Logger::DEBUG);
|
2019-05-12 13:52:26 +00:00
|
|
|
|
|
|
|
$lineFormatter = new LineFormatter("[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n", "Y-m-d H:i:s");
|
|
|
|
$lineFormatter->includeStacktraces(true);
|
|
|
|
|
|
|
|
$streamHandler->setFormatter($lineFormatter);
|
2018-11-11 16:02:50 +00:00
|
|
|
|
|
|
|
$logger->pushHandler($streamHandler);
|
|
|
|
|
|
|
|
return $logger;
|
|
|
|
};
|
|
|
|
|
2019-01-10 22:22:19 +00:00
|
|
|
$container['session'] = function ($container) {
|
2019-02-10 12:48:20 +00:00
|
|
|
return new Session('xbackbone_session', BASE_DIR . 'resources/sessions');
|
2019-01-10 22:22:19 +00:00
|
|
|
};
|
2018-04-28 12:20:07 +00:00
|
|
|
|
2018-11-11 16:02:50 +00:00
|
|
|
$container['database'] = function ($container) use (&$config) {
|
2019-02-10 12:48:20 +00:00
|
|
|
$dsn = $config['db']['connection'] === 'sqlite' ? BASE_DIR . $config['db']['dsn'] : $config['db']['dsn'];
|
2019-01-10 22:22:19 +00:00
|
|
|
return new DB($config['db']['connection'] . ':' . $dsn, $config['db']['username'], $config['db']['password']);
|
2018-11-11 16:02:50 +00:00
|
|
|
};
|
|
|
|
|
2019-05-19 13:39:42 +00:00
|
|
|
$container['storage'] = function ($container) use (&$config) {
|
|
|
|
|
|
|
|
switch ($config['storage']['driver']) {
|
|
|
|
case 'local':
|
|
|
|
return new Filesystem(new Local($config['storage']['path']));
|
|
|
|
case 's3':
|
|
|
|
$client = new S3Client([
|
|
|
|
'credentials' => [
|
|
|
|
'key' => $config['storage']['key'],
|
|
|
|
'secret' => $config['storage']['secret'],
|
|
|
|
],
|
|
|
|
'region' => $config['storage']['region'],
|
|
|
|
'version' => 'latest',
|
|
|
|
]);
|
|
|
|
|
|
|
|
return new Filesystem(new AwsS3Adapter($client, $config['storage']['bucket'], $config['storage']['path']));
|
|
|
|
case 'dropbox':
|
|
|
|
$client = new DropboxClient($config['storage']['token']);
|
|
|
|
return new Filesystem(new DropboxAdapter($client), ['case_sensitive' => false]);
|
|
|
|
case 'ftp':
|
|
|
|
return new Filesystem(new FtpAdapter([
|
|
|
|
'host' => $config['storage']['host'],
|
|
|
|
'username' => $config['storage']['username'],
|
|
|
|
'password' => $config['storage']['password'],
|
|
|
|
'port' => $config['storage']['port'],
|
|
|
|
'root' => $config['storage']['path'],
|
|
|
|
'passive' => $config['storage']['passive'],
|
|
|
|
'ssl' => $config['storage']['ssl'],
|
|
|
|
'timeout' => 30,
|
|
|
|
]));
|
|
|
|
case 'google-cloud':
|
|
|
|
$client = new StorageClient([
|
|
|
|
'projectId' => $config['storage']['project_id'],
|
|
|
|
'keyFilePath' => $config['storage']['key_path'],
|
|
|
|
]);
|
|
|
|
return new Filesystem(new GoogleStorageAdapter($client, $client->bucket($config['storage']['bucket'])));
|
|
|
|
default:
|
|
|
|
throw new InvalidArgumentException('The driver specified is not supported.');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-01-10 22:22:19 +00:00
|
|
|
$container['lang'] = function ($container) {
|
2019-02-10 12:48:20 +00:00
|
|
|
return Lang::build(Lang::recognize(), BASE_DIR . 'resources/lang/');
|
2019-01-10 22:22:19 +00:00
|
|
|
};
|
2018-11-19 11:19:47 +00:00
|
|
|
|
2018-11-11 16:02:50 +00:00
|
|
|
$container['view'] = function ($container) use (&$config) {
|
2019-05-06 22:49:24 +00:00
|
|
|
$view = new Twig(BASE_DIR . 'resources/templates', [
|
2019-02-10 12:48:20 +00:00
|
|
|
'cache' => BASE_DIR . 'resources/cache',
|
2018-11-11 16:02:50 +00:00
|
|
|
'autoescape' => 'html',
|
|
|
|
'debug' => $config['displayErrorDetails'],
|
|
|
|
'auto_reload' => $config['displayErrorDetails'],
|
|
|
|
]);
|
|
|
|
|
|
|
|
// Instantiate and add Slim specific extension
|
|
|
|
$router = $container->get('router');
|
2019-05-06 22:49:24 +00:00
|
|
|
$uri = Uri::createFromEnvironment(new Environment($_SERVER));
|
2018-11-11 16:02:50 +00:00
|
|
|
$view->addExtension(new Slim\Views\TwigExtension($router, $uri));
|
|
|
|
|
|
|
|
$view->getEnvironment()->addGlobal('config', $config);
|
|
|
|
$view->getEnvironment()->addGlobal('request', $container->get('request'));
|
2019-01-10 22:22:19 +00:00
|
|
|
$view->getEnvironment()->addGlobal('alerts', $container->get('session')->getAlert());
|
|
|
|
$view->getEnvironment()->addGlobal('session', $container->get('session')->all());
|
|
|
|
$view->getEnvironment()->addGlobal('current_lang', $container->get('lang')->getLang());
|
2018-11-11 16:02:50 +00:00
|
|
|
$view->getEnvironment()->addGlobal('PLATFORM_VERSION', PLATFORM_VERSION);
|
2018-11-19 18:04:43 +00:00
|
|
|
|
2019-05-06 22:49:24 +00:00
|
|
|
$view->getEnvironment()->addFunction(new TwigFunction('route', 'route'));
|
|
|
|
$view->getEnvironment()->addFunction(new TwigFunction('lang', 'lang'));
|
|
|
|
$view->getEnvironment()->addFunction(new TwigFunction('urlFor', 'urlFor'));
|
|
|
|
$view->getEnvironment()->addFunction(new TwigFunction('mime2font', 'mime2font'));
|
|
|
|
$view->getEnvironment()->addFunction(new TwigFunction('queryParams', 'queryParams'));
|
2018-11-11 16:02:50 +00:00
|
|
|
return $view;
|
|
|
|
};
|
|
|
|
|
2019-02-10 12:48:20 +00:00
|
|
|
$container['phpErrorHandler'] = function ($container) {
|
2019-05-06 22:49:24 +00:00
|
|
|
return function (Request $request, Response $response, Throwable $error) use (&$container) {
|
2019-05-12 13:52:26 +00:00
|
|
|
$container->logger->critical('Fatal runtime error during app execution', ['exception' => $error]);
|
2019-02-10 12:48:20 +00:00
|
|
|
return $container->view->render($response->withStatus(500), 'errors/500.twig', ['exception' => $error]);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2018-11-11 16:02:50 +00:00
|
|
|
$container['errorHandler'] = function ($container) {
|
2019-05-06 22:49:24 +00:00
|
|
|
return function (Request $request, Response $response, Exception $exception) use (&$container) {
|
2018-11-11 16:02:50 +00:00
|
|
|
|
2019-05-06 22:49:24 +00:00
|
|
|
if ($exception instanceof MaintenanceException) {
|
2019-01-31 10:48:39 +00:00
|
|
|
return $container->view->render($response->withStatus(503), 'errors/maintenance.twig');
|
|
|
|
}
|
|
|
|
|
2019-05-06 22:49:24 +00:00
|
|
|
if ($exception instanceof UnauthorizedException) {
|
2018-11-11 16:02:50 +00:00
|
|
|
return $container->view->render($response->withStatus(403), 'errors/403.twig');
|
|
|
|
}
|
|
|
|
|
2019-05-12 13:52:26 +00:00
|
|
|
$container->logger->critical('Fatal exception during app execution', ['exception' => $exception]);
|
2018-11-11 16:02:50 +00:00
|
|
|
return $container->view->render($response->withStatus(500), 'errors/500.twig', ['exception' => $exception]);
|
|
|
|
};
|
|
|
|
};
|
2018-11-11 18:18:27 +00:00
|
|
|
|
2019-02-10 12:48:20 +00:00
|
|
|
$container['notAllowedHandler'] = function ($container) {
|
2019-05-06 22:49:24 +00:00
|
|
|
return function (Request $request, Response $response, $methods) use (&$container) {
|
2019-02-10 12:48:20 +00:00
|
|
|
return $container->view->render($response->withStatus(405)->withHeader('Allow', implode(', ', $methods)), 'errors/405.twig');
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2018-11-11 16:02:50 +00:00
|
|
|
$container['notFoundHandler'] = function ($container) {
|
2019-05-06 22:49:24 +00:00
|
|
|
return function (Request $request, Response $response) use (&$container) {
|
2018-11-11 16:02:50 +00:00
|
|
|
$response->withStatus(404)->withHeader('Content-Type', 'text/html');
|
|
|
|
return $container->view->render($response, 'errors/404.twig');
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
$app = new App($container);
|
2018-04-28 12:20:07 +00:00
|
|
|
|
2018-11-13 17:05:17 +00:00
|
|
|
// Permanently redirect paths with a trailing slash to their non-trailing counterpart
|
2019-05-06 22:49:24 +00:00
|
|
|
$app->add(function (Request $request, Response $response, callable $next) {
|
2018-11-13 17:05:17 +00:00
|
|
|
$uri = $request->getUri();
|
|
|
|
$path = $uri->getPath();
|
|
|
|
|
|
|
|
if ($path !== '/' && substr($path, -1) === '/') {
|
|
|
|
$uri = $uri->withPath(substr($path, 0, -1));
|
|
|
|
|
|
|
|
if ($request->getMethod() === 'GET') {
|
|
|
|
return $response->withRedirect((string)$uri, 301);
|
|
|
|
} else {
|
|
|
|
return $next($request->withUri($uri), $response);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $next($request, $response);
|
|
|
|
});
|
|
|
|
|
2018-10-13 16:25:48 +00:00
|
|
|
// Load the application routes
|
2019-05-06 22:49:24 +00:00
|
|
|
require BASE_DIR . 'app/routes.php';
|
|
|
|
|
|
|
|
return $app;
|