core/Pimf/Application.php
<?php
/**
* Pimf
*
* @copyright Copyright (c) Gjero Krsteski (http://krsteski.de)
* @license http://opensource.org/licenses/MIT MIT License
*/
namespace Pimf;
use Pimf\Util\Character as Str, Pimf\Util\Header, Pimf\Util\Header\ResponseStatus, Pimf\Util\Uuid;
/**
* Provides a facility for applications which provides reusable resources,
* common-based bootstrapping and dependency checking.
*
* @package Pimf
* @author Gjero Krsteski <gjero@krsteski.de>
*
*/
final class Application
{
const VERSION = '1.11.0';
/**
* @var Environment
*/
protected static $env;
/**
* @var Logger
*/
protected static $logger;
/**
* @var EntityManager
*/
protected static $em;
/**
* @var Router
*/
protected static $router;
/**
* Mechanism used to do initial setup and edging before a application runs.
*
* @param array $conf The array of configuration options.
* @param array $server Array of information such as headers, paths, and script locations.
*
* @return boolean|null
*/
public static function bootstrap(array $conf, array $server = array())
{
$problems = array();
try {
Config::load($conf);
$environment = Config::get('environment');
date_default_timezone_set(Config::get('timezone'));
self::setupUtils($server, Config::get('bootstrap.local_temp_directory'), Config::get('logging.storage', 'file'));
self::loadListeners(BASE_PATH . 'app/' . Config::get('app.name') . '/events.php');
self::setupErrorHandling($environment);
self::loadPdoDriver($environment, Config::get($environment . '.db'), Config::get('app.name'));
self::loadRoutes(
Config::get('app.routeable'),
BASE_PATH . 'app/' . Config::get('app.name') . '/routes.php'
);
} catch (\Throwable $throwable) {
$problems[] = $throwable->getMessage();
} catch (\Exception $exception) {
$problems[] = $exception->getMessage();
}
self::reportIf($problems, PHP_VERSION);
}
/**
* Please bootstrap first, than run the application!
* Run a application, let application accept a request, route the request,
* dispatch to controller/action, render response and return response to client finally.
*
* @param array $get Array of variables passed to the current script via the URL parameters.
* @param array $post Array of variables passed to the current script via the HTTP POST method.
* @param array $cookie Array of variables passed to the current script via HTTP Cookies.
* @param array $files An associative array FILES of items uploaded to the current script via the HTTP POST method.
*
* @return void
*/
public static function run(array $get, array $post, array $cookie, array $files)
{
$cli = array();
if (Sapi::isCli()) {
$cli = Cli::parse((array)self::$env->argv);
if (count($cli) < 1 || isset($cli['list'])) {
Cli::absorb();
exit(0);
}
}
$prefix = Str::ensureTrailing('\\', Config::get('app.name'));
$repository = BASE_PATH . 'app/' . Config::get('app.name') . '/Controller';
if (isset($cli['controller']) && $cli['controller'] == 'core') {
$prefix = 'Pimf\\';
$repository = BASE_PATH . 'pimf-framework/core/Pimf/Controller';
}
$request = new Request($get, $post, $cookie, $cli, $files, self::$env);
$resolver = new Resolver($request, $repository, $prefix, self::$router);
$sessionized = (Sapi::isWeb() && Config::get('session.storage') !== '');
if ($sessionized) {
Session::load();
}
$pimf = $resolver->process(self::$env, self::$em, self::$logger);
if ($sessionized) {
Session::save();
Cookie::send();
}
$pimf->render();
}
/**
* @param string $environment
*/
private static function setupErrorHandling($environment)
{
if ($environment == 'testing') {
error_reporting(E_ALL | E_STRICT);
} else {
$logger = self::$logger;
set_exception_handler(
function ($exception) use ($logger) {
Error::exception($exception, $logger);
}
);
set_error_handler(
function ($code, $error, $file, $line) use ($logger) {
Error::native($code, $error, $file, $line, $logger, error_reporting());
}
);
register_shutdown_function(
function () use ($logger) {
Error::shutdown($logger, error_get_last());
}
);
error_reporting(-1);
}
}
/**
* @param array $server
* @param $tmpPath
* @param string $logging
*/
private static function setupUtils(array $server, $tmpPath, $logging = 'file')
{
self::$env = new Environment($server);
$envData = self::$env->data();
Logger::setup(
self::$env->getIp(),
$envData->get('PHP_SELF', $envData->get('SCRIPT_NAME'))
);
ResponseStatus::setup($envData->get('SERVER_PROTOCOL', 'HTTP/1.0'));
Header::setup(
self::$env->getUserAgent()
);
Url::setup(self::$env->getUrl(), self::$env->isHttps());
Uri::setup(self::$env->PATH_INFO, self::$env->REQUEST_URI);
Uuid::setup(self::$env->getIp(), self::$env->getHost());
if ($logging === 'file') {
self::$logger = new Logger(
new Adapter\File($tmpPath, "pimf-logs.txt"),
new Adapter\File($tmpPath, "pimf-warnings.txt"),
new Adapter\File($tmpPath, "pimf-errors.txt")
);
} else {
self::$logger = new Logger(
new Adapter\Std(Adapter\Std::OUT),
new Adapter\Std(Adapter\Std::OUT),
new Adapter\Std(Adapter\Std::ERR)
);
}
self::$logger->init();
}
/**
* @param string $environment
* @param array $dbConf
* @param string $appName
*/
private static function loadPdoDriver($environment, $dbConf, $appName)
{
if (is_array($dbConf) && $environment != 'testing') {
self::$em = new EntityManager(Pdo\Factory::get($dbConf), $appName);
}
}
/**
* @param boolean $routeable
* @param string $routes Path to routes definition file.
*/
private static function loadRoutes($routeable, $routes)
{
if ($routeable === true && file_exists($routes)) {
self::$router = new Router();
foreach ((array)(include $routes) as $route) {
self::$router->map($route);
}
}
}
/**
* @param string $events Path to event listeners
*/
private static function loadListeners($events)
{
if (file_exists($events)) {
include_once $events;
}
}
/**
* @param array $problems
* @param float $version
* @param bool $die
*
* @return array|void
*/
private static function reportIf(array $problems, $version, $die = true)
{
if (version_compare($version, 5.3) == -1) {
$problems[] = 'You have PHP ' . $version . ' and you need 5.3 or higher!';
}
if (!empty($problems)) {
return ($die === true) ? die(implode(PHP_EOL . PHP_EOL, $problems)) : $problems;
}
}
/**
* PIMF Application can not be cloned.
*/
private function __clone()
{
}
/**
* Stopping the PHP process for PHP-FastCGI users to speed up some PHP queries.
*/
public static function finish()
{
if (function_exists('fastcgi_finish_request')) {
fastcgi_finish_request();
}
}
}