Uncaught SmartyException

Unable to load template 'file:forum/forum_index.tpl'

(File: /home/padow/Websites/dev/vendor/smarty/smarty/libs/sysplugins/smarty_internal_template.php)

https://dev.namelessmc.xyz/forum/


File: /home/padow/Websites/dev/vendor/smarty/smarty/libs/sysplugins/smarty_internal_template.php
    /**
     * render template
     *
     * @param bool      $no_output_filter if true do not run output filter
     * @param null|bool $display          true: display, false: fetch null: sub-template
     *
     * @return string
     * @throws \Exception
     * @throws \SmartyException
     */
    public function render($no_output_filter = true, $display = null)
    {
        if ($this->smarty->debugging) {
            if (!isset($this->smarty->_debug)) {
                $this->smarty->_debug = new Smarty_Internal_Debug();
            }
            $this->smarty->_debug->start_template($this, $display);
        }
        // checks if template exists
        if (!$this->source->exists) {
            throw new SmartyException(
                "Unable to load template '{$this->source->type}:{$this->source->name}'" .
                ($this->_isSubTpl() ? " in '{$this->parent->template_resource}'" : '')
            );
        }
        // disable caching for evaluated code
        if ($this->source->handler->recompiled) {
            $this->caching = Smarty::CACHING_OFF;
        }
        // read from cache or render
        if ($this->caching === Smarty::CACHING_LIFETIME_CURRENT || $this->caching === Smarty::CACHING_LIFETIME_SAVED) {
            if (!isset($this->cached) || $this->cached->cache_id !== $this->cache_id
                || $this->cached->compile_id !== $this->compile_id
            ) {
                $this->loadCached(true);
            }
            $this->cached->render($this, $no_output_filter);
        } else {
            if (!isset($this->compiled) || $this->compiled->compile_id !== $this->compile_id) {
                $this->loadCompiled(true);
            }
File: /home/padow/Websites/dev/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php
                if ($template->caching) {
                    // return cache status of template
                    if (!isset($template->cached)) {
                        $template->loadCached();
                    }
                    $result = $template->cached->isCached($template);
                    Smarty_Internal_Template::$isCacheTplObj[ $template->_getTemplateId() ] = $template;
                } else {
                    return false;
                }
            } else {
                if ($saveVars) {
                    $savedTplVars = $template->tpl_vars;
                    $savedConfigVars = $template->config_vars;
                }
                ob_start();
                $template->_mergeVars();
                if (!empty(Smarty::$global_tpl_vars)) {
                    $template->tpl_vars = array_merge(Smarty::$global_tpl_vars, $template->tpl_vars);
                }
                $result = $template->render(false, $function);
                $template->_cleanUp();
                if ($saveVars) {
                    $template->tpl_vars = $savedTplVars;
                    $template->config_vars = $savedConfigVars;
                } else {
                    if (!$function && !isset(Smarty_Internal_Template::$tplObjCache[ $template->templateId ])) {
                        $template->parent = null;
                        $template->tpl_vars = $template->config_vars = array();
                        Smarty_Internal_Template::$tplObjCache[ $template->templateId ] = $template;
                    }
                }
            }

            if (isset($errorHandler)) {
                $errorHandler->deactivate();
            }

            if (isset($_smarty_old_error_level)) {
                error_reporting($_smarty_old_error_level);
            }
File: /home/padow/Websites/dev/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php
    public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null)
    {
        $result = $this->_execute($template, $cache_id, $compile_id, $parent, 0);
        return $result === null ? ob_get_clean() : $result;
    }

    /**
     * displays a Smarty template
     *
     * @param string $template   the resource handle of the template file or template object
     * @param mixed  $cache_id   cache id to be used with this template
     * @param mixed  $compile_id compile id to be used with this template
     * @param object $parent     next higher level of Smarty variables
     *
     * @throws \Exception
     * @throws \SmartyException
     */
    public function display($template = null, $cache_id = null, $compile_id = null, $parent = null)
    {
        // display template
        $this->_execute($template, $cache_id, $compile_id, $parent, 1);
    }

    /**
     * test if cache is valid
     *
     * @api  Smarty::isCached()
     * @link https://www.smarty.net/docs/en/api.is.cached.tpl
     *
     * @param null|string|\Smarty_Internal_Template $template   the resource handle of the template file or template
     *                                                          object
     * @param mixed                                 $cache_id   cache id to be used with this template
     * @param mixed                                 $compile_id compile id to be used with this template
     * @param object                                $parent     next higher level of Smarty variables
     *
     * @return bool cache status
     * @throws \Exception
     * @throws \SmartyException
     */
    public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null)
    {
File: /home/padow/Websites/dev/core/classes/Templates/TemplateBase.php
    public function displayTemplate(string $template, Smarty $smarty): void {
        [$css, $js] = $this->assets()->compile();

        // Put the assets at the start of the arrays, so they load first (SBAdmin requires JQuery first, etc.)
        array_unshift($this->_css, ...$css);
        array_unshift($this->_js, ...$js);

        $smarty->assign([
            'TEMPLATE_CSS' => $this->getCSS(),
            'TEMPLATE_JS' => $this->getJS()
        ]);

        if (defined('PHPDEBUGBAR') && PHPDEBUGBAR) {
            $debugBar = DebugBarHelper::getInstance()->getDebugBar()->getJavascriptRenderer();
            $smarty->assign([
                'DEBUGBAR_JS' => $debugBar->renderHead(),
                'DEBUGBAR_HTML' => $debugBar->render()
            ]);
        }

        $smarty->display($template);
    }

    /**
     * Get all internal CSS styles.
     *
     * @return array Array of strings of CSS.
     */
    public function getCSS(): array {
        return $this->_css;
    }

    /**
     * Get all internal JS code.
     *
     * @return array Array of strings of JS.
     */
    public function getJS(): array {
        return $this->_js;
    }

File: /home/padow/Websites/dev/modules/Forum/pages/forum/index.php

$smarty->assign('FORUMS', $forums);
$smarty->assign('YES', $language->get('general', 'yes'));
$smarty->assign('NO', $language->get('general', 'no'));
$smarty->assign('SUBFORUMS', $forum_language->get('forum', 'subforums'));

$smarty->assign('FORUM_INDEX_LINK', URL::build('/forum'));

// Load modules + template
Module::loadPage($user, $pages, $cache, $smarty, [$navigation, $cc_nav, $staffcp_nav], $widgets, $template);

$template->onPageLoad();

$smarty->assign('WIDGETS_LEFT', $widgets->getWidgets('left'));
$smarty->assign('WIDGETS_RIGHT', $widgets->getWidgets('right'));

require(ROOT_PATH . '/core/templates/navbar.php');
require(ROOT_PATH . '/core/templates/footer.php');

// Display template
$template->displayTemplate('forum/forum_index.tpl', $smarty);
File: /home/padow/Websites/dev/index.php
        $pages->setActivePage($pages->getPageByURL('/'));
        require(ROOT_PATH . '/modules/Core/pages/index.php');
    }
    die();
}

$route = rtrim(strtok($_GET['route'], '?'), '/');

$all_pages = $pages->returnPages();

