Compare commits

..

70 Commits

Author SHA1 Message Date
slawkens
233bf001ce Set $title to 'Lost Account' 2025-09-14 19:49:26 +02:00
slawkens
d2f1f41576 Use myaac-table class for tables 2025-09-14 19:44:30 +02:00
slawkens
2f9ae38c19 Merge branch 'main' into feature/refactor-account-lost 2025-09-14 19:35:26 +02:00
slawkens
a6032093b2 Better look for myaac-table 2025-09-14 19:35:12 +02:00
slawkens
b1b536ce68 Update form.html.twig 2025-09-14 19:34:52 +02:00
slawkens
25695a039d [WIP] Refactor account/lost 2025-09-14 17:41:53 +02:00
slawkens
e27d974c46 Merge branch 'main' into feature/refactor-account-lost 2025-09-14 13:02:41 +02:00
slawkens
4eab805d26 Fix when config.local.php cannot be saved 2025-09-09 17:49:05 +02:00
slawkens
3f24f961b1 Possibility to override routes with plugins pages, like characters.php
No need to define routes in plugin.json anymore
2025-09-09 15:17:06 +02:00
slawkens
0b86459940 Start v1.8.2-dev 2025-09-07 09:33:18 +02:00
slawkens
7a9b11434e Release v1.8.1 2025-09-05 13:25:25 +02:00
slawkens
9725a3c2bd Some servers don't have guild_invites table 2025-09-03 23:47:27 +02:00
slawkens
46adeefce3 Update settings.php 2025-08-27 15:30:52 +02:00
slawkens
e4b66f34ac Fix check for donate column 2025-08-27 12:15:52 +02:00
slawkens
2465bb6f9a Update settings.php 2025-08-27 11:40:54 +02:00
André Morais
42671c5c19 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 <slawkens@gmail.com>
2025-08-27 11:26:46 +02:00
slawkens
fec773ba4b plugin:enable/disable commands 2025-08-25 11:35:56 +02:00
slawkens
1b9f68c9ec Update PluginUninstallCommand.php 2025-08-25 10:58:54 +02:00
slawkens
7a08f91d3f plugin:unistall command 2025-08-25 09:31:50 +02:00
slawkens
4b948e9510 Option to change/set plugin settings by plugin name 2025-08-22 18:20:37 +02:00
slawkens
17ca93d020 Same with default 2025-08-22 17:51:19 +02:00
slawkens
bcc4b48eb0 Settings: Option to set boolean values as "yes" 2025-08-22 17:39:14 +02:00
slawkens
f8c4332e03 Option to reset plugin settings by plugin name 2025-08-22 17:27:53 +02:00
slawkens
235e0f394d Refactor code to use Cache::remember 2025-08-22 16:04:52 +02:00
slawkens
3451715e96 Settings class: Add type hints 2025-08-22 15:30:19 +02:00
slawkens
d85681880e Rename file name to PluginSetupCommand 2025-08-21 21:12:55 +02:00
slawkens
4701461b1f Add some comment about optional sorting, into migrate:run command 2025-08-21 20:54:58 +02:00
slawkens
482f4067b2 Menus should be saved for each template separately
Trying to fix some weird bug
2025-08-17 18:45:49 +02:00
slawkens
2f26748112 ❤️ 2025-08-17 18:19:07 +02:00
slawkens
98073a110a Fix online skulls display (Fix #320) 2025-08-17 17:50:16 +02:00
slawkens
11dae90fa9 Fix MenuBotton display if some elements are removed
From menu_categories
2025-08-12 17:42:06 +02:00
slawkens
20f99903ae 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.
2025-08-12 12:46:39 +02:00
slawkens
b6e1620f14 Fix #318 (online.php throws error in one scenario) 2025-08-07 21:17:25 +02:00
dependabot[bot]
9cb7792623 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] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-07 16:21:22 +02:00
dependabot[bot]
0db908be18 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] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-02 14:15:13 +02:00
slawkens
785d38312b Start 1.8.1-dev 2025-08-02 12:41:35 +02:00
slawkens
e1c04ed28e Release v1.8 2025-08-02 12:28:13 +02:00
slawkens
c836308601 pages/online: add cache, resulting in 20x performance boost
(for an example server with 2k players)
2025-07-31 13:28:46 +02:00
slawkens
0efe47ce71 Twig: add cache variable 2025-07-31 13:15:06 +02:00
slawkens
3b47e9df2f Cache::remember: $ttl = 0 means no cache 2025-07-31 13:02:55 +02:00
slawkens
43415cf35d Add missing $fillable into PlayerOnline model 2025-07-31 12:32:18 +02:00
slawkens
cf7fd20452 Mailer: send only to verified accounts (option) 2025-07-31 09:19:49 +02:00
slawkens
080cc2781f Fix mailer: send to email link from accounts page 2025-07-31 07:31:15 +02:00
slawkens
20d69a641c Fix exception if setting not found 2025-07-24 23:30:28 +02:00
slawkens
2d4be327b2 Fix if highscores show outfit disabled 2025-07-24 23:07:49 +02:00
slawkens
bb097b69ce Update settings.php 2025-07-22 22:06:32 +02:00
slawkens
6e5a4ff8c7 Fix if setting found in db, but not found in plugins 2025-07-22 21:49:05 +02:00
slawkens
caf326a658 Refactor to use HAS_ACCOUNT_COINS
$db->hasColumn('accounts', 'coins') -> HAS_ACCOUNT_COINS
2025-07-22 21:44:09 +02:00
slawkens
bccf8e056d Rewrite to use constants (account transferable coins) 2025-07-22 21:33:45 +02:00
slawkens
7d27e5a0ba New setting: Default Account Transferable Coins 2025-07-22 21:32:51 +02:00
slawkens
9b6f410459 Update phpstan.neon 2025-07-22 19:11:42 +02:00
slawkens
c06b0017f1 Update phpstan.neon 2025-07-22 19:07:58 +02:00
slawkens
d8132d4d76 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
2025-07-22 18:18:29 +02:00
slawkens
1566deb84a Add getExperienceForLevel (level) 2025-07-19 15:46:51 +02:00
slawkens
536b29be95 That is duplicated 2025-07-19 15:11:09 +02:00
slawkens
5271633bdb Account -> isPremium -> ignore config.freePremium 2025-07-19 15:00:17 +02:00
slawkens
ce5b1cf2a6 Update CacheClearCommand.php 2025-07-19 11:16:55 +02:00
slawkens
83f84172e0 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.
2025-07-19 11:16:03 +02:00
slawkens
34fead906e Allow for timestamp as integer in the timeago twig function 2025-07-19 10:05:25 +02:00
slawkens
ec11c14024 kathrine: possibility to add custom menu categories 2025-07-19 07:48:01 +02:00
slawkens
2fe9924437 Start 1.7.2-dev 2025-07-08 19:20:45 +02:00
slawkens
f0f2e3785f Fix phpstan 2025-07-08 15:44:45 +02:00
slawkens
36ca755243 New setting: Display Skills Box on highscores
Better space management
2025-07-08 14:28:48 +02:00
slawkens
f17269e44c Move admin bar code into body_start place_holder 2025-07-08 14:22:51 +02:00
slawkens
dcb96f4ce1 Refactor code - early exit 2025-07-08 13:48:33 +02:00
slawkens
a89f9a8484 Set $process_sections to true 2025-07-08 09:22:12 +02:00
slawkens
45d6047031 Add Coins Transferable to accounts editor 2025-07-05 14:22:58 +02:00
slawkens
67f54eacbc Merge branch 'develop' into feature/refactor-account-lost 2024-09-12 08:24:06 +02:00
slawkens
cde8891b9b Merge branch 'develop' into feature/refactor-account-lost 2024-07-14 05:58:47 +02:00
slawkens
50a8b8169f [WIP] Account Lost refactor 2024-07-10 18:08:21 +02:00
70 changed files with 1584 additions and 1071 deletions

