Uncaught TypeError

count(): Argument #1 ($value) must be of type Countable|array, null given

/data/modules/Patreon/module.php

https://dev4.partydragen.com/soldier/Tora/rounds
/data/modules/Patreon/module.php

                $members_list[] = [
                    'user_id' => $target_user->data()->id,
                    'username' => $target_user->getDisplayname(),
                    'user_style' => $target_user->getGroupStyle(),
                    'user_profile' => $target_user->getProfileURL(),
                    'avatar' => $target_user->getAvatar(),
                    'groups' => $target_user->getAllGroupHtml(),
                    'user_title' => Output::getPurified($target_user->data()->user_title),
                    'signature' => Output::getPurified(Text::renderEmojis($target_user->getSignature())),
                    'currently_entitled_amount' => $patreon->amount / 100,
                    'hide_amount' => $patreon->hide_amount,
                    'tier_id' => $patreon->tier_id
                ];
            }

            $cache->store('members_list', $members_list, 300);
        }

        $random_members_list = $members_list;
        if (count($random_members_list)) {
            if (count($random_members_list) > 10) {
                $rand_keys = array_rand($random_members_list, 10);

                $random_members_list = [
                    $random_members_list[$rand_keys[0]],
                    $random_members_list[$rand_keys[1]],
                    $random_members_list[$rand_keys[2]],
                    $random_members_list[$rand_keys[3]],
                    $random_members_list[$rand_keys[4]],
                    $random_members_list[$rand_keys[5]],
                    $random_members_list[$rand_keys[6]],
                    $random_members_list[$rand_keys[7]],
                    $random_members_list[$rand_keys[8]],
                    $random_members_list[$rand_keys[9]]
                ];
            }
        }

        $template->getEngine()->addVariables([
            'RANDOM_PATREONS_LIST' => $random_members_list,
/data/core/classes/Core/Module.php
        }

        $this->_load_before = $load_before;
        $this->_load_after = $load_after;
    }

    /**
     * Call `onPageLoad()` function for all registered modules.
     *
     * @param User                   $user     User viewing the page.
     * @param Pages                  $pages    Instance of pages class.
     * @param Cache                  $cache    Instance of cache to pass.
     * @param FakeSmarty|Smarty|null $smarty   Instance of Smarty to pass
     * @param Navigation[]           $navs     Array of loaded navigation menus.
     * @param Widgets                $widgets  Instance of widget class to pass.
     * @param TemplateBase           $template Template to pass.
     */
    public static function loadPage(User $user, Pages $pages, Cache $cache, $smarty, iterable $navs, Widgets $widgets, TemplateBase $template): void
    {
        foreach (self::getModules() as $module) {
            $module->onPageLoad($user, $pages, $cache, $smarty, $navs, $widgets, $template);
        }
    }

    /** @return Module[] */
    public static function getModules(): iterable
    {
        return self::$_modules;
    }

    /**
     * Handle page loading for this module.
     * Often used to register permissions, sitemaps, widgets, etc.
     *
     * @param User              $user     User viewing the page.
     * @param Pages             $pages    Instance of pages class.
     * @param Cache             $cache    Instance of cache to pass.
     * @param FakeSmarty|Smarty $smarty   Instance of smarty to pass, to be removed in 2.3.0
     * @param Navigation[]      $navs     Array of loaded navigation menus.
     * @param Widgets           $widgets  Instance of widget class to pass.
     * @param TemplateBase      $template Active template to render.
/data/modules/Reclamation/pages/soldier.php
}

$template->getEngine()->addVariables([
    'USERNAME' => Output::getClean($player->data()->username),
    'CRPT_VALUE' => Output::getClean($player->data()->crpt),

    'PDTC_VALUE' => Reclamation::getDB()->query('SELECT SUM(amount) AS dogtags FROM players_dogtags WHERE pid = ?', [$player->data()->pid])->first()->dogtags ?? 0,
    'ENLISTED_VALUE' => $timeago->inWords($player->data()->acdt, $language),
    'LAST_SEEN_VALUE' => $timeago->inWords($player->data()->lgdt, $language),

    'KDR_VALUE' => Output::getClean(sprintf('%0.2f', $player->data()->klls / Reclamation::chz($player->data()->dths))),
    'WLR_VALUE' => Output::getClean(sprintf('%0.2f', $player->data()->wins / Reclamation::chz($player->data()->los))),
    'TT_VALUE' => Output::getClean(sprintf("%d hours", $player->data()->tt / 3600)),

    'OVERVIEW_LINK' => URL::build('/soldier/' . $player->data()->username),
    'DOGTAGS_LINK' => URL::build('/soldier/' . $player->data()->username . '/dogtags'),
    'ROUNDS_LINK' => URL::build('/soldier/' . $player->data()->username . '/rounds')
]);

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

$template->onPageLoad();

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

// Display template
$template->displayTemplate($template_file);
/data/index.php
        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]);
                require($path);
                die;
            }
        }
    }
}

require(ROOT_PATH . '/404.php');
/data/modules/Reclamation/pages/soldier.php
SELECT SUM(amount) AS dogtags FROM players_dogtags WHERE pid = '10126832';
                    );
                }
            }

            $template->getEngine()->addVariables([
                'ROUNDS_LIST' => $rounds_list
            ]);

            $template_file = 'reclamation/soldier_rounds';
            break;
        default:
            Redirect::to(URL::build('/soldier/' . $player->data()->username));
            break;
    }
}

$template->getEngine()->addVariables([
    'USERNAME' => Output::getClean($player->data()->username),
    'CRPT_VALUE' => Output::getClean($player->data()->crpt),

    'PDTC_VALUE' => Reclamation::getDB()->query('SELECT SUM(amount) AS dogtags FROM players_dogtags WHERE pid = ?', [$player->data()->pid])->first()->dogtags ?? 0,
    'ENLISTED_VALUE' => $timeago->inWords($player->data()->acdt, $language),
    'LAST_SEEN_VALUE' => $timeago->inWords($player->data()->lgdt, $language),

    'KDR_VALUE' => Output::getClean(sprintf('%0.2f', $player->data()->klls / Reclamation::chz($player->data()->dths))),
    'WLR_VALUE' => Output::getClean(sprintf('%0.2f', $player->data()->wins / Reclamation::chz($player->data()->los))),
    'TT_VALUE' => Output::getClean(sprintf("%d hours", $player->data()->tt / 3600)),

    'OVERVIEW_LINK' => URL::build('/soldier/' . $player->data()->username),
    'DOGTAGS_LINK' => URL::build('/soldier/' . $player->data()->username . '/dogtags'),
    'ROUNDS_LINK' => URL::build('/soldier/' . $player->data()->username . '/rounds')
]);

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

$template->onPageLoad();

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

/data/modules/Reclamation/pages/soldier.php
SELECT players_rounds.*, mapend, gm FROM players_rounds LEFT JOIN rounds ON round_id=rounds.id WHERE players_rounds.pid = '10126832' AND tt > 60 ORDER BY rounds.mapend DESC LIMIT 30;
                        'avatar_url' => Reclamation::getRank($tag->crpt)['image'],
                        'group_style' => $target_user->exists() ? $target_user->getGroupStyle() : 'color: #6AA5D7;',
                        'user_id' => $target_user->exists() ? $target_user->data()->id : null,
                        'profile_url' => URL::build('/soldier/' . $tag->username),
                        'count' => Output::getClean($tag->amount),
                        'group_html' => [],
                        'metadata' => []
                    ];
                }
            }

            $template->getEngine()->addVariables([
                'DOGTAGS_LIST' => $dogtags_list
            ]);

            $template_file = 'reclamation/soldier_dogtags';
            break;
        case 'rounds':
            // Recent Rounds
            $rounds_list = [];
            $rounds = Reclamation::getDB()->query('SELECT players_rounds.*, mapend, gm FROM players_rounds LEFT JOIN rounds ON round_id=rounds.id WHERE players_rounds.pid = ? AND tt > 60 ORDER BY rounds.mapend DESC LIMIT 30', [$player->data()->pid]);
            if ($rounds->count()) {
                foreach ($rounds->results() as $round) {
                    $rounds_list[] = array(
                        'round_id' => $round->round_id,
                        'date' => $timeago->inWords($round->mapend, $language),
                        'mode' => Reclamation::getMode($round->gm),
                        'kills' => $round->klls,
                        'score' => $round->gsco,
                        'deaths' => $round->dths,
                        'kd' => ($round->dths > 0) ? round($round->klls / $round->dths, 2) : $round->klls,
                        'tt' => Output::getClean(sprintf("%d mins", $round->tt / 60)),
                    );
                }
            }

            $template->getEngine()->addVariables([
                'ROUNDS_LIST' => $rounds_list
            ]);

            $template_file = 'reclamation/soldier_rounds';
/data/core/classes/Core/User.php
SELECT * FROM nl2_users WHERE `username` = 'Tora';
    }

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

            return true;
        }

        if ($field !== 'hash') {
            $data = $this->_db->get('users', [$field, $value]);
        } else {
            $data = $this->_db->query(
                <<<'SQL'
                SELECT
                    nl2_users.*
                FROM nl2_users
                    LEFT JOIN nl2_users_session
                    ON nl2_users.id = nl2_users_session.user_id
                WHERE
                    nl2_users_session.hash = ?
                    AND nl2_users_session.active = 1
                    AND (
                        nl2_users_session.expires_at IS NULL
                        OR nl2_users_session.expires_at > ?
                    )
                SQL,
                [
                    $value,
                    time(),
                ]
/data/modules/Reclamation/classes/Player.php
SELECT * FROM playerprogress WHERE `username` = 'Tora';
<?php
class Player {

    private DB $_db;
    private $_data;

    // Construct Player class
    public function __construct($value = null, $field = 'pid') {
        $this->_db = Reclamation::getDB();

        $data = $this->_db->get('playerprogress', array($field, '=', $value));
        if ($data->count()) {
            $this->_data = $data->first();
        }
    }

    /**
     * Update a player data in the database.
     *
     * @param array $fields Column names and values to update.
     */
    public function update($fields = []): void {
        if (!$this->_db->update('playerprogress', ['pid', '=', $this->data()->pid], $fields)) {
            throw new Exception('There was a problem updating server');
        }
    }

    /**
     * Create a new player.
     *
     * @param array $fields Column names and values to insert to database.
/data/core/templates/frontend_init.php
SELECT * FROM nl2_page_descriptions WHERE `page` = '/soldier/Tora/rounds';
        $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]);
    if ($page_metadata->count()) {
        $page_metadata = $page_metadata->first();
        $template->getEngine()->addVariables([
            'PAGE_DESCRIPTION' => str_replace('{site}', Output::getClean(SITE_NAME), addslashes(strip_tags($page_metadata->description))),
            'PAGE_KEYWORDS' => addslashes(strip_tags($page_metadata->tags)),
        ]);

        $og_image = $page_metadata->image;
        if ($og_image) {
            $template->getEngine()->addVariable('OG_IMAGE', rtrim(URL::getSelfURL(), '/') . $og_image);
        }
    } else {
        $template->getEngine()->addVariables([
            'PAGE_DESCRIPTION' => str_replace('{site}', Output::getClean(SITE_NAME), addslashes(strip_tags(Settings::get('default_meta_description', '')))),
            'PAGE_KEYWORDS' => addslashes(strip_tags(Settings::get('default_meta_keywords', ''))),
        ]);
    }
} else {
    $template->getEngine()->addVariables([
        'PAGE_DESCRIPTION' => str_replace('{site}', Output::getClean(SITE_NAME), addslashes(strip_tags(PAGE_DESCRIPTION))),
/data/core/init.php
UPDATE nl2_online_guests SET `last_seen` = '1850' WHERE `id` =;
                    Redirect::to(URL::build('/user/settings', 'do=enable_tfa'));
                }
            }
        }

        $user_integrations = [];
        foreach ($user->getIntegrations() as $integrationUser) {
            $user_integrations[$integrationUser->getIntegration()->getName()] = [
                'username' => Output::getClean($integrationUser->data()->username),
                'identifier' => Output::getClean($integrationUser->data()->identifier),
            ];
        }
    } 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;
        }

        // Auto language enabled?
        if (Settings::get('auto_language_detection')) {
            define('AUTO_LANGUAGE', true);
        }
    }

    // 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')) {
/data/core/init.php
SELECT * FROM nl2_online_guests WHERE `ip` = '216.73.216.54';
        if (isset($forced) && $forced) {
            // Do they have TFA configured?
            if (!$user->data()->tfa_enabled && rtrim($_GET['route'], '/') != '/logout') {
                if (!str_contains($_SERVER['REQUEST_URI'], 'do=enable_tfa') && !isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
                    Session::put('force_tfa_alert', $language->get('admin', 'force_tfa_alert'));
                    Redirect::to(URL::build('/user/settings', 'do=enable_tfa'));
                }
            }
        }

        $user_integrations = [];
        foreach ($user->getIntegrations() as $integrationUser) {
            $user_integrations[$integrationUser->getIntegration()->getName()] = [
                'username' => Output::getClean($integrationUser->data()->username),
                'identifier' => Output::getClean($integrationUser->data()->identifier),
            ];
        }
    } 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;
        }

        // Auto language enabled?
        if (Settings::get('auto_language_detection')) {
            define('AUTO_LANGUAGE', true);
        }
    }

    // Dark mode
    $cache->setCache('template_settings');
/data/core/init.php
SELECT * FROM nl2_groups WHERE `default_group` = '1';
                            : [DiscordHook::class, 'execute'],
                        'events' => json_decode($hook->events, true),
                    ];
                }
                $cache->store('hooks', $hook_array);
            }
        }
    }
    EventHandler::registerWebhooks($hook_array);

    // Get IP
    $ip = HttpUtils::getRemoteAddress();

    // 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);

    // Perform tasks if the user is logged in
    if ($user->isLoggedIn()) {
        Debugging::setCanViewDetailedError($user->hasPermission('admincp.errors'));
        Debugging::setCanGenerateDebugLink($user->hasPermission('admincp.core.debugging'));

        // Ensure a user is not banned
        if ($user->data()->isbanned == 1) {
            $user->logout();
            Session::flash('home_error', $language->get('user', 'you_have_been_banned'));
            Redirect::to(URL::build('/'));
        }

        // Is the IP address banned?
        $ip_bans = DB::getInstance()->get('ip_bans', ['ip', $ip])->results();
        if (count($ip_bans)) {
/data/core/classes/Integrations/IntegrationBase.php
SELECT * FROM nl2_integrations WHERE name = 'Discord';
 * @author Partydragen
 * @version 2.1.0
 * @license MIT
 */
