Compare commits

..

3 Commits

Author SHA1 Message Date
slawkens
7c49c16215 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.
2025-06-19 16:26:16 +02:00
slawkens
1c6bb2eb8d 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.
2025-06-19 16:18:55 +02:00
slawkens
e91b44f036 Check plugins versions from plugins.my-aac.org/api 2025-06-18 23:16:10 +02:00
50 changed files with 504 additions and 890 deletions

View File

@@ -1,82 +1,5 @@
# Changelog # 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
* 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
* 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
* 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] ## [1.6.1 - 11.06.2025]
### Fixed ### Fixed

View File

@@ -26,6 +26,7 @@ if (setting('core.account_country'))
$nameOrNumberColumn = getAccountIdentityColumn(); $nameOrNumberColumn = getAccountIdentityColumn();
$hasSecretColumn = $db->hasColumn('accounts', 'secret'); $hasSecretColumn = $db->hasColumn('accounts', 'secret');
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
$hasTypeColumn = $db->hasColumn('accounts', 'type'); $hasTypeColumn = $db->hasColumn('accounts', 'type');
$hasGroupColumn = $db->hasColumn('accounts', 'group_id'); $hasGroupColumn = $db->hasColumn('accounts', 'group_id');
@@ -136,17 +137,10 @@ else if (isset($_REQUEST['search'])) {
$errors['email'] = Validator::getLastError(); $errors['email'] = Validator::getLastError();
//tibia coins //tibia coins
if (HAS_ACCOUNT_COINS) { if ($hasCoinsColumn) {
$t_coins = $_POST['t_coins']; $t_coins = $_POST['t_coins'];
verify_number($t_coins, 'Tibia coins', 12); verify_number($t_coins, 'Tibia coins', 12);
} }
// transferable tibia coins
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);
}
// prem days // prem days
$p_days = (int)$_POST['p_days']; $p_days = (int)$_POST['p_days'];
verify_number($p_days, 'Prem days', 11); verify_number($p_days, 'Prem days', 11);
@@ -191,18 +185,12 @@ else if (isset($_REQUEST['search'])) {
if ($hasSecretColumn) { if ($hasSecretColumn) {
$account->setCustomField('secret', $secret); $account->setCustomField('secret', $secret);
} }
$account->setCustomField('key', $key); $account->setCustomField('key', $key);
$account->setEMail($email); $account->setEMail($email);
if ($hasCoinsColumn) {
if (HAS_ACCOUNT_COINS) {
$account->setCustomField('coins', $t_coins); $account->setCustomField('coins', $t_coins);
} }
if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS) {
$account->setCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN, $t_coins_transferable);
}
$lastDay = 0; $lastDay = 0;
if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) { if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
$lastDay = time(); $lastDay = time();
@@ -235,6 +223,9 @@ else if (isset($_REQUEST['search'])) {
$password = encrypt($password); $password = encrypt($password);
$account->setPassword($password); $account->setPassword($password);
if (USE_ACCOUNT_SALT)
$account->setCustomField('salt', $salt);
} }
$account->save(); $account->save();
@@ -404,18 +395,12 @@ else if (isset($_REQUEST['search'])) {
<label for="email">Email:</label><?php echo (setting('core.mail_enabled') ? ' (<a href="' . ADMIN_URL . '?p=mailer&mail_to=' . $account->getEMail() . '">Send Mail</a>)' : ''); ?> <label for="email">Email:</label><?php echo (setting('core.mail_enabled') ? ' (<a href="' . ADMIN_URL . '?p=mailer&mail_to=' . $account->getEMail() . '">Send Mail</a>)' : ''); ?>
<input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/> <input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/>
</div> </div>
<?php if (HAS_ACCOUNT_COINS): ?> <?php if ($hasCoinsColumn): ?>
<div class="col-12 col-sm-12 col-lg-6"> <div class="col-12 col-sm-12 col-lg-6">
<label for="t_coins">Tibia Coins:</label> <label for="t_coins">Tibia Coins:</label>
<input type="text" class="form-control" id="t_coins" name="t_coins" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField('coins') ?>"/> <input type="text" class="form-control" id="t_coins" name="t_coins" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField('coins') ?>"/>
</div> </div>
<?php endif; ?> <?php endif; ?>
<?php if (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS): ?>
<div class="col-12 col-sm-12 col-lg-6">
<label for="t_coins_transferable">Transferable Tibia Coins:</label>
<input type="text" class="form-control" id="t_coins_transferable" name="t_coins_transferable" autocomplete="off" maxlength="11" value="<?php echo $account->getCustomField(ACCOUNT_COINS_TRANSFERABLE_COLUMN) ?>"/>
</div>
<?php endif; ?>
<div class="col-12 col-sm-12 col-lg-6"> <div class="col-12 col-sm-12 col-lg-6">
<label for="p_days">Premium Days:</label> <label for="p_days">Premium Days:</label>
<input type="text" class="form-control" id="p_days" name="p_days" autocomplete="off" maxlength="11" value="<?php echo $account->getPremDays(); ?>"/> <input type="text" class="form-control" id="p_days" name="p_days" autocomplete="off" maxlength="11" value="<?php echo $account->getPremDays(); ?>"/>

View File

@@ -25,10 +25,9 @@ if (!setting('core.mail_enabled')) {
return; return;
} }
$mail_to = isset($_REQUEST['mail_to']) ? stripslashes(trim($_REQUEST['mail_to'])) : null; $mail_to = isset($_POST['mail_to']) ? stripslashes(trim($_POST['mail_to'])) : null;
$mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null; $mail_subject = isset($_POST['mail_subject']) ? stripslashes($_POST['mail_subject']) : null;
$mail_content = isset($_POST['mail_content']) ? stripslashes($_POST['mail_content']) : 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 (isset($_POST['submit'])) {
if (empty($mail_subject)) { if (empty($mail_subject)) {
@@ -59,14 +58,14 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) {
$success = 0; $success = 0;
$failed = 0; $failed = 0;
$query = Account::where('email', '!=', ''); $add = '';
if (setting('core.account_mail_verify')) {
if ($mail_verified_only) { note('Note: Sending only to users with verified E-Mail.');
info('Note: Sending only to users with verified E-Mail.'); $add = ' AND `email_verified` = 1';
$query->where('email_verified', 1);
} }
foreach ($query->get(['email']) as $email) { $query = Account::where('email', '!=', '')->get(['email']);
foreach ($query as $email) {
if (_mail($email->email, $mail_subject, $mail_content)) { if (_mail($email->email, $mail_subject, $mail_content)) {
$success++; $success++;
} }
@@ -85,6 +84,5 @@ if (!empty($mail_content) && !empty($mail_subject) && empty($mail_to)) {
$twig->display('admin.mailer.html.twig', [ $twig->display('admin.mailer.html.twig', [
'mail_to' => $mail_to, 'mail_to' => $mail_to,
'mail_subject' => $mail_subject, 'mail_subject' => $mail_subject,
'mail_content' => $mail_content, 'mail_content' => $mail_content
'mail_verified_only' => $mail_verified_only,
]); ]);

View File

@@ -18,6 +18,7 @@ $title = 'Mass Account Actions';
csrfProtect(); csrfProtect();
$hasCoinsColumn = $db->hasColumn('accounts', 'coins');
$hasPointsColumn = $db->hasColumn('accounts', 'premium_points'); $hasPointsColumn = $db->hasColumn('accounts', 'premium_points');
$freePremium = $config['lua']['freePremium']; $freePremium = $config['lua']['freePremium'];
@@ -39,7 +40,9 @@ function admin_give_points($points)
function admin_give_coins($coins) function admin_give_coins($coins)
{ {
if (!HAS_ACCOUNT_COINS) { global $hasCoinsColumn;
if (!$hasCoinsColumn) {
displayMessage('Coins not supported.'); displayMessage('Coins not supported.');
return; return;
} }
@@ -164,19 +167,19 @@ if (!empty(ACTION) && isRequestMethod('post')) {
} }
else { else {
$twig->display('admin.tools.account.html.twig', array( $twig->display('admin.tools.account.html.twig', array(
'hasCoinsColumn' => HAS_ACCOUNT_COINS, 'hasCoinsColumn' => $hasCoinsColumn,
'hasPointsColumn' => $hasPointsColumn, 'hasPointsColumn' => $hasPointsColumn,
'freePremium' => $freePremium, 'freePremium' => $freePremium,
)); ));
} }
function displayMessage($message, $success = false) { function displayMessage($message, $success = false) {
global $twig, $hasPointsColumn, $freePremium; global $twig, $hasCoinsColumn, $hasPointsColumn, $freePremium;
$success ? success($message): error($message); $success ? success($message): error($message);
$twig->display('admin.tools.account.html.twig', array( $twig->display('admin.tools.account.html.twig', array(
'hasCoinsColumn' => HAS_ACCOUNT_COINS, 'hasCoinsColumn' => $hasCoinsColumn,
'hasPointsColumn' => $hasPointsColumn, 'hasPointsColumn' => $hasPointsColumn,
'freePremium' => $freePremium, 'freePremium' => $freePremium,
)); ));

View File

@@ -6,7 +6,7 @@ defined('MYAAC') or die('Direct access not allowed!');
$coins = 0; $coins = 0;
if (HAS_ACCOUNT_COINS) { if ($db->hasColumn('accounts', 'coins')) {
$whatToGet = ['id', 'coins']; $whatToGet = ['id', 'coins'];
if (USE_ACCOUNT_NAME) { if (USE_ACCOUNT_NAME) {
$whatToGet[] = 'name'; $whatToGet[] = 'name';

View File

@@ -26,7 +26,7 @@
if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.'); if (version_compare(phpversion(), '8.1', '<')) die('PHP version 8.1 or higher is required.');
const MYAAC = true; const MYAAC = true;
const MYAAC_VERSION = '1.8.2-dev'; const MYAAC_VERSION = '1.6.1';
const DATABASE_VERSION = 45; const DATABASE_VERSION = 45;
const TABLE_PREFIX = 'myaac_'; const TABLE_PREFIX = 'myaac_';
define('START_TIME', microtime(true)); define('START_TIME', microtime(true));

View File

@@ -162,6 +162,15 @@ 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']; $title_full = (isset($title) ? $title . ' - ' : '') . $config['lua']['serverName'];
require $template_path . '/' . $template_index; require $template_path . '/' . $template_index;

View File

@@ -42,9 +42,10 @@ if(!$error) {
$configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true); $configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true);
$configToSave['database_auto_migrate'] = true; $configToSave['database_auto_migrate'] = true;
if(!$error) {
$content = ''; $content = '';
$saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content); $saved = Settings::saveConfig($configToSave, BASE . 'config.local.php', $content);
if ($saved || file_exists(BASE . 'config.local.php')) { if ($saved) {
success($locale['step_database_config_saved']); success($locale['step_database_config_saved']);
$_SESSION['saved'] = true; $_SESSION['saved'] = true;
@@ -73,15 +74,15 @@ if(!$error) {
} }
} }
} else { } else {
$error = true;
$_SESSION['config_content'] = $content; $_SESSION['config_content'] = $content;
unset($_SESSION['saved']); unset($_SESSION['saved']);
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.local.php</b>', $locale['step_database_error_file']); $locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.php</b>', $locale['step_database_error_file']);
error($locale['step_database_error_file'] . '<br/> error($locale['step_database_error_file'] . '<br/>
<textarea cols="70" rows="10">' . $content . '</textarea>'); <textarea cols="70" rows="10">' . $content . '</textarea>');
} }
} }
}
?> ?>
<div class="text-center m-3"> <div class="text-center m-3">

13
package-lock.json generated
View File

@@ -976,16 +976,15 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.4", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0", "es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
}, },
"engines": { "engines": {
@@ -2085,9 +2084,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/tmp": { "node_modules/tmp": {
"version": "0.2.4", "version": "0.2.3",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.4.tgz", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
"integrity": "sha512-UdiSoX6ypifLmrfQ/XfiawN6hkjSBpCjhKxxZcWlUUmoXLaCKQU0bx4HF/tdDK2uzRuchf1txGvrWBzYREssoQ==", "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {

View File

@@ -28,9 +28,10 @@ parameters:
- '#Variable \$guild might not be defined#' - '#Variable \$guild might not be defined#'
- '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#' - '#Variable \$[a-zA-Z0-9\\_]+ might not be defined#'
# Eloquent models # 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 static method [a-zA-Z0-9\\_]+::[a-zA-Z0-9\\_]+\(\)#'
- '#Call to an undefined method object::toArray\(\)#'
# system/pages/highscores.php # 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::\$online_status#'
- '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$vocation_name#' - '#Access to an undefined property Illuminate\\Database\\Eloquent\\Model::\$vocation_name#'
- -

View File

@@ -512,13 +512,6 @@ function template_place_holder($type): string
} }
elseif ($type === 'body_start') { elseif ($type === 'body_start') {
$ret .= $twig->render('browsehappy.html.twig'); $ret .= $twig->render('browsehappy.html.twig');
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') { elseif($type === 'body_end') {
$ret .= template_ga_code(); $ret .= template_ga_code();
@@ -774,10 +767,6 @@ function formatExperience($exp, $color = true)
return $ret; return $ret;
} }
function getExperienceForLevel($level): float|int {
return ( 50 / 3 ) * pow( $level, 3 ) - ( 100 * pow( $level, 2 ) ) + ( ( 850 / 3 ) * $level ) - 200;
}
function get_locales() function get_locales()
{ {
$ret = array(); $ret = array();
@@ -993,12 +982,11 @@ function load_config_lua($filename)
foreach($lines as $ln => $line) foreach($lines as $ln => $line)
{ {
$line = trim($line); $line = trim($line);
if(isset($line[0]) && ($line[0] === '{' || $line[0] === '}')) { if(@$line[0] === '{' || @$line[0] === '}') {
// arrays are not supported yet // arrays are not supported yet
// just ignore the error // just ignore the error
continue; continue;
} }
$tmp_exp = explode('=', $line, 2); $tmp_exp = explode('=', $line, 2);
if(str_contains($line, 'dofile')) { if(str_contains($line, 'dofile')) {
$delimiter = '"'; $delimiter = '"';
@@ -1228,8 +1216,7 @@ function setting($key)
return $settings[$key[0]] = $key[1]; return $settings[$key[0]] = $key[1];
} }
$ret = $settings[$key]; return $settings[$key]['value'];
return isset($ret) ? $ret['value'] : null;
} }
function clearCache() function clearCache()
@@ -1276,17 +1263,20 @@ function clearCache()
global $db; global $db;
$db->setClearCacheAfter(true); $db->setClearCacheAfter(true);
}
if (function_exists('apcu_clear_cache')) { if (function_exists('apcu_clear_cache')) {
apcu_clear_cache(); apcu_clear_cache();
} }
}
deleteDirectory(CACHE . 'signatures', ['index.html'], true); deleteDirectory(CACHE . 'signatures', ['index.html'], true);
deleteDirectory(CACHE . 'twig', ['index.html'], true); deleteDirectory(CACHE . 'twig', ['index.html'], true);
deleteDirectory(CACHE . 'plugins', ['index.html'], true); deleteDirectory(CACHE . 'plugins', ['index.html'], true);
deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true); deleteDirectory(CACHE, ['signatures', 'twig', 'plugins', 'index.html', 'persistent'], true);
// routes cache
clearRouteCache();
global $hooks; global $hooks;
$hooks->trigger(HOOK_CACHE_CLEAR, ['cache' => Cache::getInstance()]); $hooks->trigger(HOOK_CACHE_CLEAR, ['cache' => Cache::getInstance()]);

View File

@@ -144,15 +144,6 @@ $ots = POT::getInstance();
$eloquentConnection = null; $eloquentConnection = null;
require_once SYSTEM . 'database.php'; 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', $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');
$twig->addGlobal('logged', false); $twig->addGlobal('logged', false);
$twig->addGlobal('account_logged', new \OTS_Account()); $twig->addGlobal('account_logged', new \OTS_Account());
@@ -197,6 +188,10 @@ if($settingsItemImagesURL[strlen($settingsItemImagesURL) - 1] !== '/') {
setting(['core.item_images_url', $settingsItemImagesURL . '/']); 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) { $towns = Cache::remember('towns', 10 * 60, function () use ($db) {
if ($db->hasTable('towns') && Town::count() > 0) { if ($db->hasTable('towns') && Town::count() > 0) {
return Town::orderBy('id', 'ASC')->pluck('name', 'id')->toArray(); return Town::orderBy('id', 'ASC')->pluck('name', 'id')->toArray();

View File

@@ -473,6 +473,9 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
public function isPremium() public function isPremium()
{ {
global $config;
if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true;
if(isset($this->data['premium_ends_at'])) { if(isset($this->data['premium_ends_at'])) {
return $this->data['premium_ends_at'] > time(); return $this->data['premium_ends_at'] > time();
} }

View File

@@ -8,7 +8,7 @@
* @link https://my-aac.org * @link https://my-aac.org
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Not Found'; $title = '404 Not Found';
header('HTTP/1.0 404 Not Found'); header('HTTP/1.0 404 Not Found');
?> ?>

View File

@@ -8,7 +8,7 @@
* @link https://my-aac.org * @link https://my-aac.org
*/ */
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Method Not Allowed'; $title = '405 Method Not Allowed';
header('HTTP/1.0 405 Method Not Allowed'); header('HTTP/1.0 405 Method Not Allowed');
?> ?>

View File

@@ -227,15 +227,10 @@ if($save)
} }
$accountDefaultCoins = setting('core.account_coins'); $accountDefaultCoins = setting('core.account_coins');
if(HAS_ACCOUNT_COINS && $accountDefaultCoins > 0) { if($db->hasColumn('accounts', 'coins') && $accountDefaultCoins > 0) {
$new_account->setCustomField('coins', $accountDefaultCoins); $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; $tmp_account = $email;
if (!config('account_login_by_email')) { if (!config('account_login_by_email')) {
$tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id); $tmp_account = (USE_ACCOUNT_NAME ? $account_name : $account_id);

View File

@@ -23,12 +23,6 @@ if(!Validator::guildName($guild_name)) {
$errors[] = Validator::getLastError(); $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)) { if(empty($errors)) {
$guild = new OTS_Guild(); $guild = new OTS_Guild();
$guild->find($guild_name); $guild->find($guild_name);
@@ -64,7 +58,7 @@ if(empty($errors)) {
} }
} }
if(empty($errors) && !$guild_vice) { if(!$guild_vice) {
$errors[] = 'You are not a leader or vice leader of guild <b>'.$guild_name.'</b>.'.$level_in_guild; $errors[] = 'You are not a leader or vice leader of guild <b>'.$guild_name.'</b>.'.$level_in_guild;
} }
@@ -90,7 +84,6 @@ if(isset($_POST['todo']) && $_POST['todo'] == 'save') {
} }
} }
} }
if(empty($errors)) { if(empty($errors)) {
include(SYSTEM . 'libs/pot/InvitesDriver.php'); include(SYSTEM . 'libs/pot/InvitesDriver.php');
new InvitesDriver($guild); new InvitesDriver($guild);
@@ -111,7 +104,6 @@ if(!empty($errors)) {
else { else {
if(isset($_POST['todo']) && $_POST['todo'] == 'save') { if(isset($_POST['todo']) && $_POST['todo'] == 'save') {
$guild->invite($player); $guild->invite($player);
$twig->display('success.html.twig', array( $twig->display('success.html.twig', array(
'title' => 'Invite player', 'title' => 'Invite player',
'description' => 'Player with name <b>' . $player->getName() . '</b> has been invited to your guild.', 'description' => 'Player with name <b>' . $player->getName() . '</b> has been invited to your guild.',

View File

@@ -121,27 +121,24 @@ foreach($rank_list as $rank)
} }
} }
$invited_list = [];
$show_accept_invite = 0;
if ($db->hasTableAndColumns('guild_invites', ['player_id'])) {
include(SYSTEM . 'libs/pot/InvitesDriver.php'); include(SYSTEM . 'libs/pot/InvitesDriver.php');
new InvitesDriver($guild); new InvitesDriver($guild);
$invited_list = $guild->listInvites(); $invited_list = $guild->listInvites();
$show_accept_invite = 0;
if($logged && count($invited_list) > 0) { if($logged && count($invited_list) > 0)
foreach($invited_list as $invited_player) { {
if(count($account_players) > 0) { foreach($invited_list as $invited_player)
foreach($account_players as $player_from_acc) { {
if($player_from_acc->isLoaded() && $invited_player->isLoaded() && $player_from_acc->getName() == $invited_player->getName()) { 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++; $show_accept_invite++;
} }
} }
} }
} }
}
}
$useGuildNick = $db->hasTable('guild_members') || $db->hasTable('guild_membership') || $db->hasColumn('players', 'guildnick'); $useGuildNick = $db->hasTable('guild_members') || $db->hasTable('guild_membership') || $db->hasColumn('players', 'guildnick');

View File

@@ -123,11 +123,17 @@ if($db->hasColumn('players', 'promotion'))
$promotion = ',players.promotion'; $promotion = ',players.promotion';
$outfit_addons = false; $outfit_addons = false;
$outfit = '';
$settingHighscoresOutfit = setting('core.highscores_outfit');
if($settingHighscoresOutfit) {
$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype'; $outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype';
if($db->hasColumn('players', 'lookaddons')) { if($db->hasColumn('players', 'lookaddons')) {
$outfit .= ', lookaddons'; $outfit .= ', lookaddons';
$outfit_addons = true; $outfit_addons = true;
} }
}
$configHighscoresPerPage = setting('core.highscores_per_page'); $configHighscoresPerPage = setting('core.highscores_per_page');
$limit = $configHighscoresPerPage + 1; $limit = $configHighscoresPerPage + 1;
@@ -140,24 +146,17 @@ $cache = Cache::getInstance();
if ($cache->enabled() && $highscoresTTL > 0) { if ($cache->enabled() && $highscoresTTL > 0) {
$tmp = ''; $tmp = '';
if ($cache->fetch($cacheKey, $tmp)) { if ($cache->fetch($cacheKey, $tmp)) {
$data = unserialize($tmp); $highscores = unserialize($tmp);
$totalResults = $data['totalResults'];
$highscores = $data['highscores'];
$updatedAt = $data['updatedAt'];
$needReCache = false; $needReCache = false;
} }
} }
$offset = ($page - 1) * $configHighscoresPerPage; $offset = ($page - 1) * $configHighscoresPerPage;
$query->withOnlineStatus() $query->join('accounts', 'accounts.id', '=', 'players.account_id')
->withOnlineStatus()
->whereNotIn('players.id', setting('core.highscores_ids_hidden')) ->whereNotIn('players.id', setting('core.highscores_ids_hidden'))
->notDeleted() ->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) ->limit($limit)
->offset($offset) ->offset($offset)
->selectRaw('accounts.country, players.id, players.name, players.account_id, players.level, players.vocation' . $outfit . $promotion) ->selectRaw('accounts.country, players.id, players.name, players.account_id, players.level, players.vocation' . $outfit . $promotion)
@@ -216,24 +215,17 @@ if (empty($highscores)) {
return $tmp; return $tmp;
})->toArray(); })->toArray();
$updatedAt = time();
$totalResults = $totalResultsQuery->count();
} }
if ($highscoresTTL > 0 && $cache->enabled() && $needReCache) { if ($highscoresTTL > 0 && $cache->enabled() && $needReCache) {
$cache->set($cacheKey, serialize( $cache->set($cacheKey, serialize($highscores), $highscoresTTL * 60);
[
'totalResults' => $totalResults,
'highscores' => $highscores,
'updatedAt' => $updatedAt,
]
), $highscoresTTL * 60);
} }
$show_link_to_next_page = false; $show_link_to_next_page = false;
$i = 0; $i = 0;
$settingHighscoresVocation = setting('core.highscores_vocation');
foreach($highscores as $id => &$player) foreach($highscores as $id => &$player)
{ {
if(++$i <= $configHighscoresPerPage) if(++$i <= $configHighscoresPerPage)
@@ -247,23 +239,11 @@ foreach($highscores as $id => &$player)
$player['link'] = getPlayerLink($player['name'], false); $player['link'] = getPlayerLink($player['name'], false);
$player['flag'] = getFlagImage($player['country']); $player['flag'] = getFlagImage($player['country']);
if($settingHighscoresOutfit) {
$player['outfit'] = '<img style="position:absolute;margin-top:' . (in_array($player['looktype'], setting('core.outfit_images_wrong_looktypes')) ? '-15px;margin-left:5px' : '-45px;margin-left:-25px') . ';" src="' . $player['outfit_url'] . '" alt="" />'; $player['outfit'] = '<img style="position:absolute;margin-top:' . (in_array($player['looktype'], setting('core.outfit_images_wrong_looktypes')) ? '-15px;margin-left:5px' : '-45px;margin-left:-25px') . ';" src="' . $player['outfit_url'] . '" alt="" />';
if ($skill != POT::SKILL__LEVEL) {
if (isset($lastValue) && $lastValue == $player['value']) {
$player['rank'] = $lastRank;
} }
else {
$player['rank'] = $offset + $i; $player['rank'] = $offset + $i;
} }
$lastRank = $player['rank'] ;
$lastValue = $player['value'];
}
else {
$player['rank'] = $offset + $i;
}
}
else { else {
unset($highscores[$id]); unset($highscores[$id]);
$show_link_to_next_page = true; $show_link_to_next_page = true;
@@ -283,8 +263,6 @@ if($show_link_to_next_page) {
$linkNextPage = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/' . ($page + 1); $linkNextPage = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/' . ($page + 1);
} }
$baseLink = getLink('highscores') . '/' . $list . ($vocation !== 'all' ? '/' . $vocation : '') . '/';
$types = array( $types = array(
'experience' => 'Experience', 'experience' => 'Experience',
'magic' => 'Magic', 'magic' => 'Magic',
@@ -319,8 +297,4 @@ $twig->display('highscores.html.twig', [
'types' => $types, 'types' => $types,
'linkPreviousPage' => $linkPreviousPage, 'linkPreviousPage' => $linkPreviousPage,
'linkNextPage' => $linkNextPage, 'linkNextPage' => $linkNextPage,
'totalResults' => $totalResults,
'page' => $page,
'baseLink' => $baseLink,
'updatedAt' => $updatedAt,
]); ]);

View File

@@ -9,21 +9,18 @@
* @link https://my-aac.org * @link https://my-aac.org
*/ */
use MyAAC\Cache\Cache;
use MyAAC\Models\ServerConfig; use MyAAC\Models\ServerConfig;
use MyAAC\Models\ServerRecord; use MyAAC\Models\ServerRecord;
defined('MYAAC') or die('Direct access not allowed!'); defined('MYAAC') or die('Direct access not allowed!');
$title = 'Who is online?'; $title = 'Who is online?';
if (setting('core.account_country')) { if (setting('core.account_country'))
require SYSTEM . 'countries.conf.php'; require SYSTEM . 'countries.conf.php';
}
$promotion = ''; $promotion = '';
if($db->hasColumn('players', 'promotion')) { if($db->hasColumn('players', 'promotion'))
$promotion = '`promotion`,'; $promotion = '`promotion`,';
}
$order = $_GET['order'] ?? 'name_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'])) { if(!in_array($order, ['country_asc', 'country_desc', 'name_asc', 'name_desc', 'level_asc', 'level_desc', 'vocation_asc', 'vocation_desc'])) {
@@ -33,7 +30,6 @@ else if($order == 'vocation_asc' || $order == 'vocation_desc') {
$order = $promotion . 'vocation_' . (str_contains($order, 'asc') ? 'asc' : 'desc'); $order = $promotion . 'vocation_' . (str_contains($order, 'asc') ? 'asc' : 'desc');
} }
$cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60, function() use($db, $promotion, $order) {
$orderExplode = explode('_', $order); $orderExplode = explode('_', $order);
$orderSql = $orderExplode[0] . ' ' . $orderExplode[1]; $orderSql = $orderExplode[0] . ' ' . $orderExplode[1];
@@ -48,74 +44,72 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60
} }
$outfit_addons = false; $outfit_addons = false;
$outfit = '';
if (setting('core.online_outfit')) {
$outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype'; $outfit = ', lookbody, lookfeet, lookhead, looklegs, looktype';
if($db->hasColumn('players', 'lookaddons')) { if($db->hasColumn('players', 'lookaddons')) {
$outfit .= ', lookaddons'; $outfit .= ', lookaddons';
$outfit_addons = true; $outfit_addons = true;
} }
}
$vocations = array_map(function ($name) { $vocs = [];
return 0; if (setting('core.online_vocations')) {
}, setting('core.vocations')); foreach($config['vocations'] as $id => $name) {
$vocs[$id] = 0;
}
}
if($db->hasTable('players_online')) // tfs 1.0 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); $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 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); $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);
$settingVocations = setting('core.vocations'); $players_data = [];
$settingVocationsAmount = setting('core.vocations_amount'); $players = 0;
$data = '';
$players = [];
foreach($playersOnline as $player) { foreach($playersOnline as $player) {
$skull = ''; $skull = '';
if($player['skulltime'] > 0) { if (setting('core.online_skulls'))
if($player['skull'] == 3) { {
if($player['skulltime'] > 0)
{
if($player['skull'] == 3)
$skull = ' <img style="border: 0;" src="images/white_skull.gif"/>'; $skull = ' <img style="border: 0;" src="images/white_skull.gif"/>';
} elseif($player['skull'] == 4)
elseif($player['skull'] == 4) {
$skull = ' <img style="border: 0;" src="images/red_skull.gif"/>'; $skull = ' <img style="border: 0;" src="images/red_skull.gif"/>';
} elseif($player['skull'] == 5)
elseif($player['skull'] == 5) {
$skull = ' <img style="border: 0;" src="images/black_skull.gif"/>'; $skull = ' <img style="border: 0;" src="images/black_skull.gif"/>';
} }
} }
if(isset($player['promotion'])) { if(isset($player['promotion'])) {
if((int)$player['promotion'] > 0) if((int)$player['promotion'] > 0)
$player['vocation'] += ($player['promotion'] * $settingVocationsAmount); $player['vocation'] += ($player['promotion'] * $config['vocations_amount']);
} }
$players[] = array( $players_data[] = array(
'name' => getPlayerLink($player['name']), 'name' => getPlayerLink($player['name']),
'player' => $player, 'player' => $player,
'level' => $player['level'], 'level' => $player['level'],
'vocation' => $settingVocations[$player['vocation']], 'vocation' => $config['vocations'][$player['vocation']],
'skull' => $skull, 'country_image' => setting('core.account_country') ? getFlagImage($player['country']) : null,
'country_image' => getFlagImage($player['country']), '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
'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'])]++; if (setting('core.online_vocations')) {
$vocs[($player['vocation'] > $config['vocations_amount'] ? $player['vocation'] - $config['vocations_amount'] : $player['vocation'])]++;
}
} }
$record = ''; $record = '';
if(count($players) > 0) { if(count($players_data) > 0) {
if( setting('core.online_record')) { if( setting('core.online_record')) {
$result = null; $result = null;
$timestamp = false; $timestamp = false;
if($db->hasTable('server_record')) { if($db->hasTable('server_record')) {
$timestamp = $db->hasColumn('server_record', 'timestamp'); $timestamp = true;
$serverRecordQuery = ServerRecord::query(); $result = ServerRecord::where('world_id', $config['lua']['worldId'])->orderByDesc('record')->first()->toArray();
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 } else if($db->hasTable('server_config')) { // tfs 1.0
$row = ServerConfig::where('config', 'players_record')->first(); $row = ServerConfig::where('config', 'players_record')->first();
if ($row) { if ($row) {
@@ -129,20 +123,13 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60
} }
} }
return [
'players' => $players,
'record' => $record,
'vocations' => $vocations,
];
});
$twig->display('online.html.twig', array( $twig->display('online.html.twig', array(
'players' => $cached['players'], 'players' => $players_data,
'record' => $cached['record'], 'record' => $record,
'vocations' => $cached['vocations'], 'vocs' => $vocs,
'vocs' => $cached['vocations'], // deprecated, to be removed
'order' => $order, 'order' => $order,
)); ));
//search bar //search bar
$twig->display('characters.form.html.twig'); $twig->display('characters.form.html.twig');
?>

View File

@@ -94,30 +94,19 @@ $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r)
$routesFinal[] = ['*', $page, '__database__/' . $page, 100]; $routesFinal[] = ['*', $page, '__database__/' . $page, 100];
} }
$routes = require SYSTEM . 'routes.php';
Plugins::clearWarnings(); Plugins::clearWarnings();
foreach (Plugins::getRoutes() as $route) {
foreach (Plugins::getRoutes() as $pluginRoute) { $routesFinal[] = [$route[0], $route[1], $route[2], $route[3] ?? 1000];
$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 '<pre>'; echo '<pre>';
var_dump($pluginRoute[1], $pluginRoute[3], $pluginRoute[2]); var_dump($route[1], $route[3], $route[2]);
echo '/<pre>'; echo '/<pre>';
*/ */
} }
$routes = require SYSTEM . 'routes.php';
foreach ($routes as $route) { 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])) { if (!is_file(BASE . 'system/pages/' . $route[2])) {
continue; continue;
} }