View File

@@ -1,5 +1,57 @@
# 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

View File

@@ -26,7 +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');
@@ -136,11 +135,18 @@ else if (isset($_REQUEST['search'])) {
if (!Validator::email($email))
$errors['email'] = Validator::getLastError();
//tibia coins
if ($hasCoinsColumn) {
// tibia coins
if (HAS_ACCOUNT_COINS) {
$t_coins = $_POST['t_coins'];
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
$p_days = (int)$_POST['p_days'];
verify_number($p_days, 'Prem days', 11);
@@ -185,12 +191,18 @@ else if (isset($_REQUEST['search'])) {
if ($hasSecretColumn) {
$account->setCustomField('secret', $secret);
}
$account->setCustomField('key', $key);
$account->setEMail($email);
if ($hasCoinsColumn) {
if (HAS_ACCOUNT_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;
if($p_days != 0 && $p_days != OTS_Account::GRATIS_PREMIUM_DAYS) {
$lastDay = time();
@@ -223,9 +235,6 @@ else if (isset($_REQUEST['search'])) {
$password = encrypt($password);
$account->setPassword($password);
if (USE_ACCOUNT_SALT)
$account->setCustomField('salt', $salt);
}
$account->save();
@@ -395,12 +404,18 @@ 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>)' : ''); ?>
<input type="text" class="form-control" id="email" name="email" autocomplete="off" value="<?php echo $account->getEMail(); ?>"/>
</div>
<?php if ($hasCoinsColumn): ?>
<?php if (HAS_ACCOUNT_COINS): ?>
<div class="col-12 col-sm-12 col-lg-6">
<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') ?>"/>
</div>
<?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">
<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(); ?>"/>

View File

@@ -25,9 +25,10 @@ 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;
$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,
]);

View File

@@ -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,
));

View File

@@ -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';

View File

@@ -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.8.2-dev';
const DATABASE_VERSION = 45;
const TABLE_PREFIX = 'myaac_';
define('START_TIME', microtime(true));

View File

@@ -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;

View File

@@ -42,10 +42,9 @@ 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) {
if ($saved || file_exists(BASE . 'config.local.php')) {
success($locale['step_database_config_saved']);
$_SESSION['saved'] = true;
@@ -74,14 +73,14 @@ if(!$error) {
}
}
} else {
$error = true;
$_SESSION['config_content'] = $content;
unset($_SESSION['saved']);
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.php</b>', $locale['step_database_error_file']);
$locale['step_database_error_file'] = str_replace('$FILE$', '<b>' . BASE . 'config.local.php</b>', $locale['step_database_error_file']);
error($locale['step_database_error_file'] . '<br/>
<textarea cols="70" rows="10">' . $content . '</textarea>');
}
}
}
?>

13
package-lock.json generated
View File

@@ -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": {
@@ -2084,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": {

View File

@@ -28,10 +28,9 @@ 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
- '#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#'
-

View File

@@ -512,6 +512,13 @@ function template_place_holder($type): string
}
elseif ($type === 'body_start') {
$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') {
$ret .= template_ga_code();
@@ -767,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();
@@ -1217,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()

View File

@@ -144,6 +144,15 @@ $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', $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('account_logged', new \OTS_Account());
@@ -188,10 +197,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();

View File

@@ -473,9 +473,6 @@ 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();
}

View File

@@ -227,10 +227,15 @@ 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);
}
$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);

View File