abstract class IntegrationBase
{
    private DB $_db;
    private IntegrationData $_data;
    protected string $_icon;
    private array $_errors = [];
    protected Language $_language;
    protected ?string $_settings = null;

    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.
/data/core/classes/Integrations/IntegrationBase.php
SELECT * FROM nl2_integrations WHERE name = 'Patreon';
 * @author Partydragen
 * @version 2.1.0
 * @license MIT
 */
abstract class IntegrationBase
{
    private DB $_db;
    private IntegrationData $_data;
    protected string $_icon;
    private array $_errors = [];
    protected Language $_language;
    protected ?string $_settings = null;

    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.
/data/core/classes/Integrations/IntegrationBase.php
SELECT * FROM nl2_integrations WHERE name = 'BF2142';
 * @author Partydragen
 * @version 2.1.0
 * @license MIT
 */
abstract class IntegrationBase
{
    private DB $_db;
    private IntegrationData $_data;
    protected string $_icon;
    private array $_errors = [];
    protected Language $_language;
    protected ?string $_settings = null;

    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.
/data/core/classes/Core/Module.php
SELECT * FROM nl2_modules WHERE `name` = 'Core';

    /**
     * Get this module's ID.
     *
     * @return int The ID for the module
     */
    public function getId(): int
    {
        return DB::getInstance()->query('SELECT `id` FROM nl2_modules WHERE `name` = ?', [$this->_name])->first()->id;
    }

