diff --git a/bin/auth_ejabberd.php b/bin/auth_ejabberd.php index ba3a9b8dd..a097febbc 100755 --- a/bin/auth_ejabberd.php +++ b/bin/auth_ejabberd.php @@ -32,7 +32,8 @@ * */ -use Friendica\Factory; +use Friendica\App\Mode; +use Friendica\BaseObject; use Friendica\Util\ExAuth; if (sizeof($_SERVER["argv"]) == 0) { @@ -53,10 +54,11 @@ require dirname(__DIR__) . '/vendor/autoload.php'; $dice = new \Dice\Dice(); $dice = $dice->addRules(include __DIR__ . '/../static/dependencies.config.php'); +BaseObject::setDependencyInjection($dice); -$a = Factory\DependencyFactory::setUp('auth_ejabbered', $dice); +$appMode = $dice->create(Mode::class); -if ($a->getMode()->isNormal()) { +if ($appMode->isNormal()) { $oAuth = new ExAuth(); $oAuth->readStdin(); } diff --git a/bin/console.php b/bin/console.php index 6fa804fb9..15fbf437c 100755 --- a/bin/console.php +++ b/bin/console.php @@ -3,12 +3,9 @@ require dirname(__DIR__) . '/vendor/autoload.php'; -use Friendica\Factory; - $dice = new \Dice\Dice(); $dice = $dice->addRules(include __DIR__ . '/../static/dependencies.config.php'); -$a = Factory\DependencyFactory::setUp('console', $dice); -\Friendica\BaseObject::setApp($a); +\Friendica\BaseObject::setDependencyInjection($dice); (new Friendica\Core\Console($argv))->execute(); diff --git a/bin/daemon.php b/bin/daemon.php index 1b0a7edb3..ac6385cbb 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -11,7 +11,6 @@ use Friendica\Core\Config; use Friendica\Core\Logger; use Friendica\Core\Worker; use Friendica\Database\DBA; -use Friendica\Factory; // Get options $shortopts = 'f'; @@ -35,7 +34,8 @@ require dirname(__DIR__) . '/vendor/autoload.php'; $dice = new \Dice\Dice(); $dice = $dice->addRules(include __DIR__ . '/../static/dependencies.config.php'); -$a = Factory\DependencyFactory::setUp('daemon', $dice); +\Friendica\BaseObject::setDependencyInjection($dice); +$a = \Friendica\BaseObject::getApp(); if ($a->getMode()->isInstall()) { die("Friendica isn't properly installed yet.\n"); @@ -147,7 +147,7 @@ if (!$foreground) { file_put_contents($pidfile, $pid); // We lose the database connection upon forking - $a->getDatabase()->reconnect(); + DBA::reconnect(); } Config::set('system', 'worker_daemon_mode', true); diff --git a/bin/worker.php b/bin/worker.php index f4b012026..e630ee234 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -9,7 +9,6 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\Update; use Friendica\Core\Worker; -use Friendica\Factory; // Get options $shortopts = 'sn'; @@ -33,7 +32,8 @@ require dirname(__DIR__) . '/vendor/autoload.php'; $dice = new \Dice\Dice(); $dice = $dice->addRules(include __DIR__ . '/../static/dependencies.config.php'); -$a = Factory\DependencyFactory::setUp('worker', $dice); +\Friendica\BaseObject::setDependencyInjection($dice); +$a = \Friendica\BaseObject::getApp(); // Check the database structure and possibly fixes it Update::check($a->getBasePath(), true, $a->getMode()); diff --git a/include/api.php b/include/api.php index 23afa72de..bb241039a 100644 --- a/include/api.php +++ b/include/api.php @@ -27,6 +27,7 @@ use Friendica\Model\Group; use Friendica\Model\Item; use Friendica\Model\Mail; use Friendica\Model\Photo; +use Friendica\Model\Profile; use Friendica\Model\User; use Friendica\Network\FKOAuth1; use Friendica\Network\HTTPException; @@ -6205,47 +6206,39 @@ function api_friendica_profile_show($type) // get data of the specified profile id or all profiles of the user if not specified if ($profile_id != 0) { - $r = q( - "SELECT * FROM `profile` WHERE `uid` = %d AND `id` = %d", - intval(api_user()), - intval($profile_id) - ); - + $r = Profile::getById(api_user(), $profile_id); // error message if specified gid is not in database if (!DBA::isResult($r)) { throw new BadRequestException("profile_id not available"); } } else { - $r = q( - "SELECT * FROM `profile` WHERE `uid` = %d", - intval(api_user()) - ); + $r = Profile::getListByUser(api_user()); } // loop through all returned profiles and retrieve data and users $k = 0; $profiles = []; - foreach ($r as $rr) { - $profile = api_format_items_profiles($rr); + if (DBA::isResult($r)) { + foreach ($r as $rr) { + $profile = api_format_items_profiles($rr); - // select all users from contact table, loop and prepare standard return for user data - $users = []; - $nurls = q( - "SELECT `id`, `nurl` FROM `contact` WHERE `uid`= %d AND `profile-id` = %d", - intval(api_user()), - intval($rr['id']) - ); + // select all users from contact table, loop and prepare standard return for user data + $users = []; + $nurls = Contact::select(['id', 'nurl'], ['uid' => api_user(), 'profile-id' => $rr['id']]); - foreach ($nurls as $nurl) { - $user = api_get_user($a, $nurl['nurl']); - ($type == "xml") ? $users[$k++ . ":user"] = $user : $users[] = $user; - } - $profile['users'] = $users; + if (DBA::isResult($nurls)) { + foreach ($nurls as $nurl) { + $user = api_get_user($a, $nurl['nurl']); + ($type == "xml") ? $users[$k++ . ":user"] = $user : $users[] = $user; + } + } + $profile['users'] = $users; - // add prepared profile data to array for final return - if ($type == "xml") { - $profiles[$k++ . ":profile"] = $profile; - } else { - $profiles[] = $profile; + // add prepared profile data to array for final return + if ($type == "xml") { + $profiles[$k++ . ":profile"] = $profile; + } else { + $profiles[] = $profile; + } } } @@ -6275,7 +6268,7 @@ function api_saved_searches_list($type) $terms = DBA::select('search', ['id', 'term'], ['uid' => local_user()]); $result = []; - while ($term = $terms->fetch()) { + while ($term = DBA::fetch($terms)) { $result[] = [ 'created_at' => api_date(time()), 'id' => intval($term['id']), diff --git a/index.php b/index.php index 7b7146aeb..3e5609708 100644 --- a/index.php +++ b/index.php @@ -4,8 +4,6 @@ * Friendica */ -use Friendica\Factory; - 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,6 +13,8 @@ require __DIR__ . '/vendor/autoload.php'; $dice = new \Dice\Dice(); $dice = $dice->addRules(include __DIR__ . '/static/dependencies.config.php'); -$a = Factory\DependencyFactory::setUp('index', $dice, false); +\Friendica\BaseObject::setDependencyInjection($dice); + +$a = \Friendica\BaseObject::getApp(); $a->runFrontend(); diff --git a/mod/settings.php b/mod/settings.php index 702a931df..5c6d313fa 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -378,7 +378,7 @@ function settings_post(App $a) theme_post($a); } } else { - $a->getDatabase()->update('user', ['theme' => $theme], ['uid' => local_user()]); + DBA::update('user', ['theme' => $theme], ['uid' => local_user()]); } } else { notice(L10n::t('The theme you chose isn\'t available.')); diff --git a/src/App.php b/src/App.php index 2f6901095..bf9e1296c 100644 --- a/src/App.php +++ b/src/App.php @@ -197,32 +197,6 @@ class App return $this->mode; } - /** - * Returns the router of the Application - * - * @return App\Router - */ - public function getRouter() - { - return $this->router; - } - - /** - * @return Database - */ - public function getDatabase() - { - return $this->database; - } - - /** - * @return L10n - */ - public function getL10n() - { - return $this->l10n; - } - /** * Register a stylesheet file path to be included in the tag of every page. * Inclusion is done in App->initHead(). @@ -270,14 +244,11 @@ class App * @param LoggerInterface $logger The current app logger * @param Profiler $profiler The profiler of this application * @param L10n $l10n The translator instance - * @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(Database $database, Configuration $config, App\Mode $mode, App\Router $router, BaseURL $baseURL, LoggerInterface $logger, Profiler $profiler, L10n $l10n, $isBackend = true) + public function __construct(Database $database, Configuration $config, App\Mode $mode, App\Router $router, BaseURL $baseURL, LoggerInterface $logger, Profiler $profiler, L10n $l10n) { - BaseObject::setApp($this); - $this->database = $database; $this->config = $config; $this->mode = $mode; @@ -354,7 +325,7 @@ class App $this->module = 'home'; } - $this->isBackend = $isBackend || $this->checkBackend($this->module); + $this->isBackend = $this->isBackend || $this->checkBackend($this->module); // Detect mobile devices $mobile_detect = new MobileDetect(); @@ -375,6 +346,8 @@ class App */ public function reload() { + $this->isBackend = basename($_SERVER['PHP_SELF'], '.php') !== 'index'; + $this->getMode()->determine($this->getBasePath()); if ($this->getMode()->has(App\Mode::DBAVAILABLE)) { diff --git a/src/BaseObject.php b/src/BaseObject.php index 9a2d06475..fcec89bb4 100644 --- a/src/BaseObject.php +++ b/src/BaseObject.php @@ -6,19 +6,32 @@ namespace Friendica; require_once __DIR__ . '/../boot.php'; +use Dice\Dice; use Friendica\Network\HTTPException\InternalServerErrorException; /** * Basic object * * Contains what is useful to any object + * + * Act's like a global registry for classes */ class BaseObject { /** - * @var App + * @var Dice The Dependency Injection library */ - private static $app = null; + private static $dice; + + /** + * Set's the dependency injection library for a global usage + * + * @param Dice $dice The dependency injection library + */ + public static function setDependencyInjection(Dice $dice) + { + self::$dice = $dice; + } /** * Get the app @@ -26,26 +39,31 @@ class BaseObject * Same as get_app from boot.php * * @return App - * @throws \Exception */ public static function getApp() { - if (empty(self::$app)) { - throw new InternalServerErrorException('App isn\'t initialized.'); - } - - return self::$app; + return self::getClass(App::class); } /** - * Set the app + * Returns the initialized class based on it's name * - * @param App $app App + * @param string $name The name of the class * - * @return void + * @return object The initialized name + * + * @throws InternalServerErrorException */ - public static function setApp(App $app) + protected static function getClass(string $name) { - self::$app = $app; + if (empty(self::$dice)) { + throw new InternalServerErrorException('DICE isn\'t initialized.'); + } + + if (class_exists($name) || interface_exists($name )) { + return self::$dice->create($name); + } else { + throw new InternalServerErrorException('Class \'' . $name . '\' isn\'t valid.'); + } } } diff --git a/src/Core/Config.php b/src/Core/Config.php index 4bf9c5b11..cec7a460e 100644 --- a/src/Core/Config.php +++ b/src/Core/Config.php @@ -8,6 +8,9 @@ */ namespace Friendica\Core; +use Friendica\BaseObject; +use Friendica\Core\Config\Configuration; + /** * @brief Arbitrary system configuration storage * @@ -15,23 +18,8 @@ namespace Friendica\Core; * If we ever would decide to return exactly the variable type as entered, * we will have fun with the additional features. :-) */ -class Config +class Config extends BaseObject { - /** - * @var Config\Configuration - */ - private static $config; - - /** - * Initialize the config - * - * @param Config\Configuration $config - */ - public static function init(Config\Configuration $config) - { - self::$config = $config; - } - /** * @brief Loads all configuration values of family into a cached storage. * @@ -41,7 +29,7 @@ class Config */ public static function load($cat = "config") { - self::$config->load($cat); + self::getClass(Configuration::class)->load($cat); } /** @@ -57,7 +45,7 @@ class Config */ public static function get($cat, $key, $default_value = null, $refresh = false) { - return self::$config->get($cat, $key, $default_value, $refresh); + return self::getClass(Configuration::class)->get($cat, $key, $default_value, $refresh); } /** @@ -75,7 +63,7 @@ class Config */ public static function set($cat, $key, $value) { - return self::$config->set($cat, $key, $value); + return self::getClass(Configuration::class)->set($cat, $key, $value); } /** @@ -88,6 +76,6 @@ class Config */ public static function delete($cat, $key) { - return self::$config->delete($cat, $key); + return self::getClass(Configuration::class)->delete($cat, $key); } } diff --git a/src/Core/Installer.php b/src/Core/Installer.php index 8163d546a..d0beedc09 100644 --- a/src/Core/Installer.php +++ b/src/Core/Installer.php @@ -7,10 +7,9 @@ namespace Friendica\Core; use DOMDocument; use Exception; use Friendica\Core\Config\Cache\ConfigCache; -use Friendica\Database\Database; +use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\Object\Image; -use Friendica\Util\Logger\VoidLogger; use Friendica\Util\Network; use Friendica\Util\Profiler; use Friendica\Util\Strings; @@ -600,9 +599,9 @@ class Installer */ public function checkDB(ConfigCache $configCache, Profiler $profiler) { - $database = new Database($configCache, $profiler, new VoidLogger()); + DBA::reconnect(); - if ($database->connected()) { + if (DBA::connected()) { if (DBStructure::existsTable('user')) { $this->addCheck(L10n::t('Database already in use.'), false, true, ''); diff --git a/src/Core/L10n.php b/src/Core/L10n.php index 55991dab4..db008d6a9 100644 --- a/src/Core/L10n.php +++ b/src/Core/L10n.php @@ -4,29 +4,15 @@ */ namespace Friendica\Core; +use Friendica\BaseObject; use Friendica\Core\L10n\L10n as L10nClass; /** * Provide Language, Translation, and Localization functions to the application * Localization can be referred to by the numeronym L10N (as in: "L", followed by ten more letters, and then "N"). */ -class L10n +class L10n extends BaseObject { - /** - * @var L10nClass - */ - private static $l10n; - - /** - * Initializes the L10n static wrapper with the instance - * - * @param L10nClass $l10n The l10n class - */ - public static function init(L10nClass $l10n) - { - self::$l10n = $l10n; - } - /** * Returns the current language code * @@ -34,7 +20,7 @@ class L10n */ public static function getCurrentLang() { - return self::$l10n->getCurrentLang(); + return self::getClass(L10nClass::class)->getCurrentLang(); } /** @@ -52,7 +38,7 @@ class L10n */ public static function pushLang($lang) { - self::$l10n->pushLang($lang); + self::getClass(L10nClass::class)->pushLang($lang); } /** @@ -60,7 +46,7 @@ class L10n */ public static function popLang() { - self::$l10n->popLang(); + self::getClass(L10nClass::class)->popLang(); } /** @@ -81,7 +67,7 @@ class L10n */ public static function t($s, ...$vars) { - return self::$l10n->t($s, ...$vars); + return self::getClass(L10nClass::class)->t($s, ...$vars); } /** @@ -105,7 +91,7 @@ class L10n */ public static function tt(string $singular, string $plural, int $count) { - return self::$l10n->tt($singular, $plural, $count); + return self::getClass(L10nClass::class)->tt($singular, $plural, $count); } /** @@ -121,7 +107,7 @@ class L10n */ public static function getAvailableLanguages() { - return self::$l10n::getAvailableLanguages(); + return L10nClass::getAvailableLanguages(); } /** @@ -132,7 +118,7 @@ class L10n */ public static function getDay($s) { - return self::$l10n->getDay($s); + return self::getClass(L10nClass::class)->getDay($s); } /** @@ -143,6 +129,6 @@ class L10n */ public static function getDayShort($s) { - return self::$l10n->getDayShort($s); + return self::getClass(L10nClass::class)->getDayShort($s); } } diff --git a/src/Core/L10n/L10n.php b/src/Core/L10n/L10n.php index 355f4c6ed..f4e14c78e 100644 --- a/src/Core/L10n/L10n.php +++ b/src/Core/L10n/L10n.php @@ -59,8 +59,6 @@ class L10n $this->logger = $logger; $this->loadTranslationTable(L10n::detectLanguage($config->get('system', 'language', 'en'))); - - \Friendica\Core\L10n::init($this); } /** diff --git a/src/Core/Logger.php b/src/Core/Logger.php index fc2dde1df..e376485e5 100644 --- a/src/Core/Logger.php +++ b/src/Core/Logger.php @@ -4,13 +4,15 @@ */ namespace Friendica\Core; +use Friendica\BaseObject; +use Friendica\Util\Logger\WorkerLogger; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; /** * @brief Logger functions */ -class Logger +class Logger extends BaseObject { /** * @see Logger::error() @@ -37,6 +39,19 @@ class Logger */ const ALL = LogLevel::DEBUG; + /** + * @var LoggerInterface The default Logger type + */ + const TYPE_LOGGER = LoggerInterface::class; + /** + * @var WorkerLogger A specific worker logger type, which can be anabled + */ + const TYPE_WORKER = WorkerLogger::class; + /** + * @var LoggerInterface The current logger type + */ + private static $type = self::TYPE_LOGGER; + /** * @var array the legacy loglevels * @deprecated 2019.03 use PSR-3 loglevels @@ -53,33 +68,24 @@ class Logger ]; /** - * @var LoggerInterface A PSR-3 compliant logger instance - */ - private static $logger; - - /** - * @var LoggerInterface A PSR-3 compliant logger instance for developing only - */ - private static $devLogger; - - /** - * Sets the default logging handler for Friendica. + * Enable additional logging for worker usage * - * @param LoggerInterface $logger The Logger instance of this Application + * @param string $functionName The worker function, which got called + * + * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function init(LoggerInterface $logger) + public static function enableWorker(string $functionName) { - self::$logger = $logger; + self::$type = self::TYPE_WORKER; + self::getClass(self::$type)->setFunctionName($functionName); } /** - * Sets the default dev-logging handler for Friendica. - * - * @param LoggerInterface $logger The Logger instance of this Application + * Disable additional logging for worker usage */ - public static function setDevLogger(LoggerInterface $logger) + public static function disableWorker() { - self::$devLogger = $logger; + self::$type = self::TYPE_LOGGER; } /** @@ -95,7 +101,7 @@ class Logger */ public static function emergency($message, $context = []) { - self::$logger->emergency($message, $context); + self::getClass(self::$type)->emergency($message, $context); } /** @@ -113,7 +119,7 @@ class Logger */ public static function alert($message, $context = []) { - self::$logger->alert($message, $context); + self::getClass(self::$type)->alert($message, $context); } /** @@ -130,7 +136,7 @@ class Logger */ public static function critical($message, $context = []) { - self::$logger->critical($message, $context); + self::getClass(self::$type)->critical($message, $context); } /** @@ -146,7 +152,7 @@ class Logger */ public static function error($message, $context = []) { - self::$logger->error($message, $context); + self::getClass(self::$type)->error($message, $context); } /** @@ -164,7 +170,7 @@ class Logger */ public static function warning($message, $context = []) { - self::$logger->warning($message, $context); + self::getClass(self::$type)->warning($message, $context); } /** @@ -179,7 +185,7 @@ class Logger */ public static function notice($message, $context = []) { - self::$logger->notice($message, $context); + self::getClass(self::$type)->notice($message, $context); } /** @@ -196,7 +202,7 @@ class Logger */ public static function info($message, $context = []) { - self::$logger->info($message, $context); + self::getClass(self::$type)->info($message, $context); } /** @@ -211,7 +217,7 @@ class Logger */ public static function debug($message, $context = []) { - self::$logger->debug($message, $context); + self::getClass(self::$type)->debug($message, $context); } /** @@ -225,7 +231,7 @@ class Logger */ public static function log($msg, $level = LogLevel::INFO) { - self::$logger->log($level, $msg); + self::getClass(self::$type)->log($level, $msg); } /** @@ -240,10 +246,6 @@ class Logger */ public static function devLog($msg, $level = LogLevel::DEBUG) { - if (!isset(self::$devLogger)) { - return; - } - - self::$devLogger->log($level, $msg); + self::getClass('$devLogger')->log($level, $msg); } } diff --git a/src/Core/PConfig.php b/src/Core/PConfig.php index 49e34720f..e96935c4e 100644 --- a/src/Core/PConfig.php +++ b/src/Core/PConfig.php @@ -8,6 +8,9 @@ */ namespace Friendica\Core; +use Friendica\BaseObject; +use Friendica\Core\Config\PConfiguration; + /** * @brief Management of user configuration storage * Note: @@ -15,23 +18,8 @@ namespace Friendica\Core; * The PConfig::get() functions return boolean false for keys that are unset, * and this could lead to subtle bugs. */ -class PConfig +class PConfig extends BaseObject { - /** - * @var Config\PConfiguration - */ - private static $config; - - /** - * Initialize the config with only the cache - * - * @param Config\PConfiguration $config The configuration cache - */ - public static function init(Config\PConfiguration $config) - { - self::$config = $config; - } - /** * @brief Loads all configuration values of a user's config family into a cached storage. * @@ -42,7 +30,7 @@ class PConfig */ public static function load(int $uid, string $cat) { - self::$config->load($uid, $cat); + self::getClass(PConfiguration::class)->load($uid, $cat); } /** @@ -59,7 +47,7 @@ class PConfig */ public static function get(int $uid, string $cat, string $key, $default_value = null, bool $refresh = false) { - return self::$config->get($uid, $cat, $key, $default_value, $refresh); + return self::getClass(PConfiguration::class)->get($uid, $cat, $key, $default_value, $refresh); } /** @@ -74,7 +62,7 @@ class PConfig */ public static function set(int $uid, string $cat, string $key, $value) { - return self::$config->set($uid, $cat, $key, $value); + return self::getClass(PConfiguration::class)->set($uid, $cat, $key, $value); } /** @@ -88,6 +76,6 @@ class PConfig */ public static function delete(int $uid, string $cat, string $key) { - return self::$config->delete($uid, $cat, $key); + return self::getClass(PConfiguration::class)->delete($uid, $cat, $key); } } diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 8fdd60c2a..225a92800 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -8,7 +8,6 @@ use Friendica\BaseObject; use Friendica\Database\DBA; use Friendica\Model\Process; use Friendica\Util\DateTimeFormat; -use Friendica\Util\Logger\WorkerLogger; use Friendica\Util\Network; /** @@ -378,10 +377,9 @@ class Worker $argc = count($argv); - $logger = $a->getLogger(); - $workerLogger = new WorkerLogger($logger, $funcname); + Logger::enableWorker($funcname); - $workerLogger ->info("Process start.", ['priority' => $queue["priority"], 'id' => $queue["id"]]); + Logger::info("Process start.", ['priority' => $queue["priority"], 'id' => $queue["id"]]); $stamp = (float)microtime(true); @@ -397,13 +395,13 @@ class Worker unset($_SESSION); // Set the workerLogger as new default logger - Logger::init($workerLogger); if ($method_call) { call_user_func_array(sprintf('Friendica\Worker\%s::execute', $funcname), $argv); } else { $funcname($argv, $argc); } - Logger::init($logger); + + Logger::disableWorker(); unset($a->queue); @@ -423,7 +421,7 @@ class Worker $rest = round(max(0, $up_duration - (self::$db_duration + self::$lock_duration)), 2); $exec = round($duration, 2); - $logger->info('Performance:', ['state' => self::$state, 'count' => $dbcount, 'stat' => $dbstat, 'write' => $dbwrite, 'lock' => $dblock, 'total' => $dbtotal, 'rest' => $rest, 'exec' => $exec]); + Logger::info('Performance:', ['state' => self::$state, 'count' => $dbcount, 'stat' => $dbstat, 'write' => $dbwrite, 'lock' => $dblock, 'total' => $dbtotal, 'rest' => $rest, 'exec' => $exec]); self::$up_start = microtime(true); self::$db_duration = 0; @@ -433,23 +431,23 @@ class Worker self::$lock_duration = 0; if ($duration > 3600) { - $logger->info('Longer than 1 hour.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'duration' => round($duration/60, 3)]); + Logger::info('Longer than 1 hour.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'duration' => round($duration/60, 3)]); } elseif ($duration > 600) { - $logger->info('Longer than 10 minutes.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'duration' => round($duration/60, 3)]); + Logger::info('Longer than 10 minutes.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'duration' => round($duration/60, 3)]); } elseif ($duration > 300) { - $logger->info('Longer than 5 minutes.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'duration' => round($duration/60, 3)]); + Logger::info('Longer than 5 minutes.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'duration' => round($duration/60, 3)]); } elseif ($duration > 120) { - $logger->info('Longer than 2 minutes.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'duration' => round($duration/60, 3)]); + Logger::info('Longer than 2 minutes.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'duration' => round($duration/60, 3)]); } - $workerLogger->info('Process done.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'duration' => round($duration, 3)]); + Logger::info('Process done.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'duration' => round($duration, 3)]); $a->getProfiler()->saveLog($a->getLogger(), "ID " . $queue["id"] . ": " . $funcname); $cooldown = Config::get("system", "worker_cooldown", 0); if ($cooldown > 0) { - $logger->info('Cooldown.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'cooldown' => $cooldown]); + Logger::info('Cooldown.', ['priority' => $queue["priority"], 'id' => $queue["id"], 'cooldown' => $cooldown]); sleep($cooldown); } } diff --git a/src/Database/DBA.php b/src/Database/DBA.php index 9bc314c9c..9bdeaa046 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -2,6 +2,7 @@ namespace Friendica\Database; +use Friendica\BaseObject; use mysqli; use mysqli_result; use mysqli_stmt; @@ -13,7 +14,7 @@ use PDOStatement; * * This class is for the low level database stuff that does driver specific things. */ -class DBA +class DBA extends BaseObject { /** * Lowest possible date value @@ -24,19 +25,9 @@ class DBA */ const NULL_DATETIME = '0001-01-01 00:00:00'; - /** - * @var Database - */ - private static $database; - - public static function init(Database $database) - { - self::$database = $database; - } - public static function connect() { - return self::$database->connect(); + return self::getClass(Database::class)->connect(); } /** @@ -44,7 +35,7 @@ class DBA */ public static function disconnect() { - self::$database->disconnect(); + self::getClass(Database::class)->disconnect(); } /** @@ -52,7 +43,7 @@ class DBA */ public static function reconnect() { - return self::$database->reconnect(); + return self::getClass(Database::class)->reconnect(); } /** @@ -61,7 +52,7 @@ class DBA */ public static function getConnection() { - return self::$database->getConnection(); + return self::getClass(Database::class)->getConnection(); } /** @@ -74,7 +65,7 @@ class DBA */ public static function serverInfo() { - return self::$database->serverInfo(); + return self::getClass(Database::class)->serverInfo(); } /** @@ -85,17 +76,17 @@ class DBA */ public static function databaseName() { - return self::$database->databaseName(); + return self::getClass(Database::class)->databaseName(); } public static function escape($str) { - return self::$database->escape($str); + return self::getClass(Database::class)->escape($str); } public static function connected() { - return self::$database->connected(); + return self::getClass(Database::class)->connected(); } /** @@ -111,7 +102,7 @@ class DBA */ public static function anyValueFallback($sql) { - return self::$database->anyValueFallback($sql); + return self::getClass(Database::class)->anyValueFallback($sql); } /** @@ -167,7 +158,7 @@ class DBA { $params = self::getParam(func_get_args()); - return self::$database->p($sql, $params); + return self::getClass(Database::class)->p($sql, $params); } /** @@ -183,7 +174,7 @@ class DBA $params = self::getParam(func_get_args()); - return self::$database->e($sql, $params); + return self::getClass(Database::class)->e($sql, $params); } /** @@ -197,7 +188,7 @@ class DBA */ public static function exists($table, $condition) { - return self::$database->exists($table, $condition); + return self::getClass(Database::class)->exists($table, $condition); } /** @@ -214,7 +205,7 @@ class DBA { $params = self::getParam(func_get_args()); - return self::$database->fetchFirst($sql, $params); + return self::getClass(Database::class)->fetchFirst($sql, $params); } /** @@ -224,7 +215,7 @@ class DBA */ public static function affectedRows() { - return self::$database->affectedRows(); + return self::getClass(Database::class)->affectedRows(); } /** @@ -235,7 +226,7 @@ class DBA */ public static function columnCount($stmt) { - return self::$database->columnCount($stmt); + return self::getClass(Database::class)->columnCount($stmt); } /** * @brief Returns the number of rows of a statement @@ -245,7 +236,7 @@ class DBA */ public static function numRows($stmt) { - return self::$database->numRows($stmt); + return self::getClass(Database::class)->numRows($stmt); } /** @@ -256,7 +247,7 @@ class DBA */ public static function fetch($stmt) { - return self::$database->fetch($stmt); + return self::getClass(Database::class)->fetch($stmt); } /** @@ -271,7 +262,7 @@ class DBA */ public static function insert($table, $param, $on_duplicate_update = false) { - return self::$database->insert($table, $param, $on_duplicate_update); + return self::getClass(Database::class)->insert($table, $param, $on_duplicate_update); } /** @@ -281,7 +272,7 @@ class DBA */ public static function lastInsertId() { - return self::$database->lastInsertId(); + return self::getClass(Database::class)->lastInsertId(); } /** @@ -296,7 +287,7 @@ class DBA */ public static function lock($table) { - return self::$database->lock($table); + return self::getClass(Database::class)->lock($table); } /** @@ -307,7 +298,7 @@ class DBA */ public static function unlock() { - return self::$database->unlock(); + return self::getClass(Database::class)->unlock(); } /** @@ -317,7 +308,7 @@ class DBA */ public static function transaction() { - return self::$database->transaction(); + return self::getClass(Database::class)->transaction(); } /** @@ -327,7 +318,7 @@ class DBA */ public static function commit() { - return self::$database->commit(); + return self::getClass(Database::class)->commit(); } /** @@ -337,7 +328,7 @@ class DBA */ public static function rollback() { - return self::$database->rollback(); + return self::getClass(Database::class)->rollback(); } /** @@ -354,7 +345,7 @@ class DBA */ public static function delete($table, array $conditions, array $options = []) { - return self::$database->delete($table, $conditions, $options); + return self::getClass(Database::class)->delete($table, $conditions, $options); } /** @@ -388,7 +379,7 @@ class DBA */ public static function update($table, $fields, $condition, $old_fields = []) { - return self::$database->update($table, $fields, $condition, $old_fields); + return self::getClass(Database::class)->update($table, $fields, $condition, $old_fields); } /** @@ -405,7 +396,7 @@ class DBA */ public static function selectFirst($table, array $fields = [], array $condition = [], $params = []) { - return self::$database->selectFirst($table, $fields, $condition, $params); + return self::getClass(Database::class)->selectFirst($table, $fields, $condition, $params); } /** @@ -422,7 +413,7 @@ class DBA */ public static function selectToArray(string $table, array $fields = [], array $condition = [], array $params = []) { - return self::$database->selectToArray($table, $fields, $condition, $params); + return self::getClass(Database::class)->selectToArray($table, $fields, $condition, $params); } /** @@ -450,7 +441,7 @@ class DBA */ public static function select($table, array $fields = [], array $condition = [], array $params = []) { - return self::$database->select($table, $fields, $condition, $params); + return self::getClass(Database::class)->select($table, $fields, $condition, $params); } /** @@ -473,7 +464,7 @@ class DBA */ public static function count($table, array $condition = []) { - return self::$database->count($table, $condition); + return self::getClass(Database::class)->count($table, $condition); } /** @@ -605,7 +596,7 @@ class DBA */ public static function toArray($stmt, $do_close = true) { - return self::$database->toArray($stmt, $do_close); + return self::getClass(Database::class)->toArray($stmt, $do_close); } /** @@ -615,7 +606,7 @@ class DBA */ public static function errorNo() { - return self::$database->errorNo(); + return self::getClass(Database::class)->errorNo(); } /** @@ -625,7 +616,7 @@ class DBA */ public static function errorMessage() { - return self::$database->errorMessage(); + return self::getClass(Database::class)->errorMessage(); } /** @@ -636,7 +627,7 @@ class DBA */ public static function close($stmt) { - return self::$database->close($stmt); + return self::getClass(Database::class)->close($stmt); } /** @@ -649,7 +640,7 @@ class DBA */ public static function processlist() { - return self::$database->processlist(); + return self::getClass(Database::class)->processlist(); } /** @@ -661,7 +652,7 @@ class DBA */ public static function isResult($array) { - return self::$database->isResult($array); + return self::getClass(Database::class)->isResult($array); } /** @@ -673,6 +664,6 @@ class DBA */ public static function escapeArray(&$arr, $add_quotation = false) { - return self::$database->escapeArray($arr, $add_quotation); + return self::getClass(Database::class)->escapeArray($arr, $add_quotation); } } diff --git a/src/Database/Database.php b/src/Database/Database.php index 29d1ac8cc..501d65fe7 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -21,29 +21,29 @@ use Psr\Log\LoggerInterface; */ class Database { - private $connected = false; + protected $connected = false; /** * @var ConfigCache */ - private $configCache; + protected $configCache; /** * @var Profiler */ - private $profiler; + protected $profiler; /** * @var LoggerInterface */ - private $logger; - private $server_info = ''; + protected $logger; + protected $server_info = ''; /** @var PDO|mysqli */ - private $connection; - private $driver; + protected $connection; + protected $driver; private $error = false; private $errorno = 0; private $affected_rows = 0; - private $in_transaction = false; - private $in_retrial = false; + protected $in_transaction = false; + protected $in_retrial = false; private $relation = []; public function __construct(ConfigCache $configCache, Profiler $profiler, LoggerInterface $logger, array $server = []) @@ -56,8 +56,6 @@ class Database $this->readServerVariables($server); $this->connect(); - DBA::init($this); - if ($this->isConnected()) { // Loads DB_UPDATE_VERSION constant DBStructure::definition($configCache->get('system', 'basepath'), false); @@ -1072,7 +1070,7 @@ class Database return true; } - private function performCommit() + protected function performCommit() { switch ($this->driver) { case 'pdo': diff --git a/src/Factory/ConfigFactory.php b/src/Factory/ConfigFactory.php index 08fcddace..494a5c720 100644 --- a/src/Factory/ConfigFactory.php +++ b/src/Factory/ConfigFactory.php @@ -2,7 +2,6 @@ namespace Friendica\Factory; -use Friendica\Core; use Friendica\Core\Config; use Friendica\Core\Config\Cache; use Friendica\Model\Config\Config as ConfigModel; @@ -39,9 +38,6 @@ class ConfigFactory } - // Set the config in the static container for legacy usage - Core\Config::init($configuration); - return $configuration; } @@ -60,9 +56,6 @@ class ConfigFactory $configuration = new Config\JitPConfiguration($pConfigCache, $configModel); } - // Set the config in the static container for legacy usage - Core\PConfig::init($configuration); - return $configuration; } } diff --git a/src/Factory/DependencyFactory.php b/src/Factory/DependencyFactory.php deleted file mode 100644 index 8ead2f615..000000000 --- a/src/Factory/DependencyFactory.php +++ /dev/null @@ -1,30 +0,0 @@ -create(PConfiguration::class); - $logger = $dice->create(LoggerInterface::class, [$channel]); - $devLogger = $dice->create('$devLogger', [$channel]); - - return $dice->create(App::class, [$isBackend]); - } -} diff --git a/src/Factory/LoggerFactory.php b/src/Factory/LoggerFactory.php index 2a054607c..0feb3b2f7 100644 --- a/src/Factory/LoggerFactory.php +++ b/src/Factory/LoggerFactory.php @@ -25,6 +25,8 @@ use Psr\Log\LogLevel; */ class LoggerFactory { + const DEV_CHANNEL = 'dev'; + /** * A list of classes, which shouldn't get logged * @@ -36,10 +38,19 @@ class LoggerFactory 'Friendica\\Util\\Logger', ]; + /** + * Retrieve the channel based on the __FILE__ + * + * @return string + */ + private function findChannel() + { + return basename($_SERVER['PHP_SELF'], '.php'); + } + /** * Creates a new PSR-3 compliant logger instances * - * @param string $channel The channel of the logger instance * @param Configuration $config The config * @param Profiler $profiler The profiler of the app * @@ -48,12 +59,11 @@ class LoggerFactory * @throws \Exception * @throws InternalServerErrorException */ - public function create($channel, Database $database, Configuration $config, Profiler $profiler) + public function create(Database $database, Configuration $config, Profiler $profiler) { if (empty($config->get('system', 'debugging', false))) { $logger = new VoidLogger(); $database->setLogger($logger); - Logger::init($logger); return $logger; } @@ -66,7 +76,7 @@ class LoggerFactory $loggerTimeZone = new \DateTimeZone('UTC'); Monolog\Logger::setTimezone($loggerTimeZone); - $logger = new Monolog\Logger($channel); + $logger = new Monolog\Logger($this->findChannel()); $logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor()); $logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor()); $logger->pushProcessor(new Monolog\Processor\UidProcessor()); @@ -81,7 +91,7 @@ class LoggerFactory break; case 'syslog': - $logger = new SyslogLogger($channel, $introspection, $loglevel); + $logger = new SyslogLogger($this->findChannel(), $introspection, $loglevel); break; case 'stream': @@ -89,7 +99,7 @@ class LoggerFactory $stream = $config->get('system', 'logfile'); // just add a stream in case it's either writable or not file if (!is_file($stream) || is_writable($stream)) { - $logger = new StreamLogger($channel, $stream, $introspection, $loglevel); + $logger = new StreamLogger($this->findChannel(), $stream, $introspection, $loglevel); } else { $logger = new VoidLogger(); } @@ -104,8 +114,6 @@ class LoggerFactory } $database->setLogger($logger); - Logger::init($logger); - return $logger; } @@ -117,7 +125,6 @@ class LoggerFactory * * It should never get filled during normal usage of Friendica * - * @param string $channel The channel of the logger instance * @param Configuration $config The config * @param Profiler $profiler The profiler of the app * @@ -126,7 +133,7 @@ class LoggerFactory * @throws InternalServerErrorException * @throws \Exception */ - public static function createDev($channel, Configuration $config, Profiler $profiler) + public static function createDev(Configuration $config, Profiler $profiler) { $debugging = $config->get('system', 'debugging'); $stream = $config->get('system', 'dlogfile'); @@ -135,7 +142,6 @@ class LoggerFactory if ((!isset($developerIp) || !$debugging) && (!is_file($stream) || is_writable($stream))) { $logger = new VoidLogger(); - Logger::setDevLogger($logger); return $logger; } @@ -150,7 +156,7 @@ class LoggerFactory $loggerTimeZone = new \DateTimeZone('UTC'); Monolog\Logger::setTimezone($loggerTimeZone); - $logger = new Monolog\Logger($channel); + $logger = new Monolog\Logger(self::DEV_CHANNEL); $logger->pushProcessor(new Monolog\Processor\PsrLogMessageProcessor()); $logger->pushProcessor(new Monolog\Processor\ProcessIdProcessor()); $logger->pushProcessor(new Monolog\Processor\UidProcessor()); @@ -162,12 +168,12 @@ class LoggerFactory break; case 'syslog': - $logger = new SyslogLogger($channel, $introspection, LogLevel::DEBUG); + $logger = new SyslogLogger(self::DEV_CHANNEL, $introspection, LogLevel::DEBUG); break; case 'stream': default: - $logger = new StreamLogger($channel, $stream, $introspection, LogLevel::DEBUG); + $logger = new StreamLogger(self::DEV_CHANNEL, $stream, $introspection, LogLevel::DEBUG); break; } @@ -178,8 +184,6 @@ class LoggerFactory $logger = new ProfilerLogger($logger, $profiler); } - Logger::setDevLogger($logger); - return $logger; } diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 5a2adea9d..f215af1af 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -45,6 +45,35 @@ class Profile return $profile; } + /** + * @brief Returns default profile for a given user ID and ID + * + * @param int $uid The contact ID + * @param int $id The contact owner ID + * @param array $fields The selected fields + * + * @return array Profile data for the ID + * @throws \Exception + */ + public static function getById(int $uid, int $id, array $fields = []) + { + return DBA::selectFirst('profile', $fields, ['uid' => $uid, 'id' => $id]); + } + + /** + * @brief Returns profile data for the contact owner + * + * @param int $uid The User ID + * @param array $fields The fields to retrieve + * + * @return array Array of profile data + * @throws \Exception + */ + public static function getListByUser(int $uid, array $fields = []) + { + return DBA::selectToArray('profile', $fields, ['uid' => $uid]); + } + /** * @brief Returns a formatted location string from the given profile array * diff --git a/src/Util/Logger/WorkerLogger.php b/src/Util/Logger/WorkerLogger.php index be7f82a9f..04edecc69 100644 --- a/src/Util/Logger/WorkerLogger.php +++ b/src/Util/Logger/WorkerLogger.php @@ -31,13 +31,23 @@ class WorkerLogger implements LoggerInterface * @param string $functionName The current function name of the worker * @param int $idLength The length of the generated worker ID */ - public function __construct(LoggerInterface $logger, $functionName, $idLength = 7) + public function __construct(LoggerInterface $logger, $functionName = '', $idLength = 7) { $this->logger = $logger; $this->functionName = $functionName; $this->workerId = Strings::getRandomHex($idLength); } + /** + * Sets the function name for additional logging + * + * @param string $functionName + */ + public function setFunctionName(string $functionName) + { + $this->functionName = $functionName; + } + /** * Adds the worker context for each log entry * diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php index 5f9d3bf72..3c3f835eb 100644 --- a/tests/DatabaseTest.php +++ b/tests/DatabaseTest.php @@ -5,19 +5,10 @@ namespace Friendica\Test; -use Friendica\App\Mode; -use Friendica\Core\Config\Cache\ConfigCache; -use Friendica\Database\Database; -use Friendica\Factory\ConfigFactory; -use Friendica\Util\BasePath; -use Friendica\Util\ConfigFileLoader; -use Friendica\Util\Profiler; +use Friendica\Test\Util\Database\StaticDatabase; use PHPUnit\DbUnit\DataSet\YamlDataSet; use PHPUnit\DbUnit\TestCaseTrait; use PHPUnit_Extensions_Database_DB_IDatabaseConnection; -use Psr\Log\NullLogger; - -require_once __DIR__ . '/../boot.php'; /** * Abstract class used by tests that need a database. @@ -26,34 +17,6 @@ abstract class DatabaseTest extends MockedTest { use TestCaseTrait; - /** @var Database */ - protected static $dba; - - /** @var BasePath */ - protected static $basePath; - - /** @var Mode */ - protected static $mode; - - /** @var ConfigCache */ - protected static $configCache; - - /** @var Profiler */ - protected static $profiler; - - public static function setUpBeforeClass() - { - parent::setUpBeforeClass(); - - self::$basePath = new BasePath(dirname(__DIR__)); - $configLoader = new ConfigFileLoader(self::$basePath->getPath()); - $configFactory = new ConfigFactory(); - self::$configCache = $configFactory->createCache($configLoader); - self::$profiler = new Profiler(self::$configCache); - self::$dba = new Database(self::$configCache, self::$profiler, new NullLogger(), $_SERVER); - self::$mode = new Mode(self::$basePath, self::$dba, self::$configCache); - } - /** * Get database connection. * @@ -67,23 +30,14 @@ abstract class DatabaseTest extends MockedTest */ protected function getConnection() { - if (!getenv('MYSQL_DATABASE')) { - $this->markTestSkipped('Please set the MYSQL_* environment variables to your test database credentials.'); - } - - if (!self::$dba->isConnected()) { - if (!self::$dba->connect()) { - $this->markTestSkipped('Could not connect to the database.'); - } - } - - return $this->createDefaultDBConnection(self::$dba->getConnection(), getenv('MYSQL_DATABASE')); + return $this->createDefaultDBConnection(StaticDatabase::getGlobConnection(), getenv('MYSQL_DATABASE')); } /** * Get dataset to populate the database with. + * * @return YamlDataSet - * @see https://phpunit.de/manual/5.7/en/database.html + * @see https://phtablepunit.de/manual/5.7/en/database.html */ protected function getDataSet() { diff --git a/tests/Util/AppMockTrait.php b/tests/Util/AppMockTrait.php index caf8a7c08..f9b026979 100644 --- a/tests/Util/AppMockTrait.php +++ b/tests/Util/AppMockTrait.php @@ -2,6 +2,7 @@ namespace Friendica\Test\Util; +use Dice\Dice; use Friendica\App; use Friendica\BaseObject; use Friendica\Core\Config; @@ -35,6 +36,11 @@ trait AppMockTrait */ protected $mode; + /** + * @var MockInterface|Dice The dependency injection library + */ + protected $dice; + /** * Mock the App * @@ -43,18 +49,31 @@ trait AppMockTrait */ public function mockApp(vfsStreamDirectory $root, $raw = false) { + $this->dice = \Mockery::mock(Dice::class)->makePartial(); + $this->dice = $this->dice->addRules(include __DIR__ . '/../../static/dependencies.config.php'); + $this->configMock = \Mockery::mock(Config\Cache\ConfigCache::class); + $this->dice->shouldReceive('create') + ->with(Config\Cache\ConfigCache::class) + ->andReturn($this->configMock); $this->mode = \Mockery::mock(App\Mode::class); + $this->dice->shouldReceive('create') + ->with(App\Mode::class) + ->andReturn($this->mode); $configModel= \Mockery::mock(\Friendica\Model\Config\Config::class); // Disable the adapter $configModel->shouldReceive('isConnected')->andReturn(false); $config = new Config\JitConfiguration($this->configMock, $configModel); - // Initialize empty Config - Config::init($config); + $this->dice->shouldReceive('create') + ->with(Config\Configuration::class) + ->andReturn($config); // Mocking App and most used functions $this->app = \Mockery::mock(App::class); + $this->dice->shouldReceive('create') + ->with(App::class) + ->andReturn($this->app); $this->app ->shouldReceive('getBasePath') ->andReturn($root->url()); @@ -65,6 +84,9 @@ trait AppMockTrait $this->profilerMock = \Mockery::mock(Profiler::class); $this->profilerMock->shouldReceive('saveTimestamp'); + $this->dice->shouldReceive('create') + ->with(Profiler::class) + ->andReturn($this->profilerMock); $this->app ->shouldReceive('getConfigCache') @@ -87,7 +109,7 @@ trait AppMockTrait return $this->configMock->get('system', 'url'); }); - BaseObject::setApp($this->app); + BaseObject::setDependencyInjection($this->dice); if ($raw) { return; diff --git a/tests/Util/Database/ExtendedPDO.php b/tests/Util/Database/ExtendedPDO.php new file mode 100644 index 000000000..6bb0251c5 --- /dev/null +++ b/tests/Util/Database/ExtendedPDO.php @@ -0,0 +1,97 @@ +_transactionDepth; + } + + /** + * Test if database driver support savepoints + * + * @return bool + */ + protected function hasSavepoint() + { + return in_array($this->getAttribute(PDO::ATTR_DRIVER_NAME), + self::$_supportedDrivers); + } + + + /** + * Start transaction + * + * @return bool|void + */ + public function beginTransaction() + { + if($this->_transactionDepth == 0 || !$this->hasSavepoint()) { + parent::beginTransaction(); + } else { + $this->exec("SAVEPOINT LEVEL{$this->_transactionDepth}"); + } + + $this->_transactionDepth++; + } + + /** + * Commit current transaction + * + * @return bool|void + */ + public function commit() + { + $this->_transactionDepth--; + + if($this->_transactionDepth == 0 || !$this->hasSavepoint()) { + parent::commit(); + } else { + $this->exec("RELEASE SAVEPOINT LEVEL{$this->_transactionDepth}"); + } + } + + /** + * Rollback current transaction, + * + * @throws PDOException if there is no transaction started + * @return bool|void + */ + public function rollBack() + { + + if ($this->_transactionDepth == 0) { + throw new PDOException('Rollback error : There is no transaction started'); + } + + $this->_transactionDepth--; + + if($this->_transactionDepth == 0 || !$this->hasSavepoint()) { + parent::rollBack(); + } else { + $this->exec("ROLLBACK TO SAVEPOINT LEVEL{$this->_transactionDepth}"); + } + } +} diff --git a/tests/Util/Database/StaticDatabase.php b/tests/Util/Database/StaticDatabase.php new file mode 100644 index 000000000..63544c4f6 --- /dev/null +++ b/tests/Util/Database/StaticDatabase.php @@ -0,0 +1,136 @@ +connection) && $this->connected()) { + return true; + } + + if (!isset(self::$staticConnection)) { + + $port = 0; + $serveraddr = trim($this->configCache->get('database', 'hostname')); + $serverdata = explode(':', $serveraddr); + $server = $serverdata[0]; + if (count($serverdata) > 1) { + $port = trim($serverdata[1]); + } + $server = trim($server); + $user = trim($this->configCache->get('database', 'username')); + $pass = trim($this->configCache->get('database', 'password')); + $db = trim($this->configCache->get('database', 'database')); + $charset = trim($this->configCache->get('database', 'charset')); + + if (!(strlen($server) && strlen($user))) { + return false; + } + + $connect = "mysql:host=" . $server . ";dbname=" . $db; + + if ($port > 0) { + $connect .= ";port=" . $port; + } + + if ($charset) { + $connect .= ";charset=" . $charset; + } + + + try { + self::$staticConnection = @new ExtendedPDO($connect, $user, $pass); + self::$staticConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); + } catch (PDOException $e) { + /// @TODO At least log exception, don't ignore it! + } + } + + $this->driver = 'pdo'; + $this->connection = self::$staticConnection; + $this->connected = true; + + return $this->connected; + } + + /** + * Override the transaction since there are now hierachical transactions possible + * + * @return bool + */ + public function transaction() + { + if (!$this->connection->inTransaction() && !$this->connection->beginTransaction()) { + return false; + } + + $this->in_transaction = true; + return true; + } + + /** + * @brief Does a commit + * + * @return boolean Was the command executed successfully? + */ + public function commit() + { + if (!$this->performCommit()) { + return false; + } + $this->in_transaction = false; + return true; + } + + /** + * @return ExtendedPDO The global, static connection + */ + public static function getGlobConnection() + { + return self::$staticConnection; + } + + /** + * Perform a global commit for every nested transaction of the static connection + */ + public static function statCommit() + { + if (isset(self::$staticConnection)) { + while (self::$staticConnection->getTransactionDepth() > 0) { + self::$staticConnection->commit(); + } + } + } + + /** + * Perform a global rollback for every nested transaction of the static connection + */ + public static function statRollback() + { + if (isset(self::$staticConnection)) { + while (self::$staticConnection->getTransactionDepth() > 0) { + self::$staticConnection->rollBack(); + } + } + } +} diff --git a/tests/include/ApiTest.php b/tests/include/ApiTest.php index a7193c887..15da51527 100644 --- a/tests/include/ApiTest.php +++ b/tests/include/ApiTest.php @@ -5,16 +5,16 @@ namespace Friendica\Test; +use Dice\Dice; use Friendica\App; +use Friendica\BaseObject; use Friendica\Core\Config; -use Friendica\Core\Config\Cache\PConfigCache; -use Friendica\Core\L10n\L10n; use Friendica\Core\PConfig; use Friendica\Core\Protocol; use Friendica\Core\System; -use Friendica\Factory; +use Friendica\Database\Database; use Friendica\Network\HTTPException; -use Friendica\Util\BaseURL; +use Friendica\Test\Util\Database\StaticDatabase; use Monolog\Handler\TestHandler; require_once __DIR__ . '/../../include/api.php'; @@ -32,9 +32,6 @@ class ApiTest extends DatabaseTest */ protected $logOutput; - /** @var App */ - protected $app; - /** @var array */ protected $selfUser; /** @var array */ @@ -44,27 +41,27 @@ class ApiTest extends DatabaseTest protected $wrongUserId; + /** @var App */ + protected $app; + /** * Create variables used by tests. */ public function setUp() { - $configModel = new \Friendica\Model\Config\Config(self::$dba); - $configFactory = new Factory\ConfigFactory(); - $config = $configFactory->createConfig(self::$configCache, $configModel); - $pconfigModel = new \Friendica\Model\Config\PConfig(self::$dba); - $configFactory->createPConfig(self::$configCache, new PConfigCache(), $pconfigModel); - $loggerFactory = new Factory\LoggerFactory(); - $logger = $loggerFactory->create('test', self::$dba, $config, self::$profiler); - $baseUrl = new BaseURL($config, $_SERVER); - $router = new App\Router(); - $l10n = new L10n($config, - self::$dba, - $logger); - $this->app = new App(self::$dba, $config, self::$mode, $router, $baseUrl, $logger, self::$profiler, $l10n, false); + StaticDatabase::statRollback(); + + $dice = new Dice(); + $dice = $dice->addRules(include __DIR__ . '/../../static/dependencies.config.php'); + $dice = $dice->addRule(Database::class, ['instanceOf' => StaticDatabase::class, 'shared' => true]); + BaseObject::setDependencyInjection($dice); + $this->app = BaseObject::getApp(); parent::setUp(); + $this->app->argc = 1; + $this->app->argv = ['home']; + // User data that the test database is populated with $this->selfUser = [ 'id' => 42, @@ -107,15 +104,9 @@ class ApiTest extends DatabaseTest Config::set('system', 'theme', 'system_theme'); } - /** - * Cleanup variables used by tests. - */ protected function tearDown() { - parent::tearDown(); - - $this->app->argc = 1; - $this->app->argv = ['home']; + StaticDatabase::statRollback(); } /** diff --git a/tests/src/BaseObjectTest.php b/tests/src/BaseObjectTest.php index cb980b47e..693521452 100644 --- a/tests/src/BaseObjectTest.php +++ b/tests/src/BaseObjectTest.php @@ -23,20 +23,6 @@ class BaseObjectTest extends TestCase */ private $baseObject; - /** - * Test the setApp() and getApp() function. - * @return void - */ - public function testGetSetApp() - { - $baseObject = new BaseObject(); - $this->setUpVfsDir(); - $this->mockApp($this->root); - - $baseObject->setApp($this->app); - $this->assertEquals($this->app, $baseObject->getApp()); - } - /** * Test the getApp() function without App * @expectedException Friendica\Network\HTTPException\InternalServerErrorException diff --git a/tests/src/Content/Text/BBCodeTest.php b/tests/src/Content/Text/BBCodeTest.php index df89bda31..3affe4e77 100644 --- a/tests/src/Content/Text/BBCodeTest.php +++ b/tests/src/Content/Text/BBCodeTest.php @@ -41,8 +41,9 @@ class BBCodeTest extends MockedTest $l10nMock = \Mockery::mock(L10n::class); $l10nMock->shouldReceive('t')->withAnyArgs()->andReturnUsing(function ($args) { return $args; }); - \Friendica\Core\L10n::init($l10nMock); - + $this->dice->shouldReceive('create') + ->with(L10n::class) + ->andReturn($l10nMock); } public function dataLinks() diff --git a/tests/src/Core/Cache/MemoryCacheTest.php b/tests/src/Core/Cache/MemoryCacheTest.php index 7ddcc4572..6688153b0 100644 --- a/tests/src/Core/Cache/MemoryCacheTest.php +++ b/tests/src/Core/Cache/MemoryCacheTest.php @@ -3,7 +3,7 @@ namespace Friendica\Test\src\Core\Cache; use Friendica\Core\Cache\IMemoryCacheDriver; -use Friendica\Core\Logger; +use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; abstract class MemoryCacheTest extends CacheTest @@ -15,9 +15,13 @@ abstract class MemoryCacheTest extends CacheTest protected function setUp() { - Logger::init(new NullLogger()); - parent::setUp(); + + $logger = new NullLogger(); + $this->dice->shouldReceive('create') + ->with(LoggerInterface::class) + ->andReturn($logger); + if (!($this->instance instanceof IMemoryCacheDriver)) { throw new \Exception('MemoryCacheTest unsupported'); } diff --git a/tests/src/Core/InstallerTest.php b/tests/src/Core/InstallerTest.php index 942cdec1a..a898dd295 100644 --- a/tests/src/Core/InstallerTest.php +++ b/tests/src/Core/InstallerTest.php @@ -3,6 +3,8 @@ // this is in the same namespace as Install for mocking 'function_exists' namespace Friendica\Core; +use Dice\Dice; +use Friendica\BaseObject; use Friendica\Core\Config\Cache\ConfigCache; use Friendica\Network\CurlResult; use Friendica\Object\Image; @@ -27,7 +29,16 @@ class InstallerTest extends MockedTest $this->setUpVfsDir(); $this->l10nMock = \Mockery::mock(\Friendica\Core\L10n\L10n::class); - L10n::init($this->l10nMock); + + /** @var Dice|MockInterface $dice */ + $dice = \Mockery::mock(Dice::class)->makePartial(); + $dice = $dice->addRules(include __DIR__ . '/../../../static/dependencies.config.php'); + + $dice->shouldReceive('create') + ->with(\Friendica\Core\L10n\L10n::class) + ->andReturn($this->l10nMock); + + BaseObject::setDependencyInjection($dice); } private function mockL10nT(string $text, $times = null) diff --git a/tests/src/Core/Lock/LockTest.php b/tests/src/Core/Lock/LockTest.php index 7202058e4..59d6ee2d5 100644 --- a/tests/src/Core/Lock/LockTest.php +++ b/tests/src/Core/Lock/LockTest.php @@ -2,10 +2,10 @@ namespace Friendica\Test\src\Core\Lock; -use Friendica\Core\Logger; use Friendica\Test\MockedTest; use Friendica\Test\Util\AppMockTrait; use Friendica\Test\Util\VFSTrait; +use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; abstract class LockTest extends MockedTest @@ -34,7 +34,10 @@ abstract class LockTest extends MockedTest ->shouldReceive('getHostname') ->andReturn('friendica.local'); - Logger::init(new NullLogger()); + $logger = new NullLogger(); + $this->dice->shouldReceive('create') + ->with(LoggerInterface::class) + ->andReturn($logger); parent::setUp(); $this->instance = $this->getInstance(); diff --git a/tests/src/Database/DBATest.php b/tests/src/Database/DBATest.php index 69ea267bd..d6f59542f 100644 --- a/tests/src/Database/DBATest.php +++ b/tests/src/Database/DBATest.php @@ -1,35 +1,22 @@ createConfig(self::$configCache, $configModel); - $pconfigModel = new \Friendica\Model\Config\PConfig(self::$dba); - $configFactory->createPConfig(self::$configCache, new PConfigCache(), $pconfigModel); - $loggerFactory = new Factory\LoggerFactory(); - $logger = $loggerFactory->create('test', self::$dba, $config, self::$profiler); - $baseUrl = new BaseURL($config, $_SERVER); - $router = new App\Router(); - $l10n = new L10n($config, - self::$dba, - $logger); - $this->app = new App(self::$dba, $config, self::$mode, $router, $baseUrl, $logger, self::$profiler, $l10n, false); - parent::setUp(); + $dice = new Dice(); + $dice = $dice->addRules(include __DIR__ . '/../../../static/dependencies.config.php'); + BaseObject::setDependencyInjection($dice); + // Default config Config::set('config', 'hostname', 'localhost'); Config::set('system', 'throttle_limit_day', 100); diff --git a/tests/src/Database/DBStructureTest.php b/tests/src/Database/DBStructureTest.php index a951d1c09..2747c3df2 100644 --- a/tests/src/Database/DBStructureTest.php +++ b/tests/src/Database/DBStructureTest.php @@ -2,14 +2,10 @@ namespace Friendica\Test\src\Database; -use Friendica\App; -use Friendica\Core\Config\Cache\PConfigCache; -use Friendica\Core\L10n\L10n; +use Dice\Dice; +use Friendica\BaseObject; use Friendica\Database\DBStructure; -use Friendica\Factory; -use Friendica\Model\Config\Config; use Friendica\Test\DatabaseTest; -use Friendica\Util\BaseURL; class DBStructureTest extends DatabaseTest { @@ -18,20 +14,11 @@ class DBStructureTest extends DatabaseTest */ public function setUp() { - $configModel = new Config(self::$dba); - $configFactory = new Factory\ConfigFactory(); - $config = $configFactory->createConfig(self::$configCache, $configModel); - $pconfigModel = new \Friendica\Model\Config\PConfig(self::$dba); - $configFactory->createPConfig(self::$configCache, new PConfigCache(), $pconfigModel); - $loggerFactory = new Factory\LoggerFactory(); - $logger = $loggerFactory->create('test', self::$dba, $config, self::$profiler); - $baseUrl = new BaseURL($config, $_SERVER); - $router = new App\Router(); - $l10n = new L10n($config, - self::$dba, - $logger); - $this->app = new App(self::$dba, $config, self::$mode, $router, $baseUrl, $logger, self::$profiler, $l10n, false); parent::setUp(); + + $dice = new Dice(); + $dice = $dice->addRules(include __DIR__ . '/../../../static/dependencies.config.php'); + BaseObject::setDependencyInjection($dice); } /** diff --git a/tests/src/Network/CurlResultTest.php b/tests/src/Network/CurlResultTest.php index b542371b3..72991c6d0 100644 --- a/tests/src/Network/CurlResultTest.php +++ b/tests/src/Network/CurlResultTest.php @@ -2,10 +2,13 @@ namespace Friendica\Test\src\Network; -use Friendica\Core\Logger; +use Dice\Dice; +use Friendica\BaseObject; use Friendica\Network\CurlResult; -use Friendica\Util\Logger\VoidLogger; +use Mockery\MockInterface; use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; class CurlResultTest extends TestCase { @@ -13,7 +16,17 @@ class CurlResultTest extends TestCase { parent::setUp(); - Logger::init(new VoidLogger()); + + /** @var Dice|MockInterface $dice */ + $dice = \Mockery::mock(Dice::class)->makePartial(); + $dice = $dice->addRules(include __DIR__ . '/../../../static/dependencies.config.php'); + + $logger = new NullLogger(); + $dice->shouldReceive('create') + ->with(LoggerInterface::class) + ->andReturn($logger); + + BaseObject::setDependencyInjection($dice); } /**