@@ -9,540 +9,11 @@
* @link https://my-aac.org
*/
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Lost Account Interface';
$title = 'Lost Account';
if(!setting('core.mail_enabled'))
{
echo '<b>Account maker is not configured to send e-mails, you can\'t use Lost Account Interface. Contact with admin to get help.</b>';
if(!setting('core.mail_enabled')) {
echo "<b>Account maker is not configured to send e-mails, you can't use Lost Account Interface. Contact with admin to get help.</b>";
return;
}
$action_type = isset($_REQUEST['action_type']) ? $_REQUEST['action_type'] : '';
if($action == '')
{
$twig->display('account.lost.form.html.twig');
}
else if($action == 'step1' && $action_type == '') {
$twig->display('account.lost.noaction.html.twig');
}
elseif($action == 'step1' && $action_type == 'email')
{
$nick = stripslashes($_REQUEST['nick']);
if(Validator::characterName($nick))
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
if($account->getCustomField('email_next') < time())
echo 'Please enter e-mail to account with this character.<BR>
<form action="' . getLink('account/lost') . '?action=sendcode" method=post>
<input type=hidden name="character">
<table cellspacing=1 cellpadding=4 border=0 width=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter e-mail to account</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Character: <INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR>
E-mail to account:<INPUT TYPE=text NAME="email" VALUE="" SIZE="40"><BR>
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
else
{
$insec = (int)$account->getCustomField('email_next') - time();
$minutesleft = floor($insec / 60);
$secondsleft = $insec - ($minutesleft * 60);
$timeleft = $minutesleft.' minutes '.$secondsleft.' seconds';
echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
}
}
else
echo 'Player or account of player <b>' . $nick . '</b> doesn\'t exist.';
}
else
echo 'Invalid player name format. If you have other characters on account try with other name.';
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<a href="' . getLink('account/lost') . '" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'sendcode')
{
$email = $_REQUEST['email'];
$nick = stripslashes($_REQUEST['nick']);
if(Validator::characterName($nick))
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
if($account->getCustomField('email_next') < time())
{
if($account->getEMail() == $email)
{
$newcode = generateRandomString(30, true, false, true);
$mailBody = '
You asked to reset your ' . $config['lua']['serverName'] . ' password.<br/>
<p>Account name: '.$account->getName().'</p>
<br />
To do so, please click this link:
<p><a href="' . getLink('account/lost') . '?action=checkcode&code='.$newcode.'&character='.urlencode($nick).'">' . getLink('account/lost') . '?action=checkcode&code='.$newcode.'&character='.urlencode($nick).'</a></p>
<p>or open page: <i>' . getLink('account/lost') . '?action=checkcode</i> and in field "code" write <b>'.$newcode.'</b></p>
<br/>
<p>If you did not request a password change, you may ignore this message and your password will remain unchanged.';
$account_mail = $account->getCustomField('email');
if(_mail($account_mail, $config['lua']['serverName'].' - Recover your account', $mailBody))
{
$account->setCustomField('email_code', $newcode);
$account->setCustomField('email_next', (time() + setting('core.mail_lost_account_interval')));
echo '<br />Details about steps required to recover your account has been sent to <b>' . $account_mail . '</b>. You should receive this email within 15 minutes. Please check your inbox/spam directory.';
}
else
{
$account->setCustomField('email_next', (time() + 60));
echo '<br /><p class="error">An error occurred while sending email! Try again later or contact with admin. For Admin: More info can be found in system/logs/mailer-error.log</p>';
}
}
else
echo 'Invalid e-mail to account of character <b>'.$nick.'</b>. Try again.';
}
else
{
$insec = (int)$account->getCustomField('email_next') - time();
$minutesleft = floor($insec / 60);
$secondsleft = $insec - ($minutesleft * 60);
$timeleft = $minutesleft.' minutes '.$secondsleft.' seconds';
echo 'Account of selected character (<b>'.$nick.'</b>) received e-mail in last '.ceil(setting('core.mail_lost_account_interval') / 60).' minutes. You must wait '.$timeleft.' before you can use Lost Account Interface again.';
}
}
else
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
}
else
echo 'Invalid player name format. If you have other characters on account try with other name.';
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<a href="' . getLink('account/lost') . '?action=step1&action_type=email&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'step1' && $action_type == 'reckey')
{
$nick = stripslashes($_REQUEST['nick']);
if(Validator::characterName($nick))
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
$account_key = $account->getCustomField('key');
if(!empty($account_key))
{
echo 'If you enter right recovery key you will see form to set new e-mail and password to account. To this e-mail will be send your new password and account name.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=step2" METHOD=post>
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter your recovery key</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Character name:&nbsp;<INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR />
Recovery key:&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE=text NAME="key" VALUE="" SIZE="40"><BR>
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
}
else
echo 'Account of this character has no recovery key!';
}
else
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
}
else
echo 'Invalid player name format. If you have other characters on account try with other name.';
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<a href="' . getLink('account/lost') . '" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'step2')
{
$rec_key = trim($_REQUEST['key']);
$nick = stripslashes($_REQUEST['nick']);
if(Validator::characterName($nick))
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
$account_key = $account->getCustomField('key');
if(!empty($account_key))
{
if($account_key == $rec_key)
{
echo '<script type="text/javascript">
function validate_required(field,alerttxt)
{
with (field)
{
if (value==null||value==""||value==" ")
{alert(alerttxt);return false;}
else {return true}
}
}
function validate_email(field,alerttxt)
{
with (field)
{
apos=value.indexOf("@");
dotpos=value.lastIndexOf(".");
if (apos<1||dotpos-apos<2)
{alert(alerttxt);return false;}
else {return true;}
}
}
function validate_form(thisform)
{
with (thisform)
{
if (validate_required(email,"Please enter your e-mail!")==false)
{email.focus();return false;}
if (validate_email(email,"Invalid e-mail format!")==false)
{email.focus();return false;}
if (validate_required(passor,"Please enter password!")==false)
{passor.focus();return false;}
if (validate_required(passor2,"Please repeat password!")==false)
{passor2.focus();return false;}
if (passor2.value!=passor.value)
{alert(\'Repeated password is not equal to password!\');return false;}
}
}
</script>';
echo 'Set new password and e-mail to your account.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=step3" onsubmit="return validate_form(this)" METHOD=post>
<INPUT TYPE=hidden NAME="character" VALUE="">
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Please enter new password and e-mail</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Account of character:&nbsp;&nbsp;<INPUT TYPE=text NAME="nick" VALUE="'.$nick.'" SIZE="40" readonly="readonly"><BR />
New password:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT id="passor" TYPE=password NAME="passor" VALUE="" SIZE="40"><BR>
Repeat new password:&nbsp;&nbsp;<INPUT id="passor2" TYPE=password NAME="passor" VALUE="" SIZE="40"><BR>
New e-mail address:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT id="email" TYPE=text NAME="email" VALUE="" SIZE="40"><BR>
<INPUT TYPE=hidden NAME="key" VALUE="'.$rec_key.'">
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
}
else
echo 'Wrong recovery key!';
}
else
echo 'Account of this character has no recovery key!';
}
else
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
}
else
echo 'Invalid player name format. If you have other characters on account try with other name.';
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<a href="' . getLink('account/lost') . '?action=step1&action_type=reckey&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'step3')
{
$rec_key = trim($_REQUEST['key']);
$nick = stripslashes($_REQUEST['nick']);
$new_pass = trim($_REQUEST['passor']);
$new_email = trim($_REQUEST['email']);
if(Validator::characterName($nick))
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
$account_key = $account->getCustomField('key');
if(!empty($account_key))
{
if($account_key == $rec_key)
{
if(Validator::password($new_pass))
{
if(Validator::email($new_email))
{
$account->setEMail($new_email);
$tmp_new_pass = $new_pass;
if(USE_ACCOUNT_SALT)
{
$salt = generateRandomString(10, false, true, true);
$tmp_new_pass = $salt . $new_pass;
}
$account->setPassword(encrypt($tmp_new_pass));
$account->save();
if(USE_ACCOUNT_SALT)
$account->setCustomField('salt', $salt);
echo 'Your account name, new password and new e-mail.<BR>
<FORM ACTION="' . getLink('account/manage') . '" onsubmit="return validate_form(this)" METHOD=post>
<INPUT TYPE=hidden NAME="character" VALUE="">
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Your account name, new password and new e-mail</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Account name:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>'.$account->getName().'</b><BR>
New password:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>'.$new_pass.'</b><BR>
New e-mail address:&nbsp;<b>'.$new_email.'</b><BR>';
if($account->getCustomField('email_next') < time())
{
$mailBody = '
<h3>Your account name and new password!</h3>
<p>Changed password and e-mail to your account in Lost Account Interface on server <a href="'.BASE_URL.'"><b>'.$config['lua']['serverName'].'</b></a></p>
<p>Account name: <b>'.$account->getName().'</b></p>
<p>New password: <b>'.$new_pass.'</b></p>
<p>E-mail: <b>'.$new_email.'</b> (this e-mail)</p>
<br />
<p><u>It\'s automatic e-mail from OTS Lost Account System. Do not reply!</u></p>';
if(_mail($account->getCustomField('email'), $config['lua']['serverName']." - New password to your account", $mailBody))
{
echo '<br /><small>Sent e-mail with your account name and password to new e-mail. You should receive this e-mail in 15 minutes. You can login now with new password!</small>';
}
else
{
echo '<br /><p class="error">An error occurred while sending email! You will not receive e-mail with this informations. For Admin: More info can be found in system/logs/mailer-error.log</p>';
}
}
else
{
echo '<br /><small>You will not receive e-mail with this informations.</small>';
}
echo '<INPUT TYPE=hidden NAME="account_login" VALUE="'.$account->getId().'">
<INPUT TYPE=hidden NAME="password_login" VALUE="'.$new_pass.'">
</TD></TR></TABLE><BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<INPUT TYPE=image NAME="Login" ALT="Login" SRC="'.$template_path.'/images/global/buttons/sbutton_login.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
</TD></TR></FORM></TABLE></TABLE>';
}
else
echo Validator::getLastError();
}
else
echo Validator::getLastError();
}
else
echo 'Wrong recovery key!';
}
else
echo 'Account of this character has no recovery key!';
}
else
echo 'Player or account of player <b>'.$nick.'</b> doesn\'t exist.';
}
else
echo 'Invalid player name format. If you have other characters on account try with other name.';
echo '<BR /><TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<a href="' . getLink('account/lost') . '?action=step1&action_type=reckey&nick='.urlencode($nick).'" border="0"><IMG SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" NAME="Back" ALT="Back" BORDER=0 WIDTH=120 HEIGHT=18></a></div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'checkcode')
{
$code = trim($_REQUEST['code']);
$character = stripslashes(trim($_REQUEST['character']));
if(empty($code) || empty($character))
echo 'Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Your code:&nbsp;<INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
Character:&nbsp;<INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
else
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($character);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
if($account->getCustomField('email_code') == $code)
{
echo '<script type="text/javascript">
function validate_required(field,alerttxt)
{
with (field)
{
if (value==null||value==""||value==" ")
{alert(alerttxt);return false;}
else {return true}
}
}
function validate_form(thisform)
{
with (thisform)
{
if (validate_required(passor,"Please enter password!")==false)
{passor.focus();return false;}
if (validate_required(passor2,"Please repeat password!")==false)
{passor2.focus();return false;}
if (passor2.value!=passor.value)
{alert(\'Repeated password is not equal to password!\');return false;}
}
}
</script>
Please enter new password to your account and repeat to make sure you remember password.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=setnewpassword" onsubmit="return validate_form(this)" METHOD=post>
<INPUT TYPE=hidden NAME="character" VALUE="'.$character.'">
<INPUT TYPE=hidden NAME="code" VALUE="'.$code.'">
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & account name</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
New password:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE=password ID="passor" NAME="passor" VALUE="" SIZE="40")><BR />
Repeat new password:&nbsp;<INPUT TYPE=password ID="passor2" NAME="passor2" VALUE="" SIZE="40")><BR />
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
}
else
$error= 'Wrong code to change password.';
}
else
$error = 'Account of this character or this character doesn\'t exist.';
}
if(!empty($error))
echo '<span style="color: red"><b>'.$error.'</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Your code:&nbsp;<INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
Character:&nbsp;<INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
}
elseif($action == 'setnewpassword')
{
$newpassword = $_REQUEST['passor'];
$code = $_REQUEST['code'];
$character = stripslashes($_REQUEST['character']);
echo '';
if(empty($code) || empty($character) || empty($newpassword))
echo '<span style="color: red"><b>Error. Try again.</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
<BR><FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<INPUT TYPE=image NAME="Back" ALT="Back" SRC="'.$template_path.'/images/global/buttons/sbutton_back.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
</TD></TR></FORM></TABLE></TABLE>';
else
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($character);
if($player->isLoaded())
$account = $player->getAccount();
if($account->isLoaded())
{
if($account->getCustomField('email_code') == $code)
{
if(Validator::password($newpassword))
{
$tmp_new_pass = $newpassword;
if(USE_ACCOUNT_SALT)
{
$salt = generateRandomString(10, false, true, true);
$tmp_new_pass = $salt . $newpassword;
$account->setCustomField('salt', $salt);
}
$account->setPassword(encrypt($tmp_new_pass ));
$account->save();
$account->setCustomField('email_code', '');
echo 'New password to your account is below. Now you can login.<BR>
<INPUT TYPE=hidden NAME="character" VALUE="'.$character.'">
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Changed password</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
New password:&nbsp;<b>'.$newpassword.'</b><BR />
Account name:&nbsp;&nbsp;&nbsp;<i>(Already on your e-mail)</i><BR />';
$mailBody = '
<h3>Your account name and password!</h3>
<p>Changed password to your account in Lost Account Interface on server <a href="'.BASE_URL.'"><b>'.$config['lua']['serverName'].'</b></a></p>
<p>Account name: <b>'.$account->getName().'</b></p>
<p>New password: <b>'.$newpassword.'</b></p>
<br />
<p><u>It\'s automatic e-mail from OTS Lost Account System. Do not reply!</u></p>';
if(_mail($account->getCustomField('email'), $config['lua']['serverName']." - Your new password", $mailBody))
{
echo '<br /><small>New password work! Sent e-mail with your password and account name. You should receive this e-mail in 15 minutes. You can login now with new password!';
}
else
{
echo '<br /><p class="error">New password work! An error occurred while sending email! You will not receive e-mail with new password. For Admin: More info can be found in system/logs/mailer-error.log';
}
echo '</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
<FORM ACTION="' . getLink('account/manage') . '" METHOD=post>
<INPUT TYPE=image NAME="Login" ALT="Login" SRC="'.$template_path.'/images/global/buttons/sbutton_login.gif" BORDER=0 WIDTH=120 HEIGHT=18></div>
</TD></TR></FORM></TABLE></TABLE>';
}
else
$error= Validator::getLastError();
}
else
$error= 'Wrong code to change password.';
}
else
$error = 'Account of this character or this character doesn\'t exist.';
}
if(!empty($error))
echo '<span style="color: red"><b>'.$error.'</b></span><br />Please enter code from e-mail and name of one character from account. Then press Submit.<BR>
<FORM ACTION="' . getLink('account/lost') . '?action=checkcode" METHOD=post>
<TABLE CELLSPACING=1 CELLPADDING=4 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="'.$config['vdarkborder'].'" class="white"><B>Code & character name</B></TD></TR>
<TR><TD BGCOLOR="'.$config['darkborder'].'">
Your code:&nbsp;<INPUT TYPE=text NAME="code" VALUE="" SIZE="40")><BR />
Character:&nbsp;<INPUT TYPE=text NAME="character" VALUE="" SIZE="40")><BR />
</TD></TR>
</TABLE>
<BR>
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%><TR><TD><div style="text-align:center">
' . $twig->render('buttons.submit.html.twig') . '</div>
</TD></TR></FORM></TABLE></TABLE>';
}
$twig->display('account/lost/form.html.twig');

