AzuraCast/app/bootstrap.php

345 lines
9.4 KiB
PHP

<?php
/**
* Global bootstrap file.
*/
// Security settings
define("APP_IS_COMMAND_LINE", (PHP_SAPI == "cli"));
define("APP_IS_SECURE", (!APP_IS_COMMAND_LINE && (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on")) ? TRUE : FALSE);
if (!defined('APP_TESTING_MODE'))
define('APP_TESTING_MODE', false);
// General includes
define("APP_INCLUDE_BASE", dirname(__FILE__));
define("APP_INCLUDE_ROOT", realpath(APP_INCLUDE_BASE.'/..'));
define("APP_INCLUDE_WEB", APP_INCLUDE_ROOT.'/web');
define("APP_INCLUDE_STATIC", APP_INCLUDE_WEB.'/static');
define("APP_INCLUDE_MODELS", APP_INCLUDE_BASE.'/models');
define("APP_INCLUDE_MODULES", APP_INCLUDE_BASE.'/modules');
define("APP_INCLUDE_TEMP", APP_INCLUDE_ROOT.'/../www_tmp');
define("APP_INCLUDE_CACHE", APP_INCLUDE_TEMP.'/cache');
define("APP_INCLUDE_LIB", APP_INCLUDE_BASE.'/library');
define("APP_INCLUDE_VENDOR", APP_INCLUDE_ROOT.'/vendor');
define("APP_UPLOAD_FOLDER", APP_INCLUDE_STATIC);
// Application environment.
if (isset($_SERVER['APP_APPLICATION_ENV']))
define('APP_APPLICATION_ENV', $_SERVER['APP_APPLICATION_ENV']);
elseif (file_exists(APP_INCLUDE_BASE.'/.env'))
define('APP_APPLICATION_ENV', ($env = @file_get_contents(APP_INCLUDE_BASE.'/.env')) ? trim($env) : 'development');
elseif (isset($_SERVER['X-App-Dev-Environment']) && $_SERVER['X-App-Dev-Environment'])
define('APP_APPLICATION_ENV', 'development');
else
define('APP_APPLICATION_ENV', 'development');
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']))
$_SERVER['HTTPS'] = (strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https');
// Composer autoload.
$autoloader = require(APP_INCLUDE_VENDOR . '/autoload.php');
$autoloader->add('App', APP_INCLUDE_LIB);
// Set up DI container.
$app_settings = [
'outputBuffering' => false,
'displayErrorDetails' => true,
'addContentLengthHeader' => false,
];
if (APP_APPLICATION_ENV !== 'development')
$app_settings['routerCacheFile'] = APP_INCLUDE_TEMP.'/app_routes.cache.php';
$di = new \Slim\Container(['settings' => $app_settings]);
// Save configuration object.
$config = new \App\Config(APP_INCLUDE_BASE.'/config', $di);
// Add application autoloaders to Composer's autoloader handler.
$autoload_classes = $config->application->autoload->toArray();
foreach($autoload_classes['psr0'] as $class_key => $class_dir)
$autoloader->add($class_key, $class_dir);
foreach($autoload_classes['psr4'] as $class_key => $class_dir)
$autoloader->addPsr4($class_key, $class_dir);
// Set URL constants from configuration.
$app_cfg = $config->application;
if ($app_cfg->base_url)
define('APP_BASE_URL', $app_cfg->base_url);
// Apply PHP settings.
$php_settings = $config->application->phpSettings->toArray();
foreach($php_settings as $setting_key => $setting_value)
{
if (is_array($setting_value)) {
foreach($setting_value as $setting_subkey => $setting_subval)
ini_set($setting_key.'.'.$setting_subkey, $setting_subval);
} else {
ini_set($setting_key, $setting_value);
}
}
// Override Slim handlers.
$di['callableResolver'] = function($di) {
return new \App\Mvc\Resolver($di);
};
$di['errorHandler'] = function($di) {
return function ($request, $response, $exception) use ($di) {
return \App\Mvc\ErrorHandler::handle($di, $request, $response, $exception);
};
};
$di['notFoundHandler'] = function ($di) {
return function ($request, $response) use ($di) {
$view = $di['view'];
$template = $view->render('system/error_pagenotfound');
$response->getBody()->write($template);
return $response;
};
};
// Loop through modules to find configuration files.
$modules = array_diff(scandir(APP_INCLUDE_MODULES), ['..', '.']);
$module_config = array();
foreach($modules as $module)
{
$full_path = APP_INCLUDE_MODULES.'/'.$module;
$config_directory = $full_path.'/config';
if (file_exists($config_directory))
$module_config[$module] = new \App\Config($config_directory, $di);
$module_class = 'Modules\\'.ucfirst($module).'\\Controllers\\';
$autoloader->addPsr4($module_class, $full_path.'/controllers');
}
// Configs
$di['config'] = $config;
$di['module_config'] = $module_config;
// Database
$di['em'] = function($di) {
try
{
$config = $di['config'];
$db_conf = $config->application->doctrine->toArray();
$db_conf['conn'] = $config->db->toArray();
return \App\Doctrine\EntityManagerFactory::create($di, $db_conf);
}
catch(\Exception $e)
{
throw new \App\Exception\Bootstrap($e->getMessage());
}
};
$di['db'] = function($di) {
try
{
$config = $di['config'];
$db_conf = $config->application->doctrine->toArray();
$db_conf['conn'] = $config->db->toArray();
$config = new \Doctrine\DBAL\Configuration;
return \Doctrine\DBAL\DriverManager::getConnection($db_conf['conn'], $config);
}
catch(\Exception $e)
{
throw new \App\Exception\Bootstrap($e->getMessage());
}
};
// Auth and ACL
$di['auth'] = function($di) {
return new \App\Auth($di['session'], $di['em']->getRepository('Entity\User'));
};
$di['acl'] = function($di) {
return new \App\Acl\StationAcl($di['em'], $di['auth']);
};
// Caching
$di['cache_driver'] = function($di) {
$config = $di['config'];
$cache_config = $config->cache->toArray();
switch($cache_config['cache'])
{
case 'redis':
$cache_driver = new \Stash\Driver\Redis($cache_config['redis']);
break;
case 'memcached':
$cache_driver = new \Stash\Driver\Memcache($cache_config['memcached']);
break;
case 'file':
$cache_driver = new \Stash\Driver\FileSystem($cache_config['file']);
break;
default:
case 'memory':
case 'ephemeral':
$cache_driver = new \Stash\Driver\Ephemeral;
break;
}
// Register Stash as session handler if necessary.
if (!($cache_driver instanceof \Stash\Driver\Ephemeral))
{
$pool = new \Stash\Pool($cache_driver);
$pool->setNamespace(\App\Cache::getSitePrefix('session'));
$session = new \Stash\Session($pool);
\Stash\Session::registerHandler($session);
}
return $cache_driver;
};
$di['cache'] = function($di) {
return new \App\Cache($di['cache_driver'], 'user');
};
// Register URL handler.
$di['url'] = function($di) {
return new \App\Url($di);
};
// Register session service.
$di['session'] = function($di) {
// Depends on cache driver.
$di->get('cache_driver');
return new \App\Session;
};
// Register CSRF prevention security token service.
$di['csrf'] = function($di) {
return new \App\Csrf($di['session']);
};
// Register Flash notification service.
$di['flash'] = function($di) {
return new \App\Flash($di['session']);
};
// InfluxDB
$di['influx'] = function($di) {
$config = $di['config'];
$opts = $config->influx->toArray();
$influx = new \InfluxDB\Client($opts['host'], $opts['port']);
return $influx->selectDB('stations');
};
// E-mail Messenger
$di['messenger'] = function($di) {
return new \App\Messenger($di);
};
// Scheduled synchronization manager
$di['sync'] = function($di) {
return new \App\Sync($di);
};
// Currently logged in user
$di['user'] = function($di) {
$auth = $di['auth'];
if ($auth->isLoggedIn())
return $auth->getLoggedInUser();
else
return NULL;
};
$di['customization'] = function($di) {
return new \App\Customization($di);
};
$di['view'] = function($di) {
$view = new \App\Mvc\View(APP_INCLUDE_BASE.'/templates');
$view->setFileExtension('phtml');
$view->addAppCommands($di);
$view->addData([
'di' => $di,
'auth' => $di['auth'],
'acl' => $di['acl'],
'url' => $di['url'],
'config' => $di['config'],
'flash' => $di['flash'],
'customization' => $di['customization'],
]);
return $view;
};
// Initialize cache.
$cache = $di->get('cache');
if (!APP_IS_COMMAND_LINE)
{
/** @var \App\Customization $customization */
$customization = $di->get('customization');
// Set time zone.
date_default_timezone_set($customization->getTimeZone());
// Localization
$locale = $customization->getLocale();
putenv("LANG=".$locale);
setlocale(LC_ALL, $locale);
$locale_domain = 'default';
bindtextdomain($locale_domain, APP_INCLUDE_BASE.'/locale');
bind_textdomain_codeset($locale_domain, 'UTF-8');
textdomain($locale_domain);
}
// Set up application and routing.
$di['app'] = function($di) use ($modules) {
$app = new \Slim\App($di);
// Remove trailing slash from all URLs when routing.
$app->add(function (\Psr\Http\Message\RequestInterface $request, \Psr\Http\Message\ResponseInterface $response, callable $next)
{
$uri = $request->getUri();
$path = $uri->getPath();
if ($path != '/' && substr($path, -1) == '/')
{
// permanently redirect paths with a trailing slash
// to their non-trailing counterpart
$uri = $uri->withPath(substr($path, 0, -1));
return $response->withRedirect((string)$uri, 301);
}
return $next($request, $response);
});
// Loop through modules to configure routes.
foreach ($modules as $module)
{
$routes_file = APP_INCLUDE_MODULES . DIRECTORY_SEPARATOR . $module . DIRECTORY_SEPARATOR . 'routes.php';
if (file_exists($routes_file))
include($routes_file);
}
return $app;
};
return $di;