Merge pull request #6724 from nupplaphil/issue/config_set

Config Set Bugfix
This commit is contained in:
Hypolite Petovan 2019-02-22 21:29:26 -05:00 committed by GitHub
commit 98d584b737
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 208 additions and 236 deletions

View file

@ -144,7 +144,9 @@ if (!$foreground) {
file_put_contents($pidfile, $pid); file_put_contents($pidfile, $pid);
// We lose the database connection upon forking // We lose the database connection upon forking
Factory\DBFactory::init($a->getConfigCache(), $a->getProfiler(), $_SERVER); /// @todo refactoring during https://github.com/friendica/friendica/issues/6720
$basePath = \Friendica\Util\BasePath::create(dirname(__DIR__), $_SERVER);
Factory\DBFactory::init($basePath, $a->getConfigCache(), $a->getProfiler(), $_SERVER);
} }
Config::set('system', 'worker_daemon_mode', true); Config::set('system', 'worker_daemon_mode', true);

View file

@ -205,6 +205,7 @@ class App
/** /**
* @brief App constructor. * @brief App constructor.
* *
* @param string $basePath The basedir of the app
* @param Configuration $config The Configuration * @param Configuration $config The Configuration
* @param LoggerInterface $logger The current app logger * @param LoggerInterface $logger The current app logger
* @param Profiler $profiler The profiler of this application * @param Profiler $profiler The profiler of this application
@ -212,14 +213,15 @@ class App
* *
* @throws Exception if the Basepath is not usable * @throws Exception if the Basepath is not usable
*/ */
public function __construct(Configuration $config, LoggerInterface $logger, Profiler $profiler, $isBackend = true) public function __construct($basePath, Configuration $config, LoggerInterface $logger, Profiler $profiler, $isBackend = true)
{ {
BaseObject::setApp($this); BaseObject::setApp($this);
$this->logger = $logger; $this->logger = $logger;
$this->config = $config; $this->config = $config;
$this->profiler = $profiler; $this->profiler = $profiler;
$this->basePath = $this->config->get('system', 'basepath'); $cfgBasePath = $this->config->get('system', 'basepath');
$this->basePath = !empty($cfgBasePath) ? $cfgBasePath : $basePath;
if (!Core\System::isDirectoryUsable($this->basePath, false)) { if (!Core\System::isDirectoryUsable($this->basePath, false)) {
throw new Exception('Basepath \'' . $this->basePath . '\' isn\'t usable.'); throw new Exception('Basepath \'' . $this->basePath . '\' isn\'t usable.');

View file

@ -6,7 +6,11 @@ use Friendica\Database\DBA;
abstract class AbstractDbaConfigAdapter abstract class AbstractDbaConfigAdapter
{ {
/** @var bool */ /**
* The connection state of the adapter
*
* @var bool
*/
protected $connected = true; protected $connected = true;
public function __construct() public function __construct()
@ -14,8 +18,66 @@ abstract class AbstractDbaConfigAdapter
$this->connected = DBA::connected(); $this->connected = DBA::connected();
} }
/**
* Checks if the adapter is currently connected
*
* @return bool
*/
public function isConnected() public function isConnected()
{ {
return $this->connected; return $this->connected;
} }
/**
* Formats a DB value to a config value
* - null = The db-value isn't set
* - bool = The db-value is either '0' or '1'
* - array = The db-value is a serialized array
* - string = The db-value is a string
*
* Keep in mind that there aren't any numeric/integer config values in the database
*
* @param null|string $value
*
* @return null|array|string
*/
protected function toConfigValue($value)
{
if (!isset($value)) {
return null;
}
switch (true) {
// manage array value
case preg_match("|^a:[0-9]+:{.*}$|s", $value):
return unserialize($value);
default:
return $value;
}
}
/**
* Formats a config value to a DB value (string)
*
* @param mixed $value
*
* @return string
*/
protected function toDbValue($value)
{
// if not set, save an empty string
if (!isset($value)) {
return '';
}
switch (true) {
// manage arrays
case is_array($value):
return serialize($value);
default:
return (string)$value;
}
}
} }

View file

@ -21,10 +21,12 @@ interface IConfigAdapter
* Get a particular system-wide config variable given the category name * Get a particular system-wide config variable given the category name
* ($family) and a key. * ($family) and a key.
* *
* Note: Boolean variables are defined as 0/1 in the database
*
* @param string $cat The category of the configuration value * @param string $cat The category of the configuration value
* @param string $key The configuration key to query * @param string $key The configuration key to query
* *
* @return mixed Stored value or "!<unset>!" if it does not exist * @return null|mixed Stored value or null if it does not exist
*/ */
public function get($cat, $key); public function get($cat, $key);
@ -46,9 +48,9 @@ interface IConfigAdapter
* and removes it from the database. * and removes it from the database.
* *
* @param string $cat The category of the configuration value * @param string $cat The category of the configuration value
* @param string $key The configuration key to delete * @param string $key The configuration key to delete
* *
* @return mixed * @return bool Operation success
*/ */
public function delete($cat, $key); public function delete($cat, $key);

View file

@ -28,11 +28,13 @@ interface IPConfigAdapter
* 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. * ($family) and a key.
* *
* Note: Boolean variables are defined as 0/1 in the database
*
* @param string $uid The user_id * @param string $uid The user_id
* @param string $cat The category of the configuration value * @param string $cat The category of the configuration value
* @param string $key The configuration key to query * @param string $key The configuration key to query
* *
* @return mixed Stored value or "!<unset>!" if it does not exist * @return null|mixed Stored value or null if it does not exist
*/ */
public function get($uid, $cat, $key); public function get($uid, $cat, $key);
@ -59,7 +61,7 @@ interface IPConfigAdapter
* @param string $cat The category of the configuration value * @param string $cat The category of the configuration value
* @param string $key The configuration key to delete * @param string $key The configuration key to delete
* *
* @return bool * @return bool Operation success
*/ */
public function delete($uid, $cat, $key); public function delete($uid, $cat, $key);

View file

@ -34,40 +34,48 @@ class JITConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapte
$configs = DBA::select('config', ['v', 'k'], ['cat' => $cat]); $configs = DBA::select('config', ['v', 'k'], ['cat' => $cat]);
while ($config = DBA::fetch($configs)) { while ($config = DBA::fetch($configs)) {
$key = $config['k']; $key = $config['k'];
$value = $config['v']; $value = $this->toConfigValue($config['v']);
if (isset($value) && $value !== '') { // The value was in the db, so don't check it again (unless you have to)
$this->in_db[$cat][$key] = true;
// just save it in case it is set
if (isset($value)) {
$return[$key] = $value; $return[$key] = $value;
$this->in_db[$cat][$key] = true;
} }
} }
DBA::close($configs); DBA::close($configs);
return [$cat => $config]; return [$cat => $return];
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @param bool $mark if true, mark the selection of the current cat/key pair
*/ */
public function get($cat, $key) public function get($cat, $key, $mark = true)
{ {
if (!$this->isConnected()) { if (!$this->isConnected()) {
return '!<unset>!'; return null;
}
// The value got checked, so mark it to avoid checking it over and over again
if ($mark) {
$this->in_db[$cat][$key] = true;
} }
$config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]); $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]);
if (DBA::isResult($config)) { if (DBA::isResult($config)) {
// manage array value $value = $this->toConfigValue($config['v']);
$value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']);
if (isset($value) && $value !== '') { // just return it in case it is set
$this->in_db[$cat][$key] = true; if (isset($value)) {
return $value; return $value;
} }
} }
$this->in_db[$cat][$key] = false; return null;
return '!<unset>!';
} }
/** /**
@ -82,9 +90,8 @@ class JITConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapte
// We store our setting values in a string variable. // We store our setting values in a string variable.
// So we have to do the conversion here so that the compare below works. // So we have to do the conversion here so that the compare below works.
// The exception are array values. // The exception are array values.
$dbvalue = (!is_array($value) ? (string)$value : $value); $compare_value = (!is_array($value) ? (string)$value : $value);
$stored_value = $this->get($cat, $key, false);
$stored = $this->get($cat, $key);
if (!isset($this->in_db[$cat])) { if (!isset($this->in_db[$cat])) {
$this->in_db[$cat] = []; $this->in_db[$cat] = [];
@ -93,12 +100,11 @@ class JITConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapte
$this->in_db[$cat][$key] = false; $this->in_db[$cat][$key] = false;
} }
if (($stored === $dbvalue) && $this->in_db[$cat][$key]) { if (isset($stored_value) && ($stored_value === $compare_value) && $this->in_db[$cat][$key]) {
return true; return true;
} }
// manage array value $dbvalue = $this->toDbValue($value);
$dbvalue = (is_array($value) ? serialize($value) : $dbvalue);
$result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true); $result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true);

View file

@ -29,16 +29,18 @@ class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdap
if (DBA::isResult($pconfigs)) { if (DBA::isResult($pconfigs)) {
while ($pconfig = DBA::fetch($pconfigs)) { while ($pconfig = DBA::fetch($pconfigs)) {
$key = $pconfig['k']; $key = $pconfig['k'];
$value = $pconfig['v']; $value = $this->toConfigValue($pconfig['v']);
if (isset($value) && $value !== '') { // The value was in the db, so don't check it again (unless you have to)
$this->in_db[$uid][$cat][$key] = true;
if (isset($value)) {
$return[$key] = $value; $return[$key] = $value;
$this->in_db[$uid][$cat][$key] = true;
} }
} }
} else if ($cat != 'config') { } else if ($cat != 'config') {
// Negative caching // Negative caching
$return = "!<unset>!"; $return = null;
} }
DBA::close($pconfigs); DBA::close($pconfigs);
@ -47,26 +49,31 @@ class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdap
/** /**
* {@inheritdoc} * {@inheritdoc}
*
* @param bool $mark if true, mark the selection of the current cat/key pair
*/ */
public function get($uid, $cat, $key) public function get($uid, $cat, $key, $mark = true)
{ {
if (!$this->isConnected()) { if (!$this->isConnected()) {
return '!<unset>!'; return null;
}
// The value was in the db, so don't check it again (unless you have to)
if ($mark) {
$this->in_db[$uid][$cat][$key] = true;
} }
$pconfig = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]); $pconfig = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
if (DBA::isResult($pconfig)) { if (DBA::isResult($pconfig)) {
// manage array value $value = $this->toConfigValue($pconfig['v']);
$value = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']);
if (isset($value) && $value !== '') { if (isset($value)) {
$this->in_db[$uid][$cat][$key] = true;
return $value; return $value;
} }
} }
$this->in_db[$uid][$cat][$key] = false; $this->in_db[$uid][$cat][$key] = false;
return '!<unset>!'; return null;
} }
/** /**
@ -81,9 +88,8 @@ class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdap
// We store our setting values in a string variable. // We store our setting values in a string variable.
// So we have to do the conversion here so that the compare below works. // So we have to do the conversion here so that the compare below works.
// The exception are array values. // The exception are array values.
$dbvalue = (!is_array($value) ? (string)$value : $value); $compare_value = (!is_array($value) ? (string)$value : $value);
$stored_value = $this->get($uid, $cat, $key, false);
$stored = $this->get($uid, $cat, $key);
if (!isset($this->in_db[$uid])) { if (!isset($this->in_db[$uid])) {
$this->in_db[$uid] = []; $this->in_db[$uid] = [];
@ -95,12 +101,12 @@ class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdap
$this->in_db[$uid][$cat][$key] = false; $this->in_db[$uid][$cat][$key] = false;
} }
if (($stored === $dbvalue) && $this->in_db[$uid][$cat][$key]) { if (isset($stored_value) && ($stored_value === $compare_value) && $this->in_db[$uid][$cat][$key]) {
return true; return true;
} }
// manage array value // manage array value
$dbvalue = (is_array($value) ? serialize($value) : $dbvalue); $dbvalue = (is_array($value) ? serialize($value) : $value);
$result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true); $result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true);
@ -118,13 +124,11 @@ class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdap
return false; return false;
} }
if (!empty($this->in_db[$uid][$cat][$key])) { if (isset($this->in_db[$uid][$cat][$key])) {
unset($this->in_db[$uid][$cat][$key]); unset($this->in_db[$uid][$cat][$key]);
} }
$result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]); return DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
return $result;
} }
/** /**

View file

@ -32,11 +32,9 @@ class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAd
$configs = DBA::select('config', ['cat', 'v', 'k']); $configs = DBA::select('config', ['cat', 'v', 'k']);
while ($config = DBA::fetch($configs)) { while ($config = DBA::fetch($configs)) {
$value = $config['v']; $value = $this->toConfigValue($config['v']);
if (isset($value) && $value !== '') { if (isset($value)) {
$return[$config['cat']][$config['k']] = $value; $return[$config['cat']][$config['k']] = $value;
} else {
$return[$config['cat']][$config['k']] = '!<unset>!';
} }
} }
DBA::close($configs); DBA::close($configs);
@ -52,20 +50,19 @@ class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAd
public function get($cat, $key) public function get($cat, $key)
{ {
if (!$this->isConnected()) { if (!$this->isConnected()) {
return '!<unset>!'; return null;
} }
$config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]); $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]);
if (DBA::isResult($config)) { if (DBA::isResult($config)) {
// manage array value $value = $this->toConfigValue($config['v']);
$value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']);
if (isset($value) && $value !== '') { if (isset($value)) {
return $value; return $value;
} }
} }
return '!<unset>!'; return null;
} }
/** /**
@ -81,17 +78,15 @@ class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAd
// So we have to do the conversion here so that the compare below works. // So we have to do the conversion here so that the compare below works.
// The exception are array values. // The exception are array values.
$compare_value = !is_array($value) ? (string)$value : $value; $compare_value = !is_array($value) ? (string)$value : $value;
$stored_value = $this->get($cat, $key);
if ($this->get($cat, $key) === $compare_value) { if (isset($stored_value) && $stored_value === $compare_value) {
return true; return true;
} }
// manage array value $dbvalue = $this->toDbValue($value);
$dbvalue = is_array($value) ? serialize($value) : $value;
$result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true); return DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true);
return $result;
} }
/** /**
@ -103,9 +98,7 @@ class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAd
return false; return false;
} }
$result = DBA::delete('config', ['cat' => $cat, 'k' => $key]); return DBA::delete('config', ['cat' => $cat, 'k' => $key]);
return $result;
} }
/** /**

View file

@ -49,11 +49,9 @@ class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfig
$pconfigs = DBA::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]); $pconfigs = DBA::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]);
while ($pconfig = DBA::fetch($pconfigs)) { while ($pconfig = DBA::fetch($pconfigs)) {
$value = $pconfig['v']; $value = $this->toConfigValue($pconfig['v']);
if (isset($value) && $value !== '') { if (isset($value)) {
$return[$pconfig['cat']][$pconfig['k']] = $value; $return[$pconfig['cat']][$pconfig['k']] = $value;
} else {
$return[$pconfig['cat']][$pconfig['k']] = '!<unset>!';
} }
} }
DBA::close($pconfigs); DBA::close($pconfigs);
@ -69,7 +67,7 @@ class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfig
public function get($uid, $cat, $key) public function get($uid, $cat, $key)
{ {
if (!$this->isConnected()) { if (!$this->isConnected()) {
return '!<unset>!'; return null;
} }
if (!$this->isLoaded($uid, $cat, $key)) { if (!$this->isLoaded($uid, $cat, $key)) {
@ -78,14 +76,13 @@ class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfig
$config = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]); $config = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
if (DBA::isResult($config)) { if (DBA::isResult($config)) {
// manage array value $value = $this->toConfigValue($config['v']);
$value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']);
if (isset($value) && $value !== '') { if (isset($value)) {
return $value; return $value;
} }
} }
return '!<unset>!'; return null;
} }
/** /**
@ -104,17 +101,15 @@ class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfig
// So we have to do the conversion here so that the compare below works. // So we have to do the conversion here so that the compare below works.
// The exception are array values. // The exception are array values.
$compare_value = !is_array($value) ? (string)$value : $value; $compare_value = !is_array($value) ? (string)$value : $value;
$stored_value = $this->get($uid, $cat, $key);
if ($this->get($uid, $cat, $key) === $compare_value) { if (isset($stored_value) && $stored_value === $compare_value) {
return true; return true;
} }
// manage array value $dbvalue = $this->toDbValue($value);
$dbvalue = is_array($value) ? serialize($value) : $value;
$result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true); return DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true);
return $result;
} }
/** /**
@ -130,9 +125,7 @@ class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfig
$this->load($uid, $cat); $this->load($uid, $cat);
} }
$result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]); return DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
return $result;
} }
/** /**

View file

@ -6,8 +6,6 @@ namespace Friendica\Core\Config\Cache;
* The Friendica config cache for the application * The Friendica config cache for the application
* Initial, all *.config.php files are loaded into this cache with the * Initial, all *.config.php files are loaded into this cache with the
* ConfigCacheLoader ( @see ConfigCacheLoader ) * ConfigCacheLoader ( @see ConfigCacheLoader )
*
* Is used for further caching operations too (depending on the ConfigAdapter )
*/ */
class ConfigCache implements IConfigCache, IPConfigCache class ConfigCache implements IConfigCache, IPConfigCache
{ {
@ -37,7 +35,7 @@ class ConfigCache implements IConfigCache, IPConfigCache
foreach ($keys as $key) { foreach ($keys as $key) {
$value = $config[$category][$key]; $value = $config[$category][$key];
if (isset($value) && $value !== '!<unset>!') { if (isset($value)) {
if ($overwrite) { if ($overwrite) {
$this->set($category, $key, $value); $this->set($category, $key, $value);
} else { } else {
@ -56,22 +54,13 @@ class ConfigCache implements IConfigCache, IPConfigCache
{ {
if (isset($this->config[$cat][$key])) { if (isset($this->config[$cat][$key])) {
return $this->config[$cat][$key]; return $this->config[$cat][$key];
} elseif ($key == null && isset($this->config[$cat])) { } elseif (!isset($key) && isset($this->config[$cat])) {
return $this->config[$cat]; return $this->config[$cat];
} else { } else {
return '!<unset>!'; return null;
} }
} }
/**
* {@inheritdoc}
*/
public function has($cat, $key = null)
{
return (isset($this->config[$cat][$key]) && $this->config[$cat][$key] !== '!<unset>!') ||
($key == null && isset($this->config[$cat]) && $this->config[$cat] !== '!<unset>!' && is_array($this->config[$cat]));
}
/** /**
* Sets a default value in the config cache. Ignores already existing keys. * Sets a default value in the config cache. Ignores already existing keys.
* *
@ -91,9 +80,6 @@ class ConfigCache implements IConfigCache, IPConfigCache
*/ */
public function set($cat, $key, $value) 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 (!isset($this->config[$cat])) { if (!isset($this->config[$cat])) {
$this->config[$cat] = []; $this->config[$cat] = [];
} }
@ -103,15 +89,6 @@ class ConfigCache implements IConfigCache, IPConfigCache
return true; return true;
} }
/**
* {@inheritdoc}
*/
public function hasP($uid, $cat, $key = null)
{
return (isset($this->config[$uid][$cat][$key]) && $this->config[$uid][$cat][$key] !== '!<unset>!') ||
($key == null && isset($this->config[$uid][$cat]) && $this->config[$uid][$cat] !== '!<unset>!' && is_array($this->config[$uid][$cat]));
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -142,7 +119,7 @@ class ConfigCache implements IConfigCache, IPConfigCache
foreach ($keys as $key) { foreach ($keys as $key) {
$value = $config[$category][$key]; $value = $config[$category][$key];
if (isset($value) && $value !== '!<unset>!') { if (isset($value)) {
$this->setP($uid, $category, $key, $value); $this->setP($uid, $category, $key, $value);
} }
} }
@ -157,10 +134,10 @@ class ConfigCache implements IConfigCache, IPConfigCache
{ {
if (isset($this->config[$uid][$cat][$key])) { if (isset($this->config[$uid][$cat][$key])) {
return $this->config[$uid][$cat][$key]; return $this->config[$uid][$cat][$key];
} elseif ($key == null && isset($this->config[$uid][$cat])) { } elseif (!isset($key) && isset($this->config[$uid][$cat])) {
return $this->config[$uid][$cat]; return $this->config[$uid][$cat];
} else { } else {
return '!<unset>!'; return null;
} }
} }
@ -169,9 +146,6 @@ class ConfigCache implements IConfigCache, IPConfigCache
*/ */
public function setP($uid, $cat, $key, $value) 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])) { if (!isset($this->config[$uid]) || !is_array($this->config[$uid])) {
$this->config[$uid] = []; $this->config[$uid] = [];
} }

View file

@ -37,9 +37,6 @@ class ConfigCacheLoader
*/ */
public function loadConfigFiles(ConfigCache $config) public function loadConfigFiles(ConfigCache $config)
{ {
// Setting at least the basepath we know
$config->set('system', 'basepath', $this->baseDir);
$config->load($this->loadCoreConfig('defaults')); $config->load($this->loadCoreConfig('defaults'));
$config->load($this->loadCoreConfig('settings')); $config->load($this->loadCoreConfig('settings'));

View file

@ -20,9 +20,9 @@ interface IConfigCache
* Gets a value from the config cache. * Gets a value from the config cache.
* *
* @param string $cat Config category * @param string $cat Config category
* @param string $key Config key * @param string $key Config key
* *
* @return mixed Returns the value of the Config entry or '!<unset>!' if not set * @return null|mixed Returns the value of the Config entry or null if not set
*/ */
function get($cat, $key = null); function get($cat, $key = null);
@ -47,15 +47,6 @@ interface IConfigCache
*/ */
function delete($cat, $key); function delete($cat, $key);
/**
* Checks if a value is set in the config cache.
*
* @param string $cat Config category
* @param string $key Config key
* @return bool
*/
function has($cat, $key = null);
/** /**
* Returns the whole configuration cache * Returns the whole configuration cache
* *

View file

@ -23,7 +23,7 @@ interface IPConfigCache
* @param string $cat Config category * @param string $cat Config category
* @param string $key Config key * @param string $key Config key
* *
* @return string The value of the config entry or '!<unset>!' if not set * @return null|string The value of the config entry or null if not set
*/ */
function getP($uid, $cat, $key = null); function getP($uid, $cat, $key = null);
@ -50,17 +50,6 @@ interface IPConfigCache
*/ */
function deleteP($uid, $cat, $key); function deleteP($uid, $cat, $key);
/**
* Checks if a value is set in the user config cache.
*
* @param int $uid User Id
* @param string $cat Config category
* @param string $key Config key
* @return bool
*/
function hasP($uid, $cat, $key = null);
/** /**
* Returns the whole configuration cache * Returns the whole configuration cache
* *

View file

@ -83,20 +83,19 @@ class Configuration
if ($this->configAdapter->isConnected() && if ($this->configAdapter->isConnected() &&
(!$this->configAdapter->isLoaded($cat, $key) || (!$this->configAdapter->isLoaded($cat, $key) ||
$refresh)) { $refresh)) {
$dbvalue = $this->configAdapter->get($cat, $key); $dbvalue = $this->configAdapter->get($cat, $key);
if ($dbvalue !== '!<unset>!') { if (isset($dbvalue)) {
$this->configCache->set($cat, $key, $dbvalue); $this->configCache->set($cat, $key, $dbvalue);
return $dbvalue; return $dbvalue;
} }
} }
// use the config cache for return // use the config cache for return
if ($this->configCache->has($cat, $key)) { $result = $this->configCache->get($cat, $key);
return $this->configCache->get($cat, $key);
} else { return (isset($result)) ? $result : $default_value;
return $default_value;
}
} }
/** /**

View file

@ -77,18 +77,15 @@ class PConfiguration
$refresh)) { $refresh)) {
$dbValue = $this->configAdapter->get($uid, $cat, $key); $dbValue = $this->configAdapter->get($uid, $cat, $key);
if ($dbValue !== '!<unset>!') { if (isset($dbValue)) {
$this->configCache->setP($uid, $cat, $key, $dbValue); $this->configCache->setP($uid, $cat, $key, $dbValue);
return $dbValue; return $dbValue;
} }
} }
// use the config cache for return // use the config cache for return
if ($this->configCache->hasP($uid, $cat, $key)) { $result = $this->configCache->getP($uid, $cat, $key);
return $this->configCache->getP($uid, $cat, $key); return (isset($result)) ? $result : $default_value;
} else {
return $default_value;
}
} }
/** /**

View file

@ -65,8 +65,6 @@ class PConfig
/** /**
* @brief Sets a configuration value for a user * @brief Sets a configuration value for a user
* *
* @note Please do not store booleans - convert to 0/1 integer values!
*
* @param string $uid The user_id * @param string $uid The user_id
* @param string $cat The category of the configuration value * @param string $cat The category of the configuration value
* @param string $key The configuration key to set * @param string $key The configuration key to set

View file

@ -40,6 +40,10 @@ class DBA
* @var Profiler * @var Profiler
*/ */
private static $profiler; private static $profiler;
/**
* @var string
*/
private static $basedir;
private static $server_info = ''; private static $server_info = '';
private static $connection; private static $connection;
private static $driver; private static $driver;
@ -55,13 +59,14 @@ class DBA
private static $db_name = ''; private static $db_name = '';
private static $db_charset = ''; private static $db_charset = '';
public static function connect(IConfigCache $configCache, Profiler $profiler, $serveraddr, $user, $pass, $db, $charset = null) public static function connect($basedir, IConfigCache $configCache, Profiler $profiler, $serveraddr, $user, $pass, $db, $charset = null)
{ {
if (!is_null(self::$connection) && self::connected()) { if (!is_null(self::$connection) && self::connected()) {
return true; return true;
} }
// We are storing these values for being able to perform a reconnect // We are storing these values for being able to perform a reconnect
self::$basedir = $basedir;
self::$configCache = $configCache; self::$configCache = $configCache;
self::$profiler = $profiler; self::$profiler = $profiler;
self::$db_serveraddr = $serveraddr; self::$db_serveraddr = $serveraddr;
@ -1034,7 +1039,7 @@ class DBA
* This process must only be started once, since the value is cached. * This process must only be started once, since the value is cached.
*/ */
private static function buildRelationData() { private static function buildRelationData() {
$definition = DBStructure::definition(self::$configCache->get('system', 'basepath')); $definition = DBStructure::definition(self::$basedir);
foreach ($definition AS $table => $structure) { foreach ($definition AS $table => $structure) {
foreach ($structure['fields'] AS $field => $field_struct) { foreach ($structure['fields'] AS $field => $field_struct) {

View file

@ -11,13 +11,16 @@ class DBFactory
/** /**
* Initialize the DBA connection * Initialize the DBA connection
* *
* @param string $basePath The basepath of the application
* @param Cache\IConfigCache $configCache The configuration cache * @param Cache\IConfigCache $configCache The configuration cache
* @param Profiler $profiler The profiler * @param Profiler $profiler The profiler
* @param array $server The $_SERVER variables * @param array $server The $_SERVER variables
* *
* @throws \Exception if connection went bad * @throws \Exception if connection went bad
*
* @todo refactor basedir during https://github.com/friendica/friendica/issues/6720
*/ */
public static function init(Cache\IConfigCache $configCache, Profiler $profiler, array $server) public static function init($basePath, Cache\IConfigCache $configCache, Profiler $profiler, array $server)
{ {
if (Database\DBA::connected()) { if (Database\DBA::connected()) {
return; return;
@ -48,9 +51,9 @@ class DBFactory
$db_data = $server['MYSQL_DATABASE']; $db_data = $server['MYSQL_DATABASE'];
} }
if (Database\DBA::connect($configCache, $profiler, $db_host, $db_user, $db_pass, $db_data, $charset)) { if (Database\DBA::connect($basePath, $configCache, $profiler, $db_host, $db_user, $db_pass, $db_data, $charset)) {
// Loads DB_UPDATE_VERSION constant // Loads DB_UPDATE_VERSION constant
Database\DBStructure::definition($configCache->get('system', 'basepath'), false); Database\DBStructure::definition($basePath, false);
} }
unset($db_host, $db_user, $db_pass, $db_data, $charset); unset($db_host, $db_user, $db_pass, $db_data, $charset);

View file

@ -22,16 +22,16 @@ class DependencyFactory
*/ */
public static function setUp($channel, $directory, $isBackend = true) public static function setUp($channel, $directory, $isBackend = true)
{ {
$basedir = BasePath::create($directory, $_SERVER); $basePath = BasePath::create($directory, $_SERVER);
$configLoader = new Cache\ConfigCacheLoader($basedir); $configLoader = new Cache\ConfigCacheLoader($basePath);
$configCache = Factory\ConfigFactory::createCache($configLoader); $configCache = Factory\ConfigFactory::createCache($configLoader);
$profiler = Factory\ProfilerFactory::create($configCache); $profiler = Factory\ProfilerFactory::create($configCache);
Factory\DBFactory::init($configCache, $profiler, $_SERVER); Factory\DBFactory::init($basePath, $configCache, $profiler, $_SERVER);
$config = Factory\ConfigFactory::createConfig($configCache); $config = Factory\ConfigFactory::createConfig($configCache);
// needed to call PConfig::init() // needed to call PConfig::init()
Factory\ConfigFactory::createPConfig($configCache); Factory\ConfigFactory::createPConfig($configCache);
$logger = Factory\LoggerFactory::create($channel, $config); $logger = Factory\LoggerFactory::create($channel, $config);
return new App($config, $logger, $profiler, $isBackend); return new App($basePath, $config, $logger, $profiler, $isBackend);
} }
} }

View file

@ -10,8 +10,8 @@ use Friendica\BaseObject;
use Friendica\Core\Cache; use Friendica\Core\Cache;
use Friendica\Core\Config; use Friendica\Core\Config;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Core\StorageManager; use Friendica\Core\StorageManager;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\Database\DBStructure; use Friendica\Database\DBStructure;
use Friendica\Model\Storage\IStorage; use Friendica\Model\Storage\IStorage;
@ -203,7 +203,7 @@ class Photo extends BaseObject
*/ */
private static function getFields() private static function getFields()
{ {
$allfields = DBStructure::definition(false); $allfields = DBStructure::definition(self::getApp()->getBasePath(), false);
$fields = array_keys($allfields["photo"]["fields"]); $fields = array_keys($allfields["photo"]["fields"]);
array_splice($fields, array_search("data", $fields), 1); array_splice($fields, array_search("data", $fields), 1);
return $fields; return $fields;

View file

@ -47,6 +47,7 @@ abstract class DatabaseTest extends MockedTest
$profiler = \Mockery::mock(Profiler::class); $profiler = \Mockery::mock(Profiler::class);
DBA::connect( DBA::connect(
$basedir,
$config, $config,
$profiler, $profiler,
getenv('MYSQL_HOST'), getenv('MYSQL_HOST'),

View file

@ -36,15 +36,15 @@ class ApiTest extends DatabaseTest
*/ */
public function setUp() public function setUp()
{ {
$basedir = BasePath::create(dirname(__DIR__) . '/../'); $basePath = BasePath::create(dirname(__DIR__) . '/../');
$configLoader = new Cache\ConfigCacheLoader($basedir); $configLoader = new Cache\ConfigCacheLoader($basePath);
$configCache = Factory\ConfigFactory::createCache($configLoader); $configCache = Factory\ConfigFactory::createCache($configLoader);
$profiler = Factory\ProfilerFactory::create($configCache); $profiler = Factory\ProfilerFactory::create($configCache);
Factory\DBFactory::init($configCache, $profiler, $_SERVER); Factory\DBFactory::init($basePath, $configCache, $profiler, $_SERVER);
$config = Factory\ConfigFactory::createConfig($configCache); $config = Factory\ConfigFactory::createConfig($configCache);
Factory\ConfigFactory::createPConfig($configCache); Factory\ConfigFactory::createPConfig($configCache);
$logger = Factory\LoggerFactory::create('test', $config); $logger = Factory\LoggerFactory::create('test', $config);
$this->app = new App($config, $logger, $profiler, false); $this->app = new App($basePath, $config, $logger, $profiler, false);
parent::setUp(); parent::setUp();

View file

@ -19,19 +19,6 @@ class ConfigCacheLoaderTest extends MockedTest
$this->setUpVfsDir(); $this->setUpVfsDir();
} }
/**
* Test the loadConfigFiles() method with default values
*/
public function testLoadConfigFiles()
{
$configCacheLoader = new ConfigCacheLoader($this->root->url());
$configCache = new ConfigCache();
$configCacheLoader->loadConfigFiles($configCache);
$this->assertEquals($this->root->url(), $configCache->get('system', 'basepath'));
}
/** /**
* Test the loadConfigFiles() method with a wrong local.config.php * Test the loadConfigFiles() method with a wrong local.config.php
* @expectedException \Exception * @expectedException \Exception

View file

@ -138,22 +138,7 @@ class ConfigCacheTest extends MockedTest
{ {
$configCache = new ConfigCache(); $configCache = new ConfigCache();
$this->assertEquals('!<unset>!', $configCache->get('something', 'value')); $this->assertNull($configCache->get('something', 'value'));
}
/**
* Test the has() method
*/
public function testHas()
{
$configCache = new ConfigCache();
$this->assertFalse($configCache->has('system', 'test'));
$this->assertFalse($configCache->has('system'));
$configCache->set('system', 'test', 'it');
$this->assertTrue($configCache->has('system', 'test'));
$this->assertTrue($configCache->has('system'));
} }
/** /**
@ -171,8 +156,6 @@ class ConfigCacheTest extends MockedTest
], ],
]); ]);
$this->assertTrue($configCache->has('system'));
$this->assertEquals([ $this->assertEquals([
'key1' => 'value1', 'key1' => 'value1',
'key2' => 'value2', 'key2' => 'value2',
@ -233,8 +216,6 @@ class ConfigCacheTest extends MockedTest
], ],
]); ]);
$this->assertTrue($configCache->hasP($uid,'system'));
$this->assertEquals([ $this->assertEquals([
'key1' => 'value1', 'key1' => 'value1',
'key2' => 'value2', 'key2' => 'value2',
@ -264,20 +245,4 @@ class ConfigCacheTest extends MockedTest
$this->assertEmpty($configCache->getAll()); $this->assertEmpty($configCache->getAll());
} }
/**
* Test the hasP() method
*/
public function testHasP()
{
$configCache = new ConfigCache();
$uid = 345;
$this->assertFalse($configCache->hasP($uid, 'system', 'test'));
$this->assertFalse($configCache->hasP($uid, 'system'));
$configCache->setP($uid, 'system', 'test', 'it');
$this->assertTrue($configCache->hasP($uid, 'system', 'test'));
$this->assertTrue($configCache->hasP($uid, 'system'));
}
} }

View file

@ -142,7 +142,7 @@ class ConfigurationTest extends MockedTest
$this->assertNull($configuration->get('test', 'it')); $this->assertNull($configuration->get('test', 'it'));
/// beware that the cache returns '!<unset>!' and not null for a non existing value /// beware that the cache returns '!<unset>!' and not null for a non existing value
$this->assertEquals('!<unset>!', $configuration->getCache()->get('test', 'it')); $this->assertNull($configuration->getCache()->get('test', 'it'));
// with default value // with default value
$this->assertEquals('default', $configuration->get('test', 'it', 'default')); $this->assertEquals('default', $configuration->get('test', 'it', 'default'));
@ -165,7 +165,7 @@ class ConfigurationTest extends MockedTest
$configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(true)->twice(); $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(true)->twice();
$configAdapter->shouldReceive('get')->with('test', 'it')->andReturn($data)->once(); $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn($data)->once();
$configAdapter->shouldReceive('isLoaded')->with('test', 'not')->andReturn(false)->once(); $configAdapter->shouldReceive('isLoaded')->with('test', 'not')->andReturn(false)->once();
$configAdapter->shouldReceive('get')->with('test', 'not')->andReturn('!<unset>!')->once(); $configAdapter->shouldReceive('get')->with('test', 'not')->andReturn(null)->once();
$configuration = new Configuration($configCache, $configAdapter); $configuration = new Configuration($configCache, $configAdapter);
@ -179,7 +179,7 @@ class ConfigurationTest extends MockedTest
// without refresh and wrong value and default // without refresh and wrong value and default
$this->assertEquals('default', $configuration->get('test', 'not', 'default')); $this->assertEquals('default', $configuration->get('test', 'not', 'default'));
$this->assertEquals('!<unset>!', $configuration->getCache()->get('test', 'not')); $this->assertNull($configuration->getCache()->get('test', 'not'));
} }
/** /**
@ -195,7 +195,7 @@ class ConfigurationTest extends MockedTest
$configAdapter->shouldReceive('load')->andReturn([])->once(); $configAdapter->shouldReceive('load')->andReturn([])->once();
$configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(false)->once(); $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(false)->once();
$configAdapter->shouldReceive('get')->with('test', 'it')->andReturn('!<unset>!')->once(); $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn(null)->once();
$configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(false)->once(); $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(false)->once();
$configAdapter->shouldReceive('get')->with('test', 'it')->andReturn($data)->once(); $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn($data)->once();
@ -234,7 +234,7 @@ class ConfigurationTest extends MockedTest
$this->assertTrue($configuration->delete('test', 'it')); $this->assertTrue($configuration->delete('test', 'it'));
$this->assertNull($configuration->get('test', 'it')); $this->assertNull($configuration->get('test', 'it'));
$this->assertEquals('!<unset>!', $configuration->getCache()->get('test', 'it')); $this->assertNull($configuration->getCache()->get('test', 'it'));
$this->assertEmpty($configuration->getCache()->getAll()); $this->assertEmpty($configuration->getCache()->getAll());
} }

View file

@ -145,7 +145,7 @@ class PConfigurationTest extends MockedTest
$configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(true)->twice(); $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(true)->twice();
$configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn($data)->once(); $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn($data)->once();
$configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'not')->andReturn(false)->once(); $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'not')->andReturn(false)->once();
$configAdapter->shouldReceive('get')->with($uid, 'test', 'not')->andReturn('!<unset>!')->once(); $configAdapter->shouldReceive('get')->with($uid, 'test', 'not')->andReturn(null)->once();
$configuration = new PConfiguration($configCache, $configAdapter); $configuration = new PConfiguration($configCache, $configAdapter);
@ -173,7 +173,7 @@ class PConfigurationTest extends MockedTest
$configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3);
$configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(false)->once(); $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(false)->once();
$configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn('!<unset>!')->once(); $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn(null)->once();
$configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(false)->once(); $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(false)->once();
$configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn($data)->once(); $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn($data)->once();

View file

@ -13,15 +13,15 @@ class DBATest extends DatabaseTest
{ {
public function setUp() public function setUp()
{ {
$basedir = BasePath::create(dirname(__DIR__) . '/../../'); $basePath = BasePath::create(dirname(__DIR__) . '/../../');
$configLoader = new Cache\ConfigCacheLoader($basedir); $configLoader = new Cache\ConfigCacheLoader($basePath);
$configCache = Factory\ConfigFactory::createCache($configLoader); $configCache = Factory\ConfigFactory::createCache($configLoader);
$profiler = Factory\ProfilerFactory::create($configCache); $profiler = Factory\ProfilerFactory::create($configCache);
Factory\DBFactory::init($configCache, $profiler, $_SERVER); Factory\DBFactory::init($basePath, $configCache, $profiler, $_SERVER);
$config = Factory\ConfigFactory::createConfig($configCache); $config = Factory\ConfigFactory::createConfig($configCache);
Factory\ConfigFactory::createPConfig($configCache); Factory\ConfigFactory::createPConfig($configCache);
$logger = Factory\LoggerFactory::create('test', $config); $logger = Factory\LoggerFactory::create('test', $config);
$this->app = new App($config, $logger, $profiler, false); $this->app = new App($basePath, $config, $logger, $profiler, false);
parent::setUp(); parent::setUp();

View file

@ -13,15 +13,15 @@ class DBStructureTest extends DatabaseTest
{ {
public function setUp() public function setUp()
{ {
$basedir = BasePath::create(dirname(__DIR__) . '/../../'); $basePath = BasePath::create(dirname(__DIR__) . '/../../');
$configLoader = new Cache\ConfigCacheLoader($basedir); $configLoader = new Cache\ConfigCacheLoader($basePath);
$configCache = Factory\ConfigFactory::createCache($configLoader); $configCache = Factory\ConfigFactory::createCache($configLoader);
$profiler = Factory\ProfilerFactory::create($configCache); $profiler = Factory\ProfilerFactory::create($configCache);
Factory\DBFactory::init($configCache, $profiler, $_SERVER); Factory\DBFactory::init($basePath, $configCache, $profiler, $_SERVER);
$config = Factory\ConfigFactory::createConfig($configCache); $config = Factory\ConfigFactory::createConfig($configCache);
Factory\ConfigFactory::createPConfig($configCache); Factory\ConfigFactory::createPConfig($configCache);
$logger = Factory\LoggerFactory::create('test', $config); $logger = Factory\LoggerFactory::create('test', $config);
$this->app = new App($config, $logger, $profiler, false); $this->app = new App($basePath, $config, $logger, $profiler, false);
parent::setUp(); parent::setUp();
} }