diff --git a/bin/auth_ejabberd.php b/bin/auth_ejabberd.php index a6f30d2019..11df438952 100755 --- a/bin/auth_ejabberd.php +++ b/bin/auth_ejabberd.php @@ -33,8 +33,10 @@ */ use Friendica\App; +use Friendica\Core\Config; +use Friendica\Factory; +use Friendica\Util\BasePath; use Friendica\Util\ExAuth; -use Friendica\Util\LoggerFactory; if (sizeof($_SERVER["argv"]) == 0) { die(); @@ -52,9 +54,12 @@ chdir($directory); require dirname(__DIR__) . '/vendor/autoload.php'; -$logger = LoggerFactory::create('auth_ejabberd'); +$basedir = BasePath::create(dirname(__DIR__), $_SERVER); +$configLoader = new Config\ConfigCacheLoader($basedir); +$config = Factory\ConfigFactory::createCache($configLoader); +$logger = Factory\LoggerFactory::create('auth_ejabberd', $config); -$a = new App(dirname(__DIR__), $logger); +$a = new App($config, $logger); if ($a->getMode()->isNormal()) { $oAuth = new ExAuth(); diff --git a/bin/console.php b/bin/console.php index 9264e3eee4..9061824d87 100755 --- a/bin/console.php +++ b/bin/console.php @@ -3,11 +3,16 @@ require dirname(__DIR__) . '/vendor/autoload.php'; -use Friendica\Util\LoggerFactory; +use Friendica\Core\Config; +use Friendica\Factory; +use Friendica\Util\BasePath; -$logger = LoggerFactory::create('console'); +$basedir = BasePath::create(dirname(__DIR__), $_SERVER); +$configLoader = new Config\ConfigCacheLoader($basedir); +$config = Factory\ConfigFactory::createCache($configLoader); +$logger = Factory\LoggerFactory::create('console', $config); -$a = new Friendica\App(dirname(__DIR__), $logger); +$a = new Friendica\App($config, $logger); \Friendica\BaseObject::setApp($a); (new Friendica\Core\Console($argv))->execute(); diff --git a/bin/daemon.php b/bin/daemon.php index c7b321c11c..5c014a9270 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -11,7 +11,8 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\Worker; use Friendica\Database\DBA; -use Friendica\Util\LoggerFactory; +use Friendica\Factory; +use Friendica\Util\BasePath; // Get options $shortopts = 'f'; @@ -32,9 +33,12 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) { require dirname(__DIR__) . '/vendor/autoload.php'; -$logger = LoggerFactory::create('daemon'); +$basedir = BasePath::create(dirname(__DIR__), $_SERVER); +$configLoader = new Config\ConfigCacheLoader($basedir); +$config = Factory\ConfigFactory::createCache($configLoader); +$logger = Factory\LoggerFactory::create('daemon', $config); -$a = new App(dirname(__DIR__), $logger); +$a = new App($config, $logger); if ($a->getMode()->isInstall()) { die("Friendica isn't properly installed yet.\n"); diff --git a/bin/worker.php b/bin/worker.php index a64b6a8330..553e984977 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -4,11 +4,13 @@ * @file bin/worker.php * @brief Starts the background processing */ + use Friendica\App; use Friendica\Core\Config; -use Friendica\Core\Worker; use Friendica\Core\Update; -use Friendica\Util\LoggerFactory; +use Friendica\Core\Worker; +use Friendica\Factory; +use Friendica\Util\BasePath; // Get options $shortopts = 'sn'; @@ -29,12 +31,15 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) { require dirname(__DIR__) . '/vendor/autoload.php'; -$logger = LoggerFactory::create('worker'); +$basedir = BasePath::create(dirname(__DIR__), $_SERVER); +$configLoader = new Config\ConfigCacheLoader($basedir); +$config = Factory\ConfigFactory::createCache($configLoader); +$logger = Factory\LoggerFactory::create('worker', $config); -$a = new App(dirname(__DIR__), $logger); +$a = new App($config, $logger); // Check the database structure and possibly fixes it -Update::check(true); +Update::check($a->getBasePath(), true); // Quit when in maintenance if (!$a->getMode()->has(App\Mode::MAINTENANCEDISABLED)) { diff --git a/boot.php b/boot.php index 7dc99bbe88..318798e324 100644 --- a/boot.php +++ b/boot.php @@ -19,18 +19,13 @@ use Friendica\App; use Friendica\BaseObject; -use Friendica\Core\Addon; -use Friendica\Core\Cache; use Friendica\Core\Config; -use Friendica\Core\L10n; use Friendica\Core\PConfig; use Friendica\Core\Protocol; use Friendica\Core\System; -use Friendica\Core\Update; -use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\Model\Contact; -use Friendica\Model\Conversation; +use Friendica\Util\BasePath; use Friendica\Util\DateTimeFormat; define('FRIENDICA_PLATFORM', 'Friendica'); @@ -640,18 +635,18 @@ function get_temppath() $temppath = Config::get("system", "temppath"); - if (($temppath != "") && App::isDirectoryUsable($temppath)) { + if (($temppath != "") && System::isDirectoryUsable($temppath)) { // We have a temp path and it is usable - return App::getRealPath($temppath); + return BasePath::getRealPath($temppath); } // We don't have a working preconfigured temp path, so we take the system path. $temppath = sys_get_temp_dir(); // Check if it is usable - if (($temppath != "") && App::isDirectoryUsable($temppath)) { + if (($temppath != "") && System::isDirectoryUsable($temppath)) { // Always store the real path, not the path through symlinks - $temppath = App::getRealPath($temppath); + $temppath = BasePath::getRealPath($temppath); // To avoid any interferences with other systems we create our own directory $new_temppath = $temppath . "/" . $a->getHostName(); @@ -660,7 +655,7 @@ function get_temppath() mkdir($new_temppath); } - if (App::isDirectoryUsable($new_temppath)) { + if (System::isDirectoryUsable($new_temppath)) { // The new path is usable, we are happy Config::set("system", "temppath", $new_temppath); return $new_temppath; @@ -742,8 +737,8 @@ function get_itemcachepath() } $itemcache = Config::get('system', 'itemcache'); - if (($itemcache != "") && App::isDirectoryUsable($itemcache)) { - return App::getRealPath($itemcache); + if (($itemcache != "") && System::isDirectoryUsable($itemcache)) { + return BasePath::getRealPath($itemcache); } $temppath = get_temppath(); @@ -754,7 +749,7 @@ function get_itemcachepath() mkdir($itemcache); } - if (App::isDirectoryUsable($itemcache)) { + if (System::isDirectoryUsable($itemcache)) { Config::set("system", "itemcache", $itemcache); return $itemcache; } @@ -770,7 +765,7 @@ function get_itemcachepath() function get_spoolpath() { $spoolpath = Config::get('system', 'spoolpath'); - if (($spoolpath != "") && App::isDirectoryUsable($spoolpath)) { + if (($spoolpath != "") && System::isDirectoryUsable($spoolpath)) { // We have a spool path and it is usable return $spoolpath; } @@ -785,7 +780,7 @@ function get_spoolpath() mkdir($spoolpath); } - if (App::isDirectoryUsable($spoolpath)) { + if (System::isDirectoryUsable($spoolpath)) { // The new path is usable, we are happy Config::set("system", "spoolpath", $spoolpath); return $spoolpath; diff --git a/index.php b/index.php index c2dd31bcf2..7e7396785f 100644 --- a/index.php +++ b/index.php @@ -5,7 +5,9 @@ */ use Friendica\App; -use Friendica\Util\LoggerFactory; +use Friendica\Core\Config; +use Friendica\Factory; +use Friendica\Util\BasePath; if (!file_exists(__DIR__ . '/vendor/autoload.php')) { die('Vendor path not found. Please execute "bin/composer.phar --no-dev install" on the command line in the web root.'); @@ -13,10 +15,13 @@ if (!file_exists(__DIR__ . '/vendor/autoload.php')) { require __DIR__ . '/vendor/autoload.php'; -$logger = LoggerFactory::create('index'); +$basedir = BasePath::create(__DIR__, $_SERVER); +$configLoader = new Config\ConfigCacheLoader($basedir); +$config = Factory\ConfigFactory::createCache($configLoader); +$logger = Factory\LoggerFactory::create('index', $config); // We assume that the index.php is called by a frontend process // The value is set to "true" by default in App -$a = new App(__DIR__, $logger, false); +$a = new App($config, $logger, false); $a->runFrontend(); diff --git a/mod/admin.php b/mod/admin.php index be28168e62..da39e1beee 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -15,11 +15,11 @@ use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\Logger; use Friendica\Core\Renderer; +use Friendica\Core\StorageManager; use Friendica\Core\System; use Friendica\Core\Theme; use Friendica\Core\Update; use Friendica\Core\Worker; -use Friendica\Core\StorageManager; use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\Model\Contact; @@ -30,6 +30,7 @@ use Friendica\Module; use Friendica\Module\Login; use Friendica\Module\Tos; use Friendica\Util\Arrays; +use Friendica\Util\BasePath; use Friendica\Util\DateTimeFormat; use Friendica\Util\Network; use Friendica\Util\Strings; @@ -915,7 +916,7 @@ function admin_page_summary(App $a) } if (Config::get('system', 'dbupdate', DBStructure::UPDATE_NOT_CHECKED) == DBStructure::UPDATE_NOT_CHECKED) { - DBStructure::update(false, true); + DBStructure::update($a->getBasePath(), false, true); } if (Config::get('system', 'dbupdate') == DBStructure::UPDATE_FAILED) { $showwarning = true; @@ -1375,7 +1376,7 @@ function admin_page_site_post(App $a) Config::set('system', 'dbclean-expire-unclaimed', $dbclean_unclaimed); if ($itemcache != '') { - $itemcache = App::getRealPath($itemcache); + $itemcache = BasePath::getRealPath($itemcache); } Config::set('system', 'itemcache', $itemcache); @@ -1383,13 +1384,13 @@ function admin_page_site_post(App $a) Config::set('system', 'max_comments', $max_comments); if ($temppath != '') { - $temppath = App::getRealPath($temppath); + $temppath = BasePath::getRealPath($temppath); } Config::set('system', 'temppath', $temppath); if ($basepath != '') { - $basepath = App::getRealPath($basepath); + $basepath = BasePath::getRealPath($basepath); } Config::set('system', 'basepath' , $basepath); @@ -1724,7 +1725,7 @@ function admin_page_dbsync(App $a) } if (($a->argc > 2) && (intval($a->argv[2]) || ($a->argv[2] === 'check'))) { - $retval = DBStructure::update(false, true); + $retval = DBStructure::update($a->getBasePath(), false, true); if ($retval === '') { $o .= L10n::t("Database structure update %s was successfully applied.", DB_UPDATE_VERSION) . "
"; Config::set('database', 'last_successful_update', DB_UPDATE_VERSION); diff --git a/mod/friendica.php b/mod/friendica.php index d10deb2e88..80d5f34cc8 100644 --- a/mod/friendica.php +++ b/mod/friendica.php @@ -29,7 +29,7 @@ function friendica_init(App $a) } $sql_extra = ''; - if (!empty($a->config['admin_nickname'])) { + if (Config::get('config', 'admin_nickname') !== null) { $sql_extra = sprintf(" AND `nickname` = '%s' ", DBA::escape(Config::get('config', 'admin_nickname'))); } if (!empty(Config::get('config', 'admin_email'))) { @@ -48,8 +48,9 @@ function friendica_init(App $a) Config::load('feature_lock'); $locked_features = []; - if (!empty($a->config['feature_lock'])) { - foreach ($a->config['feature_lock'] as $k => $v) { + $featureLock = Config::get('config', 'feature_lock'); + if (isset($featureLock)) { + foreach ($featureLock as $k => $v) { if ($k === 'config_loaded') { continue; } diff --git a/src/App.php b/src/App.php index b910765e12..8068a1530b 100644 --- a/src/App.php +++ b/src/App.php @@ -8,7 +8,10 @@ use Detection\MobileDetect; use DOMDocument; use DOMXPath; use Exception; +use Friendica\Core\Config\ConfigCache; +use Friendica\Core\Config\ConfigCacheLoader; use Friendica\Database\DBA; +use Friendica\Factory\ConfigFactory; use Friendica\Network\HTTPException\InternalServerErrorException; use Psr\Log\LoggerInterface; @@ -30,7 +33,6 @@ class App public $module_loaded = false; public $module_class = null; public $query_string = ''; - public $config = []; public $page = []; public $profile; public $profile_uid; @@ -112,6 +114,31 @@ class App */ private $logger; + /** + * @var ConfigCache The cached config + */ + private $config; + + /** + * Returns the current config cache of this node + * + * @return ConfigCache + */ + public function getConfig() + { + return $this->config; + } + + /** + * The basepath of this app + * + * @return string + */ + public function getBasePath() + { + return $this->basePath; + } + /** * Register a stylesheet file path to be included in the tag of every page. * Inclusion is done in App->initHead(). @@ -124,7 +151,7 @@ class App */ public function registerStylesheet($path) { - $url = str_replace($this->getBasePath() . DIRECTORY_SEPARATOR, '', $path); + $url = str_replace($this->basePath . DIRECTORY_SEPARATOR, '', $path); $this->stylesheets[] = trim($url, '/'); } @@ -141,7 +168,7 @@ class App */ public function registerFooterScript($path) { - $url = str_replace($this->getBasePath() . DIRECTORY_SEPARATOR, '', $path); + $url = str_replace($this->basePath . DIRECTORY_SEPARATOR, '', $path); $this->footerScripts[] = trim($url, '/'); } @@ -154,23 +181,25 @@ class App /** * @brief App constructor. * - * @param string $basePath Path to the app base folder + * @param ConfigCache $config The Cached Config * @param LoggerInterface $logger Logger of this application * @param bool $isBackend Whether it is used for backend or frontend (Default true=backend) * * @throws Exception if the Basepath is not usable */ - public function __construct($basePath, LoggerInterface $logger, $isBackend = true) + public function __construct(ConfigCache $config, LoggerInterface $logger, $isBackend = true) { - $this->logger = $logger; + $this->config = $config; + $this->logger = $logger; + $this->basePath = $this->config->get('system', 'basepath'); - if (!static::isDirectoryUsable($basePath, false)) { - throw new Exception('Basepath ' . $basePath . ' isn\'t usable.'); + if (!Core\System::isDirectoryUsable($this->basePath, false)) { + throw new Exception('Basepath ' . $this->basePath . ' isn\'t usable.'); } + $this->basePath = rtrim($this->basePath, DIRECTORY_SEPARATOR); BaseObject::setApp($this); - $this->basePath = rtrim($basePath, DIRECTORY_SEPARATOR); $this->checkBackend($isBackend); $this->checkFriendicaApp(); @@ -195,7 +224,7 @@ class App $this->callstack['rendering'] = []; $this->callstack['parser'] = []; - $this->mode = new App\Mode($basePath); + $this->mode = new App\Mode($this->basePath); $this->reload(); @@ -226,9 +255,9 @@ class App set_include_path( get_include_path() . PATH_SEPARATOR - . $this->getBasePath() . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR - . $this->getBasePath() . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR - . $this->getBasePath()); + . $this->basePath . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR + . $this->basePath . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR + . $this->basePath); if (!empty($_SERVER['QUERY_STRING']) && strpos($_SERVER['QUERY_STRING'], 'pagename=') === 0) { $this->query_string = substr($_SERVER['QUERY_STRING'], 9); @@ -332,21 +361,32 @@ class App */ public function reload() { - // The order of the following calls is important to ensure proper initialization - $this->loadConfigFiles(); + Core\Config::init($this->config); + Core\PConfig::init($this->config); $this->loadDatabase(); - $this->getMode()->determine($this->getBasePath()); + $this->getMode()->determine($this->basePath); $this->determineURLPath(); - Core\Config::load(); + if ($this->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { + $adapterType = $this->config->get('system', 'config_adapter'); + $adapter = ConfigFactory::createConfig($adapterType, $this->config); + Core\Config::setAdapter($adapter); + $adapterP = ConfigFactory::createPConfig($adapterType, $this->config); + Core\PConfig::setAdapter($adapterP); + Core\Config::load(); + } + + // again because DB-config could change the config + $this->getMode()->determine($this->basePath); if ($this->getMode()->has(App\Mode::DBAVAILABLE)) { Core\Hook::loadHooks(); - - $this->loadAddonConfig(); + $loader = new ConfigCacheLoader($this->basePath); + Core\Hook::callAll('load_config', $loader); + $this->config->loadConfigArray($loader->loadCoreConfig('addon'), true); } $this->loadDefaultTimezone(); @@ -358,158 +398,6 @@ class App Core\Logger::setLogger($this->logger); } - /** - * Load the configuration files - * - * First loads the default value for all the configuration keys, then the legacy configuration files, then the - * expected local.config.php - */ - private function loadConfigFiles() - { - $this->loadConfigFile($this->getBasePath() . '/config/defaults.config.php'); - $this->loadConfigFile($this->getBasePath() . '/config/settings.config.php'); - - // Legacy .htconfig.php support - if (file_exists($this->getBasePath() . '/.htpreconfig.php')) { - $a = $this; - include $this->getBasePath() . '/.htpreconfig.php'; - } - - // Legacy .htconfig.php support - if (file_exists($this->getBasePath() . '/.htconfig.php')) { - $a = $this; - - include $this->getBasePath() . '/.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', 'default_timezone', $default_timezone); - unset($default_timezone); - } - - if (isset($pidfile)) { - $this->setConfigValue('system', 'pidfile', $pidfile); - unset($pidfile); - } - - if (isset($lang)) { - $this->setConfigValue('system', 'language', $lang); - unset($lang); - } - } - - if (file_exists($this->getBasePath() . '/config/local.config.php')) { - $this->loadConfigFile($this->getBasePath() . '/config/local.config.php', true); - } elseif (file_exists($this->getBasePath() . '/config/local.ini.php')) { - $this->loadINIConfigFile($this->getBasePath() . '/config/local.ini.php', true); - } - } - - /** - * Tries to load the specified legacy configuration file into the App->config array. - * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. - * - * @deprecated since version 2018.12 - * @param string $filepath - * @param bool $overwrite Force value overwrite if the config key already exists - * @throws Exception - */ - public function loadINIConfigFile($filepath, $overwrite = false) - { - if (!file_exists($filepath)) { - throw new Exception('Error parsing non-existent INI config file ' . $filepath); - } - - $contents = include($filepath); - - $config = parse_ini_string($contents, true, INI_SCANNER_TYPED); - - if ($config === false) { - throw new Exception('Error parsing INI config file ' . $filepath); - } - - $this->loadConfigArray($config, $overwrite); - } - - /** - * Tries to load the specified configuration file into the App->config array. - * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. - * - * The config format is PHP array and the template for configuration files is the following: - * - * [ - * 'key' => 'value', - * ], - * ]; - * - * @param string $filepath - * @param bool $overwrite Force value overwrite if the config key already exists - * @throws Exception - */ - public function loadConfigFile($filepath, $overwrite = false) - { - if (!file_exists($filepath)) { - throw new Exception('Error loading non-existent config file ' . $filepath); - } - - $config = include($filepath); - - if (!is_array($config)) { - throw new Exception('Error loading config file ' . $filepath); - } - - $this->loadConfigArray($config, $overwrite); - } - - /** - * Loads addons configuration files - * - * First loads all activated addons default configuration through the load_config hook, then load the local.config.php - * again to overwrite potential local addon configuration. - */ - private function loadAddonConfig() - { - // Loads addons default config - Core\Hook::callAll('load_config'); - - // Load the local addon config file to overwritten default addon config values - if (file_exists($this->getBasePath() . '/config/addon.config.php')) { - $this->loadConfigFile($this->getBasePath() . '/config/addon.config.php', true); - } elseif (file_exists($this->getBasePath() . '/config/addon.ini.php')) { - $this->loadINIConfigFile($this->getBasePath() . '/config/addon.ini.php', true); - } - } - - /** - * Tries to load the specified configuration array into the App->config array. - * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. - * - * @param array $config - * @param bool $overwrite Force value overwrite if the config key already exists - */ - private function loadConfigArray(array $config, $overwrite = false) - { - foreach ($config as $category => $values) { - foreach ($values as $key => $value) { - if ($overwrite) { - $this->setConfigValue($category, $key, $value); - } else { - $this->setDefaultConfigValue($category, $key, $value); - } - } - } - } - /** * Loads the default timezone * @@ -519,8 +407,8 @@ class App */ private function loadDefaultTimezone() { - if ($this->getConfigValue('system', 'default_timezone')) { - $this->timezone = $this->getConfigValue('system', 'default_timezone'); + if ($this->config->get('system', 'default_timezone')) { + $this->timezone = $this->config->get('system', 'default_timezone'); } else { global $default_timezone; $this->timezone = !empty($default_timezone) ? $default_timezone : 'UTC'; @@ -546,7 +434,7 @@ class App $relative_script_path = defaults($_SERVER, 'SCRIPT_URL' , $relative_script_path); $relative_script_path = defaults($_SERVER, 'REQUEST_URI' , $relative_script_path); - $this->urlPath = $this->getConfigValue('system', 'urlpath'); + $this->urlPath = $this->config->get('system', 'urlpath'); /* $relative_script_path gives /relative/path/to/friendica/module/parameter * QUERY_STRING gives pagename=module/parameter @@ -574,11 +462,11 @@ class App return; } - $db_host = $this->getConfigValue('database', 'hostname'); - $db_user = $this->getConfigValue('database', 'username'); - $db_pass = $this->getConfigValue('database', 'password'); - $db_data = $this->getConfigValue('database', 'database'); - $charset = $this->getConfigValue('database', 'charset'); + $db_host = $this->config->get('database', 'hostname'); + $db_user = $this->config->get('database', 'username'); + $db_pass = $this->config->get('database', 'password'); + $db_data = $this->config->get('database', 'database'); + $charset = $this->config->get('database', 'charset'); // Use environment variables for mysql if they are set beforehand if (!empty(getenv('MYSQL_HOST')) @@ -601,9 +489,9 @@ class App $stamp1 = microtime(true); - if (DBA::connect($db_host, $db_user, $db_pass, $db_data, $charset)) { + if (DBA::connect($this->config, $db_host, $db_user, $db_pass, $db_data, $charset)) { // Loads DB_UPDATE_VERSION constant - Database\DBStructure::definition(false); + Database\DBStructure::definition($this->basePath, false); } unset($db_host, $db_user, $db_pass, $db_data, $charset); @@ -611,55 +499,6 @@ class App $this->saveTimestamp($stamp1, 'network'); } - /** - * @brief Returns the base filesystem path of the App - * - * It first checks for the internal variable, then for DOCUMENT_ROOT and - * finally for PWD - * - * @return string - * @throws InternalServerErrorException - */ - public function getBasePath() - { - $basepath = $this->basePath; - - if (!$basepath) { - $basepath = Core\Config::get('system', 'basepath'); - } - - if (!$basepath && !empty($_SERVER['DOCUMENT_ROOT'])) { - $basepath = $_SERVER['DOCUMENT_ROOT']; - } - - if (!$basepath && !empty($_SERVER['PWD'])) { - $basepath = $_SERVER['PWD']; - } - - return self::getRealPath($basepath); - } - - /** - * @brief Returns a normalized file path - * - * This is a wrapper for the "realpath" function. - * That function cannot detect the real path when some folders aren't readable. - * Since this could happen with some hosters we need to handle this. - * - * @param string $path The path that is about to be normalized - * @return string normalized path - when possible - */ - public static function getRealPath($path) - { - $normalized = realpath($path); - - if (!is_bool($normalized)) { - return $normalized; - } else { - return $path; - } - } - public function getScheme() { return $this->scheme; @@ -735,8 +574,8 @@ class App $this->urlPath = trim($parsed['path'], '\\/'); } - if (file_exists($this->getBasePath() . '/.htpreconfig.php')) { - include $this->getBasePath() . '/.htpreconfig.php'; + if (file_exists($this->basePath . '/.htpreconfig.php')) { + include $this->basePath . '/.htpreconfig.php'; } if (Core\Config::get('config', 'hostname') != '') { @@ -789,9 +628,9 @@ class App // compose the page title from the sitename and the // current module called if (!$this->module == '') { - $this->page['title'] = $this->config['sitename'] . ' (' . $this->module . ')'; + $this->page['title'] = $this->config->get('config', 'sitename') . ' (' . $this->module . ')'; } else { - $this->page['title'] = $this->config['sitename']; + $this->page['title'] = $this->config->get('config', 'sitename'); } if (!empty(Core\Renderer::$theme['stylesheet'])) { @@ -912,7 +751,9 @@ class App */ public function saveTimestamp($timestamp, $value) { - if (!isset($this->config['system']['profiler']) || !$this->config['system']['profiler']) { + $profiler = $this->config->get('system', 'profiler'); + + if (!isset($profiler) || !$profiler) { return; } @@ -1150,7 +991,7 @@ class App return; } - $cmdline = $this->getConfigValue('config', 'php_path', 'php') . ' ' . escapeshellarg($command); + $cmdline = $this->config->get('config', 'php_path', 'php') . ' ' . escapeshellarg($command); foreach ($args as $key => $value) { if (!is_null($value) && is_bool($value) && !$value) { @@ -1168,9 +1009,9 @@ class App } if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { - $resource = proc_open('cmd /c start /b ' . $cmdline, [], $foo, $this->getBasePath()); + $resource = proc_open('cmd /c start /b ' . $cmdline, [], $foo, $this->basePath); } else { - $resource = proc_open($cmdline . ' &', [], $foo, $this->getBasePath()); + $resource = proc_open($cmdline . ' &', [], $foo, $this->basePath); } if (!is_resource($resource)) { Core\Logger::log('We got no resource for command ' . $cmdline, Core\Logger::DEBUG); @@ -1179,203 +1020,6 @@ class App proc_close($resource); } - /** - * @brief Returns the system user that is executing the script - * - * This mostly returns something like "www-data". - * - * @return string system username - */ - private static function getSystemUser() - { - if (!function_exists('posix_getpwuid') || !function_exists('posix_geteuid')) { - return ''; - } - - $processUser = posix_getpwuid(posix_geteuid()); - return $processUser['name']; - } - - /** - * @brief Checks if a given directory is usable for the system - * - * @param $directory - * @param bool $check_writable - * @return boolean the directory is usable - * @throws Exception - */ - public static function isDirectoryUsable($directory, $check_writable = true) - { - if ($directory == '') { - Core\Logger::log('Directory is empty. This shouldn\'t happen.', Core\Logger::DEBUG); - return false; - } - - if (!file_exists($directory)) { - Core\Logger::log('Path "' . $directory . '" does not exist for user ' . self::getSystemUser(), Core\Logger::DEBUG); - return false; - } - - if (is_file($directory)) { - Core\Logger::log('Path "' . $directory . '" is a file for user ' . self::getSystemUser(), Core\Logger::DEBUG); - return false; - } - - if (!is_dir($directory)) { - Core\Logger::log('Path "' . $directory . '" is not a directory for user ' . self::getSystemUser(), Core\Logger::DEBUG); - return false; - } - - if ($check_writable && !is_writable($directory)) { - Core\Logger::log('Path "' . $directory . '" is not writable for user ' . self::getSystemUser(), Core\Logger::DEBUG); - return false; - } - - return true; - } - - /** - * @param string $cat Config category - * @param string $k Config key - * @param mixed $default Default value if it isn't set - * - * @return string Returns the value of the Config entry - */ - public function getConfigValue($cat, $k, $default = null) - { - $return = $default; - - if ($cat === 'config') { - if (isset($this->config[$k])) { - $return = $this->config[$k]; - } - } else { - if (isset($this->config[$cat][$k])) { - $return = $this->config[$cat][$k]; - } - } - - return $return; - } - - /** - * Sets a default value in the config cache. Ignores already existing keys. - * - * @param string $cat Config category - * @param string $k Config key - * @param mixed $v Default value to set - */ - private function setDefaultConfigValue($cat, $k, $v) - { - if (!isset($this->config[$cat][$k])) { - $this->setConfigValue($cat, $k, $v); - } - } - - /** - * Sets a value in the config cache. Accepts raw output from the config table - * - * @param string $cat Config category - * @param string $k Config key - * @param mixed $v Value to set - */ - public function setConfigValue($cat, $k, $v) - { - // Only arrays are serialized in database, so we have to unserialize sparingly - $value = is_string($v) && preg_match("|^a:[0-9]+:{.*}$|s", $v) ? unserialize($v) : $v; - - if ($cat === 'config') { - $this->config[$k] = $value; - } else { - if (!isset($this->config[$cat])) { - $this->config[$cat] = []; - } - - $this->config[$cat][$k] = $value; - } - } - - /** - * Deletes a value from the config cache - * - * @param string $cat Config category - * @param string $k Config key - */ - public function deleteConfigValue($cat, $k) - { - if ($cat === 'config') { - if (isset($this->config[$k])) { - unset($this->config[$k]); - } - } else { - if (isset($this->config[$cat][$k])) { - unset($this->config[$cat][$k]); - } - } - } - - - /** - * Retrieves a value from the user config cache - * - * @param int $uid User Id - * @param string $cat Config category - * @param string $k Config key - * @param mixed $default Default value if key isn't set - * - * @return string The value of the config entry - */ - public function getPConfigValue($uid, $cat, $k, $default = null) - { - $return = $default; - - if (isset($this->config[$uid][$cat][$k])) { - $return = $this->config[$uid][$cat][$k]; - } - - return $return; - } - - /** - * Sets a value in the user config cache - * - * Accepts raw output from the pconfig table - * - * @param int $uid User Id - * @param string $cat Config category - * @param string $k Config key - * @param mixed $v Value to set - */ - public function setPConfigValue($uid, $cat, $k, $v) - { - // Only arrays are serialized in database, so we have to unserialize sparingly - $value = is_string($v) && preg_match("|^a:[0-9]+:{.*}$|s", $v) ? unserialize($v) : $v; - - if (!isset($this->config[$uid]) || !is_array($this->config[$uid])) { - $this->config[$uid] = []; - } - - if (!isset($this->config[$uid][$cat]) || !is_array($this->config[$uid][$cat])) { - $this->config[$uid][$cat] = []; - } - - $this->config[$uid][$cat][$k] = $value; - } - - /** - * Deletes a value from the user config cache - * - * @param int $uid User Id - * @param string $cat Config category - * @param string $k Config key - */ - public function deletePConfigValue($uid, $cat, $k) - { - if (isset($this->config[$uid][$cat][$k])) { - unset($this->config[$uid][$cat][$k]); - } - } - /** * Generates the site's default sender email address * @@ -1643,7 +1287,7 @@ class App $this->module = 'maintenance'; } else { $this->checkURL(); - Core\Update::check(false); + Core\Update::check($this->basePath, false); Core\Addon::loadAddons(); Core\Hook::loadHooks(); } diff --git a/src/BaseObject.php b/src/BaseObject.php index 84ff193823..4a6fa12d24 100644 --- a/src/BaseObject.php +++ b/src/BaseObject.php @@ -6,7 +6,7 @@ namespace Friendica; require_once 'boot.php'; -use Friendica\Util\LoggerFactory; +use Friendica\Network\HTTPException\InternalServerErrorException; /** * Basic object @@ -28,8 +28,7 @@ class BaseObject public static function getApp() { if (empty(self::$app)) { - $logger = $logger = LoggerFactory::create('app'); - self::$app = new App(dirname(__DIR__), $logger); + throw new InternalServerErrorException('App isn\'t initialized.'); } return self::$app; diff --git a/src/Core/Addon.php b/src/Core/Addon.php index 1118280a53..14b163f165 100644 --- a/src/Core/Addon.php +++ b/src/Core/Addon.php @@ -12,6 +12,12 @@ use Friendica\Database\DBA; */ class Addon extends BaseObject { + /** + * The addon sub-directory + * @var string + */ + const DIRECTORY = 'addon'; + /** * List of the names of enabled addons * diff --git a/src/Core/Config.php b/src/Core/Config.php index 755dc6ebbc..6ceb637701 100644 --- a/src/Core/Config.php +++ b/src/Core/Config.php @@ -8,8 +8,9 @@ */ namespace Friendica\Core; -use Friendica\App; -use Friendica\BaseObject; +use Friendica\Core\Config\ConfigCache; +use Friendica\Core\Config\IConfigAdapter; +use Friendica\Core\Config\IConfigCache; /** * @brief Arbitrary system configuration storage @@ -18,49 +19,53 @@ use Friendica\BaseObject; * If we ever would decide to return exactly the variable type as entered, * we will have fun with the additional features. :-) */ -class Config extends BaseObject +class Config { /** - * @var \Friendica\Core\Config\IConfigAdapter + * @var Config\IConfigAdapter */ - private static $adapter = null; + private static $adapter; - public static function init() + /** + * @var Config\IConfigCache + */ + private static $cache; + + /** + * Initialize the config with only the cache + * + * @param Config\IConfigCache $cache The configuration cache + */ + public static function init(Config\IConfigCache $cache) { - // Database isn't ready or populated yet - if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - return; - } + self::$cache = $cache; + } - if (self::getApp()->getConfigValue('system', 'config_adapter') == 'preload') { - self::$adapter = new Config\PreloadConfigAdapter(); - } else { - self::$adapter = new Config\JITConfigAdapter(); - } + /** + * Add the adapter for DB-backend + * + * @param Config\IConfigAdapter $adapter + */ + public static function setAdapter(Config\IConfigAdapter $adapter) + { + self::$adapter = $adapter; } /** * @brief Loads all configuration values of family into a cached storage. * - * All configuration values of the system are stored in global cache - * which is available under the global variable $a->config + * All configuration values of the system are stored in the cache ( @see IConfigCache ) * * @param string $family The category of the configuration value * * @return void - * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ public static function load($family = "config") { - // Database isn't ready or populated yet - if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { + if (!isset(self::$adapter)) { return; } - if (empty(self::$adapter)) { - self::init(); - } - self::$adapter->load($family); } @@ -69,12 +74,8 @@ class Config extends BaseObject * ($family) and a key. * * Get a particular config value from the given category ($family) - * and the $key from a cached storage in $a->config[$uid]. - * $instore is only used by the set_config function - * to determine if the key already exists in the DB - * If a key is found in the DB but doesn't exist in - * local config cache, pull it into the cache so we don't have - * to hit the DB again for this item. + * and the $key from a cached storage either from the self::$adapter + * (@see IConfigAdapter ) or from the static::$cache (@see IConfigCache ). * * @param string $family The category of the configuration value * @param string $key The configuration key to query @@ -82,17 +83,11 @@ class Config extends BaseObject * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) * * @return mixed Stored value or null if it does not exist - * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ public static function get($family, $key, $default_value = null, $refresh = false) { - // Database isn't ready or populated yet, fallback to file config - if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - return self::getApp()->getConfigValue($family, $key, $default_value); - } - - if (empty(self::$adapter)) { - self::init(); + if (!isset(self::$adapter)) { + return self::$cache->get($family, $key, $default_value); } return self::$adapter->get($family, $key, $default_value, $refresh); @@ -102,7 +97,6 @@ class Config extends BaseObject * @brief Sets a configuration value for system config * * Stores a config value ($value) in the category ($family) under the key ($key) - * for the user_id $uid. * * Note: Please do not store booleans - convert to 0/1 integer values! * @@ -111,17 +105,12 @@ class Config extends BaseObject * @param mixed $value The value to store * * @return bool Operation success - * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ public static function set($family, $key, $value) { - // Database isn't ready or populated yet - if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - return false; - } - - if (empty(self::$adapter)) { - self::init(); + if (!isset(self::$adapter)) { + self::$cache->set($family, $key, $value); + return true; } return self::$adapter->set($family, $key, $value); @@ -130,24 +119,18 @@ class Config extends BaseObject /** * @brief Deletes the given key from the system configuration. * - * Removes the configured value from the stored cache in $a->config - * and removes it from the database. + * Removes the configured value from the stored cache in self::$config + * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ). * * @param string $family The category of the configuration value * @param string $key The configuration key to delete * * @return mixed - * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ public static function delete($family, $key) { - // Database isn't ready or populated yet - if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - return false; - } - - if (empty(self::$adapter)) { - self::init(); + if (!isset(self::$adapter)) { + self::$cache->delete($family, $key); } return self::$adapter->delete($family, $key); diff --git a/src/Core/Config/ConfigCache.php b/src/Core/Config/ConfigCache.php new file mode 100644 index 0000000000..e03d352566 --- /dev/null +++ b/src/Core/Config/ConfigCache.php @@ -0,0 +1,173 @@ +config = $config; + } + + /** + * Tries to load the specified configuration array into the App->config array. + * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. + * + * @param array $config + * @param bool $overwrite Force value overwrite if the config key already exists + */ + public function loadConfigArray(array $config, $overwrite = false) + { + foreach ($config as $category => $values) { + foreach ($values as $key => $value) { + if ($overwrite) { + $this->set($category, $key, $value); + } else { + $this->setDefault($category, $key, $value); + } + } + } + } + + /** + * {@inheritdoc} + */ + public function get($cat, $key = null, $default = null) + { + $return = $default; + + if ($cat === 'config') { + if (isset($this->config[$key])) { + $return = $this->config[$key]; + } + } else { + if (isset($this->config[$cat][$key])) { + $return = $this->config[$cat][$key]; + } elseif ($key == null && isset($this->config[$cat])) { + $return = $this->config[$cat]; + } + } + + return $return; + } + + /** + * Sets a default value in the config cache. Ignores already existing keys. + * + * @param string $cat Config category + * @param string $k Config key + * @param mixed $v Default value to set + */ + private function setDefault($cat, $k, $v) + { + if (!isset($this->config[$cat][$k])) { + $this->set($cat, $k, $v); + } + } + + /** + * {@inheritdoc} + */ + public function set($cat, $key, $value) + { + // Only arrays are serialized in database, so we have to unserialize sparingly + $value = is_string($value) && preg_match("|^a:[0-9]+:{.*}$|s", $value) ? unserialize($value) : $value; + + if ($cat === 'config') { + $this->config[$key] = $value; + } else { + if (!isset($this->config[$cat])) { + $this->config[$cat] = []; + } + + $this->config[$cat][$key] = $value; + } + } + + /** + * {@inheritdoc} + */ + public function delete($cat, $key) + { + if ($cat === 'config') { + if (isset($this->config[$key])) { + unset($this->config[$key]); + } + } else { + if (isset($this->config[$cat][$key])) { + unset($this->config[$cat][$key]); + } + } + } + + /** + * {@inheritdoc} + */ + public function getP($uid, $cat, $key = null, $default = null) + { + $return = $default; + + if (isset($this->config[$uid][$cat][$key])) { + $return = $this->config[$uid][$cat][$key]; + } elseif ($key === null && isset($this->config[$uid][$cat])) { + $return = $this->config[$uid][$cat]; + } + + return $return; + } + + /** + * {@inheritdoc} + */ + public function setP($uid, $cat, $key, $value) + { + // Only arrays are serialized in database, so we have to unserialize sparingly + $value = is_string($value) && preg_match("|^a:[0-9]+:{.*}$|s", $value) ? unserialize($value) : $value; + + if (!isset($this->config[$uid]) || !is_array($this->config[$uid])) { + $this->config[$uid] = []; + } + + if (!isset($this->config[$uid][$cat]) || !is_array($this->config[$uid][$cat])) { + $this->config[$uid][$cat] = []; + } + + if ($key === null) { + $this->config[$uid][$cat] = $value; + } else { + $this->config[$uid][$cat][$key] = $value; + } + } + + /** + * {@inheritdoc} + */ + public function deleteP($uid, $cat, $key) + { + if (isset($this->config[$uid][$cat][$key])) { + unset($this->config[$uid][$cat][$key]); + } + } + + /** + * Returns the whole configuration + * + * @return array The configuration + */ + public function getAll() + { + return $this->config; + } +} diff --git a/src/Core/Config/ConfigCacheLoader.php b/src/Core/Config/ConfigCacheLoader.php new file mode 100644 index 0000000000..0b8761415c --- /dev/null +++ b/src/Core/Config/ConfigCacheLoader.php @@ -0,0 +1,208 @@ +baseDir = $baseDir; + $this->configDir = $baseDir . DIRECTORY_SEPARATOR . self::SUBDIRECTORY; + } + + /** + * Load the configuration files + * + * First loads the default value for all the configuration keys, then the legacy configuration files, then the + * expected local.config.php + */ + public function loadConfigFiles(ConfigCache $config) + { + // Setting at least the basepath we know + $config->set('system', 'basepath', $this->baseDir); + + $config->loadConfigArray($this->loadCoreConfig('defaults')); + $config->loadConfigArray($this->loadCoreConfig('settings')); + + $config->loadConfigArray($this->loadLegacyConfig('htpreconfig'), true); + $config->loadConfigArray($this->loadLegacyConfig('htconfig'), true); + + $config->loadConfigArray($this->loadCoreConfig('local'), true); + } + + /** + * Tries to load the specified core-configuration and returns the config array. + * + * @param string $name The name of the configuration + * + * @return array The config array (empty if no config found) + * + * @throws \Exception if the configuration file isn't readable + */ + public function loadCoreConfig($name) + { + if (file_exists($this->configDir . DIRECTORY_SEPARATOR . $name . '.config.php')) { + return $this->loadConfigFile($this->configDir . DIRECTORY_SEPARATOR . $name . '.config.php'); + } elseif (file_exists($this->configDir . DIRECTORY_SEPARATOR . $name . '.ini.php')) { + return $this->loadINIConfigFile($this->configDir . DIRECTORY_SEPARATOR . $name . '.ini.php'); + } else { + return []; + } + } + + /** + * Tries to load the specified addon-configuration and returns the config array. + * + * @param string $name The name of the configuration + * + * @return array The config array (empty if no config found) + * + * @throws \Exception if the configuration file isn't readable + */ + public function loadAddonConfig($name) + { + $filepath = $this->baseDir . DIRECTORY_SEPARATOR . // /var/www/html/ + Addon::DIRECTORY . DIRECTORY_SEPARATOR . // addon/ + $name . DIRECTORY_SEPARATOR . // openstreetmap/ + self::SUBDIRECTORY . DIRECTORY_SEPARATOR . // config/ + $name . ".config.php"; // openstreetmap.config.php + + if (file_exists($filepath)) { + return $this->loadConfigFile($filepath); + } else { + return []; + } + } + + /** + * Tries to load the legacy config files (.htconfig.php, .htpreconfig.php) and returns the config array. + * + * @param string $name The name of the config file + * + * @return array The configuration array (empty if no config found) + * + * @deprecated since version 2018.09 + */ + private function loadLegacyConfig($name) + { + $filePath = $this->baseDir . DIRECTORY_SEPARATOR . '.' . $name . '.php'; + + if (file_exists($filePath)) { + $a = new \stdClass(); + $a->config = []; + include $filePath; + + if (isset($db_host)) { + $a->config['database']['hostname'] = $db_host; + unset($db_host); + } + if (isset($db_user)) { + $a->config['database']['username'] = $db_user; + unset($db_user); + } + if (isset($db_pass)) { + $a->config['database']['password'] = $db_pass; + unset($db_pass); + } + if (isset($db_data)) { + $a->config['database']['database'] = $db_data; + unset($db_data); + } + if (isset($a->config['system']['db_charset'])) { + $a->config['database']['charset'] = $a->config['system']['charset']; + } + if (isset($pidfile)) { + $a->config['system']['pidfile'] = $pidfile; + unset($pidfile); + } + if (isset($default_timezone)) { + $a->config['system']['default_timezone'] = $default_timezone; + unset($default_timezone); + } + if (isset($lang)) { + $a->config['system']['language'] = $lang; + unset($lang); + } + + return $a->config; + } else { + return []; + } + } + + /** + * Tries to load the specified legacy configuration file and returns the config array. + * + * @deprecated since version 2018.12 + * @param string $filepath + * + * @return array The configuration array + * @throws \Exception + */ + private function loadINIConfigFile($filepath) + { + if (!file_exists($filepath)) { + throw new \Exception('Error parsing non-existent INI config file ' . $filepath); + } + + $contents = include($filepath); + + $config = parse_ini_string($contents, true, INI_SCANNER_TYPED); + + if ($config === false) { + throw new \Exception('Error parsing INI config file ' . $filepath); + } + + return $config; + } + + /** + * Tries to load the specified configuration file and returns the config array. + * + * The config format is PHP array and the template for configuration files is the following: + * + * [ + * 'key' => 'value', + * ], + * ]; + * + * @param string $filepath The filepath of the + * @return array The config array0 + * + * @throws \Exception if the config cannot get loaded. + */ + private function loadConfigFile($filepath) + { + if (!file_exists($filepath)) { + throw new \Exception('Error loading non-existent config file ' . $filepath); + } + + $config = include($filepath); + + if (!is_array($config)) { + throw new \Exception('Error loading config file ' . $filepath); + } + + return $config; + } +} diff --git a/src/Core/Config/IConfigAdapter.php b/src/Core/Config/IConfigAdapter.php index 9d8eefd777..139483de26 100644 --- a/src/Core/Config/IConfigAdapter.php +++ b/src/Core/Config/IConfigAdapter.php @@ -9,10 +9,7 @@ namespace Friendica\Core\Config; interface IConfigAdapter { /** - * @brief Loads all configuration values into a cached storage. - * - * All configuration values of the system are stored in global cache - * which is available under the global variable $a->config + * Loads all configuration values into a cached storage. * * @param string $cat The category of the configuration values to load * @@ -21,17 +18,9 @@ interface IConfigAdapter public function load($cat = "config"); /** - * @brief Get a particular user's config variable given the category name + * Get a particular user's config variable given the category name * ($family) and a key. * - * Get a particular config value from the given category ($family) - * and the $key from a cached storage in $a->config[$uid]. - * $instore is only used by the set_config function - * to determine if the key already exists in the DB - * If a key is found in the DB but doesn't exist in - * local config cache, pull it into the cache so we don't have - * to hit the DB again for this item. - * * @param string $cat The category of the configuration value * @param string $k The configuration key to query * @param mixed $default_value optional, The value to return if key is not set (default: null) @@ -42,8 +31,6 @@ interface IConfigAdapter public function get($cat, $k, $default_value = null, $refresh = false); /** - * @brief Sets a configuration value for system config - * * Stores a config value ($value) in the category ($family) under the key ($key) * for the user_id $uid. * @@ -58,9 +45,7 @@ interface IConfigAdapter public function set($cat, $k, $value); /** - * @brief Deletes the given key from the system configuration. - * - * Removes the configured value from the stored cache in $a->config + * Removes the configured value from the stored cache * and removes it from the database. * * @param string $cat The category of the configuration value diff --git a/src/Core/Config/IConfigCache.php b/src/Core/Config/IConfigCache.php new file mode 100644 index 0000000000..8266cc2dd4 --- /dev/null +++ b/src/Core/Config/IConfigCache.php @@ -0,0 +1,37 @@ +config[$uid]. + * Loads all configuration values of a user's config family into a cached storage. * * @param string $uid The user_id * @param string $cat The category of the configuration value @@ -28,12 +25,9 @@ interface IPConfigAdapter public function load($uid, $cat); /** - * @brief Get a particular user's config variable given the category name + * Get a particular user's config variable given the category name * ($family) and a key. * - * Get a particular user's config value from the given category ($family) - * and the $key from a cached storage in $a->config[$uid]. - * * @param string $uid The user_id * @param string $cat The category of the configuration value * @param string $k The configuration key to query @@ -45,8 +39,6 @@ interface IPConfigAdapter public function get($uid, $cat, $k, $default_value = null, $refresh = false); /** - * @brief Sets a configuration value for a user - * * Stores a config value ($value) in the category ($family) under the key ($key) * for the user_id $uid. * @@ -62,9 +54,7 @@ interface IPConfigAdapter public function set($uid, $cat, $k, $value); /** - * @brief Deletes the given key from the users's configuration. - * - * Removes the configured value from the stored cache in $a->config[$uid] + * Removes the configured value from the stored cache * and removes it from the database. * * @param string $uid The user_id diff --git a/src/Core/Config/IPConfigCache.php b/src/Core/Config/IPConfigCache.php new file mode 100644 index 0000000000..6a57dafa89 --- /dev/null +++ b/src/Core/Config/IPConfigCache.php @@ -0,0 +1,44 @@ + */ -class JITConfigAdapter extends BaseObject implements IConfigAdapter +class JITConfigAdapter implements IConfigAdapter { private $cache; private $in_db; + /** + * @var IConfigCache The config cache of this driver + */ + private $configCache; + + /** + * @param IConfigCache $configCache The config cache of this driver + */ + public function __construct(IConfigCache $configCache) + { + $this->configCache = $configCache; + } + + /** + * {@inheritdoc} + */ public function load($cat = "config") { // We don't preload "system" anymore. @@ -28,7 +43,7 @@ class JITConfigAdapter extends BaseObject implements IConfigAdapter while ($config = DBA::fetch($configs)) { $k = $config['k']; - self::getApp()->setConfigValue($cat, $k, $config['v']); + $this->configCache->set($cat, $k, $config['v']); if ($cat !== 'config') { $this->cache[$cat][$k] = $config['v']; @@ -38,10 +53,11 @@ class JITConfigAdapter extends BaseObject implements IConfigAdapter DBA::close($configs); } + /** + * {@inheritdoc} + */ public function get($cat, $k, $default_value = null, $refresh = false) { - $a = self::getApp(); - if (!$refresh) { // Do we have the cached value? Then return it if (isset($this->cache[$cat][$k])) { @@ -62,18 +78,18 @@ class JITConfigAdapter extends BaseObject implements IConfigAdapter $this->cache[$cat][$k] = $value; $this->in_db[$cat][$k] = true; return $value; - } elseif (isset($a->config[$cat][$k])) { + } elseif ($this->configCache->get($cat, $k) !== null) { // Assign the value (mostly) from config/local.config.php file to the cache - $this->cache[$cat][$k] = $a->config[$cat][$k]; + $this->cache[$cat][$k] = $this->configCache->get($cat, $k); $this->in_db[$cat][$k] = false; - return $a->config[$cat][$k]; - } elseif (isset($a->config[$k])) { + return $this->configCache->get($cat, $k); + } elseif ($this->configCache->get('config', $k) !== null) { // Assign the value (mostly) from config/local.config.php file to the cache - $this->cache[$k] = $a->config[$k]; + $this->cache[$k] = $this->configCache->get('config', $k); $this->in_db[$k] = false; - return $a->config[$k]; + return $this->configCache->get('config', $k); } $this->cache[$cat][$k] = '!!'; @@ -82,6 +98,9 @@ class JITConfigAdapter extends BaseObject implements IConfigAdapter return $default_value; } + /** + * {@inheritdoc} + */ public function set($cat, $k, $value) { // We store our setting values in a string variable. @@ -102,7 +121,7 @@ class JITConfigAdapter extends BaseObject implements IConfigAdapter return true; } - self::getApp()->setConfigValue($cat, $k, $value); + $this->configCache->set($cat, $k, $value); // Assign the just added value to the cache $this->cache[$cat][$k] = $dbvalue; @@ -119,6 +138,9 @@ class JITConfigAdapter extends BaseObject implements IConfigAdapter return $result; } + /** + * {@inheritdoc} + */ public function delete($cat, $k) { if (isset($this->cache[$cat][$k])) { diff --git a/src/Core/Config/JITPConfigAdapter.php b/src/Core/Config/JITPConfigAdapter.php index bdaca407ff..b1a15601cc 100644 --- a/src/Core/Config/JITPConfigAdapter.php +++ b/src/Core/Config/JITPConfigAdapter.php @@ -1,7 +1,6 @@ */ -class JITPConfigAdapter extends BaseObject implements IPConfigAdapter +class JITPConfigAdapter implements IPConfigAdapter { private $in_db; + /** + * The config cache of this adapter + * @var IPConfigCache + */ + private $configCache; + + /** + * @param IPConfigCache $configCache The config cache of this adapter + */ + public function __construct(IPConfigCache $configCache) + { + $this->configCache = $configCache; + } + + /** + * {@inheritdoc} + */ public function load($uid, $cat) { - $a = self::getApp(); - $pconfigs = DBA::select('pconfig', ['v', 'k'], ['cat' => $cat, 'uid' => $uid]); if (DBA::isResult($pconfigs)) { while ($pconfig = DBA::fetch($pconfigs)) { $k = $pconfig['k']; - self::getApp()->setPConfigValue($uid, $cat, $k, $pconfig['v']); + $this->configCache->setP($uid, $cat, $k, $pconfig['v']); $this->in_db[$uid][$cat][$k] = true; } } else if ($cat != 'config') { // Negative caching - $a->config[$uid][$cat] = "!!"; + $this->configCache->setP($uid, $cat, null, "!!"); } DBA::close($pconfigs); } + /** + * {@inheritdoc} + */ public function get($uid, $cat, $k, $default_value = null, $refresh = false) { - $a = self::getApp(); - if (!$refresh) { // Looking if the whole family isn't set - if (isset($a->config[$uid][$cat])) { - if ($a->config[$uid][$cat] === '!!') { + if ($this->configCache->getP($uid, $cat) !== null) { + if ($this->configCache->getP($uid, $cat) === '!!') { return $default_value; } } - if (isset($a->config[$uid][$cat][$k])) { - if ($a->config[$uid][$cat][$k] === '!!') { + if ($this->configCache->getP($uid, $cat, $k) !== null) { + if ($this->configCache->getP($uid, $cat, $k) === '!!') { return $default_value; } - return $a->config[$uid][$cat][$k]; + return $this->configCache->getP($uid, $cat, $k); } } @@ -59,13 +74,13 @@ class JITPConfigAdapter extends BaseObject implements IPConfigAdapter if (DBA::isResult($pconfig)) { $val = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']); - self::getApp()->setPConfigValue($uid, $cat, $k, $val); + $this->configCache->setP($uid, $cat, $k, $val); $this->in_db[$uid][$cat][$k] = true; return $val; } else { - self::getApp()->setPConfigValue($uid, $cat, $k, '!!'); + $this->configCache->setP($uid, $cat, $k, '!!'); $this->in_db[$uid][$cat][$k] = false; @@ -73,6 +88,9 @@ class JITPConfigAdapter extends BaseObject implements IPConfigAdapter } } + /** + * {@inheritdoc} + */ public function set($uid, $cat, $k, $value) { // We store our setting values in a string variable. @@ -86,7 +104,7 @@ class JITPConfigAdapter extends BaseObject implements IPConfigAdapter return true; } - self::getApp()->setPConfigValue($uid, $cat, $k, $value); + $this->configCache->setP($uid, $cat, $k, $value); // manage array value $dbvalue = (is_array($value) ? serialize($value) : $dbvalue); @@ -100,9 +118,12 @@ class JITPConfigAdapter extends BaseObject implements IPConfigAdapter return $result; } + /** + * {@inheritdoc} + */ public function delete($uid, $cat, $k) { - self::getApp()->deletePConfigValue($uid, $cat, $k); + $this->configCache->deleteP($uid, $cat, $k); if (!empty($this->in_db[$uid][$cat][$k])) { unset($this->in_db[$uid][$cat][$k]); diff --git a/src/Core/Config/PreloadConfigAdapter.php b/src/Core/Config/PreloadConfigAdapter.php index ac59d94558..d5fbd982bf 100644 --- a/src/Core/Config/PreloadConfigAdapter.php +++ b/src/Core/Config/PreloadConfigAdapter.php @@ -3,7 +3,6 @@ namespace Friendica\Core\Config; use Exception; -use Friendica\BaseObject; use Friendica\Database\DBA; /** @@ -13,15 +12,27 @@ use Friendica\Database\DBA; * * @author Hypolite Petovan */ -class PreloadConfigAdapter extends BaseObject implements IConfigAdapter +class PreloadConfigAdapter implements IConfigAdapter { private $config_loaded = false; - public function __construct() + /** + * @var IConfigCache The config cache of this driver + */ + private $configCache; + + /** + * @param IConfigCache $configCache The config cache of this driver + */ + public function __construct(IConfigCache $configCache) { + $this->configCache = $configCache; $this->load(); } + /** + * {@inheritdoc} + */ public function load($family = 'config') { if ($this->config_loaded) { @@ -30,27 +41,33 @@ class PreloadConfigAdapter extends BaseObject implements IConfigAdapter $configs = DBA::select('config', ['cat', 'v', 'k']); while ($config = DBA::fetch($configs)) { - self::getApp()->setConfigValue($config['cat'], $config['k'], $config['v']); + $this->configCache->set($config['cat'], $config['k'], $config['v']); } DBA::close($configs); $this->config_loaded = true; } + /** + * {@inheritdoc} + */ public function get($cat, $k, $default_value = null, $refresh = false) { if ($refresh) { $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $k]); if (DBA::isResult($config)) { - self::getApp()->setConfigValue($cat, $k, $config['v']); + $this->configCache->set($cat, $k, $config['v']); } } - $return = self::getApp()->getConfigValue($cat, $k, $default_value); + $return = $this->configCache->get($cat, $k, $default_value); return $return; } + /** + * {@inheritdoc} + */ public function set($cat, $k, $value) { // We store our setting values as strings. @@ -58,11 +75,11 @@ class PreloadConfigAdapter extends BaseObject implements IConfigAdapter // The exception are array values. $compare_value = !is_array($value) ? (string)$value : $value; - if (self::getApp()->getConfigValue($cat, $k) === $compare_value) { + if ($this->configCache->get($cat, $k) === $compare_value) { return true; } - self::getApp()->setConfigValue($cat, $k, $value); + $this->configCache->set($cat, $k, $value); // manage array value $dbvalue = is_array($value) ? serialize($value) : $value; @@ -75,9 +92,12 @@ class PreloadConfigAdapter extends BaseObject implements IConfigAdapter return true; } + /** + * {@inheritdoc} + */ public function delete($cat, $k) { - self::getApp()->deleteConfigValue($cat, $k); + $this->configCache->delete($cat, $k); $result = DBA::delete('config', ['cat' => $cat, 'k' => $k]); diff --git a/src/Core/Config/PreloadPConfigAdapter.php b/src/Core/Config/PreloadPConfigAdapter.php index 6658efa3f6..af97815ade 100644 --- a/src/Core/Config/PreloadPConfigAdapter.php +++ b/src/Core/Config/PreloadPConfigAdapter.php @@ -3,7 +3,6 @@ namespace Friendica\Core\Config; use Exception; -use Friendica\BaseObject; use Friendica\Database\DBA; /** @@ -13,15 +12,31 @@ use Friendica\Database\DBA; * * @author Hypolite Petovan */ -class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter +class PreloadPConfigAdapter implements IPConfigAdapter { private $config_loaded = false; - public function __construct($uid) + /** + * The config cache of this adapter + * @var IPConfigCache + */ + private $configCache; + + /** + * @param IPConfigCache $configCache The config cache of this adapter + * @param int $uid The UID of the current user + */ + public function __construct(IPConfigCache $configCache, $uid = null) { - $this->load($uid, 'config'); + $this->configCache = $configCache; + if (isset($uid)) { + $this->load($uid, 'config'); + } } + /** + * {@inheritdoc} + */ public function load($uid, $family) { if ($this->config_loaded) { @@ -34,13 +49,16 @@ class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter $pconfigs = DBA::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]); while ($pconfig = DBA::fetch($pconfigs)) { - self::getApp()->setPConfigValue($uid, $pconfig['cat'], $pconfig['k'], $pconfig['v']); + $this->configCache->setP($uid, $pconfig['cat'], $pconfig['k'], $pconfig['v']); } DBA::close($pconfigs); $this->config_loaded = true; } + /** + * {@inheritdoc} + */ public function get($uid, $cat, $k, $default_value = null, $refresh = false) { if (!$this->config_loaded) { @@ -50,17 +68,18 @@ class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter if ($refresh) { $config = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]); if (DBA::isResult($config)) { - self::getApp()->setPConfigValue($uid, $cat, $k, $config['v']); + $this->configCache->setP($uid, $cat, $k, $config['v']); } else { - self::getApp()->deletePConfigValue($uid, $cat, $k); + $this->configCache->deleteP($uid, $cat, $k); } } - $return = self::getApp()->getPConfigValue($uid, $cat, $k, $default_value); - - return $return; + return $this->configCache->getP($uid, $cat, $k, $default_value);; } + /** + * {@inheritdoc} + */ public function set($uid, $cat, $k, $value) { if (!$this->config_loaded) { @@ -71,11 +90,11 @@ class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter // The exception are array values. $compare_value = !is_array($value) ? (string)$value : $value; - if (self::getApp()->getPConfigValue($uid, $cat, $k) === $compare_value) { + if ($this->configCache->getP($uid, $cat, $k) === $compare_value) { return true; } - self::getApp()->setPConfigValue($uid, $cat, $k, $value); + $this->configCache->setP($uid, $cat, $k, $value); // manage array value $dbvalue = is_array($value) ? serialize($value) : $value; @@ -88,13 +107,16 @@ class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter return true; } + /** + * {@inheritdoc} + */ public function delete($uid, $cat, $k) { if (!$this->config_loaded) { $this->load($uid, $cat); } - self::getApp()->deletePConfigValue($uid, $cat, $k); + $this->configCache->deleteP($uid, $cat, $k); $result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]); diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index c38dab9806..da078545e3 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -100,10 +100,10 @@ HELP; } } - $db_host = $a->getConfigValue('database', 'hostname'); - $db_user = $a->getConfigValue('database', 'username'); - $db_pass = $a->getConfigValue('database', 'password'); - $db_data = $a->getConfigValue('database', 'database'); + $db_host = $a->getConfig()->get('database', 'hostname'); + $db_user = $a->getConfig()->get('database', 'username'); + $db_pass = $a->getConfig()->get('database', 'password'); + $db_data = $a->getConfig()->get('database', 'database'); } else { // Creating config file $this->out("Creating config file...\n"); @@ -158,7 +158,7 @@ HELP; $installer->resetChecks(); - if (!$installer->installDatabase()) { + if (!$installer->installDatabase($a->getBasePath())) { $errorMessage = $this->extractErrors($installer->getChecks()); throw new RuntimeException($errorMessage); } diff --git a/src/Core/Console/Config.php b/src/Core/Console/Config.php index ce367fffbf..b1c3df54e0 100644 --- a/src/Core/Console/Config.php +++ b/src/Core/Console/Config.php @@ -113,7 +113,7 @@ HELP; if (is_array($value)) { foreach ($value as $k => $v) { - $this->out("{$cat}.{$key}[{$k}] => " . $v); + $this->out("{$cat}.{$key}[{$k}] => " . (is_array($v) ? implode(', ', $v) : $v)); } } else { $this->out("{$cat}.{$key} => " . $value); @@ -124,12 +124,13 @@ HELP; $cat = $this->getArgument(0); Core\Config::load($cat); - if (!is_null($a->config[$cat])) { + if ($a->getConfig()->get($cat) !== null) { $this->out("[{$cat}]"); - foreach ($a->config[$cat] as $key => $value) { + $catVal = $a->getConfig()->get($cat); + foreach ($catVal as $key => $value) { if (is_array($value)) { foreach ($value as $k => $v) { - $this->out("{$key}[{$k}] => " . $v); + $this->out("{$key}[{$k}] => " . (is_array($v) ? implode(', ', $v) : $v)); } } else { $this->out("{$key} => " . $value); @@ -147,12 +148,13 @@ HELP; $this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only'); } - foreach ($a->config as $cat => $section) { + $config = $a->getConfig()->getAll(); + foreach ($config as $cat => $section) { if (is_array($section)) { foreach ($section as $key => $value) { if (is_array($value)) { foreach ($value as $k => $v) { - $this->out("{$cat}.{$key}[{$k}] => " . $v); + $this->out("{$cat}.{$key}[{$k}] => " . (is_array($v) ? implode(', ', $v) : $v)); } } else { $this->out("{$cat}.{$key} => " . $value); diff --git a/src/Core/Console/DatabaseStructure.php b/src/Core/Console/DatabaseStructure.php index 724feea5e4..1ec108d2e6 100644 --- a/src/Core/Console/DatabaseStructure.php +++ b/src/Core/Console/DatabaseStructure.php @@ -61,17 +61,19 @@ HELP; Core\Config::load(); + $a = get_app(); + switch ($this->getArgument(0)) { case "dryrun": - $output = DBStructure::update(true, false); + $output = DBStructure::update($a->getBasePath(), true, false); break; case "update": $force = $this->getOption(['f', 'force'], false); - $output = Update::run($force, true, false); + $output = Update::run($a->getBasePath(), $force, true, false); break; case "dumpsql": ob_start(); - DBStructure::printStructure(); + DBStructure::printStructure($a->getBasePath()); $output = ob_get_clean(); break; case "toinnodb": diff --git a/src/Core/Console/PostUpdate.php b/src/Core/Console/PostUpdate.php index 17ed231f97..103d0fef7e 100644 --- a/src/Core/Console/PostUpdate.php +++ b/src/Core/Console/PostUpdate.php @@ -2,8 +2,8 @@ namespace Friendica\Core\Console; -use Friendica\Core\L10n; use Friendica\Core\Config; +use Friendica\Core\L10n; use Friendica\Core\Update; /** @@ -56,7 +56,7 @@ HELP; } echo L10n::t('Check for pending update actions.') . "\n"; - Update::run(true, true, false); + Update::run($a->getBasePath(), true, true, false); echo L10n::t('Done.') . "\n"; echo L10n::t('Execute pending post updates.') . "\n"; diff --git a/src/Core/Console/Typo.php b/src/Core/Console/Typo.php index 82357b4753..32ba6ded35 100644 --- a/src/Core/Console/Typo.php +++ b/src/Core/Console/Typo.php @@ -2,6 +2,8 @@ namespace Friendica\Core\Console; +use Friendica\BaseObject; + /** * Tired of chasing typos and finding them after a commit. * Run this and quickly see if we've got any parse errors in our application files. @@ -41,9 +43,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - $a = \get_app(); - - $php_path = $a->getConfigValue('config', 'php_path', 'php'); + $php_path = BaseObject::getApp()->getConfig()->get('config', 'php_path', 'php'); if ($this->getOption('v')) { $this->out('Directory: src'); diff --git a/src/Core/Installer.php b/src/Core/Installer.php index a487aec78b..7e79f29f15 100644 --- a/src/Core/Installer.php +++ b/src/Core/Installer.php @@ -168,12 +168,14 @@ class Installer /*** * Installs the DB-Scheme for Friendica * + * @param string $basePath The base path of this application + * * @return bool true if the installation was successful, otherwise false * @throws Exception */ - public function installDatabase() + public function installDatabase($basePath) { - $result = DBStructure::update(false, true, true); + $result = DBStructure::update($basePath, false, true, true); if ($result) { $txt = L10n::t('You may need to import the file "database.sql" manually using phpmyadmin or mysql.') . EOL; diff --git a/src/Core/Logger.php b/src/Core/Logger.php index 277a091641..6b8112796f 100644 --- a/src/Core/Logger.php +++ b/src/Core/Logger.php @@ -5,8 +5,8 @@ namespace Friendica\Core; use Friendica\BaseObject; +use Friendica\Factory\LoggerFactory; use Friendica\Network\HTTPException\InternalServerErrorException; -use Friendica\Util\LoggerFactory; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; diff --git a/src/Core/PConfig.php b/src/Core/PConfig.php index 584318adbc..df024f0f34 100644 --- a/src/Core/PConfig.php +++ b/src/Core/PConfig.php @@ -8,9 +8,6 @@ */ namespace Friendica\Core; -use Friendica\App; -use Friendica\BaseObject; - /** * @brief Management of user configuration storage * Note: @@ -18,52 +15,55 @@ use Friendica\BaseObject; * The PConfig::get() functions return boolean false for keys that are unset, * and this could lead to subtle bugs. */ -class PConfig extends BaseObject +class PConfig { /** - * @var \Friendica\Core\Config\IPConfigAdapter + * @var Config\IPConfigAdapter */ - private static $adapter = null; + private static $adapter; - public static function init($uid) + /** + * @var Config\IPConfigCache + */ + private static $cache; + + /** + * Initialize the config with only the cache + * + * @param Config\IPConfigCache $cache The configuration cache + */ + public static function init(Config\IPConfigCache $cache) { - $a = self::getApp(); + self::$cache = $cache; + } - // Database isn't ready or populated yet - if (!$a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - return; - } - - if ($a->getConfigValue('system', 'config_adapter') == 'preload') { - self::$adapter = new Config\PreloadPConfigAdapter($uid); - } else { - self::$adapter = new Config\JITPConfigAdapter(); - } + /** + * Add the adapter for DB-backend + * + * @param Config\IPConfigAdapter $adapter + */ + public static function setAdapter(Config\IPConfigAdapter $adapter) + { + self::$adapter = $adapter; } /** * @brief Loads all configuration values of a user's config family into a cached storage. * - * All configuration values of the given user are stored in global cache - * which is available under the global variable $a->config[$uid]. + * All configuration values of the given user are stored with the $uid in + * the cache ( @see IPConfigCache ) * * @param string $uid The user_id * @param string $family The category of the configuration value * * @return void - * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ public static function load($uid, $family) { - // Database isn't ready or populated yet - if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { + if (!isset(self::$adapter)) { return; } - if (empty(self::$adapter)) { - self::init($uid); - } - self::$adapter->load($uid, $family); } @@ -72,7 +72,8 @@ class PConfig extends BaseObject * ($family) and a key. * * Get a particular user's config value from the given category ($family) - * and the $key from a cached storage in $a->config[$uid]. + * and the $key with the $uid from a cached storage either from the self::$adapter + * (@see IConfigAdapter ) or from the static::$cache (@see IConfigCache ). * * @param string $uid The user_id * @param string $family The category of the configuration value @@ -81,17 +82,11 @@ class PConfig extends BaseObject * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) * * @return mixed Stored value or null if it does not exist - * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ public static function get($uid, $family, $key, $default_value = null, $refresh = false) { - // Database isn't ready or populated yet - if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - return; - } - - if (empty(self::$adapter)) { - self::init($uid); + if (!isset(self::$adapter)) { + return self::$cache->getP($uid, $family, $key, $default_value); } return self::$adapter->get($uid, $family, $key, $default_value, $refresh); @@ -111,17 +106,11 @@ class PConfig extends BaseObject * @param mixed $value The value to store * * @return bool Operation success - * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ public static function set($uid, $family, $key, $value) { - // Database isn't ready or populated yet - if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - return false; - } - - if (empty(self::$adapter)) { - self::init($uid); + if (!isset(self::$adapter)) { + return self::$cache->setP($uid, $family, $key, $value); } return self::$adapter->set($uid, $family, $key, $value); @@ -130,25 +119,20 @@ class PConfig extends BaseObject /** * @brief Deletes the given key from the users's configuration. * - * Removes the configured value from the stored cache in $a->config[$uid] - * and removes it from the database. + * Removes the configured value from the stored cache in self::$config + * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ) + * with the given $uid. * * @param string $uid The user_id * @param string $family The category of the configuration value * @param string $key The configuration key to delete * * @return mixed - * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ public static function delete($uid, $family, $key) { - // Database isn't ready or populated yet - if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - return false; - } - - if (empty(self::$adapter)) { - self::init($uid); + if (!isset(self::$adapter)) { + return self::$cache->deleteP($uid, $family, $key); } return self::$adapter->delete($uid, $family, $key); diff --git a/src/Core/System.php b/src/Core/System.php index ba3d03e622..f0ed083573 100644 --- a/src/Core/System.php +++ b/src/Core/System.php @@ -286,6 +286,61 @@ class System extends BaseObject exit(); } + /** + * @brief Returns the system user that is executing the script + * + * This mostly returns something like "www-data". + * + * @return string system username + */ + public static function getUser() + { + if (!function_exists('posix_getpwuid') || !function_exists('posix_geteuid')) { + return ''; + } + + $processUser = posix_getpwuid(posix_geteuid()); + return $processUser['name']; + } + + /** + * @brief Checks if a given directory is usable for the system + * + * @param $directory + * @param bool $check_writable + * + * @return boolean the directory is usable + */ + public static function isDirectoryUsable($directory, $check_writable = true) + { + if ($directory == '') { + Logger::log('Directory is empty. This shouldn\'t happen.', Logger::DEBUG); + return false; + } + + if (!file_exists($directory)) { + Logger::log('Path "' . $directory . '" does not exist for user ' . static::getUser(), Logger::DEBUG); + return false; + } + + if (is_file($directory)) { + Logger::log('Path "' . $directory . '" is a file for user ' . static::getUser(), Logger::DEBUG); + return false; + } + + if (!is_dir($directory)) { + Logger::log('Path "' . $directory . '" is not a directory for user ' . static::getUser(), Logger::DEBUG); + return false; + } + + if ($check_writable && !is_writable($directory)) { + Logger::log('Path "' . $directory . '" is not writable for user ' . static::getUser(), Logger::DEBUG); + return false; + } + + return true; + } + /// @todo Move the following functions from boot.php /* function killme() diff --git a/src/Core/Update.php b/src/Core/Update.php index 368f5f55cc..5df0675cda 100644 --- a/src/Core/Update.php +++ b/src/Core/Update.php @@ -14,10 +14,11 @@ class Update /** * @brief Function to check if the Database structure needs an update. * + * @param string $basePath The base path of this application * @param boolean $via_worker boolean Is the check run via the worker? * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function check($via_worker) + public static function check($basePath, $via_worker) { if (!DBA::connected()) { return; @@ -38,7 +39,7 @@ class Update if ($build < DB_UPDATE_VERSION) { // When we cannot execute the database update via the worker, we will do it directly if (!Worker::add(PRIORITY_CRITICAL, 'DBUpdate') && $via_worker) { - self::run(); + self::run($basePath); } } } @@ -46,14 +47,15 @@ class Update /** * Automatic database updates * - * @param bool $force Force the Update-Check even if the lock is set - * @param bool $verbose Run the Update-Check verbose - * @param bool $sendMail Sends a Mail to the administrator in case of success/failure + * @param string $basePath The base path of this application + * @param bool $force Force the Update-Check even if the lock is set + * @param bool $verbose Run the Update-Check verbose + * @param bool $sendMail Sends a Mail to the administrator in case of success/failure * * @return string Empty string if the update is successful, error messages otherwise * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function run($force = false, $verbose = false, $sendMail = true) + public static function run($basePath, $force = false, $verbose = false, $sendMail = true) { // In force mode, we release the dbupdate lock first // Necessary in case of an stuck update @@ -91,7 +93,7 @@ class Update } // update the structure in one call - $retval = DBStructure::update($verbose, true); + $retval = DBStructure::update($basePath, $verbose, true); if ($retval) { if ($sendMail) { self::updateFailed( @@ -125,7 +127,7 @@ class Update } } } elseif ($force) { - DBStructure::update($verbose, true); + DBStructure::update($basePath, $verbose, true); } return ''; diff --git a/src/Database/DBA.php b/src/Database/DBA.php index e14d94ce04..d2a739e931 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -2,10 +2,7 @@ namespace Friendica\Database; -// Do not use Core\Config in this class at risk of infinite loop. -// Please use App->getConfigVariable() instead. -//use Friendica\Core\Config; - +use Friendica\Core\Config\IConfigCache; use Friendica\Core\Logger; use Friendica\Core\System; use Friendica\Util\DateTimeFormat; @@ -34,6 +31,10 @@ class DBA public static $connected = false; + /** + * @var IConfigCache + */ + private static $configCache; private static $server_info = ''; private static $connection; private static $driver; @@ -49,13 +50,14 @@ class DBA private static $db_name = ''; private static $db_charset = ''; - public static function connect($serveraddr, $user, $pass, $db, $charset = null) + public static function connect($configCache, $serveraddr, $user, $pass, $db, $charset = null) { if (!is_null(self::$connection) && self::connected()) { return true; } // We are storing these values for being able to perform a reconnect + self::$configCache = $configCache; self::$db_serveraddr = $serveraddr; self::$db_user = $user; self::$db_pass = $pass; @@ -156,7 +158,7 @@ class DBA public static function reconnect() { self::disconnect(); - $ret = self::connect(self::$db_serveraddr, self::$db_user, self::$db_pass, self::$db_name, self::$db_charset); + $ret = self::connect(self::$configCache, self::$db_serveraddr, self::$db_user, self::$db_pass, self::$db_name, self::$db_charset); return $ret; } @@ -210,9 +212,8 @@ class DBA * @throws \Exception */ private static function logIndex($query) { - $a = \get_app(); - if (!$a->getConfigVariable('system', 'db_log_index')) { + if (!self::$configCache->get('system', 'db_log_index')) { return; } @@ -231,18 +232,18 @@ class DBA return; } - $watchlist = explode(',', $a->getConfigVariable('system', 'db_log_index_watch')); - $blacklist = explode(',', $a->getConfigVariable('system', 'db_log_index_blacklist')); + $watchlist = explode(',', self::$configCache->get('system', 'db_log_index_watch')); + $blacklist = explode(',', self::$configCache->get('system', 'db_log_index_blacklist')); while ($row = self::fetch($r)) { - if ((intval($a->getConfigVariable('system', 'db_loglimit_index')) > 0)) { + if ((intval(self::$configCache->get('system', 'db_loglimit_index')) > 0)) { $log = (in_array($row['key'], $watchlist) && - ($row['rows'] >= intval($a->getConfigVariable('system', 'db_loglimit_index')))); + ($row['rows'] >= intval(self::$configCache->get('system', 'db_loglimit_index')))); } else { $log = false; } - if ((intval($a->getConfigVariable('system', 'db_loglimit_index_high')) > 0) && ($row['rows'] >= intval($a->getConfigVariable('system', 'db_loglimit_index_high')))) { + if ((intval(self::$configCache->get('system', 'db_loglimit_index_high')) > 0) && ($row['rows'] >= intval(self::$configCache->get('system', 'db_loglimit_index_high')))) { $log = true; } @@ -252,7 +253,7 @@ class DBA if ($log) { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); - @file_put_contents($a->getConfigVariable('system', 'db_log_index'), DateTimeFormat::utcNow()."\t". + @file_put_contents(self::$configCache->get('system', 'db_log_index'), DateTimeFormat::utcNow()."\t". $row['key']."\t".$row['rows']."\t".$row['Extra']."\t". basename($backtrace[1]["file"])."\t". $backtrace[1]["line"]."\t".$backtrace[2]["function"]."\t". @@ -422,7 +423,7 @@ class DBA $orig_sql = $sql; - if ($a->getConfigValue('system', 'db_callstack')) { + if (self::$configCache->get('system', 'db_callstack') !== null) { $sql = "/*".System::callstack()." */ ".$sql; } @@ -583,15 +584,15 @@ class DBA $a->saveTimestamp($stamp1, 'database'); - if ($a->getConfigValue('system', 'db_log')) { + if (self::$configCache->get('system', 'db_log')) { $stamp2 = microtime(true); $duration = (float)($stamp2 - $stamp1); - if (($duration > $a->getConfigValue('system', 'db_loglimit'))) { + if (($duration > self::$configCache->get('system', 'db_loglimit'))) { $duration = round($duration, 3); $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); - @file_put_contents($a->getConfigValue('system', 'db_log'), DateTimeFormat::utcNow()."\t".$duration."\t". + @file_put_contents(self::$configCache->get('system', 'db_log'), DateTimeFormat::utcNow()."\t".$duration."\t". basename($backtrace[1]["file"])."\t". $backtrace[1]["line"]."\t".$backtrace[2]["function"]."\t". substr(self::replaceParameters($sql, $args), 0, 2000)."\n", FILE_APPEND); @@ -1030,7 +1031,7 @@ class DBA * This process must only be started once, since the value is cached. */ private static function buildRelationData() { - $definition = DBStructure::definition(); + $definition = DBStructure::definition(self::$configCache->get('system', 'basepath')); foreach ($definition AS $table => $structure) { foreach ($structure['fields'] AS $field => $field_struct) { diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php index 7d52e60cae..75a5c86241 100644 --- a/src/Database/DBStructure.php +++ b/src/Database/DBStructure.php @@ -74,9 +74,9 @@ class DBStructure return L10n::t('Errors encountered performing database changes: ') . $message . EOL; } - public static function printStructure() + public static function printStructure($basePath) { - $database = self::definition(false); + $database = self::definition($basePath, false); echo "-- ------------------------------------------\n"; echo "-- " . FRIENDICA_PLATFORM . " " . FRIENDICA_VERSION . " (" . FRIENDICA_CODENAME, ")\n"; @@ -98,15 +98,15 @@ class DBStructure * * @see config/dbstructure.config.php * @param boolean $with_addons_structure Whether to tack on addons additional tables + * @param string $basePath The base path of this application * @return array * @throws Exception */ - public static function definition($with_addons_structure = true) + public static function definition($basePath, $with_addons_structure = true) { if (!self::$definition) { - $a = \Friendica\BaseObject::getApp(); - $filename = $a->getBasePath() . '/config/dbstructure.config.php'; + $filename = $basePath . '/config/dbstructure.config.php'; if (!is_readable($filename)) { throw new Exception('Missing database structure config file config/dbstructure.config.php'); @@ -247,15 +247,16 @@ class DBStructure /** * Updates DB structure and returns eventual errors messages * - * @param bool $verbose - * @param bool $action Whether to actually apply the update - * @param bool $install Is this the initial update during the installation? - * @param array $tables An array of the database tables - * @param array $definition An array of the definition tables + * @param string $basePath The base path of this application + * @param bool $verbose + * @param bool $action Whether to actually apply the update + * @param bool $install Is this the initial update during the installation? + * @param array $tables An array of the database tables + * @param array $definition An array of the definition tables * @return string Empty string if the update is successful, error messages otherwise * @throws Exception */ - public static function update($verbose, $action, $install = false, array $tables = null, array $definition = null) + public static function update($basePath, $verbose, $action, $install = false, array $tables = null, array $definition = null) { if ($action && !$install) { Config::set('system', 'maintenance', 1); @@ -284,7 +285,7 @@ class DBStructure // Get the definition if (is_null($definition)) { - $definition = self::definition(); + $definition = self::definition($basePath); } // MySQL >= 5.7.4 doesn't support the IGNORE keyword in ALTER TABLE statements diff --git a/src/Factory/ConfigFactory.php b/src/Factory/ConfigFactory.php new file mode 100644 index 0000000000..269daea8b8 --- /dev/null +++ b/src/Factory/ConfigFactory.php @@ -0,0 +1,52 @@ +loadConfigFiles($configCache); + + return $configCache; + } + + /** + * @param string $type The adapter type + * @param Config\IConfigCache $config The config cache of this adapter + * + * @return Config\IConfigAdapter + */ + public static function createConfig($type, Config\IConfigCache $config) + { + if ($type == 'preload') { + return new Config\PreloadConfigAdapter($config); + } else { + return new Config\JITConfigAdapter($config); + } + } + + /** + * @param string $type The adapter type + * @param Config\IPConfigCache $config The config cache of this adapter + * @param int $uid The UID of the current user + * + * @return Config\IPConfigAdapter + */ + public static function createPConfig($type, Config\IPConfigCache $config, $uid = null) + { + if ($type == 'preload') { + return new Config\PreloadPConfigAdapter($config, $uid); + } else { + return new Config\JITPConfigAdapter($config); + } + } +} diff --git a/src/Util/LoggerFactory.php b/src/Factory/LoggerFactory.php similarity index 88% rename from src/Util/LoggerFactory.php rename to src/Factory/LoggerFactory.php index 4d3a287165..751a6357da 100644 --- a/src/Util/LoggerFactory.php +++ b/src/Factory/LoggerFactory.php @@ -1,7 +1,8 @@ pushProcessor(new Monolog\Processor\PsrLogMessageProcessor()); @@ -31,6 +33,16 @@ class LoggerFactory $logger->pushProcessor(new Monolog\Processor\UidProcessor()); $logger->pushProcessor(new FriendicaIntrospectionProcessor(LogLevel::DEBUG, ['Friendica\\Core\\Logger'])); + if (isset($config)) { + $debugging = $config->get('system', 'debugging'); + $stream = $config->get('system', 'logfile'); + $level = $config->get('system', 'loglevel'); + + if ($debugging) { + static::addStreamHandler($logger, $stream, $level); + } + } + return $logger; } diff --git a/src/Model/Attach.php b/src/Model/Attach.php index 7efb56f95a..d65e67fe3e 100644 --- a/src/Model/Attach.php +++ b/src/Model/Attach.php @@ -7,15 +7,15 @@ namespace Friendica\Model; use Friendica\BaseObject; -use Friendica\Core\System; use Friendica\Core\StorageManager; +use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\Model\Storage\IStorage; use Friendica\Object\Image; -use Friendica\Util\Security; use Friendica\Util\DateTimeFormat; use Friendica\Util\Mimetype; +use Friendica\Util\Security; /** * Class to handle attach dabatase table @@ -31,7 +31,7 @@ class Attach extends BaseObject */ private static function getFields() { - $allfields = DBStructure::definition(false); + $allfields = DBStructure::definition(self::getApp()->getBasePath(), false); $fields = array_keys($allfields['attach']['fields']); array_splice($fields, array_search('data', $fields), 1); return $fields; diff --git a/src/Module/Install.php b/src/Module/Install.php index d1a35c1518..327e59422c 100644 --- a/src/Module/Install.php +++ b/src/Module/Install.php @@ -103,7 +103,7 @@ class Install extends BaseModule return; } - self::$installer->installDatabase(); + self::$installer->installDatabase($a->getBasePath()); break; } diff --git a/src/Util/BasePath.php b/src/Util/BasePath.php new file mode 100644 index 0000000000..a2849831eb --- /dev/null +++ b/src/Util/BasePath.php @@ -0,0 +1,53 @@ +getBasePath()); } } diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php index 2cb76dcad9..79af5b5468 100644 --- a/tests/DatabaseTest.php +++ b/tests/DatabaseTest.php @@ -5,7 +5,10 @@ namespace Friendica\Test; +use Friendica\Core\Config; use Friendica\Database\DBA; +use Friendica\Factory; +use Friendica\Util\BasePath; use PHPUnit\DbUnit\DataSet\YamlDataSet; use PHPUnit\DbUnit\TestCaseTrait; use PHPUnit_Extensions_Database_DB_IDatabaseConnection; @@ -36,7 +39,13 @@ abstract class DatabaseTest extends MockedTest $this->markTestSkipped('Please set the MYSQL_* environment variables to your test database credentials.'); } - DBA::connect(getenv('MYSQL_HOST'), + $basedir = BasePath::create(dirname(__DIR__)); + $configLoader = new Config\ConfigCacheLoader($basedir); + $config = Factory\ConfigFactory::createCache($configLoader); + + DBA::connect( + $config, + getenv('MYSQL_HOST'), getenv('MYSQL_USERNAME'), getenv('MYSQL_PASSWORD'), getenv('MYSQL_DATABASE')); diff --git a/tests/Util/AppMockTrait.php b/tests/Util/AppMockTrait.php index c679321844..290191cba1 100644 --- a/tests/Util/AppMockTrait.php +++ b/tests/Util/AppMockTrait.php @@ -4,6 +4,7 @@ namespace Friendica\Test\Util; use Friendica\App; use Friendica\BaseObject; +use Friendica\Core\Config\ConfigCache; use Friendica\Render\FriendicaSmartyEngine; use Mockery\MockInterface; use org\bovigo\vfs\vfsStreamDirectory; @@ -24,8 +25,9 @@ trait AppMockTrait * Mock the App * * @param vfsStreamDirectory $root The root directory + * @param MockInterface|ConfigCache $config The config cache */ - public function mockApp($root) + public function mockApp($root, $config) { $this->mockConfigGet('system', 'theme', 'testtheme'); @@ -35,22 +37,26 @@ trait AppMockTrait ->shouldReceive('getBasePath') ->andReturn($root->url()); - $this->app - ->shouldReceive('getConfigValue') + $config + ->shouldReceive('get') ->with('database', 'hostname') ->andReturn(getenv('MYSQL_HOST')); - $this->app - ->shouldReceive('getConfigValue') + $config + ->shouldReceive('get') ->with('database', 'username') ->andReturn(getenv('MYSQL_USERNAME')); - $this->app - ->shouldReceive('getConfigValue') + $config + ->shouldReceive('get') ->with('database', 'password') ->andReturn(getenv('MYSQL_PASSWORD')); - $this->app - ->shouldReceive('getConfigValue') + $config + ->shouldReceive('get') ->with('database', 'database') ->andReturn(getenv('MYSQL_DATABASE')); + $this->app + ->shouldReceive('getConfig') + ->andReturn($config); + $this->app ->shouldReceive('getTemplateEngine') ->andReturn(new FriendicaSmartyEngine()); diff --git a/tests/include/ApiTest.php b/tests/include/ApiTest.php index cf7571073a..be70d923bd 100644 --- a/tests/include/ApiTest.php +++ b/tests/include/ApiTest.php @@ -5,13 +5,14 @@ namespace Friendica\Test; -use Friendica\BaseObject; +use Friendica\App; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\Protocol; use Friendica\Core\System; +use Friendica\Factory; use Friendica\Network\HTTPException; -use Friendica\Util\LoggerFactory; +use Friendica\Util\BasePath; use Monolog\Handler\TestHandler; require_once __DIR__ . '/../../include/api.php'; @@ -34,10 +35,14 @@ class ApiTest extends DatabaseTest */ public function setUp() { - parent::setUp(); + $basedir = BasePath::create(dirname(__DIR__) . '/../'); + $configLoader = new Config\ConfigCacheLoader($basedir); + $config = Factory\ConfigFactory::createCache($configLoader); + $logger = Factory\LoggerFactory::create('test', $config); + $this->app = new App($config, $logger, false); + $this->logOutput = FActory\LoggerFactory::enableTest($this->app->getLogger()); - $this->app = BaseObject::getApp(); - $this->logOutput = LoggerFactory::enableTest($this->app->getLogger()); + parent::setUp(); // User data that the test database is populated with $this->selfUser = [ diff --git a/tests/src/BaseObjectTest.php b/tests/src/BaseObjectTest.php index 2b10556af6..b2c73780a4 100644 --- a/tests/src/BaseObjectTest.php +++ b/tests/src/BaseObjectTest.php @@ -31,9 +31,6 @@ class BaseObjectTest extends TestCase */ protected function setUp() { - $this->setUpVfsDir(); - $this->mockApp($this->root); - $this->baseObject = new BaseObject(); } @@ -43,6 +40,10 @@ class BaseObjectTest extends TestCase */ public function testGetApp() { + $this->setUpVfsDir(); + $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $this->mockApp($this->root, $configMock); + $this->assertInstanceOf(App::class, $this->baseObject->getApp()); } @@ -52,7 +53,20 @@ class BaseObjectTest extends TestCase */ public function testSetApp() { + $this->setUpVfsDir(); + $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $this->mockApp($this->root, $configMock); + $this->assertNull($this->baseObject->setApp($this->app)); $this->assertEquals($this->app, $this->baseObject->getApp()); } + + /** + * Test the getApp() function without App + * @expectedException Friendica\Network\HTTPException\InternalServerErrorException + */ + public function testGetAppFailed() + { + BaseObject::getApp(); + } } diff --git a/tests/src/Core/Cache/CacheTest.php b/tests/src/Core/Cache/CacheTest.php index b9a22ee9ca..d0b357bf46 100644 --- a/tests/src/Core/Cache/CacheTest.php +++ b/tests/src/Core/Cache/CacheTest.php @@ -69,7 +69,8 @@ abstract class CacheTest extends MockedTest protected function setUp() { $this->setUpVfsDir(); - $this->mockApp($this->root); + $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $this->mockApp($this->root, $configMock); $this->app ->shouldReceive('getHostname') ->andReturn('friendica.local'); diff --git a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php index 361608d375..127a8bc3f8 100644 --- a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php +++ b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php @@ -181,7 +181,7 @@ FIN; $this->mockConnect(true, 1); $this->mockConnected(true, 1); $this->mockExistsTable('user', false, 1); - $this->mockUpdate([false, true, true], null, 1); + $this->mockUpdate([$this->root->url(), false, true, true], null, 1); $config = <<mockConnect(true, 1); $this->mockConnected(true, 1); $this->mockExistsTable('user', false, 1); - $this->mockUpdate([false, true, true], null, 1); + $this->mockUpdate([$this->root->url(), false, true, true], null, 1); $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); $this->mockReplaceMacros('testTemplate', $this->createArgumentsForMacro(true), '', 1); @@ -267,7 +267,7 @@ CONF; $this->mockConnect(true, 1); $this->mockConnected(true, 1); $this->mockExistsTable('user', false, 1); - $this->mockUpdate([false, true, true], null, 1); + $this->mockUpdate([$this->root->url(), false, true, true], null, 1); $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); $this->mockReplaceMacros('testTemplate', $this->createArgumentsForMacro(false), '', 1); @@ -292,7 +292,7 @@ CONF; $this->mockConnect(true, 1); $this->mockConnected(true, 1); $this->mockExistsTable('user', false, 1); - $this->mockUpdate([false, true, true], null, 1); + $this->mockUpdate([$this->root->url(), false, true, true], null, 1); $this->mockGetMarkupTemplate('local.config.tpl', 'testTemplate', 1); $this->mockReplaceMacros('testTemplate', $this->createArgumentsForMacro(true), '', 1); diff --git a/tests/src/Core/Console/ConsoleTest.php b/tests/src/Core/Console/ConsoleTest.php index 4f7acc9c42..905d214cac 100644 --- a/tests/src/Core/Console/ConsoleTest.php +++ b/tests/src/Core/Console/ConsoleTest.php @@ -29,7 +29,8 @@ abstract class ConsoleTest extends MockedTest Intercept::setUp(); $this->setUpVfsDir(); - $this->mockApp($this->root); + $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $this->mockApp($this->root, $configMock); } /** diff --git a/tests/src/Core/Lock/LockTest.php b/tests/src/Core/Lock/LockTest.php index 320beb3054..2d11a71ae1 100644 --- a/tests/src/Core/Lock/LockTest.php +++ b/tests/src/Core/Lock/LockTest.php @@ -31,7 +31,8 @@ abstract class LockTest extends MockedTest // Reusable App object $this->setUpVfsDir(); - $this->mockApp($this->root); + $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $this->mockApp($this->root, $configMock); $this->app ->shouldReceive('getHostname') ->andReturn('friendica.local'); diff --git a/tests/src/Database/DBATest.php b/tests/src/Database/DBATest.php index 17ac55fd7a..f2a5cc5558 100644 --- a/tests/src/Database/DBATest.php +++ b/tests/src/Database/DBATest.php @@ -1,19 +1,25 @@ app = new App($config, $logger, false); + $this->logOutput = FActory\LoggerFactory::enableTest($this->app->getLogger()); - // Reusable App object - $this->app = BaseObject::getApp(); + parent::setUp(); // Default config Config::set('config', 'hostname', 'localhost'); diff --git a/tests/src/Database/DBStructureTest.php b/tests/src/Database/DBStructureTest.php index 268bf8eedd..53c4e8895b 100644 --- a/tests/src/Database/DBStructureTest.php +++ b/tests/src/Database/DBStructureTest.php @@ -2,19 +2,25 @@ namespace Friendica\Test\Database; -use Friendica\BaseObject; +use Friendica\App; use Friendica\Core\Config; use Friendica\Database\DBStructure; +use Friendica\Factory; use Friendica\Test\DatabaseTest; +use Friendica\Util\BasePath; class DBStructureTest extends DatabaseTest { public function setUp() { - parent::setUp(); + $basedir = BasePath::create(dirname(__DIR__) . '/../../'); + $configLoader = new Config\ConfigCacheLoader($basedir); + $config = Factory\ConfigFactory::createCache($configLoader); + $logger = Factory\LoggerFactory::create('test', $config); + $this->app = new App($config, $logger, false); + $this->logOutput = FActory\LoggerFactory::enableTest($this->app->getLogger()); - // Reusable App object - $this->app = BaseObject::getApp(); + parent::setUp(); // Default config Config::set('config', 'hostname', 'localhost');