se, $ret, true); } /** * Add a log file for FOF * * @param string $file * * @return void */ public function logAddLogger($file): void { Log::addLogger(['text_file' => $file], Log::ALL, ['fof']); } /** * Logs a deprecated practice. In Joomla! this results in the $message being output in the * deprecated log file, found in your site's log directory. * * @param string $message The deprecated practice log message * * @return void */ public function logDeprecated(string $message): void { Log::add($message, Log::WARNING, 'deprecated'); } /** * Adds a message to the application's debug log * * @param string $message * * @return void * * @codeCoverageIgnore */ public function logDebug(string $message): void { Log::add($message, Log::DEBUG, 'fof'); } /** @inheritDoc */ public function logUserAction($title, string $logText, string $extension, User $user = null): void { if (!is_string($title) && !is_array($title)) { throw new InvalidArgumentException(sprintf('%s::%s -- $title expects a string or an array', __CLASS__, __METHOD__)); } static $joomlaModelAdded = false; // User Actions Log is available only under Joomla 3.9+ if (version_compare(JVERSION, '3.9', 'lt')) { return; } // Do not perform logging if we're under CLI. Even if we _could_ have a logged user in CLI, ActionlogsModelActionlog // model always uses JoomlaFactory to fetch the current user, fetching data from the session. This means that under the CLI // (where there is no session) such session is started, causing warnings because usually output was already started before if ($this->isCli()) { return; } // Include required Joomla Model if (!$joomlaModelAdded) { BaseDatabaseModel::addIncludePath(JPATH_ROOT . '/administrator/components/com_actionlogs/models', 'ActionlogsModel'); $joomlaModelAdded = true; } $user = $this->getUser(); // No log for guest users if ($user->guest) { return; } $message = [ 'title' => $title, 'username' => $user->username, 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id, ]; if (is_array($title)) { unset ($message['title']); $message = array_merge($message, $title); } /** @var ActionlogsModelActionlog $model * */ try { $model = BaseDatabaseModel::getInstance('Actionlog', 'ActionlogsModel'); $model->addLog([$message], $logText, $extension, $user->id); } catch (Exception $e) { // Ignore any error } } /** * Returns the root URI for the request. * * @param bool $pathonly If false, prepend the scheme, host and port information. Default is false. * @param string|null $path The path * * @return string The root URI string. * * @codeCoverageIgnore */ public function URIroot(bool $pathonly = false, ?string $path = null): string { return Uri::root($pathonly, $path); } /** * Returns the base URI for the request. * * @param bool $pathonly If false, prepend the scheme, host and port information. Default is false. * * @return string The base URI string */ public function URIbase(bool $pathonly = false): string { return Uri::base($pathonly); } /** * Method to set a response header. If the replace flag is set then all headers * with the given name will be replaced by the new one (only if the current platform supports header caching) * * @param string $name The name of the header to set. * @param string $value The value of the header to set. * @param bool $replace True to replace any headers with the same name. * * @return void * * @codeCoverageIgnore */ public function setHeader(string $name, string $value, bool $replace = false): void { try { JoomlaFactory::getApplication()->setHeader($name, $value, $replace); } catch (Exception $e) { return; } } /** * In platforms that perform header caching, send all headers. * * @return void * * @codeCoverageIgnore */ public function sendHeaders(): void { try { JoomlaFactory::getApplication()->sendHeaders(); } catch (Exception $e) { return; } } /** * Immediately terminate the containing application's execution * * @param int $code The result code which should be returned by the application * * @return void */ public function closeApplication(int $code = 0): void { // Necessary workaround for broken System - Page Cache plugin in Joomla! 3.7.0 $this->bugfixJoomlaCachePlugin(); try { JoomlaFactory::getApplication()->close($code); } catch (Exception $e) { exit($code); } } /** * Perform a redirection to a different page, optionally enqueuing a message for the user. * * @param string $url The URL to redirect to * @param int $status (optional) The HTTP redirection status code, default 303 (See Other) * @param string $msg (optional) A message to enqueue * @param string $type (optional) The message type, e.g. 'message' (default), 'warning' or 'error'. * * @return void */ public function redirect(string $url, int $status = 301, ?string $msg = null, string $type = 'message'): void { // Necessary workaround for broken System - Page Cache plugin in Joomla! 3.7.0 $this->bugfixJoomlaCachePlugin(); try { $app = JoomlaFactory::getApplication(); } catch (Exception $e) { die(sprintf('Please go to %1$s', $url)); } if (!empty($msg)) { if (empty($type)) { $type = 'message'; } $app->enqueueMessage($msg, $type); } // Joomla 4: redirecting to index.php in the backend takes you to the frontend. I need to address that. $isJoomla4 = version_compare(JVERSION, '3.999.999', 'gt'); $isBareIndex = substr($url, 0, 9) === 'index.php'; if ($isJoomla4 && $isBareIndex && $this->isBackend()) { $givenUri = new Uri($url); $newUri = new Uri(Uri::base()); $newUri->setQuery($givenUri->getQuery()); if ($givenUri->getFragment()) { $newUri->setFragment($givenUri->getFragment()); } $url = $newUri->toString(); } // Finally, do the redirection $app->redirect($url, $status); } /** * Handle an exception in a way that results to an error page. We use this under Joomla! to work around a bug in * Joomla! 3.7 which results in error pages leading to white pages because Joomla's System - Page Cache plugin is * broken. * * @param Exception $exception The exception to handle * * @throws Exception We rethrow the exception */ public function showErrorPage(Exception $exception): void { // Necessary workaround for broken System - Page Cache plugin in Joomla! 3.7.0 $this->bugfixJoomlaCachePlugin(); throw $exception; } /** * Set a variable in the user session * * @param string $name The name of the variable to set * @param string|null $value (optional) The value to set it to, default is null * @param string $namespace (optional) The variable's namespace e.g. the component name. Default: 'default' * * @return void */ public function setSessionVar(string $name, $value = null, string $namespace = 'default'): void { // CLI if ($this->isCli() && !class_exists('FOFApplicationCLI')) { static::$fakeSession->set("$namespace.$name", $value); return; } // Joomla 3 if (version_compare(JVERSION, '3.9999.9999', 'le')) { $this->container->session->set($name, $value, $namespace); } // Joomla 4 if (empty($namespace)) { $this->container->session->set($name, $value); return; } $registry = $this->container->session->get('registry'); if (is_null($registry)) { $registry = new Registry(); $this->container->session->set('registry', $registry); } $registry->set($namespace . '.' . $name, $value); } /** * Get a variable from the user session * * @param string $name The name of the variable to set * @param string $default (optional) The default value to return if the variable does not exit, default: null * @param string $namespace (optional) The variable's namespace e.g. the component name. Default: 'default' * * @return mixed */ public function getSessionVar(string $name, $default = null, $namespace = 'default') { // CLI if ($this->isCli() && !class_exists('FOFApplicationCLI')) { return static::$fakeSession->get("$namespace.$name", $default); } // Joomla 3 if (version_compare(JVERSION, '3.9999.9999', 'le')) { return $this->container->session->get($name, $default, $namespace); } // Joomla 4 if (empty($namespace)) { return $this->container->session->get($name, $default); } $registry = $this->container->session->get('registry'); if (is_null($registry)) { $registry = new Registry(); $this->container->session->set('registry', $registry); } return $registry->get($namespace . '.' . $name, $default); } /** * Unset a variable from the user session * * @param string $name The name of the variable to unset * @param string $namespace (optional) The variable's namespace e.g. the component name. Default: 'default' * * @return void */ public function unsetSessionVar(string $name, string $namespace = 'default'): void { $this->setSessionVar($name, null, $namespace); } /** * Return the session token. Two types of tokens can be returned: * * Session token ($formToken == false): Used for anti-spam protection of forms. This is specific to a session * object. * * Form token ($formToken == true): A secure hash of the user ID with the session token. Both the session and the * user are fetched from the application container. * * @param bool $formToken Should I return a form token? * @param bool $forceNew Should I force the creation of a new token? * * @return mixed */ public function getToken(bool $formToken = false, bool $forceNew = false): string { // For CLI apps we implement our own fake token system if ($this->isCli()) { $token = $this->getSessionVar('session.token'); // Create a token if (is_null($token) || $forceNew) { $token = UserHelper::genRandomPassword(32); $this->setSessionVar('session.token', $token); } if (!$formToken) { return $token; } $user = $this->getUser(); return ApplicationHelper::getHash($user->id . $token); } // Web application, go through the regular Joomla! API. if ($formToken) { return Session::getFormToken($forceNew); } return $this->container->session->getToken($forceNew); } /** @inheritDoc */ public function addScriptOptions($key, $value, $merge = true) { /** @var HtmlDocument $document */ $document = $this->getDocument(); if (!method_exists($document, 'addScriptOptions')) { return; } $document->addScriptOptions($key, $value, $merge); } /** @inheritDoc */ public function getScriptOptions($key = null) { /** @var HtmlDocument $document */ $document = $this->getDocument(); if (!method_exists($document, 'getScriptOptions')) { return []; } return $document->getScriptOptions($key); } /** * Main function to detect if we're running in a CLI environment, if we're admin or if it's an API application * * @return array isCLI and isAdmin. It's not an associative array, so we can use list(). */ protected function isCliAdminApi(): array { if (is_null(static::$isCLI) && is_null(static::$isAdmin)) { static::$isCLI = false; static::$isAdmin = false; static::$isApi = false; try { if (is_null(JoomlaFactory::$application)) { static::$isCLI = true; static::$isAdmin = false; return [static::$isCLI, static::$isAdmin, static::$isApi]; } $app = JoomlaFactory::getApplication(); static::$isCLI = $app instanceof Exception || $app instanceof CliApplication; if (class_exists('Joomla\CMS\Application\CliApplication')) { static::$isCLI = static::$isCLI || $app instanceof JApplicationCli; } if (class_exists('Joomla\CMS\Application\ConsoleApplication')) { static::$isCLI = static::$isCLI || ($app instanceof ConsoleApplication); } } catch (Exception $e) { static::$isCLI = true; } if (static::$isCLI) { return [static::$isCLI, static::$isAdmin, static::$isApi]; } try { $app = JoomlaFactory::getApplication(); } catch (Exception $e) { return [static::$isCLI, static::$isAdmin, static::$isApi]; } if (method_exists($app, 'isAdmin')) { static::$isAdmin = $app->isAdmin(); } elseif (method_exists($app, 'isClient')) { static::$isAdmin = $app->isClient('administrator'); static::$isApi = $app->isClient('api'); } } return [static::$isCLI, static::$isAdmin, static::$isApi]; } /** * Gets a reference to the cache object, loading it from the disk if * needed. * * @param bool $force Should I forcibly reload the registry? * * @return Registry */ private function &getCacheObject(bool $force = false): Registry { // Check if we have to load the cache file or we are forced to do that if (is_null($this->_cache) || $force) { // Try to get data from Joomla!'s cache $cache = JoomlaFactory::getCache('fof', ''); $this->_cache = $cache->get('cache', 'fof'); $isRegistry = is_object($this->_cache); if ($isRegistry) { $isRegistry = $this->_cache instanceof Registry; } if (!$isRegistry) { // Create a new Registry object $this->_cache = new Registry(); } } return $this->_cache; } /** * Save the cache object back to disk * * @return bool True on success */ private function saveCache(): bool { // Get the Registry object of our cached data $registry = $this->getCacheObject(); $cache = JoomlaFactory::getCache('fof', ''); return $cache->store($registry, 'cache', 'fof'); } /** * Joomla! 3.7 has a broken System - Page Cache plugin. When this plugin is enabled it FORCES the caching of all * pages as soon as Joomla! starts loading, before the plugin has a chance to request to not be cached. Event worse, * in case of a redirection, it doesn't try to remove the cache lock. This means that the next request will be * treated as though the result of the page should be cached. Since there is NO cache content for the page Joomla! * returns an empty response with a 200 OK header. This will, of course, get in the way of every single attempt to * perform a redirection in the frontend of the site. * * @return void */ private function bugfixJoomlaCachePlugin(): void { // Only do something when the System - Cache plugin is activated if (!class_exists('PlgSystemCache')) { return; } // Forcibly uncache the current request $options = [ 'defaultgroup' => 'page', 'browsercache' => false, 'caching' => false, ]; $cache_key = Uri::getInstance()->toString(); Cache::getInstance('page', $options)->cache->remove($cache_key, 'page'); } } 500 Internal Server Error
Failed to load 'rt_gemini' template: Please install Gantry 5 Framework!