Compare commits

..

48 Commits
v1.1 ... v1.3.2

Author SHA1 Message Date
slawkens
211b6ea698 Update CHANGELOG-1.x.md 2025-04-01 07:37:43 +02:00
slawkens
6d156ae080 Update CHANGELOG-1.x.md 2025-04-01 07:29:43 +02:00
slawkens
a5b3940e59 Prepare to release 1.3.2 2025-04-01 07:28:36 +02:00
slawkens
dbf73d0b61 Show/hide IP Ban Protection options depending on the value (enabled/disabled) 2025-03-31 20:38:42 +02:00
slawkens
65696f63e3 Fix debugbar/admin panel menu when using custom base_dir 2025-03-31 18:13:45 +02:00
slawkens
6341093578 Update version 2025-03-30 07:10:16 +02:00
slawkens
d25c71857f Do not require init.php in cache:clear command 2025-03-30 07:10:05 +02:00
slawkens
7dcb5c4a1f Update version to 1.x-dev 2025-03-26 22:02:56 +01:00
slawkens
ff1723b756 Release v1.3.1 2025-03-19 20:37:44 +01:00
slawkens
1a5771ad51 Fix migrate:run command 2025-03-16 20:33:53 +01:00
slawkens
6fac883659 Replace links with from accountmanagement to account/manage 2025-03-16 12:39:07 +01:00
slawkens
4a6896b446 getPremDays: returns -1 if freePremium 2025-03-15 22:48:59 +01:00
slawkens
0852fba6f0 Release v1.3 2025-03-10 20:26:25 +01:00
slawkens
9239a4f419 Fix the second "Save" button -> addition to previous commit 2025-03-10 12:46:33 +01:00
slawkens
00fe1adc15 Fix: add possibility to remove all menu items 2025-03-10 10:48:12 +01:00
slawkens
c2f55791c0 Nothing important, just better code style 2025-03-03 20:07:59 +01:00
slawkens
464492d826 Update OTS_Account.php 2025-02-26 16:16:45 +01:00
slawkens
887b5068ad Fix house links 2025-02-15 12:15:35 +01:00
slawkens
4c5cc8b573 Change monster link to $_GET ?name= 2025-02-15 12:03:44 +01:00
slawkens
529bdcf016 Use latest outfit-images host from @gesior 2025-02-12 18:20:24 +01:00
slawkens
3e3f4bb5a5 Fix long title on headline.php 2025-02-12 16:17:03 +01:00
slawkens
aa52df6e2e Fix menu colors once again, plus add !important tag 2025-02-09 20:54:47 +01:00
slawkens
3b31915c22 Update CHANGELOG.md 2025-02-09 12:25:56 +01:00
slawkens
1c6cda4df9 Update year 2025-02-09 11:50:14 +01:00
slawkens
cf51f7aa8d Release v1.2 2025-02-09 11:32:34 +01:00
slawkens
ed89b99cd1 Addition to previous commit, allow list types with spaces 2025-02-09 01:29:32 +01:00
slawkens
9d7fc98e1e Fix if vocation name has more words 2025-02-09 01:16:15 +01:00
slawkens
f646856e20 Unification of the variable menu_default_links_color 2025-02-09 01:02:14 +01:00
slawkens
f97f8cbe87 Move admin.menus.header html to twig 2025-02-09 00:47:46 +01:00
slawkens
3da3e62c5b Option to reset menus 2025-02-09 00:42:11 +01:00
slawkens
d5dd7297b5 Fix deprecation warnings from jquery 2025-02-09 00:03:39 +01:00
slawkens
73de93a561 Rework menus: Different categories can have different colors 2025-02-08 23:56:58 +01:00
slawkens
ae1161d770 Add template_name to twig variables 2025-02-08 23:43:15 +01:00
slawkens
4455964db4 Update cypress.yml 2025-02-02 22:41:31 +01:00
slawkens
84870dbf2d Update release.sh 2025-02-02 22:39:06 +01:00
slawkens
329153fda6 Fix branch name in workflows 2025-02-02 22:38:40 +01:00
slawkens
4b6024dc45 Save settings in a transaction 2025-02-02 22:36:18 +01:00
slawkens
28fef952f8 feat: Settings: enable Save button only if changes has been made 2025-02-02 22:36:17 +01:00
slawkens
4fda4f643b feat: Settings: password input with hide/show options 2025-02-02 21:55:16 +01:00
slawkens
19686725dc Add HOOK_INIT, executed just after $hooks are loaded 2025-02-02 16:17:49 +01:00
slawkens
a73fb1003e Fix HOOK_STARTUP location 2025-02-02 16:17:24 +01:00
slawkens
b46ddb43d0 Twig session(key) function + reworked session functions to accept multi-array like in Laravel
Important: getSession returns NULL now instead of false if session value not found
2025-02-02 16:16:59 +01:00
slawkens
de468a8dcd Fixed need to click on button second time 2025-02-02 14:22:57 +01:00
slawkens
ea51ad27c3 Fix online status + vocation for TFS 0.x 2025-02-01 00:35:22 +01:00
dependabot[bot]
d2a4748a59 Bump twig/twig from 3.18.0 to 3.19.0 (#284)
Bumps [twig/twig](https://github.com/twigphp/Twig) from 3.18.0 to 3.19.0.
- [Changelog](https://github.com/twigphp/Twig/blob/3.x/CHANGELOG)
- [Commits](https://github.com/twigphp/Twig/compare/v3.18.0...v3.19.0)

---
updated-dependencies:
- dependency-name: twig/twig
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-29 20:00:58 +01:00
slawkens
a1ed209591 Update README.md 2025-01-27 22:58:32 +01:00
slawkens
34321613d6 Start v1.1.1 2025-01-27 22:57:40 +01:00
slawkens
19b290feb7 Update CHANGELOG.md 2025-01-27 22:48:32 +01:00
41 changed files with 424 additions and 193 deletions

View File

@@ -1,9 +1,9 @@
name: Cypress name: Cypress
on: on:
pull_request: pull_request:
branches: [master] branches: [main]
push: push:
branches: [master] branches: [main]
jobs: jobs:
cypress: cypress:
@@ -35,7 +35,7 @@ jobs:
- name: Checkout MyAAC - name: Checkout MyAAC
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
ref: master ref: main
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:

View File

@@ -1,9 +1,9 @@
name: PHP Linting name: PHP Linting
on: on:
pull_request: pull_request:
branches: [master] branches: [main]
push: push:
branches: [master] branches: [main]
jobs: jobs:
phplint: phplint:

View File

@@ -2,9 +2,9 @@ name: "PHPStan"
on: on:
pull_request: pull_request:
branches: [master] branches: [main]
push: push:
branches: [master] branches: [main]
jobs: jobs:
tests: tests:

View File

@@ -1,5 +1,54 @@
# Changelog # Changelog
## [1.3.2 - 01.04.2025]
### Fixed
* Fix debugBar/admin panel menu when using custom base_dir (https://github.com/slawkens/myaac/commit/65696f63e3aac02ff952ea81279e7cb2fa7570fb)
### Changed
* Settings: Show/hide IP Ban Protection options depending on the value (enabled/disabled) (https://github.com/slawkens/myaac/commit/dbf73d0b61b45601ae95e51b23c051c2704169c5)
* Do not require init.php in cache:clear command (https://github.com/slawkens/myaac/commit/d25c71857f767834239bbffacd00fdc671adb157)
## [1.3.1 - 19.03.2025]
### Fixed
* Fixed migrate:run command (https://github.com/slawkens/myaac/commit/1a5771ad51e595fe13368a0721b059c4ecefb17d)
### Changed
* Small adjustments (https://github.com/slawkens/myaac/commit/6fac883659f581baac1361826d046410156f1e58, https://github.com/slawkens/myaac/commit/4a6896b4469968b9904292734cf6c14ba5eeef14)
## [1.3 - 10.03.2025]
### Changed
* Use latest outfit-images host from @gesior (https://github.com/slawkens/myaac/commit/529bdcf016dd0f9dffbc34d81f99a046a9ddb70d)
* Change monster link to $_GET ?name= (https://github.com/slawkens/myaac/commit/4c5cc8b573b2b3e7ec00a22b7ede30a68083a924)
### Fixed
* Fixed house links (https://github.com/slawkens/myaac/commit/887b5068ad11c4cdab614afd34525caba785ce13)
* Fixed long title on headline.php (https://github.com/slawkens/myaac/commit/3e3f4bb5a514158ec8777684ca6c7f1c2a37bed5)
* Fixed menu colors once again, plus add !important tag (https://github.com/slawkens/myaac/commit/aa52df6e2ec92cafc25b655ae907bf2e1746d9cc)
* Fix: add possibility to remove all menu items in admin panel (https://github.com/slawkens/myaac/commit/00fe1adc15ea7646596d755f6e6e1f7854ffc1d5, https://github.com/slawkens/myaac/commit/9239a4f4198c3ad260802ac3b47e9c41b80b754e)
## [1.2 - 09.02.2025]
### Added
* Twig session(key) function + reworked session functions to accept multi-array like in Laravel (https://github.com/slawkens/myaac/commit/b46ddb43d03ef7e5fc34e555e92e856bdc905691)
* add template_name to twig variables (https://github.com/slawkens/myaac/commit/ae1161d77050bda181802b4496c9de920a7bb1bc)
* add HOOK_INIT, executed just after $hooks are loaded (https://github.com/slawkens/myaac/commit/19686725dc810f63a07f049f82c66cf336d90ca6)
### Changed
* settings: password input hide/show, enable Save button only if changes has been made, save settings in transaction (https://github.com/slawkens/myaac/commit/4fda4f643b60a151179e5dd4f04912fb2618d98f, https://github.com/slawkens/myaac/commit/28fef952f857b79d64bc7495ffa5e1999e68e192, https://github.com/slawkens/myaac/commit/4b6024dc451accadb6c469fa282a9a764c1c0a81)
* rework menus: Different categories can have different colors + Option to reset menus (https://github.com/slawkens/myaac/commit/73de93a561f6b13111e019075724357d8a617249, https://github.com/slawkens/myaac/commit/3da3e62c5b12390d75de9b3320729bcca6e0b458)
### Fixed
* highscores: Fix online status + vocation for TFS 0.x (https://github.com/slawkens/myaac/commit/ea51ad27c38be88d86514cb979bb394fcfbef1f0)
* clear cache button in admin bar needed to be clicked twice until it worked (https://github.com/slawkens/myaac/commit/ea51ad27c38be88d86514cb979bb394fcfbef1f0)
* HOOK_STARTUP location (https://github.com/slawkens/myaac/commit/a73fb1003ee3f812cf182d1834d65f08e6f60d1f)
* if vocation name has more words (https://github.com/slawkens/myaac/commit/9d7fc98e1e0a96b59ecc1a7c39800a64445db364)
### Updated
* Bump twig/twig from 3.18.0 to 3.19.0 (#284)
## [1.1 - 27.01.2025] ## [1.1 - 27.01.2025]
### Changed ### Changed
@@ -10,7 +59,7 @@
### Fixed ### Fixed
* general fixes in the tibiacom template menus, better support for custom menus * general fixes in the tibiacom template menus, better support for custom menus
* make functions_custom.php optional * make functions_custom.php optional (https://github.com/slawkens/myaac/commit/dc2b5afd9980984e2b259c9fc99f2ade46f70a5a)
* error in CLI, where BASE_URL is not defined (https://github.com/slawkens/myaac/commit/4d749b881582f64b5a46196dbbb5ee8097127f03) * error in CLI, where BASE_URL is not defined (https://github.com/slawkens/myaac/commit/4d749b881582f64b5a46196dbbb5ee8097127f03)
* hook ACCOUNT_LOGIN_BEFORE_ACCOUNT location (https://github.com/slawkens/myaac/commit/669c447fca8643ce56d9ef8c1374ec647c780998) * hook ACCOUNT_LOGIN_BEFORE_ACCOUNT location (https://github.com/slawkens/myaac/commit/669c447fca8643ce56d9ef8c1374ec647c780998)

View File

@@ -1,3 +1,3 @@
* Gesior.pl (2007 - 2008) * Gesior.pl (2007 - 2008)
* Slawkens (2009 - 2023) * Slawkens (2009 - 2025)
* Contributors listed in CONTRIBUTORS.txt * Contributors listed in CONTRIBUTORS.txt

View File

@@ -10,12 +10,12 @@ Official website: https://my-aac.org
[![OpenTibia Discord](https://img.shields.io/discord/288399552581468162)](https://discord.gg/2J39Wus) [![OpenTibia Discord](https://img.shields.io/discord/288399552581468162)](https://discord.gg/2J39Wus)
[![Closed Issues](https://img.shields.io/github/issues-closed-raw/slawkens/myaac)](https://github.com/slawkens/myaac/issues?q=is%3Aissue+is%3Aclosed) [![Closed Issues](https://img.shields.io/github/issues-closed-raw/slawkens/myaac)](https://github.com/slawkens/myaac/issues?q=is%3Aissue+is%3Aclosed)
| Version | Status | Branch | Requirements | | Version | Status | Branch | Requirements |
|:--------|:-----------------------|:--------|:---------------| |:--------|:-----------------------|:-------|:---------------|
| **1.x** | **Active development** | develop | **PHP >= 8.1** | | **1.x** | **Active development** | master | **PHP >= 8.1** |
| 0.9.x | Not developed anymore | 0.9 | PHP >= 7.2.5 | | 0.9.x | Not developed anymore | 0.9 | PHP >= 7.2.5 |
| 0.8.x | Active support | master | PHP >= 7.2.5 | | 0.8.x | Active support | 0.8 | PHP >= 7.2.5 |
| 0.7.x | End Of Life | 0.7 | PHP >= 5.3.3 | | 0.7.x | End Of Life | 0.7 | PHP >= 5.3.3 |
### Requirements ### Requirements

View File

@@ -7,7 +7,7 @@ $hooks->register('debugbar_admin_head_end', HOOK_ADMIN_HEAD_END, function ($para
return; return;
} }
$debugBarRenderer = $debugBar->getJavascriptRenderer(); $debugBarRenderer = $debugBar->getJavascriptRenderer(BASE_URL . 'vendor/maximebf/debugbar/src/DebugBar/Resources/');
echo $debugBarRenderer->renderHead(); echo $debugBarRenderer->renderHead();
}); });
$hooks->register('debugbar_admin_body_end', HOOK_ADMIN_BODY_END, function ($params) { $hooks->register('debugbar_admin_body_end', HOOK_ADMIN_BODY_END, function ($params) {
@@ -17,6 +17,6 @@ $hooks->register('debugbar_admin_body_end', HOOK_ADMIN_BODY_END, function ($para
return; return;
} }
$debugBarRenderer = $debugBar->getJavascriptRenderer(); $debugBarRenderer = $debugBar->getJavascriptRenderer(BASE_URL . 'vendor/maximebf/debugbar/src/DebugBar/Resources/');
echo $debugBarRenderer->render(); echo $debugBarRenderer->render();
}); });

View File

@@ -27,11 +27,11 @@ $pluginThemes = Plugins::getThemes();
if (isset($_POST['template'])) { if (isset($_POST['template'])) {
$template = $_POST['template']; $template = $_POST['template'];
if (isset($_POST['menu'])) { if (isset($_POST['save'])) {
$post_menu = $_POST['menu']; $post_menu = $_POST['menu'] ?? [];
$post_menu_link = $_POST['menu_link']; $post_menu_link = $_POST['menu_link'] ?? [];
$post_menu_blank = $_POST['menu_blank']; $post_menu_blank = $_POST['menu_blank'] ?? [];
$post_menu_color = $_POST['menu_color']; $post_menu_color = $_POST['menu_color'] ?? [];
if (count($post_menu) != count($post_menu_link)) { if (count($post_menu) != count($post_menu_link)) {
echo 'Menu count is not equal menu links. Something went wrong when sending form.'; echo 'Menu count is not equal menu links. Something went wrong when sending form.';
return; return;
@@ -59,11 +59,7 @@ if (isset($_POST['template'])) {
} }
} }
$cache = Cache::getInstance(); onTemplateMenusChange();
if ($cache->enabled()) {
$cache->delete('template_menus');
}
success('Saved at ' . date('H:i')); success('Saved at ' . date('H:i'));
} }
@@ -82,38 +78,48 @@ if (isset($_POST['template'])) {
return; return;
} }
if (isset($_GET['reset_colors'])) {
if (isset($config['menu_default_color'])) {
Menu::where('template', $template)->update(['color' => str_replace('#', '', $config['menu_default_color'])]);
success('Colors has been reset.');
}
else {
warning('There is no default color defined, cannot reset colors.');
}
}
if (!isset($config['menu_categories'])) { if (!isset($config['menu_categories'])) {
echo "No menu categories set in template config.php.<br/>This template doesn't support dynamic menus."; echo "No menu categories set in template config.php.<br/>This template doesn't support dynamic menus.";
return; return;
} }
if (isset($_GET['reset_colors'])) {
foreach ($config['menu_categories'] as $id => $options) {
$color = $options['default_links_color'] ?? ($config['menu_default_links_color'] ?? ($config['menu_default_color'] ?? '#ffffff'));
Menu::where('template', $template)->where('category', $id)->update(['color' => str_replace('#', '', $color)]);
}
onTemplateMenusChange();
success('Colors has been reset at ' . date('H:i'));
}
if (isset($_GET['reset_menus'])) {
$configMenus = config('menus');
if (isset($configMenus)) {
Plugins::installMenus($template, config('menus'), true);
onTemplateMenusChange();
success('Menus has been reset at ' . date('H:i'));
}
else {
error("This template don't support reinstalling menus.");
}
}
$title = 'Menus - ' . $template; $title = 'Menus - ' . $template;
$canResetColors = isset($config['menu_default_color']) || isset($config['menu_default_links_color']);
foreach ($config['menu_categories'] as $id => $options) {
if (isset($options['default_links_color'])) {
$canResetColors = true;
}
}
$twig->display('admin.menus.header.html.twig', [
'template' => $template,
'canResetColors' => $canResetColors
]);
?> ?>
<div align="center" class="text-center">
<p class="note">You are editing: <?= $template ?><br/><br/>
Hint: You can drag menu items.<br/>
Hint: Add links to external sites using: <b>http://</b> or <b>https://</b> prefix.<br/>
Not all templates support blank and colorful links.
</p>
<?php if (isset($config['menu_default_color'])) {?>
<form method="post" action="?p=menus&reset_colors" onsubmit="return confirm('Do you really want to reset colors?');">
<?php csrf(); ?>
<input type="hidden" name="template" value="<?php echo $template ?>"/>
<button type="submit" class="btn btn-danger">Reset Colors to default</button>
</form>
<br/>
<?php } ?>
</div>
<?php <?php
$menus = Menu::query() $menus = Menu::query()
->select('name', 'link', 'blank', 'color', 'category', 'ordering') ->select('name', 'link', 'blank', 'color', 'category', 'ordering')
@@ -129,7 +135,7 @@ if (isset($_POST['template'])) {
<form method="post" id="menus-form" action="?p=menus"> <form method="post" id="menus-form" action="?p=menus">
<?php csrf(); ?> <?php csrf(); ?>
<input type="hidden" name="template" value="<?php echo $template ?>"/> <input type="hidden" name="template" value="<?php echo $template ?>"/>
<button type="submit" class="btn btn-info">Save</button><br/><br/> <button type="submit" name="save" class="btn btn-info">Save</button><br/><br/>
<div class="row"> <div class="row">
<?php foreach ($config['menu_categories'] as $id => $cat): ?> <?php foreach ($config['menu_categories'] as $id => $cat): ?>
<div class="col-md-12 col-lg-6"> <div class="col-md-12 col-lg-6">
@@ -143,12 +149,13 @@ if (isset($_POST['template'])) {
if (isset($menus[$id])) { if (isset($menus[$id])) {
$i = 0; $i = 0;
foreach ($menus[$id] as $menu): foreach ($menus[$id] as $menu):
$color = (empty($menu['color']) ? ($cat['default_links_color'] ?? ($config['menu_default_links_color'] ?? ($config['menu_default_color'] ?? '#ffffff'))) : '#' . $menu['color']);
?> ?>
<li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>"><label>Name:</label> <input type="text" name="menu[<?php echo $id ?>][]" value="<?php echo escapeHtml($menu['name']); ?>"/> <li class="ui-state-default" id="list-<?php echo $id ?>-<?php echo $i ?>"><label>Name:</label> <input type="text" name="menu[<?php echo $id ?>][]" value="<?php echo escapeHtml($menu['name']); ?>"/>
<label>Link:</label> <input type="text" name="menu_link[<?php echo $id ?>][]" value="<?php echo $menu['link'] ?>"/> <label>Link:</label> <input type="text" name="menu_link[<?php echo $id ?>][]" value="<?php echo $menu['link'] ?>"/>
<input type="hidden" name="menu_blank[<?php echo $id ?>][]" value="0"/> <input type="hidden" name="menu_blank[<?php echo $id ?>][]" value="0"/>
<label><input class="blank-checkbox" type="checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label> <label><input class="blank-checkbox" type="checkbox" <?php echo($menu['blank'] == 1 ? 'checked' : '') ?>/><span title="Open in New Window">New Window</span></label>
<input class="color-picker" type="text" name="menu_color[<?php echo $id ?>][]" value="<?php echo (empty($menu['color']) ? ($config['menu_default_color'] ?? '#ffffff') : $menu['color']); ?>"/> <input class="color-picker" type="text" name="menu_color[<?php echo $id ?>][]" value="<?php echo $color; ?>"/>
<a class="remove-button" id="remove-button-<?php echo $id ?>-<?php echo $i ?>"><i class="fas fa-trash"></a></i></li> <a class="remove-button" id="remove-button-<?php echo $id ?>-<?php echo $i ?>"><i class="fas fa-trash"></a></i></li>
<?php $i++; $last_id[$id] = $i; <?php $i++; $last_id[$id] = $i;
endforeach; endforeach;
@@ -161,7 +168,7 @@ if (isset($_POST['template'])) {
</div> </div>
<div class="row pb-2"> <div class="row pb-2">
<div class="col-md-12"> <div class="col-md-12">
<button type="submit" class="btn btn-info">Save</button> <button type="submit" name="save" class="btn btn-info">Save</button>
<?php <?php
echo '<button type="button" class="btn btn-danger float-right" value="Cancel" onclick="window.location = \'' . ADMIN_URL . '?p=menus\';"><i class="fas fa-cancel"></i> Cancel</button>'; echo '<button type="button" class="btn btn-danger float-right" value="Cancel" onclick="window.location = \'' . ADMIN_URL . '?p=menus\';"><i class="fas fa-cancel"></i> Cancel</button>';
?> ?>
@@ -172,7 +179,6 @@ if (isset($_POST['template'])) {
$twig->display('admin.menus.js.html.twig', array( $twig->display('admin.menus.js.html.twig', array(
'menus' => $menus, 'menus' => $menus,
'last_id' => $last_id, 'last_id' => $last_id,
'menu_default_color' => $config['menu_default_color'] ?? '#ffffff'
)); ));
?> ?>
<?php <?php
@@ -194,3 +200,11 @@ if (isset($_POST['template'])) {
'templates' => $templates 'templates' => $templates
)); ));
} }
function onTemplateMenusChange(): void
{
$cache = Cache::getInstance();
if ($cache->enabled()) {
$cache->delete('template_menus');
}
}

View File

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

18
composer.lock generated
View File

@@ -2637,16 +2637,16 @@
}, },
{ {
"name": "twig/twig", "name": "twig/twig",
"version": "v3.18.0", "version": "v3.19.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/twigphp/Twig.git", "url": "https://github.com/twigphp/Twig.git",
"reference": "acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50" "reference": "d4f8c2b86374f08efc859323dbcd95c590f7124e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50", "url": "https://api.github.com/repos/twigphp/Twig/zipball/d4f8c2b86374f08efc859323dbcd95c590f7124e",
"reference": "acffa88cc2b40dbe42eaf3a5025d6c0d4600cc50", "reference": "d4f8c2b86374f08efc859323dbcd95c590f7124e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2701,7 +2701,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/twigphp/Twig/issues", "issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.18.0" "source": "https://github.com/twigphp/Twig/tree/v3.19.0"
}, },
"funding": [ "funding": [
{ {
@@ -2713,7 +2713,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-12-29T10:51:50+00:00" "time": "2025-01-29T07:06:14+00:00"
}, },
{ {
"name": "voku/portable-ascii", "name": "voku/portable-ascii",
@@ -2910,7 +2910,7 @@
], ],
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": {}, "stability-flags": [],
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
@@ -2921,6 +2921,6 @@
"ext-xml": "*", "ext-xml": "*",
"ext-dom": "*" "ext-dom": "*"
}, },
"platform-dev": {}, "platform-dev": [],
"plugin-api-version": "2.6.0" "plugin-api-version": "2.3.0"
} }

View File

@@ -76,6 +76,8 @@ require_once SYSTEM . 'status.php';
$twig->addGlobal('config', $config); $twig->addGlobal('config', $config);
$twig->addGlobal('status', $status); $twig->addGlobal('status', $status);
$hooks->trigger(HOOK_STARTUP);
// backward support for gesior // backward support for gesior
if(setting('core.backward_support')) { if(setting('core.backward_support')) {
define('INITIALIZED', true); define('INITIALIZED', true);
@@ -117,8 +119,6 @@ if(setting('core.backward_support')) {
require_once SYSTEM . 'router.php'; require_once SYSTEM . 'router.php';
$hooks->trigger(HOOK_STARTUP);
// anonymous usage statistics // anonymous usage statistics
// sent only when user agrees // sent only when user agrees
if(setting('core.anonymous_usage_statistics')) { if(setting('core.anonymous_usage_statistics')) {

View File

@@ -22,7 +22,7 @@ if [ $1 = "prepare" ]; then
mkdir -p tmp mkdir -p tmp
# get myaac from git archive # get myaac from git archive
git archive --format zip --output tmp/myaac.zip master git archive --format zip --output tmp/myaac.zip main
cd tmp/ || exit cd tmp/ || exit

View File

@@ -121,7 +121,7 @@ function getPlayerLink($name, $generate = true, bool $colored = false): string
function getMonsterLink($name, $generate = true): string function getMonsterLink($name, $generate = true): string
{ {
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'monsters/' . urlencode($name); $url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'monsters?name=' . urlencode($name);
if(!$generate) return $url; if(!$generate) return $url;
return generateLink($url, $name); return generateLink($url, $name);
@@ -129,16 +129,14 @@ function getMonsterLink($name, $generate = true): string
function getHouseLink($name, $generate = true): string function getHouseLink($name, $generate = true): string
{ {
if(is_numeric($name)) if(is_numeric($name)) {
{
$house = House::find(intval($name), ['name']); $house = House::find(intval($name), ['name']);
if ($house) { if ($house) {
$name = $house->name; $name = $house->name;
} }
} }
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'houses?name=' . urlencode($name);
$url = BASE_URL . (setting('core.friendly_urls') ? '' : 'index.php/') . 'houses/' . urlencode($name);
if(!$generate) return $url; if(!$generate) return $url;
return generateLink($url, $name); return generateLink($url, $name);
@@ -984,31 +982,29 @@ function load_config_lua($filename)
continue; continue;
} }
$tmp_exp = explode('=', $line, 2); $tmp_exp = explode('=', $line, 2);
if(strpos($line, 'dofile') !== false) if(str_contains($line, 'dofile')) {
{
$delimiter = '"'; $delimiter = '"';
if(strpos($line, $delimiter) === false) if(!str_contains($line, $delimiter)) {
$delimiter = "'"; $delimiter = "'";
}
$tmp = explode($delimiter, $line); $tmp = explode($delimiter, $line);
$result = array_merge($result, load_config_lua($config['server_path'] . $tmp[1])); $result = array_merge($result, load_config_lua($config['server_path'] . $tmp[1]));
} }
else if(count($tmp_exp) >= 2) else if(count($tmp_exp) >= 2) {
{
$key = trim($tmp_exp[0]); $key = trim($tmp_exp[0]);
if(0 !== strpos($key, '--')) if(!str_starts_with($key, '--')) {
{
$value = trim($tmp_exp[1]); $value = trim($tmp_exp[1]);
if(strpos($value, '--') !== false) {// found some deep comment if(str_contains($value, '--')) {// found some deep comment
$value = preg_replace('/--.*$/i', '', $value); $value = preg_replace('/--.*$/i', '', $value);
} }
if(is_numeric($value)) if(is_numeric($value))
$result[$key] = (float) $value; $result[$key] = (float) $value;
elseif(in_array(@$value[0], array("'", '"')) && in_array(@$value[strlen($value) - 1], array("'", '"'))) elseif(in_array(@$value[0], array("'", '"')) && in_array(@$value[strlen($value) - 1], array("'", '"')))
$result[$key] = (string) substr(substr($value, 1), 0, -1); $result[$key] = substr(substr($value, 1), 0, -1);
elseif(in_array($value, array('true', 'false'))) elseif(in_array($value, array('true', 'false')))
$result[$key] = ($value === 'true') ? true : false; $result[$key] = $value === 'true';
elseif(@$value[0] === '{') { elseif(@$value[0] === '{') {
// arrays are not supported yet // arrays are not supported yet
// just ignore the error // just ignore the error
@@ -1016,7 +1012,7 @@ function load_config_lua($filename)
} }
else else
{ {
foreach($result as $tmp_key => $tmp_value) // load values definied by other keys, like: dailyFragsToBlackSkull = dailyFragsToRedSkull foreach($result as $tmp_key => $tmp_value) // load values defined by other keys, like: dailyFragsToBlackSkull = dailyFragsToRedSkull
$value = str_replace($tmp_key, $tmp_value, $value); $value = str_replace($tmp_key, $tmp_value, $value);
$ret = @eval("return $value;"); $ret = @eval("return $value;");
if((string) $ret == '' && trim($value) !== '""') // = parser error if((string) $ret == '' && trim($value) !== '""') // = parser error
@@ -1030,8 +1026,7 @@ function load_config_lua($filename)
} }
} }
$result = array_merge($result, isset($config['lua']) ? $config['lua'] : array()); return array_merge($result, $config['lua'] ?? []);
return $result;
} }
function str_replace_first($search,$replace, $subject) { function str_replace_first($search,$replace, $subject) {
@@ -1057,17 +1052,36 @@ function get_browser_real_ip() {
return '0'; return '0';
} }
function setSession($key, $data): void { function setSession($key, $value = null): void {
$_SESSION[setting('core.session_prefix') . $key] = $data; if (!is_array($key)) {
$key = [$key => $value];
}
foreach ($key as $arrayKey => $arrayValue) {
if (is_null($arrayValue)) {
unsetSession($arrayKey);
}
else {
$_SESSION[setting('core.session_prefix') . $arrayKey] = $arrayValue;
}
}
} }
function getSession($key) { function getSession($key) {
$key = setting('core.session_prefix') . $key; return $_SESSION[setting('core.session_prefix') . $key] ?? null;
return $_SESSION[$key] ?? false;
} }
function unsetSession($key): void { function unsetSession($key): void {
unset($_SESSION[setting('core.session_prefix') . $key]); unset($_SESSION[setting('core.session_prefix') . $key]);
} }
function session($key): mixed {
if (is_array($key)) {
setSession($key);
return null;
}
return getSession($key);
}
function csrf(bool $return = false): string { function csrf(bool $return = false): string {
return CsrfToken::create($return); return CsrfToken::create($return);
} }
@@ -1107,10 +1121,6 @@ function getTopPlayers($limit = 5, $skill = 'level') {
$columns[] = 'lookaddons'; $columns[] = 'lookaddons';
} }
if ($db->hasColumn('players', 'online')) {
$columns[] = 'online';
}
return Player::query() return Player::query()
->select($columns) ->select($columns)
->withOnlineStatus() ->withOnlineStatus()

View File

@@ -50,6 +50,7 @@ $cache = Cache::getInstance();
global $hooks; global $hooks;
$hooks = new Hooks(); $hooks = new Hooks();
$hooks->load(); $hooks->load();
$hooks->trigger(HOOK_INIT);
// twig // twig
require_once SYSTEM . 'twig.php'; require_once SYSTEM . 'twig.php';

View File

@@ -443,19 +443,19 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
throw new E_OTS_NotLoaded(); throw new E_OTS_NotLoaded();
} }
$configFreePremium = configLua('freePremium');
if(isset($configFreePremium) && getBoolean($configFreePremium)) {return -1;}
if(isset($this->data['premium_ends_at']) || isset($this->data['premend'])) { if(isset($this->data['premium_ends_at']) || isset($this->data['premend'])) {
$col = isset($this->data['premium_ends_at']) ? 'premium_ends_at' : 'premend'; $col = isset($this->data['premium_ends_at']) ? 'premium_ends_at' : 'premend';
$ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60)); $ret = ceil(($this->data[$col] - time()) / (24 * 60 * 60));
return $ret > 0 ? $ret : 0; return max($ret, 0);
} }
if($this->data['premdays'] == 0) { if($this->data['premdays'] == 0) {
return 0; return 0;
} }
global $config;
if(isset($config['lua']['freePremium']) && getBoolean($config['lua']['freePremium'])) return -1;
if($this->data['premdays'] == self::GRATIS_PREMIUM_DAYS){ if($this->data['premdays'] == self::GRATIS_PREMIUM_DAYS){
return self::GRATIS_PREMIUM_DAYS; return self::GRATIS_PREMIUM_DAYS;
} }
@@ -1011,7 +1011,7 @@ class OTS_Account extends OTS_Row_DAO implements IteratorAggregate, Countable
public function logAction($action) public function logAction($action)
{ {
$ip = get_browser_real_ip(); $ip = get_browser_real_ip();
if(strpos($ip, ":") === false) { if(!str_contains($ip, ":")) {
$ipv6 = '0'; $ipv6 = '0';
} }
else { else {

View File

@@ -14,12 +14,12 @@ $account_logged = new OTS_Account();
// stay-logged with sessions // stay-logged with sessions
$current_session = getSession('account'); $current_session = getSession('account');
if($current_session !== false) if($current_session)
{ {
$account_logged->load($current_session); $account_logged->load($current_session);
if($account_logged->isLoaded() && $account_logged->getPassword() == getSession('password') if($account_logged->isLoaded() && $account_logged->getPassword() == getSession('password')
//&& (!isset($_SESSION['admin']) || admin()) //&& (!isset($_SESSION['admin']) || admin())
&& (getSession('remember_me') !== false || getSession('last_visit') > time() - 15 * 60)) { // login for 15 minutes if "remember me" is not used && (getSession('remember_me') || getSession('last_visit') > time() - 15 * 60)) { // login for 15 minutes if "remember me" is not used
$logged = true; $logged = true;
} }
else { else {

View File

@@ -21,9 +21,9 @@ $settingHighscoresCountryBox = setting('core.highscores_country_box');
if(config('account_country') && $settingHighscoresCountryBox) if(config('account_country') && $settingHighscoresCountryBox)
require SYSTEM . 'countries.conf.php'; require SYSTEM . 'countries.conf.php';
$list = $_GET['list'] ?? 'experience'; $list = urldecode($_GET['list'] ?? 'experience');
$page = $_GET['page'] ?? 1; $page = $_GET['page'] ?? 1;
$vocation = $_GET['vocation'] ?? 'all'; $vocation = urldecode($_GET['vocation'] ?? 'all');
if(!is_numeric($page) || $page < 1 || $page > PHP_INT_MAX) { if(!is_numeric($page) || $page < 1 || $page > PHP_INT_MAX) {
$page = 1; $page = 1;
@@ -234,10 +234,6 @@ foreach($highscores as $id => &$player)
$player['experience'] = number_format($player['experience']); $player['experience'] = number_format($player['experience']);
} }
if(!$settingHighscoresVocation) {
unset($player['vocation']);
}
$player['link'] = getPlayerLink($player['name'], false); $player['link'] = getPlayerLink($player['name'], false);
$player['flag'] = getFlagImage($player['country']); $player['flag'] = getFlagImage($player['country']);
if($settingHighscoresOutfit) { if($settingHighscoresOutfit) {

View File

@@ -30,11 +30,11 @@ $state = '';
$order = ''; $order = '';
$type = ''; $type = '';
if(isset($_GET['page']) && $_GET['page'] == 'view' && isset($_REQUEST['house'])) if(isset($_REQUEST['name']))
{ {
$beds = array("", "one", "two", "three", "fourth", "fifth"); $beds = array("", "one", "two", "three", "fourth", "fifth");
$houseName = $_REQUEST['house']; $houseName = urldecode($_REQUEST['name']);
$houseId = (Validator::number($_REQUEST['house']) ? $_REQUEST['house'] : -1); $houseId = (Validator::number($_REQUEST['name']) ? $_REQUEST['name'] : -1);
$selectHouse = $db->query('SELECT * FROM ' . $db->tableName('houses') . ' WHERE ' . $db->fieldName('name') . ' LIKE ' . $db->quote($houseName) . ' OR `id` = ' . $db->quote($houseId)); $selectHouse = $db->query('SELECT * FROM ' . $db->tableName('houses') . ' WHERE ' . $db->fieldName('name') . ' LIKE ' . $db->quote($houseName) . ' OR `id` = ' . $db->quote($houseId));
$house = array(); $house = array();
@@ -187,7 +187,7 @@ if(isset($_POST['town']) && isset($_POST['state']) && isset($_POST['order']) &&
$houseRent = 'Free'; $houseRent = 'Free';
} }
$houses[] = array('owner' => $owner, 'name' => $house['name'], 'size' => ($hasTilesColumn ? $house['tiles'] : $house['size']), 'rent' => $house['rent'], 'rentedBy' => $houseRent); $houses[] = array('owner' => $owner, 'name' => $house['name'], 'size' => ($hasTilesColumn ? $house['tiles'] : $house['size']), 'rent' => $house['rent'], 'rentedBy' => $houseRent, 'link' => getHouseLink($house['name'], false));
} }
$housesSearch = true; $housesSearch = true;

View File

@@ -100,7 +100,7 @@ function getColorByPercent($percent)
if(!$logged) if(!$logged)
{ {
echo 'You are not logged in. <a href="?subtopic=accountmanagement&redirect=' . BASE_URL . urlencode('?subtopic=polls') . '">Log in</a> to vote in polls.<br /><br />'; echo 'You are not logged in. <a href="' . getLink('account/manage') . '?redirect=' . BASE_URL . urlencode('?subtopic=polls') . '">Log in</a> to vote in polls.<br /><br />';
return; return;
} }

View File

@@ -39,10 +39,10 @@ return [
[['GET', 'POST'], 'guilds/{guild:string}', 'guilds/show.php'], [['GET', 'POST'], 'guilds/{guild:string}', 'guilds/show.php'],
['GET', 'highscores/{list:alphanum}/{vocation:alphanum}/{page:int}', 'highscores.php'], ['GET', 'highscores/{list:string}/{vocation:string}/{page:int}', 'highscores.php'],
['GET', 'highscores/{list:alphanum}/{page:int}', 'highscores.php'], ['GET', 'highscores/{list:string}/{page:int}', 'highscores.php'],
['GET', 'highscores/{list:alphanum}/{vocation:alphanum}', 'highscores.php'], ['GET', 'highscores/{list:string}/{vocation:string}', 'highscores.php'],
['GET', 'highscores/{list:alphanum}', 'highscores.php'], ['GET', 'highscores/{list:string}', 'highscores.php'],
/* /*
'/^polls\/[0-9]+\/?$/' => array('subtopic' => 'polls', 'id' => '$1'), '/^polls\/[0-9]+\/?$/' => array('subtopic' => 'polls', 'id' => '$1'),
'/^spells\/[A-Za-z0-9-_%]+\/[A-Za-z0-9-_]+\/?$/' => array('subtopic' => 'spells', 'vocation' => '$1', 'order' => '$2'), '/^spells\/[A-Za-z0-9-_%]+\/[A-Za-z0-9-_]+\/?$/' => array('subtopic' => 'spells', 'vocation' => '$1', 'order' => '$2'),

View File

@@ -348,7 +348,7 @@ return [
], ],
'database_password' => [ 'database_password' => [
'name' => 'Database Password', 'name' => 'Database Password',
'type' => 'text', 'type' => 'password',
'default' => '', 'default' => '',
'show_if' => [ 'show_if' => [
'database_overwrite', '=', 'true' 'database_overwrite', '=', 'true'
@@ -1403,7 +1403,7 @@ Sent by MyAAC,<br/>
'name' => 'Outfit Images URL', 'name' => 'Outfit Images URL',
'type' => 'text', 'type' => 'text',
'desc' => 'Set to animoutfit.php for animated outfit', 'desc' => 'Set to animoutfit.php for animated outfit',
'default' => 'https://outfit-images.ots.me/outfit.php', 'default' => 'https://outfit-images.ots.me/latest/outfit.php',
], ],
'outfit_images_wrong_looktypes' => [ 'outfit_images_wrong_looktypes' => [
'name' => 'Outfit Images Wrong Looktypes', 'name' => 'Outfit Images Wrong Looktypes',
@@ -1622,14 +1622,20 @@ Sent by MyAAC,<br/>
'name' => 'Login Attempts Limit', 'name' => 'Login Attempts Limit',
'type' => 'number', 'type' => 'number',
'desc' => 'Number of incorrect login attempts before banning the IP', 'desc' => 'Number of incorrect login attempts before banning the IP',
'default' => 5, // Ajuste conforme necessário 'default' => 5,
'show_if' => [
'account_login_ipban_protection', '=', 'true'
]
], ],
'account_login_ban_time' => [ 'account_login_ban_time' => [
'name' => 'Ban Time (Minutes)', 'name' => 'Ban Time (Minutes)',
'type' => 'number', 'type' => 'number',
'desc' => 'Time in minutes the IP will be banned after exceeding login attempts', 'desc' => 'Time in minutes the IP will be banned after exceeding login attempts',
'default' => 30, // Ajuste conforme necessário 'default' => 30,
'show_if' => [
'account_login_ipban_protection', '=', 'true'
]
], ],
], ],
'callbacks' => [ 'callbacks' => [

View File

@@ -2,6 +2,7 @@
namespace MyAAC\Commands; namespace MyAAC\Commands;
use MyAAC\Hooks;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
@@ -16,7 +17,10 @@ class CacheClearCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output): int protected function execute(InputInterface $input, OutputInterface $output): int
{ {
require SYSTEM . 'init.php'; global $hooks;
$hooks = new Hooks();
$hooks->load();
$hooks->trigger(HOOK_INIT);
$io = new SymfonyStyle($input, $output); $io = new SymfonyStyle($input, $output);

View File

@@ -4,6 +4,7 @@ namespace MyAAC\Commands;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Style\SymfonyStyle;
@@ -16,7 +17,8 @@ class MigrateRunCommand extends Command
->addArgument('id', ->addArgument('id',
InputArgument::IS_ARRAY | InputArgument::REQUIRED, InputArgument::IS_ARRAY | InputArgument::REQUIRED,
'Id or ids of migration(s)' 'Id or ids of migration(s)'
); )
->addOption('down', 'd', InputOption::VALUE_NONE, 'Down');;
} }
protected function execute(InputInterface $input, OutputInterface $output): int protected function execute(InputInterface $input, OutputInterface $output): int
@@ -41,8 +43,10 @@ class MigrateRunCommand extends Command
} }
} }
$down = $input->getOption('down') ?? false;
foreach ($ids as $id) { foreach ($ids as $id) {
$this->executeMigration($id, $io); $this->executeMigration($id, $io, !$down);
} }
return Command::SUCCESS; return Command::SUCCESS;
@@ -52,13 +56,24 @@ class MigrateRunCommand extends Command
return file_exists(SYSTEM . 'migrations/' . $id . '.php'); return file_exists(SYSTEM . 'migrations/' . $id . '.php');
} }
private function executeMigration($id, $io): void private function executeMigration($id, $io, $_up = true): void
{ {
global $db; global $db;
$db->revalidateCache(); $db->revalidateCache();
require SYSTEM . 'migrations/' . $id . '.php'; require SYSTEM . 'migrations/' . $id . '.php';
$io->success('Migration ' . $id . ' successfully executed'); if ($_up) {
if (isset($up)) {
$up();
}
}
else {
if (isset($down)) {
$down();
}
}
$io->success('Migration ' . $id . ' successfully executed' . ($_up ? '' : ' (downgrade)'));
} }
} }

View File

@@ -49,8 +49,8 @@ class Player extends Model {
public function getVocationNameAttribute() public function getVocationNameAttribute()
{ {
$vocation = $this->vocation; $vocation = $this->vocation;
if (isset($this->promotion)) { if (isset($this->promotion) && $this->promotion > 0) {
$vocation *= $this->promotion; $vocation += ($this->promotion * setting('core.vocations_amount'));
} }
return config('vocations')[$vocation] ?? 'Unknown'; return config('vocations')[$vocation] ?? 'Unknown';
@@ -80,11 +80,17 @@ class Player extends Model {
$query->where($column, 0); $query->where($column, 0);
} }
public function scopeWithOnlineStatus($query) { public function scopeWithOnlineStatus($query)
{
global $db; global $db;
$query->when($db->hasTable('players_online'), function ($query) { if ($db->hasColumn('players', 'online')) {
$query->with('onlineTable'); $query->addSelect('online');
}); }
else {
$query->when($db->hasTable('players_online'), function ($query) {
$query->with('onlineTable');
});
}
} }
public function getOutfitUrlAttribute() { public function getOutfitUrlAttribute() {

View File

@@ -72,24 +72,32 @@ class Settings implements \ArrayAccess
} }
} }
$this->errors = []; global $db;
ModelsSettings::where('name', $pluginName)->delete();
foreach ($values as $key => $value) { try {
$errorMessage = ''; $db->beginTransaction();
if (isset($settings['settings'][$key]['callbacks']['beforeSave']) && !$settings['settings'][$key]['callbacks']['beforeSave']($key, $value, $errorMessage)) {
$this->errors[] = $errorMessage; $this->errors = [];
continue; ModelsSettings::where('name', $pluginName)->delete();
} foreach ($values as $key => $value) {
$errorMessage = '';
if (isset($settings['settings'][$key]['callbacks']['beforeSave']) && !$settings['settings'][$key]['callbacks']['beforeSave']($key, $value, $errorMessage)) {
$this->errors[] = $errorMessage;
continue;
}
try {
ModelsSettings::create([ ModelsSettings::create([
'name' => $pluginName, 'name' => $pluginName,
'key' => $key, 'key' => $key,
'value' => $value 'value' => $value
]); ]);
} catch (\PDOException $error) {
$this->errors[] = 'Error while saving setting (' . $pluginName . ' - ' . $key . '): ' . $error->getMessage();
} }
$db->commit();
} catch (\Exception $error) {
$db->rollBack();
$this->errors[] = 'Error while saving settings (' . $pluginName . ')<br/>' . $error->getMessage();
return false;
} }
$this->clearCache(); $this->clearCache();
@@ -247,7 +255,15 @@ class Settings implements \ArrayAccess
$min = $max = $step = ''; $min = $max = $step = '';
} }
if ($setting['type'] === 'password') {
echo '<div class="input-group" id="show-hide-' . $key . '">';
}
echo '<input class="form-control" type="' . $setting['type'] . '" name="settings[' . $key . ']" value="' . ($settingsDb[$key] ?? ($setting['default'] ?? '')) . '" id="' . $key . '"' . $min . $max . $step . '/>'; echo '<input class="form-control" type="' . $setting['type'] . '" name="settings[' . $key . ']" value="' . ($settingsDb[$key] ?? ($setting['default'] ?? '')) . '" id="' . $key . '"' . $min . $max . $step . '/>';
if ($setting['type'] === 'password') {
echo '<div class="input-group-append input-group-text"><a href=""><i class="fas fa-eye-slash" ></i></a></div></div>';
}
} }
else if($setting['type'] === 'textarea') { else if($setting['type'] === 'textarea') {

View File

@@ -5,6 +5,7 @@ const SKILL_BALANCE = -2;
$i = 0; $i = 0;
define('HOOK_INIT', ++$i);
define('HOOK_STARTUP', ++$i); define('HOOK_STARTUP', ++$i);
define('HOOK_BEFORE_PAGE', ++$i); define('HOOK_BEFORE_PAGE', ++$i);
define('HOOK_AFTER_PAGE', ++$i); define('HOOK_AFTER_PAGE', ++$i);
@@ -96,7 +97,7 @@ define('HOOK_CACHE_CLEAR', ++$i);
define('HOOK_INSTALL_FINISH', ++$i); define('HOOK_INSTALL_FINISH', ++$i);
define('HOOK_INSTALL_FINISH_END', ++$i); define('HOOK_INSTALL_FINISH_END', ++$i);
const HOOK_FIRST = HOOK_STARTUP; const HOOK_FIRST = HOOK_INIT;
define('HOOK_LAST', $i); define('HOOK_LAST', $i);
function is_sub_dir($path = NULL, $parent_folder = BASE): bool|string function is_sub_dir($path = NULL, $parent_folder = BASE): bool|string

View File

@@ -41,7 +41,7 @@ if(setting('core.template_allow_change'))
} }
else { else {
$template_session = getSession('template'); $template_session = getSession('template');
if ($template_session !== false) { if ($template_session) {
if (!preg_match("/[^A-z0-9_\-]/", $template_session)) { if (!preg_match("/[^A-z0-9_\-]/", $template_session)) {
$template_name = $template_session; $template_name = $template_session;
} }
@@ -133,6 +133,7 @@ if($forumSetting != '')
$template['link_forum'] = "<a href='" . $forumSetting . "' target='_blank'>"; $template['link_forum'] = "<a href='" . $forumSetting . "' target='_blank'>";
} }
$twig->addGlobal('template_name', $template_name);
$twig->addGlobal('template_path', $template_path); $twig->addGlobal('template_path', $template_path);
if($twig_loader) { if($twig_loader) {
$twig_loader->prependPath(BASE . $template_path); $twig_loader->prependPath(BASE . $template_path);
@@ -152,17 +153,40 @@ function get_template_menus(): array
return $result->toArray(); return $result->toArray();
}); });
$menus = array(); $configMenuCategories = config('menu_categories');
$configMenuDefaultColor = config('menu_default_links_color') ?? config('menu_default_color');
$menus = [];
foreach($result as $menu) { foreach($result as $menu) {
$link_full = strpos(trim($menu['link']), 'http') === 0 ? $menu['link'] : getLink($menu['link']); if (empty($menu['link'])) {
$menus[$menu['category']][] = array('name' => $menu['name'], 'link' => $menu['link'], 'link_full' => $link_full, 'blank' => $menu['blank'] == 1, 'target_blank' => ($menu['blank'] == 1 ? ' target="blank"' : ''), 'color' => $menu['color']); $menu['link'] = 'news';
}
$link_full = (str_starts_with(trim($menu['link']), 'http') ? $menu['link'] : getLink($menu['link']));
$target_blank = ($menu['blank'] == 1 ? ' target="blank"' : '');
$color = (empty($menu['color']) ? ($configMenuCategories[$menu['category']]['default_links_color'] ?? ($configMenuDefaultColor ?? '')) : $menu['color']);
$color = str_replace('#', '', $color);
if (in_array('#' . $color, [$configMenuCategories[$menu['category']]['default_links_color'] ?? '', $configMenuDefaultColor])) {
$color = '';
}
$style_color = (empty($color) ? '' : 'style="color: #' . $color . ' !important"');
$menus[$menu['category']][] = [
'name' => $menu['name'],
'link' => $menu['link'], 'link_full' => $link_full,
'blank' => $menu['blank'] == 1, 'target_blank' => $target_blank,
'color' => $color, 'style_color' => $style_color,
];
} }
$new_menus = array(); $new_menus = [];
/** /**
* @var array $configMenuCategories * @var array $configMenuCategories
*/ */
$configMenuCategories = config('menu_categories');
if($configMenuCategories === null) { if($configMenuCategories === null) {
return []; return [];
} }

View File

@@ -110,7 +110,7 @@ html { margin-top: 32px !important; }
<form method="post" action="{{ constant('ADMIN_URL') }}?p=dashboard"> <form method="post" action="{{ constant('ADMIN_URL') }}?p=dashboard">
{{ csrf() }} {{ csrf() }}
<input type="hidden" name="clear_cache" value="1" /> <input type="hidden" name="clear_cache" value="1" />
<a class="ab-item" href="#" onclick="confirm('Are you sure that you want to clear cache?') && $(this).closest('form').submit()" title="Clear Cache">Clear Cache</a> <a class="ab-item" href="javascript:void(0);" onclick="confirm('Are you sure that you want to clear cache?') && $(this).closest('form').submit()" title="Clear Cache">Clear Cache</a>
</form> </form>
</li> </li>
</ul> </ul>

View File

@@ -0,0 +1,31 @@
<div align="center" class="text-center">
<p class="note">You are editing: {{ template }}<br/><br/>
Hint: You can drag menu items.<br/>
Hint: Add links to external sites using: <b>http://</b> or <b>https://</b> prefix.<br/>
Not all templates support blank and colorful links.
</p>
<div class="row text-center">
<div class="col-md-2 col-sm-1"></div>
<div class="col-md-8 col-sm-10">
<div class="row justify-content-center">
{% if config('menus') is not null %}
<form method="post" action="?p=menus&reset_menus" onsubmit="return confirm('Do you really want to reset menus?');">
{{ csrf() }}
<input type="hidden" name="template" value="{{ template }}"/>
<button type="submit" class="btn btn-danger">Reset Menus to default</button>
</form>
<br/>
{% endif %}
{% if canResetColors %}
<form method="post" action="?p=menus&reset_colors" onsubmit="return confirm('Do you really want to reset colors?');">
{{ csrf() }}
<input type="hidden" name="template" value="{{ template }}"/>
<button type="submit" class="btn btn-warning" style="margin-left: 20px">Reset Colors to default</button>
</form>
<br/>
{% endif %}
</div>
</div>
<div class="col-md-2 col-sm-1"></div>
</div>
</div>

View File

@@ -1,31 +1,41 @@
<link type="text/css" rel="stylesheet" href="{{ constant('BASE_URL') }}tools/ext/jquery-ui/themes/base/jquery-ui.min.css"> <link type="text/css" rel="stylesheet" href="{{ constant('BASE_URL') }}tools/ext/jquery-ui/themes/base/jquery-ui.min.css">
<script> <script>
var last_id = []; let last_id = [];
let colors = [];
{% for cat, menu in menus %} {% for cat, menu in menus %}
last_id[{{ cat }}] = {{ last_id[cat] }}; last_id[{{ cat }}] = {{ last_id[cat] }};
{% endfor %} {% endfor %}
$(function () {
$(".sortable").sortable();
$(".sortable").disableSelection();
$(".remove-button").click(function () { {% set menuDefaultLinksColor = config('menu_default_links_color') %}
{% for cat, options in config('menu_categories') %}
colors[{{ cat }}] = '{{ options['default_links_color'] ?? (menuDefaultLinksColor ?? config('menu_default_color')) }}';
{% endfor %}
$(function () {
const $sortable = $(".sortable");
$sortable.sortable();
$sortable.disableSelection();
$(".remove-button").on('click', function () {
var id = $(this).attr("id"); var id = $(this).attr("id");
$('#list-' + id.replace('remove-button-', '')).remove(); $('#list-' + id.replace('remove-button-', '')).remove();
}); });
$(".add-button").click(function () { $(".add-button").on('click', function () {
var cat = $(this).attr("id").replace('add-button-', ''); var cat = $(this).attr("id").replace('add-button-', '');
var id = last_id[cat]; var id = last_id[cat];
last_id[cat]++; last_id[cat]++;
$('#sortable-' + cat).append('<li class="ui-state-default" id="list-' + cat + '-' + id + '"><label>Name:</label> <input type="text" name="menu[' + cat + '][]" value=""/> <label>Link:</label> <input type="text" name="menu_link[' + cat + '][]" value=""/><input type="hidden" name="menu_blank[' + cat + '][]" value="0" /> <label><input class="blank-checkbox" type="checkbox"/><span title="Open in New Window">New Window</span></label> <input class="color-picker" type="text" name="menu_color[' + cat + '][]" value="{{ menu_default_color }}" /><a class="remove-button" id="remove-button-' + cat + '-' + id + '"><i class="fas fa-trash"></i></a></li>'); //add input bo const color = colors[cat];
$('#remove-button-' + cat + '-' + id).click(function () { $('#sortable-' + cat).append('<li class="ui-state-default" id="list-' + cat + '-' + id + '"><label>Name:</label> <input type="text" name="menu[' + cat + '][]" value=""/> <label>Link:</label> <input type="text" name="menu_link[' + cat + '][]" value=""/><input type="hidden" name="menu_blank[' + cat + '][]" value="0" /> <label><input class="blank-checkbox" type="checkbox"/><span title="Open in New Window">New Window</span></label> <input class="color-picker" type="text" name="menu_color[' + cat + '][]" value="#' + color + '" /> <a class="remove-button" id="remove-button-' + cat + '-' + id + '"><i class="fas fa-trash"></i></a></li>'); //add input bo
$('#remove-button-' + cat + '-' + id).on('click', function () {
$('#list-' + $(this).attr("id").replace('remove-button-', '')).remove(); $('#list-' + $(this).attr("id").replace('remove-button-', '')).remove();
}); });
initialiceSpectrum(); initializeSpectrum();
}); });
$("#menus-form").submit(function (e) { $("#menus-form").on('submit', function (e) {
$('.blank-checkbox:not(:checked)').each(function (i, obj) { $('.blank-checkbox:not(:checked)').each(function (i, obj) {
$(obj).parent().prev().val("off"); $(obj).parent().prev().val("off");
}); });
@@ -52,11 +62,11 @@
<script type="text/javascript" src="{{ constant('BASE_URL') }}tools/js/spectrum.js"></script> <script type="text/javascript" src="{{ constant('BASE_URL') }}tools/js/spectrum.js"></script>
<link type="text/css" rel="stylesheet" href="{{ constant('BASE_URL') }}tools/css/spectrum.css"/> <link type="text/css" rel="stylesheet" href="{{ constant('BASE_URL') }}tools/css/spectrum.css"/>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () { $(function () {
initialiceSpectrum(); initializeSpectrum();
}); });
function initialiceSpectrum() { function initializeSpectrum() {
$(".color-picker").spectrum({ $(".color-picker").spectrum({
preferredFormat: "hex", preferredFormat: "hex",
showInput: true, showInput: true,

View File

@@ -80,7 +80,26 @@
} }
}); });
$('#settings').submit(function(e) { const noChangesText = "No changes has been made";
$('form')
.each(function(){
$(this).data('serialized', $(this).serialize())
})
.on('change input', function(){
const disable = $(this).serialize() === $(this).data('serialized');
$(this)
.find('input:submit, button:submit')
.prop('disabled', disable)
.prop('title', disable ? noChangesText : '')
;
})
.find('input:submit, button:submit')
.prop('disabled', true)
.prop('title', noChangesText)
;
$('#settings').on('submit', function(e) {
e.preventDefault(); e.preventDefault();
$.ajax({ $.ajax({
@@ -94,6 +113,13 @@
duration: 3000, duration: 3000,
escapeMarkup: false, escapeMarkup: false,
}).showToast(); }).showToast();
let $settings = $('#settings');
$settings.data('serialized', $settings.serialize());
$settings
.find('input:submit, button:submit')
.prop('disabled', true)
.prop('title', noChangesText);
}, },
error : function(response) { error : function(response) {
Toastify({ Toastify({
@@ -109,3 +135,27 @@
}); });
}); });
</script> </script>
<script>
{% for key, value in settings %}
{% if value.type == 'password' %}
$(function () {
$('#show-hide-{{ key}} a').on('click', function(event) {
event.preventDefault();
const $showHideIcon = $('#show-hide-{{ key}} i');
const $showHideInput = $('#show-hide-{{ key }} input');
if($showHideInput.attr('type') === 'text'){
$showHideInput.attr('type', 'password');
$showHideIcon.addClass('fa-eye-slash');
$showHideIcon.removeClass('fa-eye');
}else if($showHideInput.attr("type") === 'password'){
$showHideInput.attr('type', 'text');
$showHideIcon.removeClass('fa-eye-slash');
$showHideIcon.addClass('fa-eye');
}
});
});
{% endif %}
{% endfor %}
</script>

View File

@@ -114,7 +114,7 @@
{% else %} {% else %}
<b>Before you can create a guild you must login.</b> <b>Before you can create a guild you must login.</b>
<br/> <br/>
<form action="?subtopic=accountmanagement&redirect={{ getLink('guilds') }}" method="post"> <form action="{{ getLink('account/manage') }}?redirect={{ getLink('guilds') }}" method="post">
{{ csrf() }} {{ csrf() }}
{% include('buttons.login.html.twig') %} {% include('buttons.login.html.twig') %}
</form> </form>

View File

@@ -215,7 +215,7 @@
<tbody> <tbody>
<tr> <tr>
{% if not logged %} {% if not logged %}
<form action="?subtopic=accountmanagement&redirect={{ getGuildLink(guild_name|url_encode, false) }}" method="post"> <form action="{{ getLink('account/manage') }}?redirect={{ getGuildLink(guild_name|url_encode, false) }}" method="post">
{{ csrf() }} {{ csrf() }}
<td> <td>
{{ include('buttons.login.html.twig') }} {{ include('buttons.login.html.twig') }}

View File

@@ -9,19 +9,17 @@
<td> <td>
<label for="skillFilter">Choose a Skill</label> <label for="skillFilter">Choose a Skill</label>
<select onchange="location = this.value;" id="skillFilter"> <select onchange="location = this.value;" id="skillFilter">
{% set i = 0 %}
{% for link, name in types %} {% for link, name in types %}
<option value="{{ getLink('highscores') }}/{{ link }}{% if vocation is not null %}/{{ vocation }}{% endif %}" class="size_xs" {% if list is not null and list == link %}selected{% endif %}>{{ name }}</option> <option value="{{ getLink('highscores') }}/{{ link|urlencode }}{% if vocation is not null %}/{{ vocation|lower|urlencode }}{% endif %}" class="size_xs" {% if list is not null and list == link %}selected{% endif %}>{{ name }}</option>
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
<td> <td>
<label for="vocationFilter">Choose a vocation</label> <label for="vocationFilter">Choose a vocation</label>
<select onchange="location = this.value;" id="vocationFilter"> <select onchange="location = this.value;" id="vocationFilter">
<option value="{{ getLink('highscores') }}/{{ list }}" class="size_xs">[ALL]</option> <option value="{{ getLink('highscores') }}/{{ list|urlencode }}" class="size_xs">[ALL]</option>
{% set i = 0 %}
{% for i in 0..config.vocations_amount %} {% for i in 0..config.vocations_amount %}
<option value="{{ getLink('highscores') }}/{{ list }}/{{ config.vocations[i]|lower }}" class="size_xs" {% if vocationId is not null and vocationId == i %}selected{% endif %}>{{ config.vocations[i]}}</option> <option value="{{ getLink('highscores') }}/{{ list|urlencode }}/{{ config.vocations[i]|lower|urlencode }}" class="size_xs" {% if vocationId is not null and vocationId == i %}selected{% endif %}>{{ config.vocations[i]}}</option>
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
@@ -105,7 +103,7 @@
<tr bgcolor="{{ config.lightborder }}"> <tr bgcolor="{{ config.lightborder }}">
<td> <td>
{% for link, name in types %} {% for link, name in types %}
<a href="{{ getLink('highscores') }}/{{ link }}{% if vocation is not null %}/{{ vocation }}{% endif %}" class="size_xs">{{ name }}</a><br/> <a href="{{ getLink('highscores') }}/{{ link|urlencode }}{% if vocation is not null %}/{{ vocation|urlencode }}{% endif %}" class="size_xs">{{ name }}</a><br/>
{% endfor %} {% endfor %}
</td> </td>
</tr> </tr>
@@ -118,9 +116,9 @@
</tr> </tr>
<tr bgcolor="{{ config.lightborder }}"> <tr bgcolor="{{ config.lightborder }}">
<td> <td>
<a href="{{ getLink('highscores') }}/{{ list }}" class="size_xs">[ALL]</a><br/> <a href="{{ getLink('highscores') }}/{{ list|urlencode }}" class="size_xs">[ALL]</a><br/>
{% for i in 0..config.vocations_amount %} {% for i in 0..config.vocations_amount %}
<a href="{{ getLink('highscores') }}/{{ list }}/{{ config.vocations[i]|lower }}" class="size_xs">{{ config.vocations[i]}}</a><br/> <a href="{{ getLink('highscores') }}/{{ list|urlencode }}/{{ config.vocations[i]|lower|urlencode }}" class="size_xs">{{ config.vocations[i]}}</a><br/>
{% endfor %} {% endfor %}
</td> </td>
</tr> </tr>

View File

@@ -56,10 +56,9 @@ the search criteria and start a new search.
</td> </td>
<td> <td>
<form action="{{ getLink('houses/view') }}" method="post"> <a href="{{ house.link }}">
<input type="hidden" name="house" value="{{ house.name }}">
{{ include('buttons.view.html.twig') }} {{ include('buttons.view.html.twig') }}
</form> </a>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@@ -140,6 +140,11 @@ $function = new TwigFunction('csrfToken', function () {
}); });
$twig->addFunction($function); $twig->addFunction($function);
$function = new TwigFunction('session', function ($key) {
return session($key);
});
$twig->addFunction($function);
$filter = new TwigFilter('urlencode', function ($s) { $filter = new TwigFilter('urlencode', function ($s) {
return urlencode($s); return urlencode($s);
}); });

View File

@@ -1,5 +1,5 @@
<?php <?php
$config['menu_default_color'] = '#ffffff'; $config['menu_default_links_color'] = '#ffffff';
$config['menu_categories'] = array( $config['menu_categories'] = array(
MENU_CATEGORY_NEWS => array('id' => 'news', 'name' => 'Latest News'), MENU_CATEGORY_NEWS => array('id' => 'news', 'name' => 'Latest News'),
@@ -8,3 +8,5 @@ $config['menu_categories'] = array(
MENU_CATEGORY_LIBRARY => array('id' => 'library', 'name' => 'Library'), MENU_CATEGORY_LIBRARY => array('id' => 'library', 'name' => 'Library'),
MENU_CATEGORY_SHOP => array('id' => 'shops', 'name' => 'Shop') MENU_CATEGORY_SHOP => array('id' => 'shops', 'name' => 'Shop')
); );
$config['menus'] = require __DIR__ . '/menus.php';

View File

@@ -42,8 +42,6 @@ defined('MYAAC') or die('Direct access not allowed!');
<div id="mainsubmenu"> <div id="mainsubmenu">
<?php <?php
$default_menu_color = "ffffff";
foreach($menus as $category => $menu) { foreach($menus as $category => $menu) {
if(!isset($menus[$category])) { if(!isset($menus[$category])) {
continue; continue;
@@ -54,8 +52,8 @@ defined('MYAAC') or die('Direct access not allowed!');
$size = count($menus[$category]); $size = count($menus[$category]);
$i = 0; $i = 0;
foreach($menus[$category] as $menu) { foreach($menus[$category] as $link) {
echo '<a href="' . $menu['link_full'] . '"' . ($menu['blank'] ? ' target="_blank"' : '') . ' style="color: #' . (strlen($menu['color']) == 0 ? $default_menu_color : $menu['color']) . ';">' . $menu['name'] . '</a>'; echo '<a href="' . $link['link_full'] . '" ' . $link['target_blank'] . ' ' . $link['style_color'] . '>' . $link['name'] . '</a>';
if(++$i != $size) { if(++$i != $size) {
echo '<span class="separator"></span>'; echo '<span class="separator"></span>';

View File

@@ -1,5 +1,5 @@
<?php <?php
$config['menu_default_color'] = '#ffffff'; $config['menu_default_links_color'] = '#ffffff';
$config['menu_categories'] = array( $config['menu_categories'] = array(
MENU_CATEGORY_NEWS => array('id' => 'news', 'name' => 'Latest News'), MENU_CATEGORY_NEWS => array('id' => 'news', 'name' => 'Latest News'),
@@ -9,3 +9,5 @@ $config['menu_categories'] = array(
MENU_CATEGORY_LIBRARY => array('id' => 'library', 'name' => 'Library'), MENU_CATEGORY_LIBRARY => array('id' => 'library', 'name' => 'Library'),
MENU_CATEGORY_SHOP => array('id' => 'shops', 'name' => 'Shop') MENU_CATEGORY_SHOP => array('id' => 'shops', 'name' => 'Shop')
); );
$config['menus'] = require __DIR__ . '/menus.php';

View File

@@ -7,7 +7,7 @@ if(strlen($text) > 100) // max limit
putenv('GDFONTPATH=' . __DIR__); putenv('GDFONTPATH=' . __DIR__);
// create image // create image
$image = imagecreatetruecolor(250, 28); $image = imagecreatetruecolor(600, 28);
// make the background transparent // make the background transparent
imagecolortransparent($image, imagecolorallocate($image, 0, 0, 0)); imagecolortransparent($image, imagecolorallocate($image, 0, 0, 0));

View File

@@ -372,19 +372,13 @@ foreach($config['menu_categories'] as $id => $cat) {
</span> </span>
<div id='<?php echo $cat['id']; ?>_Submenu' class='Submenu'> <div id='<?php echo $cat['id']; ?>_Submenu' class='Submenu'>
<?php <?php
$default_menu_color = "ffffff";
foreach($menus[$id] as $category => $menu) { foreach($menus[$id] as $category => $menu) {
if (empty($menu['link'])) {
$menu['link'] = 'news';
}
$link_color = '#' . (strlen($menu['color']) == 0 ? $default_menu_color : $menu['color']);
?> ?>
<a href='<?php echo $menu['link_full']; ?>'<?= $menu['target_blank']?>> <a href='<?php echo $menu['link_full']; ?>'<?= $menu['target_blank']?>>
<div id='submenu_<?php echo str_replace('/', '_', $menu['link']); ?>' class='Submenuitem' onMouseOver='MouseOverSubmenuItem(this)' onMouseOut='MouseOutSubmenuItem(this)' style="color: <?php echo $link_color; ?>;"> <div id='submenu_<?php echo str_replace('/', '_', $menu['link']); ?>' class='Submenuitem' onMouseOver='MouseOverSubmenuItem(this)' onMouseOut='MouseOutSubmenuItem(this)' >
<div class='LeftChain' style='background-image:url(<?php echo $template_path; ?>/images/general/chain.gif);'></div> <div class='LeftChain' style='background-image:url(<?php echo $template_path; ?>/images/general/chain.gif);'></div>
<div id='ActiveSubmenuItemIcon_<?php echo str_replace('/', '_', $menu['link']); ?>' class='ActiveSubmenuItemIcon' style='background-image:url(<?php echo $template_path; ?>/images/menu/icon-activesubmenu.gif);'></div> <div id='ActiveSubmenuItemIcon_<?php echo str_replace('/', '_', $menu['link']); ?>' class='ActiveSubmenuItemIcon' style='background-image:url(<?php echo $template_path; ?>/images/menu/icon-activesubmenu.gif);'></div>
<div class='SubmenuitemLabel' style="color: <?php echo $link_color; ?>;"><?php echo $menu['name']; ?></div> <div class='SubmenuitemLabel' <?php echo $menu['style_color']; ?>><?php echo $menu['name']; ?></div>
<div class='RightChain' style='background-image:url(<?php echo $template_path; ?>/images/general/chain.gif);'></div> <div class='RightChain' style='background-image:url(<?php echo $template_path; ?>/images/general/chain.gif);'></div>
</div> </div>
</a> </a>