View File

@@ -0,0 +1,49 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Lost Account';
$code = isset($_REQUEST['code']) ? trim($_REQUEST['code']) : '';
$character = isset($_REQUEST['character']) ? stripslashes(trim($_REQUEST['character'])) : '';
if(empty($code) || empty($character))
$twig->display('account/lost/check-code.html.twig', [
'code' => $code,
'characters' => $character,
]);
else
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($character);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if($account->isLoaded()) {
if($account->getCustomField('email_code') == $code) {
$twig->display('account/lost/check-code.finish.html.twig', [
'character' => $character,
'code' => $code,
]);
}
else {
$error = 'Wrong code to change password.';
}
}
else {
$error = "Account of this character or this character doesn't exist.";
}
}
if(!empty($error)) {
$twig->display('error_box.html.twig', [
'errors' => [$error],
]);
echo '<br/>';
$twig->display('account/lost/check-code.html.twig', [
]);
}

View File

@@ -0,0 +1,61 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Lost Account';
$email = $_REQUEST['email'];
$nick = stripslashes($_REQUEST['nick']);
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if($account->isLoaded()) {
if($account->getCustomField('email_next') < time()) {
if($account->getEMail() == $email) {
$newCode = generateRandomString(30, true, false, true);
$mailBody = $twig->render('mail.account.lost.code.html.twig', [
'newCode' => $newCode,
'account' => $account,
'nick' => $nick,
]);
$accountEMail = $account->getCustomField('email');
if(_mail($accountEMail, configLua('serverName') . ' - Recover your account', $mailBody)) {
$account->setCustomField('email_code', $newCode);
$account->setCustomField('email_next', (time() + setting('core.mail_lost_account_interval')));
echo '<br />Details about steps required to recover your account has been sent to <b>' . $accountEMail . '</b>. You should receive this email within 15 minutes. Please check your inbox/spam directory.';
}
else {
$account->setCustomField('email_next', (time() + 60));
error('An error occurred while sending email! Try again later or contact with admin. For Admin: More info can be found in system/logs/mailer-error.log</p>');
}
}
else {
echo 'Invalid e-mail to account of character <b>' . htmlspecialchars($nick) . '</b>. Try again.';
}
}
else {
$inSec = (int)$account->getCustomField('email_next') - time();
$minutesLeft = floor($inSec / 60);
$secondsLeft = $inSec - ($minutesLeft * 60);
$timeLeft = $minutesLeft.' minutes '.$secondsLeft.' seconds';
$timeRounded = ceil(setting('core.mail_lost_account_interval') / 60);
echo "Account of selected character (<b>" . escapeHtml($nick) . "</b>) received e-mail in last $timeRounded minutes. You must wait $timeLeft before you can use Lost Account Interface again.";
}
}
else {
echo "Player or account of player <b>" . htmlspecialchars($nick) . "</b> doesn't exist.";
}
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost') . '?action=step1&action_type=email&nick=' . urlencode($nick),
]);

