Browse Source

Merge pull request #6920 from nupplaphil/feature/basepath/hostname_config

Removing basepath/hostname from admin site settings
pull/6934/head
Hypolite Petovan 3 years ago
committed by GitHub
parent
commit
76414a5169
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .gitignore
  2. 21
      mod/admin.php
  3. 97
      src/App.php
  4. 2
      src/Core/Config/Cache/ConfigCache.php
  5. 12
      src/Core/Config/Configuration.php
  6. 5
      src/Core/Console/AutomaticInstallation.php
  7. 87
      src/Core/Update.php
  8. 7
      src/Factory/ConfigFactory.php
  9. 6
      src/Factory/DependencyFactory.php
  10. 48
      src/Util/Config/ConfigFileLoader.php
  11. 90
      src/Util/Config/ConfigFileManager.php
  12. 341
      src/Util/Config/ConfigFileSaver.php
  13. 6
      src/Worker/DBUpdate.php
  14. 4
      tests/DatabaseTest.php
  15. 4
      tests/datasets/config/.htconfig.php
  16. 1
      tests/datasets/config/local.config.php
  17. 3
      tests/datasets/config/local.ini.php
  18. 6
      tests/include/ApiTest.php
  19. 6
      tests/src/Database/DBATest.php
  20. 6
      tests/src/Database/DBStructureTest.php
  21. 38
      tests/src/Util/Config/ConfigFileLoaderTest.php
  22. 189
      tests/src/Util/Config/ConfigFileSaverTest.php
  23. 15
      update.php
  24. 2
      view/templates/admin/site.tpl
  25. 1
      view/templates/local.config.tpl

4
.gitignore

@ -1,6 +1,6 @@
favicon.*
.htconfig.php
.htpreconfig.php
/.htconfig.php
/.htpreconfig.php
\#*
*.log
*.out

21
mod/admin.php

@ -923,6 +923,10 @@ function admin_page_summary(App $a)
$showwarning = true;
$warningtext[] = L10n::t('The database update failed. Please run "php bin/console.php dbstructure update" from the command line and have a look at the errors that might appear.');
}
if (Config::get('system', 'update') == Update::FAILED) {
$showwarning = true;
$warningtext[] = L10n::t('The last update failed. Please run "php bin/console.php dbstructure update" from the command line and have a look at the errors that might appear. (Some of the errors are possibly inside the logfile.)');
}
$last_worker_call = Config::get('system', 'last_worker_execution', false);
if (!$last_worker_call) {
@ -1087,7 +1091,9 @@ function admin_page_site_post(App $a)
update_table($a, "gcontact", ['connect', 'addr'], $old_host, $new_host);
// update config
Config::set('system', 'hostname', parse_url($new_url, PHP_URL_HOST));
$configFileSaver = new \Friendica\Util\Config\ConfigFileSaver($a->getBasePath());
$configFileSaver->addConfigValue('config', 'hostname', parse_url($new_url, PHP_URL_HOST));
$configFileSaver->saveToConfigFile();
Config::set('system', 'url', $new_url);
$a->setBaseURL($new_url);
@ -1105,7 +1111,6 @@ function admin_page_site_post(App $a)
// end relocate
$sitename = (!empty($_POST['sitename']) ? Strings::escapeTags(trim($_POST['sitename'])) : '');
$hostname = (!empty($_POST['hostname']) ? Strings::escapeTags(trim($_POST['hostname'])) : '');
$sender_email = (!empty($_POST['sender_email']) ? Strings::escapeTags(trim($_POST['sender_email'])) : '');
$banner = (!empty($_POST['banner']) ? trim($_POST['banner']) : false);
$shortcut_icon = (!empty($_POST['shortcut_icon']) ? Strings::escapeTags(trim($_POST['shortcut_icon'])) : '');
@ -1176,7 +1181,6 @@ function admin_page_site_post(App $a)
$itemcache_duration = (!empty($_POST['itemcache_duration']) ? intval($_POST['itemcache_duration']) : 0);
$max_comments = (!empty($_POST['max_comments']) ? intval($_POST['max_comments']) : 0);
$temppath = (!empty($_POST['temppath']) ? Strings::escapeTags(trim($_POST['temppath'])) : '');
$basepath = (!empty($_POST['basepath']) ? Strings::escapeTags(trim($_POST['basepath'])) : '');
$singleuser = (!empty($_POST['singleuser']) ? Strings::escapeTags(trim($_POST['singleuser'])) : '');
$proxy_disabled = !empty($_POST['proxy_disabled']);
$only_tag_search = !empty($_POST['only_tag_search']);
@ -1296,7 +1300,6 @@ function admin_page_site_post(App $a)
Config::set('system', 'poco_local_search' , $poco_local_search);
Config::set('system', 'nodeinfo' , $nodeinfo);
Config::set('config', 'sitename' , $sitename);
Config::set('config', 'hostname' , $hostname);
Config::set('config', 'sender_email' , $sender_email);
Config::set('system', 'suppress_tags' , $suppress_tags);
Config::set('system', 'shortcut_icon' , $shortcut_icon);
@ -1392,11 +1395,6 @@ function admin_page_site_post(App $a)
Config::set('system', 'temppath', $temppath);
if ($basepath != '') {
$basepath = BasePath::getRealPath($basepath);
}
Config::set('system', 'basepath' , $basepath);
Config::set('system', 'proxy_disabled' , $proxy_disabled);
Config::set('system', 'only_tag_search' , $only_tag_search);
@ -1536,9 +1534,6 @@ function admin_page_site(App $a)
"develop" => L10n::t("check the development version")
];
if (empty(Config::get('config', 'hostname'))) {
Config::set('config', 'hostname', $a->getHostName());
}
$diaspora_able = ($a->getURLPath() == "");
$optimize_max_tablesize = Config::get('system', 'optimize_max_tablesize', -1);
@ -1597,7 +1592,6 @@ function admin_page_site(App $a)
// name, label, value, help string, extra data...
'$sitename' => ['sitename', L10n::t("Site name"), Config::get('config', 'sitename'), ''],
'$hostname' => ['hostname', L10n::t("Host name"), Config::get('config', 'hostname'), ""],
'$sender_email' => ['sender_email', L10n::t("Sender Email"), Config::get('config', 'sender_email'), L10n::t("The email address your server shall use to send notification emails from."), "", "", "email"],
'$banner' => ['banner', L10n::t("Banner/Logo"), $banner, ""],
'$shortcut_icon' => ['shortcut_icon', L10n::t("Shortcut icon"), Config::get('system', 'shortcut_icon'), L10n::t("Link to an icon that will be used for browsers.")],
@ -1675,7 +1669,6 @@ function admin_page_site(App $a)
'$itemcache_duration' => ['itemcache_duration', L10n::t("Cache duration in seconds"), Config::get('system', 'itemcache_duration'), L10n::t("How long should the cache files be hold? Default value is 86400 seconds \x28One day\x29. To disable the item cache, set the value to -1.")],
'$max_comments' => ['max_comments', L10n::t("Maximum numbers of comments per post"), Config::get('system', 'max_comments'), L10n::t("How much comments should be shown for each post? Default value is 100.")],
'$temppath' => ['temppath', L10n::t("Temp path"), Config::get('system', 'temppath'), L10n::t("If you have a restricted system where the webserver can't access the system temp path, enter another path here.")],
'$basepath' => ['basepath', L10n::t("Base path to installation"), Config::get('system', 'basepath'), L10n::t("If the system cannot detect the correct path to your installation, enter the correct path here. This setting should only be set if you are using a restricted system and symbolic links to your webroot.")],
'$proxy_disabled' => ['proxy_disabled', L10n::t("Disable picture proxy"), Config::get('system', 'proxy_disabled'), L10n::t("The picture proxy increases performance and privacy. It shouldn't be used on systems with very low bandwidth.")],
'$only_tag_search' => ['only_tag_search', L10n::t("Only search in tags"), Config::get('system', 'only_tag_search'), L10n::t("On large systems the text search can slow down the system extremely.")],