    /**
     * Get a module ID from name.
     *
     * @param string $name Module name
     *
     * @return ?int Module ID
     */
    public static function getIdFromName(string $name): ?int
    {
        $query = DB::getInstance()->get('modules', ['name', $name]);

        if ($query->count()) {
            return $query->first()->id;
        }

        return null;
    }

    /**
     * Get a module name from ID.
     *
     * @param int $id Module ID
     *
     * @return ?string Module name
     */
    public static function getNameFromId(int $id): ?string
    {
        $query = DB::getInstance()->get('modules', ['id', $id]);

        if ($query->count()) {
/data/core/classes/Integrations/IntegrationBase.php
SELECT * FROM nl2_integrations WHERE name = 'Google';
 * @author Partydragen
 * @version 2.1.0
 * @license MIT
 */
abstract class IntegrationBase
{
    private DB $_db;
    private IntegrationData $_data;
    protected string $_icon;
    private array $_errors = [];
    protected Language $_language;
    protected ?string $_settings = null;

    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.
/data/modules/Core/module.php
SELECT * FROM nl2_custom_pages_permissions WHERE `group_id` = '0';
                                                $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');
/data/modules/Core/module.php
SELECT * FROM nl2_custom_pages WHERE `id` <> '0';
        }

        // "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', 'Support', '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();
/data/core/classes/Core/Settings.php
SELECT `name`, `value` FROM `nl2_settings` WHERE `module` IS NULL;
    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 get(string $setting, ?string $fallback = null, string $module = 'core'): ?string
    {
        if (!self::hasSettingsCache($module)) {
            // 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);
        }

        $cache = &self::getSettingsCache($module);

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

    /**
     * Modify a setting in the database table `nl2_settings`.
     *
     * @param string      $setting   Setting name.
/data/core/classes/Database/PhinxAdapter.php
SELECT version, migration_name FROM nl2_phinxlog;

        if (!$migrationDir) {
            $migrationDir = __DIR__ . '/../../migrations';
        }

        $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($migrationDir), static function ($file_name) {
                // Pattern that matches Phinx migration file names (eg: 20230403000000_create_stroopwafel_table.php)
                return preg_match('/^\d{14}_\w+\.php$/', $file_name);
            }),
        );

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

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

        if ($returnResults) {
            return [
                'missing' => count($missing),
                'extra' => count($extra),
            ];
        }

        // 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>';
            }
        }