sql = null; $this->session = null; $this->user = null; $this->router = null; $this->redis = null; $this->configuration = new Configuration(); $this->setLanguage(Language::DEFAULT_LANGUAGE()); if (!$this->isCLI()) { @session_start(); } } public static function instance(): self { if (!isset(self::$instance)) { self::$instance = new Context(); } return self::$instance; } public function __destruct() { if ($this->sql && $this->sql->isConnected()) { $this->sql->close(); $this->sql = null; } if ($this->redis && $this->redis->isConnected()) { $this->redis->close(); $this->redis = null; } } public function setLanguage(Language $language): void { // 1st: check if the language really exists... if ($language->getId() === null) { $language = Language::findBy(Language::createBuilder($this->sql, true) ->whereEq("code", $language->getCode())); if ($language === false || $language === null) { // if not, load the default language $language = Language::DEFAULT_LANGUAGE(); } } $this->language = $language; $this->language->activate(); if ($this->user && $this->user->language->getId() !== $language->getId()) { $this->user->language = $language; } } public function initSQL(): ?SQL { $databaseConf = $this->configuration->getDatabase(); if ($databaseConf) { $this->sql = SQL::createConnection($databaseConf); if ($this->sql->isConnected()) { $settings = $this->configuration->getSettings(); $settings->loadFromDatabase($this); return $this->sql; } } else { $this->sql = null; } return null; } public function getSQL(): ?SQL { return $this->sql; } public function getSettings(): Settings { return $this->configuration->getSettings(); } public function getUser(): ?User { return $this->user; } public function sendCookies(): void { $domain = getCurrentHostName(); $this->language->sendCookie($domain); $this->session?->sendCookie($domain); $this->session?->update(); session_write_close(); } private function loadSession(string $sessionUUID): void { $this->session = Session::init($this, $sessionUUID); $this->user = $this->session?->getUser(); } public function parseCookies(): void { $settings = $this->getSettings(); if (!$settings->isInstalled()) { // we cannot process user sessions or localization yet. return; } if (isset($_COOKIE['session']) && is_string($_COOKIE['session']) && !empty($_COOKIE['session'])) { $this->loadSession($_COOKIE['session']); } // set language by priority: 1. GET parameter, 2. cookie, 3. user's settings, 4. accept-language header if (isset($_GET['lang']) && is_string($_GET["lang"]) && !empty($_GET["lang"])) { $this->updateLanguage($_GET['lang']); } else if (isset($_COOKIE['lang']) && is_string($_COOKIE["lang"]) && !empty($_COOKIE["lang"])) { $this->updateLanguage($_COOKIE['lang']); } else if ($this->user) { $this->setLanguage($this->user->language); } else { $language = Language::fromHeader(); if ($language !== null) { $this->setLanguage($language); } } } public function updateLanguage(string $lang): bool { if ($this->sql) { $language = Language::findBy(Language::createBuilder($this->sql, true) ->where(new CondOr( new CondLike(new Column("name"), "%$lang%"), // english new Compare("code", $lang), // de_DE new CondLike(new Column("code"), "{$lang}_%") // de -> de_% )) ); if ($language) { $this->setLanguage($language); return true; } } return false; } private function isBot(): bool { if (empty($_SERVER["HTTP_USER_AGENT"])) { return false; } return preg_match('/robot|spider|crawler|curl|^$/i', $_SERVER['HTTP_USER_AGENT']) === 1; } public function isCLI(): bool { return php_sapi_name() === "cli"; } public function getConfig(): Configuration { return $this->configuration; } public function getSession(): ?Session { return $this->session; } public function loadApiKey(string $apiKey): bool { $this->user = User::findBy(User::createBuilder($this->sql, true) ->addJoin(new InnerJoin("ApiKey", "ApiKey.user_id", "User.id")) ->whereEq("ApiKey.api_key", $apiKey) ->whereGt("valid_until", $this->sql->currentTimestamp()) ->whereTrue("ApiKey.active") ->whereTrue("User.confirmed") ->whereTrue("User.active") ->fetchEntities()); return $this->user !== null; } public function createSession(User $user, bool $stayLoggedIn): ?Session { $this->user = $user; $this->session = new Session($this, $this->user); $this->session->stayLoggedIn = $stayLoggedIn; if ($this->session->update()) { return $this->session; } else { $this->user = null; $this->session = null; return null; } } public function getLanguage(): Language { return $this->language; } public function invalidateSessions(bool $keepCurrent = false): bool { $query = $this->sql->update("Session") ->set("active", false) ->whereEq("user_id", $this->user->getId()); if ($keepCurrent && $this->session !== null) { $query->whereNeq("id", $this->session->getId()); } return $query->execute(); } public function getRedis(): ?RedisConnection { if ($this->redis === null) { $settings = $this->getSettings(); $connectionData = $settings->getRedisConfiguration(); $this->redis = new RedisConnection($this->sql); if (!$this->redis->connect($connectionData)) { $this->redis = null; } } return $this->redis; } }