View File

@@ -0,0 +1,84 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Lost Account';
$newPassword = $_REQUEST['passor'];
$code = $_REQUEST['code'];
$character = stripslashes($_REQUEST['character']);
if(empty($code) || empty($character) || empty($newPassword)) {
echo '<span style="color: red"><b>Error. Try again.</b></span><br/>Please enter code from e-mail and name of one character from account. Then press Submit.<br>';
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost/check-code')
]);
}
else
{
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($character);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if($account->isLoaded()) {
if($account->getCustomField('email_code') == $code) {
if(Validator::password($newPassword)) {
$tmp_new_pass = $newPassword;
if(USE_ACCOUNT_SALT) {
$salt = generateRandomString(10, false, true, true);
$tmp_new_pass = $salt . $newPassword;
$account->setCustomField('salt', $salt);
}
$account->setPassword(encrypt($tmp_new_pass));
$account->save();
$account->setCustomField('email_code', '');
$mailBody = $twig->render('mail.account.lost.new-password.html.twig', [
'account' => $account,
'newPassword' => $newPassword,
]);
$statusMsg = '';
if(_mail($account->getCustomField('email'), configLua('serverName') . ' - Your new password', $mailBody)) {
$statusMsg = '<br /><small>New password work! Sent e-mail with your password and account name. You should receive this e-mail in 15 minutes. You can login now with new password!';
}
else {
$statusMsg = '<br /><p class="error">New password work! An error occurred while sending email! You will not receive e-mail with new password. For Admin: More info can be found in system/logs/mailer-error.log';
}
$twig->display('account/lost/finish.new-password.html.twig', [
'statusMsg' => $statusMsg,
'newPassword' => $newPassword,
]);
}
else {
$error = Validator::getLastError();
}
}
else {
$error = 'Wrong code to change password.';
}
}
else {
$error = "Account of this character or this character doesn't exist.";
}
}
if(!empty($error)) {
$twig->display('error_box.html.twig', [
'errors' => [$error],
]);
echo '<br/>';
$twig->display('account/lost/check-code.html.twig', [
'code' => $code,
'character' => $character,
]);
}

View File

@@ -0,0 +1,30 @@
<?php
$title = 'Lost Account';
if($account->isLoaded()) {
if($account->getCustomField('email_next') < time()) {
$twig->display('account/lost/email.html.twig', [
'nick' => $nick,
]);
}
else {
$inSec = (int)$account->getCustomField('email_next') - time();
$minutesLeft = floor($inSec / 60);
$secondsLeft = $inSec - ($minutesLeft * 60);
$timeLeft = $minutesLeft.' minutes '.$secondsLeft.' seconds';
$timeRounded = ceil(setting('core.mail_lost_account_interval') / 60);
echo "Account of selected character (<b>" . escapeHtml($nick) . "</b>) received e-mail in last $timeRounded minutes. You must wait $timeLeft before you can use Lost Account Interface again.";
}
}
else {
echo "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
}
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost'),
]);

View File

@@ -0,0 +1,26 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Lost Account';
if($account->isLoaded()) {
$account_key = $account->getCustomField('key');
if(!empty($account_key)) {
$twig->display('account/lost/recovery-key.html.twig', [
'nick' => $nick,
]);
}
else {
echo 'Account of this character has no recovery key!';
}
}
else {
echo "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
}
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost'),
]);

View File

@@ -0,0 +1,40 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Lost Account';
$recKey = trim($_REQUEST['key']);
$nick = stripslashes($_REQUEST['nick']);
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if($account->isLoaded()) {
$accountKey = $account->getCustomField('key');
if(!empty($accountKey)) {
if($accountKey == $recKey) {
$twig->display('account/lost/step2.html.twig', [
'nick' => $nick,
'recKey' => $recKey,
]);
}
else {
echo 'Wrong recovery key!';
}
}
else {
echo 'Account of this character has no recovery key!';
}
}
else
echo "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost') . '?action=step1&action_type=reckey&nick=' . urlencode($nick),
]);

View File

@@ -0,0 +1,91 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Lost Account';
$recKey = trim($_REQUEST['key']);
$nick = stripslashes($_REQUEST['nick']);
$newPassword = trim($_REQUEST['passor']);
$newEmail = trim($_REQUEST['email']);
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if($account->isLoaded()) {
$accountKey = $account->getCustomField('key');
if(!empty($accountKey)) {
if($accountKey == $recKey) {
if(Validator::password($newPassword)) {
if(Validator::email($newEmail)) {
$account->setEMail($newEmail);
$tmp_new_pass = $newPassword;
if(USE_ACCOUNT_SALT)
{
$salt = generateRandomString(10, false, true, true);
$tmp_new_pass = $salt . $newPassword;
}
$account->setPassword(encrypt($tmp_new_pass));
$account->save();
if(USE_ACCOUNT_SALT) {
$account->setCustomField('salt', $salt);
}
$statusMsg = '';
if($account->getCustomField('email_next') < time()) {
$mailBody = $twig->render('mail.account.lost.new-email.html.twig', [
'account' => $account,
'newPassword' => $newPassword,
'newEmail' => $newEmail,
]);
if(_mail($account->getCustomField('email'), $config['lua']['serverName']." - New password to your account", $mailBody)) {
$statusMsg = '<br /><small>Sent e-mail with your account name and password to new e-mail. You should receive this e-mail in 15 minutes. You can login now with new password!</small>';
}
else {
$statusMsg = '<br /><p class="error">An error occurred while sending email! You will not receive e-mail with this informations. For Admin: More info can be found in system/logs/mailer-error.log</p>';
}
}
else {
$statusMsg = '<br /><small>You will not receive e-mail with this informations.</small>';
}
$twig->display('account/lost/finish.new-email.html.twig', [
'statusMsg' => $statusMsg,
'account' => $account,
'newPassword' => $newPassword,
'newEmail' => $newEmail,
]);
}
else {
echo Validator::getLastError();
}
}
else {
echo Validator::getLastError();
}
}
else {
echo 'Wrong recovery key!';
}
}
else {
echo 'Account of this character has no recovery key!';
}
}
else {
echo "Player or account of player <b>" . escapeHtml($nick) . "</b> doesn't exist.";
}
$twig->display('account.back_button.html.twig', [
'new_line' => true,
'center' => true,
'action' => getLink('account/lost') . '?action=step1&action_type=reckey&nick=' . urlencode($nick),
]);

View File