97
src/App.php

@ -8,12 +8,12 @@ use Detection\MobileDetect;
use DOMDocument;
use DOMXPath;
use Exception;
use Friendica\Core\Config\Cache\ConfigCacheLoader;
use Friendica\Core\Config\Cache\IConfigCache;
use Friendica\Core\Config\Configuration;
use Friendica\Database\DBA;
use Friendica\Model\Profile;
use Friendica\Network\HTTPException\InternalServerErrorException;
use Friendica\Util\Config\ConfigFileLoader;
use Friendica\Util\HTTPSignature;
use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface;
@ -75,11 +75,6 @@ class App
*/
private $mode;
/**
* @var string The App base path
*/
private $basePath;
/**
* @var string The App URL path
*/
@ -142,7 +137,7 @@ class App
*/
public function getBasePath()
{
return $this->basePath;
return $this->config->get('system', 'basepath');
}
/**
@ -187,7 +182,7 @@ class App
*/
public function registerStylesheet($path)
{
$url = str_replace($this->basePath . DIRECTORY_SEPARATOR, '', $path);
$url = str_replace($this->getBasePath() . DIRECTORY_SEPARATOR, '', $path);
$this->stylesheets[] = trim($url, '/');
}
@ -204,7 +199,7 @@ class App
*/
public function registerFooterScript($path)
{
$url = str_replace($this->basePath . DIRECTORY_SEPARATOR, '', $path);
$url = str_replace($this->getBasePath() . DIRECTORY_SEPARATOR, '', $path);
$this->footerScripts[] = trim($url, '/');
}
@ -216,7 +211,6 @@ class App
/**
* @brief App constructor.
*
* @param string $basePath The basedir of the app
* @param Configuration $config The Configuration
* @param App\Mode $mode The mode of this Friendica app
* @param LoggerInterface $logger The current app logger
@ -225,7 +219,7 @@ class App
*
* @throws Exception if the Basepath is not usable
*/
public function __construct($basePath, Configuration $config, App\Mode $mode, LoggerInterface $logger, Profiler $profiler, $isBackend = true)
public function __construct(Configuration $config, App\Mode $mode, LoggerInterface $logger, Profiler $profiler, $isBackend = true)
{
BaseObject::setApp($this);
@ -233,13 +227,6 @@ class App
$this->config = $config;
$this->profiler = $profiler;
$this->mode = $mode;
$cfgBasePath = $this->config->get('system', 'basepath');
$this->basePath = !empty($cfgBasePath) ? $cfgBasePath : $basePath;
if (!Core\System::isDirectoryUsable($this->basePath, false)) {
throw new Exception('Basepath \'' . $this->basePath . '\' isn\'t usable.');
}
$this->basePath = rtrim($this->basePath, DIRECTORY_SEPARATOR);
$this->checkBackend($isBackend);
$this->checkFriendicaApp();
@ -275,9 +262,9 @@ class App
set_include_path(
get_include_path() . PATH_SEPARATOR
. $this->basePath . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR
. $this->basePath . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR
. $this->basePath);
. $this->getBasePath() . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR
. $this->getBasePath() . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR
. $this->getBasePath());
if (!empty($_SERVER['QUERY_STRING']) && strpos($_SERVER['QUERY_STRING'], 'pagename=') === 0) {
$this->query_string = substr($_SERVER['QUERY_STRING'], 9);
@ -352,10 +339,10 @@ class App
{
$this->determineURLPath();
$this->getMode()->determine($this->basePath);
$this->getMode()->determine($this->getBasePath());
if ($this->getMode()->has(App\Mode::DBAVAILABLE)) {
$loader = new ConfigCacheLoader($this->basePath, $this->getMode());
$loader = new ConfigFileLoader($this->getBasePath(), $this->getMode());
$this->config->getCache()->load($loader->loadCoreConfig('addon'), true);
$this->profiler->update(
@ -363,7 +350,7 @@ class App
$this->config->get('rendertime', 'callstack', false));
Core\Hook::loadHooks();
$loader = new ConfigCacheLoader($this->basePath, $this->mode);
$loader = new ConfigFileLoader($this->getBasePath(), $this->mode);
Core\Hook::callAll('load_config', $loader);
}
@ -465,14 +452,14 @@ class App
{
$scheme = $this->scheme;
if (Core\Config::get('system', 'ssl_policy') == SSL_POLICY_FULL) {
if ($this->config->get('system', 'ssl_policy') == SSL_POLICY_FULL) {
$scheme = 'https';
}
// Basically, we have $ssl = true on any links which can only be seen by a logged in user
// (and also the login link). Anything seen by an outsider will have it turned off.
if (Core\Config::get('system', 'ssl_policy') == SSL_POLICY_SELFSIGN) {
if ($this->config->get('system', 'ssl_policy') == SSL_POLICY_SELFSIGN) {
if ($ssl) {
$scheme = 'https';
} else {
@ -480,8 +467,8 @@ class App
}
}
if (Core\Config::get('config', 'hostname') != '') {
$this->hostname = Core\Config::get('config', 'hostname');
if ($this->config->get('config', 'hostname') != '') {
$this->hostname = $this->config->get('config', 'hostname');
}
return $scheme . '://' . $this->hostname . (!empty($this->getURLPath()) ? '/' . $this->getURLPath() : '' );
@ -516,12 +503,12 @@ class App
$this->urlPath = trim($parsed['path'], '\\/');
}
if (file_exists($this->basePath . '/.htpreconfig.php')) {
include $this->basePath . '/.htpreconfig.php';
if (file_exists($this->getBasePath() . '/.htpreconfig.php')) {
include $this->getBasePath() . '/.htpreconfig.php';
}
if (Core\Config::get('config', 'hostname') != '') {
$this->hostname = Core\Config::get('config', 'hostname');
if ($this->config->get('config', 'hostname') != '') {
$this->hostname = $this->config->get('config', 'hostname');
}
if (!isset($this->hostname) || ($this->hostname == '')) {
@ -532,8 +519,8 @@ class App
public function getHostName()
{
if (Core\Config::get('config', 'hostname') != '') {
$this->hostname = Core\Config::get('config', 'hostname');
if ($this->config->get('config', 'hostname') != '') {
$this->hostname = $this->config->get('config', 'hostname');
}
return $this->hostname;
@ -583,12 +570,12 @@ class App
$this->registerStylesheet($stylesheet);
$shortcut_icon = Core\Config::get('system', 'shortcut_icon');
$shortcut_icon = $this->config->get('system', 'shortcut_icon');
if ($shortcut_icon == '') {
$shortcut_icon = 'images/friendica-32.png';
}
$touch_icon = Core\Config::get('system', 'touch_icon');
$touch_icon = $this->config->get('system', 'touch_icon');
if ($touch_icon == '') {
$touch_icon = 'images/friendica-128.png';
}
@ -608,7 +595,7 @@ class App
'$update_interval' => $interval,
'$shortcut_icon' => $shortcut_icon,
'$touch_icon' => $touch_icon,
'$block_public' => intval(Core\Config::get('system', 'block_public')),
'$block_public' => intval($this->config->get('system', 'block_public')),
'$stylesheets' => $this->stylesheets,
]) . $this->page['htmlhead'];
}
@ -781,13 +768,13 @@ class App
*
if ($this->is_backend()) {
$process = 'backend';
$max_processes = Core\Config::get('system', 'max_processes_backend');
$max_processes = $this->config->get('system', 'max_processes_backend');
if (intval($max_processes) == 0) {
$max_processes = 5;
}
} else {
$process = 'frontend';
$max_processes = Core\Config::get('system', 'max_processes_frontend');
$max_processes = $this->config->get('system', 'max_processes_frontend');
if (intval($max_processes) == 0) {
$max_processes = 20;
}
@ -814,7 +801,7 @@ class App
*/
public function isMinMemoryReached()
{
$min_memory = Core\Config::get('system', 'min_memory', 0);
$min_memory = $this->config->get('system', 'min_memory', 0);
if ($min_memory == 0) {
return false;
}
@ -861,13 +848,13 @@ class App
{
if ($this->isBackend()) {
$process = 'backend';
$maxsysload = intval(Core\Config::get('system', 'maxloadavg'));
$maxsysload = intval($this->config->get('system', 'maxloadavg'));
if ($maxsysload < 1) {
$maxsysload = 50;
}
} else {
$process = 'frontend';
$maxsysload = intval(Core\Config::get('system', 'maxloadavg_frontend'));
$maxsysload = intval($this->config->get('system', 'maxloadavg_frontend'));
if ($maxsysload < 1) {
$maxsysload = 50;
}
@ -914,9 +901,9 @@ class App
}
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$resource = proc_open('cmd /c start /b ' . $cmdline, [], $foo, $this->basePath);
$resource = proc_open('cmd /c start /b ' . $cmdline, [], $foo, $this->getBasePath());
} else {
$resource = proc_open($cmdline . ' &', [], $foo, $this->basePath);
$resource = proc_open($cmdline . ' &', [], $foo, $this->getBasePath());
}
if (!is_resource($resource)) {
Core\Logger::log('We got no resource for command ' . $cmdline, Core\Logger::DEBUG);
@ -933,7 +920,7 @@ class App
*/
public function getSenderEmailAddress()
{
$sender_email = Core\Config::get('config', 'sender_email');
$sender_email = $this->config->get('config', 'sender_email');
if (empty($sender_email)) {
$hostname = $this->getHostName();
if (strpos($hostname, ':')) {
@ -977,7 +964,7 @@ class App
*/
private function computeCurrentTheme()
{
$system_theme = Core\Config::get('system', 'theme');
$system_theme = $this->config->get('system', 'theme');
if (!$system_theme) {
throw new Exception(Core\L10n::t('No system theme config value set.'));
}
@ -985,7 +972,7 @@ class App
// Sane default
$this->currentTheme = $system_theme;
$allowed_themes = explode(',', Core\Config::get('system', 'allowed_themes', $system_theme));
$allowed_themes = explode(',', $this->config->get('system', 'allowed_themes', $system_theme));
$page_theme = null;
// Find the theme that belongs to the user whose stuff we are looking at
@ -1002,7 +989,7 @@ class App
// Specific mobile theme override
if (($this->is_mobile || $this->is_tablet) && Core\Session::get('show-mobile', true)) {
$system_mobile_theme = Core\Config::get('system', 'mobile-theme');
$system_mobile_theme = $this->config->get('system', 'mobile-theme');
$user_mobile_theme = Core\Session::get('mobile-theme', $system_mobile_theme);
// --- means same mobile theme as desktop
@ -1073,7 +1060,7 @@ class App
*/
public function checkURL()
{
$url = Core\Config::get('system', 'url');
$url = $this->config->get('system', 'url');
// if the url isn't set or the stored url is radically different
// than the currently visited url, store the current value accordingly.
@ -1082,7 +1069,7 @@ class App
// We will only change the url to an ip address if there is no existing setting
if (empty($url) || (!Util\Strings::compareLink($url, $this->getBaseURL())) && (!preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/", $this->getHostName()))) {
Core\Config::set('system', 'url', $this->getBaseURL());
$this->config->set('system', 'url', $this->getBaseURL());
}
}
@ -1115,8 +1102,8 @@ class App
if (!$this->getMode()->isInstall()) {
// Force SSL redirection
if (Core\Config::get('system', 'force_ssl') && ($this->getScheme() == "http")
&& intval(Core\Config::get('system', 'ssl_policy')) == SSL_POLICY_FULL
if ($this->config->get('system', 'force_ssl') && ($this->getScheme() == "http")
&& intval($this->config->get('system', 'ssl_policy')) == SSL_POLICY_FULL
&& strpos($this->getBaseURL(), 'https://') === 0
&& $_SERVER['REQUEST_METHOD'] == 'GET') {
header('HTTP/1.1 302 Moved Temporarily');
@ -1199,7 +1186,7 @@ class App
$this->module = 'maintenance';
} else {
$this->checkURL();
Core\Update::check($this->basePath, false);
Core\Update::check($this->getBasePath(), false);
Core\Addon::loadAddons();
Core\Hook::loadHooks();
}
@ -1256,7 +1243,7 @@ class App
$this->module = "login";
}
$privateapps = Core\Config::get('config', 'private_addons', false);
$privateapps = $this->config->get('config', 'private_addons', false);
if (Core\Addon::isEnabled($this->module) && file_exists("addon/{$this->module}/{$this->module}.php")) {
//Check if module is an app and if public access to apps is allowed or not
if ((!local_user()) && Core\Hook::isAddonApp($this->module) && $privateapps) {
@ -1441,7 +1428,7 @@ class App
header("X-Friendica-Version: " . FRIENDICA_VERSION);
header("Content-type: text/html; charset=utf-8");
if (Core\Config::get('system', 'hsts') && (Core\Config::get('system', 'ssl_policy') == SSL_POLICY_FULL)) {
if ($this->config->get('system', 'hsts') && ($this->config->get('system', 'ssl_policy') == SSL_POLICY_FULL)) {
header("Strict-Transport-Security: max-age=31536000");
}

2
src/Core/Config/Cache/ConfigCache.php

@ -5,7 +5,7 @@ namespace Friendica\Core\Config\Cache;
/**
* The Friendica config cache for the application
* Initial, all *.config.php files are loaded into this cache with the
* ConfigCacheLoader ( @see ConfigCacheLoader )
* ConfigFileLoader ( @see ConfigFileLoader )
*/
class ConfigCache implements IConfigCache, IPConfigCache
{

12
src/Core/Config/Configuration.php

@ -10,6 +10,16 @@ namespace Friendica\Core\Config;
*/
class Configuration
{
/**
* The blacklist of configuration settings, which should not get saved to the backend
* @var array
*/
private $configSaveBlacklist = [
'config' => [
'hostname' => true,
]
];
/**
* @var Cache\IConfigCache
*/
@ -117,7 +127,7 @@ class Configuration
$cached = $this->configCache->set($cat, $key, $value);
// If there is no connected adapter, we're finished
if (!$this->configAdapter->isConnected()) {
if (!$this->configAdapter->isConnected() || !empty($this->configSaveBlacklist[$cat][$key])) {
return $cached;
}

5
src/Core/Console/AutomaticInstallation.php

@ -7,6 +7,7 @@ use Friendica\BaseObject;
use Friendica\Core\Config;
use Friendica\Core\Installer;
use Friendica\Core\Theme;
use Friendica\Util\Config\ConfigFileLoader;
use RuntimeException;
class AutomaticInstallation extends Console
@ -103,8 +104,8 @@ HELP;
}
//reload the config cache
$loader = new Config\Cache\ConfigCacheLoader($a->getBasePath(), $a->getMode());
$loader->loadConfigFiles($configCache);
$loader = new ConfigFileLoader($a->getBasePath(), $a->getMode());
$loader->setupCache($configCache);
} else {
// Creating config file

87
src/Core/Update.php

@ -2,8 +2,12 @@
namespace Friendica\Core;
use Friendica\App;
use Friendica\Core\Config\Cache\IConfigCache;
use Friendica\Database\DBA;
use Friendica\Database\DBStructure;
use Friendica\Util\Config\ConfigFileLoader;
use Friendica\Util\Config\ConfigFileSaver;
use Friendica\Util\Strings;
class Update
@ -24,6 +28,11 @@ class Update
return;
}
// Don't check the status if the last update was failed
if (Config::get('system', 'update', Update::SUCCESS, true) == Update::FAILED) {
return;
}
$build = Config::get('system', 'build');
if (empty($build)) {
@ -101,7 +110,9 @@ class Update
for ($x = $stored + 1; $x <= $current; $x++) {
$r = self::runUpdateFunction($x, 'pre_update');
if (!$r) {
break;
Config::set('system', 'update', Update::FAILED);
Lock::release('dbupdate');
return $r;
}
}
@ -115,6 +126,7 @@ class Update
);
}
Logger::error('Update ERROR.', ['from' => $stored, 'to' => $current, 'retval' => $retval]);
Config::set('system', 'update', Update::FAILED);
Lock::release('dbupdate');
return $retval;
} else {
@ -127,7 +139,9 @@ class Update
for ($x = $stored + 1; $x <= $current; $x++) {
$r = self::runUpdateFunction($x, 'update');
if (!$r) {
break;
Config::set('system', 'update', Update::FAILED);
Lock::release('dbupdate');
return $r;
}
}
@ -136,6 +150,7 @@ class Update
self::updateSuccessfull($stored, $current);
}
Config::set('system', 'update', Update::SUCCESS);
Lock::release('dbupdate');
}
}
@ -208,6 +223,74 @@ class Update
}
}
/**
* Checks the config settings and saves given config values into the config file
*
* @param string $basePath The basepath of Friendica
* @param App\Mode $mode The Application mode
*
* @return bool True, if something has been saved
*/
public static function saveConfigToFile($basePath, App\Mode $mode)
{
$configFileLoader = new ConfigFileLoader($basePath, $mode);
$configCache = new Config\Cache\ConfigCache();
$configFileLoader->setupCache($configCache);
$configFileSaver = new ConfigFileSaver($basePath);
$updated = false;
if (self::updateConfigEntry($configCache, $configFileSaver,'config', 'hostname')) {
$updated = true;
};
if (self::updateConfigEntry($configCache, $configFileSaver,'system', 'basepath')) {
$updated = true;
}
if (!$configFileSaver->saveToConfigFile()) {
Logger::alert('Config entry update failed - maybe wrong permission?');
return false;
}
DBA::delete('config', ['cat' => 'config', 'k' => 'hostname']);
DBA::delete('config', ['cat' => 'system', 'k' => 'basepath']);
return $updated;
}
/**
* Adds a value to the ConfigFileSave in case it isn't already updated
*
* @param IConfigCache $configCache The cached config file
* @param ConfigFileSaver $configFileSaver The config file saver
* @param string $cat The config category
* @param string $key The config key
*
* @return boolean True, if a value was updated
*
* @throws \Exception if DBA or Logger doesn't work
*/
private static function updateConfigEntry(IConfigCache $configCache, ConfigFileSaver $configFileSaver, $cat, $key)
{
// check if the config file differs from the whole configuration (= The db contains other values)
$fileConfig = $configCache->get($cat, $key);
$savedConfig = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]);
if (!DBA::isResult($savedConfig)) {
return false;
}
if ($fileConfig !== $savedConfig['v']) {
Logger::info('Difference in config found', ['cat' => $cat, 'key' => $key, 'file' => $fileConfig, 'saved' => $savedConfig['v']]);
$configFileSaver->addConfigValue($cat, $key, $savedConfig['v']);
} else {
Logger::info('No Difference in config found', ['cat' => $cat, 'key' => $key, 'value' => $fileConfig, 'saved' => $savedConfig['v']]);
}
return true;
}
/**
* send the email and do what is needed to do on update fails
*

7
src/Factory/ConfigFactory.php

@ -6,18 +6,19 @@ use Friendica\Core;
use Friendica\Core\Config;
use Friendica\Core\Config\Adapter;
use Friendica\Core\Config\Cache;
use Friendica\Util\Config\ConfigFileLoader;
class ConfigFactory
{
/**
* @param Cache\ConfigCacheLoader $loader The Config Cache loader (INI/config/.htconfig)
* @param ConfigFileLoader $loader The Config Cache loader (INI/config/.htconfig)
*
* @return Cache\ConfigCache
*/
public static function createCache(Cache\ConfigCacheLoader $loader)
public static function createCache(ConfigFileLoader $loader)
{
$configCache = new Cache\ConfigCache();
$loader->loadConfigFiles($configCache);
$loader->setupCache($configCache);
return $configCache;
}

6
src/Factory/DependencyFactory.php

@ -3,9 +3,9 @@
namespace Friendica\Factory;
use Friendica\App;
use Friendica\Core\Config\Cache;
use Friendica\Factory;
use Friendica\Util\BasePath;
use Friendica\Util\Config;
class DependencyFactory
{
@ -24,7 +24,7 @@ class DependencyFactory
{
$basePath = BasePath::create($directory, $_SERVER);
$mode = new App\Mode($basePath);
$configLoader = new Cache\ConfigCacheLoader($basePath, $mode);
$configLoader = new Config\ConfigFileLoader($basePath, $mode);
$configCache = Factory\ConfigFactory::createCache($configLoader);
$profiler = Factory\ProfilerFactory::create($configCache);
Factory\DBFactory::init($basePath, $configCache, $profiler, $_SERVER);
@ -34,6 +34,6 @@ class DependencyFactory
$logger = Factory\LoggerFactory::create($channel, $config, $profiler);
Factory\LoggerFactory::createDev($channel, $config, $profiler);
return new App($basePath, $config, $mode, $logger, $profiler, $isBackend);
return new App($config, $mode, $logger, $profiler, $isBackend);
}
}

48
src/Core/Config/Cache/ConfigCacheLoader.php → src/Util/Config/ConfigFileLoader.php

@ -1,29 +1,21 @@
<?php
namespace Friendica\Core\Config\Cache;
namespace Friendica\Util\Config;
use Friendica\App;
use Friendica\Core\Addon;
use Friendica\Core\Config\Cache\IConfigCache;
/**
* The ConfigCacheLoader loads config-files and stores them in a ConfigCache ( @see ConfigCache )
* The ConfigFileLoader loads config-files and stores them in a IConfigCache ( @see IConfigCache )
*
* It is capable of loading the following config files:
* - *.config.php (current)
* - *.ini.php (deprecated)
* - *.htconfig.php (deprecated)
*/
class ConfigCacheLoader
class ConfigFileLoader extends ConfigFileManager
{
/**
* The Sub directory of the config-files
* @var string
*/
const SUBDIRECTORY = 'config';
private $baseDir;
private $configDir;
/**
* @var App\Mode
*/
@ -31,22 +23,21 @@ class ConfigCacheLoader
public function __construct($baseDir, App\Mode $mode)
{
parent::__construct($baseDir);
$this->appMode = $mode;
$this->baseDir = $baseDir;
$this->configDir = $baseDir . DIRECTORY_SEPARATOR . self::SUBDIRECTORY;
}
/**
* Load the configuration files
* Load the configuration files into an configuration cache
*
* First loads the default value for all the configuration keys, then the legacy configuration files, then the
* expected local.config.php
*
* @param IConfigCache The config cache to load to
* @param IConfigCache $config The config cache to load to
*
* @throws \Exception
*/
public function loadConfigFiles(IConfigCache $config)
public function setupCache(IConfigCache $config)
{
$config->load($this->loadCoreConfig('defaults'));
$config->load($this->loadCoreConfig('settings'));
@ -66,18 +57,18 @@ class ConfigCacheLoader
/**
* Tries to load the specified core-configuration and returns the config array.
*
* @param string $name The name of the configuration
* @param string $name The name of the configuration (default is empty, which means 'local')
*
* @return array The config array (empty if no config found)
*
* @throws \Exception if the configuration file isn't readable
*/
public function loadCoreConfig($name)
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');
if (!empty($this->getConfigFullName($name))) {
return $this->loadConfigFile($this->getConfigFullName($name));
} elseif (!empty($this->getIniFullName($name))) {
return $this->loadINIConfigFile($this->getIniFullName($name));
} else {
return [];
}
@ -110,22 +101,19 @@ class ConfigCacheLoader
/**
* 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
* @param string $name The name of the config file (default is empty, which means .htconfig.php)
*
* @return array The configuration array (empty if no config found)
*
* @deprecated since version 2018.09
*/
private function loadLegacyConfig($name)
private function loadLegacyConfig($name = '')
{
$filePath = $this->baseDir . DIRECTORY_SEPARATOR . '.' . $name . '.php';
$config = [];
if (file_exists($filePath)) {
if (!empty($this->getHtConfigFullName($name))) {
$a = new \stdClass();
$a->config = [];
include $filePath;
include $this->getHtConfigFullName($name);
$htConfigCategories = array_keys($a->config);

90
src/Util/Config/ConfigFileManager.php

@ -0,0 +1,90 @@
<?php
namespace Friendica\Util\Config;
/**
* An abstract class in case of handling with config files
*/
abstract class ConfigFileManager
{
/**
* The Sub directory of the config-files
* @var string
*/
const SUBDIRECTORY = 'config';
/**
* The default name of the user defined config file
* @var string
*/
const CONFIG_LOCAL = 'local';
/**
* The default name of the user defined ini file
* @var string
*/
const CONFIG_INI = 'local';
/**
* The default name of the user defined legacy config file
* @var string
*/
const CONFIG_HTCONFIG = 'htconfig';
protected $baseDir;
protected $configDir;
/**
* @param string $baseDir The base directory of Friendica
*/
public function __construct($baseDir)
{
$this->baseDir = $baseDir;
$this->configDir = $baseDir . DIRECTORY_SEPARATOR . self::SUBDIRECTORY;
}
/**
* Gets the full name (including the path) for a *.config.php (default is local.config.php)
*
* @param string $name The config name (default is empty, which means local.config.php)
*
* @return string The full name or empty if not found
*/
protected function getConfigFullName($name = '')
{
$name = !empty($name) ? $name : self::CONFIG_LOCAL;
$fullName = $this->configDir . DIRECTORY_SEPARATOR . $name . '.config.php';
return file_exists($fullName) ? $fullName : '';
}
/**
* Gets the full name (including the path) for a *.ini.php (default is local.ini.php)
*
* @param string $name The config name (default is empty, which means local.ini.php)
*
* @return string The full name or empty if not found
*/
protected function getIniFullName($name = '')
{
$name = !empty($name) ? $name : self::CONFIG_INI;
$fullName = $this->configDir . DIRECTORY_SEPARATOR . $name . '.ini.php';
return file_exists($fullName) ? $fullName : '';
}
/**
* Gets the full name (including the path) for a .*.php (default is .htconfig.php)
*
* @param string $name The config name (default is empty, which means .htconfig.php)
*
* @return string The full name or empty if not found
*/
protected function getHtConfigFullName($name = '')
{
$name = !empty($name) ? $name : self::CONFIG_HTCONFIG;
$fullName = $this->baseDir . DIRECTORY_SEPARATOR . '.' . $name . '.php';
return file_exists($fullName) ? $fullName : '';
}
}

341
src/Util/Config/ConfigFileSaver.php

@ -0,0 +1,341 @@
<?php
namespace Friendica\Util\Config;
/**
* The ConfigFileSaver saves specific variables into the config-files
*
* It is capable of loading the following config files:
* - *.config.php (current)
* - *.ini.php (deprecated)
* - *.htconfig.php (deprecated)
*/
class ConfigFileSaver extends ConfigFileManager
{
/**
* The standard indentation for config files
* @var string
*/
const INDENT = "\t";
/**
* The settings array to save to
* @var array
*/
private $settings = [];
/**
* Adds a given value to the config file
* Either it replaces the current value or it will get added
*
* @param string $cat The configuration category
* @param string $key The configuration key
* @param string $value The new value
*/
public function addConfigValue($cat, $key, $value)
{
$settingsCount = count(array_keys($this->settings));
for ($i = 0; $i < $settingsCount; $i++) {
// if already set, overwrite the value
if ($this->settings[$i]['cat'] === $cat &&
$this->settings[$i]['key'] === $key) {
$this->settings[$i] = ['cat' => $cat, 'key' => $key, 'value' => $value];
return;
}
}
$this->settings[] = ['cat' => $cat, 'key' => $key, 'value' => $value];
}
/**
* Resetting all added configuration entries so far
*/
public function reset()
{
$this->settings = [];
}
/**
* Save all added configuration entries to the given config files
* After updating the config entries, all configuration entries will be reseted
*
* @param string $name The name of the configuration file (default is empty, which means the default name each type)
*
* @return bool true, if at least one configuration file was successfully updated or nothing to do
*/
public function saveToConfigFile($name = '')
{
// If no settings et, return true
if (count(array_keys($this->settings)) === 0) {
return true;
}
$saved = false;
// Check for the *.config.php file inside the /config/ path
list($reading, $writing) = $this->openFile($this->getConfigFullName($name));
if (isset($reading) && isset($writing)) {
$this->saveConfigFile($reading, $writing);
// Close the current file handler and rename them
if ($this->closeFile($this->getConfigFullName($name), $reading, $writing)) {
// just return true, if everything went fine
$saved = true;
}
}
// Check for the *.ini.php file inside the /config/ path
list($reading, $writing) = $this->openFile($this->getIniFullName($name));
if (isset($reading) && isset($writing)) {
$this->saveINIConfigFile($reading, $writing);
// Close the current file handler and rename them
if ($this->closeFile($this->getIniFullName($name), $reading, $writing)) {
// just return true, if everything went fine
$saved = true;
}
}
// Check for the *.php file (normally .htconfig.php) inside the / path
list($reading, $writing) = $this->openFile($this->getHtConfigFullName($name));
if (isset($reading) && isset($writing)) {
$this->saveToLegacyConfig($reading, $writing);
// Close the current file handler and rename them
if ($this->closeFile($this->getHtConfigFullName($name), $reading, $writing)) {
// just return true, if everything went fine
$saved = true;
}
}
$this->reset();
return $saved;
}
/**
* Opens a config file and returns two handler for reading and writing
*
* @param string $fullName The full name of the current config
*
* @return array An array containing the two reading and writing handler
*/
private function openFile($fullName)
{
if (empty($fullName)) {
return [null, null];
}
try {
$reading = fopen($fullName, 'r');
} catch (\Exception $exception) {
return [null, null];
}
if (!$reading) {
return [null, null];
}
try {
$writing = fopen($fullName . '.tmp', 'w');
} catch (\Exception $exception) {
fclose($reading);
return [null, null];
}
if (!$writing) {
fclose($reading);
return [null, null];
}
return [$reading, $writing];
}
/**
* Close and rename the config file
*
* @param string $fullName The full name of the current config
* @param resource $reading The reading resource handler
* @param resource $writing The writing resource handler
*
* @return bool True, if the close was successful
*/
private function closeFile($fullName, $reading, $writing)
{
fclose($reading);
fclose($writing);
try {
$renamed = rename($fullName, $fullName . '.old');
} catch (\Exception $exception) {
return false;
}
if (!$renamed) {
return false;
}
try {
$renamed = rename($fullName . '.tmp', $fullName);
} catch (\Exception $exception) {
// revert the move of the current config file to have at least the old config
rename($fullName . '.old', $fullName);
return false;
}
if (!$renamed) {
// revert the move of the current config file to have at least the old config
rename($fullName . '.old', $fullName);
return false;
}
return true;
}
/**
* Saves all configuration values to a config file
*
* @param resource $reading The reading handler
* @param resource $writing The writing handler
*/
private function saveConfigFile($reading, $writing)
{
$settingsCount = count(array_keys($this->settings));
$categoryFound = array_fill(0, $settingsCount, false);
$categoryBracketFound = array_fill(0, $settingsCount, false);;
$lineFound = array_fill(0, $settingsCount, false);;
$lineArrowFound = array_fill(0, $settingsCount, false);;
while (!feof($reading)) {
$line = fgets($reading);
// check for each added setting if we have to replace a config line
for ($i = 0; $i < $settingsCount; $i++) {
// find the first line like "'system' =>"
if (!$categoryFound[$i] && stristr($line, sprintf('\'%s\'', $this->settings[$i]['cat']))) {
$categoryFound[$i] = true;
}
// find the first line with a starting bracket ( "[" )
if ($categoryFound[$i] && !$categoryBracketFound[$i] && stristr($line, '[')) {
$categoryBracketFound[$i] = true;
}
// find the first line with the key like "'value'"
if ($categoryBracketFound[$i] && !$lineFound[$i] && stristr($line, sprintf('\'%s\'', $this->settings[$i]['key']))) {
$lineFound[$i] = true;
}
// find the first line with an arrow ("=>") after finding the key
if ($lineFound[$i] && !$lineArrowFound[$i] && stristr($line, '=>')) {
$lineArrowFound[$i] = true;
}
// find the current value and replace it
if ($lineArrowFound[$i] && preg_match_all('/\'(.*?)\'/', $line, $matches, PREG_SET_ORDER)) {
$lineVal = end($matches)[0];
$line = str_replace($lineVal, '\'' . $this->settings[$i]['value'] . '\'', $line);
$categoryFound[$i] = false;
$categoryBracketFound[$i] = false;
$lineFound[$i] = false;
$lineArrowFound[$i] = false;
// if a line contains a closing bracket for the category ( "]" ) and we didn't find the key/value pair,
// add it as a new line before the closing bracket
} elseif ($categoryBracketFound[$i] && !$lineArrowFound[$i] && stristr($line, ']')) {
$categoryFound[$i] = false;
$categoryBracketFound[$i] = false;
$lineFound[$i] = false;
$lineArrowFound[$i] = false;
$newLine = sprintf(self::INDENT . self::INDENT . '\'%s\' => \'%s\',' . PHP_EOL, $this->settings[$i]['key'], $this->settings[$i]['value']);
$line = $newLine . $line;
}
}
fputs($writing, $line);
}
}
/**
* Saves a value to a ini file
*
* @param resource $reading The reading handler
* @param resource $writing The writing handler
*/
private function saveINIConfigFile($reading, $writing)
{
$settingsCount = count(array_keys($this->settings));
$categoryFound = array_fill(0, $settingsCount, false);
while (!feof($reading)) {
$line = fgets($reading);
// check for each added setting if we have to replace a config line
for ($i = 0; $i < $settingsCount; $i++) {
// find the category of the current setting
if (!$categoryFound[$i] && stristr($line, sprintf('[%s]', $this->settings[$i]['cat']))) {
$categoryFound[$i] = true;
// check the current value
} elseif ($categoryFound[$i] && preg_match_all('/^' . $this->settings[$i]['key'] . '\s*=\s*(.*?)$/', $line, $matches, PREG_SET_ORDER)) {
$line = $this->settings[$i]['key'] . ' = ' . $this->settings[$i]['value'] . PHP_EOL;
$categoryFound[$i] = false;
// If end of INI file, add the line before the INI end
} elseif ($categoryFound[$i] && (preg_match_all('/^\[.*?\]$/', $line) || preg_match_all('/^INI;.*$/', $line))) {
$categoryFound[$i] = false;
$newLine = $this->settings[$i]['key'] . ' = ' . $this->settings[$i]['value'] . PHP_EOL;
$line = $newLine . $line;
}
}
fputs($writing, $line);
}
}
/**
* Saves a value to a .php file (normally .htconfig.php)
*
* @param resource $reading The reading handler
* @param resource $writing The writing handler
*/
private function saveToLegacyConfig($reading, $writing)
{
$settingsCount = count(array_keys($this->settings));
$found = array_fill(0, $settingsCount, false);
while (!feof($reading)) {
$line = fgets($reading);
// check for each added setting if we have to replace a config line
for ($i = 0; $i < $settingsCount; $i++) {
// check for a non plain config setting (use category too)
if ($this->settings[$i]['cat'] !== 'config' && preg_match_all('/^\$a\-\>config\[\'' . $this->settings[$i]['cat'] . '\'\]\[\'' . $this->settings[$i]['key'] . '\'\]\s*=\s\'*(.*?)\';$/', $line, $matches, PREG_SET_ORDER)) {
$line = '$a->config[\'' . $this->settings[$i]['cat'] . '\'][\'' . $this->settings[$i]['key'] . '\'] = \'' . $this->settings[$i]['value'] . '\';' . PHP_EOL;
$found[$i] = true;
// check for a plain config setting (don't use a category)
} elseif ($this->settings[$i]['cat'] === 'config' && preg_match_all('/^\$a\-\>config\[\'' . $this->settings[$i]['key'] . '\'\]\s*=\s\'*(.*?)\';$/', $line, $matches, PREG_SET_ORDER)) {
$line = '$a->config[\'' . $this->settings[$i]['key'] . '\'] = \'' . $this->settings[$i]['value'] . '\';' . PHP_EOL;
$found[$i] = true;
}
}
fputs($writing, $line);
}
for ($i = 0; $i < $settingsCount; $i++) {
if (!$found[$i]) {
if ($this->settings[$i]['cat'] !== 'config') {
$line = '$a->config[\'' . $this->settings[$i]['cat'] . '\'][\'' . $this->settings[$i]['key'] . '\'] = \'' . $this->settings[$i]['value'] . '\';' . PHP_EOL;
} else {
$line = '$a->config[\'' . $this->settings[$i]['key'] . '\'] = \'' . $this->settings[$i]['value'] . '\';' . PHP_EOL;
}
fputs($writing, $line);
}
}
}
}

6
src/Worker/DBUpdate.php

@ -6,12 +6,16 @@
namespace Friendica\Worker;
use Friendica\BaseObject;
use Friendica\Core\Config;
use Friendica\Core\Update;
class DBUpdate extends BaseObject
{
public static function execute()
{
Update::run(self::getApp()->getBasePath());
// Just in case the last update wasn't failed
if (Config::get('system', 'update', Update::SUCCESS, true) != Update::FAILED) {
Update::run(self::getApp()->getBasePath());
}
}
}

4
tests/DatabaseTest.php

@ -6,10 +6,10 @@
namespace Friendica\Test;
use Friendica\App;
use Friendica\Core\Config\Cache;
use Friendica\Database\DBA;
use Friendica\Factory;
use Friendica\Util\BasePath;
use Friendica\Util\Config\ConfigFileLoader;
use Friendica\Util\Profiler;
use PHPUnit\DbUnit\DataSet\YamlDataSet;
use PHPUnit\DbUnit\TestCaseTrait;
@ -43,7 +43,7 @@ abstract class DatabaseTest extends MockedTest
$basePath = BasePath::create(dirname(__DIR__));
$mode = new App\Mode($basePath);
$configLoader = new Cache\ConfigCacheLoader($basePath, $mode);
$configLoader = new ConfigFileLoader($basePath, $mode);
$config = Factory\ConfigFactory::createCache($configLoader);
$profiler = \Mockery::mock(Profiler::class);

4
tests/datasets/config/.htconfig.test.php → tests/datasets/config/.htconfig.php

@ -33,7 +33,7 @@ $a->config['sitename'] = "Friendica My Network";
// must precisely match the email address of the person logged in.
$a->config['register_policy'] = REGISTER_OPEN;
$a->config['register_text'] = 'A register text';
$a->config['admin_email'] = 'admin@friendica.local';
$a->config['admin_email'] = 'admin@test.it';
$a->config['admin_nickname'] = 'Friendly admin';
// Maximum size of an imported message, 0 is unlimited
@ -52,7 +52,7 @@ $a->config['system']['huburl'] = '[internal]';
$a->config['system']['allowed_themes'] = 'quattro,vier,duepuntozero';
// default system theme
$a->config['system']['theme'] = 'duepuntozero';
$a->config['system']['theme'] = 'frio';
// By default allow pseudonyms
$a->config['system']['no_regfullname'] = true;

1
tests/datasets/config/local.config.php

@ -23,5 +23,6 @@ return [
'system' => [
'default_timezone' => 'UTC',
'language' => 'en',
'theme' => 'frio',
],
];

3
tests/datasets/config/local.ini.php

@ -11,6 +11,9 @@ username = testuser
password = testpw
database = testdb
[system]
theme = frio
[config]
admin_email = admin@test.it
INI;

6
tests/include/ApiTest.php

@ -7,13 +7,13 @@ namespace Friendica\Test;
use Friendica\App;
use Friendica\Core\Config;
use Friendica\Core\Config\Cache;
use Friendica\Core\PConfig;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Factory;
use Friendica\Network\HTTPException;
use Friendica\Util\BasePath;
use Friendica\Util\Config\ConfigFileLoader;
use Monolog\Handler\TestHandler;
require_once __DIR__ . '/../../include/api.php';
@ -50,14 +50,14 @@ class ApiTest extends DatabaseTest
{
$basePath = BasePath::create(dirname(__DIR__) . '/../');
$mode = new App\Mode($basePath);
$configLoader = new Cache\ConfigCacheLoader($basePath, $mode);
$configLoader = new ConfigFileLoader($basePath, $mode);
$configCache = Factory\ConfigFactory::createCache($configLoader);
$profiler = Factory\ProfilerFactory::create($configCache);
Factory\DBFactory::init($basePath, $configCache, $profiler, $_SERVER);
$config = Factory\ConfigFactory::createConfig($configCache);
Factory\ConfigFactory::createPConfig($configCache);
$logger = Factory\LoggerFactory::create('test', $config, $profiler);
$this->app = new App($basePath, $config, $mode, $logger, $profiler, false);
$this->app = new App($config, $mode, $logger, $profiler, false);
parent::setUp();

6
tests/src/Database/DBATest.php

@ -3,11 +3,11 @@ namespace Friendica\Test\src\Database;
use Friendica\App;
use Friendica\Core\Config;
use Friendica\Core\Config\Cache;
use Friendica\Database\DBA;
use Friendica\Factory;
use Friendica\Test\DatabaseTest;
use Friendica\Util\BasePath;
use Friendica\Util\Config\ConfigFileLoader;
class DBATest extends DatabaseTest
{
@ -15,14 +15,14 @@ class DBATest extends DatabaseTest
{
$basePath = BasePath::create(dirname(__DIR__) . '/../../');
$mode = new App\Mode($basePath);
$configLoader = new Cache\ConfigCacheLoader($basePath, $mode);
$configLoader = new ConfigFileLoader($basePath, $mode);
$configCache = Factory\ConfigFactory::createCache($configLoader);
$profiler = Factory\ProfilerFactory::create($configCache);
Factory\DBFactory::init($basePath, $configCache, $profiler, $_SERVER);
$config = Factory\ConfigFactory::createConfig($configCache);
Factory\ConfigFactory::createPConfig($configCache);
$logger = Factory\LoggerFactory::create('test', $config, $profiler);
$this->app = new App($basePath, $config, $mode, $logger, $profiler, false);
$this->app = new App($config, $mode, $logger, $profiler, false);
parent::setUp();

6
tests/src/Database/DBStructureTest.php

@ -3,11 +3,11 @@
namespace Friendica\Test\src\Database;
use Friendica\App;
use Friendica\Core\Config\Cache;
use Friendica\Database\DBStructure;
use Friendica\Factory;
use Friendica\Test\DatabaseTest;
use Friendica\Util\BasePath;
use Friendica\Util\Config\ConfigFileLoader;
class DBStructureTest extends DatabaseTest
{
@ -15,14 +15,14 @@ class DBStructureTest extends DatabaseTest
{
$basePath = BasePath::create(dirname(__DIR__) . '/../../');
$mode = new App\Mode($basePath);
$configLoader = new Cache\ConfigCacheLoader($basePath, $mode);
$configLoader = new ConfigFileLoader($basePath, $mode);
$configCache = Factory\ConfigFactory::createCache($configLoader);
$profiler = Factory\ProfilerFactory::create($configCache);
Factory\DBFactory::init($basePath, $configCache, $profiler, $_SERVER);
$config = Factory\ConfigFactory::createConfig($configCache);
Factory\ConfigFactory::createPConfig($configCache);
$logger = Factory\LoggerFactory::create('test', $config, $profiler);
$this->app = new App($basePath, $config, $mode, $logger, $profiler, false);
$this->app = new App($config, $mode, $logger, $profiler, false);
parent::setUp();
}

38
tests/src/Core/Config/Cache/ConfigCacheLoaderTest.php → tests/src/Util/Config/ConfigFileLoaderTest.php

@ -1,16 +1,16 @@
<?php
namespace Friendica\Test\src\Core\Config\Cache;
namespace Friendica\Test\src\Util\Config;
use Friendica\App;
use Friendica\Core\Config\Cache\ConfigCache;
use Friendica\Core\Config\Cache\ConfigCacheLoader;
use Friendica\Test\MockedTest;
use Friendica\Test\Util\VFSTrait;
use Friendica\Util\Config\ConfigFileLoader;
use Mockery\MockInterface;
use org\bovigo\vfs\vfsStream;
class ConfigCacheLoaderTest extends MockedTest
class ConfigFileLoaderTest extends MockedTest
{
use VFSTrait;
@ -34,10 +34,10 @@ class ConfigCacheLoaderTest extends MockedTest
*/
public function testLoadConfigFiles()
{
$configCacheLoader = new ConfigCacheLoader($this->root->url(), $this->mode);
$configFileLoader = new ConfigFileLoader($this->root->url(), $this->mode);
$configCache = new ConfigCache();
$configCacheLoader->loadConfigFiles($configCache);
$configFileLoader->setupCache($configCache);
$this->assertEquals($this->root->url(), $configCache->get('system', 'basepath'));
}
@ -55,10 +55,10 @@ class ConfigCacheLoaderTest extends MockedTest
->at($this->root->getChild('config'))
->setContent('<?php return true;');
$configCacheLoader = new ConfigCacheLoader($this->root->url(), $this->mode);
$configFileLoader = new ConfigFileLoader($this->root->url(), $this->mode);
$configCache = new ConfigCache();
$configCacheLoader->loadConfigFiles($configCache);
$configFileLoader->setupCache($configCache);
}
/**
@ -69,7 +69,6 @@ class ConfigCacheLoaderTest extends MockedTest
$this->delConfigFile('local.config.php');
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'datasets' . DIRECTORY_SEPARATOR .
@ -80,10 +79,10 @@ class ConfigCacheLoaderTest extends MockedTest
->at($this->root->getChild('config'))
->setContent(file_get_contents($file));
$configCacheLoader = new ConfigCacheLoader($this->root->url(), $this->mode);
$configFileLoader = new ConfigFileLoader($this->root->url(), $this->mode);
$configCache = new ConfigCache();
$configCacheLoader->loadConfigFiles($configCache);
$configFileLoader->setupCache($configCache);
$this->assertEquals('testhost', $configCache->get('database', 'hostname'));
$this->assertEquals('testuser', $configCache->get('database', 'username'));
@ -102,7 +101,6 @@ class ConfigCacheLoaderTest extends MockedTest
$this->delConfigFile('local.config.php');
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'datasets' . DIRECTORY_SEPARATOR .
@ -113,10 +111,10 @@ class ConfigCacheLoaderTest extends MockedTest
->at($this->root->getChild('config'))
->setContent(file_get_contents($file));
$configCacheLoader = new ConfigCacheLoader($this->root->url(), $this->mode);
$configFileLoader = new ConfigFileLoader($this->root->url(), $this->mode);
$configCache = new ConfigCache();
$configCacheLoader->loadConfigFiles($configCache);
$configFileLoader->setupCache($configCache);
$this->assertEquals('testhost', $configCache->get('database', 'hostname'));
$this->assertEquals('testuser', $configCache->get('database', 'username'));
@ -134,21 +132,20 @@ class ConfigCacheLoaderTest extends MockedTest
$this->delConfigFile('local.config.php');
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'datasets' . DIRECTORY_SEPARATOR .
'config' . DIRECTORY_SEPARATOR .
'.htconfig.test.php';
'.htconfig.php';
vfsStream::newFile('.htconfig.php')
->at($this->root)
->setContent(file_get_contents($file));
$configCacheLoader = new ConfigCacheLoader($this->root->url(), $this->mode);
$configFileLoader = new ConfigFileLoader($this->root->url(), $this->mode);
$configCache = new ConfigCache();
$configCacheLoader->loadConfigFiles($configCache);
$configFileLoader->setupCache($configCache);
$this->assertEquals('testhost', $configCache->get('database', 'hostname'));
$this->assertEquals('testuser', $configCache->get('database', 'username'));
@ -160,7 +157,7 @@ class ConfigCacheLoaderTest extends MockedTest
$this->assertEquals('Europe/Berlin', $configCache->get('system', 'default_timezone'));
$this->assertEquals('fr', $configCache->get('system', 'language'));
$this->assertEquals('admin@friendica.local', $configCache->get('config', 'admin_email'));
$this->assertEquals('admin@test.it', $configCache->get('config', 'admin_email'));
$this->assertEquals('Friendly admin', $configCache->get('config', 'admin_nickname'));
$this->assertEquals('/another/php', $configCache->get('config', 'php_path'));
@ -184,7 +181,6 @@ class ConfigCacheLoaderTest extends MockedTest
vfsStream::create($structure, $this->root);
$file = dirname(__DIR__) . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'datasets' . DIRECTORY_SEPARATOR .
@ -195,9 +191,9 @@ class ConfigCacheLoaderTest extends MockedTest
->at($this->root->getChild('addon')->getChild('test')->getChild('config'))
->setContent(file_get_contents($file));
$configCacheLoader = new ConfigCacheLoader($this->root->url(), $this->mode);
$configFileLoader = new ConfigFileLoader($this->root->url(), $this->mode);
$conf = $configCacheLoader->loadAddonConfig('test');
$conf = $configFileLoader->loadAddonConfig('test');
$this->assertEquals('testhost', $conf['database']['hostname']);
$this->assertEquals('testuser', $conf['database']['username']);

189
tests/src/Util/Config/ConfigFileSaverTest.php

@ -0,0 +1,189 @@
<?php
namespace Friendica\Test\src\Util\Config;
use Friendica\App;
use Friendica\Core\Config\Cache\ConfigCache;
use Friendica\Test\MockedTest;
use Friendica\Test\Util\VFSTrait;
use Friendica\Util\Config\ConfigFileLoader;
use Friendica\Util\Config\ConfigFileSaver;
use Mockery\MockInterface;
use org\bovigo\vfs\vfsStream;
class ConfigFileSaverTest extends MockedTest
{
use VFSTrait;
/**
* @var App\Mode|MockInterface
*/
private $mode;
protected function setUp()
{
parent::setUp();
$this->setUpVfsDir();
$this->mode = \Mockery::mock(App\Mode::class);
$this->mode->shouldReceive('isInstall')->andReturn(true);
}
public function dataConfigFiles()
{
return [
'config' => [
'fileName' => 'local.config.php',
'filePath' => dirname(__DIR__) . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'datasets' . DIRECTORY_SEPARATOR .
'config',
'relativePath' => 'config',
],
'ini' => [
'fileName' => 'local.ini.php',
'filePath' => dirname(__DIR__) . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .
'..' . DIRECTORY_SEPARATOR .