diff --git a/mod/friendica.php b/mod/friendica.php index d10deb2e88..10a4f93aff 100644 --- a/mod/friendica.php +++ b/mod/friendica.php @@ -29,7 +29,7 @@ function friendica_init(App $a) } $sql_extra = ''; - if (!empty($a->config['admin_nickname'])) { + if (Config::getConfigValue('config', 'admin_nickname') !== null) { $sql_extra = sprintf(" AND `nickname` = '%s' ", DBA::escape(Config::get('config', 'admin_nickname'))); } if (!empty(Config::get('config', 'admin_email'))) { @@ -48,8 +48,9 @@ function friendica_init(App $a) Config::load('feature_lock'); $locked_features = []; - if (!empty($a->config['feature_lock'])) { - foreach ($a->config['feature_lock'] as $k => $v) { + $featureLock = Config::getConfigValue('config', 'feature_lock'); + if (isset($featureLock)) { + foreach ($featureLock as $k => $v) { if ($k === 'config_loaded') { continue; } diff --git a/src/App.php b/src/App.php index b910765e12..db35c45c19 100644 --- a/src/App.php +++ b/src/App.php @@ -381,28 +381,29 @@ class App include $this->getBasePath() . '/.htconfig.php'; - $this->setConfigValue('database', 'hostname', $db_host); - $this->setConfigValue('database', 'username', $db_user); - $this->setConfigValue('database', 'password', $db_pass); - $this->setConfigValue('database', 'database', $db_data); - if (isset($a->config['system']['db_charset'])) { - $this->setConfigValue('database', 'charset', $a->config['system']['db_charset']); + Core\Config::setConfigValue('database', 'hostname', $db_host); + Core\Config::setConfigValue('database', 'username', $db_user); + Core\Config::setConfigValue('database', 'password', $db_pass); + Core\Config::setConfigValue('database', 'database', $db_data); + $charset = Core\Config::getConfigValue('system', 'db_charset'); + if (isset($charset)) { + Core\Config::setConfigValue('database', 'charset', $charset); } unset($db_host, $db_user, $db_pass, $db_data); if (isset($default_timezone)) { - $this->setConfigValue('system', 'default_timezone', $default_timezone); + Core\Config::setConfigValue('system', 'default_timezone', $default_timezone); unset($default_timezone); } if (isset($pidfile)) { - $this->setConfigValue('system', 'pidfile', $pidfile); + Core\Config::setConfigValue('system', 'pidfile', $pidfile); unset($pidfile); } if (isset($lang)) { - $this->setConfigValue('system', 'language', $lang); + Core\Config::setConfigValue('system', 'language', $lang); unset($lang); } } @@ -437,7 +438,7 @@ class App throw new Exception('Error parsing INI config file ' . $filepath); } - $this->loadConfigArray($config, $overwrite); + Core\Config::loadConfigArray($config, $overwrite); } /** @@ -468,7 +469,7 @@ class App throw new Exception('Error loading config file ' . $filepath); } - $this->loadConfigArray($config, $overwrite); + Core\Config::loadConfigArray($config, $overwrite); } /** @@ -490,26 +491,6 @@ class App } } - /** - * Tries to load the specified configuration array into the App->config array. - * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. - * - * @param array $config - * @param bool $overwrite Force value overwrite if the config key already exists - */ - private function loadConfigArray(array $config, $overwrite = false) - { - foreach ($config as $category => $values) { - foreach ($values as $key => $value) { - if ($overwrite) { - $this->setConfigValue($category, $key, $value); - } else { - $this->setDefaultConfigValue($category, $key, $value); - } - } - } - } - /** * Loads the default timezone * @@ -519,8 +500,8 @@ class App */ private function loadDefaultTimezone() { - if ($this->getConfigValue('system', 'default_timezone')) { - $this->timezone = $this->getConfigValue('system', 'default_timezone'); + if (Core\Config::getConfigValue('system', 'default_timezone')) { + $this->timezone = Core\Config::getConfigValue('system', 'default_timezone'); } else { global $default_timezone; $this->timezone = !empty($default_timezone) ? $default_timezone : 'UTC'; @@ -546,7 +527,7 @@ class App $relative_script_path = defaults($_SERVER, 'SCRIPT_URL' , $relative_script_path); $relative_script_path = defaults($_SERVER, 'REQUEST_URI' , $relative_script_path); - $this->urlPath = $this->getConfigValue('system', 'urlpath'); + $this->urlPath = Core\Config::getConfigValue('system', 'urlpath'); /* $relative_script_path gives /relative/path/to/friendica/module/parameter * QUERY_STRING gives pagename=module/parameter @@ -574,11 +555,11 @@ class App return; } - $db_host = $this->getConfigValue('database', 'hostname'); - $db_user = $this->getConfigValue('database', 'username'); - $db_pass = $this->getConfigValue('database', 'password'); - $db_data = $this->getConfigValue('database', 'database'); - $charset = $this->getConfigValue('database', 'charset'); + $db_host = Core\Config::getConfigValue('database', 'hostname'); + $db_user = Core\Config::getConfigValue('database', 'username'); + $db_pass = Core\Config::getConfigValue('database', 'password'); + $db_data = Core\Config::getConfigValue('database', 'database'); + $charset = Core\Config::getConfigValue('database', 'charset'); // Use environment variables for mysql if they are set beforehand if (!empty(getenv('MYSQL_HOST')) @@ -789,9 +770,9 @@ class App // compose the page title from the sitename and the // current module called if (!$this->module == '') { - $this->page['title'] = $this->config['sitename'] . ' (' . $this->module . ')'; + $this->page['title'] = Core\Config::getConfigValue('config', 'sitename') . ' (' . $this->module . ')'; } else { - $this->page['title'] = $this->config['sitename']; + $this->page['title'] = Core\Config::getConfigValue('config', 'sitename'); } if (!empty(Core\Renderer::$theme['stylesheet'])) { @@ -912,7 +893,9 @@ class App */ public function saveTimestamp($timestamp, $value) { - if (!isset($this->config['system']['profiler']) || !$this->config['system']['profiler']) { + $profiler = Core\Config::getConfigValue('system', 'profiler'); + + if (!isset($profiler) || !$profiler) { return; } @@ -1150,7 +1133,7 @@ class App return; } - $cmdline = $this->getConfigValue('config', 'php_path', 'php') . ' ' . escapeshellarg($command); + $cmdline = Core\Config::getConfigValue('config', 'php_path', 'php') . ' ' . escapeshellarg($command); foreach ($args as $key => $value) { if (!is_null($value) && is_bool($value) && !$value) { @@ -1234,87 +1217,6 @@ class App return true; } - /** - * @param string $cat Config category - * @param string $k Config key - * @param mixed $default Default value if it isn't set - * - * @return string Returns the value of the Config entry - */ - public function getConfigValue($cat, $k, $default = null) - { - $return = $default; - - if ($cat === 'config') { - if (isset($this->config[$k])) { - $return = $this->config[$k]; - } - } else { - if (isset($this->config[$cat][$k])) { - $return = $this->config[$cat][$k]; - } - } - - return $return; - } - - /** - * Sets a default value in the config cache. Ignores already existing keys. - * - * @param string $cat Config category - * @param string $k Config key - * @param mixed $v Default value to set - */ - private function setDefaultConfigValue($cat, $k, $v) - { - if (!isset($this->config[$cat][$k])) { - $this->setConfigValue($cat, $k, $v); - } - } - - /** - * Sets a value in the config cache. Accepts raw output from the config table - * - * @param string $cat Config category - * @param string $k Config key - * @param mixed $v Value to set - */ - public function setConfigValue($cat, $k, $v) - { - // Only arrays are serialized in database, so we have to unserialize sparingly - $value = is_string($v) && preg_match("|^a:[0-9]+:{.*}$|s", $v) ? unserialize($v) : $v; - - if ($cat === 'config') { - $this->config[$k] = $value; - } else { - if (!isset($this->config[$cat])) { - $this->config[$cat] = []; - } - - $this->config[$cat][$k] = $value; - } - } - - /** - * Deletes a value from the config cache - * - * @param string $cat Config category - * @param string $k Config key - */ - public function deleteConfigValue($cat, $k) - { - if ($cat === 'config') { - if (isset($this->config[$k])) { - unset($this->config[$k]); - } - } else { - if (isset($this->config[$cat][$k])) { - unset($this->config[$cat][$k]); - } - } - } - - /** * Retrieves a value from the user config cache * diff --git a/src/Core/Config.php b/src/Core/Config.php index 755dc6ebbc..2a719e8e41 100644 --- a/src/Core/Config.php +++ b/src/Core/Config.php @@ -20,6 +20,8 @@ use Friendica\BaseObject; */ class Config extends BaseObject { + public static $config = []; + /** * @var \Friendica\Core\Config\IConfigAdapter */ @@ -32,7 +34,7 @@ class Config extends BaseObject return; } - if (self::getApp()->getConfigValue('system', 'config_adapter') == 'preload') { + if (self::getConfigValue('system', 'config_adapter') == 'preload') { self::$adapter = new Config\PreloadConfigAdapter(); } else { self::$adapter = new Config\JITConfigAdapter(); @@ -69,7 +71,7 @@ class Config extends BaseObject * ($family) and a key. * * Get a particular config value from the given category ($family) - * and the $key from a cached storage in $a->config[$uid]. + * and the $key from a cached storage in static::config[$uid]. * $instore is only used by the set_config function * to determine if the key already exists in the DB * If a key is found in the DB but doesn't exist in @@ -88,7 +90,7 @@ class Config extends BaseObject { // Database isn't ready or populated yet, fallback to file config if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { - return self::getApp()->getConfigValue($family, $key, $default_value); + return self::getConfigValue($family, $key, $default_value); } if (empty(self::$adapter)) { @@ -152,4 +154,116 @@ class Config extends BaseObject return self::$adapter->delete($family, $key); } + + /** + * Tries to load the specified configuration array into the App->config array. + * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. + * + * @param array $config + * @param bool $overwrite Force value overwrite if the config key already exists + */ + public function loadConfigArray(array $config, $overwrite = false) + { + foreach ($config as $category => $values) { + foreach ($values as $key => $value) { + if ($overwrite) { + self::setConfigValue($category, $key, $value); + } else { + self::setDefaultConfigValue($category, $key, $value); + } + } + } + } + + /** + * @param string $cat Config category + * @param string $k Config key + * @param mixed $default Default value if it isn't set + * + * @return string Returns the value of the Config entry + */ + public static function getConfigValue($cat, $k = null, $default = null) + { + $return = $default; + + if ($cat === 'config') { + if (isset(self::$config[$k])) { + $return = self::$config[$k]; + } + } else { + if (isset(self::$config[$cat][$k])) { + $return = self::$config[$cat][$k]; + } elseif ($k == null && isset(self::$config[$cat])) { + $return = self::$config[$cat]; + } + } + + return $return; + } + + /** + * Sets a default value in the config cache. Ignores already existing keys. + * + * @param string $cat Config category + * @param string $k Config key + * @param mixed $v Default value to set + */ + private static function setDefaultConfigValue($cat, $k, $v) + { + if (!isset(self::$config[$cat][$k])) { + self::setConfigValue($cat, $k, $v); + } + } + + /** + * Sets a value in the config cache. Accepts raw output from the config table + * + * @param string $cat Config category + * @param string $k Config key + * @param mixed $v Value to set + */ + public static function setConfigValue($cat, $k, $v) + { + // Only arrays are serialized in database, so we have to unserialize sparingly + $value = is_string($v) && preg_match("|^a:[0-9]+:{.*}$|s", $v) ? unserialize($v) : $v; + + if ($cat === 'config') { + self::$config[$k] = $value; + } else { + if (!isset(self::$config[$cat])) { + self::$config[$cat] = []; + } + + self::$config[$cat][$k] = $value; + } + } + + /** + * Deletes a value from the config cache + * + * @param string $cat Config category + * @param string $k Config key + */ + public static function deleteConfigValue($cat, $k) + { + if ($cat === 'config') { + if (isset(self::$config[$k])) { + unset(self::$config[$k]); + } + } else { + if (isset(self::$config[$cat][$k])) { + unset(self::$config[$cat][$k]); + } + } + } + + /** + * Returns the whole configuration + * + * @return array The configuration + */ + public static function getAll() + { + return self::$config; + } } diff --git a/src/Core/Config/IConfigAdapter.php b/src/Core/Config/IConfigAdapter.php index 9d8eefd777..5861b4c7e1 100644 --- a/src/Core/Config/IConfigAdapter.php +++ b/src/Core/Config/IConfigAdapter.php @@ -25,7 +25,7 @@ interface IConfigAdapter * ($family) and a key. * * Get a particular config value from the given category ($family) - * and the $key from a cached storage in $a->config[$uid]. + * and the $key from a cached storage in static::$config[$uid]. * $instore is only used by the set_config function * to determine if the key already exists in the DB * If a key is found in the DB but doesn't exist in diff --git a/src/Core/Config/JITConfigAdapter.php b/src/Core/Config/JITConfigAdapter.php index ce1c13b2ca..dbae202917 100644 --- a/src/Core/Config/JITConfigAdapter.php +++ b/src/Core/Config/JITConfigAdapter.php @@ -1,7 +1,7 @@ */ -class JITConfigAdapter extends BaseObject implements IConfigAdapter +class JITConfigAdapter implements IConfigAdapter { private $cache; private $in_db; @@ -28,7 +28,7 @@ class JITConfigAdapter extends BaseObject implements IConfigAdapter while ($config = DBA::fetch($configs)) { $k = $config['k']; - self::getApp()->setConfigValue($cat, $k, $config['v']); + Config::setConfigValue($cat, $k, $config['v']); if ($cat !== 'config') { $this->cache[$cat][$k] = $config['v']; @@ -40,8 +40,6 @@ class JITConfigAdapter extends BaseObject implements IConfigAdapter public function get($cat, $k, $default_value = null, $refresh = false) { - $a = self::getApp(); - if (!$refresh) { // Do we have the cached value? Then return it if (isset($this->cache[$cat][$k])) { @@ -62,18 +60,18 @@ class JITConfigAdapter extends BaseObject implements IConfigAdapter $this->cache[$cat][$k] = $value; $this->in_db[$cat][$k] = true; return $value; - } elseif (isset($a->config[$cat][$k])) { + } elseif (Config::getConfigValue($cat, $k) !== null) { // Assign the value (mostly) from config/local.config.php file to the cache - $this->cache[$cat][$k] = $a->config[$cat][$k]; + $this->cache[$cat][$k] = Config::getConfigValue($cat, $k); $this->in_db[$cat][$k] = false; - return $a->config[$cat][$k]; - } elseif (isset($a->config[$k])) { + return Config::getConfigValue($cat, $k); + } elseif (Config::getConfigValue('config', $k) !== null) { // Assign the value (mostly) from config/local.config.php file to the cache - $this->cache[$k] = $a->config[$k]; + $this->cache[$k] = Config::getConfigValue('config', $k); $this->in_db[$k] = false; - return $a->config[$k]; + return Config::getConfigValue('config', $k); } $this->cache[$cat][$k] = '!!'; @@ -102,7 +100,7 @@ class JITConfigAdapter extends BaseObject implements IConfigAdapter return true; } - self::getApp()->setConfigValue($cat, $k, $value); + Config::setConfigValue($cat, $k, $value); // Assign the just added value to the cache $this->cache[$cat][$k] = $dbvalue; diff --git a/src/Core/Config/PreloadConfigAdapter.php b/src/Core/Config/PreloadConfigAdapter.php index ac59d94558..dc5c45379f 100644 --- a/src/Core/Config/PreloadConfigAdapter.php +++ b/src/Core/Config/PreloadConfigAdapter.php @@ -3,7 +3,7 @@ namespace Friendica\Core\Config; use Exception; -use Friendica\BaseObject; +use Friendica\Core\Config; use Friendica\Database\DBA; /** @@ -13,7 +13,7 @@ use Friendica\Database\DBA; * * @author Hypolite Petovan */ -class PreloadConfigAdapter extends BaseObject implements IConfigAdapter +class PreloadConfigAdapter implements IConfigAdapter { private $config_loaded = false; @@ -30,7 +30,7 @@ class PreloadConfigAdapter extends BaseObject implements IConfigAdapter $configs = DBA::select('config', ['cat', 'v', 'k']); while ($config = DBA::fetch($configs)) { - self::getApp()->setConfigValue($config['cat'], $config['k'], $config['v']); + Config::setConfigValue($config['cat'], $config['k'], $config['v']); } DBA::close($configs); @@ -42,11 +42,11 @@ class PreloadConfigAdapter extends BaseObject implements IConfigAdapter if ($refresh) { $config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $k]); if (DBA::isResult($config)) { - self::getApp()->setConfigValue($cat, $k, $config['v']); + Config::setConfigValue($cat, $k, $config['v']); } } - $return = self::getApp()->getConfigValue($cat, $k, $default_value); + $return = Config::getConfigValue($cat, $k, $default_value); return $return; } @@ -58,11 +58,11 @@ class PreloadConfigAdapter extends BaseObject implements IConfigAdapter // The exception are array values. $compare_value = !is_array($value) ? (string)$value : $value; - if (self::getApp()->getConfigValue($cat, $k) === $compare_value) { + if (Config::getConfigValue($cat, $k) === $compare_value) { return true; } - self::getApp()->setConfigValue($cat, $k, $value); + Config::setConfigValue($cat, $k, $value); // manage array value $dbvalue = is_array($value) ? serialize($value) : $value; @@ -77,7 +77,7 @@ class PreloadConfigAdapter extends BaseObject implements IConfigAdapter public function delete($cat, $k) { - self::getApp()->deleteConfigValue($cat, $k); + Config::deleteConfigValue($cat, $k); $result = DBA::delete('config', ['cat' => $cat, 'k' => $k]); diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index c38dab9806..9a63f56ed4 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -100,10 +100,10 @@ HELP; } } - $db_host = $a->getConfigValue('database', 'hostname'); - $db_user = $a->getConfigValue('database', 'username'); - $db_pass = $a->getConfigValue('database', 'password'); - $db_data = $a->getConfigValue('database', 'database'); + $db_host = Config::getConfigValue('database', 'hostname'); + $db_user = Config::getConfigValue('database', 'username'); + $db_pass = Config::getConfigValue('database', 'password'); + $db_data = Config::getConfigValue('database', 'database'); } else { // Creating config file $this->out("Creating config file...\n"); diff --git a/src/Core/Console/Config.php b/src/Core/Console/Config.php index ce367fffbf..8a0e0f88cf 100644 --- a/src/Core/Console/Config.php +++ b/src/Core/Console/Config.php @@ -124,9 +124,10 @@ HELP; $cat = $this->getArgument(0); Core\Config::load($cat); - if (!is_null($a->config[$cat])) { + if (Core\Config::getConfigValue($cat) !== null) { $this->out("[{$cat}]"); - foreach ($a->config[$cat] as $key => $value) { + $catVal = Core\Config::getConfigValue($cat); + foreach ($catVal as $key => $value) { if (is_array($value)) { foreach ($value as $k => $v) { $this->out("{$key}[{$k}] => " . $v); @@ -147,7 +148,8 @@ HELP; $this->out('Warning: The JIT (Just In Time) Config adapter doesn\'t support loading the entire configuration, showing file config only'); } - foreach ($a->config as $cat => $section) { + $config = Core\Config::getAll(); + foreach ($config as $cat => $section) { if (is_array($section)) { foreach ($section as $key => $value) { if (is_array($value)) { diff --git a/src/Core/Console/Typo.php b/src/Core/Console/Typo.php index 82357b4753..3f9dce84e0 100644 --- a/src/Core/Console/Typo.php +++ b/src/Core/Console/Typo.php @@ -41,9 +41,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - $a = \get_app(); - - $php_path = $a->getConfigValue('config', 'php_path', 'php'); + $php_path = \Friendica\Core\Config::getConfigValue('config', 'php_path', 'php'); if ($this->getOption('v')) { $this->out('Directory: src'); diff --git a/src/Core/PConfig.php b/src/Core/PConfig.php index 584318adbc..ffd72f0a7f 100644 --- a/src/Core/PConfig.php +++ b/src/Core/PConfig.php @@ -34,7 +34,7 @@ class PConfig extends BaseObject return; } - if ($a->getConfigValue('system', 'config_adapter') == 'preload') { + if (Config::getConfigValue('system', 'config_adapter') == 'preload') { self::$adapter = new Config\PreloadPConfigAdapter($uid); } else { self::$adapter = new Config\JITPConfigAdapter(); diff --git a/src/Database/DBA.php b/src/Database/DBA.php index e14d94ce04..51b9be967e 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -2,10 +2,9 @@ namespace Friendica\Database; -// Do not use Core\Config in this class at risk of infinite loop. -// Please use App->getConfigVariable() instead. -//use Friendica\Core\Config; - +// Do not use native get/set/load of Core\Config in this class at risk of infinite loop. +// Please use Core\Config::getConfigVariable() instead. +use Friendica\Core\Config; use Friendica\Core\Logger; use Friendica\Core\System; use Friendica\Util\DateTimeFormat; @@ -212,7 +211,7 @@ class DBA private static function logIndex($query) { $a = \get_app(); - if (!$a->getConfigVariable('system', 'db_log_index')) { + if (!Config::getConfigValue('system', 'db_log_index')) { return; } @@ -231,18 +230,18 @@ class DBA return; } - $watchlist = explode(',', $a->getConfigVariable('system', 'db_log_index_watch')); - $blacklist = explode(',', $a->getConfigVariable('system', 'db_log_index_blacklist')); + $watchlist = explode(',', Config::getConfigValue('system', 'db_log_index_watch')); + $blacklist = explode(',', Config::getConfigValue('system', 'db_log_index_blacklist')); while ($row = self::fetch($r)) { - if ((intval($a->getConfigVariable('system', 'db_loglimit_index')) > 0)) { + if ((intval(Config::getConfigValue('system', 'db_loglimit_index')) > 0)) { $log = (in_array($row['key'], $watchlist) && - ($row['rows'] >= intval($a->getConfigVariable('system', 'db_loglimit_index')))); + ($row['rows'] >= intval(Config::getConfigValue('system', 'db_loglimit_index')))); } else { $log = false; } - if ((intval($a->getConfigVariable('system', 'db_loglimit_index_high')) > 0) && ($row['rows'] >= intval($a->getConfigVariable('system', 'db_loglimit_index_high')))) { + if ((intval(Config::getConfigValue('system', 'db_loglimit_index_high')) > 0) && ($row['rows'] >= intval($Config::getConfigValue('system', 'db_loglimit_index_high')))) { $log = true; } @@ -252,7 +251,7 @@ class DBA if ($log) { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); - @file_put_contents($a->getConfigVariable('system', 'db_log_index'), DateTimeFormat::utcNow()."\t". + @file_put_contents(Config::getConfigValue('system', 'db_log_index'), DateTimeFormat::utcNow()."\t". $row['key']."\t".$row['rows']."\t".$row['Extra']."\t". basename($backtrace[1]["file"])."\t". $backtrace[1]["line"]."\t".$backtrace[2]["function"]."\t". @@ -422,7 +421,7 @@ class DBA $orig_sql = $sql; - if ($a->getConfigValue('system', 'db_callstack')) { + if (Config::getConfigValue('system', 'db_callstack')) { $sql = "/*".System::callstack()." */ ".$sql; } @@ -583,15 +582,15 @@ class DBA $a->saveTimestamp($stamp1, 'database'); - if ($a->getConfigValue('system', 'db_log')) { + if (Config::getConfigValue('system', 'db_log')) { $stamp2 = microtime(true); $duration = (float)($stamp2 - $stamp1); - if (($duration > $a->getConfigValue('system', 'db_loglimit'))) { + if (($duration > Config::getConfigValue('system', 'db_loglimit'))) { $duration = round($duration, 3); $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); - @file_put_contents($a->getConfigValue('system', 'db_log'), DateTimeFormat::utcNow()."\t".$duration."\t". + @file_put_contents(Config::getConfigValue('system', 'db_log'), DateTimeFormat::utcNow()."\t".$duration."\t". basename($backtrace[1]["file"])."\t". $backtrace[1]["line"]."\t".$backtrace[2]["function"]."\t". substr(self::replaceParameters($sql, $args), 0, 2000)."\n", FILE_APPEND);