@@ -0,0 +1,24 @@
<?php
defined('MYAAC') or die('Direct access not allowed!');
$title = 'Lost Account';
$nick = stripslashes($_REQUEST['nick']);
$player = new OTS_Player();
$account = new OTS_Account();
$player->find($nick);
if($player->isLoaded()) {
$account = $player->getAccount();
}
if (ACTION == 'email') {
require __DIR__ . '/email/step-1.php';
}
else if (ACTION == 'recovery-key') {
require __DIR__ . '/recovery-key/step-1.php';
}
else {
$twig->display('account/lost/no-action.html.twig');
}

View File

@@ -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 <b>'.$guild_name.'</b>.'.$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 <b>' . $player->getName() . '</b> has been invited to your guild.',

View File

@@ -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())
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(

View File

@@ -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 = ', lookbody, lookfeet, lookhead, looklegs, looktype';
if($db->hasColumn('players', 'lookaddons')) {
$outfit .= ', lookaddons';
$outfit_addons = true;
}
}
$configHighscoresPerPage = setting('core.highscores_per_page');
@@ -146,17 +140,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 +216,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,11 +247,23 @@ foreach($highscores as $id => &$player)
$player['link'] = getPlayerLink($player['name'], false);
$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="" />';
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;
}
}
else {
unset($highscores[$id]);
$show_link_to_next_page = true;
@@ -263,6 +283,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 +319,8 @@ $twig->display('highscores.html.twig', [
'types' => $types,
'linkPreviousPage' => $linkPreviousPage,
'linkNextPage' => $linkNextPage,
'totalResults' => $totalResults,
'page' => $page,
'baseLink' => $baseLink,
'updatedAt' => $updatedAt,
]);

View File

@@ -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,86 +33,89 @@ 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';
if($db->hasColumn('players', 'skull_type')) {
$skull_type = 'skull_type';
}
}
$skull_time = 'skulltime';
if($db->hasColumn('players', '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
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
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) {
$settingVocations = setting('core.vocations');
$settingVocationsAmount = setting('core.vocations_amount');
$players = [];
foreach($playersOnline as $player) {
$skull = '';
if (setting('core.online_skulls'))
{
if($player['skulltime'] > 0)
{
if($player['skull'] == 3)
if($player['skulltime'] > 0) {
if($player['skull'] == 3) {
$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"/>';
elseif($player['skull'] == 5)
}
elseif($player['skull'] == 5) {
$skull = ' <img style="border: 0;" src="images/black_skull.gif"/>';
}
}
if(isset($player['promotion'])) {
if((int)$player['promotion'] > 0)
$player['vocation'] += ($player['promotion'] * $config['vocations_amount']);
$player['vocation'] += ($player['promotion'] * $settingVocationsAmount);
}
$players_data[] = array(
$players[] = 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
'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'],
);
if (setting('core.online_vocations')) {
$vocs[($player['vocation'] > $config['vocations_amount'] ? $player['vocation'] - $config['vocations_amount'] : $player['vocation'])]++;
$vocations[($player['vocation'] > $settingVocationsAmount ? $player['vocation'] - $settingVocationsAmount : $player['vocation'])]++;
}
}
$record = '';
if(count($players_data) > 0) {
$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', $config['lua']['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) {
@@ -121,15 +127,22 @@ if(count($players_data) > 0) {
$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');
?>

View File

@@ -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 '<pre>';
var_dump($route[1], $route[3], $route[2]);
var_dump($pluginRoute[1], $pluginRoute[3], $pluginRoute[2]);
echo '/<pre>';
*/
}
$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;
}

View File

@@ -28,6 +28,15 @@ if (!IS_CLI) {
$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 [
'name' => 'MyAAC',
'settings' => [
@@ -694,7 +703,14 @@ Sent by MyAAC,<br/>
'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' => [
'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,
],
'account_mail_change' => [
@@ -1062,6 +1078,12 @@ 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.',
'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',
@@ -1074,6 +1096,12 @@ Sent by MyAAC,<br/>
'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',
@@ -1228,6 +1256,14 @@ Sent by MyAAC,<br/>
'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',
@@ -1268,7 +1304,7 @@ Sent by MyAAC,<br/>
'name' => 'Data Center',
'type' => 'text',
'desc' => 'Server Location, will be shown on online page',
'default' => 'Frankfurt - Germany',
'default' => 'Poland - Warsaw',
],
[
'type' => 'section',
@@ -1571,13 +1607,14 @@ Sent by MyAAC,<br/>
'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) {
global $db;
if ($value == 'coins' && !$db->hasColumn('accounts', '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;

View File

@@ -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();
}

View File

@@ -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,13 @@ class CacheClearCommand extends Command
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');
return Command::SUCCESS;
}

View File

@@ -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);
}

View File

@@ -0,0 +1,36 @@
<?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

@@ -0,0 +1,36 @@
<?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,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
{

View File

@@ -0,0 +1,40 @@
<?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,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 {

View File

@@ -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();

View File

@@ -53,9 +53,6 @@ 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();
}

View File

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

View File

@@ -532,8 +532,9 @@ 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']))) {
@@ -689,7 +690,10 @@ class Plugins {
}
}
if($continue) {
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();
@@ -713,13 +717,8 @@ class Plugins {
}
clearCache();
return true;
}
}
return false;
}
public static function isEnabled($pluginFileName): bool
{

View File

@@ -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,28 +23,21 @@ class Settings implements \ArrayAccess
return self::$instance;
}
public function load()
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) {
$this->settingsDatabase[$setting->name][$setting->key] = $setting->value;
$settingsDatabase[$setting->name][$setting->key] = $setting->value;
}
if ($cache->enabled()) {
$cache->set('settings', serialize($this->settingsDatabase), 600);
}
return $settingsDatabase;
});
}
public function save($pluginName, $values)
public function save($pluginName, $values): bool
{
$this->loadPlugin($pluginName);
@@ -104,7 +94,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 +107,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();
@@ -217,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'];
@@ -230,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);
@@ -383,7 +368,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 +408,7 @@ class Settings implements \ArrayAccess
}
#[\ReturnTypeWillChange]
public function offsetUnset($offset)
public function offsetUnset($offset): void
{
$this->loadPlugin($offset);
@@ -455,7 +440,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])) {
@@ -472,24 +457,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'];
}
@@ -523,7 +506,7 @@ class Settings implements \ArrayAccess
return $ret;
}
private function updateValuesAsked($offset)
private function updateValuesAsked($offset): void
{
$pluginKeyName = $offset;
if (strpos($offset, '.')) {
@@ -539,7 +522,7 @@ class Settings implements \ArrayAccess
}
}
private function loadPlugin($offset)
private function loadPlugin($offset): void
{
$this->updateValuesAsked($offset);
@@ -568,7 +551,7 @@ class Settings implements \ArrayAccess
}
}
public static function saveConfig($config, $filename, &$content = '')
public static function saveConfig($config, $filename, &$content = ''): bool|int
{
$content = "<?php" . PHP_EOL;

View File

@@ -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()) {
@@ -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')

View File

@@ -1,7 +1,26 @@
{% if new_line is defined and new_line %}
<br/>
{% endif %}
<form action="{% if action is not defined %}{{ getLink('account/manage') }}{% else %}{{ action }}{% endif %}" method="post">
{% set _center = false %}
{% if center is defined and center %}
{% set _center = true %}
{% endif %}
{% if _center %}
<table border="0" cellspacing="1" cellpadding="4" width="100%">
<tbody>
<tr>
<td align="center">
{% endif %}
<form action="{% if action is not defined %}{{ getLink('account/manage') }}{% else %}{{ action }}{% endif %}" method="post">
{{ csrf() }}
{{ include('buttons.back.html.twig') }}
</form>
</form>
{% if _center %}
</td>
</tr>
</tbody>
</table>
{% endif %}

View File

@@ -1,36 +0,0 @@
The Lost Account Interface can help you to get back your account name and password. Please enter your character name and select what you want to do.<br/>
<form action="{{ getLink('account/lost') }}?action=step1" method="post">
{{ csrf() }}
<input type="hidden" name="character" value="">
<table cellspacing="1" cellpadding="4" border="0" width="100%">
<tr>
<td bgcolor="{{ config.vdarkborder }}" class="white"><b>Please enter your character name</b></td>
</tr>
<tr>
<td bgcolor="{{ config.darkborder }}">
<input type="text" name="nick" size="40" autofocus/><br>
</td>
</tr>
</table>
<table cellspacing="1" cellpadding="4" border="0" width="100%">
<tr>
<td bgcolor="{{ config.vdarkborder }}" class="white"><b>What do you want?</b></td>
</tr>
<tr>
<td bgcolor="{{ config.darkborder }}">
<input type="radio" name="action_type" id="action_type_email" value="email">
<label for="action_type_email"> Send me new password and my account name to account e-mail adress.</label><br/>
<input type=radio name="action_type" id="action_type_key" value="reckey">
<label for="action_type_key"> I got <b>recovery key</b> and want set new password and e-mail adress to my account.</label><br/>
</td>
</tr>
</table>
<br/>
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td align="center">
{{ include('buttons.submit.html.twig') }}
</td>
</tr>
</table>
</form>

View File

@@ -1,10 +0,0 @@
Please select action.<br/>
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td align="center">
<a href="{{ getLink('account/lost') }}" border="0">
{{ include('buttons.back.html.twig') }}
</a>
</td>
</tr>
</table>

View File

@@ -0,0 +1,33 @@
Please enter new password to your account and repeat to make sure you remember password.<BR>
<form action="{{ getLink('account/lost/email/set-new-password') }}" method="post">
<input type="hidden" name="character" value="{{ character }}">
<input type="hidden" name="code" value="{{ code }}">
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white"><B>Passwords</B></th>
</tr>
</thead>
<tbody>
<tr>
<td>
New password:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="password" ID="passor" name="passor" value="" size="40"><br/>
Repeat new password:&nbsp;<input TYPE="password" ID="passor2" name="passor2" value="" size="40"><br/>
</td>
</tr>
</tbody>
</table>
<br/>
<table style="width: 100%">
<tr>
<td>
<div style="text-align: center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</div>
</td>
</tr>
</table>
</form>

View File

@@ -0,0 +1,30 @@
Please enter code from e-mail and name of one character from account. Then press Submit.<br/>
<form action="{{ getLink('account/lost/check-code') }}" method="post">
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white">
<b>Code & character name</b>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Your code:&nbsp;<input type="text" name="code" value="{{ code }}" size="40"><br/>
Character:&nbsp;<input type="text" name="character" value="{{ character }}" size="40"><br/>
</td>
</tr>
</tbody>
</table>
<br>
<table style="width: 100%">
<tr>
<td align="center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</td>
</tr>
</table>
</form>

View File

@@ -0,0 +1,33 @@
Please enter e-mail to account with this character.<br/>
<form action="{{ getLink('account/lost/email/send-code') }}" method="post">
<input type=hidden name="character">
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white"><b>Please enter e-mail to account</b></th>
</tr>
</thead>
<tbody>
<tr>
<td>
Character: <input type=text name="nick" value="{{ nick }}" size="40" readonly="readonly"><br/>
E-mail to account: <input type=text name="email" value="" size="40"><br/>
</td>
</tr>
</tbody>
</table>
<br>
<table style="width: 100%">
<tr>
<td>
<div style="text-align:center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</div>
</td>
</tr>
</table>
</form>

View File

@@ -0,0 +1,33 @@
Your account name, new password and new e-mail.<br/>
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white">
<b>Your account name, new password and new e-mail</b>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Account name:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>{{ account.getName() }}</b><br/>
New password:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>{{ newPassword }}</b><br/>
New e-mail address:&nbsp;<b>{{ newEmail }}</b><br/>
{{ statusMsg|raw }}
</td>
</tr>
</tbody>
</table>
<br>
<table style="width: 100%">
<tr>
<td align="center">
<form action="{{ getLink('account/manage') }}" method="post">
{{ include('buttons.login.html.twig') }}
</form>
</td>
</tr>
</table>

View File

@@ -0,0 +1,30 @@
New password to your account is below. Now you can log in.<BR>
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white"><b>Changed password</b></th>
</tr>
</thead>
<tbody>
<tr>
<td>
New password:&nbsp;<b>{{ newPassword }}</b><br/>
Account name:&nbsp;&nbsp;&nbsp;<i>(Already on your e-mail)</i><br/>
{{ statusMsg|raw }}
</td>
</tr>
</tbody>
</table>
<br/>
<table style="width: 100%">
<tr>
<td align="center">
<form action="{{ getLink('account/manage') }}">
{% set button_name = 'Login' %}
{% include('buttons.base.html.twig') %}
</form>
</td>
</tr>
</table>

View File

@@ -0,0 +1,41 @@
The Lost Account Interface can help you to get back your account name and password. Please enter your character name and select what you want to do.<br/>
<form action="{{ getLink('account/lost/step-1') }}" method="post">
{{ csrf() }}
<input type="hidden" name="character" value="">
<table class="myaac-table" style="width: 100%">
<thead>
<tr>
<th class="white"><b>Please enter your character name</b></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="text" name="nick" size="40" autofocus/><br>
</td>
</tr>
</tbody>
</table>
<table style="width: 100%; border-spacing: 1px">
<tr>
<td style="padding: 4px; background: {{ config('vdarkborder') }}" class="white"><b>What do you want?</b></td>
</tr>
<tr>
<td style="padding: 4px; background: {{ config('darkborder') }}">
<input type="radio" name="action" id="action_type_email" value="email">
<label for="action_type_email"> Send me new password and my account name to account e-mail address.</label><br/>
<input type=radio name="action" id="action_type_key" value="recovery-key">
<label for="action_type_key"> I got <b>recovery key</b> and want set new password and e-mail address to my account.</label><br/>
</td>
</tr>
</table>
<br/>
<table style="width: 100%">
<tr>
<td align="center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</td>
</tr>
</table>
</form>

View File

@@ -0,0 +1,10 @@
Please select action.<br/>
<table style="width: 100%">
<tr>
<td align="center">
<a href="{{ getLink('account/lost') }}">
{{ include('buttons.back.html.twig') }}
</a>
</td>
</tr>
</table>

View File

@@ -0,0 +1,34 @@
If you enter right recovery key you will see form to set new e-mail and password to account. To this e-mail will be send your new password and account name.<BR>
<form action="{{ getLink('account/lost/recovery-key/step-2') }}" method="post">
<table class="myaac-table" style="width: 100%;">
<thead>
<tr>
<th class="white">
<b>Please enter your recovery key</b>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Character name:&nbsp;<input type=text name="nick" value="{{ nick }}" size="40" readonly="readonly"><br/>
Recovery key:&nbsp;&nbsp;&nbsp;&nbsp;<input type="text" name="key" value="" size="40"><br/>
</td>
</tr>
</tbody>
</table>
<br>
<table style="width: 100%">
<tr>
<td>
<div style="text-align:center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</div>
</td>
</tr>
</table>
</form>

View File

@@ -0,0 +1,35 @@
Set new password and e-mail to your account.<br>
<form action="{{ getLink('account/lost/step-3') }}" method="post">
<input type="hidden" name="character" value="">
<table class="myaac-table" style="width: 100%">
<thead>
<tr>
<th class="white">
<b>Please enter new password and e-mail</b>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Account of character:&nbsp;&nbsp;<input type="text" name="nick" value="{{ nick }}" size="40" readonly="readonly"><br/>
New password:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input id="passor" type="password" name="passor" value="" size="40"><br/>
Repeat new password:&nbsp;&nbsp;<input id="passor2" type="password" name="passor" value="" size="40"><br/>
New e-mail address:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input id="email" type="text" name="email" value="" size="40"><br/>
<input type="hidden" name="key" VALUE="{{ recKey }}">
</td>
</tr>
</tbody>
</table>
<br>
<table style="width: 100%">
<tr>
<td align="center">
{% set button_name = 'Submit' %}
{% include('buttons.base.html.twig') %}
</td>
</tr>
</table>
</form>

View File

@@ -16,6 +16,13 @@
<input class="form-control" type="text" id="mail_to" name="mail_to" value="{{ mail_to }}"/>
</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">
<label for="mail_subject">Subject:</label>
<input class="form-control" type="text" id="mail_subject" name="mail_subject" value="{{ mail_subject }}" maxlength="30"/>

View File

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

View File

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

View File

@@ -0,0 +1,10 @@
You asked to reset your {{ config('lua')['serverName'] }} password.<br/>
<p>Account name: {{ account.getName() }}</p>
<br/>
To do so, please click this link:
<p>
<a href="{{ getLink('account/lost/check-code') }}?code={{ newCode }}&character={{ nick|urlencode }}">{{ getLink('account/lost/check-code') }}?code={{ newCode }}&character={{ nick|urlencode }}</a>
</p>
<p>or open page: <i>{{ getLink('account/lost/check-code') }}</i> and in field "code" write <b>{{ newCode }}</b></p>
<br/>
<p>If you did not request a password change, you may ignore this message and your password will remain unchanged.

View File

@@ -0,0 +1,7 @@
<h3>Your account name and new password!</h3>
<p>Changed password and e-mail to your account in Lost Account Interface on server <a href="{{ constant('BASE_URL') }}"><b>{{ config('lua')['serverName'] }}</b></a></p>
<p>Account name: <b>{{ account.getName() }}</b></p>
<p>New password: <b>{{ newPassword }}</b></p>
<p>E-mail: <b>{{ $newEmail }}</b> (this e-mail)</p>
<br/>
<p><u>It's automatic e-mail from OTS Lost Account System. Do not reply!</u></p>

View File

@@ -0,0 +1,6 @@
<h3>Your account name and password!</h3>
<p>Changed password to your account in Lost Account Interface on server <a href="{{ constant('BASE_URL') }}"><b>{{ config('lua')['serverName'] }}</b></a></p>
<p>Account name: <b>{{ account.getName() }}</b></p>
<p>New password: <b>{{ newPassword }}</b></p>
<br/>
<p><u>It's automatic e-mail from OTS Lost Account System. Do not reply!</u></p>

View File

@@ -1,3 +1,9 @@
{% 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 #}
{% if setting('core.online_vocations') %}
<br/>
@@ -84,7 +90,7 @@
</td>
</tr>
{% if setting('core.online_record') %}
{% if setting('core.online_record') and record|length > 0 %}
<tr>
<td class="LabelV150"><b>Online Record:</b></td>
<td>
@@ -155,7 +161,7 @@
{% endif %}
<td style="width:70%; text-align:left">
{{ player.name|raw }}{{ player.skull }}
{{ player.name|raw }}{{ player.skull|raw }}
</td>
<td style="width:10%">{{ player.level }}</td>
<td style="width:20%">{{ player.vocation }}</td>

View File

@@ -1,6 +1,9 @@
<style>
.myaac-table {border-spacing: 1px;}
.myaac-table tbody tr:nth-child(even) {background: {{ config.lightborder }}}
.myaac-table tbody tr:nth-child(odd) {background: {{ config.darkborder }}}
.myaac-table thead td {background: {{ config.vdarkborder }}; color: #ffffff !important;}
.myaac-table tfoot td {background: {{ config.vdarkborder }}; color: #ffffff !important;}
.myaac-table tbody td {padding: 4px; }
.myaac-table thead td {padding: 4px; background: {{ config.vdarkborder }}; color: #ffffff !important;}
.myaac-table thead th {padding: 4px; background: {{ config.vdarkborder }}; color: #ffffff !important;}
.myaac-table tfoot td {padding: 4px; background: {{ config.vdarkborder }}; color: #ffffff !important;}
</style>

View File

@@ -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',
@@ -152,3 +156,5 @@ $twig->addFilter($filter);
unset($function, $filter);
$hooks->trigger(HOOK_TWIG, ['twig' => $twig, 'twig_loader' => $twig_loader]);
$twig->addGlobal('cache', $cache);

View File

@@ -1,12 +1,18 @@
<?php
$config['menu_default_links_color'] = '#ffffff';
$config['menu_categories'] = array(
MENU_CATEGORY_NEWS => 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';

View File

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

View File

@@ -1,10 +1,10 @@
var list = new Array();
{% set i = 0 %}
{% for cat in categories %}
{% if cat.id != 'shops' or setting('core.gifts_system') %}
{% 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()

View File

@@ -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

View File

@@ -8,7 +8,9 @@ defined('MYAAC') or die('Direct access not allowed!');
<link rel="stylesheet" href="<?php echo $template_path; ?>/style.css" type="text/css" />
<script type="text/javascript">
<?php
$twig->display('menu.js.html.twig', array('categories' => $config['menu_categories']));
$menus = get_template_menus();
$twig->display('menu.js.html.twig', ['menus' => $menus]);
?>
</script>
<script type="text/javascript" src="tools/basic.js"></script>
@@ -28,11 +30,24 @@ defined('MYAAC') or die('Direct access not allowed!');
<div id="header"></div>
<!-- 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 -->
<div id="tabs">
<div id="tabs" style="<?= $tabsStyle; ?>">
<?php
foreach($config['menu_categories'] as $id => $cat) {
if($id != MENU_CATEGORY_SHOP || $config['gifts_system']) { ?>
if (($id != MENU_CATEGORY_SHOP || $config['gifts_system']) && isset($menus[$id])) { ?>
<span id="<?php echo $cat['id']; ?>" onclick="menuSwitch('<?php echo $cat['id']; ?>');"><?php echo $cat['name']; ?></span>
<?php
}

View File

@@ -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";
@@ -387,7 +391,7 @@ foreach($config['menu_categories'] as $id => $cat) {
?>
</div>
<?php
if($id == MENU_CATEGORY_SHOP || (!setting('core.gifts_system') && $i == $countElements)) {
if ($i == $countElements) {
?>
<div id='MenuBottom' style='background-image:url(<?php echo $template_path; ?>/images/general/box-bottom.gif);'></div>
<?php