View File

@@ -28,15 +28,6 @@ if (!IS_CLI) {
$siteURL = $serverUrl . $baseDir; $siteURL = $serverUrl . $baseDir;
} }
$donateColumnOptions = [
'premium_points' => 'Premium Points',
'coins' => 'Coins',
];
if (defined('HAS_ACCOUNT_COINS_TRANSFERABLE') && (HAS_ACCOUNT_COINS_TRANSFERABLE || HAS_ACCOUNT_TRANSFERABLE_COINS)) {
$donateColumnOptions[ACCOUNT_COINS_TRANSFERABLE_COLUMN] = 'Coins Transferable';
}
return [ return [
'name' => 'MyAAC', 'name' => 'MyAAC',
'settings' => [ 'settings' => [
@@ -703,14 +694,7 @@ Sent by MyAAC,<br/>
'name' => 'Default Account Coins', 'name' => 'Default Account Coins',
'type' => 'number', 'type' => 'number',
'desc' => 'Default coins on new account', 'desc' => 'Default coins on new account',
'hidden' => ($db && !HAS_ACCOUNT_COINS), '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' => ($db && !HAS_ACCOUNT_COINS_TRANSFERABLE && !HAS_ACCOUNT_TRANSFERABLE_COINS),
'default' => 0, 'default' => 0,
], ],
'account_mail_change' => [ 'account_mail_change' => [
@@ -1078,12 +1062,6 @@ Sent by MyAAC,<br/>
'desc' => 'How often to update highscores from database in minutes. Too low may slow down your website.<br/>0 to disable.', 'desc' => 'How often to update highscores from database in minutes. Too low may slow down your website.<br/>0 to disable.',
'default' => 15, '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' => [ 'highscores_vocation_box' => [
'name' => 'Display Vocation Box', 'name' => 'Display Vocation Box',
'type' => 'boolean', 'type' => 'boolean',
@@ -1096,12 +1074,6 @@ Sent by MyAAC,<br/>
'desc' => 'Show player vocation under his nickname?', 'desc' => 'Show player vocation under his nickname?',
'default' => true, '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' => [ 'highscores_frags' => [
'name' => 'Display Top Frags', 'name' => 'Display Top Frags',
'type' => 'boolean', 'type' => 'boolean',
@@ -1256,14 +1228,6 @@ Sent by MyAAC,<br/>
'type' => 'section', 'type' => 'section',
'title' => 'Online Page' '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' => [ 'online_record' => [
'name' => 'Display Players Record', 'name' => 'Display Players Record',
'type' => 'boolean', 'type' => 'boolean',
@@ -1304,7 +1268,7 @@ Sent by MyAAC,<br/>
'name' => 'Data Center', 'name' => 'Data Center',
'type' => 'text', 'type' => 'text',
'desc' => 'Server Location, will be shown on online page', 'desc' => 'Server Location, will be shown on online page',
'default' => 'Poland - Warsaw', 'default' => 'Frankfurt - Germany',
], ],
[ [
'type' => 'section', 'type' => 'section',
@@ -1607,14 +1571,13 @@ Sent by MyAAC,<br/>
'name' => 'Donate Column', 'name' => 'Donate Column',
'type' => 'options', 'type' => 'options',
'desc' => 'What to give to player after donation - what column in accounts table to use.', 'desc' => 'What to give to player after donation - what column in accounts table to use.',
'options' => $donateColumnOptions, 'options' => ['premium_points' => 'Premium Points', 'coins' => 'Coins'],
'default' => 'premium_points', 'default' => 'premium_points',
'callbacks' => [ 'callbacks' => [
'beforeSave' => function($key, $value, &$errorMessage) { 'beforeSave' => function($key, $value, &$errorMessage) {
global $db; global $db;
if ($value == 'coins' && !$db->hasColumn('accounts', 'coins')) {
if (!$db->hasColumn('accounts', $value)) { $errorMessage = "Shop: Donate Column: Cannot set column to coins, because it doesn't exist in database.";
$errorMessage = "Shop: Donate Column: Cannot set column to $value, because it doesn't exist in database.";
return false; return false;
} }
return true; return true;

View File

@@ -106,7 +106,7 @@ class Cache
public static function remember($key, $ttl, $callback) public static function remember($key, $ttl, $callback)
{ {
$cache = self::getInstance(); $cache = self::getInstance();
if (!$cache->enabled() || $ttl == 0) { if (!$cache->enabled()) {
return $callback(); return $callback();
} }

View File

@@ -2,7 +2,6 @@
namespace MyAAC\Commands; namespace MyAAC\Commands;
use MyAAC\Cache\Cache;
use MyAAC\Hooks; use MyAAC\Hooks;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -18,7 +17,10 @@ class CacheClearCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): int protected function execute(InputInterface $input, OutputInterface $output): int
{ {
require SYSTEM . 'init.php'; global $hooks;
$hooks = new Hooks();
$hooks->load();
$hooks->trigger(HOOK_INIT);
$io = new SymfonyStyle($input, $output); $io = new SymfonyStyle($input, $output);
@@ -27,13 +29,6 @@ class CacheClearCommand extends Command
return Command::FAILURE; return Command::FAILURE;
} }
$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'); $io->success('Cache cleared');
return Command::SUCCESS; return Command::SUCCESS;
} }

View File

@@ -12,10 +12,9 @@ class MailSendCommand extends Command
{ {
protected function configure(): void protected function configure(): void
{ {
$this->setName('email:send') $this->setName('mail:send')
->setAliases(['mail:send'])
->setDescription('This command sends E-Mail to single user. Message can be provided as follows: ' . PHP_EOL ->setDescription('This command sends E-Mail to single user. Message can be provided as follows: ' . PHP_EOL
. ' echo "Hello World" | php aac email:send --subject="This is the subject" test@test.com') . ' echo "Hello World" | php sa email:send --subject="This is the subject" test@test.com')
->addArgument('recipient', InputArgument::REQUIRED, 'Email, Account Name, Account id or Player Name') ->addArgument('recipient', InputArgument::REQUIRED, 'Email, Account Name, Account id or Player Name')
->addOption('subject', 's', InputOption::VALUE_REQUIRED, 'Subject'); ->addOption('subject', 's', InputOption::VALUE_REQUIRED, 'Subject');
} }

View File

@@ -45,22 +45,6 @@ class MigrateRunCommand extends Command
$down = $input->getOption('down') ?? false; $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) { foreach ($ids as $id) {
$this->executeMigration($id, $io, !$down); $this->executeMigration($id, $io, !$down);
} }

View File

@@ -1,36 +0,0 @@
<?php
namespace MyAAC\Commands;
use MyAAC\Plugins;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class PluginDisableCommand extends Command
{
protected function configure(): void
{
$this->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;
}
}

View File

@@ -1,36 +0,0 @@
<?php
namespace MyAAC\Commands;
use MyAAC\Plugins;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class PluginEnableCommand extends Command
{
protected function configure(): void
{
$this->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;
}
}

View File

@@ -8,12 +8,11 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
class PluginSetupCommand extends Command class PluginInstallInstallCommand extends Command
{ {
protected function configure(): void protected function configure(): void
{ {
$this->setName('plugin:setup') $this->setName('plugin:install:install')
->setAliases(['plugin:install:install'])
->setDescription('This command executes the "install" part of the plugin') ->setDescription('This command executes the "install" part of the plugin')
->addArgument('plugin', InputArgument::REQUIRED, 'Plugin name'); ->addArgument('plugin', InputArgument::REQUIRED, 'Plugin name');
} }

View File

@@ -1,40 +0,0 @@
<?php
namespace MyAAC\Commands;
use MyAAC\Plugins;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class PluginUninstallCommand extends Command
{
protected function configure(): void
{
$this->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('Successfully uninstalled plugin ' . $pluginName);
return Command::SUCCESS;
}
}

View File

@@ -3,7 +3,6 @@
namespace MyAAC\Commands; namespace MyAAC\Commands;
use MyAAC\Models\Settings as SettingsModel; use MyAAC\Models\Settings as SettingsModel;
use MyAAC\Plugins;
use MyAAC\Settings; use MyAAC\Settings;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@@ -35,14 +34,7 @@ class SettingsResetCommand extends Command
return Command::FAILURE; return Command::FAILURE;
} }
// find by plugin name if (!$name) {
foreach (Plugins::getAllPluginsSettings() as $key => $setting) {
if ($setting['pluginFilename'] === $name) {
$name = $key;
}
}
if (empty($name)) {
SettingsModel::truncate(); SettingsModel::truncate();
} }
else { else {

View File

@@ -3,7 +3,6 @@
namespace MyAAC\Commands; namespace MyAAC\Commands;
use MyAAC\Models\Settings as SettingsModel; use MyAAC\Models\Settings as SettingsModel;
use MyAAC\Plugins;
use MyAAC\Settings; use MyAAC\Settings;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@@ -18,7 +17,7 @@ class SettingsSetCommand extends Command
->setDescription('Updates the setting specified by argument in database') ->setDescription('Updates the setting specified by argument in database')
->addArgument('key', ->addArgument('key',
InputArgument::REQUIRED, InputArgument::REQUIRED,
'Setting key in format name.key' 'Setting name/key'
) )
->addArgument('value', ->addArgument('value',
InputArgument::REQUIRED, InputArgument::REQUIRED,
@@ -35,18 +34,6 @@ class SettingsSetCommand extends Command
$key = $input->getArgument('key'); $key = $input->getArgument('key');
$value = $input->getArgument('value'); $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 = Settings::getInstance();
$settings->clearCache(); $settings->clearCache();
$settings->load(); $settings->load();
@@ -57,6 +44,10 @@ class SettingsSetCommand extends Command
return Command::FAILURE; return Command::FAILURE;
} }
// format plugin_name.key
// example: core.template
$explode = explode('.', $key);
$settings->updateInDatabase($explode[0], $explode[1], $value); $settings->updateInDatabase($explode[0], $explode[1], $value);
$settings->clearCache(); $settings->clearCache();

View File

@@ -53,6 +53,9 @@ class Account extends Model {
public function getIsPremiumAttribute() public function getIsPremiumAttribute()
{ {
global $config;
if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return true;
if(isset($this->premium_ends_at)) { if(isset($this->premium_ends_at)) {
return $this->premium_ends_at > time(); return $this->premium_ends_at > time();
} }

View File

@@ -9,10 +9,6 @@ class PlayerOnline extends Model {
public $timestamps = false; public $timestamps = false;
protected $fillable = [
'player_id',
];
public function player() public function player()
{ {
return $this->belongsTo(Player::class); return $this->belongsTo(Player::class);

View File

@@ -532,9 +532,8 @@ class Plugins {
self::$plugin_json = $plugin_json; self::$plugin_json = $plugin_json;
if ($plugin_json == null) { if ($plugin_json == null) {
self::$warnings[] = 'Cannot load ' . $file_name . '. File might be not a valid json code.'; self::$warnings[] = 'Cannot load ' . $file_name . '. File might be not a valid json code.';
return false;
} }
else {
$continue = true; $continue = true;
if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) { if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) {
@@ -690,10 +689,7 @@ class Plugins {
} }
} }
if(!$continue) { if($continue) {
return false;
}
if(!$zip->extractTo(BASE)) { // "Real" Install if(!$zip->extractTo(BASE)) { // "Real" Install
self::$error = 'There was a problem with extracting zip archive to base directory.'; self::$error = 'There was a problem with extracting zip archive to base directory.';
$zip->close(); $zip->close();
@@ -717,8 +713,13 @@ class Plugins {
} }
clearCache(); clearCache();
return true; return true;
} }
}
return false;
}
public static function isEnabled($pluginFileName): bool public static function isEnabled($pluginFileName): bool
{ {
@@ -780,20 +781,15 @@ class Plugins {
return false; return false;
} }
$install = $plugin_json['install'] ?? ''; if(!isset($plugin_json['install'])) {
if (self::getAutoLoadOption($plugin_json, 'install', true) && is_file(PLUGINS . $plugin_name . '/install.php')) { self::$error = "Plugin doesn't have install options defined. Skipping...";
$install = 'plugins/' . $plugin_name . '/install.php';
}
if (empty($install)) {
self::$error = "This plugin doesn't seem to have install script defined.";
return false; return false;
} }
global $db; global $db;
if (file_exists(BASE . $install)) { if (file_exists(BASE . $plugin_json['install'])) {
$db->revalidateCache(); $db->revalidateCache();
require BASE . $install; require BASE . $plugin_json['install'];
$db->revalidateCache(); $db->revalidateCache();
} }
else { else {

View File

@@ -7,13 +7,16 @@ use MyAAC\Models\Settings as ModelsSettings;
class Settings implements \ArrayAccess class Settings implements \ArrayAccess
{ {
static private ?Settings $instance = null; static private $instance;
private array $settingsFile = []; private $settingsFile = [];
private array $settingsDatabase = []; private $settingsDatabase = [];
private array $cache = []; private $cache = [];
private array $valuesAsked = []; private $valuesAsked = [];
private array $errors = []; private $errors = [];
/**
* @return Settings
*/
public static function getInstance(): Settings public static function getInstance(): Settings
{ {
if (!self::$instance) { if (!self::$instance) {
@@ -23,21 +26,28 @@ class Settings implements \ArrayAccess
return self::$instance; return self::$instance;
} }
public function load(): void public function load()
{ {
$this->settingsDatabase = Cache::remember('settings', 10 * 60, function () { $cache = Cache::getInstance();
$settingsDatabase = []; if ($cache->enabled()) {
$tmp = '';
if ($cache->fetch('settings', $tmp)) {
$this->settingsDatabase = unserialize($tmp);
return;
}
}
$settings = ModelsSettings::all(); $settings = ModelsSettings::all();
foreach ($settings as $setting) { foreach ($settings as $setting) {
$settingsDatabase[$setting->name][$setting->key] = $setting->value; $this->settingsDatabase[$setting->name][$setting->key] = $setting->value;
} }
return $settingsDatabase; if ($cache->enabled()) {
}); $cache->set('settings', serialize($this->settingsDatabase), 600);
}
} }
public function save($pluginName, $values): bool public function save($pluginName, $values)
{ {
$this->loadPlugin($pluginName); $this->loadPlugin($pluginName);
@@ -94,7 +104,7 @@ class Settings implements \ArrayAccess
return true; return true;
} }
public function updateInDatabase($pluginName, $key, $value): void public function updateInDatabase($pluginName, $key, $value)
{ {
if (ModelsSettings::where(['name' => $pluginName, 'key' => $key])->exists()) { if (ModelsSettings::where(['name' => $pluginName, 'key' => $key])->exists()) {
ModelsSettings::where(['name' => $pluginName, 'key' => $key])->update(['value' => $value]); ModelsSettings::where(['name' => $pluginName, 'key' => $key])->update(['value' => $value]);
@@ -107,7 +117,7 @@ class Settings implements \ArrayAccess
$this->clearCache(); $this->clearCache();
} }
public function deleteFromDatabase($pluginName, $key = null): void public function deleteFromDatabase($pluginName, $key = null)
{ {
if (!isset($key)) { if (!isset($key)) {
ModelsSettings::where('name', $pluginName)->delete(); ModelsSettings::where('name', $pluginName)->delete();
@@ -207,7 +217,7 @@ class Settings implements \ArrayAccess
if (isset($setting['hidden']) && $setting['hidden']) { if (isset($setting['hidden']) && $setting['hidden']) {
$value = ''; $value = '';
if ($setting['type'] === 'boolean') { if ($setting['type'] === 'boolean') {
$value = (getBoolean($setting['default']) ? 'true' : 'false'); $value = ($setting['default'] ? 'true' : 'false');
} }
else if (in_array($setting['type'], ['text', 'number', 'float', 'double', 'email', 'password', 'textarea'])) { else if (in_array($setting['type'], ['text', 'number', 'float', 'double', 'email', 'password', 'textarea'])) {
$value = $setting['default']; $value = $setting['default'];
@@ -220,7 +230,12 @@ class Settings implements \ArrayAccess
} }
else if ($setting['type'] === 'boolean') { else if ($setting['type'] === 'boolean') {
if(isset($settingsDb[$key])) { if(isset($settingsDb[$key])) {
$value = getBoolean($settingsDb[$key]); if($settingsDb[$key] === 'true') {
$value = true;
}
else {
$value = false;
}
} }
else { else {
$value = ($setting['default'] ?? false); $value = ($setting['default'] ?? false);
@@ -368,7 +383,7 @@ class Settings implements \ArrayAccess
} }
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetSet($offset, $value): void public function offsetSet($offset, $value)
{ {
if (is_null($offset)) { if (is_null($offset)) {
throw new \RuntimeException("Settings: You cannot set empty offset with value: $value!"); throw new \RuntimeException("Settings: You cannot set empty offset with value: $value!");
@@ -408,7 +423,7 @@ class Settings implements \ArrayAccess
} }
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetUnset($offset): void public function offsetUnset($offset)
{ {
$this->loadPlugin($offset); $this->loadPlugin($offset);
@@ -440,7 +455,7 @@ class Settings implements \ArrayAccess
* @return array|mixed * @return array|mixed
*/ */
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function offsetGet($offset): mixed public function offsetGet($offset)
{ {
// try cache hit // try cache hit
if(isset($this->cache[$offset])) { if(isset($this->cache[$offset])) {
@@ -457,15 +472,13 @@ class Settings implements \ArrayAccess
if (!isset($this->settingsFile[$pluginKeyName]['settings'])) { if (!isset($this->settingsFile[$pluginKeyName]['settings'])) {
throw new \RuntimeException('Unknown plugin settings: ' . $pluginKeyName); throw new \RuntimeException('Unknown plugin settings: ' . $pluginKeyName);
} }
return $this->settingsFile[$pluginKeyName]['settings']; return $this->settingsFile[$pluginKeyName]['settings'];
} }
if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) { $ret = [];
return null; if(isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
}
$ret = $this->settingsFile[$pluginKeyName]['settings'][$key]; $ret = $this->settingsFile[$pluginKeyName]['settings'][$key];
}
if(isset($this->settingsDatabase[$pluginKeyName][$key])) { if(isset($this->settingsDatabase[$pluginKeyName][$key])) {
$value = $this->settingsDatabase[$pluginKeyName][$key]; $value = $this->settingsDatabase[$pluginKeyName][$key];
@@ -473,6 +486,10 @@ class Settings implements \ArrayAccess
$ret['value'] = $value; $ret['value'] = $value;
} }
else { else {
if (!isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
return null;
}
$ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default']; $ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default'];
} }
@@ -506,7 +523,7 @@ class Settings implements \ArrayAccess
return $ret; return $ret;
} }
private function updateValuesAsked($offset): void private function updateValuesAsked($offset)
{ {
$pluginKeyName = $offset; $pluginKeyName = $offset;
if (strpos($offset, '.')) { if (strpos($offset, '.')) {
@@ -522,7 +539,7 @@ class Settings implements \ArrayAccess
} }
} }
private function loadPlugin($offset): void private function loadPlugin($offset)
{ {
$this->updateValuesAsked($offset); $this->updateValuesAsked($offset);
@@ -551,7 +568,7 @@ class Settings implements \ArrayAccess
} }
} }
public static function saveConfig($config, $filename, &$content = ''): bool|int public static function saveConfig($config, $filename, &$content = '')
{ {
$content = "<?php" . PHP_EOL; $content = "<?php" . PHP_EOL;

View File

@@ -91,7 +91,7 @@ else {
$file = BASE . $template_path . '/layout_config.ini'; $file = BASE . $template_path . '/layout_config.ini';
} }
$template_ini = parse_ini_file($file, true); $template_ini = parse_ini_file($file);
unset($file); unset($file);
if ($cache->enabled()) { if ($cache->enabled()) {
@@ -148,7 +148,7 @@ function get_template_menus(): array
{ {
global $template_name; global $template_name;
$result = Cache::remember('template_menus_' . $template_name, 10 * 60, function () use ($template_name) { $result = Cache::remember('template_menus', 10 * 60, function () use ($template_name) {
$result = Menu::select(['name', 'link', 'blank', 'color', 'category']) $result = Menu::select(['name', 'link', 'blank', 'color', 'category'])
->where('template', $template_name) ->where('template', $template_name)
->orderBy('category') ->orderBy('category')

View File

@@ -16,13 +16,6 @@
<input class="form-control" type="text" id="mail_to" name="mail_to" value="{{ mail_to }}"/> <input class="form-control" type="text" id="mail_to" name="mail_to" value="{{ mail_to }}"/>
</div> </div>
{% if setting('core.account_mail_verify') %}
<div class="form-check">
<input type="checkbox" class="form-check-input" id="mail_verified_only" name="mail_verified_only" {% if mail_verified_only %}checked{% endif %}>
<label class="form-check-label" for="mail_verified_only">Mail only verified users</label>
</div>
{% endif %}
<div class="form-group row"> <div class="form-group row">
<label for="mail_subject">Subject:</label> <label for="mail_subject">Subject:</label>
<input class="form-control" type="text" id="mail_subject" name="mail_subject" value="{{ mail_subject }}" maxlength="30"/> <input class="form-control" type="text" id="mail_subject" name="mail_subject" value="{{ mail_subject }}" maxlength="30"/>

View File

@@ -4,7 +4,7 @@
<th>Plugin Name</th> <th>Plugin Name</th>
<th>Your Version</th> <th>Your Version</th>
<th>Latest Version</th> <th>Latest Version</th>
<th>Download Link</th> <th>Download link</th>
</tr> </tr>
</thead> </thead>
{% for plugin in plugins %} {% for plugin in plugins %}

View File

@@ -235,7 +235,6 @@
{% endif %} {% endif %}
{% if isVice %} {% if isVice %}
{% if db.hasTableAndColumns('guild_invites', ['player_id']) %}
<form action="{{ getLink('guilds') }}?action=invite&guild={{ guild_name|url_encode }}" method="post"> <form action="{{ getLink('guilds') }}?action=invite&guild={{ guild_name|url_encode }}" method="post">
{{ csrf() }} {{ csrf() }}
<td> <td>
@@ -244,7 +243,6 @@
{% include('buttons.base.html.twig') %} {% include('buttons.base.html.twig') %}
</td> </td>
</form> </form>
{% endif %}
<form action="{{ getLink('guilds') }}?action=change_rank&guild={{ guild_name|url_encode }}" method="post"> <form action="{{ getLink('guilds') }}?action=change_rank&guild={{ guild_name|url_encode }}" method="post">
{{ csrf() }} {{ csrf() }}

View File

@@ -66,7 +66,7 @@
<td> <td>
<a href="{{ player.link }}"> <a href="{{ player.link }}">
<span {% if setting('core.highscores_online_status') %}style="color: {% if player.online > 0 %}green{% else %}red{% endif %}"{% endif %}>{{ player.name }}</span> <span style="color: {% if player.online > 0 %}green{% else %}red{% endif %}">{{ player.name }}</span>
</a> </a>
{% if setting('core.highscores_vocation') %} {% if setting('core.highscores_vocation') %}
<br/><small>{{ player.vocation }}</small> <br/><small>{{ player.vocation }}</small>
@@ -94,10 +94,8 @@
{% endif %} {% endif %}
</table> </table>
</td> </td>
{% if setting('core.highscores_skills_box') or setting('core.highscores_vocation_box') %}
<td width="5%"></td> <td width="5%"></td>
<td width="15%" valign="top" align="right"> <td width="15%" valign="top" align="right">
{% if setting('core.highscores_skills_box') %}
<table style="border: 0; width: 100%" cellpadding="4" cellspacing="1"> <table style="border: 0; width: 100%" cellpadding="4" cellspacing="1">
<tr bgcolor="{{ config.vdarkborder }}"> <tr bgcolor="{{ config.vdarkborder }}">
<td class="white"><B>Choose a skill</B></TD> <td class="white"><B>Choose a skill</B></TD>
@@ -111,8 +109,7 @@
</tr> </tr>
</table> </table>
<br/> <br/>
{% endif %} {% if config.highscores_vocation_box %}
{% if setting('core.highscores_vocation_box') %}
<table border="0" width="100%" cellpadding="4" cellspacing="1"> <table border="0" width="100%" cellpadding="4" cellspacing="1">
<tr bgcolor="{{ config.vdarkborder }}"> <tr bgcolor="{{ config.vdarkborder }}">
<td class="white"><b>Choose a vocation</b></td> <td class="white"><b>Choose a vocation</b></td>
@@ -129,6 +126,5 @@
{% endif %} {% endif %}
</td> </td>
<td style="width: 18px"></td> <td style="width: 18px"></td>
{% endif %}
</tr> </tr>
</table> </table>

View File

@@ -1,9 +1,3 @@
{% set onlineTTL = setting('core.online_cache_ttl') %}
{% if onlineTTL > 0 and cache.enabled() %}
<small>*Note: Online List is updated every {{ onlineTTL > 1 ? ' ' ~ onlineTTL : '' }} minute{{ onlineTTL > 1 ? 's' : '' }}.</small>
<br/>
{% endif %}
{# vocation statistics #} {# vocation statistics #}
{% if setting('core.online_vocations') %} {% if setting('core.online_vocations') %}
<br/> <br/>
@@ -90,7 +84,7 @@
</td> </td>
</tr> </tr>
{% if setting('core.online_record') and record|length > 0 %} {% if setting('core.online_record') %}
<tr> <tr>
<td class="LabelV150"><b>Online Record:</b></td> <td class="LabelV150"><b>Online Record:</b></td>
<td> <td>
@@ -161,7 +155,7 @@
{% endif %} {% endif %}
<td style="width:70%; text-align:left"> <td style="width:70%; text-align:left">
{{ player.name|raw }}{{ player.skull|raw }} {{ player.name|raw }}{{ player.skull }}
</td> </td>
<td style="width:10%">{{ player.level }}</td> <td style="width:10%">{{ player.level }}</td>
<td style="width:20%">{{ player.vocation }}</td> <td style="width:20%">{{ player.vocation }}</td>

View File

@@ -36,11 +36,7 @@ $twig->addExtension(new MyAAC\Twig\Extension\TypeCastingExtension());
$filter = new TwigFilter('timeago', function ($datetime) { $filter = new TwigFilter('timeago', function ($datetime) {
if (!is_int($datetime)) { $time = time() - strtotime($datetime);
$datetime = strtotime($datetime);
}
$time = time() - $datetime;
$units = array ( $units = array (
31536000 => 'year', 31536000 => 'year',
@@ -156,5 +152,3 @@ $twig->addFilter($filter);
unset($function, $filter); unset($function, $filter);
$hooks->trigger(HOOK_TWIG, ['twig' => $twig, 'twig_loader' => $twig_loader]); $hooks->trigger(HOOK_TWIG, ['twig' => $twig, 'twig_loader' => $twig_loader]);
$twig->addGlobal('cache', $cache);

View File

@@ -1,18 +1,12 @@
<?php <?php
$config['menu_default_links_color'] = '#ffffff'; $config['menu_default_links_color'] = '#ffffff';
// max 7 menus for kathrine $config['menu_categories'] = array(
$config['menu_categories'] = [ MENU_CATEGORY_NEWS => array('id' => 'news', 'name' => 'Latest News'),
MENU_CATEGORY_NEWS => ['id' => 'news', 'name' => 'Latest News'], MENU_CATEGORY_ACCOUNT => array('id' => 'account', 'name' => 'Account'),
// you can add custom menu by uncommenting this MENU_CATEGORY_COMMUNITY => array('id' => 'community', 'name' => 'Community'),
// after doing it, go to admin panel -> Menus and add your entries for this category MENU_CATEGORY_LIBRARY => array('id' => 'library', 'name' => 'Library'),
// tip: you can move it up/down to show it on specific position MENU_CATEGORY_SHOP => array('id' => 'shops', 'name' => 'Shop')
//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'; $config['menus'] = require __DIR__ . '/menus.php';

View File

@@ -1,40 +1,42 @@
<?php <?php
function get_template_pages($category): array $menus = get_template_menus();
{
function get_template_pages($category) {
global $menus; global $menus;
$ret = array(); $ret = array();
foreach($menus[$category] ?? [] as $menu) { foreach($menus[$category] as $menu) {
$ret[] = $menu['link']; $ret[] = $menu['link'];
} }
return $ret; return $ret;
} }
?> ?>
let category = '<?php var category = '<?php
if(str_contains(URI, 'subtopic=')) { if(strpos(URI, 'subtopic=') !== false) {
$tmp = [$_REQUEST['subtopic']]; $tmp = array($_REQUEST['subtopic']);
} }
else { else {
$tmp = URI; $tmp = URI;
if(empty($tmp)) { if(empty($tmp)) {
$tmp = ['news']; $tmp = array('news');
} }
else { else {
$tmp = explode('/', URI); $tmp = explode('/', URI);
} }
} }
foreach (config('menu_categories') as $id => $info) { if(in_array($tmp[0], get_template_pages(MENU_CATEGORY_NEWS)))
$templatePages = get_template_pages($id); echo 'news';
elseif(in_array($tmp[0], get_template_pages(MENU_CATEGORY_LIBRARY)))
if ($id == MENU_CATEGORY_ACCOUNT) { echo 'library';
$templatePages = array_merge($templatePages, ['account']); elseif(in_array($tmp[0], get_template_pages(MENU_CATEGORY_COMMUNITY)))
} echo 'community';
elseif(in_array($tmp[0], array_merge(get_template_pages(MENU_CATEGORY_ACCOUNT), array('account'))))
if (in_array($tmp[0], $templatePages)) { echo 'account';
echo $info['id']; elseif(in_array($tmp[0], get_template_pages(MENU_CATEGORY_SHOP)))
break; echo 'shops';
} else {
echo 'news';
} }
?>'; ?>';

View File

@@ -1,10 +1,10 @@
var list = new Array(); var list = new Array();
{% set i = 0 %} {% set i = 0 %}
{% for id, cat in config('menu_categories') %} {% for cat in categories %}
{% if (cat.id != 'shops' or setting('core.gifts_system')) and menus[id]|length > 0 %} {% if cat.id != 'shops' or setting('core.gifts_system') %}
list[{{ i }}] = '{{ cat.id }}'; list[{{ i }}] = '{{ cat.id }}';
{% set i = i + 1 %}
{% endif %} {% endif %}
{% set i = i + 1 %}
{% endfor %} {% endfor %}
function initMenu() function initMenu()

View File

@@ -27,13 +27,11 @@ body
#tabs #tabs
{ {
width: 99%; width: 580px;
height: 32px; height: 32px;
background: url('images/tabs-bg.png') no-repeat; background: url('images/tabs-bg.png') no-repeat;
float: left;
padding-left: 200px; padding-left: 200px;
position: relative;
display: inline-flex;
right: 0;
} }
#tabs .tab #tabs .tab

View File

@@ -8,9 +8,7 @@ defined('MYAAC') or die('Direct access not allowed!');
<link rel="stylesheet" href="<?php echo $template_path; ?>/style.css" type="text/css" /> <link rel="stylesheet" href="<?php echo $template_path; ?>/style.css" type="text/css" />
<script type="text/javascript"> <script type="text/javascript">
<?php <?php
$menus = get_template_menus(); $twig->display('menu.js.html.twig', array('categories' => $config['menu_categories']));
$twig->display('menu.js.html.twig', ['menus' => $menus]);
?> ?>
</script> </script>
<script type="text/javascript" src="tools/basic.js"></script> <script type="text/javascript" src="tools/basic.js"></script>
@@ -30,24 +28,11 @@ defined('MYAAC') or die('Direct access not allowed!');
<div id="header"></div> <div id="header"></div>
<!-- End --> <!-- End -->
<!-- Custom Style for #tabs -->
<?php
$menusCount = count($menus);
$tabsStyle = '';
if ($menusCount > 6) {
$tabsStyle .= 'padding-left: 4px;';
$tabsStyle .= 'padding-right: 12px;';
}
elseif ($menusCount > 5) {
$tabsStyle .= 'padding-left: 90px;';
}
?>
<!-- Menu Section --> <!-- Menu Section -->
<div id="tabs" style="<?= $tabsStyle; ?>"> <div id="tabs">
<?php <?php
foreach($config['menu_categories'] as $id => $cat) { foreach($config['menu_categories'] as $id => $cat) {
if (($id != MENU_CATEGORY_SHOP || $config['gifts_system']) && isset($menus[$id])) { ?> if($id != MENU_CATEGORY_SHOP || $config['gifts_system']) { ?>
<span id="<?php echo $cat['id']; ?>" onclick="menuSwitch('<?php echo $cat['id']; ?>');"><?php echo $cat['name']; ?></span> <span id="<?php echo $cat['id']; ?>" onclick="menuSwitch('<?php echo $cat['id']; ?>');"><?php echo $cat['name']; ?></span>
<?php <?php
} }

View File

@@ -1,6 +1,6 @@
<div id="CurrentPollBox" class="Themebox" style="background-image:url({{ template_path }}/images/themeboxes/current-poll/currentpollbox.gif);"> <div id="CurrentPollBox" class="Themebox" style="background-image:url({{ template_path }}/images/themeboxes/current-poll/currentpollbox.gif);">
<div id="CurrentPollText">{{ poll.question }}</div> <div id="CurrentPollText">{{ poll.question }}</div>
<a class="ThemeboxButton" href="{{ getLink('polls') }}?ìd={{ poll.id }}" onMouseOver="MouseOverBigButton(this);" onMouseOut="MouseOutBigButton(this);" style="background-image:url({{ template_path }}/images/global/buttons/sbutton.gif);"><div class="BigButtonOver" style="background-image:url({{ template_path }}/images/global/buttons/sbutton_over.gif);"></div><div class="ButtonText" style="background-image:url({{ template_path }}/images/global/buttons/_sbutton_votenow.gif);"></div> <a class="ThemeboxButton" href="{{ getLink('polls') }}/{{ poll.id }}" onMouseOver="MouseOverBigButton(this);" onMouseOut="MouseOutBigButton(this);" style="background-image:url({{ template_path }}/images/global/buttons/sbutton.gif);"><div class="BigButtonOver" style="background-image:url({{ template_path }}/images/global/buttons/sbutton_over.gif);"></div><div class="ButtonText" style="background-image:url({{ template_path }}/images/global/buttons/_sbutton_votenow.gif);"></div>
</a> </a>
<div class="Bottom" style="background-image:url({{ template_path }}/images/general/box-bottom.gif);"></div> <div class="Bottom" style="background-image:url({{ template_path }}/images/general/box-bottom.gif);"></div>
</div> </div>

View File

@@ -164,10 +164,6 @@ if(isset($config['boxes']))
function InitializeMenu() function InitializeMenu()
{ {
for(menuItemName in menu[0]) { for(menuItemName in menu[0]) {
if (!document.getElementById(menuItemName+"_Submenu")) {
continue;
}
if(menu[0][menuItemName] == "0") { if(menu[0][menuItemName] == "0") {
document.getElementById(menuItemName+"_Submenu").style.visibility = "hidden"; document.getElementById(menuItemName+"_Submenu").style.visibility = "hidden";
document.getElementById(menuItemName+"_Submenu").style.display = "none"; document.getElementById(menuItemName+"_Submenu").style.display = "none";
@@ -391,7 +387,7 @@ foreach($config['menu_categories'] as $id => $cat) {
?> ?>
</div> </div>
<?php <?php
if ($i == $countElements) { if($id == MENU_CATEGORY_SHOP || (!setting('core.gifts_system') && $i == $countElements)) {
?> ?>
<div id='MenuBottom' style='background-image:url(<?php echo $template_path; ?>/images/general/box-bottom.gif);'></div> <div id='MenuBottom' style='background-image:url(<?php echo $template_path; ?>/images/general/box-bottom.gif);'></div>
<?php <?php
@@ -458,7 +454,7 @@ foreach($config['menu_categories'] as $id => $cat) {
foreach($config['boxes'] as $box) { foreach($config['boxes'] as $box) {
/** @var string $template_name */ /** @var string $template_name */
$file = __DIR__ . '/boxes/' . $box . '.php'; $file = TEMPLATES . $template_name . '/boxes/' . $box . '.php';
if(file_exists($file)) { if(file_exists($file)) {
include($file); ?> include($file); ?>
<?php <?php