From 28886551e86fe562172c4c7f2afb89a2e7672c2e Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 28 May 2025 13:33:36 +0200 Subject: [PATCH 001/216] feat: Add new account coins setting --- system/pages/account/create.php | 10 ++++++++-- system/settings.php | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 0befa362..947ad0ad 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -221,8 +221,14 @@ if($save) } } - if(setting('core.account_premium_points') && setting('core.account_premium_points') > 0) { - $new_account->setCustomField('premium_points', setting('core.account_premium_points')); + $accountDefaultPremiumPoints = setting('core.account_premium_points'); + if($accountDefaultPremiumPoints > 0) { + $new_account->setCustomField('premium_points', $accountDefaultPremiumPoints); + } + + $accountDefaultCoins = setting('core.account_coins'); + if($db->hasColumn('accounts', 'coins') && $accountDefaultCoins > 0) { + $new_account->setCustomField('coins', $accountDefaultCoins); } $tmp_account = $email; diff --git a/system/settings.php b/system/settings.php index d0a705a0..c212587d 100644 --- a/system/settings.php +++ b/system/settings.php @@ -19,6 +19,8 @@ $templates = Cache::remember('templates', 5 * 60, function () { }); $defaultTemplate = in_array('kathrine', $templates) ? 'kathrine' : $templates[0]; +global $db; + return [ 'name' => 'MyAAC', 'settings' => [ @@ -674,6 +676,13 @@ Sent by MyAAC,
'desc' => 'Default premium points on new account', 'default' => 0, ], + 'account_coins' => [ + 'name' => 'Default Account Coins', + 'type' => 'number', + 'desc' => 'Default coins on new account', + 'hidden' => !$db->hasColumn('accounts', 'coins'), + 'default' => 0, + ], 'account_mail_change' => [ 'name' => 'Account Mail Change Days', 'type' => 'number', From 4b7b121550a60d0b7395b75f5e1190e27145bcf1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 28 May 2025 14:08:50 +0200 Subject: [PATCH 002/216] Try fix workflow --- system/src/Validator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Validator.php b/system/src/Validator.php index ad9e3e50..6c189b29 100644 --- a/system/src/Validator.php +++ b/system/src/Validator.php @@ -121,7 +121,7 @@ class Validator return false; } - if(setting('core.account_mail_block_plus_sign')) { + if(!defined('MYAAC_INSTALL') && setting('core.account_mail_block_plus_sign')) { $explode = explode('@', $email); if(isset($explode[0]) && (strpos($explode[0],'+') !== false)) { self::$lastError = 'Please do not use plus (+) sign in your e-mail.'; From 52109f5cca448349040de02f796648d6066b4347 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 28 May 2025 14:13:04 +0200 Subject: [PATCH 003/216] Another solution --- system/settings.php | 2 +- system/src/Validator.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system/settings.php b/system/settings.php index c212587d..a7a5ee0a 100644 --- a/system/settings.php +++ b/system/settings.php @@ -680,7 +680,7 @@ Sent by MyAAC,
'name' => 'Default Account Coins', 'type' => 'number', 'desc' => 'Default coins on new account', - 'hidden' => !$db->hasColumn('accounts', 'coins'), + 'hidden' => ($db && !$db->hasColumn('accounts', 'coins')), 'default' => 0, ], 'account_mail_change' => [ diff --git a/system/src/Validator.php b/system/src/Validator.php index 6c189b29..ad9e3e50 100644 --- a/system/src/Validator.php +++ b/system/src/Validator.php @@ -121,7 +121,7 @@ class Validator return false; } - if(!defined('MYAAC_INSTALL') && setting('core.account_mail_block_plus_sign')) { + if(setting('core.account_mail_block_plus_sign')) { $explode = explode('@', $email); if(isset($explode[0]) && (strpos($explode[0],'+') !== false)) { self::$lastError = 'Please do not use plus (+) sign in your e-mail.'; From d8a6090be382c35c19117cfef964b594ed02b8d4 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 29 May 2025 09:27:29 +0200 Subject: [PATCH 004/216] Add new setting/configurable: site_url, prevents domain spoofing --- common.php | 49 ++++++++++------------- install/steps/4-config.php | 8 ++++ system/base.php | 19 +++++++++ system/locale/de/install.php | 2 + system/locale/en/install.php | 2 + system/locale/pl/install.php | 2 + system/settings.php | 12 ++++++ system/templates/install.config.html.twig | 2 +- 8 files changed, 67 insertions(+), 29 deletions(-) create mode 100644 system/base.php diff --git a/common.php b/common.php index 7fc7f95f..14d4a5db 100644 --- a/common.php +++ b/common.php @@ -122,38 +122,31 @@ if (!IS_CLI) { session_start(); } -// basedir -$basedir = ''; -$tmp = explode('/', $_SERVER['SCRIPT_NAME']); -$size = count($tmp) - 1; -for($i = 1; $i < $size; $i++) - $basedir .= '/' . $tmp[$i]; - -$basedir = str_replace(['/' . ADMIN_PANEL_FOLDER, '/install', '/tools'], '', $basedir); -define('BASE_DIR', $basedir); - -if(!IS_CLI) { - if (isset($_SERVER['HTTP_HOST'][0])) { - $baseHost = $_SERVER['HTTP_HOST']; - } else { - if (isset($_SERVER['SERVER_NAME'][0])) { - $baseHost = $_SERVER['SERVER_NAME']; - } else { - $baseHost = $_SERVER['SERVER_ADDR']; - } - } - - define('SERVER_URL', 'http' . (isHttps() ? 's' : '') . '://' . $baseHost); - define('BASE_URL', SERVER_URL . BASE_DIR . '/'); - define('ADMIN_URL', SERVER_URL . BASE_DIR . '/' . ADMIN_PANEL_FOLDER . '/'); - - //define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); -} - if (file_exists(BASE . 'config.local.php')) { require BASE . 'config.local.php'; } +if(!IS_CLI) { + require SYSTEM . 'base.php'; + define('BASE_DIR', $baseDir); + + if (isset($config['site_url'])) { + $hasSlashAtEnd = ($config['site_url'][strlen($config['site_url']) - 1] == '/'); + + define('SERVER_URL', $config['site_url']); + define('BASE_URL', SERVER_URL . ($hasSlashAtEnd ? '' : '/')); + define('ADMIN_URL', SERVER_URL . ($hasSlashAtEnd ? '' : '/') . ADMIN_PANEL_FOLDER . '/'); + } + else { + define('SERVER_URL', 'http' . (isHttps() ? 's' : '') . '://' . $baseHost); + define('BASE_URL', SERVER_URL . BASE_DIR . '/'); + define('ADMIN_URL', SERVER_URL . BASE_DIR . '/' . ADMIN_PANEL_FOLDER . '/'); + + //define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); + } + +} + /** @var array $config */ ini_set('log_errors', 1); if(@$config['env'] === 'dev' || defined('MYAAC_INSTALL')) { diff --git a/install/steps/4-config.php b/install/steps/4-config.php index 325b97f1..342edd06 100644 --- a/install/steps/4-config.php +++ b/install/steps/4-config.php @@ -10,6 +10,14 @@ foreach($config['clients'] as $client) { $clients[$client] = $client_version; } +if (empty($_SESSION['var_site_url'])) { + //require SYSTEM . 'base.php'; + $serverUrl = 'http' . (isHttps() ? 's' : '') . '://' . $baseHost; + $siteURL = $serverUrl . $baseDir; + + $_SESSION['var_site_url'] = $siteURL; +} + $twig->display('install.config.html.twig', array( 'clients' => $clients, 'timezones' => DateTimeZone::listIdentifiers(), diff --git a/system/base.php b/system/base.php new file mode 100644 index 00000000..a0ba4e6b --- /dev/null +++ b/system/base.php @@ -0,0 +1,19 @@ + 'MyAAC', 'settings' => [ @@ -32,6 +37,13 @@ return [ 'type' => 'section', 'title' => 'General' ], + 'site_url' => [ + 'name' => 'Website URL', + 'type' => 'text', + 'desc' => 'Website address of this MyAAC instance', + 'default' => $siteURL, + 'is_config' => true, + ], 'env' => [ 'name' => 'App Environment', 'type' => 'options', diff --git a/system/templates/install.config.html.twig b/system/templates/install.config.html.twig index ab4fc361..8c0aa50a 100644 --- a/system/templates/install.config.html.twig +++ b/system/templates/install.config.html.twig @@ -9,7 +9,7 @@
- {% for value in ['server_path'] %} + {% for value in ['site_url', 'server_path'] %}
From fb91281140cc81cb0837a46b896959473cff9f51 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 29 May 2025 09:35:20 +0200 Subject: [PATCH 005/216] Fix phpstan workflow --- common.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common.php b/common.php index 14d4a5db..cec3a3c2 100644 --- a/common.php +++ b/common.php @@ -126,10 +126,10 @@ if (file_exists(BASE . 'config.local.php')) { require BASE . 'config.local.php'; } -if(!IS_CLI) { - require SYSTEM . 'base.php'; - define('BASE_DIR', $baseDir); +require SYSTEM . 'base.php'; +define('BASE_DIR', $baseDir); +if(!IS_CLI) { if (isset($config['site_url'])) { $hasSlashAtEnd = ($config['site_url'][strlen($config['site_url']) - 1] == '/'); @@ -144,7 +144,6 @@ if(!IS_CLI) { //define('CURRENT_URL', BASE_URL . $_SERVER['REQUEST_URI']); } - } /** @var array $config */ From 6e0f5913831f8dba69fd2d1505be3e2a303c6324 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 29 May 2025 12:22:16 +0200 Subject: [PATCH 006/216] Do not allow access to tools/ folder after install --- install/steps/7-finish.php | 9 --------- install/tools/5-database.php | 5 +++++ install/tools/7-finish.php | 15 +++++++++++++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/install/steps/7-finish.php b/install/steps/7-finish.php index 0ae302ea..afe63603 100644 --- a/install/steps/7-finish.php +++ b/install/steps/7-finish.php @@ -195,13 +195,4 @@ if(!isset($_SESSION['installed'])) { $_SESSION['installed'] = true; } -foreach($_SESSION as $key => $value) { - if(strpos($key, 'var_') !== false) - unset($_SESSION[$key]); -} -unset($_SESSION['saved']); -if(file_exists(CACHE . 'install.txt')) { - unlink(CACHE . 'install.txt'); -} - $hooks->trigger(HOOK_INSTALL_FINISH_END); diff --git a/install/tools/5-database.php b/install/tools/5-database.php index 395492ee..b9ff587f 100644 --- a/install/tools/5-database.php +++ b/install/tools/5-database.php @@ -7,6 +7,11 @@ require SYSTEM . 'functions.php'; require BASE . 'install/includes/functions.php'; require BASE . 'install/includes/locale.php'; +if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) { + warning($locale['already_installed']); + return; +} + $error = false; require BASE . 'install/includes/config.php'; diff --git a/install/tools/7-finish.php b/install/tools/7-finish.php index c1ab5c1d..9c64382b 100644 --- a/install/tools/7-finish.php +++ b/install/tools/7-finish.php @@ -17,11 +17,11 @@ ini_set('max_execution_time', 300); ob_implicit_flush(); header('X-Accel-Buffering: no'); -/* + if(isset($config['installed']) && $config['installed'] && !isset($_SESSION['saved'])) { warning($locale['already_installed']); return; -}*/ +} require SYSTEM . 'init.php'; @@ -94,6 +94,17 @@ $hooks->trigger(HOOK_INSTALL_FINISH); $db->setClearCacheAfter(true); +// cleanup +foreach($_SESSION as $key => $value) { + if(str_contains($key, 'var_')) { + unset($_SESSION[$key]); + } +} +unset($_SESSION['saved']); +if(file_exists(CACHE . 'install.txt')) { + unlink(CACHE . 'install.txt'); +} + $locale['step_finish_desc'] = str_replace('$ADMIN_PANEL$', generateLink(str_replace('tools/', '',ADMIN_URL), $locale['step_finish_admin_panel'], true), $locale['step_finish_desc']); $locale['step_finish_desc'] = str_replace('$HOMEPAGE$', generateLink(str_replace('tools/', '', BASE_URL), $locale['step_finish_homepage'], true), $locale['step_finish_desc']); $locale['step_finish_desc'] = str_replace('$LINK$', generateLink('https://my-aac.org', 'https://my-aac.org', true), $locale['step_finish_desc']); From 756d94bb3e746f0ea81bcd8b3bc825222508c771 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 29 May 2025 16:08:23 +0200 Subject: [PATCH 007/216] Fix warning from CLI --- system/base.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/system/base.php b/system/base.php index a0ba4e6b..9cab2925 100644 --- a/system/base.php +++ b/system/base.php @@ -8,12 +8,14 @@ for($i = 1; $i < $size; $i++) $baseDir = str_replace(['/' . ADMIN_PANEL_FOLDER, '/install', '/tools'], '', $baseDir); -if (isset($_SERVER['HTTP_HOST'][0])) { - $baseHost = $_SERVER['HTTP_HOST']; -} else { - if (isset($_SERVER['SERVER_NAME'][0])) { - $baseHost = $_SERVER['SERVER_NAME']; +if(!IS_CLI) { + if (isset($_SERVER['HTTP_HOST'][0])) { + $baseHost = $_SERVER['HTTP_HOST']; } else { - $baseHost = $_SERVER['SERVER_ADDR']; + if (isset($_SERVER['SERVER_NAME'][0])) { + $baseHost = $_SERVER['SERVER_NAME']; + } else { + $baseHost = $_SERVER['SERVER_ADDR']; + } } } From 770ffcfc528f35cb873d72ab71026d9a15b71297 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 29 May 2025 16:10:46 +0200 Subject: [PATCH 008/216] Fix warnings in CLI (part 2) --- system/settings.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/system/settings.php b/system/settings.php index 7a7a48a6..4cfe5c9f 100644 --- a/system/settings.php +++ b/system/settings.php @@ -21,10 +21,12 @@ $defaultTemplate = in_array('kathrine', $templates) ? 'kathrine' : $templates[0] global $db; -require SYSTEM . 'base.php'; +if (!IS_CLI) { + require SYSTEM . 'base.php'; -$serverUrl = 'http' . (isHttps() ? 's' : '') . '://' . $baseHost; -$siteURL = $serverUrl . $baseDir; + $serverUrl = 'http' . (isHttps() ? 's' : '') . '://' . $baseHost; + $siteURL = $serverUrl . $baseDir; +} return [ 'name' => 'MyAAC', @@ -41,7 +43,7 @@ return [ 'name' => 'Website URL', 'type' => 'text', 'desc' => 'Website address of this MyAAC instance', - 'default' => $siteURL, + 'default' => IS_CLI ? '' : $siteURL, 'is_config' => true, ], 'env' => [ From c961a1ebf837f2ab1734a825ff2c57b4937610c9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 06:21:44 +0200 Subject: [PATCH 009/216] Two new hooks for pages loaded from database (custom pages) HOOK_BEFORE_PAGE_CUSTOM, HOOK_AFTER_PAGE_CUSTOM --- system/router.php | 4 +++- system/src/global.php | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/system/router.php b/system/router.php index b87a843d..40b45861 100644 --- a/system/router.php +++ b/system/router.php @@ -252,7 +252,7 @@ else { $success = false; $tmp_content = getCustomPage($pageName, $success); - if ($success) { + if ($success && $hooks->trigger(HOOK_BEFORE_PAGE_CUSTOM)) { $content .= $tmp_content; if (hasFlag(FLAG_CONTENT_PAGES) || superAdmin()) { $pageInfo = getCustomPageInfo($pageName); @@ -260,6 +260,8 @@ else { ) . $content; } + $hooks->trigger(HOOK_AFTER_PAGE_CUSTOM); + $page = $pageName; $file = false; } diff --git a/system/src/global.php b/system/src/global.php index 62366c1c..f374568d 100644 --- a/system/src/global.php +++ b/system/src/global.php @@ -8,7 +8,9 @@ $i = 0; define('HOOK_INIT', ++$i); define('HOOK_STARTUP', ++$i); define('HOOK_BEFORE_PAGE', ++$i); +define('HOOK_BEFORE_PAGE_CUSTOM', ++$i); define('HOOK_AFTER_PAGE', ++$i); +define('HOOK_AFTER_PAGE_CUSTOM', ++$i); define('HOOK_FINISH', ++$i); define('HOOK_TIBIACOM_ARTICLE', ++$i); define('HOOK_TIBIACOM_BORDER_3', ++$i); From 8fdea943768b20193eede99d60313ee84511a0be Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 08:39:48 +0200 Subject: [PATCH 010/216] Add globals into $hooks->executeFIlter --- system/src/Hook.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/src/Hook.php b/system/src/Hook.php index 161b2ffc..6acdf6ef 100644 --- a/system/src/Hook.php +++ b/system/src/Hook.php @@ -38,6 +38,8 @@ class Hook } public function executeFilter(&$args) { + global $db, $config, $template_path, $ots, $content, $twig; + return include BASE . $this->_file; } From 207d6bc69120aba1af2b51808f17e0059b571fed Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 08:52:33 +0200 Subject: [PATCH 011/216] feat: AutoLoad plugins init.php, by default disabled --- system/init.php | 6 ++++++ system/src/Plugins.php | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/system/init.php b/system/init.php index 44634265..821ac440 100644 --- a/system/init.php +++ b/system/init.php @@ -12,6 +12,7 @@ use DebugBar\StandardDebugBar; use MyAAC\Cache\Cache; use MyAAC\CsrfToken; use MyAAC\Hooks; +use MyAAC\Plugins; use MyAAC\Models\Town; use MyAAC\Settings; @@ -46,6 +47,11 @@ if(isset($config['gzip_output']) && $config['gzip_output'] && isset($_SERVER['HT global $cache; $cache = Cache::getInstance(); +// load plugins init.php +foreach (Plugins::getInits() as $init) { + require $init; +} + // event system global $hooks; $hooks = new Hooks(); diff --git a/system/src/Plugins.php b/system/src/Plugins.php index 438fe32e..85f0a2ba 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -11,6 +11,25 @@ class Plugins { private static $error = null; private static $plugin_json = []; + public static function getInits() + { + return Cache::remember('plugins_inits', 10 * 60, function () { + $inits = []; + foreach(self::getAllPluginsJson() as $plugin) { + if (!self::getAutoLoadOption($plugin, 'init', false)) { + continue; + } + + $pluginInits = glob(PLUGINS . $plugin['filename'] . '/init.php'); + foreach ($pluginInits as $path) { + $inits[] = $path; + } + } + + return $inits; + }); + } + public static function getAdminPages() { return Cache::remember('plugins_admin_pages', 10 * 60, function () { From c61747dc7589f7aa546bb6f8d3cd99a91fe1e535 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 10:17:08 +0200 Subject: [PATCH 012/216] Update coins.html.twig --- admin/pages/modules/templates/coins.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/pages/modules/templates/coins.html.twig b/admin/pages/modules/templates/coins.html.twig index 722064f8..ae586ee8 100644 --- a/admin/pages/modules/templates/coins.html.twig +++ b/admin/pages/modules/templates/coins.html.twig @@ -19,7 +19,7 @@ {% set i = i + 1 %} {{ i }} - {{ result.name }} + {{ result.name ?? result.id }} {{ result.coins }} {% endfor %} From 064b92984172e0e5ece25b36902f1026b49aa43c Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 16:39:02 +0200 Subject: [PATCH 013/216] Allow [] in character name (for :string) --- system/router.php | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/system/router.php b/system/router.php index 40b45861..516c4286 100644 --- a/system/router.php +++ b/system/router.php @@ -129,14 +129,14 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) return ($a[3] < $b[3]) ? -1 : 1; }); + $aliases = [ + [':int', ':string', ':alphanum'], + [':\d+', ':[A-Za-z0-9-_%+\' \[\]]+', ':[A-Za-z0-9]+'], + ]; + // remove duplicates // if same route pattern, but different priority - $routesFinal = array_filter($routesFinal, function ($a) { - $aliases = [ - [':int', ':string', ':alphanum'], - [':\d+', ':[A-Za-z0-9-_%+\' ]+', ':[A-Za-z0-9]+'], - ]; - + $routesFinal = array_filter($routesFinal, function ($a) use ($aliases) { // apply aliases $a[1] = str_replace($aliases[0], $aliases[1], $a[1]); @@ -171,11 +171,6 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) $route[0] = array_map($toUpperCase, $route[0]); } - $aliases = [ - [':int', ':string', ':alphanum'], - [':\d+', ':[A-Za-z0-9-_%+\' ]+', ':[A-Za-z0-9]+'], - ]; - // apply aliases $route[1] = str_replace($aliases[0], $aliases[1], $route[1]); From dd731fd49be9d0f33e8c582b4445a254160e1855 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 16:43:43 +0200 Subject: [PATCH 014/216] Revert previous commit partially --- system/router.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/router.php b/system/router.php index 516c4286..1102ef0e 100644 --- a/system/router.php +++ b/system/router.php @@ -131,7 +131,7 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) $aliases = [ [':int', ':string', ':alphanum'], - [':\d+', ':[A-Za-z0-9-_%+\' \[\]]+', ':[A-Za-z0-9]+'], + [':\d+', ':[A-Za-z0-9-_%+\' ]+', ':[A-Za-z0-9]+'], ]; // remove duplicates From de6603a51347b9e656c58637ed9971fffdd7cedd Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 16:49:45 +0200 Subject: [PATCH 015/216] Allow [] in character name (again), example: [God] Test --- system/routes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/routes.php b/system/routes.php index 13cee37f..c804ec8c 100644 --- a/system/routes.php +++ b/system/routes.php @@ -22,7 +22,7 @@ return [ ['GET', 'account/confirm-email/{hash:alphanum}', 'account/confirm-email.php'], ['GET', 'bans/{page:int}', 'bans.php'], - [['GET', 'POST'], 'characters[/{name:string}]', 'characters.php'], + [['GET', 'POST'], 'characters[/{name:[A-Za-z0-9-_%+\' \[\]]+}]', 'characters.php'], ['GET', 'changelog[/{page:int}]', 'changelog.php'], [['GET', 'POST'], 'monsters[/{name:string}]', 'monsters.php'], From 01d49692ede5a3cc426f0711c642d66d5d0e2d70 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 16:59:20 +0200 Subject: [PATCH 016/216] Update CHANGELOG-1.x.md --- CHANGELOG-1.x.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 291b5441..9c68b895 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,26 @@ # Changelog +## [1.6 - 03.06.2025] + +### Added +* Add new setting/configurable: site_url, prevents domain spoofing (https://github.com/slawkens/myaac/commit/d8a6090be382c35c19117cfef964b594ed02b8d4) +* Add new account coins setting (https://github.com/slawkens/myaac/commit/28886551e86fe562172c4c7f2afb89a2e7672c2e) +* autoload: settings/install/init.php (https://github.com/slawkens/myaac/commit/e5749437074c3b3556628a2aeb5bad2edf97bde0, https://github.com/slawkens/myaac/commit/7d213f479a7e40c6254069b5fc4e578dc32bf8d9) +* Protect against csrf in more places (accounts & guilds & forums pages) (https://github.com/slawkens/myaac/commit/6eda38603c8ed7e99b92a78a4600b1245377f74d, https://github.com/slawkens/myaac/commit/e776bd52beb3064a9e694efd1b9021ec972ee2f6, https://github.com/slawkens/myaac/commit/84d502bf105f2a789481fba1acc820d236b4de66) +* Added two new hooks for pages loaded from database (custom pages): HOOK_BEFORE_PAGE_CUSTOM, HOOK_AFTER_PAGE_CUSTOM (https://github.com/slawkens/myaac/commit/c961a1ebf837f2ab1734a825ff2c57b4937610c9) +* Add global variables into $hooks->executeFilter (https://github.com/slawkens/myaac/commit/8fdea943768b20193eede99d60313ee84511a0be) +* Add getNPCsCount() to OTS_InfoRespond (https://github.com/slawkens/myaac/commit/7d435ff6433ef1fb2295ee79ed043ee10dc725e9) + +### Fixed +* Allow [] in character name (https://github.com/slawkens/myaac/commit/064b92984172e0e5ece25b36902f1026b49aa43c) +* Do not allow access to tools/ folder after install (https://github.com/slawkens/myaac/commit/6e0f5913831f8dba69fd2d1505be3e2a303c6324) +* Fix CHANGELOG-1.x.md loading in admin panel (https://github.com/slawkens/myaac/commit/4a30fb495dbfbe1d434e8d52419eaf44fe517aee) +* Fix links not working in admin dashboard modules (https://github.com/slawkens/myaac/commit/be7b27c31aa3bbd6c0289c34d1e61139a3fe015c) +* Fix twig variables: logged + account_logged being not set directly after login (https://github.com/slawkens/myaac/commit/1e9b10d6489c488cadf7f6ed17b42f1ea6c767a8) + +### Changed +* OTS_ServerInfo -> move setTimeout out of class - Possibility to use the class without MyAAC (https://github.com/slawkens/myaac/commit/40d65a6613149fda51bdceb82c807e5301a3388b) + ## [1.5 - 14.05.2025] ### Added From dc839abfbbb826cd0674c30ab623422eb24efdff Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 16:59:55 +0200 Subject: [PATCH 017/216] Release v1.6 --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index cec3a3c2..35af07af 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.5.1-dev'; +const MYAAC_VERSION = '1.6'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From ce2af2bb7afe5f5e203d1695622550e4d5c01f74 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 17:33:17 +0200 Subject: [PATCH 018/216] Update CHANGELOG-1.x.md --- CHANGELOG-1.x.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 9c68b895..d3d81a56 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -5,14 +5,14 @@ ### Added * Add new setting/configurable: site_url, prevents domain spoofing (https://github.com/slawkens/myaac/commit/d8a6090be382c35c19117cfef964b594ed02b8d4) * Add new account coins setting (https://github.com/slawkens/myaac/commit/28886551e86fe562172c4c7f2afb89a2e7672c2e) -* autoload: settings/install/init.php (https://github.com/slawkens/myaac/commit/e5749437074c3b3556628a2aeb5bad2edf97bde0, https://github.com/slawkens/myaac/commit/7d213f479a7e40c6254069b5fc4e578dc32bf8d9) +* autoload: settings/install/init.php (https://github.com/slawkens/myaac/commit/e5749437074c3b3556628a2aeb5bad2edf97bde0, https://github.com/slawkens/myaac/commit/7d213f479a7e40c6254069b5fc4e578dc32bf8d9, https://github.com/slawkens/myaac/commit/207d6bc69120aba1af2b51808f17e0059b571fed) * Protect against csrf in more places (accounts & guilds & forums pages) (https://github.com/slawkens/myaac/commit/6eda38603c8ed7e99b92a78a4600b1245377f74d, https://github.com/slawkens/myaac/commit/e776bd52beb3064a9e694efd1b9021ec972ee2f6, https://github.com/slawkens/myaac/commit/84d502bf105f2a789481fba1acc820d236b4de66) * Added two new hooks for pages loaded from database (custom pages): HOOK_BEFORE_PAGE_CUSTOM, HOOK_AFTER_PAGE_CUSTOM (https://github.com/slawkens/myaac/commit/c961a1ebf837f2ab1734a825ff2c57b4937610c9) * Add global variables into $hooks->executeFilter (https://github.com/slawkens/myaac/commit/8fdea943768b20193eede99d60313ee84511a0be) * Add getNPCsCount() to OTS_InfoRespond (https://github.com/slawkens/myaac/commit/7d435ff6433ef1fb2295ee79ed043ee10dc725e9) ### Fixed -* Allow [] in character name (https://github.com/slawkens/myaac/commit/064b92984172e0e5ece25b36902f1026b49aa43c) +* Allow [] in character name (https://github.com/slawkens/myaac/commit/de6603a51347b9e656c58637ed9971fffdd7cedd) * Do not allow access to tools/ folder after install (https://github.com/slawkens/myaac/commit/6e0f5913831f8dba69fd2d1505be3e2a303c6324) * Fix CHANGELOG-1.x.md loading in admin panel (https://github.com/slawkens/myaac/commit/4a30fb495dbfbe1d434e8d52419eaf44fe517aee) * Fix links not working in admin dashboard modules (https://github.com/slawkens/myaac/commit/be7b27c31aa3bbd6c0289c34d1e61139a3fe015c) From 2dba778167d349a5230c1dcd4f9e19c2728562fa Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 18:38:02 +0200 Subject: [PATCH 019/216] Update example.json --- plugins/example.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/example.json b/plugins/example.json index 395db41d..fd5e183b 100644 --- a/plugins/example.json +++ b/plugins/example.json @@ -51,5 +51,8 @@ "themes": true, "admin-pages": true, "admin-pages-sub-folders": true, + "settings": true, + "install": true, + "init": false } } From db09980de10ee2b9f45a37ef839ca0c712edbaf1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 3 Jun 2025 22:57:33 +0200 Subject: [PATCH 020/216] Start v1.6.1-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 35af07af..2af620c9 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.6'; +const MYAAC_VERSION = '1.6.1-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 9d8e9d27bd87167d8d4005942a6af62bfe4c0892 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 5 Jun 2025 18:11:31 +0200 Subject: [PATCH 021/216] Ignore duplicated route exception --- system/router.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/system/router.php b/system/router.php index 1102ef0e..20f3f07a 100644 --- a/system/router.php +++ b/system/router.php @@ -174,7 +174,12 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) // apply aliases $route[1] = str_replace($aliases[0], $aliases[1], $route[1]); - $r->addRoute($route[0], $route[1], $route[2]); + try { + $r->addRoute($route[0], $route[1], $route[2]); + } + catch (\Exception $e) { + // duplicated route, just ignore + } } if (config('env') === 'dev') { From dcc703b1eb432586935fad5f05ce4a2561a0f020 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 5 Jun 2025 18:11:44 +0200 Subject: [PATCH 022/216] Remove optional param, make it required for few routes --- system/routes.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/system/routes.php b/system/routes.php index c804ec8c..b4af29f0 100644 --- a/system/routes.php +++ b/system/routes.php @@ -22,11 +22,11 @@ return [ ['GET', 'account/confirm-email/{hash:alphanum}', 'account/confirm-email.php'], ['GET', 'bans/{page:int}', 'bans.php'], - [['GET', 'POST'], 'characters[/{name:[A-Za-z0-9-_%+\' \[\]]+}]', 'characters.php'], - ['GET', 'changelog[/{page:int}]', 'changelog.php'], - [['GET', 'POST'], 'monsters[/{name:string}]', 'monsters.php'], + [['GET', 'POST'], 'characters/{name:[A-Za-z0-9-_%+\' \[\]]+}', 'characters.php'], + ['GET', 'changelog/{page:int}', 'changelog.php'], + [['GET', 'POST'], 'monsters/{name:string}', 'monsters.php'], - [['GET', 'POST'], 'faq[/{action:string}]', 'faq.php'], + [['GET', 'POST'], 'faq/{action:string}', 'faq.php'], [['GET', 'POST'], 'forum/{action:string}', 'forum.php'], ['GET', 'forum/board/{id:int}', 'forum/show_board.php'], From 835dda9659cb6b419baf25807ecf9f5cd5ca8b04 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 5 Jun 2025 19:08:53 +0200 Subject: [PATCH 023/216] Remove duplicated code - account redirect, already in account/manage --- system/pages/account/redirect.php | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 system/pages/account/redirect.php diff --git a/system/pages/account/redirect.php b/system/pages/account/redirect.php deleted file mode 100644 index 78bc54d9..00000000 --- a/system/pages/account/redirect.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @author Slawkens - * @copyright 2019 MyAAC - * @link https://my-aac.org - */ -defined('MYAAC') or die('Direct access not allowed!'); - -$redirect = urldecode($_REQUEST['redirect']); - -// should never happen, unless hacker modify the URL -if (!str_contains($redirect, BASE_URL)) { - error('Fatal error: Cannot redirect outside the website.'); - return; -} - -$twig->display('account.redirect.html.twig', array( - 'redirect' => $redirect -)); From f78285030708ad3c74ab048711f73bbf3ee5281e Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 6 Jun 2025 22:10:13 +0200 Subject: [PATCH 024/216] Move counter & visitors code before router In case someone wants to include that info on page --- index.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/index.php b/index.php index bc8a3663..87204e01 100644 --- a/index.php +++ b/index.php @@ -117,6 +117,14 @@ if(setting('core.backward_support')) { $config['status']['serverStatus_' . $key] = $value; } +if(setting('core.views_counter')) { + require_once SYSTEM . 'counter.php'; +} + +if(setting('core.visitors_counter')) { + $visitors = new Visitors(setting('core.visitors_counter_ttl')); +} + require_once SYSTEM . 'router.php'; // anonymous usage statistics @@ -153,13 +161,6 @@ if(setting('core.anonymous_usage_statistics')) { } } -if(setting('core.views_counter')) - require_once SYSTEM . 'counter.php'; - -if(setting('core.visitors_counter')) { - $visitors = new Visitors(setting('core.visitors_counter_ttl')); -} - /** * @var OTS_Account $account_logged */ From 8d29fdb98b92dbc3d2853ef88a185c67036b4a77 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 9 Jun 2025 14:24:22 +0200 Subject: [PATCH 025/216] Set TinyMCE license key to gpl (Avoid warning message in browser console) --- system/templates/tinymce.html.twig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/templates/tinymce.html.twig b/system/templates/tinymce.html.twig index effea162..7f065477 100644 --- a/system/templates/tinymce.html.twig +++ b/system/templates/tinymce.html.twig @@ -23,6 +23,8 @@ {title: 'Colored Table', value: 'myaac-table'}, ], + license_key: 'gpl', + setup: function (ed) { ed.on('NodeChange', function (e) { if (ed.getContent() !== lastContent) { From 309c1fb715b882e67cb673b1544a03befbf64a22 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 9 Jun 2025 14:24:36 +0200 Subject: [PATCH 026/216] Remove deprecated TinyMCE plugin - template --- system/templates/tinymce.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/templates/tinymce.html.twig b/system/templates/tinymce.html.twig index 7f065477..00f1638a 100644 --- a/system/templates/tinymce.html.twig +++ b/system/templates/tinymce.html.twig @@ -8,7 +8,7 @@ selector: "#editor", content_css: '{{ constant('ADMIN_URL') }}template/style.css', theme: "silver", - plugins: 'preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help code emoticons', + plugins: 'preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help code emoticons', toolbar1: 'formatselect | bold italic strikethrough forecolor backcolor | emoticons link | alignleft aligncenter alignright alignjustify | numlist bullist outdent indent | removeformat code', resize: 'both', image_advtab: true, From 0812fe025d3bd13ddc9b40ebc851b5f2185123e6 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 9 Jun 2025 21:14:44 +0200 Subject: [PATCH 027/216] Update settings_save.php --- admin/tools/settings_save.php | 1 - 1 file changed, 1 deletion(-) diff --git a/admin/tools/settings_save.php b/admin/tools/settings_save.php index dffea976..b161838c 100644 --- a/admin/tools/settings_save.php +++ b/admin/tools/settings_save.php @@ -1,6 +1,5 @@ Date: Mon, 9 Jun 2025 21:18:42 +0200 Subject: [PATCH 028/216] Add missing csrf() into account manage actions --- .../tibiacom/account.management.html.twig | 104 ++++++++++-------- 1 file changed, 58 insertions(+), 46 deletions(-) diff --git a/templates/tibiacom/account.management.html.twig b/templates/tibiacom/account.management.html.twig index 5125f3ed..7d8cf37c 100644 --- a/templates/tibiacom/account.management.html.twig +++ b/templates/tibiacom/account.management.html.twig @@ -11,13 +11,14 @@ - - - + - - + + +
+
+ + {{ csrf() }} {{ include('buttons.logout.html.twig') }} -
@@ -59,13 +60,14 @@
- - - + - - + + +
+
+ + {{ csrf() }} {{ include('buttons.register_account.html.twig') }} -
@@ -94,13 +96,14 @@
- - - + - - + + +
+
+ + {{ csrf() }} {{ include('buttons.edit.html.twig') }} -
@@ -177,26 +180,29 @@ - - - + - - + + +
+
+ + {{ csrf() }} {{ include('buttons.change_password.html.twig') }} -
- - - + - - + + +
+
+ + {{ csrf() }} + {{ include('buttons.change_email.html.twig') }} -
@@ -204,13 +210,14 @@ {% if recovery_key is empty %} - - - + - - + + +
+
+ + {{ csrf() }} {{ include('buttons.register_account.html.twig') }} -
{% endif %} @@ -258,13 +265,14 @@ - - - + - - + + +
+
+ + {{ csrf() }} {{ include('buttons.edit.html.twig') }} -
@@ -398,8 +406,9 @@ - @@ -410,8 +419,9 @@ - - -
+
+ {{ csrf() }} {{ include('buttons.create_character.html.twig') }}
- @@ -423,8 +433,9 @@ From 4def6a6cae47d28451662a519334f43df509b956 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 10:39:45 +0200 Subject: [PATCH 041/216] Style --- system/templates/guilds.view.html.twig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/templates/guilds.view.html.twig b/system/templates/guilds.view.html.twig index 8f29dbf6..b8c0d0be 100644 --- a/system/templates/guilds.view.html.twig +++ b/system/templates/guilds.view.html.twig @@ -62,6 +62,7 @@ {{ hook('HOOK_GUILDS_AFTER_GUILD_INFORMATION') }} {% set title = 'Guild Members' %} + {% set background = config('lightborder') %} {% set content %}
+
+ {{ csrf() }} {{ include('buttons.change_name.html.twig') }}
- @@ -436,8 +447,9 @@
+
+ {{ csrf() }} {{ include('buttons.change_sex.html.twig') }}
- From fffb427eaed880b49a305a6351853c47eabe021a Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 9 Jun 2025 21:18:45 +0200 Subject: [PATCH 029/216] Update account.generate_recovery_key.html.twig --- .../account.generate_recovery_key.html.twig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/system/templates/account.generate_recovery_key.html.twig b/system/templates/account.generate_recovery_key.html.twig index c34132f0..526d4659 100644 --- a/system/templates/account.generate_recovery_key.html.twig +++ b/system/templates/account.generate_recovery_key.html.twig @@ -32,14 +32,14 @@ To generate recovery key for your account please enter your password.

From 524e982a0e343a3d36966ca8c01db4ef0e924175 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 11 Jun 2025 05:51:39 +0200 Subject: [PATCH 030/216] Release v1.6.1 --- CHANGELOG-1.x.md | 13 +++++++++++++ common.php | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index d3d81a56..ddee50e6 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,18 @@ # Changelog +## [1.6.1 - 11.06.2025] + +### Fixed +* Fixed "Request has been cancelled due to security reasons", cause of missing csrf() in twig files (https://github.com/slawkens/myaac/commit/10cd71a6630ffec91b43a26a6d685b66c5836a6a) +* Fix: Ignore duplicated route exception (https://github.com/slawkens/myaac/commit/9d8e9d27bd87167d8d4005942a6af62bfe4c0892) + +### Changed +* Move counter & visitors code before router (In case someone wants to include that info on page) (https://github.com/slawkens/myaac/commit/f78285030708ad3c74ab048711f73bbf3ee5281e) +* Set TinyMCE license key to gpl (Avoid warning message in browser console) (https://github.com/slawkens/myaac/commit/8d29fdb98b92dbc3d2853ef88a185c67036b4a77) + +### Removed +* Remove deprecated TinyMCE plugin - template (https://github.com/slawkens/myaac/commit/309c1fb715b882e67cb673b1544a03befbf64a22) + ## [1.6 - 03.06.2025] ### Added diff --git a/common.php b/common.php index 2af620c9..6df62349 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.6.1-dev'; +const MYAAC_VERSION = '1.6.1'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 0c95bcfd06b68b21512e477646ef7bd3a0d4912b Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 13 Jun 2025 21:03:09 +0200 Subject: [PATCH 031/216] Better $title inventing --- system/router.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/router.php b/system/router.php index 20f3f07a..a6da5f4b 100644 --- a/system/router.php +++ b/system/router.php @@ -326,7 +326,9 @@ if (isset($_REQUEST['_page_only'])) { if(!isset($title)) { $title = str_replace('index.php/', '', $page); - $title = ucfirst($title); + $title = str_replace(['_', '-', '/'], ' ', $page); + + $title = ucwords($title); } if(setting('core.backward_support')) { From 98b13c91a4efc06d78cbefa0a2b37ec86766a717 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 13 Jun 2025 21:24:52 +0200 Subject: [PATCH 032/216] Update notice about how to enable Visitors Counter --- admin/pages/visitors.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/admin/pages/visitors.php b/admin/pages/visitors.php index 9e83d339..f0ac731f 100644 --- a/admin/pages/visitors.php +++ b/admin/pages/visitors.php @@ -19,8 +19,7 @@ $use_datatable = true; if (!setting('core.visitors_counter')): ?> Visitors counter is disabled.
- You can enable it by editing this configurable in config.local.php file:
-

$config['visitors_counter'] = true;

+ You can enable it Settings -> General -> Visitors Counter.
Date: Fri, 13 Jun 2025 21:25:13 +0200 Subject: [PATCH 033/216] Ignore empty values --- admin/pages/visitors.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/pages/visitors.php b/admin/pages/visitors.php index f0ac731f..dfc92ff0 100644 --- a/admin/pages/visitors.php +++ b/admin/pages/visitors.php @@ -45,7 +45,7 @@ foreach ($tmp as &$visitor) { if ($dd->isBot()) { $bot = $dd->getBot(); $message = '(Bot) %s, %s'; - $browser = sprintf($message, $bot['category'], $bot['url'], $bot['name']); + $browser = sprintf($message, $bot['category'] ?? 'Unknown', $bot['url'] ?? '', $bot['name'] ?? 'Unknown name'); } else { $osFamily = OperatingSystem::getOsFamily($dd->getOs('name')); From 4d4f7759d32ebac6536c767b34f254a4a8bd55c3 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 13 Jun 2025 21:31:04 +0200 Subject: [PATCH 034/216] Update visitors.php --- admin/pages/visitors.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/pages/visitors.php b/admin/pages/visitors.php index dfc92ff0..9fae4d24 100644 --- a/admin/pages/visitors.php +++ b/admin/pages/visitors.php @@ -19,7 +19,7 @@ $use_datatable = true; if (!setting('core.visitors_counter')): ?> Visitors counter is disabled.
- You can enable it Settings -> General -> Visitors Counter.
+ You can enable it in Settings -> General -> Visitors Counter.
Date: Fri, 13 Jun 2025 22:14:20 +0200 Subject: [PATCH 035/216] Nothing important: convert to tabs --- system/libs/pot/OTS_Toolbox.php | 104 ++++++++++++++++---------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/system/libs/pot/OTS_Toolbox.php b/system/libs/pot/OTS_Toolbox.php index 980e5cb5..567f318d 100644 --- a/system/libs/pot/OTS_Toolbox.php +++ b/system/libs/pot/OTS_Toolbox.php @@ -15,7 +15,7 @@ /** * Toolbox for common operations. - * + * * @package POT * @version 0.1.5 */ @@ -23,41 +23,41 @@ class OTS_Toolbox { /** * Calculates experience points needed for given level. - * + * * @param int $level Level for which experience should be calculated. * @param int $experience Current experience points. * @return int Experience points for level. */ public static function experienceForLevel($level, $experience = 0) - { - //return 50 * ($level - 1) * ($level * $level - 5 * $level + 12) / 3 - $experience; + { + //return 50 * ($level - 1) * ($level * $level - 5 * $level + 12) / 3 - $experience; $level = $level - 1; return ((50 * $level * $level * $level) - (150 * $level * $level) + (400 * $level)) / 3; - } + } /** * Finds out which level user have basing on his/her experience. - * + * *

* PHP doesn't support complex numbers natively so solving third-level polynomials would be quite hard. Rather then doing this, this method iterates calculating experience for next levels until it finds one which requires enought experience we have. Because of that, for high experience values this function can take relatively long time to be executed. *

- * + * * @param int $experience Current experience points. * @return int Experience level. */ - public static function levelForExperience($experience) - { - // default level - $level = 1; + public static function levelForExperience($experience) + { + // default level + $level = 1; - // until we will find level which requires more experience then we have we will step to next - while( self::experienceForLevel($level + 1) <= $experience) - { - $level++; - } + // until we will find level which requires more experience then we have we will step to next + while( self::experienceForLevel($level + 1) <= $experience) + { + $level++; + } - return $level; - } + return $level; + } /** * @version 0.1.5 @@ -65,25 +65,25 @@ class OTS_Toolbox * @return OTS_Players_List Filtered list. * @deprecated 0.1.5 Use OTS_PlayerBans_List. */ - public static function bannedPlayers() - { - // creates filter - $filter = new OTS_SQLFilter(); - $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_PLAYER); - $filter->addFilter( new OTS_SQLField('active', 'bans'), 1); - $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'players') ); + public static function bannedPlayers() + { + // creates filter + $filter = new OTS_SQLFilter(); + $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_PLAYER); + $filter->addFilter( new OTS_SQLField('active', 'bans'), 1); + $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'players') ); - // selects only active bans - $actives = new OTS_SQLFilter(); - $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0); - $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR); - $filter->addFilter($actives); + // selects only active bans + $actives = new OTS_SQLFilter(); + $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0); + $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR); + $filter->addFilter($actives); - // creates list and aplies filter - $list = new OTS_Players_List(); - $list->setFilter($filter); - return $list; - } + // creates list and aplies filter + $list = new OTS_Players_List(); + $list->setFilter($filter); + return $list; + } /** * @version 0.1.5 @@ -91,25 +91,25 @@ class OTS_Toolbox * @return OTS_Accounts_List Filtered list. * @deprecated 0.1.5 Use OTS_AccountBans_List. */ - public static function bannedAccounts() - { - // creates filter - $filter = new OTS_SQLFilter(); - $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_ACCOUNT); - $filter->addFilter( new OTS_SQLField('active', 'bans'), 1); - $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'accounts') ); + public static function bannedAccounts() + { + // creates filter + $filter = new OTS_SQLFilter(); + $filter->addFilter( new OTS_SQLField('type', 'bans'), POT::BAN_ACCOUNT); + $filter->addFilter( new OTS_SQLField('active', 'bans'), 1); + $filter->addFilter( new OTS_SQLField('value', 'bans'), new OTS_SQLField('id', 'accounts') ); - // selects only active bans - $actives = new OTS_SQLFilter(); - $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0); - $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR); - $filter->addFilter($actives); + // selects only active bans + $actives = new OTS_SQLFilter(); + $actives->addFilter( new OTS_SQLField('expires', 'bans'), 0); + $actives->addFilter( new OTS_SQLField('time', 'bans'), time(), OTS_SQLFilter::OPERATOR_GREATER, OTS_SQLFilter::CRITERIUM_OR); + $filter->addFilter($actives); - // creates list and aplies filter - $list = new OTS_Accounts_List(); - $list->setFilter($filter); - return $list; - } + // creates list and aplies filter + $list = new OTS_Accounts_List(); + $list->setFilter($filter); + return $list; + } } /**#@-*/ From e222957893c4a1de0dc8dbba55bce1a43418d275 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 13 Jun 2025 22:25:36 +0200 Subject: [PATCH 036/216] OTS_Toolbox::getVocationName($id, $promotion); --- system/libs/pot/OTS_Player.php | 11 ++--------- system/libs/pot/OTS_Toolbox.php | 9 +++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/system/libs/pot/OTS_Player.php b/system/libs/pot/OTS_Player.php index 7b688d1c..4b859dd9 100644 --- a/system/libs/pot/OTS_Player.php +++ b/system/libs/pot/OTS_Player.php @@ -2953,21 +2953,14 @@ class OTS_Player extends OTS_Row_DAO * @return string Player proffesion name. * @throws E_OTS_NotLoaded If player is not loaded or global vocations list is not loaded. */ - public function getVocationName() + public function getVocationName(): string { if( !isset($this->data['vocation']) ) { throw new E_OTS_NotLoaded(); } - global $config; - $voc = $this->getVocation(); - if(!isset($config['vocations'][$voc])) { - return 'Unknown'; - } - - return $config['vocations'][$voc]; - //return POT::getInstance()->getVocationsList()->getVocationName($this->data['vocation']); + return OTS_Toolbox::getVocationName($this->data['vocation'], $this->data['promotion'] ?? 0); } /** diff --git a/system/libs/pot/OTS_Toolbox.php b/system/libs/pot/OTS_Toolbox.php index 567f318d..575dba6f 100644 --- a/system/libs/pot/OTS_Toolbox.php +++ b/system/libs/pot/OTS_Toolbox.php @@ -110,6 +110,15 @@ class OTS_Toolbox $list->setFilter($filter); return $list; } + + public static function getVocationName($id, $promotion = 0): string + { + if($promotion > 0) { + $id = ($id + ($promotion * config('vocations_amount'))); + } + + return config('vocations')[$id] ?? 'Unknown'; + } } /**#@-*/ From c074a48f245df55646b6705737f667b6a84149b2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 00:44:00 +0200 Subject: [PATCH 037/216] New hook: HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS --- system/src/global.php | 1 + system/templates/account.management.html.twig | 2 ++ templates/tibiacom/account.management.html.twig | 5 ++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/system/src/global.php b/system/src/global.php index f374568d..37f507a0 100644 --- a/system/src/global.php +++ b/system/src/global.php @@ -54,6 +54,7 @@ define('HOOK_ACCOUNT_MANAGE_BEFORE_GENERAL_INFORMATION', ++$i); define('HOOK_ACCOUNT_MANAGE_BEFORE_PUBLIC_INFORMATION', ++$i); define('HOOK_ACCOUNT_MANAGE_BEFORE_ACCOUNT_LOGS', ++$i); define('HOOK_ACCOUNT_MANAGE_BEFORE_CHARACTERS', ++$i); +define('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS', ++$i); define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i); define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i); define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i); diff --git a/system/templates/account.management.html.twig b/system/templates/account.management.html.twig index 2db1e57c..03e2c2a6 100644 --- a/system/templates/account.management.html.twig +++ b/system/templates/account.management.html.twig @@ -228,5 +228,7 @@
+
+ {{ csrf() }} {{ include('buttons.delete_character.html.twig') }}
- - {{ csrf() }} - - + - - + + +
+
+ + {{ csrf() }} {{ include('buttons.back.html.twig') }} -
+
+ {{ hook('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS') }} diff --git a/templates/tibiacom/account.management.html.twig b/templates/tibiacom/account.management.html.twig index 7d8cf37c..649eba36 100644 --- a/templates/tibiacom/account.management.html.twig +++ b/templates/tibiacom/account.management.html.twig @@ -463,4 +463,7 @@
{% endset %} {% include 'tables.headline.html.twig' %} -

+
+{{ hook('HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS') }} + +
From 00c3635c5ff5800056432b29f2bd3a2f21417394 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 00:59:10 +0200 Subject: [PATCH 038/216] Add $config['site']['serverPath'] for better compatibility with Gesior --- index.php | 1 + 1 file changed, 1 insertion(+) diff --git a/index.php b/index.php index 87204e01..bf7069d4 100644 --- a/index.php +++ b/index.php @@ -93,6 +93,7 @@ if(setting('core.backward_support')) { if($logged && $account_logged) $group_id_of_acc_logged = $account_logged->getGroupId(); + $config['serverPath'] = $config['server_path']; $config['site'] = &$config; $config['server'] = &$config['lua']; $config['site']['shop_system'] = setting('core.gifts_system'); From 522f6c11d835afd36fd07a07074d96d7e219b488 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 08:26:43 +0200 Subject: [PATCH 039/216] Add OTS_Player->isNameLocked() --- system/libs/pot/OTS_Player.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/system/libs/pot/OTS_Player.php b/system/libs/pot/OTS_Player.php index 4b859dd9..099f5db1 100644 --- a/system/libs/pot/OTS_Player.php +++ b/system/libs/pot/OTS_Player.php @@ -2919,6 +2919,32 @@ class OTS_Player extends OTS_Row_DAO $this->data['banned'] = $ban['active']; $this->data['banned_time'] = $ban['expires']; } + + public function isNameLocked(): bool + { + // nothing can't be banned + if( !$this->isLoaded() ) { + throw new E_OTS_NotLoaded(); + } + + if($this->db->hasTable('player_namelocks')) { + $ban = $this->db->query('SELECT 1 FROM `player_namelocks` WHERE `player_id` = ' . $this->data['id'])->fetch(PDO::FETCH_ASSOC); + return (isset($ban['1'])); + } + else if($this->db->hasTable('bans')) { + if($this->db->hasColumn('bans', 'active')) { + $ban = $this->db->query('SELECT `active`, `expires` FROM `bans` WHERE `type` = 2 AND `active` = 1 AND `value` = ' . $this->data['id'] . ' AND (`expires` > ' . time() .' OR `expires` = -1) ORDER BY `expires` DESC')->fetch(); + return isset($ban['active']); + } + else { // tfs 0.2 + $ban = $this->db->query('SELECT `time` FROM `bans` WHERE `type` = 2 AND `account` = ' . $this->data['account_id'] . ' AND (`time` > ' . time() .' OR `time` = -1) ORDER BY `time` DESC')->fetch(); + + return isset($ban['time']) && ($ban['time'] == -1 || $ban['time'] > 0); + } + } + + return false; + } /** * Deletes player. * From e6100a1b72de8695bba1dae9ba4e28bfdce47b10 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 10:36:38 +0200 Subject: [PATCH 040/216] New hook: HOOK_GUILDS_AFTER_MANAGE_BUTTON --- system/src/global.php | 1 + system/templates/guilds.view.html.twig | 1 + 2 files changed, 2 insertions(+) diff --git a/system/src/global.php b/system/src/global.php index 37f507a0..8f1885f3 100644 --- a/system/src/global.php +++ b/system/src/global.php @@ -93,6 +93,7 @@ define('HOOK_EMAIL_CONFIRMED', ++$i); define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i); define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i); define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i); +define('HOOK_GUILDS_AFTER_MANAGE_BUTTON', ++$i); define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i); define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i); define('HOOK_TWIG', ++$i); diff --git a/system/templates/guilds.view.html.twig b/system/templates/guilds.view.html.twig index a25d9570..8f29dbf6 100644 --- a/system/templates/guilds.view.html.twig +++ b/system/templates/guilds.view.html.twig @@ -49,6 +49,7 @@ {% include('buttons.base.html.twig') %} {% endif %} + {{ hook('HOOK_GUILDS_AFTER_MANAGE_BUTTON') }}
@@ -152,6 +153,7 @@ {{ hook('HOOK_GUILDS_AFTER_GUILD_MEMBERS') }} {% set title = 'Invited Characters' %} + {% set background = config('lightborder') %} {% set content %}
From b8abc11b96156da929122e9542994a3a7328fd26 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 11:33:47 +0200 Subject: [PATCH 042/216] Update list.php --- system/pages/guilds/list.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/system/pages/guilds/list.php b/system/pages/guilds/list.php index 26d77d3a..94c49854 100644 --- a/system/pages/guilds/list.php +++ b/system/pages/guilds/list.php @@ -36,10 +36,9 @@ if(count($guilds_list) > 0) { $guildName = $guild->getName(); $guilds[] = array('name' => $guildName, 'logo' => $guild_logo, 'link' => getGuildLink($guildName, false), 'description' => $description); } -}; +} $twig->display('guilds.list.html.twig', array( 'guilds' => $guilds, - 'logged' => $logged ?? false, 'isAdmin' => admin(), )); From 577037beccd740168d56b05124f95c2d28ab803a Mon Sep 17 00:00:00 2001 From: Goosey Date: Sat, 14 Jun 2025 17:58:08 +0400 Subject: [PATCH 043/216] fix: boostedcreatures for 13.40 (#307) * boostedcreatures fix for 13.40 Fixes the boosted boss/creature display on the login page for 13.40 running the default cipsoft client. * Adjust version --------- Co-authored-by: slawkens --- login.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/login.php b/login.php index 88d5d88a..d4d25529 100644 --- a/login.php +++ b/login.php @@ -88,8 +88,8 @@ switch ($action) { case 'boostedcreature': $clientVersion = (int)setting('core.client'); - // 14.00 and up - if ($clientVersion >= 1400) { + // 13.40 and up + if ($clientVersion >= 1340) { $creatureBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_creature'))->fetchAll(); $bossBoost = $db->query("SELECT * FROM " . $db->tableName('boosted_boss'))->fetchAll(); die(json_encode([ From a7efacdbacdee40a470e010eb239147d378ecbdb Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 20:50:54 +0200 Subject: [PATCH 044/216] Delete online.form, use revamped characters.form --- system/pages/online.php | 2 +- system/templates/characters.form.html.twig | 40 +++++++++++++--------- system/templates/online.form.html.twig | 25 -------------- 3 files changed, 24 insertions(+), 43 deletions(-) delete mode 100644 system/templates/online.form.html.twig diff --git a/system/pages/online.php b/system/pages/online.php index 4f0baa7d..f292a4b1 100644 --- a/system/pages/online.php +++ b/system/pages/online.php @@ -127,5 +127,5 @@ $twig->display('online.html.twig', array( )); //search bar -$twig->display('online.form.html.twig'); +$twig->display('characters.form.html.twig'); ?> diff --git a/system/templates/characters.form.html.twig b/system/templates/characters.form.html.twig index d731b4e2..0fd85608 100644 --- a/system/templates/characters.form.html.twig +++ b/system/templates/characters.form.html.twig @@ -1,17 +1,23 @@ -
-
- - - - -
Search Character
- - - - - -
Name: - {{ include('buttons.submit.html.twig') }} -
-
- \ No newline at end of file +
+
+ {% set title = 'Search Character' %} + {% set tableClass = 'Table1' %} + {% set background = config('darkborder') %} + {% set content %} + + + + + + +
+ Character Name: + + + + {% set button_name = 'Submit' %} + {{ include('buttons.base.html.twig') }} +
+ {% endset %} + {{ include('tables.headline.html.twig') }} +
diff --git a/system/templates/online.form.html.twig b/system/templates/online.form.html.twig deleted file mode 100644 index 82c6f7b2..00000000 --- a/system/templates/online.form.html.twig +++ /dev/null @@ -1,25 +0,0 @@ -
-
- - - - - - - -
- Search Character -
- - - - - - -
Name: - - - {{ include('buttons.submit.html.twig') }} -
-
-
\ No newline at end of file From ba4ed6a04b285bc179ca4db89409a6f0168524c1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 20:52:38 +0200 Subject: [PATCH 045/216] Add LabelV120, LabelV150, LabelV200 --- templates/kathrine/style.css | 21 +++++++++++++++++++++ templates/tibiacom/basic.css | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/templates/kathrine/style.css b/templates/kathrine/style.css index a021b1d9..45a1a9d4 100644 --- a/templates/kathrine/style.css +++ b/templates/kathrine/style.css @@ -453,6 +453,27 @@ a:hover white-space: nowrap; vertical-align: top; } +.LabelV120 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 120px; +} +.LabelV150 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 150px; +} +.LabelV200 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 200px; +} .LabelH { font-weight: bold; padding-right: 10px; diff --git a/templates/tibiacom/basic.css b/templates/tibiacom/basic.css index 4633c5ed..a4f0fc24 100644 --- a/templates/tibiacom/basic.css +++ b/templates/tibiacom/basic.css @@ -1446,6 +1446,27 @@ img { white-space: nowrap; vertical-align: top; } +.LabelV120 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 120px; +} +.LabelV150 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 150px; +} +.LabelV200 { + font-weight: bold; + padding-right: 10px; + white-space: nowrap; + vertical-align: top; + width: 200px; +} .LabelH { font-weight: bold; padding-right: 10px; From 9a90e4aae280e607430511c6727d9a714b11f4c5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 21:12:47 +0200 Subject: [PATCH 046/216] Revamped online page --- images/order_asc.gif | Bin 0 -> 56 bytes images/order_desc.gif | Bin 0 -> 56 bytes system/pages/online.php | 26 +++-- system/settings.php | 6 ++ system/templates/online.html.twig | 162 +++++++++++++++++++----------- 5 files changed, 127 insertions(+), 67 deletions(-) create mode 100644 images/order_asc.gif create mode 100644 images/order_desc.gif diff --git a/images/order_asc.gif b/images/order_asc.gif new file mode 100644 index 0000000000000000000000000000000000000000..c9698a5a02f81238b51b1d12bf85840fb7c1fdbe GIT binary patch literal 56 zcmZ?wbhEHbgRG IH3Ne+0CC0*ssI20 literal 0 HcmV?d00001 diff --git a/images/order_desc.gif b/images/order_desc.gif new file mode 100644 index 0000000000000000000000000000000000000000..4a764bd585acf65719cff63448779a4b584fdd09 GIT binary patch literal 56 zcmZ?wbhEHbhasColumn('players', 'promotion')) $promotion = '`promotion`,'; -$order = $_GET['order'] ?? 'name'; -if(!in_array($order, array('country', 'name', 'level', 'vocation'))) - $order = $db->fieldName('name'); -else if($order == 'country') - $order = $db->tableName('accounts') . '.' . $db->fieldName('country'); -else if($order == 'vocation') - $order = $promotion . 'vocation ASC'; +$order = $_GET['order'] ?? 'name_asc'; +if(!in_array($order, ['country_asc', 'country_desc', 'name_asc', 'name_desc', 'level_asc', 'level_desc', 'vocation_asc', 'vocation_desc'])) { + $order = 'name_asc'; +} +else if($order == 'vocation_asc' || $order == 'vocation_desc') { + $order = $promotion . 'vocation_' . (str_contains($order, 'asc') ? 'asc' : 'desc'); +} + +$orderExplode = explode('_', $order); +$orderSql = $orderExplode[0] . ' ' . $orderExplode[1]; $skull_type = 'skull'; if($db->hasColumn('players', 'skull_type')) { @@ -58,11 +61,11 @@ if (setting('core.online_vocations')) { } if($db->hasTable('players_online')) // tfs 1.0 - $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $order); + $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); else - $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $order); + $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); -$players_data = array(); +$players_data = []; $players = 0; $data = ''; foreach($playersOnline as $player) { @@ -115,7 +118,7 @@ if(count($players_data) > 0) { } if($result) { - $record = 'The maximum on this game world was ' . $result['record'] . ' players' . ($timestamp ? ' on ' . date("M d Y, H:i:s", $result['timestamp']) . '.' : '.'); + $record = $result['record'] . ' player' . ($result['record'] > 1 ? 's' : '') . ($timestamp ? ' (on ' . date("M d Y, H:i:s", $result['timestamp']) . ')' : ''); } } } @@ -124,6 +127,7 @@ $twig->display('online.html.twig', array( 'players' => $players_data, 'record' => $record, 'vocs' => $vocs, + 'order' => $order, )); //search bar diff --git a/system/settings.php b/system/settings.php index 4cfe5c9f..40c8be03 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1264,6 +1264,12 @@ Sent by MyAAC,
'desc' => '', 'default' => false, ], + 'online_datacenter' => [ + 'name' => 'Data Center', + 'type' => 'text', + 'desc' => 'Server Location, will be shown on online page', + 'default' => 'Frankfurt - Germany', + ], [ 'type' => 'section', 'title' => 'Team Page' diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index 0210d80f..2555873e 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -1,39 +1,7 @@ - - - - -{% if players|length == 0 %} -
Server Status
Currently no one is playing on {{ config.lua.serverName }}.
-{% else %} -
- {% if not status.online %} - Server is offline.
- {% else %} - {% if setting('core.online_afk') %} - {% set players_count = players|length %} - {% set afk = players_count - status.players %} - {% if afk < 0 %} - {% set players_count = players_count + afk|abs %} - {% set afk = 0 %} - {% endif %} - Currently there are {{ status.players }} active and {{ afk }} AFK players.
- Total number of players: {{ players_count }}.
- {% else %} - Currently {{ players|length }} players are online.
- {% endif %} - {% endif %} - {% if setting('core.online_record') %} - {{ record }} - {% endif %} -
+{# vocation statistics #} +{% if setting('core.online_vocations') %}
- {# vocation statistics #} - {% if setting('core.online_vocations') %} -
- {% if setting('core.online_vocations_images') %} + {% if setting('core.online_vocations_images') %} @@ -69,11 +37,13 @@ {% endfor %}

- {% endif %} {% endif %} +{% endif %} - {# show skulls #} - {% if setting('core.online_skulls') %} +
+ +{# show skulls #} +{% if setting('core.online_skulls') %}
@@ -83,34 +53,114 @@
+{% endif %} + +
+ +{% set title = 'World Information' %} +{% set tableClass = 'Table3' %} +{% set background = config('darkborder') %} +{% set content %} + + + + + + + + + + + {% if setting('core.online_record') %} + + + + {% endif %} -
Status:{% if not status.online %}Offline{% else %}Online{% endif %}
Players Online: + {% if setting('core.online_afk') %} + {% set players_count = players|length %} + {% set afk = players_count - status.players %} + {% if afk < 0 %} + {% set players_count = players_count + afk|abs %} + {% set afk = 0 %} + {% endif %} + Currently there are {{ status.players }} active and {{ afk }} AFK players.
+ Total number of players: {{ players_count }}.
+ {% else %} + {{ players|length }} Players Online. + {% endif %} +
Online Record: + {{ record }} +
- + + + + + + + + +
Location Datacenter:{{ setting('core.online_datacenter') }} (Server date & time: - {{ "now"|date("d/m/Y H:i:s") }})
PvP Type: + {% set worldType = config('lua')['worldType']|lower %} + {% if worldType in ['pvp','2','normal','open','openpvp'] %} + Open PvP + {% elseif worldType in ['no-pvp','nopvp','non-pvp','nonpvp','1','safe','optional','optionalpvp'] %} + Optional PvP + {% elseif worldType in ['pvp-enforced','pvpenforced','pvp-enfo','pvpenfo','pvpe','enforced','enfo','3','war','hardcore','hardcorepvp'] %} + Hardcore PvP + {% endif %} +
+{% endset %} +{% include 'tables.headline.html.twig' %} +
+
+ +{% set title = 'Players Online' %} +{% set tableClass = 'Table2' %} +{% set content %} + + {% if setting('core.account_country') %} - + {% endif %} {% if setting('core.online_outfit') %} - + {% endif %} - - - + + + + {% set i = 0 %} {% for player in players %} {% set i = i + 1 %} - - {% if setting('core.account_country') %} - - {% endif %} - {% if setting('core.online_outfit') %} - - {% endif %} - - - + + + {% if setting('core.account_country') %} + + {% endif %} + + {% if setting('core.online_outfit') %} + + {% endif %} + + + + {% endfor %}
##   + OutfitOutfitNameLevelVocationName   + [sort] + Level   + [sort] + + Vocation   + [sort] + +
{{ player.country_image|raw }}player outfit{{ player.name|raw }}{{ player.skull }}{{ player.level }}{{ player.vocation }}
{{ player.country_image|raw }}player outfit + {{ player.name|raw }}{{ player.skull }} + {{ player.level }}{{ player.vocation }}
-{% endif %} +{% endset %} +{{ include('tables.headline.html.twig') }} From 4767120043b09141870383e249f3729638d53dc2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 14 Jun 2025 21:19:52 +0200 Subject: [PATCH 047/216] Update online.html.twig --- system/templates/online.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index 2555873e..26a756ed 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -79,7 +79,7 @@ Currently there are {{ status.players }} active and {{ afk }} AFK players.
Total number of players: {{ players_count }}.
{% else %} - {{ players|length }} Players Online. + {{ players|length }} {% endif %} From 29faa4f6957dcbbcc16fb4468be4871e7d787ace Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 15 Jun 2025 19:03:03 +0200 Subject: [PATCH 048/216] Add missing csrf() in success.html.twig --- system/templates/success.html.twig | 1 + 1 file changed, 1 insertion(+) diff --git a/system/templates/success.html.twig b/system/templates/success.html.twig index 5d9a9b8b..eaee1fb1 100644 --- a/system/templates/success.html.twig +++ b/system/templates/success.html.twig @@ -19,6 +19,7 @@
+ {{ csrf() }} From 8dc42b654473ac4133effd7f26125619bbc64fb2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 15 Jun 2025 19:05:47 +0200 Subject: [PATCH 050/216] Nothing important: just formatting --- .../templates/account.change-email.html.twig | 16 ++++++++-------- ...account.characters.change-comment.html.twig | 18 +++++++++--------- .../account.characters.delete.html.twig | 16 ++++++++-------- system/templates/success.html.twig | 14 +++++++------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/system/templates/account.change-email.html.twig b/system/templates/account.change-email.html.twig index ea627cc7..ab2a8c06 100644 --- a/system/templates/account.change-email.html.twig +++ b/system/templates/account.change-email.html.twig @@ -28,7 +28,7 @@ Please enter your password and the new email address. Make sure that you enter a - + {% for plugin in plugins %} From 566c2a9151ab6392286f74e26853faa19a1b4f24 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 22 Jun 2025 08:48:24 +0200 Subject: [PATCH 055/216] Move out of $cache->enabled --- system/functions.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/functions.php b/system/functions.php index 56cf378b..add481e5 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1263,10 +1263,10 @@ function clearCache() global $db; $db->setClearCacheAfter(true); + } - if (function_exists('apcu_clear_cache')) { - apcu_clear_cache(); - } + if (function_exists('apcu_clear_cache')) { + apcu_clear_cache(); } deleteDirectory(CACHE . 'signatures', ['index.html'], true); From bb830bce4425bec02c42e99e68e9e18fd3eea7dc Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 22 Jun 2025 08:55:29 +0200 Subject: [PATCH 056/216] Release v1.7 --- CHANGELOG-1.x.md | 16 ++++++++++++++++ common.php | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index ddee50e6..34439313 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,21 @@ # Changelog +## [1.7 - 22.06.2025] + +### Added +* Feature: plugins versions check (#310) +* New hooks: HOOK_ACCOUNT_MANAGE_AFTER_CHARACTERS, HOOK_GUILDS_AFTER_MANAGE_BUTTON (https://github.com/slawkens/myaac/commit/c074a48f245df55646b6705737f667b6a84149b2, https://github.com/slawkens/myaac/commit/e6100a1b72de8695bba1dae9ba4e28bfdce47b10) +* Add OTS_Toolbox::getVocationName(id, promotion) + OTS_Player->isNameLocked() (https://github.com/slawkens/myaac/commit/e222957893c4a1de0dc8dbba55bce1a43418d275, https://github.com/slawkens/myaac/commit/522f6c11d835afd36fd07a07074d96d7e219b488) +* Add missing csrf in more places, causing white page with error about Request (https://github.com/slawkens/myaac/commit/dca904e61d21d856bf809070e7652803a2df0f58, https://github.com/slawkens/myaac/commit/c720ccc451ff90ef40b2a1595468d061ffd7e1e4) + +### Changed +* Revamped online page (https://github.com/slawkens/myaac/commit/9a90e4aae280e607430511c6727d9a714b11f4c5, https://github.com/slawkens/myaac/commit/4767120043b09141870383e249f3729638d53dc2) +* Better $title inventing (https://github.com/slawkens/myaac/commit/0c95bcfd06b68b21512e477646ef7bd3a0d4912b) + +### Fixed +* Use apcu cache clear (https://github.com/slawkens/myaac/commit/b329da52aae9d0e21120a6444d3caf442420ce50, https://github.com/slawkens/myaac/commit/566c2a9151ab6392286f74e26853faa19a1b4f24) +* fix: boostedcreatures for 13.40 (by @GooseWithAKnife) (#307) + ## [1.6.1 - 11.06.2025] ### Fixed diff --git a/common.php b/common.php index 6df62349..1ed07a7f 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.6.1'; +const MYAAC_VERSION = '1.7'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 5cfa3a697f37f2a4e75497de68640f975223d5d2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 22 Jun 2025 11:25:45 +0200 Subject: [PATCH 057/216] Start v1.7.1-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 1ed07a7f..e07242b6 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.7'; +const MYAAC_VERSION = '1.7.1-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 6cf4b9dac52dc9de565a9d23b088b776063858da Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 22 Jun 2025 18:51:20 +0200 Subject: [PATCH 058/216] Fix xdebug warnings in load_config_lua --- system/functions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/functions.php b/system/functions.php index add481e5..3ef7a8a2 100644 --- a/system/functions.php +++ b/system/functions.php @@ -982,11 +982,12 @@ function load_config_lua($filename) foreach($lines as $ln => $line) { $line = trim($line); - if(@$line[0] === '{' || @$line[0] === '}') { + if(isset($line[0]) && ($line[0] === '{' || $line[0] === '}')) { // arrays are not supported yet // just ignore the error continue; } + $tmp_exp = explode('=', $line, 2); if(str_contains($line, 'dofile')) { $delimiter = '"'; From 0da524fefe93b3028392e9014550eea3324d3a22 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 23 Jun 2025 00:21:41 +0200 Subject: [PATCH 059/216] Fix plugin install:install command --- system/src/Plugins.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/system/src/Plugins.php b/system/src/Plugins.php index 85f0a2ba..37a1af3c 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -781,15 +781,15 @@ class Plugins { return false; } - if(!isset($plugin_json['install'])) { - self::$error = "Plugin doesn't have install options defined. Skipping..."; - return false; + $install = $plugin_json['install'] ?? ''; + if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $plugin_name . '/install.php')) { + $install = 'plugins/' . $plugin_name . '/install.php'; } global $db; - if (file_exists(BASE . $plugin_json['install'])) { + if (file_exists(BASE . $install)) { $db->revalidateCache(); - require BASE . $plugin_json['install']; + require BASE . $install; $db->revalidateCache(); } else { From 181131f7f3402b324747fdb2e7a32d1d9d9179ee Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 24 Jun 2025 12:44:34 +0200 Subject: [PATCH 060/216] Use __DIR__ instead of template path --- templates/tibiacom/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 6d0d1e63..46ef0698 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -454,7 +454,7 @@ foreach($config['menu_categories'] as $id => $cat) { foreach($config['boxes'] as $box) { /** @var string $template_name */ - $file = TEMPLATES . $template_name . '/boxes/' . $box . '.php'; + $file = __DIR__ . '/boxes/' . $box . '.php'; if(file_exists($file)) { include($file); ?> Date: Tue, 24 Jun 2025 12:44:43 +0200 Subject: [PATCH 061/216] Fix polls link --- templates/tibiacom/boxes/templates/poll.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/tibiacom/boxes/templates/poll.html.twig b/templates/tibiacom/boxes/templates/poll.html.twig index 0b643ee5..25f10865 100644 --- a/templates/tibiacom/boxes/templates/poll.html.twig +++ b/templates/tibiacom/boxes/templates/poll.html.twig @@ -1,6 +1,6 @@
{{ poll.question }}
-
+
From f78ebad136c36ddeace2f90d714d1190af89262e Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 24 Jun 2025 14:57:01 +0200 Subject: [PATCH 062/216] Remove error number from 404 & 405 pages --- system/pages/404.php | 2 +- system/pages/405.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system/pages/404.php b/system/pages/404.php index 90a8921a..60fb66aa 100644 --- a/system/pages/404.php +++ b/system/pages/404.php @@ -8,7 +8,7 @@ * @link https://my-aac.org */ defined('MYAAC') or die('Direct access not allowed!'); -$title = '404 Not Found'; +$title = 'Not Found'; header('HTTP/1.0 404 Not Found'); ?> diff --git a/system/pages/405.php b/system/pages/405.php index 3d585f59..d1eee43a 100644 --- a/system/pages/405.php +++ b/system/pages/405.php @@ -8,7 +8,7 @@ * @link https://my-aac.org */ defined('MYAAC') or die('Direct access not allowed!'); -$title = '405 Method Not Allowed'; +$title = 'Method Not Allowed'; header('HTTP/1.0 405 Method Not Allowed'); ?> From 13d33822b59df349199e885a78a3d6beb0863d0b Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 25 Jun 2025 17:36:02 +0200 Subject: [PATCH 063/216] Rename to plugin:setup, also add alias to previous command --- system/src/Commands/PluginInstallInstallCommand.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/src/Commands/PluginInstallInstallCommand.php b/system/src/Commands/PluginInstallInstallCommand.php index fe1b4f14..116eeb13 100644 --- a/system/src/Commands/PluginInstallInstallCommand.php +++ b/system/src/Commands/PluginInstallInstallCommand.php @@ -12,7 +12,8 @@ class PluginInstallInstallCommand extends Command { protected function configure(): void { - $this->setName('plugin:install:install') + $this->setName('plugin:setup') + ->setAliases(['plugin:install:install']) ->setDescription('This command executes the "install" part of the plugin') ->addArgument('plugin', InputArgument::REQUIRED, 'Plugin name'); } From 6d43fc181fce9a40a78954689a3d0f744a6eea3b Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 25 Jun 2025 17:36:43 +0200 Subject: [PATCH 064/216] In case the script don't have install option, inform the user --- system/src/Plugins.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system/src/Plugins.php b/system/src/Plugins.php index 37a1af3c..c880dd90 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -786,6 +786,11 @@ class Plugins { $install = 'plugins/' . $plugin_name . '/install.php'; } + if (empty($install)) { + self::$error = "This plugin doesn't seem to have install script defined."; + return false; + } + global $db; if (file_exists(BASE . $install)) { $db->revalidateCache(); From 0bff910a056974d4698a02f5a9398d6a2be1f3be Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 25 Jun 2025 19:43:40 +0200 Subject: [PATCH 065/216] adjust command email:send + mail:send (alias) --- system/src/Commands/MailSendCommand.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/system/src/Commands/MailSendCommand.php b/system/src/Commands/MailSendCommand.php index ff1450e6..983e6fc5 100644 --- a/system/src/Commands/MailSendCommand.php +++ b/system/src/Commands/MailSendCommand.php @@ -12,9 +12,10 @@ class MailSendCommand extends Command { protected function configure(): void { - $this->setName('mail:send') + $this->setName('email:send') + ->setAliases(['mail:send']) ->setDescription('This command sends E-Mail to single user. Message can be provided as follows: ' . PHP_EOL - . ' echo "Hello World" | php sa email:send --subject="This is the subject" test@test.com') + . ' echo "Hello World" | php aac email:send --subject="This is the subject" test@test.com') ->addArgument('recipient', InputArgument::REQUIRED, 'Email, Account Name, Account id or Player Name') ->addOption('subject', 's', InputOption::VALUE_REQUIRED, 'Subject'); } From fe8281594e989f00280ba1adc734a9198c6b5cc1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 27 Jun 2025 07:13:33 +0200 Subject: [PATCH 066/216] Fix cache:clear command (missing init) --- system/src/Commands/CacheClearCommand.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/system/src/Commands/CacheClearCommand.php b/system/src/Commands/CacheClearCommand.php index 3b052995..5b1715b5 100644 --- a/system/src/Commands/CacheClearCommand.php +++ b/system/src/Commands/CacheClearCommand.php @@ -17,10 +17,7 @@ class CacheClearCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): int { - global $hooks; - $hooks = new Hooks(); - $hooks->load(); - $hooks->trigger(HOOK_INIT); + require SYSTEM . 'init.php'; $io = new SymfonyStyle($input, $output); From 047742848bf1a14282ceac2af7cc397ce5ae6725 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 27 Jun 2025 07:15:13 +0200 Subject: [PATCH 067/216] Delete clearRouteCache, was useless Directory is cleaned already --- system/functions.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/system/functions.php b/system/functions.php index 3ef7a8a2..a3c302c3 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1275,23 +1275,12 @@ function clearCache() deleteDirectory(CACHE . 'plugins', ['index.html'], true); deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true); - // routes cache - clearRouteCache(); - global $hooks; $hooks->trigger(HOOK_CACHE_CLEAR, ['cache' => Cache::getInstance()]); return true; } -function clearRouteCache(): void -{ - $routeCacheFile = CACHE . 'route.cache'; - if (file_exists($routeCacheFile)) { - unlink($routeCacheFile); - } -} - function getCustomPageInfo($name) { global $logged_access; From b4b62442fe9470e94c94812c533cc132e165003f Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 27 Jun 2025 07:21:19 +0200 Subject: [PATCH 068/216] Release v1.7.1 --- CHANGELOG-1.x.md | 9 +++++++++ common.php | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 34439313..28c946ec 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,14 @@ # Changelog +## [1.7.1 - 27.06.2025] + +### Changed +* Rename plugin:install:install to plugin:setup, also add alias to previous command (https://github.com/slawkens/myaac/commit/13d33822b59df349199e885a78a3d6beb0863d0b) + +### Fixed +* Fix commands: setup + cache:clear (https://github.com/slawkens/myaac/commit/0da524fefe93b3028392e9014550eea3324d3a22, https://github.com/slawkens/myaac/commit/fe8281594e989f00280ba1adc734a9198c6b5cc1) +* Fix polls link in tibiacom template (https://github.com/slawkens/myaac/commit/d90fa323d7c77d81768df60feeb1c374b1650a0c) + ## [1.7 - 22.06.2025] ### Added diff --git a/common.php b/common.php index e07242b6..94395409 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.7.1-dev'; +const MYAAC_VERSION = '1.7.1'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From c92148d467e9c19fdf68d0f77dacec9cfe2e34cf Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 27 Jun 2025 07:23:22 +0200 Subject: [PATCH 069/216] Revert delete clearRouteCache, is used somewhere else --- system/functions.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/system/functions.php b/system/functions.php index a3c302c3..540c9af3 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1281,6 +1281,14 @@ function clearCache() return true; } +function clearRouteCache(): void +{ + $routeCacheFile = CACHE . 'route.cache'; + if (file_exists($routeCacheFile)) { + unlink($routeCacheFile); + } +} + function getCustomPageInfo($name) { global $logged_access; From 45d6047031c9c3a0e7e512dc5d15c75629aec5a2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 5 Jul 2025 14:22:58 +0200 Subject: [PATCH 070/216] Add Coins Transferable to accounts editor --- admin/pages/accounts.php | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/admin/pages/accounts.php b/admin/pages/accounts.php index c2154299..0358753b 100644 --- a/admin/pages/accounts.php +++ b/admin/pages/accounts.php @@ -27,6 +27,13 @@ $nameOrNumberColumn = getAccountIdentityColumn(); $hasSecretColumn = $db->hasColumn('accounts', 'secret'); $hasCoinsColumn = $db->hasColumn('accounts', 'coins'); + +$hasCoinsTransferableColumn = $db->hasColumn('accounts', 'coins_transferable'); +$hasTransferableCoinsColumn = $db->hasColumn('accounts', 'transferable_coins'); +$coinsTransferableColumn = + $hasTransferableCoinsColumn ? + 'transferable_coins' : 'coins_transferable'; + $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $hasTypeColumn = $db->hasColumn('accounts', 'type'); $hasGroupColumn = $db->hasColumn('accounts', 'group_id'); @@ -136,11 +143,18 @@ else if (isset($_REQUEST['search'])) { if (!Validator::email($email)) $errors['email'] = Validator::getLastError(); - //tibia coins + // tibia coins if ($hasCoinsColumn) { $t_coins = $_POST['t_coins']; verify_number($t_coins, 'Tibia coins', 12); } + + // transferable tibia coins + if ($hasCoinsTransferableColumn || $hasTransferableCoinsColumn) { + $t_coins_transferable = $_POST['t_coins_transferable']; + verify_number($t_coins_transferable, 'Transferable Tibia coins', 12); + } + // prem days $p_days = (int)$_POST['p_days']; verify_number($p_days, 'Prem days', 11); @@ -185,12 +199,18 @@ else if (isset($_REQUEST['search'])) { if ($hasSecretColumn) { $account->setCustomField('secret', $secret); } + $account->setCustomField('key', $key); $account->setEMail($email); + if ($hasCoinsColumn) { $account->setCustomField('coins', $t_coins); } + if ($hasCoinsTransferableColumn || $hasTransferableCoinsColumn) { + $account->setCustomField($coinsTransferableColumn, $t_coins_transferable); + } + $lastDay = 0; if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) { $lastDay = time(); @@ -401,6 +421,12 @@ else if (isset($_REQUEST['search'])) { + +
+ + +
+
From a89f9a84847630eb75b4890fdcc8b7a7bfa6b8ac Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 09:22:12 +0200 Subject: [PATCH 071/216] Set $process_sections to true --- system/template.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/template.php b/system/template.php index f051e640..c97c8416 100644 --- a/system/template.php +++ b/system/template.php @@ -91,7 +91,7 @@ else { $file = BASE . $template_path . '/layout_config.ini'; } - $template_ini = parse_ini_file($file); + $template_ini = parse_ini_file($file, true); unset($file); if ($cache->enabled()) { From dcb96f4ce1e0fe90bdbf66036ded51155959b51d Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 13:48:33 +0200 Subject: [PATCH 072/216] Refactor code - early exit --- system/src/Plugins.php | 325 ++++++++++++++++++++--------------------- 1 file changed, 162 insertions(+), 163 deletions(-) diff --git a/system/src/Plugins.php b/system/src/Plugins.php index c880dd90..e1a58620 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -532,193 +532,192 @@ class Plugins { self::$plugin_json = $plugin_json; if ($plugin_json == null) { self::$warnings[] = 'Cannot load ' . $file_name . '. File might be not a valid json code.'; + return false; } - else { - $continue = true; - if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) { - self::$error = 'Plugin "name" tag is not set.'; + $continue = true; + + if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) { + self::$error = 'Plugin "name" tag is not set.'; + return false; + } + + if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) { + self::$warnings[] = 'Plugin "version" tag is not set.'; + } + + if(isset($plugin_json['require'])) { + $require = $plugin_json['require']; + + $myaac_satified = true; + if(isset($require['myaac_'])) { + $require_myaac = $require['myaac_']; + if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) { + $myaac_satified = false; + } + } + else if(isset($require['myaac'])) { + $require_myaac = $require['myaac']; + if(version_compare(MYAAC_VERSION, $require_myaac, '<')) { + $myaac_satified = false; + } + } + + if(!$myaac_satified) { + self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . "."; return false; } - if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) { - self::$warnings[] = 'Plugin "version" tag is not set.'; + $php_satisfied = true; + if(isset($require['php_'])) { + $require_php = $require['php_']; + if(!Semver::satisfies(phpversion(), $require_php)) { + $php_satisfied = false; + } + } + else if(isset($require['php'])) { + $require_php = $require['php']; + if(version_compare(phpversion(), $require_php, '<')) { + $php_satisfied = false; + } } - if(isset($plugin_json['require'])) { - $require = $plugin_json['require']; + if(!$php_satisfied) { + self::$error = "Your PHP version doesn't meet the requirement of this plugin. Required version is: " . $require_php . ", and you're using version " . phpversion() . "."; + $continue = false; + } - $myaac_satified = true; - if(isset($require['myaac_'])) { - $require_myaac = $require['myaac_']; - if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) { - $myaac_satified = false; + $database_satisfied = true; + if(isset($require['database_'])) { + $require_database = $require['database_']; + if(!Semver::satisfies(DATABASE_VERSION, $require_database)) { + $database_satisfied = false; + } + } + else if(isset($require['database'])) { + $require_database = $require['database']; + if(version_compare(DATABASE_VERSION, $require_database, '<')) { + $database_satisfied = false; + } + } + + if(!$database_satisfied) { + self::$error = "Your database version doesn't meet the requirement of this plugin. Required version is: " . $require_database . ", and you're using version " . DATABASE_VERSION . "."; + $continue = false; + } + + if($continue) { + foreach($require as $req => $version) { + $req = strtolower(trim($req)); + $version = trim($version); + + if(in_array($req, array('myaac', 'myaac_', 'php', 'php_', 'database', 'database_'))) { + continue; } - } - else if(isset($require['myaac'])) { - $require_myaac = $require['myaac']; - if(version_compare(MYAAC_VERSION, $require_myaac, '<')) { - $myaac_satified = false; - } - } - if(!$myaac_satified) { - self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . "."; - return false; - } + if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension + $tmpDisplayError = false; + $explode = explode(',', $version); - $php_satisfied = true; - if(isset($require['php_'])) { - $require_php = $require['php_']; - if(!Semver::satisfies(phpversion(), $require_php)) { - $php_satisfied = false; - } - } - else if(isset($require['php'])) { - $require_php = $require['php']; - if(version_compare(phpversion(), $require_php, '<')) { - $php_satisfied = false; - } - } - - if(!$php_satisfied) { - self::$error = "Your PHP version doesn't meet the requirement of this plugin. Required version is: " . $require_php . ", and you're using version " . phpversion() . "."; - $continue = false; - } - - $database_satisfied = true; - if(isset($require['database_'])) { - $require_database = $require['database_']; - if(!Semver::satisfies(DATABASE_VERSION, $require_database)) { - $database_satisfied = false; - } - } - else if(isset($require['database'])) { - $require_database = $require['database']; - if(version_compare(DATABASE_VERSION, $require_database, '<')) { - $database_satisfied = false; - } - } - - if(!$database_satisfied) { - self::$error = "Your database version doesn't meet the requirement of this plugin. Required version is: " . $require_database . ", and you're using version " . DATABASE_VERSION . "."; - $continue = false; - } - - if($continue) { - foreach($require as $req => $version) { - $req = strtolower(trim($req)); - $version = trim($version); - - if(in_array($req, array('myaac', 'myaac_', 'php', 'php_', 'database', 'database_'))) { - continue; + foreach ($explode as $item) { + if(!extension_loaded($item)) { + $errors[] = "This plugin requires php extension: " . $item . " to be installed."; + $tmpDisplayError = true; + } } - if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension - $tmpDisplayError = false; - $explode = explode(',', $version); - - foreach ($explode as $item) { - if(!extension_loaded($item)) { - $errors[] = "This plugin requires php extension: " . $item . " to be installed."; - $tmpDisplayError = true; - } - } - - if ($tmpDisplayError) { - self::$error = implode('
', $errors); - $continue = false; - break; - } - } - else if($req == 'table') { - $tmpDisplayError = false; - $explode = explode(',', $version); - foreach ($explode as $item) { - if(!$db->hasTable($item)) { - $errors[] = "This plugin requires table: " . $item . " to exist in the database."; - $tmpDisplayError = true; - } - } - - if ($tmpDisplayError) { - self::$error = implode('
', $errors); - $continue = false; - break; - } - } - else if($req == 'column') { - $tmpDisplayError = false; - $explode = explode(',', $version); - foreach ($explode as $item) { - $tmp = explode('.', $item); - - if(count($tmp) == 2) { - if(!$db->hasColumn($tmp[0], $tmp[1])) { - $errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database."; - $tmpDisplayError = true; - } - } - else { - self::$warnings[] = "Invalid plugin require column: " . $item; - } - } - - if ($tmpDisplayError) { - self::$error = implode('
', $errors); - $continue = false; - break; - } - } - else if(strpos($req, 'ext-') !== false) { - $tmp = explode('-', $req); - if(count($tmp) == 2) { - if(!extension_loaded($tmp[1]) || !Semver::satisfies(phpversion($tmp[1]), $version)) { - self::$error = "This plugin requires php extension: " . $tmp[1] . ", version " . $version . " to be installed."; - $continue = false; - break; - } - } - } - else if(!self::is_installed($req, $version)) { - self::$error = "This plugin requires another plugin to run correctly. The another plugin is: " . $req . ", with version " . $version . "."; + if ($tmpDisplayError) { + self::$error = implode('
', $errors); $continue = false; break; } } - } - } + else if($req == 'table') { + $tmpDisplayError = false; + $explode = explode(',', $version); + foreach ($explode as $item) { + if(!$db->hasTable($item)) { + $errors[] = "This plugin requires table: " . $item . " to exist in the database."; + $tmpDisplayError = true; + } + } - if($continue) { - if(!$zip->extractTo(BASE)) { // "Real" Install - self::$error = 'There was a problem with extracting zip archive to base directory.'; - $zip->close(); - return false; - } - - $install = $plugin_json['install'] ?? ''; - if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $pluginFilename . '/install.php')) { - $install = 'plugins/' . $pluginFilename . '/install.php'; - } - - if (!empty($install)) { - if (file_exists(BASE . $install)) { - $db->revalidateCache(); - require BASE . $install; - $db->revalidateCache(); + if ($tmpDisplayError) { + self::$error = implode('
', $errors); + $continue = false; + break; + } } - else { - self::$warnings[] = 'Cannot load install script. Your plugin might be not working correctly.'; + else if($req == 'column') { + $tmpDisplayError = false; + $explode = explode(',', $version); + foreach ($explode as $item) { + $tmp = explode('.', $item); + + if(count($tmp) == 2) { + if(!$db->hasColumn($tmp[0], $tmp[1])) { + $errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database."; + $tmpDisplayError = true; + } + } + else { + self::$warnings[] = "Invalid plugin require column: " . $item; + } + } + + if ($tmpDisplayError) { + self::$error = implode('
', $errors); + $continue = false; + break; + } + } + else if(strpos($req, 'ext-') !== false) { + $tmp = explode('-', $req); + if(count($tmp) == 2) { + if(!extension_loaded($tmp[1]) || !Semver::satisfies(phpversion($tmp[1]), $version)) { + self::$error = "This plugin requires php extension: " . $tmp[1] . ", version " . $version . " to be installed."; + $continue = false; + break; + } + } + } + else if(!self::is_installed($req, $version)) { + self::$error = "This plugin requires another plugin to run correctly. The another plugin is: " . $req . ", with version " . $version . "."; + $continue = false; + break; } } - - clearCache(); - - return true; } } - return false; + if(!$continue) { + return false; + } + + if(!$zip->extractTo(BASE)) { // "Real" Install + self::$error = 'There was a problem with extracting zip archive to base directory.'; + $zip->close(); + return false; + } + + $install = $plugin_json['install'] ?? ''; + if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $pluginFilename . '/install.php')) { + $install = 'plugins/' . $pluginFilename . '/install.php'; + } + + if (!empty($install)) { + if (file_exists(BASE . $install)) { + $db->revalidateCache(); + require BASE . $install; + $db->revalidateCache(); + } + else { + self::$warnings[] = 'Cannot load install script. Your plugin might be not working correctly.'; + } + } + + clearCache(); + return true; } public static function isEnabled($pluginFileName): bool From f17269e44ce9dd38447bd2e2a8e1bdb065d4161f Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 14:22:51 +0200 Subject: [PATCH 073/216] Move admin bar code into body_start place_holder --- index.php | 9 --------- system/functions.php | 10 ++++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/index.php b/index.php index bf7069d4..ee8f7a87 100644 --- a/index.php +++ b/index.php @@ -162,15 +162,6 @@ if(setting('core.anonymous_usage_statistics')) { } } -/** - * @var OTS_Account $account_logged - */ -if ($logged && admin()) { - $content .= $twig->render('admin-bar.html.twig', [ - 'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId() - ]); -} - $title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName']; require $template_path . '/' . $template_index; diff --git a/system/functions.php b/system/functions.php index 540c9af3..7f54e69f 100644 --- a/system/functions.php +++ b/system/functions.php @@ -512,6 +512,16 @@ function template_place_holder($type): string } elseif ($type === 'body_start') { $ret .= $twig->render('browsehappy.html.twig'); + + /** + * @var OTS_Account $account_logged + */ + if (admin()) { + global $account_logged; + $ret .= $twig->render('admin-bar.html.twig', [ + 'username' => USE_ACCOUNT_NAME ? $account_logged->getName() : $account_logged->getId() + ]); + } } elseif($type === 'body_end') { $ret .= template_ga_code(); From 36ca755243ef1c83f6ac87465b426d4d8d3b0bb9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 14:28:48 +0200 Subject: [PATCH 074/216] New setting: Display Skills Box on highscores Better space management --- system/settings.php | 6 ++++++ system/templates/highscores.html.twig | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index 40c8be03..fb5c0301 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1062,6 +1062,12 @@ Sent by MyAAC,
'desc' => 'How often to update highscores from database in minutes. Too low may slow down your website.
0 to disable.', 'default' => 15, ], + 'highscores_skills_box' => [ + 'name' => 'Display Skills Box', + 'type' => 'boolean', + 'desc' => 'show "Choose a skill" box on the highscores (allowing peoples to sort highscores by skill)?', + 'default' => true, + ], 'highscores_vocation_box' => [ 'name' => 'Display Vocation Box', 'type' => 'boolean', diff --git a/system/templates/highscores.html.twig b/system/templates/highscores.html.twig index 86599b90..3e85cf5d 100644 --- a/system/templates/highscores.html.twig +++ b/system/templates/highscores.html.twig @@ -94,8 +94,10 @@ {% endif %}
{{ include('buttons.back.html.twig') }} From dca904e61d21d856bf809070e7652803a2df0f58 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 15 Jun 2025 19:05:19 +0200 Subject: [PATCH 049/216] Add missing csrf() --- templates/tibiacom/success.html.twig | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/tibiacom/success.html.twig b/templates/tibiacom/success.html.twig index 4aac4acb..c87a1971 100644 --- a/templates/tibiacom/success.html.twig +++ b/templates/tibiacom/success.html.twig @@ -35,6 +35,7 @@
+ {{ csrf() }} {{ include('buttons.back.html.twig') }} - diff --git a/system/templates/account.characters.change-comment.html.twig b/system/templates/account.characters.change-comment.html.twig index 8bb94c80..ab8fb384 100644 --- a/system/templates/account.characters.change-comment.html.twig +++ b/system/templates/account.characters.change-comment.html.twig @@ -88,7 +88,7 @@ If you do not want to specify a certain field, just leave it blank.

+
{{ csrf() }} @@ -40,14 +40,14 @@ Please enter your password and the new email address. Make sure that you enter a
- - {{ csrf() }} - - + - - + + +
+
+ + {{ csrf() }} {{ include('buttons.back.html.twig') }} -
- + +
+ {{ include('buttons.submit.html.twig') }} @@ -99,15 +99,15 @@ If you do not want to specify a certain field, just leave it blank.

- - {{ csrf() }} - - + - - -
+
+ + {{ csrf() }} {{ include('buttons.back.html.twig') }} -
+ +
diff --git a/system/templates/account.characters.delete.html.twig b/system/templates/account.characters.delete.html.twig index 8593f7ed..b946d221 100644 --- a/system/templates/account.characters.delete.html.twig +++ b/system/templates/account.characters.delete.html.twig @@ -24,7 +24,7 @@ To delete a character enter the name of the character and your password.

- diff --git a/system/templates/success.html.twig b/system/templates/success.html.twig index eaee1fb1..3c69dad6 100644 --- a/system/templates/success.html.twig +++ b/system/templates/success.html.twig @@ -18,14 +18,14 @@ {% else %}
+
{{ csrf() }} @@ -36,14 +36,14 @@ To delete a character enter the name of the character and your password.

- - {{ csrf() }} - - + - - + + +
+
+ + {{ csrf() }} {{ include('buttons.back.html.twig') }} -
- - {{ csrf() }} - - + - - + + +
+
+ + {{ csrf() }} {{ include('buttons.back.html.twig') }} -
{% endif %} From c720ccc451ff90ef40b2a1595468d061ffd7e1e4 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 15 Jun 2025 19:35:12 +0200 Subject: [PATCH 051/216] Add missing csrf() --- system/pages/account/change-email.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/pages/account/change-email.php b/system/pages/account/change-email.php index 857623f9..6dc8d388 100644 --- a/system/pages/account/change-email.php +++ b/system/pages/account/change-email.php @@ -166,7 +166,7 @@ if(isset($_POST['emailchangecancel']) && $_POST['emailchangecancel'] == 1) { $account_logged->setCustomField("email_new", ""); $account_logged->setCustomField("email_new_time", 0); - $custom_buttons = '
' . $twig->render('buttons.back.html.twig') . '
'; + $custom_buttons = '
' . csrf(true) . '
' . $twig->render('buttons.back.html.twig') . '
'; $twig->display('success.html.twig', array( 'title' => 'Email Address Change Cancelled', From b329da52aae9d0e21120a6444d3caf442420ce50 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 17 Jun 2025 17:52:23 +0200 Subject: [PATCH 052/216] Use apcu_clear_cache --- system/functions.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/functions.php b/system/functions.php index 6e58ca9d..56cf378b 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1263,6 +1263,10 @@ function clearCache() global $db; $db->setClearCacheAfter(true); + + if (function_exists('apcu_clear_cache')) { + apcu_clear_cache(); + } } deleteDirectory(CACHE . 'signatures', ['index.html'], true); From 0ea247ce7e8d28c4386f63411c2b928628e1daa0 Mon Sep 17 00:00:00 2001 From: Slawomir Boczek Date: Thu, 19 Jun 2025 16:46:22 +0200 Subject: [PATCH 053/216] Feature/plugins versions check (#310) * Check plugins versions from plugins.my-aac.org/api * Improve plugin update check messaging Updated the success message when checking for plugin updates to clarify the source. Added an informational message when outdated plugins are found to improve user feedback. * Use configurable API URI for plugin updates Replaces hardcoded plugin API URI with a configurable value from config, defaulting to the official API. Also fixes a typo in the success message. --- admin/pages/plugins.php | 50 ++ composer.json | 3 +- composer.lock | 537 +++++++++++++++++- system/src/Admin/Plugins.php | 49 ++ system/templates/admin.plugins.form.html.twig | 4 +- .../admin.plugins.outdated.html.twig | 18 + 6 files changed, 655 insertions(+), 6 deletions(-) create mode 100644 system/src/Admin/Plugins.php create mode 100644 system/templates/admin.plugins.outdated.html.twig diff --git a/admin/pages/plugins.php b/admin/pages/plugins.php index db886635..82f8309c 100644 --- a/admin/pages/plugins.php +++ b/admin/pages/plugins.php @@ -51,6 +51,56 @@ else { } else { error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError()); } + } + else if (isset($_GET['check-updates'])) { + $repoUri = $config['admin_plugins_api_uri'] ?? 'https://plugins.my-aac.org/api/'; + success("Fetching latest info from $repoUri.."); + + $adminPlugins = new \MyAAC\Admin\Plugins(); + + $adminPlugins->setApiBaseUri($repoUri); + + try { + $plugins = $adminPlugins->getLatestVersions(); + } + catch (Exception $e) { + error($e->getMessage()); + } + + if (isset($plugins) && count($plugins) > 0) { + $outdated = []; + + foreach (get_plugins(true) as $plugin) { + $string = file_get_contents(BASE . 'plugins/' . $plugin . '.json'); + $plugin_info = json_decode($string, true); + + if (!$plugin_info) { + continue; + } + + $disabled = (str_contains($plugin, 'disabled.')); + $pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin); + + $info = $plugins[$pluginOriginal] ?? false; + if ($info && version_compare($info['version'], $plugin_info['version'], '>')) { + $outdated[] = [ + 'name' => $pluginOriginal, + 'yourVersion' => $plugin_info['version'], + 'latestVersion' => $info['version'], + 'link' => $info['link'] ?? 'Unknown', + 'download_link' => $info['download_link'] ?? 'Unknown', + ]; + } + } + + if (count($outdated) > 0) { + info('Following updates have been found for your plugins:'); + $twig->display('admin.plugins.outdated.html.twig', ['plugins' => $outdated]); + } + else { + success('All plugins up to date!'); + } + } } else if (isset($_FILES['plugin']['name'])) { $file = $_FILES['plugin']; $filename = $file['name']; diff --git a/composer.json b/composer.json index a150c7a3..fd7e5a44 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ "symfony/string": "^6.4", "symfony/var-dumper": "^6.4", "filp/whoops": "^2.15", - "maximebf/debugbar": "1.*" + "maximebf/debugbar": "1.*", + "guzzlehttp/guzzle": "7.9.3" }, "require-dev": { "phpstan/phpstan": "^1.10" diff --git a/composer.lock b/composer.lock index 3a484492..9c831948 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "be4d1489a53a9cd8eec6bcaa7a096f30", + "content-hash": "5317e97a5025ebc2a977214bd3fa964c", "packages": [ { "name": "brick/math", @@ -493,6 +493,331 @@ ], "time": "2024-09-25T12:00:00+00:00" }, + { + "name": "guzzlehttp/guzzle", + "version": "7.9.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:37:11+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.2.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:27:01+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.7.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.7.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2025-03-27T12:30:47+00:00" + }, { "name": "illuminate/collections", "version": "v10.48.25", @@ -1472,6 +1797,166 @@ }, "time": "2021-11-05T16:47:00+00:00" }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, { "name": "psr/log", "version": "3.0.2", @@ -1573,6 +2058,50 @@ }, "time": "2021-10-29T13:26:27+00:00" }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, { "name": "symfony/console", "version": "v6.4.17", @@ -2910,7 +3439,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -2921,6 +3450,6 @@ "ext-xml": "*", "ext-dom": "*" }, - "platform-dev": [], - "plugin-api-version": "2.3.0" + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/system/src/Admin/Plugins.php b/system/src/Admin/Plugins.php new file mode 100644 index 00000000..f7b781f2 --- /dev/null +++ b/system/src/Admin/Plugins.php @@ -0,0 +1,49 @@ + $this->api_base_uri, + // You can set any number of default request options. + 'timeout' => 3.0, + ]); + + $plugins = get_plugins(true); + foreach ($plugins as &$plugin) { + if (str_contains($plugin, 'disabled.')) { + $plugin = str_replace('disabled.', '', $plugin); + } + } + + try { + $response = $client->get('get-latest-versions', [ + 'json' => ['plugins' => $plugins], + ]); + } + catch (\Exception $e) { + error('API Error. Please try again later.'); + return []; + } + + $statusCode = $response->getStatusCode(); + if ($statusCode != 200) { + throw new \Exception('Error getting info from plugins repository. Please try again later.'); + } + + $data = $response->getBody(); + return json_decode($data, true); + } + + public function setApiBaseUri(string $uri): void { + $this->api_base_uri = $uri; + } +} diff --git a/system/templates/admin.plugins.form.html.twig b/system/templates/admin.plugins.form.html.twig index aec82a8a..f8eddd41 100644 --- a/system/templates/admin.plugins.form.html.twig +++ b/system/templates/admin.plugins.form.html.twig @@ -1,7 +1,9 @@
-
Install plugin
+
Install plugin + Check for updates +
{{ csrf() }} diff --git a/system/templates/admin.plugins.outdated.html.twig b/system/templates/admin.plugins.outdated.html.twig new file mode 100644 index 00000000..d587204e --- /dev/null +++ b/system/templates/admin.plugins.outdated.html.twig @@ -0,0 +1,18 @@ + + + + + + + + + + {% for plugin in plugins %} + + + + + + + {% endfor %} +
Plugin NameYour VersionLatest VersionDownload link
{{ plugin.name }}{{ plugin.yourVersion }}{{ plugin.latestVersion }}{{ plugin.download_link }}
From 0f48f12e2e3112acab4bc2b6ab766ee6dbf7a9a5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 19 Jun 2025 18:53:11 +0200 Subject: [PATCH 054/216] Update admin.plugins.outdated.html.twig --- system/templates/admin.plugins.outdated.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/templates/admin.plugins.outdated.html.twig b/system/templates/admin.plugins.outdated.html.twig index d587204e..95421edc 100644 --- a/system/templates/admin.plugins.outdated.html.twig +++ b/system/templates/admin.plugins.outdated.html.twig @@ -4,7 +4,7 @@
Plugin Name Your Version Latest VersionDownload linkDownload Link
+ {% if setting('core.highscores_skills_box') or setting('core.highscores_vocation_box') %} + {% if setting('core.highscores_skills_box') %} @@ -109,7 +111,8 @@
Choose a skill

- {% if config.highscores_vocation_box %} + {% endif %} + {% if setting('core.highscores_vocation_box') %} @@ -126,5 +129,6 @@ {% endif %} + {% endif %}
Choose a vocation
From f0f2e3785f7b46d813f38cb6c1be3e1e6152c3e4 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 15:44:45 +0200 Subject: [PATCH 075/216] Fix phpstan --- system/functions.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/system/functions.php b/system/functions.php index 7f54e69f..d1351f35 100644 --- a/system/functions.php +++ b/system/functions.php @@ -513,9 +513,6 @@ function template_place_holder($type): string elseif ($type === 'body_start') { $ret .= $twig->render('browsehappy.html.twig'); - /** - * @var OTS_Account $account_logged - */ if (admin()) { global $account_logged; $ret .= $twig->render('admin-bar.html.twig', [ From 2fe9924437c93b2363574af5e83e7192b6917ed5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 8 Jul 2025 19:20:45 +0200 Subject: [PATCH 076/216] Start 1.7.2-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 94395409..7d8a905d 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.7.1'; +const MYAAC_VERSION = '1.7.2-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From ec11c1402417c25980582467546d1c1e9bb8267f Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 07:48:01 +0200 Subject: [PATCH 077/216] kathrine: possibility to add custom menu categories --- templates/kathrine/config.php | 20 ++++++++++----- templates/kathrine/javascript.php | 38 +++++++++++++--------------- templates/kathrine/menu.js.html.twig | 8 +++--- templates/kathrine/style.css | 6 +++-- templates/kathrine/template.php | 21 ++++++++++++--- 5 files changed, 57 insertions(+), 36 deletions(-) diff --git a/templates/kathrine/config.php b/templates/kathrine/config.php index 63847317..52835ff4 100644 --- a/templates/kathrine/config.php +++ b/templates/kathrine/config.php @@ -1,12 +1,18 @@ array('id' => 'news', 'name' => 'Latest News'), - MENU_CATEGORY_ACCOUNT => array('id' => 'account', 'name' => 'Account'), - MENU_CATEGORY_COMMUNITY => array('id' => 'community', 'name' => 'Community'), - MENU_CATEGORY_LIBRARY => array('id' => 'library', 'name' => 'Library'), - MENU_CATEGORY_SHOP => array('id' => 'shops', 'name' => 'Shop') -); +// max 7 menus for kathrine +$config['menu_categories'] = [ + MENU_CATEGORY_NEWS => ['id' => 'news', 'name' => 'Latest News'], + // you can add custom menu by uncommenting this + // after doing it, go to admin panel -> Menus and add your entries for this category + // tip: you can move it up/down to show it on specific position + //7 => array('id' => 'testing', 'name' => 'Test Menu 1'), + //8 => array('id' => 'testing2', 'name' => 'Test Menu 2'), + MENU_CATEGORY_ACCOUNT => ['id' => 'account', 'name' => 'Account'], + MENU_CATEGORY_COMMUNITY => ['id' => 'community', 'name' => 'Community'], + MENU_CATEGORY_LIBRARY => ['id' => 'library', 'name' => 'Library'], + MENU_CATEGORY_SHOP => ['id' => 'shops', 'name' => 'Shop'] +]; $config['menus'] = require __DIR__ . '/menus.php'; diff --git a/templates/kathrine/javascript.php b/templates/kathrine/javascript.php index a092b7c2..32fcf53d 100644 --- a/templates/kathrine/javascript.php +++ b/templates/kathrine/javascript.php @@ -1,42 +1,40 @@ -var category = ' $info) { + $templatePages = get_template_pages($id); + + if ($id == MENU_CATEGORY_ACCOUNT) { + $templatePages = array_merge($templatePages, ['account']); + } + + if (in_array($tmp[0], $templatePages)) { + echo $info['id']; + break; + } } ?>'; diff --git a/templates/kathrine/menu.js.html.twig b/templates/kathrine/menu.js.html.twig index adf7ceb0..ae8ad3bf 100644 --- a/templates/kathrine/menu.js.html.twig +++ b/templates/kathrine/menu.js.html.twig @@ -1,10 +1,10 @@ var list = new Array(); {% set i = 0 %} -{% for cat in categories %} - {% if cat.id != 'shops' or setting('core.gifts_system') %} - list[{{ i }}] = '{{ cat.id }}'; +{% for id, cat in config('menu_categories') %} + {% if (cat.id != 'shops' or setting('core.gifts_system')) and menus[id]|length > 0 %} + list[{{ i }}] = '{{ cat.id }}'; + {% set i = i + 1 %} {% endif %} -{% set i = i + 1 %} {% endfor %} function initMenu() diff --git a/templates/kathrine/style.css b/templates/kathrine/style.css index 45a1a9d4..cc212685 100644 --- a/templates/kathrine/style.css +++ b/templates/kathrine/style.css @@ -27,11 +27,13 @@ body #tabs { - width: 580px; + width: 99%; height: 32px; background: url('images/tabs-bg.png') no-repeat; - float: left; padding-left: 200px; + position: relative; + display: inline-flex; + right: 0; } #tabs .tab diff --git a/templates/kathrine/template.php b/templates/kathrine/template.php index af03b3c9..ffa2195a 100644 --- a/templates/kathrine/template.php +++ b/templates/kathrine/template.php @@ -8,7 +8,9 @@ defined('MYAAC') or die('Direct access not allowed!'); @@ -28,11 +30,24 @@ defined('MYAAC') or die('Direct access not allowed!'); + + 6) { + $tabsStyle .= 'padding-left: 4px;'; + $tabsStyle .= 'padding-right: 12px;'; + } + elseif ($menusCount > 5) { + $tabsStyle .= 'padding-left: 90px;'; + } + ?> + -
+
$cat) { - if($id != MENU_CATEGORY_SHOP || $config['gifts_system']) { ?> + if (($id != MENU_CATEGORY_SHOP || $config['gifts_system']) && isset($menus[$id])) { ?> Date: Sat, 19 Jul 2025 10:05:25 +0200 Subject: [PATCH 078/216] Allow for timestamp as integer in the timeago twig function --- system/twig.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/system/twig.php b/system/twig.php index f59230e3..baeae276 100644 --- a/system/twig.php +++ b/system/twig.php @@ -36,7 +36,11 @@ $twig->addExtension(new MyAAC\Twig\Extension\TypeCastingExtension()); $filter = new TwigFilter('timeago', function ($datetime) { - $time = time() - strtotime($datetime); + if (!is_int($datetime)) { + $datetime = strtotime($datetime); + } + + $time = time() - $datetime; $units = array ( 31536000 => 'year', From 83f84172e02e8ea2ccb6dca29bc033e44c35aebc Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 11:16:03 +0200 Subject: [PATCH 079/216] Add warning about APCu clear in CLI Adds a warning message if attempting to clear APCu cache from the CLI, as this is not supported. Users are advised to use the Admin Panel for clearing APCu cache outside of development environments. --- system/src/Commands/CacheClearCommand.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/system/src/Commands/CacheClearCommand.php b/system/src/Commands/CacheClearCommand.php index 5b1715b5..ac899655 100644 --- a/system/src/Commands/CacheClearCommand.php +++ b/system/src/Commands/CacheClearCommand.php @@ -2,6 +2,7 @@ namespace MyAAC\Commands; +use MyAAC\Cache\Cache; use MyAAC\Hooks; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -26,6 +27,15 @@ class CacheClearCommand extends Command return Command::FAILURE; } + $cache = Cache::getInstance(); + + $cacheEngine = config('cache_engine') == 'auto' ? + Cache::detect() : config('cache_engine'); + + if (config('env') !== 'dev' && $cacheEngine == 'apcu') { + $io->warning('APCu cache cannot be cleared in CLI. Please visit the Admin Panel and clear there.'); + } + $io->success('Cache cleared'); return Command::SUCCESS; } From ce5b1cf2a665a636bad51966b80527e2ca3381ca Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 11:16:55 +0200 Subject: [PATCH 080/216] Update CacheClearCommand.php --- system/src/Commands/CacheClearCommand.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/system/src/Commands/CacheClearCommand.php b/system/src/Commands/CacheClearCommand.php index ac899655..5f9bae0b 100644 --- a/system/src/Commands/CacheClearCommand.php +++ b/system/src/Commands/CacheClearCommand.php @@ -27,8 +27,6 @@ class CacheClearCommand extends Command return Command::FAILURE; } - $cache = Cache::getInstance(); - $cacheEngine = config('cache_engine') == 'auto' ? Cache::detect() : config('cache_engine'); From 5271633bdbfbbfed0b1d59c403093ce6fc2b7d20 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 15:00:17 +0200 Subject: [PATCH 081/216] Account -> isPremium -> ignore config.freePremium --- system/libs/pot/OTS_Account.php | 9 +++------ system/src/Models/Account.php | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index 8528cf3f..20c7fe32 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -473,12 +473,9 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable public function isPremium() { - global $config; - if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true; - - if(isset($this->data['premium_ends_at'])) { - return $this->data['premium_ends_at'] > time(); - } + if(isset($this->data['premium_ends_at'])) { + return $this->data['premium_ends_at'] > time(); + } if(isset($this->data['premend'])) { return $this->data['premend'] > time(); diff --git a/system/src/Models/Account.php b/system/src/Models/Account.php index b11c2a48..f0bd435f 100644 --- a/system/src/Models/Account.php +++ b/system/src/Models/Account.php @@ -53,12 +53,9 @@ class Account extends Model { public function getIsPremiumAttribute() { - global $config; - if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true; - - if(isset($this->premium_ends_at)) { - return $this->premium_ends_at > time(); - } + if(isset($this->premium_ends_at)) { + return $this->premium_ends_at > time(); + } if(isset($this->premend)) { return $this->premend > time(); From 536b29be950a1108d0f7e4b16db9d096880eb6cd Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 15:11:09 +0200 Subject: [PATCH 082/216] That is duplicated --- admin/pages/accounts.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/admin/pages/accounts.php b/admin/pages/accounts.php index 0358753b..c1b90eac 100644 --- a/admin/pages/accounts.php +++ b/admin/pages/accounts.php @@ -243,9 +243,6 @@ else if (isset($_REQUEST['search'])) { $password = encrypt($password); $account->setPassword($password); - - if (USE_ACCOUNT_SALT) - $account->setCustomField('salt', $salt); } $account->save(); From 1566deb84a082176b8c683fda205d828bc38fbcc Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 19 Jul 2025 15:46:51 +0200 Subject: [PATCH 083/216] Add getExperienceForLevel (level) --- system/functions.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/functions.php b/system/functions.php index d1351f35..8859d36f 100644 --- a/system/functions.php +++ b/system/functions.php @@ -774,6 +774,10 @@ function formatExperience($exp, $color = true) return $ret; } +function getExperienceForLevel($level): float|int { + return ( 50 / 3 ) * pow( $level, 3 ) - ( 100 * pow( $level, 2 ) ) + ( ( 850 / 3 ) * $level ) - 200; +} + function get_locales() { $ret = array(); From d8132d4d76e03d5aa0c042be426320655a601392 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 18:18:29 +0200 Subject: [PATCH 084/216] Highscores revamp a bit * Show real rank, if 2 or more players have the same skill, show them with same rank * New setting: highscores_online_status * Additional fields passed to twig: updatedAt, totalResults, page, baseLink --- system/pages/highscores.php | 52 +++++++++++++++++++++------ system/settings.php | 6 ++++ system/templates/highscores.html.twig | 2 +- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/system/pages/highscores.php b/system/pages/highscores.php index 6deb842c..15ce8ef8 100644 --- a/system/pages/highscores.php +++ b/system/pages/highscores.php @@ -146,17 +146,24 @@ $cache = Cache::getInstance(); if ($cache->enabled() && $highscoresTTL > 0) { $tmp = ''; if ($cache->fetch($cacheKey, $tmp)) { - $highscores = unserialize($tmp); + $data = unserialize($tmp); + $totalResults = $data['totalResults']; + $highscores = $data['highscores']; + $updatedAt = $data['updatedAt']; $needReCache = false; } } $offset = ($page - 1) * $configHighscoresPerPage; -$query->join('accounts', 'accounts.id', '=', 'players.account_id') - ->withOnlineStatus() +$query->withOnlineStatus() ->whereNotIn('players.id', setting('core.highscores_ids_hidden')) ->notDeleted() - ->where('players.group_id', '<', setting('core.highscores_groups_hidden')) + ->where('players.group_id', '<', setting('core.highscores_groups_hidden')); + +$totalResultsQuery = clone $query; + +$query + ->join('accounts', 'accounts.id', '=', 'players.account_id') ->limit($limit) ->offset($offset) ->selectRaw('accounts.country, players.id, players.name, players.account_id, players.level, players.vocation' . $outfit . $promotion) @@ -215,17 +222,24 @@ if (empty($highscores)) { return $tmp; })->toArray(); + + $updatedAt = time(); + $totalResults = $totalResultsQuery->count(); } if ($highscoresTTL > 0 && $cache->enabled() && $needReCache) { - $cache->set($cacheKey, serialize($highscores), $highscoresTTL * 60); + $cache->set($cacheKey, serialize( + [ + 'totalResults' => $totalResults, + 'highscores' => $highscores, + 'updatedAt' => $updatedAt, + ] + ), $highscoresTTL * 60); } $show_link_to_next_page = false; $i = 0; -$settingHighscoresVocation = setting('core.highscores_vocation'); - foreach($highscores as $id => &$player) { if(++$i <= $configHighscoresPerPage) @@ -239,10 +253,22 @@ foreach($highscores as $id => &$player) $player['link'] = getPlayerLink($player['name'], false); $player['flag'] = getFlagImage($player['country']); - if($settingHighscoresOutfit) { - $player['outfit'] = ''; + $player['outfit'] = ''; + + if ($skill != POT::SKILL__LEVEL) { + if (isset($lastValue) && $lastValue == $player['value']) { + $player['rank'] = $lastRank; + } + else { + $player['rank'] = $offset + $i; + } + + $lastRank = $player['rank'] ; + $lastValue = $player['value']; + } + else { + $player['rank'] = $offset + $i; } - $player['rank'] = $offset + $i; } else { unset($highscores[$id]); @@ -263,6 +289,8 @@ if($show_link_to_next_page) { $linkNextPage = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/' . ($page + 1); } +$baseLink = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/'; + $types = array( 'experience' => 'Experience', 'magic' => 'Magic', @@ -297,4 +325,8 @@ $twig->display('highscores.html.twig', [ 'types' => $types, 'linkPreviousPage' => $linkPreviousPage, 'linkNextPage' => $linkNextPage, + 'totalResults' => $totalResults, + 'page' => $page, + 'baseLink' => $baseLink, + 'updatedAt' => $updatedAt, ]); diff --git a/system/settings.php b/system/settings.php index fb5c0301..d7c124c2 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1080,6 +1080,12 @@ Sent by MyAAC,
'desc' => 'Show player vocation under his nickname?', 'default' => true, ], + 'highscores_online_status' => [ + 'name' => 'Display Online Status', + 'type' => 'boolean', + 'desc' => 'Show player status as red (offline) or green (online)', + 'default' => false, + ], 'highscores_frags' => [ 'name' => 'Display Top Frags', 'type' => 'boolean', diff --git a/system/templates/highscores.html.twig b/system/templates/highscores.html.twig index 3e85cf5d..88bf579b 100644 --- a/system/templates/highscores.html.twig +++ b/system/templates/highscores.html.twig @@ -66,7 +66,7 @@ - {{ player.name }} + {{ player.name }} {% if setting('core.highscores_vocation') %}
{{ player.vocation }} From c06b0017f1ad50383fae127e4ea86d00e20360d6 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 19:07:58 +0200 Subject: [PATCH 085/216] Update phpstan.neon --- phpstan.neon | 1 + 1 file changed, 1 insertion(+) diff --git a/phpstan.neon b/phpstan.neon index 020fa3a6..cb5cd4d3 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -28,6 +28,7 @@ parameters: - '#Variable \$guild might not be defined#' - '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#' # Eloquent models + - '#Call to an undefined method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#' - '#Call to an undefined static method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#' - '#Call to an undefined method object::toArray\(\)#' # system/pages/highscores.php From 9b6f41045988f081cfc34b6bf202b5e099c1dba5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 19:11:42 +0200 Subject: [PATCH 086/216] Update phpstan.neon --- phpstan.neon | 2 -- 1 file changed, 2 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index cb5cd4d3..68e1aa6a 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -30,9 +30,7 @@ parameters: # Eloquent models - '#Call to an undefined method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#' - '#Call to an undefined static method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#' - - '#Call to an undefined method object::toArray\(\)#' # system/pages/highscores.php - - '#Call to an undefined method Illuminate\\Database\\Query\\Builder::withOnlineStatus\(\)#' - '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$online_status#' - '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$vocation_name#' - From 7d27e5a0bace31f0df79ae45afdd9a0cbc4e7ac9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 21:32:51 +0200 Subject: [PATCH 087/216] New setting: Default Account Transferable Coins --- system/init.php | 12 ++++++++---- system/pages/account/create.php | 5 +++++ system/settings.php | 7 +++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/system/init.php b/system/init.php index 821ac440..b0c36c48 100644 --- a/system/init.php +++ b/system/init.php @@ -144,6 +144,14 @@ $ots = POT::getInstance(); $eloquentConnection = null; require_once SYSTEM . 'database.php'; +define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name')); +define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number')); +define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt')); + +define('HAS_ACCOUNT_COINS_TRANSFERABLE', $db->hasColumn('accounts', 'coins_transferable')); +define('HAS_ACCOUNT_TRANSFERABLE_COINS', $db->hasColumn('accounts', 'transferable_coins')); +const ACCOUNT_COINS_TRANSFERABLE_COLUMN = (HAS_ACCOUNT_COINS_TRANSFERABLE ? 'coins_transferable' : 'transferable_coins'); + $twig->addGlobal('logged', false); $twig->addGlobal('account_logged', new \OTS_Account()); @@ -188,10 +196,6 @@ if($settingsItemImagesURL[strlen($settingsItemImagesURL) - 1] !== '/') { setting(['core.item_images_url', $settingsItemImagesURL . '/']); } -define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name')); -define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number')); -define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt')); - $towns = Cache::remember('towns', 10 * 60, function () use ($db) { if ($db->hasTable('towns') && Town::count() > 0) { return Town::orderBy('id', 'ASC')->pluck('name', 'id')->toArray(); diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 947ad0ad..8967c8e1 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -231,6 +231,11 @@ if($save) $new_account->setCustomField('coins', $accountDefaultCoins); } + $accountDefaultCoinsTransferable = setting('core.account_coins_transferable'); + if((HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) && $accountDefaultCoinsTransferable > 0) { + $new_account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $accountDefaultCoinsTransferable); + } + $tmp_account = $email; if (!config('account_login_by_email')) { $tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id); diff --git a/system/settings.php b/system/settings.php index d7c124c2..e0f1fdb6 100644 --- a/system/settings.php +++ b/system/settings.php @@ -697,6 +697,13 @@ Sent by MyAAC,
'hidden' => ($db && !$db->hasColumn('accounts', 'coins')), 'default' => 0, ], + 'account_coins_transferable' => [ + 'name' => 'Default Account Transferable Coins', + 'type' => 'number', + 'desc' => 'Default transferable coins on new account', + 'hidden' => (!HAS_ACCOUNT_COINS_TRANSFERABLE && !HAS_ACCOUNT_TRANSFERABLE_COINS), + 'default' => 0, + ], 'account_mail_change' => [ 'name' => 'Account Mail Change Days', 'type' => 'number', From bccf8e056df985bbe1bab5f7ab5492f714d6b62b Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 21:33:45 +0200 Subject: [PATCH 088/216] Rewrite to use constants (account transferable coins) --- admin/pages/accounts.php | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/admin/pages/accounts.php b/admin/pages/accounts.php index c1b90eac..35543b0a 100644 --- a/admin/pages/accounts.php +++ b/admin/pages/accounts.php @@ -28,12 +28,6 @@ $nameOrNumberColumn = getAccountIdentityColumn(); $hasSecretColumn = $db->hasColumn('accounts', 'secret'); $hasCoinsColumn = $db->hasColumn('accounts', 'coins'); -$hasCoinsTransferableColumn = $db->hasColumn('accounts', 'coins_transferable'); -$hasTransferableCoinsColumn = $db->hasColumn('accounts', 'transferable_coins'); -$coinsTransferableColumn = - $hasTransferableCoinsColumn ? - 'transferable_coins' : 'coins_transferable'; - $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $hasTypeColumn = $db->hasColumn('accounts', 'type'); $hasGroupColumn = $db->hasColumn('accounts', 'group_id'); @@ -150,7 +144,7 @@ else if (isset($_REQUEST['search'])) { } // transferable tibia coins - if ($hasCoinsTransferableColumn || $hasTransferableCoinsColumn) { + if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) { $t_coins_transferable = $_POST['t_coins_transferable']; verify_number($t_coins_transferable, 'Transferable Tibia coins', 12); } @@ -207,8 +201,8 @@ else if (isset($_REQUEST['search'])) { $account->setCustomField('coins', $t_coins); } - if ($hasCoinsTransferableColumn || $hasTransferableCoinsColumn) { - $account->setCustomField($coinsTransferableColumn, $t_coins_transferable); + if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) { + $account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $t_coins_transferable); } $lastDay = 0; @@ -418,10 +412,10 @@ else if (isset($_REQUEST['search'])) {
- +
- +
From caf326a6584a234775ebc6c8000ea02b3fecd160 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 21:44:09 +0200 Subject: [PATCH 089/216] Refactor to use HAS_ACCOUNT_COINS $db->hasColumn('accounts', 'coins') -> HAS_ACCOUNT_COINS --- admin/pages/accounts.php | 8 +++----- admin/pages/mass_account.php | 11 ++++------- admin/pages/modules/coins.php | 2 +- system/init.php | 1 + system/pages/account/create.php | 2 +- system/settings.php | 4 ++-- 6 files changed, 12 insertions(+), 16 deletions(-) diff --git a/admin/pages/accounts.php b/admin/pages/accounts.php index 35543b0a..2d9c1bbd 100644 --- a/admin/pages/accounts.php +++ b/admin/pages/accounts.php @@ -26,8 +26,6 @@ if (setting('core.account_country')) $nameOrNumberColumn = getAccountIdentityColumn(); $hasSecretColumn = $db->hasColumn('accounts', 'secret'); -$hasCoinsColumn = $db->hasColumn('accounts', 'coins'); - $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $hasTypeColumn = $db->hasColumn('accounts', 'type'); $hasGroupColumn = $db->hasColumn('accounts', 'group_id'); @@ -138,7 +136,7 @@ else if (isset($_REQUEST['search'])) { $errors['email'] = Validator::getLastError(); // tibia coins - if ($hasCoinsColumn) { + if (HAS_ACCOUNT_COINS) { $t_coins = $_POST['t_coins']; verify_number($t_coins, 'Tibia coins', 12); } @@ -197,7 +195,7 @@ else if (isset($_REQUEST['search'])) { $account->setCustomField('key', $key); $account->setEMail($email); - if ($hasCoinsColumn) { + if (HAS_ACCOUNT_COINS) { $account->setCustomField('coins', $t_coins); } @@ -406,7 +404,7 @@ else if (isset($_REQUEST['search'])) { getEMail() . '">Send Mail)' : ''); ?>
- +
diff --git a/admin/pages/mass_account.php b/admin/pages/mass_account.php index 46c9bc9d..6b1ccb46 100644 --- a/admin/pages/mass_account.php +++ b/admin/pages/mass_account.php @@ -18,7 +18,6 @@ $title = 'Mass Account Actions'; csrfProtect(); -$hasCoinsColumn = $db->hasColumn('accounts', 'coins'); $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $freePremium = $config['lua']['freePremium']; @@ -40,9 +39,7 @@ function admin_give_points($points) function admin_give_coins($coins) { - global $hasCoinsColumn; - - if (!$hasCoinsColumn) { + if (!HAS_ACCOUNT_COINS) { displayMessage('Coins not supported.'); return; } @@ -167,19 +164,19 @@ if (!empty(ACTION) && isRequestMethod('post')) { } else { $twig->display('admin.tools.account.html.twig', array( - 'hasCoinsColumn' => $hasCoinsColumn, + 'hasCoinsColumn' => HAS_ACCOUNT_COINS, 'hasPointsColumn' => $hasPointsColumn, 'freePremium' => $freePremium, )); } function displayMessage($message, $success = false) { - global $twig, $hasCoinsColumn, $hasPointsColumn, $freePremium; + global $twig, $hasPointsColumn, $freePremium; $success ? success($message): error($message); $twig->display('admin.tools.account.html.twig', array( - 'hasCoinsColumn' => $hasCoinsColumn, + 'hasCoinsColumn' => HAS_ACCOUNT_COINS, 'hasPointsColumn' => $hasPointsColumn, 'freePremium' => $freePremium, )); diff --git a/admin/pages/modules/coins.php b/admin/pages/modules/coins.php index 939ee16c..66ce0186 100644 --- a/admin/pages/modules/coins.php +++ b/admin/pages/modules/coins.php @@ -6,7 +6,7 @@ defined('MYAAC') or die('Direct access not allowed!'); $coins = 0; -if ($db->hasColumn('accounts', 'coins')) { +if (HAS_ACCOUNT_COINS) { $whatToGet = ['id', 'coins']; if (USE_ACCOUNT_NAME) { $whatToGet[] = 'name'; diff --git a/system/init.php b/system/init.php index b0c36c48..57c299ba 100644 --- a/system/init.php +++ b/system/init.php @@ -148,6 +148,7 @@ define('USE_ACCOUNT_NAME', $db->hasColumn('accounts', 'name')); define('USE_ACCOUNT_NUMBER', $db->hasColumn('accounts', 'number')); define('USE_ACCOUNT_SALT', $db->hasColumn('accounts', 'salt')); +define('HAS_ACCOUNT_COINS', $db->hasColumn('accounts', 'coins')); define('HAS_ACCOUNT_COINS_TRANSFERABLE', $db->hasColumn('accounts', 'coins_transferable')); define('HAS_ACCOUNT_TRANSFERABLE_COINS', $db->hasColumn('accounts', 'transferable_coins')); const ACCOUNT_COINS_TRANSFERABLE_COLUMN = (HAS_ACCOUNT_COINS_TRANSFERABLE ? 'coins_transferable' : 'transferable_coins'); diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 8967c8e1..15f2b8b5 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -227,7 +227,7 @@ if($save) } $accountDefaultCoins = setting('core.account_coins'); - if($db->hasColumn('accounts', 'coins') && $accountDefaultCoins > 0) { + if(HAS_ACCOUNT_COINS && $accountDefaultCoins > 0) { $new_account->setCustomField('coins', $accountDefaultCoins); } diff --git a/system/settings.php b/system/settings.php index e0f1fdb6..c39c706a 100644 --- a/system/settings.php +++ b/system/settings.php @@ -694,7 +694,7 @@ Sent by MyAAC,
'name' => 'Default Account Coins', 'type' => 'number', 'desc' => 'Default coins on new account', - 'hidden' => ($db && !$db->hasColumn('accounts', 'coins')), + 'hidden' => ($db && !HAS_ACCOUNT_COINS), 'default' => 0, ], 'account_coins_transferable' => [ @@ -1595,7 +1595,7 @@ Sent by MyAAC,
'callbacks' => [ 'beforeSave' => function($key, $value, &$errorMessage) { global $db; - if ($value == 'coins' && !$db->hasColumn('accounts', 'coins')) { + if ($value == 'coins' && !HAS_ACCOUNT_COINS) { $errorMessage = "Shop: Donate Column: Cannot set column to coins, because it doesn't exist in database."; return false; } From 6e5a4ff8c78ff5373aba091baa66cae029557643 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 21:49:05 +0200 Subject: [PATCH 090/216] Fix if setting found in db, but not found in plugins --- system/src/Settings.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/system/src/Settings.php b/system/src/Settings.php index ca4192ad..ef3da830 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -472,24 +472,22 @@ class Settings implements \ArrayAccess if (!isset($this->settingsFile[$pluginKeyName]['settings'])) { throw new \RuntimeException('Unknown plugin settings: ' . $pluginKeyName); } + return $this->settingsFile[$pluginKeyName]['settings']; } - $ret = []; - if(isset($this->settingsFile[$pluginKeyName]['settings'][$key])) { - $ret = $this->settingsFile[$pluginKeyName]['settings'][$key]; + if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) { + return null; } + $ret = $this->settingsFile[$pluginKeyName]['settings'][$key]; + if(isset($this->settingsDatabase[$pluginKeyName][$key])) { $value = $this->settingsDatabase[$pluginKeyName][$key]; $ret['value'] = $value; } else { - if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) { - return null; - } - $ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default']; } From bb097b69ce106500a49686d6f4fe604348eaa310 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 22 Jul 2025 22:06:32 +0200 Subject: [PATCH 091/216] Update settings.php --- system/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index c39c706a..ae61fd52 100644 --- a/system/settings.php +++ b/system/settings.php @@ -701,7 +701,7 @@ Sent by MyAAC,
'name' => 'Default Account Transferable Coins', 'type' => 'number', 'desc' => 'Default transferable coins on new account', - 'hidden' => (!HAS_ACCOUNT_COINS_TRANSFERABLE && !HAS_ACCOUNT_TRANSFERABLE_COINS), + 'hidden' => ($db && !HAS_ACCOUNT_COINS_TRANSFERABLE && !HAS_ACCOUNT_TRANSFERABLE_COINS), 'default' => 0, ], 'account_mail_change' => [ From 2d4be327b278c01d27a935fcb48825c1fc94e0cc Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 24 Jul 2025 23:07:49 +0200 Subject: [PATCH 092/216] Fix if highscores show outfit disabled --- system/pages/highscores.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/system/pages/highscores.php b/system/pages/highscores.php index 15ce8ef8..cec95d15 100644 --- a/system/pages/highscores.php +++ b/system/pages/highscores.php @@ -123,16 +123,10 @@ if($db->hasColumn('players', 'promotion')) $promotion = ',players.promotion'; $outfit_addons = false; -$outfit = ''; - -$settingHighscoresOutfit = setting('core.highscores_outfit'); - -if($settingHighscoresOutfit) { - $outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype'; - if($db->hasColumn('players', 'lookaddons')) { - $outfit .= ', lookaddons'; - $outfit_addons = true; - } +$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype'; +if($db->hasColumn('players', 'lookaddons')) { + $outfit .= ', lookaddons'; + $outfit_addons = true; } $configHighscoresPerPage = setting('core.highscores_per_page'); From 20d69a641c0a933d14889a89da6d32f6a4bc6c7d Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 24 Jul 2025 23:30:28 +0200 Subject: [PATCH 093/216] Fix exception if setting not found --- system/functions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/functions.php b/system/functions.php index 8859d36f..8c365391 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1228,7 +1228,8 @@ function setting($key) return $settings[$key[0]] = $key[1]; } - return $settings[$key]['value']; + $ret = $settings[$key]; + return isset($ret) ? $ret['value'] : null; } function clearCache() From 080cc2781f034c844af658229e495e9a47fd2298 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 07:31:15 +0200 Subject: [PATCH 094/216] Fix mailer: send to email link from accounts page --- admin/pages/mailer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/pages/mailer.php b/admin/pages/mailer.php index 1f8d3188..f57be2d9 100644 --- a/admin/pages/mailer.php +++ b/admin/pages/mailer.php @@ -25,7 +25,7 @@ if (!setting('core.mail_enabled')) { return; } -$mail_to = isset($_POST['mail_to']) ? stripslashes(trim($_POST['mail_to'])) : null; +$mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null; $mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null; $mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null; From cf7fd20452e863980045bb5d6012ec86c6e8e01f Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 09:19:49 +0200 Subject: [PATCH 095/216] Mailer: send only to verified accounts (option) --- admin/pages/mailer.php | 16 +++++++++------- system/templates/admin.mailer.html.twig | 7 +++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/admin/pages/mailer.php b/admin/pages/mailer.php index f57be2d9..5ac8f58c 100644 --- a/admin/pages/mailer.php +++ b/admin/pages/mailer.php @@ -28,6 +28,7 @@ if (!setting('core.mail_enabled')) { $mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null; $mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null; $mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : null; +$mail_verified_only = $_POST['mail_verified_only'] ?? false; if (isset($_POST['submit'])) { if (empty($mail_subject)) { @@ -58,14 +59,14 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) { $success = 0; $failed = 0; - $add = ''; - if (setting('core.account_mail_verify')) { - note('Note: Sending only to users with verified E-Mail.'); - $add = ' AND `email_verified` = 1'; + $query = Account::where('email', '!=', ''); + + if ($mail_verified_only) { + info('Note: Sending only to users with verified E-Mail.'); + $query->where('email_verified', 1); } - $query = Account::where('email', '!=', '')->get(['email']); - foreach ($query as $email) { + foreach ($query->get(['email']) as $email) { if (_mail($email->email, $mail_subject, $mail_content)) { $success++; } @@ -84,5 +85,6 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) { $twig->display('admin.mailer.html.twig', [ 'mail_to' => $mail_to, 'mail_subject' => $mail_subject, - 'mail_content' => $mail_content + 'mail_content' => $mail_content, + 'mail_verified_only' => $mail_verified_only, ]); diff --git a/system/templates/admin.mailer.html.twig b/system/templates/admin.mailer.html.twig index 0b77ccb3..1dd2eb30 100644 --- a/system/templates/admin.mailer.html.twig +++ b/system/templates/admin.mailer.html.twig @@ -16,6 +16,13 @@
+ {% if setting('core.account_mail_verify') %} +
+ + +
+ {% endif %} +
From 43415cf35db1c1307f2684c1728693d65065ffff Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 12:32:18 +0200 Subject: [PATCH 096/216] Add missing $fillable into PlayerOnline model --- system/src/Models/PlayerOnline.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/src/Models/PlayerOnline.php b/system/src/Models/PlayerOnline.php index e81b591e..6405d9c4 100644 --- a/system/src/Models/PlayerOnline.php +++ b/system/src/Models/PlayerOnline.php @@ -9,6 +9,10 @@ class PlayerOnline extends Model { public $timestamps = false; + protected $fillable = [ + 'player_id', + ]; + public function player() { return $this->belongsTo(Player::class); From 3b47e9df2f4051807c5ff87892f7fa3d348f9c55 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 13:02:55 +0200 Subject: [PATCH 097/216] Cache::remember: $ttl = 0 means no cache --- system/src/Cache/Cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Cache/Cache.php b/system/src/Cache/Cache.php index 0a369202..53a84530 100644 --- a/system/src/Cache/Cache.php +++ b/system/src/Cache/Cache.php @@ -106,7 +106,7 @@ class Cache public static function remember($key, $ttl, $callback) { $cache = self::getInstance(); - if (!$cache->enabled()) { + if (!$cache->enabled() || $ttl == 0) { return $callback(); } From 0efe47ce71c4b364a9e96bc5a55b1655326ae6da Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 13:15:06 +0200 Subject: [PATCH 098/216] Twig: add cache variable --- system/twig.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/twig.php b/system/twig.php index baeae276..10f77cf3 100644 --- a/system/twig.php +++ b/system/twig.php @@ -156,3 +156,5 @@ $twig->addFilter($filter); unset($function, $filter); $hooks->trigger(HOOK_TWIG, ['twig' => $twig, 'twig_loader' => $twig_loader]); + +$twig->addGlobal('cache', $cache); From c8363086015cbb6e8786c398c7b9ac3959a26ec4 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 31 Jul 2025 13:28:46 +0200 Subject: [PATCH 099/216] pages/online: add cache, resulting in 20x performance boost (for an example server with 2k players) --- system/pages/online.php | 164 +++++++++++++++--------------- system/settings.php | 8 ++ system/templates/online.html.twig | 6 ++ 3 files changed, 98 insertions(+), 80 deletions(-) diff --git a/system/pages/online.php b/system/pages/online.php index e1bc25d4..3aa98c8f 100644 --- a/system/pages/online.php +++ b/system/pages/online.php @@ -9,18 +9,21 @@ * @link https://my-aac.org */ +use MyAAC\Cache\Cache; use MyAAC\Models\ServerConfig; use MyAAC\Models\ServerRecord; defined('MYAAC') or die('Direct access not allowed!'); $title = 'Who is online?'; -if (setting('core.account_country')) +if (setting('core.account_country')) { require SYSTEM . 'countries.conf.php'; +} $promotion = ''; -if($db->hasColumn('players', 'promotion')) +if($db->hasColumn('players', 'promotion')) { $promotion = '`promotion`,'; +} $order = $_GET['order'] ?? 'name_asc'; if(!in_array($order, ['country_asc', 'country_desc', 'name_asc', 'name_desc', 'level_asc', 'level_desc', 'vocation_asc', 'vocation_desc'])) { @@ -30,106 +33,107 @@ else if($order == 'vocation_asc' || $order == 'vocation_desc') { $order = $promotion . 'vocation_' . (str_contains($order, 'asc') ? 'asc' : 'desc'); } -$orderExplode = explode('_', $order); -$orderSql = $orderExplode[0] . ' ' . $orderExplode[1]; +$cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60, function() use($db, $promotion, $order) { + $orderExplode = explode('_', $order); + $orderSql = $orderExplode[0] . ' ' . $orderExplode[1]; -$skull_type = 'skull'; -if($db->hasColumn('players', 'skull_type')) { - $skull_type = 'skull_type'; -} + $skull_type = 'skull'; + if($db->hasColumn('players', 'skull_type')) { + $skull_type = 'skull_type'; + } -$skull_time = 'skulltime'; -if($db->hasColumn('players', 'skull_time')) { - $skull_time = 'skull_time'; -} + $skull_time = 'skulltime'; + if($db->hasColumn('players', 'skull_time')) { + $skull_time = 'skull_time'; + } -$outfit_addons = false; -$outfit = ''; -if (setting('core.online_outfit')) { + $outfit_addons = false; $outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype'; if($db->hasColumn('players', 'lookaddons')) { $outfit .= ', lookaddons'; $outfit_addons = true; } -} -$vocs = []; -if (setting('core.online_vocations')) { - foreach($config['vocations'] as $id => $name) { - $vocs[$id] = 0; - } -} + $vocations = array_map(function ($name) { + return 0; + }, setting('core.vocations')); -if($db->hasTable('players_online')) // tfs 1.0 - $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); -else - $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); + if($db->hasTable('players_online')) // tfs 1.0 + $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); + else + $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); -$players_data = []; -$players = 0; -$data = ''; -foreach($playersOnline as $player) { - $skull = ''; - if (setting('core.online_skulls')) - { - if($player['skulltime'] > 0) - { - if($player['skull'] == 3) + $settingVocations = setting('core.vocations'); + $settingVocationsAmount = setting('core.vocations_amount'); + + $players = []; + foreach($playersOnline as $player) { + $skull = ''; + if($player['skulltime'] > 0) { + if($player['skull'] == 3) { $skull = ' '; - elseif($player['skull'] == 4) + } + elseif($player['skull'] == 4) { $skull = ' '; - elseif($player['skull'] == 5) + } + elseif($player['skull'] == 5) { $skull = ' '; - } - } - - if(isset($player['promotion'])) { - if((int)$player['promotion'] > 0) - $player['vocation'] += ($player['promotion'] * $config['vocations_amount']); - } - - $players_data[] = array( - 'name' => getPlayerLink($player['name']), - 'player' => $player, - 'level' => $player['level'], - 'vocation' => $config['vocations'][$player['vocation']], - 'country_image' => setting('core.account_country') ? getFlagImage($player['country']) : null, - 'outfit' => setting('core.online_outfit') ? setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'] : null - ); - - if (setting('core.online_vocations')) { - $vocs[($player['vocation'] > $config['vocations_amount'] ? $player['vocation'] - $config['vocations_amount'] : $player['vocation'])]++; - } -} - -$record = ''; -if(count($players_data) > 0) { - if( setting('core.online_record')) { - $result = null; - $timestamp = false; - if($db->hasTable('server_record')) { - $timestamp = true; - $result = ServerRecord::where('world_id', $config['lua']['worldId'])->orderByDesc('record')->first()->toArray(); - } else if($db->hasTable('server_config')) { // tfs 1.0 - $row = ServerConfig::where('config', 'players_record')->first(); - if ($row) { - $result = ['record' => $row->value]; } } - if($result) { - $record = $result['record'] . ' player' . ($result['record'] > 1 ? 's' : '') . ($timestamp ? ' (on ' . date("M d Y, H:i:s", $result['timestamp']) . ')' : ''); + if(isset($player['promotion'])) { + if((int)$player['promotion'] > 0) + $player['vocation'] += ($player['promotion'] * $settingVocationsAmount); + } + + $players[] = array( + 'name' => getPlayerLink($player['name']), + 'player' => $player, + 'level' => $player['level'], + 'vocation' => $settingVocations[$player['vocation']], + 'skull' => $skull, + 'country_image' => getFlagImage($player['country']), + 'outfit' => setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'], + ); + + $vocations[($player['vocation'] > $settingVocationsAmount ? $player['vocation'] - $settingVocationsAmount : $player['vocation'])]++; + } + + $record = ''; + if(count($players) > 0) { + if( setting('core.online_record')) { + $result = null; + $timestamp = false; + if($db->hasTable('server_record')) { + $timestamp = true; + $result = ServerRecord::where('world_id', configLua('worldId'))->orderByDesc('record')->first()->toArray(); + } else if($db->hasTable('server_config')) { // tfs 1.0 + $row = ServerConfig::where('config', 'players_record')->first(); + if ($row) { + $result = ['record' => $row->value]; + } + } + + if($result) { + $record = $result['record'] . ' player' . ($result['record'] > 1 ? 's' : '') . ($timestamp ? ' (on ' . date("M d Y, H:i:s", $result['timestamp']) . ')' : ''); + } } } -} + + return [ + 'players' => $players, + 'record' => $record, + 'vocations' => $vocations, + ]; +}); $twig->display('online.html.twig', array( - 'players' => $players_data, - 'record' => $record, - 'vocs' => $vocs, + 'players' => $cached['players'], + 'record' => $cached['record'], + 'vocations' => $cached['vocations'], + 'vocs' => $cached['vocations'], // deprecated, to be removed 'order' => $order, )); -//search bar +// search bar $twig->display('characters.form.html.twig'); -?> diff --git a/system/settings.php b/system/settings.php index ae61fd52..5befa9ca 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1247,6 +1247,14 @@ Sent by MyAAC,
'type' => 'section', 'title' => 'Online Page' ], + 'online_cache_ttl' => [ + 'name' => 'Online Cache TTL (in minutes)', + 'type' => 'number', + 'min' => 0, + 'desc' => 'How often to update online list from database in minutes. Too low may slow down your website.' . PHP_EOL . + '0 to disable.', + 'default' => 15, + ], 'online_record' => [ 'name' => 'Display Players Record', 'type' => 'boolean', diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index 26a756ed..b5716858 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -1,3 +1,9 @@ +{% set onlineTTL = setting('core.online_cache_ttl') %} +{% if onlineTTL > 0 and cache.enabled() %} +*Note: Online List is updated every {{ onlineTTL > 1 ? ' ' ~ onlineTTL : '' }} minute{{ onlineTTL > 1 ? 's' : '' }}. +
+{% endif %} + {# vocation statistics #} {% if setting('core.online_vocations') %}
From e1c04ed28e0619a11f1636c18d81691284d78788 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 2 Aug 2025 12:28:13 +0200 Subject: [PATCH 100/216] Release v1.8 --- CHANGELOG-1.x.md | 36 ++++++++++++++++++++++++++++++++++++ common.php | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 28c946ec..716d11da 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,41 @@ # Changelog +## [1.8 - 01.08.2025] + +### Added +* Templates - Kathrine: Possibility to add custom menu categories (https://github.com/slawkens/myaac/commit/ec11c1402417c25980582467546d1c1e9bb8267f) +* Admin Panel - Accounts Editor: Add Coins Transferable (https://github.com/slawkens/myaac/commit/45d6047031c9c3a0e7e512dc5d15c75629aec5a2, https://github.com/slawkens/myaac/commit/bb097b69ce106500a49686d6f4fe604348eaa310) +* Highscores: + * Revamped: (https://github.com/slawkens/myaac/commit/d8132d4d76e03d5aa0c042be426320655a601392) + * Show real rank, if 2 or more players have the same skill, show them with same rank + * New setting: highscores_online_status + * Additional fields passed to twig: updatedAt, totalResults, page, baseLink + * Add new Setting: Display Skills Box (https://github.com/slawkens/myaac/commit/36ca755243ef1c83f6ac87465b426d4d8d3b0bb9) +* Functions: Add getExperienceForLevel (level) (https://github.com/slawkens/myaac/commit/1566deb84a082176b8c683fda205d828bc38fbcc) +* Commands - cache:clear : Add warning about APCu clear in CLI (https://github.com/slawkens/myaac/commit/83f84172e02e8ea2ccb6dca29bc033e44c35aebc) +* Models - PlayerOnline: Add missing $fillable into model (https://github.com/slawkens/myaac/commit/43415cf35db1c1307f2684c1728693d65065ffff) +* Twig: add cache variable (https://github.com/slawkens/myaac/commit/0efe47ce71c4b364a9e96bc5a55b1655326ae6da) + +### Changed +* pages/online: add cache, resulting in 20x performance boost + * (for an example server with 2k players) (https://github.com/slawkens/myaac/commit/c8363086015cbb6e8786c398c7b9ac3959a26ec4) +* Admin Bar: Move admin bar code into body_start place_holder (https://github.com/slawkens/myaac/commit/f17269e44ce9dd38447bd2e2a8e1bdb065d4161f) +* Cache::remember: $ttl = 0 means no cache (https://github.com/slawkens/myaac/commit/3b47e9df2f4051807c5ff87892f7fa3d348f9c55) +* Templates: Load config.ini with $process_sections set to true (https://github.com/slawkens/myaac/commit/a89f9a84847630eb75b4890fdcc8b7a7bfa6b8ac) +* Twig: Allow for timestamp as integer in the timeago twig function + (https://github.com/slawkens/myaac/commit/34fead906ea13b9f09d7a3c41ed88109d34d386c) + +### Fixed +* Settings: Fixed two exceptions (https://github.com/slawkens/myaac/commit/6e5a4ff8c78ff5373aba091baa66cae029557643, https://github.com/slawkens/myaac/commit/20d69a641c0a933d14889a89da6d32f6a4bc6c7d) +* Models\Account + OTS_Account -> isPremium -> ignore config.freePremium (https://github.com/slawkens/myaac/commit/5271633bdbfbbfed0b1d59c403093ce6fc2b7d20) +* Admin Panel - Mailer: + * Fix send to email link redirecting from accounts page (https://github.com/slawkens/myaac/commit/080cc2781f034c844af658229e495e9a47fd2298) + * Option to send only to verified accounts - only if setting('core.account_mail_verify') enabled (https://github.com/slawkens/myaac/commit/cf7fd20452e863980045bb5d6012ec86c6e8e01f) + +### Internal +* Rewrite to use constants (account transferable coins) (https://github.com/slawkens/myaac/commit/bccf8e056df985bbe1bab5f7ab5492f714d6b62b) +* Refactor to use HAS_ACCOUNT_COINS (https://github.com/slawkens/myaac/commit/caf326a6584a234775ebc6c8000ea02b3fecd160) + ## [1.7.1 - 27.06.2025] ### Changed diff --git a/common.php b/common.php index 7d8a905d..cf1909c3 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.7.2-dev'; +const MYAAC_VERSION = '1.8'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 785d38312b4673142089c1bfaa282f5841cd4531 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 2 Aug 2025 12:41:35 +0200 Subject: [PATCH 101/216] Start 1.8.1-dev --- CHANGELOG-1.x.md | 2 +- common.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 716d11da..b513cebf 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,6 +1,6 @@ # Changelog -## [1.8 - 01.08.2025] +## [1.8 - 02.08.2025] ### Added * Templates - Kathrine: Possibility to add custom menu categories (https://github.com/slawkens/myaac/commit/ec11c1402417c25980582467546d1c1e9bb8267f) diff --git a/common.php b/common.php index cf1909c3..3e6a9291 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8'; +const MYAAC_VERSION = '1.8.1-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 0db908be181f66b0434b4aad0b69462aa6eee4a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Aug 2025 14:15:13 +0200 Subject: [PATCH 102/216] Bump form-data from 4.0.2 to 4.0.4 (#315) Bumps [form-data](https://github.com/form-data/form-data) from 4.0.2 to 4.0.4. - [Release notes](https://github.com/form-data/form-data/releases) - [Changelog](https://github.com/form-data/form-data/blob/master/CHANGELOG.md) - [Commits](https://github.com/form-data/form-data/compare/v4.0.2...v4.0.4) --- updated-dependencies: - dependency-name: form-data dependency-version: 4.0.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7cdffe23..fb820852 100644 --- a/package-lock.json +++ b/package-lock.json @@ -976,15 +976,16 @@ } }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { From 9cb7792623a856fa3a4d6c0523c12456c96df238 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 16:21:22 +0200 Subject: [PATCH 103/216] Bump tmp from 0.2.3 to 0.2.4 (#317) Bumps [tmp](https://github.com/raszi/node-tmp) from 0.2.3 to 0.2.4. - [Changelog](https://github.com/raszi/node-tmp/blob/master/CHANGELOG.md) - [Commits](https://github.com/raszi/node-tmp/compare/v0.2.3...v0.2.4) --- updated-dependencies: - dependency-name: tmp dependency-version: 0.2.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb820852..3ea74539 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2085,9 +2085,9 @@ "license": "MIT" }, "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz", + "integrity": "sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==", "dev": true, "license": "MIT", "engines": { From b6e1620f14c20eecfc9001a7d86dfb67942985c6 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 7 Aug 2025 21:17:25 +0200 Subject: [PATCH 104/216] Fix #318 (online.php throws error in one scenario) --- system/pages/online.php | 13 +++++++++++-- system/templates/online.html.twig | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/system/pages/online.php b/system/pages/online.php index 3aa98c8f..21f2ee0d 100644 --- a/system/pages/online.php +++ b/system/pages/online.php @@ -105,8 +105,17 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60 $result = null; $timestamp = false; if($db->hasTable('server_record')) { - $timestamp = true; - $result = ServerRecord::where('world_id', configLua('worldId'))->orderByDesc('record')->first()->toArray(); + $timestamp = $db->hasColumn('server_record', 'timestamp'); + $serverRecordQuery = ServerRecord::query(); + + if ($db->hasColumn('server_record', 'world_id')) { + $serverRecordQuery->where('world_id', configLua('worldId')); + } + + $result = $serverRecordQuery->orderByDesc('record')->first(); + if ($result) { + $result = $result->toArray(); + } } else if($db->hasTable('server_config')) { // tfs 1.0 $row = ServerConfig::where('config', 'players_record')->first(); if ($row) { diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index b5716858..3a741aa1 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -90,7 +90,7 @@ - {% if setting('core.online_record') %} + {% if setting('core.online_record') and record|length > 0 %} Online Record: From 20f99903ae80c74ad66c1cf5a5ea8d0b0fc2fd70 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 12 Aug 2025 12:46:39 +0200 Subject: [PATCH 105/216] Fix submenu initialization for missing elements Added a check in InitializeMenu to skip submenu items if their corresponding DOM element does not exist, preventing potential JavaScript errors. --- templates/tibiacom/index.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 46ef0698..cb482018 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -164,6 +164,10 @@ if(isset($config['boxes'])) function InitializeMenu() { for(menuItemName in menu[0]) { + if (!document.getElementById(menuItemName+"_Submenu")) { + continue; + } + if(menu[0][menuItemName] == "0") { document.getElementById(menuItemName+"_Submenu").style.visibility = "hidden"; document.getElementById(menuItemName+"_Submenu").style.display = "none"; From 11dae90fa94fbbf47447017db5e5847c33d6aadf Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 12 Aug 2025 17:42:06 +0200 Subject: [PATCH 106/216] Fix MenuBotton display if some elements are removed From menu_categories --- templates/tibiacom/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index cb482018..9746e8d8 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -391,7 +391,7 @@ foreach($config['menu_categories'] as $id => $cat) { ?>
Date: Sun, 17 Aug 2025 17:50:16 +0200 Subject: [PATCH 107/216] Fix online skulls display (Fix #320) --- system/templates/online.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index 3a741aa1..bb6c786c 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -161,7 +161,7 @@ {% endif %} - {{ player.name|raw }}{{ player.skull }} + {{ player.name|raw }}{{ player.skull|raw }} {{ player.level }} {{ player.vocation }} From 2f26748112d412ba8106eb0cdbabeb8c69c98e87 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 17 Aug 2025 18:19:07 +0200 Subject: [PATCH 108/216] =?UTF-8?q?=E2=9D=A4=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- system/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index 5befa9ca..71cbc34e 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1295,7 +1295,7 @@ Sent by MyAAC,
'name' => 'Data Center', 'type' => 'text', 'desc' => 'Server Location, will be shown on online page', - 'default' => 'Frankfurt - Germany', + 'default' => 'Poland - Warsaw', ], [ 'type' => 'section', From 482f4067b2a2e7513d9ba214274a361ffaf123d8 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 17 Aug 2025 18:45:49 +0200 Subject: [PATCH 109/216] Menus should be saved for each template separately Trying to fix some weird bug --- system/template.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/template.php b/system/template.php index c97c8416..30cb5535 100644 --- a/system/template.php +++ b/system/template.php @@ -148,7 +148,7 @@ function get_template_menus(): array { global $template_name; - $result = Cache::remember('template_menus', 10 * 60, function () use ($template_name) { + $result = Cache::remember('template_menus_' . $template_name, 10 * 60, function () use ($template_name) { $result = Menu::select(['name', 'link', 'blank', 'color', 'category']) ->where('template', $template_name) ->orderBy('category') From 4701461b1f27ee23f660014c3c14fedeb6a98964 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 21 Aug 2025 20:54:58 +0200 Subject: [PATCH 110/216] Add some comment about optional sorting, into migrate:run command --- system/src/Commands/MigrateRunCommand.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/system/src/Commands/MigrateRunCommand.php b/system/src/Commands/MigrateRunCommand.php index 3bdb1452..0c8aa325 100644 --- a/system/src/Commands/MigrateRunCommand.php +++ b/system/src/Commands/MigrateRunCommand.php @@ -45,6 +45,22 @@ class MigrateRunCommand extends Command $down = $input->getOption('down') ?? false; + /** + * Sort according to $down option. + * Do we really want it? + * Or should we use order provided by user, + * even when it's not sorted correctly? + * Leaving it for consideration. + */ + /* + if ($down) { + rsort($ids); + } + else { + sort($ids); + } + */ + foreach ($ids as $id) { $this->executeMigration($id, $io, !$down); } From d85681880ee53164749fec1544b17205924960b8 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 21 Aug 2025 21:12:55 +0200 Subject: [PATCH 111/216] Rename file name to PluginSetupCommand --- .../{PluginInstallInstallCommand.php => PluginSetupCommand.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename system/src/Commands/{PluginInstallInstallCommand.php => PluginSetupCommand.php} (95%) diff --git a/system/src/Commands/PluginInstallInstallCommand.php b/system/src/Commands/PluginSetupCommand.php similarity index 95% rename from system/src/Commands/PluginInstallInstallCommand.php rename to system/src/Commands/PluginSetupCommand.php index 116eeb13..8923360c 100644 --- a/system/src/Commands/PluginInstallInstallCommand.php +++ b/system/src/Commands/PluginSetupCommand.php @@ -8,7 +8,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -class PluginInstallInstallCommand extends Command +class PluginSetupCommand extends Command { protected function configure(): void { From 3451715e96c4826989f4708cc9924adb41e7de67 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 22 Aug 2025 15:30:19 +0200 Subject: [PATCH 112/216] Settings class: Add type hints --- system/src/Settings.php | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/system/src/Settings.php b/system/src/Settings.php index ef3da830..fe16b2e7 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -7,16 +7,13 @@ use MyAAC\Models\Settings as ModelsSettings; class Settings implements \ArrayAccess { - static private $instance; - private $settingsFile = []; - private $settingsDatabase = []; - private $cache = []; - private $valuesAsked = []; - private $errors = []; + static private ?Settings $instance = null; + private array $settingsFile = []; + private array $settingsDatabase = []; + private array $cache = []; + private array $valuesAsked = []; + private array $errors = []; - /** - * @return Settings - */ public static function getInstance(): Settings { if (!self::$instance) { @@ -26,7 +23,7 @@ class Settings implements \ArrayAccess return self::$instance; } - public function load() + public function load(): void { $cache = Cache::getInstance(); if ($cache->enabled()) { @@ -47,7 +44,7 @@ class Settings implements \ArrayAccess } } - public function save($pluginName, $values) + public function save($pluginName, $values): bool { $this->loadPlugin($pluginName); @@ -104,7 +101,7 @@ class Settings implements \ArrayAccess return true; } - public function updateInDatabase($pluginName, $key, $value) + public function updateInDatabase($pluginName, $key, $value): void { if (ModelsSettings::where(['name' => $pluginName, 'key' => $key])->exists()) { ModelsSettings::where(['name' => $pluginName, 'key' => $key])->update(['value' => $value]); @@ -117,7 +114,7 @@ class Settings implements \ArrayAccess $this->clearCache(); } - public function deleteFromDatabase($pluginName, $key = null) + public function deleteFromDatabase($pluginName, $key = null): void { if (!isset($key)) { ModelsSettings::where('name', $pluginName)->delete(); @@ -383,7 +380,7 @@ class Settings implements \ArrayAccess } #[\ReturnTypeWillChange] - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { if (is_null($offset)) { throw new \RuntimeException("Settings: You cannot set empty offset with value: $value!"); @@ -423,7 +420,7 @@ class Settings implements \ArrayAccess } #[\ReturnTypeWillChange] - public function offsetUnset($offset) + public function offsetUnset($offset): void { $this->loadPlugin($offset); @@ -455,7 +452,7 @@ class Settings implements \ArrayAccess * @return array|mixed */ #[\ReturnTypeWillChange] - public function offsetGet($offset) + public function offsetGet($offset): mixed { // try cache hit if(isset($this->cache[$offset])) { @@ -521,7 +518,7 @@ class Settings implements \ArrayAccess return $ret; } - private function updateValuesAsked($offset) + private function updateValuesAsked($offset): void { $pluginKeyName = $offset; if (strpos($offset, '.')) { @@ -537,7 +534,7 @@ class Settings implements \ArrayAccess } } - private function loadPlugin($offset) + private function loadPlugin($offset): void { $this->updateValuesAsked($offset); @@ -566,7 +563,7 @@ class Settings implements \ArrayAccess } } - public static function saveConfig($config, $filename, &$content = '') + public static function saveConfig($config, $filename, &$content = ''): bool|int { $content = " Date: Fri, 22 Aug 2025 16:04:52 +0200 Subject: [PATCH 113/216] Refactor code to use Cache::remember --- system/src/Settings.php | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/system/src/Settings.php b/system/src/Settings.php index fe16b2e7..17dc11f4 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -25,23 +25,16 @@ class Settings implements \ArrayAccess public function load(): void { - $cache = Cache::getInstance(); - if ($cache->enabled()) { - $tmp = ''; - if ($cache->fetch('settings', $tmp)) { - $this->settingsDatabase = unserialize($tmp); - return; + $this->settingsDatabase = Cache::remember('settings', 10 * 60, function () { + $settingsDatabase = []; + + $settings = ModelsSettings::all(); + foreach ($settings as $setting) { + $settingsDatabase[$setting->name][$setting->key] = $setting->value; } - } - $settings = ModelsSettings::all(); - foreach ($settings as $setting) { - $this->settingsDatabase[$setting->name][$setting->key] = $setting->value; - } - - if ($cache->enabled()) { - $cache->set('settings', serialize($this->settingsDatabase), 600); - } + return $settingsDatabase; + }); } public function save($pluginName, $values): bool From f8c4332e03e838d285ea0afb4b72b7c23e324d45 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 22 Aug 2025 17:27:53 +0200 Subject: [PATCH 114/216] Option to reset plugin settings by plugin name --- system/src/Commands/SettingsResetCommand.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/system/src/Commands/SettingsResetCommand.php b/system/src/Commands/SettingsResetCommand.php index 78748b00..3e4d793c 100644 --- a/system/src/Commands/SettingsResetCommand.php +++ b/system/src/Commands/SettingsResetCommand.php @@ -3,6 +3,7 @@ namespace MyAAC\Commands; use MyAAC\Models\Settings as SettingsModel; +use MyAAC\Plugins; use MyAAC\Settings; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -34,7 +35,14 @@ class SettingsResetCommand extends Command return Command::FAILURE; } - if (!$name) { + // find by plugin name + foreach (Plugins::getAllPluginsSettings() as $key => $setting) { + if ($setting['pluginFilename'] === $name) { + $name = $key; + } + } + + if (empty($name)) { SettingsModel::truncate(); } else { From bcc4b48eb05c4a9a61c7451ff7dfafa2266f530c Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 22 Aug 2025 17:39:14 +0200 Subject: [PATCH 115/216] Settings: Option to set boolean values as "yes" --- system/src/Settings.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/system/src/Settings.php b/system/src/Settings.php index 17dc11f4..bd4fb488 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -220,12 +220,7 @@ class Settings implements \ArrayAccess } else if ($setting['type'] === 'boolean') { if(isset($settingsDb[$key])) { - if($settingsDb[$key] === 'true') { - $value = true; - } - else { - $value = false; - } + $value = getBoolean($settingsDb[$key]); } else { $value = ($setting['default'] ?? false); From 17ca93d02020f18c3db86e72934d92b4e2e7b546 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 22 Aug 2025 17:51:19 +0200 Subject: [PATCH 116/216] Same with default --- system/src/Settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Settings.php b/system/src/Settings.php index bd4fb488..ec4a83fa 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -207,7 +207,7 @@ class Settings implements \ArrayAccess if (isset($setting['hidden']) && $setting['hidden']) { $value = ''; if ($setting['type'] === 'boolean') { - $value = ($setting['default'] ? 'true' : 'false'); + $value = (getBoolean($setting['default']) ? 'true' : 'false'); } else if (in_array($setting['type'], ['text', 'number', 'float', 'double', 'email', 'password', 'textarea'])) { $value = $setting['default']; From 4b948e9510f7ba69d00f84d7fdaea8b3bf05b630 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 22 Aug 2025 18:20:37 +0200 Subject: [PATCH 117/216] Option to change/set plugin settings by plugin name --- system/src/Commands/SettingsSetCommand.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/system/src/Commands/SettingsSetCommand.php b/system/src/Commands/SettingsSetCommand.php index 4ad33227..eac0ecc5 100644 --- a/system/src/Commands/SettingsSetCommand.php +++ b/system/src/Commands/SettingsSetCommand.php @@ -3,6 +3,7 @@ namespace MyAAC\Commands; use MyAAC\Models\Settings as SettingsModel; +use MyAAC\Plugins; use MyAAC\Settings; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -17,7 +18,7 @@ class SettingsSetCommand extends Command ->setDescription('Updates the setting specified by argument in database') ->addArgument('key', InputArgument::REQUIRED, - 'Setting name/key' + 'Setting key in format name.key' ) ->addArgument('value', InputArgument::REQUIRED, @@ -34,6 +35,18 @@ class SettingsSetCommand extends Command $key = $input->getArgument('key'); $value = $input->getArgument('value'); + // format settings_name.key + // example: core.template + $explode = explode('.', $key); + + // find by plugin name + foreach (Plugins::getAllPluginsSettings() as $_key => $setting) { + if ($setting['pluginFilename'] === $explode[0]) { + $explode[0] = $_key; + $key = implode('.', $explode); + } + } + $settings = Settings::getInstance(); $settings->clearCache(); $settings->load(); @@ -44,10 +57,6 @@ class SettingsSetCommand extends Command return Command::FAILURE; } - // format plugin_name.key - // example: core.template - $explode = explode('.', $key); - $settings->updateInDatabase($explode[0], $explode[1], $value); $settings->clearCache(); From 7a08f91d3fc0897c1ff76089ef3c649a2c6d2003 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 25 Aug 2025 09:31:50 +0200 Subject: [PATCH 118/216] plugin:unistall command --- .../src/Commands/PluginUninstallCommand.php | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 system/src/Commands/PluginUninstallCommand.php diff --git a/system/src/Commands/PluginUninstallCommand.php b/system/src/Commands/PluginUninstallCommand.php new file mode 100644 index 00000000..f1a14138 --- /dev/null +++ b/system/src/Commands/PluginUninstallCommand.php @@ -0,0 +1,40 @@ +setName('plugin:uninstall') + ->setDescription('This command uninstalls plugin') + ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to uninstall'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + require SYSTEM . 'init.php'; + + $io = new SymfonyStyle($input, $output); + + $pluginName = $input->getArgument('plugin-name'); + + if (!Plugins::uninstall($pluginName)) { + $io->error('Error while uninstalling plugin ' . $pluginName . ': ' . Plugins::getError()); + return 2; + } + + foreach(Plugins::getWarnings() as $warning) { + $io->warning($warning); + } + + $io->success($pluginName . ' plugin has been successfully installed.'); + return Command::SUCCESS; + } +} From 1b9f68c9ec92365fde317de3d7820d8a416d71ca Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 25 Aug 2025 10:58:54 +0200 Subject: [PATCH 119/216] Update PluginUninstallCommand.php --- system/src/Commands/PluginUninstallCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Commands/PluginUninstallCommand.php b/system/src/Commands/PluginUninstallCommand.php index f1a14138..a5cc00f5 100644 --- a/system/src/Commands/PluginUninstallCommand.php +++ b/system/src/Commands/PluginUninstallCommand.php @@ -34,7 +34,7 @@ class PluginUninstallCommand extends Command $io->warning($warning); } - $io->success($pluginName . ' plugin has been successfully installed.'); + $io->success('Successfully uninstalled plugin ' . $pluginName); return Command::SUCCESS; } } From fec773ba4b740f35c0a3ef92ca8444a4c7d02082 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 25 Aug 2025 11:35:56 +0200 Subject: [PATCH 120/216] plugin:enable/disable commands --- system/src/Commands/PluginDisableCommand.php | 36 ++++++++++++++++++++ system/src/Commands/PluginEnableCommand.php | 36 ++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 system/src/Commands/PluginDisableCommand.php create mode 100644 system/src/Commands/PluginEnableCommand.php diff --git a/system/src/Commands/PluginDisableCommand.php b/system/src/Commands/PluginDisableCommand.php new file mode 100644 index 00000000..baa268dd --- /dev/null +++ b/system/src/Commands/PluginDisableCommand.php @@ -0,0 +1,36 @@ +setName('plugin:disable') + ->setDescription('This command disables plugin') + ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to disable'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + require SYSTEM . 'init.php'; + + $io = new SymfonyStyle($input, $output); + + $pluginName = $input->getArgument('plugin-name'); + + if (!Plugins::disable($pluginName)) { + $io->error('Error while disabling plugin ' . $pluginName . ': ' . Plugins::getError()); + return 2; + } + + $io->success('Successfully disabled plugin ' . $pluginName); + return Command::SUCCESS; + } +} diff --git a/system/src/Commands/PluginEnableCommand.php b/system/src/Commands/PluginEnableCommand.php new file mode 100644 index 00000000..ae1acea0 --- /dev/null +++ b/system/src/Commands/PluginEnableCommand.php @@ -0,0 +1,36 @@ +setName('plugin:enable') + ->setDescription('This command enables plugin') + ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to enable'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + require SYSTEM . 'init.php'; + + $io = new SymfonyStyle($input, $output); + + $pluginName = $input->getArgument('plugin-name'); + + if (!Plugins::enable($pluginName)) { + $io->error('Error while enabling plugin ' . $pluginName . ': ' . Plugins::getError()); + return 2; + } + + $io->success('Successfully enabled plugin ' . $pluginName); + return Command::SUCCESS; + } +} From 42671c5c199dd9e91c774d8c9d30da9e12f1b695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Morais?= Date: Wed, 27 Aug 2025 06:26:46 -0300 Subject: [PATCH 121/216] Update settings.php (#321) * Update settings.php added Transferable Coins to the store dropdown menu in the admin area * Adjust code a bit --------- Co-authored-by: slawkens --- system/settings.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index 71cbc34e..904c46f5 100644 --- a/system/settings.php +++ b/system/settings.php @@ -28,6 +28,15 @@ if (!IS_CLI) { $siteURL = $serverUrl . $baseDir; } +$donateColumnOptions = [ + 'premium_points' => 'Premium Points', + 'coins' => 'Coins', +]; + +if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) { + $donateColumnOptions[ACCOUNT_COINS_TRANSFERABLE_COLUMN] = 'Coins Transferable'; +} + return [ 'name' => 'MyAAC', 'settings' => [ @@ -1598,7 +1607,7 @@ Sent by MyAAC,
'name' => 'Donate Column', 'type' => 'options', 'desc' => 'What to give to player after donation - what column in accounts table to use.', - 'options' => ['premium_points' => 'Premium Points', 'coins' => 'Coins'], + 'options' => $donateColumnOptions, 'default' => 'premium_points', 'callbacks' => [ 'beforeSave' => function($key, $value, &$errorMessage) { From 2465bb6f9a284596024491eecd1e4c1223996d37 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 27 Aug 2025 11:40:54 +0200 Subject: [PATCH 122/216] Update settings.php --- system/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index 904c46f5..8f69dd48 100644 --- a/system/settings.php +++ b/system/settings.php @@ -33,7 +33,7 @@ $donateColumnOptions = [ 'coins' => 'Coins', ]; -if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) { +if (defined('HAS_ACCOUNT_COINS_TRANSFERABLE') && (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS)) { $donateColumnOptions[ACCOUNT_COINS_TRANSFERABLE_COLUMN] = 'Coins Transferable'; } From e4b66f34ac1751c3e3c2559c631cf8ec58c3cb3c Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 27 Aug 2025 12:15:52 +0200 Subject: [PATCH 123/216] Fix check for donate column --- system/settings.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/system/settings.php b/system/settings.php index 8f69dd48..5c703494 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1612,8 +1612,9 @@ Sent by MyAAC,
'callbacks' => [ 'beforeSave' => function($key, $value, &$errorMessage) { global $db; - if ($value == 'coins' && !HAS_ACCOUNT_COINS) { - $errorMessage = "Shop: Donate Column: Cannot set column to coins, because it doesn't exist in database."; + + if (!$db->hasColumn('accounts', $value)) { + $errorMessage = "Shop: Donate Column: Cannot set column to $value, because it doesn't exist in database."; return false; } return true; From 46adeefce3368835a876acca712310a4398a0410 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 27 Aug 2025 15:30:52 +0200 Subject: [PATCH 124/216] Update settings.php --- system/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/settings.php b/system/settings.php index 5c703494..73605530 100644 --- a/system/settings.php +++ b/system/settings.php @@ -1612,7 +1612,7 @@ Sent by MyAAC,
'callbacks' => [ 'beforeSave' => function($key, $value, &$errorMessage) { global $db; - + if (!$db->hasColumn('accounts', $value)) { $errorMessage = "Shop: Donate Column: Cannot set column to $value, because it doesn't exist in database."; return false; From 9725a3c2bdb7003f5cb48febb77604c31a9b805b Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 3 Sep 2025 23:47:27 +0200 Subject: [PATCH 125/216] Some servers don't have guild_invites table --- system/pages/guilds/invite.php | 10 ++++++++- system/pages/guilds/show.php | 29 ++++++++++++++------------ system/templates/guilds.view.html.twig | 18 +++++++++------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/system/pages/guilds/invite.php b/system/pages/guilds/invite.php index 9d6c9c06..0984fd0a 100644 --- a/system/pages/guilds/invite.php +++ b/system/pages/guilds/invite.php @@ -23,6 +23,12 @@ if(!Validator::guildName($guild_name)) { $errors[] = Validator::getLastError(); } +if (!$db->hasTableAndColumns('guild_invites', ['player_id'])) { + $errors[] = "Guild invite is not possible on this website."; + $twig->display('error_box.html.twig', ['errors' => $errors]); + return; +} + if(empty($errors)) { $guild = new OTS_Guild(); $guild->find($guild_name); @@ -58,7 +64,7 @@ if(empty($errors)) { } } -if(!$guild_vice) { +if(empty($errors) && !$guild_vice) { $errors[] = 'You are not a leader or vice leader of guild '.$guild_name.'.'.$level_in_guild; } @@ -84,6 +90,7 @@ if(isset($_POST['todo']) && $_POST['todo'] == 'save') { } } } + if(empty($errors)) { include(SYSTEM . 'libs/pot/InvitesDriver.php'); new InvitesDriver($guild); @@ -104,6 +111,7 @@ if(!empty($errors)) { else { if(isset($_POST['todo']) && $_POST['todo'] == 'save') { $guild->invite($player); + $twig->display('success.html.twig', array( 'title' => 'Invite player', 'description' => 'Player with name ' . $player->getName() . ' has been invited to your guild.', diff --git a/system/pages/guilds/show.php b/system/pages/guilds/show.php index 6fd07a91..99ac6599 100644 --- a/system/pages/guilds/show.php +++ b/system/pages/guilds/show.php @@ -121,25 +121,28 @@ foreach($rank_list as $rank) } } -include(SYSTEM . 'libs/pot/InvitesDriver.php'); -new InvitesDriver($guild); -$invited_list = $guild->listInvites(); +$invited_list = []; $show_accept_invite = 0; -if($logged && count($invited_list) > 0) -{ - foreach($invited_list as $invited_player) - { - if(count($account_players) > 0) - { - foreach($account_players as $player_from_acc) - { - if($player_from_acc->isLoaded() && $invited_player->isLoaded() && $player_from_acc->getName() == $invited_player->getName()) - $show_accept_invite++; + +if ($db->hasTableAndColumns('guild_invites', ['player_id'])) { + include(SYSTEM . 'libs/pot/InvitesDriver.php'); + new InvitesDriver($guild); + $invited_list = $guild->listInvites(); + + if($logged && count($invited_list) > 0) { + foreach($invited_list as $invited_player) { + if(count($account_players) > 0) { + foreach($account_players as $player_from_acc) { + if($player_from_acc->isLoaded() && $invited_player->isLoaded() && $player_from_acc->getName() == $invited_player->getName()) { + $show_accept_invite++; + } + } } } } } + $useGuildNick = $db->hasTable('guild_members') || $db->hasTable('guild_membership') || $db->hasColumn('players', 'guildnick'); $twig->display('guilds.view.html.twig', array( diff --git a/system/templates/guilds.view.html.twig b/system/templates/guilds.view.html.twig index b8c0d0be..33dc1d3d 100644 --- a/system/templates/guilds.view.html.twig +++ b/system/templates/guilds.view.html.twig @@ -235,14 +235,16 @@ {% endif %} {% if isVice %} - - {{ csrf() }} - - {% set button_name = 'Invite Character' %} - {% set button_image = '_sbutton_invitecharacter' %} - {% include('buttons.base.html.twig') %} - - + {% if db.hasTableAndColumns('guild_invites', ['player_id']) %} +
+ {{ csrf() }} + + {% set button_name = 'Invite Character' %} + {% set button_image = '_sbutton_invitecharacter' %} + {% include('buttons.base.html.twig') %} + +
+ {% endif %}
{{ csrf() }} From 7a9b11434e29a4c6345251b6f3e522143b3e6234 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 5 Sep 2025 13:25:25 +0200 Subject: [PATCH 126/216] Release v1.8.1 --- CHANGELOG-1.x.md | 16 ++++++++++++++++ common.php | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index b513cebf..8602a0c6 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,21 @@ # Changelog +## [1.8.1 - 05.09.2025] + +### Added +* New Commands: plugin:enable/disable/uninstall {plugin-name} (https://github.com/slawkens/myaac/commit/7a08f91d3fc0897c1ff76089ef3c649a2c6d2003, https://github.com/slawkens/myaac/commit/fec773ba4b740f35c0a3ef92ca8444a4c7d02082) +* Gifts: Added Transferable Coins to the store dropdown menu in the admin area (by @andreoam, #321) (https://github.com/slawkens/myaac/commit/42671c5c199dd9e91c774d8c9d30da9e12f1b695) + +### Changed +* Commands: Allow settings to be changed/reset by plugin name (https://github.com/slawkens/myaac/commit/f8c4332e03e838d285ea0afb4b72b7c23e324d45, https://github.com/slawkens/myaac/commit/4b948e9510f7ba69d00f84d7fdaea8b3bf05b630) +* Templates: Menus should be saved for each template separately (https://github.com/slawkens/myaac/commit/482f4067b2a2e7513d9ba214274a361ffaf123d8) + +### Fixed +* Online: Fix skulls display (#320) (https://github.com/slawkens/myaac/commit/98073a110ae13f9592ec9d2c4d1d1aace87587a9) +* Online: Fix if there is no world_id in the server_record table (https://github.com/slawkens/myaac/commit/b6e1620f14c20eecfc9001a7d86dfb67942985c6) (Reported by @gesior in #318) +* tibiacom: some fixes to menus (https://github.com/slawkens/myaac/commit/20f99903ae80c74ad66c1cf5a5ea8d0b0fc2fd70, https://github.com/slawkens/myaac/commit/11dae90fa94fbbf47447017db5e5847c33d6aadf) +* Guilds: Fix for some servers that don't have guild_invites table (https://github.com/slawkens/myaac/commit/9725a3c2bdb7003f5cb48febb77604c31a9b805b) + ## [1.8 - 02.08.2025] ### Added diff --git a/common.php b/common.php index 3e6a9291..2e80ad4b 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.1-dev'; +const MYAAC_VERSION = '1.8.1'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 0b8645994092d53f69fa4253be4f348f78025ff1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 7 Sep 2025 09:33:18 +0200 Subject: [PATCH 127/216] Start v1.8.2-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 2e80ad4b..3c0f7890 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.1'; +const MYAAC_VERSION = '1.8.2-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 3f24f961b1cdeff5c60387e837ae454448bc5e1b Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 9 Sep 2025 15:17:06 +0200 Subject: [PATCH 128/216] Possibility to override routes with plugins pages, like characters.php No need to define routes in plugin.json anymore --- system/router.php | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/system/router.php b/system/router.php index a6da5f4b..9c9ce4ad 100644 --- a/system/router.php +++ b/system/router.php @@ -94,19 +94,30 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) $routesFinal[] = ['*', $page, '__database__/' . $page, 100]; } + $routes = require SYSTEM . 'routes.php'; Plugins::clearWarnings(); - foreach (Plugins::getRoutes() as $route) { - $routesFinal[] = [$route[0], $route[1], $route[2], $route[3] ?? 1000]; + + foreach (Plugins::getRoutes() as $pluginRoute) { + + $routesFinal[] = [$pluginRoute[0], $pluginRoute[1], $pluginRoute[2], $pluginRoute[3] ?? 1000]; + + // Possibility to override routes with plugins pages, like characters.php + foreach ($routes as &$route) { + if (str_contains($pluginRoute[2], 'pages/' . $route[2])) { + $route[2] = $pluginRoute[2]; + } + } /* echo '
';
-		var_dump($route[1], $route[3], $route[2]);
+		var_dump($pluginRoute[1], $pluginRoute[3], $pluginRoute[2]);
 		echo '/
';
 */
 	}
 
-	$routes = require SYSTEM . 'routes.php';
 	foreach ($routes as $route) {
-		if (!str_contains($route[2], '__redirect__') && !str_contains($route[2], '__database__')) {
+		if (!str_contains($route[2], '__redirect__') && !str_contains($route[2], '__database__')
+			&& !str_contains($route[2], 'plugins/')
+		) {
 			if (!is_file(BASE . 'system/pages/' . $route[2])) {
 				continue;
 			}

From 4eab805d26d8c5562b29ed699769919d77dabced Mon Sep 17 00:00:00 2001
From: slawkens 
Date: Tue, 9 Sep 2025 17:49:05 +0200
Subject: [PATCH 129/216] Fix when config.local.php cannot be saved

---
 install/steps/5-database.php | 61 ++++++++++++++++++------------------
 1 file changed, 30 insertions(+), 31 deletions(-)

diff --git a/install/steps/5-database.php b/install/steps/5-database.php
index cb4f14a3..ecf7f150 100644
--- a/install/steps/5-database.php
+++ b/install/steps/5-database.php
@@ -42,45 +42,44 @@ if(!$error) {
 	$configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true);
 	$configToSave['database_auto_migrate'] = true;
 
-	if(!$error) {
-		$content = '';
-		$saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
-		if ($saved) {
-			success($locale['step_database_config_saved']);
-			$_SESSION['saved'] = true;
+	$content = '';
+	$saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
+	if ($saved || file_exists(BASE . 'config.local.php')) {
+		success($locale['step_database_config_saved']);
+		$_SESSION['saved'] = true;
 
-			require BASE . 'config.local.php';
-			require BASE . 'install/includes/config.php';
+		require BASE . 'config.local.php';
+		require BASE . 'install/includes/config.php';
 
-			if (!$error) {
-				require BASE . 'install/includes/database.php';
+		if (!$error) {
+			require BASE . 'install/includes/database.php';
 
-				if (isset($database_error)) { // we failed connect to the database
-					error($database_error);
+			if (isset($database_error)) { // we failed connect to the database
+				error($database_error);
+			}
+			else {
+				if (!$db->hasTable('accounts')) {
+					$tmp = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']);
+					error($tmp);
+					$error = true;
 				}
-				else {
-					if (!$db->hasTable('accounts')) {
-						$tmp = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']);
-						error($tmp);
-						$error = true;
-					}
 
-					if (!$error) {
-						$twig->display('install.installer.html.twig', array(
-							'url' => 'tools/5-database.php',
-							'message' => $locale['loading_spinner']
-						));
-					}
+				if (!$error) {
+					$twig->display('install.installer.html.twig', array(
+						'url' => 'tools/5-database.php',
+						'message' => $locale['loading_spinner']
+					));
 				}
 			}
-		} else {
-			$_SESSION['config_content'] = $content;
-			unset($_SESSION['saved']);
-
-			$locale['step_database_error_file'] = str_replace('$FILE$', '' . BASE . 'config.php', $locale['step_database_error_file']);
-			error($locale['step_database_error_file'] . '
- '); } + } else { + $error = true; + $_SESSION['config_content'] = $content; + unset($_SESSION['saved']); + + $locale['step_database_error_file'] = str_replace('$FILE$', '' . BASE . 'config.local.php', $locale['step_database_error_file']); + error($locale['step_database_error_file'] . '
+ '); } } ?> From a6032093b21e5bb3f0e75d2704da87d6dea6469d Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 14 Sep 2025 19:35:12 +0200 Subject: [PATCH 130/216] Better look for myaac-table --- system/templates/tables.style.html.twig | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/system/templates/tables.style.html.twig b/system/templates/tables.style.html.twig index 479db426..d4c2e91a 100644 --- a/system/templates/tables.style.html.twig +++ b/system/templates/tables.style.html.twig @@ -1,6 +1,9 @@ From 5aa9bbf1c8e580d973ec82ac012489f8e7bc437e Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 14 Sep 2025 20:50:00 +0200 Subject: [PATCH 131/216] Ignore child tables of myaac-table class --- system/templates/tables.style.html.twig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/system/templates/tables.style.html.twig b/system/templates/tables.style.html.twig index d4c2e91a..8aa6305b 100644 --- a/system/templates/tables.style.html.twig +++ b/system/templates/tables.style.html.twig @@ -1,9 +1,9 @@ From ed9beaf2b6ca069e304e569c52e5b9188b58f05c Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 14 Sep 2025 21:02:01 +0200 Subject: [PATCH 132/216] Fix account lost routes in tibiacom template --- templates/tibiacom/index.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 9746e8d8..bd00cf02 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -37,7 +37,9 @@ if(isset($config['boxes'])) $tmp = str_replace('/', '_', PAGE); $exp = explode('/', PAGE); if(PAGE !== 'account/create' && PAGE !== 'account/lost' && isset($exp[1])) { - if ($exp[0] === 'account') { + if ($exp[0] === 'account' && $exp[1] === 'lost') { + $tmp = 'account_lost'; + } elseif ($exp[0] === 'account') { $tmp = 'account_manage'; } else if ($exp[0] === 'news' && $exp[1] === 'archive') { $tmp = 'news_archive'; From d0112d1a67e8b854b65ad131f0375b79305df8d3 Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 23 Sep 2025 21:45:32 +0200 Subject: [PATCH 133/216] Fix exception when email cannot be send on create account --- system/pages/account/create.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 15f2b8b5..7a0d3c56 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -268,8 +268,10 @@ if($save) } else { - error('An error occorred while sending email! Account not created. Try again. For Admin: More info can be found in system/logs/mailer-error.log'); + error('An error occurred while sending email! Account not created. Try again. For Admin: More info can be found in system/logs/mailer-error.log'); $new_account->delete(); + + return; } } else From 3c0cb53e17dd0b85394cfa0fdc9cf9ad8d4551df Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 23 Sep 2025 21:45:49 +0200 Subject: [PATCH 134/216] Add missing csrf() - fix create account buton --- templates/tibiacom/account.login.html.twig | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/tibiacom/account.login.html.twig b/templates/tibiacom/account.login.html.twig index 505cb38a..2125bee9 100644 --- a/templates/tibiacom/account.login.html.twig +++ b/templates/tibiacom/account.login.html.twig @@ -130,6 +130,7 @@
{% apply spaceless %} + {{ csrf() }}
From 85e7005fd3f0be51466151a3c122b96085fdfe68 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 24 Sep 2025 15:39:47 +0200 Subject: [PATCH 135/216] Fix Menu div wrong tag/closing (#329) --- templates/tibiacom/index.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index bd00cf02..4fd5a72a 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -338,7 +338,7 @@ if(isset($config['boxes']))
- + From e0cc19ad86408ea27d2e5bbe8acfc3dc1bcb28c0 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 26 Sep 2025 07:54:40 +0200 Subject: [PATCH 136/216] Release v1.8.2 --- CHANGELOG-1.x.md | 15 +++++++++++++++ common.php | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 8602a0c6..98a7b537 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,20 @@ # Changelog +## [1.8.2 - 26.09.2025] + +### Added +* Routes: Possibility to override routes with plugins pages, like characters.php - No need to define routes in plugin.json anymore (https://github.com/slawkens/myaac/commit/3f24f961b1cdeff5c60387e837ae454448bc5e1b) + +### Changed +* Style: Better look for myaac-table (https://github.com/slawkens/myaac/commit/a6032093b21e5bb3f0e75d2704da87d6dea6469d, https://github.com/slawkens/myaac/commit/5aa9bbf1c8e580d973ec82ac012489f8e7bc437e) + +### Fixed +* Install: Fix when config.local.php cannot be saved (https://github.com/slawkens/myaac/commit/4eab805d26d8c5562b29ed699769919d77dabced) +* Create Account: Fix an exception when email cannot be sent (https://github.com/slawkens/myaac/commit/d0112d1a67e8b854b65ad131f0375b79305df8d3) +* Login Page: Add missing csrf() - fix create account button (https://github.com/slawkens/myaac/commit/3c0cb53e17dd0b85394cfa0fdc9cf9ad8d4551df) +* tibiacom template: Fix account lost menu (https://github.com/slawkens/myaac/commit/ed9beaf2b6ca069e304e569c52e5b9188b58f05c) +* tibiacom template: Fix Menu div wrong tag/closing (#329) (https://github.com/slawkens/myaac/commit/85e7005fd3f0be51466151a3c122b96085fdfe68) + ## [1.8.1 - 05.09.2025] ### Added diff --git a/common.php b/common.php index 3c0f7890..868754d2 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.2-dev'; +const MYAAC_VERSION = '1.8.2'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From df7b6e29fb8875da97f431468c81ee99116271d9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 26 Sep 2025 08:56:15 +0200 Subject: [PATCH 137/216] Replace firstChild with firstElementChild (Thanks to @un000000) --- templates/tibiacom/index.php | 12 ++++++------ tools/basic.js | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 4fd5a72a..5812b1cf 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -92,13 +92,13 @@ if(isset($config['boxes'])) // mouse-over and click events of the loginbox function MouseOverLoginBoxText(source) { - source.lastChild.style.visibility = "visible"; - source.firstChild.style.visibility = "hidden"; + source.lastElementChild.style.visibility = "visible"; + source.firstElementChild.style.visibility = "hidden"; } function MouseOutLoginBoxText(source) { - source.firstChild.style.visibility = "visible"; - source.lastChild.style.visibility = "hidden"; + source.firstElementChild.style.visibility = "visible"; + source.lastElementChild.style.visibility = "hidden"; } function LoginButtonAction() { @@ -228,11 +228,11 @@ if(isset($config['boxes'])) // mouse-over effects of menubuttons and submenuitems function MouseOverMenuItem(source) { - source.firstChild.style.visibility = "visible"; + source.firstElementChild.style.visibility = "visible"; } function MouseOutMenuItem(source) { - source.firstChild.style.visibility = "hidden"; + source.firstElementChild.style.visibility = "hidden"; } function MouseOverSubmenuItem(source) { diff --git a/tools/basic.js b/tools/basic.js index 8fa21fa9..c5f84618 100644 --- a/tools/basic.js +++ b/tools/basic.js @@ -1,11 +1,11 @@ function MouseOverBigButton(source) { - if (source?.firstChild?.style) { - source.firstChild.style.visibility = "visible"; + if (source?.firstElementChild?.style) { + source.firstElementChild.style.visibility = "visible"; } } function MouseOutBigButton(source) { - if (source?.firstChild?.style) { - source.firstChild.style.visibility = "hidden"; + if (source?.firstElementChild?.style) { + source.firstElementChild.style.visibility = "hidden"; } } function BigButtonAction(path) { From ac41b82579cbe231b33fdc13f93d7f284965cf0c Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 26 Sep 2025 10:14:38 +0200 Subject: [PATCH 138/216] Update index.php --- templates/tibiacom/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 5812b1cf..1bfe6164 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -102,14 +102,14 @@ if(isset($config['boxes'])) } function LoginButtonAction() { - if(loginStatus == "false") { + if(loginStatus === "false") { window.location = ""; } else { window.location = ""; } } function LoginstatusTextAction(source) { - if(loginStatus == "false") { + if(loginStatus === "false") { window.location = ""; } else { window.location = ""; From 8bc328d6fbc1d74eb243a946ba1204771f057a02 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 26 Sep 2025 10:14:48 +0200 Subject: [PATCH 139/216] Now v1.8.2 real --- CHANGELOG-1.x.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 98a7b537..17e2a06e 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -14,6 +14,7 @@ * Login Page: Add missing csrf() - fix create account button (https://github.com/slawkens/myaac/commit/3c0cb53e17dd0b85394cfa0fdc9cf9ad8d4551df) * tibiacom template: Fix account lost menu (https://github.com/slawkens/myaac/commit/ed9beaf2b6ca069e304e569c52e5b9188b58f05c) * tibiacom template: Fix Menu div wrong tag/closing (#329) (https://github.com/slawkens/myaac/commit/85e7005fd3f0be51466151a3c122b96085fdfe68) +* tibiacom template: Replace firstChild with firstElementChild (Thanks to @un000000) (https://github.com/slawkens/myaac/commit/df7b6e29fb8875da97f431468c81ee99116271d9) ## [1.8.1 - 05.09.2025] From 4e9999cc0d3ae351645b3e7962d4c34d41d527b5 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 14:13:51 +0200 Subject: [PATCH 140/216] Do not use constant on twig hooks So it can be displayed which hook is used --- system/templates/characters.html.twig | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/system/templates/characters.html.twig b/system/templates/characters.html.twig index 2e09bd26..75e15b68 100644 --- a/system/templates/characters.html.twig +++ b/system/templates/characters.html.twig @@ -9,7 +9,7 @@
- {{ hook(constant('HOOK_CHARACTERS_BEFORE_INFORMATIONS')) }} + {{ hook('HOOK_CHARACTERS_BEFORE_INFORMATIONS') }} {% if canEdit %} Edit @@ -153,11 +153,11 @@ {% if account.isPremium() %}Premium Account{% else %}Free Account{% endif %}
- {{ hook(constant('HOOK_CHARACTERS_AFTER_INFORMATIONS')) }} + {{ hook('HOOK_CHARACTERS_AFTER_INFORMATIONS') }}
- {{ hook(constant('HOOK_CHARACTERS_BEFORE_SKILLS')) }} + {{ hook('HOOK_CHARACTERS_BEFORE_SKILLS') }} {% if config.characters.skills %} @@ -179,7 +179,7 @@ {% endif %} - {{ hook(constant('HOOK_CHARACTERS_AFTER_SKILLS')) }} + {{ hook('HOOK_CHARACTERS_AFTER_SKILLS') }} {% if quests_enabled %} @@ -201,7 +201,7 @@ {% endif %} - {{ hook(constant('HOOK_CHARACTERS_AFTER_QUESTS')) }} + {{ hook('HOOK_CHARACTERS_AFTER_QUESTS') }} {% if config.characters.equipment %} @@ -239,11 +239,11 @@ {% endif %} - {{ hook(constant('HOOK_CHARACTERS_AFTER_EQUIPMENT')) }} + {{ hook('HOOK_CHARACTERS_AFTER_EQUIPMENT') }}
- {{ hook(constant('HOOK_CHARACTERS_BEFORE_DEATHS')) }} + {{ hook('HOOK_CHARACTERS_BEFORE_DEATHS') }} {% if deaths|length > 0 %} @@ -283,7 +283,7 @@ {% endif %} - {{ hook(constant('HOOK_CHARACTERS_BEFORE_SIGNATURE')) }} + {{ hook('HOOK_CHARACTERS_BEFORE_SIGNATURE') }} {% if setting('core.signature_enabled') %} @@ -327,7 +327,7 @@ {% endif %} - {{ hook(constant('HOOK_CHARACTERS_AFTER_SIGNATURE')) }} + {{ hook('HOOK_CHARACTERS_AFTER_SIGNATURE') }} {% if not player.isHidden() %} {% set rows = 0 %} @@ -377,7 +377,7 @@ - {{ hook(constant('HOOK_CHARACTERS_AFTER_ACCOUNT')) }} + {{ hook('HOOK_CHARACTERS_AFTER_ACCOUNT') }}

@@ -421,7 +421,7 @@
{% endif %} - {{ hook(constant('HOOK_CHARACTERS_AFTER_CHARACTERS')) }} + {{ hook('HOOK_CHARACTERS_AFTER_CHARACTERS') }} {% if canEdit %} Edit From 228780f0ad8b6c5e16a93f3e946a74a6e9ad4cf8 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 14:14:26 +0200 Subject: [PATCH 141/216] Just leaving it here, for future use (twig hook display) Maybe configurable in the future --- system/twig.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/twig.php b/system/twig.php index 10f77cf3..ecc7a957 100644 --- a/system/twig.php +++ b/system/twig.php @@ -101,6 +101,8 @@ $twig->addFunction($function); $function = new TwigFunction('hook', function ($context, $hook, array $params = []) { global $hooks; + //note($hook); + if(is_string($hook)) { if (defined($hook)) { $hook = constant($hook); From 4c6277c124e6244a63280e64fde7b5b0c9bada0d Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 14:16:28 +0200 Subject: [PATCH 142/216] Start v1.8.3-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 868754d2..6bb6be85 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.2'; +const MYAAC_VERSION = '1.8.3-dev'; const DATABASE_VERSION = 45; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 56bd7ec5ed904666074492f2e4f13e4fce226bee Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 16:09:14 +0200 Subject: [PATCH 143/216] Prevent injection in $db->hasColumn --- system/libs/pot/OTS_DB_MySQL.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/libs/pot/OTS_DB_MySQL.php b/system/libs/pot/OTS_DB_MySQL.php index baa38c76..5b1e01cb 100644 --- a/system/libs/pot/OTS_DB_MySQL.php +++ b/system/libs/pot/OTS_DB_MySQL.php @@ -230,8 +230,8 @@ class OTS_DB_MySQL extends OTS_Base_DB return $this->hasColumnInternal($table, $column); } - private function hasColumnInternal($table, $column) { - return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE '" . $column . "'")->fetchAll()) > 0); + private function hasColumnInternal($table, $column): bool { + return $this->hasTable($table) && ($this->has_column_cache[$table . '.' . $column] = count($this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column))->fetchAll()) > 0); } public function hasTableAndColumns(string $table, array $columns = []): bool From 73c07d470d90d943ce93c1e2f7c22bca90766901 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 16:10:58 +0200 Subject: [PATCH 144/216] Add variable types, don't use $config --- system/libs/pot/OTS_DB_MySQL.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/system/libs/pot/OTS_DB_MySQL.php b/system/libs/pot/OTS_DB_MySQL.php index 5b1e01cb..7439adae 100644 --- a/system/libs/pot/OTS_DB_MySQL.php +++ b/system/libs/pot/OTS_DB_MySQL.php @@ -26,10 +26,10 @@ use MyAAC\Cache\Cache; */ class OTS_DB_MySQL extends OTS_Base_DB { - private $has_table_cache = array(); - private $has_column_cache = array(); + private array $has_table_cache = []; + private array $has_column_cache = []; - private $clearCacheAfter = false; + private bool $clearCacheAfter = false; /** * Creates database connection. * @@ -209,7 +209,8 @@ class OTS_DB_MySQL extends OTS_Base_DB return $sql; } - public function hasTable($name) { + public function hasTable($name): bool + { if(isset($this->has_table_cache[$name])) { return $this->has_table_cache[$name]; } @@ -217,12 +218,13 @@ class OTS_DB_MySQL extends OTS_Base_DB return $this->hasTableInternal($name); } - private function hasTableInternal($name) { - global $config; - return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote($config['database_name']) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0); + private function hasTableInternal($name): bool + { + return ($this->has_table_cache[$name] = $this->query('SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = ' . $this->quote(config('database_name')) . ' AND `TABLE_NAME` = ' . $this->quote($name) . ' LIMIT 1;')->rowCount() > 0); } - public function hasColumn($table, $column) { + public function hasColumn($table, $column): bool + { if(isset($this->has_column_cache[$table . '.' . $column])) { return $this->has_column_cache[$table . '.' . $column]; } From c898fe25efff6793a01d11c26fc153cb23fcb858 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 28 Sep 2025 16:21:31 +0200 Subject: [PATCH 145/216] New function: getColumnInfo($table, $column) --- system/libs/pot/OTS_DB_MySQL.php | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/system/libs/pot/OTS_DB_MySQL.php b/system/libs/pot/OTS_DB_MySQL.php index 7439adae..68f34787 100644 --- a/system/libs/pot/OTS_DB_MySQL.php +++ b/system/libs/pot/OTS_DB_MySQL.php @@ -28,6 +28,7 @@ class OTS_DB_MySQL extends OTS_Base_DB { private array $has_table_cache = []; private array $has_column_cache = []; + private array $get_column_info_cache = []; private bool $clearCacheAfter = false; /** @@ -249,6 +250,51 @@ class OTS_DB_MySQL extends OTS_Base_DB return true; } + public function getColumnInfo(string $table, string $column): bool|array + { + if(isset($this->get_column_info_cache[$table . '.' . $column])) { + return $this->get_column_info_cache[$table . '.' . $column]; + } + + return $this->getColumnInfoInternal($table, $column); + } + + private function getColumnInfoInternal(string $table, string $column): bool|array + { + if (!$this->hasTable($table) || !$this->hasColumn($table, $column)) { + return false; + } + + $formatResult = function ($result) { + return [ + 'field' => $result['Field'], + 'type' => $result['Type'], + 'null' => strtolower($result['Null']), + 'default' => $result['Default'], + 'extra' => $result['Extra'], + ]; + }; + + $query = $this->query('SHOW COLUMNS FROM `' . $table . "` LIKE " . $this->quote($column)); + $rowCount = $query->rowCount(); + if ($rowCount > 1) { + $tmp = []; + + $results = $query->fetchAll(PDO::FETCH_ASSOC); + foreach ($results as $result) { + $tmp[] = $formatResult($result); + } + + return ($this->get_column_info_cache[$table . '.' . $column] = $tmp); + } + else if ($rowCount == 1) { + $result = $query->fetch(PDO::FETCH_ASSOC); + return ($this->get_column_info_cache[$table . '.' . $column] = $formatResult($result)); + } + + return []; + } + public function revalidateCache() { foreach($this->has_table_cache as $key => $value) { $this->hasTableInternal($key); From f54b1bdd2af4c16c64ddff0e87a6c96bc4cf9eeb Mon Sep 17 00:00:00 2001 From: Slawomir Boczek Date: Sun, 28 Sep 2025 19:00:51 +0200 Subject: [PATCH 146/216] First attempt (#331) --- admin/pages/players.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/admin/pages/players.php b/admin/pages/players.php index c44bc012..bd3ab713 100644 --- a/admin/pages/players.php +++ b/admin/pages/players.php @@ -669,11 +669,17 @@ else if (isset($_REQUEST['search'])) {
From 97f9d3d6f6c28aef6d824973058d7133f56e09c4 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 15:06:57 +0200 Subject: [PATCH 147/216] Add option to use ?subtopic=x for plugins pages --- system/router.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/system/router.php b/system/router.php index 9c9ce4ad..0f1845f2 100644 --- a/system/router.php +++ b/system/router.php @@ -88,8 +88,10 @@ if($logged && $account_logged && $account_logged->isLoaded()) { /** * Routes loading */ +$routesFinal = []; $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) { - $routesFinal = []; + global $routesFinal; + foreach(getDatabasePages() as $page) { $routesFinal[] = ['*', $page, '__database__/' . $page, 100]; } @@ -165,7 +167,7 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) echo '
'; die; */ - foreach ($routesFinal as $route) { + foreach ($routesFinal as &$route) { if ($route[0] === '*') { $route[0] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD']; } @@ -212,7 +214,7 @@ $found = true; // old support for pages like /?subtopic=accountmanagement $page = $_REQUEST['p'] ?? ($_REQUEST['subtopic'] ?? ''); -if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) { +if(!empty($page) && preg_match('/^[A-z0-9\/\-]+$/', $page)) { if (isset($_REQUEST['p'])) { // some plugins may require this $_REQUEST['subtopic'] = $_REQUEST['p']; } @@ -221,9 +223,20 @@ if(!empty($page) && preg_match('/^[A-z0-9\-]+$/', $page)) { require SYSTEM . 'compat/pages.php'; } - $file = loadPageFromFileSystem($page, $found); - if(!$found) { - $file = false; + $foundRoute = false; + foreach ($routesFinal as $route) { + if ($page === $route[1]) { + $file = $route[2]; + $foundRoute = true; + break; + } + } + + if (!$foundRoute) { + $file = loadPageFromFileSystem($page, $found); + if(!$found) { + $file = false; + } } } else { From 64acf70d3854182d88aaf0b67f77cea2a254f179 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 22:13:15 +0200 Subject: [PATCH 148/216] Cache::remember -1 = infinite --- system/src/Cache/Cache.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system/src/Cache/Cache.php b/system/src/Cache/Cache.php index 53a84530..1b7d284b 100644 --- a/system/src/Cache/Cache.php +++ b/system/src/Cache/Cache.php @@ -115,6 +115,11 @@ class Cache return unserialize($value); } + // -1 for infinite cache + if ($ttl == -1) { + $ttl = 10 * 365 * 24 * 60 * 60; // 10 years should be enough + } + $value = $callback(); $cache->set($key, serialize($value), $ttl); return $value; From 3bb272ebbbd2eb7769d174b7082061d14a17bd44 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 22:13:33 +0200 Subject: [PATCH 149/216] Allow for img in online_datacenter --- system/templates/online.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index bb6c786c..6f798740 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -101,7 +101,7 @@ Location Datacenter: - {{ setting('core.online_datacenter') }} (Server date & time: - {{ "now"|date("d/m/Y H:i:s") }}) + {{ setting('core.online_datacenter')|raw }} (Server date & time: - {{ "now"|date("d/m/Y H:i:s") }}) PvP Type: From d8b73f55a310704ee884f1338dead9ff2c48a2f2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 22:16:29 +0200 Subject: [PATCH 150/216] Fix routes_final for prod env --- system/router.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/system/router.php b/system/router.php index 0f1845f2..ec79f9b3 100644 --- a/system/router.php +++ b/system/router.php @@ -88,9 +88,9 @@ if($logged && $account_logged && $account_logged->isLoaded()) { /** * Routes loading */ -$routesFinal = []; $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) { - global $routesFinal; + global $cache; + $routesFinal = []; foreach(getDatabasePages() as $page) { $routesFinal[] = ['*', $page, '__database__/' . $page, 100]; @@ -200,6 +200,8 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) log_append('router.log', $warning); } } + + $cache->set('routes_final', serialize($routesFinal), 10 * 365 * 24 * 60 * 60); // 10 years / infinite }, [ 'cacheFile' => CACHE . 'route.cache', @@ -224,6 +226,13 @@ if(!empty($page) && preg_match('/^[A-z0-9\/\-]+$/', $page)) { } $foundRoute = false; + + $routesFinal = []; + $tmp = null; + if ($cache->fetch('routes_final', $tmp)) { + $routesFinal = unserialize($tmp); + } + foreach ($routesFinal as $route) { if ($page === $route[1]) { $file = $route[2]; From 0cb9d3a20801045d5553e303f1933ef82650923b Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 22:31:02 +0200 Subject: [PATCH 151/216] Fix routes_final cache --- system/router.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/system/router.php b/system/router.php index ec79f9b3..f876a9b2 100644 --- a/system/router.php +++ b/system/router.php @@ -88,9 +88,9 @@ if($logged && $account_logged && $account_logged->isLoaded()) { /** * Routes loading */ +$routesFinal = []; $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) { - global $cache; - $routesFinal = []; + global $cache, $routesFinal; foreach(getDatabasePages() as $page) { $routesFinal[] = ['*', $page, '__database__/' . $page, 100]; @@ -201,7 +201,9 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) } } - $cache->set('routes_final', serialize($routesFinal), 10 * 365 * 24 * 60 * 60); // 10 years / infinite + if ($cache->enabled()) { + $cache->set('routes_final', serialize($routesFinal), 10 * 365 * 24 * 60 * 60); // 10 years / infinite + } }, [ 'cacheFile' => CACHE . 'route.cache', @@ -227,9 +229,8 @@ if(!empty($page) && preg_match('/^[A-z0-9\/\-]+$/', $page)) { $foundRoute = false; - $routesFinal = []; $tmp = null; - if ($cache->fetch('routes_final', $tmp)) { + if ($cache->enabled() && $cache->fetch('routes_final', $tmp)) { $routesFinal = unserialize($tmp); } From 0d8f68a48e0b5ce3071567ad955475263981879c Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 2 Oct 2025 22:31:16 +0200 Subject: [PATCH 152/216] Fix menus for ?subtopic= --- templates/tibiacom/index.php | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/templates/tibiacom/index.php b/templates/tibiacom/index.php index 1bfe6164..a6b57841 100644 --- a/templates/tibiacom/index.php +++ b/templates/tibiacom/index.php @@ -27,26 +27,18 @@ if(isset($config['boxes'])) var loginStatus=""; Date: Fri, 3 Oct 2025 00:25:41 +0200 Subject: [PATCH 153/216] Add lookmount into getTopPlayers --- system/functions.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/functions.php b/system/functions.php index 8c365391..b5141b2f 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1146,6 +1146,10 @@ function getTopPlayers($limit = 5, $skill = 'level') { $columns[] = 'lookaddons'; } + if ($db->hasColumn('players', 'lookmount')) { + $columns[] = 'lookmount'; + } + return Player::query() ->select($columns) ->withOnlineStatus() From 901df48d134079d648a18f9d82b60182e818ac02 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 3 Oct 2025 00:31:03 +0200 Subject: [PATCH 154/216] Add promotion into getTopPlayers --- system/functions.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/system/functions.php b/system/functions.php index b5141b2f..212a043e 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1142,6 +1142,10 @@ function getTopPlayers($limit = 5, $skill = 'level') { 'looktype', 'lookhead', 'lookbody', 'looklegs', 'lookfeet' ]; + if ($db->hasColumn('players', 'promotion')) { + $columns[] = 'promotion'; + } + if ($db->hasColumn('players', 'lookaddons')) { $columns[] = 'lookaddons'; } From 8272f1373c8592feebf2db5e092b294c4372ea75 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 3 Oct 2025 16:24:02 +0200 Subject: [PATCH 155/216] Fix database column info cache --- system/libs/pot/OTS_DB_MySQL.php | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/system/libs/pot/OTS_DB_MySQL.php b/system/libs/pot/OTS_DB_MySQL.php index 68f34787..8b9626d9 100644 --- a/system/libs/pot/OTS_DB_MySQL.php +++ b/system/libs/pot/OTS_DB_MySQL.php @@ -120,6 +120,11 @@ class OTS_DB_MySQL extends OTS_Base_DB if($cache->fetch('database_columns', $tmp) && $tmp) { $this->has_column_cache = unserialize($tmp); } + + $tmp = null; + if($cache->fetch('database_columns_info', $tmp) && $tmp) { + $this->get_column_info_cache = unserialize($tmp); + } } } @@ -156,11 +161,13 @@ class OTS_DB_MySQL extends OTS_Base_DB if ($this->clearCacheAfter) { $cache->delete('database_tables'); $cache->delete('database_columns'); + $cache->delete('database_columns_info'); $cache->delete('database_checksum'); } else { $cache->set('database_tables', serialize($this->has_table_cache), 3600); $cache->set('database_columns', serialize($this->has_column_cache), 3600); + $cache->set('database_columns_info', serialize($this->get_column_info_cache), 3600); $cache->set('database_checksum', serialize(sha1($config['database_host'] . '.' . $config['database_name'])), 3600); } } @@ -295,7 +302,8 @@ class OTS_DB_MySQL extends OTS_Base_DB return []; } - public function revalidateCache() { + public function revalidateCache(): void + { foreach($this->has_table_cache as $key => $value) { $this->hasTableInternal($key); } @@ -310,6 +318,21 @@ class OTS_DB_MySQL extends OTS_Base_DB $this->hasColumnInternal($explode[0], $explode[1]); } } + + foreach($this->get_column_info_cache as $key => $value) { + $explode = explode('.', $key); + if(!isset($this->has_table_cache[$explode[0]])) { // first check if table exist + $this->hasTableInternal($explode[0]); + } + + if($this->has_table_cache[$explode[0]]) { + $this->hasColumnInternal($explode[0], $explode[1]); + } + + if($this->has_table_cache[$explode[0]]) { + $this->getColumnInfoInternal($explode[0], $explode[1]); + } + } } public function setClearCacheAfter($clearCache) From 2eae44e0755e624a91be68b4d1ec26d01eb4d9a1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 8 Oct 2025 14:39:23 +0200 Subject: [PATCH 156/216] Add missing compat config: email_lai_sec_interval --- system/compat/config.php | 1 + 1 file changed, 1 insertion(+) diff --git a/system/compat/config.php b/system/compat/config.php index 9d58f4d6..4fc3004a 100644 --- a/system/compat/config.php +++ b/system/compat/config.php @@ -81,6 +81,7 @@ $deprecatedConfig = [ 'account_change_character_name_points' => 'account_change_character_name_price', 'account_change_character_sex', 'account_change_character_sex_points' => 'account_change_character_name_price', + 'email_lai_sec_interval' => 'mail_lost_account_interval', ]; foreach ($deprecatedConfig as $key => $value) { From 8c3cb0e06f9709c1de3398b48221241e7cbdd310 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 11 Oct 2025 18:34:15 +0200 Subject: [PATCH 157/216] New configurable: hooks_debug To view where hooks are located in .twig files --- system/twig.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/twig.php b/system/twig.php index ecc7a957..89f25939 100644 --- a/system/twig.php +++ b/system/twig.php @@ -101,7 +101,9 @@ $twig->addFunction($function); $function = new TwigFunction('hook', function ($context, $hook, array $params = []) { global $hooks; - //note($hook); + if (config('hooks_debug')) { + note($hook); + } if(is_string($hook)) { if (defined($hook)) { From 9acad15451071639acf7a7d4e81619b0a9742b12 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 12 Oct 2025 00:15:04 +0200 Subject: [PATCH 158/216] Allow links in error_box --- system/templates/error_box.html.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/templates/error_box.html.twig b/system/templates/error_box.html.twig index e6ed4992..ba9a2263 100644 --- a/system/templates/error_box.html.twig +++ b/system/templates/error_box.html.twig @@ -9,7 +9,7 @@
The Following Errors Have Occurred:
{% for error in errors %} -
  • {{ error|striptags('')|raw }}
  • +
  • {{ error|striptags('')|raw }}
  • {% endfor %}
    @@ -17,4 +17,4 @@
    -
    \ No newline at end of file +
    From fe821c58085483e70491dcf76376ad5b96de3fdd Mon Sep 17 00:00:00 2001 From: Slawomir Boczek Date: Sun, 12 Oct 2025 11:19:30 +0200 Subject: [PATCH 159/216] Feature/resend email verify (#333) * feat: Resend Email Verify + rework the whole concept, based on new table for email hashes This make it possible that every email will work, not matter if first or last * Nothing important: change variable name * Change message --- common.php | 2 +- install/includes/schema.sql | 11 ++- install/tools/5-database.php | 9 +- .../migrations/46-account_emails_verify.sql | 8 ++ system/migrations/46.php | 24 +++++ system/pages/account/confirm-email.php | 13 ++- system/pages/account/create.php | 8 +- system/pages/account/login.php | 4 +- system/pages/account/resend-email-verify.php | 94 +++++++++++++++++++ system/src/Models/AccountEmailVerify.php | 15 +++ .../account.resend-email-verify.html.twig | 45 +++++++++ ...mail.account.resend-email-verify.html.twig | 7 ++ 12 files changed, 225 insertions(+), 15 deletions(-) create mode 100644 system/migrations/46-account_emails_verify.sql create mode 100644 system/migrations/46.php create mode 100644 system/pages/account/resend-email-verify.php create mode 100644 system/src/Models/AccountEmailVerify.php create mode 100644 system/templates/account.resend-email-verify.html.twig create mode 100644 system/templates/mail.account.resend-email-verify.html.twig diff --git a/common.php b/common.php index 6bb6be85..e26921c5 100644 --- a/common.php +++ b/common.php @@ -27,7 +27,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is const MYAAC = true; const MYAAC_VERSION = '1.8.3-dev'; -const DATABASE_VERSION = 45; +const DATABASE_VERSION = 46; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); define('MYAAC_OS', stripos(PHP_OS, 'WIN') === 0 ? 'WINDOWS' : (strtoupper(PHP_OS) === 'DARWIN' ? 'MAC' : 'LINUX')); diff --git a/install/includes/schema.sql b/install/includes/schema.sql index eccaee54..b53ffab2 100644 --- a/install/includes/schema.sql +++ b/install/includes/schema.sql @@ -1,4 +1,4 @@ -SET @myaac_database_version = 45; +SET @myaac_database_version = 46; CREATE TABLE `myaac_account_actions` ( @@ -10,6 +10,15 @@ CREATE TABLE `myaac_account_actions` KEY (`account_id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; +CREATE TABLE `myaac_account_emails_verify` +( + `id` int NOT NULL AUTO_INCREMENT, + `account_id` int NOT NULL, + `hash` varchar(32) NOT NULL, + `sent_at` int NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; + CREATE TABLE `myaac_admin_menu` ( `id` int NOT NULL AUTO_INCREMENT, diff --git a/install/tools/5-database.php b/install/tools/5-database.php index b9ff587f..f97eca11 100644 --- a/install/tools/5-database.php +++ b/install/tools/5-database.php @@ -102,18 +102,13 @@ if(!$db->hasColumn('accounts', 'web_flags')) { success($locale['step_database_adding_field'] . ' accounts.web_flags...'); } -if(!$db->hasColumn('accounts', 'email_hash')) { - if(query("ALTER TABLE `accounts` ADD `email_hash` VARCHAR(32) NOT NULL DEFAULT '' AFTER `web_flags`;")) - success($locale['step_database_adding_field'] . ' accounts.email_hash...'); -} - if(!$db->hasColumn('accounts', 'email_verified')) { - if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `email_hash`;")) + if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `web_flags`;")) success($locale['step_database_adding_field'] . ' accounts.email_verified...'); } if(!$db->hasColumn('accounts', 'email_new')) { - if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_hash`;")) + if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_verified`;")) success($locale['step_database_adding_field'] . ' accounts.email_new...'); } diff --git a/system/migrations/46-account_emails_verify.sql b/system/migrations/46-account_emails_verify.sql new file mode 100644 index 00000000..13d42b16 --- /dev/null +++ b/system/migrations/46-account_emails_verify.sql @@ -0,0 +1,8 @@ +CREATE TABLE `myaac_account_emails_verify` +( + `id` int NOT NULL AUTO_INCREMENT, + `account_id` int NOT NULL, + `hash` varchar(32) NOT NULL, + `sent_at` int NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; diff --git a/system/migrations/46.php b/system/migrations/46.php new file mode 100644 index 00000000..452527e5 --- /dev/null +++ b/system/migrations/46.php @@ -0,0 +1,24 @@ +hasColumn('accounts', 'email_hash')) { + $db->dropColumn('accounts', 'email_hash'); + } + + if (!$db->hasTable(TABLE_PREFIX . 'account_emails_verify')) { + $db->query(file_get_contents(__DIR__ . '/46-account_emails_verify.sql')); + } +}; + +$down = function () use ($db) { + if (!$db->hasColumn('accounts', 'email_hash')) { + $db->addColumn('accounts', 'email_hash', "varchar(32) NOT NULL DEFAULT ''"); + } + + if ($db->hasTable(TABLE_PREFIX . 'account_emails_verify')) { + $db->dropTable(TABLE_PREFIX . 'account_emails_verify'); + } +}; diff --git a/system/pages/account/confirm-email.php b/system/pages/account/confirm-email.php index 615dd942..87183a3c 100644 --- a/system/pages/account/confirm-email.php +++ b/system/pages/account/confirm-email.php @@ -9,6 +9,7 @@ */ use MyAAC\Models\Account; +use MyAAC\Models\AccountEmailVerify; defined('MYAAC') or die('Direct access not allowed!'); @@ -20,16 +21,20 @@ if(empty($hash)) { return; } -if(!Account::where('email_hash', $hash)->exists()) { - note("Your email couldn't be verified. Please contact staff to do it manually."); +// by default link is valid for 30 days +$accountEmailVerify = AccountEmailVerify::where('hash', $hash)->where('sent_at', '>', time() - 30 * 24 * 60 * 60)->first(); +if(!$accountEmailVerify) { + note("Wrong link or link has expired."); } else { - $accountModel = Account::where('email_hash', $hash)->where('email_verified', 0)->first(); + $accountModel = Account::where('id', $accountEmailVerify->account_id)->where('email_verified', 0)->first(); if ($accountModel) { $accountModel->email_verified = 1; $accountModel->save(); + AccountEmailVerify::where('account_id', $accountModel->id)->delete(); + success('You have now verified your e-mail, this will increase the security of your account. Thank you for doing this. You can now
    log in.'); $account = new OTS_Account(); @@ -39,6 +44,6 @@ else } } else { - error('Link has expired.'); + error('Your account is already verified.'); } } diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 7a0d3c56..9ffdf6f7 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -10,6 +10,7 @@ */ use MyAAC\CreateCharacter; +use MyAAC\Models\AccountEmailVerify; defined('MYAAC') or die('Direct access not allowed!'); $title = 'Create Account'; @@ -244,7 +245,12 @@ if($save) if(setting('core.mail_enabled') && setting('core.account_mail_verify')) { $hash = md5(generateRandomString(16, true, true) . $email); - $new_account->setCustomField('email_hash', $hash); + + AccountEmailVerify::create([ + 'account_id' => $new_account->getId(), + 'hash' => $hash, + 'sent_at' => time(), + ]); $verify_url = getLink('account/confirm-email/' . $hash); $body_html = $twig->render('mail.account.verify.html.twig', array( diff --git a/system/pages/account/login.php b/system/pages/account/login.php index d6771c91..e18dacf4 100644 --- a/system/pages/account/login.php +++ b/system/pages/account/login.php @@ -48,7 +48,9 @@ if(!empty($login_account) && !empty($login_password)) ) { if (setting('core.account_mail_verify') && (int)$account_logged->getCustomField('email_verified') !== 1) { - $errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.'; + $link = getLink('account/resend-email-verify'); + $errors[] = 'Your account is not verified. Please verify your email address. If the message is not coming check the SPAM folder in your E-Mail client.
    ' . + 'You can resend the Email here: ' . $link . ''; } else { session_regenerate_id(); setSession('account', $account_logged->getId()); diff --git a/system/pages/account/resend-email-verify.php b/system/pages/account/resend-email-verify.php new file mode 100644 index 00000000..ffccb548 --- /dev/null +++ b/system/pages/account/resend-email-verify.php @@ -0,0 +1,94 @@ +display('error_box.html.twig', ['errors' => $errors]); + $twig->display('account.back_button.html.twig', [ + 'action' => getLink('account/resend-email-verify'), + ]); +}; + +if (!setting('core.mail_enabled') || !setting('core.account_mail_verify')) { + $errorWithBackButton('Resending email is not possible on this server.'); + return; +} + +$showForm = true; + +if (isset($_POST['submit']) && $_POST['submit'] == '1') { + $email = $_REQUEST['email']; + + if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) { + $errorWithBackButton('Please enter valid Email.'); + return; + } + + $account = new OTS_Account(); + $account->findByEMail($email); + if ($account->isLoaded()) { + if ($account->getCustomField('email_verified') == '1') { + $errorWithBackButton('This account is already verified! You can log in on the website.'); + return; + } + + $accountEmailVerify = AccountEmailVerify::where('account_id', $account->getId())->orderBy('sent_at', 'DESC')->first(); + if ($accountEmailVerify && time() - $accountEmailVerify->sent_at < 60) { + $errorWithBackButton('Only one Email per minute is allowed. Please try again later.'); + return; + } + + $tmp_account = $email; + if (!config('account_login_by_email')) { + $tmp_account = (USE_ACCOUNT_NAME ? $account->getName() : $account->getId()); + } + + $hash = md5(generateRandomString(16, true, true) . $email); + + AccountEmailVerify::create([ + 'account_id' => $account->getId(), + 'hash' => $hash, + 'sent_at' => time(), + ]); + + $verify_url = getLink('account/confirm-email/' . $hash); + $body_html = $twig->render('mail.account.resend-email-verify.html.twig', array( + 'account' => $tmp_account, + 'verify_url' => generateLink($verify_url, $verify_url, true) + )); + + if (_mail($account->getEMail(), configLua('serverName') . ' - Verify Account', $body_html)) { + $message = "If account with this email exists - you will become an email with verification link."; + $showForm = false; + } else { + $message = "

    An error occurred while sending email ({$email} )! Try again later. For Admin: More info can be found in system/logs/mailer-error.log

    "; + } + } + else { + $message = "
    If account with this email exists - you will become an email with verification link."; + $showForm = false; + } + + $twig->display('success.html.twig', array( + 'title' => 'Verify Email Sent', + 'description' => $message, + )); +} + +//show errors if not empty +if (!empty($errors)) { + $twig->display('error_box.html.twig', ['errors' => $errors]); + $twig->display('account.back_button.html.twig', [ + 'action' => getLink('account/resend-email-verify'), + ]); +} + +if ($showForm) { + $twig->display('account.resend-email-verify.html.twig'); +} diff --git a/system/src/Models/AccountEmailVerify.php b/system/src/Models/AccountEmailVerify.php new file mode 100644 index 00000000..8773750f --- /dev/null +++ b/system/src/Models/AccountEmailVerify.php @@ -0,0 +1,15 @@ +
    +{% set title = 'Resend Email' %} +{% set background = config('darkborder') %} +{% set content %} + + + + + +
    + + + +
    +{% endset %} +{% include 'tables.headline.html.twig' %} +
    + + + + + +
    + + + + +
    + + {{ csrf() }} + + {{ include('buttons.submit.html.twig') }} + +
    +
    + + + + +
    +
    + {{ include('buttons.back.html.twig') }} +
    +
    +
    diff --git a/system/templates/mail.account.resend-email-verify.html.twig b/system/templates/mail.account.resend-email-verify.html.twig new file mode 100644 index 00000000..75bdab8b --- /dev/null +++ b/system/templates/mail.account.resend-email-verify.html.twig @@ -0,0 +1,7 @@ +Hello {{ account }}!
    +
    +You requested to resend the verify Email on {{ config.lua.serverName }}!
    +
    + +To verify your email address please click the link below:
    +{{ verify_url|raw }} From c91bb5d4097647dca2196d3dea87bc90c89181d2 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 12 Oct 2025 21:53:01 +0200 Subject: [PATCH 160/216] Fix guild create with freePremium --- system/pages/guilds/create.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/system/pages/guilds/create.php b/system/pages/guilds/create.php index ef0117e8..ba348a36 100644 --- a/system/pages/guilds/create.php +++ b/system/pages/guilds/create.php @@ -21,6 +21,8 @@ if(!$logged) { $errors[] = 'You are not logged in. You can\'t create guild.'; } +$freePremium = getBoolean(configLua('freePremium')); + $array_of_player_nig = array(); if(empty($errors)) { @@ -31,7 +33,7 @@ if(empty($errors)) if(!$player_rank->isLoaded()) { if($player->getLevel() >= setting('core.guild_need_level')) { - if(!setting('core.guild_need_premium') || $account_logged->isPremium()) { + if(!setting('core.guild_need_premium') || $account_logged->isPremium() || $freePremium) { $array_of_player_nig[] = $player->getName(); } } @@ -95,7 +97,7 @@ if($todo == 'save') if($player->getLevel() < setting('core.guild_need_level')) { $errors[] = 'Character '.$name.' has too low level. To create guild you need character with level ' . setting('core.guild_need_level') . '.'; } - if(setting('core.guild_need_premium') && !$account_logged->isPremium()) { + if(setting('core.guild_need_premium') && !$account_logged->isPremium() && !$freePremium) { $errors[] = 'Character '.$name.' is on FREE account. To create guild you need PREMIUM account.'; } } From 90c846379751ab53b127ab7210efafbcd6353487 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 13 Oct 2025 17:52:39 +0200 Subject: [PATCH 161/216] Update create.php --- system/pages/guilds/create.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/pages/guilds/create.php b/system/pages/guilds/create.php index ba348a36..6921595f 100644 --- a/system/pages/guilds/create.php +++ b/system/pages/guilds/create.php @@ -21,7 +21,8 @@ if(!$logged) { $errors[] = 'You are not logged in. You can\'t create guild.'; } -$freePremium = getBoolean(configLua('freePremium')); +$configLuaFreePremium = configLua('freePremium'); +$freePremium = (isset($configLuaFreePremium) && getBoolean($configLuaFreePremium)) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS; $array_of_player_nig = array(); if(empty($errors)) From b797908e49fe66518f59d8854d939f9b9f8a2e5e Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 13 Oct 2025 17:53:26 +0200 Subject: [PATCH 162/216] Update create.php --- system/pages/guilds/create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/pages/guilds/create.php b/system/pages/guilds/create.php index 6921595f..08bc8817 100644 --- a/system/pages/guilds/create.php +++ b/system/pages/guilds/create.php @@ -22,7 +22,7 @@ if(!$logged) { } $configLuaFreePremium = configLua('freePremium'); -$freePremium = (isset($configLuaFreePremium) && getBoolean($configLuaFreePremium)) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS; +$freePremium = (isset($configLuaFreePremium) && getBoolean($configLuaFreePremium)) || ($logged && $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS); $array_of_player_nig = array(); if(empty($errors)) From 82d417b5906c15580bd796fb54099151f3889260 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 13 Oct 2025 18:01:19 +0200 Subject: [PATCH 163/216] Change spaces to tabs --- system/libs/pot/OTS_Account.php | 824 ++++++++++++++++---------------- 1 file changed, 412 insertions(+), 412 deletions(-) diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index 20c7fe32..872d1c89 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -38,7 +38,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @var array * @version 0.1.5 */ - private $data = array('email' => '', 'rlname' => '','location' => '', 'country' => '','web_flags' => 0, 'lastday' => 0, 'premdays' => 0, 'created' => 0); + private $data = array('email' => '', 'rlname' => '','location' => '', 'country' => '','web_flags' => 0, 'lastday' => 0, 'premdays' => 0, 'created' => 0); public static $cache = array(); @@ -66,39 +66,39 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @example examples/create.php create.php * @tutorial POT/Accounts.pkg#create */ - public function createNamed($name = null) - { - // if name is not passed then it will be generated randomly - if( !isset($name) ) - { - // reads already existing names - foreach( $this->db->query('SELECT ' . $this->db->fieldName('name') . ' FROM ' . $this->db->tableName('accounts') )->fetchAll() as $account) - { - $exist[] = $account['name']; - } + public function createNamed($name = null) + { + // if name is not passed then it will be generated randomly + if( !isset($name) ) + { + // reads already existing names + foreach( $this->db->query('SELECT ' . $this->db->fieldName('name') . ' FROM ' . $this->db->tableName('accounts') )->fetchAll() as $account) + { + $exist[] = $account['name']; + } - // initial name - $name = uniqid(); + // initial name + $name = uniqid(); - // repeats until name is unique - while( in_array($name, $exist) ) - { - $name .= '_'; - } + // repeats until name is unique + while( in_array($name, $exist) ) + { + $name .= '_'; + } - // resets array for account numbers loop - $exist = array(); - } + // resets array for account numbers loop + $exist = array(); + } - // saves blank account info - $this->db->exec('INSERT INTO ' . $this->db->tableName('accounts') . ' (' . $this->db->fieldName('name') . ', ' . $this->db->fieldName('password') . ', ' . $this->db->fieldName('email') . ') VALUES (' . $this->db->quote($name) . ', \'\', \'\')'); + // saves blank account info + $this->db->exec('INSERT INTO ' . $this->db->tableName('accounts') . ' (' . $this->db->fieldName('name') . ', ' . $this->db->fieldName('password') . ', ' . $this->db->fieldName('email') . ') VALUES (' . $this->db->quote($name) . ', \'\', \'\')'); - // reads created account's ID - $this->data['id'] = $this->db->lastInsertId(); + // reads created account's ID + $this->data['id'] = $this->db->lastInsertId(); - // return name of newly created account - return $name; - } + // return name of newly created account + return $name; + } /** * @param $email @@ -166,8 +166,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws Exception ON lastInsertId error. * @deprecated 0.1.5 Use createNamed(). */ - public function create($name = NULL, $id = NULL) - { + public function create($name = NULL, $id = NULL) + { if(isset($name)) { $nameOrNumber = 'name'; $nameOrNumberValue = $name; @@ -183,8 +183,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable } } - // saves blank account info - $this->db->exec('INSERT INTO `accounts` (' . (isset($id) ? '`id`,' : '') . (isset($nameOrNumber) ? '`' . $nameOrNumber . '`,' : '') . '`password`, `email`, `created`) VALUES (' . (isset($id) ? $id . ',' : '') . (isset($nameOrNumber) ? $this->db->quote($nameOrNumberValue) . ',' : '') . ' \'\', \'\',' . time() . ')'); + // saves blank account info + $this->db->exec('INSERT INTO `accounts` (' . (isset($id) ? '`id`,' : '') . (isset($nameOrNumber) ? '`' . $nameOrNumber . '`,' : '') . '`password`, `email`, `created`) VALUES (' . (isset($id) ? $id . ',' : '') . (isset($nameOrNumber) ? $this->db->quote($nameOrNumberValue) . ',' : '') . ' \'\', \'\',' . time() . ')'); if(isset($name)) { $this->data['name'] = $name; @@ -206,8 +206,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable throw new Exception(__CLASS__ . ':' . __METHOD__ . ' unexpected error. Please report to MyAAC Developers.'); } - return $this->data['id']; - } + return $this->data['id']; + } /** * @version 0.0.6 @@ -218,10 +218,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return int Created account number. * @deprecated 0.0.6 There is no more group_id field in database, use create(). */ - public function createEx(OTS_Group $group, $min = 1, $max = 9999999) - { - return $this->create($min, $max); - } + public function createEx(OTS_Group $group, $min = 1, $max = 9999999) + { + return $this->create($min, $max); + } /** * Loads account with given number. @@ -230,8 +230,8 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @param int $id Account number. * @throws PDOException On PDO operation error. */ - public function load($id, $fresh = false) - { + public function load($id, $fresh = false) + { if(!$fresh && isset(self::$cache[$id])) { $this->data = self::$cache[$id]; return; @@ -244,10 +244,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable $nameOrNumber = '`number`,'; } - // SELECT query on database + // SELECT query on database $this->data = $this->db->query('SELECT `id`, ' . $nameOrNumber . '`password`, `email`, `rlname`, `location`, `country`, `web_flags`, ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays`, ' : '') . ($this->db->hasColumn('accounts', 'lastday') ? '`lastday`, ' : ($this->db->hasColumn('accounts', 'premend') ? '`premend`,' : ($this->db->hasColumn('accounts', 'premium_ends_at') ? '`premium_ends_at`,' : ''))) . '`created` FROM `accounts` WHERE `id` = ' . (int) $id)->fetch(); self::$cache[$id] = $this->data; - } + } /** * Loads account by it's name. @@ -261,22 +261,22 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @param string $name Account's name. * @throws PDOException On PDO operation error. */ - public function find($name) - { + public function find($name) + { $nameOrNumberColumn = 'name'; if (USE_ACCOUNT_NUMBER) { $nameOrNumberColumn = 'number'; } - // finds player's ID - $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` = ' . $this->db->quote($name) )->fetch(); + // finds player's ID + $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `' . $nameOrNumberColumn . '` = ' . $this->db->quote($name) )->fetch(); - // if anything was found - if( isset($id['id']) ) - { - $this->load($id['id']); - } - } + // if anything was found + if( isset($id['id']) ) + { + $this->load($id['id']); + } + } /** * Loads account by it's e-mail address. @@ -286,27 +286,27 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @param string $email Account's e-mail address. * @throws PDOException On PDO operation error. */ - public function findByEMail($email) - { - // finds player's ID - $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `email` = ' . $this->db->quote($email) )->fetch(); + public function findByEMail($email) + { + // finds player's ID + $id = $this->db->query('SELECT `id` FROM `accounts` WHERE `email` = ' . $this->db->quote($email) )->fetch(); - // if anything was found - if( isset($id['id']) ) - { - $this->load($id['id']); - } - } + // if anything was found + if( isset($id['id']) ) + { + $this->load($id['id']); + } + } /** * Checks if object is loaded. * * @return bool Load state. */ - public function isLoaded() - { - return isset($this->data['id']); - } + public function isLoaded() + { + return isset($this->data['id']); + } /** * Updates account in database. @@ -323,16 +323,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws E_OTS_NotLoaded If account doesn't have ID assigned. * @throws PDOException On PDO operation error. */ - public function save() - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function save() + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } $field = 'lastday'; if($this->db->hasColumn('accounts', 'premend')) { // othire - $field = 'premend'; + $field = 'premend'; if(!isset($this->data['premend'])) { $this->data['premend'] = 0; } @@ -344,9 +344,9 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable } } - // UPDATE query on database - $this->db->exec('UPDATE `accounts` SET ' . ($this->db->hasColumn('accounts', 'name') ? '`name` = ' . $this->db->quote($this->data['name']) . ',' : '') . '`password` = ' . $this->db->quote($this->data['password']) . ', `email` = ' . $this->db->quote($this->data['email']) . ', `rlname` = ' . $this->db->quote($this->data['rlname']) . ', `location` = ' . $this->db->quote($this->data['location']) . ', `country` = ' . $this->db->quote($this->data['country']) . ', `web_flags` = ' . (int) $this->data['web_flags'] . ', ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays` = ' . (int) $this->data['premdays'] . ',' : '') . '`' . $field . '` = ' . (int) $this->data[$field] . ' WHERE `id` = ' . $this->data['id']); - } + // UPDATE query on database + $this->db->exec('UPDATE `accounts` SET ' . ($this->db->hasColumn('accounts', 'name') ? '`name` = ' . $this->db->quote($this->data['name']) . ',' : '') . '`password` = ' . $this->db->quote($this->data['password']) . ', `email` = ' . $this->db->quote($this->data['email']) . ', `rlname` = ' . $this->db->quote($this->data['rlname']) . ', `location` = ' . $this->db->quote($this->data['location']) . ', `country` = ' . $this->db->quote($this->data['country']) . ', `web_flags` = ' . (int) $this->data['web_flags'] . ', ' . ($this->db->hasColumn('accounts', 'premdays') ? '`premdays` = ' . (int) $this->data['premdays'] . ',' : '') . '`' . $field . '` = ' . (int) $this->data[$field] . ' WHERE `id` = ' . $this->data['id']); + } /** * Account number. @@ -359,15 +359,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return int Account number. * @throws E_OTS_NotLoaded If account is not loaded. */ - public function getId() - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getId() + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['id']; - } + return $this->data['id']; + } public function getNumber() { @@ -378,45 +378,45 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable return $this->data['id']; } - public function getRLName() - { - if( !isset($this->data['rlname']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getRLName() + { + if( !isset($this->data['rlname']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['rlname']; - } + return $this->data['rlname']; + } - public function getLocation() - { - if( !isset($this->data['location']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getLocation() + { + if( !isset($this->data['location']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['location']; - } + return $this->data['location']; + } - public function getCountry() - { - if( !isset($this->data['country']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getCountry() + { + if( !isset($this->data['country']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['country']; - } + return $this->data['country']; + } - public function getWebFlags() - { - if( !isset($this->data['web_flags']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getWebFlags() + { + if( !isset($this->data['web_flags']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['web_flags']; - } + return $this->data['web_flags']; + } public function hasFlag($flag) { @@ -462,17 +462,17 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable } public function getLastLogin() - { - if( !isset($this->data['lastday']) ) - { - throw new E_OTS_NotLoaded(); - } + { + if( !isset($this->data['lastday']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['lastday']; - } + return $this->data['lastday']; + } - public function isPremium() - { + public function isPremium() + { if(isset($this->data['premium_ends_at'])) { return $this->data['premium_ends_at'] > time(); } @@ -484,15 +484,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable return ($this->data['premdays'] - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->data['lastday']))) - date("z", $this->data['lastday'])) > 0); } - public function getCreated() - { - if( !isset($this->data['created']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getCreated() + { + if( !isset($this->data['created']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['created']; - } + return $this->data['created']; + } /** * Name. @@ -501,37 +501,37 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @since 0.7.5 * @throws E_OTS_NotLoaded If account is not loaded. */ - public function setPremDays($premdays) - { + public function setPremDays($premdays) + { $this->data['premdays'] = (int) $premdays; $this->data['premend'] = time() + ($premdays * 24 * 60 * 60); $this->data['premium_ends_at'] = time() + ($premdays * 24 * 60 * 60); - } + } - public function setRLName($name) - { - $this->data['rlname'] = (string) $name; - } + public function setRLName($name) + { + $this->data['rlname'] = (string) $name; + } - public function setLocation($location) - { - $this->data['location'] = (string) $location; - } + public function setLocation($location) + { + $this->data['location'] = (string) $location; + } - public function setCountry($country) - { - $this->data['country'] = (string) $country; - } + public function setCountry($country) + { + $this->data['country'] = (string) $country; + } public function setLastLogin($lastlogin) - { - $this->data['lastday'] = (int) $lastlogin; - } + { + $this->data['lastday'] = (int) $lastlogin; + } - public function setWebFlags($webflags) - { - $this->data['web_flags'] = (int) $webflags; - } + public function setWebFlags($webflags) + { + $this->data['web_flags'] = (int) $webflags; + } /** * Name. @@ -541,15 +541,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return string Name. * @throws E_OTS_NotLoaded If account is not loaded. */ - public function getName() - { - if( !isset($this->data['name']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getName() + { + if( !isset($this->data['name']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['name']; - } + return $this->data['name']; + } /** * Sets account's name. @@ -562,10 +562,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @since 0.1.5 * @param string $name Account name. */ - public function setName($name) - { - $this->data['name'] = (string) $name; - } + public function setName($name) + { + $this->data['name'] = (string) $name; + } /** * Account's password. @@ -582,15 +582,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return string Password. * @throws E_OTS_NotLoaded If account is not loaded. */ - public function getPassword() - { - if( !isset($this->data['password']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getPassword() + { + if( !isset($this->data['password']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['password']; - } + return $this->data['password']; + } /** * Sets account's password. @@ -605,10 +605,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * * @param string $password Password. */ - public function setPassword($password) - { - $this->data['password'] = (string) $password; - } + public function setPassword($password) + { + $this->data['password'] = (string) $password; + } /** * E-mail address. * @@ -620,15 +620,15 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return string E-mail. * @throws E_OTS_NotLoaded If account is not loaded. */ - public function getEMail() - { - if( !isset($this->data['email']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getEMail() + { + if( !isset($this->data['email']) ) + { + throw new E_OTS_NotLoaded(); + } - return $this->data['email']; - } + return $this->data['email']; + } /** * Sets account's email. @@ -639,10 +639,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * * @param string $email E-mail address. */ - public function setEMail($email) - { - $this->data['email'] = (string) $email; - } + public function setEMail($email) + { + $this->data['email'] = (string) $email; + } /** * Reads custom field. @@ -662,16 +662,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws E_OTS_NotLoaded If account is not loaded. * @throws PDOException On PDO operation error. */ - public function getCustomField($field) - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getCustomField($field) + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - $value = $this->db->query('SELECT ' . $this->db->fieldName($field) . ' FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id'])->fetch(); - return $value[$field]; - } + $value = $this->db->query('SELECT ' . $this->db->fieldName($field) . ' FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id'])->fetch(); + return $value[$field]; + } /** * Writes custom field. @@ -695,20 +695,20 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws E_OTS_NotLoaded If account is not loaded. * @throws PDOException On PDO operation error. */ - public function setCustomField($field, $value) - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function setCustomField($field, $value) + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - // quotes value for SQL query - if(!( is_int($value) || is_float($value) )) - { - $value = $this->db->quote($value); - } - $this->db->exec('UPDATE ' . $this->db->tableName('accounts') . ' SET ' . $this->db->fieldName($field) . ' = ' . $value . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']); - } + // quotes value for SQL query + if(!( is_int($value) || is_float($value) )) + { + $value = $this->db->quote($value); + } + $this->db->exec('UPDATE ' . $this->db->tableName('accounts') . ' SET ' . $this->db->fieldName($field) . ' = ' . $value . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']); + } /** * @version 0.1.0 @@ -716,25 +716,25 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws E_OTS_NotLoaded If account is not loaded. * @deprecated 0.0.5 Use getPlayersList(). */ - public function getPlayers() - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getPlayers() + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - $players = array(); + $players = array(); - foreach( $this->db->query('SELECT ' . $this->db->fieldName('id') . ' FROM ' . $this->db->tableName('players') . ' WHERE ' . $this->db->fieldName('account_id') . ' = ' . $this->data['id'])->fetchAll() as $player) - { - // creates new object - $object = new OTS_Player(); - $object->load($player['id']); - $players[] = $object; - } + foreach( $this->db->query('SELECT ' . $this->db->fieldName('id') . ' FROM ' . $this->db->tableName('players') . ' WHERE ' . $this->db->fieldName('account_id') . ' = ' . $this->data['id'])->fetchAll() as $player) + { + // creates new object + $object = new OTS_Player(); + $object->load($player['id']); + $players[] = $object; + } - return $players; - } + return $players; + } /** * List of characters on account. @@ -752,16 +752,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return OTS_Players_List List of players from current account. * @throws E_OTS_NotLoaded If account is not loaded. */ - public function getPlayersList($withDeleted = true) - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function getPlayersList($withDeleted = true) + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - // creates filter - $filter = new OTS_SQLFilter(); - $filter->compareField('account_id', (int) $this->data['id']); + // creates filter + $filter = new OTS_SQLFilter(); + $filter->compareField('account_id', (int) $this->data['id']); if(!$withDeleted) { global $db; @@ -772,12 +772,12 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable } } - // creates list object - $list = new OTS_Players_List(); - $list->setFilter($filter); + // creates list object + $list = new OTS_Players_List(); + $list->setFilter($filter); - return $list; - } + return $list; + } /** * @version 0.1.5 @@ -786,22 +786,22 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws PDOException On PDO operation error. * @deprecated 0.1.5 Use OTS_AccountBan class. */ - public function ban($time = 0) - { - // can't ban nothing - if( !$this->isLoaded() ) - { - throw new E_OTS_NotLoaded(); - } + public function ban($time = 0) + { + // can't ban nothing + if( !$this->isLoaded() ) + { + throw new E_OTS_NotLoaded(); + } - // creates ban entry - $ban = new OTS_AccountBan(); - $ban->setValue($this->data['id']); - $ban->setExpires($time); - $ban->setAdded( time() ); - $ban->activate(); - $ban->save(); - } + // creates ban entry + $ban = new OTS_AccountBan(); + $ban->setValue($this->data['id']); + $ban->setExpires($time); + $ban->setAdded( time() ); + $ban->activate(); + $ban->save(); + } /** * @version 0.1.5 @@ -809,19 +809,19 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws PDOException On PDO operation error. * @deprecated 0.1.5 Use OTS_AccountBan class. */ - public function unban() - { - // can't unban nothing - if( !$this->isLoaded() ) - { - throw new E_OTS_NotLoaded(); - } + public function unban() + { + // can't unban nothing + if( !$this->isLoaded() ) + { + throw new E_OTS_NotLoaded(); + } - // deletes ban entry - $ban = new OTS_AccountBan(); - $ban->find($this->data['id']); - $ban->delete(); - } + // deletes ban entry + $ban = new OTS_AccountBan(); + $ban->find($this->data['id']); + $ban->delete(); + } /** * @version 0.1.5 @@ -830,37 +830,37 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws PDOException On PDO operation error. * @deprecated 0.1.5 Use OTS_AccountBan class. */ - public function isBanned() - { - // nothing can't be banned - if( !$this->isLoaded() ) - { - throw new E_OTS_NotLoaded(); - } + public function isBanned() + { + // nothing can't be banned + if( !$this->isLoaded() ) + { + throw new E_OTS_NotLoaded(); + } if( !isset($this->data['banned']) ) $this->loadBan(); - return ($this->data['banned'] === true); - } + return ($this->data['banned'] === true); + } - public function getBanTime() - { - // nothing can't be banned - if( !$this->isLoaded() ) - { - throw new E_OTS_NotLoaded(); - } + public function getBanTime() + { + // nothing can't be banned + if( !$this->isLoaded() ) + { + throw new E_OTS_NotLoaded(); + } if( !isset($this->data['banned_time']) ) $this->loadBan(); - return $this->data['banned_time']; - } + return $this->data['banned_time']; + } - public function loadBan() - { - // nothing can't be banned - if( !$this->isLoaded() ) - { - throw new E_OTS_NotLoaded(); - } + public function loadBan() + { + // nothing can't be banned + if( !$this->isLoaded() ) + { + throw new E_OTS_NotLoaded(); + } if($this->db->hasTable('account_bans')) { $ban = $this->db->query('SELECT `expires_at` FROM `account_bans` WHERE `account_id` = ' . $this->data['id'] . ' AND (`expires_at` > ' . time() .' OR `expires_at` = -1) ORDER BY `expires_at` DESC')->fetch(); @@ -883,7 +883,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable $this->data['banned'] = false; $this->data['banned_time'] = 0; } - } + } /** * Deletes account. @@ -897,19 +897,19 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws E_OTS_NotLoaded If account is not loaded. * @throws PDOException On PDO operation error. */ - public function delete() - { - if( !isset($this->data['id']) ) - { - throw new E_OTS_NotLoaded(); - } + public function delete() + { + if( !isset($this->data['id']) ) + { + throw new E_OTS_NotLoaded(); + } - // deletes row from database - $this->db->exec('DELETE FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']); + // deletes row from database + $this->db->exec('DELETE FROM ' . $this->db->tableName('accounts') . ' WHERE ' . $this->db->fieldName('id') . ' = ' . $this->data['id']); - // resets object handle - unset($this->data['id']); - } + // resets object handle + unset($this->data['id']); + } /** * Checks highest access level of account. @@ -917,10 +917,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return int Access level (highest access level of all characters). * @throws PDOException On PDO operation error. */ - public function getAccess() - { + public function getAccess() + { return $this->getGroupId(); - } + } public function getGroupId() { @@ -982,25 +982,25 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return int Access level (highest access level of all characters). * @throws PDOException On PDO operation error. */ - public function getGuildAccess(OTS_Guild $guild) - { - // by default - $access = 0; + public function getGuildAccess(OTS_Guild $guild) + { + // by default + $access = 0; - // finds ranks of all characters - foreach($this->getPlayersList(false) as $player) - { - $rank = $player->getRank(); + // finds ranks of all characters + foreach($this->getPlayersList(false) as $player) + { + $rank = $player->getRank(); - // checks if rank's access level is higher then previouls found highest - if( isset($rank) && $rank->isLoaded() && $rank->getGuild()->getId() == $guild->getId() && $rank->getLevel() > $access) - { - $access = $rank->getLevel(); - } - } + // checks if rank's access level is higher then previouls found highest + if( isset($rank) && $rank->isLoaded() && $rank->getGuild()->getId() == $guild->getId() && $rank->getLevel() > $access) + { + $access = $rank->getLevel(); + } + } - return $access; - } + return $access; + } public function logAction($action) { @@ -1039,10 +1039,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @return Iterator List of players. */ #[\ReturnTypeWillChange] - public function getIterator() - { - return $this->getPlayersList(); - } + public function getIterator() + { + return $this->getPlayersList(); + } /** * Returns number of player within. @@ -1053,10 +1053,10 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws PDOException On PDO operation error. * @return int Count of players. */ - public function count(): int - { - return $this->getPlayersList()->count(); - } + public function count(): int + { + return $this->getPlayersList()->count(); + } /** * Magic PHP5 method. @@ -1069,44 +1069,44 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws OutOfBoundsException For non-supported properties. * @throws PDOException On PDO operation error. */ - public function __get($name) - { - switch($name) - { - case 'id': - return $this->getId(); + public function __get($name) + { + switch($name) + { + case 'id': + return $this->getId(); - case 'name': - return $this->getName(); + case 'name': + return $this->getName(); - case 'password': - return $this->getPassword(); + case 'password': + return $this->getPassword(); - case 'eMail': - return $this->getEMail(); + case 'eMail': + return $this->getEMail(); - case 'premiumEnd': - return $this->getPremiumEnd(); + case 'premiumEnd': + return $this->getPremiumEnd(); - case 'loaded': - return $this->isLoaded(); + case 'loaded': + return $this->isLoaded(); - case 'playersList': - return $this->getPlayersList(); + case 'playersList': + return $this->getPlayersList(); - case 'deleted': - return $this->isDeleted(); + case 'deleted': + return $this->isDeleted(); - case 'banned': - return $this->isBanned(); + case 'banned': + return $this->isBanned(); - case 'access': - return $this->getAccess(); + case 'access': + return $this->getAccess(); - default: - throw new OutOfBoundsException(); - } - } + default: + throw new OutOfBoundsException(); + } + } /** * Magic PHP5 method. @@ -1119,52 +1119,52 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @throws OutOfBoundsException For non-supported properties. * @throws PDOException On PDO operation error. */ - public function __set($name, $value) - { - switch($name) - { - case 'name': - $this->setName($name); - break; + public function __set($name, $value) + { + switch($name) + { + case 'name': + $this->setName($name); + break; - case 'password': - $this->setPassword($value); - break; + case 'password': + $this->setPassword($value); + break; - case 'eMail': - $this->setEMail($value); - break; + case 'eMail': + $this->setEMail($value); + break; - case 'premiumEnd': - $this->setPremiumEnd($value); - break; + case 'premiumEnd': + $this->setPremiumEnd($value); + break; - case 'deleted': - if($value) - { - $this->setDeleted(); - } - else - { - $this->unsetDeleted(); - } - break; + case 'deleted': + if($value) + { + $this->setDeleted(); + } + else + { + $this->unsetDeleted(); + } + break; - case 'banned': - if($value) - { - $this->ban(); - } - else - { - $this->unban(); - } - break; + case 'banned': + if($value) + { + $this->ban(); + } + else + { + $this->unban(); + } + break; - default: - throw new OutOfBoundsException(); - } - } + default: + throw new OutOfBoundsException(); + } + } /** * Returns string representation of object. @@ -1177,18 +1177,18 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable * @since 0.1.0 * @return string String representation of object. */ - public function __toString() - { - $ots = POT::getInstance(); + public function __toString() + { + $ots = POT::getInstance(); - // checks if display driver is loaded - if( $ots->isDisplayDriverLoaded() ) - { - return $ots->getDisplayDriver()->displayAccount($this); - } + // checks if display driver is loaded + if( $ots->isDisplayDriverLoaded() ) + { + return $ots->getDisplayDriver()->displayAccount($this); + } - return $this->getId(); - } + return $this->getId(); + } } /**#@-*/ From c88b08eb1ec1f560cbfdaaa16b24e3a0f26da7b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Morais?= Date: Wed, 15 Oct 2025 06:46:52 -0300 Subject: [PATCH 164/216] feature: show vip days in account management (#334) * feature: show vip days in account management This feature causes VIP days to be shown in account management when vipSystemEnabled is true in the canary config.lua * Some fixes & adjustments * If freePremium = true and vipEnabled = show gratis VIP * Revert to previous version --------- Co-authored-by: slawkens --- system/pages/account/manage.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/system/pages/account/manage.php b/system/pages/account/manage.php index 3776a732..b74f7bd8 100644 --- a/system/pages/account/manage.php +++ b/system/pages/account/manage.php @@ -38,15 +38,24 @@ csrfProtect(); $groups = new OTS_Groups_List(); -$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS; -$dayOrDays = $account_logged->getPremDays() == 1 ? 'day' : 'days'; /** * @var OTS_Account $account_logged */ -if(!$account_logged->isPremium()) +$premDays = $account_logged->getPremDays(); + +$freePremium = isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium']) || $premDays == OTS_Account::GRATIS_PREMIUM_DAYS; +$dayOrDays = ($premDays == 1 ? 'day' : 'days'); + +$vipSystemEnabled = isset($config['lua']['vipSystemEnabled']) && getBoolean($config['lua']['vipSystemEnabled']); +$premiumLabel = $vipSystemEnabled ? 'VIP' : 'Premium Account'; + +if ($freePremium && !$vipSystemEnabled) { + $account_status = 'Gratis Premium Account'; +} else if(!$account_logged->isPremium()) { $account_status = 'Free Account'; -else - $account_status = '' . ($freePremium ? 'Gratis Premium Account' : 'Premium Account, ' . $account_logged->getPremDays() . ' '.$dayOrDays.' left') . ''; +} else { + $account_status = '' . $premiumLabel . ', ' . $premDays . ' '.$dayOrDays.' left'; +} $recovery_key = $account_logged->getCustomField('key'); if(empty($recovery_key)) From 3e61692780d4add93b7b0e9f12f7a283bd8f4b7a Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 15 Oct 2025 15:49:58 +0200 Subject: [PATCH 165/216] Fix premDays count in canary --- system/functions.php | 6 ++++++ system/libs/pot/OTS_Account.php | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/system/functions.php b/system/functions.php index 212a043e..b3f1189f 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1704,6 +1704,12 @@ function getAccountIdentityColumn(): string return 'id'; } +function isCanary(): bool +{ + $vipSystemEnabled = configLua('vipSystemEnabled'); + return isset($vipSystemEnabled); +} + // validator functions require_once SYSTEM . 'compat/base.php'; diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index 872d1c89..5cee25a4 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -449,6 +449,11 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable return max($ret, 0); } + if (isCanary() && isset($this->data['lastday'])) { + $ret = ceil(($this->data['lastday'] - time()) / 86400); + return $ret > 0 ? $ret : 0; + } + if($this->data['premdays'] == 0) { return 0; } From 38902c30d114fdbce259467f5820f97037b393e9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 15 Oct 2025 15:50:22 +0200 Subject: [PATCH 166/216] Comment code to update lastday --- login.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/login.php b/login.php index d4d25529..438754e2 100644 --- a/login.php +++ b/login.php @@ -220,6 +220,8 @@ switch ($action) { } } + /* + * not needed anymore? if (fieldExist('premdays', 'accounts') && fieldExist('lastday', 'accounts')) { $save = false; $timeNow = time(); @@ -256,6 +258,7 @@ switch ($action) { $account->save(); } } + */ $worlds = [$world]; $playdata = compact('worlds', 'characters'); From 12e40b2592ee4bb3a80a17158f5e2aa16142baac Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 15 Oct 2025 15:50:25 +0200 Subject: [PATCH 167/216] Update functions.php --- system/functions.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/system/functions.php b/system/functions.php index b3f1189f..582f9c30 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1640,13 +1640,14 @@ function camelCaseToUnderscore($input) return ltrim(strtolower(preg_replace('/[A-Z]([A-Z](?![a-z]))*/', '_$0', $input)), '_'); } -function removeIfFirstSlash(&$text) { +function removeIfFirstSlash(&$text): void +{ if(strpos($text, '/') === 0) { $text = str_replace_first('/', '', $text); } }; -function escapeHtml($html) { +function escapeHtml($html): string { return htmlspecialchars($html); } @@ -1660,7 +1661,7 @@ function getGuildNameById($id) return false; } -function getGuildLogoById($id) +function getGuildLogoById($id): string { $logo = 'default.gif'; @@ -1676,7 +1677,8 @@ function getGuildLogoById($id) return BASE_URL . GUILD_IMAGES_DIR . $logo; } -function displayErrorBoxWithBackButton($errors, $action = null) { +function displayErrorBoxWithBackButton($errors, $action = null): void +{ global $twig; $twig->display('error_box.html.twig', ['errors' => $errors]); $twig->display('account.back_button.html.twig', [ From 7f60b3d31d53addb806631dd9edd5ac0e4c79d54 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 15 Oct 2025 15:59:49 +0200 Subject: [PATCH 168/216] Add same code in Models\Account + Optimize code --- system/libs/pot/OTS_Account.php | 11 ++++++----- system/src/Models/Account.php | 9 +++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index 5cee25a4..a5007e3b 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -443,15 +443,16 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable throw new E_OTS_NotLoaded(); } - if(isset($this->data['premium_ends_at']) || isset($this->data['premend'])) { - $col = isset($this->data['premium_ends_at']) ? 'premium_ends_at' : 'premend'; - $ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60)); - return max($ret, 0); + if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) || + (isCanary() && isset($this->data['lastday']))) { + $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); + $ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60)); + return max($ret, 0); } if (isCanary() && isset($this->data['lastday'])) { $ret = ceil(($this->data['lastday'] - time()) / 86400); - return $ret > 0 ? $ret : 0; + return max($ret, 0); } if($this->data['premdays'] == 0) { diff --git a/system/src/Models/Account.php b/system/src/Models/Account.php index f0bd435f..fdd7d540 100644 --- a/system/src/Models/Account.php +++ b/system/src/Models/Account.php @@ -33,10 +33,11 @@ class Account extends Model { public function getPremiumDaysAttribute() { - if(isset($this->premium_ends_at) || isset($this->premend)) { - $col = isset($this->premium_ends_at) ? 'premium_ends_at' : 'premend'; - $ret = ceil(($this->{$col}- time()) / (24 * 60 * 60)); - return $ret > 0 ? $ret : 0; + if(isset($this->premium_ends_at) || isset($this->premend) || + (isCanary() && isset($this->data['lastday']))) { + $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); + $ret = ceil(($this->{$col}- time()) / (24 * 60 * 60)); + return max($ret, 0); } if($this->premdays == 0) { From 470555f2687809a0c12491bbb27597e64b8929c1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 16 Oct 2025 21:22:49 +0200 Subject: [PATCH 169/216] New hooks for account/change-password HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_OLD_PASSWORD + HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_NEW_PASSWORD --- system/src/global.php | 2 ++ system/templates/account.change-password.html.twig | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/system/src/global.php b/system/src/global.php index 8f1885f3..85f9476d 100644 --- a/system/src/global.php +++ b/system/src/global.php @@ -28,6 +28,8 @@ define('HOOK_CHARACTERS_AFTER_CHARACTERS', ++$i); define('HOOK_LOGIN', ++$i); define('HOOK_LOGIN_ATTEMPT', ++$i); define('HOOK_LOGOUT', ++$i); +define('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_OLD_PASSWORD', ++$i); +define('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_NEW_PASSWORD', ++$i); define('HOOK_ACCOUNT_CHANGE_PASSWORD_POST', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i); define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i); diff --git a/system/templates/account.change-password.html.twig b/system/templates/account.change-password.html.twig index df101323..db2c1f74 100644 --- a/system/templates/account.change-password.html.twig +++ b/system/templates/account.change-password.html.twig @@ -12,6 +12,9 @@ Please enter your current password and a new password. For your security, please + + {{ hook('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_OLD_PASSWORD') }} + New Password: @@ -20,6 +23,9 @@ Please enter your current password and a new password. For your security, please + + {{ hook('HOOK_ACCOUNT_CHANGE_PASSWORD_AFTER_NEW_PASSWORD') }} + New Password Again: From 16849e7578321c92bec12674e5bf46ad4d38140f Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 16 Oct 2025 21:36:14 +0200 Subject: [PATCH 170/216] account/change-password refactor a bit Add "The old password is same as the new password!" Better post variables names --- system/pages/account/change-password.php | 18 ++++++++++-------- .../account.change-password.html.twig | 6 +++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/system/pages/account/change-password.php b/system/pages/account/change-password.php index 35058d3d..157515b7 100644 --- a/system/pages/account/change-password.php +++ b/system/pages/account/change-password.php @@ -19,18 +19,17 @@ if(!$logged) { csrfProtect(); -$new_password = $_POST['newpassword'] ?? NULL; -$new_password_confirm = $_POST['newpassword_confirm'] ?? NULL; -$old_password = $_POST['oldpassword'] ?? NULL; +$new_password = $_POST['new_password'] ?? null; +$new_password_confirm = $_POST['new_password_confirm'] ?? null; +$old_password = $_POST['old_password'] ?? null; if(empty($new_password) && empty($new_password_confirm) && empty($old_password)) { $twig->display('account.change-password.html.twig'); } -else -{ +else { if(empty($new_password) || empty($new_password_confirm) || empty($old_password)){ $errors[] = 'Please fill in form.'; } - $password_strlen = strlen($new_password); + if($new_password != $new_password_confirm) { $errors[] = 'The new passwords do not match!'; } @@ -41,10 +40,13 @@ else } /** @var OTS_Account $account_logged */ - $old_password = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password); - if($old_password != $account_logged->getPassword()) { + $old_password_hashed = encrypt((USE_ACCOUNT_SALT ? $account_logged->getCustomField('salt') : '') . $old_password); + if($old_password_hashed != $account_logged->getPassword()) { $errors[] = 'Current password is incorrect!'; } + else if ($old_password == $new_password) { + $errors[] = 'The old password is same as the new password!'; + } $hooks->trigger(HOOK_ACCOUNT_CHANGE_PASSWORD_POST); } diff --git a/system/templates/account.change-password.html.twig b/system/templates/account.change-password.html.twig index db2c1f74..03f82d9b 100644 --- a/system/templates/account.change-password.html.twig +++ b/system/templates/account.change-password.html.twig @@ -9,7 +9,7 @@ Please enter your current password and a new password. For your security, please Current Password: - + @@ -20,7 +20,7 @@ Please enter your current password and a new password. For your security, please New Password: - + @@ -31,7 +31,7 @@ Please enter your current password and a new password. For your security, please New Password Again: - + From 89fae38caa7e4f645957fcf1a9330a36358ac04f Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 21 Oct 2025 12:18:56 +0200 Subject: [PATCH 171/216] Ignore set last visit for AJAX pages - Fixes template change redirect --- admin/tools/phpinfo.php | 3 ++- admin/tools/reload_data.php | 1 + admin/tools/settings_save.php | 1 + admin/tools/status.php | 3 ++- admin/tools/upload_image.php | 3 ++- system/login.php | 10 ++++++---- tools/generate_account_number.php | 2 ++ tools/status.php | 3 +++ tools/validate.php | 2 ++ 9 files changed, 21 insertions(+), 7 deletions(-) diff --git a/admin/tools/phpinfo.php b/admin/tools/phpinfo.php index cd043279..bd09fb5d 100644 --- a/admin/tools/phpinfo.php +++ b/admin/tools/phpinfo.php @@ -1,5 +1,6 @@ addGlobal('account_logged', $account_logged); } -setSession('last_visit', time()); -if(defined('PAGE')) { - setSession('last_page', PAGE); +if (!defined('IGNORE_SET_LAST_VISIT') || !IGNORE_SET_LAST_VISIT) { + setSession('last_visit', time()); + if(defined('PAGE')) { + setSession('last_page', PAGE); + } + setSession('last_uri', $_SERVER['REQUEST_URI']); } -setSession('last_uri', $_SERVER['REQUEST_URI']); diff --git a/tools/generate_account_number.php b/tools/generate_account_number.php index a53ba9a3..643bb2c2 100644 --- a/tools/generate_account_number.php +++ b/tools/generate_account_number.php @@ -9,6 +9,8 @@ * @link https://my-aac.org */ +const IGNORE_SET_LAST_VISIT = true; + // we need some functions require '../common.php'; require SYSTEM . 'functions.php'; diff --git a/tools/status.php b/tools/status.php index ae0ee49d..9e9c8a29 100644 --- a/tools/status.php +++ b/tools/status.php @@ -1,4 +1,7 @@ Date: Tue, 21 Oct 2025 17:18:07 +0200 Subject: [PATCH 172/216] Release v1.8.3 --- CHANGELOG-1.x.md | 25 +++++++++++++++++++++++++ common.php | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 17e2a06e..8779d2c5 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,30 @@ # Changelog +## [1.8.3 - 21.10.2025] + +### Added +* Feature: resend email verify (https://github.com/slawkens/myaac/commit/fe821c58085483e70491dcf76376ad5b96de3fdd) +* New config: hooks_debug (To view where hooks are located in .twig files) (https://github.com/slawkens/myaac/commit/8c3cb0e06f9709c1de3398b48221241e7cbdd310) +* Functions: Add db->getColumnInfo(table, column) (https://github.com/slawkens/myaac/commit/c898fe25efff6793a01d11c26fc153cb23fcb858) +* Plugins: Add option to use ?subtopic=x for plugins pages (https://github.com/slawkens/myaac/commit/97f9d3d6f6c28aef6d824973058d7133f56e09c4) +* getTopPlayers() Function - Add lookmount & promotion (https://github.com/slawkens/myaac/commit/2da0024c68f1cedc38a16ebbc6f52ffa55e65f7a, https://github.com/slawkens/myaac/commit/901df48d134079d648a18f9d82b60182e818ac02) +* New hooks for account/change-password (https://github.com/slawkens/myaac/commit/470555f2687809a0c12491bbb27597e64b8929c1) + +### Changed +* Feature: show vip days in account management (https://github.com/slawkens/myaac/commit/c88b08eb1ec1f560cbfdaaa16b24e3a0f26da7b3, by @andreoam) +* Allow links in error_box.html.twig (https://github.com/slawkens/myaac/commit/9acad15451071639acf7a7d4e81619b0a9742b12) +* Canary - Comment code to update lastday in login.php (https://github.com/slawkens/myaac/commit/38902c30d114fdbce259467f5820f97037b393e9) +* Cache::remember $ttl = -1 = infinite (https://github.com/slawkens/myaac/commit/64acf70d3854182d88aaf0b67f77cea2a254f179) + +### Fixed +* Online - Allow for html code (example - img) in online_datacenter (https://github.com/slawkens/myaac/commit/3bb272ebbbd2eb7769d174b7082061d14a17bd44) +* Guilds - Fix guild create with freePremium enabled (https://github.com/slawkens/myaac/commit/c91bb5d4097647dca2196d3dea87bc90c89181d2) +* Canary - Fix premDays count (https://github.com/slawkens/myaac/commit/3e61692780d4add93b7b0e9f12f7a283bd8f4b7a) +* Template Change: Ignore set last visit for AJAX pages - Fixes template change redirect (https://github.com/slawkens/myaac/commit/89fae38caa7e4f645957fcf1a9330a36358ac04f) +* Admin Panel - Accounts: Fix lastip v6 (TFS master) (https://github.com/slawkens/myaac/commit/f54b1bdd2af4c16c64ddff0e87a6c96bc4cf9eeb) +* Functions - Prevent injection in $db->hasColumn (https://github.com/slawkens/myaac/commit/56bd7ec5ed904666074492f2e4f13e4fce226bee) +* Compat Config: Add missing config: email_lai_sec_interval (https://github.com/slawkens/myaac/commit/2eae44e0755e624a91be68b4d1ec26d01eb4d9a1) + ## [1.8.2 - 26.09.2025] ### Added diff --git a/common.php b/common.php index e26921c5..1cbd0dd8 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.3-dev'; +const MYAAC_VERSION = '1.8.3'; const DATABASE_VERSION = 46; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 13ea68cc0c9349380c8e4051d702a6c2c8256f44 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 24 Oct 2025 21:10:55 +0200 Subject: [PATCH 173/216] Use low level env init on migrate:run + migrate:to --- aac | 4 ++- system/src/Commands/Env.php | 33 +++++++++++++++++++++++ system/src/Commands/MigrateRunCommand.php | 6 +++-- system/src/Commands/MigrateToCommand.php | 29 +++----------------- 4 files changed, 43 insertions(+), 29 deletions(-) create mode 100644 system/src/Commands/Env.php diff --git a/aac b/aac index d4ce7b7d..8f213136 100644 --- a/aac +++ b/aac @@ -25,7 +25,9 @@ foreach ($commandsGlob as $item) { } $commandPre = '\\MyAAC\Commands\\'; - $application->add(new ($commandPre . $name)); + if (!trait_exists($class = $commandPre . $name)) { + $application->add(new $class); + } } $pluginCommands = Plugins::getCommands(); diff --git a/system/src/Commands/Env.php b/system/src/Commands/Env.php new file mode 100644 index 00000000..e3130806 --- /dev/null +++ b/system/src/Commands/Env.php @@ -0,0 +1,33 @@ +setName('migrate:run') @@ -23,12 +25,12 @@ class MigrateRunCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): int { - require SYSTEM . 'init.php'; - $io = new SymfonyStyle($input, $output); $ids = $input->getArgument('id'); + $this->init(); + // pre-check // in case one of the migrations doesn't exist - we won't execute any of them foreach ($ids as $id) { diff --git a/system/src/Commands/MigrateToCommand.php b/system/src/Commands/MigrateToCommand.php index b82012ed..72be5730 100644 --- a/system/src/Commands/MigrateToCommand.php +++ b/system/src/Commands/MigrateToCommand.php @@ -11,6 +11,8 @@ use Symfony\Component\Console\Style\SymfonyStyle; class MigrateToCommand extends Command { + use Env; + protected function configure(): void { $this->setName('migrate:to') @@ -32,7 +34,7 @@ class MigrateToCommand extends Command return Command::FAILURE; } - $this->initEnv(); + $this->init(); $currentVersion = Config::where('name', 'database_version')->first()->value; if ($currentVersion > $versionDest) { @@ -80,29 +82,4 @@ class MigrateToCommand extends Command updateDatabaseConfig('database_version', ($_up ? $id : $id - 1)); } - - private function initEnv() - { - global $config; - if (!isset($config['installed']) || !$config['installed']) { - throw new \RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.'); - } - - if(empty($config['server_path'])) { - throw new \RuntimeException('Server Path has been not set. Go to config.php and set it.'); - } - - // take care of trailing slash at the end - if($config['server_path'][strlen($config['server_path']) - 1] !== '/') - $config['server_path'] .= '/'; - - $config['lua'] = load_config_lua($config['server_path'] . 'config.lua'); - - // POT - require_once SYSTEM . 'libs/pot/OTS.php'; - $ots = POT::getInstance(); - $eloquentConnection = null; - - require_once SYSTEM . 'database.php'; - } } From 07fd034fe4cb0ffdb88667b1e400f414d0c6d06f Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 24 Oct 2025 21:12:40 +0200 Subject: [PATCH 174/216] Use low level env init on migrate command --- system/src/Commands/MigrateCommand.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/src/Commands/MigrateCommand.php b/system/src/Commands/MigrateCommand.php index a8a21016..73868ce3 100644 --- a/system/src/Commands/MigrateCommand.php +++ b/system/src/Commands/MigrateCommand.php @@ -9,6 +9,8 @@ use Symfony\Component\Console\Style\SymfonyStyle; class MigrateCommand extends Command { + use Env; + protected function configure(): void { $this->setName('migrate') @@ -17,7 +19,7 @@ class MigrateCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): int { - require SYSTEM . 'init.php'; + $this->init(); $io = new SymfonyStyle($input, $output); require SYSTEM . 'migrate.php'; From 727f68a57594b7d98682024b6aac778804ad84a1 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 24 Oct 2025 21:14:49 +0200 Subject: [PATCH 175/216] migrate command: show "Already on latest version" --- system/migrate.php | 2 ++ system/src/Commands/MigrateCommand.php | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/system/migrate.php b/system/migrate.php index 2199fd73..2bbb3786 100644 --- a/system/migrate.php +++ b/system/migrate.php @@ -9,6 +9,8 @@ */ defined('MYAAC') or die('Direct access not allowed!'); +global $db; + // database migrations $tmp = ''; if(fetchDatabaseConfig('database_version', $tmp)) { // we got version diff --git a/system/src/Commands/MigrateCommand.php b/system/src/Commands/MigrateCommand.php index 73868ce3..fe110190 100644 --- a/system/src/Commands/MigrateCommand.php +++ b/system/src/Commands/MigrateCommand.php @@ -22,6 +22,16 @@ class MigrateCommand extends Command $this->init(); $io = new SymfonyStyle($input, $output); + + $tmp = ''; + if(fetchDatabaseConfig('database_version', $tmp)) { // we got version + $tmp = (int)$tmp; + if ($tmp >= DATABASE_VERSION) { + $io->success('Already on latest version.'); + return Command::SUCCESS; + } + } + require SYSTEM . 'migrate.php'; $io->success('Migrated to latest version (' . DATABASE_VERSION . ')'); From 44110a9496b4385e42c31b75de301037e711b6c3 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 25 Oct 2025 21:32:49 +0200 Subject: [PATCH 176/216] Show if there is mysql error on import schema Weird fix, don't know why it didn't worked with query() --- install/tools/5-database.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/tools/5-database.php b/install/tools/5-database.php index f97eca11..f377b809 100644 --- a/install/tools/5-database.php +++ b/install/tools/5-database.php @@ -40,7 +40,7 @@ else { $locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']); success($locale['step_database_importing']); - $db->query(file_get_contents(BASE . 'install/includes/schema.sql')); + $db->exec(file_get_contents(BASE . 'install/includes/schema.sql')); $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']); success($locale['step_database_success_schema']); From 9d92a11fb7cb6d7a1619d79c12faaa0b1c01f980 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 14:34:53 +0100 Subject: [PATCH 177/216] Fix the premium checks, introduced in v1.8.3 --- system/libs/pot/OTS_Account.php | 17 +++++++---------- system/src/Models/Account.php | 22 +++++++++++++--------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index a5007e3b..f617bbfc 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -445,16 +445,11 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) || (isCanary() && isset($this->data['lastday']))) { - $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); + $col = (isset($this->data['premium_ends_at']) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); $ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60)); return max($ret, 0); } - if (isCanary() && isset($this->data['lastday'])) { - $ret = ceil(($this->data['lastday'] - time()) / 86400); - return max($ret, 0); - } - if($this->data['premdays'] == 0) { return 0; } @@ -479,12 +474,14 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable public function isPremium() { - if(isset($this->data['premium_ends_at'])) { - return $this->data['premium_ends_at'] > time(); + if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) || + (isCanary() && isset($this->data['lastday']))) { + $col = (isset($this->data['premium_ends_at']) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); + return $this->data[$col] > time(); } - if(isset($this->data['premend'])) { - return $this->data['premend'] > time(); + if($this->data['premdays'] == self::GRATIS_PREMIUM_DAYS){ + return true; } return ($this->data['premdays'] - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->data['lastday']))) - date("z", $this->data['lastday'])) > 0); diff --git a/system/src/Models/Account.php b/system/src/Models/Account.php index fdd7d540..5f2de268 100644 --- a/system/src/Models/Account.php +++ b/system/src/Models/Account.php @@ -10,6 +10,8 @@ use Illuminate\Database\Eloquent\Model; */ class Account extends Model { + const GRATIS_PREMIUM_DAYS = 65535; + protected $table = 'accounts'; public $timestamps = false; @@ -34,9 +36,9 @@ class Account extends Model { public function getPremiumDaysAttribute() { if(isset($this->premium_ends_at) || isset($this->premend) || - (isCanary() && isset($this->data['lastday']))) { - $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->data['lastday']) ? 'lastday' : 'premend')); - $ret = ceil(($this->{$col}- time()) / (24 * 60 * 60)); + (isCanary() && isset($this->lastday))) { + $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->lastday) ? 'lastday' : 'premend')); + $ret = ceil(($this->{$col} - time()) / (24 * 60 * 60)); return max($ret, 0); } @@ -44,8 +46,8 @@ class Account extends Model { return 0; } - if($this->premdays == 65535){ - return 65535; + if($this->premdays == self::GRATIS_PREMIUM_DAYS){ + return self::GRATIS_PREMIUM_DAYS; } $ret = ceil($this->premdays - ((int)date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday))); @@ -54,12 +56,14 @@ class Account extends Model { public function getIsPremiumAttribute() { - if(isset($this->premium_ends_at)) { - return $this->premium_ends_at > time(); + if(isset($this->premium_ends_at) || isset($this->premend) || + (isCanary() && isset($this->lastday))) { + $col = (isset($this->premium_ends_at) ? 'premium_ends_at' : (isset($this->lastday) ? 'lastday' : 'premend')); + return $this->{$col} > time(); } - if(isset($this->premend)) { - return $this->premend > time(); + if($this->premdays == self::GRATIS_PREMIUM_DAYS){ + return true; } return ($this->premdays - (date("z", time()) + (365 * (date("Y", time()) - date("Y", $this->lastday))) - date("z", $this->lastday)) > 0); From 6cd38ee1ecb519ec48d37d01e5fc5370f3e07b2a Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 14:38:52 +0100 Subject: [PATCH 178/216] Fix php stan --- system/src/Models/Account.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/src/Models/Account.php b/system/src/Models/Account.php index 5f2de268..26a09f51 100644 --- a/system/src/Models/Account.php +++ b/system/src/Models/Account.php @@ -5,6 +5,8 @@ namespace MyAAC\Models; use Illuminate\Database\Eloquent\Model; /** + * @property integer $premium_ends_at + * @property integer $premend * @property integer $lastday * @property integer $premdays */ From 8f47b36dc88ad4d4c3176e4afda86b520394e8e8 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 15:03:24 +0100 Subject: [PATCH 179/216] Add return type --- system/libs/pot/OTS_Account.php | 2 +- system/src/Models/Account.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system/libs/pot/OTS_Account.php b/system/libs/pot/OTS_Account.php index f617bbfc..8505128e 100644 --- a/system/libs/pot/OTS_Account.php +++ b/system/libs/pot/OTS_Account.php @@ -472,7 +472,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable return $this->data['lastday']; } - public function isPremium() + public function isPremium(): bool { if(isset($this->data['premium_ends_at']) || isset($this->data['premend']) || (isCanary() && isset($this->data['lastday']))) { diff --git a/system/src/Models/Account.php b/system/src/Models/Account.php index 26a09f51..4b44b153 100644 --- a/system/src/Models/Account.php +++ b/system/src/Models/Account.php @@ -56,7 +56,7 @@ class Account extends Model { return max($ret, 0); } - public function getIsPremiumAttribute() + public function getIsPremiumAttribute(): bool { if(isset($this->premium_ends_at) || isset($this->premend) || (isCanary() && isset($this->lastday))) { From 2580edadf84779f09fd395c21f92019b2c762f83 Mon Sep 17 00:00:00 2001 From: Slawomir Boczek Date: Mon, 27 Oct 2025 16:27:22 +0100 Subject: [PATCH 180/216] Database import tables on every install with "IF NOT EXISTS" (#336) * Database import tables on every install with "IF NOT EXISTS" This fixed errors when one table is missing or is duplicated * Add success message on import data * Reorder --- install/includes/import_base_data.php | 69 +++++++++++++++++++++++++++ install/includes/schema.sql | 57 ++++++++-------------- install/tools/5-database.php | 30 +++++------- system/locale/de/install.php | 1 + system/locale/en/install.php | 1 + system/locale/pl/install.php | 3 +- system/src/Models/Changelog.php | 9 ++++ system/src/Models/ForumBoard.php | 16 +++++++ system/src/Models/Gallery.php | 5 ++ system/src/Models/NewsCategory.php | 15 ++++++ 10 files changed, 150 insertions(+), 56 deletions(-) create mode 100644 install/includes/import_base_data.php create mode 100644 system/src/Models/ForumBoard.php create mode 100644 system/src/Models/NewsCategory.php diff --git a/install/includes/import_base_data.php b/install/includes/import_base_data.php new file mode 100644 index 00000000..45c803ed --- /dev/null +++ b/install/includes/import_base_data.php @@ -0,0 +1,69 @@ + 3, + 'where' => 2, + 'date' => time(), + 'body' => 'MyAAC installed. (:', + 'hide' => 0, + ]); +} + +if (Config::where('name', 'database_version')->count() === 0) { + Config::create([ + 'name' => 'database_version', + 'value' => DATABASE_VERSION, + ]); +} + +if (ForumBoard::count() === 0) { + $forumBoards = [ + ['name' => 'News', 'description' => 'News commenting', 'closed' => 1], + ['name' => 'Trade', 'description' => 'Trade offers.', 'closed' => 0], + ['name' => 'Quests', 'description' => 'Quest making.', 'closed' => 0], + ['name' => 'Pictures', 'description' => 'Your pictures.', 'closed' => 0], + ['name' => 'Bug Report', 'description' => 'Report bugs there.', 'closed' => 0], + ]; + + $i = 0; + foreach ($forumBoards as $forumBoard) { + ForumBoard::create([ + 'name' => $forumBoard['name'], + 'description' => $forumBoard['description'], + 'ordering' => $i++, + 'closed' => $forumBoard['closed'], + ]); + } +} + +if (NewsCategory::count() === 0) { + $newsCategoriesIcons = [ + 0, 1, 2, 3, 4 + ]; + + foreach ($newsCategoriesIcons as $iconId) { + NewsCategory::create([ + 'icon_id' => $iconId, + ]); + } +} + +if (Gallery::count() === 0) { + Gallery::create([ + 'comment' => 'Demon', + 'image' => 'images/gallery/demon.jpg', + 'thumb' => 'images/gallery/demon_thumb.gif', + 'author' => 'MyAAC', + 'ordering' => 0, + ]); +} + +success($locale['step_database_success_import_data']); diff --git a/install/includes/schema.sql b/install/includes/schema.sql index b53ffab2..d4bc97d6 100644 --- a/install/includes/schema.sql +++ b/install/includes/schema.sql @@ -1,6 +1,4 @@ -SET @myaac_database_version = 46; - -CREATE TABLE `myaac_account_actions` +CREATE TABLE IF NOT EXISTS `myaac_account_actions` ( `account_id` int NOT NULL, `ip` int unsigned NOT NULL DEFAULT 0, @@ -10,7 +8,7 @@ CREATE TABLE `myaac_account_actions` KEY (`account_id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_account_emails_verify` +CREATE TABLE IF NOT EXISTS `myaac_account_emails_verify` ( `id` int NOT NULL AUTO_INCREMENT, `account_id` int NOT NULL, @@ -19,7 +17,7 @@ CREATE TABLE `myaac_account_emails_verify` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_admin_menu` +CREATE TABLE IF NOT EXISTS `myaac_admin_menu` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL DEFAULT '', @@ -30,7 +28,7 @@ CREATE TABLE `myaac_admin_menu` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_changelog` +CREATE TABLE IF NOT EXISTS `myaac_changelog` ( `id` int NOT NULL AUTO_INCREMENT, `body` varchar(500) NOT NULL DEFAULT '', @@ -42,9 +40,7 @@ CREATE TABLE `myaac_changelog` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -INSERT INTO `myaac_changelog` (`id`, `type`, `where`, `date`, `body`, `hide`) VALUES (1, 3, 2, UNIX_TIMESTAMP(), 'MyAAC installed. (:', 0); - -CREATE TABLE `myaac_config` +CREATE TABLE IF NOT EXISTS `myaac_config` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL, @@ -53,9 +49,7 @@ CREATE TABLE `myaac_config` UNIQUE (`name`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -INSERT INTO `myaac_config` (`name`, `value`) VALUES ('database_version', @myaac_database_version); - -CREATE TABLE `myaac_faq` +CREATE TABLE IF NOT EXISTS `myaac_faq` ( `id` int NOT NULL AUTO_INCREMENT, `question` varchar(255) NOT NULL DEFAULT '', @@ -65,7 +59,7 @@ CREATE TABLE `myaac_faq` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_forum_boards` +CREATE TABLE IF NOT EXISTS `myaac_forum_boards` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, @@ -77,13 +71,8 @@ CREATE TABLE `myaac_forum_boards` `hide` tinyint NOT NULL DEFAULT 0, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`, `closed`) VALUES (NULL, 'News', 'News commenting', 0, 1); -INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Trade', 'Trade offers.', 1); -INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Quests', 'Quest making.', 2); -INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Pictures', 'Your pictures.', 3); -INSERT INTO `myaac_forum_boards` (`id`, `name`, `description`, `ordering`) VALUES (NULL, 'Bug Report', 'Report bugs there.', 4); -CREATE TABLE `myaac_forum` +CREATE TABLE IF NOT EXISTS `myaac_forum` ( `id` int NOT NULL AUTO_INCREMENT, `first_post` int NOT NULL DEFAULT 0, @@ -107,7 +96,7 @@ CREATE TABLE `myaac_forum` KEY `section` (`section`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_menu` +CREATE TABLE IF NOT EXISTS `myaac_menu` ( `id` int NOT NULL AUTO_INCREMENT, `template` varchar(255) NOT NULL, @@ -121,7 +110,7 @@ CREATE TABLE `myaac_menu` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_monsters` ( +CREATE TABLE IF NOT EXISTS `myaac_monsters` ( `id` int NOT NULL AUTO_INCREMENT, `hide` tinyint NOT NULL DEFAULT 0, `name` varchar(255) NOT NULL, @@ -154,7 +143,7 @@ CREATE TABLE `myaac_monsters` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_news` +CREATE TABLE IF NOT EXISTS `myaac_news` ( `id` int NOT NULL AUTO_INCREMENT, `title` varchar(100) NOT NULL, @@ -172,7 +161,7 @@ CREATE TABLE `myaac_news` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_news_categories` +CREATE TABLE IF NOT EXISTS `myaac_news_categories` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT "", @@ -182,13 +171,7 @@ CREATE TABLE `myaac_news_categories` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 0); -INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 1); -INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 2); -INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 3); -INSERT INTO `myaac_news_categories` (`id`, `icon_id`) VALUES (NULL, 4); - -CREATE TABLE `myaac_notepad` +CREATE TABLE IF NOT EXISTS `myaac_notepad` ( `id` int NOT NULL AUTO_INCREMENT, `account_id` int NOT NULL, @@ -198,7 +181,7 @@ CREATE TABLE `myaac_notepad` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_pages` +CREATE TABLE IF NOT EXISTS `myaac_pages` ( `id` INT NOT NULL AUTO_INCREMENT, `name` varchar(30) NOT NULL, @@ -214,7 +197,7 @@ CREATE TABLE `myaac_pages` UNIQUE (`name`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_gallery` +CREATE TABLE IF NOT EXISTS `myaac_gallery` ( `id` int NOT NULL AUTO_INCREMENT, `comment` varchar(255) NOT NULL DEFAULT '', @@ -226,9 +209,7 @@ CREATE TABLE `myaac_gallery` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -INSERT INTO `myaac_gallery` (`id`, `ordering`, `comment`, `image`, `thumb`, `author`) VALUES (NULL, 1, 'Demon', 'images/gallery/demon.jpg', 'images/gallery/demon_thumb.gif', 'MyAAC'); - -CREATE TABLE `myaac_settings` +CREATE TABLE IF NOT EXISTS `myaac_settings` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL DEFAULT '', @@ -238,7 +219,7 @@ CREATE TABLE `myaac_settings` KEY `key` (`key`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_spells` +CREATE TABLE IF NOT EXISTS `myaac_spells` ( `id` int NOT NULL AUTO_INCREMENT, `spell` varchar(255) NOT NULL DEFAULT '', @@ -261,7 +242,7 @@ CREATE TABLE `myaac_spells` UNIQUE (`name`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_visitors` +CREATE TABLE IF NOT EXISTS `myaac_visitors` ( `ip` varchar(45) NOT NULL, `lastvisit` int NOT NULL DEFAULT 0, @@ -270,7 +251,7 @@ CREATE TABLE `myaac_visitors` UNIQUE (`ip`) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4; -CREATE TABLE `myaac_weapons` +CREATE TABLE IF NOT EXISTS `myaac_weapons` ( `id` int NOT NULL, `level` int NOT NULL DEFAULT 0, diff --git a/install/tools/5-database.php b/install/tools/5-database.php index f377b809..6406ee48 100644 --- a/install/tools/5-database.php +++ b/install/tools/5-database.php @@ -30,26 +30,22 @@ if(!$error) { } } -if($db->hasTable(TABLE_PREFIX . 'account_actions')) { - $locale['step_database_error_table_exist'] = str_replace('$TABLE$', TABLE_PREFIX . 'account_actions', $locale['step_database_error_table_exist']); - warning($locale['step_database_error_table_exist']); -} -else { - // import schema - try { - $locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']); - success($locale['step_database_importing']); +// import schema +try { + $locale['step_database_importing'] = str_replace('$DATABASE_NAME$', config('database_name'), $locale['step_database_importing']); + success($locale['step_database_importing']); - $db->exec(file_get_contents(BASE . 'install/includes/schema.sql')); + $db->exec(file_get_contents(BASE . 'install/includes/schema.sql')); - $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']); - success($locale['step_database_success_schema']); - } - catch(PDOException $error_) { - error($locale['step_database_error_schema'] . ' ' . $error_); - return; - } + $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']); + success($locale['step_database_success_schema']); } +catch(PDOException $error_) { + error($locale['step_database_error_schema'] . ' ' . $error_); + return; +} + +require BASE . 'install/includes/import_base_data.php'; if(!$db->hasColumn('accounts', 'email')) { if(query("ALTER TABLE `accounts` ADD `email` varchar(255) NOT NULL DEFAULT '';")) diff --git a/system/locale/de/install.php b/system/locale/de/install.php index 927da34b..351f6009 100644 --- a/system/locale/de/install.php +++ b/system/locale/de/install.php @@ -78,6 +78,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL ist nicht richtig konfig $locale['step_database_error_mysql_connect_4'] = 'MySQL-Server läuft nicht.'; $locale['step_database_error_schema'] = 'Fehler beim Importieren des Schemas:'; $locale['step_database_success_schema'] = '$PREFIX$ Tabellen wurden erfolgreich installiert.'; +$locale['step_database_success_import_data'] = 'Import von Daten für Tabellen was erfolgreich.'; $locale['step_database_error_file'] = '$FILE$ konnte nicht geöffnet werden. Bitte kopieren Sie diesen Inhalt und fügen Sie ihn dort ein:'; $locale['step_database_adding_field'] = 'Folgendes Feld wurde hinzugefügt: '; $locale['step_database_modifying_field'] = 'Folgendes Feld wurde geändert: '; diff --git a/system/locale/en/install.php b/system/locale/en/install.php index 376e82c3..c623035c 100644 --- a/system/locale/en/install.php +++ b/system/locale/en/install.php @@ -83,6 +83,7 @@ $locale['step_database_error_mysql_connect_3'] = 'MySQL is not configured proper $locale['step_database_error_mysql_connect_4'] = 'MySQL server is not running.'; $locale['step_database_error_schema'] = 'Error while importing schema:'; $locale['step_database_success_schema'] = 'Successfully installed $PREFIX$ tables.'; +$locale['step_database_success_import_data'] = 'Successfully imported base data for tables.'; $locale['step_database_error_file'] = '$FILE$ couldn\'t be opened. Please copy this content and paste there:'; $locale['step_database_adding_field'] = 'Adding field'; $locale['step_database_modifying_field'] = 'Modifying field'; diff --git a/system/locale/pl/install.php b/system/locale/pl/install.php index 159a7d8f..a8ea0cf6 100644 --- a/system/locale/pl/install.php +++ b/system/locale/pl/install.php @@ -81,7 +81,8 @@ $locale['step_database_error_mysql_connect_2'] = 'Możliwe przyczyny:'; $locale['step_database_error_mysql_connect_3'] = 'MySQL nie jest poprawnie skonfigurowane w config.lua.'; $locale['step_database_error_mysql_connect_4'] = 'Serwer MySQL nie jest uruchomiony.'; $locale['step_database_error_schema'] = 'Błąd podczas importowania struktury bazy danych:'; -$locale['step_database_success_schema'] = 'Pomyślnie zainstalowano tabele $PREFIX$.'; +$locale['step_database_success_schema'] = 'Pomyślnie zaimportowano tabele $PREFIX$.'; +$locale['step_database_success_import_data'] = 'Pomyślnie załadowano bazowe dane dla tabel.'; $locale['step_database_error_file'] = '$FILE$ nie mógł zostać otwarty. Proszę skopiować zawartość pola tekstowego i wkleić do tego pliku:'; $locale['step_database_adding_field'] = 'Dodawanie pola'; $locale['step_database_modifying_field'] = 'Modyfikacja pola'; diff --git a/system/src/Models/Changelog.php b/system/src/Models/Changelog.php index b7356166..45f8cf59 100644 --- a/system/src/Models/Changelog.php +++ b/system/src/Models/Changelog.php @@ -18,7 +18,16 @@ class Changelog extends Model { public $timestamps = false; + protected $fillable = [ + 'body', 'type', 'where', + 'date', 'player_id', 'hide', + ]; + public function scopeIsPublic($query) { $query->where('hide', '!=', 1); } + + public function player() { + return $this->belongsTo(Player::class); + } } diff --git a/system/src/Models/ForumBoard.php b/system/src/Models/ForumBoard.php new file mode 100644 index 00000000..ee03fde9 --- /dev/null +++ b/system/src/Models/ForumBoard.php @@ -0,0 +1,16 @@ + Date: Mon, 27 Oct 2025 16:43:34 +0100 Subject: [PATCH 181/216] Release v1.8.4 --- CHANGELOG-1.x.md | 10 ++++++++++ common.php | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index 8779d2c5..bea711e1 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,15 @@ # Changelog +## [1.8.4 - 27.10.2025] + +### Changed +* Reimport myaac_ tables on every install, this fixes errors when one table is missing or is duplicated (https://github.com/slawkens/myaac/commit/2580edadf84779f09fd395c21f92019b2c762f83) +* Use custom env init on migrate, migrate:run and migrate:to (https://github.com/slawkens/myaac/commit/13ea68cc0c9349380c8e4051d702a6c2c8256f44, https://github.com/slawkens/myaac/commit/07fd034fe4cb0ffdb88667b1e400f414d0c6d06f) + +### Fixed +* Show if there is mysql error on import schema (https://github.com/slawkens/myaac/commit/44110a9496b4385e42c31b75de301037e711b6c3) +* Fix the premium checks (mostly TFS 1.6+), introduced in v1.8.3 (https://github.com/slawkens/myaac/commit/9d92a11fb7cb6d7a1619d79c12faaa0b1c01f980) + ## [1.8.3 - 21.10.2025] ### Added diff --git a/common.php b/common.php index 1cbd0dd8..4c9d9155 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.3'; +const MYAAC_VERSION = '1.8.4'; const DATABASE_VERSION = 46; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 4b8c3ffae253bbec5a503667d5aa94a5335f0c85 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 16:55:29 +0100 Subject: [PATCH 182/216] Code smell --- admin/pages/mass_account.php | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/admin/pages/mass_account.php b/admin/pages/mass_account.php index 6b1ccb46..4ee9f63b 100644 --- a/admin/pages/mass_account.php +++ b/admin/pages/mass_account.php @@ -6,6 +6,7 @@ * @package MyAAC * @author Slawkens * @author Lee + * @author gpedro * @copyright 2020 MyAAC * @link https://my-aac.org */ @@ -19,9 +20,9 @@ $title = 'Mass Account Actions'; csrfProtect(); $hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); -$freePremium = $config['lua']['freePremium']; +$freePremium = getBoolean(configLua('freePremium')); -function admin_give_points($points) +function admin_give_points($points): void { global $hasPointsColumn; @@ -37,7 +38,7 @@ function admin_give_points($points) displayMessage($points . ' points added to all accounts.', true); } -function admin_give_coins($coins) +function admin_give_coins($coins): void { if (!HAS_ACCOUNT_COINS) { displayMessage('Coins not supported.'); @@ -52,7 +53,7 @@ function admin_give_coins($coins) displayMessage($coins . ' coins added to all accounts.', true); } -function admin_give_premdays($days) +function admin_give_premdays($days): void { global $db, $freePremium; @@ -63,6 +64,7 @@ function admin_give_premdays($days) $value = $days * 86400; $now = time(); + // othire if ($db->hasColumn('accounts', 'premend')) { // append premend @@ -70,14 +72,11 @@ function admin_give_premdays($days) // set premend if (Account::where('premend', '<=', $now)->update(['premend' => $now + $value])) { displayMessage($days . ' premium days added to all accounts.', true); - return; } else { displayMessage('Failed to execute set query.'); - return; } } else { displayMessage('Failed to execute append query.'); - return; } return; @@ -92,20 +91,14 @@ function admin_give_premdays($days) // set lastday if (Account::where('lastday', '<=', $now)->update(['lastday' => $now + $value])) { displayMessage($days . ' premium days added to all accounts.', true); - return; } else { displayMessage('Failed to execute set query.'); - return; } - - return; } else { displayMessage('Failed to execute append query.'); - return; } } else { displayMessage('Failed to execute set days query.'); - return; } return; @@ -118,14 +111,11 @@ function admin_give_premdays($days) // set premium_ends_at if (Account::where('premium_ends_at', '<=', $now)->update(['premium_ends_at' => $now + $value])) { displayMessage($days . ' premium days added to all accounts.', true); - return; } else { displayMessage('Failed to execute set query.'); - return; } } else { displayMessage('Failed to execute append query.'); - return; } return; @@ -170,7 +160,8 @@ else { )); } -function displayMessage($message, $success = false) { +function displayMessage($message, $success = false): void +{ global $twig, $hasPointsColumn, $freePremium; $success ? success($message): error($message); From a2f8759a5236112d4e360c69bb39c7bd3965e62d Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 17:10:16 +0100 Subject: [PATCH 183/216] Update CHANGELOG-1.x.md --- CHANGELOG-1.x.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index bea711e1..b8c57ce7 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -8,7 +8,7 @@ ### Fixed * Show if there is mysql error on import schema (https://github.com/slawkens/myaac/commit/44110a9496b4385e42c31b75de301037e711b6c3) -* Fix the premium checks (mostly TFS 1.6+), introduced in v1.8.3 (https://github.com/slawkens/myaac/commit/9d92a11fb7cb6d7a1619d79c12faaa0b1c01f980) +* Fix the premium checks, introduced in v1.8.3 (https://github.com/slawkens/myaac/commit/9d92a11fb7cb6d7a1619d79c12faaa0b1c01f980) ## [1.8.3 - 21.10.2025] From d24bde2c1df2244388b63ce7fbf556b359f8c155 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 27 Oct 2025 21:45:34 +0100 Subject: [PATCH 184/216] Start v1.8.5-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 4c9d9155..48945038 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.4'; +const MYAAC_VERSION = '1.8.5-dev'; const DATABASE_VERSION = 46; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From bc4107bd16965e3f4b5f5d7e4aa0846e91445f49 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 30 Oct 2025 18:54:11 +0100 Subject: [PATCH 185/216] Ignore only top-most Lua folder --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b198856f..15c069b1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ Thumbs.db # /.htaccess -lua +/lua # composer composer.phar From 26c5aa2e51c215f9a14db170a7591430ad7787d9 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 31 Oct 2025 06:52:56 +0100 Subject: [PATCH 186/216] Added more code into Items::getDescription Is not ready yet --- system/src/Items.php | 48 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/system/src/Items.php b/system/src/Items.php index 977aa602..0f92b005 100644 --- a/system/src/Items.php +++ b/system/src/Items.php @@ -76,10 +76,11 @@ class Items public static function get($id) { self::load(); - return isset(self::$items[$id]) ? self::$items[$id] : []; + return self::$items[$id] ?? []; } - public static function getDescription($id, $count = 1) { + public static function getDescription($id, $count = 1): string + { $item = self::get($id); $attr = $item['attributes']; @@ -112,15 +113,15 @@ class Items $s .= 'an item of type ' . $item['id']; if(isset($attr['type']) && strtolower($attr['type']) == 'rune') { - $item = Spell::where('item_id', $id)->first(); - if($item) { - if($item->level > 0 && $item->maglevel > 0) { - $s .= '. ' . ($count > 1 ? "They" : "It") . ' can only be used by '; + $spell = Spell::where('item_id', $id)->first(); + if($spell) { + if($spell->level > 0 && $spell->maglevel > 0) { + $s .= '. ' . ($count > 1 ? 'They' : 'It') . ' can only be used by '; } $configVocations = config('vocations'); - if(!empty(trim($item->vocations))) { - $vocations = json_decode($item->vocations); + if(!empty(trim($spell->vocations))) { + $vocations = json_decode($spell->vocations); if(count($vocations) > 0) { foreach($vocations as $voc => $show) { $vocations[$configVocations[$voc]] = $show; @@ -133,8 +134,39 @@ class Items $s .= ' with'; + if ($spell->level > 0) { + $s .= ' level ' . $spell->level; + } + + if ($spell->maglevel > 0) { + if ($spell->level > 0) { + $s .= ' and'; + } + + $s .= ' magic level ' . $spell->maglevel; + } + + $s .= ' or higher'; } } + + if (!empty($item['weaponType'])) { + if ($item['weaponType'] == 'distance' && isset($item['ammoType'])) { + $s .= ' (Range:' . $item['range']; + } + + if (isset($item['attack']) && $item['attack'] != 0) { + $s .= ', Atk ' . ($item['attack'] > 0 ? '+' . $item['attack'] : '-' . $item['attack']); + } + + if (isset($item['hitChance']) && $item['hitChance'] != -1) { + $s .= ', Hit% ' . ($item['hitChance'] > 0 ? '+' . $item['hitChance'] : '-' . $item['hitChance']); + } + elseif ($item['weaponType'] != 'ammo') { + + } + } + return $s; } } From fd729242ff7e74a1a4307e7059a421afc74d8744 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 2 Nov 2025 12:05:47 +0100 Subject: [PATCH 187/216] Fix typo -> satisfied --- system/src/Plugins.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/system/src/Plugins.php b/system/src/Plugins.php index e1a58620..ac57d484 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -549,21 +549,21 @@ class Plugins { if(isset($plugin_json['require'])) { $require = $plugin_json['require']; - $myaac_satified = true; + $myaac_satisfied = true; if(isset($require['myaac_'])) { $require_myaac = $require['myaac_']; if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) { - $myaac_satified = false; + $myaac_satisfied = false; } } else if(isset($require['myaac'])) { $require_myaac = $require['myaac']; if(version_compare(MYAAC_VERSION, $require_myaac, '<')) { - $myaac_satified = false; + $myaac_satisfied = false; } } - if(!$myaac_satified) { + if(!$myaac_satisfied) { self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . "."; return false; } From 730a0f29124811f525207c24c06eb0d088fa3434 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 2 Nov 2025 12:21:29 +0100 Subject: [PATCH 188/216] Ensure some cache folders & index.html exists --- system/functions.php | 18 +++++++++++++++++- system/init.php | 3 +++ system/src/Cache/PHP.php | 3 +++ system/src/Plugins.php | 3 +++ tools/signature/index.php | 3 +++ 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/system/functions.php b/system/functions.php index 582f9c30..88c02102 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1177,7 +1177,8 @@ function getTopPlayers($limit = 5, $skill = 'level') { }); } -function deleteDirectory($dir, $ignore = array(), $contentOnly = false) { +function deleteDirectory($dir, $ignore = array(), $contentOnly = false): bool +{ if(!file_exists($dir)) { return true; } @@ -1203,6 +1204,21 @@ function deleteDirectory($dir, $ignore = array(), $contentOnly = false) { return rmdir($dir); } +function ensureFolderExists($dir): void +{ + if (!file_exists($dir)) { + mkdir($dir, 0777, true); + } +} + +function ensureIndexExists($dir): void +{ + $dir = rtrim($dir, '/'); + if (!file_exists($file = $dir . '/index.html')) { + touch($file); + } +} + function config($key) { global $config; if (is_array($key)) { diff --git a/system/init.php b/system/init.php index 57c299ba..862b5370 100644 --- a/system/init.php +++ b/system/init.php @@ -18,6 +18,9 @@ use MyAAC\Settings; defined('MYAAC') or die('Direct access not allowed!'); +ensureIndexExists(CACHE); +ensureIndexExists(CACHE . 'twig/'); + global $config; if(!isset($config['installed']) || !$config['installed']) { throw new RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.'); diff --git a/system/src/Cache/PHP.php b/system/src/Cache/PHP.php index e42bd928..0b13db07 100644 --- a/system/src/Cache/PHP.php +++ b/system/src/Cache/PHP.php @@ -27,6 +27,9 @@ class PHP { $var = var_export($var, true); + ensureFolderExists($this->dir); + ensureIndexExists($this->dir); + // Write to temp file first to ensure atomicity $tmp = $this->dir . "tmp_$key." . uniqid('', true) . '.tmp'; file_put_contents($tmp, 'getId() . '.png'; if(file_exists($cached) && (time() < (filemtime($cached) + (60 * setting('core.signature_cache_time'))))) { From 25a3db68e69a161a586de4b176ec7eae7f41c86b Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 2 Nov 2025 13:10:09 +0100 Subject: [PATCH 189/216] Use $db->hasTableAndColumns + move $skulls to correct place --- system/pages/characters.php | 38 +++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/system/pages/characters.php b/system/pages/characters.php index 89f98cf0..b88368ff 100644 --- a/system/pages/characters.php +++ b/system/pages/characters.php @@ -202,36 +202,38 @@ if($player->isLoaded() && !$player->isDeleted()) unset($storage); } - if($db->hasTable('player_items') && $db->hasColumn('player_items', 'pid') && $db->hasColumn('player_items', 'sid') && $db->hasColumn('player_items', 'itemtype')) { + if ($db->hasTableAndColumns('player_items', ['pid', 'sid', 'itemtype'])) { $eq_sql = $db->query('SELECT `pid`, `itemtype` FROM player_items WHERE player_id = '.$player->getId().' AND (`pid` >= 1 and `pid` <= 10)'); - $equipment = array(); - foreach($eq_sql as $eq) + $equipment = []; + foreach($eq_sql as $eq) { $equipment[$eq['pid']] = $eq['itemtype']; + } - $empty_slots = array("", "no_helmet", "no_necklace", "no_backpack", "no_armor", "no_handleft", "no_handright", "no_legs", "no_boots", "no_ring", "no_ammo"); - for($i = 0; $i <= 10; $i++) - { + $empty_slots = ["", "no_helmet", "no_necklace", "no_backpack", "no_armor", "no_handleft", "no_handright", "no_legs", "no_boots", "no_ring", "no_ammo"]; + + for($i = 0; $i <= 10; $i++) { if(!isset($equipment[$i]) || $equipment[$i] == 0) $equipment[$i] = $empty_slots[$i]; } - for($i = 1; $i < 11; $i++) - { - if(Validator::number($equipment[$i])) + for($i = 1; $i < 11; $i++) { + if(Validator::number($equipment[$i])) { $equipment[$i] = getItemImage($equipment[$i]); - else + } + else { $equipment[$i] = ' ' . $equipment[$i] . ''; + } } - - $skulls = array( - 1 => 'yellow_skull', - 2 => 'green_skull', - 3 => 'white_skull', - 4 => 'red_skull', - 5 => 'black_skull' - ); } + $skulls = [ + 1 => 'yellow_skull', + 2 => 'green_skull', + 3 => 'white_skull', + 4 => 'red_skull', + 5 => 'black_skull', + ]; + $dead_add_content = ''; $deaths = array(); if($db->hasTable('killers')) { From 49246969439642500c95e943ed848e8d593a5141 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 2 Nov 2025 13:23:30 +0100 Subject: [PATCH 190/216] Try to fix "VirtualProtect() failed [87] The parameter is incorrect" in php logs --- .github/workflows/cypress.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index e93257f1..e05b58ef 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -114,6 +114,7 @@ jobs: with: php-version: ${{ matrix.php-versions }} extensions: mbstring, dom, fileinfo, mysql, json, xml, pdo, pdo_mysql + ini-values: opcache.jit_buffer_size=16M - name: Get composer cache directory id: composer-cache From d201e75b116ca03ec148b7ea7999e8181c592cdf Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 2 Nov 2025 13:38:15 +0100 Subject: [PATCH 191/216] Revert "Try to fix "VirtualProtect() failed [87] The parameter is incorrect" in php logs" This reverts commit 49246969439642500c95e943ed848e8d593a5141. --- .github/workflows/cypress.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index e05b58ef..e93257f1 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -114,7 +114,6 @@ jobs: with: php-version: ${{ matrix.php-versions }} extensions: mbstring, dom, fileinfo, mysql, json, xml, pdo, pdo_mysql - ini-values: opcache.jit_buffer_size=16M - name: Get composer cache directory id: composer-cache From ae7a47464f2379944e4e1be1f59b4d5fc9c5fb21 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 3 Nov 2025 20:37:14 +0100 Subject: [PATCH 192/216] Update menus.php --- admin/template/menus.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/template/menus.php b/admin/template/menus.php index 0bcd7304..6df84745 100644 --- a/admin/template/menus.php +++ b/admin/template/menus.php @@ -60,7 +60,7 @@ usort($menus, function ($a, $b) { foreach ($menus as $i => $menu) { if (isset($menu['link']) && is_array($menu['link'])) { - usort($menus[$i]['link'], function ($a, $b) { + usort($menu['link'], function ($a, $b) { return $a['order'] - $b['order']; }); } From 6367054487368c92741bfd1dc7c70c52aea9ee87 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 3 Nov 2025 21:06:27 +0100 Subject: [PATCH 193/216] Add plugin:remove + plugin:delete as alias for plugin:uninstall --- system/src/Commands/PluginUninstallCommand.php | 1 + 1 file changed, 1 insertion(+) diff --git a/system/src/Commands/PluginUninstallCommand.php b/system/src/Commands/PluginUninstallCommand.php index a5cc00f5..fb5982d4 100644 --- a/system/src/Commands/PluginUninstallCommand.php +++ b/system/src/Commands/PluginUninstallCommand.php @@ -13,6 +13,7 @@ class PluginUninstallCommand extends Command protected function configure(): void { $this->setName('plugin:uninstall') + ->setAliases(['plugin:remove', 'plugin:delete']) ->setDescription('This command uninstalls plugin') ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to uninstall'); } From baec6c9ebf5c342b3b2f7123427c6ba21dbb93bc Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 4 Nov 2025 08:17:41 +0100 Subject: [PATCH 194/216] plugin:activate/deactivate alias --- system/src/Commands/PluginDisableCommand.php | 1 + system/src/Commands/PluginEnableCommand.php | 1 + 2 files changed, 2 insertions(+) diff --git a/system/src/Commands/PluginDisableCommand.php b/system/src/Commands/PluginDisableCommand.php index baa268dd..36c3b766 100644 --- a/system/src/Commands/PluginDisableCommand.php +++ b/system/src/Commands/PluginDisableCommand.php @@ -13,6 +13,7 @@ class PluginDisableCommand extends Command protected function configure(): void { $this->setName('plugin:disable') + ->setAliases(['plugin:deactivate']) ->setDescription('This command disables plugin') ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to disable'); } diff --git a/system/src/Commands/PluginEnableCommand.php b/system/src/Commands/PluginEnableCommand.php index ae1acea0..8d5d0be5 100644 --- a/system/src/Commands/PluginEnableCommand.php +++ b/system/src/Commands/PluginEnableCommand.php @@ -13,6 +13,7 @@ class PluginEnableCommand extends Command protected function configure(): void { $this->setName('plugin:enable') + ->setAliases(['plugin:activate']) ->setDescription('This command enables plugin') ->addArgument('plugin-name', InputArgument::REQUIRED, 'Plugin that you want to enable'); } From 7ca05e47ff7f52a05f0bd740b0e7d7a5cbd4158e Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 4 Nov 2025 22:01:55 +0100 Subject: [PATCH 195/216] Just testing something, excuse me --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 48945038..14f3759d 100644 --- a/common.php +++ b/common.php @@ -69,7 +69,7 @@ const ARTICLE = 3; // this may improve security const ADMIN_PANEL_FOLDER = 'admin'; -// directories +// directoriess const BASE = __DIR__ . '/'; const ADMIN = BASE . ADMIN_PANEL_FOLDER . '/'; const SYSTEM = BASE . 'system/'; From 1c7af30997f121c541fccf154f61ea40bd92035f Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 4 Nov 2025 22:17:00 +0100 Subject: [PATCH 196/216] Revert "Just testing something, excuse me" This reverts commit 7ca05e47ff7f52a05f0bd740b0e7d7a5cbd4158e. --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 14f3759d..48945038 100644 --- a/common.php +++ b/common.php @@ -69,7 +69,7 @@ const ARTICLE = 3; // this may improve security const ADMIN_PANEL_FOLDER = 'admin'; -// directoriess +// directories const BASE = __DIR__ . '/'; const ADMIN = BASE . ADMIN_PANEL_FOLDER . '/'; const SYSTEM = BASE . 'system/'; From 88532b0ebb41ebdab74c4b1e2033a4cdd38c1098 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 5 Nov 2025 19:32:31 +0100 Subject: [PATCH 197/216] Better message than "Access denied" --- admin/tools/settings_save.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/tools/settings_save.php b/admin/tools/settings_save.php index 9bf745d8..2f2f4cb0 100644 --- a/admin/tools/settings_save.php +++ b/admin/tools/settings_save.php @@ -12,7 +12,7 @@ require SYSTEM . 'login.php'; if(!admin()) { http_response_code(500); - die('Access denied.'); + die('You are not logged in. Probably session expired. Please login again.'); } csrfProtect(); From 9ce55db44cf1afc6e033ad9ff0ca321ad5774d24 Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 5 Nov 2025 22:02:11 +0100 Subject: [PATCH 198/216] Display error message after failed settings save - just in case --- admin/tools/settings_save.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/admin/tools/settings_save.php b/admin/tools/settings_save.php index 2f2f4cb0..0f0cb028 100644 --- a/admin/tools/settings_save.php +++ b/admin/tools/settings_save.php @@ -40,3 +40,6 @@ if (count($errors) > 0) { if ($success) { echo 'Saved at ' . date('H:i'); } +else { + echo 'Something unexpected happened - it was impossible to save the settings, please try again later. If problem persists - contact MyAAC developers.'; +} From 175e97828b9a08ec3080cc8d3fb4eb3f1c08649f Mon Sep 17 00:00:00 2001 From: slawkens Date: Wed, 5 Nov 2025 22:21:42 +0100 Subject: [PATCH 199/216] Don't display hidden news for admin - it's confusing --- system/pages/news.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/system/pages/news.php b/system/pages/news.php index dc8c700e..eb7ccd2f 100644 --- a/system/pages/news.php +++ b/system/pages/news.php @@ -122,7 +122,7 @@ if(!$news_cached) ); } - $tickers_db = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . TICKER .($canEdit ? '' : ' AND `hide` != 1') .' ORDER BY `date` DESC LIMIT ' . setting('core.news_ticker_limit')); + $tickers_db = $db->query('SELECT * FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . TICKER . ' AND `hide` != 1 ORDER BY `date` DESC LIMIT ' . setting('core.news_ticker_limit')); $tickers_content = ''; if($tickers_db->rowCount() > 0) { @@ -142,7 +142,8 @@ if(!$news_cached) if($cache->enabled() && !$canEdit) $cache->set('news_' . $template_name . '_' . TICKER, $tickers_content, 60 * 60); - $featured_article_db =$db->query('SELECT `id`, `title`, `article_text`, `article_image`, `hide` FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . ARTICLE . ($canEdit ? '' : ' AND `hide` != 1') .' ORDER BY `date` DESC LIMIT 1'); + $featured_article_db =$db->query('SELECT `id`, `title`, `article_text`, `article_image`, `hide` FROM `' . TABLE_PREFIX . 'news` WHERE `type` = ' . ARTICLE . ' AND `hide` != 1 ORDER BY `date` DESC LIMIT 1'); + $article = ''; if($featured_article_db->rowCount() > 0) { $article = $featured_article_db->fetch(); @@ -175,7 +176,7 @@ else { if(!$news_cached) { ob_start(); - $newses = $db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'news') . ' WHERE type = ' . NEWS . ($canEdit ? '' : ' AND hide != 1') . ' ORDER BY date' . ' DESC LIMIT ' . setting('core.news_limit')); + $newses = $db->query('SELECT * FROM ' . $db->tableName(TABLE_PREFIX . 'news') . ' WHERE type = ' . NEWS . ' AND hide != 1 ORDER BY date' . ' DESC LIMIT ' . setting('core.news_limit')); if($newses->rowCount() > 0) { foreach($newses as $news) From 5861efdbe900ccd35309913af0c0a5f3d4cdc1a8 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 6 Nov 2025 11:48:42 +0100 Subject: [PATCH 200/216] Settings: escapeHtml in values (support for html code) --- system/src/Settings.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/src/Settings.php b/system/src/Settings.php index ec4a83fa..fea52d04 100644 --- a/system/src/Settings.php +++ b/system/src/Settings.php @@ -248,7 +248,7 @@ class Settings implements \ArrayAccess echo '
    '; } - echo ''; + echo ''; if ($setting['type'] === 'password') { echo '
    '; @@ -266,7 +266,7 @@ class Settings implements \ArrayAccess if ($rows < 2) { $rows = 2; // always min 2 rows for textarea } - echo ''; + echo ''; } else if ($setting['type'] === 'options') { From 946364f59d7cd01472877108ab27ec78fb28307a Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 6 Nov 2025 12:01:33 +0100 Subject: [PATCH 201/216] New Setting: Account Countries Most Popular --- system/pages/account/create.php | 2 +- system/settings.php | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/system/pages/account/create.php b/system/pages/account/create.php index 9ffdf6f7..731771b7 100644 --- a/system/pages/account/create.php +++ b/system/pages/account/create.php @@ -367,7 +367,7 @@ if(!empty($errors)) if (setting('core.account_country')) { $countries = array(); - foreach (array('pl', 'se', 'br', 'us', 'gb') as $c) + foreach (setting('core.account_countries_most_popular') ?? [] as $c) $countries[$c] = $config['countries'][$c]; $countries['--'] = '----------'; diff --git a/system/settings.php b/system/settings.php index 73605530..96f24a8c 100644 --- a/system/settings.php +++ b/system/settings.php @@ -737,6 +737,18 @@ Sent by MyAAC,
    'desc' => 'should country of user be automatically recognized by his IP? This makes an external API call to http://ipinfo.io', 'default' => true, ], + 'account_countries_most_popular' => [ + 'name' => 'Account Countries Most Popular', + 'type' => 'text', + 'desc' => 'Those countries will be display at the top of the list on the create account page. The short codes of countries can be found in file system/countries.conf.php', + 'default' => 'pl,se,br,us,gb', + 'callbacks' => [ + 'get' => function ($value) { + $tmp = array_map('trim', explode(',', $value)); + return array_filter($tmp, function ($v) {return !empty($v); }); + }, + ], + ], 'characters_per_account' => [ 'name' => 'Characters per Account', 'type' => 'number', From 4d17001a0b3a2e4367d61c663ef76806d1ce6520 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 6 Nov 2025 12:48:33 +0100 Subject: [PATCH 202/216] Add some popular network images (Facebook, Instagram, WhatsApp) --- images/facebook_16x16.png | Bin 0 -> 718 bytes images/instagram_16x16.png | Bin 0 -> 721 bytes images/whatsapp_16x16.png | Bin 0 -> 688 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/facebook_16x16.png create mode 100644 images/instagram_16x16.png create mode 100644 images/whatsapp_16x16.png diff --git a/images/facebook_16x16.png b/images/facebook_16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..d64c153a2a541a95b25a14a49224a9f47c5ca41d GIT binary patch literal 718 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbL!Lb6AYF9SoB8UsT^3j@P1pisjL z28L1t28LG&3=CE?7#PG0=Ijcz0ZJSW@Ck91DE~wd36*?m+WO=F|Nn<>|BC-JgRW}RPp_x#*(_4l?bzhf7C(`o*E!hz*O`n10NLGAOuKnD$B_UeuRi_TeCc=6qHndEejL2@Tcq?;&88m*ZvB?4{?xy60mwT-B|(0{ z46Gh2p8OV{^nRn~pXE<}|9-MO!(`_)pe$pOx4R2p{$2xrAcwQSBeIx*A#WE5GhVy5 zQ5-19UgGKN%Knm@jax@!{ntg4fI=HRT^vIsF5C8B7i%&Qa1nRfo-Yz;sAaYx;eEuv z|Eqn(O5}^u-k(%4W?-0gj_0z;jCG8?sn#BkZ-~9s`*(b*%Vy7_dpSQlwz0|Geg1aA z<+p_;HVIkZ5AT!UaTio#c5eLW;*Fkpglogr-zsMJ?T@;h2d1~dar(Rpb@&o?r zuURD$F+VNY5a@W-64!{5l*E!$tK_0oAjM#0U}UOmXsByo7Gh{nC}Q!>*kach`3ftL}eK?80>NoH~yHyTa1wrN1k zKFPv$K&nv0t$%`rZWOd}Z=01MwWTOjSCU48Ae17dV7jxNdGmNN>daghd3h?v4-V(t z%lW>0&UXVuW`Fn0J8kH%H?q@>-drQ=HZjx6G>0*6Wc#h`K`pyh8-MhowLd~+R&b+{ zEj6;6b?E=lw7pTQr`1f{QJqQUx)@K%Pdo2%c`JzbaA|VA(Q>=%(eg>x z--bOOj4_wWC8B!zeBXy!_dFS%4TcAY6Fv7Swi_;E5fY<12uVjSl^+VkWqkt+1~vl+ zN1DOIgJ8JXF?=<8GlSHqPE=_sN0@XDCUrdS52{H%9JZqrMIE_XE`_jVXkf>@jd;$9 zzfJX&P;Lm-cJO^QSs_hARi|=|cqlOO;CAqLp(X%XfAa}*QD+c!EE(FDQM}3`6)lH1{Q@Nk<@;|o?pZOMx@hzE@aCd6J6lttp zYJ~gZkKT)SwDAk8$60qABCB=C+5^vC3h^hiYB!XYlx`{PsEiaC;>jczDD@1zqV&4b z*P@jG6OoHb>q^fn%_()2Ok-%QFjjh?@VSRR4*dBSv;*~bM?7Z300000NkvXXu0mjf Dw6RGU literal 0 HcmV?d00001 diff --git a/images/whatsapp_16x16.png b/images/whatsapp_16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..a13d2faf9210f5e49223658e9c565980c9650f1d GIT binary patch literal 688 zcmV;h0#E&kP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0!2wgK~y+TbyGWU z6G0HZ0+47B4FwVn0>q=Hrb0?Vhtfp8z4PmKZ}05bh6)M_Fa;$NA)=&B2O>g=65qqG zJVQ=KJQ`nO)7MF1rtOFPzxmFS;rXP4$z=Fg_E#1L>}YwgiDS1tA& zRoX2m5hmbSCp8K=Zp&VOHku)ELbik-s7}CuhpaQJ;J71~2W(k`3xRnJ(ok8%_PQqg z;#`m|`+(%0N&qFL9Tdx6H+W>ds1Agx^c`ZgGMbf4gyvhsP9uP$Cn92X5DXx<@|6N1 zlK_)~^E_fJ<-Otw;KcP2LpC&MbBKU$Tx4y7KsIw%aV)QMbOblHr|TI%G^kk*PbLH`DPY4%$C2o5<;H~#^S&ktn4o6;qJIZ6X7_k( zJ)sNsL$(q^A{ZGWVD+RS#7fKzVyU3{xh2pXO((q`E zBx{V(Oi73xNp3s)+TY7xPO;i()K4qvWh=()h7R(E`5r+{kdlB9lcDb)lKxr5)+?IW zNA%$Fcd49)`A&mjPQX6k7-eFeDoGvZ#W*W{uA2<7Xj&WP)$%zFmQnT!x=X;HH2V%! z`u}61+ea^Rd2V$s0mDR`x$W=dA1-`axH#F%u3e{z^oUeHXX-`Y@8;@W^Qf7L8OA>? WuKeO?hF+ln0000 Date: Thu, 6 Nov 2025 13:47:09 +0100 Subject: [PATCH 203/216] Fix $status['uptimeReadable'], was totally wrong --- system/functions.php | 37 +++++++++++++++++++++++++++++++++++++ system/status.php | 8 +------- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/system/functions.php b/system/functions.php index 88c02102..ca7989ed 100644 --- a/system/functions.php +++ b/system/functions.php @@ -1728,6 +1728,43 @@ function isCanary(): bool return isset($vipSystemEnabled); } +function getStatusUptimeReadable(int $uptime): string +{ + $fullMinute = 60; + $fullHour = (60 * $fullMinute); + $fullDay = (24 * $fullHour); + $fullMonth = (30 * $fullDay); + $fullYear = (365 * $fullDay); + + // years + $years = floor($uptime / $fullYear); + $y = ($years > 1 ? "$years years, " : ($years == 1 ? 'year, ' : '')); + + $uptime -= $years * $fullYear; + + // months + $months = floor($uptime / $fullMonth); + $m = ($months > 1 ? "$months months, " : ($months == 1 ? 'month, ' : '')); + + $uptime -= $months * $fullMonth; + + // days + $days = floor($uptime / $fullDay); + $d = ($days > 1 ? "$days days, " : ($days == 1 ? 'day, ' : '')); + + $uptime -= $days * $fullDay; + + // hours + $hours = floor($uptime / $fullHour); + + $uptime -= $hours * $fullHour; + + // minutes + $min = floor($uptime / $fullMinute); + + return "{$y}{$m}{$d}{$hours}h {$min}m"; +} + // validator functions require_once SYSTEM . 'compat/base.php'; diff --git a/system/status.php b/system/status.php index 8e8225dd..b69e7acc 100644 --- a/system/status.php +++ b/system/status.php @@ -145,13 +145,7 @@ function updateStatus() { } $uptime = $status['uptime'] = $serverStatus->getUptime(); - $m = date('m', $uptime); - $m = $m > 1 ? "$m months, " : ($m == 1 ? 'month, ' : ''); - $d = date('d', $uptime); - $d = $d > 1 ? "$d days, " : ($d == 1 ? 'day, ' : ''); - $h = date('H', $uptime); - $min = date('i', $uptime); - $status['uptimeReadable'] = "{$m}{$d}{$h}h {$min}m"; + $status['uptimeReadable'] = getStatusUptimeReadable($uptime); $status['monsters'] = $serverStatus->getMonstersCount(); $status['motd'] = $serverStatus->getMOTD(); From 780d4ccef741c1dd45a00bfc121fba9f1a175313 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 6 Nov 2025 22:06:05 +0100 Subject: [PATCH 204/216] Server Status: Write to status-error.log if there is connection error --- system/libs/pot/OTS_ServerInfo.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/system/libs/pot/OTS_ServerInfo.php b/system/libs/pot/OTS_ServerInfo.php index 76ebcaf7..a0ee464f 100644 --- a/system/libs/pot/OTS_ServerInfo.php +++ b/system/libs/pot/OTS_ServerInfo.php @@ -97,6 +97,8 @@ class OTS_ServerInfo return new OTS_Buffer($data); } + log_append('status-error.log', "Cannot connect to {$this->server}:{$this->port} - Error code: $error, message: $message"); + return false; } From e440c0d6a6e78032beabc7865a71ba59943d7d69 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 13 Nov 2025 19:14:59 +0100 Subject: [PATCH 205/216] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 15c069b1..7da27c57 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ releases tmp config.local.php +config2.local.php # all custom templates templates/* From 6775a061bebc9ff449522f0173556d4a7a44fa5e Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 18 Nov 2025 00:15:32 +0100 Subject: [PATCH 206/216] Detect "deletion" column in guilds show --- system/pages/guilds/show.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/system/pages/guilds/show.php b/system/pages/guilds/show.php index 99ac6599..527f29d7 100644 --- a/system/pages/guilds/show.php +++ b/system/pages/guilds/show.php @@ -91,13 +91,18 @@ $guild_owner = $guild->getOwner(); if($guild_owner->isLoaded()) $guild_owner_name = $guild_owner->getName(); +$deletedColumn = 'deleted'; +if ($db->hasColumn('players', 'deletion')) { + $deletedColumn = 'deletion'; +} + $guild_members = array(); foreach($rank_list as $rank) { if($db->hasTable(GUILD_MEMBERS_TABLE)) - $players_with_rank = $db->query('SELECT `players`.`id` as `id`, `' . GUILD_MEMBERS_TABLE . '`.`rank_id` as `rank_id` FROM `players`, `' . GUILD_MEMBERS_TABLE . '` WHERE `' . GUILD_MEMBERS_TABLE . '`.`rank_id` = ' . $rank->getId() . ' AND `players`.`id` = `' . GUILD_MEMBERS_TABLE . '`.`player_id` ORDER BY `name`;'); + $players_with_rank = $db->query('SELECT `players`.`id` as `id`, `' . GUILD_MEMBERS_TABLE . '`.`rank_id` as `rank_id` FROM `players`, `' . GUILD_MEMBERS_TABLE . '` WHERE `' . GUILD_MEMBERS_TABLE . '`.`rank_id` = ' . $rank->getId() . ' AND `players`.`id` = `' . GUILD_MEMBERS_TABLE . '`.`player_id` AND `' . $deletedColumn . '` = 0 ORDER BY `name`;'); else if($db->hasColumn('players', 'rank_id')) - $players_with_rank = $db->query('SELECT `id`, `rank_id` FROM `players` WHERE `rank_id` = ' . $rank->getId() . ' AND `deleted` = 0;'); + $players_with_rank = $db->query('SELECT `id`, `rank_id` FROM `players` WHERE `rank_id` = ' . $rank->getId() . ' AND `' . $deletedColumn . '` = 0;'); $players_with_rank_number = $players_with_rank->rowCount(); if($players_with_rank_number > 0) From 603d860b56bc7418db09e206f40aa06d0682c00e Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 18 Nov 2025 09:56:07 +0100 Subject: [PATCH 207/216] Detect "deletion" column in guilds delete --- system/functions.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/system/functions.php b/system/functions.php index ca7989ed..f11fa382 100644 --- a/system/functions.php +++ b/system/functions.php @@ -433,16 +433,22 @@ function delete_guild($id) $rank_list->orderBy('level'); global $db; + + $deletedColumn = 'deleted'; + if ($db->hasColumn('players', 'deletion')) { + $deletedColumn = 'deletion'; + } + /** * @var OTS_GuildRank $rank_in_guild */ foreach($rank_list as $rank_in_guild) { if($db->hasTable('guild_members')) - $players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_members`.`rank_id` as `rank_id` FROM `players`, `guild_members` WHERE `guild_members`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_members`.`player_id` ORDER BY `name`;'); + $players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_members`.`rank_id` as `rank_id` FROM `players`, `guild_members` WHERE `guild_members`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_members`.`player_id` AND `' . $deletedColumn . '` = 0 ORDER BY `name`;'); else if($db->hasTable('guild_membership')) - $players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_membership`.`rank_id` as `rank_id` FROM `players`, `guild_membership` WHERE `guild_membership`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_membership`.`player_id` ORDER BY `name`;'); + $players_with_rank = $db->query('SELECT `players`.`id` as `id`, `guild_membership`.`rank_id` as `rank_id` FROM `players`, `guild_membership` WHERE `guild_membership`.`rank_id` = ' . $rank_in_guild->getId() . ' AND `players`.`id` = `guild_membership`.`player_id` AND `' . $deletedColumn . '` = 0 ORDER BY `name`;'); else - $players_with_rank = $db->query('SELECT `id`, `rank_id` FROM `players` WHERE `rank_id` = ' . $rank_in_guild->getId() . ' AND `deleted` = 0;'); + $players_with_rank = $db->query('SELECT `id`, `rank_id` FROM `players` WHERE `rank_id` = ' . $rank_in_guild->getId() . ' AND `' . $deletedColumn . '` = 0;'); $players_with_rank_number = $players_with_rank->rowCount(); if($players_with_rank_number > 0) { From 1d21f4d682b28ab5d5073bd664ab2a3c85bac01a Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 18 Nov 2025 12:24:22 +0100 Subject: [PATCH 208/216] Update create.php --- system/pages/guilds/create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/pages/guilds/create.php b/system/pages/guilds/create.php index 08bc8817..47ae690b 100644 --- a/system/pages/guilds/create.php +++ b/system/pages/guilds/create.php @@ -22,7 +22,7 @@ if(!$logged) { } $configLuaFreePremium = configLua('freePremium'); -$freePremium = (isset($configLuaFreePremium) && getBoolean($configLuaFreePremium)) || ($logged && $account_logged->getPremDays() == OTS_Account::GRATIS_PREMIUM_DAYS); +$freePremium = (isset($configLuaFreePremium) && getBoolean($configLuaFreePremium)); $array_of_player_nig = array(); if(empty($errors)) From 9c327336d3a2f60fdcdd8e284afbb6c65ec94ab0 Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 21 Nov 2025 14:51:28 +0100 Subject: [PATCH 209/216] Release v1.8.5 --- CHANGELOG-1.x.md | 16 ++++++++++++++++ common.php | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG-1.x.md b/CHANGELOG-1.x.md index b8c57ce7..0d3777f8 100644 --- a/CHANGELOG-1.x.md +++ b/CHANGELOG-1.x.md @@ -1,5 +1,21 @@ # Changelog +## [1.8.5 - 21.11.2025] + +### Added +* New Setting: Account Countries Most Popular (https://github.com/slawkens/myaac/commit/946364f59d7cd01472877108ab27ec78fb28307a) + +### Changed +* Status: Write to status-error.log if there is connection error (https://github.com/slawkens/myaac/commit/780d4ccef741c1dd45a00bfc121fba9f1a175313) +* Settings: escapeHtml in values (support for html code) (https://github.com/slawkens/myaac/commit/5861efdbe900ccd35309913af0c0a5f3d4cdc1a8) +* News Page: Don't display hidden news for admin - it's confusing (https://github.com/slawkens/myaac/commit/175e97828b9a08ec3080cc8d3fb4eb3f1c08649f) +* Plugins System: Add plugin:remove + plugin:delete as alias for plugin:uninstall + plugin:activate/deactivate (https://github.com/slawkens/myaac/commit/6367054487368c92741bfd1dc7c70c52aea9ee87, https://github.com/slawkens/myaac/commit/baec6c9ebf5c342b3b2f7123427c6ba21dbb93bc) + +### Fixed +* Status: Fix $status['uptimeReadable'], was totally wrong (https://github.com/slawkens/myaac/commit/0a6d44bf21417562491aabc93543a2bc3a44b2df) +* Guilds: Detect "deletion" column in guilds show/delete (https://github.com/slawkens/myaac/commit/6775a061bebc9ff449522f0173556d4a7a44fa5e, https://github.com/slawkens/myaac/commit/603d860b56bc7418db09e206f40aa06d0682c00e) +* General: Ensure some cache folders & index.html exists (https://github.com/slawkens/myaac/commit/730a0f29124811f525207c24c06eb0d088fa3434) + ## [1.8.4 - 27.10.2025] ### Changed diff --git a/common.php b/common.php index 48945038..0049595d 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.5-dev'; +const MYAAC_VERSION = '1.8.5'; const DATABASE_VERSION = 46; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From ae5df2b7044d3a7ad9d715c45f09a64749258eff Mon Sep 17 00:00:00 2001 From: slawkens Date: Fri, 21 Nov 2025 18:08:30 +0100 Subject: [PATCH 210/216] Start v1.8.6-dev --- common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.php b/common.php index 0049595d..de7a9bfd 100644 --- a/common.php +++ b/common.php @@ -26,7 +26,7 @@ if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); const MYAAC = true; -const MYAAC_VERSION = '1.8.5'; +const MYAAC_VERSION = '1.8.6-dev'; const DATABASE_VERSION = 46; const TABLE_PREFIX = 'myaac_'; define('START_TIME', microtime(true)); From 8e6749c59984631288e8e9803819b2f0ff389761 Mon Sep 17 00:00:00 2001 From: slawkens Date: Mon, 24 Nov 2025 18:04:09 +0100 Subject: [PATCH 211/216] Hook for adding custom rules to validate new character name --- system/src/Validator.php | 10 ++++++++++ system/src/global.php | 1 + 2 files changed, 11 insertions(+) diff --git a/system/src/Validator.php b/system/src/Validator.php index ad9e3e50..7261454e 100644 --- a/system/src/Validator.php +++ b/system/src/Validator.php @@ -342,6 +342,16 @@ class Validator } } + global $hooks; + + $params = ['name' => $name, 'error' => '']; + $hooks->triggerFilter(HOOK_FILTER_VALIDATE_CHARACTER_NEW_NAME, $params); + + if (!empty($params['error'])) { + self::$lastError = $params['error']; + return false; + } + return true; } diff --git a/system/src/global.php b/system/src/global.php index 85f9476d..a140bdde 100644 --- a/system/src/global.php +++ b/system/src/global.php @@ -108,6 +108,7 @@ define('HOOK_FILTER_ROUTES', ++$i); define('HOOK_FILTER_TWIG_DISPLAY', ++$i); define('HOOK_FILTER_TWIG_RENDER', ++$i); define('HOOK_FILTER_THEME_FOOTER', ++$i); +define('HOOK_FILTER_VALIDATE_CHARACTER_NEW_NAME', ++$i); const HOOK_FIRST = HOOK_INIT; define('HOOK_LAST', $i); From 3011b969a45e4e3149adbfccc0209c0fe3fd5eae Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 30 Nov 2025 17:05:14 +0100 Subject: [PATCH 212/216] Add php 8.5 to cypress workflow --- .github/workflows/cypress.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index e93257f1..4dd8e9dd 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -22,7 +22,7 @@ jobs: strategy: fail-fast: false matrix: - php-versions: [ '8.1', '8.2', '8.3', '8.4' ] + php-versions: [ '8.1', '8.2', '8.3', '8.4', '8.5' ] ots: ['tfs-1.4', 'canary-3.1.2'] # TODO: add 'tfs-master' (actually doesn't work cause AAC doesn't support reading .env configuration) name: Cypress (PHP ${{ matrix.php-versions }}, ${{ matrix.ots }}) steps: From fd74f01291d0e9cdb92ee1b95021c9d7b591ad7c Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 9 Dec 2025 22:04:21 +0100 Subject: [PATCH 213/216] Fix typo $up -> $down, migration was failing due that --- system/migrations/7.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/migrations/7.php b/system/migrations/7.php index a96ed7c9..5a6a7925 100644 --- a/system/migrations/7.php +++ b/system/migrations/7.php @@ -9,7 +9,7 @@ $up = function () use ($db) { } }; -$up = function () use ($db) { +$down = function () use ($db) { if (!$db->hasColumn(TABLE_PREFIX . 'screenshots', 'name')) { $db->addColumn(TABLE_PREFIX . 'screenshots', 'name', 'VARCHAR(30) NOT NULL'); } From c86257e6dacbad773aa09c0958eeaa106a967f2d Mon Sep 17 00:00:00 2001 From: slawkens Date: Sat, 13 Dec 2025 21:19:00 +0100 Subject: [PATCH 214/216] Highscores: Fix ordering by different skills Adjust order by desc: skill_tries, manaspent, experience --- system/pages/highscores.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/system/pages/highscores.php b/system/pages/highscores.php index cec95d15..79d4feee 100644 --- a/system/pages/highscores.php +++ b/system/pages/highscores.php @@ -176,7 +176,9 @@ if (empty($highscores)) { POT::SKILL_FISH => 'skill_fishing', ); - $query->addSelect($skill_ids[$skill] . ' as value'); + $query + ->addSelect($skill_ids[$skill] . ' as value') + ->orderByDesc($skill_ids[$skill] . '_tries'); } else { $query ->join('player_skills', 'player_skills.player_id', '=', 'players.id') @@ -198,11 +200,11 @@ if (empty($highscores)) { if ($skill == POT::SKILL__MAGLEVEL) { $query ->addSelect('players.maglevel as value', 'players.maglevel') - ->orderBy('manaspent'); + ->orderByDesc('manaspent'); } else { // level $query ->addSelect('players.level as value', 'players.experience') - ->orderBy('experience'); + ->orderByDesc('experience'); $list = 'experience'; } } From 18a1178e4b93607a350259679e0366cb83fb4126 Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 14 Dec 2025 10:20:59 +0100 Subject: [PATCH 215/216] Fix exception show on first install, when there is no vendor Before it displayed 500 white page, now it display the exception --- common.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common.php b/common.php index de7a9bfd..fdfd35bd 100644 --- a/common.php +++ b/common.php @@ -148,16 +148,16 @@ if(!IS_CLI) { /** @var array $config */ ini_set('log_errors', 1); -if(@$config['env'] === 'dev' || defined('MYAAC_INSTALL')) { - ini_set('display_errors', 1); - ini_set('display_startup_errors', 1); - error_reporting(E_ALL); -} -else { +if(isset($config['env']) && $config['env'] !== 'dev' && !defined('MYAAC_INSTALL')) { ini_set('display_errors', 0); ini_set('display_startup_errors', 0); error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT); } +else { + ini_set('display_errors', 1); + ini_set('display_startup_errors', 1); + error_reporting(E_ALL); +} $autoloadFile = VENDOR . 'autoload.php'; if (!is_file($autoloadFile)) { From 9ed06782e67772826d927ad847a077b99df5060d Mon Sep 17 00:00:00 2001 From: slawkens Date: Sun, 14 Dec 2025 10:21:23 +0100 Subject: [PATCH 216/216] Ini set html_errors = 0, to show html code in exceptions --- common.php | 1 + 1 file changed, 1 insertion(+) diff --git a/common.php b/common.php index fdfd35bd..c93cce36 100644 --- a/common.php +++ b/common.php @@ -154,6 +154,7 @@ if(isset($config['env']) && $config['env'] !== 'dev' && !defined('MYAAC_INSTALL' error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT); } else { + ini_set('html_errors', 0); ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL);