icingaweb2/library/Icinga/Application/ApplicationBootstrap.php
Eric Lippmann 9cbfe88ea6 Do not exit the application when the logger has errors logged during bootstrap and stop preference loading on every request
Only fatals should exit the application.
Preferences must be loaded only once after login.
2014-02-14 10:56:29 +01:00

426 lines
9.4 KiB
PHP
Executable File

<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga Web 2.
*
* Icinga Web 2 - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Application;
use \DateTimeZone;
use \Exception;
use \Icinga\Application\Modules\Manager as ModuleManager;
use \Icinga\Exception\ConfigurationError;
use \Icinga\Util\DateTimeFactory;
use \Icinga\Util\Translator;
use Icinga\Data\ResourceFactory;
/**
* This class bootstraps a thin Icinga application layer
*
* Usage example for CLI:
* <code>
* use Icinga\Application\Cli;
* Cli::start();
* </code>
*
* Usage example for Icinga Web application:
* <code>
* use Icinga\Application\Web;
* Web::start()->dispatch();
* </code>
*
* Usage example for Icinga-Web 1.x compatibility mode:
* <code>
* use Icinga\Application\LegacyWeb;
* LegacyWeb::start()->setIcingaWebBasedir(ICINGAWEB_BASEDIR)->dispatch();
* </code>
*/
abstract class ApplicationBootstrap
{
/**
* Icinga auto loader
*
* @var Loader
*/
private $loader;
/**
* Library directory
*
* @var string
*/
private $libDir;
/**
* Config object
*
* @var Config
*/
protected $config;
/**
* Configuration directory
*
* @var string
*/
private $configDir;
/**
* Application directory
*
* @var string
*/
private $appDir;
/**
* Module manager
*
* @var ModuleManager
*/
private $moduleManager;
/**
* Flag indicates we're on cli environment
*
* @var bool
*/
protected $isCli = false;
/**
* Flag indicates we're on web environment
*
* @var bool
*/
protected $isWeb = false;
/**
* Constructor
*/
protected function __construct($configDir)
{
$this->libDir = realpath(__DIR__ . '/../..');
if (!defined('ICINGA_LIBDIR')) {
define('ICINGA_LIBDIR', $this->libDir);
}
// TODO: Make appdir configurable for packagers
$this->appDir = realpath($this->libDir. '/../application');
if (!defined('ICINGA_APPDIR')) {
define('ICINGA_APPDIR', $this->appDir);
}
$this->setupAutoloader();
$this->setupZendAutoloader();
Benchmark::measure('Bootstrap, autoloader registered');
Icinga::setApp($this);
$this->configDir = realpath($configDir);
require_once dirname(__FILE__) . '/functions.php';
}
/**
* Bootstrap interface method for concrete bootstrap objects
*
* @return mixed
*/
abstract protected function bootstrap();
/**
* Getter for module manager
*
* @return ModuleManager
*/
public function getModuleManager()
{
return $this->moduleManager;
}
/**
* Getter for class loader
*
* @return Loader
*/
public function getLoader()
{
return $this->loader;
}
/**
* Getter for configuration object
*
* @return Config
*/
public function getConfig()
{
return $this->config;
}
/**
* Flag indicates we're on cli environment
*
* @return bool
*/
public function isCli()
{
return $this->isCli;
}
/**
* Flag indicates we're on web environment
*
* @return bool
*/
public function isWeb()
{
return $this->isWeb;
}
/**
* Getter for application dir
*
* Optional append sub directory
*
* @param string $subdir optional subdir
*
* @return string
*/
public function getApplicationDir($subdir = null)
{
return $this->getDirWithSubDir($this->appDir, $subdir);
}
/**
* Getter for config dir
*
* @param string $subdir
*
* @return string
*/
public function getConfigDir($subdir = null)
{
return $this->getDirWithSubDir($this->configDir, $subdir);
}
/**
* Helper to glue directories together
*
* @param string $dir
* @param string $subdir
*
* @return string
*/
private function getDirWithSubDir($dir, $subdir = null)
{
if ($subdir !== null) {
$dir .= '/' . ltrim($subdir, '/');
}
return $dir;
}
/**
* Starting concrete bootstrap classes
*
* @param string $configDir
*
* @return ApplicationBootstrap
*/
public static function start($configDir)
{
$application = new static($configDir);
$application->bootstrap();
return $application;
}
/**
* Setup Icinga auto loader
*
* @return self
*/
public function setupAutoloader()
{
require $this->libDir . '/Icinga/Application/Loader.php';
$this->loader = new Loader();
$this->loader->registerNamespace('Icinga', $this->libDir. '/Icinga');
$this->loader->registerNamespace('Icinga\\Form', $this->appDir. '/forms');
$this->loader->register();
return $this;
}
/**
* Register the Zend Autoloader
*
* @return self
*/
protected function setupZendAutoloader()
{
require_once 'Zend/Loader/Autoloader.php';
\Zend_Loader_Autoloader::getInstance();
// Unfortunately this is needed to get the Zend Plugin loader working:
set_include_path(
implode(
PATH_SEPARATOR,
array($this->libDir, get_include_path())
)
);
return $this;
}
/**
* Setup module manager
*
* @return self
*/
protected function setupModuleManager()
{
$this->moduleManager = new ModuleManager(
$this,
$this->configDir . '/enabledModules',
explode(':', $this->config->global->get('modulePath', ICINGA_APPDIR . '/../modules'))
);
return $this;
}
/**
* Load all enabled modules
*
* @return self
*/
protected function loadEnabledModules()
{
try {
$this->moduleManager->loadEnabledModules();
} catch (Exception $e) {
Logger::fatal(
'Could not load modules. An exception was thrown during bootstrap: %s',
$e->getMessage()
);
}
return $this;
}
/**
* Load configuration
*
* @return self
*/
protected function loadConfig()
{
Config::$configDir = $this->configDir;
$this->config = Config::app();
return $this;
}
/**
* Error handling configuration
*
* @return self
*/
protected function setupErrorHandling()
{
error_reporting(E_ALL | E_NOTICE);
ini_set('display_startup_errors', 1);
ini_set('display_errors', 1);
return $this;
}
/**
* Set up logger
*
* @return self
*/
protected function setupLogger()
{
Logger::create($this->config->logging);
return $this;
}
/**
* Setup factories that provide access to the resources
*
* @return self
*/
protected function setupResourceFactory()
{
$config = Config::app('resources');
ResourceFactory::setConfig($config);
return $this;
}
/**
* Setup default timezone
*
* @return self
* @throws ConfigurationError if the timezone in config.ini isn't valid
*/
protected function setupTimezone()
{
$timeZoneString = $this->config->global->get('timezone', 'UTC');
try {
$tz = new DateTimeZone($timeZoneString);
} catch (Exception $e) {
throw new ConfigurationError(t('Invalid timezone') . ' "' . $timeZoneString . '"');
}
date_default_timezone_set($timeZoneString);
DateTimeFactory::setConfig(array('timezone' => $tz));
return $this;
}
/**
* Setup internationalization using gettext
*
* Uses the language defined in the global config or the default one
*
* @return self
*/
protected function setupInternationalization()
{
try {
Translator::setupLocale($this->config->global->get('language', Translator::DEFAULT_LOCALE));
} catch (Exception $error) {
Logger::info($error->getMessage());
}
$localeDir = $this->getApplicationDir('locale');
if (file_exists($localeDir) && is_dir($localeDir)) {
Translator::registerDomain('icinga', $localeDir);
}
return $this;
}
}