*/
class App
{
- const MODE_NORMAL = 0;
- const MODE_INSTALL = 1;
- const MODE_MAINTENANCE = 2;
+ const MODE_LOCALCONFIGPRESENT = 1;
+ const MODE_DBAVAILABLE = 2;
+ const MODE_DBCONFIGAVAILABLE = 4;
+ const MODE_MAINTENANCEDISABLED = 8;
+
+ /**
+ * @deprecated since version 2008.08 Use App->isInstallMode() instead to check for install mode.
+ */
+ const MODE_INSTALL = 0;
+
+ /**
+ * @deprecated since version 2008.08 Use the precise mode constant to check for a specific capability instead.
+ */
+ const MODE_NORMAL = App::MODE_LOCALCONFIGPRESENT | App::MODE_DBAVAILABLE | App::MODE_DBCONFIGAVAILABLE | App::MODE_MAINTENANCEDISABLED;
public $module_loaded = false;
public $module_class = null;
public $argv;
public $argc;
public $module;
- public $mode = App::MODE_NORMAL;
+ public $mode = App::MODE_INSTALL;
public $strings;
public $basepath;
public $urlpath;
throw new Exception('Basepath ' . $basepath . ' isn\'t usable.');
}
- $this->basepath = rtrim($basepath, DIRECTORY_SEPARATOR);
-
- $this->determineUrlPath();
-
- $this->loadConfigFiles();
+ BaseObject::setApp($this);
- $this->loadDatabase();
-
- $this->determineMode();
-
- $this->loadDefaultTimezone();
+ $this->basepath = rtrim($basepath, DIRECTORY_SEPARATOR);
$this->performance['start'] = microtime(true);
$this->performance['database'] = 0;
$this->callstack['rendering'] = [];
$this->callstack['parser'] = [];
+ // The order of the following calls is important to ensure proper initialization
+ $this->loadConfigFiles();
+
+ $this->loadDatabase();
+
+ $this->determineMode();
+
+ $this->determineUrlPath();
+
+ Config::load();
+
+ if ($this->mode & self::MODE_DBAVAILABLE) {
+ Core\Addon::loadHooks();
+
+ $this->loadAddonConfig();
+ }
+
+ $this->loadDefaultTimezone();
+
$this->page = [
'aside' => '',
'bottom' => '',
$this->register_template_engine('Friendica\Render\FriendicaSmartyEngine');
}
+ /**
+ * Load the configuration files
+ *
+ * First loads the default value for all the configuration keys, then the legacy configuration files, then the
+ * expected local.ini.php
+ */
private function loadConfigFiles()
{
- $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'defaults.ini.php');
+ $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.ini.php');
+ $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'settings.ini.php');
// Legacy .htconfig.php support
if (file_exists($this->basepath . DIRECTORY_SEPARATOR . '.htpreconfig.php')) {
$a = $this;
include $this->basepath . DIRECTORY_SEPARATOR . '.htconfig.php';
+
+ $this->setConfigValue('database', 'hostname', $db_host);
+ $this->setConfigValue('database', 'username', $db_user);
+ $this->setConfigValue('database', 'password', $db_pass);
+ $this->setConfigValue('database', 'database', $db_data);
+ if (isset($a->config['system']['db_charset'])) {
+ $this->setConfigValue('database', 'charset', $a->config['system']['db_charset']);
+ }
+
unset($db_host, $db_user, $db_pass, $db_data);
if (isset($default_timezone)) {
$this->setConfigValue('system', 'pidfile', $pidfile);
unset($pidfile);
}
+
+ if (isset($lang)) {
+ $this->setConfigValue('system', 'language', $lang);
+ unset($lang);
+ }
}
if (file_exists($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php')) {
}
}
+ /**
+ * Tries to load the specified configuration file into the App->config array.
+ * Overwrites previously set values.
+ *
+ * The config format is INI and the template for configuration files is the following:
+ *
+ * <?php return <<<INI
+ *
+ * [section]
+ * key = value
+ *
+ * INI;
+ * // Keep this line
+ *
+ * @param type $filepath
+ * @throws Exception
+ */
public function loadConfigFile($filepath)
{
if (!file_exists($filepath)) {
throw new Exception('Error parsing config file ' . $filepath);
}
- foreach($config as $category => $values) {
- foreach($values as $key => $value) {
+ foreach ($config as $category => $values) {
+ foreach ($values as $key => $value) {
$this->setConfigValue($category, $key, $value);
}
}
}
+ /**
+ * Loads addons configuration files
+ *
+ * First loads all activated addons default configuration throught the load_config hook, then load the local.ini.php
+ * again to overwrite potential local addon configuration.
+ */
private function loadAddonConfig()
{
// Loads addons default config
Core\Addon::callHooks('load_config');
- // Load the local config file again in case there are overwritten addon config
- if (file_exists($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php')) {
- $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php');
+ // Load the local addon config file to overwritten default addon config values
+ if (file_exists($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'addon.ini.php')) {
+ $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'addon.ini.php');
}
}
+ /**
+ * Loads the default timezone
+ *
+ * Include support for legacy $default_timezone
+ *
+ * @global string $default_timezone
+ */
private function loadDefaultTimezone()
{
if ($this->getConfigValue('system', 'default_timezone')) {
}
/**
- * Figure out if we are running at the top of a domain
- * or in a sub-directory and adjust accordingly
+ * Figure out if we are running at the top of a domain or in a sub-directory and adjust accordingly
*/
private function determineUrlPath()
{
*
* To get /path/to/friendica we perform dirname() for as many levels as there are slashes in the QUERY_STRING
*/
- if (!empty($_SERVER['SCRIPT_URL']) && !empty($_SERVER['QUERY_STRING'])) {
- $path = trim(dirname($_SERVER['SCRIPT_URL'], substr_count(trim($_SERVER['QUERY_STRING'], '/'), '/') + 1), '/');
+ if (!empty($_SERVER['SCRIPT_URL'])) {
+ // Module
+ if (!empty($_SERVER['QUERY_STRING'])) {
+ $path = trim(dirname($_SERVER['SCRIPT_URL'], substr_count(trim($_SERVER['QUERY_STRING'], '/'), '/') + 1), '/');
+ } else {
+ // Root page
+ $path = trim($_SERVER['SCRIPT_URL'], '/');
+ }
if ($path && $path != $this->urlpath) {
$this->urlpath = $path;
}
}
+ /**
+ * Sets the App mode
+ *
+ * - App::MODE_INSTALL : Either the database connection can't be established or the config table doesn't exist
+ * - App::MODE_MAINTENANCE: The maintenance mode has been set
+ * - App::MODE_NORMAL : Normal run with all features enabled
+ *
+ * @return type
+ */
private function determineMode()
{
- $this->mode = App::MODE_INSTALL;
+ $this->mode = 0;
+
+ if (!file_exists($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php')
+ && !file_exists($this->basepath . DIRECTORY_SEPARATOR . '.htconfig.php')) {
+ return;
+ }
+
+ $this->mode |= App::MODE_LOCALCONFIGPRESENT;
- // Missing DB connection
if (!\dba::connected()) {
return;
}
- // Working DB connection, missing tables
+ $this->mode |= App::MODE_DBAVAILABLE;
+
if (\dba::fetch_first("SHOW TABLES LIKE 'config'") === false) {
return;
}
- // Maintenance mode check
+ $this->mode |= App::MODE_DBCONFIGAVAILABLE;
+
if (Config::get('system', 'maintenance')) {
- $this->mode = App::MODE_MAINTENANCE;
- } else {
- $this->mode = App::MODE_NORMAL;
+ return;
}
+
+ $this->mode |= App::MODE_MAINTENANCEDISABLED;
}
public function loadDatabase()
// Use environment variables for mysql if they are set beforehand
if (!empty(getenv('MYSQL_HOST'))
- && !empty(getenv('MYSQL_PORT'))
&& (!empty(getenv('MYSQL_USERNAME')) || !empty(getenv('MYSQL_USER')))
- && !empty(getenv('MYSQL_PASSWORD'))
+ && getenv('MYSQL_PASSWORD') !== false
&& !empty(getenv('MYSQL_DATABASE')))
{
- $db_host = getenv('MYSQL_HOST') . ':' . getenv('MYSQL_PORT');
-
+ $db_host = getenv('MYSQL_HOST');
+ if (!empty(getenv('MYSQL_PORT'))) {
+ $db_host .= ':' . getenv('MYSQL_PORT');
+ }
if (!empty(getenv('MYSQL_USERNAME'))) {
$db_user = getenv('MYSQL_USERNAME');
- } elseif (!empty(getenv('MYSQL_USER'))) {
+ } else {
$db_user = getenv('MYSQL_USER');
}
-
- $db_pass = getenv('MYSQL_PASSWORD');
+ $db_pass = (string) getenv('MYSQL_PASSWORD');
$db_data = getenv('MYSQL_DATABASE');
- }elseif (file_exists($this->basepath . DIRECTORY_SEPARATOR . '.htconfig.php')) {
- $a = new \stdClass();
- include $this->basepath . DIRECTORY_SEPARATOR . '.htconfig.php';
- $charset = isset($a->config["system"]["db_charset"]) ? $a->config["system"]["db_charset"] : $charset;
-
- unset($a);
}
$stamp1 = microtime(true);
\dba::connect($db_host, $db_user, $db_pass, $db_data, $charset);
unset($db_host, $db_user, $db_pass, $db_data, $charset);
- $this->save_timestamp($stamp1, "network");
+ $this->save_timestamp($stamp1, 'network');
+ }
+
+ /**
+ * Install mode is when the local config file is missing or the DB schema hasn't been installed yet.
+ *
+ * @return bool
+ */
+ public function isInstallMode()
+ {
+ return !($this->mode & App::MODE_LOCALCONFIGPRESENT) || !($this->mode & App::MODE_DBCONFIGAVAILABLE);
}
/**
$this->hostname = Config::get('config', 'hostname');
}
- return $scheme . '://' . $this->hostname . ((isset($this->path) && strlen($this->path)) ? '/' . $this->path : '' );
+ return $scheme . '://' . $this->hostname . (!empty($this->urlpath) ? '/' . $this->urlpath : '' );
}
/**
$hostname .= ':' . $parsed['port'];
}
if (x($parsed, 'path')) {
- $this->path = trim($parsed['path'], '\\/');
+ $this->urlpath = trim($parsed['path'], '\\/');
}
if (file_exists($this->basepath . DIRECTORY_SEPARATOR . '.htpreconfig.php')) {
public function get_path()
{
- return $this->path;
+ return $this->urlpath;
}
public function set_pager_total($n)
*
* @return bool Is the limit reached?
*/
- public function max_processes_reached()
+ public function isMaxProcessesReached()
{
// Deactivated, needs more investigating if this check really makes sense
return false;
*
* @return bool Is the load reached?
*/
- public function maxload_reached()
+ public function isMaxLoadReached()
{
if ($this->is_backend()) {
$process = 'backend';
*/
public function getCurrentTheme()
{
- if ($this->mode == App::MODE_INSTALL) {
+ if ($this->isInstallMode()) {
return '';
}