if (array_key_exists($route, $all_pages)) {
    $pages->setActivePage($all_pages[$route]);
    if (isset($all_pages[$route]['custom'])) {
        require(implode(DIRECTORY_SEPARATOR, [ROOT_PATH, 'modules', 'Core', 'pages', 'custom.php']));
        die();
    }

    $path = implode(DIRECTORY_SEPARATOR, [ROOT_PATH, 'modules', $all_pages[$route]['module'], $all_pages[$route]['file']]);

    if (file_exists($path)) {
        require($path);
        die();
    }
} else {
    // Use recursion to check - might have URL parameters in path
    $path_array = explode('/', $route);

    for ($i = count($path_array) - 2; $i > 0; $i--) {

        $new_path = '/';
        for ($n = 1; $n <= $i; $n++) {
            $new_path .= $path_array[$n] . '/';
        }

        $new_path = rtrim($new_path, '/');

        if (array_key_exists($new_path, $all_pages)) {
            $path = implode(DIRECTORY_SEPARATOR, [ROOT_PATH, 'modules', $all_pages[$new_path]['module'], $all_pages[$new_path]['file']]);

            if (file_exists($path)) {
                $pages->setActivePage($all_pages[$new_path]);
SQL query:
SELECT count(*) FROM nl2_posts WHERE deleted = 0;
File: /home/padow/Websites/dev/modules/Core/widgets/StatsWidget.php
                $online_guests = 0;
            }
        } else {
            $online_guests = $this->_cache->retrieve('online_guests');
        }

        $forum_module = DB::getInstance()->get('modules', ['name', 'Forum'])->results();
        $forum_module = $forum_module[0];

        if ($forum_module->enabled) {
            $this->_cache->setCache('forum_stats');
            if (!$this->_cache->isCached('total_topics')) {
                $total_topics = DB::getInstance()->query('SELECT count(*) FROM nl2_topics WHERE deleted = 0')->first();
                $total_topics = $total_topics->{'count(*)'};
                $this->_cache->store('total_topics', $total_topics, 60);
            } else {
                $total_topics = $this->_cache->retrieve('total_topics');
            }

            if (!$this->_cache->isCached('total_posts')) {
                $total_posts = DB::getInstance()->query('SELECT count(*) FROM nl2_posts WHERE deleted = 0')->first();
                $total_posts = $total_posts->{'count(*)'};
                $this->_cache->store('total_posts', $total_posts, 60);
            } else {
                $total_posts = $this->_cache->retrieve('total_posts');
            }

            $this->_smarty->assign([
                'FORUM_STATISTICS' => $this->_language->get('general', 'forum_statistics'),
                'TOTAL_THREADS' => $this->_language->get('general', 'total_threads'),
                'TOTAL_THREADS_VALUE' => $total_topics,
                'TOTAL_POSTS' => $this->_language->get('general', 'total_posts'),
                'TOTAL_POSTS_VALUE' => $total_posts,
            ]);
        }

        $this->_smarty->assign([
            'STATISTICS' => $this->_language->get('general', 'statistics'),
            'USERS_REGISTERED' => $this->_language->get('general', 'users_registered'),
            'USERS_REGISTERED_VALUE' => $users_registered,
            'LATEST_MEMBER' => $this->_language->get('general', 'latest_member'),
SQL query:
SELECT count(*) FROM nl2_topics WHERE deleted = 0;
File: /home/padow/Websites/dev/modules/Core/widgets/StatsWidget.php

        if (!$this->_cache->isCached('online_guests')) {
            try {
                $online_guests = DB::getInstance()->query('SELECT count(*) FROM nl2_online_guests WHERE last_seen > ?', [strtotime('-5 minutes')])->first();
                $online_guests = $online_guests->{'count(*)'};
                $this->_cache->store('online_guests', $online_guests, 60);
            } catch (Exception $e) {
                // Upgrade script hasn't been run
                $online_guests = 0;
            }
        } else {
            $online_guests = $this->_cache->retrieve('online_guests');
        }

        $forum_module = DB::getInstance()->get('modules', ['name', 'Forum'])->results();
        $forum_module = $forum_module[0];

        if ($forum_module->enabled) {
            $this->_cache->setCache('forum_stats');
            if (!$this->_cache->isCached('total_topics')) {
                $total_topics = DB::getInstance()->query('SELECT count(*) FROM nl2_topics WHERE deleted = 0')->first();
                $total_topics = $total_topics->{'count(*)'};
                $this->_cache->store('total_topics', $total_topics, 60);
            } else {
                $total_topics = $this->_cache->retrieve('total_topics');
            }

            if (!$this->_cache->isCached('total_posts')) {
                $total_posts = DB::getInstance()->query('SELECT count(*) FROM nl2_posts WHERE deleted = 0')->first();
                $total_posts = $total_posts->{'count(*)'};
                $this->_cache->store('total_posts', $total_posts, 60);
            } else {
                $total_posts = $this->_cache->retrieve('total_posts');
            }

            $this->_smarty->assign([
                'FORUM_STATISTICS' => $this->_language->get('general', 'forum_statistics'),
                'TOTAL_THREADS' => $this->_language->get('general', 'total_threads'),
                'TOTAL_THREADS_VALUE' => $total_topics,
                'TOTAL_POSTS' => $this->_language->get('general', 'total_posts'),
                'TOTAL_POSTS_VALUE' => $total_posts,
SQL query:
SELECT * FROM nl2_modules WHERE `name` = 'Forum';
File: /home/padow/Websites/dev/modules/Core/widgets/StatsWidget.php
            $online_users = DB::getInstance()->query('SELECT count(*) FROM nl2_users WHERE last_online > ?', [strtotime('-5 minutes')])->first();
            $online_users = $online_users->{'count(*)'};
            $this->_cache->store('online_users', $online_users, 60);
        } else {
            $online_users = $this->_cache->retrieve('online_users');
        }

        if (!$this->_cache->isCached('online_guests')) {
            try {
                $online_guests = DB::getInstance()->query('SELECT count(*) FROM nl2_online_guests WHERE last_seen > ?', [strtotime('-5 minutes')])->first();
                $online_guests = $online_guests->{'count(*)'};
                $this->_cache->store('online_guests', $online_guests, 60);
            } catch (Exception $e) {
                // Upgrade script hasn't been run
                $online_guests = 0;
            }
        } else {
            $online_guests = $this->_cache->retrieve('online_guests');
        }

        $forum_module = DB::getInstance()->get('modules', ['name', 'Forum'])->results();
        $forum_module = $forum_module[0];

        if ($forum_module->enabled) {
            $this->_cache->setCache('forum_stats');
            if (!$this->_cache->isCached('total_topics')) {
                $total_topics = DB::getInstance()->query('SELECT count(*) FROM nl2_topics WHERE deleted = 0')->first();
                $total_topics = $total_topics->{'count(*)'};
                $this->_cache->store('total_topics', $total_topics, 60);
            } else {
                $total_topics = $this->_cache->retrieve('total_topics');
            }

            if (!$this->_cache->isCached('total_posts')) {
                $total_posts = DB::getInstance()->query('SELECT count(*) FROM nl2_posts WHERE deleted = 0')->first();
                $total_posts = $total_posts->{'count(*)'};
                $this->_cache->store('total_posts', $total_posts, 60);
            } else {
                $total_posts = $this->_cache->retrieve('total_posts');
            }

SQL query:
SELECT count(*) FROM nl2_online_guests WHERE last_seen > '1675848639';
File: /home/padow/Websites/dev/modules/Core/widgets/StatsWidget.php
                'statistics',
                [
                    'users_registered' => $users_registered,
                    'latest_member' => $latest_member
                ],
                120
            );

        }

        if (!$this->_cache->isCached('online_users')) {
            $online_users = DB::getInstance()->query('SELECT count(*) FROM nl2_users WHERE last_online > ?', [strtotime('-5 minutes')])->first();
            $online_users = $online_users->{'count(*)'};
            $this->_cache->store('online_users', $online_users, 60);
        } else {
            $online_users = $this->_cache->retrieve('online_users');
        }

        if (!$this->_cache->isCached('online_guests')) {
            try {
                $online_guests = DB::getInstance()->query('SELECT count(*) FROM nl2_online_guests WHERE last_seen > ?', [strtotime('-5 minutes')])->first();
                $online_guests = $online_guests->{'count(*)'};
                $this->_cache->store('online_guests', $online_guests, 60);
            } catch (Exception $e) {
                // Upgrade script hasn't been run
                $online_guests = 0;
            }
        } else {
            $online_guests = $this->_cache->retrieve('online_guests');
        }

        $forum_module = DB::getInstance()->get('modules', ['name', 'Forum'])->results();
        $forum_module = $forum_module[0];

        if ($forum_module->enabled) {
            $this->_cache->setCache('forum_stats');
            if (!$this->_cache->isCached('total_topics')) {
                $total_topics = DB::getInstance()->query('SELECT count(*) FROM nl2_topics WHERE deleted = 0')->first();
                $total_topics = $total_topics->{'count(*)'};
                $this->_cache->store('total_topics', $total_topics, 60);
            } else {
SQL query:
SELECT count(*) FROM nl2_users WHERE last_online > '1675848639';
File: /home/padow/Websites/dev/modules/Core/widgets/StatsWidget.php
                'avatar' => $latest_user->getAvatar(),
                'username' => $latest_user->getDisplayname(true),
                'nickname' => $latest_user->getDisplayname(),
                'id' => Output::getClean($users_query[0]->id)
            ];

            $users_query = null;

            $this->_cache->store(
                'statistics',
                [
                    'users_registered' => $users_registered,
                    'latest_member' => $latest_member
                ],
                120
            );

        }

        if (!$this->_cache->isCached('online_users')) {
            $online_users = DB::getInstance()->query('SELECT count(*) FROM nl2_users WHERE last_online > ?', [strtotime('-5 minutes')])->first();
            $online_users = $online_users->{'count(*)'};
            $this->_cache->store('online_users', $online_users, 60);
        } else {
            $online_users = $this->_cache->retrieve('online_users');
        }

        if (!$this->_cache->isCached('online_guests')) {
            try {
                $online_guests = DB::getInstance()->query('SELECT count(*) FROM nl2_online_guests WHERE last_seen > ?', [strtotime('-5 minutes')])->first();
                $online_guests = $online_guests->{'count(*)'};
                $this->_cache->store('online_guests', $online_guests, 60);
            } catch (Exception $e) {
                // Upgrade script hasn't been run
                $online_guests = 0;
            }
        } else {
            $online_guests = $this->_cache->retrieve('online_guests');
        }

        $forum_module = DB::getInstance()->get('modules', ['name', 'Forum'])->results();
SQL query:
SELECT nl2_users_integrations.*, nl2_integrations.name as integration_name FROM nl2_users_integrations LEFT JOIN nl2_integrations ON integration_id=nl2_integrations.id WHERE user_id = '9';
File: /home/padow/Websites/dev/core/classes/Core/User.php
    }

    /**
     * Get the user's groups.
     *
     * @return array Their groups.
     */
    public function getGroups(): array {
        return $this->_groups;
    }

    /**
     * Get the user's integrations.
     *
     * @return IntegrationUser[] Their integrations.
     */
    public function getIntegrations(): array {
        return $this->_integrations ??= (function (): array {
            $integrations = Integrations::getInstance();

            $integrations_query = $this->_db->query('SELECT nl2_users_integrations.*, nl2_integrations.name as integration_name FROM nl2_users_integrations LEFT JOIN nl2_integrations ON integration_id=nl2_integrations.id WHERE user_id = ?', [$this->data()->id]);
            if ($integrations_query->count()) {
                $integrations_query = $integrations_query->results();

                $integrations_list = [];
                foreach ($integrations_query as $item) {
                    $integration = $integrations->getIntegration($item->integration_name);
                    if ($integration != null) {
                        $integrationUser = new IntegrationUser($integration, $this->data()->id, 'user_id', $item);

                        $integrations_list[$item->integration_name] = $integrationUser;
                    }
                }

                return $integrations_list;
            }

            return [];
        })();
    }

SQL query:
SELECT nl2_groups.* FROM nl2_users_groups INNER JOIN nl2_groups ON group_id = nl2_groups.id WHERE user_id = '9' AND deleted = 0 ORDER BY `order`;
File: /home/padow/Websites/dev/core/classes/Core/User.php
     */
    public function find(string $value = null, string $field = 'id'): bool {
        if ($value) {
            if (isset(self::$_user_cache["$value.$field"])) {
                $cache = self::$_user_cache["$value.$field"];
                $this->_data = $cache['data'];
                $this->_groups = $cache['groups'];
                return true;
            }

            if ($field != 'hash') {
                $data = $this->_db->get('users', [$field, $value]);
            } else {
                $data = $this->_db->query('SELECT nl2_users.* FROM nl2_users LEFT JOIN nl2_users_session ON nl2_users.id = user_id WHERE hash = ? AND nl2_users_session.active = 1', [$value]);
            }

            if ($data->count()) {
                $this->_data = new UserData($data->first());

                // Get user groups
                $groups_query = $this->_db->query('SELECT nl2_groups.* FROM nl2_users_groups INNER JOIN nl2_groups ON group_id = nl2_groups.id WHERE user_id = ? AND deleted = 0 ORDER BY `order`;', [$this->data()->id]);

                if ($groups_query->count()) {

                    $groups_query = $groups_query->results();
                    foreach ($groups_query as $item) {
                        $this->_groups[$item->id] = new Group($item);
                    }

                    self::$_user_cache["$value.$field"] = [
                        'data' => $this->_data,
                        'groups' => $this->_groups,
                    ];

                } else {
                    // Get default group
                    // TODO: Use PRE_VALIDATED_DEFAULT ?
                    $default_group = $this->_db->query('SELECT * FROM nl2_groups WHERE default_group = 1', [])->first();
                    if ($default_group) {
                        $default_group_id = $default_group->id;
                    } else {
SQL query:
SELECT * FROM nl2_users WHERE `id` = '9';
File: /home/padow/Websites/dev/core/classes/Core/User.php

    /**
     * Find a user by unique identifier (username, ID, email, etc).
     * Loads instance variables for this class.
     *
     * @param string|null $value Unique identifier.
     * @param string $field What column to check for their unique identifier in.
     *
     * @return bool True/false on success or failure respectfully.
     */
    public function find(string $value = null, string $field = 'id'): bool {
        if ($value) {
            if (isset(self::$_user_cache["$value.$field"])) {
                $cache = self::$_user_cache["$value.$field"];
                $this->_data = $cache['data'];
                $this->_groups = $cache['groups'];
                return true;
            }

            if ($field != 'hash') {
                $data = $this->_db->get('users', [$field, $value]);
            } else {
                $data = $this->_db->query('SELECT nl2_users.* FROM nl2_users LEFT JOIN nl2_users_session ON nl2_users.id = user_id WHERE hash = ? AND nl2_users_session.active = 1', [$value]);
            }

            if ($data->count()) {
                $this->_data = new UserData($data->first());

                // Get user groups
                $groups_query = $this->_db->query('SELECT nl2_groups.* FROM nl2_users_groups INNER JOIN nl2_groups ON group_id = nl2_groups.id WHERE user_id = ? AND deleted = 0 ORDER BY `order`;', [$this->data()->id]);

                if ($groups_query->count()) {

                    $groups_query = $groups_query->results();
                    foreach ($groups_query as $item) {
                        $this->_groups[$item->id] = new Group($item);
                    }

                    self::$_user_cache["$value.$field"] = [
                        'data' => $this->_data,
                        'groups' => $this->_groups,
SQL query:
SELECT * FROM nl2_users ORDER BY joined DESC;
File: /home/padow/Websites/dev/modules/Core/widgets/StatsWidget.php

        // Set widget variables
        $this->_module = 'Core';
        $this->_name = 'Statistics';
        $this->_location = $widget_query->location;
        $this->_description = 'Displays the basic statistics of your website.';
        $this->_order = $widget_query->order;
    }

    public function initialise(): void {
        $this->_cache->setCache('statistics');

        if ($this->_cache->isCached('statistics')) {

            $users_query = $this->_cache->retrieve('statistics');
            $users_registered = $users_query['users_registered'];
            $latest_member = $users_query['latest_member'];

        } else {

            $users_query = DB::getInstance()->orderAll('users', 'joined', 'DESC')->results();
            $users_registered = count($users_query);

            $latest_user = new User($users_query[0]->id);
            $latest_member = [
                'style' => $latest_user->getGroupStyle(),
                'profile' => $latest_user->getProfileURL(),
                'avatar' => $latest_user->getAvatar(),
                'username' => $latest_user->getDisplayname(true),
                'nickname' => $latest_user->getDisplayname(),
                'id' => Output::getClean($users_query[0]->id)
            ];

            $users_query = null;

            $this->_cache->store(
                'statistics',
                [
                    'users_registered' => $users_registered,
                    'latest_member' => $latest_member
                ],
SQL query:
SELECT U.id FROM nl2_users AS U JOIN nl2_users_groups AS UG ON (U.id = UG.user_id) JOIN nl2_groups AS G ON (UG.group_id = G.id) WHERE G.order = (SELECT min(iG.`order`) FROM nl2_users_groups AS iUG JOIN nl2_groups AS iG ON (iUG.group_id = iG.id) WHERE iUG.user_id = U.id GROUP BY iUG.user_id ORDER BY NULL) AND U.last_online > 1675848639 AND G.staff = 0;
File: /home/padow/Websites/dev/modules/Core/widgets/OnlineUsersWidget.php
        if ($this->_cache->isCached('users')) {
            $online = $this->_cache->retrieve('users');
            $use_nickname_show = $this->_cache->retrieve('show_nickname_instead');
        } else {
            if ($this->_cache->isCached('include_staff_in_users')) {
                $include_staff = $this->_cache->retrieve('include_staff_in_users');
            } else {
                $include_staff = 0;
                $this->_cache->store('include_staff_in_users', 0);
            }
            if ($this->_cache->isCached('show_nickname_instead')) {
                $use_nickname_show = $this->_cache->retrieve('show_nickname_instead');
            } else {
                $use_nickname_show = 0;
                $this->_cache->store('show_nickname_instead', 0);
            }

            if ($include_staff) {
                $online = DB::getInstance()->query('SELECT id FROM nl2_users WHERE last_online > ?', [strtotime('-5 minutes')])->results();
            } else {
                $online = DB::getInstance()->query('SELECT U.id FROM nl2_users AS U JOIN nl2_users_groups AS UG ON (U.id = UG.user_id) JOIN nl2_groups AS G ON (UG.group_id = G.id) WHERE G.order = (SELECT min(iG.`order`) FROM nl2_users_groups AS iUG JOIN nl2_groups AS iG ON (iUG.group_id = iG.id) WHERE iUG.user_id = U.id GROUP BY iUG.user_id ORDER BY NULL) AND U.last_online > ' . strtotime('-5 minutes') . ' AND G.staff = 0', [])->results();
            }

            $this->_cache->store('users', $online, 120);
        }

        // Generate HTML code for widget
        if (count($online)) {
            $users = [];

            foreach ($online as $item) {
                $online_user = new User($item->id);
                $users[] = [
                    'profile' => $online_user->getProfileURL(),
                    'style' => $online_user->getGroupStyle(),
                    'username' => $online_user->getDisplayname(true),
                    'nickname' => $online_user->getDisplayname(),
                    'avatar' => $online_user->getAvatar(),
                    'id' => Output::getClean($online_user->data()->id),
                    'title' => Output::getClean($online_user->data()->user_title),
                    'group' => $online_user->getMainGroup()->group_html
SQL query:
SELECT U.id FROM nl2_users AS U JOIN nl2_users_groups AS UG ON (U.id = UG.user_id) JOIN nl2_groups AS G ON (UG.group_id = G.id) WHERE G.order = (SELECT min(iG.`order`) FROM nl2_users_groups AS iUG JOIN nl2_groups AS iG ON (iUG.group_id = iG.id) WHERE iUG.user_id = U.id GROUP BY iUG.user_id ORDER BY NULL) AND U.last_online > 1675848639 AND G.staff = 1;
File: /home/padow/Websites/dev/modules/Core/widgets/OnlineStaffWidget.php
        $this->_cache = $cache;
        $this->_smarty = $smarty;
        $this->_language = $language;

        parent::__construct(self::parsePages($widget_query));

        // Set widget variables
        $this->_module = 'Core';
        $this->_name = 'Online Staff';
        $this->_location = $widget_query->location;
        $this->_description = 'Displays a list of online staff members on your website.';
        $this->_order = $widget_query->order;
    }

    public function initialise(): void {
        $this->_cache->setCache('online_members');

        if ($this->_cache->isCached('staff')) {
            $online = $this->_cache->retrieve('staff');
        } else {
            $online = DB::getInstance()->query('SELECT U.id FROM nl2_users AS U JOIN nl2_users_groups AS UG ON (U.id = UG.user_id) JOIN nl2_groups AS G ON (UG.group_id = G.id) WHERE G.order = (SELECT min(iG.`order`) FROM nl2_users_groups AS iUG JOIN nl2_groups AS iG ON (iUG.group_id = iG.id) WHERE iUG.user_id = U.id GROUP BY iUG.user_id ORDER BY NULL) AND U.last_online > ' . strtotime('-5 minutes') . ' AND G.staff = 1', [])->results();
            $this->_cache->store('staff', $online, 120);
        }

        // Generate HTML code for widget
        if (count($online)) {
            $staff_members = [];

            foreach ($online as $staff) {
                $staff_user = new User($staff->id);
                $staff_members[] = [
                    'profile' => $staff_user->getProfileURL(),
                    'style' => $staff_user->getGroupStyle(),
                    'username' => $staff_user->getDisplayname(true),
                    'nickname' => $staff_user->getDisplayname(),
                    'avatar' => $staff_user->getAvatar(),
                    'id' => Output::getClean($staff_user->data()->id),
                    'group' => $staff_user->getMainGroup()->group_html,
                    'group_order' => $staff_user->getMainGroup()->order
                ];
            }
SQL query:
SELECT * FROM nl2_tailpad_settings WHERE `id` <> '0';
File: /home/padow/Websites/dev/custom/templates/TailPad/template_settings/classes/PadUtil.php
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
            curl_setopt($ch, CURLOPT_TIMEOUT, 5);
            curl_setopt($ch, CURLOPT_URL, 'https://discordapp.com/api/servers/' . $id . '/widget.json');
            $result = curl_exec($ch);
            $result = json_decode($result);
            curl_close($ch);
            $discord_server = [
                'name' => $result->name,
                'members' => $result->presence_count,
                'link' => $result->instant_invite
            ];
        }
        return $discord_server;
    }
    
    public static function getSettingsToSmarty(): array
    {
        $settings_data = DB::getInstance()->get('tailpad_settings', ['id', '<>', 0])->results();
        $result = [];
        if (count($settings_data)) {
            foreach ($settings_data as $value) {
                $settings_data_array[$value->name] = [
                    'id' => Output::getClean($value->id),
                    'value' => Output::getClean($value->value)
                ];
                $result[strtoupper($value->name)] = htmlspecialchars_decode($settings_data_array[$value->name]['value']);
            }
        }
        return $result;
    }

    public static function updateOrCreateParam($key, $value)
    {
        $array = DB::getInstance()->get('tailpad_settings', ['name', '=', $key])->results();
        $data = end($array);
        if (!empty($data)) {
            DB::getInstance()->update('tailpad_settings', $data->id, [
                'value' => $value
SQL query:
SELECT * FROM nl2_mc_trade_config WHERE `name` = 'link_conf';
File: /home/padow/Websites/dev/modules/McTrade/module.php
    require_once(ROOT_PATH . '/modules/McTrade/widgets/McTradeBalance.php');
    $widgets->add(new McTradeBalance($smarty, $user, $this->_McTradeLanguage));

    require_once(ROOT_PATH . '/modules/McTrade/widgets/McTradeLastBuy.php');
    $widgets->add(new McTradeLastBuy($smarty, $user, $this->_McTradeLanguage));


    if (defined('FRONT_END')) {

      if ($user->isLoggedIn() == 1) {
        $smarty->assign('LOGIN_STATUS', 'Is logged');
      } else {
        $smarty->assign('LOGIN_STATUS', 'No is logged');
      }


      // Link Location

      $trade_title = $this->_McTradeLanguage->get('general', 'mctrade_head_front_end');

      $settings_link = DB::getInstance()->get('mc_trade_config', array('name', '=', 'link_conf'))->results();
      $settings_link = $settings_link['0'];


      if (isset($settings_link) && !empty($settings_link)) {

        $link_order = (int) $settings_link->value_one;
        $icon = $settings_link->value_two;

        if ($settings_link->value == 'footer') {

          $navs[0]->add($this->module_name, $trade_title, URL::build('/shop'), 'footer', null, $link_order, $icon);
        } elseif ($settings_link->value == 'top') {

          $navs[0]->add($this->module_name, $trade_title, URL::build('/shop'), 'top', null, $link_order, $icon);
        } elseif ($settings_link->value == 'dropdown') {

          $navs[0]->addItemToDropdown('more_dropdown', $this->module_name, $trade_title, URL::build('/shop'), 'top', null, $icon);
        } elseif ($settings_link->value == 'no_location') {
        }
      } else {
SQL query:
SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = 'McTradeLastBuy';
File: /home/padow/Websites/dev/core/classes/Widgets/WidgetBase.php
     * Get the display order of this widget.
     *
     * @return int Display order of widget.
     */
    public function getOrder(): ?int {
        return $this->_order;
    }

    /**
     * Generate this widget's `$_content`.
     */
    abstract public function initialise(): void;

    /**
     * Get the data (location, order, pages) for a widget.
     *
     * @param string $name The widget to get data for.
     * @return object|null Widgets data.
     */
    protected static function getData(string $name): ?object {
        return DB::getInstance()->query('SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = ?', [$name])->first();
    }

    /**
     * Parse the widgets JSON pages string into an array.
     *
     * @param object|null $data The widget data to get pages from.
     * @return array The parsed pages array.
     */
    protected static function parsePages(?object $data): array {
        if (isset($data->pages)) {
            return json_decode($data->pages, true) ?? [];
        }
        return [];
    }
}
SQL query:
SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = 'McTradeBalance';
File: /home/padow/Websites/dev/core/classes/Widgets/WidgetBase.php
     * Get the display order of this widget.
     *
     * @return int Display order of widget.
     */
    public function getOrder(): ?int {
        return $this->_order;
    }

    /**
     * Generate this widget's `$_content`.
     */
    abstract public function initialise(): void;

    /**
     * Get the data (location, order, pages) for a widget.
     *
     * @param string $name The widget to get data for.
     * @return object|null Widgets data.
     */
    protected static function getData(string $name): ?object {
        return DB::getInstance()->query('SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = ?', [$name])->first();
    }

    /**
     * Parse the widgets JSON pages string into an array.
     *
     * @param object|null $data The widget data to get pages from.
     * @return array The parsed pages array.
     */
    protected static function parsePages(?object $data): array {
        if (isset($data->pages)) {
            return json_decode($data->pages, true) ?? [];
        }
        return [];
    }
}
SQL query:
SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = 'Latest Posts';
File: /home/padow/Websites/dev/core/classes/Widgets/WidgetBase.php
     * Get the display order of this widget.
     *
     * @return int Display order of widget.
     */
    public function getOrder(): ?int {
        return $this->_order;
    }

    /**
     * Generate this widget's `$_content`.
     */
    abstract public function initialise(): void;

    /**
     * Get the data (location, order, pages) for a widget.
     *
     * @param string $name The widget to get data for.
     * @return object|null Widgets data.
     */
    protected static function getData(string $name): ?object {
        return DB::getInstance()->query('SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = ?', [$name])->first();
    }

    /**
     * Parse the widgets JSON pages string into an array.
     *
     * @param object|null $data The widget data to get pages from.
     * @return array The parsed pages array.
     */
    protected static function parsePages(?object $data): array {
        if (isset($data->pages)) {
            return json_decode($data->pages, true) ?? [];
        }
        return [];
    }
}
SQL query:
SELECT * FROM nl2_mc_servers WHERE `parent_server` = '1';
File: /home/padow/Websites/dev/modules/Core/module.php
        // Check page type (frontend or backend)
        if (defined('FRONT_END')) {
            // Minecraft integration?
            if (defined('MINECRAFT') && MINECRAFT === true) {
                // Query main server
                $cache->setCache('mc_default_server');

                // Already cached?
                if ($cache->isCached('default_query')) {
                    $result = $cache->retrieve('default_query');
                    $default = $cache->retrieve('default');
                } else {
                    if ($cache->isCached('default')) {
                        $default = $cache->retrieve('default');
                        $sub_servers = $cache->retrieve('default_sub');
                    } else {
                        // Get default server from database
                        $default = DB::getInstance()->get('mc_servers', ['is_default', true])->results();
                        if (count($default)) {
                            // Get sub-servers of default server
                            $sub_servers = DB::getInstance()->get('mc_servers', ['parent_server', $default[0]->id])->results();
                            if (count($sub_servers)) {
                                $cache->store('default_sub', $sub_servers);
                            } else {
                                $cache->store('default_sub', []);
                            }

                            $default = $default[0];

                            $cache->store('default', $default, 60);
                        } else {
                            $cache->store('default', null, 60);
                        }
                    }

                    if (!is_null($default) && isset($default->ip)) {
                        $full_ip = ['ip' => $default->ip . (is_null($default->port) ? '' : ':' . $default->port), 'pre' => $default->pre, 'name' => $default->name];

                        // Get query type
                        $query_type = Util::getSetting('external_query') === '1' ? 'external' : 'internal';

SQL query:
SELECT * FROM nl2_mc_servers WHERE `is_default` = '1';
File: /home/padow/Websites/dev/modules/Core/module.php
            $navs[0]->add('leaderboards', $language->get('general', 'leaderboards'), URL::build('/leaderboards'), 'top', null, $leaderboards_order, $leaderboards_icon);
        }

        // Check page type (frontend or backend)
        if (defined('FRONT_END')) {
            // Minecraft integration?
            if (defined('MINECRAFT') && MINECRAFT === true) {
                // Query main server
                $cache->setCache('mc_default_server');

                // Already cached?
                if ($cache->isCached('default_query')) {
                    $result = $cache->retrieve('default_query');
                    $default = $cache->retrieve('default');
                } else {
                    if ($cache->isCached('default')) {
                        $default = $cache->retrieve('default');
                        $sub_servers = $cache->retrieve('default_sub');
                    } else {
                        // Get default server from database
                        $default = DB::getInstance()->get('mc_servers', ['is_default', true])->results();
                        if (count($default)) {
                            // Get sub-servers of default server
                            $sub_servers = DB::getInstance()->get('mc_servers', ['parent_server', $default[0]->id])->results();
                            if (count($sub_servers)) {
                                $cache->store('default_sub', $sub_servers);
                            } else {
                                $cache->store('default_sub', []);
                            }

                            $default = $default[0];

                            $cache->store('default', $default, 60);
                        } else {
                            $cache->store('default', null, 60);
                        }
                    }

                    if (!is_null($default) && isset($default->ip)) {
                        $full_ip = ['ip' => $default->ip . (is_null($default->port) ? '' : ':' . $default->port), 'pre' => $default->pre, 'name' => $default->name];

SQL query:
SELECT * FROM nl2_placeholders_settings WHERE `name` <> '';
File: /home/padow/Websites/dev/core/classes/Misc/Placeholders.php
<?php
/**
 * Manages registering and retrieving PAPI placeholders.
 *
 * @package NamelessMC\Misc
 * @author Aberdeener
 * @version 2.0.0-pr12
 * @license MIT
 */
class Placeholders extends Instanceable {

    private DB $_db;

    private array $_all_placeholders;

    public function __construct() {
        $this->_db = DB::getInstance();

        $placeholders_query = $this->_db->get('placeholders_settings', ['name', '<>', ''])->results();
        $placeholders = [];

        foreach ($placeholders_query as $placeholder) {
            $data = new stdClass();

            $sort = $placeholder->leaderboard_sort;

            if (!in_array($sort, ['ASC', 'DESC'])) {
                $sort = 'DESC';
            }

            $data->server_id = $placeholder->server_id;
            $data->name = $placeholder->name;
            $data->safe_name = sha1($placeholder->name);
            $data->friendly_name = $placeholder->friendly_name ?? $placeholder->name;
            $data->show_on_profile = $placeholder->show_on_profile;
            $data->show_on_forum = $placeholder->show_on_forum;
            $data->leaderboard = $placeholder->leaderboard;
            $data->leaderboard_title = $placeholder->leaderboard_title ?? $data->friendly_name;
            $data->leaderboard_sort = $sort;
SQL query:
SELECT * FROM nl2_groups WHERE `default_group` = '1';
File: /home/padow/Websites/dev/modules/Core/module.php
            $widgets->add(new StatsWidget($smarty, $language, $cache));
        }

        // Validate user hook
        $validate_action = Util::getSetting('validate_user_action');
        $validate_action = json_decode($validate_action, true);

        if ($validate_action['action'] == 'promote') {
            EventHandler::registerListener('validateUser', 'ValidateHook::execute');
            define('VALIDATED_DEFAULT', $validate_action['group']);
        }

        // Define default group pre validation
        $cache->setCache('pre_validation_default');
        $group_id = null;

        if ($cache->isCached('pre_validation_default')) {
            $group_id = $cache->retrieve('pre_validation_default');

        } else {
            $group_id = DB::getInstance()->get('groups', ['default_group', '1'])->results();
            $group_id = $group_id[0]->id;
        }

        define('PRE_VALIDATED_DEFAULT', $group_id);

        // Check for updates
        if ($user->isLoggedIn()) {
            if ((defined('PANEL_PAGE') && PANEL_PAGE !== 'update') && $user->hasPermission('admincp.update')) {
                $cache->setCache('update_check');
                if ($cache->isCached('update_check')) {
                    $update_check = $cache->retrieve('update_check');
                } else {
                    $update_check = Util::updateCheck();
                    $cache->store('update_check', $update_check, 3600);
                }

                if (!is_string($update_check) && $update_check->updateAvailable()) {
                    $smarty->assign([
                        'NEW_UPDATE' => $update_check->isUrgent()
                            ? $language->get('admin', 'new_urgent_update_available')
SQL query:
SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = 'Statistics';
File: /home/padow/Websites/dev/core/classes/Widgets/WidgetBase.php
     * Get the display order of this widget.
     *
     * @return int Display order of widget.
     */
    public function getOrder(): ?int {
        return $this->_order;
    }

    /**
     * Generate this widget's `$_content`.
     */
    abstract public function initialise(): void;

    /**
     * Get the data (location, order, pages) for a widget.
     *
     * @param string $name The widget to get data for.
     * @return object|null Widgets data.
     */
    protected static function getData(string $name): ?object {
        return DB::getInstance()->query('SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = ?', [$name])->first();
    }

    /**
     * Parse the widgets JSON pages string into an array.
     *
     * @param object|null $data The widget data to get pages from.
     * @return array The parsed pages array.
     */
    protected static function parsePages(?object $data): array {
        if (isset($data->pages)) {
            return json_decode($data->pages, true) ?? [];
        }
        return [];
    }
}
SQL query:
SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = 'Server Status';
File: /home/padow/Websites/dev/core/classes/Widgets/WidgetBase.php
     * Get the display order of this widget.
     *
     * @return int Display order of widget.
     */
    public function getOrder(): ?int {
        return $this->_order;
    }

    /**
     * Generate this widget's `$_content`.
     */
    abstract public function initialise(): void;

    /**
     * Get the data (location, order, pages) for a widget.
     *
     * @param string $name The widget to get data for.
     * @return object|null Widgets data.
     */
    protected static function getData(string $name): ?object {
        return DB::getInstance()->query('SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = ?', [$name])->first();
    }

    /**
     * Parse the widgets JSON pages string into an array.
     *
     * @param object|null $data The widget data to get pages from.
     * @return array The parsed pages array.
     */
    protected static function parsePages(?object $data): array {
        if (isset($data->pages)) {
            return json_decode($data->pages, true) ?? [];
        }
        return [];
    }
}
SQL query:
SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = 'Online Users';
File: /home/padow/Websites/dev/core/classes/Widgets/WidgetBase.php
     * Get the display order of this widget.
     *
     * @return int Display order of widget.
     */
    public function getOrder(): ?int {
        return $this->_order;
    }

    /**
     * Generate this widget's `$_content`.
     */
    abstract public function initialise(): void;

    /**
     * Get the data (location, order, pages) for a widget.
     *
     * @param string $name The widget to get data for.
     * @return object|null Widgets data.
     */
    protected static function getData(string $name): ?object {
        return DB::getInstance()->query('SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = ?', [$name])->first();
    }

    /**
     * Parse the widgets JSON pages string into an array.
     *
     * @param object|null $data The widget data to get pages from.
     * @return array The parsed pages array.
     */
    protected static function parsePages(?object $data): array {
        if (isset($data->pages)) {
            return json_decode($data->pages, true) ?? [];
        }
        return [];
    }
}
SQL query:
SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = 'Online Staff';
File: /home/padow/Websites/dev/core/classes/Widgets/WidgetBase.php
     * Get the display order of this widget.
     *
     * @return int Display order of widget.
     */
    public function getOrder(): ?int {
        return $this->_order;
    }

    /**
     * Generate this widget's `$_content`.
     */
    abstract public function initialise(): void;

    /**
     * Get the data (location, order, pages) for a widget.
     *
     * @param string $name The widget to get data for.
     * @return object|null Widgets data.
     */
    protected static function getData(string $name): ?object {
        return DB::getInstance()->query('SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = ?', [$name])->first();
    }

    /**
     * Parse the widgets JSON pages string into an array.
     *
     * @param object|null $data The widget data to get pages from.
     * @return array The parsed pages array.
     */
    protected static function parsePages(?object $data): array {
        if (isset($data->pages)) {
            return json_decode($data->pages, true) ?? [];
        }
        return [];
    }
}
SQL query:
SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = 'Latest Profile Posts';
File: /home/padow/Websites/dev/core/classes/Widgets/WidgetBase.php
     * Get the display order of this widget.
     *
     * @return int Display order of widget.
     */
    public function getOrder(): ?int {
        return $this->_order;
    }

    /**
     * Generate this widget's `$_content`.
     */
    abstract public function initialise(): void;

    /**
     * Get the data (location, order, pages) for a widget.
     *
     * @param string $name The widget to get data for.
     * @return object|null Widgets data.
     */
    protected static function getData(string $name): ?object {
        return DB::getInstance()->query('SELECT `location`, `order`, `pages` FROM nl2_widgets WHERE `name` = ?', [$name])->first();
    }

    /**
     * Parse the widgets JSON pages string into an array.
     *
     * @param object|null $data The widget data to get pages from.
     * @return array The parsed pages array.
     */
    protected static function parsePages(?object $data): array {
        if (isset($data->pages)) {
            return json_decode($data->pages, true) ?? [];
        }
        return [];
    }
}
SQL query:
SELECT nl2_users_integrations.*, nl2_integrations.name as integration_name FROM nl2_users_integrations LEFT JOIN nl2_integrations ON integration_id=nl2_integrations.id WHERE user_id = '1';
File: /home/padow/Websites/dev/core/classes/Core/User.php
    }

    /**
     * Get the user's groups.
     *
     * @return array Their groups.
     */
    public function getGroups(): array {
        return $this->_groups;
    }

    /**
     * Get the user's integrations.
     *
     * @return IntegrationUser[] Their integrations.
     */
    public function getIntegrations(): array {
        return $this->_integrations ??= (function (): array {
            $integrations = Integrations::getInstance();

            $integrations_query = $this->_db->query('SELECT nl2_users_integrations.*, nl2_integrations.name as integration_name FROM nl2_users_integrations LEFT JOIN nl2_integrations ON integration_id=nl2_integrations.id WHERE user_id = ?', [$this->data()->id]);
            if ($integrations_query->count()) {
                $integrations_query = $integrations_query->results();

                $integrations_list = [];
                foreach ($integrations_query as $item) {
                    $integration = $integrations->getIntegration($item->integration_name);
                    if ($integration != null) {
                        $integrationUser = new IntegrationUser($integration, $this->data()->id, 'user_id', $item);

                        $integrations_list[$item->integration_name] = $integrationUser;
                    }
                }

                return $integrations_list;
            }

            return [];
        })();
    }

SQL query:
SELECT nl2_groups.* FROM nl2_users_groups INNER JOIN nl2_groups ON group_id = nl2_groups.id WHERE user_id = '1' AND deleted = 0 ORDER BY `order`;
File: /home/padow/Websites/dev/core/classes/Core/User.php
     */
    public function find(string $value = null, string $field = 'id'): bool {
        if ($value) {
            if (isset(self::$_user_cache["$value.$field"])) {
                $cache = self::$_user_cache["$value.$field"];
                $this->_data = $cache['data'];
                $this->_groups = $cache['groups'];
                return true;
            }

            if ($field != 'hash') {
                $data = $this->_db->get('users', [$field, $value]);
            } else {
                $data = $this->_db->query('SELECT nl2_users.* FROM nl2_users LEFT JOIN nl2_users_session ON nl2_users.id = user_id WHERE hash = ? AND nl2_users_session.active = 1', [$value]);
            }

            if ($data->count()) {
                $this->_data = new UserData($data->first());

                // Get user groups
                $groups_query = $this->_db->query('SELECT nl2_groups.* FROM nl2_users_groups INNER JOIN nl2_groups ON group_id = nl2_groups.id WHERE user_id = ? AND deleted = 0 ORDER BY `order`;', [$this->data()->id]);

                if ($groups_query->count()) {

                    $groups_query = $groups_query->results();
                    foreach ($groups_query as $item) {
                        $this->_groups[$item->id] = new Group($item);
                    }

                    self::$_user_cache["$value.$field"] = [
                        'data' => $this->_data,
                        'groups' => $this->_groups,
                    ];

                } else {
                    // Get default group
                    // TODO: Use PRE_VALIDATED_DEFAULT ?
                    $default_group = $this->_db->query('SELECT * FROM nl2_groups WHERE default_group = 1', [])->first();
                    if ($default_group) {
                        $default_group_id = $default_group->id;
                    } else {
SQL query:
SELECT * FROM nl2_users WHERE `id` = '1';
File: /home/padow/Websites/dev/core/classes/Core/User.php

    /**
     * Find a user by unique identifier (username, ID, email, etc).
     * Loads instance variables for this class.
     *
     * @param string|null $value Unique identifier.
     * @param string $field What column to check for their unique identifier in.
     *
     * @return bool True/false on success or failure respectfully.
     */
    public function find(string $value = null, string $field = 'id'): bool {
        if ($value) {
            if (isset(self::$_user_cache["$value.$field"])) {
                $cache = self::$_user_cache["$value.$field"];
                $this->_data = $cache['data'];
                $this->_groups = $cache['groups'];
                return true;
            }

            if ($field != 'hash') {
                $data = $this->_db->get('users', [$field, $value]);
            } else {
                $data = $this->_db->query('SELECT nl2_users.* FROM nl2_users LEFT JOIN nl2_users_session ON nl2_users.id = user_id WHERE hash = ? AND nl2_users_session.active = 1', [$value]);
            }

            if ($data->count()) {
                $this->_data = new UserData($data->first());

                // Get user groups
                $groups_query = $this->_db->query('SELECT nl2_groups.* FROM nl2_users_groups INNER JOIN nl2_groups ON group_id = nl2_groups.id WHERE user_id = ? AND deleted = 0 ORDER BY `order`;', [$this->data()->id]);

                if ($groups_query->count()) {

                    $groups_query = $groups_query->results();
                    foreach ($groups_query as $item) {
                        $this->_groups[$item->id] = new Group($item);
                    }

                    self::$_user_cache["$value.$field"] = [
                        'data' => $this->_data,
                        'groups' => $this->_groups,
SQL query:
SELECT * FROM nl2_forums WHERE parent = 2 ORDER BY forum_order ASC;
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php

                                if (isset($last_reply) && count($last_reply)) {
                                    $n = 0;
                                    while (isset($last_reply[$n]) && $last_reply[$n]->deleted == 1) {
                                        $n++;
                                    }

                                    if (!isset($last_reply[$n])) {
                                        continue;
                                    }

                                    // Title
                                    $last_topic = $this->_db->get('topics', ['id', $last_reply[$n]->topic_id])->results();

                                    $return[$forum->id]['subforums'][$item->id]->last_post = $last_reply[$n];
                                    $return[$forum->id]['subforums'][$item->id]->last_post->title = Output::getClean($last_topic[0]->topic_title);
                                    $return[$forum->id]['subforums'][$item->id]->last_post->link = URL::build('/forum/topic/' . urlencode($last_reply[$n]->topic_id) . '-' . $this->titleToURL($last_topic[0]->topic_title), 'pid=' . $last_reply[0]->id);
                                }

                                // Get list of subforums (names + links)
                                $subforums = $this->_db->orderWhere('forums', 'parent = ' . $item->id, 'forum_order', 'ASC')->results();
                                if (count($subforums)) {
                                    foreach ($subforums as $subforum) {
                                        if ($this->forumExist($subforum->id, $groups)) {
                                            if (!isset($return[$forum->id]['subforums'][$item->id]->subforums)) {
                                                $return[$forum->id]['subforums'][$item->id]->subforums = [];
                                            }
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id] = new stdClass();
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->title = Output::getClean($subforum->forum_title);
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->link = URL::build('/forum/view/' . urlencode($subforum->id) . '-' . $this->titleToURL($subforum->forum_title));
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->icon = Output::getPurified($subforum->icon);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

SQL query:
SELECT * FROM nl2_topics WHERE `id` = '3';
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
                                } else {
                                    $last_topic = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0 AND topic_creator = ' . $user_id, 'topic_reply_date', 'DESC')->results();
                                    if (count($last_topic)) {
                                        $last_reply = $this->_db->orderWhere('posts', 'topic_id = ' . $last_topic[0]->id, 'created', 'DESC')->results();
                                    } else {
                                        $last_reply = null;
                                    }
                                }

                                if (isset($last_reply) && count($last_reply)) {
                                    $n = 0;
                                    while (isset($last_reply[$n]) && $last_reply[$n]->deleted == 1) {
                                        $n++;
                                    }

                                    if (!isset($last_reply[$n])) {
                                        continue;
                                    }

                                    // Title
                                    $last_topic = $this->_db->get('topics', ['id', $last_reply[$n]->topic_id])->results();

                                    $return[$forum->id]['subforums'][$item->id]->last_post = $last_reply[$n];
                                    $return[$forum->id]['subforums'][$item->id]->last_post->title = Output::getClean($last_topic[0]->topic_title);
                                    $return[$forum->id]['subforums'][$item->id]->last_post->link = URL::build('/forum/topic/' . urlencode($last_reply[$n]->topic_id) . '-' . $this->titleToURL($last_topic[0]->topic_title), 'pid=' . $last_reply[0]->id);
                                }

                                // Get list of subforums (names + links)
                                $subforums = $this->_db->orderWhere('forums', 'parent = ' . $item->id, 'forum_order', 'ASC')->results();
                                if (count($subforums)) {
                                    foreach ($subforums as $subforum) {
                                        if ($this->forumExist($subforum->id, $groups)) {
                                            if (!isset($return[$forum->id]['subforums'][$item->id]->subforums)) {
                                                $return[$forum->id]['subforums'][$item->id]->subforums = [];
                                            }
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id] = new stdClass();
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->title = Output::getClean($subforum->forum_title);
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->link = URL::build('/forum/view/' . urlencode($subforum->id) . '-' . $this->titleToURL($subforum->forum_title));
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->icon = Output::getPurified($subforum->icon);
                                        }
                                    }
SQL query:
SELECT * FROM nl2_posts WHERE topic_id = 3 ORDER BY created DESC;
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
                                $return[$forum->id]['subforums'][$item->id] = $item;
                                $return[$forum->id]['subforums'][$item->id]->forum_title = Output::getClean($item->forum_title);
                                $return[$forum->id]['subforums'][$item->id]->forum_description = Output::getClean($item->forum_description);
                                $return[$forum->id]['subforums'][$item->id]->icon = Output::getPurified($item->icon);
                                $return[$forum->id]['subforums'][$item->id]->link = URL::build('/forum/view/' . urlencode($item->id) . '-' . $this->titleToURL($item->forum_title));
                                $return[$forum->id]['subforums'][$item->id]->redirect_to = Output::getClean($item->redirect_url);

                                // Get topic/post count
                                $topics = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $topics = count($topics);
                                $return[$forum->id]['subforums'][$item->id]->topics = $topics;

                                $posts = $this->_db->orderWhere('posts', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $posts = count($posts);
                                $return[$forum->id]['subforums'][$item->id]->posts = $posts;

                                // Can the user view other topics
                                if ($item->last_user_posted == $user_id || $this->canViewOtherTopics($item->id, $groups)) {
                                    if ($item->last_topic_posted) {
                                        // Last reply
                                        $last_reply = $this->_db->orderWhere('posts', 'topic_id = ' . $item->last_topic_posted, 'created', 'DESC')->results();
                                    } else {
                                        $last_reply = null;
                                    }
                                } else {
                                    $last_topic = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0 AND topic_creator = ' . $user_id, 'topic_reply_date', 'DESC')->results();
                                    if (count($last_topic)) {
                                        $last_reply = $this->_db->orderWhere('posts', 'topic_id = ' . $last_topic[0]->id, 'created', 'DESC')->results();
                                    } else {
                                        $last_reply = null;
                                    }
                                }

                                if (isset($last_reply) && count($last_reply)) {
                                    $n = 0;
                                    while (isset($last_reply[$n]) && $last_reply[$n]->deleted == 1) {
                                        $n++;
                                    }

                                    if (!isset($last_reply[$n])) {
                                        continue;
SQL query:
SELECT * FROM nl2_forums_permissions WHERE `forum_id` = '2';
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
    public function titleToURL(string $topic = null): string {
        if ($topic) {
            $topic = str_replace(self::URL_EXCLUDE_CHARS, '', Util::cyrillicToLatin($topic));
            return Output::getClean(strtolower(urlencode(str_replace(' ', '-', $topic))));
        }

        return '';
    }

    // Returns true/false depending on whether the current user can view a forum
    // Params: $forum_id (integer) - forum id to check, $groups (array) - user groups
    public function canViewOtherTopics(int $forum_id, array $groups = [0]): bool {
        $cache_key = 'topics_view_' . $forum_id . '_' . implode('_', $groups);
        if (isset(self::$_permission_cache[$cache_key])) {
            return true;
        }
        // Does the forum exist?
        $exists = $this->_db->get('forums', ['id', $forum_id])->results();
        if (count($exists)) {
            // Can the user view other topics?
            $access = $this->_db->get('forums_permissions', ['forum_id', $forum_id])->results();

            foreach ($access as $item) {
                if (in_array($item->group_id, $groups)) {
                    if ($item->view_other_topics == 1) {
                        self::$_permission_cache[$cache_key] = true;
                        return true;
                    }
                }
            }
        }

        return false;
    }

    /**
     * Get the newest 50 topics this user/group can view
     *
     * @param array $groups Array of groups the user is in
     * @param int $user_id User ID
     * @return array 50 latest topics
SQL query:
SELECT * FROM nl2_forums WHERE `id` = '2';
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
        return false;
    }

    public function titleToURL(string $topic = null): string {
        if ($topic) {
            $topic = str_replace(self::URL_EXCLUDE_CHARS, '', Util::cyrillicToLatin($topic));
            return Output::getClean(strtolower(urlencode(str_replace(' ', '-', $topic))));
        }

        return '';
    }

    // Returns true/false depending on whether the current user can view a forum
    // Params: $forum_id (integer) - forum id to check, $groups (array) - user groups
    public function canViewOtherTopics(int $forum_id, array $groups = [0]): bool {
        $cache_key = 'topics_view_' . $forum_id . '_' . implode('_', $groups);
        if (isset(self::$_permission_cache[$cache_key])) {
            return true;
        }
        // Does the forum exist?
        $exists = $this->_db->get('forums', ['id', $forum_id])->results();
        if (count($exists)) {
            // Can the user view other topics?
            $access = $this->_db->get('forums_permissions', ['forum_id', $forum_id])->results();

            foreach ($access as $item) {
                if (in_array($item->group_id, $groups)) {
                    if ($item->view_other_topics == 1) {
                        self::$_permission_cache[$cache_key] = true;
                        return true;
                    }
                }
            }
        }

        return false;
    }

    /**
     * Get the newest 50 topics this user/group can view
     *
SQL query:
SELECT * FROM nl2_posts WHERE forum_id = 2 AND deleted = 0 ORDER BY id ASC;
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
                    $return[$forum->id]['title'] = Output::getClean($forum->forum_title);
                    $return[$forum->id]['icon'] = Output::getPurified($forum->icon);

                    // Get subforums
                    $forums = $this->_db->orderWhere('forums', 'parent = ' . $forum->id, 'forum_order', 'ASC')->results();
                    if (count($forums)) {
                        foreach ($forums as $item) {
                            if ($this->forumExist($item->id, $groups)) {
                                $return[$forum->id]['subforums'][$item->id] = $item;
                                $return[$forum->id]['subforums'][$item->id]->forum_title = Output::getClean($item->forum_title);
                                $return[$forum->id]['subforums'][$item->id]->forum_description = Output::getClean($item->forum_description);
                                $return[$forum->id]['subforums'][$item->id]->icon = Output::getPurified($item->icon);
                                $return[$forum->id]['subforums'][$item->id]->link = URL::build('/forum/view/' . urlencode($item->id) . '-' . $this->titleToURL($item->forum_title));
                                $return[$forum->id]['subforums'][$item->id]->redirect_to = Output::getClean($item->redirect_url);

                                // Get topic/post count
                                $topics = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $topics = count($topics);
                                $return[$forum->id]['subforums'][$item->id]->topics = $topics;

                                $posts = $this->_db->orderWhere('posts', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $posts = count($posts);
                                $return[$forum->id]['subforums'][$item->id]->posts = $posts;

                                // Can the user view other topics
                                if ($item->last_user_posted == $user_id || $this->canViewOtherTopics($item->id, $groups)) {
                                    if ($item->last_topic_posted) {
                                        // Last reply
                                        $last_reply = $this->_db->orderWhere('posts', 'topic_id = ' . $item->last_topic_posted, 'created', 'DESC')->results();
                                    } else {
                                        $last_reply = null;
                                    }
                                } else {
                                    $last_topic = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0 AND topic_creator = ' . $user_id, 'topic_reply_date', 'DESC')->results();
                                    if (count($last_topic)) {
                                        $last_reply = $this->_db->orderWhere('posts', 'topic_id = ' . $last_topic[0]->id, 'created', 'DESC')->results();
                                    } else {
                                        $last_reply = null;
                                    }
                                }

SQL query:
SELECT * FROM nl2_topics WHERE forum_id = 2 AND deleted = 0 ORDER BY id ASC;
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
        if (count($parent_forums)) {
            foreach ($parent_forums as $forum) {
                if ($this->forumExist($forum->id, $groups)) {
                    $return[$forum->id]['description'] = Output::getClean($forum->forum_description);
                    $return[$forum->id]['title'] = Output::getClean($forum->forum_title);
                    $return[$forum->id]['icon'] = Output::getPurified($forum->icon);

                    // Get subforums
                    $forums = $this->_db->orderWhere('forums', 'parent = ' . $forum->id, 'forum_order', 'ASC')->results();
                    if (count($forums)) {
                        foreach ($forums as $item) {
                            if ($this->forumExist($item->id, $groups)) {
                                $return[$forum->id]['subforums'][$item->id] = $item;
                                $return[$forum->id]['subforums'][$item->id]->forum_title = Output::getClean($item->forum_title);
                                $return[$forum->id]['subforums'][$item->id]->forum_description = Output::getClean($item->forum_description);
                                $return[$forum->id]['subforums'][$item->id]->icon = Output::getPurified($item->icon);
                                $return[$forum->id]['subforums'][$item->id]->link = URL::build('/forum/view/' . urlencode($item->id) . '-' . $this->titleToURL($item->forum_title));
                                $return[$forum->id]['subforums'][$item->id]->redirect_to = Output::getClean($item->redirect_url);

                                // Get topic/post count
                                $topics = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $topics = count($topics);
                                $return[$forum->id]['subforums'][$item->id]->topics = $topics;

                                $posts = $this->_db->orderWhere('posts', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $posts = count($posts);
                                $return[$forum->id]['subforums'][$item->id]->posts = $posts;

                                // Can the user view other topics
                                if ($item->last_user_posted == $user_id || $this->canViewOtherTopics($item->id, $groups)) {
                                    if ($item->last_topic_posted) {
                                        // Last reply
                                        $last_reply = $this->_db->orderWhere('posts', 'topic_id = ' . $item->last_topic_posted, 'created', 'DESC')->results();
                                    } else {
                                        $last_reply = null;
                                    }
                                } else {
                                    $last_topic = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0 AND topic_creator = ' . $user_id, 'topic_reply_date', 'DESC')->results();
                                    if (count($last_topic)) {
                                        $last_reply = $this->_db->orderWhere('posts', 'topic_id = ' . $last_topic[0]->id, 'created', 'DESC')->results();
                                    } else {
SQL query:
SELECT * FROM nl2_forums_permissions WHERE `forum_id` = '2';
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
        if (count($exists)) {
            return $this->hasPermission($forum_id, 'view', $groups);
        }

        return false;
    }

    /**
     * Determines if any groups have permission to do a certain action on a forum
     *
     * @param int $forum_id ID of the forum
     * @param string $required_permission Required permission
     * @param array $groups Array of groups the user is in
     * @return bool Whether the groups have permission or not
     */
    private function hasPermission(int $forum_id, string $required_permission, array $groups): bool {
        $cache_key = 'forum_permissions_' . $forum_id . '_' . $required_permission . '_' . implode('_', $groups);
        if (isset(self::$_permission_cache[$cache_key])) {
            return true;
        }
        $permissions = $this->_db->get('forums_permissions', ['forum_id', $forum_id])->results();
        foreach ($permissions as $permission) {
            if (in_array($permission->group_id, $groups)) {
                if ($permission->{$required_permission} == 1) {
                    self::$_permission_cache[$cache_key] = true;
                    return true;
                }
            }
        }
        return false;
    }

    public function titleToURL(string $topic = null): string {
        if ($topic) {
            $topic = str_replace(self::URL_EXCLUDE_CHARS, '', Util::cyrillicToLatin($topic));
            return Output::getClean(strtolower(urlencode(str_replace(' ', '-', $topic))));
        }

        return '';
    }

SQL query:
SELECT * FROM nl2_forums WHERE `id` = '2';
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        return $return;
    }

    /**
     * Determine if a forum exists (in the context of a specific user)
     *
     * @param int $forum_id ID of the forum
     * @param array $groups Array of groups the user is in
     * @return bool Whether the forum exists or not
     */
    public function forumExist(int $forum_id, array $groups = [0]): bool {
        $exists = $this->_db->get('forums', ['id', $forum_id])->results();
        if (count($exists)) {
            return $this->hasPermission($forum_id, 'view', $groups);
        }

        return false;
    }

    /**
     * Determines if any groups have permission to do a certain action on a forum
     *
     * @param int $forum_id ID of the forum
     * @param string $required_permission Required permission
     * @param array $groups Array of groups the user is in
     * @return bool Whether the groups have permission or not
     */
    private function hasPermission(int $forum_id, string $required_permission, array $groups): bool {
        $cache_key = 'forum_permissions_' . $forum_id . '_' . $required_permission . '_' . implode('_', $groups);
        if (isset(self::$_permission_cache[$cache_key])) {
            return true;
        }
SQL query:
SELECT * FROM nl2_forums WHERE parent = 1 ORDER BY forum_order ASC;
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
            $user_id = 0;
        }

        if (!$user_id) {
            $user_id = 0;
        }

        // Get a list of parent forums
        $parent_forums = $this->_db->orderWhere('forums', 'parent = 0', 'forum_order', 'ASC')->results();

        $return = [];

        if (count($parent_forums)) {
            foreach ($parent_forums as $forum) {
                if ($this->forumExist($forum->id, $groups)) {
                    $return[$forum->id]['description'] = Output::getClean($forum->forum_description);
                    $return[$forum->id]['title'] = Output::getClean($forum->forum_title);
                    $return[$forum->id]['icon'] = Output::getPurified($forum->icon);

                    // Get subforums
                    $forums = $this->_db->orderWhere('forums', 'parent = ' . $forum->id, 'forum_order', 'ASC')->results();
                    if (count($forums)) {
                        foreach ($forums as $item) {
                            if ($this->forumExist($item->id, $groups)) {
                                $return[$forum->id]['subforums'][$item->id] = $item;
                                $return[$forum->id]['subforums'][$item->id]->forum_title = Output::getClean($item->forum_title);
                                $return[$forum->id]['subforums'][$item->id]->forum_description = Output::getClean($item->forum_description);
                                $return[$forum->id]['subforums'][$item->id]->icon = Output::getPurified($item->icon);
                                $return[$forum->id]['subforums'][$item->id]->link = URL::build('/forum/view/' . urlencode($item->id) . '-' . $this->titleToURL($item->forum_title));
                                $return[$forum->id]['subforums'][$item->id]->redirect_to = Output::getClean($item->redirect_url);

                                // Get topic/post count
                                $topics = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $topics = count($topics);
                                $return[$forum->id]['subforums'][$item->id]->topics = $topics;

                                $posts = $this->_db->orderWhere('posts', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $posts = count($posts);
                                $return[$forum->id]['subforums'][$item->id]->posts = $posts;

                                // Can the user view other topics
SQL query:
SELECT * FROM nl2_forums_permissions WHERE `forum_id` = '1';
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
        if (count($exists)) {
            return $this->hasPermission($forum_id, 'view', $groups);
        }

        return false;
    }

    /**
     * Determines if any groups have permission to do a certain action on a forum
     *
     * @param int $forum_id ID of the forum
     * @param string $required_permission Required permission
     * @param array $groups Array of groups the user is in
     * @return bool Whether the groups have permission or not
     */
    private function hasPermission(int $forum_id, string $required_permission, array $groups): bool {
        $cache_key = 'forum_permissions_' . $forum_id . '_' . $required_permission . '_' . implode('_', $groups);
        if (isset(self::$_permission_cache[$cache_key])) {
            return true;
        }
        $permissions = $this->_db->get('forums_permissions', ['forum_id', $forum_id])->results();
        foreach ($permissions as $permission) {
            if (in_array($permission->group_id, $groups)) {
                if ($permission->{$required_permission} == 1) {
                    self::$_permission_cache[$cache_key] = true;
                    return true;
                }
            }
        }
        return false;
    }

    public function titleToURL(string $topic = null): string {
        if ($topic) {
            $topic = str_replace(self::URL_EXCLUDE_CHARS, '', Util::cyrillicToLatin($topic));
            return Output::getClean(strtolower(urlencode(str_replace(' ', '-', $topic))));
        }

        return '';
    }

SQL query:
SELECT * FROM nl2_forums WHERE `id` = '1';
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        return $return;
    }

    /**
     * Determine if a forum exists (in the context of a specific user)
     *
     * @param int $forum_id ID of the forum
     * @param array $groups Array of groups the user is in
     * @return bool Whether the forum exists or not
     */
    public function forumExist(int $forum_id, array $groups = [0]): bool {
        $exists = $this->_db->get('forums', ['id', $forum_id])->results();
        if (count($exists)) {
            return $this->hasPermission($forum_id, 'view', $groups);
        }

        return false;
    }

    /**
     * Determines if any groups have permission to do a certain action on a forum
     *
     * @param int $forum_id ID of the forum
     * @param string $required_permission Required permission
     * @param array $groups Array of groups the user is in
     * @return bool Whether the groups have permission or not
     */
    private function hasPermission(int $forum_id, string $required_permission, array $groups): bool {
        $cache_key = 'forum_permissions_' . $forum_id . '_' . $required_permission . '_' . implode('_', $groups);
        if (isset(self::$_permission_cache[$cache_key])) {
            return true;
        }
SQL query:
SELECT * FROM nl2_forums WHERE parent = 4 ORDER BY forum_order ASC;
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php

                                if (isset($last_reply) && count($last_reply)) {
                                    $n = 0;
                                    while (isset($last_reply[$n]) && $last_reply[$n]->deleted == 1) {
                                        $n++;
                                    }

                                    if (!isset($last_reply[$n])) {
                                        continue;
                                    }

                                    // Title
                                    $last_topic = $this->_db->get('topics', ['id', $last_reply[$n]->topic_id])->results();

                                    $return[$forum->id]['subforums'][$item->id]->last_post = $last_reply[$n];
                                    $return[$forum->id]['subforums'][$item->id]->last_post->title = Output::getClean($last_topic[0]->topic_title);
                                    $return[$forum->id]['subforums'][$item->id]->last_post->link = URL::build('/forum/topic/' . urlencode($last_reply[$n]->topic_id) . '-' . $this->titleToURL($last_topic[0]->topic_title), 'pid=' . $last_reply[0]->id);
                                }

                                // Get list of subforums (names + links)
                                $subforums = $this->_db->orderWhere('forums', 'parent = ' . $item->id, 'forum_order', 'ASC')->results();
                                if (count($subforums)) {
                                    foreach ($subforums as $subforum) {
                                        if ($this->forumExist($subforum->id, $groups)) {
                                            if (!isset($return[$forum->id]['subforums'][$item->id]->subforums)) {
                                                $return[$forum->id]['subforums'][$item->id]->subforums = [];
                                            }
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id] = new stdClass();
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->title = Output::getClean($subforum->forum_title);
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->link = URL::build('/forum/view/' . urlencode($subforum->id) . '-' . $this->titleToURL($subforum->forum_title));
                                            $return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->icon = Output::getPurified($subforum->icon);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

SQL query:
SELECT * FROM nl2_posts WHERE forum_id = 4 AND deleted = 0 ORDER BY id ASC;
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
                    $return[$forum->id]['title'] = Output::getClean($forum->forum_title);
                    $return[$forum->id]['icon'] = Output::getPurified($forum->icon);

                    // Get subforums
                    $forums = $this->_db->orderWhere('forums', 'parent = ' . $forum->id, 'forum_order', 'ASC')->results();
                    if (count($forums)) {
                        foreach ($forums as $item) {
                            if ($this->forumExist($item->id, $groups)) {
                                $return[$forum->id]['subforums'][$item->id] = $item;
                                $return[$forum->id]['subforums'][$item->id]->forum_title = Output::getClean($item->forum_title);
                                $return[$forum->id]['subforums'][$item->id]->forum_description = Output::getClean($item->forum_description);
                                $return[$forum->id]['subforums'][$item->id]->icon = Output::getPurified($item->icon);
                                $return[$forum->id]['subforums'][$item->id]->link = URL::build('/forum/view/' . urlencode($item->id) . '-' . $this->titleToURL($item->forum_title));
                                $return[$forum->id]['subforums'][$item->id]->redirect_to = Output::getClean($item->redirect_url);

                                // Get topic/post count
                                $topics = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $topics = count($topics);
                                $return[$forum->id]['subforums'][$item->id]->topics = $topics;

                                $posts = $this->_db->orderWhere('posts', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $posts = count($posts);
                                $return[$forum->id]['subforums'][$item->id]->posts = $posts;

                                // Can the user view other topics
                                if ($item->last_user_posted == $user_id || $this->canViewOtherTopics($item->id, $groups)) {
                                    if ($item->last_topic_posted) {
                                        // Last reply
                                        $last_reply = $this->_db->orderWhere('posts', 'topic_id = ' . $item->last_topic_posted, 'created', 'DESC')->results();
                                    } else {
                                        $last_reply = null;
                                    }
                                } else {
                                    $last_topic = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0 AND topic_creator = ' . $user_id, 'topic_reply_date', 'DESC')->results();
                                    if (count($last_topic)) {
                                        $last_reply = $this->_db->orderWhere('posts', 'topic_id = ' . $last_topic[0]->id, 'created', 'DESC')->results();
                                    } else {
                                        $last_reply = null;
                                    }
                                }

SQL query:
SELECT * FROM nl2_topics WHERE forum_id = 4 AND deleted = 0 ORDER BY id ASC;
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
        if (count($parent_forums)) {
            foreach ($parent_forums as $forum) {
                if ($this->forumExist($forum->id, $groups)) {
                    $return[$forum->id]['description'] = Output::getClean($forum->forum_description);
                    $return[$forum->id]['title'] = Output::getClean($forum->forum_title);
                    $return[$forum->id]['icon'] = Output::getPurified($forum->icon);

                    // Get subforums
                    $forums = $this->_db->orderWhere('forums', 'parent = ' . $forum->id, 'forum_order', 'ASC')->results();
                    if (count($forums)) {
                        foreach ($forums as $item) {
                            if ($this->forumExist($item->id, $groups)) {
                                $return[$forum->id]['subforums'][$item->id] = $item;
                                $return[$forum->id]['subforums'][$item->id]->forum_title = Output::getClean($item->forum_title);
                                $return[$forum->id]['subforums'][$item->id]->forum_description = Output::getClean($item->forum_description);
                                $return[$forum->id]['subforums'][$item->id]->icon = Output::getPurified($item->icon);
                                $return[$forum->id]['subforums'][$item->id]->link = URL::build('/forum/view/' . urlencode($item->id) . '-' . $this->titleToURL($item->forum_title));
                                $return[$forum->id]['subforums'][$item->id]->redirect_to = Output::getClean($item->redirect_url);

                                // Get topic/post count
                                $topics = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $topics = count($topics);
                                $return[$forum->id]['subforums'][$item->id]->topics = $topics;

                                $posts = $this->_db->orderWhere('posts', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $posts = count($posts);
                                $return[$forum->id]['subforums'][$item->id]->posts = $posts;

                                // Can the user view other topics
                                if ($item->last_user_posted == $user_id || $this->canViewOtherTopics($item->id, $groups)) {
                                    if ($item->last_topic_posted) {
                                        // Last reply
                                        $last_reply = $this->_db->orderWhere('posts', 'topic_id = ' . $item->last_topic_posted, 'created', 'DESC')->results();
                                    } else {
                                        $last_reply = null;
                                    }
                                } else {
                                    $last_topic = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0 AND topic_creator = ' . $user_id, 'topic_reply_date', 'DESC')->results();
                                    if (count($last_topic)) {
                                        $last_reply = $this->_db->orderWhere('posts', 'topic_id = ' . $last_topic[0]->id, 'created', 'DESC')->results();
                                    } else {
SQL query:
SELECT * FROM nl2_forums_permissions WHERE `forum_id` = '4';
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
        if (count($exists)) {
            return $this->hasPermission($forum_id, 'view', $groups);
        }

        return false;
    }

    /**
     * Determines if any groups have permission to do a certain action on a forum
     *
     * @param int $forum_id ID of the forum
     * @param string $required_permission Required permission
     * @param array $groups Array of groups the user is in
     * @return bool Whether the groups have permission or not
     */
    private function hasPermission(int $forum_id, string $required_permission, array $groups): bool {
        $cache_key = 'forum_permissions_' . $forum_id . '_' . $required_permission . '_' . implode('_', $groups);
        if (isset(self::$_permission_cache[$cache_key])) {
            return true;
        }
        $permissions = $this->_db->get('forums_permissions', ['forum_id', $forum_id])->results();
        foreach ($permissions as $permission) {
            if (in_array($permission->group_id, $groups)) {
                if ($permission->{$required_permission} == 1) {
                    self::$_permission_cache[$cache_key] = true;
                    return true;
                }
            }
        }
        return false;
    }

    public function titleToURL(string $topic = null): string {
        if ($topic) {
            $topic = str_replace(self::URL_EXCLUDE_CHARS, '', Util::cyrillicToLatin($topic));
            return Output::getClean(strtolower(urlencode(str_replace(' ', '-', $topic))));
        }

        return '';
    }

SQL query:
SELECT * FROM nl2_forums WHERE `id` = '4';
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        return $return;
    }

    /**
     * Determine if a forum exists (in the context of a specific user)
     *
     * @param int $forum_id ID of the forum
     * @param array $groups Array of groups the user is in
     * @return bool Whether the forum exists or not
     */
    public function forumExist(int $forum_id, array $groups = [0]): bool {
        $exists = $this->_db->get('forums', ['id', $forum_id])->results();
        if (count($exists)) {
            return $this->hasPermission($forum_id, 'view', $groups);
        }

        return false;
    }

    /**
     * Determines if any groups have permission to do a certain action on a forum
     *
     * @param int $forum_id ID of the forum
     * @param string $required_permission Required permission
     * @param array $groups Array of groups the user is in
     * @return bool Whether the groups have permission or not
     */
    private function hasPermission(int $forum_id, string $required_permission, array $groups): bool {
        $cache_key = 'forum_permissions_' . $forum_id . '_' . $required_permission . '_' . implode('_', $groups);
        if (isset(self::$_permission_cache[$cache_key])) {
            return true;
        }
SQL query:
SELECT * FROM nl2_forums WHERE parent = 3 ORDER BY forum_order ASC;
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
            $user_id = 0;
        }

        if (!$user_id) {
            $user_id = 0;
        }

        // Get a list of parent forums
        $parent_forums = $this->_db->orderWhere('forums', 'parent = 0', 'forum_order', 'ASC')->results();

        $return = [];

        if (count($parent_forums)) {
            foreach ($parent_forums as $forum) {
                if ($this->forumExist($forum->id, $groups)) {
                    $return[$forum->id]['description'] = Output::getClean($forum->forum_description);
                    $return[$forum->id]['title'] = Output::getClean($forum->forum_title);
                    $return[$forum->id]['icon'] = Output::getPurified($forum->icon);

                    // Get subforums
                    $forums = $this->_db->orderWhere('forums', 'parent = ' . $forum->id, 'forum_order', 'ASC')->results();
                    if (count($forums)) {
                        foreach ($forums as $item) {
                            if ($this->forumExist($item->id, $groups)) {
                                $return[$forum->id]['subforums'][$item->id] = $item;
                                $return[$forum->id]['subforums'][$item->id]->forum_title = Output::getClean($item->forum_title);
                                $return[$forum->id]['subforums'][$item->id]->forum_description = Output::getClean($item->forum_description);
                                $return[$forum->id]['subforums'][$item->id]->icon = Output::getPurified($item->icon);
                                $return[$forum->id]['subforums'][$item->id]->link = URL::build('/forum/view/' . urlencode($item->id) . '-' . $this->titleToURL($item->forum_title));
                                $return[$forum->id]['subforums'][$item->id]->redirect_to = Output::getClean($item->redirect_url);

                                // Get topic/post count
                                $topics = $this->_db->orderWhere('topics', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $topics = count($topics);
                                $return[$forum->id]['subforums'][$item->id]->topics = $topics;

                                $posts = $this->_db->orderWhere('posts', 'forum_id = ' . $item->id . ' AND deleted = 0', 'id', 'ASC')->results();
                                $posts = count($posts);
                                $return[$forum->id]['subforums'][$item->id]->posts = $posts;

                                // Can the user view other topics
SQL query:
SELECT * FROM nl2_forums_permissions WHERE `forum_id` = '3';
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
        if (count($exists)) {
            return $this->hasPermission($forum_id, 'view', $groups);
        }

        return false;
    }

    /**
     * Determines if any groups have permission to do a certain action on a forum
     *
     * @param int $forum_id ID of the forum
     * @param string $required_permission Required permission
     * @param array $groups Array of groups the user is in
     * @return bool Whether the groups have permission or not
     */
    private function hasPermission(int $forum_id, string $required_permission, array $groups): bool {
        $cache_key = 'forum_permissions_' . $forum_id . '_' . $required_permission . '_' . implode('_', $groups);
        if (isset(self::$_permission_cache[$cache_key])) {
            return true;
        }
        $permissions = $this->_db->get('forums_permissions', ['forum_id', $forum_id])->results();
        foreach ($permissions as $permission) {
            if (in_array($permission->group_id, $groups)) {
                if ($permission->{$required_permission} == 1) {
                    self::$_permission_cache[$cache_key] = true;
                    return true;
                }
            }
        }
        return false;
    }

    public function titleToURL(string $topic = null): string {
        if ($topic) {
            $topic = str_replace(self::URL_EXCLUDE_CHARS, '', Util::cyrillicToLatin($topic));
            return Output::getClean(strtolower(urlencode(str_replace(' ', '-', $topic))));
        }

        return '';
    }

SQL query:
SELECT * FROM nl2_forums WHERE `id` = '3';
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        return $return;
    }

    /**
     * Determine if a forum exists (in the context of a specific user)
     *
     * @param int $forum_id ID of the forum
     * @param array $groups Array of groups the user is in
     * @return bool Whether the forum exists or not
     */
    public function forumExist(int $forum_id, array $groups = [0]): bool {
        $exists = $this->_db->get('forums', ['id', $forum_id])->results();
        if (count($exists)) {
            return $this->hasPermission($forum_id, 'view', $groups);
        }

        return false;
    }

    /**
     * Determines if any groups have permission to do a certain action on a forum
     *
     * @param int $forum_id ID of the forum
     * @param string $required_permission Required permission
     * @param array $groups Array of groups the user is in
     * @return bool Whether the groups have permission or not
     */
    private function hasPermission(int $forum_id, string $required_permission, array $groups): bool {
        $cache_key = 'forum_permissions_' . $forum_id . '_' . $required_permission . '_' . implode('_', $groups);
        if (isset(self::$_permission_cache[$cache_key])) {
            return true;
        }
SQL query:
SELECT * FROM nl2_forums WHERE parent = 0 ORDER BY forum_order ASC;
File: /home/padow/Websites/dev/modules/Forum/classes/Forum.php
        $this->_db = DB::getInstance();
    }

    /**
     * Get an array of forums a user can access, including topic information
     *
     * @param array $groups Users groups
     * @param int $user_id User ID
     * @return array Array of forums a user can access
     */
    public function listAllForums(array $groups = [0], int $user_id = 0): array {
        if (in_array(0, $groups)) {
            $user_id = 0;
        }

        if (!$user_id) {
            $user_id = 0;
        }

        // Get a list of parent forums
        $parent_forums = $this->_db->orderWhere('forums', 'parent = 0', 'forum_order', 'ASC')->results();

        $return = [];

        if (count($parent_forums)) {
            foreach ($parent_forums as $forum) {
                if ($this->forumExist($forum->id, $groups)) {
                    $return[$forum->id]['description'] = Output::getClean($forum->forum_description);
                    $return[$forum->id]['title'] = Output::getClean($forum->forum_title);
                    $return[$forum->id]['icon'] = Output::getPurified($forum->icon);

                    // Get subforums
                    $forums = $this->_db->orderWhere('forums', 'parent = ' . $forum->id, 'forum_order', 'ASC')->results();
                    if (count($forums)) {
                        foreach ($forums as $item) {
                            if ($this->forumExist($item->id, $groups)) {
                                $return[$forum->id]['subforums'][$item->id] = $item;
                                $return[$forum->id]['subforums'][$item->id]->forum_title = Output::getClean($item->forum_title);
                                $return[$forum->id]['subforums'][$item->id]->forum_description = Output::getClean($item->forum_description);
                                $return[$forum->id]['subforums'][$item->id]->icon = Output::getPurified($item->icon);
                                $return[$forum->id]['subforums'][$item->id]->link = URL::build('/forum/view/' . urlencode($item->id) . '-' . $this->titleToURL($item->forum_title));
SQL query:
SELECT * FROM nl2_page_descriptions WHERE `page` = '/forum';
File: /home/padow/Websites/dev/core/templates/frontend_init.php
        $default_group = $cache->retrieve('default_group');
    } else {
        try {
            $default_group = Group::find(1, 'default_group')->id;
        } catch (Exception $e) {
            $default_group = 1;
        }

        $cache->store('default_group', $default_group);
    }
}

// Page metadata
if (isset($_GET['route']) && $_GET['route'] != '/') {
    $route = rtrim($_GET['route'], '/');
} else {
    $route = '/';
}

if (!defined('PAGE_DESCRIPTION')) {
    $page_metadata = DB::getInstance()->get('page_descriptions', ['page', $route])->results();
    if (count($page_metadata)) {
        $smarty->assign([
            'PAGE_DESCRIPTION' => str_replace('{site}', Output::getClean(SITE_NAME), $page_metadata[0]->description),
            'PAGE_KEYWORDS' => $page_metadata[0]->tags
        ]);
    }
} else {
    $smarty->assign([
        'PAGE_DESCRIPTION' => str_replace('{site}', Output::getClean(SITE_NAME), PAGE_DESCRIPTION),
        'PAGE_KEYWORDS' => (defined('PAGE_KEYWORDS') ? PAGE_KEYWORDS : '')
    ]);
}

$smarty->assign('TITLE', $page_title);

$cache->setCache('backgroundcache');

$banner_image = $cache->retrieve('banner_image');

if (!empty($banner_image)) {
SQL query:
SHOW TABLES LIKE 'nl2_tailpad_settings';
File: /home/padow/Websites/dev/custom/templates/TailPad/template_settings/classes/PadUtil.php
    }

    public static function updateOrCreateParam($key, $value)
    {
        $array = DB::getInstance()->get('tailpad_settings', ['name', '=', $key])->results();
        $data = end($array);
        if (!empty($data)) {
            DB::getInstance()->update('tailpad_settings', $data->id, [
                'value' => $value
            ]);
        } else {
            DB::getInstance()->insert('tailpad_settings', [
                'name' => $key,
                'value' => $value
            ]);
        }
    }

    public static function initialise()
    {
        if (DB::getInstance()->showTables('tailpad_settings')) {
            return;
        }

        try {
            $group = DB::getInstance()->get('groups', ['id', '=', 2])->results();
            $group = $group[0];
            $group_permissions = json_decode($group->permissions, TRUE);
            $group_permissions['admincp.tailpad'] = 1;
            $group_permissions = json_encode($group_permissions);
            DB::getInstance()->update('groups', 2, ['permissions' => $group_permissions]);
        } catch (Exception $e) {
            // Error
        }
        try {
            $engine = Config::get('mysql/engine');
            $charset = Config::get('mysql/charset');
        } catch (Exception $e) {
            $engine = 'InnoDB';
            $charset = 'utf8mb4';
        }
SQL query:
UPDATE nl2_online_guests SET `last_seen` = '1097' WHERE `id` =;
File: /home/padow/Websites/dev/core/init.php
            'user_title' => Output::getClean($user->data()->user_title),
            'avatar' => $user->getAvatar(),
            'integrations' => $user_integrations
        ]);

        // Panel access?
        if ($user->canViewStaffCP()) {
            $smarty->assign([
                'PANEL_LINK' => URL::build('/panel'),
                'PANEL' => $language->get('moderator', 'staff_cp')
            ]);
        }
    } else {
        // Perform tasks for guests
        if (!$_SESSION['checked'] || (isset($_SESSION['checked']) && $_SESSION['checked'] <= strtotime('-5 minutes'))) {
            $already_online = DB::getInstance()->get('online_guests', ['ip', $ip])->results();

            $date = date('U');

            if (count($already_online)) {
                DB::getInstance()->update('online_guests', $already_online[0]->id, ['last_seen' => $date]);
            } else {
                DB::getInstance()->insert('online_guests', ['ip' => $ip, 'last_seen' => $date]);
            }

            $_SESSION['checked'] = $date;
        }
    }

    // Dark mode
    $cache->setCache('template_settings');
    $darkMode = $cache->isCached('darkMode') ? $cache->retrieve('darkMode') : '0';
    if ($user->isLoggedIn()) {
        $darkMode = $user->data()->night_mode !== null ? $user->data()->night_mode : $darkMode;
    } else {
        if (Cookie::exists('night_mode')) {
            $darkMode = Cookie::get('night_mode');
        }
    }

    define('DARK_MODE', $darkMode);
SQL query:
SELECT * FROM nl2_online_guests WHERE `ip` = '3.214.216.26';
File: /home/padow/Websites/dev/core/init.php
            'username' => $user->getDisplayname(true),
            'nickname' => $user->getDisplayname(),
            'profile' => $user->getProfileURL(),
            'panel_profile' => URL::build('/panel/user/' . urlencode($user->data()->id) . '-' . urlencode($user->data()->username)),
            'username_style' => $user->getGroupStyle(),
            'user_title' => Output::getClean($user->data()->user_title),
            'avatar' => $user->getAvatar(),
            'integrations' => $user_integrations
        ]);

        // Panel access?
        if ($user->canViewStaffCP()) {
            $smarty->assign([
                'PANEL_LINK' => URL::build('/panel'),
                'PANEL' => $language->get('moderator', 'staff_cp')
            ]);
        }
    } else {
        // Perform tasks for guests
        if (!$_SESSION['checked'] || (isset($_SESSION['checked']) && $_SESSION['checked'] <= strtotime('-5 minutes'))) {
            $already_online = DB::getInstance()->get('online_guests', ['ip', $ip])->results();

            $date = date('U');

            if (count($already_online)) {
                DB::getInstance()->update('online_guests', $already_online[0]->id, ['last_seen' => $date]);
            } else {
                DB::getInstance()->insert('online_guests', ['ip' => $ip, 'last_seen' => $date]);
            }

            $_SESSION['checked'] = $date;
        }
    }

    // Dark mode
    $cache->setCache('template_settings');
    $darkMode = $cache->isCached('darkMode') ? $cache->retrieve('darkMode') : '0';
    if ($user->isLoggedIn()) {
        $darkMode = $user->data()->night_mode !== null ? $user->data()->night_mode : $darkMode;
    } else {
        if (Cookie::exists('night_mode')) {
SQL query:
SELECT * FROM nl2_integrations WHERE name = 'Minecraft';
File: /home/padow/Websites/dev/core/classes/Integrations/IntegrationBase.php
 * @package NamelessMC\Integrations
 * @author Partydragen
 * @version 2.0.0-pr13
 * @license MIT
 */

abstract class IntegrationBase {

    private DB $_db;
    private IntegrationData $_data;
    protected string $_icon;
    private array $_errors = [];
    protected Language $_language;

    protected string $_name;
    protected ?int $_order;

    public function __construct() {
        $this->_db = DB::getInstance();

        $integration = $this->_db->query('SELECT * FROM nl2_integrations WHERE name = ?', [$this->_name]);
        if ($integration->count()) {
            $integration = $integration->first();

            $this->_data = new IntegrationData($integration);
            $this->_order = $integration->order;
        } else {
            // Register integration to database
            $this->_db->query('INSERT INTO nl2_integrations (name) VALUES (?)', [
                $this->_name
            ]);

            $integration = $this->_db->query('SELECT * FROM nl2_integrations WHERE name = ?', [$this->_name])->first();

            $this->_data = new IntegrationData($integration);
            $this->_order = $integration->order;
        }
    }

    /**
     * Get the name of this integration.
SQL query:
SELECT * FROM nl2_custom_pages_permissions WHERE `group_id` = '0';
File: /home/padow/Websites/dev/modules/Core/module.php
                                                $navigation->add(
                                                    $custom_page->id,
                                                    Output::getClean($custom_page->title),
                                                    (is_null($redirect)) ? URL::build(Output::urlEncodeAllowSlashes($custom_page->url)) : $redirect,
                                                    'footer', $custom_page->target ? '_blank' : null,
                                                    2000,
                                                    $custom_page->icon
                                                );
                                                break;
                                        }
                                        break 2;
                                    }

                                    break;
                                }
                            }
                        }
                    }
                }
            } else {
                $custom_page_permissions = DB::getInstance()->get('custom_pages_permissions', ['group_id', 0])->results();
                if (count($custom_page_permissions)) {
                    foreach ($custom_pages as $custom_page) {
                        $redirect = null;

                        if ($custom_page->redirect == 1) {
                            $redirect = Output::getClean($custom_page->link);
                        }

                        $pages->addCustom(Output::urlEncodeAllowSlashes($custom_page->url), Output::getClean($custom_page->title), !$custom_page->basic);

                        foreach ($custom_page_permissions as $permission) {
                            if ($permission->page_id == $custom_page->id) {
                                if ($permission->view == 1) {
                                    // Check cache for order
                                    if (!$cache->isCached($custom_page->id . '_order')) {
                                        // Create cache entry now
                                        $page_order = 200;
                                        $cache->store($custom_page->id . '_order', 200);
                                    } else {
                                        $page_order = $cache->retrieve($custom_page->id . '_order');
SQL query:
SELECT * FROM nl2_custom_pages WHERE `id` <> '0';
File: /home/padow/Websites/dev/modules/Core/module.php
        $pages->addAjaxScript(URL::build('/queries/servers'));

        // "More" dropdown
        $cache->setCache('navbar_icons');
        if ($cache->isCached('more_dropdown_icon')) {
            $icon = $cache->retrieve('more_dropdown_icon');
        } else {
            $icon = '';
        }

        $cache->setCache('navbar_order');
        if ($cache->isCached('more_dropdown_order')) {
            $order = $cache->retrieve('more_dropdown_order');
        } else {
            $order = 2500;
        }

        $navigation->addDropdown('more_dropdown', $language->get('general', 'more'), 'top', $order, $icon);

        // Custom pages
        $custom_pages = DB::getInstance()->get('custom_pages', ['id', '<>', 0])->results();
        if (count($custom_pages)) {
            $more = [];
            $cache->setCache('navbar_order');

            if ($user->isLoggedIn()) {
                // Check all groups
                $user_groups = $user->getAllGroupIds();

                foreach ($custom_pages as $custom_page) {
                    $redirect = null;

                    // Get redirect URL if enabled
                    if ($custom_page->redirect == 1) {
                        $redirect = $custom_page->link;
                    }

                    $pages->addCustom(Output::urlEncodeAllowSlashes($custom_page->url), Output::getClean($custom_page->title), !$custom_page->basic);

                    foreach ($user_groups as $user_group) {
                        $custom_page_permissions = DB::getInstance()->get('custom_pages_permissions', ['group_id', $user_group])->results();
SQL query:
SELECT `name`, `value` FROM `nl2_settings` WHERE `module` IS NULL;
File: /home/padow/Websites/dev/core/classes/Core/Util.php
    private static function setSettingsCache(?string $module, array $cache): void {
        $cache_name = $module !== null ? $module : 'core';
        self::$_cached_settings[$cache_name] = $cache;
    }

    /**
     * Get a setting from the database table `nl2_settings`.
     *
     * @param string $setting Setting to check.
     * @param ?string $fallback Fallback to return if $setting is not set in DB. Defaults to null.
     * @param string $module Module name to keep settings separate from other modules. Set module
     *                       to 'Core' for global settings.
     * @return ?string Setting from DB or $fallback.
     */
    public static function getSetting(string $setting, ?string $fallback = null, string $module = 'core'): ?string {
        $cache = self::getSettingsCache($module);

        if ($cache === null) {
            // Load all settings for this module and store it as a dictionary
            if ($module === 'core') {
                $result = DB::getInstance()->query('SELECT `name`, `value` FROM `nl2_settings` WHERE `module` IS NULL')->results();
            } else {
                $result = DB::getInstance()->query('SELECT `name`, `value` FROM `nl2_settings` WHERE `module` = ?', [$module])->results();
            }

            $cache = [];
            foreach ($result as $row) {
                $cache[$row->name] = $row->value;
            }
            self::setSettingsCache($module, $cache);
        }

        return $cache[$setting] ?? $fallback;
    }

    /**
     * Modify a setting in the database table `nl2_settings`.
     *
     * @param string $setting Setting name.
     * @param string|null $new_value New setting value, or null to delete
     * @param string $module Module name to keep settings separate from other modules. Set module
SQL query:
SELECT version, migration_name FROM nl2_phinxlog;
File: /home/padow/Websites/dev/core/classes/Database/PhinxAdapter.php
    /**
     * Checks the number of existing migration files compared to executed migrations in the database.
     * Alternatively we could check the output of a Phinx command, but that takes ~8x as long to execute.
     *
     * @throws RuntimeException If these numbers don't match.
     */
    public static function ensureUpToDate(): void {
        $migration_files = array_map(
            static function ($file_name) {
                [$version, $migration_name] = explode('_', $file_name, 2);
                $migration_name = str_replace(['.php', '_'], '', ucwords($migration_name, '_'));
                return $version . '_' . $migration_name;
            },
            array_filter(scandir(__DIR__ . '/../../migrations'), static function ($file_name) {
                return !in_array($file_name, ['.', '..', 'phinx.php']);
            }),
        );

        $migration_database_entries = array_map(static function ($row) {
            return $row->version . '_' . $row->migration_name;
        }, DB::getInstance()->query('SELECT version, migration_name FROM nl2_phinxlog')->results());

        $missing = array_diff($migration_files, $migration_database_entries);
        $extra = array_diff($migration_database_entries, $migration_files);

        // Likely a pull from the repo dev branch or migrations
        // weren't run during an upgrade script.
        if (($missing_count = count($missing)) > 0) {
            echo "There are $missing_count migrations files which have not been executed:" . '<br>';
            foreach ($missing as $missing_migration) {
                echo " - $missing_migration" . '<br>';
            }
        }

        // Something went wonky, either they've deleted migration files,
        // or they've added stuff to the nl2_phinxlog table.
        if (($extra_count = count($extra)) > 0) {
            if ($missing_count > 0) {
                echo '<br>';
            }
            echo "There are $extra_count executed migrations which do not have migration files associated:" . '<br>';