From 5e6e1a80250a9b03a0689bbda92a6a66140cc669 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 16 Feb 2019 23:11:30 +0100 Subject: [PATCH 01/20] Introducing Profiler --- bin/auth_ejabberd.php | 3 +- bin/console.php | 3 +- bin/daemon.php | 3 +- bin/worker.php | 3 +- include/api.php | 64 +----- index.php | 3 +- src/App.php | 84 ++----- src/Content/Text/BBCode.php | 6 +- src/Content/Text/Markdown.php | 2 +- src/Core/Addon.php | 2 +- src/Core/Cache.php | 8 +- src/Core/Console/AutomaticInstallation.php | 2 +- src/Core/Installer.php | 6 +- src/Core/Logger.php | 20 +- src/Core/Renderer.php | 4 +- src/Core/Theme.php | 2 +- src/Core/Worker.php | 86 +------ src/Database/DBA.php | 22 +- src/Factory/ProfilerFactory.php | 25 ++ src/Module/Install.php | 4 +- src/Object/Image.php | 10 +- src/Util/Network.php | 14 +- src/Util/Profiler.php | 252 +++++++++++++++++++++ tests/DatabaseTest.php | 4 + 24 files changed, 370 insertions(+), 262 deletions(-) create mode 100644 src/Factory/ProfilerFactory.php create mode 100644 src/Util/Profiler.php diff --git a/bin/auth_ejabberd.php b/bin/auth_ejabberd.php index 11df43895..8a5c43c6d 100755 --- a/bin/auth_ejabberd.php +++ b/bin/auth_ejabberd.php @@ -58,8 +58,9 @@ $basedir = BasePath::create(dirname(__DIR__), $_SERVER); $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('auth_ejabberd', $config); +$profiler = Factory\ProfilerFactory::create($config); -$a = new App($config, $logger); +$a = new App($config, $logger, $profiler); if ($a->getMode()->isNormal()) { $oAuth = new ExAuth(); diff --git a/bin/console.php b/bin/console.php index 9061824d8..ceccfc823 100755 --- a/bin/console.php +++ b/bin/console.php @@ -11,8 +11,9 @@ $basedir = BasePath::create(dirname(__DIR__), $_SERVER); $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('console', $config); +$profiler = Factory\ProfilerFactory::create($config); -$a = new Friendica\App($config, $logger); +$a = new Friendica\App($config, $logger, $profiler); \Friendica\BaseObject::setApp($a); (new Friendica\Core\Console($argv))->execute(); diff --git a/bin/daemon.php b/bin/daemon.php index 5c014a927..3b5c04b7a 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -37,8 +37,9 @@ $basedir = BasePath::create(dirname(__DIR__), $_SERVER); $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('daemon', $config); +$profiler = Factory\ProfilerFactory::create($config); -$a = new App($config, $logger); +$a = new App($config, $logger, $profiler); if ($a->getMode()->isInstall()) { die("Friendica isn't properly installed yet.\n"); diff --git a/bin/worker.php b/bin/worker.php index 553e98497..c93abaf0f 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -35,8 +35,9 @@ $basedir = BasePath::create(dirname(__DIR__), $_SERVER); $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('worker', $config); +$profiler = Factory\ProfilerFactory::create($config); -$a = new App($config, $logger); +$a = new App($config, $logger, $profiler); // Check the database structure and possibly fixes it Update::check($a->getBasePath(), true); diff --git a/include/api.php b/include/api.php index 052d32b17..6bd08d01d 100644 --- a/include/api.php +++ b/include/api.php @@ -326,69 +326,7 @@ function api_call(App $a) Logger::info(API_LOG_PREFIX . 'username {username}', ['module' => 'api', 'action' => 'call', 'username' => $a->user['username'], 'duration' => round($duration, 2)]); - if (Config::get("system", "profiler")) { - $duration = microtime(true)-$a->performance["start"]; - - /// @TODO round() really everywhere? - Logger::debug( - API_LOG_PREFIX . 'performance', - [ - 'module' => 'api', - 'action' => 'call', - 'database_read' => round($a->performance["database"] - $a->performance["database_write"], 3), - 'database_write' => round($a->performance["database_write"], 3), - 'cache_read' => round($a->performance["cache"], 3), - 'cache_write' => round($a->performance["cache_write"], 3), - 'network_io' => round($a->performance["network"], 2), - 'file_io' => round($a->performance["file"], 2), - 'other_io' => round($duration - ($a->performance["database"] - + $a->performance["cache"] + $a->performance["cache_write"] - + $a->performance["network"] + $a->performance["file"]), 2), - 'total' => round($duration, 2) - ] - ); - - if (Config::get("rendertime", "callstack")) { - $o = "Database Read:\n"; - foreach ($a->callstack["database"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func . ": " . $time . "\n"; - } - } - $o .= "\nDatabase Write:\n"; - foreach ($a->callstack["database_write"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func . ": " . $time . "\n"; - } - } - - $o = "Cache Read:\n"; - foreach ($a->callstack["cache"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func . ": " . $time . "\n"; - } - } - $o .= "\nCache Write:\n"; - foreach ($a->callstack["cache_write"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func . ": " . $time . "\n"; - } - } - - $o .= "\nNetwork:\n"; - foreach ($a->callstack["network"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func . ": " . $time . "\n"; - } - } - Logger::debug(API_LOG_PREFIX . $o, ['module' => 'api', 'action' => 'call']); - } - } + $a->getProfiler()->saveLog(API_LOG_PREFIX . 'performance'); if (false === $return) { /* diff --git a/index.php b/index.php index 7e7396785..d8c233be2 100644 --- a/index.php +++ b/index.php @@ -19,9 +19,10 @@ $basedir = BasePath::create(__DIR__, $_SERVER); $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('index', $config); +$profiler = Factory\ProfilerFactory::create($config); // We assume that the index.php is called by a frontend process // The value is set to "true" by default in App -$a = new App($config, $logger, false); +$a = new App($config, $logger, $profiler, false); $a->runFrontend(); diff --git a/src/App.php b/src/App.php index 8068a1530..6e1f83fdd 100644 --- a/src/App.php +++ b/src/App.php @@ -13,6 +13,7 @@ use Friendica\Core\Config\ConfigCacheLoader; use Friendica\Database\DBA; use Friendica\Factory\ConfigFactory; use Friendica\Network\HTTPException\InternalServerErrorException; +use Friendica\Util\Profiler; use Psr\Log\LoggerInterface; /** @@ -53,8 +54,6 @@ class App public $identities; public $is_mobile = false; public $is_tablet = false; - public $performance = []; - public $callstack = []; public $theme_info = []; public $category; // Allow themes to control internal parameters @@ -119,6 +118,11 @@ class App */ private $config; + /** + * @var Profiler The profiler of this app + */ + private $profiler; + /** * Returns the current config cache of this node * @@ -139,6 +143,16 @@ class App return $this->basePath; } + /** + * The profiler of this app + * + * @return Profiler + */ + public function getProfiler() + { + return $this->profiler; + } + /** * Register a stylesheet file path to be included in the tag of every page. * Inclusion is done in App->initHead(). @@ -183,14 +197,16 @@ class App * * @param ConfigCache $config The Cached Config * @param LoggerInterface $logger Logger of this application + * @param Profiler $profiler The profiler of this application * @param bool $isBackend Whether it is used for backend or frontend (Default true=backend) * * @throws Exception if the Basepath is not usable */ - public function __construct(ConfigCache $config, LoggerInterface $logger, $isBackend = true) + public function __construct(ConfigCache $config, LoggerInterface $logger, Profiler $profiler, $isBackend = true) { $this->config = $config; $this->logger = $logger; + $this->profiler = $profiler; $this->basePath = $this->config->get('system', 'basepath'); if (!Core\System::isDirectoryUsable($this->basePath, false)) { @@ -203,26 +219,7 @@ class App $this->checkBackend($isBackend); $this->checkFriendicaApp(); - $this->performance['start'] = microtime(true); - $this->performance['database'] = 0; - $this->performance['database_write'] = 0; - $this->performance['cache'] = 0; - $this->performance['cache_write'] = 0; - $this->performance['network'] = 0; - $this->performance['file'] = 0; - $this->performance['rendering'] = 0; - $this->performance['parser'] = 0; - $this->performance['marktime'] = 0; - $this->performance['markstart'] = microtime(true); - - $this->callstack['database'] = []; - $this->callstack['database_write'] = []; - $this->callstack['cache'] = []; - $this->callstack['cache_write'] = []; - $this->callstack['network'] = []; - $this->callstack['file'] = []; - $this->callstack['rendering'] = []; - $this->callstack['parser'] = []; + $this->profiler->reset(); $this->mode = new App\Mode($this->basePath); @@ -489,14 +486,14 @@ class App $stamp1 = microtime(true); - if (DBA::connect($this->config, $db_host, $db_user, $db_pass, $db_data, $charset)) { + if (DBA::connect($this->config, $this->profiler, $db_host, $db_user, $db_pass, $db_data, $charset)) { // Loads DB_UPDATE_VERSION constant Database\DBStructure::definition($this->basePath, false); } unset($db_host, $db_user, $db_pass, $db_data, $charset); - $this->saveTimestamp($stamp1, 'network'); + $this->profiler->saveTimestamp($stamp1, 'network'); } public function getScheme() @@ -742,41 +739,6 @@ class App } } - /** - * Saves a timestamp for a value - f.e. a call - * Necessary for profiling Friendica - * - * @param int $timestamp the Timestamp - * @param string $value A value to profile - */ - public function saveTimestamp($timestamp, $value) - { - $profiler = $this->config->get('system', 'profiler'); - - if (!isset($profiler) || !$profiler) { - return; - } - - $duration = (float) (microtime(true) - $timestamp); - - if (!isset($this->performance[$value])) { - // Prevent ugly E_NOTICE - $this->performance[$value] = 0; - } - - $this->performance[$value] += (float) $duration; - $this->performance['marktime'] += (float) $duration; - - $callstack = Core\System::callstack(); - - if (!isset($this->callstack[$value][$callstack])) { - // Prevent ugly E_NOTICE - $this->callstack[$value][$callstack] = 0; - } - - $this->callstack[$value][$callstack] += (float) $duration; - } - /** * Returns the current UserAgent as a String * @@ -1227,7 +1189,7 @@ class App if (!$this->isBackend()) { $stamp1 = microtime(true); session_start(); - $this->saveTimestamp($stamp1, 'parser'); + $this->profiler->saveTimestamp($stamp1, 'parser'); Core\L10n::setSessionVariable(); Core\L10n::setLangFromSession(); } else { diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index a8b5ec202..75cb32b62 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -1027,7 +1027,7 @@ class BBCode extends BaseObject @curl_exec($ch); $curl_info = @curl_getinfo($ch); - $a->saveTimestamp($stamp1, "network"); + $a->getProfiler()->saveTimestamp($stamp1, "network"); if (substr($curl_info["content_type"], 0, 6) == "image/") { $text = "[url=" . $match[1] . "]" . $match[1] . "[/url]"; @@ -1086,7 +1086,7 @@ class BBCode extends BaseObject @curl_exec($ch); $curl_info = @curl_getinfo($ch); - $a->saveTimestamp($stamp1, "network"); + $a->getProfiler()->saveTimestamp($stamp1, "network"); // if its a link to a picture then embed this picture if (substr($curl_info["content_type"], 0, 6) == "image/") { @@ -1915,7 +1915,7 @@ class BBCode extends BaseObject // unmask the special chars back to HTML $text = str_replace(['&\_lt\_;', '&\_gt\_;', '&\_amp\_;'], ['<', '>', '&'], $text); - $a->saveTimestamp($stamp1, "parser"); + $a->getProfiler()->saveTimestamp($stamp1, "parser"); // Libertree has a problem with escaped hashtags. $text = str_replace(['\#'], ['#'], $text); diff --git a/src/Content/Text/Markdown.php b/src/Content/Text/Markdown.php index ceb5b043b..28ee215b2 100644 --- a/src/Content/Text/Markdown.php +++ b/src/Content/Text/Markdown.php @@ -36,7 +36,7 @@ class Markdown extends BaseObject $html = $MarkdownParser->transform($text); $html = preg_replace('/getProfiler()->saveTimestamp($stamp1, "parser"); return $html; } diff --git a/src/Core/Addon.php b/src/Core/Addon.php index 6697a44ae..483882c3e 100644 --- a/src/Core/Addon.php +++ b/src/Core/Addon.php @@ -219,7 +219,7 @@ class Addon extends BaseObject $stamp1 = microtime(true); $f = file_get_contents("addon/$addon/$addon.php"); - $a->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file"); $r = preg_match("|/\*.*\*/|msU", $f, $m); diff --git a/src/Core/Cache.php b/src/Core/Cache.php index 39c29566d..cd1581ef9 100644 --- a/src/Core/Cache.php +++ b/src/Core/Cache.php @@ -63,7 +63,7 @@ class Cache extends \Friendica\BaseObject $return = self::getDriver()->getAllKeys($prefix); - self::getApp()->saveTimestamp($time, 'cache'); + self::getApp()->getProfiler()->saveTimestamp($time, 'cache'); return $return; } @@ -82,7 +82,7 @@ class Cache extends \Friendica\BaseObject $return = self::getDriver()->get($key); - self::getApp()->saveTimestamp($time, 'cache'); + self::getApp()->getProfiler()->saveTimestamp($time, 'cache'); return $return; } @@ -105,7 +105,7 @@ class Cache extends \Friendica\BaseObject $return = self::getDriver()->set($key, $value, $duration); - self::getApp()->saveTimestamp($time, 'cache_write'); + self::getApp()->getProfiler()->saveTimestamp($time, 'cache_write'); return $return; } @@ -124,7 +124,7 @@ class Cache extends \Friendica\BaseObject $return = self::getDriver()->delete($key); - self::getApp()->saveTimestamp($time, 'cache_write'); + self::getApp()->getProfiler()->saveTimestamp($time, 'cache_write'); return $return; } diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index 7f2585e63..d5c63dd99 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -146,7 +146,7 @@ HELP; $installer->resetChecks(); - if (!$installer->checkDB($a->getConfig(), $db_host, $db_user, $db_pass, $db_data)) { + if (!$installer->checkDB($a->getConfig(), $a->getProfiler(), $db_host, $db_user, $db_pass, $db_data)) { $errorMessage = $this->extractErrors($installer->getChecks()); throw new RuntimeException($errorMessage); } diff --git a/src/Core/Installer.php b/src/Core/Installer.php index 4a287a885..dd9e3d22e 100644 --- a/src/Core/Installer.php +++ b/src/Core/Installer.php @@ -11,6 +11,7 @@ use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\Object\Image; use Friendica\Util\Network; +use Friendica\Util\Profiler; use Friendica\Util\Strings; /** @@ -583,6 +584,7 @@ class Installer * Checking the Database connection and if it is available for the current installation * * @param ConfigCache $configCache The configuration cache + * @param Profiler $profiler The profiler of this app * @param string $dbhost Hostname/IP of the Friendica Database * @param string $dbuser Username of the Database connection credentials * @param string $dbpass Password of the Database connection credentials @@ -591,9 +593,9 @@ class Installer * @return bool true if the check was successful, otherwise false * @throws Exception */ - public function checkDB(ConfigCache $configCache, $dbhost, $dbuser, $dbpass, $dbdata) + public function checkDB(ConfigCache $configCache, Profiler $profiler, $dbhost, $dbuser, $dbpass, $dbdata) { - if (!DBA::connect($configCache, $dbhost, $dbuser, $dbpass, $dbdata)) { + if (!DBA::connect($configCache, $profiler, $dbhost, $dbuser, $dbpass, $dbdata)) { $this->addCheck(L10n::t('Could not connect to database.'), false, true, ''); return false; diff --git a/src/Core/Logger.php b/src/Core/Logger.php index 6b8112796..69be501a3 100644 --- a/src/Core/Logger.php +++ b/src/Core/Logger.php @@ -155,7 +155,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->emergency($message, $context); - self::getApp()->saveTimestamp($stamp1, 'file'); + self::getApp()->GetProfiler()->saveTimestamp($stamp1, 'file'); } /** @@ -179,7 +179,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->alert($message, $context); - self::getApp()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); } /** @@ -202,7 +202,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->critical($message, $context); - self::getApp()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); } /** @@ -225,7 +225,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->error($message, $context); - self::getApp()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); } /** @@ -249,7 +249,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->warning($message, $context); - self::getApp()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); } /** @@ -270,7 +270,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->notice($message, $context); - self::getApp()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); } /** @@ -293,7 +293,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->info($message, $context); - self::getApp()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); } /** @@ -314,7 +314,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->debug($message, $context); - self::getApp()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); } /** @@ -334,7 +334,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->log($level, $msg); - self::getApp()->saveTimestamp($stamp1, "file"); + self::getApp()->getProfiler()->saveTimestamp($stamp1, "file"); } /** @@ -355,6 +355,6 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$devLogger->log($level, $msg); - self::getApp()->saveTimestamp($stamp1, "file"); + self::getApp()->getProfiler()->saveTimestamp($stamp1, "file"); } } diff --git a/src/Core/Renderer.php b/src/Core/Renderer.php index 67bc5e3ba..c032448c9 100644 --- a/src/Core/Renderer.php +++ b/src/Core/Renderer.php @@ -74,7 +74,7 @@ class Renderer extends BaseObject exit(); } - $a->saveTimestamp($stamp1, "rendering"); + $a->getProfiler()->saveTimestamp($stamp1, "rendering"); return $output; } @@ -101,7 +101,7 @@ class Renderer extends BaseObject exit(); } - $a->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file"); return $template; } diff --git a/src/Core/Theme.php b/src/Core/Theme.php index 62dfaa51f..dbfc0fd90 100644 --- a/src/Core/Theme.php +++ b/src/Core/Theme.php @@ -51,7 +51,7 @@ class Theme $a = \get_app(); $stamp1 = microtime(true); $theme_file = file_get_contents("view/theme/$theme/theme.php"); - $a->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file"); $result = preg_match("|/\*.*\*/|msU", $theme_file, $matches); diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 75d4e4874..dff60e9fa 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -380,20 +380,7 @@ class Worker // We use the callstack here to analyze the performance of executed worker entries. // For this reason the variables have to be initialized. - if (Config::get("system", "profiler")) { - $a->performance["start"] = microtime(true); - $a->performance["database"] = 0; - $a->performance["database_write"] = 0; - $a->performance["cache"] = 0; - $a->performance["cache_write"] = 0; - $a->performance["network"] = 0; - $a->performance["file"] = 0; - $a->performance["rendering"] = 0; - $a->performance["parser"] = 0; - $a->performance["marktime"] = 0; - $a->performance["markstart"] = microtime(true); - $a->callstack = []; - } + $a->getProfiler()->reset(); // For better logging create a new process id for every worker call // But preserve the old one for the worker @@ -452,76 +439,7 @@ class Worker Logger::log("Process ".$mypid." - Prio ".$queue["priority"]." - ID ".$queue["id"].": ".$funcname." - done in ".number_format($duration, 4)." seconds. Process PID: ".$new_process_id); - // Write down the performance values into the log - if (Config::get("system", "profiler")) { - $duration = microtime(true)-$a->performance["start"]; - - $o = ''; - if (Config::get("rendertime", "callstack")) { - if (isset($a->callstack["database"])) { - $o .= "\nDatabase Read:\n"; - foreach ($a->callstack["database"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func.": ".$time."\n"; - } - } - } - if (isset($a->callstack["database_write"])) { - $o .= "\nDatabase Write:\n"; - foreach ($a->callstack["database_write"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func.": ".$time."\n"; - } - } - } - if (isset($a->callstack["dache"])) { - $o .= "\nCache Read:\n"; - foreach ($a->callstack["dache"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func.": ".$time."\n"; - } - } - } - if (isset($a->callstack["dache_write"])) { - $o .= "\nCache Write:\n"; - foreach ($a->callstack["dache_write"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func.": ".$time."\n"; - } - } - } - if (isset($a->callstack["network"])) { - $o .= "\nNetwork:\n"; - foreach ($a->callstack["network"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func.": ".$time."\n"; - } - } - } - } - - Logger::log( - "ID ".$queue["id"].": ".$funcname.": ".sprintf( - "DB: %s/%s, Cache: %s/%s, Net: %s, I/O: %s, Other: %s, Total: %s".$o, - number_format($a->performance["database"] - $a->performance["database_write"], 2), - number_format($a->performance["database_write"], 2), - number_format($a->performance["cache"], 2), - number_format($a->performance["cache_write"], 2), - number_format($a->performance["network"], 2), - number_format($a->performance["file"], 2), - number_format($duration - ($a->performance["database"] - + $a->performance["cache"] + $a->performance["cache_write"] - + $a->performance["network"] + $a->performance["file"]), 2), - number_format($duration, 2) - ), - Logger::DEBUG - ); - } + $a->getProfiler()->saveLog("ID " . $queue["id"] . ": " . $funcname); $cooldown = Config::get("system", "worker_cooldown", 0); diff --git a/src/Database/DBA.php b/src/Database/DBA.php index d2a739e93..7c24ecfd3 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -6,6 +6,7 @@ use Friendica\Core\Config\IConfigCache; use Friendica\Core\Logger; use Friendica\Core\System; use Friendica\Util\DateTimeFormat; +use Friendica\Util\Profiler; use mysqli; use mysqli_result; use mysqli_stmt; @@ -35,6 +36,10 @@ class DBA * @var IConfigCache */ private static $configCache; + /** + * @var Profiler + */ + private static $profiler; private static $server_info = ''; private static $connection; private static $driver; @@ -50,7 +55,7 @@ class DBA private static $db_name = ''; private static $db_charset = ''; - public static function connect($configCache, $serveraddr, $user, $pass, $db, $charset = null) + public static function connect(IConfigCache $configCache, Profiler $profiler, $serveraddr, $user, $pass, $db, $charset = null) { if (!is_null(self::$connection) && self::connected()) { return true; @@ -58,6 +63,7 @@ class DBA // We are storing these values for being able to perform a reconnect self::$configCache = $configCache; + self::$profiler = $profiler; self::$db_serveraddr = $serveraddr; self::$db_user = $user; self::$db_pass = $pass; @@ -158,7 +164,7 @@ class DBA public static function reconnect() { self::disconnect(); - $ret = self::connect(self::$configCache, self::$db_serveraddr, self::$db_user, self::$db_pass, self::$db_name, self::$db_charset); + $ret = self::connect(self::$configCache, self::$profiler, self::$db_serveraddr, self::$db_user, self::$db_pass, self::$db_name, self::$db_charset); return $ret; } @@ -392,7 +398,6 @@ class DBA * @throws \Exception */ public static function p($sql) { - $a = \get_app(); $stamp1 = microtime(true); @@ -582,7 +587,7 @@ class DBA self::$errorno = $errorno; } - $a->saveTimestamp($stamp1, 'database'); + self::$profiler->saveTimestamp($stamp1, 'database'); if (self::$configCache->get('system', 'db_log')) { $stamp2 = microtime(true); @@ -611,7 +616,6 @@ class DBA * @throws \Exception */ public static function e($sql) { - $a = \get_app(); $stamp = microtime(true); @@ -654,7 +658,7 @@ class DBA self::$errorno = $errorno; } - $a->saveTimestamp($stamp, "database_write"); + self::$profiler->saveTimestamp($stamp, "database_write"); return $retval; } @@ -777,7 +781,6 @@ class DBA * @return array current row */ public static function fetch($stmt) { - $a = \get_app(); $stamp1 = microtime(true); @@ -824,7 +827,7 @@ class DBA } } - $a->saveTimestamp($stamp1, 'database'); + self::$profiler->saveTimestamp($stamp1, 'database'); return $columns; } @@ -1534,7 +1537,6 @@ class DBA * @return boolean was the close successful? */ public static function close($stmt) { - $a = \get_app(); $stamp1 = microtime(true); @@ -1562,7 +1564,7 @@ class DBA break; } - $a->saveTimestamp($stamp1, 'database'); + self::$profiler->saveTimestamp($stamp1, 'database'); return $ret; } diff --git a/src/Factory/ProfilerFactory.php b/src/Factory/ProfilerFactory.php new file mode 100644 index 000000000..7a63c7440 --- /dev/null +++ b/src/Factory/ProfilerFactory.php @@ -0,0 +1,25 @@ +get('system', 'profiler', false); + $renderTime = $configCache->get('rendertime', 'callstack', false); + return new Profiler($logger, $enabled, $renderTime); + } +} diff --git a/src/Module/Install.php b/src/Module/Install.php index 6948dee6e..4fb4a932c 100644 --- a/src/Module/Install.php +++ b/src/Module/Install.php @@ -75,7 +75,7 @@ class Install extends BaseModule $dbdata = Strings::escapeTags(trim(defaults($_POST, 'dbdata', ''))); // If we cannot connect to the database, return to the previous step - if (!self::$installer->checkDB($a->getConfig(), $dbhost, $dbuser, $dbpass, $dbdata)) { + if (!self::$installer->checkDB($a->getConfig(), $a->getProfiler(), $dbhost, $dbuser, $dbpass, $dbdata)) { self::$currentWizardStep = self::DATABASE_CONFIG; } @@ -92,7 +92,7 @@ class Install extends BaseModule $adminmail = Strings::escapeTags(trim(defaults($_POST, 'adminmail', ''))); // If we cannot connect to the database, return to the Database config wizard - if (!self::$installer->checkDB($a->getConfig(), $dbhost, $dbuser, $dbpass, $dbdata)) { + if (!self::$installer->checkDB($a->getConfig(), $a->getProfiler(), $dbhost, $dbuser, $dbpass, $dbdata)) { self::$currentWizardStep = self::DATABASE_CONFIG; return; } diff --git a/src/Object/Image.php b/src/Object/Image.php index 9143c23c1..c43955375 100644 --- a/src/Object/Image.php +++ b/src/Object/Image.php @@ -5,6 +5,7 @@ */ namespace Friendica\Object; +use Exception; use Friendica\App; use Friendica\Core\Cache; use Friendica\Core\Config; @@ -14,7 +15,6 @@ use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model\Photo; use Friendica\Util\Network; -use Exception; use Imagick; use ImagickPixel; @@ -656,7 +656,7 @@ class Image $stamp1 = microtime(true); file_put_contents($path, $string); - $a->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file"); } /** @@ -802,7 +802,7 @@ class Image $a = \get_app(); $stamp1 = microtime(true); file_put_contents($tempfile, $img_str); - $a->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file"); $data = getimagesize($tempfile); unlink($tempfile); @@ -910,7 +910,7 @@ class Image $stamp1 = microtime(true); $imagedata = @file_get_contents($url); - $a->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file"); } $maximagesize = Config::get('system', 'maximagesize'); @@ -924,7 +924,7 @@ class Image $stamp1 = microtime(true); file_put_contents($tempfile, $imagedata); - $a->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file"); $data = getimagesize($tempfile); diff --git a/src/Util/Network.php b/src/Util/Network.php index de4b45da9..4d5afa3a3 100644 --- a/src/Util/Network.php +++ b/src/Util/Network.php @@ -4,13 +4,13 @@ */ namespace Friendica\Util; +use DOMDocument; +use DomXPath; +use Friendica\Core\Config; use Friendica\Core\Hook; use Friendica\Core\Logger; use Friendica\Core\System; -use Friendica\Core\Config; use Friendica\Network\CurlResult; -use DOMDocument; -use DomXPath; class Network { @@ -232,7 +232,7 @@ class Network @curl_close($ch); - $a->saveTimestamp($stamp1, 'network'); + $a->getProfiler()->saveTimestamp($stamp1, 'network'); return $curlResponse; } @@ -334,7 +334,7 @@ class Network curl_close($ch); - $a->saveTimestamp($stamp1, 'network'); + $a->getProfiler()->saveTimestamp($stamp1, 'network'); Logger::log('post_url: end ' . $url, Logger::DATA); @@ -641,7 +641,7 @@ class Network $http_code = $curl_info['http_code']; curl_close($ch); - $a->saveTimestamp($stamp1, "network"); + $a->getProfiler()->saveTimestamp($stamp1, "network"); if ($http_code == 0) { return $url; @@ -683,7 +683,7 @@ class Network $body = curl_exec($ch); curl_close($ch); - $a->saveTimestamp($stamp1, "network"); + $a->getProfiler()->saveTimestamp($stamp1, "network"); if (trim($body) == "") { return $url; diff --git a/src/Util/Profiler.php b/src/Util/Profiler.php new file mode 100644 index 000000000..7bf30a277 --- /dev/null +++ b/src/Util/Profiler.php @@ -0,0 +1,252 @@ +enabled = $enabled; + $this->rendertime = $renderTime; + $this->logger = $logger; + $this->performance = []; + $this->callstack = []; + } + + /** + * Saves a timestamp for a value - f.e. a call + * Necessary for profiling Friendica + * + * @param int $timestamp the Timestamp + * @param string $value A value to profile + */ + public function saveTimestamp($timestamp, $value) + { + if (!$this->enabled) { + return; + } + + $duration = (float) (microtime(true) - $timestamp); + + if (!isset($this->performance[$value])) { + // Prevent ugly E_NOTICE + $this->performance[$value] = 0; + } + + $this->performance[$value] += (float) $duration; + $this->performance['marktime'] += (float) $duration; + + $callstack = Core\System::callstack(); + + if (!isset($this->callstack[$value][$callstack])) { + // Prevent ugly E_NOTICE + $this->callstack[$value][$callstack] = 0; + } + + $this->callstack[$value][$callstack] += (float) $duration; + } + + /** + * Resets the performance and callstack profiling + * + * @param bool $performance If true, reset the performance (Default true) + * @param bool $callstack If true, reset the callstack (Default true) + */ + public function reset($performance = true, $callstack = true) + { + if ($performance) { + $this->performance = []; + $this->performance['start'] = microtime(true); + $this->performance['database'] = 0; + $this->performance['database_write'] = 0; + $this->performance['cache'] = 0; + $this->performance['cache_write'] = 0; + $this->performance['network'] = 0; + $this->performance['file'] = 0; + $this->performance['rendering'] = 0; + $this->performance['parser'] = 0; + $this->performance['marktime'] = 0; + $this->performance['markstart'] = microtime(true); + } + + if ($callstack) { + $this->callstack['database'] = []; + $this->callstack['database_write'] = []; + $this->callstack['cache'] = []; + $this->callstack['cache_write'] = []; + $this->callstack['network'] = []; + $this->callstack['file'] = []; + $this->callstack['rendering'] = []; + $this->callstack['parser'] = []; + } + } + + /** + * Save the current profiling data to a log entry + * + * @param string $message Additional message for the log + */ + public function saveLog($message) + { + // Write down the performance values into the log + if ($this->enabled) { + $duration = microtime(true)-$this->get('start'); + $this->logger->info( + $message, + [ + 'module' => 'api', + 'action' => 'call', + 'database_read' => round($this->get('database') - $this->get('database_write'), 3), + 'database_write' => round($this->get('database_write'), 3), + 'cache_read' => round($this->get('cache'), 3), + 'cache_write' => round($this->get('cache_write'), 3), + 'network_io' => round($this->get('network'), 2), + 'file_io' => round($this->get('file'), 2), + 'other_io' => round($duration - ($this->get('database') + + $this->get('cache') + $this->get('cache_write') + + $this->get('network') + $this->get('file')), 2), + 'total' => round($duration, 2) + ] + ); + + $o = ''; + if ($this->rendertime) { + if (isset($this->callstack["database"])) { + $o .= "\nDatabase Read:\n"; + foreach ($this->callstack["database"] as $func => $time) { + $time = round($time, 3); + if ($time > 0) { + $o .= $func.": ".$time."\n"; + } + } + } + if (isset($this->callstack["database_write"])) { + $o .= "\nDatabase Write:\n"; + foreach ($this->callstack["database_write"] as $func => $time) { + $time = round($time, 3); + if ($time > 0) { + $o .= $func.": ".$time."\n"; + } + } + } + if (isset($this->callstack["dache"])) { + $o .= "\nCache Read:\n"; + foreach ($this->callstack["dache"] as $func => $time) { + $time = round($time, 3); + if ($time > 0) { + $o .= $func.": ".$time."\n"; + } + } + } + if (isset($this->callstack["dache_write"])) { + $o .= "\nCache Write:\n"; + foreach ($this->callstack["dache_write"] as $func => $time) { + $time = round($time, 3); + if ($time > 0) { + $o .= $func.": ".$time."\n"; + } + } + } + if (isset($this->callstack["network"])) { + $o .= "\nNetwork:\n"; + foreach ($this->callstack["network"] as $func => $time) { + $time = round($time, 3); + if ($time > 0) { + $o .= $func.": ".$time."\n"; + } + } + } + } + + $this->logger->info( + $message . ": " . sprintf( + "DB: %s/%s, Cache: %s/%s, Net: %s, I/O: %s, Other: %s, Total: %s".$o, + number_format($this->get('database') - $this->get('database_write'), 2), + number_format($this->get('database_write'), 2), + number_format($this->get('cache'), 2), + number_format($this->get('cache_write'), 2), + number_format($this->get('network'), 2), + number_format($this->get('file'), 2), + number_format($duration - ($this->get('database') + + $this->get('cache') + $this->get('cache_write') + + $this->get('network') + $this->get('file')), 2), + number_format($duration, 2) + ) + ); + } + } + + /** + * Finds an entry of the container by its identifier and returns it. + * + * @param string $id Identifier of the entry to look for. + * + * @throws NotFoundExceptionInterface No entry was found for **this** identifier. + * @throws ContainerExceptionInterface Error while retrieving the entry. + * + * @return int Entry. + */ + public function get($id) + { + if (!$this->has($id)) { + return 0; + } else { + return $this->performance[$id]; + } + } + + /** + * Returns true if the container can return an entry for the given identifier. + * Returns false otherwise. + * + * `has($id)` returning true does not mean that `get($id)` will not throw an exception. + * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`. + * + * @param string $id Identifier of the entry to look for. + * + * @return bool + */ + public function has($id) + { + return isset($this->performance[$id]); + } +} diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php index 79af5b546..5c66711dc 100644 --- a/tests/DatabaseTest.php +++ b/tests/DatabaseTest.php @@ -9,6 +9,7 @@ use Friendica\Core\Config; use Friendica\Database\DBA; use Friendica\Factory; use Friendica\Util\BasePath; +use Friendica\Util\Profiler; use PHPUnit\DbUnit\DataSet\YamlDataSet; use PHPUnit\DbUnit\TestCaseTrait; use PHPUnit_Extensions_Database_DB_IDatabaseConnection; @@ -43,8 +44,11 @@ abstract class DatabaseTest extends MockedTest $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); + $profiler = \Mockery::mock(Profiler::class); + DBA::connect( $config, + $profiler, getenv('MYSQL_HOST'), getenv('MYSQL_USERNAME'), getenv('MYSQL_PASSWORD'), From 0a7861da652b0ea30ec4827c69cb5b98072c1a60 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 16 Feb 2019 23:17:10 +0100 Subject: [PATCH 02/20] Dependency of callstack moved one layer up --- src/App.php | 4 ++-- src/Content/Text/BBCode.php | 6 +++--- src/Content/Text/Markdown.php | 3 ++- src/Core/Addon.php | 2 +- src/Core/Cache.php | 8 ++++---- src/Core/Logger.php | 20 ++++++++++---------- src/Core/Renderer.php | 4 ++-- src/Core/Theme.php | 2 +- src/Database/DBA.php | 8 ++++---- src/Object/Image.php | 8 ++++---- src/Util/Network.php | 8 ++++---- src/Util/Profiler.php | 6 ++---- 12 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/App.php b/src/App.php index 6e1f83fdd..e61b8dbae 100644 --- a/src/App.php +++ b/src/App.php @@ -493,7 +493,7 @@ class App unset($db_host, $db_user, $db_pass, $db_data, $charset); - $this->profiler->saveTimestamp($stamp1, 'network'); + $this->profiler->saveTimestamp($stamp1, 'network', Core\System::callstack()); } public function getScheme() @@ -1189,7 +1189,7 @@ class App if (!$this->isBackend()) { $stamp1 = microtime(true); session_start(); - $this->profiler->saveTimestamp($stamp1, 'parser'); + $this->profiler->saveTimestamp($stamp1, 'parser', Core\System::callstack()); Core\L10n::setSessionVariable(); Core\L10n::setLangFromSession(); } else { diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 75cb32b62..e9b5f98d0 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -1027,7 +1027,7 @@ class BBCode extends BaseObject @curl_exec($ch); $curl_info = @curl_getinfo($ch); - $a->getProfiler()->saveTimestamp($stamp1, "network"); + $a->getProfiler()->saveTimestamp($stamp1, "network", System::callstack()); if (substr($curl_info["content_type"], 0, 6) == "image/") { $text = "[url=" . $match[1] . "]" . $match[1] . "[/url]"; @@ -1086,7 +1086,7 @@ class BBCode extends BaseObject @curl_exec($ch); $curl_info = @curl_getinfo($ch); - $a->getProfiler()->saveTimestamp($stamp1, "network"); + $a->getProfiler()->saveTimestamp($stamp1, "network", System::callstack()); // if its a link to a picture then embed this picture if (substr($curl_info["content_type"], 0, 6) == "image/") { @@ -1915,7 +1915,7 @@ class BBCode extends BaseObject // unmask the special chars back to HTML $text = str_replace(['&\_lt\_;', '&\_gt\_;', '&\_amp\_;'], ['<', '>', '&'], $text); - $a->getProfiler()->saveTimestamp($stamp1, "parser"); + $a->getProfiler()->saveTimestamp($stamp1, "parser", System::callstack()); // Libertree has a problem with escaped hashtags. $text = str_replace(['\#'], ['#'], $text); diff --git a/src/Content/Text/Markdown.php b/src/Content/Text/Markdown.php index 28ee215b2..e3e2cd3ac 100644 --- a/src/Content/Text/Markdown.php +++ b/src/Content/Text/Markdown.php @@ -7,6 +7,7 @@ namespace Friendica\Content\Text; use Friendica\BaseObject; +use Friendica\Core\System; use Friendica\Model\Contact; use Michelf\MarkdownExtra; @@ -36,7 +37,7 @@ class Markdown extends BaseObject $html = $MarkdownParser->transform($text); $html = preg_replace('/getProfiler()->saveTimestamp($stamp1, "parser", System::callstack()); return $html; } diff --git a/src/Core/Addon.php b/src/Core/Addon.php index 483882c3e..7957e0835 100644 --- a/src/Core/Addon.php +++ b/src/Core/Addon.php @@ -219,7 +219,7 @@ class Addon extends BaseObject $stamp1 = microtime(true); $f = file_get_contents("addon/$addon/$addon.php"); - $a->getProfiler()->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); $r = preg_match("|/\*.*\*/|msU", $f, $m); diff --git a/src/Core/Cache.php b/src/Core/Cache.php index cd1581ef9..cadb2444b 100644 --- a/src/Core/Cache.php +++ b/src/Core/Cache.php @@ -63,7 +63,7 @@ class Cache extends \Friendica\BaseObject $return = self::getDriver()->getAllKeys($prefix); - self::getApp()->getProfiler()->saveTimestamp($time, 'cache'); + self::getApp()->getProfiler()->saveTimestamp($time, 'cache', System::callstack()); return $return; } @@ -82,7 +82,7 @@ class Cache extends \Friendica\BaseObject $return = self::getDriver()->get($key); - self::getApp()->getProfiler()->saveTimestamp($time, 'cache'); + self::getApp()->getProfiler()->saveTimestamp($time, 'cache', System::callstack()); return $return; } @@ -105,7 +105,7 @@ class Cache extends \Friendica\BaseObject $return = self::getDriver()->set($key, $value, $duration); - self::getApp()->getProfiler()->saveTimestamp($time, 'cache_write'); + self::getApp()->getProfiler()->saveTimestamp($time, 'cache_write', System::callstack()); return $return; } @@ -124,7 +124,7 @@ class Cache extends \Friendica\BaseObject $return = self::getDriver()->delete($key); - self::getApp()->getProfiler()->saveTimestamp($time, 'cache_write'); + self::getApp()->getProfiler()->saveTimestamp($time, 'cache_write', System::callstack()); return $return; } diff --git a/src/Core/Logger.php b/src/Core/Logger.php index 69be501a3..0712c91b1 100644 --- a/src/Core/Logger.php +++ b/src/Core/Logger.php @@ -155,7 +155,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->emergency($message, $context); - self::getApp()->GetProfiler()->saveTimestamp($stamp1, 'file'); + self::getApp()->GetProfiler()->saveTimestamp($stamp1, 'file', System::callstack()); } /** @@ -179,7 +179,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->alert($message, $context); - self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file', System::callstack()); } /** @@ -202,7 +202,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->critical($message, $context); - self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file', System::callstack()); } /** @@ -225,7 +225,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->error($message, $context); - self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file', System::callstack()); } /** @@ -249,7 +249,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->warning($message, $context); - self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file', System::callstack()); } /** @@ -270,7 +270,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->notice($message, $context); - self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file', System::callstack()); } /** @@ -293,7 +293,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->info($message, $context); - self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file', System::callstack()); } /** @@ -314,7 +314,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->debug($message, $context); - self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file'); + self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file', System::callstack()); } /** @@ -334,7 +334,7 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$logger->log($level, $msg); - self::getApp()->getProfiler()->saveTimestamp($stamp1, "file"); + self::getApp()->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); } /** @@ -355,6 +355,6 @@ class Logger extends BaseObject $stamp1 = microtime(true); self::$devLogger->log($level, $msg); - self::getApp()->getProfiler()->saveTimestamp($stamp1, "file"); + self::getApp()->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); } } diff --git a/src/Core/Renderer.php b/src/Core/Renderer.php index c032448c9..8844f2688 100644 --- a/src/Core/Renderer.php +++ b/src/Core/Renderer.php @@ -74,7 +74,7 @@ class Renderer extends BaseObject exit(); } - $a->getProfiler()->saveTimestamp($stamp1, "rendering"); + $a->getProfiler()->saveTimestamp($stamp1, "rendering", System::callstack()); return $output; } @@ -101,7 +101,7 @@ class Renderer extends BaseObject exit(); } - $a->getProfiler()->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); return $template; } diff --git a/src/Core/Theme.php b/src/Core/Theme.php index dbfc0fd90..5479f8f46 100644 --- a/src/Core/Theme.php +++ b/src/Core/Theme.php @@ -51,7 +51,7 @@ class Theme $a = \get_app(); $stamp1 = microtime(true); $theme_file = file_get_contents("view/theme/$theme/theme.php"); - $a->getProfiler()->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); $result = preg_match("|/\*.*\*/|msU", $theme_file, $matches); diff --git a/src/Database/DBA.php b/src/Database/DBA.php index 7c24ecfd3..edef30901 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -587,7 +587,7 @@ class DBA self::$errorno = $errorno; } - self::$profiler->saveTimestamp($stamp1, 'database'); + self::$profiler->saveTimestamp($stamp1, 'database', System::callstack()); if (self::$configCache->get('system', 'db_log')) { $stamp2 = microtime(true); @@ -658,7 +658,7 @@ class DBA self::$errorno = $errorno; } - self::$profiler->saveTimestamp($stamp, "database_write"); + self::$profiler->saveTimestamp($stamp, "database_write", System::callstack()); return $retval; } @@ -827,7 +827,7 @@ class DBA } } - self::$profiler->saveTimestamp($stamp1, 'database'); + self::$profiler->saveTimestamp($stamp1, 'database', System::callstack()); return $columns; } @@ -1564,7 +1564,7 @@ class DBA break; } - self::$profiler->saveTimestamp($stamp1, 'database'); + self::$profiler->saveTimestamp($stamp1, 'database', System::callstack()); return $ret; } diff --git a/src/Object/Image.php b/src/Object/Image.php index c43955375..45c8bedea 100644 --- a/src/Object/Image.php +++ b/src/Object/Image.php @@ -656,7 +656,7 @@ class Image $stamp1 = microtime(true); file_put_contents($path, $string); - $a->getProfiler()->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); } /** @@ -802,7 +802,7 @@ class Image $a = \get_app(); $stamp1 = microtime(true); file_put_contents($tempfile, $img_str); - $a->getProfiler()->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); $data = getimagesize($tempfile); unlink($tempfile); @@ -910,7 +910,7 @@ class Image $stamp1 = microtime(true); $imagedata = @file_get_contents($url); - $a->getProfiler()->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); } $maximagesize = Config::get('system', 'maximagesize'); @@ -924,7 +924,7 @@ class Image $stamp1 = microtime(true); file_put_contents($tempfile, $imagedata); - $a->getProfiler()->saveTimestamp($stamp1, "file"); + $a->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); $data = getimagesize($tempfile); diff --git a/src/Util/Network.php b/src/Util/Network.php index 4d5afa3a3..cda8c9a71 100644 --- a/src/Util/Network.php +++ b/src/Util/Network.php @@ -232,7 +232,7 @@ class Network @curl_close($ch); - $a->getProfiler()->saveTimestamp($stamp1, 'network'); + $a->getProfiler()->saveTimestamp($stamp1, 'network', System::callstack()); return $curlResponse; } @@ -334,7 +334,7 @@ class Network curl_close($ch); - $a->getProfiler()->saveTimestamp($stamp1, 'network'); + $a->getProfiler()->saveTimestamp($stamp1, 'network', System::callstack()); Logger::log('post_url: end ' . $url, Logger::DATA); @@ -641,7 +641,7 @@ class Network $http_code = $curl_info['http_code']; curl_close($ch); - $a->getProfiler()->saveTimestamp($stamp1, "network"); + $a->getProfiler()->saveTimestamp($stamp1, "network", System::callstack()); if ($http_code == 0) { return $url; @@ -683,7 +683,7 @@ class Network $body = curl_exec($ch); curl_close($ch); - $a->getProfiler()->saveTimestamp($stamp1, "network"); + $a->getProfiler()->saveTimestamp($stamp1, "network", System::callstack()); if (trim($body) == "") { return $url; diff --git a/src/Util/Profiler.php b/src/Util/Profiler.php index 7bf30a277..f65bede15 100644 --- a/src/Util/Profiler.php +++ b/src/Util/Profiler.php @@ -2,7 +2,6 @@ namespace Friendica\Util; -use Friendica\Core; use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; @@ -58,8 +57,9 @@ class Profiler implements ContainerInterface * * @param int $timestamp the Timestamp * @param string $value A value to profile + * @param string $callstack The callstack of the current profiling data */ - public function saveTimestamp($timestamp, $value) + public function saveTimestamp($timestamp, $value, $callstack = '') { if (!$this->enabled) { return; @@ -75,8 +75,6 @@ class Profiler implements ContainerInterface $this->performance[$value] += (float) $duration; $this->performance['marktime'] += (float) $duration; - $callstack = Core\System::callstack(); - if (!isset($this->callstack[$value][$callstack])) { // Prevent ugly E_NOTICE $this->callstack[$value][$callstack] = 0; From cb1ad4287d114ef3c712aa2d163a7f80e9bd48f1 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 16 Feb 2019 23:18:24 +0100 Subject: [PATCH 03/20] adding parameter to App --- bin/auth_ejabberd.php | 2 +- bin/console.php | 2 +- bin/daemon.php | 2 +- bin/worker.php | 2 +- index.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/auth_ejabberd.php b/bin/auth_ejabberd.php index 8a5c43c6d..cc2517644 100755 --- a/bin/auth_ejabberd.php +++ b/bin/auth_ejabberd.php @@ -58,7 +58,7 @@ $basedir = BasePath::create(dirname(__DIR__), $_SERVER); $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('auth_ejabberd', $config); -$profiler = Factory\ProfilerFactory::create($config); +$profiler = Factory\ProfilerFactory::create($logger, $config); $a = new App($config, $logger, $profiler); diff --git a/bin/console.php b/bin/console.php index ceccfc823..757af31d5 100755 --- a/bin/console.php +++ b/bin/console.php @@ -11,7 +11,7 @@ $basedir = BasePath::create(dirname(__DIR__), $_SERVER); $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('console', $config); -$profiler = Factory\ProfilerFactory::create($config); +$profiler = Factory\ProfilerFactory::create($logger, $config); $a = new Friendica\App($config, $logger, $profiler); \Friendica\BaseObject::setApp($a); diff --git a/bin/daemon.php b/bin/daemon.php index 3b5c04b7a..da4bc1992 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -37,7 +37,7 @@ $basedir = BasePath::create(dirname(__DIR__), $_SERVER); $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('daemon', $config); -$profiler = Factory\ProfilerFactory::create($config); +$profiler = Factory\ProfilerFactory::create($logger, $config); $a = new App($config, $logger, $profiler); diff --git a/bin/worker.php b/bin/worker.php index c93abaf0f..9b396c6f9 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -35,7 +35,7 @@ $basedir = BasePath::create(dirname(__DIR__), $_SERVER); $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('worker', $config); -$profiler = Factory\ProfilerFactory::create($config); +$profiler = Factory\ProfilerFactory::create($logger, $config); $a = new App($config, $logger, $profiler); diff --git a/index.php b/index.php index d8c233be2..216fbe90a 100644 --- a/index.php +++ b/index.php @@ -19,7 +19,7 @@ $basedir = BasePath::create(__DIR__, $_SERVER); $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('index', $config); -$profiler = Factory\ProfilerFactory::create($config); +$profiler = Factory\ProfilerFactory::create($logger, $config); // We assume that the index.php is called by a frontend process // The value is set to "true" by default in App From 68c904bbf4977283b7083f411064bcf4b315a124 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 16 Feb 2019 23:19:54 +0100 Subject: [PATCH 04/20] adding parameter to App --- tests/include/ApiTest.php | 3 ++- tests/src/Database/DBATest.php | 3 ++- tests/src/Database/DBStructureTest.php | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/include/ApiTest.php b/tests/include/ApiTest.php index be70d923b..41f5c0fdf 100644 --- a/tests/include/ApiTest.php +++ b/tests/include/ApiTest.php @@ -39,7 +39,8 @@ class ApiTest extends DatabaseTest $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('test', $config); - $this->app = new App($config, $logger, false); + $profiler = Factory\ProfilerFactory::create($logger, $config); + $this->app = new App($config, $logger, $profiler, false); $this->logOutput = FActory\LoggerFactory::enableTest($this->app->getLogger()); parent::setUp(); diff --git a/tests/src/Database/DBATest.php b/tests/src/Database/DBATest.php index f2a5cc555..c6981a91d 100644 --- a/tests/src/Database/DBATest.php +++ b/tests/src/Database/DBATest.php @@ -16,7 +16,8 @@ class DBATest extends DatabaseTest $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('test', $config); - $this->app = new App($config, $logger, false); + $profiler = Factory\ProfilerFactory::create($logger, $config); + $this->app = new App($config, $logger, $profiler, false); $this->logOutput = FActory\LoggerFactory::enableTest($this->app->getLogger()); parent::setUp(); diff --git a/tests/src/Database/DBStructureTest.php b/tests/src/Database/DBStructureTest.php index bc50a0a69..250df0693 100644 --- a/tests/src/Database/DBStructureTest.php +++ b/tests/src/Database/DBStructureTest.php @@ -17,7 +17,8 @@ class DBStructureTest extends DatabaseTest $configLoader = new Config\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $logger = Factory\LoggerFactory::create('test', $config); - $this->app = new App($config, $logger, false); + $profiler = Factory\ProfilerFactory::create($logger, $config); + $this->app = new App($config, $logger, $profiler, false); $this->logOutput = FActory\LoggerFactory::enableTest($this->app->getLogger()); parent::setUp(); From 6d73dcbe3d12dea1bed0e0bc3827b39d0e98aea7 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 17 Feb 2019 00:03:38 +0100 Subject: [PATCH 05/20] Adding composer & tests --- composer.json | 9 +- composer.lock | 52 ++++++++- src/Util/Profiler.php | 31 ++---- tests/src/Util/ProfilerTest.php | 181 ++++++++++++++++++++++++++++++++ 4 files changed, 245 insertions(+), 28 deletions(-) create mode 100644 tests/src/Util/ProfilerTest.php diff --git a/composer.json b/composer.json index 39d935892..c3d5d4570 100644 --- a/composer.json +++ b/composer.json @@ -35,12 +35,12 @@ "michelf/php-markdown": "^1.7", "mobiledetect/mobiledetectlib": "2.8.*", "paragonie/random_compat": "^2.0", - "pear/Text_LanguageDetect": "1.*", + "pear/text_languageDetect": "1.*", "seld/cli-prompt": "^1.0", "smarty/smarty": "^3.1", "fxp/composer-asset-plugin": "~1.3", "bower-asset/base64": "^1.0", - "bower-asset/Chart-js": "^2.7", + "bower-asset/chart-js": "^2.7", "bower-asset/perfect-scrollbar": "^0.6", "bower-asset/vue": "^2.5", "npm-asset/jquery": "^2.0", @@ -50,7 +50,8 @@ "npm-asset/fullcalendar": "^3.0.1", "npm-asset/cropperjs": "1.2.2", "npm-asset/imagesloaded": "4.1.4", - "monolog/monolog": "^1.24" + "monolog/monolog": "^1.24", + "psr/container": "^1.0" }, "repositories": [ { @@ -96,7 +97,7 @@ "phpunit/dbunit": "^2.0", "phpdocumentor/reflection-docblock": "^3.0.2", "phpunit/php-token-stream": "^1.4.2", - "mikey179/vfsStream": "^1.6", + "mikey179/vfsstream": "^1.6", "mockery/mockery": "^1.2", "johnkary/phpunit-speedtrap": "1.1" }, diff --git a/composer.lock b/composer.lock index f91b833de..e554b1199 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b944adfb6ede89430ba3b7e9ebb45acb", + "content-hash": "19fabb14e0dd5d806ef841e51d5f6a0b", "packages": [ { "name": "asika/simple-console", @@ -1882,6 +1882,55 @@ ], "time": "2016-08-06T20:24:11+00:00" }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, { "name": "psr/http-message", "version": "1.0.1", @@ -2650,6 +2699,7 @@ "testing", "xunit" ], + "abandoned": true, "time": "2016-12-02T14:39:14+00:00" }, { diff --git a/src/Util/Profiler.php b/src/Util/Profiler.php index f65bede15..e2d070075 100644 --- a/src/Util/Profiler.php +++ b/src/Util/Profiler.php @@ -47,8 +47,7 @@ class Profiler implements ContainerInterface $this->enabled = $enabled; $this->rendertime = $renderTime; $this->logger = $logger; - $this->performance = []; - $this->callstack = []; + $this->reset(); } /** @@ -103,7 +102,7 @@ class Profiler implements ContainerInterface $this->performance['rendering'] = 0; $this->performance['parser'] = 0; $this->performance['marktime'] = 0; - $this->performance['markstart'] = microtime(true); + $this->performance['marktime'] = microtime(true); } if ($callstack) { @@ -123,7 +122,7 @@ class Profiler implements ContainerInterface * * @param string $message Additional message for the log */ - public function saveLog($message) + public function saveLog($message = '') { // Write down the performance values into the log if ($this->enabled) { @@ -166,18 +165,18 @@ class Profiler implements ContainerInterface } } } - if (isset($this->callstack["dache"])) { + if (isset($this->callstack["cache"])) { $o .= "\nCache Read:\n"; - foreach ($this->callstack["dache"] as $func => $time) { + foreach ($this->callstack["cache"] as $func => $time) { $time = round($time, 3); if ($time > 0) { $o .= $func.": ".$time."\n"; } } } - if (isset($this->callstack["dache_write"])) { + if (isset($this->callstack["cache_write"])) { $o .= "\nCache Write:\n"; - foreach ($this->callstack["dache_write"] as $func => $time) { + foreach ($this->callstack["cache_write"] as $func => $time) { $time = round($time, 3); if ($time > 0) { $o .= $func.": ".$time."\n"; @@ -193,23 +192,9 @@ class Profiler implements ContainerInterface } } } + $this->logger->info($message . ": " . $o); } - $this->logger->info( - $message . ": " . sprintf( - "DB: %s/%s, Cache: %s/%s, Net: %s, I/O: %s, Other: %s, Total: %s".$o, - number_format($this->get('database') - $this->get('database_write'), 2), - number_format($this->get('database_write'), 2), - number_format($this->get('cache'), 2), - number_format($this->get('cache_write'), 2), - number_format($this->get('network'), 2), - number_format($this->get('file'), 2), - number_format($duration - ($this->get('database') - + $this->get('cache') + $this->get('cache_write') - + $this->get('network') + $this->get('file')), 2), - number_format($duration, 2) - ) - ); } } diff --git a/tests/src/Util/ProfilerTest.php b/tests/src/Util/ProfilerTest.php new file mode 100644 index 000000000..f9febeae8 --- /dev/null +++ b/tests/src/Util/ProfilerTest.php @@ -0,0 +1,181 @@ +logger = \Mockery::mock('Psr\Log\LoggerInterface'); + } + + /** + * Test the Profiler setup + */ + public function testSetUp() + { + $profiler = new Profiler($this->logger, true, true); + } + + /** + * A dataset for different profiling settings + * @return array + */ + public function dataPerformance() + { + return [ + 'database' => [ + 'timestamp' => time(), + 'name' => 'database', + 'functions' => ['test', 'it'], + ], + 'database_write' => [ + 'timestamp' => time(), + 'name' => 'database_write', + 'functions' => ['test', 'it2'], + ], + 'cache' => [ + 'timestamp' => time(), + 'name' => 'cache', + 'functions' => ['test', 'it3'], + ], + 'cache_write' => [ + 'timestamp' => time(), + 'name' => 'cache_write', + 'functions' => ['test', 'it4'], + ], + 'network' => [ + 'timestamp' => time(), + 'name' => 'network', + 'functions' => ['test', 'it5'], + ], + 'file' => [ + 'timestamp' => time(), + 'name' => 'file', + 'functions' => [], + ], + 'rendering' => [ + 'timestamp' => time(), + 'name' => 'rendering', + 'functions' => ['test', 'it7'], + ], + 'parser' => [ + 'timestamp' => time(), + 'name' => 'parser', + 'functions' => ['test', 'it8'], + ], + 'marktime' => [ + 'timestamp' => time(), + 'name' => 'parser', + 'functions' => ['test'], + ], + // This one isn't set during reset + 'unknown' => [ + 'timestamp' => time(), + 'name' => 'unknown', + 'functions' => ['test'], + ], + ]; + } + + /** + * Test the Profiler savetimestamp + * @dataProvider dataPerformance + */ + public function testSaveTimestamp($timestamp, $name, array $functions) + { + $profiler = new Profiler($this->logger, true, true); + + foreach ($functions as $function) { + $profiler->saveTimestamp($timestamp, $name, $function); + } + + $this->assertGreaterThanOrEqual(0, $profiler->get($name)); + } + + /** + * Test the Profiler reset + * @dataProvider dataPerformance + */ + public function testReset($timestamp, $name, array $functions) + { + $profiler = new Profiler($this->logger, true, true); + + $profiler->saveTimestamp($timestamp, $name); + $profiler->reset(); + + $this->assertEquals(0, $profiler->get($name)); + } + + public function dataBig() + { + return [ + 'big' => [ + 'data' => [ + 'database' => [ + 'timestamp' => time(), + 'name' => 'database', + 'functions' => ['test', 'it'], + ], + 'database_write' => [ + 'timestamp' => time(), + 'name' => 'database_write', + 'functions' => ['test', 'it2'], + ], + 'cache' => [ + 'timestamp' => time(), + 'name' => 'cache', + 'functions' => ['test', 'it3'], + ], + 'cache_write' => [ + 'timestamp' => time(), + 'name' => 'cache_write', + 'functions' => ['test', 'it4'], + ], + 'network' => [ + 'timestamp' => time(), + 'name' => 'network', + 'functions' => ['test', 'it5'], + ], + ] + ] + ]; + } + + /** + * Test the output of the Profiler + * @dataProvider dataBig + */ + public function testSaveLog($data) + { + $this->logger + ->shouldReceive('info') + ->with('test', \Mockery::any()) + ->once(); + $this->logger + ->shouldReceive('info') + ->once(); + + $profiler = new Profiler($this->logger, true, true); + + foreach ($data as $perf => $items) { + foreach ($items['functions'] as $function) { + $profiler->saveTimestamp($items['timestamp'], $items['name'], $function); + } + } + + $profiler->saveLog('test'); + } +} From 88fd8718447ebf09ab3e8ac1701ceeb67718a8a0 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 17 Feb 2019 01:18:21 +0100 Subject: [PATCH 06/20] refactoring & test fixing --- composer.json | 6 +- src/Core/Logger.php | 2 +- src/Util/Profiler.php | 199 ++++++++++++++----------- tests/src/Core/Console/ConsoleTest.php | 6 +- 4 files changed, 118 insertions(+), 95 deletions(-) diff --git a/composer.json b/composer.json index c3d5d4570..78abd98e7 100644 --- a/composer.json +++ b/composer.json @@ -34,8 +34,10 @@ "lightopenid/lightopenid": "dev-master", "michelf/php-markdown": "^1.7", "mobiledetect/mobiledetectlib": "2.8.*", + "monolog/monolog": "^1.24", "paragonie/random_compat": "^2.0", "pear/text_languageDetect": "1.*", + "psr/container": "^1.0", "seld/cli-prompt": "^1.0", "smarty/smarty": "^3.1", "fxp/composer-asset-plugin": "~1.3", @@ -49,9 +51,7 @@ "npm-asset/jgrowl": "^1.4", "npm-asset/fullcalendar": "^3.0.1", "npm-asset/cropperjs": "1.2.2", - "npm-asset/imagesloaded": "4.1.4", - "monolog/monolog": "^1.24", - "psr/container": "^1.0" + "npm-asset/imagesloaded": "4.1.4" }, "repositories": [ { diff --git a/src/Core/Logger.php b/src/Core/Logger.php index 0712c91b1..d2b9e21ee 100644 --- a/src/Core/Logger.php +++ b/src/Core/Logger.php @@ -354,7 +354,7 @@ class Logger extends BaseObject } $stamp1 = microtime(true); - self::$devLogger->log($level, $msg); + self::$devLogger->log($level, $msg); self::getApp()->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); } } diff --git a/src/Util/Profiler.php b/src/Util/Profiler.php index e2d070075..5bad5eb6a 100644 --- a/src/Util/Profiler.php +++ b/src/Util/Profiler.php @@ -91,32 +91,49 @@ class Profiler implements ContainerInterface public function reset($performance = true, $callstack = true) { if ($performance) { - $this->performance = []; - $this->performance['start'] = microtime(true); - $this->performance['database'] = 0; - $this->performance['database_write'] = 0; - $this->performance['cache'] = 0; - $this->performance['cache_write'] = 0; - $this->performance['network'] = 0; - $this->performance['file'] = 0; - $this->performance['rendering'] = 0; - $this->performance['parser'] = 0; - $this->performance['marktime'] = 0; - $this->performance['marktime'] = microtime(true); + $this->resetPerformance(); } if ($callstack) { - $this->callstack['database'] = []; - $this->callstack['database_write'] = []; - $this->callstack['cache'] = []; - $this->callstack['cache_write'] = []; - $this->callstack['network'] = []; - $this->callstack['file'] = []; - $this->callstack['rendering'] = []; - $this->callstack['parser'] = []; + $this->resetCallstack(); } } + /** + * Resets the performance profiling data + */ + public function resetPerformance() + { + $this->performance = []; + $this->performance['start'] = microtime(true); + $this->performance['database'] = 0; + $this->performance['database_write'] = 0; + $this->performance['cache'] = 0; + $this->performance['cache_write'] = 0; + $this->performance['network'] = 0; + $this->performance['file'] = 0; + $this->performance['rendering'] = 0; + $this->performance['parser'] = 0; + $this->performance['marktime'] = 0; + $this->performance['marktime'] = microtime(true); + } + + /** + * Resets the callstack profiling data + */ + public function resetCallstack() + { + $this->callstack = []; + $this->callstack['database'] = []; + $this->callstack['database_write'] = []; + $this->callstack['cache'] = []; + $this->callstack['cache_write'] = []; + $this->callstack['network'] = []; + $this->callstack['file'] = []; + $this->callstack['rendering'] = []; + $this->callstack['parser'] = []; + } + /** * Save the current profiling data to a log entry * @@ -125,77 +142,79 @@ class Profiler implements ContainerInterface public function saveLog($message = '') { // Write down the performance values into the log - if ($this->enabled) { - $duration = microtime(true)-$this->get('start'); - $this->logger->info( - $message, - [ - 'module' => 'api', - 'action' => 'call', - 'database_read' => round($this->get('database') - $this->get('database_write'), 3), - 'database_write' => round($this->get('database_write'), 3), - 'cache_read' => round($this->get('cache'), 3), - 'cache_write' => round($this->get('cache_write'), 3), - 'network_io' => round($this->get('network'), 2), - 'file_io' => round($this->get('file'), 2), - 'other_io' => round($duration - ($this->get('database') - + $this->get('cache') + $this->get('cache_write') - + $this->get('network') + $this->get('file')), 2), - 'total' => round($duration, 2) - ] - ); - - $o = ''; - if ($this->rendertime) { - if (isset($this->callstack["database"])) { - $o .= "\nDatabase Read:\n"; - foreach ($this->callstack["database"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func.": ".$time."\n"; - } - } - } - if (isset($this->callstack["database_write"])) { - $o .= "\nDatabase Write:\n"; - foreach ($this->callstack["database_write"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func.": ".$time."\n"; - } - } - } - if (isset($this->callstack["cache"])) { - $o .= "\nCache Read:\n"; - foreach ($this->callstack["cache"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func.": ".$time."\n"; - } - } - } - if (isset($this->callstack["cache_write"])) { - $o .= "\nCache Write:\n"; - foreach ($this->callstack["cache_write"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func.": ".$time."\n"; - } - } - } - if (isset($this->callstack["network"])) { - $o .= "\nNetwork:\n"; - foreach ($this->callstack["network"] as $func => $time) { - $time = round($time, 3); - if ($time > 0) { - $o .= $func.": ".$time."\n"; - } - } - } - $this->logger->info($message . ": " . $o); - } - + if (!$this->enabled) { + return; } + $duration = microtime(true) - $this->get('start'); + $this->logger->info( + $message, + [ + 'module' => 'api', + 'action' => 'call', + 'database_read' => round($this->get('database') - $this->get('database_write'), 3), + 'database_write' => round($this->get('database_write'), 3), + 'cache_read' => round($this->get('cache'), 3), + 'cache_write' => round($this->get('cache_write'), 3), + 'network_io' => round($this->get('network'), 2), + 'file_io' => round($this->get('file'), 2), + 'other_io' => round($duration - ($this->get('database') + + $this->get('cache') + $this->get('cache_write') + + $this->get('network') + $this->get('file')), 2), + 'total' => round($duration, 2) + ] + ); + + if (!$this->rendertime) { + return; + } + + $o = ''; + if (isset($this->callstack["database"])) { + $o .= "\nDatabase Read:\n"; + foreach ($this->callstack["database"] as $func => $time) { + $time = round($time, 3); + if ($time > 0) { + $o .= $func . ": " . $time . "\n"; + } + } + } + if (isset($this->callstack["database_write"])) { + $o .= "\nDatabase Write:\n"; + foreach ($this->callstack["database_write"] as $func => $time) { + $time = round($time, 3); + if ($time > 0) { + $o .= $func . ": " . $time . "\n"; + } + } + } + if (isset($this->callstack["cache"])) { + $o .= "\nCache Read:\n"; + foreach ($this->callstack["cache"] as $func => $time) { + $time = round($time, 3); + if ($time > 0) { + $o .= $func . ": " . $time . "\n"; + } + } + } + if (isset($this->callstack["cache_write"])) { + $o .= "\nCache Write:\n"; + foreach ($this->callstack["cache_write"] as $func => $time) { + $time = round($time, 3); + if ($time > 0) { + $o .= $func . ": " . $time . "\n"; + } + } + } + if (isset($this->callstack["network"])) { + $o .= "\nNetwork:\n"; + foreach ($this->callstack["network"] as $func => $time) { + $time = round($time, 3); + if ($time > 0) { + $o .= $func . ": " . $time . "\n"; + } + } + } + $this->logger->info($message . ": " . $o); } /** diff --git a/tests/src/Core/Console/ConsoleTest.php b/tests/src/Core/Console/ConsoleTest.php index 905d214ca..715e68ab2 100644 --- a/tests/src/Core/Console/ConsoleTest.php +++ b/tests/src/Core/Console/ConsoleTest.php @@ -3,10 +3,12 @@ namespace Friendica\Test\src\Core\Console; use Asika\SimpleConsole\Console; +use Friendica\Core\Config\ConfigCache; use Friendica\Test\MockedTest; use Friendica\Test\Util\AppMockTrait; use Friendica\Test\Util\Intercept; use Friendica\Test\Util\VFSTrait; +use Friendica\Util\Profiler; abstract class ConsoleTest extends MockedTest { @@ -29,8 +31,10 @@ abstract class ConsoleTest extends MockedTest Intercept::setUp(); $this->setUpVfsDir(); - $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $configMock = \Mockery::mock(ConfigCache::class); $this->mockApp($this->root, $configMock); + $profileMock = \Mockery::mock(Profiler::class); + $this->app->shouldReceive('getProfiler')->andReturn($profileMock); } /** From a3b9a8fe6146fd845f47b9eaf430fc8efcfc0c60 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 17 Feb 2019 01:56:46 +0100 Subject: [PATCH 07/20] Excluding Profiler from Loglines (better using the class above) --- src/Factory/LoggerFactory.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Factory/LoggerFactory.php b/src/Factory/LoggerFactory.php index 751a6357d..f6e2d6039 100644 --- a/src/Factory/LoggerFactory.php +++ b/src/Factory/LoggerFactory.php @@ -3,9 +3,11 @@ namespace Friendica\Factory; use Friendica\Core\Config\ConfigCache; +use Friendica\Core\Logger; use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Util\Logger\FriendicaDevelopHandler; use Friendica\Util\Logger\FriendicaIntrospectionProcessor; +use Friendica\Util\Profiler; use Monolog; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; @@ -31,7 +33,7 @@ class LoggerFactory $logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor()); $logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor()); $logger->pushProcessor(new Monolog\Processor\UidProcessor()); - $logger->pushProcessor(new FriendicaIntrospectionProcessor(LogLevel::DEBUG, ['Friendica\\Core\\Logger'])); + $logger->pushProcessor(new FriendicaIntrospectionProcessor(LogLevel::DEBUG, [Logger::class, Profiler::class])); if (isset($config)) { $debugging = $config->get('system', 'debugging'); From 3d077745099c51ca7dad306925a10cb2a8ad5a8d Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 17 Feb 2019 01:57:59 +0100 Subject: [PATCH 08/20] removed wrong log-output --- src/Util/Profiler.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Util/Profiler.php b/src/Util/Profiler.php index 5bad5eb6a..9d04a6498 100644 --- a/src/Util/Profiler.php +++ b/src/Util/Profiler.php @@ -149,8 +149,7 @@ class Profiler implements ContainerInterface $this->logger->info( $message, [ - 'module' => 'api', - 'action' => 'call', + 'action' => 'profiling', 'database_read' => round($this->get('database') - $this->get('database_write'), 3), 'database_write' => round($this->get('database_write'), 3), 'cache_read' => round($this->get('cache'), 3), @@ -214,7 +213,7 @@ class Profiler implements ContainerInterface } } } - $this->logger->info($message . ": " . $o); + $this->logger->info($message . ": " . $o, ['action' => 'profiling']); } /** From d87a6e5a670be0e7d30d26d2ff05365e8d71fc73 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 17 Feb 2019 02:09:39 +0100 Subject: [PATCH 09/20] fixed line intends --- src/Core/Logger.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Core/Logger.php b/src/Core/Logger.php index d2b9e21ee..e42f2f033 100644 --- a/src/Core/Logger.php +++ b/src/Core/Logger.php @@ -317,25 +317,25 @@ class Logger extends BaseObject self::getApp()->getProfiler()->saveTimestamp($stamp1, 'file', System::callstack()); } - /** - * @brief Logs the given message at the given log level - * - * @param string $msg - * @param string $level + /** + * @brief Logs the given message at the given log level + * + * @param string $msg + * @param string $level * * @throws \Exception * @deprecated since 2019.03 Use Logger::debug() Logger::info() , ... instead - */ - public static function log($msg, $level = LogLevel::INFO) - { + */ + public static function log($msg, $level = LogLevel::INFO) + { if (!isset(self::$logger)) { return; } - $stamp1 = microtime(true); + $stamp1 = microtime(true); self::$logger->log($level, $msg); self::getApp()->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); - } + } /** * @brief An alternative logger for development. @@ -347,14 +347,14 @@ class Logger extends BaseObject * @param string $level * @throws \Exception */ - public static function devLog($msg, $level = LogLevel::DEBUG) - { + public static function devLog($msg, $level = LogLevel::DEBUG) + { if (!isset(self::$logger)) { return; } - $stamp1 = microtime(true); + $stamp1 = microtime(true); self::$devLogger->log($level, $msg); self::getApp()->getProfiler()->saveTimestamp($stamp1, "file", System::callstack()); - } + } } From a043848904bebf94127a0efae7e90f8661e9e90b Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 17 Feb 2019 02:12:19 +0100 Subject: [PATCH 10/20] fixed last uppercase composer entry --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 78abd98e7..3638a9495 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "mobiledetect/mobiledetectlib": "2.8.*", "monolog/monolog": "^1.24", "paragonie/random_compat": "^2.0", - "pear/text_languageDetect": "1.*", + "pear/text_languagedetect": "1.*", "psr/container": "^1.0", "seld/cli-prompt": "^1.0", "smarty/smarty": "^3.1", From c36a0eabdb87afc553039e54e0a3e15ac3a77642 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 17 Feb 2019 10:34:48 +0100 Subject: [PATCH 11/20] fixing reset() --- src/Util/Profiler.php | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/Util/Profiler.php b/src/Util/Profiler.php index 9d04a6498..a3f889380 100644 --- a/src/Util/Profiler.php +++ b/src/Util/Profiler.php @@ -84,19 +84,11 @@ class Profiler implements ContainerInterface /** * Resets the performance and callstack profiling - * - * @param bool $performance If true, reset the performance (Default true) - * @param bool $callstack If true, reset the callstack (Default true) */ - public function reset($performance = true, $callstack = true) + public function reset() { - if ($performance) { - $this->resetPerformance(); - } - - if ($callstack) { - $this->resetCallstack(); - } + $this->resetPerformance(); + $this->resetCallstack(); } /** From eafcf3592db02392770cdc88bed9ddb000cb44f2 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 10 Feb 2019 19:52:21 +0100 Subject: [PATCH 12/20] Config FollowUp - New Configuration (Config is now only holding the instance) - New PConfiguration (PConfig is now only holding the instance) - Config & PConfig-Adapter don't need "ConfigCache" anymore - DB-Connection is now outside App->reload() for better dependency-chaining --- bin/auth_ejabberd.php | 9 +- bin/console.php | 9 +- bin/daemon.php | 10 +- bin/worker.php | 8 +- index.php | 9 +- src/App.php | 72 +----- src/Core/Config.php | 80 ++----- .../AbstractDbaConfigAdapter.php | 9 +- .../Config/{ => Adapter}/IConfigAdapter.php | 22 +- .../Config/{ => Adapter}/IPConfigAdapter.php | 29 ++- src/Core/Config/Adapter/JITConfigAdapter.php | 123 ++++++++++ src/Core/Config/Adapter/JITPConfigAdapter.php | 126 ++++++++++ .../Config/Adapter/PreloadConfigAdapter.php | 104 +++++++++ .../Config/Adapter/PreloadPConfigAdapter.php | 126 ++++++++++ src/Core/Config/{ => Cache}/ConfigCache.php | 132 ++++++----- .../Config/{ => Cache}/ConfigCacheLoader.php | 12 +- src/Core/Config/Cache/IConfigCache.php | 65 ++++++ src/Core/Config/Cache/IPConfigCache.php | 70 ++++++ src/Core/Config/Configuration.php | 154 +++++++++++++ src/Core/Config/IConfigCache.php | 39 ---- src/Core/Config/IPConfigCache.php | 44 ---- src/Core/Config/JITConfigAdapter.php | 172 -------------- src/Core/Config/JITPConfigAdapter.php | 136 ----------- src/Core/Config/PConfiguration.php | 150 ++++++++++++ src/Core/Config/PreloadConfigAdapter.php | 123 ---------- src/Core/Config/PreloadPConfigAdapter.php | 125 ---------- src/Core/Console/AutomaticInstallation.php | 10 +- src/Core/Console/Config.php | 6 +- src/Core/Console/Typo.php | 2 +- src/Core/Installer.php | 6 +- src/Core/PConfig.php | 89 ++------ src/Database/DBA.php | 2 +- src/Factory/ConfigFactory.php | 53 +++-- src/Factory/DBFactory.php | 48 ++++ src/Factory/LoggerFactory.php | 8 +- src/Module/Install.php | 4 +- tests/DatabaseTest.php | 4 +- tests/Util/AppMockTrait.php | 19 +- tests/include/ApiTest.php | 8 +- tests/src/App/ModeTest.php | 18 +- tests/src/BaseObjectTest.php | 2 +- tests/src/Core/Cache/CacheTest.php | 2 +- .../Core/Cache/MemcacheCacheDriverTest.php | 4 +- .../Core/Cache/MemcachedCacheDriverTest.php | 2 +- tests/src/Core/Cache/RedisCacheDriverTest.php | 4 +- .../{ => Cache}/ConfigCacheLoaderTest.php | 10 +- .../Config/{ => Cache}/ConfigCacheTest.php | 83 ++++++- tests/src/Core/Config/ConfigurationTest.php | 215 ++++++++++++++++++ tests/src/Core/Config/PConfigurationTest.php | 186 +++++++++++++++ .../AutomaticInstallationConsoleTest.php | 2 +- tests/src/Core/Console/ConfigConsoleTest.php | 12 +- tests/src/Core/Console/ConsoleTest.php | 4 +- tests/src/Core/Lock/LockTest.php | 2 +- .../Core/Lock/MemcacheCacheLockDriverTest.php | 4 +- .../Lock/MemcachedCacheLockDriverTest.php | 2 +- .../Core/Lock/RedisCacheLockDriverTest.php | 4 +- .../src/Core/Lock/SemaphoreLockDriverTest.php | 2 +- tests/src/Database/DBATest.php | 8 +- tests/src/Database/DBStructureTest.php | 9 +- 59 files changed, 1754 insertions(+), 1038 deletions(-) rename src/Core/Config/{ => Adapter}/AbstractDbaConfigAdapter.php (52%) rename src/Core/Config/{ => Adapter}/IConfigAdapter.php (59%) rename src/Core/Config/{ => Adapter}/IPConfigAdapter.php (65%) create mode 100644 src/Core/Config/Adapter/JITConfigAdapter.php create mode 100644 src/Core/Config/Adapter/JITPConfigAdapter.php create mode 100644 src/Core/Config/Adapter/PreloadConfigAdapter.php create mode 100644 src/Core/Config/Adapter/PreloadPConfigAdapter.php rename src/Core/Config/{ => Cache}/ConfigCache.php (56%) rename src/Core/Config/{ => Cache}/ConfigCacheLoader.php (93%) create mode 100644 src/Core/Config/Cache/IConfigCache.php create mode 100644 src/Core/Config/Cache/IPConfigCache.php create mode 100644 src/Core/Config/Configuration.php delete mode 100644 src/Core/Config/IConfigCache.php delete mode 100644 src/Core/Config/IPConfigCache.php delete mode 100644 src/Core/Config/JITConfigAdapter.php delete mode 100644 src/Core/Config/JITPConfigAdapter.php create mode 100644 src/Core/Config/PConfiguration.php delete mode 100644 src/Core/Config/PreloadConfigAdapter.php delete mode 100644 src/Core/Config/PreloadPConfigAdapter.php create mode 100644 src/Factory/DBFactory.php rename tests/src/Core/Config/{ => Cache}/ConfigCacheLoaderTest.php (95%) rename tests/src/Core/Config/{ => Cache}/ConfigCacheTest.php (62%) create mode 100644 tests/src/Core/Config/ConfigurationTest.php create mode 100644 tests/src/Core/Config/PConfigurationTest.php diff --git a/bin/auth_ejabberd.php b/bin/auth_ejabberd.php index cc2517644..7682674d7 100755 --- a/bin/auth_ejabberd.php +++ b/bin/auth_ejabberd.php @@ -33,7 +33,7 @@ */ use Friendica\App; -use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Factory; use Friendica\Util\BasePath; use Friendica\Util\ExAuth; @@ -55,8 +55,11 @@ chdir($directory); require dirname(__DIR__) . '/vendor/autoload.php'; $basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Config\ConfigCacheLoader($basedir); -$config = Factory\ConfigFactory::createCache($configLoader); +$configLoader = new Cache\ConfigCacheLoader($basedir); +$configCache = Factory\ConfigFactory::createCache($configLoader); +Factory\DBFactory::init($configCache, $_SERVER); +$config = Factory\ConfigFactory::createConfig($configCache); +$pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('auth_ejabberd', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/bin/console.php b/bin/console.php index 757af31d5..9fee605b2 100755 --- a/bin/console.php +++ b/bin/console.php @@ -3,13 +3,16 @@ require dirname(__DIR__) . '/vendor/autoload.php'; -use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Factory; use Friendica\Util\BasePath; $basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Config\ConfigCacheLoader($basedir); -$config = Factory\ConfigFactory::createCache($configLoader); +$configLoader = new Cache\ConfigCacheLoader($basedir); +$configCache = Factory\ConfigFactory::createCache($configLoader); +Factory\DBFactory::init($configCache, $_SERVER); +$config = Factory\ConfigFactory::createConfig($configCache); +$pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('console', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/bin/daemon.php b/bin/daemon.php index da4bc1992..2b106b62d 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -9,6 +9,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\Factory; @@ -34,8 +35,11 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) { require dirname(__DIR__) . '/vendor/autoload.php'; $basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Config\ConfigCacheLoader($basedir); -$config = Factory\ConfigFactory::createCache($configLoader); +$configLoader = new Cache\ConfigCacheLoader($basedir); +$configCache = Factory\ConfigFactory::createCache($configLoader); +Factory\DBFactory::init($configCache, $_SERVER); +$config = Factory\ConfigFactory::createConfig($configCache); +$pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('daemon', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); @@ -151,7 +155,7 @@ if (!$foreground) { file_put_contents($pidfile, $pid); // We lose the database connection upon forking - $a->loadDatabase(); + Factory\DBFactory::init($configCache, $_SERVER); } Config::set('system', 'worker_daemon_mode', true); diff --git a/bin/worker.php b/bin/worker.php index 9b396c6f9..0a9b4cb38 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -7,6 +7,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Core\Update; use Friendica\Core\Worker; use Friendica\Factory; @@ -32,8 +33,11 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) { require dirname(__DIR__) . '/vendor/autoload.php'; $basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Config\ConfigCacheLoader($basedir); -$config = Factory\ConfigFactory::createCache($configLoader); +$configLoader = new Cache\ConfigCacheLoader($basedir); +$configCache = Factory\ConfigFactory::createCache($configLoader); +Factory\DBFactory::init($configCache, $_SERVER); +$config = Factory\ConfigFactory::createConfig($configCache); +$pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('worker', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/index.php b/index.php index 216fbe90a..9ef9490b3 100644 --- a/index.php +++ b/index.php @@ -5,7 +5,7 @@ */ use Friendica\App; -use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Factory; use Friendica\Util\BasePath; @@ -16,8 +16,11 @@ if (!file_exists(__DIR__ . '/vendor/autoload.php')) { require __DIR__ . '/vendor/autoload.php'; $basedir = BasePath::create(__DIR__, $_SERVER); -$configLoader = new Config\ConfigCacheLoader($basedir); -$config = Factory\ConfigFactory::createCache($configLoader); +$configLoader = new Cache\ConfigCacheLoader($basedir); +$configCache = Factory\ConfigFactory::createCache($configLoader); +Factory\DBFactory::init($configCache, $_SERVER); +$config = Factory\ConfigFactory::createConfig($configCache); +$pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('index', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/src/App.php b/src/App.php index e61b8dbae..e715e6ced 100644 --- a/src/App.php +++ b/src/App.php @@ -8,8 +8,9 @@ use Detection\MobileDetect; use DOMDocument; use DOMXPath; use Exception; -use Friendica\Core\Config\ConfigCache; -use Friendica\Core\Config\ConfigCacheLoader; +use Friendica\Core\Config\Cache\ConfigCacheLoader; +use Friendica\Core\Config\Cache\IConfigCache; +use Friendica\Core\Config\Configuration; use Friendica\Database\DBA; use Friendica\Factory\ConfigFactory; use Friendica\Network\HTTPException\InternalServerErrorException; @@ -114,7 +115,7 @@ class App private $logger; /** - * @var ConfigCache The cached config + * @var Configuration The config */ private $config; @@ -126,11 +127,11 @@ class App /** * Returns the current config cache of this node * - * @return ConfigCache + * @return IConfigCache */ - public function getConfig() + public function getConfigCache() { - return $this->config; + return $this->config->getCache(); } /** @@ -195,14 +196,14 @@ class App /** * @brief App constructor. * - * @param ConfigCache $config The Cached Config + * @param Configuration $config The Configuration * @param LoggerInterface $logger Logger of this application * @param Profiler $profiler The profiler of this application * @param bool $isBackend Whether it is used for backend or frontend (Default true=backend) * * @throws Exception if the Basepath is not usable */ - public function __construct(ConfigCache $config, LoggerInterface $logger, Profiler $profiler, $isBackend = true) + public function __construct(Configuration $config, LoggerInterface $logger, Profiler $profiler, $isBackend = true) { $this->config = $config; $this->logger = $logger; @@ -358,21 +359,11 @@ class App */ public function reload() { - Core\Config::init($this->config); - Core\PConfig::init($this->config); - - $this->loadDatabase(); - $this->getMode()->determine($this->basePath); $this->determineURLPath(); if ($this->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - $adapterType = $this->config->get('system', 'config_adapter'); - $adapter = ConfigFactory::createConfig($adapterType, $this->config); - Core\Config::setAdapter($adapter); - $adapterP = ConfigFactory::createPConfig($adapterType, $this->config); - Core\PConfig::setAdapter($adapterP); Core\Config::load(); } @@ -383,7 +374,7 @@ class App Core\Hook::loadHooks(); $loader = new ConfigCacheLoader($this->basePath); Core\Hook::callAll('load_config', $loader); - $this->config->loadConfigArray($loader->loadCoreConfig('addon'), true); + $this->config->getCache()->load($loader->loadCoreConfig('addon'), true); } $this->loadDefaultTimezone(); @@ -453,49 +444,6 @@ class App } } - public function loadDatabase() - { - if (DBA::connected()) { - return; - } - - $db_host = $this->config->get('database', 'hostname'); - $db_user = $this->config->get('database', 'username'); - $db_pass = $this->config->get('database', 'password'); - $db_data = $this->config->get('database', 'database'); - $charset = $this->config->get('database', 'charset'); - - // Use environment variables for mysql if they are set beforehand - if (!empty(getenv('MYSQL_HOST')) - && !empty(getenv('MYSQL_USERNAME') || !empty(getenv('MYSQL_USER'))) - && getenv('MYSQL_PASSWORD') !== false - && !empty(getenv('MYSQL_DATABASE'))) - { - $db_host = getenv('MYSQL_HOST'); - if (!empty(getenv('MYSQL_PORT'))) { - $db_host .= ':' . getenv('MYSQL_PORT'); - } - if (!empty(getenv('MYSQL_USERNAME'))) { - $db_user = getenv('MYSQL_USERNAME'); - } else { - $db_user = getenv('MYSQL_USER'); - } - $db_pass = (string) getenv('MYSQL_PASSWORD'); - $db_data = getenv('MYSQL_DATABASE'); - } - - $stamp1 = microtime(true); - - if (DBA::connect($this->config, $this->profiler, $db_host, $db_user, $db_pass, $db_data, $charset)) { - // Loads DB_UPDATE_VERSION constant - Database\DBStructure::definition($this->basePath, false); - } - - unset($db_host, $db_user, $db_pass, $db_data, $charset); - - $this->profiler->saveTimestamp($stamp1, 'network', Core\System::callstack()); - } - public function getScheme() { return $this->scheme; diff --git a/src/Core/Config.php b/src/Core/Config.php index 559ee83ec..405d14d12 100644 --- a/src/Core/Config.php +++ b/src/Core/Config.php @@ -22,116 +22,76 @@ use Friendica\Core\Config\IConfigCache; class Config { /** - * @var Config\IConfigAdapter|null + * @var Config\Configuration */ - private static $adapter; + private static $config; /** - * @var Config\IConfigCache - */ - private static $cache; - - /** - * Initialize the config with only the cache + * Initialize the config * - * @param Config\IConfigCache $cache The configuration cache + * @param Config\Configuration $config */ - public static function init(Config\IConfigCache $cache) + public static function init(Config\Configuration $config) { - self::$cache = $cache; - } - - /** - * Add the adapter for DB-backend - * - * @param Config\IConfigAdapter $adapter - */ - public static function setAdapter(Config\IConfigAdapter $adapter) - { - self::$adapter = $adapter; + self::$config = $config; } /** * @brief Loads all configuration values of family into a cached storage. * - * All configuration values of the system are stored in the cache ( @see IConfigCache ) - * - * @param string $family The category of the configuration value + * @param string $cat The category of the configuration value * * @return void */ - public static function load($family = "config") + public static function load($cat = "config") { - if (!isset(self::$adapter) || !self::$adapter->isConnected()) { - return; - } - - self::$adapter->load($family); + self::$config->load($cat); } /** * @brief Get a particular user's config variable given the category name * ($family) and a key. * - * Get a particular config value from the given category ($family) - * and the $key from a cached storage either from the self::$adapter - * (@see IConfigAdapter ) or from the static::$cache (@see IConfigCache ). - * - * @param string $family The category of the configuration value + * @param string $cat The category of the configuration value * @param string $key The configuration key to query * @param mixed $default_value optional, The value to return if key is not set (default: null) * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) * * @return mixed Stored value or null if it does not exist */ - public static function get($family, $key, $default_value = null, $refresh = false) + public static function get($cat, $key, $default_value = null, $refresh = false) { - if (!isset(self::$adapter) || !self::$adapter->isConnected()) { - return self::$cache->get($family, $key, $default_value); - } - - return self::$adapter->get($family, $key, $default_value, $refresh); + return self::$config->get($cat, $key, $default_value, $refresh); } /** * @brief Sets a configuration value for system config * - * Stores a config value ($value) in the category ($family) under the key ($key) + * Stores a config value ($value) in the category ($cat) under the key ($key) * * Note: Please do not store booleans - convert to 0/1 integer values! * - * @param string $family The category of the configuration value + * @param string $cat The category of the configuration value * @param string $key The configuration key to set * @param mixed $value The value to store * * @return bool Operation success */ - public static function set($family, $key, $value) + public static function set($cat, $key, $value) { - if (!isset(self::$adapter) || !self::$adapter->isConnected()) { - return self::$cache->set($family, $key, $value); - } - - return self::$adapter->set($family, $key, $value); + return self::$config->set($cat, $key, $value); } /** * @brief Deletes the given key from the system configuration. * - * Removes the configured value from the stored cache in self::$config - * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ). - * - * @param string $family The category of the configuration value + * @param string $cat The category of the configuration value * @param string $key The configuration key to delete * - * @return mixed + * @return bool */ - public static function delete($family, $key) + public static function delete($cat, $key) { - if (!isset(self::$adapter) || !self::$adapter->isConnected()) { - self::$cache->delete($family, $key); - } - - return self::$adapter->delete($family, $key); + return self::$config->delete($cat, $key); } } diff --git a/src/Core/Config/AbstractDbaConfigAdapter.php b/src/Core/Config/Adapter/AbstractDbaConfigAdapter.php similarity index 52% rename from src/Core/Config/AbstractDbaConfigAdapter.php rename to src/Core/Config/Adapter/AbstractDbaConfigAdapter.php index bae75122a..770dfd2c9 100644 --- a/src/Core/Config/AbstractDbaConfigAdapter.php +++ b/src/Core/Config/Adapter/AbstractDbaConfigAdapter.php @@ -1,12 +1,19 @@ connected = DBA::connected(); + } + public function isConnected() { return $this->connected; diff --git a/src/Core/Config/IConfigAdapter.php b/src/Core/Config/Adapter/IConfigAdapter.php similarity index 59% rename from src/Core/Config/IConfigAdapter.php rename to src/Core/Config/Adapter/IConfigAdapter.php index 70e141484..3bbbbbe94 100644 --- a/src/Core/Config/IConfigAdapter.php +++ b/src/Core/Config/Adapter/IConfigAdapter.php @@ -1,6 +1,6 @@ !" if it does not exist */ - public function get($cat, $k, $default_value = null, $refresh = false); + public function get($cat, $key); /** * Stores a config value ($value) in the category ($family) under the key ($key) @@ -37,23 +35,23 @@ interface IConfigAdapter * Note: Please do not store booleans - convert to 0/1 integer values! * * @param string $cat The category of the configuration value - * @param string $k The configuration key to set + * @param string $key The configuration key to set * @param mixed $value The value to store * * @return bool Operation success */ - public function set($cat, $k, $value); + public function set($cat, $key, $value); /** * Removes the configured value from the stored cache * and removes it from the database. * * @param string $cat The category of the configuration value - * @param string $k The configuration key to delete + * @param string $key The configuration key to delete * * @return mixed */ - public function delete($cat, $k); + public function delete($cat, $key); /** * Checks, if the current adapter is connected to the backend diff --git a/src/Core/Config/IPConfigAdapter.php b/src/Core/Config/Adapter/IPConfigAdapter.php similarity index 65% rename from src/Core/Config/IPConfigAdapter.php rename to src/Core/Config/Adapter/IPConfigAdapter.php index e62fc9c93..3e821efa0 100644 --- a/src/Core/Config/IPConfigAdapter.php +++ b/src/Core/Config/Adapter/IPConfigAdapter.php @@ -6,7 +6,7 @@ * and open the template in the editor. */ -namespace Friendica\Core\Config; +namespace Friendica\Core\Config\Adapter; /** * @@ -20,7 +20,7 @@ interface IPConfigAdapter * @param string $uid The user_id * @param string $cat The category of the configuration value * - * @return void + * @return array */ public function load($uid, $cat); @@ -30,13 +30,11 @@ interface IPConfigAdapter * * @param string $uid The user_id * @param string $cat The category of the configuration value - * @param string $k The configuration key to query - * @param mixed $default_value optional, The value to return if key is not set (default: null) - * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) + * @param string $key The configuration key to query * - * @return mixed Stored value or null if it does not exist + * @return mixed Stored value or "!!" if it does not exist */ - public function get($uid, $cat, $k, $default_value = null, $refresh = false); + public function get($uid, $cat, $key); /** * Stores a config value ($value) in the category ($family) under the key ($key) @@ -46,12 +44,12 @@ interface IPConfigAdapter * * @param string $uid The user_id * @param string $cat The category of the configuration value - * @param string $k The configuration key to set + * @param string $key The configuration key to set * @param string $value The value to store * * @return bool Operation success */ - public function set($uid, $cat, $k, $value); + public function set($uid, $cat, $key, $value); /** * Removes the configured value from the stored cache @@ -59,9 +57,16 @@ interface IPConfigAdapter * * @param string $uid The user_id * @param string $cat The category of the configuration value - * @param string $k The configuration key to delete + * @param string $key The configuration key to delete * - * @return mixed + * @return bool */ - public function delete($uid, $cat, $k); + public function delete($uid, $cat, $key); + + /** + * Checks, if the current adapter is connected to the backend + * + * @return bool + */ + public function isConnected(); } diff --git a/src/Core/Config/Adapter/JITConfigAdapter.php b/src/Core/Config/Adapter/JITConfigAdapter.php new file mode 100644 index 000000000..8dadfff68 --- /dev/null +++ b/src/Core/Config/Adapter/JITConfigAdapter.php @@ -0,0 +1,123 @@ + + */ +class JITConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter +{ + private $in_db; + + /** + * {@inheritdoc} + */ + public function load($cat = "config") + { + $return = []; + + if (!$this->isConnected()) { + return $return; + } + + // We don't preload "system" anymore. + // This reduces the number of database reads a lot. + if ($cat === 'system') { + return $return; + } + + $configs = DBA::select('config', ['v', 'k'], ['cat' => $cat]); + while ($config = DBA::fetch($configs)) { + $key = $config['k']; + + $return[$key] = $config['v']; + $this->in_db[$cat][$key] = true; + } + DBA::close($configs); + + return [$cat => $config]; + } + + /** + * {@inheritdoc} + */ + public function get($cat, $key) + { + if (!$this->isConnected()) { + return '!!'; + } + + $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]); + if (DBA::isResult($config)) { + // manage array value + $value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']); + + $this->in_db[$cat][$key] = true; + return $value; + } else { + + $this->in_db[$cat][$key] = false; + return '!!'; + } + } + + /** + * {@inheritdoc} + */ + public function set($cat, $key, $value) + { + if (!$this->isConnected()) { + return false; + } + + // We store our setting values in a string variable. + // So we have to do the conversion here so that the compare below works. + // The exception are array values. + $dbvalue = (!is_array($value) ? (string)$value : $value); + + $stored = $this->get($cat, $key); + + if (!isset($this->in_db[$cat])) { + $this->in_db[$cat] = []; + } + if (!isset($this->in_db[$cat][$key])) { + $this->in_db[$cat][$key] = false; + } + + if (($stored === $dbvalue) && $this->in_db[$cat][$key]) { + return true; + } + + // manage array value + $dbvalue = (is_array($value) ? serialize($value) : $dbvalue); + + $result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true); + + $this->in_db[$cat][$key] = $result; + + return $result; + } + + /** + * {@inheritdoc} + */ + public function delete($cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + if (isset($this->cache[$cat][$key])) { + unset($this->in_db[$cat][$key]); + } + + $result = DBA::delete('config', ['cat' => $cat, 'k' => $key]); + + return $result; + } +} diff --git a/src/Core/Config/Adapter/JITPConfigAdapter.php b/src/Core/Config/Adapter/JITPConfigAdapter.php new file mode 100644 index 000000000..950dd58bd --- /dev/null +++ b/src/Core/Config/Adapter/JITPConfigAdapter.php @@ -0,0 +1,126 @@ + + */ +class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdapter +{ + private $in_db; + + /** + * {@inheritdoc} + */ + public function load($uid, $cat) + { + $return = []; + + if (!$this->isConnected()) { + return $return; + } + + $pconfigs = DBA::select('pconfig', ['v', 'k'], ['cat' => $cat, 'uid' => $uid]); + if (DBA::isResult($pconfigs)) { + while ($pconfig = DBA::fetch($pconfigs)) { + $key = $pconfig['k']; + + $return[$key] = $pconfig['v']; + + $this->in_db[$uid][$cat][$key] = true; + } + } else if ($cat != 'config') { + // Negative caching + $return[null] = "!!"; + } + DBA::close($pconfigs); + + return [$cat => $return]; + } + + /** + * {@inheritdoc} + */ + public function get($uid, $cat, $key) + { + if (!$this->isConnected()) { + return null; + } + + $pconfig = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]); + if (DBA::isResult($pconfig)) { + // manage array value + $value = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']); + + $this->in_db[$uid][$cat][$key] = true; + return $value; + } else { + + $this->in_db[$uid][$cat][$key] = false; + return '!!'; + } + } + + /** + * {@inheritdoc} + */ + public function set($uid, $cat, $key, $value) + { + if (!$this->isConnected()) { + return false; + } + + // We store our setting values in a string variable. + // So we have to do the conversion here so that the compare below works. + // The exception are array values. + $dbvalue = (!is_array($value) ? (string)$value : $value); + + $stored = $this->get($uid, $cat, $key); + + if (!isset($this->in_db[$uid])) { + $this->in_db[$uid] = []; + } + if (!isset($this->in_db[$uid][$cat])) { + $this->in_db[$uid][$cat] = []; + } + if (!isset($this->in_db[$uid][$cat][$key])) { + $this->in_db[$uid][$cat][$key] = false; + } + + if (($stored === $dbvalue) && $this->in_db[$uid][$cat][$key]) { + return true; + } + + // manage array value + $dbvalue = (is_array($value) ? serialize($value) : $dbvalue); + + $result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true); + + $this->in_db[$uid][$cat][$key] = $result; + + return $result; + } + + /** + * {@inheritdoc} + */ + public function delete($uid, $cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + if (!empty($this->in_db[$uid][$cat][$key])) { + unset($this->in_db[$uid][$cat][$key]); + } + + $result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]); + + return $result; + } +} diff --git a/src/Core/Config/Adapter/PreloadConfigAdapter.php b/src/Core/Config/Adapter/PreloadConfigAdapter.php new file mode 100644 index 000000000..8cad5c555 --- /dev/null +++ b/src/Core/Config/Adapter/PreloadConfigAdapter.php @@ -0,0 +1,104 @@ + + */ +class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter +{ + private $config_loaded = false; + + /** + * {@inheritdoc} + */ + public function load($cat = 'config') + { + $return = []; + + if (!$this->isConnected()) { + return $return; + } + + if ($this->config_loaded) { + return $return; + } + + $configs = DBA::select('config', ['cat', 'v', 'k']); + while ($config = DBA::fetch($configs)) { + $return[$config['k']] = $config['v']; + } + DBA::close($configs); + + $this->config_loaded = true; + + return [$cat => $return]; + } + + /** + * {@inheritdoc} + */ + public function get($cat, $key) + { + if (!$this->isConnected()) { + return null; + } + + $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]); + if (DBA::isResult($config)) { + // manage array value + $value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']); + + return $value; + } else { + + return '!!'; + } + } + + /** + * {@inheritdoc} + */ + public function set($cat, $key, $value) + { + if (!$this->isConnected()) { + return false; + } + + // We store our setting values as strings. + // So we have to do the conversion here so that the compare below works. + // The exception are array values. + $compare_value = !is_array($value) ? (string)$value : $value; + + if ($this->get($cat, $key) === $compare_value) { + return true; + } + + // manage array value + $dbvalue = is_array($value) ? serialize($value) : $value; + + $result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true); + + return $result; + } + + /** + * {@inheritdoc} + */ + public function delete($cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + $result = DBA::delete('config', ['cat' => $cat, 'k' => $key]); + + return $result; + } +} diff --git a/src/Core/Config/Adapter/PreloadPConfigAdapter.php b/src/Core/Config/Adapter/PreloadPConfigAdapter.php new file mode 100644 index 000000000..d117ed354 --- /dev/null +++ b/src/Core/Config/Adapter/PreloadPConfigAdapter.php @@ -0,0 +1,126 @@ + + */ +class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdapter +{ + private $config_loaded = false; + + /** + * @param int $uid The UID of the current user + */ + public function __construct($uid = null) + { + parent::__construct(); + + if (isset($uid)) { + $this->load($uid, 'config'); + } + } + + /** + * {@inheritdoc} + */ + public function load($uid, $cat) + { + $return = []; + + if ($this->config_loaded) { + return $return; + } + + if (empty($uid)) { + return $return; + } + + $pconfigs = DBA::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]); + while ($pconfig = DBA::fetch($pconfigs)) { + $return[$pconfig['k']] = $pconfig['v']; + } + DBA::close($pconfigs); + + $this->config_loaded = true; + + return [$cat => $return]; + } + + /** + * {@inheritdoc} + */ + public function get($uid, $cat, $key) + { + if (!$this->isConnected()) { + return null; + } + + if (!$this->config_loaded) { + $this->load($uid, $cat); + } + + $config = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]); + if (DBA::isResult($config)) { + // manage array value + $value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']); + + return $value; + } else { + return '!!'; + } + } + + /** + * {@inheritdoc} + */ + public function set($uid, $cat, $key, $value) + { + if (!$this->isConnected()) { + return false; + } + + if (!$this->config_loaded) { + $this->load($uid, $cat); + } + // We store our setting values as strings. + // So we have to do the conversion here so that the compare below works. + // The exception are array values. + $compare_value = !is_array($value) ? (string)$value : $value; + + if ($this->get($uid, $cat, $key) === $compare_value) { + return true; + } + + // manage array value + $dbvalue = is_array($value) ? serialize($value) : $value; + + $result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true); + + return $result; + } + + /** + * {@inheritdoc} + */ + public function delete($uid, $cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + if (!$this->config_loaded) { + $this->load($uid, $cat); + } + + $result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]); + + return $result; + } +} diff --git a/src/Core/Config/ConfigCache.php b/src/Core/Config/Cache/ConfigCache.php similarity index 56% rename from src/Core/Config/ConfigCache.php rename to src/Core/Config/Cache/ConfigCache.php index b86ec3860..b1172c0c8 100644 --- a/src/Core/Config/ConfigCache.php +++ b/src/Core/Config/Cache/ConfigCache.php @@ -1,6 +1,6 @@ loadConfigArray($config); + $this->load($config); } /** - * Tries to load the specified configuration array into the App->config array. - * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. - * - * @param array $config - * @param bool $overwrite Force value overwrite if the config key already exists + * {@inheritdoc} */ - public function loadConfigArray(array $config, $overwrite = false) + public function load(array $config, $overwrite = false) { - foreach ($config as $category => $values) { - foreach ($values as $key => $value) { - if ($overwrite) { - $this->set($category, $key, $value); - } else { - $this->setDefault($category, $key, $value); + $categories = array_keys($config); + + foreach ($categories as $category) { + if (isset($config[$category]) && is_array($config[$category])) { + $keys = array_keys($config[$category]); + + foreach ($keys as $key) { + if (isset($config[$category][$key])) { + if ($overwrite) { + $this->set($category, $key, $config[$category][$key]); + } else { + $this->setDefault($category, $key, $config[$category][$key]); + } + } } } } @@ -44,23 +51,22 @@ class ConfigCache implements IConfigCache, IPConfigCache /** * {@inheritdoc} */ - public function get($cat, $key = null, $default = null) + public function get($cat, $key = null) { - $return = $default; - - if ($cat === 'config') { - if (isset($this->config[$key])) { - $return = $this->config[$key]; - } + if (isset($this->config[$cat][$key])) { + return $this->config[$cat][$key]; } else { - if (isset($this->config[$cat][$key])) { - $return = $this->config[$cat][$key]; - } elseif ($key == null && isset($this->config[$cat])) { - $return = $this->config[$cat]; - } + return '!!'; } + } - return $return; + /** + * {@inheritdoc} + */ + public function has($cat, $key = null) + { + return isset($this->config[$cat][$key]) + && $this->config[$cat][$key] !== '!!'; } /** @@ -85,34 +91,48 @@ class ConfigCache implements IConfigCache, IPConfigCache // Only arrays are serialized in database, so we have to unserialize sparingly $value = is_string($value) && preg_match("|^a:[0-9]+:{.*}$|s", $value) ? unserialize($value) : $value; - if ($cat === 'config') { - $this->config[$key] = $value; - } else { - if (!isset($this->config[$cat])) { - $this->config[$cat] = []; - } - - $this->config[$cat][$key] = $value; + if (!isset($this->config[$cat])) { + $this->config[$cat] = []; } + $this->config[$cat][$key] = $value; + return true; } + /** + * {@inheritdoc} + */ + public function hasP($uid, $cat, $key = null) + { + return isset($this->config[$uid][$cat][$key]) + && $this->config[$uid][$cat][$key] !== '!!'; + } + /** * {@inheritdoc} */ public function delete($cat, $key) { - if ($cat === 'config') { - if (isset($this->config[$key])) { - unset($this->config[$key]); + if (isset($this->config[$cat][$key])) { + unset($this->config[$cat][$key]); + if (count($this->config[$cat]) == 0) { + unset($this->config[$cat]); } + return true; } else { - if (isset($this->config[$cat][$key])) { - unset($this->config[$cat][$key]); - if (count($this->config[$cat]) == 0) { - unset($this->config[$cat]); - } + return false; + } + } + + /** + * {@inheritdoc} + */ + public function loadP($uid, array $config) + { + foreach ($config as $category => $values) { + foreach ($values as $key => $value) { + $this->setP($uid, $category, $key, $value); } } } @@ -120,17 +140,13 @@ class ConfigCache implements IConfigCache, IPConfigCache /** * {@inheritdoc} */ - public function getP($uid, $cat, $key = null, $default = null) + public function getP($uid, $cat, $key = null) { - $return = $default; - if (isset($this->config[$uid][$cat][$key])) { - $return = $this->config[$uid][$cat][$key]; - } elseif ($key === null && isset($this->config[$uid][$cat])) { - $return = $this->config[$uid][$cat]; + return $this->config[$uid][$cat][$key]; + } else { + return '!!'; } - - return $return; } /** @@ -145,15 +161,13 @@ class ConfigCache implements IConfigCache, IPConfigCache $this->config[$uid] = []; } - if (!isset($this->config[$uid][$cat]) || !is_array($this->config[$uid][$cat])) { + if (!isset($this->config[$uid][$cat])) { $this->config[$uid][$cat] = []; } - if ($key === null) { - $this->config[$uid][$cat] = $value; - } else { - $this->config[$uid][$cat][$key] = $value; - } + $this->config[$uid][$cat][$key] = $value; + + return true; } /** @@ -169,6 +183,10 @@ class ConfigCache implements IConfigCache, IPConfigCache unset($this->config[$uid]); } } + + return true; + } else { + return false; } } diff --git a/src/Core/Config/ConfigCacheLoader.php b/src/Core/Config/Cache/ConfigCacheLoader.php similarity index 93% rename from src/Core/Config/ConfigCacheLoader.php rename to src/Core/Config/Cache/ConfigCacheLoader.php index 3a6a3c803..b728d1082 100644 --- a/src/Core/Config/ConfigCacheLoader.php +++ b/src/Core/Config/Cache/ConfigCacheLoader.php @@ -1,6 +1,6 @@ set('system', 'basepath', $this->baseDir); - $config->loadConfigArray($this->loadCoreConfig('defaults')); - $config->loadConfigArray($this->loadCoreConfig('settings')); + $config->load($this->loadCoreConfig('defaults')); + $config->load($this->loadCoreConfig('settings')); - $config->loadConfigArray($this->loadLegacyConfig('htpreconfig'), true); - $config->loadConfigArray($this->loadLegacyConfig('htconfig'), true); + $config->load($this->loadLegacyConfig('htpreconfig'), true); + $config->load($this->loadLegacyConfig('htconfig'), true); - $config->loadConfigArray($this->loadCoreConfig('local'), true); + $config->load($this->loadCoreConfig('local'), true); } /** diff --git a/src/Core/Config/Cache/IConfigCache.php b/src/Core/Config/Cache/IConfigCache.php new file mode 100644 index 000000000..9d948527d --- /dev/null +++ b/src/Core/Config/Cache/IConfigCache.php @@ -0,0 +1,65 @@ +!' if not set + */ + function get($cat, $key = null); + + /** + * Sets a value in the config cache. Accepts raw output from the config table + * + * @param string $cat Config category + * @param string $key Config key + * @param mixed $value Value to set + * + * @return bool True, if the value is set + */ + function set($cat, $key, $value); + + /** + * Deletes a value from the config cache. + * + * @param string $cat Config category + * @param string $key Config key + * + * @return bool true, if deleted + */ + 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 + * + * @return array + */ + function getAll(); +} diff --git a/src/Core/Config/Cache/IPConfigCache.php b/src/Core/Config/Cache/IPConfigCache.php new file mode 100644 index 000000000..4ac21481a --- /dev/null +++ b/src/Core/Config/Cache/IPConfigCache.php @@ -0,0 +1,70 @@ +!' if not set + */ + function getP($uid, $cat, $key = null); + + /** + * Sets a value in the user config cache + * + * Accepts raw output from the pconfig table + * + * @param int $uid User Id + * @param string $cat Config category + * @param string $key Config key + * @param mixed $value Value to set + */ + function setP($uid, $cat, $key, $value); + + /** + * Deletes a value from the user config cache + * + * @param int $uid User Id + * @param string $cat Config category + * @param string $key Config key + * + * @return bool true, if deleted + */ + 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 + * + * @return array + */ + function getAll(); +} diff --git a/src/Core/Config/Configuration.php b/src/Core/Config/Configuration.php new file mode 100644 index 000000000..ccb9abda8 --- /dev/null +++ b/src/Core/Config/Configuration.php @@ -0,0 +1,154 @@ +configCache = $configCache; + $this->configAdapter = $configAdapter; + + $this->load(); + } + + /** + * Returns the Config Cache + * + * @return Cache\IConfigCache + */ + public function getCache() + { + return $this->configCache; + } + + /** + * @brief Loads all configuration values of family into a cached storage. + * + * All configuration values of the system are stored in the cache ( @see IConfigCache ) + * + * @param string $cat The category of the configuration value + * + * @return void + */ + public function load($cat = 'config') + { + // If not connected, do nothing + if (!$this->configAdapter->isConnected()) { + return; + } + + // load the whole category out of the DB into the cache + $this->configCache->load($this->configAdapter->load($cat), true); + } + + /** + * @brief Get a particular user's config variable given the category name + * ($cat) and a $key. + * + * Get a particular config value from the given category ($cat) + * and the $key from a cached storage either from the $this->configAdapter + * (@see IConfigAdapter ) or from the $this->configCache (@see IConfigCache ). + * + * @param string $cat The category of the configuration value + * @param string $key The configuration key to query + * @param mixed $default_value optional, The value to return if key is not set (default: null) + * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) + * + * @return mixed Stored value or null if it does not exist + */ + public function get($cat, $key, $default_value = null, $refresh = false) + { + // Return the value of the cache if found and no refresh is forced + if (!$refresh && $this->configCache->has($cat, $key)) { + return $this->configCache->get($cat, $key); + } + + // if we don't find the value in the cache and the adapter isn't ready, return the default value + if (!$this->configAdapter->isConnected()) { + return $default_value; + } + + // load DB value to cache + $dbvalue = $this->configAdapter->get($cat, $key); + + if ($dbvalue !== '!!') { + $this->configCache->set($cat, $key, $dbvalue); + return $dbvalue; + } else { + return $default_value; + } + } + + /** + * @brief Sets a configuration value for system config + * + * Stores a config value ($value) in the category ($cat) under the key ($key) + * + * Note: Please do not store booleans - convert to 0/1 integer values! + * + * @param string $cat The category of the configuration value + * @param string $key The configuration key to set + * @param mixed $value The value to store + * + * @return bool Operation success + */ + public function set($cat, $key, $value) + { + // set the cache first + $cached = $this->configCache->set($cat, $key, $value); + + // If there is no connected adapter, we're finished + if (!$this->configAdapter->isConnected()) { + return $cached; + } + + $stored = $this->configAdapter->set($cat, $key, $value); + + return $cached && $stored; + } + + /** + * @brief Deletes the given key from the system configuration. + * + * Removes the configured value from the stored cache in $this->configCache + * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ). + * + * @param string $cat The category of the configuration value + * @param string $key The configuration key to delete + * + * @return bool + */ + public function delete($cat, $key) + { + $cacheRemoved = $this->configCache->delete($cat, $key); + + if (!$this->configAdapter->isConnected()) { + return $cacheRemoved; + } + + $storeRemoved = $this->configAdapter->delete($cat, $key); + + return $cacheRemoved || $storeRemoved; + } +} diff --git a/src/Core/Config/IConfigCache.php b/src/Core/Config/IConfigCache.php deleted file mode 100644 index 898e3c0f8..000000000 --- a/src/Core/Config/IConfigCache.php +++ /dev/null @@ -1,39 +0,0 @@ - - */ -class JITConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter -{ - private $cache; - private $in_db; - - /** - * @var IConfigCache The config cache of this driver - */ - private $configCache; - - /** - * @param IConfigCache $configCache The config cache of this driver - */ - public function __construct(IConfigCache $configCache) - { - $this->configCache = $configCache; - $this->connected = DBA::connected(); - } - - /** - * {@inheritdoc} - */ - public function load($cat = "config") - { - if (!$this->isConnected()) { - return; - } - - // We don't preload "system" anymore. - // This reduces the number of database reads a lot. - if ($cat === 'system') { - return; - } - - $configs = DBA::select('config', ['v', 'k'], ['cat' => $cat]); - while ($config = DBA::fetch($configs)) { - $k = $config['k']; - - $this->configCache->set($cat, $k, $config['v']); - - if ($cat !== 'config') { - $this->cache[$cat][$k] = $config['v']; - $this->in_db[$cat][$k] = true; - } - } - DBA::close($configs); - } - - /** - * {@inheritdoc} - */ - public function get($cat, $k, $default_value = null, $refresh = false) - { - if (!$this->isConnected()) { - return $default_value; - } - - if (!$refresh) { - // Do we have the cached value? Then return it - if (isset($this->cache[$cat][$k])) { - if ($this->cache[$cat][$k] === '!!') { - return $default_value; - } else { - return $this->cache[$cat][$k]; - } - } - } - - $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $k]); - if (DBA::isResult($config)) { - // manage array value - $value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']); - - // Assign the value from the database to the cache - $this->cache[$cat][$k] = $value; - $this->in_db[$cat][$k] = true; - return $value; - } elseif ($this->configCache->get($cat, $k) !== null) { - // Assign the value (mostly) from config/local.config.php file to the cache - $this->cache[$cat][$k] = $this->configCache->get($cat, $k); - $this->in_db[$cat][$k] = false; - - return $this->configCache->get($cat, $k); - } elseif ($this->configCache->get('config', $k) !== null) { - // Assign the value (mostly) from config/local.config.php file to the cache - $this->cache[$k] = $this->configCache->get('config', $k); - $this->in_db[$k] = false; - - return $this->configCache->get('config', $k); - } - - $this->cache[$cat][$k] = '!!'; - $this->in_db[$cat][$k] = false; - - return $default_value; - } - - /** - * {@inheritdoc} - */ - public function set($cat, $k, $value) - { - if (!$this->isConnected()) { - return false; - } - - // We store our setting values in a string variable. - // So we have to do the conversion here so that the compare below works. - // The exception are array values. - $dbvalue = (!is_array($value) ? (string)$value : $value); - - $stored = $this->get($cat, $k, null, true); - - if (!isset($this->in_db[$cat])) { - $this->in_db[$cat] = []; - } - if (!isset($this->in_db[$cat][$k])) { - $this->in_db[$cat] = false; - } - - if (($stored === $dbvalue) && $this->in_db[$cat][$k]) { - return true; - } - - $this->configCache->set($cat, $k, $value); - - // Assign the just added value to the cache - $this->cache[$cat][$k] = $dbvalue; - - // manage array value - $dbvalue = (is_array($value) ? serialize($value) : $dbvalue); - - $result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $k], true); - - if ($result) { - $this->in_db[$cat][$k] = true; - } - - return $result; - } - - /** - * {@inheritdoc} - */ - public function delete($cat, $k) - { - if (!$this->isConnected()) { - return false; - } - - if (isset($this->cache[$cat][$k])) { - unset($this->cache[$cat][$k]); - unset($this->in_db[$cat][$k]); - } - - $result = DBA::delete('config', ['cat' => $cat, 'k' => $k]); - - return $result; - } -} diff --git a/src/Core/Config/JITPConfigAdapter.php b/src/Core/Config/JITPConfigAdapter.php deleted file mode 100644 index b1a15601c..000000000 --- a/src/Core/Config/JITPConfigAdapter.php +++ /dev/null @@ -1,136 +0,0 @@ - - */ -class JITPConfigAdapter implements IPConfigAdapter -{ - private $in_db; - - /** - * The config cache of this adapter - * @var IPConfigCache - */ - private $configCache; - - /** - * @param IPConfigCache $configCache The config cache of this adapter - */ - public function __construct(IPConfigCache $configCache) - { - $this->configCache = $configCache; - } - - /** - * {@inheritdoc} - */ - public function load($uid, $cat) - { - $pconfigs = DBA::select('pconfig', ['v', 'k'], ['cat' => $cat, 'uid' => $uid]); - if (DBA::isResult($pconfigs)) { - while ($pconfig = DBA::fetch($pconfigs)) { - $k = $pconfig['k']; - - $this->configCache->setP($uid, $cat, $k, $pconfig['v']); - - $this->in_db[$uid][$cat][$k] = true; - } - } else if ($cat != 'config') { - // Negative caching - $this->configCache->setP($uid, $cat, null, "!!"); - } - DBA::close($pconfigs); - } - - /** - * {@inheritdoc} - */ - public function get($uid, $cat, $k, $default_value = null, $refresh = false) - { - if (!$refresh) { - // Looking if the whole family isn't set - if ($this->configCache->getP($uid, $cat) !== null) { - if ($this->configCache->getP($uid, $cat) === '!!') { - return $default_value; - } - } - - if ($this->configCache->getP($uid, $cat, $k) !== null) { - if ($this->configCache->getP($uid, $cat, $k) === '!!') { - return $default_value; - } - return $this->configCache->getP($uid, $cat, $k); - } - } - - $pconfig = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]); - if (DBA::isResult($pconfig)) { - $val = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']); - - $this->configCache->setP($uid, $cat, $k, $val); - - $this->in_db[$uid][$cat][$k] = true; - - return $val; - } else { - $this->configCache->setP($uid, $cat, $k, '!!'); - - $this->in_db[$uid][$cat][$k] = false; - - return $default_value; - } - } - - /** - * {@inheritdoc} - */ - public function set($uid, $cat, $k, $value) - { - // We store our setting values in a string variable. - // So we have to do the conversion here so that the compare below works. - // The exception are array values. - $dbvalue = (!is_array($value) ? (string)$value : $value); - - $stored = $this->get($uid, $cat, $k, null, true); - - if (($stored === $dbvalue) && $this->in_db[$uid][$cat][$k]) { - return true; - } - - $this->configCache->setP($uid, $cat, $k, $value); - - // manage array value - $dbvalue = (is_array($value) ? serialize($value) : $dbvalue); - - $result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $k], true); - - if ($result) { - $this->in_db[$uid][$cat][$k] = true; - } - - return $result; - } - - /** - * {@inheritdoc} - */ - public function delete($uid, $cat, $k) - { - $this->configCache->deleteP($uid, $cat, $k); - - if (!empty($this->in_db[$uid][$cat][$k])) { - unset($this->in_db[$uid][$cat][$k]); - } - - $result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]); - - return $result; - } -} diff --git a/src/Core/Config/PConfiguration.php b/src/Core/Config/PConfiguration.php new file mode 100644 index 000000000..d3c848c9d --- /dev/null +++ b/src/Core/Config/PConfiguration.php @@ -0,0 +1,150 @@ +configCache = $configCache; + $this->configAdapter = $configAdapter; + } + + /** + * @brief Loads all configuration values of a user's config family into a cached storage. + * + * All configuration values of the given user are stored with the $uid in + * the cache ( @see IPConfigCache ) + * + * @param string $uid The user_id + * @param string $cat The category of the configuration value + * + * @return void + */ + public function load($uid, $cat = 'config') + { + // If not connected, do nothing + if (!$this->configAdapter->isConnected()) { + return; + } + + // load the whole category out of the DB into the cache + $this->configCache->loadP($uid, $this->configAdapter->load($uid, $cat)); + } + + /** + * @brief Get a particular user's config variable given the category name + * ($cat) and a key. + * + * Get a particular user's config value from the given category ($cat) + * and the $key with the $uid from a cached storage either from the $this->configAdapter + * (@see IConfigAdapter ) or from the $this->configCache (@see IConfigCache ). + * + * @param string $uid The user_id + * @param string $cat The category of the configuration value + * @param string $key The configuration key to query + * @param mixed $default_value optional, The value to return if key is not set (default: null) + * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) + * + * @return mixed Stored value or null if it does not exist + */ + public function get($uid, $cat, $key, $default_value = null, $refresh = false) + { + // Return the value of the cache if found and no refresh is forced + if (!$refresh && $this->configCache->hasP($uid, $cat, $key)) { + return $this->configCache->getP($uid, $cat, $key); + } + + // if we don't find the value in the cache and the adapter isn't ready, return the default value + if (!$this->configAdapter->isConnected()) { + return $default_value; + } + + // load DB value to cache + $dbvalue = $this->configAdapter->get($uid, $cat, $key); + + if ($dbvalue !== '!!') { + $this->configCache->setP($uid, $cat, $key, $dbvalue); + return $dbvalue; + } else { + return $default_value; + } + } + + /** + * @brief Sets a configuration value for a user + * + * Stores a config value ($value) in the category ($family) under the key ($key) + * for the user_id $uid. + * + * @note Please do not store booleans - convert to 0/1 integer values! + * + * @param string $uid The user_id + * @param string $cat The category of the configuration value + * @param string $key The configuration key to set + * @param mixed $value The value to store + * + * @return bool Operation success + */ + public function set($uid, $cat, $key, $value) + { + // set the cache first + $cached = $this->configCache->setP($uid, $cat, $key, $value); + + // If there is no connected adapter, we're finished + if (!$this->configAdapter->isConnected()) { + return $cached; + } + + $stored = $this->configAdapter->set($uid, $cat, $key, $value); + + return $cached && $stored; + } + + /** + * @brief Deletes the given key from the users's configuration. + * + * Removes the configured value from the stored cache in $this->configCache + * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ) + * with the given $uid. + * + * @param string $uid The user_id + * @param string $cat The category of the configuration value + * @param string $key The configuration key to delete + * + * @return bool + */ + public function delete($uid, $cat, $key) + { + $cacheRemoved = $this->configCache->deleteP($uid, $cat, $key); + + if (!$this->configAdapter->isConnected()) { + return $cacheRemoved; + } + + $storeRemoved = $this->configAdapter->delete($uid, $cat, $key); + + return $cacheRemoved || $storeRemoved; + } +} diff --git a/src/Core/Config/PreloadConfigAdapter.php b/src/Core/Config/PreloadConfigAdapter.php deleted file mode 100644 index 96331e7a2..000000000 --- a/src/Core/Config/PreloadConfigAdapter.php +++ /dev/null @@ -1,123 +0,0 @@ - - */ -class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter -{ - private $config_loaded = false; - - /** - * @var IConfigCache The config cache of this driver - */ - private $configCache; - - /** - * @param IConfigCache $configCache The config cache of this driver - */ - public function __construct(IConfigCache $configCache) - { - $this->configCache = $configCache; - $this->connected = DBA::connected(); - $this->load(); - } - - /** - * {@inheritdoc} - */ - public function load($family = 'config') - { - if (!$this->isConnected()) { - return; - } - - if ($this->config_loaded) { - return; - } - - $configs = DBA::select('config', ['cat', 'v', 'k']); - while ($config = DBA::fetch($configs)) { - $this->configCache->set($config['cat'], $config['k'], $config['v']); - } - DBA::close($configs); - - $this->config_loaded = true; - } - - /** - * {@inheritdoc} - */ - public function get($cat, $k, $default_value = null, $refresh = false) - { - if (!$this->isConnected()) { - return $default_value; - } - - if ($refresh) { - $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $k]); - if (DBA::isResult($config)) { - $this->configCache->set($cat, $k, $config['v']); - } - } - - $return = $this->configCache->get($cat, $k, $default_value); - - return $return; - } - - /** - * {@inheritdoc} - */ - public function set($cat, $k, $value) - { - if (!$this->isConnected()) { - return false; - } - - // We store our setting values as strings. - // So we have to do the conversion here so that the compare below works. - // The exception are array values. - $compare_value = !is_array($value) ? (string)$value : $value; - - if ($this->configCache->get($cat, $k) === $compare_value) { - return true; - } - - $this->configCache->set($cat, $k, $value); - - // manage array value - $dbvalue = is_array($value) ? serialize($value) : $value; - - $result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $k], true); - if (!$result) { - throw new Exception('Unable to store config value in [' . $cat . '][' . $k . ']'); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function delete($cat, $k) - { - if (!$this->isConnected()) { - return false; - } - - $this->configCache->delete($cat, $k); - - $result = DBA::delete('config', ['cat' => $cat, 'k' => $k]); - - return $result; - } -} diff --git a/src/Core/Config/PreloadPConfigAdapter.php b/src/Core/Config/PreloadPConfigAdapter.php deleted file mode 100644 index af97815ad..000000000 --- a/src/Core/Config/PreloadPConfigAdapter.php +++ /dev/null @@ -1,125 +0,0 @@ - - */ -class PreloadPConfigAdapter implements IPConfigAdapter -{ - private $config_loaded = false; - - /** - * The config cache of this adapter - * @var IPConfigCache - */ - private $configCache; - - /** - * @param IPConfigCache $configCache The config cache of this adapter - * @param int $uid The UID of the current user - */ - public function __construct(IPConfigCache $configCache, $uid = null) - { - $this->configCache = $configCache; - if (isset($uid)) { - $this->load($uid, 'config'); - } - } - - /** - * {@inheritdoc} - */ - public function load($uid, $family) - { - if ($this->config_loaded) { - return; - } - - if (empty($uid)) { - return; - } - - $pconfigs = DBA::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]); - while ($pconfig = DBA::fetch($pconfigs)) { - $this->configCache->setP($uid, $pconfig['cat'], $pconfig['k'], $pconfig['v']); - } - DBA::close($pconfigs); - - $this->config_loaded = true; - } - - /** - * {@inheritdoc} - */ - public function get($uid, $cat, $k, $default_value = null, $refresh = false) - { - if (!$this->config_loaded) { - $this->load($uid, $cat); - } - - if ($refresh) { - $config = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]); - if (DBA::isResult($config)) { - $this->configCache->setP($uid, $cat, $k, $config['v']); - } else { - $this->configCache->deleteP($uid, $cat, $k); - } - } - - return $this->configCache->getP($uid, $cat, $k, $default_value);; - } - - /** - * {@inheritdoc} - */ - public function set($uid, $cat, $k, $value) - { - if (!$this->config_loaded) { - $this->load($uid, $cat); - } - // We store our setting values as strings. - // So we have to do the conversion here so that the compare below works. - // The exception are array values. - $compare_value = !is_array($value) ? (string)$value : $value; - - if ($this->configCache->getP($uid, $cat, $k) === $compare_value) { - return true; - } - - $this->configCache->setP($uid, $cat, $k, $value); - - // manage array value - $dbvalue = is_array($value) ? serialize($value) : $value; - - $result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $k], true); - if (!$result) { - throw new Exception('Unable to store config value in [' . $uid . '][' . $cat . '][' . $k . ']'); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function delete($uid, $cat, $k) - { - if (!$this->config_loaded) { - $this->load($uid, $cat); - } - - $this->configCache->deleteP($uid, $cat, $k); - - $result = DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]); - - return $result; - } -} diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index d5c63dd99..682d10971 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -100,10 +100,10 @@ HELP; } } - $db_host = $a->getConfig()->get('database', 'hostname'); - $db_user = $a->getConfig()->get('database', 'username'); - $db_pass = $a->getConfig()->get('database', 'password'); - $db_data = $a->getConfig()->get('database', 'database'); + $db_host = $a->getConfigCache()->get('database', 'hostname'); + $db_user = $a->getConfigCache()->get('database', 'username'); + $db_pass = $a->getConfigCache()->get('database', 'password'); + $db_data = $a->getConfigCache()->get('database', 'database'); } else { // Creating config file $this->out("Creating config file...\n"); @@ -146,7 +146,7 @@ HELP; $installer->resetChecks(); - if (!$installer->checkDB($a->getConfig(), $a->getProfiler(), $db_host, $db_user, $db_pass, $db_data)) { + if (!$installer->checkDB($a->getConfigCache(), $a->getProfiler(), $db_host, $db_user, $db_pass, $db_data)) { $errorMessage = $this->extractErrors($installer->getChecks()); throw new RuntimeException($errorMessage); } diff --git a/src/Core/Console/Config.php b/src/Core/Console/Config.php index b1c3df54e..cf5c09fc0 100644 --- a/src/Core/Console/Config.php +++ b/src/Core/Console/Config.php @@ -124,9 +124,9 @@ HELP; $cat = $this->getArgument(0); Core\Config::load($cat); - if ($a->getConfig()->get($cat) !== null) { + if ($a->getConfigCache()->get($cat) !== null) { $this->out("[{$cat}]"); - $catVal = $a->getConfig()->get($cat); + $catVal = $a->getConfigCache()->get($cat); foreach ($catVal as $key => $value) { if (is_array($value)) { foreach ($value as $k => $v) { @@ -148,7 +148,7 @@ HELP; $this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only'); } - $config = $a->getConfig()->getAll(); + $config = $a->getConfigCache()->getAll(); foreach ($config as $cat => $section) { if (is_array($section)) { foreach ($section as $key => $value) { diff --git a/src/Core/Console/Typo.php b/src/Core/Console/Typo.php index 32ba6ded3..8d07051e8 100644 --- a/src/Core/Console/Typo.php +++ b/src/Core/Console/Typo.php @@ -43,7 +43,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - $php_path = BaseObject::getApp()->getConfig()->get('config', 'php_path', 'php'); + $php_path = BaseObject::getApp()->getConfigCache()->get('config', 'php_path', 'php'); if ($this->getOption('v')) { $this->out('Directory: src'); diff --git a/src/Core/Installer.php b/src/Core/Installer.php index dd9e3d22e..73f85785e 100644 --- a/src/Core/Installer.php +++ b/src/Core/Installer.php @@ -6,7 +6,7 @@ namespace Friendica\Core; use DOMDocument; use Exception; -use Friendica\Core\Config\ConfigCache; +use Friendica\Core\Config\Cache\IConfigCache; use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\Object\Image; @@ -583,7 +583,7 @@ class Installer /** * Checking the Database connection and if it is available for the current installation * - * @param ConfigCache $configCache The configuration cache + * @param IConfigCache $configCache The configuration cache * @param Profiler $profiler The profiler of this app * @param string $dbhost Hostname/IP of the Friendica Database * @param string $dbuser Username of the Database connection credentials @@ -593,7 +593,7 @@ class Installer * @return bool true if the check was successful, otherwise false * @throws Exception */ - public function checkDB(ConfigCache $configCache, Profiler $profiler, $dbhost, $dbuser, $dbpass, $dbdata) + public function checkDB(IConfigCache $configCache, Profiler $profiler, $dbhost, $dbuser, $dbpass, $dbdata) { if (!DBA::connect($configCache, $profiler, $dbhost, $dbuser, $dbpass, $dbdata)) { $this->addCheck(L10n::t('Could not connect to database.'), false, true, ''); diff --git a/src/Core/PConfig.php b/src/Core/PConfig.php index df024f0f3..f62b59f47 100644 --- a/src/Core/PConfig.php +++ b/src/Core/PConfig.php @@ -18,123 +18,78 @@ namespace Friendica\Core; class PConfig { /** - * @var Config\IPConfigAdapter + * @var Config\PConfiguration */ - private static $adapter; - - /** - * @var Config\IPConfigCache - */ - private static $cache; + private static $config; /** * Initialize the config with only the cache * - * @param Config\IPConfigCache $cache The configuration cache + * @param Config\PConfiguration $config The configuration cache */ - public static function init(Config\IPConfigCache $cache) + public static function init(Config\PConfiguration $config) { - self::$cache = $cache; - } - - /** - * Add the adapter for DB-backend - * - * @param Config\IPConfigAdapter $adapter - */ - public static function setAdapter(Config\IPConfigAdapter $adapter) - { - self::$adapter = $adapter; + self::$config = $config; } /** * @brief Loads all configuration values of a user's config family into a cached storage. * - * All configuration values of the given user are stored with the $uid in - * the cache ( @see IPConfigCache ) - * - * @param string $uid The user_id - * @param string $family The category of the configuration value + * @param string $uid The user_id + * @param string $cat The category of the configuration value * * @return void */ - public static function load($uid, $family) + public static function load($uid, $cat) { - if (!isset(self::$adapter)) { - return; - } - - self::$adapter->load($uid, $family); + self::$config->load($uid, $cat); } /** * @brief Get a particular user's config variable given the category name - * ($family) and a key. - * - * Get a particular user's config value from the given category ($family) - * and the $key with the $uid from a cached storage either from the self::$adapter - * (@see IConfigAdapter ) or from the static::$cache (@see IConfigCache ). + * ($cat) and a key. * * @param string $uid The user_id - * @param string $family The category of the configuration value + * @param string $cat The category of the configuration value * @param string $key The configuration key to query * @param mixed $default_value optional, The value to return if key is not set (default: null) * @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false) * * @return mixed Stored value or null if it does not exist */ - public static function get($uid, $family, $key, $default_value = null, $refresh = false) + public static function get($uid, $cat, $key, $default_value = null, $refresh = false) { - if (!isset(self::$adapter)) { - return self::$cache->getP($uid, $family, $key, $default_value); - } - - return self::$adapter->get($uid, $family, $key, $default_value, $refresh); + return self::$config->get($uid, $cat, $key, $default_value, $refresh); } /** * @brief Sets a configuration value for a user * - * Stores a config value ($value) in the category ($family) under the key ($key) - * for the user_id $uid. - * * @note Please do not store booleans - convert to 0/1 integer values! * * @param string $uid The user_id - * @param string $family The category of the configuration value + * @param string $cat The category of the configuration value * @param string $key The configuration key to set * @param mixed $value The value to store * * @return bool Operation success */ - public static function set($uid, $family, $key, $value) + public static function set($uid, $cat, $key, $value) { - if (!isset(self::$adapter)) { - return self::$cache->setP($uid, $family, $key, $value); - } - - return self::$adapter->set($uid, $family, $key, $value); + return self::$config->set($uid, $cat, $key, $value); } /** * @brief Deletes the given key from the users's configuration. * - * Removes the configured value from the stored cache in self::$config - * (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ) - * with the given $uid. + * @param string $uid The user_id + * @param string $cat The category of the configuration value + * @param string $key The configuration key to delete * - * @param string $uid The user_id - * @param string $family The category of the configuration value - * @param string $key The configuration key to delete - * - * @return mixed + * @return bool */ - public static function delete($uid, $family, $key) + public static function delete($uid, $cat, $key) { - if (!isset(self::$adapter)) { - return self::$cache->deleteP($uid, $family, $key); - } - - return self::$adapter->delete($uid, $family, $key); + return self::$config->delete($uid, $cat, $key); } } diff --git a/src/Database/DBA.php b/src/Database/DBA.php index edef30901..1c17d9aca 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -2,7 +2,7 @@ namespace Friendica\Database; -use Friendica\Core\Config\IConfigCache; +use Friendica\Core\Config\Cache\IConfigCache; use Friendica\Core\Logger; use Friendica\Core\System; use Friendica\Util\DateTimeFormat; diff --git a/src/Factory/ConfigFactory.php b/src/Factory/ConfigFactory.php index 269daea8b..6a30cf0e0 100644 --- a/src/Factory/ConfigFactory.php +++ b/src/Factory/ConfigFactory.php @@ -2,51 +2,66 @@ namespace Friendica\Factory; +use Friendica\Core; use Friendica\Core\Config; +use Friendica\Core\Config\Adapter; +use Friendica\Core\Config\Cache; class ConfigFactory { /** - * @param Config\ConfigCacheLoader $loader The Config Cache loader (INI/config/.htconfig) + * @param Cache\ConfigCacheLoader $loader The Config Cache loader (INI/config/.htconfig) * - * @return Config\ConfigCache + * @return Cache\ConfigCache */ - public static function createCache(Config\ConfigCacheLoader $loader) + public static function createCache(Cache\ConfigCacheLoader $loader) { - $configCache = new Config\ConfigCache(); + $configCache = new Cache\ConfigCache(); $loader->loadConfigFiles($configCache); return $configCache; } /** - * @param string $type The adapter type - * @param Config\IConfigCache $config The config cache of this adapter + * @param Cache\ConfigCache $configCache The config cache of this adapter * - * @return Config\IConfigAdapter + * @return Config\Configuration */ - public static function createConfig($type, Config\IConfigCache $config) + public static function createConfig(Cache\ConfigCache $configCache) { - if ($type == 'preload') { - return new Config\PreloadConfigAdapter($config); + if ($configCache->get('system', 'config_adapter') === 'preload') { + $configAdapter = new Adapter\PreloadConfigAdapter(); } else { - return new Config\JITConfigAdapter($config); + $configAdapter = new Adapter\JITConfigAdapter(); } + + $configuration = new Config\Configuration($configCache, $configAdapter); + + // Set the config in the static container for legacy usage + Core\Config::init($configuration); + + return $configuration; } /** - * @param string $type The adapter type - * @param Config\IPConfigCache $config The config cache of this adapter - * @param int $uid The UID of the current user + * @param Cache\ConfigCache $configCache The config cache of this adapter + * @param int $uid The UID of the current user * - * @return Config\IPConfigAdapter + * @return Config\PConfiguration */ - public static function createPConfig($type, Config\IPConfigCache $config, $uid = null) + public static function createPConfig(Cache\ConfigCache $configCache, $uid = null) { - if ($type == 'preload') { - return new Config\PreloadPConfigAdapter($config, $uid); + if ($configCache->get('system', 'config_adapter') === 'preload') { + $configAdapter = new Adapter\PreloadPConfigAdapter($uid); } else { - return new Config\JITPConfigAdapter($config); + $configAdapter = new Adapter\JITPConfigAdapter(); } + + $configuration = new Config\PConfiguration($configCache, $configAdapter); + + // Set the config in the static container for legacy usage + Core\PConfig::init($configuration); + + return $configuration; } } diff --git a/src/Factory/DBFactory.php b/src/Factory/DBFactory.php new file mode 100644 index 000000000..5970541c1 --- /dev/null +++ b/src/Factory/DBFactory.php @@ -0,0 +1,48 @@ +get('database', 'hostname'); + $db_user = $configCache->get('database', 'username'); + $db_pass = $configCache->get('database', 'password'); + $db_data = $configCache->get('database', 'database'); + $charset = $configCache->get('database', 'charset'); + + // Use environment variables for mysql if they are set beforehand + if (!empty($server['MYSQL_HOST']) + && !empty($server['MYSQL_USERNAME'] || !empty($server['MYSQL_USER'])) + && $server['MYSQL_PASSWORD'] !== false + && !empty($server['MYSQL_DATABASE'])) + { + $db_host = $server['MYSQL_HOST']; + if (!empty($server['MYSQL_PORT'])) { + $db_host .= ':' . $server['MYSQL_PORT']; + } + if (!empty($server['MYSQL_USERNAME'])) { + $db_user = $server['MYSQL_USERNAME']; + } else { + $db_user = $server['MYSQL_USER']; + } + $db_pass = (string) $server['MYSQL_PASSWORD']; + $db_data = $server['MYSQL_DATABASE']; + } + + if (Database\DBA::connect($configCache, $db_host, $db_user, $db_pass, $db_data, $charset)) { + // Loads DB_UPDATE_VERSION constant + Database\DBStructure::definition($configCache->get('system', 'basepath'), false); + } + + unset($db_host, $db_user, $db_pass, $db_data, $charset); + } +} diff --git a/src/Factory/LoggerFactory.php b/src/Factory/LoggerFactory.php index f6e2d6039..e9bacb38e 100644 --- a/src/Factory/LoggerFactory.php +++ b/src/Factory/LoggerFactory.php @@ -2,7 +2,7 @@ namespace Friendica\Factory; -use Friendica\Core\Config\ConfigCache; +use Friendica\Core\Config\Configuration; use Friendica\Core\Logger; use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Util\Logger\FriendicaDevelopHandler; @@ -22,12 +22,12 @@ class LoggerFactory /** * Creates a new PSR-3 compliant logger instances * - * @param string $channel The channel of the logger instance - * @param ConfigCache $config The config + * @param string $channel The channel of the logger instance + * @param Configuration $config The config * * @return LoggerInterface The PSR-3 compliant logger instance */ - public static function create($channel, ConfigCache $config = null) + public static function create($channel, Configuration $config) { $logger = new Monolog\Logger($channel); $logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor()); diff --git a/src/Module/Install.php b/src/Module/Install.php index 4fb4a932c..3414e887f 100644 --- a/src/Module/Install.php +++ b/src/Module/Install.php @@ -75,7 +75,7 @@ class Install extends BaseModule $dbdata = Strings::escapeTags(trim(defaults($_POST, 'dbdata', ''))); // If we cannot connect to the database, return to the previous step - if (!self::$installer->checkDB($a->getConfig(), $a->getProfiler(), $dbhost, $dbuser, $dbpass, $dbdata)) { + if (!self::$installer->checkDB($a->getConfigCache(), $a->getProfiler(), $dbhost, $dbuser, $dbpass, $dbdata)) { self::$currentWizardStep = self::DATABASE_CONFIG; } @@ -92,7 +92,7 @@ class Install extends BaseModule $adminmail = Strings::escapeTags(trim(defaults($_POST, 'adminmail', ''))); // If we cannot connect to the database, return to the Database config wizard - if (!self::$installer->checkDB($a->getConfig(), $a->getProfiler(), $dbhost, $dbuser, $dbpass, $dbdata)) { + if (!self::$installer->checkDB($a->getConfigCache(), $a->getProfiler(), $dbhost, $dbuser, $dbpass, $dbdata)) { self::$currentWizardStep = self::DATABASE_CONFIG; return; } diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php index 5c66711dc..dde61e856 100644 --- a/tests/DatabaseTest.php +++ b/tests/DatabaseTest.php @@ -5,7 +5,7 @@ namespace Friendica\Test; -use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Database\DBA; use Friendica\Factory; use Friendica\Util\BasePath; @@ -41,7 +41,7 @@ abstract class DatabaseTest extends MockedTest } $basedir = BasePath::create(dirname(__DIR__)); - $configLoader = new Config\ConfigCacheLoader($basedir); + $configLoader = new Cache\ConfigCacheLoader($basedir); $config = Factory\ConfigFactory::createCache($configLoader); $profiler = \Mockery::mock(Profiler::class); diff --git a/tests/Util/AppMockTrait.php b/tests/Util/AppMockTrait.php index 18188239f..66b95b04e 100644 --- a/tests/Util/AppMockTrait.php +++ b/tests/Util/AppMockTrait.php @@ -5,7 +5,6 @@ namespace Friendica\Test\Util; use Friendica\App; use Friendica\BaseObject; use Friendica\Core\Config; -use Friendica\Core\Config\ConfigCache; use Friendica\Render\FriendicaSmartyEngine; use Mockery\MockInterface; use org\bovigo\vfs\vfsStreamDirectory; @@ -21,7 +20,7 @@ trait AppMockTrait protected $app; /** - * @var MockInterface|ConfigCache The mocked Config Cache + * @var MockInterface|Config\Configuration The mocked Config Cache */ protected $configCache; @@ -29,9 +28,9 @@ trait AppMockTrait * Mock the App * * @param vfsStreamDirectory $root The root directory - * @param MockInterface|ConfigCache $config The config cache + * @param MockInterface|Config\Configuration $config The config cache */ - public function mockApp($root, $config) + public function mockApp($root, Config\Configuration $config) { $this->configCache = $config; // Mocking App and most used functions @@ -62,11 +61,14 @@ trait AppMockTrait ->andReturn('localhost'); $config ->shouldReceive('get') - ->with('system', 'theme', NULL) + ->with('system', 'theme', NULL, false) ->andReturn('system_theme'); + $config + ->shouldReceive('getConfig') + ->andReturn($config); $this->app - ->shouldReceive('getConfig') + ->shouldReceive('getConfigCache') ->andReturn($config); $this->app @@ -84,11 +86,6 @@ trait AppMockTrait // Initialize empty Config Config::init($config); - $configAdapter = \Mockery::mock('Friendica\Core\Config\IConfigAdapter'); - $configAdapter - ->shouldReceive('isConnected') - ->andReturn(false); - Config::setAdapter($configAdapter); BaseObject::setApp($this->app); } diff --git a/tests/include/ApiTest.php b/tests/include/ApiTest.php index 41f5c0fdf..7f2299d51 100644 --- a/tests/include/ApiTest.php +++ b/tests/include/ApiTest.php @@ -7,6 +7,7 @@ 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; @@ -36,8 +37,11 @@ class ApiTest extends DatabaseTest public function setUp() { $basedir = BasePath::create(dirname(__DIR__) . '/../'); - $configLoader = new Config\ConfigCacheLoader($basedir); - $config = Factory\ConfigFactory::createCache($configLoader); + $configLoader = new Cache\ConfigCacheLoader($basedir); + $configCache = Factory\ConfigFactory::createCache($configLoader); + Factory\DBFactory::init($configCache, $_SERVER); + $config = Factory\ConfigFactory::createConfig($configCache); + $pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('test', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); $this->app = new App($config, $logger, $profiler, false); diff --git a/tests/src/App/ModeTest.php b/tests/src/App/ModeTest.php index 19dad07cd..5a5c4c87e 100644 --- a/tests/src/App/ModeTest.php +++ b/tests/src/App/ModeTest.php @@ -90,19 +90,14 @@ class ModeTest extends MockedTest $this->mockConnected(true, 1); $this->mockFetchFirst('SHOW TABLES LIKE \'config\'', true, 1); - $config = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $config = \Mockery::mock('Friendica\Core\Config\Configuration'); $config ->shouldReceive('get') - ->with('system', 'maintenance', null) + ->with('system', 'maintenance', null, false) ->andReturn(true) ->once(); // Initialize empty Config Config::init($config); - $configAdapter = \Mockery::mock('Friendica\Core\Config\IConfigAdapter'); - $configAdapter - ->shouldReceive('isConnected') - ->andReturn(false); - Config::setAdapter($configAdapter); $mode = new Mode($this->root->url()); $mode->determine(); @@ -123,19 +118,14 @@ class ModeTest extends MockedTest $this->mockConnected(true, 1); $this->mockFetchFirst('SHOW TABLES LIKE \'config\'', true, 1); - $config = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $config = \Mockery::mock('Friendica\Core\Config\Configuration'); $config ->shouldReceive('get') - ->with('system', 'maintenance', null) + ->with('system', 'maintenance', null, false) ->andReturn(false) ->once(); // Initialize empty Config Config::init($config); - $configAdapter = \Mockery::mock('Friendica\Core\Config\IConfigAdapter'); - $configAdapter - ->shouldReceive('isConnected') - ->andReturn(false); - Config::setAdapter($configAdapter); $mode = new Mode($this->root->url()); $mode->determine(); diff --git a/tests/src/BaseObjectTest.php b/tests/src/BaseObjectTest.php index 784944c3a..39741eb9e 100644 --- a/tests/src/BaseObjectTest.php +++ b/tests/src/BaseObjectTest.php @@ -31,7 +31,7 @@ class BaseObjectTest extends TestCase { $baseObject = new BaseObject(); $this->setUpVfsDir(); - $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $configMock = \Mockery::mock('Friendica\Core\Config\Configuration'); $this->mockApp($this->root, $configMock); $this->assertNull($baseObject->setApp($this->app)); diff --git a/tests/src/Core/Cache/CacheTest.php b/tests/src/Core/Cache/CacheTest.php index e8bd65cbf..961ac9e1b 100644 --- a/tests/src/Core/Cache/CacheTest.php +++ b/tests/src/Core/Cache/CacheTest.php @@ -67,7 +67,7 @@ abstract class CacheTest extends MockedTest protected function setUp() { $this->setUpVfsDir(); - $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $configMock = \Mockery::mock('Friendica\Core\Config\Configuration'); $this->mockApp($this->root, $configMock); $this->app ->shouldReceive('getHostname') diff --git a/tests/src/Core/Cache/MemcacheCacheDriverTest.php b/tests/src/Core/Cache/MemcacheCacheDriverTest.php index 7832344a8..5017b6967 100644 --- a/tests/src/Core/Cache/MemcacheCacheDriverTest.php +++ b/tests/src/Core/Cache/MemcacheCacheDriverTest.php @@ -14,12 +14,12 @@ class MemcacheCacheDriverTest extends MemoryCacheTest { $this->configCache ->shouldReceive('get') - ->with('system', 'memcache_host', NULL) + ->with('system', 'memcache_host', NULL, false) ->andReturn('localhost'); $this->configCache ->shouldReceive('get') - ->with('system', 'memcache_port', NULL) + ->with('system', 'memcache_port', NULL, false) ->andReturn(11211); $this->cache = CacheDriverFactory::create('memcache'); diff --git a/tests/src/Core/Cache/MemcachedCacheDriverTest.php b/tests/src/Core/Cache/MemcachedCacheDriverTest.php index fe401f97d..7c6835359 100644 --- a/tests/src/Core/Cache/MemcachedCacheDriverTest.php +++ b/tests/src/Core/Cache/MemcachedCacheDriverTest.php @@ -14,7 +14,7 @@ class MemcachedCacheDriverTest extends MemoryCacheTest { $this->configCache ->shouldReceive('get') - ->with('system', 'memcached_hosts', NULL) + ->with('system', 'memcached_hosts', NULL, false) ->andReturn([0 => 'localhost, 11211']); $this->cache = CacheDriverFactory::create('memcached'); diff --git a/tests/src/Core/Cache/RedisCacheDriverTest.php b/tests/src/Core/Cache/RedisCacheDriverTest.php index 0a3dba439..d36e6b826 100644 --- a/tests/src/Core/Cache/RedisCacheDriverTest.php +++ b/tests/src/Core/Cache/RedisCacheDriverTest.php @@ -14,12 +14,12 @@ class RedisCacheDriverTest extends MemoryCacheTest { $this->configCache ->shouldReceive('get') - ->with('system', 'redis_host', NULL) + ->with('system', 'redis_host', NULL, false) ->andReturn('localhost'); $this->configCache ->shouldReceive('get') - ->with('system', 'redis_port', NULL) + ->with('system', 'redis_port', NULL, false) ->andReturn(null); $this->cache = CacheDriverFactory::create('redis'); diff --git a/tests/src/Core/Config/ConfigCacheLoaderTest.php b/tests/src/Core/Config/Cache/ConfigCacheLoaderTest.php similarity index 95% rename from tests/src/Core/Config/ConfigCacheLoaderTest.php rename to tests/src/Core/Config/Cache/ConfigCacheLoaderTest.php index 6be89bc40..f91f267c7 100644 --- a/tests/src/Core/Config/ConfigCacheLoaderTest.php +++ b/tests/src/Core/Config/Cache/ConfigCacheLoaderTest.php @@ -1,9 +1,9 @@ delConfigFile('local.config.php'); $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . @@ -91,6 +92,7 @@ class ConfigCacheLoaderTest extends MockedTest $this->delConfigFile('local.config.php'); $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . @@ -122,6 +124,7 @@ class ConfigCacheLoaderTest extends MockedTest $this->delConfigFile('local.config.php'); $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . @@ -160,6 +163,7 @@ class ConfigCacheLoaderTest extends MockedTest vfsStream::create($structure, $this->root); $file = dirname(__DIR__) . DIRECTORY_SEPARATOR . + '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . diff --git a/tests/src/Core/Config/ConfigCacheTest.php b/tests/src/Core/Config/Cache/ConfigCacheTest.php similarity index 62% rename from tests/src/Core/Config/ConfigCacheTest.php rename to tests/src/Core/Config/Cache/ConfigCacheTest.php index 25ea6030f..7b56ca646 100644 --- a/tests/src/Core/Config/ConfigCacheTest.php +++ b/tests/src/Core/Config/Cache/ConfigCacheTest.php @@ -1,8 +1,8 @@ loadConfigArray($data); + $configCache->load($data); $this->assertConfigValues($data, $configCache); } @@ -67,18 +67,38 @@ class ConfigCacheTest extends MockedTest ]; $configCache = new ConfigCache(); - $configCache->loadConfigArray($data); - $configCache->loadConfigArray($override); + $configCache->load($data); + $configCache->load($override); $this->assertConfigValues($data, $configCache); // override the value - $configCache->loadConfigArray($override, true); + $configCache->load($override, true); $this->assertEquals($override['system']['test'], $configCache->get('system', 'test')); $this->assertEquals($override['system']['boolTrue'], $configCache->get('system', 'boolTrue')); } + /** + * Test the loadConfigArray() method with wrong/empty datasets + */ + public function testLoadConfigArrayWrong() + { + $configCache = new ConfigCache(); + + // empty dataset + $configCache->load([]); + $this->assertEmpty($configCache->getAll()); + + // wrong dataset + $configCache->load(['system' => 'not_array']); + $this->assertEmpty($configCache->getAll()); + + // incomplete dataset (key is integer ID of the array) + $configCache->load(['system' => ['value']]); + $this->assertEquals('value', $configCache->get('system', 0)); + } + /** * Test the getAll() method * @dataProvider dataTests @@ -86,14 +106,12 @@ class ConfigCacheTest extends MockedTest public function testGetAll($data) { $configCache = new ConfigCache(); - $configCache->loadConfigArray($data); + $configCache->load($data); $all = $configCache->getAll(); $this->assertContains($data['system'], $all); - - // config values are stored directly in the array base - $this->assertEquals($data['config']['a'], $all['a']); + $this->assertContains($data['config'], $all); } /** @@ -113,6 +131,33 @@ class ConfigCacheTest extends MockedTest $this->assertConfigValues($data, $configCache); } + /** + * Test the get() method without a value + */ + public function testGetEmpty() + { + $configCache = new ConfigCache(); + + $this->assertEquals('!!', $configCache->get('something', 'value')); + } + + /** + * Test the has() method + */ + public function testHas() + { + $configCache = new ConfigCache(); + + $this->assertFalse($configCache->has('system', 'test')); + + $configCache->set('system', 'test', 'it'); + $this->assertTrue($configCache->has('system', 'test')); + + $this->assertFalse($configCache->has('system', null)); + $configCache->set('system', null, 'it'); + $this->assertTrue($configCache->has('system', null)); + } + /** * Test the delete() method * @dataProvider dataTests @@ -172,4 +217,22 @@ class ConfigCacheTest extends MockedTest $this->assertEmpty($configCache->getAll()); } + + /** + * Test the hasP() method + */ + public function testHasP() + { + $configCache = new ConfigCache(); + $uid = 345; + + $this->assertFalse($configCache->hasP($uid, 'system', 'test')); + + $configCache->setP($uid, 'system', 'test', 'it'); + $this->assertTrue($configCache->hasP($uid, 'system', 'test')); + + $this->assertFalse($configCache->hasP($uid, 'system', null)); + $configCache->setP($uid, 'system', null, 'it'); + $this->assertTrue($configCache->hasP($uid, 'system', null)); + } } diff --git a/tests/src/Core/Config/ConfigurationTest.php b/tests/src/Core/Config/ConfigurationTest.php new file mode 100644 index 000000000..6ce81a41b --- /dev/null +++ b/tests/src/Core/Config/ConfigurationTest.php @@ -0,0 +1,215 @@ +shouldReceive('isConnected')->andReturn(false)->once(); + + $configuration = new Configuration($configCache, $configAdapter); + + $this->assertInstanceOf(IConfigCache::class, $configuration->getCache()); + } + + /** + * Test if the configuration load() method + */ + public function testCacheLoad() + { + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->twice(); + // constructor loading + $configAdapter->shouldReceive('load')->andReturn([])->once(); + // expected loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + + $configuration = new Configuration($configCache, $configAdapter); + $configuration->load('testing'); + + $this->assertEquals('it', $configuration->get('testing', 'test')); + $this->assertEquals('it', $configuration->getCache()->get('testing', 'test')); + } + + /** + * Test if the configuration load() method with overwrite + */ + public function testCacheLoadDouble() + { + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); + // constructor loading + $configAdapter->shouldReceive('load')->andReturn([])->once(); + // expected loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + // expected next loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'again']])->once(); + + $configuration = new Configuration($configCache, $configAdapter); + $configuration->load('testing'); + + $this->assertEquals('it', $configuration->get('testing', 'test')); + $this->assertEquals('it', $configuration->getCache()->get('testing', 'test')); + + $configuration->load('testing'); + + $this->assertEquals('again', $configuration->get('testing', 'test')); + $this->assertEquals('again', $configuration->getCache()->get('testing', 'test')); + } + + /** + * Test if the configuration get() and set() methods without adapter + */ + public function testSetGetWithoutDB() + { + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->twice(); + + $configuration = new Configuration($configCache, $configAdapter); + + $this->assertTrue($configuration->set('test', 'it', 'now')); + + $this->assertEquals('now', $configuration->get('test', 'it')); + $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + } + + /** + * Test if the configuration get() and set() methods with adapter + */ + public function testSetGetWithDB() + { + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->twice(); + // constructor loading + $configAdapter->shouldReceive('load')->andReturn([])->once(); + $configAdapter->shouldReceive('set')->with('test', 'it', 'now')->andReturn(true)->once(); + + $configuration = new Configuration($configCache, $configAdapter); + + $this->assertTrue($configuration->set('test', 'it', 'now')); + + $this->assertEquals('now', $configuration->get('test', 'it')); + $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + } + + /** + * Test the configuration get() method with wrong value and no db + */ + public function testGetWrongWithoutDB() + { + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(4); + + $configuration = new Configuration($configCache, $configAdapter); + + // without refresh + $this->assertNull($configuration->get('test', 'it')); + + /// beware that the cache returns '!!' and not null for a non existing value + $this->assertEquals('!!', $configuration->getCache()->get('test', 'it')); + + // with default value + $this->assertEquals('default', $configuration->get('test', 'it', 'default')); + + // with default value and refresh + $this->assertEquals('default', $configuration->get('test', 'it', 'default', true)); + } + + /** + * Test the configuration get() method with refresh + */ + public function testGetWithRefresh() + { + $configCache = new ConfigCache(['test' => ['it' => 'now']]); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); + // constructor loading + $configAdapter->shouldReceive('load')->andReturn([])->once(); + $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn('again')->once(); + $configAdapter->shouldReceive('get')->with('test', 'not')->andReturn('!!')->once(); + + $configuration = new Configuration($configCache, $configAdapter); + + // without refresh + $this->assertEquals('now', $configuration->get('test', 'it')); + $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + + // with refresh + $this->assertEquals('again', $configuration->get('test', 'it', null, true)); + $this->assertEquals('again', $configuration->getCache()->get('test', 'it')); + + // without refresh and wrong value and default + $this->assertEquals('default', $configuration->get('test', 'not', 'default')); + $this->assertEquals('!!', $configuration->getCache()->get('test', 'not')); + } + + /** + * Test the configuration delete() method without adapter + */ + public function testDeleteWithoutDB() + { + $configCache = new ConfigCache(['test' => ['it' => 'now']]); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3); + + $configuration = new Configuration($configCache, $configAdapter); + + $this->assertEquals('now', $configuration->get('test', 'it')); + $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + + $this->assertTrue($configuration->delete('test', 'it')); + $this->assertNull($configuration->get('test', 'it')); + $this->assertEquals('!!', $configuration->getCache()->get('test', 'it')); + + $this->assertEmpty($configuration->getCache()->getAll()); + } + + /** + * Test the configuration delete() method with adapter + */ + public function testDeleteWithDB() + { + $configCache = new ConfigCache(['test' => ['it' => 'now', 'quarter' => 'true']]); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(5); + // constructor loading + $configAdapter->shouldReceive('load')->andReturn([])->once(); + $configAdapter->shouldReceive('delete')->with('test', 'it')->andReturn(false)->once(); + + $configAdapter->shouldReceive('delete')->with('test', 'second')->andReturn(true)->once(); + $configAdapter->shouldReceive('delete')->with('test', 'third')->andReturn(false)->once(); + $configAdapter->shouldReceive('delete')->with('test', 'quarter')->andReturn(true)->once(); + + $configuration = new Configuration($configCache, $configAdapter); + + $this->assertEquals('now', $configuration->get('test', 'it')); + $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + + // delete from cache only + $this->assertTrue($configuration->delete('test', 'it')); + // delete from db only + $this->assertTrue($configuration->delete('test', 'second')); + // no delete + $this->assertFalse($configuration->delete('test', 'third')); + // delete both + $this->assertTrue($configuration->delete('test', 'quarter')); + + $this->assertEmpty($configuration->getCache()->getAll()); + } +} diff --git a/tests/src/Core/Config/PConfigurationTest.php b/tests/src/Core/Config/PConfigurationTest.php new file mode 100644 index 000000000..3d8fb586c --- /dev/null +++ b/tests/src/Core/Config/PConfigurationTest.php @@ -0,0 +1,186 @@ +shouldReceive('isConnected')->andReturn(true)->once(); + // expected loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + $configuration->load($uid, 'testing'); + + $this->assertEquals('it', $configuration->get($uid, 'testing', 'test')); + } + + /** + * Test if the configuration load() method with overwrite + */ + public function testCacheLoadDouble() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->twice(); + // expected loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + // expected next loading + $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'again']])->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + $configuration->load($uid, 'testing'); + + $this->assertEquals('it', $configuration->get($uid, 'testing', 'test')); + + $configuration->load($uid, 'testing'); + + $this->assertEquals('again', $configuration->get($uid, 'testing', 'test')); + } + + /** + * Test if the configuration get() and set() methods without adapter + */ + public function testSetGetWithoutDB() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + + $this->assertTrue($configuration->set($uid, 'test', 'it', 'now')); + + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + } + + /** + * Test if the configuration get() and set() methods with adapter + */ + public function testSetGetWithDB() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->once(); + $configAdapter->shouldReceive('set')->with($uid, 'test', 'it', 'now')->andReturn(true)->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + + $this->assertTrue($configuration->set($uid, 'test', 'it', 'now')); + + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + } + + /** + * Test the configuration get() method with wrong value and no db + */ + public function testGetWrongWithoutDB() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3); + + $configuration = new PConfiguration($configCache, $configAdapter); + + // without refresh + $this->assertNull($configuration->get($uid, 'test', 'it')); + + // with default value + $this->assertEquals('default', $configuration->get($uid, 'test', 'it', 'default')); + + // with default value and refresh + $this->assertEquals('default', $configuration->get($uid, 'test', 'it', 'default', true)); + } + + /** + * Test the configuration get() method with refresh + */ + public function testGetWithRefresh() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); + $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn('now')->once(); + $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn('again')->once(); + $configAdapter->shouldReceive('get')->with($uid, 'test', 'not')->andReturn('!!')->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + + // without refresh + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + // use the cache again + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + + // with refresh (and load the second value out of the db) + $this->assertEquals('again', $configuration->get($uid, 'test', 'it', null, true)); + + // without refresh and wrong value and default + $this->assertEquals('default', $configuration->get($uid, 'test', 'not', 'default')); + } + + /** + * Test the configuration delete() method without adapter + */ + public function testDeleteWithoutDB() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3); + + $configuration = new PConfiguration($configCache, $configAdapter); + + $this->assertTrue($configuration->set($uid, 'test', 'it', 'now')); + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + + $this->assertTrue($configuration->delete($uid, 'test', 'it')); + $this->assertNull($configuration->get($uid, 'test', 'it')); + } + + /** + * Test the configuration delete() method with adapter + */ + public function testDeleteWithDB() + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(5); + $configAdapter->shouldReceive('set')->with($uid, 'test', 'it', 'now')->andReturn(false)->once(); + $configAdapter->shouldReceive('delete')->with($uid, 'test', 'it')->andReturn(false)->once(); + + $configAdapter->shouldReceive('delete')->with($uid, 'test', 'second')->andReturn(true)->once(); + $configAdapter->shouldReceive('delete')->with($uid, 'test', 'third')->andReturn(false)->once(); + $configAdapter->shouldReceive('delete')->with($uid, 'test', 'quarter')->andReturn(true)->once(); + + $configuration = new PConfiguration($configCache, $configAdapter); + + $this->assertFalse($configuration->set($uid, 'test', 'it', 'now')); + $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + + // delete from set + $this->assertTrue($configuration->delete($uid, 'test', 'it')); + // delete from db only + $this->assertTrue($configuration->delete($uid, 'test', 'second')); + // no delete + $this->assertFalse($configuration->delete($uid, 'test', 'third')); + // delete both + $this->assertTrue($configuration->delete($uid, 'test', 'quarter')); + } +} diff --git a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php index 41ccce0b2..ce3dac02c 100644 --- a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php +++ b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php @@ -54,7 +54,7 @@ class AutomaticInstallationConsoleTest extends ConsoleTest $this->configCache ->shouldReceive('get') - ->with('config', 'php_path', NULL) + ->with('config', 'php_path', NULL, false) ->andReturn(false); $this->mockL10nT(); diff --git a/tests/src/Core/Console/ConfigConsoleTest.php b/tests/src/Core/Console/ConfigConsoleTest.php index 505c4f794..5b7d14906 100644 --- a/tests/src/Core/Console/ConfigConsoleTest.php +++ b/tests/src/Core/Console/ConfigConsoleTest.php @@ -39,7 +39,7 @@ class ConfigConsoleTest extends ConsoleTest ->once(); $this->configCache ->shouldReceive('get') - ->with('config', 'test', NULL) + ->with('config', 'test', NULL, false) ->andReturn('now') ->twice(); @@ -52,7 +52,7 @@ class ConfigConsoleTest extends ConsoleTest $this->configCache ->shouldReceive('get') - ->with('config', 'test', null) + ->with('config', 'test', null, false) ->andReturn('now') ->once(); @@ -64,7 +64,7 @@ class ConfigConsoleTest extends ConsoleTest $this->configCache ->shouldReceive('get') - ->with('config', 'test', null) + ->with('config', 'test', null, false) ->andReturn(null) ->once(); @@ -79,7 +79,7 @@ class ConfigConsoleTest extends ConsoleTest $testArray = [1, 2, 3]; $this->configCache ->shouldReceive('get') - ->with('config', 'test', null) + ->with('config', 'test', null, false) ->andReturn($testArray) ->once(); @@ -107,7 +107,7 @@ class ConfigConsoleTest extends ConsoleTest function testVerbose() { $this->configCache ->shouldReceive('get') - ->with('test', 'it', null) + ->with('test', 'it', null, false) ->andReturn('now') ->once(); $console = new Config($this->consoleArgv); @@ -140,7 +140,7 @@ CONF; ->once(); $this->configCache ->shouldReceive('get') - ->with('test', 'it', NULL) + ->with('test', 'it', NULL, false) ->andReturn(NULL) ->once(); $console = new Config(); diff --git a/tests/src/Core/Console/ConsoleTest.php b/tests/src/Core/Console/ConsoleTest.php index 715e68ab2..f733175d3 100644 --- a/tests/src/Core/Console/ConsoleTest.php +++ b/tests/src/Core/Console/ConsoleTest.php @@ -3,7 +3,7 @@ namespace Friendica\Test\src\Core\Console; use Asika\SimpleConsole\Console; -use Friendica\Core\Config\ConfigCache; +use Friendica\Core\Config\Configuration; use Friendica\Test\MockedTest; use Friendica\Test\Util\AppMockTrait; use Friendica\Test\Util\Intercept; @@ -31,7 +31,7 @@ abstract class ConsoleTest extends MockedTest Intercept::setUp(); $this->setUpVfsDir(); - $configMock = \Mockery::mock(ConfigCache::class); + $configMock = \Mockery::mock(Configuration::class); $this->mockApp($this->root, $configMock); $profileMock = \Mockery::mock(Profiler::class); $this->app->shouldReceive('getProfiler')->andReturn($profileMock); diff --git a/tests/src/Core/Lock/LockTest.php b/tests/src/Core/Lock/LockTest.php index ab8e1b2f2..c1378aa16 100644 --- a/tests/src/Core/Lock/LockTest.php +++ b/tests/src/Core/Lock/LockTest.php @@ -27,7 +27,7 @@ abstract class LockTest extends MockedTest { // Reusable App object $this->setUpVfsDir(); - $configMock = \Mockery::mock('Friendica\Core\Config\ConfigCache'); + $configMock = \Mockery::mock('Friendica\Core\Config\Configuration'); $this->mockApp($this->root, $configMock); $this->app ->shouldReceive('getHostname') diff --git a/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php b/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php index 46f29f52e..0e118c5dd 100644 --- a/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php +++ b/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php @@ -15,12 +15,12 @@ class MemcacheCacheLockDriverTest extends LockTest { $this->configCache ->shouldReceive('get') - ->with('system', 'memcache_host', NULL) + ->with('system', 'memcache_host', NULL, false) ->andReturn('localhost'); $this->configCache ->shouldReceive('get') - ->with('system', 'memcache_port', NULL) + ->with('system', 'memcache_port', NULL, false) ->andReturn(11211); return new CacheLockDriver(CacheDriverFactory::create('memcache')); diff --git a/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php b/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php index 72271c98b..fe490a38c 100644 --- a/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php +++ b/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php @@ -15,7 +15,7 @@ class MemcachedCacheLockDriverTest extends LockTest { $this->configCache ->shouldReceive('get') - ->with('system', 'memcached_hosts', NULL) + ->with('system', 'memcached_hosts', NULL, false) ->andReturn([0 => 'localhost, 11211']); return new CacheLockDriver(CacheDriverFactory::create('memcached')); diff --git a/tests/src/Core/Lock/RedisCacheLockDriverTest.php b/tests/src/Core/Lock/RedisCacheLockDriverTest.php index 0c9deea16..f5d0a648f 100644 --- a/tests/src/Core/Lock/RedisCacheLockDriverTest.php +++ b/tests/src/Core/Lock/RedisCacheLockDriverTest.php @@ -15,12 +15,12 @@ class RedisCacheLockDriverTest extends LockTest { $this->configCache ->shouldReceive('get') - ->with('system', 'redis_host', NULL) + ->with('system', 'redis_host', NULL, false) ->andReturn('localhost'); $this->configCache ->shouldReceive('get') - ->with('system', 'redis_port', NULL) + ->with('system', 'redis_port', NULL, false) ->andReturn(null); return new CacheLockDriver(CacheDriverFactory::create('redis')); diff --git a/tests/src/Core/Lock/SemaphoreLockDriverTest.php b/tests/src/Core/Lock/SemaphoreLockDriverTest.php index c2b941457..bf422f2f8 100644 --- a/tests/src/Core/Lock/SemaphoreLockDriverTest.php +++ b/tests/src/Core/Lock/SemaphoreLockDriverTest.php @@ -14,7 +14,7 @@ class SemaphoreLockDriverTest extends LockTest $this->configCache ->shouldReceive('get') - ->with('system', 'temppath', NULL) + ->with('system', 'temppath', NULL, false) ->andReturn('/tmp/'); } diff --git a/tests/src/Database/DBATest.php b/tests/src/Database/DBATest.php index c6981a91d..a4a715575 100644 --- a/tests/src/Database/DBATest.php +++ b/tests/src/Database/DBATest.php @@ -3,6 +3,7 @@ namespace Friendica\Test\Database; use Friendica\App; use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Database\DBA; use Friendica\Factory; use Friendica\Test\DatabaseTest; @@ -13,8 +14,11 @@ class DBATest extends DatabaseTest public function setUp() { $basedir = BasePath::create(dirname(__DIR__) . '/../../'); - $configLoader = new Config\ConfigCacheLoader($basedir); - $config = Factory\ConfigFactory::createCache($configLoader); + $configLoader = new Cache\ConfigCacheLoader($basedir); + $configCache = Factory\ConfigFactory::createCache($configLoader); + Factory\DBFactory::init($configCache, $_SERVER); + $config = Factory\ConfigFactory::createConfig($configCache); + $pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('test', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); $this->app = new App($config, $logger, $profiler, false); diff --git a/tests/src/Database/DBStructureTest.php b/tests/src/Database/DBStructureTest.php index 250df0693..6a5e25e76 100644 --- a/tests/src/Database/DBStructureTest.php +++ b/tests/src/Database/DBStructureTest.php @@ -3,7 +3,7 @@ namespace Friendica\Test\Database; use Friendica\App; -use Friendica\Core\Config; +use Friendica\Core\Config\Cache; use Friendica\Database\DBStructure; use Friendica\Factory; use Friendica\Test\DatabaseTest; @@ -14,8 +14,11 @@ class DBStructureTest extends DatabaseTest public function setUp() { $basedir = BasePath::create(dirname(__DIR__) . '/../../'); - $configLoader = new Config\ConfigCacheLoader($basedir); - $config = Factory\ConfigFactory::createCache($configLoader); + $configLoader = new Cache\ConfigCacheLoader($basedir); + $configCache = Factory\ConfigFactory::createCache($configLoader); + Factory\DBFactory::init($configCache, $_SERVER); + $config = Factory\ConfigFactory::createConfig($configCache); + $pconfig = Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('test', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); $this->app = new App($config, $logger, $profiler, false); From 80f1feabe5ecf9b09b76627ba4b114ae10ddcaf6 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 11 Feb 2019 21:13:53 +0100 Subject: [PATCH 13/20] Refactoring Logging to use Configuration --- bin/auth_ejabberd.php | 3 +- bin/console.php | 3 +- bin/daemon.php | 3 +- bin/worker.php | 3 +- index.php | 3 +- src/App.php | 29 ------ src/Core/Config.php | 4 - src/Core/Config/Cache/ConfigCache.php | 12 ++- src/Core/Logger.php | 61 +----------- src/Factory/DBFactory.php | 8 ++ src/Factory/LoggerFactory.php | 97 +++++++++++-------- tests/include/ApiTest.php | 2 +- .../src/Core/Config/Cache/ConfigCacheTest.php | 59 +++++++++-- 13 files changed, 141 insertions(+), 146 deletions(-) diff --git a/bin/auth_ejabberd.php b/bin/auth_ejabberd.php index 7682674d7..003faae1f 100755 --- a/bin/auth_ejabberd.php +++ b/bin/auth_ejabberd.php @@ -59,7 +59,8 @@ $configLoader = new Cache\ConfigCacheLoader($basedir); $configCache = Factory\ConfigFactory::createCache($configLoader); Factory\DBFactory::init($configCache, $_SERVER); $config = Factory\ConfigFactory::createConfig($configCache); -$pconfig = Factory\ConfigFactory::createPConfig($configCache); +// needed to call PConfig::init() +Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('auth_ejabberd', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/bin/console.php b/bin/console.php index 9fee605b2..2b0d58821 100755 --- a/bin/console.php +++ b/bin/console.php @@ -12,7 +12,8 @@ $configLoader = new Cache\ConfigCacheLoader($basedir); $configCache = Factory\ConfigFactory::createCache($configLoader); Factory\DBFactory::init($configCache, $_SERVER); $config = Factory\ConfigFactory::createConfig($configCache); -$pconfig = Factory\ConfigFactory::createPConfig($configCache); +// needed to call PConfig::init() +Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('console', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/bin/daemon.php b/bin/daemon.php index 2b106b62d..f2970a518 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -39,7 +39,8 @@ $configLoader = new Cache\ConfigCacheLoader($basedir); $configCache = Factory\ConfigFactory::createCache($configLoader); Factory\DBFactory::init($configCache, $_SERVER); $config = Factory\ConfigFactory::createConfig($configCache); -$pconfig = Factory\ConfigFactory::createPConfig($configCache); +// needed to call PConfig::init() +Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('daemon', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/bin/worker.php b/bin/worker.php index 0a9b4cb38..530333127 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -37,7 +37,8 @@ $configLoader = new Cache\ConfigCacheLoader($basedir); $configCache = Factory\ConfigFactory::createCache($configLoader); Factory\DBFactory::init($configCache, $_SERVER); $config = Factory\ConfigFactory::createConfig($configCache); -$pconfig = Factory\ConfigFactory::createPConfig($configCache); +// needed to call PConfig::init() +Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('worker', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/index.php b/index.php index 9ef9490b3..66f023965 100644 --- a/index.php +++ b/index.php @@ -20,7 +20,8 @@ $configLoader = new Cache\ConfigCacheLoader($basedir); $configCache = Factory\ConfigFactory::createCache($configLoader); Factory\DBFactory::init($configCache, $_SERVER); $config = Factory\ConfigFactory::createConfig($configCache); -$pconfig = Factory\ConfigFactory::createPConfig($configCache); +// needed to call PConfig::init() +Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('index', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); diff --git a/src/App.php b/src/App.php index e715e6ced..3189b2da7 100644 --- a/src/App.php +++ b/src/App.php @@ -109,11 +109,6 @@ class App */ public $mobileDetect; - /** - * @var LoggerInterface The current logger of this App - */ - private $logger; - /** * @var Configuration The config */ @@ -339,35 +334,13 @@ class App return $this->mode; } - /** - * Returns the Logger of the Application - * - * @return LoggerInterface The Logger - * @throws InternalServerErrorException when the logger isn't created - */ - public function getLogger() - { - if (empty($this->logger)) { - throw new InternalServerErrorException('Logger of the Application is not defined'); - } - - return $this->logger; - } - /** * Reloads the whole app instance */ public function reload() { - $this->getMode()->determine($this->basePath); - $this->determineURLPath(); - if ($this->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - Core\Config::load(); - } - - // again because DB-config could change the config $this->getMode()->determine($this->basePath); if ($this->getMode()->has(App\Mode::DBAVAILABLE)) { @@ -382,8 +355,6 @@ class App Core\L10n::init(); $this->process_id = Core\System::processID('log'); - - Core\Logger::setLogger($this->logger); } /** diff --git a/src/Core/Config.php b/src/Core/Config.php index 405d14d12..4bf9c5b11 100644 --- a/src/Core/Config.php +++ b/src/Core/Config.php @@ -8,10 +8,6 @@ */ namespace Friendica\Core; -use Friendica\Core\Config\ConfigCache; -use Friendica\Core\Config\IConfigAdapter; -use Friendica\Core\Config\IConfigCache; - /** * @brief Arbitrary system configuration storage * diff --git a/src/Core/Config/Cache/ConfigCache.php b/src/Core/Config/Cache/ConfigCache.php index b1172c0c8..54da327db 100644 --- a/src/Core/Config/Cache/ConfigCache.php +++ b/src/Core/Config/Cache/ConfigCache.php @@ -55,6 +55,8 @@ class ConfigCache implements IConfigCache, IPConfigCache { if (isset($this->config[$cat][$key])) { return $this->config[$cat][$key]; + } elseif ($key == null && isset($this->config[$cat])) { + return $this->config[$cat]; } else { return '!!'; } @@ -65,8 +67,8 @@ class ConfigCache implements IConfigCache, IPConfigCache */ public function has($cat, $key = null) { - return isset($this->config[$cat][$key]) - && $this->config[$cat][$key] !== '!!'; + return (isset($this->config[$cat][$key]) && $this->config[$cat][$key] !== '!!') || + ($key == null && isset($this->config[$cat]) && $this->config[$cat] !== '!!' && is_array($this->config[$cat])); } /** @@ -105,8 +107,8 @@ class ConfigCache implements IConfigCache, IPConfigCache */ public function hasP($uid, $cat, $key = null) { - return isset($this->config[$uid][$cat][$key]) - && $this->config[$uid][$cat][$key] !== '!!'; + return (isset($this->config[$uid][$cat][$key]) && $this->config[$uid][$cat][$key] !== '!!') || + ($key == null && isset($this->config[$uid][$cat]) && $this->config[$uid][$cat] !== '!!' && is_array($this->config[$uid][$cat])); } /** @@ -144,6 +146,8 @@ class ConfigCache implements IConfigCache, IPConfigCache { if (isset($this->config[$uid][$cat][$key])) { return $this->config[$uid][$cat][$key]; + } elseif ($key == null && isset($this->config[$uid][$cat])) { + return $this->config[$uid][$cat]; } else { return '!!'; } diff --git a/src/Core/Logger.php b/src/Core/Logger.php index e42f2f033..a2e587342 100644 --- a/src/Core/Logger.php +++ b/src/Core/Logger.php @@ -5,8 +5,6 @@ namespace Friendica\Core; use Friendica\BaseObject; -use Friendica\Factory\LoggerFactory; -use Friendica\Network\HTTPException\InternalServerErrorException; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; @@ -67,73 +65,22 @@ class Logger extends BaseObject /** * Sets the default logging handler for Friendica. - * @todo Can be combined with other handlers too if necessary, could be configurable. * * @param LoggerInterface $logger The Logger instance of this Application - * - * @throws InternalServerErrorException if the logger factory is incompatible to this logger */ public static function setLogger($logger) { - $debugging = Config::get('system', 'debugging'); - $logfile = Config::get('system', 'logfile'); - $loglevel = Config::get('system', 'loglevel'); - - if (!$debugging || !$logfile) { - return; - } - - $loglevel = self::mapLegacyConfigDebugLevel((string)$loglevel); - - LoggerFactory::addStreamHandler($logger, $logfile, $loglevel); - self::$logger = $logger; - - $logfile = Config::get('system', 'dlogfile'); - - if (!$logfile) { - return; - } - - $developIp = Config::get('system', 'dlogip'); - - self::$devLogger = LoggerFactory::createDev('develop', $developIp); - LoggerFactory::addStreamHandler(self::$devLogger, $logfile, LogLevel::DEBUG); } /** - * Mapping a legacy level to the PSR-3 compliant levels - * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md#5-psrlogloglevel + * Sets the default dev-logging handler for Friendica. * - * @param string $level the level to be mapped - * - * @return string the PSR-3 compliant level + * @param LoggerInterface $logger The Logger instance of this Application */ - private static function mapLegacyConfigDebugLevel($level) + public static function setDevLogger($logger) { - switch ($level) { - // legacy WARNING - case "0": - return LogLevel::ERROR; - // legacy INFO - case "1": - return LogLevel::WARNING; - // legacy TRACE - case "2": - return LogLevel::NOTICE; - // legacy DEBUG - case "3": - return LogLevel::INFO; - // legacy DATA - case "4": - return LogLevel::DEBUG; - // legacy ALL - case "5": - return LogLevel::DEBUG; - // default if nothing set - default: - return $level; - } + self::$devLogger = $logger; } /** diff --git a/src/Factory/DBFactory.php b/src/Factory/DBFactory.php index 5970541c1..abfe6f99d 100644 --- a/src/Factory/DBFactory.php +++ b/src/Factory/DBFactory.php @@ -7,6 +7,14 @@ use Friendica\Database; class DBFactory { + /** + * Initialize the DBA connection + * + * @param Cache\ConfigCache $configCache The configuration cache + * @param array $server The $_SERVER variables + * + * @throws \Exception if connection went bad + */ public static function init(Cache\ConfigCache $configCache, array $server) { if (Database\DBA::connected()) { diff --git a/src/Factory/LoggerFactory.php b/src/Factory/LoggerFactory.php index e9bacb38e..74f55e637 100644 --- a/src/Factory/LoggerFactory.php +++ b/src/Factory/LoggerFactory.php @@ -35,16 +35,17 @@ class LoggerFactory $logger->pushProcessor(new Monolog\Processor\UidProcessor()); $logger->pushProcessor(new FriendicaIntrospectionProcessor(LogLevel::DEBUG, [Logger::class, Profiler::class])); - if (isset($config)) { - $debugging = $config->get('system', 'debugging'); - $stream = $config->get('system', 'logfile'); - $level = $config->get('system', 'loglevel'); + $debugging = $config->get('system', 'debugging'); + $stream = $config->get('system', 'logfile'); + $level = $config->get('system', 'loglevel'); - if ($debugging) { - static::addStreamHandler($logger, $stream, $level); - } + if ($debugging) { + $loglevel = self::mapLegacyConfigDebugLevel((string)$level); + static::addStreamHandler($logger, $stream, $loglevel); } + Logger::setLogger($logger); + return $logger; } @@ -56,25 +57,71 @@ class LoggerFactory * * It should never get filled during normal usage of Friendica * - * @param string $channel The channel of the logger instance - * @param string $developerIp The IP of the developer who wants to use the logger + * @param string $channel The channel of the logger instance + * @param Configuration $config The config * * @return LoggerInterface The PSR-3 compliant logger instance */ - public static function createDev($channel, $developerIp) + public static function createDev($channel, Configuration $config) { + $debugging = $config->get('system', 'debugging'); + $stream = $config->get('system', 'dlogfile'); + $developerIp = $config->get('system', 'dlogip'); + + if (!isset($developerIp) || !$debugging) { + return null; + } + $logger = new Monolog\Logger($channel); $logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor()); $logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor()); $logger->pushProcessor(new Monolog\Processor\UidProcessor()); $logger->pushProcessor(new FriendicaIntrospectionProcessor(LogLevel::DEBUG, ['Friendica\\Core\\Logger'])); - $logger->pushHandler(new FriendicaDevelopHandler($developerIp)); + static::addStreamHandler($logger, $stream, LogLevel::DEBUG); + + Logger::setDevLogger($logger); + return $logger; } + /** + * Mapping a legacy level to the PSR-3 compliant levels + * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md#5-psrlogloglevel + * + * @param string $level the level to be mapped + * + * @return string the PSR-3 compliant level + */ + private static function mapLegacyConfigDebugLevel($level) + { + switch ($level) { + // legacy WARNING + case "0": + return LogLevel::ERROR; + // legacy INFO + case "1": + return LogLevel::WARNING; + // legacy TRACE + case "2": + return LogLevel::NOTICE; + // legacy DEBUG + case "3": + return LogLevel::INFO; + // legacy DATA + case "4": + return LogLevel::DEBUG; + // legacy ALL + case "5": + return LogLevel::DEBUG; + // default if nothing set + default: + return $level; + } + } + /** * Adding a handler to a given logger instance * @@ -106,32 +153,4 @@ class LoggerFactory throw new InternalServerErrorException('Logger instance incompatible for MonologFactory'); } } - - /** - * This method enables the test mode of a given logger - * - * @param LoggerInterface $logger The logger - * - * @return Monolog\Handler\TestHandler the Handling for tests - * - * @throws InternalServerErrorException if the logger is incompatible to the logger factory - */ - public static function enableTest($logger) - { - if ($logger instanceof Monolog\Logger) { - // disable every handler so far - $logger->pushHandler(new Monolog\Handler\NullHandler()); - - // enable the test handler - $fileHandler = new Monolog\Handler\TestHandler(); - $formatter = new Monolog\Formatter\LineFormatter("%datetime% %channel% [%level_name%]: %message% %context% %extra%\n"); - $fileHandler->setFormatter($formatter); - - $logger->pushHandler($fileHandler); - - return $fileHandler; - } else { - throw new InternalServerErrorException('Logger instance incompatible for MonologFactory'); - } - } } diff --git a/tests/include/ApiTest.php b/tests/include/ApiTest.php index 7f2299d51..59096f5e5 100644 --- a/tests/include/ApiTest.php +++ b/tests/include/ApiTest.php @@ -41,7 +41,7 @@ class ApiTest extends DatabaseTest $configCache = Factory\ConfigFactory::createCache($configLoader); Factory\DBFactory::init($configCache, $_SERVER); $config = Factory\ConfigFactory::createConfig($configCache); - $pconfig = Factory\ConfigFactory::createPConfig($configCache); + Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('test', $config); $profiler = Factory\ProfilerFactory::create($logger, $config); $this->app = new App($config, $logger, $profiler, false); diff --git a/tests/src/Core/Config/Cache/ConfigCacheTest.php b/tests/src/Core/Config/Cache/ConfigCacheTest.php index 7b56ca646..ac9fae540 100644 --- a/tests/src/Core/Config/Cache/ConfigCacheTest.php +++ b/tests/src/Core/Config/Cache/ConfigCacheTest.php @@ -149,13 +149,34 @@ class ConfigCacheTest extends MockedTest $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')); + } - $this->assertFalse($configCache->has('system', null)); - $configCache->set('system', null, 'it'); - $this->assertTrue($configCache->has('system', null)); + /** + * Test the get() method with a category + */ + public function testGetCat() + { + $configCache = new ConfigCache([ + 'system' => [ + 'key1' => 'value1', + 'key2' => 'value2', + ], + 'config' => [ + 'key3' => 'value3', + ], + ]); + + $this->assertTrue($configCache->has('system')); + + $this->assertEquals([ + 'key1' => 'value1', + 'key2' => 'value2', + ], $configCache->get('system')); } /** @@ -194,6 +215,32 @@ class ConfigCacheTest extends MockedTest } + /** + * Test the getP() method with a category + */ + public function testGetPCat() + { + $configCache = new ConfigCache(); + $uid = 345; + + $configCache->loadP($uid, [ + 'system' => [ + 'key1' => 'value1', + 'key2' => 'value2', + ], + 'config' => [ + 'key3' => 'value3', + ], + ]); + + $this->assertTrue($configCache->hasP($uid,'system')); + + $this->assertEquals([ + 'key1' => 'value1', + 'key2' => 'value2', + ], $configCache->get($uid, 'system')); + } + /** * Test the deleteP() method * @dataProvider dataTests @@ -227,12 +274,10 @@ class ConfigCacheTest extends MockedTest $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->assertFalse($configCache->hasP($uid, 'system', null)); - $configCache->setP($uid, 'system', null, 'it'); - $this->assertTrue($configCache->hasP($uid, 'system', null)); + $this->assertTrue($configCache->hasP($uid, 'system')); } } From e1d9d67632a8d6777a2b49c227b7a40d1014437c Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 11 Feb 2019 21:36:26 +0100 Subject: [PATCH 14/20] renamed Logger::setLogger() to Logger::init() --- src/Core/Config/Adapter/IConfigAdapter.php | 13 +- src/Core/Config/Adapter/IPConfigAdapter.php | 11 ++ src/Core/Config/Adapter/JITConfigAdapter.php | 12 ++ src/Core/Config/Adapter/JITPConfigAdapter.php | 14 ++- .../Config/Adapter/PreloadConfigAdapter.php | 16 ++- .../Config/Adapter/PreloadPConfigAdapter.php | 16 ++- src/Core/Config/Configuration.php | 28 ++--- src/Core/Config/PConfiguration.php | 28 ++--- src/Core/Logger.php | 2 +- src/Factory/LoggerFactory.php | 2 +- tests/src/Core/Config/ConfigurationTest.php | 112 +++++++++++++---- tests/src/Core/Config/PConfigurationTest.php | 114 +++++++++++++----- 12 files changed, 276 insertions(+), 92 deletions(-) diff --git a/src/Core/Config/Adapter/IConfigAdapter.php b/src/Core/Config/Adapter/IConfigAdapter.php index 3bbbbbe94..8223d3367 100644 --- a/src/Core/Config/Adapter/IConfigAdapter.php +++ b/src/Core/Config/Adapter/IConfigAdapter.php @@ -29,8 +29,7 @@ interface IConfigAdapter public function get($cat, $key); /** - * Stores a config value ($value) in the category ($family) under the key ($key) - * for the user_id $uid. + * Stores a config value ($value) in the category ($family) under the key ($key). * * Note: Please do not store booleans - convert to 0/1 integer values! * @@ -59,4 +58,14 @@ interface IConfigAdapter * @return bool */ public function isConnected(); + + /** + * Checks, if a config value ($value) in the category ($cat) is already loaded. + * + * @param string $cat The configuration category + * @param string $key The configuration key + * + * @return bool + */ + public function isLoaded($cat, $key); } diff --git a/src/Core/Config/Adapter/IPConfigAdapter.php b/src/Core/Config/Adapter/IPConfigAdapter.php index 3e821efa0..e9f389292 100644 --- a/src/Core/Config/Adapter/IPConfigAdapter.php +++ b/src/Core/Config/Adapter/IPConfigAdapter.php @@ -69,4 +69,15 @@ interface IPConfigAdapter * @return bool */ public function isConnected(); + + /** + * Checks, if a config value ($value) in the category ($cat) is already loaded for the user_id $uid. + * + * @param string $uid The user_id + * @param string $cat The configuration category + * @param string $key The configuration key + * + * @return bool + */ + public function isLoaded($uid, $cat, $key); } diff --git a/src/Core/Config/Adapter/JITConfigAdapter.php b/src/Core/Config/Adapter/JITConfigAdapter.php index 8dadfff68..95211777f 100644 --- a/src/Core/Config/Adapter/JITConfigAdapter.php +++ b/src/Core/Config/Adapter/JITConfigAdapter.php @@ -120,4 +120,16 @@ class JITConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapte return $result; } + + /** + * {@inheritdoc} + */ + public function isLoaded($cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + return (isset($this->in_db[$cat][$key])) && $this->in_db[$cat][$key]; + } } diff --git a/src/Core/Config/Adapter/JITPConfigAdapter.php b/src/Core/Config/Adapter/JITPConfigAdapter.php index 950dd58bd..697e27128 100644 --- a/src/Core/Config/Adapter/JITPConfigAdapter.php +++ b/src/Core/Config/Adapter/JITPConfigAdapter.php @@ -36,7 +36,7 @@ class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdap } } else if ($cat != 'config') { // Negative caching - $return[null] = "!!"; + $return = "!!"; } DBA::close($pconfigs); @@ -123,4 +123,16 @@ class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdap return $result; } + + /** + * {@inheritdoc} + */ + public function isLoaded($uid, $cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + return (isset($this->in_db[$uid][$cat][$key])) && $this->in_db[$uid][$cat][$key]; + } } diff --git a/src/Core/Config/Adapter/PreloadConfigAdapter.php b/src/Core/Config/Adapter/PreloadConfigAdapter.php index 8cad5c555..a12c2a7ca 100644 --- a/src/Core/Config/Adapter/PreloadConfigAdapter.php +++ b/src/Core/Config/Adapter/PreloadConfigAdapter.php @@ -32,13 +32,13 @@ class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAd $configs = DBA::select('config', ['cat', 'v', 'k']); while ($config = DBA::fetch($configs)) { - $return[$config['k']] = $config['v']; + $return[$config['cat']][$config['k']] = $config['v']; } DBA::close($configs); $this->config_loaded = true; - return [$cat => $return]; + return $return; } /** @@ -101,4 +101,16 @@ class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAd return $result; } + + /** + * {@inheritdoc} + */ + public function isLoaded($cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + return $this->config_loaded; + } } diff --git a/src/Core/Config/Adapter/PreloadPConfigAdapter.php b/src/Core/Config/Adapter/PreloadPConfigAdapter.php index d117ed354..d1c44d9fb 100644 --- a/src/Core/Config/Adapter/PreloadPConfigAdapter.php +++ b/src/Core/Config/Adapter/PreloadPConfigAdapter.php @@ -44,13 +44,13 @@ class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfig $pconfigs = DBA::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]); while ($pconfig = DBA::fetch($pconfigs)) { - $return[$pconfig['k']] = $pconfig['v']; + $return[$pconfig['cat']][$pconfig['k']] = $pconfig['v']; } DBA::close($pconfigs); $this->config_loaded = true; - return [$cat => $return]; + return $return; } /** @@ -123,4 +123,16 @@ class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfig return $result; } + + /** + * {@inheritdoc} + */ + public function isLoaded($uid, $cat, $key) + { + if (!$this->isConnected()) { + return false; + } + + return $this->config_loaded; + } } diff --git a/src/Core/Config/Configuration.php b/src/Core/Config/Configuration.php index ccb9abda8..2ad11b0ba 100644 --- a/src/Core/Config/Configuration.php +++ b/src/Core/Config/Configuration.php @@ -79,22 +79,20 @@ class Configuration */ public function get($cat, $key, $default_value = null, $refresh = false) { - // Return the value of the cache if found and no refresh is forced - if (!$refresh && $this->configCache->has($cat, $key)) { + // if the value isn't loaded or refresh is needed, load it to the cache + if ($this->configAdapter->isConnected() && + (!$this->configAdapter->isLoaded($cat, $key) || + $refresh)) { + $dbvalue = $this->configAdapter->get($cat, $key); + + if ($dbvalue !== '!!') { + $this->configCache->set($cat, $key, $dbvalue); + } + } + + // use the config cache for return + if ($this->configCache->has($cat, $key)) { return $this->configCache->get($cat, $key); - } - - // if we don't find the value in the cache and the adapter isn't ready, return the default value - if (!$this->configAdapter->isConnected()) { - return $default_value; - } - - // load DB value to cache - $dbvalue = $this->configAdapter->get($cat, $key); - - if ($dbvalue !== '!!') { - $this->configCache->set($cat, $key, $dbvalue); - return $dbvalue; } else { return $default_value; } diff --git a/src/Core/Config/PConfiguration.php b/src/Core/Config/PConfiguration.php index d3c848c9d..cf7ef6adc 100644 --- a/src/Core/Config/PConfiguration.php +++ b/src/Core/Config/PConfiguration.php @@ -71,22 +71,20 @@ class PConfiguration */ public function get($uid, $cat, $key, $default_value = null, $refresh = false) { - // Return the value of the cache if found and no refresh is forced - if (!$refresh && $this->configCache->hasP($uid, $cat, $key)) { + // if the value isn't loaded or refresh is needed, load it to the cache + if ($this->configAdapter->isConnected() && + (!$this->configAdapter->isLoaded($uid, $cat, $key) || + $refresh)) { + $dbValue = $this->configAdapter->get($uid, $cat, $key); + + if ($dbValue !== '!!') { + $this->configCache->setP($uid, $cat, $key, $dbValue); + } + } + + // use the config cache for return + if ($this->configCache->hasP($uid, $cat, $key)) { return $this->configCache->getP($uid, $cat, $key); - } - - // if we don't find the value in the cache and the adapter isn't ready, return the default value - if (!$this->configAdapter->isConnected()) { - return $default_value; - } - - // load DB value to cache - $dbvalue = $this->configAdapter->get($uid, $cat, $key); - - if ($dbvalue !== '!!') { - $this->configCache->setP($uid, $cat, $key, $dbvalue); - return $dbvalue; } else { return $default_value; } diff --git a/src/Core/Logger.php b/src/Core/Logger.php index a2e587342..67e58ef6b 100644 --- a/src/Core/Logger.php +++ b/src/Core/Logger.php @@ -68,7 +68,7 @@ class Logger extends BaseObject * * @param LoggerInterface $logger The Logger instance of this Application */ - public static function setLogger($logger) + public static function init($logger) { self::$logger = $logger; } diff --git a/src/Factory/LoggerFactory.php b/src/Factory/LoggerFactory.php index 74f55e637..bbe3b0a4b 100644 --- a/src/Factory/LoggerFactory.php +++ b/src/Factory/LoggerFactory.php @@ -44,7 +44,7 @@ class LoggerFactory static::addStreamHandler($logger, $stream, $loglevel); } - Logger::setLogger($logger); + Logger::init($logger); return $logger; } diff --git a/tests/src/Core/Config/ConfigurationTest.php b/tests/src/Core/Config/ConfigurationTest.php index 6ce81a41b..0437f1e7a 100644 --- a/tests/src/Core/Config/ConfigurationTest.php +++ b/tests/src/Core/Config/ConfigurationTest.php @@ -9,6 +9,20 @@ use Friendica\Test\MockedTest; class ConfigurationTest extends MockedTest { + public function dataTests() + { + return [ + 'string' => ['data' => 'it'], + 'boolTrue' => ['data' => true], + 'boolFalse' => ['data' => false], + 'integer' => ['data' => 235], + 'decimal' => ['data' => 2.456], + 'array' => ['data' => ['1', 2, '3', true, false]], + 'boolIntTrue' => ['data' => 1], + 'boolIntFalse' => ['Data' => 0], + ]; + } + /** * Test the configuration initialization */ @@ -24,17 +38,18 @@ class ConfigurationTest extends MockedTest } /** - * Test if the configuration load() method + * Test the configuration load() method */ public function testCacheLoad() { $configCache = new ConfigCache(); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(true)->twice(); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); // constructor loading $configAdapter->shouldReceive('load')->andReturn([])->once(); // expected loading $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + $configAdapter->shouldReceive('isLoaded')->with('testing', 'test')->andReturn(true)->once(); $configuration = new Configuration($configCache, $configAdapter); $configuration->load('testing'); @@ -44,17 +59,18 @@ class ConfigurationTest extends MockedTest } /** - * Test if the configuration load() method with overwrite + * Test the configuration load() method with overwrite */ public function testCacheLoadDouble() { $configCache = new ConfigCache(); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(5); // constructor loading $configAdapter->shouldReceive('load')->andReturn([])->once(); // expected loading $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + $configAdapter->shouldReceive('isLoaded')->with('testing', 'test')->andReturn(true)->twice(); // expected next loading $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'again']])->once(); @@ -71,40 +87,43 @@ class ConfigurationTest extends MockedTest } /** - * Test if the configuration get() and set() methods without adapter + * Test the configuration get() and set() methods without adapter + * @dataProvider dataTests */ - public function testSetGetWithoutDB() + public function testSetGetWithoutDB($data) { $configCache = new ConfigCache(); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(false)->twice(); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3); $configuration = new Configuration($configCache, $configAdapter); - $this->assertTrue($configuration->set('test', 'it', 'now')); + $this->assertTrue($configuration->set('test', 'it', $data)); - $this->assertEquals('now', $configuration->get('test', 'it')); - $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + $this->assertEquals($data, $configuration->get('test', 'it')); + $this->assertEquals($data, $configuration->getCache()->get('test', 'it')); } /** - * Test if the configuration get() and set() methods with adapter + * Test the configuration get() and set() methods with adapter + * @dataProvider dataTests */ - public function testSetGetWithDB() + public function testSetGetWithDB($data) { $configCache = new ConfigCache(); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(true)->twice(); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); // constructor loading $configAdapter->shouldReceive('load')->andReturn([])->once(); - $configAdapter->shouldReceive('set')->with('test', 'it', 'now')->andReturn(true)->once(); + $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(true)->once(); + $configAdapter->shouldReceive('set')->with('test', 'it', $data)->andReturn(true)->once(); $configuration = new Configuration($configCache, $configAdapter); - $this->assertTrue($configuration->set('test', 'it', 'now')); + $this->assertTrue($configuration->set('test', 'it', $data)); - $this->assertEquals('now', $configuration->get('test', 'it')); - $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + $this->assertEquals($data, $configuration->get('test', 'it')); + $this->assertEquals($data, $configuration->getCache()->get('test', 'it')); } /** @@ -133,15 +152,18 @@ class ConfigurationTest extends MockedTest /** * Test the configuration get() method with refresh + * @dataProvider dataTests */ - public function testGetWithRefresh() + public function testGetWithRefresh($data) { $configCache = new ConfigCache(['test' => ['it' => 'now']]); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(4); // constructor loading $configAdapter->shouldReceive('load')->andReturn([])->once(); - $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn('again')->once(); + $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(true)->twice(); + $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn($data)->once(); + $configAdapter->shouldReceive('isLoaded')->with('test', 'not')->andReturn(false)->once(); $configAdapter->shouldReceive('get')->with('test', 'not')->andReturn('!!')->once(); $configuration = new Configuration($configCache, $configAdapter); @@ -151,8 +173,8 @@ class ConfigurationTest extends MockedTest $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); // with refresh - $this->assertEquals('again', $configuration->get('test', 'it', null, true)); - $this->assertEquals('again', $configuration->getCache()->get('test', 'it')); + $this->assertEquals($data, $configuration->get('test', 'it', null, true)); + $this->assertEquals($data, $configuration->getCache()->get('test', 'it')); // without refresh and wrong value and default $this->assertEquals('default', $configuration->get('test', 'not', 'default')); @@ -160,19 +182,55 @@ class ConfigurationTest extends MockedTest } /** - * Test the configuration delete() method without adapter + * Test the configuration get() method with different isLoaded settings + * @dataProvider dataTests */ - public function testDeleteWithoutDB() + public function testGetWithoutLoaded($data) { $configCache = new ConfigCache(['test' => ['it' => 'now']]); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(4); + // constructor loading + $configAdapter->shouldReceive('load')->andReturn([])->once(); + + $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(false)->once(); + $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn('!!')->once(); + + $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(false)->once(); + $configAdapter->shouldReceive('get')->with('test', 'it')->andReturn($data)->once(); + + $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(true)->once(); $configuration = new Configuration($configCache, $configAdapter); + // first run is not loaded and no data is found in the DB $this->assertEquals('now', $configuration->get('test', 'it')); $this->assertEquals('now', $configuration->getCache()->get('test', 'it')); + // second run is not loaded, but now data is found in the db (overwrote cache) + $this->assertEquals($data, $configuration->get('test', 'it')); + $this->assertEquals($data, $configuration->getCache()->get('test', 'it')); + + // third run is loaded and therefore cache is used + $this->assertEquals($data, $configuration->get('test', 'it')); + $this->assertEquals($data, $configuration->getCache()->get('test', 'it')); + } + + /** + * Test the configuration delete() method without adapter + * @dataProvider dataTests + */ + public function testDeleteWithoutDB($data) + { + $configCache = new ConfigCache(['test' => ['it' => $data]]); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(4); + + $configuration = new Configuration($configCache, $configAdapter); + + $this->assertEquals($data, $configuration->get('test', 'it')); + $this->assertEquals($data, $configuration->getCache()->get('test', 'it')); + $this->assertTrue($configuration->delete('test', 'it')); $this->assertNull($configuration->get('test', 'it')); $this->assertEquals('!!', $configuration->getCache()->get('test', 'it')); @@ -187,9 +245,11 @@ class ConfigurationTest extends MockedTest { $configCache = new ConfigCache(['test' => ['it' => 'now', 'quarter' => 'true']]); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(5); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(6); // constructor loading $configAdapter->shouldReceive('load')->andReturn([])->once(); + $configAdapter->shouldReceive('isLoaded')->with('test', 'it')->andReturn(true)->once(); + $configAdapter->shouldReceive('delete')->with('test', 'it')->andReturn(false)->once(); $configAdapter->shouldReceive('delete')->with('test', 'second')->andReturn(true)->once(); diff --git a/tests/src/Core/Config/PConfigurationTest.php b/tests/src/Core/Config/PConfigurationTest.php index 3d8fb586c..8ecc9bdf3 100644 --- a/tests/src/Core/Config/PConfigurationTest.php +++ b/tests/src/Core/Config/PConfigurationTest.php @@ -8,17 +8,35 @@ use Friendica\Test\MockedTest; class PConfigurationTest extends MockedTest { + public function dataTests() + { + return [ + 'string' => ['data' => 'it'], + 'boolTrue' => ['data' => true], + 'boolFalse' => ['data' => false], + 'integer' => ['data' => 235], + 'decimal' => ['data' => 2.456], + 'array' => ['data' => ['1', 2, '3', true, false]], + 'boolIntTrue' => ['data' => 1], + 'boolIntFalse' => ['Data' => 0], + ]; + } + /** - * Test if the configuration load() method + * Test the configuration load() method */ public function testCacheLoad() { $uid = 234; $configCache = new ConfigCache(); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(true)->once(); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->twice(); // expected loading - $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + $configAdapter->shouldReceive('load') + ->with($uid, 'testing') + ->andReturn(['testing' => ['test' => 'it']]) + ->once(); + $configAdapter->shouldReceive('isLoaded')->with($uid, 'testing', 'test')->andReturn(true)->once(); $configuration = new PConfiguration($configCache, $configAdapter); $configuration->load($uid, 'testing'); @@ -27,16 +45,17 @@ class PConfigurationTest extends MockedTest } /** - * Test if the configuration load() method with overwrite + * Test the configuration load() method with overwrite */ public function testCacheLoadDouble() { $uid = 234; $configCache = new ConfigCache(); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(true)->twice(); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(4); // expected loading - $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'it']])->once(); + $configAdapter->shouldReceive('load')->with($uid, 'testing')->andReturn(['testing' => ['test' => 'it']])->once(); + $configAdapter->shouldReceive('isLoaded')->with($uid, 'testing', 'test')->andReturn(true)->twice(); // expected next loading $configAdapter->shouldReceive('load')->andReturn(['testing' => ['test' => 'again']])->once(); @@ -51,38 +70,41 @@ class PConfigurationTest extends MockedTest } /** - * Test if the configuration get() and set() methods without adapter + * Test the configuration get() and set() methods without adapter + * @dataProvider dataTests */ - public function testSetGetWithoutDB() + public function testSetGetWithoutDB($data) { $uid = 234; $configCache = new ConfigCache(); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(false)->once(); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(2); $configuration = new PConfiguration($configCache, $configAdapter); - $this->assertTrue($configuration->set($uid, 'test', 'it', 'now')); + $this->assertTrue($configuration->set($uid, 'test', 'it', $data)); - $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + $this->assertEquals($data, $configuration->get($uid, 'test', 'it')); } /** - * Test if the configuration get() and set() methods with adapter + * Test the configuration get() and set() methods with adapter + * @dataProvider dataTests */ - public function testSetGetWithDB() + public function testSetGetWithDB($data) { $uid = 234; $configCache = new ConfigCache(); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(true)->once(); - $configAdapter->shouldReceive('set')->with($uid, 'test', 'it', 'now')->andReturn(true)->once(); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(2); + $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(true)->once(); + $configAdapter->shouldReceive('set')->with($uid, 'test', 'it', $data)->andReturn(true)->once(); $configuration = new PConfiguration($configCache, $configAdapter); - $this->assertTrue($configuration->set($uid, 'test', 'it', 'now')); + $this->assertTrue($configuration->set($uid, 'test', 'it', $data)); - $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + $this->assertEquals($data, $configuration->get($uid, 'test', 'it')); } /** @@ -109,15 +131,19 @@ class PConfigurationTest extends MockedTest /** * Test the configuration get() method with refresh + * @dataProvider dataTests */ - public function testGetWithRefresh() + public function testGetWithRefresh($data) { $uid = 234; $configCache = new ConfigCache(); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(4); + $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(false)->once(); $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn('now')->once(); - $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn('again')->once(); + $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(true)->twice(); + $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn($data)->once(); + $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'not')->andReturn(false)->once(); $configAdapter->shouldReceive('get')->with($uid, 'test', 'not')->andReturn('!!')->once(); $configuration = new PConfiguration($configCache, $configAdapter); @@ -128,26 +154,58 @@ class PConfigurationTest extends MockedTest $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); // with refresh (and load the second value out of the db) - $this->assertEquals('again', $configuration->get($uid, 'test', 'it', null, true)); + $this->assertEquals($data, $configuration->get($uid, 'test', 'it', null, true)); // without refresh and wrong value and default $this->assertEquals('default', $configuration->get($uid, 'test', 'not', 'default')); } /** - * Test the configuration delete() method without adapter + * Test the configuration get() method with different isLoaded settings + * @dataProvider dataTests */ - public function testDeleteWithoutDB() + public function testGetWithoutLoaded($data) { $uid = 234; $configCache = new ConfigCache(); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); + + $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(false)->once(); + $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn('!!')->once(); + + $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(false)->once(); + $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn($data)->once(); + + $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(true)->once(); $configuration = new PConfiguration($configCache, $configAdapter); - $this->assertTrue($configuration->set($uid, 'test', 'it', 'now')); - $this->assertEquals('now', $configuration->get($uid, 'test', 'it')); + // first run is not loaded and no data is found in the DB + $this->assertNull($configuration->get($uid, 'test', 'it')); + + // second run is not loaded, but now data is found in the db (overwrote cache) + $this->assertEquals($data, $configuration->get($uid,'test', 'it')); + + // third run is loaded and therefore cache is used + $this->assertEquals($data, $configuration->get($uid,'test', 'it')); + } + + /** + * Test the configuration delete() method without adapter + * @dataProvider dataTests + */ + public function testDeleteWithoutDB($data) + { + $uid = 234; + $configCache = new ConfigCache(); + $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(4); + + $configuration = new PConfiguration($configCache, $configAdapter); + + $this->assertTrue($configuration->set($uid, 'test', 'it', $data)); + $this->assertEquals($data, $configuration->get($uid, 'test', 'it')); $this->assertTrue($configuration->delete($uid, 'test', 'it')); $this->assertNull($configuration->get($uid, 'test', 'it')); @@ -161,8 +219,10 @@ class PConfigurationTest extends MockedTest $uid = 234; $configCache = new ConfigCache(); $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); - $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(5); + $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(6); $configAdapter->shouldReceive('set')->with($uid, 'test', 'it', 'now')->andReturn(false)->once(); + $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(true)->once(); + $configAdapter->shouldReceive('delete')->with($uid, 'test', 'it')->andReturn(false)->once(); $configAdapter->shouldReceive('delete')->with($uid, 'test', 'second')->andReturn(true)->once(); From ad1254c49cac6e6278cd777b1a3887f5042204de Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 11 Feb 2019 23:39:51 +0100 Subject: [PATCH 15/20] performance improvement in case of db-load --- src/Core/Config/Configuration.php | 1 + src/Core/Config/PConfiguration.php | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Core/Config/Configuration.php b/src/Core/Config/Configuration.php index 2ad11b0ba..2ac0da0ad 100644 --- a/src/Core/Config/Configuration.php +++ b/src/Core/Config/Configuration.php @@ -87,6 +87,7 @@ class Configuration if ($dbvalue !== '!!') { $this->configCache->set($cat, $key, $dbvalue); + return $dbvalue; } } diff --git a/src/Core/Config/PConfiguration.php b/src/Core/Config/PConfiguration.php index cf7ef6adc..99b1aa146 100644 --- a/src/Core/Config/PConfiguration.php +++ b/src/Core/Config/PConfiguration.php @@ -79,6 +79,7 @@ class PConfiguration if ($dbValue !== '!!') { $this->configCache->setP($uid, $cat, $key, $dbValue); + return $dbValue; } } From 0a318925a4bf5ee41cee4869f97a4276c2bc8d23 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 11 Feb 2019 23:45:08 +0100 Subject: [PATCH 16/20] bugfixing adapter get() in case of no connection --- src/Core/Config/Adapter/IConfigAdapter.php | 6 +++--- src/Core/Config/Adapter/IPConfigAdapter.php | 4 ++-- src/Core/Config/Adapter/JITPConfigAdapter.php | 2 +- src/Core/Config/Adapter/PreloadConfigAdapter.php | 2 +- src/Core/Config/Adapter/PreloadPConfigAdapter.php | 2 +- src/Core/Logger.php | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Core/Config/Adapter/IConfigAdapter.php b/src/Core/Config/Adapter/IConfigAdapter.php index 8223d3367..21cd9a4b2 100644 --- a/src/Core/Config/Adapter/IConfigAdapter.php +++ b/src/Core/Config/Adapter/IConfigAdapter.php @@ -9,7 +9,7 @@ namespace Friendica\Core\Config\Adapter; interface IConfigAdapter { /** - * Loads all configuration values into a cached storage. + * Loads all configuration values and returns the loaded category as an array. * * @param string $cat The category of the configuration values to load * @@ -18,7 +18,7 @@ interface IConfigAdapter public function load($cat = "config"); /** - * Get a particular user's config variable given the category name + * Get a particular system-wide config variable given the category name * ($family) and a key. * * @param string $cat The category of the configuration value @@ -60,7 +60,7 @@ interface IConfigAdapter public function isConnected(); /** - * Checks, if a config value ($value) in the category ($cat) is already loaded. + * Checks, if a config key ($key) in the category ($cat) is already loaded. * * @param string $cat The configuration category * @param string $key The configuration key diff --git a/src/Core/Config/Adapter/IPConfigAdapter.php b/src/Core/Config/Adapter/IPConfigAdapter.php index e9f389292..8e6c050b2 100644 --- a/src/Core/Config/Adapter/IPConfigAdapter.php +++ b/src/Core/Config/Adapter/IPConfigAdapter.php @@ -15,7 +15,7 @@ namespace Friendica\Core\Config\Adapter; interface IPConfigAdapter { /** - * Loads all configuration values of a user's config family into a cached storage. + * Loads all configuration values of a user's config family and returns the loaded category as an array. * * @param string $uid The user_id * @param string $cat The category of the configuration value @@ -71,7 +71,7 @@ interface IPConfigAdapter public function isConnected(); /** - * Checks, if a config value ($value) in the category ($cat) is already loaded for the user_id $uid. + * Checks, if a config key ($key) in the category ($cat) is already loaded for the user_id $uid. * * @param string $uid The user_id * @param string $cat The configuration category diff --git a/src/Core/Config/Adapter/JITPConfigAdapter.php b/src/Core/Config/Adapter/JITPConfigAdapter.php index 697e27128..c5f3a381e 100644 --- a/src/Core/Config/Adapter/JITPConfigAdapter.php +++ b/src/Core/Config/Adapter/JITPConfigAdapter.php @@ -49,7 +49,7 @@ class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdap public function get($uid, $cat, $key) { if (!$this->isConnected()) { - return null; + return '!!'; } $pconfig = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]); diff --git a/src/Core/Config/Adapter/PreloadConfigAdapter.php b/src/Core/Config/Adapter/PreloadConfigAdapter.php index a12c2a7ca..fa691a16d 100644 --- a/src/Core/Config/Adapter/PreloadConfigAdapter.php +++ b/src/Core/Config/Adapter/PreloadConfigAdapter.php @@ -47,7 +47,7 @@ class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAd public function get($cat, $key) { if (!$this->isConnected()) { - return null; + return '!!'; } $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]); diff --git a/src/Core/Config/Adapter/PreloadPConfigAdapter.php b/src/Core/Config/Adapter/PreloadPConfigAdapter.php index d1c44d9fb..e79a4a1e3 100644 --- a/src/Core/Config/Adapter/PreloadPConfigAdapter.php +++ b/src/Core/Config/Adapter/PreloadPConfigAdapter.php @@ -59,7 +59,7 @@ class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfig public function get($uid, $cat, $key) { if (!$this->isConnected()) { - return null; + return '!!'; } if (!$this->config_loaded) { diff --git a/src/Core/Logger.php b/src/Core/Logger.php index 67e58ef6b..3cb22e1e4 100644 --- a/src/Core/Logger.php +++ b/src/Core/Logger.php @@ -68,7 +68,7 @@ class Logger extends BaseObject * * @param LoggerInterface $logger The Logger instance of this Application */ - public static function init($logger) + public static function init(LoggerInterface $logger) { self::$logger = $logger; } @@ -78,7 +78,7 @@ class Logger extends BaseObject * * @param LoggerInterface $logger The Logger instance of this Application */ - public static function setDevLogger($logger) + public static function setDevLogger(LoggerInterface $logger) { self::$devLogger = $logger; } From cdcf1667d7cb5cdcf960b5939deb558dd3f22233 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Tue, 12 Feb 2019 20:12:25 +0100 Subject: [PATCH 17/20] Adding DependencyFactory --- bin/auth_ejabberd.php | 15 +------------ bin/console.php | 14 +----------- bin/daemon.php | 28 +++++++----------------- bin/worker.php | 14 +----------- index.php | 15 +------------ src/Factory/DependencyFactory.php | 36 +++++++++++++++++++++++++++++++ 6 files changed, 48 insertions(+), 74 deletions(-) create mode 100644 src/Factory/DependencyFactory.php diff --git a/bin/auth_ejabberd.php b/bin/auth_ejabberd.php index 003faae1f..bf6d069d1 100755 --- a/bin/auth_ejabberd.php +++ b/bin/auth_ejabberd.php @@ -32,10 +32,7 @@ * */ -use Friendica\App; -use Friendica\Core\Config\Cache; use Friendica\Factory; -use Friendica\Util\BasePath; use Friendica\Util\ExAuth; if (sizeof($_SERVER["argv"]) == 0) { @@ -54,17 +51,7 @@ chdir($directory); require dirname(__DIR__) . '/vendor/autoload.php'; -$basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Cache\ConfigCacheLoader($basedir); -$configCache = Factory\ConfigFactory::createCache($configLoader); -Factory\DBFactory::init($configCache, $_SERVER); -$config = Factory\ConfigFactory::createConfig($configCache); -// needed to call PConfig::init() -Factory\ConfigFactory::createPConfig($configCache); -$logger = Factory\LoggerFactory::create('auth_ejabberd', $config); -$profiler = Factory\ProfilerFactory::create($logger, $config); - -$a = new App($config, $logger, $profiler); +$a = Factory\DependencyFactory::setUp('auth_ejabbered', dirname(__DIR__)); if ($a->getMode()->isNormal()) { $oAuth = new ExAuth(); diff --git a/bin/console.php b/bin/console.php index 2b0d58821..410eabda0 100755 --- a/bin/console.php +++ b/bin/console.php @@ -3,21 +3,9 @@ require dirname(__DIR__) . '/vendor/autoload.php'; -use Friendica\Core\Config\Cache; use Friendica\Factory; -use Friendica\Util\BasePath; -$basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Cache\ConfigCacheLoader($basedir); -$configCache = Factory\ConfigFactory::createCache($configLoader); -Factory\DBFactory::init($configCache, $_SERVER); -$config = Factory\ConfigFactory::createConfig($configCache); -// needed to call PConfig::init() -Factory\ConfigFactory::createPConfig($configCache); -$logger = Factory\LoggerFactory::create('console', $config); -$profiler = Factory\ProfilerFactory::create($logger, $config); - -$a = new Friendica\App($config, $logger, $profiler); +$a = Factory\DependencyFactory::setUp('console', dirname(__DIR__)); \Friendica\BaseObject::setApp($a); (new Friendica\Core\Console($argv))->execute(); diff --git a/bin/daemon.php b/bin/daemon.php index f2970a518..257896cfa 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -7,13 +7,11 @@ * This script was taken from http://php.net/manual/en/function.pcntl-fork.php */ -use Friendica\App; use Friendica\Core\Config; -use Friendica\Core\Config\Cache; +use Friendica\Core\Logger; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\Factory; -use Friendica\Util\BasePath; // Get options $shortopts = 'f'; @@ -34,17 +32,7 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) { require dirname(__DIR__) . '/vendor/autoload.php'; -$basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Cache\ConfigCacheLoader($basedir); -$configCache = Factory\ConfigFactory::createCache($configLoader); -Factory\DBFactory::init($configCache, $_SERVER); -$config = Factory\ConfigFactory::createConfig($configCache); -// needed to call PConfig::init() -Factory\ConfigFactory::createPConfig($configCache); -$logger = Factory\LoggerFactory::create('daemon', $config); -$profiler = Factory\ProfilerFactory::create($logger, $config); - -$a = new App($config, $logger, $profiler); +$a = Factory\DependencyFactory::setUp('daemon', dirname(__DIR__)); if ($a->getMode()->isInstall()) { die("Friendica isn't properly installed yet.\n"); @@ -114,7 +102,7 @@ if ($mode == "stop") { unlink($pidfile); - $logger->notice("Worker daemon process was killed", ["pid" => $pid]); + Logger::notice("Worker daemon process was killed", ["pid" => $pid]); Config::set('system', 'worker_daemon_mode', false); die("Worker daemon process $pid was killed.\n"); @@ -124,7 +112,7 @@ if (!empty($pid) && posix_kill($pid, 0)) { die("Daemon process $pid is already running.\n"); } -$logger->notice('Starting worker daemon.', ["pid" => $pid]); +Logger::notice('Starting worker daemon.', ["pid" => $pid]); if (!$foreground) { echo "Starting worker daemon.\n"; @@ -172,7 +160,7 @@ $last_cron = 0; // Now running as a daemon. while (true) { if (!$do_cron && ($last_cron + $wait_interval) < time()) { - $logger->info('Forcing cron worker call.', ["pid" => $pid]); + Logger::info('Forcing cron worker call.', ["pid" => $pid]); $do_cron = true; } @@ -186,7 +174,7 @@ while (true) { $last_cron = time(); } - $logger->info("Sleeping", ["pid" => $pid]); + Logger::info("Sleeping", ["pid" => $pid]); $start = time(); do { $seconds = (time() - $start); @@ -203,10 +191,10 @@ while (true) { if ($timeout) { $do_cron = true; - $logger->info("Woke up after $wait_interval seconds.", ["pid" => $pid, 'sleep' => $wait_interval]); + Logger::info("Woke up after $wait_interval seconds.", ["pid" => $pid, 'sleep' => $wait_interval]); } else { $do_cron = false; - $logger->info("Worker jobs are calling to be forked.", ["pid" => $pid]); + Logger::info("Worker jobs are calling to be forked.", ["pid" => $pid]); } } diff --git a/bin/worker.php b/bin/worker.php index 530333127..c7174d81e 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -7,11 +7,9 @@ use Friendica\App; use Friendica\Core\Config; -use Friendica\Core\Config\Cache; use Friendica\Core\Update; use Friendica\Core\Worker; use Friendica\Factory; -use Friendica\Util\BasePath; // Get options $shortopts = 'sn'; @@ -32,17 +30,7 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) { require dirname(__DIR__) . '/vendor/autoload.php'; -$basedir = BasePath::create(dirname(__DIR__), $_SERVER); -$configLoader = new Cache\ConfigCacheLoader($basedir); -$configCache = Factory\ConfigFactory::createCache($configLoader); -Factory\DBFactory::init($configCache, $_SERVER); -$config = Factory\ConfigFactory::createConfig($configCache); -// needed to call PConfig::init() -Factory\ConfigFactory::createPConfig($configCache); -$logger = Factory\LoggerFactory::create('worker', $config); -$profiler = Factory\ProfilerFactory::create($logger, $config); - -$a = new App($config, $logger, $profiler); +$a = Factory\DependencyFactory::setUp('worker', dirname(__DIR__)); // Check the database structure and possibly fixes it Update::check($a->getBasePath(), true); diff --git a/index.php b/index.php index 66f023965..6bbd70a19 100644 --- a/index.php +++ b/index.php @@ -4,10 +4,7 @@ * Friendica */ -use Friendica\App; -use Friendica\Core\Config\Cache; use Friendica\Factory; -use Friendica\Util\BasePath; if (!file_exists(__DIR__ . '/vendor/autoload.php')) { die('Vendor path not found. Please execute "bin/composer.phar --no-dev install" on the command line in the web root.'); @@ -15,18 +12,8 @@ if (!file_exists(__DIR__ . '/vendor/autoload.php')) { require __DIR__ . '/vendor/autoload.php'; -$basedir = BasePath::create(__DIR__, $_SERVER); -$configLoader = new Cache\ConfigCacheLoader($basedir); -$configCache = Factory\ConfigFactory::createCache($configLoader); -Factory\DBFactory::init($configCache, $_SERVER); -$config = Factory\ConfigFactory::createConfig($configCache); -// needed to call PConfig::init() -Factory\ConfigFactory::createPConfig($configCache); -$logger = Factory\LoggerFactory::create('index', $config); -$profiler = Factory\ProfilerFactory::create($logger, $config); - // We assume that the index.php is called by a frontend process // The value is set to "true" by default in App -$a = new App($config, $logger, $profiler, false); +$a = Factory\DependencyFactory::setUp('index', __DIR__, true); $a->runFrontend(); diff --git a/src/Factory/DependencyFactory.php b/src/Factory/DependencyFactory.php new file mode 100644 index 000000000..041202e6b --- /dev/null +++ b/src/Factory/DependencyFactory.php @@ -0,0 +1,36 @@ + Date: Sun, 17 Feb 2019 21:12:12 +0100 Subject: [PATCH 18/20] Refactored DependencyFactory for Profiler --- bin/daemon.php | 2 +- include/api.php | 2 +- src/App.php | 20 +++++++++++++++++--- src/Factory/DBFactory.php | 8 +++++--- src/Factory/DependencyFactory.php | 7 ++++--- src/Factory/LoggerFactory.php | 9 +++++++++ src/Factory/ProfilerFactory.php | 17 +++++++++-------- src/Util/Profiler.php | 18 ++++++------------ tests/include/ApiTest.php | 5 ++--- tests/src/Database/DBATest.php | 7 +++---- tests/src/Database/DBStructureTest.php | 7 +++---- tests/src/Util/ProfilerTest.php | 10 +++++----- 12 files changed, 65 insertions(+), 47 deletions(-) diff --git a/bin/daemon.php b/bin/daemon.php index 257896cfa..047bf71be 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -144,7 +144,7 @@ if (!$foreground) { file_put_contents($pidfile, $pid); // We lose the database connection upon forking - Factory\DBFactory::init($configCache, $_SERVER); + Factory\DBFactory::init($a->getConfigCache(), $a->getProfiler(), $_SERVER); } Config::set('system', 'worker_daemon_mode', true); diff --git a/include/api.php b/include/api.php index 6bd08d01d..13ff75bdb 100644 --- a/include/api.php +++ b/include/api.php @@ -326,7 +326,7 @@ function api_call(App $a) Logger::info(API_LOG_PREFIX . 'username {username}', ['module' => 'api', 'action' => 'call', 'username' => $a->user['username'], 'duration' => round($duration, 2)]); - $a->getProfiler()->saveLog(API_LOG_PREFIX . 'performance'); + $a->getProfiler()->saveLog($a->getLogger(), API_LOG_PREFIX . 'performance'); if (false === $return) { /* diff --git a/src/App.php b/src/App.php index 3189b2da7..8a49f060b 100644 --- a/src/App.php +++ b/src/App.php @@ -12,7 +12,6 @@ use Friendica\Core\Config\Cache\ConfigCacheLoader; use Friendica\Core\Config\Cache\IConfigCache; use Friendica\Core\Config\Configuration; use Friendica\Database\DBA; -use Friendica\Factory\ConfigFactory; use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Util\Profiler; use Psr\Log\LoggerInterface; @@ -114,6 +113,11 @@ class App */ private $config; + /** + * @var LoggerInterface The logger + */ + private $logger; + /** * @var Profiler The profiler of this app */ @@ -139,6 +143,16 @@ class App return $this->basePath; } + /** + * The Logger of this app + * + * @return LoggerInterface + */ + public function getLogger() + { + return $this->logger; + } + /** * The profiler of this app * @@ -192,7 +206,7 @@ class App * @brief App constructor. * * @param Configuration $config The Configuration - * @param LoggerInterface $logger Logger of this application + * @param LoggerInterface $logger The current app logger * @param Profiler $profiler The profiler of this application * @param bool $isBackend Whether it is used for backend or frontend (Default true=backend) * @@ -200,8 +214,8 @@ class App */ public function __construct(Configuration $config, LoggerInterface $logger, Profiler $profiler, $isBackend = true) { - $this->config = $config; $this->logger = $logger; + $this->config = $config; $this->profiler = $profiler; $this->basePath = $this->config->get('system', 'basepath'); diff --git a/src/Factory/DBFactory.php b/src/Factory/DBFactory.php index abfe6f99d..c1a796501 100644 --- a/src/Factory/DBFactory.php +++ b/src/Factory/DBFactory.php @@ -4,18 +4,20 @@ namespace Friendica\Factory; use Friendica\Core\Config\Cache; use Friendica\Database; +use Friendica\Util\Profiler; class DBFactory { /** * Initialize the DBA connection * - * @param Cache\ConfigCache $configCache The configuration cache + * @param Cache\IConfigCache $configCache The configuration cache + * @param Profiler $profiler The profiler * @param array $server The $_SERVER variables * * @throws \Exception if connection went bad */ - public static function init(Cache\ConfigCache $configCache, array $server) + public static function init(Cache\IConfigCache $configCache, Profiler $profiler, array $server) { if (Database\DBA::connected()) { return; @@ -46,7 +48,7 @@ class DBFactory $db_data = $server['MYSQL_DATABASE']; } - if (Database\DBA::connect($configCache, $db_host, $db_user, $db_pass, $db_data, $charset)) { + if (Database\DBA::connect($configCache, $profiler, $db_host, $db_user, $db_pass, $db_data, $charset)) { // Loads DB_UPDATE_VERSION constant Database\DBStructure::definition($configCache->get('system', 'basepath'), false); } diff --git a/src/Factory/DependencyFactory.php b/src/Factory/DependencyFactory.php index 041202e6b..acbf4bfaf 100644 --- a/src/Factory/DependencyFactory.php +++ b/src/Factory/DependencyFactory.php @@ -25,12 +25,13 @@ class DependencyFactory $basedir = BasePath::create($directory, $_SERVER); $configLoader = new Cache\ConfigCacheLoader($basedir); $configCache = Factory\ConfigFactory::createCache($configLoader); - Factory\DBFactory::init($configCache, $_SERVER); + $profiler = Factory\ProfilerFactory::create($configCache); + Factory\DBFactory::init($configCache, $profiler, $_SERVER); $config = Factory\ConfigFactory::createConfig($configCache); // needed to call PConfig::init() Factory\ConfigFactory::createPConfig($configCache); - Factory\LoggerFactory::create($channel, $config); + $logger = Factory\LoggerFactory::create($channel, $config); - return new App($config, $isBackend); + return new App($config, $logger, $profiler, $isBackend); } } diff --git a/src/Factory/LoggerFactory.php b/src/Factory/LoggerFactory.php index bbe3b0a4b..77a09637c 100644 --- a/src/Factory/LoggerFactory.php +++ b/src/Factory/LoggerFactory.php @@ -42,6 +42,8 @@ class LoggerFactory if ($debugging) { $loglevel = self::mapLegacyConfigDebugLevel((string)$level); static::addStreamHandler($logger, $stream, $loglevel); + } else { + static::addVoidHandler($logger); } Logger::init($logger); @@ -153,4 +155,11 @@ class LoggerFactory throw new InternalServerErrorException('Logger instance incompatible for MonologFactory'); } } + + public static function addVoidHandler($logger) + { + if ($logger instanceof Monolog\Logger) { + $logger->pushHandler(new Monolog\Handler\NullHandler()); + } + } } diff --git a/src/Factory/ProfilerFactory.php b/src/Factory/ProfilerFactory.php index 7a63c7440..26a156639 100644 --- a/src/Factory/ProfilerFactory.php +++ b/src/Factory/ProfilerFactory.php @@ -2,24 +2,25 @@ namespace Friendica\Factory; -use Friendica\Core\Config\ConfigCache; +use Friendica\Core\Config\Cache\IConfigCache; use Friendica\Util\Profiler; -use Psr\Log\LoggerInterface; class ProfilerFactory { /** * Creates a Profiler for the current execution * - * @param LoggerInterface $logger The logger for saving the profiling data - * @param ConfigCache $configCache The configuration cache + * @param IConfigCache $configCache The configuration cache * * @return Profiler */ - public static function create(LoggerInterface $logger, ConfigCache $configCache) + public static function create(IConfigCache $configCache) { - $enabled = $configCache->get('system', 'profiler', false); - $renderTime = $configCache->get('rendertime', 'callstack', false); - return new Profiler($logger, $enabled, $renderTime); + $enabled = $configCache->get('system', 'profiler'); + $enabled = isset($enabled) && $enabled !== '!!'; + $renderTime = $configCache->get('rendertime', 'callstack'); + $renderTime = isset($renderTime) && $renderTime !== '!!'; + + return new Profiler($enabled, $renderTime); } } diff --git a/src/Util/Profiler.php b/src/Util/Profiler.php index a3f889380..2d3da3a9c 100644 --- a/src/Util/Profiler.php +++ b/src/Util/Profiler.php @@ -33,20 +33,13 @@ class Profiler implements ContainerInterface private $rendertime; /** - * @var LoggerInterface The profiler logger - */ - private $logger; - - /** - * @param LoggerInterface $logger The profiler logger * @param bool $enabled True, if the Profiler is enabled * @param bool $renderTime True, if the Profiler should measure the whole rendertime including functions */ - public function __construct(LoggerInterface $logger, $enabled = false, $renderTime = false) + public function __construct($enabled = false, $renderTime = false) { $this->enabled = $enabled; $this->rendertime = $renderTime; - $this->logger = $logger; $this->reset(); } @@ -129,16 +122,17 @@ class Profiler implements ContainerInterface /** * Save the current profiling data to a log entry * - * @param string $message Additional message for the log + * @param LoggerInterface $logger The logger to save the current log + * @param string $message Additional message for the log */ - public function saveLog($message = '') + public function saveLog(LoggerInterface $logger, $message = '') { // Write down the performance values into the log if (!$this->enabled) { return; } $duration = microtime(true) - $this->get('start'); - $this->logger->info( + $logger->info( $message, [ 'action' => 'profiling', @@ -205,7 +199,7 @@ class Profiler implements ContainerInterface } } } - $this->logger->info($message . ": " . $o, ['action' => 'profiling']); + $logger->info($message . ": " . $o, ['action' => 'profiling']); } /** diff --git a/tests/include/ApiTest.php b/tests/include/ApiTest.php index 59096f5e5..289b3fcea 100644 --- a/tests/include/ApiTest.php +++ b/tests/include/ApiTest.php @@ -39,13 +39,12 @@ class ApiTest extends DatabaseTest $basedir = BasePath::create(dirname(__DIR__) . '/../'); $configLoader = new Cache\ConfigCacheLoader($basedir); $configCache = Factory\ConfigFactory::createCache($configLoader); - Factory\DBFactory::init($configCache, $_SERVER); + $profiler = Factory\ProfilerFactory::create($configCache); + Factory\DBFactory::init($configCache, $profiler, $_SERVER); $config = Factory\ConfigFactory::createConfig($configCache); Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('test', $config); - $profiler = Factory\ProfilerFactory::create($logger, $config); $this->app = new App($config, $logger, $profiler, false); - $this->logOutput = FActory\LoggerFactory::enableTest($this->app->getLogger()); parent::setUp(); diff --git a/tests/src/Database/DBATest.php b/tests/src/Database/DBATest.php index a4a715575..e8b9c68b1 100644 --- a/tests/src/Database/DBATest.php +++ b/tests/src/Database/DBATest.php @@ -16,13 +16,12 @@ class DBATest extends DatabaseTest $basedir = BasePath::create(dirname(__DIR__) . '/../../'); $configLoader = new Cache\ConfigCacheLoader($basedir); $configCache = Factory\ConfigFactory::createCache($configLoader); - Factory\DBFactory::init($configCache, $_SERVER); + $profiler = Factory\ProfilerFactory::create($configCache); + Factory\DBFactory::init($configCache, $profiler, $_SERVER); $config = Factory\ConfigFactory::createConfig($configCache); - $pconfig = Factory\ConfigFactory::createPConfig($configCache); + Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('test', $config); - $profiler = Factory\ProfilerFactory::create($logger, $config); $this->app = new App($config, $logger, $profiler, false); - $this->logOutput = FActory\LoggerFactory::enableTest($this->app->getLogger()); parent::setUp(); diff --git a/tests/src/Database/DBStructureTest.php b/tests/src/Database/DBStructureTest.php index 6a5e25e76..325ad4e5e 100644 --- a/tests/src/Database/DBStructureTest.php +++ b/tests/src/Database/DBStructureTest.php @@ -16,13 +16,12 @@ class DBStructureTest extends DatabaseTest $basedir = BasePath::create(dirname(__DIR__) . '/../../'); $configLoader = new Cache\ConfigCacheLoader($basedir); $configCache = Factory\ConfigFactory::createCache($configLoader); - Factory\DBFactory::init($configCache, $_SERVER); + $profiler = Factory\ProfilerFactory::create($configCache); + Factory\DBFactory::init($configCache, $profiler, $_SERVER); $config = Factory\ConfigFactory::createConfig($configCache); - $pconfig = Factory\ConfigFactory::createPConfig($configCache); + Factory\ConfigFactory::createPConfig($configCache); $logger = Factory\LoggerFactory::create('test', $config); - $profiler = Factory\ProfilerFactory::create($logger, $config); $this->app = new App($config, $logger, $profiler, false); - $this->logOutput = FActory\LoggerFactory::enableTest($this->app->getLogger()); parent::setUp(); } diff --git a/tests/src/Util/ProfilerTest.php b/tests/src/Util/ProfilerTest.php index f9febeae8..f242fd43c 100644 --- a/tests/src/Util/ProfilerTest.php +++ b/tests/src/Util/ProfilerTest.php @@ -26,7 +26,7 @@ class ProfilerTest extends MockedTest */ public function testSetUp() { - $profiler = new Profiler($this->logger, true, true); + $profiler = new Profiler(true, true); } /** @@ -96,7 +96,7 @@ class ProfilerTest extends MockedTest */ public function testSaveTimestamp($timestamp, $name, array $functions) { - $profiler = new Profiler($this->logger, true, true); + $profiler = new Profiler(true, true); foreach ($functions as $function) { $profiler->saveTimestamp($timestamp, $name, $function); @@ -111,7 +111,7 @@ class ProfilerTest extends MockedTest */ public function testReset($timestamp, $name, array $functions) { - $profiler = new Profiler($this->logger, true, true); + $profiler = new Profiler(true, true); $profiler->saveTimestamp($timestamp, $name); $profiler->reset(); @@ -168,7 +168,7 @@ class ProfilerTest extends MockedTest ->shouldReceive('info') ->once(); - $profiler = new Profiler($this->logger, true, true); + $profiler = new Profiler(true, true); foreach ($data as $perf => $items) { foreach ($items['functions'] as $function) { @@ -176,6 +176,6 @@ class ProfilerTest extends MockedTest } } - $profiler->saveLog('test'); + $profiler->saveLog($this->logger, 'test'); } } From f5adbd268b0ad6f9e090ebb44dc32a0d4a1fec3c Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 17 Feb 2019 21:41:45 +0100 Subject: [PATCH 19/20] Fixing tests --- tests/Util/AppMockTrait.php | 56 +++++++++++-------- tests/Util/DBStructureMockTrait.php | 2 + tests/src/App/ModeTest.php | 4 +- tests/src/BaseObjectTest.php | 3 +- tests/src/Core/Cache/CacheTest.php | 3 +- .../Core/Cache/MemcacheCacheDriverTest.php | 8 +-- .../Core/Cache/MemcachedCacheDriverTest.php | 4 +- tests/src/Core/Cache/RedisCacheDriverTest.php | 8 +-- tests/src/Core/Config/ConfigurationTest.php | 21 +++---- tests/src/Core/Config/PConfigurationTest.php | 19 ++++--- .../AutomaticInstallationConsoleTest.php | 4 +- tests/src/Core/Console/ConfigConsoleTest.php | 28 +++++----- tests/src/Core/Console/ConsoleTest.php | 7 +-- tests/src/Core/Lock/LockTest.php | 3 +- .../Core/Lock/MemcacheCacheLockDriverTest.php | 8 +-- .../Lock/MemcachedCacheLockDriverTest.php | 4 +- .../Core/Lock/RedisCacheLockDriverTest.php | 8 +-- .../src/Core/Lock/SemaphoreLockDriverTest.php | 4 +- 18 files changed, 101 insertions(+), 93 deletions(-) diff --git a/tests/Util/AppMockTrait.php b/tests/Util/AppMockTrait.php index 66b95b04e..817570dd5 100644 --- a/tests/Util/AppMockTrait.php +++ b/tests/Util/AppMockTrait.php @@ -6,6 +6,7 @@ use Friendica\App; use Friendica\BaseObject; use Friendica\Core\Config; use Friendica\Render\FriendicaSmartyEngine; +use Friendica\Util\Profiler; use Mockery\MockInterface; use org\bovigo\vfs\vfsStreamDirectory; @@ -22,70 +23,81 @@ trait AppMockTrait /** * @var MockInterface|Config\Configuration The mocked Config Cache */ - protected $configCache; + protected $configMock; + + /** + * @var MockInterface|Profiler The mocked profiler + */ + protected $profilerMock; /** * Mock the App * * @param vfsStreamDirectory $root The root directory - * @param MockInterface|Config\Configuration $config The config cache */ - public function mockApp($root, Config\Configuration $config) + public function mockApp($root) { - $this->configCache = $config; + $this->configMock = \Mockery::mock(Config\Cache\IConfigCache::class); + $configAdapterMock = \Mockery::mock(Config\Adapter\IConfigAdapter::class); + // Disable the adapter + $configAdapterMock->shouldReceive('isConnected')->andReturn(false); + + $config = new Config\Configuration($this->configMock, $configAdapterMock); + // Initialize empty Config + Config::init($config); + // Mocking App and most used functions $this->app = \Mockery::mock(App::class); $this->app ->shouldReceive('getBasePath') ->andReturn($root->url()); - $config + $this->configMock + ->shouldReceive('has') + ->andReturn(true); + $this->configMock ->shouldReceive('get') ->with('database', 'hostname') ->andReturn(getenv('MYSQL_HOST')); - $config + $this->configMock ->shouldReceive('get') ->with('database', 'username') ->andReturn(getenv('MYSQL_USERNAME')); - $config + $this->configMock ->shouldReceive('get') ->with('database', 'password') ->andReturn(getenv('MYSQL_PASSWORD')); - $config + $this->configMock ->shouldReceive('get') ->with('database', 'database') ->andReturn(getenv('MYSQL_DATABASE')); - $config + $this->configMock ->shouldReceive('get') ->with('config', 'hostname') ->andReturn('localhost'); - $config + $this->configMock ->shouldReceive('get') - ->with('system', 'theme', NULL, false) + ->with('system', 'theme') ->andReturn('system_theme'); - $config - ->shouldReceive('getConfig') - ->andReturn($config); + + $this->profilerMock = \Mockery::mock(Profiler::class); + $this->profilerMock->shouldReceive('saveTimestamp'); $this->app ->shouldReceive('getConfigCache') - ->andReturn($config); - + ->andReturn($this->configMock); $this->app ->shouldReceive('getTemplateEngine') ->andReturn(new FriendicaSmartyEngine()); $this->app ->shouldReceive('getCurrentTheme') ->andReturn('Smarty3'); - $this->app - ->shouldReceive('saveTimestamp') - ->andReturn(true); $this->app ->shouldReceive('getBaseUrl') ->andReturn('http://friendica.local'); - - // Initialize empty Config - Config::init($config); + $this->app + ->shouldReceive('getProfiler') + ->andReturn($this->profilerMock); BaseObject::setApp($this->app); } diff --git a/tests/Util/DBStructureMockTrait.php b/tests/Util/DBStructureMockTrait.php index 87c120d3f..92ec412cb 100644 --- a/tests/Util/DBStructureMockTrait.php +++ b/tests/Util/DBStructureMockTrait.php @@ -2,6 +2,7 @@ namespace Friendica\Test\Util; +use Friendica\Database\DBStructure; use Mockery\MockInterface; /** @@ -16,6 +17,7 @@ trait DBStructureMockTrait /** * Mocking DBStructure::update() + * @see DBStructure::update(); * * @param array $args The arguments for the update call * @param bool $return True, if the connect was successful, otherwise false diff --git a/tests/src/App/ModeTest.php b/tests/src/App/ModeTest.php index 5a5c4c87e..9059e8beb 100644 --- a/tests/src/App/ModeTest.php +++ b/tests/src/App/ModeTest.php @@ -90,7 +90,7 @@ class ModeTest extends MockedTest $this->mockConnected(true, 1); $this->mockFetchFirst('SHOW TABLES LIKE \'config\'', true, 1); - $config = \Mockery::mock('Friendica\Core\Config\Configuration'); + $config = \Mockery::mock(Config\Configuration::class); $config ->shouldReceive('get') ->with('system', 'maintenance', null, false) @@ -118,7 +118,7 @@ class ModeTest extends MockedTest $this->mockConnected(true, 1); $this->mockFetchFirst('SHOW TABLES LIKE \'config\'', true, 1); - $config = \Mockery::mock('Friendica\Core\Config\Configuration'); + $config = \Mockery::mock(Config\Configuration::class); $config ->shouldReceive('get') ->with('system', 'maintenance', null, false) diff --git a/tests/src/BaseObjectTest.php b/tests/src/BaseObjectTest.php index 39741eb9e..334150391 100644 --- a/tests/src/BaseObjectTest.php +++ b/tests/src/BaseObjectTest.php @@ -31,8 +31,7 @@ class BaseObjectTest extends TestCase { $baseObject = new BaseObject(); $this->setUpVfsDir(); - $configMock = \Mockery::mock('Friendica\Core\Config\Configuration'); - $this->mockApp($this->root, $configMock); + $this->mockApp($this->root); $this->assertNull($baseObject->setApp($this->app)); $this->assertEquals($this->app, $baseObject->getApp()); diff --git a/tests/src/Core/Cache/CacheTest.php b/tests/src/Core/Cache/CacheTest.php index 961ac9e1b..ef97f5a17 100644 --- a/tests/src/Core/Cache/CacheTest.php +++ b/tests/src/Core/Cache/CacheTest.php @@ -67,8 +67,7 @@ abstract class CacheTest extends MockedTest protected function setUp() { $this->setUpVfsDir(); - $configMock = \Mockery::mock('Friendica\Core\Config\Configuration'); - $this->mockApp($this->root, $configMock); + $this->mockApp($this->root); $this->app ->shouldReceive('getHostname') ->andReturn('friendica.local'); diff --git a/tests/src/Core/Cache/MemcacheCacheDriverTest.php b/tests/src/Core/Cache/MemcacheCacheDriverTest.php index 5017b6967..f9df9eaba 100644 --- a/tests/src/Core/Cache/MemcacheCacheDriverTest.php +++ b/tests/src/Core/Cache/MemcacheCacheDriverTest.php @@ -12,14 +12,14 @@ class MemcacheCacheDriverTest extends MemoryCacheTest { protected function getInstance() { - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('system', 'memcache_host', NULL, false) + ->with('system', 'memcache_host') ->andReturn('localhost'); - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('system', 'memcache_port', NULL, false) + ->with('system', 'memcache_port') ->andReturn(11211); $this->cache = CacheDriverFactory::create('memcache'); diff --git a/tests/src/Core/Cache/MemcachedCacheDriverTest.php b/tests/src/Core/Cache/MemcachedCacheDriverTest.php index 7c6835359..4e16ef947 100644 --- a/tests/src/Core/Cache/MemcachedCacheDriverTest.php +++ b/tests/src/Core/Cache/MemcachedCacheDriverTest.php @@ -12,9 +12,9 @@ class MemcachedCacheDriverTest extends MemoryCacheTest { protected function getInstance() { - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('system', 'memcached_hosts', NULL, false) + ->with('system', 'memcached_hosts') ->andReturn([0 => 'localhost, 11211']); $this->cache = CacheDriverFactory::create('memcached'); diff --git a/tests/src/Core/Cache/RedisCacheDriverTest.php b/tests/src/Core/Cache/RedisCacheDriverTest.php index d36e6b826..20fe7eb53 100644 --- a/tests/src/Core/Cache/RedisCacheDriverTest.php +++ b/tests/src/Core/Cache/RedisCacheDriverTest.php @@ -12,14 +12,14 @@ class RedisCacheDriverTest extends MemoryCacheTest { protected function getInstance() { - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('system', 'redis_host', NULL, false) + ->with('system', 'redis_host') ->andReturn('localhost'); - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('system', 'redis_port', NULL, false) + ->with('system', 'redis_port') ->andReturn(null); $this->cache = CacheDriverFactory::create('redis'); diff --git a/tests/src/Core/Config/ConfigurationTest.php b/tests/src/Core/Config/ConfigurationTest.php index 0437f1e7a..2e4fcd4f5 100644 --- a/tests/src/Core/Config/ConfigurationTest.php +++ b/tests/src/Core/Config/ConfigurationTest.php @@ -2,6 +2,7 @@ namespace Friendica\Test\Core\Config; +use Friendica\Core\Config\Adapter\IConfigAdapter; use Friendica\Core\Config\Cache\ConfigCache; use Friendica\Core\Config\Cache\IConfigCache; use Friendica\Core\Config\Configuration; @@ -29,7 +30,7 @@ class ConfigurationTest extends MockedTest public function testSetUp() { $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter = \Mockery::mock(IConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(false)->once(); $configuration = new Configuration($configCache, $configAdapter); @@ -43,7 +44,7 @@ class ConfigurationTest extends MockedTest public function testCacheLoad() { $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter = \Mockery::mock(IConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); // constructor loading $configAdapter->shouldReceive('load')->andReturn([])->once(); @@ -64,7 +65,7 @@ class ConfigurationTest extends MockedTest public function testCacheLoadDouble() { $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter = \Mockery::mock(IConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(5); // constructor loading $configAdapter->shouldReceive('load')->andReturn([])->once(); @@ -93,7 +94,7 @@ class ConfigurationTest extends MockedTest public function testSetGetWithoutDB($data) { $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter = \Mockery::mock(IConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3); $configuration = new Configuration($configCache, $configAdapter); @@ -111,7 +112,7 @@ class ConfigurationTest extends MockedTest public function testSetGetWithDB($data) { $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter = \Mockery::mock(IConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); // constructor loading $configAdapter->shouldReceive('load')->andReturn([])->once(); @@ -132,7 +133,7 @@ class ConfigurationTest extends MockedTest public function testGetWrongWithoutDB() { $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter = \Mockery::mock(IConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(4); $configuration = new Configuration($configCache, $configAdapter); @@ -157,7 +158,7 @@ class ConfigurationTest extends MockedTest public function testGetWithRefresh($data) { $configCache = new ConfigCache(['test' => ['it' => 'now']]); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter = \Mockery::mock(IConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(4); // constructor loading $configAdapter->shouldReceive('load')->andReturn([])->once(); @@ -188,7 +189,7 @@ class ConfigurationTest extends MockedTest public function testGetWithoutLoaded($data) { $configCache = new ConfigCache(['test' => ['it' => 'now']]); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter = \Mockery::mock(IConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(4); // constructor loading $configAdapter->shouldReceive('load')->andReturn([])->once(); @@ -223,7 +224,7 @@ class ConfigurationTest extends MockedTest public function testDeleteWithoutDB($data) { $configCache = new ConfigCache(['test' => ['it' => $data]]); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter = \Mockery::mock(IConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(4); $configuration = new Configuration($configCache, $configAdapter); @@ -244,7 +245,7 @@ class ConfigurationTest extends MockedTest public function testDeleteWithDB() { $configCache = new ConfigCache(['test' => ['it' => 'now', 'quarter' => 'true']]); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IConfigAdapter'); + $configAdapter = \Mockery::mock(IConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(6); // constructor loading $configAdapter->shouldReceive('load')->andReturn([])->once(); diff --git a/tests/src/Core/Config/PConfigurationTest.php b/tests/src/Core/Config/PConfigurationTest.php index 8ecc9bdf3..025994414 100644 --- a/tests/src/Core/Config/PConfigurationTest.php +++ b/tests/src/Core/Config/PConfigurationTest.php @@ -2,6 +2,7 @@ namespace Friendica\Test\Core\Config; +use Friendica\Core\Config\Adapter\IPConfigAdapter; use Friendica\Core\Config\Cache\ConfigCache; use Friendica\Core\Config\PConfiguration; use Friendica\Test\MockedTest; @@ -29,7 +30,7 @@ class PConfigurationTest extends MockedTest { $uid = 234; $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter = \Mockery::mock(IPConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->twice(); // expected loading $configAdapter->shouldReceive('load') @@ -51,7 +52,7 @@ class PConfigurationTest extends MockedTest { $uid = 234; $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter = \Mockery::mock(IPConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(4); // expected loading $configAdapter->shouldReceive('load')->with($uid, 'testing')->andReturn(['testing' => ['test' => 'it']])->once(); @@ -77,7 +78,7 @@ class PConfigurationTest extends MockedTest { $uid = 234; $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter = \Mockery::mock(IPConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(2); $configuration = new PConfiguration($configCache, $configAdapter); @@ -95,7 +96,7 @@ class PConfigurationTest extends MockedTest { $uid = 234; $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter = \Mockery::mock(IPConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(2); $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(true)->once(); $configAdapter->shouldReceive('set')->with($uid, 'test', 'it', $data)->andReturn(true)->once(); @@ -114,7 +115,7 @@ class PConfigurationTest extends MockedTest { $uid = 234; $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter = \Mockery::mock(IPConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(3); $configuration = new PConfiguration($configCache, $configAdapter); @@ -137,7 +138,7 @@ class PConfigurationTest extends MockedTest { $uid = 234; $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter = \Mockery::mock(IPConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(4); $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(false)->once(); $configAdapter->shouldReceive('get')->with($uid, 'test', 'it')->andReturn('now')->once(); @@ -168,7 +169,7 @@ class PConfigurationTest extends MockedTest { $uid = 234; $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter = \Mockery::mock(IPConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(3); $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(false)->once(); @@ -199,7 +200,7 @@ class PConfigurationTest extends MockedTest { $uid = 234; $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter = \Mockery::mock(IPConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(false)->times(4); $configuration = new PConfiguration($configCache, $configAdapter); @@ -218,7 +219,7 @@ class PConfigurationTest extends MockedTest { $uid = 234; $configCache = new ConfigCache(); - $configAdapter = \Mockery::mock('Friendica\Core\Config\Adapter\IPConfigAdapter'); + $configAdapter = \Mockery::mock(IPConfigAdapter::class); $configAdapter->shouldReceive('isConnected')->andReturn(true)->times(6); $configAdapter->shouldReceive('set')->with($uid, 'test', 'it', 'now')->andReturn(false)->once(); $configAdapter->shouldReceive('isLoaded')->with($uid, 'test', 'it')->andReturn(true)->once(); diff --git a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php index ce3dac02c..73b6835fb 100644 --- a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php +++ b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php @@ -52,9 +52,9 @@ class AutomaticInstallationConsoleTest extends ConsoleTest $this->db_user = getenv('MYSQL_USERNAME') . getenv('MYSQL_USER'); $this->db_pass = getenv('MYSQL_PASSWORD'); - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('config', 'php_path', NULL, false) + ->with('config', 'php_path') ->andReturn(false); $this->mockL10nT(); diff --git a/tests/src/Core/Console/ConfigConsoleTest.php b/tests/src/Core/Console/ConfigConsoleTest.php index 5b7d14906..579b28e02 100644 --- a/tests/src/Core/Console/ConfigConsoleTest.php +++ b/tests/src/Core/Console/ConfigConsoleTest.php @@ -32,14 +32,14 @@ class ConfigConsoleTest extends ConsoleTest } function testSetGetKeyValue() { - $this->configCache + $this->configMock ->shouldReceive('set') ->with('config', 'test', 'now') ->andReturn(true) ->once(); - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('config', 'test', NULL, false) + ->with('config', 'test') ->andReturn('now') ->twice(); @@ -50,9 +50,9 @@ class ConfigConsoleTest extends ConsoleTest $txt = $this->dumpExecute($console); $this->assertEquals("config.test <= now\n", $txt); - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('config', 'test', null, false) + ->with('config', 'test') ->andReturn('now') ->once(); @@ -62,9 +62,9 @@ class ConfigConsoleTest extends ConsoleTest $txt = $this->dumpExecute($console); $this->assertEquals("config.test => now\n", $txt); - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('config', 'test', null, false) + ->with('config', 'test') ->andReturn(null) ->once(); @@ -77,9 +77,9 @@ class ConfigConsoleTest extends ConsoleTest function testSetArrayValue() { $testArray = [1, 2, 3]; - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('config', 'test', null, false) + ->with('config', 'test') ->andReturn($testArray) ->once(); @@ -105,9 +105,9 @@ class ConfigConsoleTest extends ConsoleTest } function testVerbose() { - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('test', 'it', null, false) + ->with('test', 'it') ->andReturn('now') ->once(); $console = new Config($this->consoleArgv); @@ -133,14 +133,14 @@ CONF; } function testUnableToSet() { - $this->configCache + $this->configMock ->shouldReceive('set') ->with('test', 'it', 'now') ->andReturn(false) ->once(); - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('test', 'it', NULL, false) + ->with('test', 'it') ->andReturn(NULL) ->once(); $console = new Config(); diff --git a/tests/src/Core/Console/ConsoleTest.php b/tests/src/Core/Console/ConsoleTest.php index f733175d3..4f7acc9c4 100644 --- a/tests/src/Core/Console/ConsoleTest.php +++ b/tests/src/Core/Console/ConsoleTest.php @@ -3,12 +3,10 @@ namespace Friendica\Test\src\Core\Console; use Asika\SimpleConsole\Console; -use Friendica\Core\Config\Configuration; use Friendica\Test\MockedTest; use Friendica\Test\Util\AppMockTrait; use Friendica\Test\Util\Intercept; use Friendica\Test\Util\VFSTrait; -use Friendica\Util\Profiler; abstract class ConsoleTest extends MockedTest { @@ -31,10 +29,7 @@ abstract class ConsoleTest extends MockedTest Intercept::setUp(); $this->setUpVfsDir(); - $configMock = \Mockery::mock(Configuration::class); - $this->mockApp($this->root, $configMock); - $profileMock = \Mockery::mock(Profiler::class); - $this->app->shouldReceive('getProfiler')->andReturn($profileMock); + $this->mockApp($this->root); } /** diff --git a/tests/src/Core/Lock/LockTest.php b/tests/src/Core/Lock/LockTest.php index c1378aa16..6dc170e51 100644 --- a/tests/src/Core/Lock/LockTest.php +++ b/tests/src/Core/Lock/LockTest.php @@ -27,8 +27,7 @@ abstract class LockTest extends MockedTest { // Reusable App object $this->setUpVfsDir(); - $configMock = \Mockery::mock('Friendica\Core\Config\Configuration'); - $this->mockApp($this->root, $configMock); + $this->mockApp($this->root); $this->app ->shouldReceive('getHostname') ->andReturn('friendica.local'); diff --git a/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php b/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php index 0e118c5dd..ad20f5bfd 100644 --- a/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php +++ b/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php @@ -13,14 +13,14 @@ class MemcacheCacheLockDriverTest extends LockTest { protected function getInstance() { - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('system', 'memcache_host', NULL, false) + ->with('system', 'memcache_host') ->andReturn('localhost'); - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('system', 'memcache_port', NULL, false) + ->with('system', 'memcache_port') ->andReturn(11211); return new CacheLockDriver(CacheDriverFactory::create('memcache')); diff --git a/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php b/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php index fe490a38c..a5bdeaedb 100644 --- a/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php +++ b/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php @@ -13,9 +13,9 @@ class MemcachedCacheLockDriverTest extends LockTest { protected function getInstance() { - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('system', 'memcached_hosts', NULL, false) + ->with('system', 'memcached_hosts') ->andReturn([0 => 'localhost, 11211']); return new CacheLockDriver(CacheDriverFactory::create('memcached')); diff --git a/tests/src/Core/Lock/RedisCacheLockDriverTest.php b/tests/src/Core/Lock/RedisCacheLockDriverTest.php index f5d0a648f..5f047bc66 100644 --- a/tests/src/Core/Lock/RedisCacheLockDriverTest.php +++ b/tests/src/Core/Lock/RedisCacheLockDriverTest.php @@ -13,14 +13,14 @@ class RedisCacheLockDriverTest extends LockTest { protected function getInstance() { - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('system', 'redis_host', NULL, false) + ->with('system', 'redis_host') ->andReturn('localhost'); - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('system', 'redis_port', NULL, false) + ->with('system', 'redis_port') ->andReturn(null); return new CacheLockDriver(CacheDriverFactory::create('redis')); diff --git a/tests/src/Core/Lock/SemaphoreLockDriverTest.php b/tests/src/Core/Lock/SemaphoreLockDriverTest.php index bf422f2f8..a37fbffbe 100644 --- a/tests/src/Core/Lock/SemaphoreLockDriverTest.php +++ b/tests/src/Core/Lock/SemaphoreLockDriverTest.php @@ -12,9 +12,9 @@ class SemaphoreLockDriverTest extends LockTest $this->app->shouldReceive('getHostname')->andReturn('friendica.local'); - $this->configCache + $this->configMock ->shouldReceive('get') - ->with('system', 'temppath', NULL, false) + ->with('system', 'temppath') ->andReturn('/tmp/'); } From bfed7b3b2faaabd627bdeb09dc3b0bd16b1f3f5e Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 17 Feb 2019 21:43:19 +0100 Subject: [PATCH 20/20] removing comment --- index.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/index.php b/index.php index 6bbd70a19..47264362c 100644 --- a/index.php +++ b/index.php @@ -12,8 +12,6 @@ if (!file_exists(__DIR__ . '/vendor/autoload.php')) { require __DIR__ . '/vendor/autoload.php'; -// We assume that the index.php is called by a frontend process -// The value is set to "true" by default in App $a = Factory\DependencyFactory::setUp('index', __DIR__, true); $a->runFrontend();